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 with
17 # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
18 # Suite 330, Boston, MA 02111-1307 USA
28 use vars qw($VERSION @ISA @EXPORT);
30 # set the version for version checking
31 $VERSION = do { my @v = '$Revision$' =~ /\d+/g;
32 shift(@v) . "." . join("_", map {sprintf "%03d", $_ } @v); };
36 C4::Accounts - Functions for dealing with Koha accounts
44 The functions in this module deal with the monetary aspect of Koha,
45 including looking up and modifying the amount of money owed by a
53 @EXPORT = qw(&recordpayment &fixaccounts &makepayment &manualinvoice
54 &getnextacctno &reconcileaccount);
59 &recordpayment($borrowernumber, $payment);
61 Record payment by a patron. C<$borrowernumber> is the patron's
62 borrower number. C<$payment> is a floating-point number, giving the
65 Amounts owed are paid off oldest first. That is, if the patron has a
66 $1 fine from Feb. 1, another $1 fine from Mar. 1, and makes a payment
67 of $1.50, then the oldest fine will be paid off in full, and $0.50
68 will be credited to the next one.
74 #here we update both the accountoffsets and the account lines
75 my ($borrowernumber,$data)=@_;
76 my $dbh = C4::Context->dbh;
79 my $branch=C4::Context->userenv->{'branch'};
80 my $amountleft = $data;
82 my $nextaccntno = getnextacctno($borrowernumber);
83 # get lines with outstanding amounts to offset
84 my $sth = $dbh->prepare("SELECT * FROM accountlines
85 WHERE (borrowernumber = ?) AND (amountoutstanding<>0)
87 $sth->execute($borrowernumber);
89 while (($accdata=$sth->fetchrow_hashref) and ($amountleft>0)){
90 if ($accdata->{'amountoutstanding'} < $amountleft) {
92 $amountleft -= $accdata->{'amountoutstanding'};
94 $newamtos = $accdata->{'amountoutstanding'} - $amountleft;
97 my $thisacct = $accdata->{accountno};
98 my $usth = $dbh->prepare("UPDATE accountlines SET amountoutstanding= ?
99 WHERE (borrowernumber = ?) AND (accountno=?)");
100 $usth->execute($newamtos,$borrowernumber,$thisacct);
102 $usth = $dbh->prepare("INSERT INTO accountoffsets
103 (borrowernumber, accountno, offsetaccount, offsetamount)
105 $usth->execute($borrowernumber,$accdata->{'accountno'},$nextaccntno,$newamtos);
109 my $usth = $dbh->prepare("INSERT INTO accountlines
110 (borrowernumber, accountno,date,amount,description,accounttype,amountoutstanding)
111 VALUES (?,?,now(),?,'Payment,thanks','Pay',?)");
112 $usth->execute($borrowernumber,$nextaccntno,0-$data,0-$amountleft);
114 UpdateStats($branch,'payment',$data,'','','',$borrowernumber);
120 &makepayment($borrowernumber, $acctnumber, $amount, $branchcode);
122 Records the fact that a patron has paid off the entire amount he or
125 C<$borrowernumber> is the patron's borrower number. C<$acctnumber> is
126 the account that was credited. C<$amount> is the amount paid (this is
127 only used to record the payment. It is assumed to be equal to the
128 amount owed). C<$branchcode> is the code of the branch where payment
134 # FIXME - I'm not at all sure about the above, because I don't
135 # understand what the acct* tables in the Koha database are for.
137 #here we update both the accountoffsets and the account lines
138 #updated to check, if they are paying off a lost item, we return the item
139 # from their card, and put a note on the item record
140 my ($borrowernumber,$accountno,$amount,$user,$branch)=@_;
141 my $dbh = C4::Context->dbh;
143 my $nextaccntno = getnextacctno($borrowernumber);
145 my $sth=$dbh->prepare("SELECT * FROM accountlines WHERE borrowernumber=? AND accountno=?");
146 $sth->execute($borrowernumber,$accountno);
147 my $data=$sth->fetchrow_hashref;
150 $dbh->do("UPDATE accountlines
151 SET amountoutstanding = 0
152 WHERE borrowernumber = $borrowernumber
153 AND accountno = $accountno
158 INSERT INTO accountoffsets
159 (borrowernumber, accountno, offsetaccount,
161 VALUES ($borrowernumber, $accountno, $nextaccntno, $newamtos)
165 my $payment=0-$amount;
167 INSERT INTO accountlines
168 (borrowernumber, accountno, date, amount,
169 description, accounttype, amountoutstanding)
170 VALUES ($borrowernumber, $nextaccntno, now(), $payment,
171 'Payment,thanks - $user', 'Pay', 0)
174 # FIXME - The second argument to &UpdateStats is supposed to be the
176 # UpdateStats is now being passed $accountno too. MTJ
177 UpdateStats($user,'payment',$amount,'','','',$borrowernumber,$accountno);
179 #check to see what accounttype
180 if ($data->{'accounttype'} eq 'Rep' || $data->{'accounttype'} eq 'L'){
181 returnlost($borrowernumber,$data->{'itemnumber'});
187 $nextacct = &getnextacctno($borrowernumber);
189 Returns the next unused account number for the patron with the given
195 # FIXME - Okay, so what does the above actually _mean_?
197 my ($borrowernumber)=@_;
199 my $dbh = C4::Context->dbh;
200 my $sth = $dbh->prepare("SELECT * FROM accountlines
201 WHERE (borrowernumber = ?)
202 ORDER BY accountno DESC");
203 $sth->execute($borrowernumber);
204 if (my $accdata=$sth->fetchrow_hashref){
205 $nextaccntno = $accdata->{'accountno'} + 1;
208 return($nextaccntno);
213 &fixaccounts($borrowernumber, $accountnumber, $amount);
218 # FIXME - I don't understand what this function does.
220 my ($borrowernumber,$accountno,$amount)=@_;
221 my $dbh = C4::Context->dbh;
222 my $sth=$dbh->prepare("SELECT * FROM accountlines WHERE borrowernumber=?
224 $sth->execute($borrowernumber,$accountno);
225 my $data=$sth->fetchrow_hashref;
226 # FIXME - Error-checking
227 my $diff=$amount-$data->{'amount'};
228 my $outstanding=$data->{'amountoutstanding'}+$diff;
233 SET amount = '$amount',
234 amountoutstanding = '$outstanding'
235 WHERE borrowernumber = $borrowernumber
236 AND accountno = $accountno
240 # FIXME - Never used, but not exported, either.
242 my ($borrowernumber,$itemnum)=@_;
243 my $dbh = C4::Context->dbh;
244 my $borrower=GetMember($borrowernumber,'borrowernumber');
245 my $sth=$dbh->prepare("UPDATE issues SET returndate=now() WHERE
246 borrowernumber=? AND itemnumber=? AND returndate IS NULL");
247 $sth->execute($borrowernumber,$itemnum);
249 my @datearr = localtime(time);
250 my $date = (1900+$datearr[5])."-".($datearr[4]+1)."-".$datearr[3];
251 my $bor="$borrower->{'firstname'} $borrower->{'surname'} $borrower->{'cardnumber'}";
252 $sth=$dbh->prepare("UPDATE items SET paidfor=? WHERE itemnumber=?");
253 $sth->execute("Paid for by $bor $date",$itemnum);
259 &manualinvoice($borrowernumber, $itemnumber, $description, $type,
262 C<$borrowernumber> is the patron's borrower number.
263 C<$description> is a description of the transaction.
264 C<$type> may be one of C<CS>, C<CB>, C<CW>, C<CF>, C<CL>, C<N>, C<L>,
266 C<$itemnumber> is the item involved, if pertinent; otherwise, it
267 should be the empty string.
272 # FIXME - Okay, so what does this function do, really?
274 my ($borrowernumber,$itemnum,$desc,$type,$amount,$user)=@_;
275 my $dbh = C4::Context->dbh;
279 my $accountno=getnextacctno($borrowernumber);
280 my $amountleft=$amount;
282 if ($type eq 'CS' || $type eq 'CB' || $type eq 'CW'
283 || $type eq 'CF' || $type eq 'CL'){
284 my $amount2=$amount*-1; # FIXME - $amount2 = -$amount
285 $amountleft=fixcredit($borrowernumber,$amount2,$itemnum,$type,$user);
294 $desc.="Account Management fee";
300 if ($type eq 'L' && $desc eq ''){
305 $desc.="Cash Refund";
306 $amountleft=refund('',$borrowernumber,$amount);
308 if(($type eq 'L') or ($type eq 'F') or ($type eq 'A') or ($type eq 'N') or ($type eq 'M') ){
314 my $sth=$dbh->prepare("INSERT INTO accountlines
315 (borrowernumber, accountno, date, amount, description, accounttype, amountoutstanding, itemnumber,notify_id)
316 VALUES (?, ?, now(), ?,?, ?,?,?,?)");
317 $sth->execute($borrowernumber, $accountno, $amount, $desc, $type, $amountleft, $itemnum,$notifyid) || return $sth->errstr;
319 my $sth=$dbh->prepare("INSERT INTO accountlines
320 (borrowernumber, accountno, date, amount, description, accounttype, amountoutstanding,notify_id)
321 VALUES (?, ?, now(), ?, ?, ?, ?,?)");
322 $sth->execute($borrowernumber, $accountno, $amount, $desc, $type, $amountleft,$notifyid);
328 $amountleft = &fixcredit($borrowernumber, $data, $barcode, $type, $user);
330 This function is only used internally, not exported.
331 FIXME - Figure out what this function does, and write it down.
336 #here we update both the accountoffsets and the account lines
337 my ($borrowernumber,$data,$barcode,$type,$user)=@_;
338 my $dbh = C4::Context->dbh;
341 my $amountleft = $data;
343 my $item=GetBiblioFromItemNumber('',$barcode);
344 my $nextaccntno = getnextacctno($borrowernumber);
345 my $query="SELECT * FROM accountlines WHERE (borrowernumber=?
346 AND itemnumber=? AND amountoutstanding > 0)";
348 $query.=" AND (accounttype = 'L' OR accounttype = 'Rep')";
349 } elsif ($type eq 'CF'){
350 $query.=" AND (accounttype = 'F' OR accounttype = 'FU' OR
351 accounttype='Res' OR accounttype='Rent')";
352 } elsif ($type eq 'CB'){
353 $query.=" and accounttype='A'";
356 my $sth=$dbh->prepare($query);
357 $sth->execute($borrowernumber,$item->{'itemnumber'});
358 $accdata=$sth->fetchrow_hashref;
360 if ($accdata->{'amountoutstanding'} < $amountleft) {
362 $amountleft -= $accdata->{'amountoutstanding'};
364 $newamtos = $accdata->{'amountoutstanding'} - $amountleft;
367 my $thisacct = $accdata->{accountno};
368 my $usth = $dbh->prepare("UPDATE accountlines SET amountoutstanding= ?
369 WHERE (borrowernumber = ?) AND (accountno=?)");
370 $usth->execute($newamtos,$borrowernumber,$thisacct);
372 $usth = $dbh->prepare("INSERT INTO accountoffsets
373 (borrowernumber, accountno, offsetaccount, offsetamount)
375 $usth->execute($borrowernumber,$accdata->{'accountno'},$nextaccntno,$newamtos);
379 my $nextaccntno = getnextacctno($borrowernumber);
380 # get lines with outstanding amounts to offset
381 my $sth = $dbh->prepare("SELECT * FROM accountlines
382 WHERE (borrowernumber = ?) AND (amountoutstanding >0)
384 $sth->execute($borrowernumber);
386 # offset transactions
387 while (($accdata=$sth->fetchrow_hashref) and ($amountleft>0)){
388 if ($accdata->{'amountoutstanding'} < $amountleft) {
390 $amountleft -= $accdata->{'amountoutstanding'};
392 $newamtos = $accdata->{'amountoutstanding'} - $amountleft;
395 my $thisacct = $accdata->{accountno};
396 my $usth = $dbh->prepare("UPDATE accountlines SET amountoutstanding= ?
397 WHERE (borrowernumber = ?) AND (accountno=?)");
398 $usth->execute($newamtos,$borrowernumber,$thisacct);
400 $usth = $dbh->prepare("INSERT INTO accountoffsets
401 (borrowernumber, accountno, offsetaccount, offsetamount)
403 $usth->execute($borrowernumber,$accdata->{'accountno'},$nextaccntno,$newamtos);
407 $type="Credit ".$type;
408 UpdateStats($user,$type,$data,$user,'','',$borrowernumber);
416 # FIXME - Figure out what this function does, and write it down.
421 #here we update both the accountoffsets and the account lines
422 my ($borrowernumber,$data)=@_;
423 my $dbh = C4::Context->dbh;
426 my $amountleft = $data *-1;
429 my $nextaccntno = getnextacctno($borrowernumber);
430 # get lines with outstanding amounts to offset
431 my $sth = $dbh->prepare("SELECT * FROM accountlines
432 WHERE (borrowernumber = ?) AND (amountoutstanding<0)
434 $sth->execute($borrowernumber);
436 # offset transactions
437 while (($accdata=$sth->fetchrow_hashref) and ($amountleft<0)){
438 if ($accdata->{'amountoutstanding'} > $amountleft) {
440 $amountleft -= $accdata->{'amountoutstanding'};
442 $newamtos = $accdata->{'amountoutstanding'} - $amountleft;
446 my $thisacct = $accdata->{accountno};
447 my $usth = $dbh->prepare("UPDATE accountlines SET amountoutstanding= ?
448 WHERE (borrowernumber = ?) AND (accountno=?)");
449 $usth->execute($newamtos,$borrowernumber,$thisacct);
451 $usth = $dbh->prepare("INSERT INTO accountoffsets
452 (borrowernumber, accountno, offsetaccount, offsetamount)
454 $usth->execute($borrowernumber,$accdata->{'accountno'},$nextaccntno,$newamtos);
462 END { } # module clean-up code here (global destructor)