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);
28 use vars
qw($VERSION @ISA @EXPORT);
31 # set the version for version checking
32 $VERSION = 3.07.00.049;
48 &recordpayment_selectaccts
55 C4::Accounts - Functions for dealing with Koha accounts
63 The functions in this module deal with the monetary aspect of Koha,
64 including looking up and modifying the amount of money owed by a
71 &recordpayment($borrowernumber, $payment);
73 Record payment by a patron. C<$borrowernumber> is the patron's
74 borrower number. C<$payment> is a floating-point number, giving the
77 Amounts owed are paid off oldest first. That is, if the patron has a
78 $1 fine from Feb. 1, another $1 fine from Mar. 1, and makes a payment
79 of $1.50, then the oldest fine will be paid off in full, and $0.50
80 will be credited to the next one.
87 #here we update the account lines
88 my ( $borrowernumber, $data ) = @_;
89 my $dbh = C4
::Context
->dbh;
92 my $branch = C4
::Context
->userenv->{'branch'};
93 my $amountleft = $data;
95 $manager_id = C4
::Context
->userenv->{'number'} if C4
::Context
->userenv;
98 my $nextaccntno = getnextacctno
($borrowernumber);
100 # get lines with outstanding amounts to offset
101 my $sth = $dbh->prepare(
102 "SELECT * FROM accountlines
103 WHERE (borrowernumber = ?) AND (amountoutstanding<>0)
106 $sth->execute($borrowernumber);
108 # offset transactions
109 while ( ( $accdata = $sth->fetchrow_hashref ) and ( $amountleft > 0 ) ) {
110 if ( $accdata->{'amountoutstanding'} < $amountleft ) {
112 $amountleft -= $accdata->{'amountoutstanding'};
115 $newamtos = $accdata->{'amountoutstanding'} - $amountleft;
118 my $thisacct = $accdata->{accountno
};
119 my $usth = $dbh->prepare(
120 "UPDATE accountlines SET amountoutstanding= ?
121 WHERE (borrowernumber = ?) AND (accountno=?)"
123 $usth->execute( $newamtos, $borrowernumber, $thisacct );
125 # $usth = $dbh->prepare(
126 # "INSERT INTO accountoffsets
127 # (borrowernumber, accountno, offsetaccount, offsetamount)
130 # $usth->execute( $borrowernumber, $accdata->{'accountno'},
131 # $nextaccntno, $newamtos );
136 my $usth = $dbh->prepare(
137 "INSERT INTO accountlines
138 (borrowernumber, accountno,date,amount,description,accounttype,amountoutstanding,manager_id)
139 VALUES (?,?,now(),?,'Payment,thanks','Pay',?,?)"
141 $usth->execute( $borrowernumber, $nextaccntno, 0 - $data, 0 - $amountleft, $manager_id );
143 UpdateStats
( $branch, 'payment', $data, '', '', '', $borrowernumber, $nextaccntno );
149 &makepayment($borrowernumber, $acctnumber, $amount, $branchcode);
151 Records the fact that a patron has paid off the entire amount he or
154 C<$borrowernumber> is the patron's borrower number. C<$acctnumber> is
155 the account that was credited. C<$amount> is the amount paid (this is
156 only used to record the payment. It is assumed to be equal to the
157 amount owed). C<$branchcode> is the code of the branch where payment
163 # FIXME - I'm not at all sure about the above, because I don't
164 # understand what the acct* tables in the Koha database are for.
167 #here we update both the accountoffsets and the account lines
168 #updated to check, if they are paying off a lost item, we return the item
169 # from their card, and put a note on the item record
170 my ( $borrowernumber, $accountno, $amount, $user, $branch ) = @_;
171 my $dbh = C4
::Context
->dbh;
173 $manager_id = C4
::Context
->userenv->{'number'} if C4
::Context
->userenv;
176 my $nextaccntno = getnextacctno
($borrowernumber);
180 "SELECT * FROM accountlines WHERE borrowernumber=? AND accountno=?");
181 $sth->execute( $borrowernumber, $accountno );
182 my $data = $sth->fetchrow_hashref;
185 if($data->{'accounttype'} eq "Pay"){
189 SET amountoutstanding = 0, description = 'Payment,thanks'
190 WHERE borrowernumber = ?
194 $udp->execute($borrowernumber, $accountno );
200 SET amountoutstanding = 0
201 WHERE borrowernumber = ?
205 $udp->execute($borrowernumber, $accountno );
209 my $payment = 0 - $amount;
214 INTO accountlines (borrowernumber, accountno, date, amount, itemnumber, description, accounttype, amountoutstanding, manager_id)
215 VALUES ( ?, ?, now(), ?, ?, 'Payment,thanks', 'Pay', 0, ?)"
217 $ins->execute($borrowernumber, $nextaccntno, $payment, $data->{'itemnumber'}, $manager_id);
221 # FIXME - The second argument to &UpdateStats is supposed to be the
223 # UpdateStats is now being passed $accountno too. MTJ
224 UpdateStats
( $user, 'payment', $amount, '', '', '', $borrowernumber,
226 #from perldoc: for SELECT only #$sth->finish;
228 #check to see what accounttype
229 if ( $data->{'accounttype'} eq 'Rep' || $data->{'accounttype'} eq 'L' ) {
230 C4
::Circulation
::ReturnLostItem
( $borrowernumber, $data->{'itemnumber'} );
236 $nextacct = &getnextacctno($borrowernumber);
238 Returns the next unused account number for the patron with the given
244 # FIXME - Okay, so what does the above actually _mean_?
245 sub getnextacctno
($) {
246 my ($borrowernumber) = shift or return undef;
247 my $sth = C4
::Context
->dbh->prepare(
248 "SELECT accountno+1 FROM accountlines
249 WHERE (borrowernumber = ?)
250 ORDER BY accountno DESC
253 $sth->execute($borrowernumber);
254 return ($sth->fetchrow || 1);
257 =head2 fixaccounts (removed)
259 &fixaccounts($borrowernumber, $accountnumber, $amount);
262 # FIXME - I don't understand what this function does.
264 my ( $borrowernumber, $accountno, $amount ) = @_;
265 my $dbh = C4::Context->dbh;
266 my $sth = $dbh->prepare(
267 "SELECT * FROM accountlines WHERE borrowernumber=?
270 $sth->execute( $borrowernumber, $accountno );
271 my $data = $sth->fetchrow_hashref;
273 # FIXME - Error-checking
274 my $diff = $amount - $data->{'amount'};
275 my $outstanding = $data->{'amountoutstanding'} + $diff;
280 SET amount = '$amount',
281 amountoutstanding = '$outstanding'
282 WHERE borrowernumber = $borrowernumber
283 AND accountno = $accountno
285 # FIXME: exceedingly bad form. Use prepare with placholders ("?") in query and execute args.
291 # lost ==1 Lost, lost==2 longoverdue, lost==3 lost and paid for
292 # FIXME: itemlost should be set to 3 after payment is made, should be a warning to the interface that
293 # a charge has been added
294 # FIXME : if no replacement price, borrower just doesn't get charged?
295 my $dbh = C4
::Context
->dbh();
296 my ($borrowernumber, $itemnumber, $amount, $description) = @_;
298 # first make sure the borrower hasn't already been charged for this item
299 my $sth1=$dbh->prepare("SELECT * from accountlines
300 WHERE borrowernumber=? AND itemnumber=? and accounttype='L'");
301 $sth1->execute($borrowernumber,$itemnumber);
302 my $existing_charge_hashref=$sth1->fetchrow_hashref();
305 unless ($existing_charge_hashref) {
307 $manager_id = C4
::Context
->userenv->{'number'} if C4
::Context
->userenv;
308 # This item is on issue ... add replacement cost to the borrower's record and mark it returned
309 # Note that we add this to the account even if there's no replacement price, allowing some other
310 # process (or person) to update it, since we don't handle any defaults for replacement prices.
311 my $accountno = getnextacctno
($borrowernumber);
312 my $sth2=$dbh->prepare("INSERT INTO accountlines
313 (borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding,itemnumber,manager_id)
314 VALUES (?,?,now(),?,?,'L',?,?,?)");
315 $sth2->execute($borrowernumber,$accountno,$amount,
316 $description,$amount,$itemnumber,$manager_id);
324 &manualinvoice($borrowernumber, $itemnumber, $description, $type,
327 C<$borrowernumber> is the patron's borrower number.
328 C<$description> is a description of the transaction.
329 C<$type> may be one of C<CS>, C<CB>, C<CW>, C<CF>, C<CL>, C<N>, C<L>,
331 C<$itemnumber> is the item involved, if pertinent; otherwise, it
332 should be the empty string.
337 # FIXME: In Koha 3.0 , the only account adjustment 'types' passed to this function
340 # 'FOR' = FORGIVEN (Formerly 'F', but 'F' is taken to mean 'FINE' elsewhere)
343 # 'A' = Account Management fee
349 my ( $borrowernumber, $itemnum, $desc, $type, $amount, $note ) = @_;
351 $manager_id = C4
::Context
->userenv->{'number'} if C4
::Context
->userenv;
352 my $dbh = C4
::Context
->dbh;
355 my $accountno = getnextacctno
($borrowernumber);
356 my $amountleft = $amount;
364 # my $amount2 = $amount * -1; # FIXME - $amount2 = -$amount
366 # fixcredit( $borrowernumber, $amount2, $itemnum, $type, $user );
368 if ( $type eq 'N' ) {
369 $desc .= " New Card";
371 if ( $type eq 'F' ) {
374 if ( $type eq 'A' ) {
375 $desc .= " Account Management fee";
377 if ( $type eq 'M' ) {
381 if ( $type eq 'L' && $desc eq '' ) {
383 $desc = " Lost Item";
385 # if ( $type eq 'REF' ) {
386 # $desc .= " Cash Refund";
387 # $amountleft = refund( '', $borrowernumber, $amount );
389 if ( ( $type eq 'L' )
393 or ( $type eq 'M' ) )
399 $desc .= ' ' . $itemnum;
400 my $sth = $dbh->prepare(
401 'INSERT INTO accountlines
402 (borrowernumber, accountno, date, amount, description, accounttype, amountoutstanding, itemnumber,notify_id, note, manager_id)
403 VALUES (?, ?, now(), ?,?, ?,?,?,?,?,?)');
404 $sth->execute($borrowernumber, $accountno, $amount, $desc, $type, $amountleft, $itemnum,$notifyid, $note, $manager_id) || return $sth->errstr;
406 my $sth=$dbh->prepare("INSERT INTO accountlines
407 (borrowernumber, accountno, date, amount, description, accounttype, amountoutstanding,notify_id, note, manager_id)
408 VALUES (?, ?, now(), ?, ?, ?, ?,?,?,?)"
410 $sth->execute( $borrowernumber, $accountno, $amount, $desc, $type,
411 $amountleft, $notifyid, $note, $manager_id );
416 =head2 fixcredit #### DEPRECATED
418 $amountleft = &fixcredit($borrowernumber, $data, $barcode, $type, $user);
420 This function is only used internally, not exported.
424 # This function is deprecated in 3.0
428 #here we update both the accountoffsets and the account lines
429 my ( $borrowernumber, $data, $barcode, $type, $user ) = @_;
430 my $dbh = C4
::Context
->dbh;
433 my $amountleft = $data;
434 if ( $barcode ne '' ) {
435 my $item = GetBiblioFromItemNumber
( '', $barcode );
436 my $nextaccntno = getnextacctno
($borrowernumber);
437 my $query = "SELECT * FROM accountlines WHERE (borrowernumber=?
438 AND itemnumber=? AND amountoutstanding > 0)";
439 if ( $type eq 'CL' ) {
440 $query .= " AND (accounttype = 'L' OR accounttype = 'Rep')";
442 elsif ( $type eq 'CF' ) {
443 $query .= " AND (accounttype = 'F' OR accounttype = 'FU' OR
444 accounttype='Res' OR accounttype='Rent')";
446 elsif ( $type eq 'CB' ) {
447 $query .= " and accounttype='A'";
451 my $sth = $dbh->prepare($query);
452 $sth->execute( $borrowernumber, $item->{'itemnumber'} );
453 $accdata = $sth->fetchrow_hashref;
455 if ( $accdata->{'amountoutstanding'} < $amountleft ) {
457 $amountleft -= $accdata->{'amountoutstanding'};
460 $newamtos = $accdata->{'amountoutstanding'} - $amountleft;
463 my $thisacct = $accdata->{accountno
};
464 my $usth = $dbh->prepare(
465 "UPDATE accountlines SET amountoutstanding= ?
466 WHERE (borrowernumber = ?) AND (accountno=?)"
468 $usth->execute( $newamtos, $borrowernumber, $thisacct );
470 $usth = $dbh->prepare(
471 "INSERT INTO accountoffsets
472 (borrowernumber, accountno, offsetaccount, offsetamount)
475 $usth->execute( $borrowernumber, $accdata->{'accountno'},
476 $nextaccntno, $newamtos );
481 my $nextaccntno = getnextacctno
($borrowernumber);
483 # get lines with outstanding amounts to offset
484 my $sth = $dbh->prepare(
485 "SELECT * FROM accountlines
486 WHERE (borrowernumber = ?) AND (amountoutstanding >0)
489 $sth->execute($borrowernumber);
492 # offset transactions
493 while ( ( $accdata = $sth->fetchrow_hashref ) and ( $amountleft > 0 ) ) {
494 if ( $accdata->{'amountoutstanding'} < $amountleft ) {
496 $amountleft -= $accdata->{'amountoutstanding'};
499 $newamtos = $accdata->{'amountoutstanding'} - $amountleft;
502 my $thisacct = $accdata->{accountno
};
503 my $usth = $dbh->prepare(
504 "UPDATE accountlines SET amountoutstanding= ?
505 WHERE (borrowernumber = ?) AND (accountno=?)"
507 $usth->execute( $newamtos, $borrowernumber, $thisacct );
509 $usth = $dbh->prepare(
510 "INSERT INTO accountoffsets
511 (borrowernumber, accountno, offsetaccount, offsetamount)
514 $usth->execute( $borrowernumber, $accdata->{'accountno'},
515 $nextaccntno, $newamtos );
519 $type = "Credit " . $type;
520 UpdateStats
( $user, $type, $data, $user, '', '', $borrowernumber );
522 return ($amountleft);
528 #FIXME : DEPRECATED SUB
529 This subroutine tracks payments and/or credits against fines/charges
530 using the accountoffsets table, which is not used consistently in
531 Koha's fines management, and so is not used in 3.0
537 #here we update both the accountoffsets and the account lines
538 my ( $borrowernumber, $data ) = @_;
539 my $dbh = C4
::Context
->dbh;
542 my $amountleft = $data * -1;
545 my $nextaccntno = getnextacctno
($borrowernumber);
547 # get lines with outstanding amounts to offset
548 my $sth = $dbh->prepare(
549 "SELECT * FROM accountlines
550 WHERE (borrowernumber = ?) AND (amountoutstanding<0)
553 $sth->execute($borrowernumber);
556 # offset transactions
557 while ( ( $accdata = $sth->fetchrow_hashref ) and ( $amountleft < 0 ) ) {
558 if ( $accdata->{'amountoutstanding'} > $amountleft ) {
560 $amountleft -= $accdata->{'amountoutstanding'};
563 $newamtos = $accdata->{'amountoutstanding'} - $amountleft;
568 my $thisacct = $accdata->{accountno
};
569 my $usth = $dbh->prepare(
570 "UPDATE accountlines SET amountoutstanding= ?
571 WHERE (borrowernumber = ?) AND (accountno=?)"
573 $usth->execute( $newamtos, $borrowernumber, $thisacct );
575 $usth = $dbh->prepare(
576 "INSERT INTO accountoffsets
577 (borrowernumber, accountno, offsetaccount, offsetamount)
580 $usth->execute( $borrowernumber, $accdata->{'accountno'},
581 $nextaccntno, $newamtos );
585 return ($amountleft);
589 my ( $borrowerno, $timestamp, $accountno ) = @_;
590 my $dbh = C4
::Context
->dbh;
591 my $timestamp2 = $timestamp - 1;
593 my $sth = $dbh->prepare(
594 "SELECT * FROM accountlines WHERE borrowernumber=? AND accountno = ?"
596 $sth->execute( $borrowerno, $accountno );
599 while ( my $data = $sth->fetchrow_hashref ) {
606 my ( $borrowernumber, $accountno, $note ) = @_;
607 my $dbh = C4
::Context
->dbh;
608 my $sth = $dbh->prepare('UPDATE accountlines SET note = ? WHERE borrowernumber = ? AND accountno = ?');
609 $sth->execute( $note, $borrowernumber, $accountno );
613 my ( $date, $date2 ) = @_;
614 my $dbh = C4
::Context
->dbh;
615 my $sth = $dbh->prepare(
616 "SELECT * FROM accountlines,borrowers
617 WHERE amount < 0 AND accounttype <> 'Pay' AND accountlines.borrowernumber = borrowers.borrowernumber
618 AND timestamp >=TIMESTAMP(?) AND timestamp < TIMESTAMP(?)"
621 $sth->execute( $date, $date2 );
623 while ( my $data = $sth->fetchrow_hashref ) {
624 $data->{'date'} = $data->{'timestamp'};
632 my ( $date, $date2 ) = @_;
633 my $dbh = C4
::Context
->dbh;
635 my $sth = $dbh->prepare(
636 "SELECT *,timestamp AS datetime
637 FROM accountlines,borrowers
638 WHERE (accounttype = 'REF'
639 AND accountlines.borrowernumber = borrowers.borrowernumber
640 AND date >=? AND date <?)"
643 $sth->execute( $date, $date2 );
646 while ( my $data = $sth->fetchrow_hashref ) {
654 my ( $borrowernumber, $accountno ) = @_;
655 my $dbh = C4
::Context
->dbh;
657 my $sth = $dbh->prepare('SELECT amountoutstanding FROM accountlines WHERE borrowernumber = ? AND accountno = ?');
658 $sth->execute( $borrowernumber, $accountno );
659 my $row = $sth->fetchrow_hashref();
660 my $amount_outstanding = $row->{'amountoutstanding'};
662 if ( $amount_outstanding <= 0 ) {
663 $sth = $dbh->prepare('UPDATE accountlines SET amountoutstanding = amount * -1, description = CONCAT( description, " Reversed -" ) WHERE borrowernumber = ? AND accountno = ?');
664 $sth->execute( $borrowernumber, $accountno );
666 $sth = $dbh->prepare('UPDATE accountlines SET amountoutstanding = 0, description = CONCAT( description, " Reversed -" ) WHERE borrowernumber = ? AND accountno = ?');
667 $sth->execute( $borrowernumber, $accountno );
671 =head2 recordpayment_selectaccts
673 recordpayment_selectaccts($borrowernumber, $payment,$accts);
675 Record payment by a patron. C<$borrowernumber> is the patron's
676 borrower number. C<$payment> is a floating-point number, giving the
677 amount that was paid. C<$accts> is an array ref to a list of
678 accountnos which the payment can be recorded against
680 Amounts owed are paid off oldest first. That is, if the patron has a
681 $1 fine from Feb. 1, another $1 fine from Mar. 1, and makes a payment
682 of $1.50, then the oldest fine will be paid off in full, and $0.50
683 will be credited to the next one.
687 sub recordpayment_selectaccts
{
688 my ( $borrowernumber, $amount, $accts ) = @_;
690 my $dbh = C4
::Context
->dbh;
693 my $branch = C4
::Context
->userenv->{branch
};
694 my $amountleft = $amount;
696 $manager_id = C4
::Context
->userenv->{'number'} if C4
::Context
->userenv;
697 my $sql = 'SELECT * FROM accountlines WHERE (borrowernumber = ?) ' .
698 'AND (amountoutstanding<>0) ';
700 $sql .= ' AND accountno IN ( ' . join ',', @
{$accts};
703 $sql .= ' ORDER BY date';
705 my $nextaccntno = getnextacctno
($borrowernumber);
707 # get lines with outstanding amounts to offset
708 my $rows = $dbh->selectall_arrayref($sql, { Slice
=> {} }, $borrowernumber);
710 # offset transactions
711 my $sth = $dbh->prepare('UPDATE accountlines SET amountoutstanding= ? ' .
712 'WHERE (borrowernumber = ?) AND (accountno=?)');
713 for my $accdata ( @
{$rows} ) {
714 if ($amountleft == 0) {
717 if ( $accdata->{amountoutstanding
} < $amountleft ) {
719 $amountleft -= $accdata->{amountoutstanding
};
722 $newamtos = $accdata->{amountoutstanding
} - $amountleft;
725 my $thisacct = $accdata->{accountno
};
726 $sth->execute( $newamtos, $borrowernumber, $thisacct );
730 $sql = 'INSERT INTO accountlines ' .
731 '(borrowernumber, accountno,date,amount,description,accounttype,amountoutstanding,manager_id) ' .
732 q
|VALUES
(?
,?
,now
(),?
,'Payment,thanks','Pay',?
,?
)|;
733 $dbh->do($sql,{},$borrowernumber, $nextaccntno, 0 - $amount, 0 - $amountleft, $manager_id );
734 UpdateStats
( $branch, 'payment', $amount, '', '', '', $borrowernumber, $nextaccntno );
738 # makepayment needs to be fixed to handle partials till then this separate subroutine
740 sub makepartialpayment
{
741 my ( $borrowernumber, $accountno, $amount, $user, $branch ) = @_;
743 $manager_id = C4
::Context
->userenv->{'number'} if C4
::Context
->userenv;
744 if (!$amount || $amount < 0) {
747 my $dbh = C4
::Context
->dbh;
749 my $nextaccntno = getnextacctno
($borrowernumber);
752 my $data = $dbh->selectrow_hashref(
753 'SELECT * FROM accountlines WHERE borrowernumber=? AND accountno=?',undef,$borrowernumber,$accountno);
754 my $new_outstanding = $data->{amountoutstanding
} - $amount;
756 my $update = 'UPDATE accountlines SET amountoutstanding = ? WHERE borrowernumber = ? '
757 . ' AND accountno = ?';
758 $dbh->do( $update, undef, $new_outstanding, $borrowernumber, $accountno);
761 my $insert = 'INSERT INTO accountlines (borrowernumber, accountno, date, amount, '
762 . 'description, accounttype, amountoutstanding, itemnumber, manager_id) '
763 . ' VALUES (?, ?, now(), ?, ?, ?, 0, ?, ?)';
765 $dbh->do( $insert, undef, $borrowernumber, $nextaccntno, $amount,
766 "Payment, thanks - $user", 'Pay', $data->{'itemnumber'}, $manager_id);
768 UpdateStats
( $user, 'payment', $amount, '', '', '', $borrowernumber, $accountno );
775 WriteOff( $borrowernumber, $accountnum, $itemnum, $accounttype, $amount, $branch );
777 Write off a fine for a patron.
778 C<$borrowernumber> is the patron's borrower number.
779 C<$accountnum> is the accountnumber of the fee to write off.
780 C<$itemnum> is the itemnumber of of item whose fine is being written off.
781 C<$accounttype> is the account type of the fine being written off.
782 C<$amount> is a floating-point number, giving the amount that is being written off.
783 C<$branch> is the branchcode of the library where the writeoff occurred.
788 my ( $borrowernumber, $accountnum, $itemnum, $accounttype, $amount, $branch ) = @_;
789 $branch ||= C4
::Context
->userenv->{branch
};
791 $manager_id = C4
::Context
->userenv->{'number'} if C4
::Context
->userenv;
793 # if no item is attached to fine, make sure to store it as a NULL
797 my $dbh = C4
::Context
->dbh();
800 UPDATE accountlines SET amountoutstanding = 0
801 WHERE accountno = ? AND borrowernumber = ?
803 $sth = $dbh->prepare( $query );
804 $sth->execute( $accountnum, $borrowernumber );
807 INSERT INTO accountlines
808 ( borrowernumber, accountno, itemnumber, date, amount, description, accounttype, manager_id )
809 VALUES ( ?, ?, ?, NOW(), ?, 'Writeoff', 'W', ? )
811 $sth = $dbh->prepare( $query );
812 my $acct = getnextacctno
($borrowernumber);
813 $sth->execute( $borrowernumber, $acct, $itemnum, $amount, $manager_id );
815 UpdateStats
( $branch, 'writeoff', $amount, q{}, q{}, q{}, $borrowernumber );
819 END { } # module clean-up code here (global destructor)