3 # Copyright 2000-2002 Katipo Communications
5 # This file is part of Koha.
7 # Koha is free software; you can redistribute it and/or modify it under the
8 # terms of the GNU General Public License as published by the Free Software
9 # Foundation; either version 2 of the License, or (at your option) any later
12 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License along
17 # with Koha; if not, write to the Free Software Foundation, Inc.,
18 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #use warnings; FIXME - Bug 2505
26 use C4::Circulation qw(ReturnLostItem);
27 use C4::Log qw(logaction);
29 use Data::Dumper qw(Dumper);
31 use vars qw($VERSION @ISA @EXPORT);
34 # set the version for version checking
35 $VERSION = 3.07.00.049;
51 &recordpayment_selectaccts
58 C4::Accounts - Functions for dealing with Koha accounts
66 The functions in this module deal with the monetary aspect of Koha,
67 including looking up and modifying the amount of money owed by a
74 &recordpayment($borrowernumber, $payment);
76 Record payment by a patron. C<$borrowernumber> is the patron's
77 borrower number. C<$payment> is a floating-point number, giving the
80 Amounts owed are paid off oldest first. That is, if the patron has a
81 $1 fine from Feb. 1, another $1 fine from Mar. 1, and makes a payment
82 of $1.50, then the oldest fine will be paid off in full, and $0.50
83 will be credited to the next one.
90 #here we update the account lines
91 my ( $borrowernumber, $data ) = @_;
92 my $dbh = C4::Context->dbh;
95 my $branch = C4::Context->userenv->{'branch'};
96 my $amountleft = $data;
98 $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
101 my $nextaccntno = getnextacctno($borrowernumber);
103 # get lines with outstanding amounts to offset
104 my $sth = $dbh->prepare(
105 "SELECT * FROM accountlines
106 WHERE (borrowernumber = ?) AND (amountoutstanding<>0)
109 $sth->execute($borrowernumber);
111 # offset transactions
113 while ( ( $accdata = $sth->fetchrow_hashref ) and ( $amountleft > 0 ) ) {
114 if ( $accdata->{'amountoutstanding'} < $amountleft ) {
116 $amountleft -= $accdata->{'amountoutstanding'};
119 $newamtos = $accdata->{'amountoutstanding'} - $amountleft;
122 my $thisacct = $accdata->{accountlines_id};
123 my $usth = $dbh->prepare(
124 "UPDATE accountlines SET amountoutstanding= ?
125 WHERE (accountlines_id = ?)"
127 $usth->execute( $newamtos, $thisacct );
129 if ( C4::Context->preference("FinesLog") ) {
130 $accdata->{'amountoutstanding_new'} = $newamtos;
131 logaction("FINES", 'MODIFY', $borrowernumber, Dumper({
132 action => 'fee_payment',
133 borrowernumber => $accdata->{'borrowernumber'},
134 old_amountoutstanding => $accdata->{'amountoutstanding'},
135 new_amountoutstanding => $newamtos,
136 amount_paid => $accdata->{'amountoutstanding'} - $newamtos,
137 accountlines_id => $accdata->{'accountlines_id'},
138 accountno => $accdata->{'accountno'},
139 manager_id => $manager_id,
141 push( @ids, $accdata->{'accountlines_id'} );
146 my $usth = $dbh->prepare(
147 "INSERT INTO accountlines
148 (borrowernumber, accountno,date,amount,description,accounttype,amountoutstanding,manager_id)
149 VALUES (?,?,now(),?,'Payment,thanks','Pay',?,?)"
151 $usth->execute( $borrowernumber, $nextaccntno, 0 - $data, 0 - $amountleft, $manager_id );
153 UpdateStats( $branch, 'payment', $data, '', '', '', $borrowernumber, $nextaccntno );
155 if ( C4::Context->preference("FinesLog") ) {
156 $accdata->{'amountoutstanding_new'} = $newamtos;
157 logaction("FINES", 'CREATE',$borrowernumber,Dumper({
158 action => 'create_payment',
159 borrowernumber => $borrowernumber,
160 accountno => $nextaccntno,
161 amount => $data * -1,
162 amountoutstanding => $amountleft * -1,
163 accounttype => 'Pay',
164 accountlines_paid => \@ids,
165 manager_id => $manager_id,
173 &makepayment($accountlines_id, $borrowernumber, $acctnumber, $amount, $branchcode);
175 Records the fact that a patron has paid off the entire amount he or
178 C<$borrowernumber> is the patron's borrower number. C<$acctnumber> is
179 the account that was credited. C<$amount> is the amount paid (this is
180 only used to record the payment. It is assumed to be equal to the
181 amount owed). C<$branchcode> is the code of the branch where payment
187 # FIXME - I'm not at all sure about the above, because I don't
188 # understand what the acct* tables in the Koha database are for.
191 #here we update both the accountoffsets and the account lines
192 #updated to check, if they are paying off a lost item, we return the item
193 # from their card, and put a note on the item record
194 my ( $accountlines_id, $borrowernumber, $accountno, $amount, $user, $branch ) = @_;
195 my $dbh = C4::Context->dbh;
197 $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
200 my $nextaccntno = getnextacctno($borrowernumber);
202 my $sth = $dbh->prepare("SELECT * FROM accountlines WHERE accountlines_id=?");
203 $sth->execute( $accountlines_id );
204 my $data = $sth->fetchrow_hashref;
208 if ( $data->{'accounttype'} eq "Pay" ){
212 SET amountoutstanding = 0, description = 'Payment,thanks'
213 WHERE accountlines_id = ?
216 $udp->execute($accountlines_id);
222 SET amountoutstanding = 0
223 WHERE accountlines_id = ?
226 $udp->execute($accountlines_id);
230 $payment = 0 - $amount;
235 INTO accountlines (borrowernumber, accountno, date, amount, itemnumber, description, accounttype, amountoutstanding, manager_id)
236 VALUES ( ?, ?, now(), ?, ?, 'Payment,thanks', 'Pay', 0, ?)"
238 $ins->execute($borrowernumber, $nextaccntno, $payment, $data->{'itemnumber'}, $manager_id);
242 if ( C4::Context->preference("FinesLog") ) {
243 logaction("FINES", 'MODIFY', $borrowernumber, Dumper({
244 action => 'fee_payment',
245 borrowernumber => $borrowernumber,
246 old_amountoutstanding => $data->{'amountoutstanding'},
247 new_amountoutstanding => 0,
248 amount_paid => $data->{'amountoutstanding'},
249 accountlines_id => $data->{'accountlines_id'},
250 accountno => $data->{'accountno'},
251 manager_id => $manager_id,
255 logaction("FINES", 'CREATE',$borrowernumber,Dumper({
256 action => 'create_payment',
257 borrowernumber => $borrowernumber,
258 accountno => $nextaccntno,
260 amountoutstanding => 0,,
261 accounttype => 'Pay',
262 accountlines_paid => [$data->{'accountlines_id'}],
263 manager_id => $manager_id,
268 # FIXME - The second argument to &UpdateStats is supposed to be the
270 # UpdateStats is now being passed $accountno too. MTJ
271 UpdateStats( $user, 'payment', $amount, '', '', '', $borrowernumber,
274 #check to see what accounttype
275 if ( $data->{'accounttype'} eq 'Rep' || $data->{'accounttype'} eq 'L' ) {
276 C4::Circulation::ReturnLostItem( $borrowernumber, $data->{'itemnumber'} );
278 my $sthr = $dbh->prepare("SELECT max(accountlines_id) AS lastinsertid FROM accountlines");
280 my $datalastinsertid = $sthr->fetchrow_hashref;
282 return $datalastinsertid->{'lastinsertid'};
287 $nextacct = &getnextacctno($borrowernumber);
289 Returns the next unused account number for the patron with the given
295 # FIXME - Okay, so what does the above actually _mean_?
297 my ($borrowernumber) = shift or return;
298 my $sth = C4::Context->dbh->prepare(
299 "SELECT accountno+1 FROM accountlines
300 WHERE (borrowernumber = ?)
301 ORDER BY accountno DESC
304 $sth->execute($borrowernumber);
305 return ($sth->fetchrow || 1);
308 =head2 fixaccounts (removed)
310 &fixaccounts($accountlines_id, $borrowernumber, $accountnumber, $amount);
313 # FIXME - I don't understand what this function does.
315 my ( $accountlines_id, $borrowernumber, $accountno, $amount ) = @_;
316 my $dbh = C4::Context->dbh;
317 my $sth = $dbh->prepare(
318 "SELECT * FROM accountlines WHERE accountlines_id=?"
320 $sth->execute( $accountlines_id );
321 my $data = $sth->fetchrow_hashref;
323 # FIXME - Error-checking
324 my $diff = $amount - $data->{'amount'};
325 my $outstanding = $data->{'amountoutstanding'} + $diff;
330 SET amount = '$amount',
331 amountoutstanding = '$outstanding'
332 WHERE accountlines_id = $accountlines_id
334 # FIXME: exceedingly bad form. Use prepare with placholders ("?") in query and execute args.
340 # lost ==1 Lost, lost==2 longoverdue, lost==3 lost and paid for
341 # FIXME: itemlost should be set to 3 after payment is made, should be a warning to the interface that
342 # a charge has been added
343 # FIXME : if no replacement price, borrower just doesn't get charged?
344 my $dbh = C4::Context->dbh();
345 my ($borrowernumber, $itemnumber, $amount, $description) = @_;
347 # first make sure the borrower hasn't already been charged for this item
348 my $sth1=$dbh->prepare("SELECT * from accountlines
349 WHERE borrowernumber=? AND itemnumber=? and accounttype='L'");
350 $sth1->execute($borrowernumber,$itemnumber);
351 my $existing_charge_hashref=$sth1->fetchrow_hashref();
354 unless ($existing_charge_hashref) {
356 $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
357 # This item is on issue ... add replacement cost to the borrower's record and mark it returned
358 # Note that we add this to the account even if there's no replacement price, allowing some other
359 # process (or person) to update it, since we don't handle any defaults for replacement prices.
360 my $accountno = getnextacctno($borrowernumber);
361 my $sth2=$dbh->prepare("INSERT INTO accountlines
362 (borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding,itemnumber,manager_id)
363 VALUES (?,?,now(),?,?,'L',?,?,?)");
364 $sth2->execute($borrowernumber,$accountno,$amount,
365 $description,$amount,$itemnumber,$manager_id);
368 if ( C4::Context->preference("FinesLog") ) {
369 logaction("FINES", 'CREATE', $borrowernumber, Dumper({
370 action => 'create_fee',
371 borrowernumber => $borrowernumber,
372 accountno => $accountno,
374 amountoutstanding => $amount,
375 description => $description,
377 itemnumber => $itemnumber,
378 manager_id => $manager_id,
387 &manualinvoice($borrowernumber, $itemnumber, $description, $type,
390 C<$borrowernumber> is the patron's borrower number.
391 C<$description> is a description of the transaction.
392 C<$type> may be one of C<CS>, C<CB>, C<CW>, C<CF>, C<CL>, C<N>, C<L>,
394 C<$itemnumber> is the item involved, if pertinent; otherwise, it
395 should be the empty string.
400 # FIXME: In Koha 3.0 , the only account adjustment 'types' passed to this function
403 # 'FOR' = FORGIVEN (Formerly 'F', but 'F' is taken to mean 'FINE' elsewhere)
406 # 'A' = Account Management fee
412 my ( $borrowernumber, $itemnum, $desc, $type, $amount, $note ) = @_;
414 $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
415 my $dbh = C4::Context->dbh;
418 my $accountno = getnextacctno($borrowernumber);
419 my $amountleft = $amount;
427 # my $amount2 = $amount * -1; # FIXME - $amount2 = -$amount
429 # fixcredit( $borrowernumber, $amount2, $itemnum, $type, $user );
431 if ( $type eq 'N' ) {
432 $desc .= " New Card";
434 if ( $type eq 'F' ) {
437 if ( $type eq 'A' ) {
438 $desc .= " Account Management fee";
440 if ( $type eq 'M' ) {
444 if ( $type eq 'L' && $desc eq '' ) {
446 $desc = " Lost Item";
448 # if ( $type eq 'REF' ) {
449 # $desc .= " Cash Refund";
450 # $amountleft = refund( '', $borrowernumber, $amount );
452 if ( ( $type eq 'L' )
456 or ( $type eq 'M' ) )
462 $desc .= ' ' . $itemnum;
463 my $sth = $dbh->prepare(
464 'INSERT INTO accountlines
465 (borrowernumber, accountno, date, amount, description, accounttype, amountoutstanding, itemnumber,notify_id, note, manager_id)
466 VALUES (?, ?, now(), ?,?, ?,?,?,?,?,?)');
467 $sth->execute($borrowernumber, $accountno, $amount, $desc, $type, $amountleft, $itemnum,$notifyid, $note, $manager_id) || return $sth->errstr;
469 my $sth=$dbh->prepare("INSERT INTO accountlines
470 (borrowernumber, accountno, date, amount, description, accounttype, amountoutstanding,notify_id, note, manager_id)
471 VALUES (?, ?, now(), ?, ?, ?, ?,?,?,?)"
473 $sth->execute( $borrowernumber, $accountno, $amount, $desc, $type,
474 $amountleft, $notifyid, $note, $manager_id );
477 if ( C4::Context->preference("FinesLog") ) {
478 logaction("FINES", 'CREATE',$borrowernumber,Dumper({
479 action => 'create_fee',
480 borrowernumber => $borrowernumber,
481 accountno => $accountno,
483 description => $desc,
484 accounttype => $type,
485 amountoutstanding => $amountleft,
486 notify_id => $notifyid,
488 itemnumber => $itemnum,
489 manager_id => $manager_id,
496 =head2 fixcredit #### DEPRECATED
498 $amountleft = &fixcredit($borrowernumber, $data, $barcode, $type, $user);
500 This function is only used internally, not exported.
504 # This function is deprecated in 3.0
508 #here we update both the accountoffsets and the account lines
509 my ( $borrowernumber, $data, $barcode, $type, $user ) = @_;
510 my $dbh = C4::Context->dbh;
513 my $amountleft = $data;
514 if ( $barcode ne '' ) {
515 my $item = GetBiblioFromItemNumber( '', $barcode );
516 my $nextaccntno = getnextacctno($borrowernumber);
517 my $query = "SELECT * FROM accountlines WHERE (borrowernumber=?
518 AND itemnumber=? AND amountoutstanding > 0)";
519 if ( $type eq 'CL' ) {
520 $query .= " AND (accounttype = 'L' OR accounttype = 'Rep')";
522 elsif ( $type eq 'CF' ) {
523 $query .= " AND (accounttype = 'F' OR accounttype = 'FU' OR
524 accounttype='Res' OR accounttype='Rent')";
526 elsif ( $type eq 'CB' ) {
527 $query .= " and accounttype='A'";
531 my $sth = $dbh->prepare($query);
532 $sth->execute( $borrowernumber, $item->{'itemnumber'} );
533 $accdata = $sth->fetchrow_hashref;
535 if ( $accdata->{'amountoutstanding'} < $amountleft ) {
537 $amountleft -= $accdata->{'amountoutstanding'};
540 $newamtos = $accdata->{'amountoutstanding'} - $amountleft;
543 my $thisacct = $accdata->{accountlines_id};
544 my $usth = $dbh->prepare(
545 "UPDATE accountlines SET amountoutstanding= ?
546 WHERE (accountlines_id = ?)"
548 $usth->execute( $newamtos, $thisacct );
550 $usth = $dbh->prepare(
551 "INSERT INTO accountoffsets
552 (borrowernumber, accountno, offsetaccount, offsetamount)
555 $usth->execute( $borrowernumber, $accdata->{'accountno'},
556 $nextaccntno, $newamtos );
561 my $nextaccntno = getnextacctno($borrowernumber);
563 # get lines with outstanding amounts to offset
564 my $sth = $dbh->prepare(
565 "SELECT * FROM accountlines
566 WHERE (borrowernumber = ?) AND (amountoutstanding >0)
569 $sth->execute($borrowernumber);
572 # offset transactions
573 while ( ( $accdata = $sth->fetchrow_hashref ) and ( $amountleft > 0 ) ) {
574 if ( $accdata->{'amountoutstanding'} < $amountleft ) {
576 $amountleft -= $accdata->{'amountoutstanding'};
579 $newamtos = $accdata->{'amountoutstanding'} - $amountleft;
582 my $thisacct = $accdata->{accountlines_id};
583 my $usth = $dbh->prepare(
584 "UPDATE accountlines SET amountoutstanding= ?
585 WHERE (accountlines_id = ?)"
587 $usth->execute( $newamtos, $thisacct );
589 $usth = $dbh->prepare(
590 "INSERT INTO accountoffsets
591 (borrowernumber, accountno, offsetaccount, offsetamount)
594 $usth->execute( $borrowernumber, $accdata->{'accountno'},
595 $nextaccntno, $newamtos );
599 $type = "Credit " . $type;
600 UpdateStats( $user, $type, $data, $user, '', '', $borrowernumber );
602 return ($amountleft);
608 #FIXME : DEPRECATED SUB
609 This subroutine tracks payments and/or credits against fines/charges
610 using the accountoffsets table, which is not used consistently in
611 Koha's fines management, and so is not used in 3.0
617 #here we update both the accountoffsets and the account lines
618 my ( $borrowernumber, $data ) = @_;
619 my $dbh = C4::Context->dbh;
622 my $amountleft = $data * -1;
625 my $nextaccntno = getnextacctno($borrowernumber);
627 # get lines with outstanding amounts to offset
628 my $sth = $dbh->prepare(
629 "SELECT * FROM accountlines
630 WHERE (borrowernumber = ?) AND (amountoutstanding<0)
633 $sth->execute($borrowernumber);
636 # offset transactions
637 while ( ( $accdata = $sth->fetchrow_hashref ) and ( $amountleft < 0 ) ) {
638 if ( $accdata->{'amountoutstanding'} > $amountleft ) {
640 $amountleft -= $accdata->{'amountoutstanding'};
643 $newamtos = $accdata->{'amountoutstanding'} - $amountleft;
648 my $thisacct = $accdata->{accountlines_id};
649 my $usth = $dbh->prepare(
650 "UPDATE accountlines SET amountoutstanding= ?
651 WHERE (accountlines_id = ?)"
653 $usth->execute( $newamtos, $thisacct );
655 $usth = $dbh->prepare(
656 "INSERT INTO accountoffsets
657 (borrowernumber, accountno, offsetaccount, offsetamount)
660 $usth->execute( $borrowernumber, $accdata->{'accountno'},
661 $nextaccntno, $newamtos );
665 return ($amountleft);
669 my ( $borrowerno, $timestamp, $accountno ) = @_;
670 my $dbh = C4::Context->dbh;
671 my $timestamp2 = $timestamp - 1;
673 my $sth = $dbh->prepare(
674 "SELECT * FROM accountlines WHERE borrowernumber=? AND accountno = ?"
676 $sth->execute( $borrowerno, $accountno );
679 while ( my $data = $sth->fetchrow_hashref ) {
686 my ( $accountlines_id, $note ) = @_;
687 my $dbh = C4::Context->dbh;
688 my $sth = $dbh->prepare('UPDATE accountlines SET note = ? WHERE accountlines_id = ?');
689 $sth->execute( $note, $accountlines_id );
693 my ( $date, $date2 ) = @_;
694 my $dbh = C4::Context->dbh;
695 my $sth = $dbh->prepare(
696 "SELECT * FROM accountlines,borrowers
697 WHERE amount < 0 AND accounttype <> 'Pay' AND accountlines.borrowernumber = borrowers.borrowernumber
698 AND timestamp >=TIMESTAMP(?) AND timestamp < TIMESTAMP(?)"
701 $sth->execute( $date, $date2 );
703 while ( my $data = $sth->fetchrow_hashref ) {
704 $data->{'date'} = $data->{'timestamp'};
712 my ( $date, $date2 ) = @_;
713 my $dbh = C4::Context->dbh;
715 my $sth = $dbh->prepare(
716 "SELECT *,timestamp AS datetime
717 FROM accountlines,borrowers
718 WHERE (accounttype = 'REF'
719 AND accountlines.borrowernumber = borrowers.borrowernumber
720 AND date >=? AND date <?)"
723 $sth->execute( $date, $date2 );
726 while ( my $data = $sth->fetchrow_hashref ) {
734 my ( $accountlines_id ) = @_;
735 my $dbh = C4::Context->dbh;
737 my $sth = $dbh->prepare('SELECT * FROM accountlines WHERE accountlines_id = ?');
738 $sth->execute( $accountlines_id );
739 my $row = $sth->fetchrow_hashref();
740 my $amount_outstanding = $row->{'amountoutstanding'};
742 if ( $amount_outstanding <= 0 ) {
743 $sth = $dbh->prepare('UPDATE accountlines SET amountoutstanding = amount * -1, description = CONCAT( description, " Reversed -" ) WHERE accountlines_id = ?');
744 $sth->execute( $accountlines_id );
746 $sth = $dbh->prepare('UPDATE accountlines SET amountoutstanding = 0, description = CONCAT( description, " Reversed -" ) WHERE accountlines_id = ?');
747 $sth->execute( $accountlines_id );
750 if ( C4::Context->preference("FinesLog") ) {
752 $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
754 if ( $amount_outstanding <= 0 ) {
755 $row->{'amountoutstanding'} *= -1;
757 $row->{'amountoutstanding'} = '0';
759 $row->{'description'} .= ' Reversed -';
760 logaction("FINES", 'MODIFY', $row->{'borrowernumber'}, Dumper({
761 action => 'reverse_fee_payment',
762 borrowernumber => $row->{'borrowernumber'},
763 old_amountoutstanding => $row->{'amountoutstanding'},
764 new_amountoutstanding => 0 - $amount_outstanding,,
765 accountlines_id => $row->{'accountlines_id'},
766 accountno => $row->{'accountno'},
767 manager_id => $manager_id,
774 =head2 recordpayment_selectaccts
776 recordpayment_selectaccts($borrowernumber, $payment,$accts);
778 Record payment by a patron. C<$borrowernumber> is the patron's
779 borrower number. C<$payment> is a floating-point number, giving the
780 amount that was paid. C<$accts> is an array ref to a list of
781 accountnos which the payment can be recorded against
783 Amounts owed are paid off oldest first. That is, if the patron has a
784 $1 fine from Feb. 1, another $1 fine from Mar. 1, and makes a payment
785 of $1.50, then the oldest fine will be paid off in full, and $0.50
786 will be credited to the next one.
790 sub recordpayment_selectaccts {
791 my ( $borrowernumber, $amount, $accts ) = @_;
793 my $dbh = C4::Context->dbh;
796 my $branch = C4::Context->userenv->{branch};
797 my $amountleft = $amount;
799 $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
800 my $sql = 'SELECT * FROM accountlines WHERE (borrowernumber = ?) ' .
801 'AND (amountoutstanding<>0) ';
803 $sql .= ' AND accountno IN ( ' . join ',', @{$accts};
806 $sql .= ' ORDER BY date';
808 my $nextaccntno = getnextacctno($borrowernumber);
810 # get lines with outstanding amounts to offset
811 my $rows = $dbh->selectall_arrayref($sql, { Slice => {} }, $borrowernumber);
813 # offset transactions
814 my $sth = $dbh->prepare('UPDATE accountlines SET amountoutstanding= ? ' .
815 'WHERE accountlines_id=?');
818 for my $accdata ( @{$rows} ) {
819 if ($amountleft == 0) {
822 if ( $accdata->{amountoutstanding} < $amountleft ) {
824 $amountleft -= $accdata->{amountoutstanding};
827 $newamtos = $accdata->{amountoutstanding} - $amountleft;
830 my $thisacct = $accdata->{accountlines_id};
831 $sth->execute( $newamtos, $thisacct );
833 if ( C4::Context->preference("FinesLog") ) {
834 logaction("FINES", 'MODIFY', $borrowernumber, Dumper({
835 action => 'fee_payment',
836 borrowernumber => $borrowernumber,
837 old_amountoutstanding => $accdata->{'amountoutstanding'},
838 new_amountoutstanding => $newamtos,
839 amount_paid => $accdata->{'amountoutstanding'} - $newamtos,
840 accountlines_id => $accdata->{'accountlines_id'},
841 accountno => $accdata->{'accountno'},
842 manager_id => $manager_id,
844 push( @ids, $accdata->{'accountlines_id'} );
850 $sql = 'INSERT INTO accountlines ' .
851 '(borrowernumber, accountno,date,amount,description,accounttype,amountoutstanding,manager_id) ' .
852 q|VALUES (?,?,now(),?,'Payment,thanks','Pay',?,?)|;
853 $dbh->do($sql,{},$borrowernumber, $nextaccntno, 0 - $amount, 0 - $amountleft, $manager_id );
854 UpdateStats( $branch, 'payment', $amount, '', '', '', $borrowernumber, $nextaccntno );
856 if ( C4::Context->preference("FinesLog") ) {
857 logaction("FINES", 'CREATE',$borrowernumber,Dumper({
858 action => 'create_payment',
859 borrowernumber => $borrowernumber,
860 accountno => $nextaccntno,
861 amount => 0 - $amount,
862 amountoutstanding => 0 - $amountleft,
863 accounttype => 'Pay',
864 accountlines_paid => \@ids,
865 manager_id => $manager_id,
872 # makepayment needs to be fixed to handle partials till then this separate subroutine
874 sub makepartialpayment {
875 my ( $accountlines_id, $borrowernumber, $accountno, $amount, $user, $branch ) = @_;
877 $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
878 if (!$amount || $amount < 0) {
881 my $dbh = C4::Context->dbh;
883 my $nextaccntno = getnextacctno($borrowernumber);
886 my $data = $dbh->selectrow_hashref(
887 'SELECT * FROM accountlines WHERE accountlines_id=?',undef,$accountlines_id);
888 my $new_outstanding = $data->{amountoutstanding} - $amount;
890 my $update = 'UPDATE accountlines SET amountoutstanding = ? WHERE accountlines_id = ? ';
891 $dbh->do( $update, undef, $new_outstanding, $accountlines_id);
893 if ( C4::Context->preference("FinesLog") ) {
894 logaction("FINES", 'MODIFY', $borrowernumber, Dumper({
895 action => 'fee_payment',
896 borrowernumber => $borrowernumber,
897 old_amountoutstanding => $data->{'amountoutstanding'},
898 new_amountoutstanding => $new_outstanding,
899 amount_paid => $data->{'amountoutstanding'} - $new_outstanding,
900 accountlines_id => $data->{'accountlines_id'},
901 accountno => $data->{'accountno'},
902 manager_id => $manager_id,
907 my $insert = 'INSERT INTO accountlines (borrowernumber, accountno, date, amount, '
908 . 'description, accounttype, amountoutstanding, itemnumber, manager_id) '
909 . ' VALUES (?, ?, now(), ?, ?, ?, 0, ?, ?)';
911 $dbh->do( $insert, undef, $borrowernumber, $nextaccntno, 0 - $amount,
912 "Payment, thanks - $user", 'Pay', $data->{'itemnumber'}, $manager_id);
914 UpdateStats( $user, 'payment', $amount, '', '', '', $borrowernumber, $accountno );
916 if ( C4::Context->preference("FinesLog") ) {
917 logaction("FINES", 'CREATE',$borrowernumber,Dumper({
918 action => 'create_payment',
919 borrowernumber => $user,
920 accountno => $nextaccntno,
921 amount => 0 - $amount,
922 accounttype => 'Pay',
923 itemnumber => $data->{'itemnumber'},
924 accountlines_paid => [ $data->{'accountlines_id'} ],
925 manager_id => $manager_id,
934 WriteOff( $borrowernumber, $accountline_id, $itemnum, $accounttype, $amount, $branch );
936 Write off a fine for a patron.
937 C<$borrowernumber> is the patron's borrower number.
938 C<$accountline_id> is the accountline_id of the fee to write off.
939 C<$itemnum> is the itemnumber of of item whose fine is being written off.
940 C<$accounttype> is the account type of the fine being written off.
941 C<$amount> is a floating-point number, giving the amount that is being written off.
942 C<$branch> is the branchcode of the library where the writeoff occurred.
947 my ( $borrowernumber, $accountlines_id, $itemnum, $accounttype, $amount, $branch ) = @_;
948 $branch ||= C4::Context->userenv->{branch};
950 $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
952 # if no item is attached to fine, make sure to store it as a NULL
956 my $dbh = C4::Context->dbh();
959 UPDATE accountlines SET amountoutstanding = 0
960 WHERE accountlines_id = ? AND borrowernumber = ?
962 $sth = $dbh->prepare( $query );
963 $sth->execute( $accountlines_id, $borrowernumber );
965 if ( C4::Context->preference("FinesLog") ) {
966 logaction("FINES", 'MODIFY', $borrowernumber, Dumper({
967 action => 'fee_writeoff',
968 borrowernumber => $borrowernumber,
969 accountlines_id => $accountlines_id,
970 manager_id => $manager_id,
975 INSERT INTO accountlines
976 ( borrowernumber, accountno, itemnumber, date, amount, description, accounttype, manager_id )
977 VALUES ( ?, ?, ?, NOW(), ?, 'Writeoff', 'W', ? )
979 $sth = $dbh->prepare( $query );
980 my $acct = getnextacctno($borrowernumber);
981 $sth->execute( $borrowernumber, $acct, $itemnum, $amount, $manager_id );
983 if ( C4::Context->preference("FinesLog") ) {
984 logaction("FINES", 'CREATE',$borrowernumber,Dumper({
985 action => 'create_writeoff',
986 borrowernumber => $borrowernumber,
988 amount => 0 - $amount,
990 itemnumber => $itemnum,
991 accountlines_paid => [ $accountlines_id ],
992 manager_id => $manager_id,
996 UpdateStats( $branch, 'writeoff', $amount, q{}, q{}, q{}, $borrowernumber );
1000 END { } # module clean-up code here (global destructor)