X-Git-Url: http://koha-dev.rot13.org:8081/gitweb/?a=blobdiff_plain;f=circ%2Fcirculation.pl;h=ef0edf7cf8c9793f40b11be7d5635da5bbe7822a;hb=df97814f3034a3d5015546c4eca21f08ae951e37;hp=b051281d2127885b075fe29073fbe33d8766df4d;hpb=8a53d284907bbbe9d3ee2552e964af9f5dfbd0ac;p=srvgit diff --git a/circ/circulation.pl b/circ/circulation.pl index b051281d21..ff32c0cc0d 100755 --- a/circ/circulation.pl +++ b/circ/circulation.pl @@ -5,75 +5,71 @@ # Copyright 2000-2002 Katipo Communications # copyright 2010 BibLibre # Copyright 2011 PTFS-Europe Ltd. +# Copyright 2012 software.coop and MJ Ray # # 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 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. +# 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. +# You should have received a copy of the GNU General Public License +# along with Koha; if not, see . use strict; use warnings; -use CGI; +use CGI qw ( -utf8 ); +use DateTime; +use DateTime::Duration; use C4::Output; use C4::Print; -use C4::Auth qw/:DEFAULT get_session/; -use C4::Dates qw/format_date/; -use C4::Branch; # GetBranches +use C4::Auth qw/:DEFAULT get_session haspermission/; use C4::Koha; # GetPrinter use C4::Circulation; -use C4::Overdues qw/CheckBorrowerDebarred/; +use C4::Utils::DataTables::Members; use C4::Members; use C4::Biblio; +use C4::Search; +use MARC::Record; use C4::Reserves; +use Koha::Holds; use C4::Context; use CGI::Session; use C4::Members::Attributes qw(GetBorrowerAttributes); +use Koha::Patron; +use Koha::Patron::Debarments qw(GetDebarments); use Koha::DateUtils; +use Koha::Database; +use Koha::Patron::Messages; +use Koha::Patron::Images; +use Koha::SearchEngine; +use Koha::SearchEngine::Search; +use Koha::Patron::Modifications; use Date::Calc qw( Today - Add_Delta_YM Add_Delta_Days Date_to_Days ); use List::MoreUtils qw/uniq/; - # # PARAMETERS READING # my $query = new CGI; +my $override_high_holds = $query->param('override_high_holds'); +my $override_high_holds_tmp = $query->param('override_high_holds_tmp'); + my $sessionID = $query->cookie("CGISESSID") ; my $session = get_session($sessionID); - -# branch and printer are now defined by the userenv -# but first we have to check if someone has tried to change them - -my $branch = $query->param('branch'); -if ($branch){ - # update our session so the userenv is updated - $session->param('branch', $branch); - $session->param('branchname', GetBranchName($branch)); -} - -my $printer = $query->param('printer'); -if ($printer){ - # update our session so the userenv is updated - $session->param('branchprinter', $printer); -} - -if (!C4::Context->userenv && !$branch){ +if (!C4::Context->userenv){ if ($session->param('branch') eq 'NO_LIBRARY_SET'){ # no branch set we can't issue print $query->redirect("/cgi-bin/koha/circ/selectbranchprinter.pl"); @@ -81,9 +77,46 @@ if (!C4::Context->userenv && !$branch){ } } +my $barcodes = []; +my $barcode = $query->param('barcode'); +# Barcode given by user could be '0' +if ( $barcode || ( defined($barcode) && $barcode eq '0' ) ) { + $barcodes = [ $barcode ]; +} else { + my $filefh = $query->upload('uploadfile'); + if ( $filefh ) { + while ( my $content = <$filefh> ) { + $content =~ s/[\r\n]*$//g; + push @$barcodes, $content if $content; + } + } elsif ( my $list = $query->param('barcodelist') ) { + push @$barcodes, split( /\s\n/, $list ); + $barcodes = [ map { $_ =~ /^\s*$/ ? () : $_ } @$barcodes ]; + } else { + @$barcodes = $query->multi_param('barcodes'); + } +} + +$barcodes = [ uniq @$barcodes ]; + +my $template_name = q|circ/circulation.tt|; +my $borrowernumber = $query->param('borrowernumber'); +my $borrower = $borrowernumber ? GetMember( borrowernumber => $borrowernumber ) : undef; +my $batch = $query->param('batch'); +my $batch_allowed = 0; +if ( $batch && C4::Context->preference('BatchCheckouts') ) { + $template_name = q|circ/circulation_batch_checkouts.tt|; + my @batch_category_codes = split '\|', C4::Context->preference('BatchCheckoutsValidCategories'); + if ( grep {/^$borrower->{categorycode}$/} @batch_category_codes ) { + $batch_allowed = 1; + } else { + $barcodes = []; + } +} + my ( $template, $loggedinuser, $cookie ) = get_template_and_user ( { - template_name => 'circ/circulation.tmpl', + template_name => $template_name, query => $query, type => "intranet", authnotrequired => 0, @@ -91,23 +124,25 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user ( } ); -my $branches = GetBranches(); +my $force_allow_issue = $query->param('forceallow') || 0; +if (!C4::Auth::haspermission( C4::Context->userenv->{id} , { circulate => 'force_checkout' } )) { + $force_allow_issue = 0; +} + +my $onsite_checkout = $query->param('onsite_checkout'); -my @failedrenews = $query->param('failedrenew'); # expected to be itemnumbers -our %renew_failed = {}; +my @failedrenews = $query->multi_param('failedrenew'); # expected to be itemnumbers +our %renew_failed = (); for (@failedrenews) { $renew_failed{$_} = 1; } -my @failedreturns = $query->param('failedreturn'); -our %return_failed = {}; +my @failedreturns = $query->multi_param('failedreturn'); +our %return_failed = (); for (@failedreturns) { $return_failed{$_} = 1; } -my $findborrower = $query->param('findborrower'); +my $findborrower = $query->param('findborrower') || q{}; $findborrower =~ s|,| |g; -my $borrowernumber = $query->param('borrowernumber'); - -$branch = C4::Context->userenv->{'branch'}; -$printer = C4::Context->userenv->{'branchprinter'}; +my $branch = C4::Context->userenv->{'branch'}; # If AutoLocation is not activated, we show the Circulation Parameters to chage settings of librarian if (C4::Context->preference("AutoLocation") != 1) { @@ -118,56 +153,63 @@ if (C4::Context->preference("DisplayClearScreenButton")) { $template->param(DisplayClearScreenButton => 1); } -if (C4::Context->preference("UseTablesortForCirc")) { - $template->param(UseTablesortForCirc => 1); +for my $barcode ( @$barcodes ) { + $barcode =~ s/^\s*|\s*$//g; # remove leading/trailing whitespace + $barcode = barcodedecode($barcode) + if( $barcode && C4::Context->preference('itemBarcodeInputFilter')); } -my $barcode = $query->param('barcode') || ''; -$barcode =~ s/^\s*|\s*$//g; # remove leading/trailing whitespace - -$barcode = barcodedecode($barcode) if( $barcode && C4::Context->preference('itemBarcodeInputFilter')); my $stickyduedate = $query->param('stickyduedate') || $session->param('stickyduedate'); my $duedatespec = $query->param('duedatespec') || $session->param('stickyduedate'); +$duedatespec = eval { output_pref( { dt => dt_from_string( $duedatespec ), dateformat => 'iso', timeformat => '24hr' }); } + if ( $duedatespec ); +my $restoreduedatespec = $query->param('restoreduedatespec') || $duedatespec || $session->param('stickyduedate'); +if ( $restoreduedatespec && $restoreduedatespec eq "highholds_empty" ) { + undef $restoreduedatespec; +} my $issueconfirmed = $query->param('issueconfirmed'); my $cancelreserve = $query->param('cancelreserve'); -my $organisation = $query->param('organisations'); -my $print = $query->param('print'); -my $newexpiry = $query->param('dateexpiry'); +my $print = $query->param('print') || q{}; my $debt_confirmed = $query->param('debt_confirmed') || 0; # Don't show the debt error dialog twice +my $charges = $query->param('charges') || q{}; # Check if stickyduedate is turned off -if ( $barcode ) { +if ( @$barcodes ) { # was stickyduedate loaded from session? if ( $stickyduedate && ! $query->param("stickyduedate") ) { $session->clear( 'stickyduedate' ); $stickyduedate = $query->param('stickyduedate'); $duedatespec = $query->param('duedatespec'); } + $session->param('auto_renew', scalar $query->param('auto_renew')); +} +else { + $session->clear('auto_renew'); } my ($datedue,$invalidduedate); my $duedatespec_allow = C4::Context->preference('SpecifyDueDate'); -if($duedatespec_allow){ - if ($duedatespec) { - if ($duedatespec =~ C4::Dates->regexp('syspref')) { - $datedue = dt_from_string($duedatespec); - } else { +if( $onsite_checkout && !$duedatespec_allow ) { + $datedue = output_pref({ dt => dt_from_string, dateonly => 1, dateformat => 'iso' }); + $datedue .= ' 23:59:00'; +} elsif( $duedatespec_allow ) { + if ( $duedatespec ) { + $datedue = eval { dt_from_string( $duedatespec ) }; + if (! $datedue ) { $invalidduedate = 1; - $template->param(IMPOSSIBLE=>1, INVALID_DATE=>$duedatespec); + $template->param( IMPOSSIBLE=>1, INVALID_DATE=>$duedatespec ); } } } -our $todaysdate = C4::Dates->new->output('iso'); - # check and see if we should print -if ( $barcode eq '' && $print eq 'maybe' ) { +if ( @$barcodes == 0 && $print eq 'maybe' ) { $print = 'yes'; } -my $inprocess = ($barcode eq '') ? '' : $query->param('inprocess'); -if ( $barcode eq '' && $query->param('charges') eq 'yes' ) { +my $inprocess = (@$barcodes == 0) ? '' : $query->param('inprocess'); +if ( @$barcodes == 0 && $charges eq 'yes' ) { $template->param( PAYCHARGES => 'yes', borrowernumber => $borrowernumber @@ -187,37 +229,35 @@ if ( $print eq 'yes' && $borrowernumber ne '' ) { # STEP 2 : FIND BORROWER # if there is a list of find borrowers.... # -my $borrowerslist; my $message; if ($findborrower) { - my $borrowers = Search($findborrower, 'cardnumber'); - my @borrowers = @$borrowers; - if (C4::Context->preference("AddPatronLists")) { - $template->param( - "AddPatronLists_".C4::Context->preference("AddPatronLists")=> "1", + my $borrower = C4::Members::GetMember( cardnumber => $findborrower ); + if ( $borrower ) { + $borrowernumber = $borrower->{borrowernumber}; + } else { + my $dt_params = { iDisplayLength => -1 }; + my $results = C4::Utils::DataTables::Members::search( + { + searchmember => $findborrower, + searchtype => 'contain', + dt_params => $dt_params, + } ); - if (C4::Context->preference("AddPatronLists")=~/code/){ - my $categories = GetBorrowercategoryList; - $categories->[0]->{'first'} = 1; - $template->param(categories=>$categories); + my $borrowers = $results->{patrons}; + if ( scalar @$borrowers == 1 ) { + $borrowernumber = $borrowers->[0]->{borrowernumber}; + $query->param( 'borrowernumber', $borrowernumber ); + $query->param( 'barcode', '' ); + } elsif ( @$borrowers ) { + $template->param( borrowers => $borrowers ); + } else { + $query->param( 'findborrower', '' ); + $message = "'$findborrower'"; } } - if ( $#borrowers == -1 ) { - $query->param( 'findborrower', '' ); - $message = "'$findborrower'"; - } - elsif ( $#borrowers == 0 ) { - $query->param( 'borrowernumber', $borrowers[0]->{'borrowernumber'} ); - $query->param( 'barcode', '' ); - $borrowernumber = $borrowers[0]->{'borrowernumber'}; - } - else { - $borrowerslist = \@borrowers; - } } # get the borrower information..... -my $borrower; if ($borrowernumber) { $borrower = GetMemberDetails( $borrowernumber, 0 ); my ( $od, $issue, $fines ) = GetMemberIssuesAndFines( $borrowernumber ); @@ -226,13 +266,6 @@ if ($borrowernumber) { my ( $today_year, $today_month, $today_day) = Today(); my ($warning_year, $warning_month, $warning_day) = split /-/, $borrower->{'dateexpiry'}; my ( $enrol_year, $enrol_month, $enrol_day) = split /-/, $borrower->{'dateenrolled'}; - # Renew day is calculated by adding the enrolment period to today - my ( $renew_year, $renew_month, $renew_day); - if ($enrol_year*$enrol_month*$enrol_day>0) { - ( $renew_year, $renew_month, $renew_day) = - Add_Delta_YM( $enrol_year, $enrol_month, $enrol_day, - 0 , $borrower->{'enrolmentperiod'}); - } # if the expiry date is before today ie they have expired if ( !$borrower->{'dateexpiry'} || $warning_year*$warning_month*$warning_day==0 || Date_to_Days($today_year, $today_month, $today_day ) @@ -240,10 +273,9 @@ if ($borrowernumber) { { #borrowercard expired, no issues $template->param( - flagged => "1", - noissues => "1", + noissues => ($force_allow_issue) ? 0 : "1", + forceallow => $force_allow_issue, expired => "1", - renewaldate => format_date("$renew_year-$renew_month-$renew_day") ); } # check for NotifyBorrowerDeparture @@ -252,8 +284,8 @@ if ($borrowernumber) { Date_to_Days( $today_year, $today_month, $today_day ) ) { # borrower card soon to expire warn librarian - $template->param("warndeparture" => format_date($borrower->{dateexpiry}), - flagged => "1",); + $template->param( "warndeparture" => $borrower->{dateexpiry} , + ); if (C4::Context->preference('ReturnBeforeExpiry')){ $template->param("returnbeforeexpiry" => 1); } @@ -264,12 +296,15 @@ if ($borrowernumber) { finetotal => $fines ); - my $debar = CheckBorrowerDebarred($borrowernumber); - if ($debar) { - $template->param( 'userdebarred' => 1 ); - $template->param( 'debarredcomment' => $borrower->{debarredcomment} ); - if ( $debar ne "9999-12-31" ) { - $template->param( 'userdebarreddate' => C4::Dates::format_date($debar) ); + my $patron = Koha::Patrons->find( $borrowernumber ); + if ( $patron and $patron->is_debarred ) { + $template->param( + 'userdebarred' => $borrower->{debarred}, + 'debarredcomment' => $borrower->{debarredcomment}, + ); + + if ( $borrower->{debarred} ne "9999-12-31" ) { + $template->param( 'userdebarreddate' => $borrower->{debarred} ); } } @@ -279,270 +314,165 @@ if ($borrowernumber) { # STEP 3 : ISSUING # # -if ($barcode) { +if (@$barcodes) { + my $checkout_infos; + for my $barcode ( @$barcodes ) { + my $template_params = { barcode => $barcode }; # always check for blockers on issuing - my ( $error, $question, $alerts ) = - CanBookBeIssued( $borrower, $barcode, $datedue , $inprocess ); + my ( $error, $question, $alerts ) = CanBookBeIssued( + $borrower, + $barcode, $datedue, + $inprocess, + undef, + { + onsite_checkout => $onsite_checkout, + override_high_holds => $override_high_holds || $override_high_holds_tmp || 0, + } + ); + my $blocker = $invalidduedate ? 1 : 0; - $template->param( alert => $alerts ); + $template_params->{alert} = $alerts; - delete $question->{'DEBT'} if ($debt_confirmed); - foreach my $impossible ( keys %$error ) { - $template->param( - $impossible => $$error{$impossible}, - IMPOSSIBLE => 1 - ); - $blocker = 1; + # Get the item title for more information + my $getmessageiteminfo = GetBiblioFromItemNumber(undef,$barcode); + $template_params->{authvalcode_notforloan} = + C4::Koha::GetAuthValCode('items.notforloan', $getmessageiteminfo->{'frameworkcode'}); + + # Fix for bug 7494: optional checkout-time fallback search for a book + + if ( $error->{'UNKNOWN_BARCODE'} + && C4::Context->preference("itemBarcodeFallbackSearch") + && not $batch + ) + { + $template_params->{FALLBACK} = 1; + + my $searcher = Koha::SearchEngine::Search->new({index => $Koha::SearchEngine::BIBLIOS_INDEX}); + my $query = "kw=" . $barcode; + my ( $searcherror, $results, $total_hits ) = $searcher->simple_search_compat($query, 0, 10); + + # if multiple hits, offer options to librarian + if ( $total_hits > 0 ) { + my @options = (); + foreach my $hit ( @{$results} ) { + my $chosen = + TransformMarcToKoha( C4::Search::new_record_from_zebra('biblioserver',$hit) ); + + # offer all barcodes individually + if ( $chosen->{barcode} ) { + foreach my $barcode ( sort split(/\s*\|\s*/, $chosen->{barcode}) ) { + my %chosen_single = %{$chosen}; + $chosen_single{barcode} = $barcode; + push( @options, \%chosen_single ); + } + } + } + $template_params->{options} = \@options; + } } - if( !$blocker ){ + + unless( $onsite_checkout and C4::Context->preference("OnSiteCheckoutsForce") ) { + delete $question->{'DEBT'} if ($debt_confirmed); + foreach my $impossible ( keys %$error ) { + $template_params->{$impossible} = $$error{$impossible}; + $template_params->{IMPOSSIBLE} = 1; + $blocker = 1; + } + } + my $iteminfo = GetBiblioFromItemNumber(undef, $barcode); + if( !$blocker || $force_allow_issue ){ my $confirm_required = 0; unless($issueconfirmed){ # Get the item title for more information - my $getmessageiteminfo = GetBiblioFromItemNumber(undef,$barcode); - $template->{VARS}->{'additional_materials'} = $getmessageiteminfo->{'materials'}; - $template->param( itemhomebranch => $getmessageiteminfo->{'homebranch'} ); + my $materials = $iteminfo->{'materials'}; + my $avcode = GetAuthValCode('items.materials'); + if ($avcode) { + $materials = GetKohaAuthorisedValueLib($avcode, $materials); + } + $template_params->{additional_materials} = $materials; + $template_params->{itemhomebranch} = $iteminfo->{'homebranch'}; # pass needsconfirmation to template if issuing is possible and user hasn't yet confirmed. foreach my $needsconfirmation ( keys %$question ) { - $template->param( - $needsconfirmation => $$question{$needsconfirmation}, - getTitleMessageIteminfo => $getmessageiteminfo->{'title'}, - getBarcodeMessageIteminfo => $getmessageiteminfo->{'barcode'}, - NEEDSCONFIRMATION => 1 - ); + $template_params->{$needsconfirmation} = $$question{$needsconfirmation}; + $template_params->{getTitleMessageIteminfo} = $iteminfo->{'title'}; + $template_params->{getBarcodeMessageIteminfo} = $iteminfo->{'barcode'}; + $template_params->{NEEDSCONFIRMATION} = 1; + $template_params->{onsite_checkout} = $onsite_checkout; $confirm_required = 1; } } unless($confirm_required) { - AddIssue( $borrower, $barcode, $datedue, $cancelreserve ); + my $issue = AddIssue( $borrower, $barcode, $datedue, $cancelreserve, undef, undef, { onsite_checkout => $onsite_checkout, auto_renew => $session->param('auto_renew') } ); + $template_params->{issue} = $issue; + $session->clear('auto_renew'); $inprocess = 1; } } - - # FIXME If the issue is confirmed, we launch another time GetMemberIssuesAndFines, now display the issue count after issue - my ( $od, $issue, $fines ) = GetMemberIssuesAndFines( $borrowernumber ); - $template->param( issuecount => $issue ); -} - -# reload the borrower info for the sake of reseting the flags..... -if ($borrowernumber) { - $borrower = GetMemberDetails( $borrowernumber, 0 ); -} - -################################################################################## -# BUILD HTML -# show all reserves of this borrower, and the position of the reservation .... -if ($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{reservenumber} = $num_res->{'reservenumber'}; - $getreserv{title} = $getiteminfo->{'title'}; - $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'} 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{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{nottransfered} = 0; - $getreserv{itemtype} = $itemtypeinfo->{'description'}; - $getreserv{author} = $getbibinfo->{'author'}; - $getreserv{biblionumber} = $num_res->{'biblionumber'}; - } - $getreserv{waitingposition} = $num_res->{'priority'}; - push( @reservloop, \%getreserv ); + # FIXME If the issue is confirmed, we launch another time GetMemberIssuesAndFines, now display the issue count after issue + my ( $od, $issue, $fines ) = GetMemberIssuesAndFines($borrowernumber); -# if we have a reserve waiting, initiate waitingreserveloop - if ($getreserv{waiting} == 1) { - push (@WaitingReserveLoop, \%getWaitingReserveInfo) - } - + if ($question->{RESERVE_WAITING} or $question->{RESERVED}){ + $template->param( + reserveborrowernumber => $question->{'resborrowernumber'} + ); } - # return result to the template - $template->param( - countreserv => scalar @reservloop, - reservloop => \@reservloop , - WaitingReserveLoop => \@WaitingReserveLoop, + $template->param( + itembiblionumber => $getmessageiteminfo->{'biblionumber'} ); - $template->param( adultborrower => 1 ) if ( $borrower->{'category_type'} eq 'A' ); -} - -# make the issued books table. -my $todaysissues = ''; -my $previssues = ''; -our @todaysissues = (); -our @previousissues = (); -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'} ); + $template_params->{issuecount} = $issue; - # 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, $reserves, undef ) = CheckReserves( $it->{'itemnumber'} ); - $it->{'can_renew'} = $can_renew; - $it->{'can_confirm'} = !$can_renew && !$restype; - $it->{'renew_error'} = $restype; - $it->{'checkoutdate'} = C4::Dates->new($it->{'issuedate'},'iso')->output('syspref'); - $it->{'issuingbranchname'} = GetBranchName($it->{'branchcode'}); - - $totalprice += $it->{'replacementprice'}; - $it->{'itemtype'} = $itemtypeinfo->{'description'}; - $it->{'itemtype_image'} = $itemtypeinfo->{'imageurl'}; - $it->{'dd'} = output_pref($it->{'date_due'}); - $it->{'displaydate'} = output_pref($it->{'issuedate'}); - #$it->{'od'} = ( $it->{'date_due'} lt $todaysdate ) ? 1 : 0 ; - $it->{'od'} = $it->{'overdue'}; - ($it->{'author'} eq '') and $it->{'author'} = ' '; - $it->{'renew_failed'} = $renew_failed{$it->{'itemnumber'}}; - $it->{'return_failed'} = $return_failed{$it->{'barcode'}}; - - if ( $it->{'issuedate'}."" gt $todaysdate or $it->{'lastreneweddate'} gt $todaysdate ) { - (!$relatives) ? push @todaysissues, $it : push @relissues, $it; - } else { - (!$relatives) ? push @previousissues, $it : push @relprevissues, $it; - } + if ( $iteminfo ) { + $iteminfo->{subtitle} = GetRecordValue('subtitle', GetMarcBiblio($iteminfo->{biblionumber}), GetFrameworkCode($iteminfo->{biblionumber})); + $template_params->{item} = $iteminfo; } + push @$checkout_infos, $template_params; + } + unless ( $batch ) { + $template->param( %{$checkout_infos->[0]} ); + $template->param( barcode => $barcodes->[0] ); + } else { + my $confirmation_needed = grep { $_->{NEEDSCONFIRMATION} } @$checkout_infos; + $template->param( + checkout_infos => $checkout_infos, + confirmation_needed => $confirmation_needed, + ); + } } -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; - } +# reload the borrower info for the sake of reseting the flags..... +if ($borrowernumber) { + $borrower = GetMemberDetails( $borrowernumber, 0 ); } - -my @values; -my %labels; -my $CGIselectborrower; -if ($borrowerslist) { - foreach ( - sort {(lc $a->{'surname'} cmp lc $b->{'surname'} || lc $a->{'firstname'} cmp lc $b->{'firstname'}) - } @$borrowerslist - ) - { - push @values, $_->{'borrowernumber'}; - $labels{ $_->{'borrowernumber'} } = -"$_->{'surname'}, $_->{'firstname'} ... ($_->{'cardnumber'} - $_->{'categorycode'} - $_->{'branchcode'}) ... $_->{'address'} "; - } - $CGIselectborrower = CGI::scrolling_list( - -name => 'borrowernumber', - -class => 'focus', - -id => 'borrowernumber', - -values => \@values, - -labels => \%labels, - -ondblclick => 'document.forms[\'mainform\'].submit()', - -size => 7, - -tabindex => '', - -multiple => 0 +################################################################################## +# BUILD HTML +# show all reserves of this borrower, and the position of the reservation .... +if ($borrowernumber) { + my $holds = Koha::Holds->search( { borrowernumber => $borrowernumber } ); + my $waiting_holds = $holds->waiting; + $template->param( + holds_count => $holds->count(), + WaitingHolds => $waiting_holds, ); + + $template->param( adultborrower => 1 ) if ( $borrower->{category_type} eq 'A' || $borrower->{category_type} eq 'I' ); } #title my $flags = $borrower->{'flags'}; foreach my $flag ( sort keys %$flags ) { - $template->param( flagged=> 1); $flags->{$flag}->{'message'} =~ s#\n#
#g; if ( $flags->{$flag}->{'noissues'} ) { $template->param( - flagged => 1, - noissues => 'true', + noissues => ($force_allow_issue) ? 0 : 'true', + forceallow => $force_allow_issue, ); if ( $flag eq 'GNA' ) { $template->param( gna => 'true' ); @@ -561,6 +491,14 @@ foreach my $flag ( sort keys %$flags ) { charges_is_blocker => 1 ); } + elsif ( $flag eq 'CHARGES_GUARANTEES' ) { + $template->param( + charges_guarantees => 'true', + chargesmsg_guarantees => $flags->{'CHARGES_GUARANTEES'}->{'message'}, + chargesamount_guarantees => $flags->{'CHARGES_GUARANTEES'}->{'amount'}, + charges_guarantees_is_blocker => 1 + ); + } elsif ( $flag eq 'CREDITS' ) { $template->param( credits => 'true', @@ -573,11 +511,17 @@ foreach my $flag ( sort keys %$flags ) { if ( $flag eq 'CHARGES' ) { $template->param( charges => 'true', - flagged => 1, chargesmsg => $flags->{'CHARGES'}->{'message'}, chargesamount => $flags->{'CHARGES'}->{'amount'}, ); } + elsif ( $flag eq 'CHARGES_GUARANTEES' ) { + $template->param( + charges_guarantees => 'true', + chargesmsg_guarantees => $flags->{'CHARGES_GUARANTEES'}->{'message'}, + chargesamount_guarantees => $flags->{'CHARGES_GUARANTEES'}->{'amount'}, + ); + } elsif ( $flag eq 'CREDITS' ) { $template->param( credits => 'true', @@ -588,7 +532,6 @@ foreach my $flag ( sort keys %$flags ) { elsif ( $flag eq 'ODUES' ) { $template->param( odues => 'true', - flagged => 1, oduesmsg => $flags->{'ODUES'}->{'message'} ); @@ -600,53 +543,36 @@ foreach my $flag ( sort keys %$flags ) { elsif ( $flag eq 'NOTES' ) { $template->param( notes => 'true', - flagged => 1, notesmsg => $flags->{'NOTES'}->{'message'} ); } } } -my $amountold = $borrower->{flags}->{'CHARGES'}->{'message'} || 0; +my $amountold = $borrower->{flags} ? $borrower->{flags}->{'CHARGES'}->{'message'} || 0 : 0; $amountold =~ s/^.*\$//; # remove upto the $, if any my ( $total, $accts, $numaccts) = GetMemberAccountRecords( $borrowernumber ); -if ( $borrower->{'category_type'} eq 'C') { - my ( $catcodes, $labels ) = GetborCatFromCatType( 'A', 'WHERE category_type = ?' ); - my $cnt = scalar(@$catcodes); - $template->param( 'CATCODE_MULTI' => 1) if $cnt > 1; - $template->param( 'catcode' => $catcodes->[0]) if $cnt == 1; +if ( $borrowernumber && $borrower->{'category_type'} eq 'C') { + my $patron_categories = Koha::Patron::Categories->search_limited({ category_type => 'A' }, {order_by => ['categorycode']}); + $template->param( 'CATCODE_MULTI' => 1) if $patron_categories->count > 1; + $template->param( 'catcode' => $patron_categories->next ) if $patron_categories->count == 1; } -my $CGIorganisations; -my $member_of_institution; -if ( C4::Context->preference("memberofinstitution") ) { - my $organisations = get_institutions(); - my @orgs; - my %org_labels; - foreach my $organisation ( keys %$organisations ) { - push @orgs, $organisation; - $org_labels{$organisation} = $organisations->{$organisation}->{'surname'}; +my $librarian_messages = Koha::Patron::Messages->search( + { + borrowernumber => $borrowernumber, + message_type => 'L', } - $member_of_institution = 1; - $CGIorganisations = CGI::popup_menu( - -id => 'organisations', - -name => 'organisations', - -labels => \%org_labels, - -values => \@orgs, - ); -} - -my $lib_messages_loop = GetMessages( $borrowernumber, 'L', $branch ); -if($lib_messages_loop){ $template->param(flagged => 1 ); } - -my $bor_messages_loop = GetMessages( $borrowernumber, 'B', $branch ); -if($bor_messages_loop){ $template->param(flagged => 1 ); } +); -# Computes full borrower address -my (undef, $roadttype_hashref) = &GetRoadTypes(); -my $address = $borrower->{'streetnumber'}.' '.$roadttype_hashref->{$borrower->{'streettype'}}.' '.$borrower->{'address'}; +my $patron_messages = Koha::Patron::Messages->search( + { + borrowernumber => $borrowernumber, + message_type => 'B', + } +); my $fast_cataloging = 0; if (defined getframeworkinfo('FA')) { @@ -660,86 +586,86 @@ if (C4::Context->preference('ExtendedPatronAttributes')) { extendedattributes => $attributes ); } +my $view = $batch + ?'batch_checkout_view' + : 'circview'; + +my @relatives; +if ( $borrowernumber ) { + if ( my $patron = Koha::Patrons->find( $borrower->{borrowernumber} ) ) { + if ( my $guarantor = $patron->guarantor ) { + push @relatives, $guarantor->borrowernumber; + push @relatives, $_->borrowernumber for $patron->siblings; + } else { + push @relatives, $_->borrowernumber for $patron->guarantees; + } + } +} +my $relatives_issues_count = + Koha::Database->new()->schema()->resultset('Issue') + ->count( { borrowernumber => \@relatives } ); + +my $roadtype = C4::Koha::GetAuthorisedValueByCode( 'ROADTYPE', $borrower->{streettype} ); + +$template->param(%$borrower); + +# Restore date if changed by holds and/or save stickyduedate to session +if ($restoreduedatespec || $stickyduedate) { + $duedatespec = $restoreduedatespec || $duedatespec; + + if ($stickyduedate) { + $session->param( 'stickyduedate', $duedatespec ); + } +} elsif (defined($duedatespec) && !defined($restoreduedatespec)) { + undef $duedatespec; +} $template->param( - lib_messages_loop => $lib_messages_loop, - bor_messages_loop => $bor_messages_loop, - all_messages_del => C4::Context->preference('AllowAllMessageDeletion'), - findborrower => $findborrower, + librarian_messages => $librarian_messages, + patron_messages => $patron_messages, borrower => $borrower, borrowernumber => $borrowernumber, + categoryname => $borrower->{'description'}, branch => $branch, - branchname => GetBranchName($borrower->{'branchcode'}), - printer => $printer, - printername => $printer, - firstname => $borrower->{'firstname'}, - surname => $borrower->{'surname'}, - showname => $borrower->{'showname'}, - category_type => $borrower->{'category_type'}, - dateexpiry => format_date($newexpiry), - expiry => format_date($borrower->{'dateexpiry'}), - categorycode => $borrower->{'categorycode'}, - categoryname => $borrower->{description}, - address => $address, - address2 => $borrower->{'address2'}, - email => $borrower->{'email'}, - emailpro => $borrower->{'emailpro'}, - borrowernotes => $borrower->{'borrowernotes'}, - city => $borrower->{'city'}, - state => $borrower->{'state'}, - zipcode => $borrower->{'zipcode'}, - country => $borrower->{'country'}, - phone => $borrower->{'phone'} || $borrower->{'mobile'}, - cardnumber => $borrower->{'cardnumber'}, - othernames => $borrower->{'othernames'}, + was_renewed => scalar $query->param('was_renewed') ? 1 : 0, + expiry => $borrower->{'dateexpiry'}, + roadtype => $roadtype, amountold => $amountold, - barcode => $barcode, + barcodes => $barcodes, stickyduedate => $stickyduedate, duedatespec => $duedatespec, + restoreduedatespec => $restoreduedatespec, message => $message, - CGIselectborrower => $CGIselectborrower, - totalprice => sprintf('%.2f', $totalprice), totaldue => sprintf('%.2f', $total), - todayissues => \@todaysissues, - previssues => \@previousissues, - relissues => \@relissues, - relprevissues => \@relprevissues, - displayrelissues => $displayrelissues, inprocess => $inprocess, - memberofinstution => $member_of_institution, - CGIorganisations => $CGIorganisations, - is_child => ($borrower->{'category_type'} eq 'C'), - circview => 1, - soundon => C4::Context->preference("SoundOn"), + is_child => ($borrowernumber && $borrower->{'category_type'} eq 'C'), + $view => 1, + batch_allowed => $batch_allowed, + batch => $batch, + AudioAlerts => C4::Context->preference("AudioAlerts"), fast_cataloging => $fast_cataloging, CircAutoPrintQuickSlip => C4::Context->preference("CircAutoPrintQuickSlip"), activeBorrowerRelationship => (C4::Context->preference('borrowerRelationship') ne ''), SuspendHoldsIntranet => C4::Context->preference('SuspendHoldsIntranet'), AutoResumeSuspendedHolds => C4::Context->preference('AutoResumeSuspendedHolds'), + RoutingSerials => C4::Context->preference('RoutingSerials'), + relatives_issues_count => $relatives_issues_count, + relatives_borrowernumbers => \@relatives, ); -# save stickyduedate to session -if ($stickyduedate) { - $session->param( 'stickyduedate', $duedatespec ); -} - -my ($picture, $dberror) = GetPatronImage($borrower->{'cardnumber'}); -$template->param( picture => 1 ) if $picture; - -# get authorised values with type of BOR_NOTES - -my $canned_notes = GetAuthorisedValues("BOR_NOTES"); +my $patron_image = Koha::Patron::Images->find($borrower->{borrowernumber}); +$template->param( picture => 1 ) if $patron_image; +my $has_modifications = Koha::Patron::Modifications->search( { borrowernumber => $borrowernumber } )->count; $template->param( debt_confirmed => $debt_confirmed, SpecifyDueDate => $duedatespec_allow, CircAutocompl => C4::Context->preference("CircAutocompl"), - AllowRenewalLimitOverride => C4::Context->preference("AllowRenewalLimitOverride"), - dateformat => C4::Context->preference("dateformat"), - DHTMLcalendar_dateformat => C4::Dates->DHTMLcalendar(), - export_remove_fields => C4::Context->preference("ExportRemoveFields"), - export_with_csv_profile => C4::Context->preference("ExportWithCsvProfile"), - canned_bor_notes_loop => $canned_notes, + debarments => GetDebarments({ borrowernumber => $borrowernumber }), + todaysdate => output_pref( { dt => dt_from_string()->set(hour => 23)->set(minute => 59), dateformat => 'sql' } ), + has_modifications => $has_modifications, + override_high_holds => $override_high_holds, + nopermission => scalar $query->param('nopermission'), ); output_html_with_http_headers $query, $cookie, $template->output;