@@ -, +, @@ --- C4/Circulation.pm | 46 ++++++++++++++++++-- C4/ILSDI/Services.pm | 3 +- circ/circulation.pl | 8 ++-- installer/data/mysql/sysprefs.sql | 1 + installer/data/mysql/updatedatabase.pl | 7 +++ .../en/modules/admin/preferences/circulation.pref | 8 ++++ .../prog/en/modules/circ/circulation.tt | 44 +++++++++++++++---- .../prog/en/modules/members/moremember.tt | 30 +++++++++++-- koha-tmpl/opac-tmpl/prog/en/modules/opac-user.tt | 5 +++ members/moremember.pl | 7 +-- opac/opac-renew.pl | 5 ++- opac/opac-user.pl | 9 +++- reserve/renewscript.pl | 4 +- 13 files changed, 153 insertions(+), 24 deletions(-) --- a/C4/Circulation.pm +++ a/C4/Circulation.pm @@ -75,6 +75,7 @@ BEGIN { push @EXPORT, qw( &CanBookBeIssued &CanBookBeRenewed + &HasWhateverRenewalToBeBlocked &AddIssue &AddRenewal &GetRenewCount @@ -2465,7 +2466,7 @@ already renewed the loan. $error will contain the reason the renewal can not pro sub CanBookBeRenewed { # check renewal status - my ( $borrowernumber, $itemnumber, $override_limit ) = @_; + my ( $borrowernumber, $itemnumber, $override_limit, $overduesblockrenew ) = @_; my $dbh = C4::Context->dbh; my $renews = 1; my $renewokay = 0; @@ -2474,13 +2475,15 @@ sub CanBookBeRenewed { my $borrower = C4::Members::GetMemberDetails( $borrowernumber, 0 ) or return; my $item = GetItem($itemnumber) or return; my $itemissue = GetItemIssue($itemnumber) or return; + my $overdue = $itemissue->{'overdue'}; my $branchcode = _GetCircControlBranch($item, $borrower); my $issuingrule = GetIssuingRule($borrower->{categorycode}, $item->{itype}, $branchcode); if ( ( $issuingrule->{renewalsallowed} > $itemissue->{renewals} ) || $override_limit ) { - $renewokay = 1; + $renewokay = ( $overduesblockrenew eq 'blockitem' and $overdue and !$override_limit ) ? 0 : 1; + $error = 'overdue' unless $renewokay; } else { $error = "too_many"; } @@ -2491,10 +2494,47 @@ sub CanBookBeRenewed { $renewokay = 0; $error = "on_reserve"; } - return ( $renewokay, $error ); } +=head2 HasWhateverRenewalToBeBlocked + + ($blockallitems, $reasonwhy, $overduesblockrenew) = &HasWhateverRenewalToBeBlocked($borrowernumber, $override_limit); + +Check whether whatever renewal must be blocked in the case patron is restricted or any of his documents are late. + +C<$blockallitems> if true, causes the renewal to be blocked for every items. + +C<$reasonwhy> if $blockallitems is true, will be an information displayed in checkouts table on patron page. + +C<$overduesblockrenew> is the value of the syspref OverduesBlockRenew. + +=cut + +sub HasWhateverRenewalToBeBlocked { + my $borrowernumber = shift; + my $override_limit = shift; + # get the option selected for the syspref OverduesBlockRenew + my $overduesblockrenew = C4::Context->preference('OverduesBlockRenew'); + my $blockallitems; + my $reasonwhy; + unless ( $override_limit ) { + # check if patron is restricted or if any of his documents are late + my ($memberblocked) = C4::Members::IsMemberBlocked($borrowernumber); + if ($memberblocked == 1) { + $reasonwhy = 'restriction'; + $blockallitems = 1; + } elsif ($memberblocked == -1) { + # check if renewal must be blocked for all the patron's documents on loan + if ( $overduesblockrenew eq 'blockall' ) { + $blockallitems = 1; + $reasonwhy = 'overdue'; + } + } + } + return($blockallitems,$reasonwhy,$overduesblockrenew); +} + =head2 AddRenewal &AddRenewal($borrowernumber, $itemnumber, $branch, [$datedue], [$lastreneweddate]); --- a/C4/ILSDI/Services.pm +++ a/C4/ILSDI/Services.pm @@ -558,7 +558,8 @@ sub RenewLoan { return { code => 'RecordNotFound' } unless $$item{itemnumber}; # Add renewal if possible - my @renewal = CanBookBeRenewed( $borrowernumber, $itemnumber ); + my ($blockallitems,$reasonwhy,$overduesblockrenew) = HasAnyRenewalToBeBlocked($borrowernumber,undef); + my @renewal = $blockallitems ? (0, $reasonwhy) : CanBookBeRenewed( $borrowernumber, $itemnumber, undef, $overduesblockrenew ); if ( $renewal[0] ) { AddRenewal( $borrowernumber, $itemnumber ); } my $issue = GetItemIssue($itemnumber); --- a/circ/circulation.pl +++ a/circ/circulation.pl @@ -469,6 +469,8 @@ my $displayrelissues; our $totalprice = 0; +my ($blockallitems, $reasonwhy, $overduesblockrenew) = HasWhateverRenewalToBeBlocked($borrowernumber, undef); + sub build_issue_data { my $issueslist = shift; my $relatives = shift; @@ -484,10 +486,10 @@ sub build_issue_data { $it->{'itemnumber'}, $it->{'borrowernumber'} ); $it->{'charge'} = sprintf("%.2f", $it->{'charge'}); - my ($can_renew, $can_renew_error) = CanBookBeRenewed( - $it->{'borrowernumber'},$it->{'itemnumber'} - ); + my ($can_renew, $can_renew_error) = $blockallitems ? (0, $reasonwhy) : CanBookBeRenewed( + $it->{'borrowernumber'},$it->{'itemnumber'}, undef, $overduesblockrenew); $it->{"renew_error_${can_renew_error}"} = 1 if defined $can_renew_error; + $it->{'blockrenewal'} = ($can_renew_error=~/overdue|restriction/) ? 1 : 0; my $restype = C4::Reserves::GetReserveStatus( $it->{'itemnumber'} ); $it->{'can_renew'} = $can_renew; $it->{'can_confirm'} = !$can_renew && !$restype; --- a/installer/data/mysql/sysprefs.sql +++ a/installer/data/mysql/sysprefs.sql @@ -287,6 +287,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('OverDriveLibraryID','','Library ID for OverDrive integration','','Integer'), ('OverdueNoticeBcc','','','Email address to bcc outgoing overdue notices sent by email','free'), ('OverduesBlockCirc','noblock','noblock|confirmation|block','When checking out an item should overdues block checkout, generate a confirmation dialogue, or allow checkout','Choice'), +('OverduesBlockRenew','allow','allow|blockitem|blockall','If any of patron checked out documents is late, should renewal be allowed, blocked only on overdue items or blocked on whatever checked out document','Choice'), ('patronimages','0',NULL,'Enable patron images for the Staff Client','YesNo'), ('PatronSelfRegistration','0',NULL,'If enabled, patrons will be able to register themselves via the OPAC.','YesNo'), ('PatronSelfRegistrationAdditionalInstructions','','','A free text field to display additional instructions to newly self registered patrons.','free'), --- a/installer/data/mysql/updatedatabase.pl +++ a/installer/data/mysql/updatedatabase.pl @@ -7330,6 +7330,13 @@ if ( CheckVersion($DBversion) ) { SetVersion($DBversion); } +$DBversion = "3.13.00.XXX"; +if ( CheckVersion($DBversion) ) { + $dbh->do("INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES ('OverduesBlockRenew','allow','If any of a patron checked out documents is late, should renewal be allowed, blocked only on overdue items or blocked on whatever checked out document','allow|blockitem|blockall','Choice')"); + print "Upgrade to $DBversion done (Bug 8236: Add system preference OverduesBlockRenew)\n"; + SetVersion($DBversion); +} + =head1 FUNCTIONS =head2 TableExists($table) --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref @@ -316,6 +316,14 @@ Circulation: confirmation: Ask for confirmation - when checking out to a borrower that has overdues outstanding - + - If any of a patron's checked out items are late, + - pref: OverduesBlockRenew + type: choice + choices: + allow: allow renewing of items. + blockall: block renewing for all items. + blockitem: block renewing only for overdue items. + - - On checkin route the returned item to - pref: HomeOrHoldingBranchReturn type: choice --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt @@ -28,6 +28,7 @@ var MSG_EXPORT_SELECT_CHECKOUTS = _("You must select checkout(s) to export"); [% IF ( borrowernumber ) %]if($.cookie("holdfor") != [% borrowernumber %]){ $.cookie("holdfor",null, { path: "/", expires: 0 }); }[% ELSE %]$.cookie("holdfor",null, { path: "/", expires: 0 });[% END %] [% UNLESS ( borrowernumber ) %][% UNLESS ( CGIselectborrower ) %]window.onload=function(){ $('#findborrower').focus(); };[% END %][% END %] $(document).ready(function() { + $(function(){ hiderenew() }); $('#patronlists').tabs([% IF ( UseTablesortForCirc ) %]{ // Correct table sizing for tables hidden in tabs // http://www.datatables.net/examples/api/tabs_and_scrolling.html @@ -71,8 +72,11 @@ var MSG_EXPORT_SELECT_CHECKOUTS = _("You must select checkout(s) to export"); $( '#override_limit' ).click( function () { if ( this.checked ) { $( '.renewals-allowed' ).show(); $( '.renewals-disabled' ).hide(); + $("input[name='renew_checked']").val('Renew or Return checked items'); + $("input[name='renew_all']").css('display','inline'); } else { $( '.renewals-allowed' ).hide(); $( '.renewals-disabled' ).show(); + hiderenew(); } } ).attr( 'checked', false ); [% END %][% IF ( CircAutoPrintQuickSlip ) %] @@ -94,6 +98,22 @@ var MSG_EXPORT_SELECT_CHECKOUTS = _("You must select checkout(s) to export"); [% END %] [% END %] }); + +function hiderenew () { + var valid=false; + $("input[name^=items]").parent().each(function(){ + if($(this).css('display') !='none'){ + valid = true; + return; + } + }); + if(!valid){ + $("input[name='renew_checked']").val('Return checked items'); + $("input[name='renew_all']").css('display','none'); + } + return; +}; + //]]> @@ -733,7 +753,7 @@ No patron matched [% message %] [% ELSE %] [% IF ( todayissue.can_confirm ) %] [% END %] @@ -822,7 +846,7 @@ No patron matched [% message %] [% ELSE %] [% IF ( previssue.can_confirm ) %] [% END %] --- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt @@ -18,6 +18,7 @@ @@ -496,7 +516,7 @@ function validate1(date) { [% IF ( issueloo.norenew ) %] [% IF ( issueloo.can_confirm ) %] [% END %] --- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-user.tt +++ a/koha-tmpl/opac-tmpl/prog/en/modules/opac-user.tt @@ -191,7 +191,11 @@ var MSG_CONFIRM_RESUME_HOLDS = _("Are you sure you want to resume all suspended [% IF ( OpacRenewalAllowed ) %] [% IF ( ISSUE.status ) %][% IF ( canrenew ) %] Renew[% END %] ([% ISSUE.renewsleft %] of [% ISSUE.renewsallowed %] renewals remaining) [% ELSE %] + [% IF ( ISSUE.norenew_overdue ) %] + Renewal not allowed (overdue on a document) + [% ELSE %] Not renewable[% IF ( ISSUE.too_many ) %] ([% ISSUE.renewsleft %] of [% ISSUE.renewsallowed %] renewals remaining)[% ELSE %][% IF ( ISSUE.on_reserve ) %] (On hold)[% END %][% END %] + [% END %] [% END %] [% END %] [% IF ( OPACFinesTab ) %] @@ -335,6 +339,7 @@ var MSG_CONFIRM_RESUME_HOLDS = _("Are you sure you want to resume all suspended [% ELSIF ( OVERDUE.status ) %] [% IF ( canrenew ) %]Renew[% END %] ([% OVERDUE.renewsleft %] of [% OVERDUE.renewsallowed %] renewals remaining) [% ELSIF ( OVERDUE.onreserve ) %]On hold +[% ELSIF ( OVERDUE.norenew_overdue ) %]Renewal not allowed(overdue on a document) [% ELSE %]No renewals left [% END %] [% END %] --- a/members/moremember.pl +++ a/members/moremember.pl @@ -251,6 +251,8 @@ my @borrowers_with_issues; my $overdues_exist = 0; my $totalprice = 0; +my ($blockallitems, $reasonwhy, $overduesblockrenew) = HasWhateverRenewalToBeBlocked($borrowernumber, $override_limit); + my @issuedata = build_issue_data($issue); my @relissuedata = build_issue_data($relissue); @@ -506,12 +508,11 @@ sub build_issue_data { $row{'charge'} = sprintf( "%.2f", $charge ); - my ( $renewokay, $renewerror ) = - CanBookBeRenewed( $borrowernumber, $issue->{itemnumber}, - $override_limit ); + my ( $renewokay, $renewerror ) = $blockallitems ? (0, $reasonwhy) : CanBookBeRenewed( $borrowernumber, $issue->{itemnumber}, $override_limit, $overduesblockrenew ); $row{'norenew'} = !$renewokay; $row{'can_confirm'} = ( !$renewokay && $renewerror ne 'on_reserve' ); $row{"norenew_reason_$renewerror"} = 1 if $renewerror; + $row{'blockrenewal'} = ($renewerror=~ /overdue|restriction/) ? 1 : 0; $row{renew_failed} = $renew_failed{ $issue->{itemnumber} }; $row{return_failed} = $return_failed{ $issue->{barcode} }; push( @{$localissue}, \%row ); --- a/opac/opac-renew.pl +++ a/opac/opac-renew.pl @@ -46,8 +46,11 @@ my @items = $query->param('item'); my $opacrenew = C4::Context->preference("OpacRenewalAllowed"); my $errorstring=''; + +my ($blockallitems, $reasonwhy, $overduesblockrenew) = HasWhateverRenewalToBeBlocked($borrowernumber, $override_limit); + for my $itemnumber ( @items ) { - my ($status,$error) = CanBookBeRenewed( $borrowernumber, $itemnumber ); + my ($status,$error) = $blockallitems ? (0, $reasonwhy) : CanBookBeRenewed( $borrowernumber, $itemnumber, undef, $overduesblockrenew ); if ( $status == 1 && $opacrenew == 1 ) { my $renewalbranch = C4::Context->preference('OpacRenewalBranch'); my $branchcode; --- a/opac/opac-user.pl +++ a/opac/opac-user.pl @@ -155,6 +155,9 @@ my @overdues; my @issuedat; my $itemtypes = GetItemTypes(); my $issues = GetPendingIssues($borrowernumber); + +my ($blockallitems, $reasonwhy, $overduesblockrenew) = HasWhateverRenewalToBeBlocked($borrowernumber, undef); + if ($issues){ foreach my $issue ( sort { $b->{date_due}->datetime() cmp $a->{date_due}->datetime() } @{$issues} ) { # check for reserves @@ -178,11 +181,12 @@ if ($issues){ $issue->{'charges'} = $charges; $issue->{'subtitle'} = GetRecordValue('subtitle', GetMarcBiblio($issue->{'biblionumber'}), GetFrameworkCode($issue->{'biblionumber'})); # check if item is renewable - my ($status,$renewerror) = CanBookBeRenewed( $borrowernumber, $issue->{'itemnumber'} ); + my ($status,$renewerror) = $blockallitems ? (0, $reasonwhy) : CanBookBeRenewed( $borrowernumber, $issue->{'itemnumber'}, undef, $overduesblockrenew); ($issue->{'renewcount'},$issue->{'renewsallowed'},$issue->{'renewsleft'}) = GetRenewCount($borrowernumber, $issue->{'itemnumber'}); if($status && C4::Context->preference("OpacRenewalAllowed")){ $issue->{'status'} = $status; } + $issue->{'norenew_overdue'} = 1 if $renewerror and $renewerror eq 'overdue'; $issue->{'too_many'} = 1 if $renewerror and $renewerror eq 'too_many'; $issue->{'on_reserve'} = 1 if $renewerror and $renewerror eq 'on_reserve'; @@ -218,6 +222,9 @@ if ($issues){ } } } + +$canrenew = 0 if ($overduesblockrenew ne 'allow' and $overdues_count == $count); + $template->param( ISSUES => \@issuedat ); $template->param( issues_count => $count ); $template->param( canrenew => $canrenew ); --- a/reserve/renewscript.pl +++ a/reserve/renewscript.pl @@ -81,11 +81,13 @@ my $borrowernumber = $input->param("borrowernumber"); my $exemptfine = $input->param("exemptfine") || 0; my $override_limit = $input->param("override_limit") || 0; my $failedrenews = q{}; +my ($blockallitems, $reasonwhy, $overduesblockrenew) = HasWhateverRenewalToBeBlocked($borrowernumber, $override_limit); + foreach my $itemno (@data) { # check status before renewing issue my ( $renewokay, $error ) = - CanBookBeRenewed( $borrowernumber, $itemno, $override_limit ); + $blockallitems ? (0, $reasonwhy) : CanBookBeRenewed( $borrowernumber, $itemno, $override_limit, $overduesblockrenew ); if ($renewokay) { AddRenewal( $borrowernumber, $itemno, $branch, $datedue ); } --