From 0b1a6c343f2ef96c99e39652e91feb4b1ee25c82 Mon Sep 17 00:00:00 2001 From: Kyle M Hall Date: Tue, 15 Jul 2014 10:55:30 -0400 Subject: [PATCH] Bug 6427 - Update existing Koha perl modules Signed-off-by: Kyle M Hall Signed-off-by: Sean McGarvey --- C4/Circulation.pm | 424 +++++++++++++++--------------- C4/ILSDI/Services.pm | 9 +- C4/Members.pm | 188 ++++--------- C4/Overdues.pm | 359 ++++++++++--------------- C4/Reports/Guided.pm | 2 +- C4/Reserves.pm | 23 +- C4/SIP/ILS/Patron.pm | 3 +- C4/SIP/ILS/Transaction/FeePayment.pm | 20 +- C4/SIP/ILS/Transaction/Renew.pm | 6 + Koha/DateUtils.pm | 7 +- Koha/Template/Plugin/AuthorisedValues.pm | 2 + Koha/Template/Plugin/Koha.pm | 5 + 12 files changed, 464 insertions(+), 584 deletions(-) diff --git a/C4/Circulation.pm b/C4/Circulation.pm index 14dfb0e..49185da 100644 --- a/C4/Circulation.pm +++ b/C4/Circulation.pm @@ -30,7 +30,8 @@ use C4::Items; use C4::Members; use C4::Dates; use C4::Dates qw(format_date); -use C4::Accounts; +use Koha::Accounts; +use Koha::Accounts::CreditTypes; use C4::ItemCirculationAlertPreference; use C4::Message; use C4::Debug; @@ -1296,7 +1297,7 @@ sub AddIssue { ## If item was lost, it has now been found, reverse any list item charges if neccessary. if ( $item->{'itemlost'} ) { if ( C4::Context->preference('RefundLostItemFeeOnReturn' ) ) { - _FixAccountForLostAndReturned( $item->{'itemnumber'}, undef, $item->{'barcode'} ); + _FixAccountForLostAndReturned( $item->{'itemnumber'} ); } } @@ -1855,7 +1856,17 @@ sub AddReturn { } if ($borrowernumber) { - if ( ( C4::Context->preference('CalculateFinesOnReturn') && $issue->{'overdue'} ) || $return_date ) { + if ( + ( !$item->{itemlost} ) # skip lost items + && ( + ( + C4::Context->preference('CalculateFinesOnReturn') + && $issue->{'overdue'} + ) + || $return_date # force fine recalculation in case fine needs reduced + ) + ) + { # we only need to calculate and change the fines if we want to do that on return # Should be on for hourly loans my $control = C4::Context->preference('CircControl'); @@ -1873,21 +1884,32 @@ sub AddReturn { $type ||= q{}; - if ( C4::Context->preference('finesMode') eq 'production' ) { - if ( $amount > 0 ) { - C4::Overdues::UpdateFine( $issue->{itemnumber}, - $issue->{borrowernumber}, - $amount, $type, output_pref($datedue) ); - } - elsif ($return_date) { - - # Backdated returns may have fines that shouldn't exist, - # so in this case, we need to drop those fines to 0 - - C4::Overdues::UpdateFine( $issue->{itemnumber}, - $issue->{borrowernumber}, - 0, $type, output_pref($datedue) ); - } + if ( $amount > 0 + && C4::Context->preference('finesMode') eq 'production' ) + { + C4::Overdues::UpdateFine( + { + itemnumber => $issue->{itemnumber}, + borrowernumber => $issue->{borrowernumber}, + amount => $amount, + due => output_pref($datedue), + issue_id => $issue->{issue_id} + } + ); + } + elsif ($return_date) { + + # Backdated returns may have fines that shouldn't exist, + # so in this case, we need to drop those fines to 0 + C4::Overdues::UpdateFine( + { + itemnumber => $issue->{itemnumber}, + borrowernumber => $issue->{borrowernumber}, + amount => 0, + due => output_pref($datedue), + issue_id => $issue->{issue_id} + } + ); } } @@ -1938,15 +1960,20 @@ sub AddReturn { $messages->{'WasLost'} = 1; if ( C4::Context->preference('RefundLostItemFeeOnReturn' ) ) { - _FixAccountForLostAndReturned($item->{'itemnumber'}, $borrowernumber, $barcode); # can tolerate undef $borrowernumber + _FixAccountForLostAndReturned( $item->{'itemnumber'} ); $messages->{'LostItemFeeRefunded'} = 1; } } # fix up the overdues in accounts... if ($borrowernumber) { - my $fix = _FixOverduesOnReturn($borrowernumber, $item->{itemnumber}, $exemptfine, $dropbox); - defined($fix) or warn "_FixOverduesOnReturn($borrowernumber, $item->{itemnumber}...) failed!"; # zero is OK, check defined + _FinalizeFine( + { + exempt_fine => $exemptfine, + dropbox => $dropbox, + issue => Koha::Database->new()->schema->resultset('OldIssue')->find( $issue->{issue_id} ), + } + ); if ( $issue->{overdue} && $issue->{date_due} ) { # fix fine days @@ -2061,10 +2088,6 @@ of the return. It is ignored when a dropbox_branch is passed in. C<$privacy> contains the privacy parameter. If the patron has set privacy to 2, the old_issue is immediately anonymised -Ideally, this function would be internal to C, -not exported, but it is currently needed by one -routine in C. - =cut sub MarkIssueReturned { @@ -2186,155 +2209,129 @@ sub _debar_user_on_return { return; } -=head2 _FixOverduesOnReturn +=head2 _FinalizeFine - &_FixOverduesOnReturn($brn,$itm, $exemptfine, $dropboxmode); - -C<$brn> borrowernumber - -C<$itm> itemnumber + _FinalizeFine({ + exempt_fine => $exempt_fine, + dropbox => $dropbox, + issue => $issue, + }); C<$exemptfine> BOOL -- remove overdue charge associated with this issue. C<$dropboxmode> BOOL -- remove lastincrement on overdue charge associated with this issue. +C<$issue> -- DBIx::Class::Row for the issue -Internal function, called only by AddReturn +This subrouting closes out the accuruing of a fine, and reduces if it exemptfine or +dropbox flags are passed in. =cut -sub _FixOverduesOnReturn { - my ($borrowernumber, $item); - unless ($borrowernumber = shift) { - warn "_FixOverduesOnReturn() not supplied valid borrowernumber"; - return; - } - unless ($item = shift) { - warn "_FixOverduesOnReturn() not supplied valid itemnumber"; - return; - } - my ($exemptfine, $dropbox) = @_; +sub _FinalizeFine { + my ( $params ) = @_; + + my $exemptfine = $params->{exempt_fine}; + my $dropbox = $params->{dropbox}; + my $issue = $params->{issue}; + my $dbh = C4::Context->dbh; - # check for overdue fine - my $sth = $dbh->prepare( -"SELECT * FROM accountlines WHERE (borrowernumber = ?) AND (itemnumber = ?) AND (accounttype='FU' OR accounttype='O')" + my $schema = Koha::Database->new()->schema; + my $fine = $schema->resultset('AccountDebit')->single( + { + issue_id => $issue->issue_id(), + type => Koha::Accounts::DebitTypes::Fine(), + accruing => 1, + } ); - $sth->execute( $borrowernumber, $item ); - # alter fine to show that the book has been returned - my $data = $sth->fetchrow_hashref; - return 0 unless $data; # no warning, there's just nothing to fix + return unless ( $fine ); + + $fine->accruing(0); - my $uquery; - my @bind = ($data->{'accountlines_id'}); if ($exemptfine) { - $uquery = "update accountlines set accounttype='FFOR', amountoutstanding=0"; - if (C4::Context->preference("FinesLog")) { - &logaction("FINES", 'MODIFY',$borrowernumber,"Overdue forgiven: item $item"); - } - } elsif ($dropbox && $data->{lastincrement}) { - my $outstanding = $data->{amountoutstanding} - $data->{lastincrement} ; - my $amt = $data->{amount} - $data->{lastincrement} ; + AddCredit( + { + borrower => $fine->borrowernumber(), + amount => $fine->amount_original(), + debit_id => $fine->debit_id(), + type => Koha::Accounts::CreditTypes::Forgiven(), + } + ); if (C4::Context->preference("FinesLog")) { - &logaction("FINES", 'MODIFY',$borrowernumber,"Dropbox adjustment $amt, item $item"); - } - $uquery = "update accountlines set accounttype='F' "; - if($outstanding >= 0 && $amt >=0) { - $uquery .= ", amount = ? , amountoutstanding=? "; - unshift @bind, ($amt, $outstanding) ; + &logaction( + "FINES", 'MODIFY', + $issue->{borrowernumber}, + "Overdue forgiven: item " . $issue->{itemnumber} + ); } - } else { - $uquery = "update accountlines set accounttype='F' "; + } elsif ($dropbox && $fine->amount_last_increment() != $fine->amount_original() ) { + if ( C4::Context->preference("FinesLog") ) { + &logaction( "FINES", 'MODIFY', $issue->{borrowernumber}, + "Dropbox adjustment " + . $fine->amount_last_increment() + . ", item " . $issue->{itemnumber} ); + } + $fine->amount_original( + $fine->amount_original() - $fine->amount_last_increment() ); + $fine->amount_outstanding( + $fine->amount_outstanding - $fine->amount_last_increment() ); + $schema->resultset('AccountOffset')->create( + { + debit_id => $fine->debit_id(), + type => Koha::Accounts::OffsetTypes::Dropbox(), + amount => $fine->amount_last_increment() * -1, + } + ); } - $uquery .= " where (accountlines_id = ?)"; - my $usth = $dbh->prepare($uquery); - return $usth->execute(@bind); + + return $fine->update(); } =head2 _FixAccountForLostAndReturned - &_FixAccountForLostAndReturned($itemnumber, [$borrowernumber, $barcode]); + &_FixAccountForLostAndReturned($itemnumber); -Calculates the charge for a book lost and returned. - -Internal function, not exported, called only by AddReturn. - -FIXME: This function reflects how inscrutable fines logic is. Fix both. -FIXME: Give a positive return value on success. It might be the $borrowernumber who received credit, or the amount forgiven. + Refunds a lost item fee in necessary =cut sub _FixAccountForLostAndReturned { - my $itemnumber = shift or return; - my $borrowernumber = @_ ? shift : undef; - my $item_id = @_ ? shift : $itemnumber; # Send the barcode if you want that logged in the description - my $dbh = C4::Context->dbh; - # check for charge made for lost book - my $sth = $dbh->prepare("SELECT * FROM accountlines WHERE itemnumber = ? AND accounttype IN ('L', 'Rep', 'W') ORDER BY date DESC, accountno DESC"); - $sth->execute($itemnumber); - my $data = $sth->fetchrow_hashref; - $data or return; # bail if there is nothing to do - $data->{accounttype} eq 'W' and return; # Written off - - # writeoff this amount - my $offset; - my $amount = $data->{'amount'}; - my $acctno = $data->{'accountno'}; - my $amountleft; # Starts off undef/zero. - if ($data->{'amountoutstanding'} == $amount) { - $offset = $data->{'amount'}; - $amountleft = 0; # Hey, it's zero here, too. - } else { - $offset = $amount - $data->{'amountoutstanding'}; # Um, isn't this the same as ZERO? We just tested those two things are == - $amountleft = $data->{'amountoutstanding'} - $amount; # Um, isn't this the same as ZERO? We just tested those two things are == - } - my $usth = $dbh->prepare("UPDATE accountlines SET accounttype = 'LR',amountoutstanding='0' - WHERE (accountlines_id = ?)"); - $usth->execute($data->{'accountlines_id'}); # We might be adjusting an account for some OTHER borrowernumber now. Not the one we passed in. - #check if any credit is left if so writeoff other accounts - my $nextaccntno = getnextacctno($data->{'borrowernumber'}); - $amountleft *= -1 if ($amountleft < 0); - if ($amountleft > 0) { - my $msth = $dbh->prepare("SELECT * FROM accountlines WHERE (borrowernumber = ?) - AND (amountoutstanding >0) ORDER BY date"); # might want to order by amountoustanding ASC (pay smallest first) - $msth->execute($data->{'borrowernumber'}); - # offset transactions - my $newamtos; - my $accdata; - while (($accdata=$msth->fetchrow_hashref) and ($amountleft>0)){ - if ($accdata->{'amountoutstanding'} < $amountleft) { - $newamtos = 0; - $amountleft -= $accdata->{'amountoutstanding'}; - } else { - $newamtos = $accdata->{'amountoutstanding'} - $amountleft; - $amountleft = 0; - } - my $thisacct = $accdata->{'accountlines_id'}; - # FIXME: move prepares outside while loop! - my $usth = $dbh->prepare("UPDATE accountlines SET amountoutstanding= ? - WHERE (accountlines_id = ?)"); - $usth->execute($newamtos,$thisacct); - $usth = $dbh->prepare("INSERT INTO accountoffsets - (borrowernumber, accountno, offsetaccount, offsetamount) - VALUES - (?,?,?,?)"); - $usth->execute($data->{'borrowernumber'},$accdata->{'accountno'},$nextaccntno,$newamtos); - } - } - $amountleft *= -1 if ($amountleft > 0); - my $desc = "Item Returned " . $item_id; - $usth = $dbh->prepare("INSERT INTO accountlines - (borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding) - VALUES (?,?,now(),?,?,'CR',?)"); - $usth->execute($data->{'borrowernumber'},$nextaccntno,0-$amount,$desc,$amountleft); - if ($borrowernumber) { - # FIXME: same as query above. use 1 sth for both - $usth = $dbh->prepare("INSERT INTO accountoffsets - (borrowernumber, accountno, offsetaccount, offsetamount) - VALUES (?,?,?,?)"); - $usth->execute($borrowernumber, $data->{'accountno'}, $nextaccntno, $offset); - } + my ( $itemnumber ) = @_; + + my $schema = Koha::Database->new()->schema; + + # Find the last issue for this item + my $issue = + $schema->resultset('Issue')->single( { itemnumber => $itemnumber } ); + $issue ||= + $schema->resultset('OldIssue')->single( { itemnumber => $itemnumber } ); + + return unless $issue; + + # Find a lost fee for this issue + my $debit = $schema->resultset('AccountDebit')->single( + { + issue_id => $issue->issue_id(), + type => Koha::Accounts::DebitTypes::Lost() + } + ); + + return unless $debit; + + # Check for an existing found credit for this debit, if there is one, the fee has already been refunded and we do nothing + my @credits = $debit->account_offsets->search_related('credit', { 'credit.type' => Koha::Accounts::CreditTypes::Found() }); + + return if @credits; + + # Ok, so we know we have an unrefunded lost item fee, let's refund it + CreditLostItem( + { + borrower => $issue->borrower(), + debit => $debit + } + ); + ModItem({ paidfor => '' }, undef, $itemnumber); - return; } =head2 _GetCircControlBranch @@ -2783,14 +2780,11 @@ sub AddRenewal { my $dbh = C4::Context->dbh; # Find the issues record for this book - my $sth = - $dbh->prepare("SELECT * FROM issues WHERE itemnumber = ?"); - $sth->execute( $itemnumber ); - my $issuedata = $sth->fetchrow_hashref; + my $issue = Koha::Database->new()->schema->resultset('Issue')->single({ itemnumber => $itemnumber }); - return unless ( $issuedata ); + return unless ( $issue ); - $borrowernumber ||= $issuedata->{borrowernumber}; + $borrowernumber ||= $issue->get_column('borrowernumber'); if ( defined $datedue && ref $datedue ne 'DateTime' ) { carp 'Invalid date passed to AddRenewal.'; @@ -2806,41 +2800,45 @@ sub AddRenewal { my $itemtype = (C4::Context->preference('item-level_itypes')) ? $biblio->{'itype'} : $biblio->{'itemtype'}; $datedue = (C4::Context->preference('RenewalPeriodBase') eq 'date_due') ? - dt_from_string( $issuedata->{date_due} ) : + dt_from_string( $issue->get_column('date_due') ) : DateTime->now( time_zone => C4::Context->tz()); - $datedue = CalcDateDue($datedue, $itemtype, $issuedata->{'branchcode'}, $borrower, 'is a renewal'); + $datedue = CalcDateDue($datedue, $itemtype, $issue->get_column('branchcode'), $borrower, 'is a renewal'); } # Update the issues record to have the new due date, and a new count # of how many times it has been renewed. - my $renews = $issuedata->{'renewals'} + 1; - $sth = $dbh->prepare("UPDATE issues SET date_due = ?, renewals = ?, lastreneweddate = ? - WHERE borrowernumber=? - AND itemnumber=?" + $issue->update( + { + date_due => $datedue->strftime('%Y-%m-%d %H:%M'), + renewals => $issue->renewals() + 1, + lastreneweddate => $lastreneweddate, + } ); - $sth->execute( $datedue->strftime('%Y-%m-%d %H:%M'), $renews, $lastreneweddate, $borrowernumber, $itemnumber ); # Update the renewal count on the item, and tell zebra to reindex - $renews = $biblio->{'renewals'} + 1; + my $renews = $biblio->{'renewals'} + 1; ModItem({ renewals => $renews, onloan => $datedue->strftime('%Y-%m-%d %H:%M')}, $biblio->{'biblionumber'}, $itemnumber); # Charge a new rental fee, if applicable? my ( $charge, $type ) = GetIssuingCharges( $itemnumber, $borrowernumber ); if ( $charge > 0 ) { - my $accountno = getnextacctno( $borrowernumber ); my $item = GetBiblioFromItemNumber($itemnumber); - my $manager_id = 0; - $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv; - $sth = $dbh->prepare( - "INSERT INTO accountlines - (date, borrowernumber, accountno, amount, manager_id, - description,accounttype, amountoutstanding, itemnumber) - VALUES (now(),?,?,?,?,?,?,?,?)" + + my $borrower = + Koha::Database->new()->schema->resultset('Borrower') + ->find($borrowernumber); + + AddDebit( + { + borrower => $borrower, + itemnumber => $itemnumber, + amount => $charge, + type => Koha::Accounts::DebitTypes::Rental(), + description => + "Renewal of Rental Item $item->{'title'} $item->{'barcode'}" + } ); - $sth->execute( $borrowernumber, $accountno, $charge, $manager_id, - "Renewal of Rental Item $item->{'title'} $item->{'barcode'}", - 'Rent', $charge, $itemnumber ); } # Send a renewal slip according to checkout alert preferencei @@ -2882,6 +2880,9 @@ sub AddRenewal { borrowernumber => $borrowernumber, ccode => $item->{'ccode'}} ); + + _FinalizeFine( { issue => $issue } ); + return $datedue; } @@ -3066,25 +3067,21 @@ sub _get_discount_from_rule { =head2 AddIssuingCharge - &AddIssuingCharge( $itemno, $borrowernumber, $charge ) + &AddIssuingCharge( $itemnumber, $borrowernumber, $amount ) =cut sub AddIssuingCharge { - my ( $itemnumber, $borrowernumber, $charge ) = @_; - my $dbh = C4::Context->dbh; - my $nextaccntno = getnextacctno( $borrowernumber ); - my $manager_id = 0; - $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv; - my $query =" - INSERT INTO accountlines - (borrowernumber, itemnumber, accountno, - date, amount, description, accounttype, - amountoutstanding, manager_id) - VALUES (?, ?, ?,now(), ?, 'Rental', 'Rent',?,?) - "; - my $sth = $dbh->prepare($query); - $sth->execute( $borrowernumber, $itemnumber, $nextaccntno, $charge, $charge, $manager_id ); + my ( $itemnumber, $borrowernumber, $amount ) = @_; + + return AddDebit( + { + borrower => Koha::Database->new()->schema->resultset('Borrower')->find($borrowernumber), + itemnumber => $itemnumber, + amount => $amount, + type => Koha::Accounts::DebitTypes::Rental(), + } + ); } =head2 GetTransfers @@ -3603,30 +3600,34 @@ sub ReturnLostItem{ sub LostItem{ my ($itemnumber, $mark_returned) = @_; - my $dbh = C4::Context->dbh(); - my $sth=$dbh->prepare("SELECT issues.*,items.*,biblio.title - FROM issues - JOIN items USING (itemnumber) - JOIN biblio USING (biblionumber) - WHERE issues.itemnumber=?"); - $sth->execute($itemnumber); - my $issues=$sth->fetchrow_hashref(); + my $schema = Koha::Database->new()->schema; - # If a borrower lost the item, add a replacement cost to the their record - if ( my $borrowernumber = $issues->{borrowernumber} ){ - my $borrower = C4::Members::GetMemberDetails( $borrowernumber ); + my $issue = + $schema->resultset('Issue')->single( { itemnumber => $itemnumber } ); + + my ( $borrower, $item ); + if ( $issue ) { + $borrower = $issue->borrower(); + $item = $issue->item(); + } + + # If a borrower lost the item, add a replacement cost to the their record + if ( $borrower ){ if (C4::Context->preference('WhenLostForgiveFine')){ - my $fix = _FixOverduesOnReturn($borrowernumber, $itemnumber, 1, 0); # 1, 0 = exemptfine, no-dropbox - defined($fix) or warn "_FixOverduesOnReturn($borrowernumber, $itemnumber...) failed!"; # zero is OK, check defined + _FinalizeFine( + { + exempt_fine => 1, + dropbox => 0, + issue => $issue, + } + ); } - if (C4::Context->preference('WhenLostChargeReplacementFee')){ - C4::Accounts::chargelostitem($borrowernumber, $itemnumber, $issues->{'replacementprice'}, "Lost Item $issues->{'title'} $issues->{'barcode'}"); - #FIXME : Should probably have a way to distinguish this from an item that really was returned. - #warn " $issues->{'borrowernumber'} / $itemnumber "; + if ( C4::Context->preference('WhenLostChargeReplacementFee') ) { + DebitLostItem( { borrower => $borrower, issue => $issue } ); } - MarkIssueReturned($borrowernumber,$itemnumber,undef,undef,$borrower->{'privacy'}) if $mark_returned; + MarkIssueReturned( $borrower->borrowernumber(), $item->itemnumber(), undef, undef, $borrower->privacy() ) if $mark_returned; } } @@ -3744,10 +3745,15 @@ sub ProcessOfflineIssue { sub ProcessOfflinePayment { my $operation = shift; - my $borrower = C4::Members::GetMemberDetails( undef, $operation->{cardnumber} ); # Get borrower from operation cardnumber - my $amount = $operation->{amount}; - - recordpayment( $borrower->{borrowernumber}, $amount ); + AddCredit( + { + borrower => Koha::Database->new()->schema->resultset('Borrower') + ->single( { cardnumber => $operation->{cardnumber} } ), + amount => $operation->{amount}, + notes => 'via offline circulation', + type => Koha::Accounts::CreditTypes::Payment, + } + ); return "Success." } diff --git a/C4/ILSDI/Services.pm b/C4/ILSDI/Services.pm index b917a82..2c6fcc0 100644 --- a/C4/ILSDI/Services.pm +++ b/C4/ILSDI/Services.pm @@ -24,7 +24,6 @@ use C4::Members; use C4::Items; use C4::Circulation; use C4::Branch; -use C4::Accounts; use C4::Biblio; use C4::Reserves qw(AddReserve GetReservesFromBiblionumber GetReservesFromBorrowernumber CanBookBeReserved CanItemBeReserved); use C4::Context; @@ -34,6 +33,7 @@ use HTML::Entities; use CGI qw ( -utf8 ); use DateTime; use C4::Auth; +use Koha::Database; =head1 NAME @@ -387,10 +387,9 @@ sub GetPatronInfo { # Fines management if ( $cgi->param('show_fines') eq "1" ) { - my @charges; - for ( my $i = 1 ; my @charge = getcharges( $borrowernumber, undef, $i ) ; $i++ ) { - push( @charges, @charge ); - } + my @charges = + Koha::Database->new()->schema()->resultset('AccountDebit') + ->search( { borrowernumber => $borrowernumber } ); $borrower->{'fines'}->{'fine'} = \@charges; } diff --git a/C4/Members.pm b/C4/Members.pm index 4fb845d..67adbea 100644 --- a/C4/Members.pm +++ b/C4/Members.pm @@ -29,7 +29,6 @@ use Date::Calc qw/Today Add_Delta_YM check_date Date_to_Days/; use C4::Log; # logaction use C4::Overdues; use C4::Reserves; -use C4::Accounts; use C4::Biblio; use C4::Letters; use C4::SQLHelper qw(InsertInTable UpdateInTable SearchInTable); @@ -47,6 +46,7 @@ use Module::Load; if ( C4::Context->preference('NorwegianPatronDBEnable') && C4::Context->preference('NorwegianPatronDBEnable') == 1 ) { load Koha::NorwegianPatronDB, qw( NLUpdateHashedPIN NLEncryptPIN NLSync ); } +use Koha::Accounts::DebitTypes; our ($VERSION,@ISA,@EXPORT,@EXPORT_OK,$debug); @@ -86,8 +86,6 @@ BEGIN { &GetHideLostItemsPreference &IsMemberBlocked - &GetMemberAccountRecords - &GetBorNotifyAcctRecord &GetborCatFromCatType &GetBorrowercategory @@ -361,9 +359,8 @@ sub GetMemberDetails { } my $borrower = $sth->fetchrow_hashref; return unless $borrower; - my ($amount) = GetMemberAccountRecords($borrower->{borrowernumber}); - $borrower->{'amountoutstanding'} = $amount; - # FIXME - patronflags calls GetMemberAccountRecords... just have patronflags return $amount + $borrower->{amountoutstanding} = $borrower->{account_balance}; + # FIXME - find all references to $borrower->{amountoutstanding}, replace with $borrower->{account_balance} my $flags = patronflags( $borrower); my $accessflagshash; @@ -467,23 +464,20 @@ The "message" field that comes from the DB is OK. # FIXME rename this function. sub patronflags { my %flags; - my ( $patroninformation) = @_; - my $dbh=C4::Context->dbh; - my ($balance, $owing) = GetMemberAccountBalance( $patroninformation->{'borrowernumber'}); - if ( $owing > 0 ) { + my ($patroninformation) = @_; + my $dbh = C4::Context->dbh; + if ( $patroninformation->{account_balance} > 0 ) { my %flaginfo; my $noissuescharge = C4::Context->preference("noissuescharge") || 5; - $flaginfo{'message'} = sprintf 'Patron owes %.02f', $owing; - $flaginfo{'amount'} = sprintf "%.02f", $owing; - if ( $owing > $noissuescharge && !C4::Context->preference("AllowFineOverride") ) { + $flaginfo{'amount'} = $patroninformation->{account_balance}; + if ( $patroninformation->{account_balance} > $noissuescharge && !C4::Context->preference("AllowFineOverride") ) { $flaginfo{'noissues'} = 1; } $flags{'CHARGES'} = \%flaginfo; } - elsif ( $balance < 0 ) { + elsif ( $patroninformation->{account_balance} < 0 ) { my %flaginfo; - $flaginfo{'message'} = sprintf 'Patron has credit of %.02f', -$balance; - $flaginfo{'amount'} = sprintf "%.02f", $balance; + $flaginfo{'amount'} = $patroninformation->{account_balance}; $flags{'CREDITS'} = \%flaginfo; } if ( $patroninformation->{'gonenoaddress'} @@ -728,7 +722,7 @@ sub GetMemberIssuesAndFines { $sth->execute($borrowernumber); my $overdue_count = $sth->fetchrow_arrayref->[0]; - $sth = $dbh->prepare("SELECT SUM(amountoutstanding) FROM accountlines WHERE borrowernumber = ?"); + $sth = $dbh->prepare("SELECT account_balance FROM borrowers WHERE borrowernumber = ?"); $sth->execute($borrowernumber); my $total_fines = $sth->fetchrow_arrayref->[0]; @@ -1262,57 +1256,14 @@ sub GetAllIssues { } -=head2 GetMemberAccountRecords - - ($total, $acctlines, $count) = &GetMemberAccountRecords($borrowernumber); - -Looks up accounting data for the patron with the given borrowernumber. - -C<&GetMemberAccountRecords> returns a three-element array. C<$acctlines> is a -reference-to-array, where each element is a reference-to-hash; the -keys are the fields of the C table in the Koha database. -C<$count> is the number of elements in C<$acctlines>. C<$total> is the -total amount outstanding for all of the account lines. - -=cut - -sub GetMemberAccountRecords { - my ($borrowernumber) = @_; - my $dbh = C4::Context->dbh; - my @acctlines; - my $numlines = 0; - my $strsth = qq( - SELECT * - FROM accountlines - WHERE borrowernumber=?); - $strsth.=" ORDER BY date desc,timestamp DESC"; - my $sth= $dbh->prepare( $strsth ); - $sth->execute( $borrowernumber ); - - my $total = 0; - while ( my $data = $sth->fetchrow_hashref ) { - if ( $data->{itemnumber} ) { - my $biblio = GetBiblioFromItemNumber( $data->{itemnumber} ); - $data->{biblionumber} = $biblio->{biblionumber}; - $data->{title} = $biblio->{title}; - } - $acctlines[$numlines] = $data; - $numlines++; - $total += int(1000 * $data->{'amountoutstanding'}); # convert float to integer to avoid round-off errors - } - $total /= 1000; - return ( $total, \@acctlines,$numlines); -} - =head2 GetMemberAccountBalance ($total_balance, $non_issue_balance, $other_charges) = &GetMemberAccountBalance($borrowernumber); Calculates amount immediately owing by the patron - non-issue charges. -Based on GetMemberAccountRecords. Charges exempt from non-issue are: -* Res (reserves) -* Rent (rental) if RentalsInNoissuesCharge syspref is set to false +* HOLD fees (reserves) +* RENTAL if RentalsInNoissuesCharge syspref is set to false * Manual invoices if ManInvInNoissuesCharge syspref is set to false =cut @@ -1320,71 +1271,41 @@ Charges exempt from non-issue are: sub GetMemberAccountBalance { my ($borrowernumber) = @_; - my $ACCOUNT_TYPE_LENGTH = 5; # this is plain ridiculous... + my $borrower = + Koha::Database->new()->schema->resultset('Borrower') + ->find($borrowernumber); my @not_fines; - push @not_fines, 'Res' unless C4::Context->preference('HoldsInNoissuesCharge'); - push @not_fines, 'Rent' unless C4::Context->preference('RentalsInNoissuesCharge'); - unless ( C4::Context->preference('ManInvInNoissuesCharge') ) { - my $dbh = C4::Context->dbh; - my $man_inv_types = $dbh->selectcol_arrayref(qq{SELECT authorised_value FROM authorised_values WHERE category = 'MANUAL_INV'}); - push @not_fines, map substr($_, 0, $ACCOUNT_TYPE_LENGTH), @$man_inv_types; - } - my %not_fine = map {$_ => 1} @not_fines; - - my ($total, $acctlines) = GetMemberAccountRecords($borrowernumber); - my $other_charges = 0; - foreach (@$acctlines) { - $other_charges += $_->{amountoutstanding} if $not_fine{ substr($_->{accounttype}, 0, $ACCOUNT_TYPE_LENGTH) }; - } - - return ( $total, $total - $other_charges, $other_charges); -} -=head2 GetBorNotifyAcctRecord + push( @not_fines, Koha::Accounts::DebitTypes::Hold() ); - ($total, $acctlines, $count) = &GetBorNotifyAcctRecord($params,$notifyid); + push( @not_fines, Koha::Accounts::DebitTypes::Rental() ) + unless C4::Context->preference('RentalsInNoissuesCharge'); -Looks up accounting data for the patron with the given borrowernumber per file number. - -C<&GetBorNotifyAcctRecord> returns a three-element array. C<$acctlines> is a -reference-to-array, where each element is a reference-to-hash; the -keys are the fields of the C table in the Koha database. -C<$count> is the number of elements in C<$acctlines>. C<$total> is the -total amount outstanding for all of the account lines. - -=cut + unless ( C4::Context->preference('ManInvInNoissuesCharge') ) { + my $dbh = C4::Context->dbh; + my $man_inv_types = $dbh->selectcol_arrayref(q{ + SELECT authorised_value FROM authorised_values WHERE category = 'MANUAL_INV' + }); + push( @not_fines, @$man_inv_types ); + } -sub GetBorNotifyAcctRecord { - my ( $borrowernumber, $notifyid ) = @_; - my $dbh = C4::Context->dbh; - my @acctlines; - my $numlines = 0; - my $sth = $dbh->prepare( - "SELECT * - FROM accountlines - WHERE borrowernumber=? - AND notify_id=? - AND amountoutstanding != '0' - ORDER BY notify_id,accounttype - "); - - $sth->execute( $borrowernumber, $notifyid ); - my $total = 0; - while ( my $data = $sth->fetchrow_hashref ) { - if ( $data->{itemnumber} ) { - my $biblio = GetBiblioFromItemNumber( $data->{itemnumber} ); - $data->{biblionumber} = $biblio->{biblionumber}; - $data->{title} = $biblio->{title}; + my $other_charges = + Koha::Database->new()->schema->resultset('AccountDebit')->search( + { + borrowernumber => $borrowernumber, + type => { -in => \@not_fines } } - $acctlines[$numlines] = $data; - $numlines++; - $total += int(100 * $data->{'amountoutstanding'}); - } - $total /= 100; - return ( $total, \@acctlines, $numlines ); + )->get_column('amount_outstanding')->sum(); + + return ( + $borrower->account_balance(), + $borrower->account_balance() - $other_charges, + $other_charges + ); } + =head2 checkuniquemember (OUEST-PROVENCE) ($result,$categorycode) = &checkuniquemember($collectivity,$surname,$firstname,$dateofbirth); @@ -2550,22 +2471,21 @@ Add enrolment fee for a patron if needed. sub AddEnrolmentFeeIfNeeded { my ( $categorycode, $borrowernumber ) = @_; - # check for enrollment fee & add it if needed - my $dbh = C4::Context->dbh; - my $sth = $dbh->prepare(q{ - SELECT enrolmentfee - FROM categories - WHERE categorycode=? - }); - $sth->execute( $categorycode ); - if ( $sth->err ) { - warn sprintf('Database returned the following error: %s', $sth->errstr); - return; - } - my ($enrolmentfee) = $sth->fetchrow; - if ($enrolmentfee && $enrolmentfee > 0) { - # insert fee in patron debts - C4::Accounts::manualinvoice( $borrowernumber, '', '', 'A', $enrolmentfee ); + + my $schema = Koha::Database->new()->schema(); + + my $category = $schema->resultset('Category')->find($categorycode); + my $fee = $category->enrolmentfee(); + + if ( $fee && $fee > 0 ) { + AddDebit( + { + borrower => + $schema->resultset('Borrower')->find($borrowernumber), + type => Koha::Accounts::DebitTypes::AccountManagementFee(), + amount => $fee, + } + ); } } diff --git a/C4/Overdues.pm b/C4/Overdues.pm index 1797923..b32e7b5 100644 --- a/C4/Overdues.pm +++ b/C4/Overdues.pm @@ -27,9 +27,12 @@ use List::MoreUtils qw( uniq ); use C4::Circulation; use C4::Context; -use C4::Accounts; use C4::Log; # logaction use C4::Debug; +use Koha::Database; +use Koha::DateUtils; +use Koha::Accounts::OffsetTypes; +use Koha::Accounts::DebitTypes; use vars qw($VERSION @ISA @EXPORT); @@ -43,12 +46,8 @@ BEGIN { &CalcFine &Getoverdues &checkoverdues - &NumberNotifyId - &AmountNotify &UpdateFine &GetFine - - &CheckItemNotify &GetOverduesForBranch &RemoveNotifyLine &AddNotifyLine @@ -463,154 +462,145 @@ sub GetIssuesIteminfo { =head2 UpdateFine - &UpdateFine($itemnumber, $borrowernumber, $amount, $type, $description); + UpdateFine( + { + itemnumber => $itemnumber, + borrowernumber => $borrowernumber, + amount => $amount, + due => $due, + issue_id => $issue_id + } + ); -(Note: the following is mostly conjecture and guesswork.) +Updates the fine owed on an overdue item. -Updates the fine owed on an overdue book. +C<$itemnumber> is the items's id. -C<$itemnumber> is the book's item number. +C<$borrowernumber> is the id of the patron who currently +has the item on loan. -C<$borrowernumber> is the borrower number of the patron who currently -has the book on loan. +C<$amount> is the total amount of the fine owed by the patron. -C<$amount> is the current amount owed by the patron. +C<&UpdateFine> updates the amount owed for a given fine if an issue_id +is passed to it. Otherwise, a new fine will be created. -C<$type> will be used in the description of the fine. +=cut -C<$description> is a string that must be present in the description of -the fine. I think this is expected to be a date in DD/MM/YYYY format. +sub UpdateFine { + my ($params) = @_; -C<&UpdateFine> looks up the amount currently owed on the given item -and sets it to C<$amount>, creating, if necessary, a new entry in the -accountlines table of the Koha database. + my $itemnumber = $params->{itemnumber}; + my $borrowernumber = $params->{borrowernumber}; + my $amount = $params->{amount}; + my $due = $params->{due}; + my $issue_id = $params->{issue_id}; -=cut + my $schema = Koha::Database->new()->schema; -# -# Question: Why should the caller have to -# specify both the item number and the borrower number? A book can't -# be on loan to two different people, so the item number should be -# sufficient. -# -# Possible Answer: You might update a fine for a damaged item, *after* it is returned. -# -sub UpdateFine { - my ( $itemnum, $borrowernumber, $amount, $type, $due ) = @_; - $debug and warn "UpdateFine($itemnum, $borrowernumber, $amount, " . ($type||'""') . ", $due) called"; - my $dbh = C4::Context->dbh; - # FIXME - What exactly is this query supposed to do? It looks up an - # entry in accountlines that matches the given item and borrower - # numbers, where the description contains $due, and where the - # account type has one of several values, but what does this _mean_? - # Does it look up existing fines for this item? - # FIXME - What are these various account types? ("FU", "O", "F", "M") - # "L" is LOST item - # "A" is Account Management Fee - # "N" is New Card - # "M" is Sundry - # "O" is Overdue ?? - # "F" is Fine ?? - # "FU" is Fine UPDATE?? - # "Pay" is Payment - # "REF" is Cash Refund - my $sth = $dbh->prepare( - "SELECT * FROM accountlines - WHERE borrowernumber=? - AND accounttype IN ('FU','O','F','M')" - ); - $sth->execute( $borrowernumber ); - my $data; - my $total_amount_other = 0.00; - my $due_qr = qr/$due/; - # Cycle through the fines and - # - find line that relates to the requested $itemnum - # - accumulate fines for other items - # so we can update $itemnum fine taking in account fine caps - while (my $rec = $sth->fetchrow_hashref) { - if ($rec->{itemnumber} == $itemnum && $rec->{description} =~ /$due_qr/) { - if ($data) { - warn "Not a unique accountlines record for item $itemnum borrower $borrowernumber"; - } else { - $data = $rec; - next; + my $borrower = $schema->resultset('Borrower')->find($borrowernumber); + + if ( my $maxfine = C4::Context->preference('MaxFine') ) { + if ( $borrower->account_balance() + $amount > $maxfine ) { + my $new_amount = $maxfine - $borrower->account_balance(); + warn "Reducing fine for item $itemnumber borrower $borrowernumber from $amount to $new_amount - MaxFine reached"; + if ( $new_amount <= 0 ) { + warn "Fine reduced to a non-positive ammount. Fine not created."; + return; } + $amount = $new_amount; } - $total_amount_other += $rec->{'amountoutstanding'}; } - if (my $maxfine = C4::Context->preference('MaxFine')) { - if ($total_amount_other + $amount > $maxfine) { - my $new_amount = $maxfine - $total_amount_other; - return if $new_amount <= 0.00; - warn "Reducing fine for item $itemnum borrower $borrowernumber from $amount to $new_amount - MaxFine reached"; - $amount = $new_amount; + my $timestamp = get_timestamp(); + + my $fine = $schema->resultset('AccountDebit')->single( + { + issue_id => $issue_id, + type => Koha::Accounts::DebitTypes::Fine, + accruing => 1, } - } + ); - if ( $data ) { - - # we're updating an existing fine. Only modify if amount changed - # Note that in the current implementation, you cannot pay against an accruing fine - # (i.e. , of accounttype 'FU'). Doing so will break accrual. - if ( $data->{'amount'} != $amount ) { - my $diff = $amount - $data->{'amount'}; - #3341: diff could be positive or negative! - my $out = $data->{'amountoutstanding'} + $diff; - my $query = " - UPDATE accountlines - SET date=now(), amount=?, amountoutstanding=?, - lastincrement=?, accounttype='FU' - WHERE borrowernumber=? - AND itemnumber=? - AND accounttype IN ('FU','O') - AND description LIKE ? - LIMIT 1 "; - my $sth2 = $dbh->prepare($query); - # FIXME: BOGUS query cannot ensure uniqueness w/ LIKE %x% !!! - # LIMIT 1 added to prevent multiple affected lines - # FIXME: accountlines table needs unique key!! Possibly a combo of borrowernumber and accountline. - # But actually, we should just have a regular autoincrementing PK and forget accountline, - # including the bogus getnextaccountno function (doesn't prevent conflict on simultaneous ops). - # FIXME: Why only 2 account types here? - $debug and print STDERR "UpdateFine query: $query\n" . - "w/ args: $amount, $out, $diff, $data->{'borrowernumber'}, $data->{'itemnumber'}, \"\%$due\%\"\n"; - $sth2->execute($amount, $out, $diff, $data->{'borrowernumber'}, $data->{'itemnumber'}, "%$due%"); - } else { - # print "no update needed $data->{'amount'}" + my $offset = 0; + my $credit; + if ($fine) { + if ( $fine->accruing() ) { # Don't update or recreate fines no longer accruing + if ( + sprintf( "%.6f", $fine->amount_original() ) + ne + sprintf( "%.6f", $amount ) ) + { + my $difference = $amount - $fine->amount_original(); + + # Fine was reduced by a change in circulation rules or another reason + # we need to credit the account the difference and zero out the amount outstanding + if ( $difference < 0 ) { + $fine->amount_outstanding( $fine->amount_outstanding() + $difference ); + + $credit = + Koha::Database->new()->schema->resultset('AccountCredit') + ->create( + { + borrowernumber => $borrowernumber, + type => Koha::Accounts::CreditTypes::FineReduction(), + amount_remaining => abs($difference), + created_on => $timestamp, + } + ); + + } else { + $fine->amount_outstanding( $amount ); + } + + $fine->amount_last_increment($difference); + $fine->amount_original( $fine->amount_original() + $difference ); + $fine->updated_on($timestamp); + $fine->update(); + + $offset = 1; + } } - } else { - my $sth4 = $dbh->prepare( - "SELECT title FROM biblio LEFT JOIN items ON biblio.biblionumber=items.biblionumber WHERE items.itemnumber=?" + } + elsif ( $amount ) { # No fine to update, don't insert fines of $0.00 + my $item = $schema->resultset('Item')->find($itemnumber); + + $fine = $schema->resultset('AccountDebit')->create( + { + borrowernumber => $borrowernumber, + itemnumber => $itemnumber, + issue_id => $issue_id, + type => Koha::Accounts::DebitTypes::Fine(), + accruing => 1, + amount_original => $amount, + amount_outstanding => $amount, + amount_last_increment => $amount, + description => $item->biblio()->title() . " / Due:$due", + created_on => $timestamp, + } ); - $sth4->execute($itemnum); - my $title = $sth4->fetchrow; - -# # print "not in account"; -# my $sth3 = $dbh->prepare("Select max(accountno) from accountlines"); -# $sth3->execute; -# -# # FIXME - Make $accountno a scalar. -# my @accountno = $sth3->fetchrow_array; -# $sth3->finish; -# $accountno[0]++; -# begin transaction - my $nextaccntno = C4::Accounts::getnextacctno($borrowernumber); - my $desc = ($type ? "$type " : '') . "$title $due"; # FIXEDME, avoid whitespace prefix on empty $type - my $query = "INSERT INTO accountlines - (borrowernumber,itemnumber,date,amount,description,accounttype,amountoutstanding,lastincrement,accountno) - VALUES (?,?,now(),?,?,'FU',?,?,?)"; - my $sth2 = $dbh->prepare($query); - $debug and print STDERR "UpdateFine query: $query\nw/ args: $borrowernumber, $itemnum, $amount, $desc, $amount, $amount, $nextaccntno\n"; - $sth2->execute($borrowernumber, $itemnum, $amount, $desc, $amount, $amount, $nextaccntno); + + $offset = 1; + } else { # No fine to update, amount is 0, just return + return; } - # logging action - &logaction( - "FINES", - $type, + + $schema->resultset('AccountOffset')->create( + { + debit_id => $fine->debit_id(), + credit_id => $credit ? $credit->credit_id() : undef, + amount => $fine->amount_last_increment(), + created_on => $timestamp, + type => Koha::Accounts::OffsetTypes::Fine(), + } + ) if $offset; + + $borrower->account_balance( $borrower->account_balance + $fine->amount_last_increment() ); + $borrower->update(); + + logaction( "FINES", Koha::Accounts::DebitTypes::Fine(), $borrowernumber, - "due=".$due." amount=".$amount." itemnumber=".$itemnum - ) if C4::Context->preference("FinesLog"); + "due=" . $due . " amount=" . $amount . " itemnumber=" . $itemnumber ) + if C4::Context->preference("FinesLog"); } =head2 BorType @@ -672,56 +662,20 @@ sub GetFine { return 0; } -=head2 NumberNotifyId - - (@notify) = &NumberNotifyId($borrowernumber); - -Returns amount for all file per borrowers -C<@notify> array contains all file per borrowers - -C<$notify_id> contains the file number for the borrower number nad item number - -=cut - -sub NumberNotifyId{ - my ($borrowernumber)=@_; - my $dbh = C4::Context->dbh; - my $query=qq| SELECT distinct(notify_id) - FROM accountlines - WHERE borrowernumber=?|; - my @notify; - my $sth = $dbh->prepare($query); - $sth->execute($borrowernumber); - while ( my ($numberofnotify) = $sth->fetchrow ) { - push( @notify, $numberofnotify ); - } - return (@notify); -} - -=head2 AmountNotify - ($totalnotify) = &AmountNotify($notifyid); - -Returns amount for all file per borrowers -C<$notifyid> is the file number - -C<$totalnotify> contains amount of a file +=head2 NumberNotifyId -C<$notify_id> contains the file number for the borrower number and item number + my $schema = Koha::Database->new()->schema; -=cut + my $amount_outstanding = $schema->resultset('AccountDebit')->search( + { + itemnumber => $itemnumber, + borrowernumber => $borrowernumber, + type => Koha::Accounts::DebitTypes::Fine(), + }, + )->get_column('amount_outstanding')->sum(); -sub AmountNotify{ - my ($notifyid,$borrowernumber)=@_; - my $dbh = C4::Context->dbh; - my $query=qq| SELECT sum(amountoutstanding) - FROM accountlines - WHERE notify_id=? AND borrowernumber = ?|; - my $sth=$dbh->prepare($query); - $sth->execute($notifyid,$borrowernumber); - my $totalnotify=$sth->fetchrow; - $sth->finish; - return ($totalnotify); + return $amount_outstanding; } =head2 GetItems @@ -777,27 +731,6 @@ sub GetBranchcodesWithOverdueRules { return @$branchcodes; } -=head2 CheckItemNotify - -Sql request to check if the document has alreday been notified -this function is not exported, only used with GetOverduesForBranch - -=cut - -sub CheckItemNotify { - my ($notify_id,$notify_level,$itemnumber) = @_; - my $dbh = C4::Context->dbh; - my $sth = $dbh->prepare(" - SELECT COUNT(*) - FROM notifys - WHERE notify_id = ? - AND notify_level = ? - AND itemnumber = ? "); - $sth->execute($notify_id,$notify_level,$itemnumber); - my $notified = $sth->fetchrow; - return ($notified); -} - =head2 GetOverduesForBranch Sql request for display all information for branchoverdues.pl @@ -823,6 +756,7 @@ sub GetOverduesForBranch { biblio.title, biblio.author, biblio.biblionumber, + issues.issue_id, issues.date_due, issues.returndate, issues.branchcode, @@ -833,25 +767,23 @@ sub GetOverduesForBranch { items.location, items.itemnumber, itemtypes.description, - accountlines.notify_id, - accountlines.notify_level, - accountlines.amountoutstanding - FROM accountlines - LEFT JOIN issues ON issues.itemnumber = accountlines.itemnumber - AND issues.borrowernumber = accountlines.borrowernumber - LEFT JOIN borrowers ON borrowers.borrowernumber = accountlines.borrowernumber + account_debits.amount_outstanding + FROM account_debits + LEFT JOIN issues ON issues.itemnumber = account_debits.itemnumber + AND issues.borrowernumber = account_debits.borrowernumber + LEFT JOIN borrowers ON borrowers.borrowernumber = account_debits.borrowernumber LEFT JOIN items ON items.itemnumber = issues.itemnumber LEFT JOIN biblio ON biblio.biblionumber = items.biblionumber LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber LEFT JOIN itemtypes ON itemtypes.itemtype = $itype_link LEFT JOIN branches ON branches.branchcode = issues.branchcode - WHERE (accountlines.amountoutstanding != '0.000000') - AND (accountlines.accounttype = 'FU' ) + WHERE (account_debits.amount_outstanding != '0.000000') + AND (account_debits.type = 'FINE') + AND (account_debits.accruing = 1 ) AND (issues.branchcode = ? ) AND (issues.date_due < NOW()) "; my @getoverdues; - my $i = 0; my $sth; if ($location) { $sth = $dbh->prepare("$select AND items.location = ? ORDER BY borrowers.surname, borrowers.firstname"); @@ -861,12 +793,7 @@ sub GetOverduesForBranch { $sth->execute($branch); } while ( my $data = $sth->fetchrow_hashref ) { - #check if the document has already been notified - my $countnotify = CheckItemNotify($data->{'notify_id'}, $data->{'notify_level'}, $data->{'itemnumber'}); - if ($countnotify eq '0') { - $getoverdues[$i] = $data; - $i++; - } + push( @getoverdues, $data ); } return (@getoverdues); } diff --git a/C4/Reports/Guided.pm b/C4/Reports/Guided.pm index aaa1ce2..51b2018 100644 --- a/C4/Reports/Guided.pm +++ b/C4/Reports/Guided.pm @@ -99,7 +99,7 @@ sub get_table_areas { CAT => [ 'items', 'biblioitems', 'biblio' ], PAT => ['borrowers'], ACQ => [ 'aqorders', 'biblio', 'items' ], - ACC => [ 'borrowers', 'accountlines' ], + ACC => [ 'borrowers', 'account_credits', 'account_debits' ], ); } diff --git a/C4/Reserves.pm b/C4/Reserves.pm index f405262..8472a98 100644 --- a/C4/Reserves.pm +++ b/C4/Reserves.pm @@ -28,7 +28,6 @@ use C4::Biblio; use C4::Members; use C4::Items; use C4::Circulation; -use C4::Accounts; # for _koha_notify_reserve use C4::Members::Messaging; @@ -177,19 +176,17 @@ sub AddReserve { $waitingdate = $resdate; } - #eval { - # updates take place here if ( $fee > 0 ) { - my $nextacctno = &getnextacctno( $borrowernumber ); - my $query = qq{ - INSERT INTO accountlines - (borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding) - VALUES - (?,?,now(),?,?,'Res',?) - }; - my $usth = $dbh->prepare($query); - $usth->execute( $borrowernumber, $nextacctno, $fee, - "Reserve Charge - $title", $fee ); + AddDebit( + { + borrowernumber => $borrowernumber, + itemnumber => $checkitem, + amount => $fee, + type => Koha::Accounts::DebitTypes::Hold(), + description => $title, + notes => "Record ID: $biblionumber", + } + ); } #if ($const eq 'a'){ diff --git a/C4/SIP/ILS/Patron.pm b/C4/SIP/ILS/Patron.pm index 4e9c152..2a11295 100644 --- a/C4/SIP/ILS/Patron.pm +++ b/C4/SIP/ILS/Patron.pm @@ -87,7 +87,7 @@ sub new { hold_ok => ( !$debarred && !$expired && !$fine_blocked), card_lost => ( $kp->{lost} || $kp->{gonenoaddress} || $flags->{LOST} ), claims_returned => 0, - fines => $fines_amount, # GetMemberAccountRecords($kp->{borrowernumber}) + fines => $fines_amount, fees => 0, # currently not distinct from fines recall_overdue => 0, items_billed => 0, @@ -102,6 +102,7 @@ sub new { inet => ( !$debarred && !$expired ), expired => $expired, fee_limit => $fee_limit, + account_balance => $kp->{account_balance}, ); } $debug and warn "patron fines: $ilspatron{fines} ... amountoutstanding: $kp->{amountoutstanding} ... CHARGES->amount: $flags->{CHARGES}->{amount}"; diff --git a/C4/SIP/ILS/Transaction/FeePayment.pm b/C4/SIP/ILS/Transaction/FeePayment.pm index df936cd..7f9ab13 100644 --- a/C4/SIP/ILS/Transaction/FeePayment.pm +++ b/C4/SIP/ILS/Transaction/FeePayment.pm @@ -20,7 +20,10 @@ use strict; # with Koha; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -use C4::Accounts qw(recordpayment); +use Koha::Accounts qw(AddCredit); +use Koha::Accounts::CreditTypes; +use Koha::Database; +use ILS; use parent qw(C4::SIP::ILS::Transaction); @@ -44,10 +47,19 @@ sub new { sub pay { my $self = shift; my $borrowernumber = shift; - my $amt = shift; + my $amount = shift; my $type = shift; - warn("RECORD:$borrowernumber::$amt"); - recordpayment( $borrowernumber, $amt,$type ); + + warn("RECORD:$borrowernumber::$amount"); + + AddCredit( + { + borrower => Koha::Database->new()->schema->resultset('Borrower')->find($borrowernumber), + amount => $amount, + notes => "via SIP2. Type:$type", + type => Koha::Accounts::CreditTypes::Payment, + } + ); } #sub DESTROY { diff --git a/C4/SIP/ILS/Transaction/Renew.pm b/C4/SIP/ILS/Transaction/Renew.pm index a96811e..25f6810 100644 --- a/C4/SIP/ILS/Transaction/Renew.pm +++ b/C4/SIP/ILS/Transaction/Renew.pm @@ -32,6 +32,12 @@ sub do_renew_for { my $self = shift; my $borrower = shift; my ($renewokay,$renewerror) = CanBookBeRenewed($borrower->{borrowernumber},$self->{item}->{itemnumber}); + + unless ( $borrower->{account_balance} < C4::Context->preference('OPACFineNoRenewals') ) { + $renewokay = 0; + $renewerror = 'too_many_fines' + } + if ($renewokay){ $self->{due} = undef; my $due_date = AddIssue( $borrower, $self->{item}->id, undef, 0 ); diff --git a/Koha/DateUtils.pm b/Koha/DateUtils.pm index 61877b9..038aa46 100644 --- a/Koha/DateUtils.pm +++ b/Koha/DateUtils.pm @@ -21,13 +21,14 @@ use warnings; use 5.010; use DateTime; use DateTime::Format::DateParse; +use DateTime::Format::MySQL; use C4::Context; use base 'Exporter'; use version; our $VERSION = qv('1.0.0'); our @EXPORT = ( - qw( dt_from_string output_pref format_sqldatetime ) + qw( dt_from_string output_pref format_sqldatetime get_timestamp ) ); =head1 DateUtils @@ -209,4 +210,8 @@ sub format_sqldatetime { return q{}; } +sub get_timestamp { + return DateTime::Format::MySQL->format_datetime( dt_from_string() ); +} + 1; diff --git a/Koha/Template/Plugin/AuthorisedValues.pm b/Koha/Template/Plugin/AuthorisedValues.pm index 36ddce1..2df9e1c 100644 --- a/Koha/Template/Plugin/AuthorisedValues.pm +++ b/Koha/Template/Plugin/AuthorisedValues.pm @@ -77,3 +77,5 @@ Kyle M Hall Jonathan Druart =cut + +1; diff --git a/Koha/Template/Plugin/Koha.pm b/Koha/Template/Plugin/Koha.pm index f5898b5..32ab15d 100644 --- a/Koha/Template/Plugin/Koha.pm +++ b/Koha/Template/Plugin/Koha.pm @@ -59,4 +59,9 @@ sub Version { }; } +sub Get { + my ( $self, $category, $selected, $opac ) = @_; + return GetAuthorisedValues( $category, $selected, $opac ); +} + 1; -- 1.7.10.4