From 7950cf4a084768547af228b4ffb5cafcd277ccd5 Mon Sep 17 00:00:00 2001 From: Andrew Isherwood Date: Fri, 22 Nov 2019 11:08:53 +0000 Subject: [PATCH] Bug 24083: Add support for unseen_renewals This patch adds support for unseen renewals. Here we retrofit knowledge of unseen renewals and add the display of unseen renewal counts and warnings, in addition to adding the ability to specify a renewal as being "unseen". The functionality added here is goverened by the UnseenRenewals syspref. --- C4/Circulation.pm | 65 +++++++++++++++++++--- C4/ILSDI/Services.pm | 2 +- C4/SIP/ILS/Transaction/Renew.pm | 1 + Koha/CirculationRules.pm | 3 + Koha/REST/V1/Checkouts.pm | 4 +- api/v1/swagger/definitions/checkout.json | 4 ++ api/v1/swagger/parameters.json | 3 + api/v1/swagger/parameters/checkout.json | 7 +++ api/v1/swagger/paths/checkouts.json | 7 ++- circ/renew.pl | 10 +++- .../intranet-tmpl/prog/css/src/staff-global.scss | 12 ++++ .../prog/en/includes/checkouts-table.inc | 4 ++ .../intranet-tmpl/prog/en/includes/strings.inc | 3 + .../prog/en/modules/circ/circulation.tt | 1 + .../intranet-tmpl/prog/en/modules/circ/renew.tt | 29 ++++++++-- .../prog/en/modules/members/moremember.tt | 1 + koha-tmpl/intranet-tmpl/prog/js/checkouts.js | 26 +++++++-- .../opac-tmpl/bootstrap/en/modules/opac-user.tt | 46 +++++++++++++-- misc/cronjobs/automatic_renewals.pl | 2 +- offline_circ/download.pl | 1 + opac/opac-renew.pl | 2 +- opac/opac-user.pl | 10 +++- svc/checkouts | 12 +++- svc/renew | 3 +- 24 files changed, 225 insertions(+), 33 deletions(-) diff --git a/C4/Circulation.pm b/C4/Circulation.pm index 813c064fd6..d4f48aa786 100644 --- a/C4/Circulation.pm +++ b/C4/Circulation.pm @@ -2782,6 +2782,7 @@ sub CanBookBeRenewed { 'no_auto_renewal_after_hard_limit', 'lengthunit', 'norenewalbefore', + 'unseen_renewals_allowed' ] } ); @@ -2789,6 +2790,11 @@ sub CanBookBeRenewed { return ( 0, "too_many" ) if not $issuing_rule->{renewalsallowed} or $issuing_rule->{renewalsallowed} <= $issue->renewals; + return ( 0, "too_unseen" ) + if C4::Context->preference('UnseenRenewals') && + $issuing_rule->{unseen_renewals_allowed} && + $issuing_rule->{unseen_renewals_allowed} <= $issue->unseen_renewals; + my $overduesblockrenewing = C4::Context->preference('OverduesBlockRenewing'); my $restrictionblockrenewing = C4::Context->preference('RestrictionBlockRenewing'); $patron = Koha::Patrons->find($borrowernumber); # FIXME Is this really useful? @@ -2879,7 +2885,7 @@ sub CanBookBeRenewed { =head2 AddRenewal - &AddRenewal($borrowernumber, $itemnumber, $branch, [$datedue], [$lastreneweddate]); + &AddRenewal($borrowernumber, $itemnumber, $branch, [$datedue], [$lastreneweddate], [$seen]); Renews a loan. @@ -2899,6 +2905,10 @@ this parameter is not supplied, lastreneweddate is set to the current date. If C<$datedue> is the empty string, C<&AddRenewal> will calculate the due date automatically from the book's item type. +C<$seen> is a boolean flag indicating if the item was seen or not during the renewal. This +informs the incrementing of the unseen_renewals column. If this flag is not supplied, we +fallback to a true value + =cut sub AddRenewal { @@ -2907,6 +2917,10 @@ sub AddRenewal { my $branch = shift; my $datedue = shift; my $lastreneweddate = shift || DateTime->now(time_zone => C4::Context->tz); + my $seen = shift; + + # Fallback on a 'seen' renewal + $seen = defined $seen && $seen == 0 ? 0 : 1; my $item_object = Koha::Items->find($itemnumber) or return; my $biblio = $item_object->biblio; @@ -2959,15 +2973,35 @@ sub AddRenewal { } ); + # Increment the unseen renewals, if appropriate + # We only do so if the syspref is enabled and + # a maximum value has been set in the circ rules + my $unseen_renewals = $issue->unseen_renewals; + if (C4::Context->preference('UnseenRenewals')) { + my $rule = Koha::CirculationRules->get_effective_rule( + { categorycode => $patron->categorycode, + itemtype => $item_object->effective_itemtype, + branchcode => $circ_library->branchcode, + rule_name => 'unseen_renewals_allowed' + } + ); + if (!$seen && $rule && $rule->rule_value) { + $unseen_renewals++; + } else { + # If the renewal is seen, unseen should revert to 0 + $unseen_renewals = 0; + } + } + # Update the issues record to have the new due date, and a new count # of how many times it has been renewed. my $renews = ( $issue->renewals || 0 ) + 1; - my $sth = $dbh->prepare("UPDATE issues SET date_due = ?, renewals = ?, lastreneweddate = ? + my $sth = $dbh->prepare("UPDATE issues SET date_due = ?, renewals = ?, unseen_renewals = ?, lastreneweddate = ? WHERE borrowernumber=? AND itemnumber=?" ); - $sth->execute( $datedue->strftime('%Y-%m-%d %H:%M'), $renews, $lastreneweddate, $borrowernumber, $itemnumber ); + $sth->execute( $datedue->strftime('%Y-%m-%d %H:%M'), $renews, $unseen_renewals, $lastreneweddate, $borrowernumber, $itemnumber ); # Update the renewal count on the item, and tell zebra to reindex $renews = ( $item_object->renewals || 0 ) + 1; @@ -3049,8 +3083,11 @@ sub GetRenewCount { my ( $bornum, $itemno ) = @_; my $dbh = C4::Context->dbh; my $renewcount = 0; + my $unseencount = 0; my $renewsallowed = 0; + my $unseenallowed = 0; my $renewsleft = 0; + my $unseenleft = 0; my $patron = Koha::Patrons->find( $bornum ); my $item = Koha::Items->find($itemno); @@ -3069,22 +3106,34 @@ sub GetRenewCount { $sth->execute( $bornum, $itemno ); my $data = $sth->fetchrow_hashref; $renewcount = $data->{'renewals'} if $data->{'renewals'}; + $unseencount = $data->{'unseen_renewals'} if $data->{'unseen_renewals'}; # $item and $borrower should be calculated my $branchcode = _GetCircControlBranch($item->unblessed, $patron->unblessed); - my $rule = Koha::CirculationRules->get_effective_rule( + my $rules = Koha::CirculationRules->get_effective_rules( { categorycode => $patron->categorycode, itemtype => $item->effective_itemtype, branchcode => $branchcode, - rule_name => 'renewalsallowed', + rules => [ 'renewalsallowed', 'unseen_renewals_allowed' ] } ); - - $renewsallowed = $rule ? $rule->rule_value : 0; + $renewsallowed = $rules ? $rules->{renewalsallowed} : 0; + $unseenallowed = $rules->{unseen_renewals_allowed} ? + $rules->{unseen_renewals_allowed} : + 0; $renewsleft = $renewsallowed - $renewcount; + $unseenleft = $unseenallowed - $unseencount; if($renewsleft < 0){ $renewsleft = 0; } - return ( $renewcount, $renewsallowed, $renewsleft ); + if($unseenleft < 0){ $unseenleft = 0; } + return ( + $renewcount, + $renewsallowed, + $renewsleft, + $unseencount, + $unseenallowed, + $unseenleft + ); } =head2 GetSoonestRenewDate diff --git a/C4/ILSDI/Services.pm b/C4/ILSDI/Services.pm index 64caa4a6fa..3d7a6cc3b3 100644 --- a/C4/ILSDI/Services.pm +++ b/C4/ILSDI/Services.pm @@ -644,7 +644,7 @@ sub RenewLoan { # Add renewal if possible my @renewal = CanBookBeRenewed( $borrowernumber, $itemnumber ); - if ( $renewal[0] ) { AddRenewal( $borrowernumber, $itemnumber ); } + if ( $renewal[0] ) { AddRenewal( $borrowernumber, $itemnumber, undef, undef, undef, 0 ); } my $issue = $item->checkout; return unless $issue; # FIXME should be handled diff --git a/C4/SIP/ILS/Transaction/Renew.pm b/C4/SIP/ILS/Transaction/Renew.pm index af96f93901..f046ba79b2 100644 --- a/C4/SIP/ILS/Transaction/Renew.pm +++ b/C4/SIP/ILS/Transaction/Renew.pm @@ -51,6 +51,7 @@ sub do_renew_for { } else { $renewerror=~s/on_reserve/Item unavailable due to outstanding holds/; $renewerror=~s/too_many/Item has reached maximum renewals/; + $renewerror=~s/too_unseen/Item has reached maximum consecutive renewals without being seen/; $renewerror=~s/item_denied_renewal/Item renewal is not allowed/; $self->screen_msg($renewerror); $self->renewal_ok(0); diff --git a/Koha/CirculationRules.pm b/Koha/CirculationRules.pm index c26f572d12..2e3518c952 100644 --- a/Koha/CirculationRules.pm +++ b/Koha/CirculationRules.pm @@ -145,6 +145,9 @@ our $RULE_KINDS = { renewalsallowed => { scope => [ 'branchcode', 'categorycode', 'itemtype' ], }, + unseen_renewals_allowed => { + scope => [ 'branchcode', 'categorycode', 'itemtype' ], + }, rentaldiscount => { scope => [ 'branchcode', 'categorycode', 'itemtype' ], }, diff --git a/Koha/REST/V1/Checkouts.pm b/Koha/REST/V1/Checkouts.pm index c3ae141e67..9f19f5de4e 100644 --- a/Koha/REST/V1/Checkouts.pm +++ b/Koha/REST/V1/Checkouts.pm @@ -151,6 +151,7 @@ sub renew { my $c = shift->openapi->valid_input or return; my $checkout_id = $c->validation->param('checkout_id'); + my $seen = $c->validation->param('seen') || 1; my $checkout = Koha::Checkouts->find( $checkout_id ); unless ($checkout) { @@ -173,7 +174,7 @@ sub renew { ); } - AddRenewal($borrowernumber, $itemnumber, $checkout->branchcode); + AddRenewal($borrowernumber, $itemnumber, $checkout->branchcode, undef, undef, $seen); $checkout = Koha::Checkouts->find($checkout_id); $c->res->headers->location( $c->req->url->to_string ); @@ -222,6 +223,7 @@ sub allows_renewal { allows_renewal => $renewable, max_renewals => $rule->rule_value, current_renewals => $checkout->renewals, + unseen_renewals => $checkout->unseen_renewals, error => $error } ); diff --git a/api/v1/swagger/definitions/checkout.json b/api/v1/swagger/definitions/checkout.json index 42b9598843..fb98afd28e 100644 --- a/api/v1/swagger/definitions/checkout.json +++ b/api/v1/swagger/definitions/checkout.json @@ -35,6 +35,10 @@ "type": ["integer", "null"], "description": "Number of renewals" }, + "unseen_renewals": { + "type": ["integer", "null"], + "description": "Number of consecutive unseen renewals" + }, "auto_renew": { "type": "boolean", "description": "Auto renewal" diff --git a/api/v1/swagger/parameters.json b/api/v1/swagger/parameters.json index adc455018c..7c9d190a51 100644 --- a/api/v1/swagger/parameters.json +++ b/api/v1/swagger/parameters.json @@ -32,6 +32,9 @@ "checkout_id_pp": { "$ref": "parameters/checkout.json#/checkout_id_pp" }, + "seen_pp": { + "$ref": "parameters/checkout.json#/seen_pp" + }, "match": { "name": "_match", "in": "query", diff --git a/api/v1/swagger/parameters/checkout.json b/api/v1/swagger/parameters/checkout.json index 2bdb20ab84..3b802f0c30 100644 --- a/api/v1/swagger/parameters/checkout.json +++ b/api/v1/swagger/parameters/checkout.json @@ -5,5 +5,12 @@ "description": "Internal checkout identifier", "required": true, "type": "integer" + }, + "seen_pp": { + "name": "seen", + "in": "query", + "description": "Item was seen flag", + "required": false, + "type": "integer" } } diff --git a/api/v1/swagger/paths/checkouts.json b/api/v1/swagger/paths/checkouts.json index ca6d970dbb..a97b9f0572 100644 --- a/api/v1/swagger/paths/checkouts.json +++ b/api/v1/swagger/paths/checkouts.json @@ -81,9 +81,10 @@ "x-mojo-to": "Checkouts#renew", "operationId": "renewCheckout", "tags": ["patrons", "checkouts"], - "parameters": [{ - "$ref": "../parameters.json#/checkout_id_pp" - }], + "parameters": [ + { "$ref": "../parameters.json#/checkout_id_pp" }, + { "$ref": "../parameters.json#/seen_pp" } + ], "produces": ["application/json"], "responses": { "201": { diff --git a/circ/renew.pl b/circ/renew.pl index df1e043bdb..d8bac409ad 100755 --- a/circ/renew.pl +++ b/circ/renew.pl @@ -44,6 +44,7 @@ my ( $template, $librarian, $cookie, $flags ) = get_template_and_user( my $schema = Koha::Database->new()->schema(); my $barcode = $cgi->param('barcode'); +my $unseen = $cgi->param('unseen') || 0; $barcode =~ s/^\s*|\s*$//g; # remove leading/trailing whitespae $barcode = barcodedecode($barcode) if( $barcode && C4::Context->preference('itemBarcodeInputFilter')); my $override_limit = $cgi->param('override_limit'); @@ -99,7 +100,14 @@ if ($barcode) { if ( $cgi->param('renewonholdduedate') ) { $date_due = dt_from_string( scalar $cgi->param('renewonholdduedate')); } - $date_due = AddRenewal( undef, $item->itemnumber(), $branchcode, $date_due ); + $date_due = AddRenewal( + undef, + $item->itemnumber(), + $branchcode, + $date_due, + undef, + !$unseen + ); $template->param( date_due => $date_due ); } } diff --git a/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss b/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss index 5e02ed1d3c..5febd28513 100644 --- a/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss +++ b/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss @@ -1004,6 +1004,10 @@ div { width: auto; } + .renew_formfield { + margin-bottom: 1em; + } + .circmessage { margin-bottom: .3em; padding: 0 .4em .4em; @@ -2404,6 +2408,14 @@ li { position: relative; } +#renew_as_unseen_label { + margin-left: 1em; +} + +#renew_as_unseen_checkbox { + margin-right: 1em; +} + #clearscreen { position: absolute; right: 0; diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table.inc index 7b967bec89..3183ff735c 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table.inc @@ -48,6 +48,10 @@ [% END %] [% END %] [% IF ( CAN_user_circulate_circulate_remaining_permissions ) %] + [% IF Koha.Preference( 'UnseenRenewals' ) %] + + + [% END %] [% END %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/strings.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/strings.inc index 5ef174db7c..2812067b23 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/strings.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/strings.inc @@ -11,6 +11,7 @@ var RETURN_CLAIMED_NOTES = _("Notes about return claim"); var NOT_CHECKED_OUT = _("not checked out"); var TOO_MANY_RENEWALS = _("too many renewals"); + var TOO_MANY_UNSEEN = _("too many consecutive renewals without being seen by the library"); var ON_RESERVE = _("on hold"); var REASON_UNKNOWN = _("reason unknown"); var TODAYS_CHECKOUTS = _("Today's checkouts"); @@ -19,6 +20,7 @@ var ON_HOLD = _("On hold"); var PLACE_HOLD = _("Place hold"); var NOT_RENEWABLE = _("Not renewable"); + var NOT_RENEWABLE_UNSEEN = _("Must be renewed at the library"); var NOT_RENEWABLE_TOO_SOON = _("No renewal before %s"); var NOT_RENEWABLE_AUTO_TOO_SOON = _("Scheduled for automatic renewal"); var NOT_RENEWABLE_AUTO_TOO_LATE = _("Can no longer be auto-renewed - number of checkout days exceeded"); @@ -27,6 +29,7 @@ var NOT_RENEWABLE_AUTO_RENEW = _("Scheduled for automatic renewal"); var NOT_RENEWABLE_DENIED = _("Renewal denied by syspref"); var RENEWALS_REMAINING = _("%s of %s renewals remaining"); + var UNSEEN_REMAINING = _("%s of %s unseen renewals remaining"); var HOLD_IS_SUSPENDED = _("Hold is suspended"); var UNTIL = _("until %s"); var NEXT_AVAILABLE_ITYPE = _("Next available %s item"); 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 1eeb19e3af..ec158fadf6 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt @@ -1030,6 +1030,7 @@ var logged_in_user_borrowernumber = "[% logged_in_user.borrowernumber | html %]"; var ClaimReturnedLostValue = "[% Koha.Preference('ClaimReturnedLostValue') | html %]"; var ClaimReturnedChargeFee = "[% Koha.Preference('ClaimReturnedChargeFee') | html %]"; + var UnseenRenewals = "[% Koha.Preference('UnseenRenewals') | html %]"; var ClaimReturnedWarningThreshold = "[% Koha.Preference('ClaimReturnedWarningThreshold') | html %]"; var MSG_DT_LOADING_RECORDS = _("Loading... you may continue scanning."); var interface = "[% interface | html %]"; diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/renew.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/renew.tt index 608ed5c84d..3fb11d4338 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/renew.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/renew.tt @@ -52,6 +52,18 @@ [% END %] + [% ELSIF error == "too_unseen" %] + +

[% INCLUDE 'biblio-title.inc' biblio=item.biblio %] ( [% item.barcode | html %] ) has been renewed the maximum number of consecutive times without being seen by the library )

+ + [% IF Koha.Preference('AllowRenewalLimitOverride') %] +
+ + + +
+ [% END %] + [% ELSIF error == "too_soon" %]

[% INCLUDE 'biblio-title.inc' biblio=item.biblio %] ( [% item.barcode | html %] ) cannot be renewed before [% soonestrenewdate | $KohaDates %].

@@ -168,10 +180,19 @@
Renew - - - - + [% IF Koha.Preference('UnseenRenewals') %] +
+ + +
+
+ + +
+ [% ELSE %] + + + [% END %]
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 19e573752d..f8e9793689 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt @@ -859,6 +859,7 @@ var ClaimReturnedLostValue = "[% Koha.Preference('ClaimReturnedLostValue') | html %]"; var ClaimReturnedChargeFee = "[% Koha.Preference('ClaimReturnedChargeFee') | html %]"; var ClaimReturnedWarningThreshold = "[% Koha.Preference('ClaimReturnedWarningThreshold') | html %]"; + var UnseenRenewals = "[% Koha.Preference('UnseenRenewals') | html %]"; var interface = "[% interface | html %]"; var theme = "[% theme | html %]"; var borrowernumber = "[% patron.borrowernumber | html %]"; diff --git a/koha-tmpl/intranet-tmpl/prog/js/checkouts.js b/koha-tmpl/intranet-tmpl/prog/js/checkouts.js index c1ca172f33..0d94953b1b 100644 --- a/koha-tmpl/intranet-tmpl/prog/js/checkouts.js +++ b/koha-tmpl/intranet-tmpl/prog/js/checkouts.js @@ -143,9 +143,15 @@ $(document).ready(function() { itemnumber: itemnumber, borrowernumber: borrowernumber, branchcode: branchcode, - override_limit: override_limit, + override_limit: override_limit }; + if (UnseenRenewals) { + var ren = $("#renew_as_unseen_checkbox"); + var renew_unseen = ren.length > 0 && ren.is(':checked') ? 1 : 0; + params.seen = renew_unseen === 1 ? 0 : 1; + } + // Determine which due date we need to use var dueDate = isOnReserve ? $("#newonholdduedate input").val() : @@ -168,6 +174,8 @@ $(document).ready(function() { content += NOT_CHECKED_OUT; } else if ( data.error == "too_many" ) { content += TOO_MANY_RENEWALS; + } else if ( data.error == "too_unseen" ) { + content += TOO_MANY_UNSEEN; } else if ( data.error == "on_reserve" ) { content += ON_RESERVE; } else if ( data.error == "restriction" ) { @@ -432,6 +440,13 @@ $(document).ready(function() { span_style = "display: none"; span_class = "renewals-allowed"; + } else if ( oObj.can_renew_error == "too_unseen" ) { + msg += "" + + NOT_RENEWABLE_UNSEEN + + ""; + + span_style = "display: none"; + span_class = "renewals-allowed"; } else if ( oObj.can_renew_error == "restriction" ) { msg += "" + NOT_RENEWABLE_RESTRICTION @@ -526,9 +541,12 @@ $(document).ready(function() { } content += msg; if ( can_renew || can_force_renew ) { - content += "(" - + RENEWALS_REMAINING.format( oObj.renewals_remaining, oObj.renewals_allowed ) - + ")"; + content += "("; + content += RENEWALS_REMAINING.format( oObj.renewals_remaining, oObj.renewals_allowed ); + if (UnseenRenewals && oObj.unseen_allowed) { + content += " / " + UNSEEN_REMAINING.format( oObj.unseen_remaining, oObj.unseen_allowed ); + } + content += ")"; } content += ""; diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt index 879867af0a..8d8d1dcf44 100644 --- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt +++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt @@ -81,6 +81,8 @@
  • Your account has expired. Please contact the library for more information.
  • [% ELSIF error == 'too_many' %]
  • You have renewed this item the maximum number of times allowed.
  • + [% ELSIF error == 'too_unseen' %] +
  • You have renewed this item the maximum number of consecutive times without it being seen by the library.
  • [% ELSIF error == 'too_soon' %]
  • It is too soon after the checkout date for this item to be renewed.
  • [% ELSIF error == 'on_reserve' %] @@ -309,27 +311,54 @@ [% IF ISSUE.itemtype_object.rentalcharge_hourly > 0 %] [% ISSUE.itemtype_object.rentalcharge_hourly | $Price %] per hour [% END %] - ([% ISSUE.renewsleft | html %] of [% ISSUE.renewsallowed | html %] renewals remaining) + ( + [% ISSUE.renewsleft | html %] of [% ISSUE.renewsallowed | html %] renewals remaining + [% IF Koha.Preference('UnseenRenewals') && ISSUE.unseenallowed %] + / [% ISSUE.unseenleft | html %] of [% ISSUE.unseenallowed | html %] renewals left before the item must be seen by the library + [% END %] + ) [% ELSIF ( ISSUE.on_reserve ) %] Not renewable (on hold) [% ELSIF ( ISSUE.too_many ) %] Not renewable + [% ELSIF ( ISSUE.too_unseen ) %] + Item must be seen by the library [% ELSIF ( ISSUE.norenew_overdue ) %] Not allowed (overdue) [% ELSIF ( ISSUE.auto_too_late ) %] No longer renewable [% ELSIF ISSUE.auto_too_much_oweing %] Automatic renewal failed, you have unpaid fines. - ([% ISSUE.renewsleft | html %] of [% ISSUE.renewsallowed | html %] renewals remaining) + ( + [% ISSUE.renewsleft | html %] of [% ISSUE.renewsallowed | html %] renewals remaining + [% IF Koha.Preference('UnseenRenewals') && ISSUE.unseenallowed %] + / [% ISSUE.unseenleft | html %] of [% ISSUE.unseenallowed | html %] renewals left before the item must be seen by the library + [% END %] + ) [% ELSIF ISSUE.auto_account_expired %] Automatic renewal failed, your account is expired. - ([% ISSUE.renewsleft | html %] of [% ISSUE.renewsallowed | html %] renewals remaining) + ( + [% ISSUE.renewsleft | html %] of [% ISSUE.renewsallowed | html %] renewals remaining + [% IF Koha.Preference('UnseenRenewals') && ISSUE.unseenallowed %] + / [% ISSUE.unseenleft | html %] of [% ISSUE.unseenallowed | html %] renewals left before the item must be seen by the library + [% END %] + ) [% ELSIF ( ISSUE.auto_renew || ISSUE.auto_too_soon ) %] Automatic renewal - ([% ISSUE.renewsleft | html %] of [% ISSUE.renewsallowed | html %] renewals remaining) + ( + [% ISSUE.renewsleft | html %] of [% ISSUE.renewsallowed | html %] renewals remaining + [% IF Koha.Preference('UnseenRenewals') && ISSUE.unseenallowed %] + / [% ISSUE.unseenleft | html %] of [% ISSUE.unseenallowed | html %] renewals left before the item must be seen by the library + [% END %] + ) [% ELSIF ( ISSUE.too_soon ) %] No renewal before [% ISSUE.soonestrenewdate | html %] - ([% ISSUE.renewsleft | html %] of [% ISSUE.renewsallowed | html %] renewals remaining) + ( + [% ISSUE.renewsleft | html %] of [% ISSUE.renewsallowed | html %] renewals remaining + [% IF Koha.Preference('UnseenRenewals') && ISSUE.unseenallowed %] + / [% ISSUE.unseenleft | html %] of [% ISSUE.unseenallowed | html %] renewals left before the item must be seen by the library + [% END %] + ) [% ELSIF ( ISSUE.item_denied_renewal ) %] Renewal not allowed [% END %] @@ -582,7 +611,12 @@ [% IF ( canrenew ) %] Renew [% END %] - ([% OVERDUE.renewsleft | html %] of [% OVERDUE.renewsallowed | html %] renewals remaining) + ( + [% OVERDUE.renewsleft | html %] of [% OVERDUE.renewsallowed | html %] renewals remaining + [% IF Koha.Preference('UnseenRenewals') && ISSUE.unseenallowed %] + / [% OVERDUE.unseenleft | html %] of [% OVERDUE.unseenallowed | html %] renewals left before the item must be seen by the library + [% END %] + ) [% ELSIF ( OVERDUE.norenew_overdue ) %] Not allowed(overdue) [% ELSIF ( OVERDUE.onreserve ) %] diff --git a/misc/cronjobs/automatic_renewals.pl b/misc/cronjobs/automatic_renewals.pl index fb1cf03ba9..56ed2ddd03 100755 --- a/misc/cronjobs/automatic_renewals.pl +++ b/misc/cronjobs/automatic_renewals.pl @@ -78,7 +78,7 @@ while ( my $auto_renew = $auto_renews->next ) { # CanBookBeRenewed returns 'auto_renew' when the renewal should be done by this script my ( $ok, $error ) = CanBookBeRenewed( $auto_renew->borrowernumber, $auto_renew->itemnumber ); if ( $error eq 'auto_renew' ) { - my $date_due = AddRenewal( $auto_renew->borrowernumber, $auto_renew->itemnumber, $auto_renew->branchcode ); + my $date_due = AddRenewal( $auto_renew->borrowernumber, $auto_renew->itemnumber, $auto_renew->branchcode, undef, undef, 0 ); $auto_renew->auto_renew_error(undef)->store; push @{ $report{ $auto_renew->borrowernumber } }, $auto_renew; } elsif ( $error eq 'too_many' diff --git a/offline_circ/download.pl b/offline_circ/download.pl index 2b6c67e113..9f37868674 100755 --- a/offline_circ/download.pl +++ b/offline_circ/download.pl @@ -68,6 +68,7 @@ my $issues_query = q{SELECT issues.date_due AS date_due, issues.issuedate AS issuedate, issues.renewals AS renewals, + issues.unseen_renewals AS unseen_renewals, borrowers.cardnumber AS cardnumber, CONCAT(borrowers.surname, ', ', borrowers.firstname) AS borrower_name FROM issues diff --git a/opac/opac-renew.pl b/opac/opac-renew.pl index 85570d54ad..37ae1e5970 100755 --- a/opac/opac-renew.pl +++ b/opac/opac-renew.pl @@ -82,7 +82,7 @@ else { else { $branchcode = 'OPACRenew'; } - AddRenewal( $borrowernumber, $itemnumber, $branchcode, undef, undef ); + AddRenewal( $borrowernumber, $itemnumber, $branchcode, undef, undef, 0 ); push( @renewed, $itemnumber ); } else { diff --git a/opac/opac-user.pl b/opac/opac-user.pl index 6c55ad2965..fb6cbf65a6 100755 --- a/opac/opac-user.pl +++ b/opac/opac-user.pl @@ -209,7 +209,14 @@ if ( $pending_checkouts->count ) { # Useless test # check if item is renewable my ($status,$renewerror) = CanBookBeRenewed( $borrowernumber, $issue->{'itemnumber'} ); - ($issue->{'renewcount'},$issue->{'renewsallowed'},$issue->{'renewsleft'}) = GetRenewCount($borrowernumber, $issue->{'itemnumber'}); + ( + $issue->{'renewcount'}, + $issue->{'renewsallowed'}, + $issue->{'renewsleft'}, + $issue->{'unseencount'}, + $issue->{'unseenallowed'}, + $issue->{'unseenleft'} + ) = GetRenewCount($borrowernumber, $issue->{'itemnumber'}); ( $issue->{'renewalfee'}, $issue->{'renewalitemtype'} ) = GetIssuingCharges( $issue->{'itemnumber'}, $borrowernumber ); $issue->{itemtype_object} = Koha::ItemTypes->find( Koha::Items->find( $issue->{itemnumber} )->effective_itemtype ); if($status && C4::Context->preference("OpacRenewalAllowed")){ @@ -220,6 +227,7 @@ if ( $pending_checkouts->count ) { # Useless test if ($renewerror) { $issue->{'too_many'} = 1 if $renewerror eq 'too_many'; + $issue->{'too_unseen'} = 1 if $renewerror eq 'too_unseen'; $issue->{'on_reserve'} = 1 if $renewerror eq 'on_reserve'; $issue->{'norenew_overdue'} = 1 if $renewerror eq 'overdue'; $issue->{'auto_renew'} = 1 if $renewerror eq 'auto_renew'; diff --git a/svc/checkouts b/svc/checkouts index f8fd541f36..1a4807fcf8 100755 --- a/svc/checkouts +++ b/svc/checkouts @@ -158,7 +158,14 @@ while ( my $c = $sth->fetchrow_hashref() ) { ) : undef; - my ( $renewals_count, $renewals_allowed, $renewals_remaining ) = + my ( + $renewals_count, + $renewals_allowed, + $renewals_remaining, + $unseen_count, + $unseen_allowed, + $unseen_remaining + ) = GetRenewCount( $c->{borrowernumber}, $c->{itemnumber} ); my $type_for_stat = Koha::ItemTypes->find( $item_level_itypes ? $c->{itype} : $c->{itemtype} ); @@ -225,6 +232,9 @@ while ( my $c = $sth->fetchrow_hashref() ) { renewals_count => $renewals_count, renewals_allowed => $renewals_allowed, renewals_remaining => $renewals_remaining, + unseen_count => $unseen_count, + unseen_allowed => $unseen_allowed, + unseen_remaining => $unseen_remaining, return_claim_id => $c->{return_claim_id}, return_claim_notes => $c->{return_claim_notes}, diff --git a/svc/renew b/svc/renew index 29e51d8cf7..c36bf977d9 100755 --- a/svc/renew +++ b/svc/renew @@ -46,6 +46,7 @@ my $borrowernumber = $input->param('borrowernumber'); my $override_limit = $input->param('override_limit'); my $branchcode = $input->param('branchcode') || C4::Context->userenv->{'branch'}; +my $seen = $input->param('seen'); my $date_due; if ( $input->param('date_due') ) { $date_due = dt_from_string( scalar $input->param('date_due') ); @@ -66,7 +67,7 @@ if ( $data->{error} && $data->{error} eq 'on_reserve' && C4::Context->preference } if ( $data->{renew_okay} ) { - $date_due = AddRenewal( $borrowernumber, $itemnumber, $branchcode, $date_due ); + $date_due = AddRenewal( $borrowernumber, $itemnumber, $branchcode, $date_due, undef, $seen ); $data->{date_due} = output_pref( { dt => $date_due, as_due_date => 1 } ); } -- 2.11.0