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;
50 &recordpayment_selectaccts
57 C4::Accounts - Functions for dealing with Koha accounts
65 The functions in this module deal with the monetary aspect of Koha,
66 including looking up and modifying the amount of money owed by a
73 &recordpayment($borrowernumber, $payment, $sip_paytype);
75 Record payment by a patron. C<$borrowernumber> is the patron's
76 borrower number. C<$payment> is a floating-point number, giving the
77 amount that was paid. C<$sip_paytype> is an optional flag to indicate this
78 payment was made over a SIP2 interface, rather than the staff client. The
79 value passed is the SIP2 payment type value (message 37, characters 21-22)
81 Amounts owed are paid off oldest first. That is, if the patron has a
82 $1 fine from Feb. 1, another $1 fine from Mar. 1, and makes a payment
83 of $1.50, then the oldest fine will be paid off in full, and $0.50
84 will be credited to the next one.
91 #here we update the account lines
92 my ( $borrowernumber, $data, $sip_paytype ) = @_;
93 my $dbh = C4::Context->dbh;
96 my $branch = C4::Context->userenv->{'branch'};
97 my $amountleft = $data;
99 $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
102 my $nextaccntno = getnextacctno($borrowernumber);
104 # get lines with outstanding amounts to offset
105 my $sth = $dbh->prepare(
106 "SELECT * FROM accountlines
107 WHERE (borrowernumber = ?) AND (amountoutstanding<>0)
110 $sth->execute($borrowernumber);
112 # offset transactions
114 while ( ( $accdata = $sth->fetchrow_hashref ) and ( $amountleft > 0 ) ) {
115 if ( $accdata->{'amountoutstanding'} < $amountleft ) {
117 $amountleft -= $accdata->{'amountoutstanding'};
120 $newamtos = $accdata->{'amountoutstanding'} - $amountleft;
123 my $thisacct = $accdata->{accountlines_id};
124 my $usth = $dbh->prepare(
125 "UPDATE accountlines SET amountoutstanding= ?
126 WHERE (accountlines_id = ?)"
128 $usth->execute( $newamtos, $thisacct );
130 if ( C4::Context->preference("FinesLog") ) {
131 $accdata->{'amountoutstanding_new'} = $newamtos;
132 logaction("FINES", 'MODIFY', $borrowernumber, Dumper({
133 action => 'fee_payment',
134 borrowernumber => $accdata->{'borrowernumber'},
135 old_amountoutstanding => $accdata->{'amountoutstanding'},
136 new_amountoutstanding => $newamtos,
137 amount_paid => $accdata->{'amountoutstanding'} - $newamtos,
138 accountlines_id => $accdata->{'accountlines_id'},
139 accountno => $accdata->{'accountno'},
140 manager_id => $manager_id,
142 push( @ids, $accdata->{'accountlines_id'} );
147 my $usth = $dbh->prepare(
148 "INSERT INTO accountlines
149 (borrowernumber, accountno,date,amount,description,accounttype,amountoutstanding,manager_id)
150 VALUES (?,?,now(),?,'Payment,thanks','Pay',?,?)"
153 my $payment_description = "Payment, thanks";
154 $payment_description .= " (via SIP2)" if defined $sip_paytype;
156 $paytype .= "-$sip_paytype" if defined $sip_paytype;
157 $usth->execute( $borrowernumber, $nextaccntno, 0 - $data, $payment_description, $paytype, 0 - $amountleft, $manager_id );
160 UpdateStats( $branch, 'payment', $data, '', '', '', $borrowernumber, $nextaccntno );
162 if ( C4::Context->preference("FinesLog") ) {
163 $accdata->{'amountoutstanding_new'} = $newamtos;
164 logaction("FINES", 'CREATE',$borrowernumber,Dumper({
165 action => 'create_payment',
166 borrowernumber => $borrowernumber,
167 accountno => $nextaccntno,
168 amount => $data * -1,
169 amountoutstanding => $amountleft * -1,
170 accounttype => 'Pay',
171 accountlines_paid => \@ids,
172 manager_id => $manager_id,
180 &makepayment($accountlines_id, $borrowernumber, $acctnumber, $amount, $branchcode);
182 Records the fact that a patron has paid off the entire amount he or
185 C<$borrowernumber> is the patron's borrower number. C<$acctnumber> is
186 the account that was credited. C<$amount> is the amount paid (this is
187 only used to record the payment. It is assumed to be equal to the
188 amount owed). C<$branchcode> is the code of the branch where payment
194 # FIXME - I'm not at all sure about the above, because I don't
195 # understand what the acct* tables in the Koha database are for.
198 #here we update both the accountoffsets and the account lines
199 #updated to check, if they are paying off a lost item, we return the item
200 # from their card, and put a note on the item record
201 my ( $accountlines_id, $borrowernumber, $accountno, $amount, $user, $branch, $payment_note ) = @_;
202 my $dbh = C4::Context->dbh;
204 $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
207 my $nextaccntno = getnextacctno($borrowernumber);
209 my $sth = $dbh->prepare("SELECT * FROM accountlines WHERE accountlines_id=?");
210 $sth->execute( $accountlines_id );
211 my $data = $sth->fetchrow_hashref;
214 if ( $data->{'accounttype'} eq "Pay" ){
218 SET amountoutstanding = 0
219 WHERE accountlines_id = ?
222 $udp->execute($accountlines_id);
227 SET amountoutstanding = 0
228 WHERE accountlines_id = ?
231 $udp->execute($accountlines_id);
234 my $payment = 0 - $amount;
235 $payment_note //= "";
240 INTO accountlines (borrowernumber, accountno, date, amount, itemnumber, description, accounttype, amountoutstanding, manager_id, note)
241 VALUES ( ?, ?, now(), ?, ?, '', 'Pay', 0, ?, ?)"
243 $ins->execute($borrowernumber, $nextaccntno, $payment, $data->{'itemnumber'}, $manager_id, $payment_note);
246 if ( C4::Context->preference("FinesLog") ) {
247 logaction("FINES", 'MODIFY', $borrowernumber, Dumper({
248 action => 'fee_payment',
249 borrowernumber => $borrowernumber,
250 old_amountoutstanding => $data->{'amountoutstanding'},
251 new_amountoutstanding => 0,
252 amount_paid => $data->{'amountoutstanding'},
253 accountlines_id => $data->{'accountlines_id'},
254 accountno => $data->{'accountno'},
255 manager_id => $manager_id,
259 logaction("FINES", 'CREATE',$borrowernumber,Dumper({
260 action => 'create_payment',
261 borrowernumber => $borrowernumber,
262 accountno => $nextaccntno,
264 amountoutstanding => 0,,
265 accounttype => 'Pay',
266 accountlines_paid => [$data->{'accountlines_id'}],
267 manager_id => $manager_id,
272 # FIXME - The second argument to &UpdateStats is supposed to be the
274 # UpdateStats is now being passed $accountno too. MTJ
275 UpdateStats( $user, 'payment', $amount, '', '', '', $borrowernumber,
278 #check to see what accounttype
279 if ( $data->{'accounttype'} eq 'Rep' || $data->{'accounttype'} eq 'L' ) {
280 C4::Circulation::ReturnLostItem( $borrowernumber, $data->{'itemnumber'} );
282 my $sthr = $dbh->prepare("SELECT max(accountlines_id) AS lastinsertid FROM accountlines");
284 my $datalastinsertid = $sthr->fetchrow_hashref;
285 return $datalastinsertid->{'lastinsertid'};
290 $nextacct = &getnextacctno($borrowernumber);
292 Returns the next unused account number for the patron with the given
298 # FIXME - Okay, so what does the above actually _mean_?
300 my ($borrowernumber) = shift or return;
301 my $sth = C4::Context->dbh->prepare(
302 "SELECT accountno+1 FROM accountlines
303 WHERE (borrowernumber = ?)
304 ORDER BY accountno DESC
307 $sth->execute($borrowernumber);
308 return ($sth->fetchrow || 1);
311 =head2 fixaccounts (removed)
313 &fixaccounts($accountlines_id, $borrowernumber, $accountnumber, $amount);
316 # FIXME - I don't understand what this function does.
318 my ( $accountlines_id, $borrowernumber, $accountno, $amount ) = @_;
319 my $dbh = C4::Context->dbh;
320 my $sth = $dbh->prepare(
321 "SELECT * FROM accountlines WHERE accountlines_id=?"
323 $sth->execute( $accountlines_id );
324 my $data = $sth->fetchrow_hashref;
326 # FIXME - Error-checking
327 my $diff = $amount - $data->{'amount'};
328 my $outstanding = $data->{'amountoutstanding'} + $diff;
333 SET amount = '$amount',
334 amountoutstanding = '$outstanding'
335 WHERE accountlines_id = $accountlines_id
337 # FIXME: exceedingly bad form. Use prepare with placholders ("?") in query and execute args.
343 # lost ==1 Lost, lost==2 longoverdue, lost==3 lost and paid for
344 # FIXME: itemlost should be set to 3 after payment is made, should be a warning to the interface that
345 # a charge has been added
346 # FIXME : if no replacement price, borrower just doesn't get charged?
347 my $dbh = C4::Context->dbh();
348 my ($borrowernumber, $itemnumber, $amount, $description) = @_;
350 # first make sure the borrower hasn't already been charged for this item
351 my $sth1=$dbh->prepare("SELECT * from accountlines
352 WHERE borrowernumber=? AND itemnumber=? and accounttype='L'");
353 $sth1->execute($borrowernumber,$itemnumber);
354 my $existing_charge_hashref=$sth1->fetchrow_hashref();
357 unless ($existing_charge_hashref) {
359 $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
360 # This item is on issue ... add replacement cost to the borrower's record and mark it returned
361 # Note that we add this to the account even if there's no replacement price, allowing some other
362 # process (or person) to update it, since we don't handle any defaults for replacement prices.
363 my $accountno = getnextacctno($borrowernumber);
364 my $sth2=$dbh->prepare("INSERT INTO accountlines
365 (borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding,itemnumber,manager_id)
366 VALUES (?,?,now(),?,?,'L',?,?,?)");
367 $sth2->execute($borrowernumber,$accountno,$amount,
368 $description,$amount,$itemnumber,$manager_id);
370 if ( C4::Context->preference("FinesLog") ) {
371 logaction("FINES", 'CREATE', $borrowernumber, Dumper({
372 action => 'create_fee',
373 borrowernumber => $borrowernumber,
374 accountno => $accountno,
376 amountoutstanding => $amount,
377 description => $description,
379 itemnumber => $itemnumber,
380 manager_id => $manager_id,
389 &manualinvoice($borrowernumber, $itemnumber, $description, $type,
392 C<$borrowernumber> is the patron's borrower number.
393 C<$description> is a description of the transaction.
394 C<$type> may be one of C<CS>, C<CB>, C<CW>, C<CF>, C<CL>, C<N>, C<L>,
396 C<$itemnumber> is the item involved, if pertinent; otherwise, it
397 should be the empty string.
402 # FIXME: In Koha 3.0 , the only account adjustment 'types' passed to this function
405 # 'FOR' = FORGIVEN (Formerly 'F', but 'F' is taken to mean 'FINE' elsewhere)
408 # 'A' = Account Management fee
414 my ( $borrowernumber, $itemnum, $desc, $type, $amount, $note ) = @_;
416 $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
417 my $dbh = C4::Context->dbh;
420 my $accountno = getnextacctno($borrowernumber);
421 my $amountleft = $amount;
423 if ( ( $type eq 'L' )
427 or ( $type eq 'M' ) )
433 $desc .= ' ' . $itemnum;
434 my $sth = $dbh->prepare(
435 'INSERT INTO accountlines
436 (borrowernumber, accountno, date, amount, description, accounttype, amountoutstanding, itemnumber,notify_id, note, manager_id)
437 VALUES (?, ?, now(), ?,?, ?,?,?,?,?,?)');
438 $sth->execute($borrowernumber, $accountno, $amount, $desc, $type, $amountleft, $itemnum,$notifyid, $note, $manager_id) || return $sth->errstr;
440 my $sth=$dbh->prepare("INSERT INTO accountlines
441 (borrowernumber, accountno, date, amount, description, accounttype, amountoutstanding,notify_id, note, manager_id)
442 VALUES (?, ?, now(), ?, ?, ?, ?,?,?,?)"
444 $sth->execute( $borrowernumber, $accountno, $amount, $desc, $type,
445 $amountleft, $notifyid, $note, $manager_id );
448 if ( C4::Context->preference("FinesLog") ) {
449 logaction("FINES", 'CREATE',$borrowernumber,Dumper({
450 action => 'create_fee',
451 borrowernumber => $borrowernumber,
452 accountno => $accountno,
454 description => $desc,
455 accounttype => $type,
456 amountoutstanding => $amountleft,
457 notify_id => $notifyid,
459 itemnumber => $itemnum,
460 manager_id => $manager_id,
468 my ( $borrowerno, $timestamp, $accountno ) = @_;
469 my $dbh = C4::Context->dbh;
470 my $timestamp2 = $timestamp - 1;
472 my $sth = $dbh->prepare(
473 "SELECT * FROM accountlines WHERE borrowernumber=? AND accountno = ?"
475 $sth->execute( $borrowerno, $accountno );
478 while ( my $data = $sth->fetchrow_hashref ) {
485 my ( $accountlines_id, $note ) = @_;
486 my $dbh = C4::Context->dbh;
487 my $sth = $dbh->prepare('UPDATE accountlines SET note = ? WHERE accountlines_id = ?');
488 $sth->execute( $note, $accountlines_id );
492 my ( $date, $date2 ) = @_;
493 my $dbh = C4::Context->dbh;
494 my $sth = $dbh->prepare(
495 "SELECT * FROM accountlines,borrowers
496 WHERE amount < 0 AND accounttype not like 'Pay%' AND accountlines.borrowernumber = borrowers.borrowernumber
497 AND timestamp >=TIMESTAMP(?) AND timestamp < TIMESTAMP(?)"
500 $sth->execute( $date, $date2 );
502 while ( my $data = $sth->fetchrow_hashref ) {
503 $data->{'date'} = $data->{'timestamp'};
511 my ( $date, $date2 ) = @_;
512 my $dbh = C4::Context->dbh;
514 my $sth = $dbh->prepare(
515 "SELECT *,timestamp AS datetime
516 FROM accountlines,borrowers
517 WHERE (accounttype = 'REF'
518 AND accountlines.borrowernumber = borrowers.borrowernumber
519 AND date >=? AND date <?)"
522 $sth->execute( $date, $date2 );
525 while ( my $data = $sth->fetchrow_hashref ) {
533 my ( $accountlines_id ) = @_;
534 my $dbh = C4::Context->dbh;
536 my $sth = $dbh->prepare('SELECT * FROM accountlines WHERE accountlines_id = ?');
537 $sth->execute( $accountlines_id );
538 my $row = $sth->fetchrow_hashref();
539 my $amount_outstanding = $row->{'amountoutstanding'};
541 if ( $amount_outstanding <= 0 ) {
542 $sth = $dbh->prepare('UPDATE accountlines SET amountoutstanding = amount * -1, description = CONCAT( description, " Reversed -" ) WHERE accountlines_id = ?');
543 $sth->execute( $accountlines_id );
545 $sth = $dbh->prepare('UPDATE accountlines SET amountoutstanding = 0, description = CONCAT( description, " Reversed -" ) WHERE accountlines_id = ?');
546 $sth->execute( $accountlines_id );
549 if ( C4::Context->preference("FinesLog") ) {
551 $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
553 if ( $amount_outstanding <= 0 ) {
554 $row->{'amountoutstanding'} *= -1;
556 $row->{'amountoutstanding'} = '0';
558 $row->{'description'} .= ' Reversed -';
559 logaction("FINES", 'MODIFY', $row->{'borrowernumber'}, Dumper({
560 action => 'reverse_fee_payment',
561 borrowernumber => $row->{'borrowernumber'},
562 old_amountoutstanding => $row->{'amountoutstanding'},
563 new_amountoutstanding => 0 - $amount_outstanding,,
564 accountlines_id => $row->{'accountlines_id'},
565 accountno => $row->{'accountno'},
566 manager_id => $manager_id,
573 =head2 recordpayment_selectaccts
575 recordpayment_selectaccts($borrowernumber, $payment,$accts);
577 Record payment by a patron. C<$borrowernumber> is the patron's
578 borrower number. C<$payment> is a floating-point number, giving the
579 amount that was paid. C<$accts> is an array ref to a list of
580 accountnos which the payment can be recorded against
582 Amounts owed are paid off oldest first. That is, if the patron has a
583 $1 fine from Feb. 1, another $1 fine from Mar. 1, and makes a payment
584 of $1.50, then the oldest fine will be paid off in full, and $0.50
585 will be credited to the next one.
589 sub recordpayment_selectaccts {
590 my ( $borrowernumber, $amount, $accts, $note ) = @_;
592 my $dbh = C4::Context->dbh;
595 my $branch = C4::Context->userenv->{branch};
596 my $amountleft = $amount;
598 $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
599 my $sql = 'SELECT * FROM accountlines WHERE (borrowernumber = ?) ' .
600 'AND (amountoutstanding<>0) ';
602 $sql .= ' AND accountno IN ( ' . join ',', @{$accts};
605 $sql .= ' ORDER BY date';
607 my $nextaccntno = getnextacctno($borrowernumber);
609 # get lines with outstanding amounts to offset
610 my $rows = $dbh->selectall_arrayref($sql, { Slice => {} }, $borrowernumber);
612 # offset transactions
613 my $sth = $dbh->prepare('UPDATE accountlines SET amountoutstanding= ? ' .
614 'WHERE accountlines_id=?');
617 for my $accdata ( @{$rows} ) {
618 if ($amountleft == 0) {
621 if ( $accdata->{amountoutstanding} < $amountleft ) {
623 $amountleft -= $accdata->{amountoutstanding};
626 $newamtos = $accdata->{amountoutstanding} - $amountleft;
629 my $thisacct = $accdata->{accountlines_id};
630 $sth->execute( $newamtos, $thisacct );
632 if ( C4::Context->preference("FinesLog") ) {
633 logaction("FINES", 'MODIFY', $borrowernumber, Dumper({
634 action => 'fee_payment',
635 borrowernumber => $borrowernumber,
636 old_amountoutstanding => $accdata->{'amountoutstanding'},
637 new_amountoutstanding => $newamtos,
638 amount_paid => $accdata->{'amountoutstanding'} - $newamtos,
639 accountlines_id => $accdata->{'accountlines_id'},
640 accountno => $accdata->{'accountno'},
641 manager_id => $manager_id,
643 push( @ids, $accdata->{'accountlines_id'} );
649 $sql = 'INSERT INTO accountlines ' .
650 '(borrowernumber, accountno,date,amount,description,accounttype,amountoutstanding,manager_id,note) ' .
651 q|VALUES (?,?,now(),?,'','Pay',?,?,?)|;
652 $dbh->do($sql,{},$borrowernumber, $nextaccntno, 0 - $amount, 0 - $amountleft, $manager_id, $note );
653 UpdateStats( $branch, 'payment', $amount, '', '', '', $borrowernumber, $nextaccntno );
655 if ( C4::Context->preference("FinesLog") ) {
656 logaction("FINES", 'CREATE',$borrowernumber,Dumper({
657 action => 'create_payment',
658 borrowernumber => $borrowernumber,
659 accountno => $nextaccntno,
660 amount => 0 - $amount,
661 amountoutstanding => 0 - $amountleft,
662 accounttype => 'Pay',
663 accountlines_paid => \@ids,
664 manager_id => $manager_id,
671 # makepayment needs to be fixed to handle partials till then this separate subroutine
673 sub makepartialpayment {
674 my ( $accountlines_id, $borrowernumber, $accountno, $amount, $user, $branch, $payment_note ) = @_;
676 $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
677 if (!$amount || $amount < 0) {
680 $payment_note //= "";
681 my $dbh = C4::Context->dbh;
683 my $nextaccntno = getnextacctno($borrowernumber);
686 my $data = $dbh->selectrow_hashref(
687 'SELECT * FROM accountlines WHERE accountlines_id=?',undef,$accountlines_id);
688 my $new_outstanding = $data->{amountoutstanding} - $amount;
690 my $update = 'UPDATE accountlines SET amountoutstanding = ? WHERE accountlines_id = ? ';
691 $dbh->do( $update, undef, $new_outstanding, $accountlines_id);
693 if ( C4::Context->preference("FinesLog") ) {
694 logaction("FINES", 'MODIFY', $borrowernumber, Dumper({
695 action => 'fee_payment',
696 borrowernumber => $borrowernumber,
697 old_amountoutstanding => $data->{'amountoutstanding'},
698 new_amountoutstanding => $new_outstanding,
699 amount_paid => $data->{'amountoutstanding'} - $new_outstanding,
700 accountlines_id => $data->{'accountlines_id'},
701 accountno => $data->{'accountno'},
702 manager_id => $manager_id,
707 my $insert = 'INSERT INTO accountlines (borrowernumber, accountno, date, amount, '
708 . 'description, accounttype, amountoutstanding, itemnumber, manager_id, note) '
709 . ' VALUES (?, ?, now(), ?, ?, ?, 0, ?, ?, ?)';
711 $dbh->do( $insert, undef, $borrowernumber, $nextaccntno, $amount,
712 "Payment, thanks - $user", 'Pay', $data->{'itemnumber'}, $manager_id, $payment_note);
714 UpdateStats( $user, 'payment', $amount, '', '', '', $borrowernumber, $accountno );
716 if ( C4::Context->preference("FinesLog") ) {
717 logaction("FINES", 'CREATE',$borrowernumber,Dumper({
718 action => 'create_payment',
719 borrowernumber => $user,
720 accountno => $nextaccntno,
721 amount => 0 - $amount,
722 accounttype => 'Pay',
723 itemnumber => $data->{'itemnumber'},
724 accountlines_paid => [ $data->{'accountlines_id'} ],
725 manager_id => $manager_id,
734 WriteOffFee( $borrowernumber, $accountline_id, $itemnum, $accounttype, $amount, $branch, $payment_note );
736 Write off a fine for a patron.
737 C<$borrowernumber> is the patron's borrower number.
738 C<$accountline_id> is the accountline_id of the fee to write off.
739 C<$itemnum> is the itemnumber of of item whose fine is being written off.
740 C<$accounttype> is the account type of the fine being written off.
741 C<$amount> is a floating-point number, giving the amount that is being written off.
742 C<$branch> is the branchcode of the library where the writeoff occurred.
743 C<$payment_note> is the note to attach to this payment
748 my ( $borrowernumber, $accountlines_id, $itemnum, $accounttype, $amount, $branch, $payment_note ) = @_;
749 $payment_note //= "";
750 $branch ||= C4::Context->userenv->{branch};
752 $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
754 # if no item is attached to fine, make sure to store it as a NULL
758 my $dbh = C4::Context->dbh();
761 UPDATE accountlines SET amountoutstanding = 0
762 WHERE accountlines_id = ? AND borrowernumber = ?
764 $sth = $dbh->prepare( $query );
765 $sth->execute( $accountlines_id, $borrowernumber );
767 if ( C4::Context->preference("FinesLog") ) {
768 logaction("FINES", 'MODIFY', $borrowernumber, Dumper({
769 action => 'fee_writeoff',
770 borrowernumber => $borrowernumber,
771 accountlines_id => $accountlines_id,
772 manager_id => $manager_id,
777 INSERT INTO accountlines
778 ( borrowernumber, accountno, itemnumber, date, amount, description, accounttype, manager_id, note )
779 VALUES ( ?, ?, ?, NOW(), ?, 'Writeoff', 'W', ?, ? )
781 $sth = $dbh->prepare( $query );
782 my $acct = getnextacctno($borrowernumber);
783 $sth->execute( $borrowernumber, $acct, $itemnum, $amount, $manager_id, $payment_note );
785 if ( C4::Context->preference("FinesLog") ) {
786 logaction("FINES", 'CREATE',$borrowernumber,Dumper({
787 action => 'create_writeoff',
788 borrowernumber => $borrowernumber,
790 amount => 0 - $amount,
792 itemnumber => $itemnum,
793 accountlines_paid => [ $accountlines_id ],
794 manager_id => $manager_id,
798 UpdateStats( $branch, 'writeoff', $amount, q{}, q{}, q{}, $borrowernumber );
802 END { } # module clean-up code here (global destructor)