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
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
22 #use warnings; FIXME - Bug 2505
26 use C4::Circulation qw(ReturnLostItem);
27 use C4::Log qw(logaction);
29 use Koha::Account::Lines;
30 use Koha::Account::Offsets;
32 use Data::Dumper qw(Dumper);
34 use vars qw(@ISA @EXPORT);
48 &purge_zero_balance_fees
54 C4::Accounts - Functions for dealing with Koha accounts
62 The functions in this module deal with the monetary aspect of Koha,
63 including looking up and modifying the amount of money owed by a
70 $nextacct = &getnextacctno($borrowernumber);
72 Returns the next unused account number for the patron with the given
78 # FIXME - Okay, so what does the above actually _mean_?
80 my ($borrowernumber) = shift or return;
81 my $sth = C4::Context->dbh->prepare(
82 "SELECT accountno+1 FROM accountlines
83 WHERE (borrowernumber = ?)
84 ORDER BY accountno DESC
87 $sth->execute($borrowernumber);
88 return ($sth->fetchrow || 1);
91 =head2 fixaccounts (removed)
93 &fixaccounts($accountlines_id, $borrowernumber, $accountnumber, $amount);
96 # FIXME - I don't understand what this function does.
98 my ( $accountlines_id, $borrowernumber, $accountno, $amount ) = @_;
99 my $dbh = C4::Context->dbh;
100 my $sth = $dbh->prepare(
101 "SELECT * FROM accountlines WHERE accountlines_id=?"
103 $sth->execute( $accountlines_id );
104 my $data = $sth->fetchrow_hashref;
106 # FIXME - Error-checking
107 my $diff = $amount - $data->{'amount'};
108 my $outstanding = $data->{'amountoutstanding'} + $diff;
113 SET amount = '$amount',
114 amountoutstanding = '$outstanding'
115 WHERE accountlines_id = $accountlines_id
117 # FIXME: exceedingly bad form. Use prepare with placholders ("?") in query and execute args.
122 =head2 chargelostitem
124 In a default install of Koha the following lost values are set
127 3 = Lost and paid for
129 FIXME: itemlost should be set to 3 after payment is made, should be a warning to the interface that a charge has been added
130 FIXME : if no replacement price, borrower just doesn't get charged?
135 my $dbh = C4::Context->dbh();
136 my ($borrowernumber, $itemnumber, $amount, $description) = @_;
138 # first make sure the borrower hasn't already been charged for this item
139 my $existing_charges = Koha::Account::Lines->search(
141 borrowernumber => $borrowernumber,
142 itemnumber => $itemnumber,
148 unless ($existing_charges) {
150 $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
151 # This item is on issue ... add replacement cost to the borrower's record and mark it returned
152 # Note that we add this to the account even if there's no replacement price, allowing some other
153 # process (or person) to update it, since we don't handle any defaults for replacement prices.
154 my $accountno = getnextacctno($borrowernumber);
156 my $accountline = Koha::Account::Line->new(
158 borrowernumber => $borrowernumber,
159 accountno => $accountno,
162 description => $description,
164 amountoutstanding => $amount,
165 itemnumber => $itemnumber,
166 manager_id => $manager_id,
170 my $account_offset = Koha::Account::Offset->new(
172 debit_id => $accountline->id,
178 if ( C4::Context->preference("FinesLog") ) {
179 logaction("FINES", 'CREATE', $borrowernumber, Dumper({
180 action => 'create_fee',
181 borrowernumber => $borrowernumber,
182 accountno => $accountno,
184 amountoutstanding => $amount,
185 description => $description,
187 itemnumber => $itemnumber,
188 manager_id => $manager_id,
197 &manualinvoice($borrowernumber, $itemnumber, $description, $type,
200 C<$borrowernumber> is the patron's borrower number.
201 C<$description> is a description of the transaction.
202 C<$type> may be one of C<CS>, C<CB>, C<CW>, C<CF>, C<CL>, C<N>, C<L>,
204 C<$itemnumber> is the item involved, if pertinent; otherwise, it
205 should be the empty string.
210 # FIXME: In Koha 3.0 , the only account adjustment 'types' passed to this function
213 # 'FOR' = FORGIVEN (Formerly 'F', but 'F' is taken to mean 'FINE' elsewhere)
216 # 'A' = Account Management fee
222 my ( $borrowernumber, $itemnum, $desc, $type, $amount, $note ) = @_;
224 $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
225 my $dbh = C4::Context->dbh;
228 my $accountno = getnextacctno($borrowernumber);
229 my $amountleft = $amount;
231 if ( ( $type eq 'L' )
235 or ( $type eq 'M' ) )
240 my $accountline = Koha::Account::Line->new(
242 borrowernumber => $borrowernumber,
243 accountno => $accountno,
246 description => $desc,
247 accounttype => $type,
248 amountoutstanding => $amountleft,
249 itemnumber => $itemnum || undef,
250 notify_id => $notifyid,
252 manager_id => $manager_id,
256 my $account_offset = Koha::Account::Offset->new(
258 debit_id => $accountline->id,
259 type => 'Manual Debit',
264 if ( C4::Context->preference("FinesLog") ) {
265 logaction("FINES", 'CREATE',$borrowernumber,Dumper({
266 action => 'create_fee',
267 borrowernumber => $borrowernumber,
268 accountno => $accountno,
270 description => $desc,
271 accounttype => $type,
272 amountoutstanding => $amountleft,
273 notify_id => $notifyid,
275 itemnumber => $itemnum,
276 manager_id => $manager_id,
284 my ( $borrowerno, $timestamp, $accountno ) = @_;
285 my $dbh = C4::Context->dbh;
286 my $timestamp2 = $timestamp - 1;
288 my $sth = $dbh->prepare(
289 "SELECT * FROM accountlines WHERE borrowernumber=? AND accountno = ?"
291 $sth->execute( $borrowerno, $accountno );
294 while ( my $data = $sth->fetchrow_hashref ) {
301 my ( $accountlines_id, $note ) = @_;
302 my $dbh = C4::Context->dbh;
303 my $sth = $dbh->prepare('UPDATE accountlines SET note = ? WHERE accountlines_id = ?');
304 $sth->execute( $note, $accountlines_id );
308 my ( $date, $date2 ) = @_;
309 my $dbh = C4::Context->dbh;
310 my $sth = $dbh->prepare(
311 "SELECT * FROM accountlines,borrowers
312 WHERE amount < 0 AND accounttype not like 'Pay%' AND accountlines.borrowernumber = borrowers.borrowernumber
313 AND timestamp >=TIMESTAMP(?) AND timestamp < TIMESTAMP(?)"
316 $sth->execute( $date, $date2 );
318 while ( my $data = $sth->fetchrow_hashref ) {
319 $data->{'date'} = $data->{'timestamp'};
327 my ( $date, $date2 ) = @_;
328 my $dbh = C4::Context->dbh;
330 my $sth = $dbh->prepare(
331 "SELECT *,timestamp AS datetime
332 FROM accountlines,borrowers
333 WHERE (accounttype = 'REF'
334 AND accountlines.borrowernumber = borrowers.borrowernumber
335 AND date >=? AND date <?)"
338 $sth->execute( $date, $date2 );
341 while ( my $data = $sth->fetchrow_hashref ) {
348 #FIXME: ReversePayment should be replaced with a Void Payment feature
350 my ($accountlines_id) = @_;
351 my $dbh = C4::Context->dbh;
353 my $accountline = Koha::Account::Lines->find($accountlines_id);
354 my $amount_outstanding = $accountline->amountoutstanding;
356 my $new_amountoutstanding =
357 $amount_outstanding <= 0 ? $accountline->amount * -1 : 0;
359 $accountline->description( $accountline->description . " Reversed -" );
360 $accountline->amountoutstanding($new_amountoutstanding);
361 $accountline->store();
363 my $account_offset = Koha::Account::Offset->new(
365 credit_id => $accountline->id,
366 type => 'Reverse Payment',
367 amount => $amount_outstanding - $new_amountoutstanding,
371 if ( C4::Context->preference("FinesLog") ) {
373 $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
377 $accountline->borrowernumber,
380 action => 'reverse_fee_payment',
381 borrowernumber => $accountline->borrowernumber,
382 old_amountoutstanding => $amount_outstanding,
383 new_amountoutstanding => $new_amountoutstanding,
385 accountlines_id => $accountline->id,
386 accountno => $accountline->accountno,
387 manager_id => $manager_id,
394 =head2 purge_zero_balance_fees
396 purge_zero_balance_fees( $days );
398 Delete accountlines entries where amountoutstanding is 0 or NULL which are more than a given number of days old.
400 B<$days> -- Zero balance fees older than B<$days> days old will be deleted.
402 B<Warning:> Because fines and payments are not linked in accountlines, it is
403 possible for a fine to be deleted without the accompanying payment,
404 or vise versa. This won't affect the account balance, but might be
409 sub purge_zero_balance_fees {
413 my $dbh = C4::Context->dbh;
414 my $sth = $dbh->prepare(
416 DELETE FROM accountlines
417 WHERE date < date_sub(curdate(), INTERVAL ? DAY)
418 AND ( amountoutstanding = 0 or amountoutstanding IS NULL );
421 $sth->execute($days) or die $dbh->errstr;
424 END { } # module clean-up code here (global destructor)