Bug 7284 follow-up, DBrev number
[koha.git] / C4 / Accounts.pm
blobc3d121d8822bb83ab87fa6e5298ae24428d3ee3c
1 package C4::Accounts;
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
10 # version.
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.
21 use strict;
22 #use warnings; FIXME - Bug 2505
23 use C4::Context;
24 use C4::Stats;
25 use C4::Members;
26 use C4::Circulation qw(ReturnLostItem);
28 use vars qw($VERSION @ISA @EXPORT);
30 BEGIN {
31 # set the version for version checking
32 $VERSION = 3.03;
33 require Exporter;
34 @ISA = qw(Exporter);
35 @EXPORT = qw(
36 &recordpayment &makepayment &manualinvoice
37 &getnextacctno &reconcileaccount &getcharges &ModNote &getcredits
38 &getrefunds &chargelostitem
39 &ReversePayment
40 makepartialpayment
41 recordpayment_selectaccts
45 =head1 NAME
47 C4::Accounts - Functions for dealing with Koha accounts
49 =head1 SYNOPSIS
51 use C4::Accounts;
53 =head1 DESCRIPTION
55 The functions in this module deal with the monetary aspect of Koha,
56 including looking up and modifying the amount of money owed by a
57 patron.
59 =head1 FUNCTIONS
61 =head2 recordpayment
63 &recordpayment($borrowernumber, $payment);
65 Record payment by a patron. C<$borrowernumber> is the patron's
66 borrower number. C<$payment> is a floating-point number, giving the
67 amount that was paid.
69 Amounts owed are paid off oldest first. That is, if the patron has a
70 $1 fine from Feb. 1, another $1 fine from Mar. 1, and makes a payment
71 of $1.50, then the oldest fine will be paid off in full, and $0.50
72 will be credited to the next one.
74 =cut
77 sub recordpayment {
79 #here we update the account lines
80 my ( $borrowernumber, $data ) = @_;
81 my $dbh = C4::Context->dbh;
82 my $newamtos = 0;
83 my $accdata = "";
84 my $branch = C4::Context->userenv->{'branch'};
85 my $amountleft = $data;
87 # begin transaction
88 my $nextaccntno = getnextacctno($borrowernumber);
90 # get lines with outstanding amounts to offset
91 my $sth = $dbh->prepare(
92 "SELECT * FROM accountlines
93 WHERE (borrowernumber = ?) AND (amountoutstanding<>0)
94 ORDER BY date"
96 $sth->execute($borrowernumber);
98 # offset transactions
99 while ( ( $accdata = $sth->fetchrow_hashref ) and ( $amountleft > 0 ) ) {
100 if ( $accdata->{'amountoutstanding'} < $amountleft ) {
101 $newamtos = 0;
102 $amountleft -= $accdata->{'amountoutstanding'};
104 else {
105 $newamtos = $accdata->{'amountoutstanding'} - $amountleft;
106 $amountleft = 0;
108 my $thisacct = $accdata->{accountno};
109 my $usth = $dbh->prepare(
110 "UPDATE accountlines SET amountoutstanding= ?
111 WHERE (borrowernumber = ?) AND (accountno=?)"
113 $usth->execute( $newamtos, $borrowernumber, $thisacct );
114 $usth->finish;
115 # $usth = $dbh->prepare(
116 # "INSERT INTO accountoffsets
117 # (borrowernumber, accountno, offsetaccount, offsetamount)
118 # VALUES (?,?,?,?)"
119 # );
120 # $usth->execute( $borrowernumber, $accdata->{'accountno'},
121 # $nextaccntno, $newamtos );
122 $usth->finish;
125 # create new line
126 my $usth = $dbh->prepare(
127 "INSERT INTO accountlines
128 (borrowernumber, accountno,date,amount,description,accounttype,amountoutstanding)
129 VALUES (?,?,now(),?,'Payment,thanks','Pay',?)"
131 $usth->execute( $borrowernumber, $nextaccntno, 0 - $data, 0 - $amountleft );
132 $usth->finish;
133 UpdateStats( $branch, 'payment', $data, '', '', '', $borrowernumber, $nextaccntno );
134 $sth->finish;
137 =head2 makepayment
139 &makepayment($borrowernumber, $acctnumber, $amount, $branchcode);
141 Records the fact that a patron has paid off the entire amount he or
142 she owes.
144 C<$borrowernumber> is the patron's borrower number. C<$acctnumber> is
145 the account that was credited. C<$amount> is the amount paid (this is
146 only used to record the payment. It is assumed to be equal to the
147 amount owed). C<$branchcode> is the code of the branch where payment
148 was made.
150 =cut
153 # FIXME - I'm not at all sure about the above, because I don't
154 # understand what the acct* tables in the Koha database are for.
155 sub makepayment {
157 #here we update both the accountoffsets and the account lines
158 #updated to check, if they are paying off a lost item, we return the item
159 # from their card, and put a note on the item record
160 my ( $borrowernumber, $accountno, $amount, $user, $branch ) = @_;
161 my $dbh = C4::Context->dbh;
162 my $manager_id = 0;
163 $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
165 # begin transaction
166 my $nextaccntno = getnextacctno($borrowernumber);
167 my $newamtos = 0;
168 my $sth =
169 $dbh->prepare(
170 "SELECT * FROM accountlines WHERE borrowernumber=? AND accountno=?");
171 $sth->execute( $borrowernumber, $accountno );
172 my $data = $sth->fetchrow_hashref;
173 $sth->finish;
175 if($data->{'accounttype'} eq "Pay"){
176 my $udp =
177 $dbh->prepare(
178 "UPDATE accountlines
179 SET amountoutstanding = 0, description = 'Payment,thanks'
180 WHERE borrowernumber = ?
181 AND accountno = ?
184 $udp->execute($borrowernumber, $accountno );
185 $udp->finish;
186 }else{
187 my $udp =
188 $dbh->prepare(
189 "UPDATE accountlines
190 SET amountoutstanding = 0
191 WHERE borrowernumber = ?
192 AND accountno = ?
195 $udp->execute($borrowernumber, $accountno );
196 $udp->finish;
198 # create new line
199 my $payment = 0 - $amount;
201 my $ins =
202 $dbh->prepare(
203 "INSERT
204 INTO accountlines (borrowernumber, accountno, date, amount, itemnumber, description, accounttype, amountoutstanding, manager_id)
205 VALUES ( ?, ?, now(), ?, ?, 'Payment,thanks', 'Pay', 0, ?)"
207 $ins->execute($borrowernumber, $nextaccntno, $payment, $data->{'itemnumber'}, $manager_id);
208 $ins->finish;
211 # FIXME - The second argument to &UpdateStats is supposed to be the
212 # branch code.
213 # UpdateStats is now being passed $accountno too. MTJ
214 UpdateStats( $user, 'payment', $amount, '', '', '', $borrowernumber,
215 $accountno );
216 #from perldoc: for SELECT only #$sth->finish;
218 #check to see what accounttype
219 if ( $data->{'accounttype'} eq 'Rep' || $data->{'accounttype'} eq 'L' ) {
220 C4::Circulation::ReturnLostItem( $borrowernumber, $data->{'itemnumber'} );
224 =head2 getnextacctno
226 $nextacct = &getnextacctno($borrowernumber);
228 Returns the next unused account number for the patron with the given
229 borrower number.
231 =cut
234 # FIXME - Okay, so what does the above actually _mean_?
235 sub getnextacctno ($) {
236 my ($borrowernumber) = shift or return undef;
237 my $sth = C4::Context->dbh->prepare(
238 "SELECT accountno+1 FROM accountlines
239 WHERE (borrowernumber = ?)
240 ORDER BY accountno DESC
241 LIMIT 1"
243 $sth->execute($borrowernumber);
244 return ($sth->fetchrow || 1);
247 =head2 fixaccounts (removed)
249 &fixaccounts($borrowernumber, $accountnumber, $amount);
252 # FIXME - I don't understand what this function does.
253 sub fixaccounts {
254 my ( $borrowernumber, $accountno, $amount ) = @_;
255 my $dbh = C4::Context->dbh;
256 my $sth = $dbh->prepare(
257 "SELECT * FROM accountlines WHERE borrowernumber=?
258 AND accountno=?"
260 $sth->execute( $borrowernumber, $accountno );
261 my $data = $sth->fetchrow_hashref;
263 # FIXME - Error-checking
264 my $diff = $amount - $data->{'amount'};
265 my $outstanding = $data->{'amountoutstanding'} + $diff;
266 $sth->finish;
268 $dbh->do(<<EOT);
269 UPDATE accountlines
270 SET amount = '$amount',
271 amountoutstanding = '$outstanding'
272 WHERE borrowernumber = $borrowernumber
273 AND accountno = $accountno
275 # FIXME: exceedingly bad form. Use prepare with placholders ("?") in query and execute args.
278 =cut
280 sub chargelostitem{
281 # lost ==1 Lost, lost==2 longoverdue, lost==3 lost and paid for
282 # FIXME: itemlost should be set to 3 after payment is made, should be a warning to the interface that
283 # a charge has been added
284 # FIXME : if no replacement price, borrower just doesn't get charged?
285 my $dbh = C4::Context->dbh();
286 my ($borrowernumber, $itemnumber, $amount, $description) = @_;
288 # first make sure the borrower hasn't already been charged for this item
289 my $sth1=$dbh->prepare("SELECT * from accountlines
290 WHERE borrowernumber=? AND itemnumber=? and accounttype='L'");
291 $sth1->execute($borrowernumber,$itemnumber);
292 my $existing_charge_hashref=$sth1->fetchrow_hashref();
294 # OK, they haven't
295 unless ($existing_charge_hashref) {
296 # This item is on issue ... add replacement cost to the borrower's record and mark it returned
297 # Note that we add this to the account even if there's no replacement price, allowing some other
298 # process (or person) to update it, since we don't handle any defaults for replacement prices.
299 my $accountno = getnextacctno($borrowernumber);
300 my $sth2=$dbh->prepare("INSERT INTO accountlines
301 (borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding,itemnumber)
302 VALUES (?,?,now(),?,?,'L',?,?)");
303 $sth2->execute($borrowernumber,$accountno,$amount,
304 $description,$amount,$itemnumber);
305 $sth2->finish;
306 # FIXME: Log this ?
310 =head2 manualinvoice
312 &manualinvoice($borrowernumber, $itemnumber, $description, $type,
313 $amount, $note);
315 C<$borrowernumber> is the patron's borrower number.
316 C<$description> is a description of the transaction.
317 C<$type> may be one of C<CS>, C<CB>, C<CW>, C<CF>, C<CL>, C<N>, C<L>,
318 or C<REF>.
319 C<$itemnumber> is the item involved, if pertinent; otherwise, it
320 should be the empty string.
322 =cut
325 # FIXME: In Koha 3.0 , the only account adjustment 'types' passed to this function
326 # are :
327 # 'C' = CREDIT
328 # 'FOR' = FORGIVEN (Formerly 'F', but 'F' is taken to mean 'FINE' elsewhere)
329 # 'N' = New Card fee
330 # 'F' = Fine
331 # 'A' = Account Management fee
332 # 'M' = Sundry
333 # 'L' = Lost Item
336 sub manualinvoice {
337 my ( $borrowernumber, $itemnum, $desc, $type, $amount, $note ) = @_;
338 my $manager_id = 0;
339 $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
340 my $dbh = C4::Context->dbh;
341 my $notifyid = 0;
342 my $insert;
343 my $accountno = getnextacctno($borrowernumber);
344 my $amountleft = $amount;
346 # if ( $type eq 'CS'
347 # || $type eq 'CB'
348 # || $type eq 'CW'
349 # || $type eq 'CF'
350 # || $type eq 'CL' )
352 # my $amount2 = $amount * -1; # FIXME - $amount2 = -$amount
353 # $amountleft =
354 # fixcredit( $borrowernumber, $amount2, $itemnum, $type, $user );
356 if ( $type eq 'N' ) {
357 $desc .= " New Card";
359 if ( $type eq 'F' ) {
360 $desc .= " Fine";
362 if ( $type eq 'A' ) {
363 $desc .= " Account Management fee";
365 if ( $type eq 'M' ) {
366 $desc .= " Sundry";
369 if ( $type eq 'L' && $desc eq '' ) {
371 $desc = " Lost Item";
373 # if ( $type eq 'REF' ) {
374 # $desc .= " Cash Refund";
375 # $amountleft = refund( '', $borrowernumber, $amount );
377 if ( ( $type eq 'L' )
378 or ( $type eq 'F' )
379 or ( $type eq 'A' )
380 or ( $type eq 'N' )
381 or ( $type eq 'M' ) )
383 $notifyid = 1;
386 if ( $itemnum ) {
387 $desc .= ' ' . $itemnum;
388 my $sth = $dbh->prepare(
389 'INSERT INTO accountlines
390 (borrowernumber, accountno, date, amount, description, accounttype, amountoutstanding, itemnumber,notify_id, note, manager_id)
391 VALUES (?, ?, now(), ?,?, ?,?,?,?,?,?)');
392 $sth->execute($borrowernumber, $accountno, $amount, $desc, $type, $amountleft, $itemnum,$notifyid, $note, $manager_id) || return $sth->errstr;
393 } else {
394 my $sth=$dbh->prepare("INSERT INTO accountlines
395 (borrowernumber, accountno, date, amount, description, accounttype, amountoutstanding,notify_id, note, manager_id)
396 VALUES (?, ?, now(), ?, ?, ?, ?,?,?,?)"
398 $sth->execute( $borrowernumber, $accountno, $amount, $desc, $type,
399 $amountleft, $notifyid, $note, $manager_id );
401 return 0;
404 =head2 fixcredit #### DEPRECATED
406 $amountleft = &fixcredit($borrowernumber, $data, $barcode, $type, $user);
408 This function is only used internally, not exported.
410 =cut
412 # This function is deprecated in 3.0
414 sub fixcredit {
416 #here we update both the accountoffsets and the account lines
417 my ( $borrowernumber, $data, $barcode, $type, $user ) = @_;
418 my $dbh = C4::Context->dbh;
419 my $newamtos = 0;
420 my $accdata = "";
421 my $amountleft = $data;
422 if ( $barcode ne '' ) {
423 my $item = GetBiblioFromItemNumber( '', $barcode );
424 my $nextaccntno = getnextacctno($borrowernumber);
425 my $query = "SELECT * FROM accountlines WHERE (borrowernumber=?
426 AND itemnumber=? AND amountoutstanding > 0)";
427 if ( $type eq 'CL' ) {
428 $query .= " AND (accounttype = 'L' OR accounttype = 'Rep')";
430 elsif ( $type eq 'CF' ) {
431 $query .= " AND (accounttype = 'F' OR accounttype = 'FU' OR
432 accounttype='Res' OR accounttype='Rent')";
434 elsif ( $type eq 'CB' ) {
435 $query .= " and accounttype='A'";
438 # print $query;
439 my $sth = $dbh->prepare($query);
440 $sth->execute( $borrowernumber, $item->{'itemnumber'} );
441 $accdata = $sth->fetchrow_hashref;
442 $sth->finish;
443 if ( $accdata->{'amountoutstanding'} < $amountleft ) {
444 $newamtos = 0;
445 $amountleft -= $accdata->{'amountoutstanding'};
447 else {
448 $newamtos = $accdata->{'amountoutstanding'} - $amountleft;
449 $amountleft = 0;
451 my $thisacct = $accdata->{accountno};
452 my $usth = $dbh->prepare(
453 "UPDATE accountlines SET amountoutstanding= ?
454 WHERE (borrowernumber = ?) AND (accountno=?)"
456 $usth->execute( $newamtos, $borrowernumber, $thisacct );
457 $usth->finish;
458 $usth = $dbh->prepare(
459 "INSERT INTO accountoffsets
460 (borrowernumber, accountno, offsetaccount, offsetamount)
461 VALUES (?,?,?,?)"
463 $usth->execute( $borrowernumber, $accdata->{'accountno'},
464 $nextaccntno, $newamtos );
465 $usth->finish;
468 # begin transaction
469 my $nextaccntno = getnextacctno($borrowernumber);
471 # get lines with outstanding amounts to offset
472 my $sth = $dbh->prepare(
473 "SELECT * FROM accountlines
474 WHERE (borrowernumber = ?) AND (amountoutstanding >0)
475 ORDER BY date"
477 $sth->execute($borrowernumber);
479 # print $query;
480 # offset transactions
481 while ( ( $accdata = $sth->fetchrow_hashref ) and ( $amountleft > 0 ) ) {
482 if ( $accdata->{'amountoutstanding'} < $amountleft ) {
483 $newamtos = 0;
484 $amountleft -= $accdata->{'amountoutstanding'};
486 else {
487 $newamtos = $accdata->{'amountoutstanding'} - $amountleft;
488 $amountleft = 0;
490 my $thisacct = $accdata->{accountno};
491 my $usth = $dbh->prepare(
492 "UPDATE accountlines SET amountoutstanding= ?
493 WHERE (borrowernumber = ?) AND (accountno=?)"
495 $usth->execute( $newamtos, $borrowernumber, $thisacct );
496 $usth->finish;
497 $usth = $dbh->prepare(
498 "INSERT INTO accountoffsets
499 (borrowernumber, accountno, offsetaccount, offsetamount)
500 VALUE (?,?,?,?)"
502 $usth->execute( $borrowernumber, $accdata->{'accountno'},
503 $nextaccntno, $newamtos );
504 $usth->finish;
506 $sth->finish;
507 $type = "Credit " . $type;
508 UpdateStats( $user, $type, $data, $user, '', '', $borrowernumber );
509 $amountleft *= -1;
510 return ($amountleft);
514 =head2 refund
516 #FIXME : DEPRECATED SUB
517 This subroutine tracks payments and/or credits against fines/charges
518 using the accountoffsets table, which is not used consistently in
519 Koha's fines management, and so is not used in 3.0
521 =cut
523 sub refund {
525 #here we update both the accountoffsets and the account lines
526 my ( $borrowernumber, $data ) = @_;
527 my $dbh = C4::Context->dbh;
528 my $newamtos = 0;
529 my $accdata = "";
530 my $amountleft = $data * -1;
532 # begin transaction
533 my $nextaccntno = getnextacctno($borrowernumber);
535 # get lines with outstanding amounts to offset
536 my $sth = $dbh->prepare(
537 "SELECT * FROM accountlines
538 WHERE (borrowernumber = ?) AND (amountoutstanding<0)
539 ORDER BY date"
541 $sth->execute($borrowernumber);
543 # print $amountleft;
544 # offset transactions
545 while ( ( $accdata = $sth->fetchrow_hashref ) and ( $amountleft < 0 ) ) {
546 if ( $accdata->{'amountoutstanding'} > $amountleft ) {
547 $newamtos = 0;
548 $amountleft -= $accdata->{'amountoutstanding'};
550 else {
551 $newamtos = $accdata->{'amountoutstanding'} - $amountleft;
552 $amountleft = 0;
555 # print $amountleft;
556 my $thisacct = $accdata->{accountno};
557 my $usth = $dbh->prepare(
558 "UPDATE accountlines SET amountoutstanding= ?
559 WHERE (borrowernumber = ?) AND (accountno=?)"
561 $usth->execute( $newamtos, $borrowernumber, $thisacct );
562 $usth->finish;
563 $usth = $dbh->prepare(
564 "INSERT INTO accountoffsets
565 (borrowernumber, accountno, offsetaccount, offsetamount)
566 VALUES (?,?,?,?)"
568 $usth->execute( $borrowernumber, $accdata->{'accountno'},
569 $nextaccntno, $newamtos );
570 $usth->finish;
572 $sth->finish;
573 return ($amountleft);
576 sub getcharges {
577 my ( $borrowerno, $timestamp, $accountno ) = @_;
578 my $dbh = C4::Context->dbh;
579 my $timestamp2 = $timestamp - 1;
580 my $query = "";
581 my $sth = $dbh->prepare(
582 "SELECT * FROM accountlines WHERE borrowernumber=? AND accountno = ?"
584 $sth->execute( $borrowerno, $accountno );
586 my @results;
587 while ( my $data = $sth->fetchrow_hashref ) {
588 push @results,$data;
590 return (@results);
593 sub ModNote {
594 my ( $borrowernumber, $accountno, $note ) = @_;
595 my $dbh = C4::Context->dbh;
596 my $sth = $dbh->prepare('UPDATE accountlines SET note = ? WHERE borrowernumber = ? AND accountno = ?');
597 $sth->execute( $note, $borrowernumber, $accountno );
600 sub getcredits {
601 my ( $date, $date2 ) = @_;
602 my $dbh = C4::Context->dbh;
603 my $sth = $dbh->prepare(
604 "SELECT * FROM accountlines,borrowers
605 WHERE amount < 0 AND accounttype <> 'Pay' AND accountlines.borrowernumber = borrowers.borrowernumber
606 AND timestamp >=TIMESTAMP(?) AND timestamp < TIMESTAMP(?)"
609 $sth->execute( $date, $date2 );
610 my @results;
611 while ( my $data = $sth->fetchrow_hashref ) {
612 $data->{'date'} = $data->{'timestamp'};
613 push @results,$data;
615 return (@results);
619 sub getrefunds {
620 my ( $date, $date2 ) = @_;
621 my $dbh = C4::Context->dbh;
623 my $sth = $dbh->prepare(
624 "SELECT *,timestamp AS datetime
625 FROM accountlines,borrowers
626 WHERE (accounttype = 'REF'
627 AND accountlines.borrowernumber = borrowers.borrowernumber
628 AND date >=? AND date <?)"
631 $sth->execute( $date, $date2 );
633 my @results;
634 while ( my $data = $sth->fetchrow_hashref ) {
635 push @results,$data;
638 return (@results);
641 sub ReversePayment {
642 my ( $borrowernumber, $accountno ) = @_;
643 my $dbh = C4::Context->dbh;
645 my $sth = $dbh->prepare('SELECT amountoutstanding FROM accountlines WHERE borrowernumber = ? AND accountno = ?');
646 $sth->execute( $borrowernumber, $accountno );
647 my $row = $sth->fetchrow_hashref();
648 my $amount_outstanding = $row->{'amountoutstanding'};
650 if ( $amount_outstanding <= 0 ) {
651 $sth = $dbh->prepare('UPDATE accountlines SET amountoutstanding = amount * -1, description = CONCAT( description, " Reversed -" ) WHERE borrowernumber = ? AND accountno = ?');
652 $sth->execute( $borrowernumber, $accountno );
653 } else {
654 $sth = $dbh->prepare('UPDATE accountlines SET amountoutstanding = 0, description = CONCAT( description, " Reversed -" ) WHERE borrowernumber = ? AND accountno = ?');
655 $sth->execute( $borrowernumber, $accountno );
659 =head2 recordpayment_selectaccts
661 recordpayment_selectaccts($borrowernumber, $payment,$accts);
663 Record payment by a patron. C<$borrowernumber> is the patron's
664 borrower number. C<$payment> is a floating-point number, giving the
665 amount that was paid. C<$accts> is an array ref to a list of
666 accountnos which the payment can be recorded against
668 Amounts owed are paid off oldest first. That is, if the patron has a
669 $1 fine from Feb. 1, another $1 fine from Mar. 1, and makes a payment
670 of $1.50, then the oldest fine will be paid off in full, and $0.50
671 will be credited to the next one.
673 =cut
675 sub recordpayment_selectaccts {
676 my ( $borrowernumber, $amount, $accts ) = @_;
678 my $dbh = C4::Context->dbh;
679 my $newamtos = 0;
680 my $accdata = q{};
681 my $branch = C4::Context->userenv->{branch};
682 my $amountleft = $amount;
683 my $sql = 'SELECT * FROM accountlines WHERE (borrowernumber = ?) ' .
684 'AND (amountoutstanding<>0) ';
685 if (@{$accts} ) {
686 $sql .= ' AND accountno IN ( ' . join ',', @{$accts};
687 $sql .= ' ) ';
689 $sql .= ' ORDER BY date';
690 # begin transaction
691 my $nextaccntno = getnextacctno($borrowernumber);
693 # get lines with outstanding amounts to offset
694 my $rows = $dbh->selectall_arrayref($sql, { Slice => {} }, $borrowernumber);
696 # offset transactions
697 my $sth = $dbh->prepare('UPDATE accountlines SET amountoutstanding= ? ' .
698 'WHERE (borrowernumber = ?) AND (accountno=?)');
699 for my $accdata ( @{$rows} ) {
700 if ($amountleft == 0) {
701 last;
703 if ( $accdata->{amountoutstanding} < $amountleft ) {
704 $newamtos = 0;
705 $amountleft -= $accdata->{amountoutstanding};
707 else {
708 $newamtos = $accdata->{amountoutstanding} - $amountleft;
709 $amountleft = 0;
711 my $thisacct = $accdata->{accountno};
712 $sth->execute( $newamtos, $borrowernumber, $thisacct );
715 # create new line
716 $sql = 'INSERT INTO accountlines ' .
717 '(borrowernumber, accountno,date,amount,description,accounttype,amountoutstanding) ' .
718 q|VALUES (?,?,now(),?,'Payment,thanks','Pay',?)|;
719 $dbh->do($sql,{},$borrowernumber, $nextaccntno, 0 - $amount, 0 - $amountleft );
720 UpdateStats( $branch, 'payment', $amount, '', '', '', $borrowernumber, $nextaccntno );
721 return;
724 # makepayment needs to be fixed to handle partials till then this separate subroutine
725 # fills in
726 sub makepartialpayment {
727 my ( $borrowernumber, $accountno, $amount, $user, $branch ) = @_;
728 my $manager_id = 0;
729 $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
730 if (!$amount || $amount < 0) {
731 return;
733 my $dbh = C4::Context->dbh;
735 my $nextaccntno = getnextacctno($borrowernumber);
736 my $newamtos = 0;
738 my $data = $dbh->selectrow_hashref(
739 'SELECT * FROM accountlines WHERE borrowernumber=? AND accountno=?',undef,$borrowernumber,$accountno);
740 my $new_outstanding = $data->{amountoutstanding} - $amount;
742 my $update = 'UPDATE accountlines SET amountoutstanding = ? WHERE borrowernumber = ? '
743 . ' AND accountno = ?';
744 $dbh->do( $update, undef, $new_outstanding, $borrowernumber, $accountno);
746 # create new line
747 my $insert = 'INSERT INTO accountlines (borrowernumber, accountno, date, amount, '
748 . 'description, accounttype, amountoutstanding, itemnumber, manager_id) '
749 . ' VALUES (?, ?, now(), ?, ?, ?, 0, ?, ?)';
751 $dbh->do( $insert, undef, $borrowernumber, $nextaccntno, $amount,
752 "Payment, thanks - $user", 'Pay', $data->{'itemnumber'}, $manager_id);
754 UpdateStats( $user, 'payment', $amount, '', '', '', $borrowernumber, $accountno );
756 return;
761 END { } # module clean-up code here (global destructor)
764 __END__
766 =head1 SEE ALSO
768 DBI(3)
770 =cut