fixed perms on fm_idl for ahrrre and order by statement in hold.js added limit of 500 notes.
<field reporter:label="Requesting Library" name="request_lib" reporter:datatype="org_unit"/>
<field reporter:label="Request Date/Time" name="request_time" reporter:datatype="timestamp"/>
<field reporter:label="Requesting User" name="requestor" reporter:datatype="link"/>
+ <field reporter:label="Reset Entries" name="reset_entries" oils_persist:virtual="true" reporter:datatype="link"/>
<field reporter:label="Item Selection Depth" name="selection_depth" />
<field reporter:label="Selection Locus" name="selection_ou" reporter:datatype="org_unit"/>
<field reporter:label="Target Object ID" name="target" reporter:datatype="link"/>
<link field="request_lib" reltype="has_a" key="id" map="" class="aou"/>
<link field="transit" reltype="might_have" key="hold" map="" class="ahtc"/>
<link field="notifications" reltype="has_many" key="hold" map="" class="ahn"/>
+ <link field="reset_entries" reltype="has_many" key="hold" map="" class="ahrrre"/>
<link field="eligible_copies" reltype="has_many" key="hold" map="target_copy" class="ahcm"/>
<link field="bib_rec" reltype="might_have" key="id" map="" class="rhrr"/>
<link field="cancel_cause" reltype="might_have" key="id" map="" class="ahrcc"/>
</fields>
</class>
- <class id="ahrrr" controller="open-ils.cstore" oils_obj:fieldmapper="action::hold_request_reset_reason" oils_persist:tablename="action.hold_request_reset_reason" reporter:label="Hold Request Reset Reason" oils_persist:field_safe="true">
+ <class id="ahrrr" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="action::hold_request_reset_reason" oils_persist:tablename="action.hold_request_reset_reason" reporter:label="Hold Request Reset Reason" oils_persist:field_safe="true">
<fields oils_persist:primary="id" oils_persist:sequence="action.hold_request_reset_reason_id_seq">
<field name="id" reporter:selector="name" reporter:datatype="id" reporter:label="ID"/>
<field name="name" reporter:datatype="text" oils_persist:i18n="true" reporter:label="Name"/>
<field name="manual" reporter:datatype="bool" reporter:label="Manual"/>
</fields>
+ <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
+ <actions>
+ <retrieve/>
+ </actions>
+ </permacrud>
</class>
- <class id="ahrrre" controller="open-ils.cstore" oils_obj:fieldmapper="action::hold_request_reset_reason_entry" oils_persist:tablename="action.hold_request_reset_reason_entry" reporter:label="Hold Request Reset Reason Entry" oils_persist:field_safe="true">
+ <class id="ahrrre" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="action::hold_request_reset_reason_entry" oils_persist:tablename="action.hold_request_reset_reason_entry" reporter:label="Hold Request Reset Reason Entry" oils_persist:field_safe="true">
<fields oils_persist:primary="id" oils_persist:sequence="action.hold_request_reset_reason_entry_id_seq">
<field name="id" reporter:datatype="id" reporter:label="ID"/>
<field name="hold" reporter:label="ID" reporter:datatype="link"/>
<links>
<link field="hold" reltype="has_a" key="id" map="" class="ahr"/>
<link field="reset_reason" reltype="has_a" key="id" map="" class="ahrrr"/>
- <link field="requestor" reltype="might_have" key="id" map="" class="au"/>
- <link field="requestor_workstation" reltype="might_have" key="id" map="" class="aws"/>
- <link field="previous_copy" reltype="might_have" key="id" map="" class="acp"/>
+ <link field="requestor" reltype="has_a" key="id" map="" class="au"/>
+ <link field="requestor_workstation" reltype="has_a" key="id" map="" class="aws"/>
+ <link field="previous_copy" reltype="has_a" key="id" map="" class="acp"/>
</links>
+ <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
+ <actions>
+ <retrieve permission="VIEW_HOLD">
+ <context link="pickup_lib" field="hold"/>
+ </retrieve>
+ </actions>
+ </permacrud>
</class>
sub create_reset_reason_entry
{
- my($self, $conn, $auth, $hold, $reset_reason, $note) = @_;
+ my($self, $conn, $auth, $hold, $reset_reason, $note, $previous_copy) = @_;
my $e = new_editor(authtoken => $auth, xact => 1);
#checkauth to set the requestor (if available)
$e->checkauth;
for my $holdid (@holds){
try{
my ($hold, $evt) = $U->fetch_hold($holdid);
- _create_reset_reason_entry($e, $hold, $reset_reason, $note) unless $evt;
+ _create_reset_reason_entry(
+ $e,
+ $hold,
+ $reset_reason,
+ $note,
+ $previous_copy)
+ unless $evt;
}
catch Error with{
$logger->error("holds: create reset reason failed with ".shift());
$entry->reset_reason($reset_reason);
$entry->reset_time('now');
$entry->previous_copy($last_copy);
- $entry->note($note);
+ $entry->note($note) if defined $note;
$entry->requestor($e->requestor->id) if defined $e->requestor;
$entry->requestor_workstation($e->requestor->wsid) if defined $e->requestor;
$e->create_action_hold_request_reset_reason_entry($entry) or return $e->die_event;
$single->editor()->authtoken,
$hold_id,
OILS_HOLD_TIMED_OUT,
+ undef,
$single->{previous_copy_id}
- ) unless defined $args->{hold};
+ ) unless defined
+ $args->{hold} ||
+ $single->{previous_copy_id} == $single->hold->current_copy;
} catch Error with {
$logger->error(
"hold-targeter: create reset reason failed with ".shift()
OIDS=FALSE
);
+CREATE INDEX ahrrre_hold ON action.hold_request_reset_reason_entry (hold);
+
INSERT INTO config.global_flag (name, label, enabled)
VALUES (
'circ.holds.retarget_previous_targets_interval',
[% l('Staff Notifications') %]
</a>
</li>
+ <li ng-class="{active : detail_tab == 'resets'}">
+ <a href ng-click="show_resets_tab()">
+ [% l('Reset Entries') %]
+ </a>
+ </li>
</ul>
<div class="tab-content">
<div class="tab-pane active">
</div><!-- notes tab content -->
<div ng-if="detail_tab == 'notify'">
+ <div class="btn-group column-picker">
+ <!-- first page -->
+ <button type="button" class="btn btn-default"
+
+ ng-class="{disabled : on_first_rs_page()}"
+ ng-disabled="on_first_rs_page()"
+ ng-click="first_rs_page()"
+ title="[% l('Start') %]">
+ <span class="glyphicon glyphicon-fast-backward"></span>
+ </button>
+
+ <!-- previous page -->
+ <button type="button" class="btn btn-default"
+ ng-class="{disabled : on_first_rs_page()}"
+ ng-disabled="on_first_rs_page()"
+ ng-click="decrement_rs_page()"
+ title="[% l('Previous Page') %]">
+ <span class="glyphicon glyphicon-backward"></span>
+ </button>
+
+ <!-- next page -->
+ <!-- todo: paging needs a total count value to be fully functional -->
+ <button type="button" class="btn btn-default"
+
+ ng-class="{disabled : !has_next_rs_page()}"
+ ng-disabled="!has_next_rs_page()"
+ ng-click="increment_rs_page()"
+ title="[% l('Next Page') %]">
+ <span class="glyphicon glyphicon-forward"></span>
+ </button>
+ </div>
<button class="btn btn-default" ng-click="new_notification()">
[% l('Add Record of Notification') %]
</button>
<div class="row pad-vert"
- ng-repeat="notify in hold.notifications()">
+ ng-repeat="notify in filteredResets">
<div class="col-md-12">
<div class="row">
<div class="col-md-6 strong-text">{{notify.method()}}</div>
</div>
</div>
</div><!-- notes tab content -->
+
+ <div ng-if="detail_tab == 'resets'">
+ <div class="btn-group column-picker">
+ <!-- change order -->
+ <button type="button" class="btn btn-default"
+ ng-click="reverse_reset_order()"
+ title="[% l('Reverse Order') %]">
+ <span class="glyphicon {{reverseResetOrder ? 'glyphicon-chevron-up' : 'glyphicon-chevron-down' }}"></span>
+ </button>
+
+ <!-- first page -->
+ <button type="button" class="btn btn-default"
+
+ ng-class="{disabled : on_first_rs_page()}"
+ ng-disabled="on_first_rs_page()"
+ ng-click="first_rs_page()"
+ title="[% l('Start') %]">
+ <span class="glyphicon glyphicon-fast-backward"></span>
+ </button>
+
+ <!-- previous page -->
+ <button type="button" class="btn btn-default"
+
+ ng-class="{disabled : on_first_rs_page()}"
+ ng-disabled="on_first_rs_page()"
+ ng-click="decrement_rs_page()"
+ title="[% l('Previous Page') %]">
+ <span class="glyphicon glyphicon-backward"></span>
+ </button>
+
+ <!-- next page -->
+ <!-- todo: paging needs a total count value to be fully functional -->
+ <button type="button" class="btn btn-default"
+
+ ng-class="{disabled : !has_next_rs_page()}"
+ ng-disabled="!has_next_rs_page()"
+ ng-click="increment_rs_page()"
+ title="[% l('Next Page') %]">
+ <span class="glyphicon glyphicon-forward"></span>
+ </button>
+ </div>
+ <div ng-show="!resetsLoaded" style="text-align:center;">
+ <img src='[% ctx.media_prefix %]/opac/images/progressbar_green.gif[% ctx.cache_key %]' style='height:32px;width:32px;' alt='[% l("Search In Progress") %]'/>
+ </div>
+ <div class="flex-container-striped flex-container-bordered" ng-show="resetsLoaded && filteredResets.length">
+ <div class="flex-row">
+ <div class="flex-cell strong-text">Time</div>
+ <div class="flex-cell strong-text">Reason</div>
+ <div class="flex-cell strong-text">Requestor</div>
+ <div class="flex-cell strong-text">Note</div>
+ <div class="flex-cell strong-text">Previous Copy</div>
+ </div>
+ <div class="flex-row" ng-repeat="reset in filteredResets">
+ <div class="flex-cell">{{reset.reset_time() | date:$root.egDateAndTimeFormat}}</div>
+ <div class="flex-cell">{{reset.reset_reason().name()}}</div>
+ <div class="flex-cell">{{reset.requestor().usrname()}}</div>
+ <div class="flex-cell">{{reset.note()}}</div>
+ <div class="flex-cell">
+ <a href="./cat/item/{{reset.previous_copy().id()}}" target="_self">
+ {{reset.previous_copy().barcode()}}
+ </a>
+ </div>
+ </div>
+ </div>
+ <div class="flex-container-striped flex-container-bordered" ng-show="resetsLoaded && !filteredResets.length">
+ <div class="flex-row">
+ [%- l('No reset entries found for this hold.') -%]
+ </div>
+ </div>
+ </div><!-- resets tab content -->
</div><!-- tab pane -->
</div><!-- tab-content -->
// if set, called whenever hold details are retrieved. The
// argument is the hold blob returned from hold.details.retrieve
holdRetrieved : '=',
- showPatron : '='
+ showPatron : '=',
},
controller : [
'$scope','$uibModal','egCore','egHolds','egCirc',
});
}
+
+ $scope.resetPage = 1;
+ $scope.resetsPerPage = 10;
+ $scope.maximumPages = 25;
+ $scope.resetsLoaded = false;
+ $scope.reverseResetOrder = false;
+
+ $scope.show_resets_tab = function() {
+ $scope.detail_tab = 'resets';
+ egCore.pcrud.search('ahrrre',
+ {hold : $scope.hold.id()},
+ {
+ flesh : 1,
+ flesh_fields : {ahrrre : ['reset_reason','requestor','previous_copy']},
+ limit : $scope.resetsPerPage * $scope.maximumPages
+ },
+ {atomic : true}
+ ).then(function(ents) {
+ // sort the reset notes by date
+ ents.sort(
+ function(a,b){
+ return Date.parse(a.reset_time()) - Date.parse(b.reset_time());
+ }
+ );
+ $scope.hold.reset_entries(ents);
+ $scope.filter_resets();
+ $scope.resetsLoaded = true;
+ });
+ }
+
+ $scope.filter_resets = function(){
+ if(
+ typeof($scope.hold) === 'undefined' ||
+ typeof($scope.hold.reset_entries) === 'undefined' ||
+ $scope.hold.reset_entries() === null
+ )
+ return;
+ var begin = (($scope.resetPage - 1) * $scope.resetsPerPage),
+ end = begin + $scope.resetsPerPage;
+ $scope.filteredResets = $scope.hold
+ .reset_entries()
+ .slice(begin,end);
+ }
+
+ $scope.reverse_reset_order = function(){
+ $scope.hold.reset_entries().reverse()
+ $scope.reverseResetOrder = !$scope.reverseResetOrder;
+ $scope.first_rs_page();
+ }
+
+ $scope.on_first_rs_page = function(){
+ return $scope.resetPage == 1;
+ }
+
+ $scope.has_next_rs_page = function(){
+ return $scope.resetPage < $scope.max_rs_pages();
+ }
+
+ $scope.max_rs_pages = function(){
+ if(typeof($scope.hold.reset_entries) === 'undefined' || $scope.hold.reset_entries() === null)
+ return 0;
+ return $scope.hold.reset_entries().length/$scope.resetsPerPage;
+ }
+
+ $scope.first_rs_page = function() {
+ $scope.resetPage = 1;
+ }
+
+ $scope.increment_rs_page = function() {
+ $scope.resetPage++;
+ }
+ $scope.decrement_rs_page = function() {
+ $scope.resetPage--;
+ }
+
+ $scope.$watch('resetPage',$scope.filter_resets);
+ $scope.$watch('reverseResetOrder',$scope.filter_resets);
+
$scope.show_notify_tab = function() {
$scope.detail_tab = 'notify';
egCore.pcrud.search('ahn',