lp1777675 inventory date support
authorKyle Huckins <khuckins@catalyte.io>
Mon, 9 Jul 2018 18:11:05 +0000 (18:11 +0000)
committerKathy Lussier <klussier@masslnc.org>
Tue, 4 Sep 2018 18:49:56 +0000 (14:49 -0400)
- Add toggle for updating inventory date and workstation on checkin
- Create new table asset.last_copy_inventory containing inventory date and inventory workstation columns.
- Add code to do_checkin subroutine to update last_copy_inventory table on checkin.
- Update Holdings view, Checkins table, copy buckets, and item detail grid and lists to display new
inventory date and workstation information.
- Add Update Inventory action to Item Status detail and list views.

Signed-off-by: Kyle Huckins <khuckins@catalyte.io>
Signed-off-by: Kathy Lussier <klussier@masslnc.org>

Conflicts:
Open-ILS/web/js/ui/default/staff/circ/services/item.js

Signed-off-by: Dan Wells <dbw2@calvin.edu>

20 files changed:
Open-ILS/examples/fm_IDL.xml
Open-ILS/src/perlmods/lib/OpenILS/Application/Circ.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Circulate.pm
Open-ILS/src/sql/Pg/040.schema.asset.sql
Open-ILS/src/sql/Pg/800.fkeys.sql
Open-ILS/src/sql/Pg/upgrade/XXXX-create-inventory-workstation-and-date.sql [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/bucket/copy/t_pending.tt2
Open-ILS/src/templates/staff/cat/bucket/copy/t_view.tt2
Open-ILS/src/templates/staff/cat/catalog/t_holdings.tt2
Open-ILS/src/templates/staff/cat/item/index.tt2
Open-ILS/src/templates/staff/cat/item/t_list.tt2
Open-ILS/src/templates/staff/cat/item/t_summary_pane.tt2
Open-ILS/src/templates/staff/circ/checkin/t_checkin.tt2
Open-ILS/src/templates/staff/circ/checkin/t_checkin_table.tt2
Open-ILS/web/js/ui/default/staff/cat/bucket/copy/app.js
Open-ILS/web/js/ui/default/staff/cat/item/app.js
Open-ILS/web/js/ui/default/staff/cat/services/holdings.js
Open-ILS/web/js/ui/default/staff/circ/checkin/app.js
Open-ILS/web/js/ui/default/staff/circ/services/circ.js
Open-ILS/web/js/ui/default/staff/circ/services/item.js

index c9a60dd..d6a4f20 100644 (file)
@@ -7393,6 +7393,7 @@ SELECT  usr,
                        <field reporter:label="Peer Record Maps" name="peer_record_maps" oils_persist:virtual="true" reporter:datatype="link"/>
                        <field reporter:label="Peer Records" name="peer_records" oils_persist:virtual="true" reporter:datatype="link"/>
                        <field reporter:label="Last Captured Hold" name="last_captured_hold" oils_persist:virtual="true" reporter:datatype="link"/>
+                       <field reporter:label="Last Copy Inventory" name="last_copy_inventory" oils_persist:virtual="true" reporter:datatype="link"/>
                        <field reporter:label="Has Holds" name="holds_count" oils_persist:virtual="true" reporter:datatype="link"/>
                        <field reporter:label="Copy Tags" name="tags" oils_persist:virtual="true" reporter:datatype="link"/>
                        <field reporter:label="Copy Alerts" name="copy_alerts" oils_persist:virtual="true" reporter:datatype="link"/>
@@ -7419,6 +7420,7 @@ SELECT  usr,
                        <link field="peer_record_maps" reltype="has_many" key="target_copy" map="" class="bpbcm"/>
                        <link field="peer_records" reltype="has_many" key="target_copy" map="peer_record" class="bpbcm"/>
                        <link field="last_captured_hold" reltype="has_a" key="current_copy" map="" class="alhr"/>
+                       <link field="last_copy_inventory" reltype="might_have" key="copy" map="" class="alci"/>
                        <link field="floating" reltype="has_a" key="id" map="" class="cfg"/>
                        <link field="holds_count" reltype="might_have" key="id" map="" class="hasholdscount"/>
                        <link field="tags" reltype="has_many" key="copy" map="" class="acptcm"/>
@@ -7441,6 +7443,27 @@ SELECT  usr,
         </permacrud>
        </class>
 
+       <class id="alci" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="asset::last_copy_inventory" oils_persist:tablename="asset.last_copy_inventory" reporter:core="true" reporter:label="Last Copy Inventory">
+               <fields oils_persist:primary="id" oils_persist:sequence="asset.last_copy_inventory_id_seq">
+            <field reporter:label="Last Inventory ID" name="id" reporter:datatype="id"/>
+                       <field reporter:label="Last Inventory Date" name="inventory_date" reporter:datatype="timestamp"/>
+                       <field reporter:label="Last Inventory Workstation" name="inventory_workstation" reporter:datatype="link"/>
+                       <field reporter:label="Copy" name="copy" reporter:datatype="link"/>
+               </fields>
+               <links>
+                       <link field="inventory_workstation" reltype="has_a" key="id" map="" class="aws"/>
+                       <link field="copy" reltype="has_a" key="id" map="" class="acp"/>
+               </links>
+        <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
+            <actions>
+                               <create/>
+                               <retrieve/>
+                               <update/>
+                               <delete/>
+            </actions>
+        </permacrud>
+       </class>
+
        <class id="ccat" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::copy_alert_type" oils_persist:tablename="config.copy_alert_type" reporter:label="Copy Alert Type" oils_persist:restrict_primary="100">
                <fields oils_persist:primary="id" oils_persist:sequence="config.copy_alert_type_id_seq">
                        <field reporter:label="Id" name="id" reporter:selector="name" reporter:datatype="id"/>
index 3a59bf9..ddddbc8 100644 (file)
@@ -370,6 +370,37 @@ sub new_set_circ_lost {
     return 1;
 }
 
+__PACKAGE__->register_method(
+    method    => "update_last_copy_inventory",
+    api_name  => "open-ils.circ.circulation.update_last_copy_inventory");
+
+sub update_last_copy_inventory {
+    my( $self, $conn, $auth, $args ) = @_;
+    my $e = new_editor(authtoken=>$auth, xact=>1);
+    return $e->die_event unless $e->checkauth;
+
+    my $copies = $$args{copy_list};
+    foreach my $copyid (@$copies) {
+        my $copy = $e->retrieve_asset_copy($copyid);
+        my $alci = $e->search_asset_last_copy_inventory({copy => $copyid})->[0];
+
+        if($alci) {
+            $alci->inventory_date('now');
+            $alci->inventory_workstation($e->requestor->wsid);
+            $e->update_asset_last_copy_inventory($alci) or return $e->die_event;
+        } else {
+            my $alci = Fieldmapper::asset::last_copy_inventory->new;
+            $alci->inventory_date('now');
+            $alci->inventory_workstation($e->requestor->wsid);
+            $alci->copy($copy->id);
+            $e->create_asset_last_copy_inventory($alci) or return $e->die_event;
+        }
+
+        $copy->last_copy_inventory($alci);
+    }
+    $e->commit;
+    return 1;
+}
 
 __PACKAGE__->register_method(
     method  => "set_circ_claims_returned",
index ab9d178..deae8f1 100644 (file)
@@ -418,6 +418,8 @@ my @AUTOLOAD_FIELDS = qw/
     remote_hold
     backdate
     reservation
+    do_inventory_update
+    last_copy_inventory
     copy
     copy_id
     copy_barcode
@@ -2673,6 +2675,20 @@ sub do_checkin {
         $self->dont_change_lost_zero($dont_change_lost_zero);
     }
 
+    my $last_copy_inventory = Fieldmapper::asset::last_copy_inventory->new;
+
+    if ($self->do_inventory_update) {
+        $last_copy_inventory->inventory_date('now');
+        $last_copy_inventory->inventory_workstation($self->editor->requestor->wsid);
+        $last_copy_inventory->copy($self->copy->id());
+    } else {
+        my $alci = $self->editor->search_asset_last_copy_inventory(
+            {copy => $self->copy->id}
+        );
+        $last_copy_inventory = $alci->[0]
+    }
+    $self->last_copy_inventory($last_copy_inventory);
+
     if( $self->checkin_check_holds_shelf() ) {
         $self->bail_on_events(OpenILS::Event->new('NO_CHANGE'));
         $self->hold($U->fetch_open_hold_by_copy($self->copy->id));
@@ -3953,6 +3969,23 @@ sub checkin_flesh_events {
         );
     }
 
+    if ($self->last_copy_inventory) {
+        # flesh some workstation fields before returning
+        $self->last_copy_inventory->inventory_workstation(
+            $self->editor->retrieve_actor_workstation([$self->last_copy_inventory->inventory_workstation])
+        );
+    }
+
+    if($self->last_copy_inventory && !$self->last_copy_inventory->id) {
+        my $alci = $self->editor->search_asset_last_copy_inventory(
+            {copy => $self->last_copy_inventory->copy}
+        );
+        if($alci->[0]) {
+            $self->last_copy_inventory->id($alci->[0]->id);
+        }
+    }
+    $self->copy->last_copy_inventory($self->last_copy_inventory);
+
     for my $evt (@{$self->events}) {
 
         my $payload         = {};
@@ -3966,6 +3999,8 @@ sub checkin_flesh_events {
         $payload->{patron}  = $self->patron;
         $payload->{reservation} = $self->reservation
             unless (not $self->reservation or $self->reservation->cancel_time);
+        $payload->{last_copy_inventory} = $self->last_copy_inventory;
+        if ($self->do_inventory_update) { $payload->{do_inventory_update} = 1; }
 
         $evt->{payload}     = $payload;
     }
index 04d98b3..374a1ec 100644 (file)
@@ -120,6 +120,14 @@ CREATE TABLE asset.copy_part_map (
 );
 CREATE UNIQUE INDEX copy_part_map_cp_part_idx ON asset.copy_part_map (target_copy, part);
 
+CREATE TABLE asset.last_copy_inventory (
+    id                          SERIAL                      PRIMARY KEY,
+    inventory_workstation       INTEGER                     REFERENCES actor.workstation (id) DEFERRABLE INITIALLY DEFERRED,
+    inventory_date              TIMESTAMP WITH TIME ZONE    DEFAULT NOW(),
+    copy                        BIGINT                                 NOT NULL
+);
+CREATE INDEX last_copy_inventory_copy_idx ON asset.last_copy_inventory (copy);
+
 CREATE TABLE asset.opac_visible_copies (
   id        BIGSERIAL primary key,
   copy_id   BIGINT, -- copy id
index c396119..50d7927 100644 (file)
@@ -169,6 +169,18 @@ BEGIN
 END;
 $f$ LANGUAGE PLPGSQL VOLATILE COST 50;
 
+CREATE OR REPLACE FUNCTION evergreen.asset_last_copy_inventory_copy_inh_fkey() RETURNS TRIGGER AS $f$
+BEGIN
+        PERFORM 1 FROM asset.copy WHERE id = NEW.copy;
+        IF NOT FOUND THEN
+                RAISE foreign_key_violation USING MESSAGE = FORMAT(
+                        $$Referenced asset.copy id not found, copy:%s$$, NEW.copy
+                );
+        END IF;
+        RETURN NEW;
+END;
+$f$ LANGUAGE PLPGSQL VOLATILE COST 50;
+
 CREATE CONSTRAINT TRIGGER inherit_asset_copy_alert_copy_fkey
         AFTER UPDATE OR INSERT ON asset.copy_alert
         DEFERRABLE FOR EACH ROW EXECUTE PROCEDURE evergreen.asset_copy_alert_copy_inh_fkey();
@@ -177,6 +189,10 @@ CREATE CONSTRAINT TRIGGER inherit_asset_copy_tag_copy_map_copy_fkey
         AFTER UPDATE OR INSERT ON asset.copy_tag_copy_map
         DEFERRABLE FOR EACH ROW EXECUTE PROCEDURE evergreen.asset_copy_tag_copy_map_copy_inh_fkey();
 
+CREATE CONSTRAINT TRIGGER inherit_asset_last_copy_inventory_copy_fkey
+        AFTER UPDATE OR INSERT ON asset.last_copy_inventory
+        DEFERRABLE FOR EACH ROW EXECUTE PROCEDURE evergreen.asset_last_copy_inventory_copy_inh_fkey();
+
 ALTER TABLE asset.copy_note ADD CONSTRAINT asset_copy_note_creator_fkey FOREIGN KEY (creator) REFERENCES actor.usr (id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
 
 ALTER TABLE asset.call_number ADD CONSTRAINT asset_call_number_owning_lib_fkey FOREIGN KEY (owning_lib) REFERENCES actor.org_unit (id) DEFERRABLE INITIALLY DEFERRED;
diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX-create-inventory-workstation-and-date.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX-create-inventory-workstation-and-date.sql
new file mode 100644 (file)
index 0000000..b4dcdf8
--- /dev/null
@@ -0,0 +1,29 @@
+BEGIN;
+
+SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version);
+
+CREATE TABLE asset.last_copy_inventory (
+    id                          SERIAL                      PRIMARY KEY,
+    inventory_workstation       INTEGER                     REFERENCES actor.workstation (id) DEFERRABLE INITIALLY DEFERRED,
+    inventory_date              TIMESTAMP WITH TIME ZONE    DEFAULT NOW(),
+    copy                        BIGINT                      NOT NULL
+);
+CREATE INDEX last_copy_inventory_copy_idx ON asset.last_copy_inventory (copy);
+
+CREATE OR REPLACE FUNCTION evergreen.asset_last_copy_inventory_copy_inh_fkey() RETURNS TRIGGER AS $f$
+BEGIN
+        PERFORM 1 FROM asset.copy WHERE id = NEW.copy;
+        IF NOT FOUND THEN
+                RAISE foreign_key_violation USING MESSAGE = FORMAT(
+                        $$Referenced asset.copy id not found, copy:%s$$, NEW.copy
+                );
+        END IF;
+        RETURN NEW;
+END;
+$f$ LANGUAGE PLPGSQL VOLATILE COST 50;
+
+CREATE CONSTRAINT TRIGGER inherit_asset_last_copy_inventory_copy_fkey
+        AFTER UPDATE OR INSERT ON asset.last_copy_inventory
+        DEFERRABLE FOR EACH ROW EXECUTE PROCEDURE evergreen.asset_last_copy_inventory_copy_inh_fkey();
+
+COMMIT;
\ No newline at end of file
index 2396333..60c1146 100644 (file)
@@ -58,5 +58,7 @@
       {{item['call_number.record.simple_record.title']}}
     </a>
   </eg-grid-field>
+  <eg-grid-field path="last_copy_inventory.inventory_date" datatype="timestamp" label="[% l('Inventory Date') %]"></eg-grid-field>
+  <eg-grid-field path="last_copy_inventory.inventory_workstation.name" label="[% l('Inventory Workstation') %]"></eg-grid-field>
 
 </eg-grid>
index fb7d3d1..43f3ee0 100644 (file)
@@ -43,5 +43,7 @@
       {{item['call_number.record.simple_record.title']}}
     </a>
   </eg-grid-field>
+  <eg-grid-field path="last_copy_inventory.inventory_date" datatype="timestamp" label="[% l('Inventory Date') %]"></eg-grid-field>
+  <eg-grid-field path="last_copy_inventory.inventory_workstation.name" label="[% l('Inventory Workstation') %]"></eg-grid-field>
 
 </eg-grid>
index f188a1a..9241250 100644 (file)
       {{item['copy_alert_count']}}
       <button ng-disabled="item['copy_alert_count'] <= 0" class="btn btn-sm btn-default" ng-click="col.handlers.copyAlertsEdit(item['id'])">[% l('Manage') %]</button>
     </eg-grid-field>
+    <eg-grid-field label="[% l('Inventory Date') %]"          datatype="timestamp" path="last_copy_inventory.inventory_date"></eg-grid-field>
+    <eg-grid-field label="[% l('Inventory Workstation') %]"   path="last_copy_inventory.inventory_workstation.name"></eg-grid-field>
   
   </eg-grid>
 </div>
index df5ed04..c661742 100644 (file)
       "[% l('One or more items could not be transferred. Override?') %]";
     s.OVERRIDE_TRANSFER_COPIES_TO_MARKED_VOLUME_BODY =
       "[% l('Reason(s) include: [_1]', '{{evt_desc}}') %]";
+    s.SUCCESS_UPDATE_INVENTORY =
+      "[% l('Updated most recent inventory data for selected items.') %]";
+    s.FAIL_UPDATE_INVENTORY =
+      "[% l('Failed to update recent inventory data for selected items.')%]"
   }])
 </script>
 [% END %]
@@ -84,6 +88,7 @@
         <li><a href ng-click="checkin()">[% l('Check In Items') %]</a></li>
         <li><a href ng-click="renew()">[% l('Renew Items') %]</a></li>
         <li><a href ng-click="cancel_transit()">[% l('Cancel Transit') %]</a></li>
+        <li><a href ng-click="update_inventory()">[% l('Update Inventory') %]</a></li>
 
         <p><b>[% l('Mark') %]</b></p>    
         <li><a href ng-click="selectedHoldingsDamaged()">[% l('Item as Damaged') %]</a></li>
index 111e722..5827342 100644 (file)
@@ -27,6 +27,8 @@
     label="[% l('Renew Items') %]"></eg-grid-action>
   <eg-grid-action handler="cancel_transit"
     label="[% l('Cancel Transit') %]"></eg-grid-action>
+  <eg-grid-action handler="update_inventory"
+    label="[% l('Update Inventory') %]"></eg-grid-action>
     
   <eg-grid-action handler="selectedHoldingsItemStatusTgrEvt" group="[% l('Show') %]"
     label="[% l('Triggered Events') %]"></eg-grid-action>
     {{item['copy_alert_count']}}
     <button ng-disabled="item['copy_alert_count'] <= 0" class="btn btn-sm btn-default" ng-click="col.handlers.copyAlertsEdit(item['id'])">[% l('Manage') %]</button>
   </eg-grid-field>
+  <eg-grid-field label="[% l('Inventory Date') %]"        path="last_copy_inventory.inventory_date" datatype="timestamp"></eg-grid-field>
+  <eg-grid-field label="[% l('Inventory Workstation') %]" path="last_copy_inventory.inventory_workstation.name"></eg-grid-field>
   
 </eg-grid>
 
index e4130a2..e67ba11 100644 (file)
   </div>
 
   <div class="flex-row">
+    <div class="flex-cell">[% l('Inventory Date') %]</div>
+    <div class="flex-cell well">{{copy.last_copy_inventory().inventory_date() | date:egDateAndTimeFormat}}</div>
+
+    <div class="flex-cell">[% l('Inventory Workstation') %]</div>
+    <div class="flex-cell well">{{copy.last_copy_inventory().inventory_workstation().name()}}</div>
+
+    <div class="flex-cell"></div>
+    <div class="flex-cell"></div>
+    <div class="flex-cell"></div>
+    <div class="flex-cell"></div>
+  </div>
+
+  <div class="flex-row">
     <div class="flex-cell">[% l('Copy Alerts') %]</div>
     <div class="flex-cell" id="item-status-alert-msg">
       <button class="btn btn-default" ng-click="addCopyAlerts(copy.id())" >[% l('Add') %]</button>
index 42d6e67..30d996b 100644 (file)
     <div ng-if="modifiers.manual_float" class="alert-danger pad-all-min">
       [% l('Manual Floating Active') %]
     </div>
+    <div ng-if="modifiers.do_inventory_update" class="alert-danger pad-all-min">
+      [% l('Update Inventory') %]
+    </div>
   </div>
 </div>
 
 <!-- checkin form -->
 <div class="row pad-vert">
-  <div class="col-md-5">
+  <div class="col-md-4">
     <form ng-submit="checkin(checkinArgs)" role="form" class="form-inline">
       <div class="input-group">
 
@@ -75,7 +78,7 @@
     </div>
   </div>
 
-  <div class="col-md-4" ng-if="!is_capture">
+  <div class="col-md-3" ng-if="!is_capture">
     <div class="flex-row">
       <div class="flex-cell"></div>
       <div class="pad-horiz">[% l('Effective Date') %]</div>
             <span>[% l('Manual Floating Active') %]</span>
           </a>
         </li>
+        <li>
+          <a href
+            ng-click="toggle_mod('do_inventory_update')">
+            <span ng-if="modifiers.do_inventory_update"
+              class="label label-success">&#x2713;</span>
+            <span ng-if="!modifiers.do_inventory_update"
+              class="label label-warning">&#x2717;</span>
+            <span>[% l('Update Inventory') %]</span>
+          </a>
+        </li>
       </ul>
     </div><!-- btn grp -->
   </div><!-- col -->
index 8f98584..aef321d 100644 (file)
   <eg-grid-field path="au.*" parent-idl-class="au" hidden></eg-grid-field>
   <eg-grid-field path="transit.*" parent-idl-class="atc" hidden></eg-grid-field>
   <eg-grid-field path="hold.*" parent-idl-class="ahr" hidden></eg-grid-field>
+  <eg-grid-field path="acp.last_copy_inventory.inventory_date" label="[% l('Inventory Date') %]" datatype="timestamp" hidden></eg-grid-field>
+  <eg-grid-field path="acp.last_copy_inventory.inventory_workstation.name" label="[% l('Inventory Workstation')%]" hidden></eg-grid-field>
 </eg-grid>
 
index 3208a42..f39346e 100644 (file)
@@ -215,6 +215,16 @@ angular.module('egCatCopyBuckets',
         return deferred.promise;
     }
 
+    // apply last inventory data to fetched bucket items
+    service.fetchRecentInventoryData = function(copy) {
+        return egCore.pcrud.search('alci',
+            {copy: copy.id},
+            {flesh: 2, flesh_fields: {alci: ['inventory_workstation']}}
+        ).then(function(alci) {
+            return alci;
+        });
+    }
+
     return service;
 }])
 
index cededcd..24178d7 100644 (file)
@@ -104,6 +104,13 @@ function($scope , $location , $timeout , egCore , egGridDataProvider , itemSvc)
         itemSvc.requestItems([$scope.args.copyId]);
     }
 
+    $scope.update_inventory = function() {
+        itemSvc.updateInventory([$scope.args.copyId], null)
+        .then(function(res) {
+            $timeout(function() { location.href = location.href; }, 1000);
+        });
+    }
+
     $scope.attach_to_peer_bib = function() {
         itemSvc.attach_to_peer_bib([{
             id : $scope.args.copyId,
@@ -236,10 +243,10 @@ function($scope , $location , $timeout , egCore , egGridDataProvider , itemSvc)
 .controller('ListCtrl', 
        ['$scope','$q','$routeParams','$location','$timeout','$window','egCore',
         'egGridDataProvider','egItem','egUser','$uibModal','egCirc','egConfirmDialog',
-        'egProgressDialog',
+        'egProgressDialog', 'ngToast',
 function($scope , $q , $routeParams , $location , $timeout , $window , egCore , 
          egGridDataProvider , itemSvc , egUser , $uibModal , egCirc , egConfirmDialog,
-         egProgressDialog) {
+         egProgressDialog, ngToast) {
 
     var copyId = [];
     var cp_list = $routeParams.idList;
@@ -385,6 +392,18 @@ function($scope , $q , $routeParams , $location , $timeout , $window , egCore ,
         itemSvc.add_copies_to_bucket(copy_list);
     }
 
+    $scope.update_inventory = function() {
+        var copy_list = gatherSelectedHoldingsIds();
+        itemSvc.updateInventory(copy_list, $scope.gridControls.allItems()).then(function(res) {
+            if (res) {
+                $scope.gridControls.allItems(res);
+                ngToast.create(egCore.strings.SUCCESS_UPDATE_INVENTORY);
+            } else {
+                ngToast.warning(egCore.strings.FAIL_UPDATE_INVENTORY);
+            }
+        });
+    }
+
     $scope.need_one_selected = function() {
         var items = $scope.gridControls.selectedItems();
         if (items.length == 1) return false;
@@ -591,6 +610,9 @@ function($scope , $q , $location , $routeParams , $timeout , $window , egCore ,
         // regardless of whether it matches the current item.
         if (!barcode && itemSvc.copy && itemSvc.copy.id() == copyId) {
             $scope.copy = itemSvc.copy;
+            if (itemSvc.last_copy_inventory && itemSvc.last_copy_inventory.copy() == copyId) {
+                $scope.last_copy_inventory = itemSvc.last_copy_inventory;
+            }
             $scope.copy_alert_count = itemSvc.copy.copy_alerts().filter(function(aca) {
                 return !aca.ack_time();
             }).length;
@@ -623,9 +645,11 @@ function($scope , $q , $location , $routeParams , $timeout , $window , egCore ,
 
             var copy = res.copy;
             itemSvc.copy = copy;
+            if (res.last_copy_inventory) itemSvc.last_copy_inventory = res.last_copy_inventory;
 
 
             $scope.copy = copy;
+            $scope.last_copy_inventory = res.last_copy_inventory;
             $scope.copy_alert_count = copy.copy_alerts().filter(function(aca) {
                 return !aca.ack_time();
             }).length;
index b4fb738..37b8b07 100644 (file)
@@ -13,10 +13,11 @@ function(egCore , $q) {
     };
 
     service.prototype.flesh = {   
-        flesh : 2, 
+        flesh : 3,
         flesh_fields : {
-            acp : ['status','location','circ_lib','parts','age_protect','copy_alerts'],
-            acn : ['prefix','suffix','copies']
+            acp : ['status','location','circ_lib','parts','age_protect','copy_alerts', 'last_copy_inventory'],
+            acn : ['prefix','suffix','copies'],
+            alci : ['inventory_workstation']
         }
     }
 
index 103a8e0..b1e0aed 100644 (file)
@@ -86,6 +86,7 @@ function($scope , $q , $window , $location , $timeout , egCore , checkinSvc , eg
     } else {
         modifiers.push('noop'); // AKA suppress holds and transits
         modifiers.push('auto_print_holds_transits');
+        modifiers.push('do_inventory_update');
     }
 
     // set modifiers from stored preferences
@@ -160,14 +161,17 @@ function($scope , $q , $window , $location , $timeout , egCore , checkinSvc , eg
                 params.retarget_mode = 'retarget';
             }
         }
+        if ($scope.modifiers.do_inventory_update) params.do_inventory_update = true;
 
         egCore.hatch.setItem('circ.checkin.strict_barcode', $scope.strict_barcode);
+        egCore.hatch.setItem('circ.checkin.do_inventory_update', $scope.modifiers.do_inventory_update);
         var options = {
             check_barcode : $scope.strict_barcode,
             no_precat_alert : $scope.modifiers.no_precat_alert,
             auto_print_holds_transits : 
                 $scope.modifiers.auto_print_holds_transits,
-            suppress_popups : suppress_popups
+            suppress_popups : suppress_popups,
+            do_inventory_update : $scope.modifiers.do_inventory_update
         };
 
         return {params : params, options: options};
@@ -196,7 +200,6 @@ function($scope , $q , $window , $location , $timeout , egCore , checkinSvc , eg
 
         // track the item in the grid before sending the request
         checkinSvc.checkins.unshift(row_item);
-
         egCirc.checkin(params, options).then(
         function(final_resp) {
             
@@ -207,6 +210,9 @@ function($scope , $q , $window , $location , $timeout , egCore , checkinSvc , eg
             
             row_item['copy_barcode'] = row_item.acp.barcode();
 
+            if (row_item.acp.last_copy_inventory().inventory_date() == "now")
+                row_item.acp.last_copy_inventory().inventory_date(Date.now());
+
             if (row_item.mbts) {
                 var amt = Number(row_item.mbts.balance_owed());
                 if (amt != 0) {
index 6be7dc4..465eaba 100644 (file)
@@ -300,6 +300,7 @@ function($uibModal , $q , egCore , egAlertDialog , egConfirmDialog,  egAddCopyAl
         data.record = payload.record;
         data.acp = payload.copy;
         data.acn = payload.volume ?  payload.volume : payload.copy ? payload.copy.call_number() : null;
+        data.alci = egCore.idl.toHash(payload.last_copy_inventory, true);
         data.au = payload.patron;
         data.transit = payload.transit;
         data.status = payload.status;
@@ -309,8 +310,16 @@ function($uibModal , $q , egCore , egAlertDialog , egConfirmDialog,  egAddCopyAl
         data.isbn = final_resp.evt[0].isbn;
         data.route_to = final_resp.evt[0].route_to;
 
+
         if (payload.circ) data.duration = payload.circ.duration();
         if (payload.circ) data.circ_lib = payload.circ.circ_lib();
+        if (payload.do_inventory_update) {
+            if (payload.last_copy_inventory.id()) {
+                egCore.pcrud.update(payload.last_copy_inventory);
+            } else {
+                egCore.pcrud.create(payload.last_copy_inventory);
+            }
+        }
 
         // for checkin, the mbts lives on the main circ
         if (payload.circ && payload.circ.billable_transaction())
@@ -1463,11 +1472,12 @@ function($uibModal , $q , egCore , egAlertDialog , egConfirmDialog,  egAddCopyAl
 
         var final_resp = {evt : evt, params : params, options : options};
 
-        var copy, hold, transit;
+        var copy, hold, transit, last_copy_inventory;
         if (evt[0].payload) {
             copy = evt[0].payload.copy;
             hold = evt[0].payload.hold;
             transit = evt[0].payload.transit;
+            last_copy_inventory = evt[0].payload.last_copy_inventory;
         }
 
         // track the barcode regardless of whether it's valid
index f8e0d9c..79d099f 100644 (file)
@@ -13,12 +13,13 @@ function(egCore , egCirc , $uibModal , $q , $timeout , $window , egConfirmDialog
     };
 
     service.flesh = {   
-        flesh : 3, 
+        flesh : 4,
         flesh_fields : {
             acp : ['call_number','location','status','location','floating','circ_modifier',
-                'age_protect','circ_lib','copy_alerts', 'editor', 'circ_as_type'],
+                'age_protect','circ_lib','copy_alerts', 'editor', 'circ_as_type', 'last_copy_inventory'],
             acn : ['record','prefix','suffix','label_class'],
-            bre : ['simple_record','creator','editor']
+            bre : ['simple_record','creator','editor'],
+            alci : ['inventory_workstation']
         },
         select : { 
             // avoid fleshing MARC on the bre
@@ -103,7 +104,6 @@ function(egCore , egCirc , $uibModal , $q , $timeout , $window , egConfirmDialog
         return fetchCopy(barcode, id).then(function(res) {
 
             if(!res.copy) { return $q.when(); }
-
             return fetchCirc(copyData.copy).then(function(res) {
                 if (copyData.circ) {
                     return fetchSummary(copyData.circ).then(function() {
@@ -195,6 +195,33 @@ function(egCore , egCirc , $uibModal , $q , $timeout , $window , egConfirmDialog
 
     }
 
+    service.updateInventory = function(copy_list, all_items, refresh) {
+        if (copy_list.length == 0) return;
+        return egCore.net.request(
+            'open-ils.circ',
+            'open-ils.circ.circulation.update_last_copy_inventory',
+            egCore.auth.token(), {copy_list: copy_list}
+        ).then(function(res) {
+            if (res) {
+                if (all_items) angular.forEach(copy_list, function(copy) {
+                    angular.forEach(all_items, function(item) {
+                        if (copy == item.id) {
+                            egCore.pcrud.search('alci', {copy: copy},
+                              {flesh: 1, flesh_fields:
+                                {alci: ['inventory_workstation']}
+                            }).then(function(alci) {
+                                item._last_copy_inventory.inventory_date = alci.inventory_date();
+                                item._last_copy_inventory._inventory_workstation_name =
+                                    alci.inventory_workstation().name();
+                            });
+                        }
+                    });
+                });
+                return all_items || res;
+            }
+        });
+    }
+
     service.add_copies_to_bucket = function(copy_list) {
         if (copy_list.length == 0) return;