Bug 7751: Decrease Loans for Items in Demand for Holds
authorColin Campbell <colin.campbell@ptfs-europe.com>
Fri, 17 Aug 2012 16:25:47 +0000 (17:25 +0100)
committerPaul Poulain <paul.poulain@biblibre.com>
Tue, 18 Sep 2012 17:01:14 +0000 (19:01 +0200)
Rebase and merge based on Mark Gavillet's patch to reduce
the loan period given to items on renewal when they are
in high demand for holds

Signed-off-by: Chris Cormack <chris@bigballofwax.co.nz>
C4/Circulation.pm
C4/SIP/ILS/Transaction/Checkout.pm
installer/data/mysql/sysprefs.sql
koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref
koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt

index dd5d843..8f60d80 100644 (file)
@@ -1005,6 +1005,22 @@ sub CanBookBeIssued {
             }
         }
     }
+
+## check for high holds decreasing loan period
+    my $decrease_loan = C4::Context->preference('decreaseLoanHighHolds');
+    if ( $decrease_loan && $decrease_loan == 1 ) {
+        my ( $reserved, $num, $duration, $returndate ) =
+          checkHighHolds( $item, $borrower );
+
+        if ( $num >= C4::Context->preference('decreaseLoanHighHoldsValue') ) {
+            $needsconfirmation{HIGHHOLDS} = {
+                num_holds  => $num,
+                duration   => $duration,
+                returndate => output_pref($returndate),
+            };
+        }
+    }
+
     return ( \%issuingimpossible, \%needsconfirmation, \%alerts );
 }
 
@@ -1057,6 +1073,50 @@ sub CanBookBeReturned {
   return ($allowed, $message);
 }
 
+=head2 CheckHighHolds
+
+    used when syspref decreaseLoanHighHolds is active. Returns 1 or 0 to define whether the minimum value held in
+    decreaseLoanHighHoldsValue is exceeded, the total number of outstanding holds, the number of days the loan
+    has been decreased to (held in syspref decreaseLoanHighHoldsValue), and the new due date
+
+=cut
+
+sub checkHighHolds {
+    my ( $item, $borrower ) = @_;
+    my $biblio = GetBiblioFromItemNumber( $item->{itemnumber} );
+    my $branch = _GetCircControlBranch( $item, $borrower );
+    my $dbh    = C4::Context->dbh;
+    my $sth    = $dbh->prepare(
+'select count(borrowernumber) as num_holds from reserves where biblionumber=?'
+    );
+    $sth->execute( $item->{'biblionumber'} );
+    my ($holds) = $sth->fetchrow_array;
+    if ($holds) {
+        my $issuedate = DateTime->now( time_zone => C4::Context->tz() );
+
+        my $calendar = Koha::Calendar->new( branchcode => $branch );
+
+        my $itype =
+          ( C4::Context->preference('item-level_itypes') )
+          ? $biblio->{'itype'}
+          : $biblio->{'itemtype'};
+        my $orig_due =
+          C4::Circulation::CalcDateDue( $issuedate, $itype, $branch,
+            $borrower );
+
+        my $reduced_datedue =
+          $calendar->addDate( $issuedate,
+            C4::Context->preference('decreaseLoanHighHoldsDuration') );
+
+        if ( DateTime->compare( $reduced_datedue, $orig_due ) == -1 ) {
+            return ( 1, $holds,
+                C4::Context->preference('decreaseLoanHighHoldsDuration'),
+                $reduced_datedue );
+        }
+    }
+    return ( 0, 0, 0, undef );
+}
+
 =head2 AddIssue
 
   &AddIssue($borrower, $barcode, [$datedue], [$cancelreserve], [$issuedate])
index 38951fc..da7a1b0 100644 (file)
@@ -54,6 +54,7 @@ sub do_checkout {
        my $shelf          = $self->{item}->hold_shelf;
        my $barcode        = $self->{item}->id;
        my $patron_barcode = $self->{patron}->id;
+        my $overridden_duedate; # usually passed as undef to AddIssue
        $debug and warn "do_checkout: patron (" . $patron_barcode . ")";
        my $borrower = $self->{patron}->getmemberdetails_object();
        $debug and warn "do_checkout borrower: . " . Dumper $borrower;
@@ -72,7 +73,7 @@ sub do_checkout {
             $noerror = 0;
         }
     } else {
-        foreach my $confirmation (keys %$needsconfirmation) {
+        foreach my $confirmation (keys %{$needsconfirmation}) {
             if ($confirmation eq 'RENEW_ISSUE'){
                 $self->screen_msg("Item already checked out to you: renewing item.");
             } elsif ($confirmation eq 'RESERVED' or $confirmation eq 'RESERVE_WAITING') {
@@ -87,6 +88,9 @@ sub do_checkout {
                 $self->screen_msg("Item already checked out to another patron.  Please return item for check-in.");
                 $noerror = 0;
             } elsif ($confirmation eq 'DEBT') {     # don't do anything, it's the minor debt, and alarms fire elsewhere
+            } elsif ($confirmation eq 'HIGHHOLDS') {
+                $overridden_duedate = $needsconfirmation->{$confirmation}->{returndate};
+                $self->screen_msg('Loan period reduced for high-demand item');
             } else {
                 $self->screen_msg($needsconfirmation->{$confirmation});
                 $noerror = 0;
@@ -118,10 +122,10 @@ sub do_checkout {
         # TODO: adjust representation in $self->item
     }
        # can issue
-       $debug and warn "do_checkout: calling AddIssue(\$borrower,$barcode, undef, 0)\n"
+       $debug and warn "do_checkout: calling AddIssue(\$borrower,$barcode, $overridden_duedate, 0)\n"
                # . "w/ \$borrower: " . Dumper($borrower)
                . "w/ C4::Context->userenv: " . Dumper(C4::Context->userenv);
-       my $due_dt  = AddIssue($borrower, $barcode, undef, 0);
+       my $due_dt  = AddIssue($borrower, $barcode, $overridden_duedate, 0);
     if ($due_dt) {
         $self->{due} = $due_dt->clone();
     } else {
index 4b4bf77..7b33ce6 100644 (file)
@@ -358,6 +358,9 @@ INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES (
 INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES ('OpacStarRatings','all',NULL,'disable|all|details','Choice');
 INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('OpacBrowseResults','1','Disable/enable browsing and paging search results from the OPAC detail page.',NULL,'YesNo');
 INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('SvcMaxReportRows','10','Maximum number of rows to return via the report web service.',NULL,'Integer');
+INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('decreaseLoanHighHolds', NULL, '', 'Decreases the loan period for items with number of holds above the threshold specified in decreaseLoanHighHoldsValue', 'YesNo');
+INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('decreaseLoanHighHoldsValue', NULL, '', 'Specifies a threshold for the minimum number of holds needed to trigger a reduction in loan duration (used with decreaseLoanHighHolds)', 'Integer');
+INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('decreaseLoanHighHoldsDuration', NULL, '', 'Specifies a number of days that a loan is reduced to when used in conjunction with decreaseLoanHighHolds', 'Integer');
 INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('ReservesControlBranch','PatronLibrary','ItemHomeLibrary|PatronLibrary','Branch checked for members reservations rights','Choice');
 INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('IssueLostItem', 'alert', 'alert|confirm|nothing', 'Defines what should be done when an attempt is made to issue an item that has been marked as lost.', 'Choice');
 INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('SuspendHoldsIntranet', '1', NULL , 'Allow holds to be suspended from the intranet.', 'YesNo');
index 9ff3056..531b878 100644 (file)
@@ -407,6 +407,22 @@ Circulation:
                   yes: Allow
                   no: "Don't allow"
             - holds to be suspended from the OPAC.
+        -
+            - pref: decreaseLoanHighHolds
+              choices:
+                  yes: Enable
+                  no:  "Don't enable"
+            - the reduction of loan period for items with number of holds above the threshold specified in decreaseLoanHighHoldsValue
+        -
+            - A loan should be reduced by
+            - pref: decreaseLoanHighHoldsDuration
+              class: integer
+            - days, when decreaseLoanHighHoldsValue threshold is reached (if decreaseLoanHighHolds is enabled)
+        -
+            - A loan should be reduced by decreaseLoanHighHoldsDuration when
+            - pref: decreaseLoanHighHoldsValue
+              class: integer
+            - holds have been places (if decreaseLoanHighHolds is enables)
     Fines Policy:
         -
             - Calculate fines based on days overdue
index 5f8fb99..db17ced 100644 (file)
@@ -364,8 +364,19 @@ function validate1(date) {
 [% IF ( ITEM_LOST ) %]
     <li>This item has been lost with a status of "[% ITEM_LOST %]". Check out anyway?</li>
 [% END %]
+
+[% IF  HIGHHOLDS %]
+       <li>High demand item. Loan period shortened to [% HIGHHOLDS.duration %] days (due [% HIGHHOLDS.returndate %]). Check out anyway?</li>
+[% END %]
 </ul>
 
+[% IF HIGHHOLDS %]
+       <script language="JavaScript" type="text/javascript">
+       $(document).ready(function() {
+               $("input[name=duedatespec]:hidden").val('[% HIGHHOLDS.returndate %]');
+       });
+       </script>
+[% END %]
 <form method="post" action="/cgi-bin/koha/circ/circulation.pl" autocomplete="off">
 
 [% IF ( RESERVED ) %]