X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=C4%2FCirculation.pm;h=2deb3678a1b3be77b5b34c5620b98774723d3e6f;hb=8d3eba6a297f4fd993ddf237b6cd66cfda38ff95;hp=6b4ae913b9b5355c5ea07fd2176bc2fc3d2eedbf;hpb=e667fc1cfc601704a72432c7efafdd1c40a6126f;p=koha.git diff --git a/C4/Circulation.pm b/C4/Circulation.pm index 6b4ae913b9..2deb3678a1 100644 --- a/C4/Circulation.pm +++ b/C4/Circulation.pm @@ -22,6 +22,7 @@ package C4::Circulation; use strict; #use warnings; FIXME - Bug 2505 use DateTime; +use POSIX qw( floor ); use Koha::DateUtils; use C4::Context; use C4::Stats; @@ -668,17 +669,18 @@ sub CanBookBeIssued { my $override_high_holds = $params->{override_high_holds} || 0; my $item = GetItem(undef, $barcode ); - my $issue = Koha::Checkouts->find( { itemnumber => $item->{itemnumber} } ); - my $biblioitem = GetBiblioItemData($item->{biblioitemnumber}); - $item->{'itemtype'}=$item->{'itype'}; - my $dbh = C4::Context->dbh; - my $patron_unblessed = $patron->unblessed; - # MANDATORY CHECKS - unless item exists, nothing else matters - unless ( $item->{barcode} ) { + unless ( $item ) { $issuingimpossible{UNKNOWN_BARCODE} = 1; } - return ( \%issuingimpossible, \%needsconfirmation ) if %issuingimpossible; + return ( \%issuingimpossible, \%needsconfirmation ) if %issuingimpossible; + + my $issue = Koha::Checkouts->find( { itemnumber => $item->{itemnumber} } ); + my $biblio = Koha::Biblios->find( $item->{biblionumber} ); + my $biblioitem = $biblio->biblioitem; + my $effective_itemtype = $item->{itype}; # GetItem deals with that + my $dbh = C4::Context->dbh; + my $patron_unblessed = $patron->unblessed; # # DUE DATE is OK ? -- should already have checked. @@ -691,8 +693,7 @@ sub CanBookBeIssued { my $issuedate = $now->clone(); my $branch = _GetCircControlBranch($item, $patron_unblessed); - my $itype = ( C4::Context->preference('item-level_itypes') ) ? $item->{'itype'} : $biblioitem->{'itemtype'}; - $duedate = CalcDateDue( $issuedate, $itype, $branch, $patron_unblessed ); + $duedate = CalcDateDue( $issuedate, $effective_itemtype, $branch, $patron_unblessed ); # Offline circ calls AddIssue directly, doesn't run through here # So issuingimpossible should be ok. @@ -716,7 +717,7 @@ sub CanBookBeIssued { branch => C4::Context->userenv->{'branch'}, type => 'localuse', itemnumber => $item->{'itemnumber'}, - itemtype => $item->{'itype'}, + itemtype => $effective_itemtype, borrowernumber => $patron->borrowernumber, ccode => $item->{'ccode'}} ); @@ -724,28 +725,19 @@ sub CanBookBeIssued { return( { STATS => 1 }, {}); } - my $flags = C4::Members::patronflags( $patron_unblessed ); - if ( ref $flags ) { - if ( $flags->{GNA} ) { - $issuingimpossible{GNA} = 1; - } - if ( $flags->{'LOST'} ) { - $issuingimpossible{CARD_LOST} = 1; - } - if ( $flags->{'DBARRED'} ) { - $issuingimpossible{DEBARRED} = 1; - } + if ( $patron->gonenoaddress == 1 ) { + $issuingimpossible{GNA} = 1; + } + + if ( $patron->lost == 1 ) { + $issuingimpossible{CARD_LOST} = 1; + } + if ( $patron->is_debarred ) { + $issuingimpossible{DEBARRED} = 1; } - if ( !defined $patron->dateexpiry || $patron->dateexpiry eq '0000-00-00') { + + if ( $patron->is_expired ) { $issuingimpossible{EXPIRED} = 1; - } else { - my $expiry_dt = dt_from_string( $patron->dateexpiry, 'sql', 'floating' ); - $expiry_dt->truncate( to => 'day'); - my $today = $now->clone()->truncate(to => 'day'); - $today->set_time_zone( 'floating' ); - if ( DateTime->compare($today, $expiry_dt) == 1 ) { - $issuingimpossible{EXPIRED} = 1; - } } # @@ -753,8 +745,10 @@ sub CanBookBeIssued { # # DEBTS - my ($balance, $non_issue_charges, $other_charges) = - C4::Members::GetMemberAccountBalance( $patron->borrowernumber ); + my $account = $patron->account; + my $balance = $account->balance; + my $non_issues_charges = $account->non_issues_charges; + my $other_charges = $balance - $non_issues_charges; my $amountlimit = C4::Context->preference("noissuescharge"); my $allowfineoverride = C4::Context->preference("AllowFineOverride"); @@ -767,8 +761,7 @@ sub CanBookBeIssued { my @guarantees = $patron->guarantees(); my $guarantees_non_issues_charges; foreach my $g ( @guarantees ) { - my ( $b, $n, $o ) = C4::Members::GetMemberAccountBalance( $g->id ); - $guarantees_non_issues_charges += $n; + $guarantees_non_issues_charges += $g->account->non_issues_charges; } if ( $guarantees_non_issues_charges > $no_issues_charge_guarantees && !$inprocess && !$allowfineoverride) { @@ -781,21 +774,21 @@ sub CanBookBeIssued { } if ( C4::Context->preference("IssuingInProcess") ) { - if ( $non_issue_charges > $amountlimit && !$inprocess && !$allowfineoverride) { - $issuingimpossible{DEBT} = sprintf( "%.2f", $non_issue_charges ); - } elsif ( $non_issue_charges > $amountlimit && !$inprocess && $allowfineoverride) { - $needsconfirmation{DEBT} = sprintf( "%.2f", $non_issue_charges ); - } elsif ( $allfinesneedoverride && $non_issue_charges > 0 && $non_issue_charges <= $amountlimit && !$inprocess ) { - $needsconfirmation{DEBT} = sprintf( "%.2f", $non_issue_charges ); + if ( $non_issues_charges > $amountlimit && !$inprocess && !$allowfineoverride) { + $issuingimpossible{DEBT} = $non_issues_charges; + } elsif ( $non_issues_charges > $amountlimit && !$inprocess && $allowfineoverride) { + $needsconfirmation{DEBT} = $non_issues_charges; + } elsif ( $allfinesneedoverride && $non_issues_charges > 0 && $non_issues_charges <= $amountlimit && !$inprocess ) { + $needsconfirmation{DEBT} = $non_issues_charges; } } else { - if ( $non_issue_charges > $amountlimit && $allowfineoverride ) { - $needsconfirmation{DEBT} = sprintf( "%.2f", $non_issue_charges ); - } elsif ( $non_issue_charges > $amountlimit && !$allowfineoverride) { - $issuingimpossible{DEBT} = sprintf( "%.2f", $non_issue_charges ); - } elsif ( $non_issue_charges > 0 && $allfinesneedoverride ) { - $needsconfirmation{DEBT} = sprintf( "%.2f", $non_issue_charges ); + if ( $non_issues_charges > $amountlimit && $allowfineoverride ) { + $needsconfirmation{DEBT} = $non_issues_charges; + } elsif ( $non_issues_charges > $amountlimit && !$allowfineoverride) { + $issuingimpossible{DEBT} = $non_issues_charges; + } elsif ( $non_issues_charges > 0 && $allfinesneedoverride ) { + $needsconfirmation{DEBT} = $non_issues_charges; } } @@ -929,20 +922,20 @@ sub CanBookBeIssued { if ($notforloan->{'notforloan'}) { if (!C4::Context->preference("AllowNotForLoanOverride")) { $issuingimpossible{NOT_FOR_LOAN} = 1; - $issuingimpossible{itemtype_notforloan} = $item->{'itype'}; + $issuingimpossible{itemtype_notforloan} = $effective_itemtype; } else { $needsconfirmation{NOT_FOR_LOAN_FORCING} = 1; - $needsconfirmation{itemtype_notforloan} = $item->{'itype'}; + $needsconfirmation{itemtype_notforloan} = $effective_itemtype; } } } - elsif ($biblioitem->{'notforloan'} == 1){ + elsif ($biblioitem->notforloan == 1){ if (!C4::Context->preference("AllowNotForLoanOverride")) { $issuingimpossible{NOT_FOR_LOAN} = 1; - $issuingimpossible{itemtype_notforloan} = $biblioitem->{'itemtype'}; + $issuingimpossible{itemtype_notforloan} = $effective_itemtype; } else { $needsconfirmation{NOT_FOR_LOAN_FORCING} = 1; - $needsconfirmation{itemtype_notforloan} = $biblioitem->{'itemtype'}; + $needsconfirmation{itemtype_notforloan} = $effective_itemtype; } } } @@ -1018,7 +1011,7 @@ sub CanBookBeIssued { } ## CHECK AGE RESTRICTION - my $agerestriction = $biblioitem->{'agerestriction'}; + my $agerestriction = $biblioitem->agerestriction; my ($restriction_age, $daysToAgeRestriction) = GetAgeRestriction( $agerestriction, $patron->unblessed ); if ( $daysToAgeRestriction && $daysToAgeRestriction > 0 ) { if ( C4::Context->preference('AgeRestrictionOverride') ) { @@ -1405,14 +1398,15 @@ sub AddIssue { datelastborrowed => DateTime->now( time_zone => C4::Context->tz() )->ymd(), }, $item->{'biblionumber'}, - $item->{'itemnumber'} + $item->{'itemnumber'}, + { log_action => 0 } ); ModDateLastSeen( $item->{'itemnumber'} ); # If it costs to borrow this book, charge it to the patron's account. my ( $charge, $itemtype ) = GetIssuingCharges( $item->{'itemnumber'}, $borrower->{'borrowernumber'} ); if ( $charge > 0 ) { - AddIssuingCharge( $item->{'itemnumber'}, $borrower->{'borrowernumber'}, $charge ); + AddIssuingCharge( $issue, $charge ); $item->{'charge'} = $charge; } @@ -1838,7 +1832,7 @@ sub AddReturn { $item->{location} = $item->{permanent_location}; } - ModItem( $item, $item->{'biblionumber'}, $item->{'itemnumber'} ); + ModItem( $item, $item->{'biblionumber'}, $item->{'itemnumber'}, { log_action => 0 } ); } # full item data, but no borrowernumber or checkout info (no issue) @@ -1862,7 +1856,7 @@ sub AddReturn { foreach my $key ( keys %$rules ) { if ( $item->{notforloan} eq $key ) { $messages->{'NotForLoanStatusUpdated'} = { from => $item->{notforloan}, to => $rules->{$key} }; - ModItem( { notforloan => $rules->{$key} }, undef, $itemnumber ); + ModItem( { notforloan => $rules->{$key} }, undef, $itemnumber, { log_action => 0 } ); last; } } @@ -1928,7 +1922,7 @@ sub AddReturn { } - ModItem({ onloan => undef }, $item->{biblionumber}, $item->{'itemnumber'}); + ModItem( { onloan => undef }, $item->{biblionumber}, $item->{itemnumber}, { log_action => 0 } ); } # the holdingbranch is updated if the document is returned to another location. @@ -2164,7 +2158,7 @@ sub MarkIssueReturned { # And finally delete the issue $issue->delete; - ModItem( { 'onloan' => undef }, undef, $itemnumber ); + ModItem( { 'onloan' => undef }, undef, $itemnumber, { log_action => 0 } ); if ( C4::Context->preference('StoreLastBorrower') ) { my $item = Koha::Items->find( $itemnumber ); @@ -2245,8 +2239,25 @@ sub _debar_user_on_return { } } - my $new_debar_dt = - $return_date->clone()->add_duration( $suspension_days ); + if ( $issuing_rule->suspension_chargeperiod > 1 ) { + # No need to / 1 and do not consider / 0 + $suspension_days = DateTime::Duration->new( + days => floor( $suspension_days->in_units('days') / $issuing_rule->suspension_chargeperiod ) + ); + } + + my $new_debar_dt; + # Use the calendar or not to calculate the debarment date + if ( C4::Context->preference('finesCalendar') eq 'noFinesWhenClosed' ) { + my $calendar = Koha::Calendar->new( + branchcode => $branchcode, + days_mode => 'Calendar' + ); + $new_debar_dt = $calendar->addDate( $return_date, $suspension_days ); + } + else { + $new_debar_dt = $return_date->clone()->add_duration($suspension_days); + } Koha::Patron::Debarments::AddUniqueDebarment({ borrowernumber => $borrower->{borrowernumber}, @@ -2403,7 +2414,7 @@ sub _FixAccountForLostAndReturned { } ); - ModItem( { paidfor => '' }, undef, $itemnumber ); + ModItem( { paidfor => '' }, undef, $itemnumber, { log_action => 0 } ); return $credit_id; } @@ -2524,12 +2535,15 @@ sub GetUpcomingDueIssues { my $dbh = C4::Context->dbh; my $statement = <= 0 AND days_until_due <= ? +SELECT * +FROM ( + SELECT issues.*, items.itype as itemtype, items.homebranch, TO_DAYS( date_due )-TO_DAYS( NOW() ) as days_until_due, branches.branchemail + FROM issues + LEFT JOIN items USING (itemnumber) + LEFT OUTER JOIN branches USING (branchcode) + WHERE returndate is NULL +) tmp +WHERE days_until_due >= 0 AND days_until_due <= ? END_SQL my @bind_parameters = ( $params->{'days_in_advance'} ); @@ -2700,7 +2714,7 @@ sub CanBookBeRenewed { if ( C4::Context->preference('OPACFineNoRenewalsBlockAutoRenew') ) { my $fine_no_renewals = C4::Context->preference("OPACFineNoRenewals"); - my ( $amountoutstanding ) = C4::Members::GetMemberAccountRecords($patron->borrowernumber); + my $amountoutstanding = $patron->account->balance; if ( $amountoutstanding and $amountoutstanding > $fine_no_renewals ) { return ( 0, "auto_too_much_oweing" ); } @@ -2825,7 +2839,7 @@ sub AddRenewal { # Update the renewal count on the item, and tell zebra to reindex $renews = $item->{renewals} + 1; - ModItem({ renewals => $renews, onloan => $datedue->strftime('%Y-%m-%d %H:%M')}, $item->{biblionumber}, $itemnumber); + ModItem( { renewals => $renews, onloan => $datedue->strftime('%Y-%m-%d %H:%M')}, $item->{biblionumber}, $itemnumber, { log_action => 0 } ); # Charge a new rental fee, if applicable? my ( $charge, $type ) = GetIssuingCharges( $itemnumber, $borrowernumber ); @@ -3161,22 +3175,25 @@ sub _get_discount_from_rule { =head2 AddIssuingCharge - &AddIssuingCharge( $itemno, $borrowernumber, $charge ) + &AddIssuingCharge( $checkout, $charge ) =cut sub AddIssuingCharge { - my ( $itemnumber, $borrowernumber, $charge ) = @_; + my ( $checkout, $charge ) = @_; + + # FIXME What if checkout does not exist? - my $nextaccntno = getnextacctno($borrowernumber); + my $nextaccntno = getnextacctno($checkout->borrowernumber); my $manager_id = 0; $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv; my $accountline = Koha::Account::Line->new( { - borrowernumber => $borrowernumber, - itemnumber => $itemnumber, + borrowernumber => $checkout->borrowernumber, + itemnumber => $checkout->itemnumber, + issue_id => $checkout->issue_id, accountno => $nextaccntno, amount => $charge, amountoutstanding => $charge, @@ -3606,9 +3623,20 @@ sub ReturnLostItem{ sub LostItem{ - my ($itemnumber, $mark_returned) = @_; + my ($itemnumber, $mark_lost_from, $force_mark_returned) = @_; + + unless ( $mark_lost_from ) { + # Temporary check to avoid regressions + die q|LostItem called without $mark_lost_from, check the API.|; + } - $mark_returned //= C4::Context->preference('MarkLostItemsAsReturned'); + my $mark_returned; + if ( $force_mark_returned ) { + $mark_returned = 1; + } else { + my $pref = C4::Context->preference('MarkLostItemsAsReturned') // q{}; + $mark_returned = ( $pref =~ m|$mark_lost_from| ); + } my $dbh = C4::Context->dbh(); my $sth=$dbh->prepare("SELECT issues.*,items.*,biblio.title @@ -3704,7 +3732,8 @@ sub ProcessOfflineReturn { ModItem( { renewals => 0, onloan => undef }, $issue->{'biblionumber'}, - $itemnumber + $itemnumber, + { log_action => 0 } ); return "Success."; } else { @@ -3943,6 +3972,7 @@ sub GetTopIssues { my $dbh = C4::Context->dbh; my $query = q{ + SELECT * FROM ( SELECT b.biblionumber, b.title, b.author, bi.itemtype, bi.publishercode, bi.place, bi.publicationyear, b.copyrightdate, bi.pages, bi.size, i.ccode, SUM(i.issues) AS count @@ -3980,11 +4010,13 @@ sub GetTopIssues { } $query .= q{ - GROUP BY b.biblionumber - HAVING count > 0 + GROUP BY b.biblionumber, b.title, b.author, bi.itemtype, bi.publishercode, + bi.place, bi.publicationyear, b.copyrightdate, bi.pages, bi.size, + i.ccode ORDER BY count DESC }; + $query .= q{ ) xxx WHERE count > 0 }; $count = int($count); if ($count > 0) { $query .= "LIMIT $count";