@@ -, +, @@ pull' list - "Allow to mark items as lost" - "Allow to mark items as lost and notify the patron" --- circ/pendingreserves.pl | 93 +++++++++++++++++++++- installer/data/mysql/atomicupdate/bug_19287.sql | 5 ++ installer/data/mysql/sysprefs.sql | 2 + .../en/modules/admin/preferences/circulation.pref | 12 +++ .../prog/en/modules/circ/pendingreserves.tt | 44 ++++++++++ 5 files changed, 154 insertions(+), 2 deletions(-) create mode 100644 installer/data/mysql/atomicupdate/bug_19287.sql --- a/circ/pendingreserves.pl +++ a/circ/pendingreserves.pl @@ -25,16 +25,21 @@ use C4::Context; use C4::Output; use CGI qw ( -utf8 ); use C4::Auth; -use Koha::Biblios; use C4::Debug; +use C4::Items qw( ModItem ModItemTransfer ); +use C4::Reserves qw( ModReserveCancelAll ); +use Koha::Biblios; use Koha::DateUtils; +use Koha::Holds; use DateTime::Duration; my $input = new CGI; my $startdate = $input->param('from'); my $enddate = $input->param('to'); - my $theme = $input->param('theme'); # only used if allowthemeoverride is set +my $op = $input->param('op') || ''; +my $borrowernumber = $input->param('borrowernumber'); +my $reserve_id = $input->param('reserve_id'); my ( $template, $loggedinuser, $cookie ) = get_template_and_user( { @@ -47,6 +52,80 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user( } ); +my @messages; +if ( $op eq 'cancel_reserve' and $reserve_id ) { + my $hold = Koha::Holds->find( $reserve_id ); + if ( $hold ) { + $hold->cancel; + push @messages, { type => 'message', code => 'hold_cancelled' }; + } +} elsif ( $op =~ m|^mark_as_lost| ) { + my $hold = Koha::Holds->find( $reserve_id ); + die "wrong reserve_id" unless $hold; # This is a bit rude, but we are not supposed to get a wrong reserve_id + my $item = $hold->item; + if ( $item and C4::Context->preference('CanMarkHoldsToPullAsLost') =~ m|^allow| ) { + my $patron = $hold->borrower; + C4::Circulation::LostItem( $item->itemnumber ); + if ( $op eq 'mark_as_lost_and_notify' and C4::Context->preference('CanMarkHoldsToPullAsLost') eq 'allow_and_notify' ) { + my $library = $hold->branch; + my $letter = C4::Letters::GetPreparedLetter( + module => 'reserves', + letter_code => 'CANCEL_HOLD_ON_LOST', + branchcode => $library->branchcode, # FIXME Is it what we want? + lang => $patron->lang, + tables => { + branches => $library->branchcode, + borrowers => $patron->borrowernumber, + items => $item->itemnumber, + biblio => $hold->biblionumber, + biblioitems => $hold->biblionumber, + reserves => $hold->unblessed, + }, + ); + if ( $letter ) { + my $admin_email_address = $library->branchemail || C4::Context->preference('KohaAdminEmailAddress'); + + C4::Letters::EnqueueLetter( + { letter => $letter, + borrowernumber => $patron->borrowernumber, + message_transport_type => 'email', + from_address => $admin_email_address, + } + ); + unless ( C4::Members::GetNoticeEmailAddress( $patron->borrowernumber ) ) { + push @messages, {type => 'alert', code => 'no_email_address', }; + } + push @messages, { type => 'message', code => 'letter_enqueued' }; + } else { + push @messages, { type => 'error', code => 'no_template_notice' }; + } + } + $hold->cancel; + if ( $item->homebranch ne $item->holdingbranch ) { + C4::Items::ModItemTransfer( $item->itemnumber, $item->holdingbranch, $item->homebranch ); + } + + if ( my $yaml = C4::Context->preference('UpdateItemWhenLostFromHoldList') ) { + $yaml = "$yaml\n\n"; # YAML is anal on ending \n. Surplus does not hurt + my $assignments; + eval { $assignments = YAML::Load($yaml); }; + if ($@) { + warn "Unable to parse UpdateItemWhenLostFromHoldList syspref : $@" if $@; + } + else { + eval { + C4::Items::ModItem( $assignments, undef, $item->itemnumber ); + }; + warn "Unable to modify item itemnumber=" . $item->itemnumber . ": $@" if $@; + } + } + + } elsif ( not $item ) { + push @messages, { type => 'alert', code => 'hold_placed_at_biblio_level'}; + } # else the url parameters have been modified and the user is not allowed to continue +} + + my $today = dt_from_string; if ( $startdate ) { @@ -91,11 +170,16 @@ if ($enddate_iso) { my $strsth = "SELECT min(reservedate) as l_reservedate, + reserves.reserve_id, reserves.borrowernumber as borrowernumber, + GROUP_CONCAT(DISTINCT items.holdingbranch ORDER BY items.itemnumber SEPARATOR '|') l_holdingbranch, reserves.biblionumber, reserves.branchcode as l_branch, + items.itemnumber, + items.holdingbranch, + items.homebranch, GROUP_CONCAT(DISTINCT items.itype ORDER BY items.itemnumber SEPARATOR '|') l_itype, GROUP_CONCAT(DISTINCT items.location @@ -167,6 +251,10 @@ while ( my $data = $sth->fetchrow_hashref ) { pullcount => $data->{icount} <= $data->{rcount} ? $data->{icount} : $data->{rcount}, itypes => [split('\|', $data->{l_itype})], locations => [split('\|', $data->{l_location})], + reserve_id => $data->{reserve_id}, + holdingbranch => $data->{holdingbranch}, + homebranch => $data->{homebranch}, + itemnumber => $data->{itemnumber}, } ); } @@ -180,6 +268,7 @@ $template->param( "BiblioDefaultView".C4::Context->preference("BiblioDefaultView") => 1, HoldsToPullStartDate => C4::Context->preference('HoldsToPullStartDate') || PULL_INTERVAL, HoldsToPullEndDate => C4::Context->preference('ConfirmFutureHolds') || 0, + messages => \@messages, ); output_html_with_http_headers $input, $cookie, $template->output; --- a/installer/data/mysql/atomicupdate/bug_19287.sql +++ a/installer/data/mysql/atomicupdate/bug_19287.sql @@ -0,0 +1,5 @@ +INSERT IGNORE INTO systempreferences ( `variable`, `value`, `options`, `explanation`, `type` ) VALUES ('CanMarkHoldsToPullAsLost','do_not_allow','do_not_allow|allow|allow_and_notify','Add a button to the "Holds to pull" screen to mark an item as lost and notify the patron.','Choice'); + +INSERT IGNORE INTO letter(module, code, branchcode, name, is_html, title, content, message_transport_type, lang) VALUES ('reserves', 'CANCEL_HOLD_ON_LOST', '', 'Hold has been cancelled', 0, "Hold has been cancelled", "Dear [% borrower.firstname %] [% borrower.surname %],\n\nWe regret to inform you that the following item cannot longer be placed on hold, it has been marked as lost\n\nTitle: [% biblio.title %]\nAuthor: [% biblio.author %]\nCopy: [% item.copynumber %]\nLocation: [% branch.branchname %]", 'email', 'default'); + +INSERT IGNORE INTO systempreferences ( `variable`, `value`, `options`, `explanation`, `type` ) VALUES ('UpdateItemWhenLostFromHoldList','',NULL,'This is a list of values to update an item when it is marked as lost from the holds to pull screen','Free'); --- a/installer/data/mysql/sysprefs.sql +++ a/installer/data/mysql/sysprefs.sql @@ -93,6 +93,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('BranchTransferLimitsType','ccode','itemtype|ccode','When using branch transfer limits, choose whether to limit by itemtype or collection code.','Choice'), ('CalculateFinesOnReturn','1','','Switch to control if overdue fines are calculated on return or not','YesNo'), ('CalendarFirstDayOfWeek','0','0|1|2|3|4|5|6','Select the first day of week to use in the calendar.','Choice'), +('CanMarkHoldsToPullAsLost','do_not_allow','do_not_allow|allow|allow_and_notify','Add a button to the "Holds to pull" screen to mark an item as lost and notify the patron.','Choice'), ('canreservefromotherbranches','1','','With Independent branches on, can a user from one library place a hold on an item from another library','YesNo'), ('CardnumberLength', '', '', 'Set a length for card numbers with a maximum of 32 characters.', 'Free'), ('casAuthentication','0','','Enable or disable CAS authentication','YesNo'), @@ -558,6 +559,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('UNIMARCAuthorityField100','afrey50 ba0',NULL,'Define the contents of UNIMARC authority control field 100 position 08-35','Textarea'), ('UNIMARCAuthorsFacetsSeparator',', ',NULL,'UNIMARC authors facets separator','short'), ('UNIMARCField100Language','fre',NULL,'UNIMARC field 100 default language','short'), +('UpdateItemWhenLostFromHoldList','',NULL,'This is a list of values to update an item when it is marked as lost from the holds to pull screen','Free'), ('UniqueItemFields','barcode','','Space-separated list of fields that should be unique (used in acquisition module for item creation). Fields must be valid SQL column names of items table','Free'), ('UpdateNotForLoanStatusOnCheckin', '', 'NULL', 'This is a list of value pairs. When an item is checked in, if the not for loan value on the left matches the items not for loan value it will be updated to the right-hand value. E.g. ''-1: 0'' will cause an item that was set to ''Ordered'' to now be available for loan. Each pair of values should be on a separate line.', 'Free'), ('UpdateTotalIssuesOnCirc','0',NULL,'Whether to update the totalissues field in the biblio on each circ.','YesNo'), --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref @@ -702,6 +702,18 @@ Circulation: - "Patron categories not affected by OPACHoldsIfAvailableAtPickup" - pref: OPACHoldsIfAvailableAtPickupExceptions - "(list of patron categories separated with a pipe '|')" + - + - pref: CanMarkHoldsToPullAsLost + choices: + do_not_allow: "Do not allow to mark items as lost" + allow: "Allow to mark items as lost" + allow_and_notify: "Allow to mark items as lost and notify the patron" + - "from the 'Holds to pull' screen" + - + - Update item's values when marked as lost from the hold to pull screen + - pref: UpdateItemWhenLostFromHoldList + type: textarea + - This is a list of values to update an item when it is marked as lost from the holds to pull screen. Interlibrary Loans: - - pref: ILLModule --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/pendingreserves.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/pendingreserves.tt @@ -1,3 +1,4 @@ +[% USE Koha %] [% USE KohaDates %] [% USE ColumnsSettings %] [% USE AuthorisedValues %] @@ -22,6 +23,24 @@
+ [% FOR m IN messages %] +
+ [% SWITCH m.code %] + [% CASE 'letter_enqueued' %] + The notice has been correctly enqueued. + [% CASE 'no_email_address' %] + The patron does not have an email address defined. + [% CASE 'no_template_notice' %] + There is no notice template with a code 'CANCEL_HOLD_ON_LOST' defined in your system. + [% CASE 'hold_cancelled' %] + The hold has been correctly cancelled. + [% CASE 'hold_placed_at_biblio_level' %] + The hold has been placed at biblio level. It is not possible to mark it as lost. + [% CASE %] + [% m.code %] + [% END %] +
+ [% END %]

Holds to pull placed between [% from | $KohaDates %] and [% to | $KohaDates %]

Reported on [% todaysdate | $KohaDates %]

@@ -43,6 +62,7 @@ Available itypes Available locations Earliest hold date + Action @@ -87,6 +107,29 @@ [% reserveloo.reservedate | $KohaDates %] in [% Branches.GetName ( reserveloo.branch ) %] + +
+ + + [% IF reserveloo.holdingbranch != reserveloo.homebranch %] + + [% ELSE %] + + [% END %] +
+ + [% IF Koha.Preference('CanMarkHoldsToPullAsLost') != 'do_not_allow' %] +
+ + [% IF Koha.Preference('CanMarkHoldsToPullAsLost') == 'allow' %] + + + [% ELSIF Koha.Preference('CanMarkHoldsToPullAsLost') == 'allow_and_notify' %] + + + [% END %] +
+ [% END %] [% END %] @@ -104,6 +147,7 @@ + --