"Fossies" - the Fresh Open Source Software Archive

Member "koha-19.11.15/circ/circulation.pl" (23 Feb 2021, 22550 Bytes) of package /linux/misc/koha-19.11.15.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Perl source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "circulation.pl" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 20.05.06_vs_20.11.00.

    1 #!/usr/bin/perl
    2 
    3 # script to execute issuing of books
    4 
    5 # Copyright 2000-2002 Katipo Communications
    6 # copyright 2010 BibLibre
    7 # Copyright 2011 PTFS-Europe Ltd.
    8 # Copyright 2012 software.coop and MJ Ray
    9 #
   10 # This file is part of Koha.
   11 #
   12 # Koha is free software; you can redistribute it and/or modify it
   13 # under the terms of the GNU General Public License as published by
   14 # the Free Software Foundation; either version 3 of the License, or
   15 # (at your option) any later version.
   16 #
   17 # Koha is distributed in the hope that it will be useful, but
   18 # WITHOUT ANY WARRANTY; without even the implied warranty of
   19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   20 # GNU General Public License for more details.
   21 #
   22 # You should have received a copy of the GNU General Public License
   23 # along with Koha; if not, see <http://www.gnu.org/licenses>.
   24 
   25 # FIXME There are too many calls to Koha::Patrons->find in this script
   26 
   27 use Modern::Perl;
   28 use CGI qw ( -utf8 );
   29 use DateTime;
   30 use DateTime::Duration;
   31 use Scalar::Util qw( looks_like_number );
   32 use C4::Output;
   33 use C4::Print;
   34 use C4::Auth qw/:DEFAULT get_session haspermission/;
   35 use C4::Koha;   # GetPrinter
   36 use C4::Circulation;
   37 use C4::Utils::DataTables::Members;
   38 use C4::Members;
   39 use C4::Biblio;
   40 use C4::Search;
   41 use MARC::Record;
   42 use C4::Reserves;
   43 use Koha::Holds;
   44 use C4::Context;
   45 use CGI::Session;
   46 use Koha::AuthorisedValues;
   47 use Koha::CsvProfiles;
   48 use Koha::Patrons;
   49 use Koha::Patron::Debarments qw(GetDebarments);
   50 use Koha::DateUtils;
   51 use Koha::Database;
   52 use Koha::BiblioFrameworks;
   53 use Koha::Items;
   54 use Koha::Patron::Messages;
   55 use Koha::SearchEngine;
   56 use Koha::SearchEngine::Search;
   57 use Koha::Patron::Modifications;
   58 
   59 use Date::Calc qw(
   60   Today
   61   Add_Delta_Days
   62   Date_to_Days
   63 );
   64 use List::MoreUtils qw/uniq/;
   65 
   66 #
   67 # PARAMETERS READING
   68 #
   69 my $query = new CGI;
   70 
   71 my $override_high_holds     = $query->param('override_high_holds');
   72 my $override_high_holds_tmp = $query->param('override_high_holds_tmp');
   73 
   74 my $sessionID = $query->cookie("CGISESSID") ;
   75 my $session = get_session($sessionID);
   76 if (!C4::Context->userenv){
   77     if ($session->param('branch') eq 'NO_LIBRARY_SET'){
   78         # no branch set we can't issue
   79         print $query->redirect("/cgi-bin/koha/circ/selectbranchprinter.pl");
   80         exit;
   81     }
   82 }
   83 
   84 my $barcodes = [];
   85 my $barcode =  $query->param('barcode');
   86 my $findborrower;
   87 my $autoswitched;
   88 my $borrowernumber = $query->param('borrowernumber');
   89 
   90 if (C4::Context->preference("AutoSwitchPatron") && $barcode) {
   91     if (Koha::Patrons->search( { cardnumber => $barcode} )->count() > 0) {
   92         $findborrower = $barcode;
   93         undef $barcode;
   94         undef $borrowernumber;
   95         $autoswitched = 1;
   96     }
   97 }
   98 $findborrower ||= $query->param('findborrower') || q{};
   99 $findborrower =~ s|,| |g;
  100 
  101 # Barcode given by user could be '0'
  102 if ( $barcode || ( defined($barcode) && $barcode eq '0' ) ) {
  103     $barcodes = [ $barcode ];
  104 } else {
  105     my $filefh = $query->upload('uploadfile');
  106     if ( $filefh ) {
  107         while ( my $content = <$filefh> ) {
  108             $content =~ s/[\r\n]*$//g;
  109             push @$barcodes, $content if $content;
  110         }
  111     } elsif ( my $list = $query->param('barcodelist') ) {
  112         push @$barcodes, split( /\s\n/, $list );
  113         $barcodes = [ map { $_ =~ /^\s*$/ ? () : $_ } @$barcodes ];
  114     } else {
  115         @$barcodes = $query->multi_param('barcodes');
  116     }
  117 }
  118 
  119 $barcodes = [ uniq @$barcodes ];
  120 
  121 my $template_name = q|circ/circulation.tt|;
  122 my $patron = $borrowernumber ? Koha::Patrons->find( $borrowernumber ) : undef;
  123 my $batch = $query->param('batch');
  124 my $batch_allowed = 0;
  125 if ( $batch && C4::Context->preference('BatchCheckouts') ) {
  126     $template_name = q|circ/circulation_batch_checkouts.tt|;
  127     my @batch_category_codes = split '\|', C4::Context->preference('BatchCheckoutsValidCategories');
  128     my $categorycode = $patron->categorycode;
  129     if ( $categorycode && grep {/^$categorycode$/} @batch_category_codes ) {
  130         $batch_allowed = 1;
  131     } else {
  132         $barcodes = [];
  133     }
  134 }
  135 
  136 my ( $template, $loggedinuser, $cookie ) = get_template_and_user (
  137     {
  138         template_name   => $template_name,
  139         query           => $query,
  140         type            => "intranet",
  141         flagsrequired   => { circulate => 'circulate_remaining_permissions' },
  142     }
  143 );
  144 my $logged_in_user = Koha::Patrons->find( $loggedinuser ) or die "Not logged in";
  145 
  146 my $force_allow_issue = $query->param('forceallow') || 0;
  147 if (!C4::Auth::haspermission( C4::Context->userenv->{id} , { circulate => 'force_checkout' } )) {
  148     $force_allow_issue = 0;
  149 }
  150 my $onsite_checkout = $query->param('onsite_checkout');
  151 
  152 if (C4::Context->preference("OnSiteCheckoutAutoCheck") && $onsite_checkout eq "on") {
  153     $template->param(onsite_checkout => $onsite_checkout);
  154 }
  155 
  156 my @failedrenews = $query->multi_param('failedrenew');    # expected to be itemnumbers
  157 our %renew_failed = ();
  158 for (@failedrenews) { $renew_failed{$_} = 1; }
  159 
  160 my @failedreturns = $query->multi_param('failedreturn');
  161 our %return_failed = ();
  162 for (@failedreturns) { $return_failed{$_} = 1; }
  163 
  164 my $searchtype = $query->param('searchtype') || q{contain};
  165 
  166 my $branch = C4::Context->userenv->{'branch'};
  167 
  168 if (C4::Context->preference("DisplayClearScreenButton")) {
  169     $template->param(DisplayClearScreenButton => 1);
  170 }
  171 
  172 for my $barcode ( @$barcodes ) {
  173     $barcode =~ s/^\s*|\s*$//g; # remove leading/trailing whitespace
  174     $barcode = barcodedecode($barcode)
  175         if( $barcode && C4::Context->preference('itemBarcodeInputFilter'));
  176 }
  177 
  178 my $stickyduedate  = $query->param('stickyduedate') || $session->param('stickyduedate');
  179 my $duedatespec    = $query->param('duedatespec')   || $session->param('stickyduedate');
  180 $duedatespec = eval { output_pref( { dt => dt_from_string( $duedatespec ), dateformat => 'iso' }); }
  181     if ( $duedatespec );
  182 my $restoreduedatespec  = $query->param('restoreduedatespec') || $duedatespec || $session->param('stickyduedate');
  183 if ( $restoreduedatespec && $restoreduedatespec eq "highholds_empty" ) {
  184     undef $restoreduedatespec;
  185 }
  186 my $issueconfirmed = $query->param('issueconfirmed');
  187 my $cancelreserve  = $query->param('cancelreserve');
  188 my $print          = $query->param('print') || q{};
  189 my $debt_confirmed = $query->param('debt_confirmed') || 0; # Don't show the debt error dialog twice
  190 my $charges        = $query->param('charges') || q{};
  191 
  192 # Check if stickyduedate is turned off
  193 if ( @$barcodes ) {
  194     # was stickyduedate loaded from session?
  195     if ( $stickyduedate && ! $query->param("stickyduedate") ) {
  196         $session->clear( 'stickyduedate' );
  197         $stickyduedate  = $query->param('stickyduedate');
  198         $duedatespec    = $query->param('duedatespec');
  199     }
  200     $session->param('auto_renew', scalar $query->param('auto_renew'));
  201 }
  202 else {
  203     $session->clear('auto_renew');
  204 }
  205 
  206 $template->param( auto_renew => $session->param('auto_renew') );
  207 
  208 my ($datedue,$invalidduedate);
  209 
  210 my $duedatespec_allow = C4::Context->preference('SpecifyDueDate');
  211 if( $onsite_checkout && !$duedatespec_allow ) {
  212     $datedue = output_pref({ dt => dt_from_string, dateonly => 1, dateformat => 'iso' });
  213     $datedue .= ' 23:59:00';
  214 } elsif( $duedatespec_allow ) {
  215     if ( $duedatespec ) {
  216         $datedue = eval { dt_from_string( $duedatespec ) };
  217         if (! $datedue ) {
  218             $invalidduedate = 1;
  219             $template->param( IMPOSSIBLE=>1, INVALID_DATE=>$duedatespec );
  220         }
  221     }
  222 }
  223 
  224 # check and see if we should print
  225 if ( @$barcodes == 0 && $print eq 'maybe' ) {
  226     $print = 'yes';
  227 }
  228 
  229 my $inprocess = (@$barcodes == 0) ? '' : $query->param('inprocess');
  230 if ( @$barcodes == 0 && $charges eq 'yes' ) {
  231     $template->param(
  232         PAYCHARGES     => 'yes',
  233         borrowernumber => $borrowernumber
  234     );
  235 }
  236 
  237 if ( $print eq 'yes' && $borrowernumber ne '' ) {
  238     if ( C4::Context->boolean_preference('printcirculationslips') ) {
  239         my $letter = IssueSlip($branch, $borrowernumber, "QUICK");
  240         NetworkPrint($letter->{content});
  241     }
  242     $query->param( 'borrowernumber', '' );
  243     $borrowernumber = '';
  244     undef $patron;
  245 }
  246 
  247 #
  248 # STEP 2 : FIND BORROWER
  249 # if there is a list of find borrowers....
  250 #
  251 my $message;
  252 if ($findborrower) {
  253     my $patron = Koha::Patrons->find( { cardnumber => $findborrower } );
  254     if ( $patron ) {
  255         $borrowernumber = $patron->borrowernumber;
  256     } else {
  257         my $dt_params = { iDisplayLength => -1 };
  258         my $results = C4::Utils::DataTables::Members::search(
  259             {
  260                 searchmember => $findborrower,
  261                 searchtype   => $searchtype,
  262                 dt_params    => $dt_params,
  263             }
  264         );
  265         my $borrowers = $results->{patrons};
  266         if ( scalar @$borrowers == 1 ) {
  267             $borrowernumber = $borrowers->[0]->{borrowernumber};
  268             $query->param( 'borrowernumber', $borrowernumber );
  269             $query->param( 'barcode',           '' );
  270         } elsif ( @$borrowers ) {
  271             $template->param( borrowers => $borrowers );
  272         } else {
  273             $query->param( 'findborrower', '' );
  274             $message = "'$findborrower'";
  275         }
  276     }
  277 }
  278 
  279 # get the borrower information.....
  280 my $balance = 0;
  281 $patron ||= Koha::Patrons->find( $borrowernumber ) if $borrowernumber;
  282 if ($patron) {
  283 
  284     $template->param( borrowernumber => $patron->borrowernumber );
  285     output_and_exit_if_error( $query, $cookie, $template, { module => 'members', logged_in_user => $logged_in_user, current_patron => $patron } );
  286 
  287     my $overdues = $patron->get_overdues;
  288     my $issues = $patron->checkouts;
  289     $balance = $patron->account->balance;
  290 
  291 
  292     # if the expiry date is before today ie they have expired
  293     if ( $patron->is_expired ) {
  294         #borrowercard expired, no issues
  295         $template->param(
  296             noissues => ($force_allow_issue) ? 0 : "1",
  297             forceallow => $force_allow_issue,
  298             expired => "1",
  299         );
  300     }
  301     # check for NotifyBorrowerDeparture
  302     elsif ( $patron->is_going_to_expire ) {
  303         # borrower card soon to expire warn librarian
  304         $template->param( "warndeparture" => $patron->dateexpiry ,
  305                         );
  306         if (C4::Context->preference('ReturnBeforeExpiry')){
  307             $template->param("returnbeforeexpiry" => 1);
  308         }
  309     }
  310     $template->param(
  311         overduecount => $overdues->count,
  312         issuecount   => $issues->count,
  313         finetotal    => $balance,
  314     );
  315 
  316     if ( $patron and $patron->is_debarred ) {
  317         $template->param(
  318             'userdebarred'    => $patron->debarred,
  319             'debarredcomment' => $patron->debarredcomment,
  320         );
  321 
  322         if ( $patron->debarred ne "9999-12-31" ) {
  323             $template->param( 'userdebarreddate' => $patron->debarred );
  324         }
  325     }
  326 
  327     # Calculate and display patron's age
  328     if ( !$patron->is_valid_age ) {
  329         $template->param( age_limitations => 1 );
  330         $template->param( age_low => $patron->category->dateofbirthrequired );
  331         $template->param( age_high => $patron->category->upperagelimit );
  332     }
  333 
  334 }
  335 
  336 #
  337 # STEP 3 : ISSUING
  338 #
  339 #
  340 if (@$barcodes) {
  341   my $checkout_infos;
  342   for my $barcode ( @$barcodes ) {
  343 
  344     my $template_params = {
  345         barcode         => $barcode,
  346         onsite_checkout => $onsite_checkout,
  347     };
  348 
  349     # always check for blockers on issuing
  350     my ( $error, $question, $alerts, $messages ) = CanBookBeIssued(
  351         $patron,
  352         $barcode, $datedue,
  353         $inprocess,
  354         undef,
  355         {
  356             onsite_checkout     => $onsite_checkout,
  357             override_high_holds => $override_high_holds || $override_high_holds_tmp || 0,
  358         }
  359     );
  360 
  361     my $blocker = $invalidduedate ? 1 : 0;
  362 
  363     $template_params->{alert} = $alerts;
  364     $template_params->{messages} = $messages;
  365 
  366     my $item = Koha::Items->find({ barcode => $barcode });
  367 
  368     my $biblio;
  369     if ( $item ) {
  370         $biblio = $item->biblio;
  371     }
  372 
  373     # Fix for bug 7494: optional checkout-time fallback search for a book
  374 
  375     if ( $error->{'UNKNOWN_BARCODE'}
  376         && C4::Context->preference("itemBarcodeFallbackSearch")
  377         && not $batch
  378     )
  379     {
  380      $template_params->{FALLBACK} = 1;
  381 
  382         my $searcher = Koha::SearchEngine::Search->new({index => $Koha::SearchEngine::BIBLIOS_INDEX});
  383         my $query = "kw=" . $barcode;
  384         my ( $searcherror, $results, $total_hits ) = $searcher->simple_search_compat($query, 0, 10);
  385 
  386         # if multiple hits, offer options to librarian
  387         if ( $total_hits > 0 ) {
  388             my @options = ();
  389             foreach my $hit ( @{$results} ) {
  390                 my $chosen =
  391                   TransformMarcToKoha( C4::Search::new_record_from_zebra('biblioserver',$hit) );
  392 
  393                 # offer all barcodes individually
  394                 if ( $chosen->{barcode} ) {
  395                     foreach my $barcode ( sort split(/\s*\|\s*/, $chosen->{barcode}) ) {
  396                         my %chosen_single = %{$chosen};
  397                         $chosen_single{barcode} = $barcode;
  398                         push( @options, \%chosen_single );
  399                     }
  400                 }
  401             }
  402             $template_params->{options} = \@options;
  403         }
  404     }
  405 
  406     if ( $error->{UNKNOWN_BARCODE} or not $onsite_checkout or not C4::Context->preference("OnSiteCheckoutsForce") ) {
  407         delete $question->{'DEBT'} if ($debt_confirmed);
  408         foreach my $impossible ( keys %$error ) {
  409             $template_params->{$impossible} = $$error{$impossible};
  410             $template_params->{IMPOSSIBLE} = 1;
  411             $blocker = 1;
  412         }
  413     }
  414 
  415     if( $item and ( !$blocker or $force_allow_issue ) ){
  416         my $confirm_required = 0;
  417         unless($issueconfirmed){
  418             #  Get the item title for more information
  419             my $materials = $item->materials;
  420             my $descriptions = Koha::AuthorisedValues->get_description_by_koha_field({ frameworkcode => $biblio->frameworkcode, kohafield => 'items.materials', authorised_value => $materials });
  421             $materials = $descriptions->{lib} // $materials;
  422             $template_params->{additional_materials} = $materials;
  423             $template_params->{itemhomebranch} = $item->homebranch;
  424 
  425             # pass needsconfirmation to template if issuing is possible and user hasn't yet confirmed.
  426             foreach my $needsconfirmation ( keys %$question ) {
  427                 $template_params->{$needsconfirmation} = $$question{$needsconfirmation};
  428                 $template_params->{getTitleMessageIteminfo} = $biblio->title;
  429                 $template_params->{getBarcodeMessageIteminfo} = $item->barcode;
  430                 $template_params->{NEEDSCONFIRMATION} = 1;
  431                 $confirm_required = 1;
  432             }
  433         }
  434         unless($confirm_required) {
  435             my $switch_onsite_checkout = exists $messages->{ONSITE_CHECKOUT_WILL_BE_SWITCHED};
  436             my $issue = AddIssue( $patron->unblessed, $barcode, $datedue, $cancelreserve, undef, undef, { onsite_checkout => $onsite_checkout, auto_renew => $session->param('auto_renew'), switch_onsite_checkout => $switch_onsite_checkout, } );
  437             $template_params->{issue} = $issue;
  438             $session->clear('auto_renew');
  439             $inprocess = 1;
  440         }
  441     }
  442 
  443     if ($question->{RESERVE_WAITING} or $question->{RESERVED}){
  444         $template->param(
  445             reserveborrowernumber => $question->{'resborrowernumber'},
  446             reserve_id => $question->{reserve_id},
  447         );
  448     }
  449 
  450 
  451     # FIXME If the issue is confirmed, we launch another time checkouts->count, now display the issue count after issue
  452     $patron = Koha::Patrons->find( $borrowernumber );
  453     $template_params->{issuecount} = $patron->checkouts->count;
  454 
  455     if ( $item ) {
  456         $template_params->{item} = $item;
  457         $template_params->{biblio} = $biblio;
  458         $template_params->{itembiblionumber} = $biblio->biblionumber;
  459     }
  460     push @$checkout_infos, $template_params;
  461   }
  462   unless ( $batch ) {
  463     $template->param( %{$checkout_infos->[0]} );
  464     $template->param( barcode => $barcodes->[0] );
  465   } else {
  466     my $confirmation_needed = grep { $_->{NEEDSCONFIRMATION} } @$checkout_infos;
  467     $template->param(
  468         checkout_infos => $checkout_infos,
  469         confirmation_needed => $confirmation_needed,
  470     );
  471   }
  472 }
  473 
  474 ##################################################################################
  475 # BUILD HTML
  476 # show all reserves of this borrower, and the position of the reservation ....
  477 if ($patron) {
  478     my $holds = Koha::Holds->search( { borrowernumber => $borrowernumber } ); # FIXME must be Koha::Patron->holds
  479     my $waiting_holds = $holds->waiting;
  480     $template->param(
  481         holds_count  => $holds->count(),
  482         WaitingHolds => $waiting_holds,
  483     );
  484 }
  485 
  486 if ( $patron ) {
  487     my $noissues;
  488     if ( $patron->gonenoaddress ) {
  489         $template->param( gna => 1 );
  490         $noissues = 1;
  491     }
  492     if ( $patron->lost ) {
  493         $template->param( lost=> 1 );
  494         $noissues = 1;
  495     }
  496     if ( $patron->is_debarred ) {
  497         $template->param( dbarred=> 1 );
  498         $noissues = 1;
  499     }
  500     my $account = $patron->account;
  501     if( ( my $owing = $account->non_issues_charges ) > 0 ) {
  502         my $noissuescharge = C4::Context->preference("noissuescharge") || 5; # FIXME If noissuescharge == 0 then 5, why??
  503         $noissues ||= ( not C4::Context->preference("AllowFineOverride") and ( $owing > $noissuescharge ) );
  504         $template->param(
  505             charges => 1,
  506             chargesamount => $owing,
  507         )
  508     } elsif ( $balance < 0 ) {
  509         $template->param(
  510             credits => 1,
  511             creditsamount => -$balance,
  512         );
  513     }
  514 
  515     my $no_issues_charge_guarantees = C4::Context->preference("NoIssuesChargeGuarantees");
  516     $no_issues_charge_guarantees = undef unless looks_like_number( $no_issues_charge_guarantees );
  517     if ( defined $no_issues_charge_guarantees ) {
  518         my $guarantees_non_issues_charges = 0;
  519         my $guarantees = $patron->guarantee_relationships->guarantees;
  520         while ( my $g = $guarantees->next ) {
  521             $guarantees_non_issues_charges += $g->account->non_issues_charges;
  522         }
  523         if ( $guarantees_non_issues_charges > $no_issues_charge_guarantees ) {
  524             $template->param(
  525                 charges_guarantees    => 1,
  526                 chargesamount_guarantees => $guarantees_non_issues_charges,
  527             );
  528             $noissues = 1 unless C4::Context->preference("allowfineoverride");
  529         }
  530     }
  531 
  532     if ( $patron->has_overdues ) {
  533         $template->param( odues => 1 );
  534     }
  535 
  536     if ( $patron->borrowernotes ) {
  537         my $borrowernotes = $patron->borrowernotes;
  538         $borrowernotes =~ s#\n#<br />#g;
  539         $template->param(
  540             notes =>1,
  541             notesmsg => $borrowernotes,
  542         )
  543     }
  544 
  545     if ( $noissues ) {
  546         $template->param(
  547             noissues => ($force_allow_issue) ? 0 : 'true',
  548             forceallow => $force_allow_issue,
  549         );
  550     }
  551 }
  552 
  553 my $messages = Koha::Patron::Messages->search(
  554     {
  555         'me.borrowernumber' => $borrowernumber,
  556     },
  557     {
  558        join => 'manager',
  559        '+select' => ['manager.surname', 'manager.firstname' ],
  560        '+as' => ['manager_surname', 'manager_firstname'],
  561     }
  562 );
  563 
  564 my $fast_cataloging = 0;
  565 if ( Koha::BiblioFrameworks->find('FA') ) {
  566     $fast_cataloging = 1 
  567 }
  568 
  569 my $view = $batch
  570     ?'batch_checkout_view'
  571     : 'circview';
  572 
  573 my @relatives;
  574 if ( $patron ) {
  575     if ( my @guarantors = $patron->guarantor_relationships()->guarantors() ) {
  576         push( @relatives, $_->id ) for @guarantors;
  577         push( @relatives, $_->id ) for $patron->siblings();
  578     } else {
  579         push( @relatives, $_->id ) for $patron->guarantee_relationships()->guarantees();
  580     }
  581 }
  582 my $relatives_issues_count =
  583   Koha::Database->new()->schema()->resultset('Issue')
  584   ->count( { borrowernumber => \@relatives } );
  585 
  586 if ( $patron ) {
  587     my $av = Koha::AuthorisedValues->search({ category => 'ROADTYPE', authorised_value => $patron->streettype });
  588     my $roadtype = $av->count ? $av->next->lib : '';
  589     $template->param(
  590         roadtype          => $roadtype,
  591         patron            => $patron,
  592         categoryname      => $patron->category->description,
  593         expiry            => $patron->dateexpiry,
  594     );
  595 }
  596 
  597 # Restore date if changed by holds and/or save stickyduedate to session
  598 if ($restoreduedatespec || $stickyduedate) {
  599     $duedatespec = $restoreduedatespec || $duedatespec;
  600 
  601     if ($stickyduedate) {
  602         $session->param( 'stickyduedate', $duedatespec );
  603     }
  604 } elsif (defined($duedatespec) && !defined($restoreduedatespec)) {
  605     undef $duedatespec;
  606 }
  607 
  608 $template->param(
  609     messages           => $messages,
  610     borrowernumber    => $borrowernumber,
  611     branch            => $branch,
  612     was_renewed       => scalar $query->param('was_renewed') ? 1 : 0,
  613     barcodes          => $barcodes,
  614     stickyduedate     => $stickyduedate,
  615     duedatespec       => $duedatespec,
  616     restoreduedatespec => $restoreduedatespec,
  617     message           => $message,
  618     totaldue          => sprintf('%.2f', $balance), # FIXME not used in template?
  619     inprocess         => $inprocess,
  620     $view             => 1,
  621     batch_allowed     => $batch_allowed,
  622     batch             => $batch,
  623     AudioAlerts           => C4::Context->preference("AudioAlerts"),
  624     fast_cataloging   => $fast_cataloging,
  625     CircAutoPrintQuickSlip   => C4::Context->preference("CircAutoPrintQuickSlip"),
  626     RoutingSerials => C4::Context->preference('RoutingSerials'),
  627     relatives_issues_count => $relatives_issues_count,
  628     relatives_borrowernumbers => \@relatives,
  629 );
  630 
  631 
  632 if ( C4::Context->preference("ExportCircHistory") ) {
  633     $template->param(csv_profiles => [ Koha::CsvProfiles->search({ type => 'marc' }) ]);
  634 }
  635 
  636 my $has_modifications = Koha::Patron::Modifications->search( { borrowernumber => $borrowernumber } )->count;
  637 $template->param(
  638     debt_confirmed            => $debt_confirmed,
  639     SpecifyDueDate            => $duedatespec_allow,
  640     PatronAutoComplete      => C4::Context->preference("PatronAutoComplete"),
  641     debarments                => scalar GetDebarments({ borrowernumber => $borrowernumber }),
  642     todaysdate                => output_pref( { dt => dt_from_string()->set(hour => 23)->set(minute => 59), dateformat => 'sql' } ),
  643     has_modifications         => $has_modifications,
  644     override_high_holds       => $override_high_holds,
  645     nopermission              => scalar $query->param('nopermission'),
  646     autoswitched              => $autoswitched,
  647     logged_in_user            => $logged_in_user,
  648 );
  649 
  650 output_html_with_http_headers $query, $cookie, $template->output;