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, $payment_note ) = @_;
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 my $payment = 0 - $amount;
231 $payment_note //= "";
236 INTO accountlines (borrowernumber, accountno, date, amount, itemnumber, description, accounttype, amountoutstanding, manager_id, note)
237 VALUES ( ?, ?, now(), ?, ?, 'Payment,thanks', 'Pay', 0, ?, ?)"
239 $ins->execute($borrowernumber, $nextaccntno, $payment, $data->{'itemnumber'}, $manager_id, $payment_note);
243 if ( C4
::Context
->preference("FinesLog") ) {
244 logaction
("FINES", 'MODIFY', $borrowernumber, Dumper
({
245 action
=> 'fee_payment',
246 borrowernumber
=> $borrowernumber,
247 old_amountoutstanding
=> $data->{'amountoutstanding'},
248 new_amountoutstanding
=> 0,
249 amount_paid
=> $data->{'amountoutstanding'},
250 accountlines_id
=> $data->{'accountlines_id'},
251 accountno
=> $data->{'accountno'},
252 manager_id
=> $manager_id,
256 logaction
("FINES", 'CREATE',$borrowernumber,Dumper
({
257 action
=> 'create_payment',
258 borrowernumber
=> $borrowernumber,
259 accountno
=> $nextaccntno,
261 amountoutstanding
=> 0,,
262 accounttype
=> 'Pay',
263 accountlines_paid
=> [$data->{'accountlines_id'}],
264 manager_id
=> $manager_id,
269 # FIXME - The second argument to &UpdateStats is supposed to be the
271 # UpdateStats is now being passed $accountno too. MTJ
272 UpdateStats
( $user, 'payment', $amount, '', '', '', $borrowernumber,
275 #check to see what accounttype
276 if ( $data->{'accounttype'} eq 'Rep' || $data->{'accounttype'} eq 'L' ) {
277 C4
::Circulation
::ReturnLostItem
( $borrowernumber, $data->{'itemnumber'} );
279 my $sthr = $dbh->prepare("SELECT max(accountlines_id) AS lastinsertid FROM accountlines");
281 my $datalastinsertid = $sthr->fetchrow_hashref;
283 return $datalastinsertid->{'lastinsertid'};
288 $nextacct = &getnextacctno($borrowernumber);
290 Returns the next unused account number for the patron with the given
296 # FIXME - Okay, so what does the above actually _mean_?
298 my ($borrowernumber) = shift or return;
299 my $sth = C4
::Context
->dbh->prepare(
300 "SELECT accountno+1 FROM accountlines
301 WHERE (borrowernumber = ?)
302 ORDER BY accountno DESC
305 $sth->execute($borrowernumber);
306 return ($sth->fetchrow || 1);
309 =head2 fixaccounts (removed)
311 &fixaccounts($accountlines_id, $borrowernumber, $accountnumber, $amount);
314 # FIXME - I don't understand what this function does.
316 my ( $accountlines_id, $borrowernumber, $accountno, $amount ) = @_;
317 my $dbh = C4::Context->dbh;
318 my $sth = $dbh->prepare(
319 "SELECT * FROM accountlines WHERE accountlines_id=?"
321 $sth->execute( $accountlines_id );
322 my $data = $sth->fetchrow_hashref;
324 # FIXME - Error-checking
325 my $diff = $amount - $data->{'amount'};
326 my $outstanding = $data->{'amountoutstanding'} + $diff;
331 SET amount = '$amount',
332 amountoutstanding = '$outstanding'
333 WHERE accountlines_id = $accountlines_id
335 # FIXME: exceedingly bad form. Use prepare with placholders ("?") in query and execute args.
341 # lost ==1 Lost, lost==2 longoverdue, lost==3 lost and paid for
342 # FIXME: itemlost should be set to 3 after payment is made, should be a warning to the interface that
343 # a charge has been added
344 # FIXME : if no replacement price, borrower just doesn't get charged?
345 my $dbh = C4
::Context
->dbh();
346 my ($borrowernumber, $itemnumber, $amount, $description) = @_;
348 # first make sure the borrower hasn't already been charged for this item
349 my $sth1=$dbh->prepare("SELECT * from accountlines
350 WHERE borrowernumber=? AND itemnumber=? and accounttype='L'");
351 $sth1->execute($borrowernumber,$itemnumber);
352 my $existing_charge_hashref=$sth1->fetchrow_hashref();
355 unless ($existing_charge_hashref) {
357 $manager_id = C4
::Context
->userenv->{'number'} if C4
::Context
->userenv;
358 # This item is on issue ... add replacement cost to the borrower's record and mark it returned
359 # Note that we add this to the account even if there's no replacement price, allowing some other
360 # process (or person) to update it, since we don't handle any defaults for replacement prices.
361 my $accountno = getnextacctno
($borrowernumber);
362 my $sth2=$dbh->prepare("INSERT INTO accountlines
363 (borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding,itemnumber,manager_id)
364 VALUES (?,?,now(),?,?,'L',?,?,?)");
365 $sth2->execute($borrowernumber,$accountno,$amount,
366 $description,$amount,$itemnumber,$manager_id);
369 if ( C4
::Context
->preference("FinesLog") ) {
370 logaction
("FINES", 'CREATE', $borrowernumber, Dumper
({
371 action
=> 'create_fee',
372 borrowernumber
=> $borrowernumber,
373 accountno
=> $accountno,
375 amountoutstanding
=> $amount,
376 description
=> $description,
378 itemnumber
=> $itemnumber,
379 manager_id
=> $manager_id,
388 &manualinvoice($borrowernumber, $itemnumber, $description, $type,
391 C<$borrowernumber> is the patron's borrower number.
392 C<$description> is a description of the transaction.
393 C<$type> may be one of C<CS>, C<CB>, C<CW>, C<CF>, C<CL>, C<N>, C<L>,
395 C<$itemnumber> is the item involved, if pertinent; otherwise, it
396 should be the empty string.
401 # FIXME: In Koha 3.0 , the only account adjustment 'types' passed to this function
404 # 'FOR' = FORGIVEN (Formerly 'F', but 'F' is taken to mean 'FINE' elsewhere)
407 # 'A' = Account Management fee
413 my ( $borrowernumber, $itemnum, $desc, $type, $amount, $note ) = @_;
415 $manager_id = C4
::Context
->userenv->{'number'} if C4
::Context
->userenv;
416 my $dbh = C4
::Context
->dbh;
419 my $accountno = getnextacctno
($borrowernumber);
420 my $amountleft = $amount;
428 # my $amount2 = $amount * -1; # FIXME - $amount2 = -$amount
430 # fixcredit( $borrowernumber, $amount2, $itemnum, $type, $user );
432 if ( $type eq 'N' ) {
433 $desc .= " New Card";
435 if ( $type eq 'F' ) {
438 if ( $type eq 'A' ) {
439 $desc .= " Account Management fee";
441 if ( $type eq 'M' ) {
445 if ( $type eq 'L' && $desc eq '' ) {
447 $desc = " Lost Item";
449 # if ( $type eq 'REF' ) {
450 # $desc .= " Cash Refund";
451 # $amountleft = refund( '', $borrowernumber, $amount );
453 if ( ( $type eq 'L' )
457 or ( $type eq 'M' ) )
463 $desc .= ' ' . $itemnum;
464 my $sth = $dbh->prepare(
465 'INSERT INTO accountlines
466 (borrowernumber, accountno, date, amount, description, accounttype, amountoutstanding, itemnumber,notify_id, note, manager_id)
467 VALUES (?, ?, now(), ?,?, ?,?,?,?,?,?)');
468 $sth->execute($borrowernumber, $accountno, $amount, $desc, $type, $amountleft, $itemnum,$notifyid, $note, $manager_id) || return $sth->errstr;
470 my $sth=$dbh->prepare("INSERT INTO accountlines
471 (borrowernumber, accountno, date, amount, description, accounttype, amountoutstanding,notify_id, note, manager_id)
472 VALUES (?, ?, now(), ?, ?, ?, ?,?,?,?)"
474 $sth->execute( $borrowernumber, $accountno, $amount, $desc, $type,
475 $amountleft, $notifyid, $note, $manager_id );
478 if ( C4
::Context
->preference("FinesLog") ) {
479 logaction
("FINES", 'CREATE',$borrowernumber,Dumper
({
480 action
=> 'create_fee',
481 borrowernumber
=> $borrowernumber,
482 accountno
=> $accountno,
484 description
=> $desc,
485 accounttype
=> $type,
486 amountoutstanding
=> $amountleft,
487 notify_id
=> $notifyid,
489 itemnumber
=> $itemnum,
490 manager_id
=> $manager_id,
497 =head2 fixcredit #### DEPRECATED
499 $amountleft = &fixcredit($borrowernumber, $data, $barcode, $type, $user);
501 This function is only used internally, not exported.
505 # This function is deprecated in 3.0
509 #here we update both the accountoffsets and the account lines
510 my ( $borrowernumber, $data, $barcode, $type, $user ) = @_;
511 my $dbh = C4
::Context
->dbh;
514 my $amountleft = $data;
515 if ( $barcode ne '' ) {
516 my $item = GetBiblioFromItemNumber
( '', $barcode );
517 my $nextaccntno = getnextacctno
($borrowernumber);
518 my $query = "SELECT * FROM accountlines WHERE (borrowernumber=?
519 AND itemnumber=? AND amountoutstanding > 0)";
520 if ( $type eq 'CL' ) {
521 $query .= " AND (accounttype = 'L' OR accounttype = 'Rep')";
523 elsif ( $type eq 'CF' ) {
524 $query .= " AND (accounttype = 'F' OR accounttype = 'FU' OR
525 accounttype='Res' OR accounttype='Rent')";
527 elsif ( $type eq 'CB' ) {
528 $query .= " and accounttype='A'";
532 my $sth = $dbh->prepare($query);
533 $sth->execute( $borrowernumber, $item->{'itemnumber'} );
534 $accdata = $sth->fetchrow_hashref;
536 if ( $accdata->{'amountoutstanding'} < $amountleft ) {
538 $amountleft -= $accdata->{'amountoutstanding'};
541 $newamtos = $accdata->{'amountoutstanding'} - $amountleft;
544 my $thisacct = $accdata->{accountlines_id
};
545 my $usth = $dbh->prepare(
546 "UPDATE accountlines SET amountoutstanding= ?
547 WHERE (accountlines_id = ?)"
549 $usth->execute( $newamtos, $thisacct );
551 $usth = $dbh->prepare(
552 "INSERT INTO accountoffsets
553 (borrowernumber, accountno, offsetaccount, offsetamount)
556 $usth->execute( $borrowernumber, $accdata->{'accountno'},
557 $nextaccntno, $newamtos );
562 my $nextaccntno = getnextacctno
($borrowernumber);
564 # get lines with outstanding amounts to offset
565 my $sth = $dbh->prepare(
566 "SELECT * FROM accountlines
567 WHERE (borrowernumber = ?) AND (amountoutstanding >0)
570 $sth->execute($borrowernumber);
573 # offset transactions
574 while ( ( $accdata = $sth->fetchrow_hashref ) and ( $amountleft > 0 ) ) {
575 if ( $accdata->{'amountoutstanding'} < $amountleft ) {
577 $amountleft -= $accdata->{'amountoutstanding'};
580 $newamtos = $accdata->{'amountoutstanding'} - $amountleft;
583 my $thisacct = $accdata->{accountlines_id
};
584 my $usth = $dbh->prepare(
585 "UPDATE accountlines SET amountoutstanding= ?
586 WHERE (accountlines_id = ?)"
588 $usth->execute( $newamtos, $thisacct );
590 $usth = $dbh->prepare(
591 "INSERT INTO accountoffsets
592 (borrowernumber, accountno, offsetaccount, offsetamount)
595 $usth->execute( $borrowernumber, $accdata->{'accountno'},
596 $nextaccntno, $newamtos );
600 $type = "Credit " . $type;
601 UpdateStats
( $user, $type, $data, $user, '', '', $borrowernumber );
603 return ($amountleft);
609 #FIXME : DEPRECATED SUB
610 This subroutine tracks payments and/or credits against fines/charges
611 using the accountoffsets table, which is not used consistently in
612 Koha's fines management, and so is not used in 3.0
618 #here we update both the accountoffsets and the account lines
619 my ( $borrowernumber, $data ) = @_;
620 my $dbh = C4
::Context
->dbh;
623 my $amountleft = $data * -1;
626 my $nextaccntno = getnextacctno
($borrowernumber);
628 # get lines with outstanding amounts to offset
629 my $sth = $dbh->prepare(
630 "SELECT * FROM accountlines
631 WHERE (borrowernumber = ?) AND (amountoutstanding<0)
634 $sth->execute($borrowernumber);
637 # offset transactions
638 while ( ( $accdata = $sth->fetchrow_hashref ) and ( $amountleft < 0 ) ) {
639 if ( $accdata->{'amountoutstanding'} > $amountleft ) {
641 $amountleft -= $accdata->{'amountoutstanding'};
644 $newamtos = $accdata->{'amountoutstanding'} - $amountleft;
649 my $thisacct = $accdata->{accountlines_id
};
650 my $usth = $dbh->prepare(
651 "UPDATE accountlines SET amountoutstanding= ?
652 WHERE (accountlines_id = ?)"
654 $usth->execute( $newamtos, $thisacct );
656 $usth = $dbh->prepare(
657 "INSERT INTO accountoffsets
658 (borrowernumber, accountno, offsetaccount, offsetamount)
661 $usth->execute( $borrowernumber, $accdata->{'accountno'},
662 $nextaccntno, $newamtos );
666 return ($amountleft);
670 my ( $borrowerno, $timestamp, $accountno ) = @_;
671 my $dbh = C4
::Context
->dbh;
672 my $timestamp2 = $timestamp - 1;
674 my $sth = $dbh->prepare(
675 "SELECT * FROM accountlines WHERE borrowernumber=? AND accountno = ?"
677 $sth->execute( $borrowerno, $accountno );
680 while ( my $data = $sth->fetchrow_hashref ) {
687 my ( $accountlines_id, $note ) = @_;
688 my $dbh = C4
::Context
->dbh;
689 my $sth = $dbh->prepare('UPDATE accountlines SET note = ? WHERE accountlines_id = ?');
690 $sth->execute( $note, $accountlines_id );
694 my ( $date, $date2 ) = @_;
695 my $dbh = C4
::Context
->dbh;
696 my $sth = $dbh->prepare(
697 "SELECT * FROM accountlines,borrowers
698 WHERE amount < 0 AND accounttype <> 'Pay' AND accountlines.borrowernumber = borrowers.borrowernumber
699 AND timestamp >=TIMESTAMP(?) AND timestamp < TIMESTAMP(?)"
702 $sth->execute( $date, $date2 );
704 while ( my $data = $sth->fetchrow_hashref ) {
705 $data->{'date'} = $data->{'timestamp'};
713 my ( $date, $date2 ) = @_;
714 my $dbh = C4
::Context
->dbh;
716 my $sth = $dbh->prepare(
717 "SELECT *,timestamp AS datetime
718 FROM accountlines,borrowers
719 WHERE (accounttype = 'REF'
720 AND accountlines.borrowernumber = borrowers.borrowernumber
721 AND date >=? AND date <?)"
724 $sth->execute( $date, $date2 );
727 while ( my $data = $sth->fetchrow_hashref ) {
735 my ( $accountlines_id ) = @_;
736 my $dbh = C4
::Context
->dbh;
738 my $sth = $dbh->prepare('SELECT * FROM accountlines WHERE accountlines_id = ?');
739 $sth->execute( $accountlines_id );
740 my $row = $sth->fetchrow_hashref();
741 my $amount_outstanding = $row->{'amountoutstanding'};
743 if ( $amount_outstanding <= 0 ) {
744 $sth = $dbh->prepare('UPDATE accountlines SET amountoutstanding = amount * -1, description = CONCAT( description, " Reversed -" ) WHERE accountlines_id = ?');
745 $sth->execute( $accountlines_id );
747 $sth = $dbh->prepare('UPDATE accountlines SET amountoutstanding = 0, description = CONCAT( description, " Reversed -" ) WHERE accountlines_id = ?');
748 $sth->execute( $accountlines_id );
751 if ( C4
::Context
->preference("FinesLog") ) {
753 $manager_id = C4
::Context
->userenv->{'number'} if C4
::Context
->userenv;
755 if ( $amount_outstanding <= 0 ) {
756 $row->{'amountoutstanding'} *= -1;
758 $row->{'amountoutstanding'} = '0';
760 $row->{'description'} .= ' Reversed -';
761 logaction
("FINES", 'MODIFY', $row->{'borrowernumber'}, Dumper
({
762 action
=> 'reverse_fee_payment',
763 borrowernumber
=> $row->{'borrowernumber'},
764 old_amountoutstanding
=> $row->{'amountoutstanding'},
765 new_amountoutstanding
=> 0 - $amount_outstanding,,
766 accountlines_id
=> $row->{'accountlines_id'},
767 accountno
=> $row->{'accountno'},
768 manager_id
=> $manager_id,
775 =head2 recordpayment_selectaccts
777 recordpayment_selectaccts($borrowernumber, $payment,$accts);
779 Record payment by a patron. C<$borrowernumber> is the patron's
780 borrower number. C<$payment> is a floating-point number, giving the
781 amount that was paid. C<$accts> is an array ref to a list of
782 accountnos which the payment can be recorded against
784 Amounts owed are paid off oldest first. That is, if the patron has a
785 $1 fine from Feb. 1, another $1 fine from Mar. 1, and makes a payment
786 of $1.50, then the oldest fine will be paid off in full, and $0.50
787 will be credited to the next one.
791 sub recordpayment_selectaccts
{
792 my ( $borrowernumber, $amount, $accts, $note ) = @_;
794 my $dbh = C4
::Context
->dbh;
797 my $branch = C4
::Context
->userenv->{branch
};
798 my $amountleft = $amount;
800 $manager_id = C4
::Context
->userenv->{'number'} if C4
::Context
->userenv;
801 my $sql = 'SELECT * FROM accountlines WHERE (borrowernumber = ?) ' .
802 'AND (amountoutstanding<>0) ';
804 $sql .= ' AND accountno IN ( ' . join ',', @
{$accts};
807 $sql .= ' ORDER BY date';
809 my $nextaccntno = getnextacctno
($borrowernumber);
811 # get lines with outstanding amounts to offset
812 my $rows = $dbh->selectall_arrayref($sql, { Slice
=> {} }, $borrowernumber);
814 # offset transactions
815 my $sth = $dbh->prepare('UPDATE accountlines SET amountoutstanding= ? ' .
816 'WHERE accountlines_id=?');
819 for my $accdata ( @
{$rows} ) {
820 if ($amountleft == 0) {
823 if ( $accdata->{amountoutstanding
} < $amountleft ) {
825 $amountleft -= $accdata->{amountoutstanding
};
828 $newamtos = $accdata->{amountoutstanding
} - $amountleft;
831 my $thisacct = $accdata->{accountlines_id
};
832 $sth->execute( $newamtos, $thisacct );
834 if ( C4
::Context
->preference("FinesLog") ) {
835 logaction
("FINES", 'MODIFY', $borrowernumber, Dumper
({
836 action
=> 'fee_payment',
837 borrowernumber
=> $borrowernumber,
838 old_amountoutstanding
=> $accdata->{'amountoutstanding'},
839 new_amountoutstanding
=> $newamtos,
840 amount_paid
=> $accdata->{'amountoutstanding'} - $newamtos,
841 accountlines_id
=> $accdata->{'accountlines_id'},
842 accountno
=> $accdata->{'accountno'},
843 manager_id
=> $manager_id,
845 push( @ids, $accdata->{'accountlines_id'} );
851 $sql = 'INSERT INTO accountlines ' .
852 '(borrowernumber, accountno,date,amount,description,accounttype,amountoutstanding,manager_id,note) ' .
853 q
|VALUES
(?
,?
,now
(),?
,'Payment,thanks','Pay',?
,?
,?
)|;
854 $dbh->do($sql,{},$borrowernumber, $nextaccntno, 0 - $amount, 0 - $amountleft, $manager_id, $note );
855 UpdateStats
( $branch, 'payment', $amount, '', '', '', $borrowernumber, $nextaccntno );
857 if ( C4
::Context
->preference("FinesLog") ) {
858 logaction
("FINES", 'CREATE',$borrowernumber,Dumper
({
859 action
=> 'create_payment',
860 borrowernumber
=> $borrowernumber,
861 accountno
=> $nextaccntno,
862 amount
=> 0 - $amount,
863 amountoutstanding
=> 0 - $amountleft,
864 accounttype
=> 'Pay',
865 accountlines_paid
=> \
@ids,
866 manager_id
=> $manager_id,
873 # makepayment needs to be fixed to handle partials till then this separate subroutine
875 sub makepartialpayment
{
876 my ( $accountlines_id, $borrowernumber, $accountno, $amount, $user, $branch, $payment_note ) = @_;
878 $manager_id = C4
::Context
->userenv->{'number'} if C4
::Context
->userenv;
879 if (!$amount || $amount < 0) {
882 $payment_note //= "";
883 my $dbh = C4
::Context
->dbh;
885 my $nextaccntno = getnextacctno
($borrowernumber);
888 my $data = $dbh->selectrow_hashref(
889 'SELECT * FROM accountlines WHERE accountlines_id=?',undef,$accountlines_id);
890 my $new_outstanding = $data->{amountoutstanding
} - $amount;
892 my $update = 'UPDATE accountlines SET amountoutstanding = ? WHERE accountlines_id = ? ';
893 $dbh->do( $update, undef, $new_outstanding, $accountlines_id);
895 if ( C4
::Context
->preference("FinesLog") ) {
896 logaction
("FINES", 'MODIFY', $borrowernumber, Dumper
({
897 action
=> 'fee_payment',
898 borrowernumber
=> $borrowernumber,
899 old_amountoutstanding
=> $data->{'amountoutstanding'},
900 new_amountoutstanding
=> $new_outstanding,
901 amount_paid
=> $data->{'amountoutstanding'} - $new_outstanding,
902 accountlines_id
=> $data->{'accountlines_id'},
903 accountno
=> $data->{'accountno'},
904 manager_id
=> $manager_id,
909 my $insert = 'INSERT INTO accountlines (borrowernumber, accountno, date, amount, '
910 . 'description, accounttype, amountoutstanding, itemnumber, manager_id, note) '
911 . ' VALUES (?, ?, now(), ?, ?, ?, 0, ?, ?, ?)';
913 $dbh->do( $insert, undef, $borrowernumber, $nextaccntno, $amount,
914 "Payment, thanks - $user", 'Pay', $data->{'itemnumber'}, $manager_id, $payment_note);
916 UpdateStats
( $user, 'payment', $amount, '', '', '', $borrowernumber, $accountno );
918 if ( C4
::Context
->preference("FinesLog") ) {
919 logaction
("FINES", 'CREATE',$borrowernumber,Dumper
({
920 action
=> 'create_payment',
921 borrowernumber
=> $user,
922 accountno
=> $nextaccntno,
923 amount
=> 0 - $amount,
924 accounttype
=> 'Pay',
925 itemnumber
=> $data->{'itemnumber'},
926 accountlines_paid
=> [ $data->{'accountlines_id'} ],
927 manager_id
=> $manager_id,
936 WriteOffFee( $borrowernumber, $accountline_id, $itemnum, $accounttype, $amount, $branch, $payment_note );
938 Write off a fine for a patron.
939 C<$borrowernumber> is the patron's borrower number.
940 C<$accountline_id> is the accountline_id of the fee to write off.
941 C<$itemnum> is the itemnumber of of item whose fine is being written off.
942 C<$accounttype> is the account type of the fine being written off.
943 C<$amount> is a floating-point number, giving the amount that is being written off.
944 C<$branch> is the branchcode of the library where the writeoff occurred.
945 C<$payment_note> is the note to attach to this payment
950 my ( $borrowernumber, $accountlines_id, $itemnum, $accounttype, $amount, $branch, $payment_note ) = @_;
951 $payment_note //= "";
952 $branch ||= C4
::Context
->userenv->{branch
};
954 $manager_id = C4
::Context
->userenv->{'number'} if C4
::Context
->userenv;
956 # if no item is attached to fine, make sure to store it as a NULL
960 my $dbh = C4
::Context
->dbh();
963 UPDATE accountlines SET amountoutstanding = 0
964 WHERE accountlines_id = ? AND borrowernumber = ?
966 $sth = $dbh->prepare( $query );
967 $sth->execute( $accountlines_id, $borrowernumber );
969 if ( C4
::Context
->preference("FinesLog") ) {
970 logaction
("FINES", 'MODIFY', $borrowernumber, Dumper
({
971 action
=> 'fee_writeoff',
972 borrowernumber
=> $borrowernumber,
973 accountlines_id
=> $accountlines_id,
974 manager_id
=> $manager_id,
979 INSERT INTO accountlines
980 ( borrowernumber, accountno, itemnumber, date, amount, description, accounttype, manager_id, note )
981 VALUES ( ?, ?, ?, NOW(), ?, 'Writeoff', 'W', ?, ? )
983 $sth = $dbh->prepare( $query );
984 my $acct = getnextacctno
($borrowernumber);
985 $sth->execute( $borrowernumber, $acct, $itemnum, $amount, $manager_id, $payment_note );
987 if ( C4
::Context
->preference("FinesLog") ) {
988 logaction
("FINES", 'CREATE',$borrowernumber,Dumper
({
989 action
=> 'create_writeoff',
990 borrowernumber
=> $borrowernumber,
992 amount
=> 0 - $amount,
994 itemnumber
=> $itemnum,
995 accountlines_paid
=> [ $accountlines_id ],
996 manager_id
=> $manager_id,
1000 UpdateStats
( $branch, 'writeoff', $amount, q{}, q{}, q{}, $borrowernumber );
1004 END { } # module clean-up code here (global destructor)