From ebf0f290dd7dd525c16ca2df9107a93bb6696514 Mon Sep 17 00:00:00 2001 From: Kyle M Hall Date: Mon, 1 Jun 2015 09:02:21 -0400 Subject: [PATCH] Bug 14310 - Suspend and resume indvidual holds from patron holds table This enhancment adds the ability to suspend and resume individual holds from the holds table on circulation.pl and moremember.pl. The interface is inspired/cribbed from the same feature already available in the opac. Test Plan: 1) Apply this patch 2) Find a patron with holds 3) Suspend a hold with no resume date 4) Resume the suspended hold 5) Suspend a hold with a resume date 6) Resume the suspended hold --- Koha/Hold.pm | 43 ++++++++++- koha-tmpl/intranet-tmpl/prog/en/js/holds.js | 87 ++++++++++++++++++-- .../prog/en/modules/circ/circulation.tt | 1 + .../prog/en/modules/members/moremember.tt | 1 + svc/hold/resume | 48 +++++++++++ svc/hold/suspend | 51 ++++++++++++ 6 files changed, 222 insertions(+), 9 deletions(-) create mode 100755 svc/hold/resume create mode 100755 svc/hold/suspend diff --git a/Koha/Hold.pm b/Koha/Hold.pm index 1b743e8..d476f88 100644 --- a/Koha/Hold.pm +++ b/Koha/Hold.pm @@ -41,6 +41,47 @@ Koha::Hold - Koha Hold object class =cut +=head3 suspend_hold + +my $hold = $hold->suspend_hold( $suspend_until_dt ); + +=cut + +sub suspend_hold { + my ( $self, $dt ) = @_; + + if ( $self->is_waiting ) { # We can't suspend waiting holds + carp "Unable to suspend waiting hold!"; + return $self; + } + + $dt ||= undef; + + $self->suspend(1); + $self->suspend_until( $dt ); + + $self->store(); + + return $self; +} + +=head3 resume + +my $hold = $hold->resume(); + +=cut + +sub resume { + my ( $self ) = @_; + + $self->suspend(0); + $self->suspend_until( undef ); + + $self->store(); + + return $self; +} + =head3 waiting_expires_on Returns a DateTime for the date a waiting holds expires on. @@ -52,7 +93,7 @@ Returns undef if the hold is not waiting ( found = 'W' ). sub waiting_expires_on { my ($self) = @_; - return unless $self->found() eq 'W'; + return unless $self->found() && $self->found() eq 'W'; my $ReservesMaxPickUpDelay = C4::Context->preference('ReservesMaxPickUpDelay'); return unless $ReservesMaxPickUpDelay; diff --git a/koha-tmpl/intranet-tmpl/prog/en/js/holds.js b/koha-tmpl/intranet-tmpl/prog/en/js/holds.js index 077b3b6..bf7ea44 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/js/holds.js +++ b/koha-tmpl/intranet-tmpl/prog/en/js/holds.js @@ -8,11 +8,12 @@ $(document).ready(function() { if ( $("#holds-tab").parent().hasClass('ui-state-active') ) { load_holds_table() } function load_holds_table() { + var holds = new Array(); if ( ! holdsTable ) { holdsTable = $("#holds-table").dataTable({ "bAutoWidth": false, "sDom": "rt", - "aoColumns": [ + "columns": [ { "mDataProp": "reservedate_formatted" }, @@ -119,21 +120,53 @@ $(document).ready(function() { + "" + ""; } + }, + { + "bSortable": false, + "mDataProp": function( oObj ) { + holds[oObj.reserve_id] = oObj; //Store holds for later use + + if ( oObj.found ) { + return ""; + } else if ( oObj.suspend == 1 ) { + return "" + + " " + _("Resume") + ""; + } else { + return "" + + " " + _("Suspend") + ""; + } + } } ], "bPaginate": false, "bProcessing": true, "bServerSide": false, - "sAjaxSource": '/cgi-bin/koha/svc/holds', - "fnServerData": function ( sSource, aoData, fnCallback ) { - aoData.push( { "name": "borrowernumber", "value": borrowernumber } ); - - $.getJSON( sSource, aoData, function (json) { - fnCallback(json) - } ); + "ajax": { + "url": '/cgi-bin/koha/svc/holds', + "data": function ( d ) { + d.borrowernumber = borrowernumber; + } }, }); + $('#holds-table').on( 'draw.dt', function () { + $(".hold-suspend").on( "click", function() { + var id = $(this).attr("id").replace("suspend", ""); + var hold = holds[id]; + $("#suspend-modal-title").html( hold.title ); + $("#suspend-modal-reserve_id").val( hold.reserve_id ); + $('#suspend-modal').modal('show'); + }); + + $(".hold-resume").on( "click", function() { + var id = $(this).attr("id").replace("resume", ""); + var hold = holds[id]; + $.post('/cgi-bin/koha/svc/hold/resume', { "reserve_id": hold.reserve_id }, function( data ){ + holdsTable.api().ajax.reload(); + }); + }); + }); + if ( $("#holds-table").length ) { $("#holds-table_processing").position({ of: $( "#holds-table" ), @@ -142,4 +175,42 @@ $(document).ready(function() { } } } + + $("body").append("\ + \ + "); + + $("#suspend-modal-until").datepicker({ minDate: 1 }); // Require that "until date" be in the future + $("#suspend-modal-clear-date").on( "click", function() { $("#suspend-modal-until").val(""); } ); + + $("#suspend-modal-submit").on( "click", function( e ) { + e.preventDefault(); + $.post('/cgi-bin/koha/svc/hold/suspend', $('#suspend-modal-form').serialize(), function( data ){ + $('#suspend-modal').modal('hide'); + holdsTable.api().ajax.reload(); + }); + }); + }); diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt index 9b58f2c..594d225 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt @@ -895,6 +895,7 @@ No patron matched [% message %] Expiration Priority Delete? + Suspend? diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt index 8ddb526..ecce9c7 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt @@ -484,6 +484,7 @@ function validate1(date) { Expiration Priority Delete? + Suspend? diff --git a/svc/hold/resume b/svc/hold/resume new file mode 100755 index 0000000..03cd017 --- /dev/null +++ b/svc/hold/resume @@ -0,0 +1,48 @@ +#!/usr/bin/perl + +# Copyright 2015 ByWater Solutions +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Koha; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +use Modern::Perl; + +use CGI; +use JSON qw(to_json); + +use C4::Context; +use C4::Auth qw(check_cookie_auth); +use Koha::DateUtils qw(dt_from_string); +use Koha::Holds; + +my $input = new CGI; + +my ( $auth_status, $sessionID ) = + check_cookie_auth( $input->cookie('CGISESSID'), + { circulate => 'circulate_remaining_permissions' } ); + +if ( $auth_status ne "ok" ) { + exit 0; +} + +binmode STDOUT, ":encoding(UTF-8)"; +print $input->header( -type => 'text/plain', -charset => 'UTF-8' ); + +my $reserve_id = $input->param('reserve_id'); + +my $hold = Koha::Holds->find( $reserve_id ); +$hold->resume(); + +print to_json( { success => !$hold->suspend() } ); diff --git a/svc/hold/suspend b/svc/hold/suspend new file mode 100755 index 0000000..880e41a --- /dev/null +++ b/svc/hold/suspend @@ -0,0 +1,51 @@ +#!/usr/bin/perl + +# Copyright 2015 ByWater Solutions +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Koha; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +use Modern::Perl; + +use CGI; +use JSON qw(to_json); + +use C4::Context; +use C4::Auth qw(check_cookie_auth); +use Koha::DateUtils qw(dt_from_string); +use Koha::Holds; + +my $input = new CGI; + +my ( $auth_status, $sessionID ) = + check_cookie_auth( $input->cookie('CGISESSID'), + { circulate => 'circulate_remaining_permissions' } ); + +if ( $auth_status ne "ok" ) { + exit 0; +} + +binmode STDOUT, ":encoding(UTF-8)"; +print $input->header( -type => 'text/plain', -charset => 'UTF-8' ); + +my $reserve_id = $input->param('reserve_id'); + +my $suspend_until = $input->param('suspend_until') || undef; +$suspend_until = dt_from_string( $suspend_until ) if $suspend_until; + +my $hold = Koha::Holds->find( $reserve_id ); +$hold->suspend_hold( $suspend_until ); + +print to_json( { success => $hold->suspend() } ); -- 1.7.2.5