fleshing out the mark-item-as-received workflow. New PhysicalObject table. Vestigial...
authorgfawcett <gfawcett@6d9bc8c9-1ec2-4278-b937-99fde70a366f>
Sun, 5 Apr 2009 20:42:51 +0000 (20:42 +0000)
committergfawcett <gfawcett@6d9bc8c9-1ec2-4278-b937-99fde70a366f>
Sun, 5 Apr 2009 20:42:51 +0000 (20:42 +0000)
git-svn-id: svn://svn.open-ils.org/ILS-Contrib/servres/trunk@278 6d9bc8c9-1ec2-4278-b937-99fde70a366f

conifer/syrup/admin.py
conifer/syrup/models.py
conifer/syrup/urls.py
conifer/syrup/views.py
conifer/templates/phys/mark_arrived_choose.xhtml
conifer/templates/simplemessage.xhtml

index 084f743..9ac7f1a 100644 (file)
@@ -6,7 +6,7 @@ import django.db.models
 from conifer.syrup.models import *
 
 for m in [LibraryUnit, ServiceDesk, Member, Department, Course, Term, UserProfile, NewsItem, 
-          Target]:
+          Target, PhysicalObject]:
     admin.site.register(m)
 
 
index 03eb491..b33818f 100644 (file)
@@ -558,16 +558,43 @@ class Target(m.Model):
 # SIP checkout
 
 class CheckInOut(m.Model):
-    """A log of checkout events."""
+    """A log of checkout-to-patron and item-return events."""
     
     is_checkout = m.BooleanField()       # in or out?
     is_successful = m.BooleanField()     # did the transaction work?
     staff  = m.ForeignKey(User)          # who processed the request?
     patron = m.CharField(max_length=100) # barcode
     patron_descrip = m.CharField(max_length=512) # ILS descrip
-    item   = m.CharField(max_length=100, null=True)
+    item   = m.CharField(max_length=100, null=True) # item barcode
     item_descrip = m.CharField(max_length=512, null=True)
     outcome = m.CharField(max_length=1024, null=True) # text msg from ILS about transaction
     processed = m.DateTimeField(auto_now_add=True)
     
 
+class PhysicalObject(m.Model):
+    """A record of a physical object entering and leaving the Reserves area."""
+    barcode     = m.CharField(max_length=100) # item barcode
+    receiver = m.ForeignKey(User, related_name='receiver') # who received the item?
+    received    = m.DateTimeField(auto_now_add=True)
+    departer = m.ForeignKey(User, blank=True, null=True, related_name='departer') # who sent it away?
+    departed    = m.DateTimeField(blank=True, null=True)
+    # an optional small-integer used as a human-shareable barcode by some institutions.
+    smallint    = m.IntegerField(blank=True, null=True)
+
+
+    def save(self, force_insert=False, force_update=False):
+        # Must ensure that barcode is unique for non-departed items. Same with smallint
+        try:
+            already = PhysicalObject.objects.exclude(pk=self.id).get(departed=None)
+            if self.smallint:
+                already = PhysicalObject.objects.exclude(pk=self.id).get(smallint=smallint)
+        except PhysicalObject.DoesNotExist:
+            super(PhysicalObject, self).save(force_insert, force_update)
+        else:
+            raise AssertionError, 'barcode is not unique in active PhysicalObject collection.'
+
+    @classmethod
+    def by_barcode(cls, barcode):
+        """Find object by barcode, searching *only* the non-departed items."""
+        res = cls.objects.filter(departed=None, barcode=barcode)
+        return res and res[0] or None
index bda3362..36b9170 100644 (file)
@@ -50,6 +50,7 @@ urlpatterns = patterns('conifer.syrup.views',
     (r'^phys/$', 'phys_index'),
     (r'^phys/checkout/$', 'phys_checkout'),
     (r'^phys/mark_arrived/$', 'phys_mark_arrived'),
+    (r'^phys/mark_arrived/match/$', 'phys_mark_arrived_match'),
 
     (r'^course/(?P<course_id>\d+)/reseq$', 'course_reseq'),
     (ITEM_PREFIX + r'reseq', 'item_heading_reseq'),
index 133311c..1c181c2 100644 (file)
@@ -1330,6 +1330,12 @@ def phys_mark_arrived(request):
         return g.render('phys/mark_arrived.xhtml')
     else:
         barcode = request.POST.get('item', '').strip()
+        already = models.PhysicalObject.by_barcode(barcode)
+        if already:
+            msg = _('This item has already been marked as received. Date received: %s')
+            msg = msg % str(already.received)
+            return simple_message(_('Item already marked as received'), msg)
+                                  
         bib_id  = lib_integration.barcode_to_bib_id(barcode)
         marcxml = lib_integration.bib_id_to_marcxml(bib_id)
         dct     = marcxml_to_dictionary(marcxml)
@@ -1342,3 +1348,28 @@ def phys_mark_arrived(request):
                         bib_id=bib_id,
                         ranked=ranked,
                         metadata=dct)
+
+@admin_only        
+def phys_mark_arrived_match(request):
+    #[(u'barcode', u'30007000110717'), (u'choose_27', u'on')]
+    choices = [int(k.split('_')[1]) for k in request.POST if k.startswith('choose_')]
+    if not choices:
+        return simple_message(_('No matching items selected!'),
+                              _('You must select one or more matching items from the list.'))
+    else:
+        barcode = request.POST.get('barcode', '').strip()
+        assert barcode
+        smallint = request.POST.get('smallint', '').strip() # will be '' for now.
+        phys = models.PhysicalObject(barcode=barcode,
+                                     receiver = request.user,
+                                     smallint = smallint or None)
+        phys.save()
+
+        for c in choices:
+            item = models.Item.objects.get(pk=c)
+            if not item.barcode():
+                item.metadata_set.create(name='syrup:barcode', value=barcode)
+                item.save()
+    return simple_message(_('Matches saved.'), '', go_back=False)
+
+
index b3b8df1..cde15bb 100644 (file)
@@ -21,7 +21,6 @@ title = _('Mark Items as Arrived: Choose Match')
 </head>
 <body>
   <h1>${title}</h1>
-  <form action="." method="POST">
     <div>
       <table class="metadata_table">
        <tr><th>Item Barcode</th><td>${barcode}</td></tr>
@@ -36,7 +35,13 @@ title = _('Mark Items as Arrived: Choose Match')
       </tr>
     </table>
     <h2>Matches</h2>
-    <p><button>Associate with matches selected below</button></p>
+    <form action="match/" method="POST">
+    <div style="float: right;">
+      Optional: Small-number ID for this item: 
+      <input type="text" name="smallint"/>
+    </div>
+    <p><input type="submit" value="Associate item with matches selected below"/></p>
+    <input type="hidden" name="barcode" value="${barcode}"/>
     <table class="metadata_table">
       <thead style="font-size: 70%;">
        <tr><th py:for="v in 'Select Title Author Course Instructor Score'.split(' ')">${v}</th></tr>
@@ -52,7 +57,7 @@ title = _('Mark Items as Arrived: Choose Match')
        </tr>
        </tbody>
     </table>
+    </form>
   </div>
-  </form>
 </body>
 </html>
index 82f5329..78f9a27 100644 (file)
@@ -8,6 +8,6 @@
 <body>
   <h1>${title}</h1>
   ${content}
-  <p py:if="defined('go_back')"><a href="javascript:history.go(-1);">Go back</a></p>
+  <p py:if="go_back"><a href="javascript:history.go(-1);">Go back</a></p>
 </body>
 </html>