@@ -, +, @@
---
Koha/Schema/Result/Issue.pm | 24 +
api/checkin.pl | 75 ++++
api/checkouts.pl | 116 +++++
api/renew.pl | 63 +++
circ/circulation.pl | 94 ----
.../intranet-tmpl/prog/en/css/staff-global.css | 2 +-
.../intranet-tmpl/prog/en/js/pages/circulation.js | 141 +++++--
.../prog/en/modules/circ/circulation.tt | 452 +++++++++-----------
8 files changed, 580 insertions(+), 387 deletions(-)
create mode 100755 api/checkin.pl
create mode 100755 api/checkouts.pl
create mode 100755 api/renew.pl
--- a/Koha/Schema/Result/Issue.pm
+++ a/Koha/Schema/Result/Issue.pm
@@ -190,4 +190,28 @@ __PACKAGE__->belongs_to(
{ join_type => "LEFT", on_delete => "CASCADE", on_update => "CASCADE" },
);
+__PACKAGE__->belongs_to(
+ "item",
+ "Koha::Schema::Result::Item",
+ { itemnumber => "itemnumber" },
+ {
+ is_deferrable => 1,
+ join_type => "LEFT",
+ on_delete => "CASCADE",
+ on_update => "CASCADE",
+ },
+);
+
+__PACKAGE__->belongs_to(
+ "branch",
+ "Koha::Schema::Result::Branch",
+ { branchcode => "branchcode" },
+ {
+ is_deferrable => 1,
+ join_type => "LEFT",
+ on_delete => "CASCADE",
+ on_update => "CASCADE",
+ },
+);
+
1;
--- a/api/checkin.pl
+++ a/api/checkin.pl
@@ -0,0 +1,75 @@
+#!/usr/bin/perl
+
+# Copyright 2014 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 JSON qw(to_json);
+
+use C4::Circulation;
+use C4::Items qw(GetBarcodeFromItemnumber);
+use C4::Context;
+use C4::Auth qw(check_cookie_auth);
+
+use Koha::DateUtils qw(output_pref_due);
+
+my $input = new CGI;
+
+my ( $auth_status, $sessionID ) =
+ check_cookie_auth( $input->cookie('CGISESSID'),
+ { circulate => 'circulate_remaining_permissions' } );
+
+if ( $auth_status ne "ok" ) {
+ exit 0;
+}
+
+binmode STDOUT, ":encoding(UTF-8)";
+print $input->header( -type => 'text/plain', -charset => 'UTF-8' );
+
+my $itemnumber = $input->param('itemnumber');
+my $borrowernumber = $input->param('borrowernumber');
+my $override_limit = $input->param('override_limit');
+my $exempt_fine = $input->param('exempt_fine');
+my $branchcode = $input->param('branchcode')
+ || C4::Context->userenv->{'branch'};
+
+my $barcode = GetBarcodeFromItemnumber($itemnumber);
+
+my $data;
+$data->{itemnumber} = $itemnumber;
+$data->{borrowernumber} = $borrowernumber;
+$data->{branchcode} = $branchcode;
+
+if ( C4::Context->preference("InProcessingToShelvingCart") ) {
+ my $item = GetItem($itemnumber);
+ if ( $item->{'location'} eq 'PROC' ) {
+ $item->{'location'} = 'CART';
+ ModItem( $item, $item->{'biblionumber'}, $item->{'itemnumber'} );
+ }
+}
+
+if ( C4::Context->preference("ReturnToShelvingCart") ) {
+ my $item = GetItem($itemnumber);
+ $item->{'location'} = 'CART';
+ ModItem( $item, $item->{'biblionumber'}, $item->{'itemnumber'} );
+}
+
+( $data->{returned} ) = AddReturn( $barcode, $branchcode, $exempt_fine );
+
+print to_json($data);
--- a/api/checkouts.pl
+++ a/api/checkouts.pl
@@ -0,0 +1,116 @@
+#!/usr/bin/perl
+
+# This software is placed under the gnu General Public License, v2 (http://www.gnu.org/licenses/gpl.html)
+
+# Copyright 2014 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 3 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 JSON qw(to_json);
+
+use C4::Context;
+use C4::Charset;
+use C4::Auth qw(check_cookie_auth);
+use C4::Circulation qw(GetIssuingCharges CanBookBeRenewed GetRenewCount);
+
+use Koha::Database;
+use Koha::DateUtils;
+
+my $input = new CGI;
+
+my ( $auth_status, $sessionID ) =
+ check_cookie_auth( $input->cookie('CGISESSID'),
+ { circulate => 'circulate_remaining_permissions' } );
+
+if ( $auth_status ne "ok" ) {
+ exit 0;
+}
+
+my $schema = Koha::Database->new()->schema();
+
+my @sort_columns = qw/date_due title itype issuedate branchcode itemcallnumber/;
+
+my $borrowernumber = $input->param('borrowernumber');
+my $offset = $input->param('iDisplayStart');
+my $results_per_page = $input->param('iDisplayLength');
+my $sorting_column = $sort_columns[ $input->param('iSortCol_0') ];
+my $sorting_direction = $input->param('sSortDir_0');
+
+$results_per_page = undef if ( $results_per_page == -1 );
+
+binmode STDOUT, ":encoding(UTF-8)";
+print $input->header( -type => 'text/plain', -charset => 'UTF-8' );
+
+my $checkouts_rs =
+ $schema->resultset('Issue')->search( { borrowernumber => $borrowernumber },
+ { prefetch => { 'item' => 'biblio' }, orderby => 'issuedate' } );
+
+my @checkouts;
+while ( my $c = $checkouts_rs->next() ) {
+ my $itemnumber = $c->itemnumber()->itemnumber();
+
+ my ($charge) = GetIssuingCharges(
+ $c->itemnumber()->itemnumber(),
+ $c->borrowernumber()->borrowernumber()
+ );
+
+ my ( $can_renew, $can_renew_error ) =
+ CanBookBeRenewed( $borrowernumber, $itemnumber );
+
+ my ( $renewals_count, $renewals_allowed, $renewals_remaining ) =
+ GetRenewCount( $borrowernumber, $itemnumber );
+
+ push(
+ @checkouts,
+ {
+ DT_RowId => "$itemnumber-$borrowernumber",
+ title => $c->item()->biblio()->title(),
+ author => $c->item()->biblio()->author(),
+ barcode => $c->item()->barcode(),
+ itemtype => $c->item()->effective_itemtype(),
+ branchcode => $c->branchcode(),
+ branchname => $c->branch->branchname(),
+ itemcallnumber => $c->item()->itemcallnumber() || q{},
+ charge => $charge,
+ price => $c->item->replacementprice() || q{},
+ can_renew => $can_renew,
+ can_renew_error => $can_renew_error,
+ itemnumber => $itemnumber,
+ borrowernumber => $borrowernumber,
+ biblionumber => $c->item()->biblio()->biblionumber,
+ issuedate => $c->issuedate(),
+ date_due => $c->date_due(),
+ renewals_count => $renewals_count,
+ renewals_allowed => $renewals_allowed,
+ renewals_remaining => $renewals_remaining,
+ issuedate_formatted =>
+ output_pref( dt_from_string( $c->issuedate() ) ),
+ date_due_formatted =>
+ output_pref_due( dt_from_string( $c->date_due() ) ),
+ }
+ );
+}
+
+my $data;
+$data->{'iTotalRecords'} = scalar @checkouts; #FIXME
+$data->{'iTotalDisplayRecords'} = scalar @checkouts;
+$data->{'sEcho'} = $input->param('sEcho') || undef;
+$data->{'aaData'} = \@checkouts;
+
+print to_json($data);
--- a/api/renew.pl
+++ a/api/renew.pl
@@ -0,0 +1,63 @@
+#!/usr/bin/perl
+
+# Copyright 2014 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 JSON qw(to_json);
+
+use C4::Circulation;
+use C4::Context;
+use C4::Auth qw(check_cookie_auth);
+
+use Koha::DateUtils qw(output_pref_due);
+
+my $input = new CGI;
+
+my ( $auth_status, $sessionID ) =
+ check_cookie_auth( $input->cookie('CGISESSID'),
+ { circulate => 'circulate_remaining_permissions' } );
+
+if ( $auth_status ne "ok" ) {
+ exit 0;
+}
+
+binmode STDOUT, ":encoding(UTF-8)";
+print $input->header( -type => 'text/plain', -charset => 'UTF-8' );
+
+my $itemnumber = $input->param('itemnumber');
+my $borrowernumber = $input->param('borrowernumber');
+my $override_limit = $input->param('override_limit');
+my $branchcode = $input->param('branchcode')
+ || C4::Context->userenv->{'branch'};
+
+my $data;
+$data->{itemnumber} = $itemnumber;
+$data->{borrowernumber} = $borrowernumber;
+$data->{branchcode} = $branchcode;
+
+( $data->{renew_okay}, $data->{error} ) =
+ CanBookBeRenewed( $borrowernumber, $itemnumber, $override_limit );
+
+if ( $data->{renew_okay} ) {
+ my $date_due = AddRenewal( $borrowernumber, $itemnumber, $branchcode );
+ $data->{date_due} = output_pref_due( $date_due );
+}
+
+print to_json($data);
--- a/circ/circulation.pl
+++ a/circ/circulation.pl
@@ -96,14 +96,6 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user (
my $branches = GetBranches();
-my @failedrenews = $query->param('failedrenew'); # expected to be itemnumbers
-our %renew_failed = ();
-for (@failedrenews) { $renew_failed{$_} = 1; }
-
-my @failedreturns = $query->param('failedreturn');
-our %return_failed = ();
-for (@failedreturns) { $return_failed{$_} = 1; }
-
my $findborrower = $query->param('findborrower') || q{};
$findborrower =~ s|,| |g;
my $borrowernumber = $query->param('borrowernumber');
@@ -466,91 +458,6 @@ our @relissues = ();
our @relprevissues = ();
my $displayrelissues;
-our $totalprice = 0;
-
-sub build_issue_data {
- my $issueslist = shift;
- my $relatives = shift;
-
- # split in 2 arrays for today & previous
- foreach my $it ( @$issueslist ) {
- my $itemtypeinfo = getitemtypeinfo( (C4::Context->preference('item-level_itypes')) ? $it->{'itype'} : $it->{'itemtype'} );
-
- # set itemtype per item-level_itype syspref - FIXME this is an ugly hack
- $it->{'itemtype'} = ( C4::Context->preference( 'item-level_itypes' ) ) ? $it->{'itype'} : $it->{'itemtype'};
-
- ($it->{'charge'}, $it->{'itemtype_charge'}) = GetIssuingCharges(
- $it->{'itemnumber'}, $it->{'borrowernumber'}
- );
- $it->{'charge'} = sprintf("%.2f", $it->{'charge'});
- my ($can_renew, $can_renew_error) = CanBookBeRenewed(
- $it->{'borrowernumber'},$it->{'itemnumber'}
- );
- $it->{"renew_error_${can_renew_error}"} = 1 if defined $can_renew_error;
- my $restype = C4::Reserves::GetReserveStatus( $it->{'itemnumber'} );
- $it->{'can_renew'} = $can_renew;
- $it->{'can_confirm'} = !$can_renew && !$restype;
- $it->{'renew_error'} = ( $restype eq "Waiting" or $restype eq "Reserved" ) ? 1 : 0;
- $it->{'checkoutdate'} = C4::Dates->new($it->{'issuedate'},'iso')->output('syspref');
- $it->{'issuingbranchname'} = GetBranchName($it->{'branchcode'});
-
- $totalprice += $it->{'replacementprice'} || 0;
- $it->{'itemtype'} = $itemtypeinfo->{'description'};
- $it->{'itemtype_image'} = $itemtypeinfo->{'imageurl'};
- $it->{'dd_sort'} = $it->{'date_due'};
- $it->{'dd'} = output_pref($it->{'date_due'});
- $it->{'displaydate_sort'} = $it->{'issuedate'};
- $it->{'displaydate'} = output_pref($it->{'issuedate'});
- #$it->{'od'} = ( $it->{'date_due'} lt $todaysdate ) ? 1 : 0 ;
- $it->{'od'} = $it->{'overdue'};
- $it->{'subtitle'} = GetRecordValue('subtitle', GetMarcBiblio($it->{biblionumber}), GetFrameworkCode($it->{biblionumber}));
- $it->{'renew_failed'} = $renew_failed{$it->{'itemnumber'}};
- $it->{'return_failed'} = $return_failed{$it->{'barcode'}};
-
- if ( ( $it->{'issuedate'} && $it->{'issuedate'} gt $todaysdate )
- || ( $it->{'lastreneweddate'} && $it->{'lastreneweddate'} gt $todaysdate ) ) {
- (!$relatives) ? push @todaysissues, $it : push @relissues, $it;
- } else {
- (!$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
- }
-}
-
-if ($borrower) {
-
- # Getting borrower relatives
- my @relborrowernumbers = GetMemberRelatives($borrower->{'borrowernumber'});
- #push @borrowernumbers, $borrower->{'borrowernumber'};
-
- # get each issue of the borrower & separate them in todayissues & previous issues
- my $issueslist = GetPendingIssues($borrower->{'borrowernumber'});
- my $relissueslist = [];
- if ( @relborrowernumbers ) {
- $relissueslist = GetPendingIssues(@relborrowernumbers);
- }
-
- build_issue_data($issueslist, 0);
- build_issue_data($relissueslist, 1);
-
- $displayrelissues = scalar($relissueslist);
-
- if ( C4::Context->preference( "todaysIssuesDefaultSortOrder" ) eq 'asc' ) {
- @todaysissues = sort { $a->{'timestamp'} cmp $b->{'timestamp'} } @todaysissues;
- }
- else {
- @todaysissues = sort { $b->{'timestamp'} cmp $a->{'timestamp'} } @todaysissues;
- }
-
- if ( C4::Context->preference( "previousIssuesDefaultSortOrder" ) eq 'asc' ){
- @previousissues = sort { $a->{'date_due'} cmp $b->{'date_due'} } @previousissues;
- }
- else {
- @previousissues = sort { $b->{'date_due'} cmp $a->{'date_due'} } @previousissues;
- }
-}
-
-
my @values;
my %labels;
my $CGIselectborrower;
@@ -739,7 +646,6 @@ $template->param(
duedatespec => $duedatespec,
message => $message,
CGIselectborrower => $CGIselectborrower,
- totalprice => sprintf('%.2f', $totalprice),
totaldue => sprintf('%.2f', $total),
todayissues => \@todaysissues,
previssues => \@previousissues,
--- a/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css
+++ a/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css
@@ -270,7 +270,7 @@ tr.even td, tr.even.highlight td {
border-right : 1px solid #BCBCBC;
}
-td.od {
+.overdue td.od {
color : #cc0000;
font-weight : bold;
}
--- a/koha-tmpl/intranet-tmpl/prog/en/js/pages/circulation.js
+++ a/koha-tmpl/intranet-tmpl/prog/en/js/pages/circulation.js
@@ -1,57 +1,128 @@
$(document).ready(function() {
- $('#patronlists').tabs();
- var allcheckboxes = $(".checkboxed");
- $("#renew_all").on("click",function(){
- allcheckboxes.checkCheckboxes(":input[name*=items]");
- allcheckboxes.unCheckCheckboxes(":input[name*=barcodes]");
- });
- $("#CheckAllitems").on("click",function(){
- allcheckboxes.checkCheckboxes(":input[name*=items]");
- allcheckboxes.unCheckCheckboxes(":input[name*=barcodes]"); return false;
+ // Handle the select all/none links for checkouts table columns
+ $("#CheckAllRenewals").on("click",function(){
+ $("#UncheckAllCheckins").click();
+ $(".renew:visible").attr("checked", "checked" );
+ return false;
});
- $("#CheckNoitems").on("click",function(){
- allcheckboxes.unCheckCheckboxes(":input[name*=items]"); return false;
+ $("#UncheckAllRenewals").on("click",function(){
+ $(".renew:visible").removeAttr("checked");
+ return false;
});
- $("#CheckAllreturns").on("click",function(){
- allcheckboxes.checkCheckboxes(":input[name*=barcodes]");
- allcheckboxes.unCheckCheckboxes(":input[name*=items]"); return false;
+
+ $("#CheckAllCheckins").on("click",function(){
+ $("#UncheckAllRenewals").click();
+ $(".checkin:visible").attr("checked", "checked" );
+ return false;
});
- $("#CheckNoreturns" ).on("click",function(){
- allcheckboxes.unCheckCheckboxes(":input[name*=barcodes]"); return false;
+ $("#UncheckAllCheckins").on("click",function(){
+ $(".checkin:visible").removeAttr("checked");
+ return false;
});
- $("#CheckAllexports").on("click",function(){
- allcheckboxes.checkCheckboxes(":input[name*=biblionumbers]");
+ $("#CheckAllExports").on("click",function(){
+ $(".export:visible").attr("checked", "checked" );
return false;
});
- $("#CheckNoexports").on("click",function(){
- allcheckboxes.unCheckCheckboxes(":input[name*=biblionumbers]");
+ $("#UncheckAllExports").on("click",function(){
+ $(".export:visible").removeAttr("checked");
return false;
});
- $("#relrenew_all").on("click",function(){
- allcheckboxes.checkCheckboxes(":input[name*=items]");
- allcheckboxes.unCheckCheckboxes(":input[name*=barcodes]");
- });
- $("#relCheckAllitems").on("click",function(){
- allcheckboxes.checkCheckboxes(":input[name*=items]");
- allcheckboxes.unCheckCheckboxes(":input[name*=barcodes]"); return false;
+ // Don't allow both return and renew checkboxes to be checked
+ $(document).on("change", '.renew', function(){
+ if ( $(this).is(":checked") ) {
+ $( "#checkin_" + $(this).val() ).removeAttr("checked");
+ }
});
- $("#relCheckNoitems").on("click",function(){
- allcheckboxes.unCheckCheckboxes(":input[name*=items]"); return false;
+ $(document).on("change", '.checkin', function(){
+ if ( $(this).is(":checked") ) {
+ $( "#renew_" + $(this).val() ).removeAttr("checked");
+ }
});
- $("#relCheckAllreturns").on("click",function(){
- allcheckboxes.checkCheckboxes(":input[name*=barcodes]");
- allcheckboxes.unCheckCheckboxes(":input[name*=items]"); return false;
+
+ // Handle renewals
+ $("#RenewCheckinChecked").on("click",function(){
+ $(".checkin:checked:visible").each(function() {
+ itemnumber = $(this).val();
+
+ $(this).replaceWith("");
+
+ params = {
+ itemnumber: itemnumber,
+ borrowernumber: borrowernumber,
+ branchcode: branchcode
+ };
+
+ $.post( "/cgi-bin/koha/api/checkin.pl", params, function( data ) {
+ id = "#checkin_" + data.itemnumber;
+
+ content = "";
+ if ( data.returned ) {
+ content = _("Returned");
+ } else {
+ content = _("Unable to return");
+ }
+
+ $(id).replaceWith( content );
+ }, "json")
+ });
+
+ $(".renew:checked:visible").each(function() {
+ var override_limit = $("#override_limit").is(':checked') ? 1 : 0;
+
+ var itemnumber = $(this).val();
+
+ $(this).replaceWith("");
+
+ var params = {
+ itemnumber: itemnumber,
+ borrowernumber: borrowernumber,
+ branchcode: branchcode,
+ override_limit: override_limit
+ };
+
+ $.post( "/cgi-bin/koha/api/renew.pl", params, function( data ) {
+ var id = "#renew_" + data.itemnumber;
+
+ var content = "";
+ if ( data.renew_okay ) {
+ content = _("Renewed, due: ") + data.date_due;
+ } else {
+ content = _("Renew failed: ");
+ if ( data.error == "no_checkout" ) {
+ content += _("not checked out");
+ } else if ( data.error == "too_many" ) {
+ content += _("too many renewals");
+ } else if ( data.error == "on_reserve" ) {
+ content += _("on reserve");
+ } else if ( data.error ) {
+ content += data.error;
+ } else {
+ content += _("reason unknown");
+ }
+ }
+
+ $(id).replaceWith( content );
+ }, "json")
+ });
});
- $("#relCheckNoreturns").on("click",function(){
- allcheckboxes.unCheckCheckboxes(":input[name*=barcodes]"); return false;
+
+ $("#RenewAll").on("click",function(){
+ $("#CheckAllRenewals").click();
+ $("#UncheckAllCheckins").click();
+ $("#RenewCheckinChecked").click();
});
+
+ $('#patronlists').tabs();
+
$("#messages ul").after(""+MSG_ADD_MESSAGE+"");
+
$("#borrower_messages .cancel").on("click",function(){
$("#add_message_form").hide();
$("#addmessage").show();
});
+
$("#addmessage").on("click",function(){
$(this).hide();
$("#add_message_form").show();
@@ -77,7 +148,7 @@ $(document).ready(function() {
return false;
});
// Clicking the table cell checks the checkbox inside it
- $("td").on("click",function(e){
+ $(document).on("click", 'td', function(e){
if(e.target.tagName.toLowerCase() == 'td'){
$(this).find("input:checkbox:visible").each( function() {
$(this).click();
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt
+++ a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt
@@ -13,15 +13,21 @@
[% INCLUDE 'doc-head-close.inc' %]
[% INCLUDE 'calendar.inc' %]
-[% IF ( UseTablesortForCirc ) %]
+
[% INCLUDE 'datatables-strings.inc' %]
-[% END %]
+