From acd8dc3cc3b8cb85bfd6876f17b1f97dcbe26012 Mon Sep 17 00:00:00 2001 From: Matthias Meusburger Date: Tue, 6 Sep 2016 16:43:04 +0200 Subject: [PATCH] Bug 23258: Batch holding This patch allows to batch place or cancel holds. Test plan: 1) Apply the patch 2) Go to Circulation -> Batch holding 3) Check that you can either upload a barcode file or use the textarea 4) Check that you can place holds on items 5) Check that you can cancel holds on items --- circ/batch_holding.pl | 181 +++++++++++++ .../prog/en/modules/circ/batch_holding.tt | 293 +++++++++++++++++++++ .../prog/en/modules/circ/circulation-home.tt | 6 +- 3 files changed, 479 insertions(+), 1 deletion(-) create mode 100755 circ/batch_holding.pl create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/circ/batch_holding.tt diff --git a/circ/batch_holding.pl b/circ/batch_holding.pl new file mode 100755 index 0000000..1e273f8 --- /dev/null +++ b/circ/batch_holding.pl @@ -0,0 +1,181 @@ +#!/usr/bin/perl + +# Copyright 2019 BibLibre +# +# 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, see . + +use Modern::Perl; +use CGI qw ( -utf8 ); + +use C4::Output; +use C4::Auth; +use Koha::Items; +use C4::Reserves; +use List::MoreUtils qw/uniq/; + +my $input = new CGI; +my $op = $input->param('op') // ''; +my @itemnumbers; + +my ( $template, $loggedinuser, $cookie ) = get_template_and_user( + { + template_name => "circ/batch_holding.tt", + query => $input, + type => "intranet", + authnotrequired => 0, + } +); + +if ( $op eq "show" ) { + my $filefh = $input->upload('uploadfile'); + my $filecontent = $input->param('filecontent'); + my $borrowernumber = $input->param('borrowernumber'); + my $branch = $input->param('branch'); + my $action = $input->param('action'); + my @notfoundbarcodes; + + my @contentlist; + if ($filefh) { + while ( my $content = <$filefh> ) { + $content =~ s/[\r\n]*$//; + push @contentlist, $content if $content; + } + + foreach my $barcode (@contentlist) { + my $item = Koha::Items->find( { barcode => $barcode } ); + if ($item) { + push @itemnumbers, $item->itemnumber; + } + else { + push @notfoundbarcodes, $barcode; + } + } + } + else { + if ( my $list = $input->param('barcodelist') ) { + push my @barcodelist, uniq( split( /\s\n/, $list ) ); + + foreach my $barcode (@barcodelist) { + + my $item = Koha::Items->find( { barcode => $barcode } ); + if ($item) { + push @itemnumbers, $item->itemnumber; + } + else { + push @notfoundbarcodes, $barcode; + } + } + + } + } + if (@notfoundbarcodes) { + my @notfoundbarcodesloop = map { { barcode => $_ } } @notfoundbarcodes; + $template->param( notfoundbarcodes => \@notfoundbarcodesloop ); + } + my @holdloop; + if (@itemnumbers) { + foreach my $itemnumber (@itemnumbers) { + my $item = Koha::Items->find( { itemnumber => $itemnumber } ); + my $biblio = + Koha::Biblios->find( { biblionumber => $item->biblionumber } ); + my $holdable = + CanItemBeReserved( $borrowernumber, $item->itemnumber )->{status}; + push @holdloop, + { + 'biblionumber' => $biblio->biblionumber, + 'title' => $biblio->title, + 'itemnumber' => $item->itemnumber, + 'barcode' => $item->barcode, + 'holdable' => ( $action eq "cancel" || $holdable eq 'OK' ) + ? 1 + : 0, + }; + } + + } + my $borrower = Koha::Patrons->find( { borrowernumber => $borrowernumber } ); + $template->param( + show => 1, + holdloop => \@holdloop, + borrowernumber => $borrowernumber, + borrowersurname => $borrower->surname, + borrowerfirstname => $borrower->firstname, + branch => $branch, + action => $action, + op => $op + ); +} + +elsif ( $op eq "result" ) { + my $branch = $input->param('branch'); + my $borrowernumber = $input->param('borrowernumber'); + my $action = $input->param('action'); + my @itemnumbers = $input->multi_param('holdable'); + my @holdloop; + foreach my $itemnumber (@itemnumbers) { + if ( $action eq "place" ) { + my $item = Koha::Items->find( { itemnumber => $itemnumber } ); + my $biblionumber = $item->biblionumber; + my $biblio = + Koha::Biblios->find( { biblionumber => $item->biblionumber } ); + my $reserve_id = AddReserve( + { + branchcode => $branch, + borrowernumber => $borrowernumber, + biblionumber => $biblionumber, + itemnumber => $itemnumber + } + ); + push @holdloop, + { + 'biblionumber' => $biblio->biblionumber, + 'title' => $biblio->title, + 'itemnumber' => $itemnumber, + 'barcode' => $item->barcode, + 'reserve_id' => $reserve_id, + }; + } + else { + my $holds = Koha::Holds->search( + { + itemnumber => $itemnumber, + borrowernumber => $borrowernumber + } + ); + if ($holds) { + while ( my $hold = $holds->next ) { + $hold->cancel; + } + + push @holdloop, { 'itemnumber' => $itemnumber, }; + } + } + } + my $borrower = Koha::Patrons->find( { borrowernumber => $borrowernumber } ); + $template->param( + result => 1, + holdloop => \@holdloop, + borrowernumber => $borrowernumber, + borrowersurname => $borrower->surname, + borrowerfirstname => $borrower->firstname, + branch => $branch, + cancel => $action eq "cancel" ? 1 : 0, + place => $action eq "place" ? 1 : 0, + op => $op + ); + +} +output_html_with_http_headers $input, $cookie, $template->output; diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/batch_holding.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/batch_holding.tt new file mode 100644 index 0000000..0c72910 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/batch_holding.tt @@ -0,0 +1,293 @@ +[% USE Koha %] +[% USE Branches %] +[% SET footerjs = 1 %] +[% INCLUDE 'doc-head-open.inc' %] + + Koha › + Circulation › + [% IF ( op == "show" ) %] + Batch place or cancel holds › + Confirm selection + [% ELSIF ( op == "result") %] + Batch place or cancel holds › + Results + [% ELSE %] + Batch place or cancel holds + [% END %] + +[% INCLUDE 'doc-head-close.inc' %] + + + +[% INCLUDE 'header.inc' %] +[% INCLUDE 'cataloging-search.inc' %] + + +
+
+ [% IF Koha.Preference('CircSidebar') %] +
+ [% ELSE %] +
+ [% END %] +
+ + [% IF show %] + [% IF ( notfoundbarcodes ) %] +

Warning, the following barcodes were not found:

+ + + + + + + [% FOREACH notfoundbarcode IN notfoundbarcodes %] + + [% END %] + +
Barcodes not found
[% notfoundbarcode.barcode | html %]
+ [% END #/IF notfoundbarcodes %] + + [% IF (holdloop) %] + [% IF ( action == "place" ) %] +

Place holds on the following barcodes

+ [% ELSE %] +

Cancel holds on the following barcodes

+ [% END %] + + + +
+ + + + [% FOREACH hold IN holdloop %] + + + + + + + [% END %] + +
HoldTitleItemComment
+ + + [% hold.title | html %] + + [% hold.barcode | html %] + + [% IF !hold.holdable %] + + This item cannot be placed on hold + [% END %] +
+ + + + +
+ + Cancel +
+
+ [% ELSE %] +

No holds can be placed or cancelled.

+ Batch place or cancel other holds + [% END # /IF holdloop %] + + [% ELSIF result %] + + [% IF (holdloop) %] +

Results

+ [% IF place %] +

The following items have been placed on hold:

+ [% END %] + [% IF cancel %] +

The following holds were cancelled:

+ [% END %] + + + + + [% FOREACH hold IN holdloop %] + + + + + + [% END %] + +
TitleItemHolds
+ [% hold.title | html %] + + [% hold.barcode | html %] + + Show holds +
+ + [% ELSE %] +

No holds could be placed or cancelled.

+ [% END %] + +

Batch place or cancel other holds

+ + [% ELSE %] + +

Batch place or cancel holds

+
+
+ Use a barcode file + + +
+ +
+ Or scan items one by one +
    +
  1. + + +
  2. +
+
+ +
+ Place hold for +
    +
  1. + + +
    + + Required +
    +
    + Enter patron card number or partial name +
    +
  2. +
  3. + + +
  4. +
+
+ +
+ Action +
    +
  1. + + +
  2. +
  3. + + +
  4. +
+
+ +
+ + +
+
+ [% END # /IF show %] + +
+
+ [% IF Koha.Preference('CircSidebar') %] +
+ +
+ [% END %] +
+ +[% MACRO jsinclude BLOCK %] + +[% END %] + +[% INCLUDE 'intranet-bottom.inc' %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation-home.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation-home.tt index 2c5a6c6..937ac87 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation-home.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation-home.tt @@ -9,7 +9,8 @@ [% INCLUDE 'header.inc' %] [% INCLUDE 'circ-search.inc' %] - + -- 2.7.4