Bug 7413: Code and intranet template changes
authorHolger Meißner <h.meissner.82@web.de>
Thu, 13 Feb 2014 16:05:08 +0000 (17:05 +0100)
committerGalen Charlton <gmc@esilibrary.com>
Mon, 7 Apr 2014 18:28:57 +0000 (18:28 +0000)
This patch modifies CanBookBeRenewed, so that based on
issuingrules.norenewalbefore a new error "too_soon" can be returned.
Also adds a new subroutine GetSoonestRenewDate.

To test:
1) Create an issuing rule with "No renewal before" set to value X
   and "Unit" set to days.
2) Test the following steps for both:
   Home > Patron > Patron details
   Home > Circulation > Checkouts
3) On the checkout page, test for today's issues as well as previous
   issues. (Check something out on one day and something else on the
   next day, then do the testing.)
4) Confirm that items can't be renewed if current date is more than
   X days before due date.
5) Confirm that the date and time of the soonest possible renewal are
   displayed in the format specified by global sysprefs "dateformat"
   and "TimeFormat".
6) Confirm that items can be renewed if "No renewal before" is
   undefined or current date is X or less days before due date.
7) Confirm that if the number of allowed renewals is exceeded
   "Not renewable" is displayed, no matter what "No renewal before"
   is set to.
8) Test the same things with "Unit" set to hours.

Sponsored-by: Hochschule für Gesundheit (hsg), Germany
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Brendan Gallagher <brendan@bywatersolutions.com>

C4/Circulation.pm
circ/circulation.pl
koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt
koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt
members/moremember.pl

index f8b204a..39c1fad 100644 (file)
@@ -79,6 +79,7 @@ BEGIN {
                &AddIssue
                &AddRenewal
                &GetRenewCount
+        &GetSoonestRenewDate
                &GetItemIssue
                &GetItemIssues
                &GetIssuingCharges
@@ -2472,7 +2473,7 @@ sub CanBookBeRenewed {
 
     my $dbh       = C4::Context->dbh;
     my $renews    = 1;
-    my $renewokay = 0;
+    my $renewokay = 1;
     my $error;
 
     my $item      = GetItem($itemnumber)      or return ( 0, 'no_item' );
@@ -2486,12 +2487,30 @@ sub CanBookBeRenewed {
 
     my $issuingrule = GetIssuingRule($borrower->{categorycode}, $item->{itype}, $branchcode);
 
-    if ( ( $issuingrule->{renewalsallowed} > $itemissue->{renewals} ) || $override_limit ) {
-        $renewokay = 1;
-    } else {
+    if ( $issuingrule->{norenewalbefore} ) {
+
+        # Get current time and add norenewalbefore. If this is smaller than date_due, it's too soon for renewal.
+        if (
+            DateTime->now( time_zone => C4::Context->tz() )->add(
+                $issuingrule->{lengthunit} => $issuingrule->{norenewalbefore}
+            ) < $itemissue->{date_due}
+        )
+        {
+            $renewokay = 0;
+            $error     = "too_soon";
+        }
+    }
+
+    if ( $issuingrule->{renewalsallowed} <= $itemissue->{renewals} ) {
+        $renewokay = 0;
         $error = "too_many";
     }
 
+    if ( $override_limit ) {
+        $renewokay = 1;
+        $error     = undef;
+    }
+
     my ( $resfound, $resrec, undef ) = C4::Reserves::CheckReserves( $itemnumber );
 
     if ( $resfound ) { # '' when no hold was found
@@ -2668,6 +2687,52 @@ sub GetRenewCount {
     return ( $renewcount, $renewsallowed, $renewsleft );
 }
 
+=head2 GetSoonestRenewDate
+
+  $NoRenewalBeforeThisDate = &GetSoonestRenewDate($borrowernumber, $itemnumber);
+
+Find out the soonest possible renew date of a borrowed item.
+
+C<$borrowernumber> is the borrower number of the patron who currently
+has the item on loan.
+
+C<$itemnumber> is the number of the item to renew.
+
+C<$GetSoonestRenewDate> returns the DateTime of the soonest possible renew date,
+based on the value "No renewal before" of the applicable issuing rule. Returns the
+current date if the item can already be renewed.
+
+=cut
+
+sub GetSoonestRenewDate {
+    my ( $borrowernumber, $itemnumber ) = @_;
+
+    my $dbh = C4::Context->dbh;
+
+    my $item      = GetItem($itemnumber)      or return ( 0, 'no_item' );
+    my $itemissue = GetItemIssue($itemnumber) or return ( 0, 'no_checkout' );
+
+    $borrowernumber ||= $itemissue->{borrowernumber};
+    my $borrower = C4::Members::GetMemberDetails($borrowernumber)
+      or return;
+
+    my $branchcode = _GetCircControlBranch( $item, $borrower );
+    my $issuingrule =
+      GetIssuingRule( $borrower->{categorycode}, $item->{itype}, $branchcode );
+
+    my $now = DateTime->now( time_zone => C4::Context->tz() );
+
+    if ( $issuingrule->{norenewalbefore} ) {
+        my $soonestrenewal =
+          $itemissue->{date_due}->subtract(
+            $issuingrule->{lengthunit} => $issuingrule->{norenewalbefore} );
+
+        $soonestrenewal = $now > $soonestrenewal ? $now : $soonestrenewal;
+        return $soonestrenewal;
+    }
+    return $now;
+}
+
 =head2 GetIssuingCharges
 
   ($charge, $item_type) = &GetIssuingCharges($itemnumber, $borrowernumber);
index cdc40e3..e02b569 100755 (executable)
@@ -513,6 +513,12 @@ sub build_issue_data {
             (!$relatives) ? push @previousissues, $it : push @relprevissues, $it;
         }
         ($it->{'renewcount'},$it->{'renewsallowed'},$it->{'renewsleft'}) = C4::Circulation::GetRenewCount($it->{'borrowernumber'},$it->{'itemnumber'}); #Add renewal count to item data display
+
+        $it->{'soonestrenewdate'} = output_pref(
+            C4::Circulation::GetSoonestRenewDate(
+                $it->{borrowernumber}, $it->{itemnumber}
+            )
+        );
     }
 }
 
index 7c611dd..d5cfc6d 100644 (file)
@@ -782,17 +782,19 @@ No patron matched <span class="ex">[% message %]</span>
                     <input type="checkbox" class="radio" name="items[]" value="[% todayissue.itemnumber %]" />
                 [% END %]
                 </span>
-                [% IF todayissue.renewsallowed && todayissue.renewsleft %]
+                [% IF todayissue.renewsallowed && todayissue.renewsleft && !todayissue.renew_error_too_soon %]
                     <span class="renewals">([% todayissue.renewsleft %] of [% todayissue.renewsallowed %] renewals remaining)</span>
                 [% END %]
                 <span class="renewals-disabled">
             [% END %]
-               [% IF ( todayissue.renew_error_on_reserve ) %]
-            <a href="/cgi-bin/koha/reserve/request.pl?biblionumber=[% todayissue.biblionumber %]">On hold</a>
-               [% END %]
-                [% IF ( todayissue.renew_error_too_many ) %]
-            Not renewable
-                [% END %]
+            [% IF ( todayissue.renew_error_on_reserve ) %]
+                <a href="/cgi-bin/koha/reserve/request.pl?biblionumber=[% todayissue.biblionumber %]">On hold</a>
+            [% ELSIF ( todayissue.renew_error_too_many ) %]
+                Not renewable
+            [% ELSIF ( todayissue.renew_error_too_soon ) %]
+                No renewal before [% todayissue.soonestrenewdate %]
+                <span class="renewals">([% todayissue.renewsleft %] of [% todayissue.renewsallowed %] renewals remaining)</span>
+            [% END %]
             [% IF ( todayissue.can_confirm ) %]
                 </span>
             [% END %]
@@ -877,17 +879,19 @@ No patron matched <span class="ex">[% message %]</span>
                     <input type="checkbox" class="radio" name="items[]" value="[% previssue.itemnumber %]" />
                 [% END %]
                 </span>
-                [% IF previssue.renewsallowed && previssue.renewsleft %]
+                [% IF previssue.renewsallowed && previssue.renewsleft && !previssue.renew_error_too_soon %]
                     <span class="renewals">([% previssue.renewsleft %] of [% previssue.renewsallowed %] renewals remaining)</span>
                 [% END %]
                 <span class="renewals-disabled">
             [% END %]
-               [% IF ( previssue.renew_error_on_reserve ) %]
-            <a href="/cgi-bin/koha/reserve/request.pl?biblionumber=[% previssue.biblionumber %]">On hold</a>
-               [% END %]
-                [% IF ( previssue.renew_error_too_many ) %]
-            Not renewable
-                [% END %]
+            [% IF ( previssue.renew_error_on_reserve ) %]
+                <a href="/cgi-bin/koha/reserve/request.pl?biblionumber=[% previssue.biblionumber %]">On Hold</a>
+            [% ELSIF ( previssue.renew_error_too_many ) %]
+                Not renewable
+            [% ELSIF ( previssue.renew_error_too_soon ) %]
+                No renewal before [% previssue.soonestrenewdate %]
+                <span class="renewals">([% previssue.renewsleft %] of [% previssue.renewsallowed %] renewals remaining)</span>
+            [% END %]
             [% IF ( previssue.can_confirm ) %]
                 </span>
             [% END %]
index c4705d1..9cd6a90 100644 (file)
@@ -497,17 +497,19 @@ function validate1(date) {
                         <input type="checkbox" name="items[]" value="[% issueloo.itemnumber %]" />
                     [% END %]
                     </span>
-                    [% IF issueloo.renewsallowed && issueloo.renewsleft %]
+                    [% IF issueloo.renewsallowed && issueloo.renewsleft && !issueloo.norenew_reason_too_soon %]
                         <span class="renewals">([% issueloo.renewsleft %] of [% issueloo.renewsallowed %] renewals remaining)</span>
                     [% END %]
                     <span class="renewals-disabled">
                 [% END %]
                 [% IF ( issueloo.norenew_reason_on_reserve ) %]
-                <a href="/cgi-bin/koha/reserve/request.pl?biblionumber=[% issueloo.biblionumber %]">On Hold</a>
+                    <a href="/cgi-bin/koha/reserve/request.pl?biblionumber=[% issueloo.biblionumber %]">On Hold</a>
+                [% ELSIF ( issueloo.norenew_reason_too_many ) %]
+                    Not renewable
+                [% ELSIF ( issueloo.norenew_reason_too_soon ) %]
+                    No renewal before [% issueloo.soonestrenewdate %]
+                    <span class="renewals">([% issueloo.renewsleft %] of [% issueloo.renewsallowed %] renewals remaining)</span>
                 [% END %]
-                    [% IF ( issueloo.norenew_reason_too_many ) %]
-                        Not renewable
-                    [% END %]
                 [% IF ( issueloo.can_confirm ) %]
                     </span>
                 [% END %]
index e794efa..40f6d43 100755 (executable)
@@ -521,6 +521,14 @@ sub build_issue_data {
         $row{renew_failed}  = $renew_failed{ $issue->{itemnumber} };
         $row{return_failed} = $return_failed{ $issue->{barcode} };
         ($row{'renewcount'},$row{'renewsallowed'},$row{'renewsleft'}) = C4::Circulation::GetRenewCount($issue->{'borrowernumber'},$issue->{'itemnumber'}); #Add renewal count to item data display
+
+        $row{'soonestrenewdate'} = output_pref(
+            C4::Circulation::GetSoonestRenewDate(
+                $issue->{borrowernumber},
+                $issue->{itemnumber}
+            )
+        );
+
         push( @{$localissue}, \%row );
     }
     return $localissue;