@@ -, +, @@ --- Koha/Schema/Result/Reserve.pm | 24 +++- api/holds.pl | 143 ++++++++++++++++++++ circ/circulation.pl | 87 +------------ koha-tmpl/intranet-tmpl/prog/en/js/holds.js | 131 ++++++++++++++++++ .../prog/en/modules/circ/circulation.tt | 70 +++------- .../prog/en/modules/members/moremember.tt | 79 ++++-------- members/moremember.pl | 74 +---------- 7 files changed, 350 insertions(+), 258 deletions(-) create mode 100755 api/holds.pl create mode 100644 koha-tmpl/intranet-tmpl/prog/en/js/holds.js --- a/Koha/Schema/Result/Reserve.pm +++ a/Koha/Schema/Result/Reserve.pm @@ -288,6 +288,28 @@ __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:ig/fobzvZf1OgAHZFtkyyQ +__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( + "biblio", + "Koha::Schema::Result::Biblio", + { biblionumber => "biblionumber" }, + { + is_deferrable => 1, + 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; --- a/api/holds.pl +++ a/api/holds.pl @@ -0,0 +1,143 @@ +#!/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::Auth qw(check_cookie_auth); +use C4::Biblio qw(GetMarcBiblio GetFrameworkCode GetRecordValue ); +use C4::Branch qw(GetBranchName); +use C4::Charset; +use C4::Circulation qw(GetTransfers); +use C4::Context; + +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 $branch = C4::Context->userenv->{'branch'}; + +my $schema = Koha::Database->new()->schema(); + +my @sort_columns = + qw/reservedate title itemcallnumber barcode expirationdate priority/; + +my $borrowernumber = $input->param('borrowernumber'); +my $offset = $input->param('iDisplayStart'); +my $results_per_page = $input->param('iDisplayLength'); +my $sorting_direction = $input->param('sSortDir_0') || 'desc'; +my $sorting_column = $sort_columns[ $input->param('iSortCol_0') ] + || 'reservedate'; + +binmode STDOUT, ":encoding(UTF-8)"; +print $input->header( -type => 'text/plain', -charset => 'UTF-8' ); + +my $holds_rs = $schema->resultset('Reserve')->search( + { borrowernumber => $borrowernumber }, + { + prefetch => { 'item' => 'biblio' }, + order_by => { "-$sorting_direction" => $sorting_column } + } +); + +my $borrower; +my @holds; +while ( my $h = $holds_rs->next() ) { + my $item = $h->item(); + + my $biblionumber = $h->biblio()->biblionumber(); + + my $hold = { + DT_RowId => $h->reserve_id(), + biblionumber => $biblionumber, + title => $h->biblio()->title(), + author => $h->biblio()->author(), + reserve_id => $h->reserve_id(), + reservedate => $h->reservedate(), + expirationdate => $h->expirationdate(), + suspend => $h->suspend(), + suspend_until => $h->suspend_until(), + found => $h->found(), + waiting => $h->found() eq 'W', + waiting_at => $h->branchcode()->branchname(), + waiting_here => $h->branchcode()->branchcode() eq $branch, + priority => $h->priority(), + subtitle => GetRecordValue( + 'subtitle', GetMarcBiblio($biblionumber), + GetFrameworkCode($biblionumber) + ), + reservedate_formatted => $h->reservedate() + ? output_pref_due( dt_from_string( $h->reservedate() ) ) + : q{}, + suspend_until_formatted => $h->suspend_until() + ? output_pref_due( dt_from_string( $h->suspend_until() ) ) + : q{}, + expirationdate_formatted => $h->expirationdate() + ? output_pref_due( dt_from_string( $h->expirationdate() ) ) + : q{}, + }; + + $hold->{transfered} = 0; + $hold->{not_transfered} = 0; + + if ($item) { + $hold->{itemnumber} = $item->itemnumber(); + $hold->{barcode} = $item->barcode(); + $hold->{itemtype} = $item->effective_itemtype(); + $hold->{itemcallnumber} = $item->itemcallnumber() || q{}; + + my ( $transferred_when, $transferred_from, $transferred_to ) = + GetTransfers( $item->itemnumber() ); + if ($transferred_when) { + $hold->{color} = 'transferred'; + $hold->{transferred} = 1; + $hold->{date_sent} = format_date($transferred_when); + $hold->{from_branch} = GetBranchName($transferred_from); + } + elsif ( $item->holdingbranch()->branchcode() ne + $h->branchcode()->branchcode() ) + { + $hold->{not_transferred} = 1; + $hold->{not_transferred_by} = $h->branchcode()->branchname(); + } + } + + push( @holds, $hold ); +} + +my $data; +$data->{'iTotalRecords'} = scalar @holds; +$data->{'iTotalDisplayRecords'} = scalar @holds; +$data->{'sEcho'} = $input->param('sEcho') || undef; +$data->{'aaData'} = \@holds; + +print to_json($data); --- a/circ/circulation.pl +++ a/circ/circulation.pl @@ -361,91 +361,10 @@ if ($borrowernumber) { # BUILD HTML # show all reserves of this borrower, and the position of the reservation .... if ($borrowernumber) { + $template->param( + holds_count => Koha::Database->new()->schema()->resultset('Reserve') + ->count( { borrowernumber => $borrowernumber } ) ); - # new op dev - # now we show the status of the borrower's reservations - my @borrowerreserv = GetReservesFromBorrowernumber($borrowernumber ); - my @reservloop; - my @WaitingReserveLoop; - - foreach my $num_res (@borrowerreserv) { - my %getreserv; - my %getWaitingReserveInfo; - my $getiteminfo = GetBiblioFromItemNumber( $num_res->{'itemnumber'} ); - my $itemtypeinfo = getitemtypeinfo( (C4::Context->preference('item-level_itypes')) ? $getiteminfo->{'itype'} : $getiteminfo->{'itemtype'} ); - my ( $transfertwhen, $transfertfrom, $transfertto ) = - GetTransfers( $num_res->{'itemnumber'} ); - - $getreserv{waiting} = 0; - $getreserv{transfered} = 0; - $getreserv{nottransfered} = 0; - - $getreserv{reservedate} = format_date( $num_res->{'reservedate'} ); - $getreserv{reserve_id} = $num_res->{'reserve_id'}; - $getreserv{title} = $getiteminfo->{'title'}; - $getreserv{subtitle} = GetRecordValue('subtitle', GetMarcBiblio($getiteminfo->{biblionumber}), GetFrameworkCode($getiteminfo->{biblionumber})); - $getreserv{itemtype} = $itemtypeinfo->{'description'}; - $getreserv{author} = $getiteminfo->{'author'}; - $getreserv{barcodereserv} = $getiteminfo->{'barcode'}; - $getreserv{itemcallnumber} = $getiteminfo->{'itemcallnumber'}; - $getreserv{biblionumber} = $getiteminfo->{'biblionumber'}; - $getreserv{waitingat} = GetBranchName( $num_res->{'branchcode'} ); - $getreserv{suspend} = $num_res->{'suspend'}; - $getreserv{suspend_until} = $num_res->{'suspend_until'}; - # check if we have a waiting status for reservations - if ( $num_res->{'found'} && $num_res->{'found'} eq 'W' ) { - $getreserv{color} = 'reserved'; - $getreserv{waiting} = 1; -# genarate information displaying only waiting reserves - $getWaitingReserveInfo{title} = $getiteminfo->{'title'}; - $getWaitingReserveInfo{biblionumber} = $getiteminfo->{'biblionumber'}; - $getWaitingReserveInfo{itemtype} = $itemtypeinfo->{'description'}; - $getWaitingReserveInfo{author} = $getiteminfo->{'author'}; - $getWaitingReserveInfo{itemcallnumber} = $getiteminfo->{'itemcallnumber'}; - $getWaitingReserveInfo{reservedate} = format_date( $num_res->{'reservedate'} ); - $getWaitingReserveInfo{waitingat} = GetBranchName( $num_res->{'branchcode'} ); - $getWaitingReserveInfo{waitinghere} = 1 if $num_res->{'branchcode'} eq $branch; - } - # check transfers with the itemnumber foud in th reservation loop - if ($transfertwhen) { - $getreserv{color} = 'transfered'; - $getreserv{transfered} = 1; - $getreserv{datesent} = format_date($transfertwhen); - $getreserv{frombranch} = GetBranchName($transfertfrom); - } elsif ($getiteminfo->{'holdingbranch'} ne $num_res->{'branchcode'}) { - $getreserv{nottransfered} = 1; - $getreserv{nottransferedby} = GetBranchName( $getiteminfo->{'holdingbranch'} ); - } - -# if we don't have a reserv on item, we put the biblio infos and the waiting position - if ( $getiteminfo->{'title'} eq '' ) { - my $getbibinfo = GetBiblioData( $num_res->{'biblionumber'} ); - - $getreserv{color} = 'inwait'; - $getreserv{title} = $getbibinfo->{'title'}; - $getreserv{subtitle} = GetRecordValue('subtitle', GetMarcBiblio($num_res->{biblionumber}), GetFrameworkCode($num_res->{biblionumber})); - $getreserv{nottransfered} = 0; - $getreserv{itemtype} = $itemtypeinfo->{'description'}; - $getreserv{author} = $getbibinfo->{'author'}; - $getreserv{biblionumber} = $num_res->{'biblionumber'}; - } - $getreserv{waitingposition} = $num_res->{'priority'}; - $getreserv{expirationdate} = $num_res->{'expirationdate'}; - push( @reservloop, \%getreserv ); - -# if we have a reserve waiting, initiate waitingreserveloop - if ($getreserv{waiting} == 1) { - push (@WaitingReserveLoop, \%getWaitingReserveInfo) - } - - } - - # return result to the template - $template->param( - countreserv => scalar @reservloop, - reservloop => \@reservloop , - WaitingReserveLoop => \@WaitingReserveLoop, - ); $template->param( adultborrower => 1 ) if ( $borrower->{'category_type'} eq 'A' ); } --- a/koha-tmpl/intranet-tmpl/prog/en/js/holds.js +++ a/koha-tmpl/intranet-tmpl/prog/en/js/holds.js @@ -0,0 +1,131 @@ +$(document).ready(function() { + // Don't load holds table unless it is clicked on + var holdsTable; + $("#holds-tab").click( function() { + if ( ! holdsTable ) { + holdsTable = $("#holds-table").dataTable({ + "sDom": "<'row-fluid'<'span6'><'span6'>r>t<'row-fluid'>t", + "aoColumns": [ + { + "mDataProp": "reservedate_formatted" + }, + { + "mDataProp": function ( oObj ) { + title = "" + + oObj.title; + + $.each(oObj.subtitle, function( index, value ) { + title += " " + value.subfield; + }); + + title += ""; + + if ( oObj.author ) { + title += " " + _("by") + " " + oObj.author; + } + + if ( oObj.itemnotes ) { + var span_class = ""; + if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) { + span_class = "circ-hlt"; + } + title += " - " + oObj.itemnotes + "" + } + + title += " " + + "" + + oObj.barcode + + ""; + + return title; + } + }, + { + "mDataProp": function( oObj ) { + return oObj.itemcallnumber || ""; + } + }, + { + "mDataProp": function( oObj ) { + var data = ""; + + if ( oObj.suspend == 1 ) { + data += "

" + _("Hold is") + " " + _("suspended") + " "; + if ( oObj.suspend_until ) { + data += " " + _("until") + " " + oObj.suspend_until_formatted; + } + data += "

"; + } + + if ( oObj.barcode ) { + data += ""; + if ( oObj.found == "W" ) { + data += _("Item is") + " " + _("waiting") + " "; + + if ( ! oObj.waiting_here ) { + data += " " + _("at") + " " + oObj.waiting_at; + } + } else if ( oObj.transferred ) { + data += _("Item is") + " " + _("in transit") + " " + _("from") + oObj.from_branch; + } else if ( oObj.not_transferred ) { + data += _("Item hasn't been transferred yet from") + " " + oObj.not_transferred_by; + } data += ""; + + data += " " + oObj.barcode + ""; + } + + return data; + } + }, + { "mDataProp": "expirationdate_formatted" }, + { + "mDataProp": function( oObj ) { + if ( oObj.priority && parseInt( oObj.priority ) && parseInt( oObj.priority ) > 0 ) { + return oObj.priority; + } else { + return ""; + } + } + }, + { + "mDataProp": function( oObj ) { + return "" + + "" + + "" + + ""; + } + } + ], + "bPaginate": false, + "bProcessing": true, + "bServerSide": true, + "sAjaxSource": '/cgi-bin/koha/api/holds.pl', + "fnServerData": function ( sSource, aoData, fnCallback ) { + aoData.push( { "name": "borrowernumber", "value": borrowernumber } ); + + $.getJSON( sSource, aoData, function (json) { + fnCallback(json) + } ); + }, + }); + + $("#holds-table_processing").position({ + of: $( "#holds-table" ), + collision: "none" + }); + } + }); + +}); --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt @@ -22,6 +22,7 @@ [% INCLUDE 'timepicker.inc' %] + [% INCLUDE 'timepicker.inc' %] +