Bug 10493: Add renewal script
authorKyle M Hall <kyle@bywatersolutions.com>
Wed, 19 Jun 2013 09:28:01 +0000 (05:28 -0400)
committerGalen Charlton <gmc@esilibrary.com>
Tue, 22 Oct 2013 17:04:03 +0000 (17:04 +0000)
This patch adds a renewal tool that functions similar to the returns where a
librarian can continuously scan items for renewal. This script blocks
renewals that are impossible, and allow the same renewal overrides
as circulation.pl

Test plan:
 1) Apply the patches for bug 8798
 2) Apply this patch
 3) Browse to /cgi-bin/koha/circ/renew.pl
 4) Enter an invalid barcode, you should get an error message
 5) Enter a valid, but not checked out barcode, you should get an error
    message.
 6) Enter a valid barcode that is checkout out and should be renewable,
    you should get a success message.
 7) Enable AllowRenewalLimitOverride
 8) Enter a barcode for an item that has been renewed too many times
 9) You should get a warning which you can override.
10) Disable AllowRenewalLimitOverride
11) Repeat steap 8
12) You should get a blocking error message
11) Enter a barcode for an item with unfilled holds on it,
    you should get an overridable warning

Signed-off-by: Owen Leonard <oleonard@myacpl.org>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
Passes all tests and QA script, some issues have been
addressed in follow-ups.

Signed-off-by: Galen Charlton <gmc@esilibrary.com>

C4/Circulation.pm
C4/Items.pm
C4/Reserves.pm
Koha/Schema/Result/Issue.pm
Koha/Schema/Result/Item.pm
circ/renew.pl [new file with mode: 0755]
koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation-home.tt
koha-tmpl/intranet-tmpl/prog/en/modules/circ/renew.tt [new file with mode: 0644]

index d74b97f..4a5103f 100644 (file)
@@ -2463,17 +2463,19 @@ already renewed the loan. $error will contain the reason the renewal can not pro
 =cut
 
 sub CanBookBeRenewed {
-
-    # check renewal status
     my ( $borrowernumber, $itemnumber, $override_limit ) = @_;
+
     my $dbh       = C4::Context->dbh;
     my $renews    = 1;
     my $renewokay = 0;
     my $error;
 
-    my $borrower    = C4::Members::GetMemberDetails( $borrowernumber, 0 )   or return;
-    my $item        = GetItem($itemnumber)                                  or return;
-    my $itemissue   = GetItemIssue($itemnumber)                             or return;
+    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);
 
@@ -2492,6 +2494,12 @@ sub CanBookBeRenewed {
         $error = "on_reserve";
     }
 
+    if ( ( $issuingrule->{renewalsallowed} > $itemissue->{renewals} ) || $override_limit ) {
+        $renewokay = 1;
+    } else {
+        $error = "too_many";
+    }
+
     return ( $renewokay, $error );
 }
 
@@ -2520,27 +2528,32 @@ from the book's item type.
 =cut
 
 sub AddRenewal {
-    my $borrowernumber  = shift or return;
+    my $borrowernumber  = shift;
     my $itemnumber      = shift or return;
     my $branch          = shift;
     my $datedue         = shift;
     my $lastreneweddate = shift || DateTime->now(time_zone => C4::Context->tz)->ymd();
+
     my $item   = GetItem($itemnumber) or return;
     my $biblio = GetBiblioFromItemNumber($itemnumber) or return;
 
     my $dbh = C4::Context->dbh;
+
     # Find the issues record for this book
     my $sth =
-      $dbh->prepare("SELECT * FROM issues
-                        WHERE borrowernumber=? 
-                        AND itemnumber=?"
-      );
-    $sth->execute( $borrowernumber, $itemnumber );
+      $dbh->prepare("SELECT * FROM issues WHERE itemnumber = ?");
+    $sth->execute( $itemnumber );
     my $issuedata = $sth->fetchrow_hashref;
-    if(defined $datedue && ref $datedue ne 'DateTime' ) {
+
+    return unless ( $issuedata );
+
+    $borrowernumber ||= $issuedata->{borrowernumber};
+
+    if ( defined $datedue && ref $datedue ne 'DateTime' ) {
         carp 'Invalid date passed to AddRenewal.';
         return;
     }
+
     # If the due date wasn't specified, calculate it by adding the
     # book's loan length to today's date or the current due date
     # based on the value of the RenewalPeriodBase syspref.
index 8116c22..67d8736 100644 (file)
@@ -145,6 +145,7 @@ sub GetItem {
     my ($itemnumber,$barcode, $serial) = @_;
     my $dbh = C4::Context->dbh;
        my $data;
+
     if ($itemnumber) {
         my $sth = $dbh->prepare("
             SELECT * FROM items 
@@ -159,6 +160,9 @@ sub GetItem {
         $sth->execute($barcode);               
         $data = $sth->fetchrow_hashref;
     }
+
+    return unless ( $data );
+
     if ( $serial) {      
     my $ssth = $dbh->prepare("SELECT serialseq,publisheddate from serialitems left join serial on serialitems.serialid=serial.serialid where serialitems.itemnumber=?");
         $ssth->execute($data->{'itemnumber'}) ;
index bf1e398..f8666a3 100644 (file)
@@ -800,10 +800,11 @@ sub GetReserveStatus {
     if(defined $found) {
         return 'Waiting'  if $found eq 'W' and $priority == 0;
         return 'Finished' if $found eq 'F';
-        return 'Reserved' if $priority > 0;
     }
-    return '';
-    #empty string here will remove need for checking undef, or less log lines
+
+    return 'Reserved' if $priority > 0;
+
+    return ''; # empty string here will remove need for checking undef, or less log lines
 }
 
 =head2 CheckReserves
index 3bf4545..282c802 100644 (file)
@@ -183,6 +183,11 @@ __PACKAGE__->belongs_to(
 # Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-10-14 20:56:21
 # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ZEh31EKBmURMKxDxI+H3EA
 
+__PACKAGE__->belongs_to(
+  "borrower",
+  "Koha::Schema::Result::Borrower",
+  { borrowernumber => "borrowernumber" },
+  { join_type => "LEFT", on_delete => "CASCADE", on_update => "CASCADE" },
+);
 
-# You can replace this text with custom content, and it will be preserved on regeneration
 1;
index b65e7d5..055f801 100644 (file)
@@ -588,6 +588,10 @@ __PACKAGE__->might_have(
 # Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-10-14 20:56:21
 # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:JV1Q/UVlKQ6QgVFMGBIZCw
 
+__PACKAGE__->belongs_to(
+    "biblio",
+    "Koha::Schema::Result::Biblio",
+    { "foreign.biblionumber" => "self.biblionumber" }
+);
 
-# You can replace this text with custom content, and it will be preserved on regeneration
 1;
diff --git a/circ/renew.pl b/circ/renew.pl
new file mode 100755 (executable)
index 0000000..6634c0c
--- /dev/null
@@ -0,0 +1,102 @@
+#!/usr/bin/perl
+
+# Copyright 2013 ByWater Solutions
+#
+# This file is part of Koha.
+#
+# Koha is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2 of the License, or (at your option) any later
+# version.
+#
+# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with Koha; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+use Modern::Perl;
+
+use CGI;
+use C4::Context;
+use C4::Auth qw/:DEFAULT get_session/;
+use C4::Output;
+use C4::Circulation;
+use Koha::DateUtils;
+use Koha::Database;
+
+my $cgi = new CGI;
+
+my ( $template, $librarian, $cookie ) = get_template_and_user(
+    {
+        template_name   => "circ/renew.tmpl",
+        query           => $cgi,
+        type            => "intranet",
+        authnotrequired => 0,
+        flagsrequired   => { circulate => "circulate_remaining_permissions" },
+    }
+);
+
+my $schema = Koha::Database->new()->schema();
+
+my $barcode        = $cgi->param('barcode');
+my $override_limit = $cgi->param('override_limit');
+my $override_holds = $cgi->param('override_holds');
+
+my ( $item, $issue, $borrower, $error );
+
+if ($barcode) {
+    $item = $schema->resultset("Item")->single( { barcode => $barcode } );
+
+    if ($item) {
+
+        $issue = $item->issues()->single();
+
+        if ($issue) {
+
+            $borrower = $issue->borrower();
+
+            if ( $borrower->debarred() lt dt_from_string()->ymd() ) {
+                my $can_renew;
+                ( $can_renew, $error ) =
+                  CanBookBeRenewed( $borrower->borrowernumber(),
+                    $item->itemnumber(), $override_limit );
+
+                if ( $error eq 'on_reserve' ) {
+                    if ($override_holds) {
+                        $can_renew = 1;
+                        $error     = undef;
+                    }
+                    else {
+                        $can_renew = 0;
+                    }
+                }
+
+                if ($can_renew) {
+                    my $date_due = AddRenewal( undef, $item->itemnumber() );
+                    $template->param( date_due => $date_due );
+                }
+            }
+            else {
+                $error = "patron_restricted";
+            }
+        }
+        else {
+            $error = "no_checkout";
+        }
+    }
+    else {
+        $error = "no_item";
+    }
+
+    $template->param(
+        item     => $item,
+        issue    => $issue,
+        borrower => $borrower,
+        error    => $error
+    );
+}
+
+output_html_with_http_headers( $cgi, $cookie, $template->output );
index 72abd1f..e5eaddc 100644 (file)
@@ -19,6 +19,7 @@
        <ul>
         <li><a href="/cgi-bin/koha/circ/circulation.pl">Check out</a></li>
         <li><a href="/cgi-bin/koha/circ/returns.pl">Check in</a></li>
+        <li><a href="/cgi-bin/koha/circ/renew.pl">Renew</a></li>
     [% IF ( display_transfer ) %]
                <li><a href="/cgi-bin/koha/circ/branchtransfers.pl">Transfer</a></li>
     [% END %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/renew.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/renew.tt
new file mode 100644 (file)
index 0000000..eba8892
--- /dev/null
@@ -0,0 +1,131 @@
+[% USE Koha %]
+[% USE KohaDates %]
+[% USE KohaBranchName %]
+
+[% INCLUDE 'doc-head-open.inc' %]
+
+<title>Koha &rsaquo; Circulation &rsaquo; Renew [% title |html %]</title>
+
+[% INCLUDE 'doc-head-close.inc' %]
+
+<script type="text/javascript">
+//<![CDATA[
+
+$(document).ready(function () {
+    $("#barcode").focus();
+});
+
+//]]>
+</script>
+
+</head>
+
+<body>
+
+[% INCLUDE 'header.inc' %]
+[% INCLUDE 'circ-search.inc' %]
+
+<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/circ/circulation-home.pl">Circulation</a> &rsaquo; Check in</div>
+
+<div id="doc" class="yui-t7">
+    <div id="bd">
+            <div id="yui-main">
+
+            <div class="yui-g">
+                [% IF error %]
+                    <div class="dialog alert">
+                        <h3>Cannot renew:</h3>
+                        <p>
+                            [% IF error == "no_item" %]
+
+                                No item matches this barcode
+
+                            [% ELSIF error == "no_checkout" %]
+
+                                <a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% item.biblionumber %]">[% item.biblio.title %] [% item.biblioitem.subtitle %]</a>
+                                ( <a href="/cgi-bin/koha/catalogue/moredetail.pl?itemnumber=[% item.itemnumber %]&biblionumber=[% item.biblionumber %]&bi=[% item.biblioitemnumber %]#item[% item.itemnumber %]">[% item.barcode %]</a> )
+                                is not checked out to a patron.
+
+                            [% ELSIF error == "too_many" %]
+
+                                [% item.biblio.title %] [% item.biblioitem.subtitle %] ( [% item.barcode %] )
+                                has been renewed the maximum number of times by
+                                [% borrower.firstname %] [% borrower.surname %] ( <a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrower.borrowernumber %]"> [% borrower.cardnumber %] </a> )
+
+                                [% IF Koha.Preference('AllowRenewalLimitOverride') %]
+                                    <form method="post" action="/cgi-bin/koha/circ/renew.pl" autocomplete="off" >
+                                        <input type="hidden" name="barcode" value="[% item.barcode %]"/>
+                                        <input type="hidden" name="override_limit" value="1" />
+                                        <input type="submit" class="submit" value="Override limit and renew" />
+                                    </form>
+                                [% END %]
+
+                            [% ELSIF error == "on_reserve" %]
+
+                                This item is on hold for other patrons.
+
+                                <form method="post" action="/cgi-bin/koha/circ/renew.pl" autocomplete="off" >
+                                    <input type="hidden" name="barcode" value="[% item.barcode %]"/>
+                                    <input type="hidden" name="override_limit" value="1" />
+                                    <input type="hidden" name="override_holds" value="1" />
+                                    <input type="submit" class="submit" value="Override and renew" />
+                                </form>
+
+                            [% ELSIF error == "patron_restricted" %]
+
+                                [% borrower.firstname %] [% borrower.surname %] ( <a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrower.borrowernumber %]"> [% borrower.cardnumber %] </a> )
+                                is currently restricted.
+
+                            [% ELSE %]
+
+                                [% error %]
+
+                            [% END %]
+
+                            <a href="/cgi-bin/koha/circ/renew.pl">Ignore & continue</a>
+                        </p>
+                    </div>
+                [% END %]
+
+                [% IF date_due %]
+                    <div class="dialog message">
+                        <p>
+                            <h3>Item renewed:</h3>
+
+                            <a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% item.biblionumber %]">[% item.biblio.title %] [% item.biblioitem.subtitle %]</a>
+                            ( <a href="/cgi-bin/koha/catalogue/moredetail.pl?itemnumber=[% item.itemnumber %]&biblionumber=[% item.biblionumber %]&bi=[% item.biblioitemnumber %]#item[% item.itemnumber %]">[% item.barcode %]</a> )
+                            renewed for
+                            [% borrower.firstname %] [% borrower.surname %] ( <a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrower.borrowernumber %]"> [% borrower.cardnumber %] </a> )
+                            now due on [% date_due | $KohaDates %]
+                        </p>
+                    </div>
+                [% END %]
+            </div>
+
+            <div class="yui-g">
+
+            [% UNLESS error %]
+                <form method="post" action="/cgi-bin/koha/circ/renew.pl" autocomplete="off" >
+
+                    <div class="yui-u first">
+                        <fieldset>
+                            <legend>Renew</legend>
+
+                            <label for="barcode">Enter item barcode: </label>
+
+                            <input name="barcode" id="barcode" size="14" class="focus"/>
+
+                            <input type="submit" class="submit" value="Submit" />
+                        </fieldset>
+                    </div>
+
+                </form>
+            [% END %]
+
+        </div>
+
+    </div>
+
+<div>
+
+[% INCLUDE 'intranet-bottom.inc' %]