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
::Log
qw(logaction);
28 use Koha
::Account
::Lines
;
29 use Koha
::Account
::Offsets
;
32 use Data
::Dumper
qw(Dumper);
34 use vars
qw(@ISA @EXPORT);
43 &purge_zero_balance_fees
49 C4::Accounts - Functions for dealing with Koha accounts
57 The functions in this module deal with the monetary aspect of Koha,
58 including looking up and modifying the amount of money owed by a
65 $nextacct = &getnextacctno($borrowernumber);
67 Returns the next unused account number for the patron with the given
73 # FIXME - Okay, so what does the above actually _mean_?
75 my ($borrowernumber) = shift or return;
76 my $sth = C4
::Context
->dbh->prepare(
77 "SELECT accountno+1 FROM accountlines
78 WHERE (borrowernumber = ?)
79 ORDER BY accountno DESC
82 $sth->execute($borrowernumber);
83 return ($sth->fetchrow || 1);
88 In a default install of Koha the following lost values are set
93 FIXME: itemlost should be set to 3 after payment is made, should be a warning to the interface that a charge has been added
94 FIXME : if no replacement price, borrower just doesn't get charged?
99 my $dbh = C4
::Context
->dbh();
100 my ($borrowernumber, $itemnumber, $amount, $description) = @_;
101 my $itype = Koha
::ItemTypes
->find({ itemtype
=> Koha
::Items
->find($itemnumber)->effective_itemtype() });
102 my $replacementprice = $amount;
103 my $defaultreplacecost = $itype->defaultreplacecost;
104 my $processfee = $itype->processfee;
105 my $usedefaultreplacementcost = C4
::Context
->preference("useDefaultReplacementCost");
106 my $processingfeenote = C4
::Context
->preference("ProcessingFeeNote");
107 if ($usedefaultreplacementcost && $amount == 0 && $defaultreplacecost){
108 $replacementprice = $defaultreplacecost;
111 my $account = Koha
::Account
->new({ patron_id
=> $borrowernumber });
112 # first make sure the borrower hasn't already been charged for this item
113 # FIXME this should be more exact
114 # there is no reason a user can't lose an item, find and return it, and lost it again
115 my $existing_charges = $account->lines->search(
117 itemnumber
=> $itemnumber,
123 unless ($existing_charges) {
124 my $checkout = Koha
::Checkouts
->find({ itemnumber
=> $itemnumber });
125 my $issue_id = $checkout ?
$checkout->issue_id : undef;
127 if ($processfee && $processfee > 0){
128 my $accountline = $account->add_debit(
130 amount
=> $processfee,
131 description
=> $description,
132 note
=> $processingfeenote,
133 user_id
=> C4
::Context
->userenv ? C4
::Context
->userenv->{'number'} : 0,
134 library_id
=> C4
::Context
->userenv ? C4
::Context
->userenv->{'branch'} : undef,
135 type
=> 'processing',
136 item_id
=> $itemnumber,
137 issue_id
=> $issue_id,
142 if ($replacementprice > 0){
143 my $accountline = $account->add_debit(
145 amount
=> $replacementprice,
146 description
=> $description,
148 user_id
=> C4
::Context
->userenv ? C4
::Context
->userenv->{'number'} : 0,
149 library_id
=> C4
::Context
->userenv ? C4
::Context
->userenv->{'branch'} : undef,
151 item_id
=> $itemnumber,
152 issue_id
=> $issue_id,
161 &manualinvoice($borrowernumber, $itemnumber, $description, $type,
164 C<$borrowernumber> is the patron's borrower number.
165 C<$description> is a description of the transaction.
166 C<$type> may be one of C<CS>, C<CB>, C<CW>, C<CF>, C<CL>, C<N>, C<L>,
168 C<$itemnumber> is the item involved, if pertinent; otherwise, it
169 should be the empty string.
174 # FIXME: In Koha 3.0 , the only account adjustment 'types' passed to this function
177 # 'FOR' = FORGIVEN (Formerly 'F', but 'F' is taken to mean 'FINE' elsewhere)
180 # 'A' = Account Management fee
186 my ( $borrowernumber, $itemnum, $desc, $type, $amount, $note ) = @_;
188 $manager_id = C4
::Context
->userenv->{'number'} if C4
::Context
->userenv;
189 my $dbh = C4
::Context
->dbh;
191 my $accountno = getnextacctno
($borrowernumber);
192 my $amountleft = $amount;
194 my $branchcode = C4
::Context
->userenv ? C4
::Context
->userenv->{'branch'} : undef;
196 my $accountline = Koha
::Account
::Line
->new(
198 borrowernumber
=> $borrowernumber,
199 accountno
=> $accountno,
202 description => $desc,
203 accounttype => $type,
204 amountoutstanding => $amountleft,
205 itemnumber => $itemnum || undef,
207 manager_id => $manager_id,
208 branchcode => $branchcode,
212 my $account_offset = Koha::Account::Offset->new(
214 debit_id => $accountline->id,
215 type => 'Manual Debit
',
220 if ( C4::Context->preference("FinesLog") ) {
221 logaction("FINES", 'CREATE
',$borrowernumber,Dumper({
222 action => 'create_fee
',
223 borrowernumber => $borrowernumber,
224 accountno => $accountno,
226 description => $desc,
227 accounttype => $type,
228 amountoutstanding => $amountleft,
230 itemnumber => $itemnum,
231 manager_id => $manager_id,
238 =head2 purge_zero_balance_fees
240 purge_zero_balance_fees( $days );
242 Delete accountlines entries where amountoutstanding is 0 or NULL which are more than a given number of days old.
244 B<$days> -- Zero balance fees older than B<$days> days old will be deleted.
246 B<Warning:> Because fines and payments are not linked in accountlines, it is
247 possible for a fine to be deleted without the accompanying payment,
248 or vise versa. This won't affect the account balance
, but might be
253 sub purge_zero_balance_fees
{
257 my $dbh = C4
::Context
->dbh;
258 my $sth = $dbh->prepare(
260 DELETE a1 FROM accountlines a1
262 LEFT JOIN account_offsets credit_offset ON ( a1.accountlines_id = credit_offset.credit_id )
263 LEFT JOIN accountlines a2 ON ( credit_offset.debit_id = a2.accountlines_id )
265 LEFT JOIN account_offsets debit_offset ON ( a1.accountlines_id = debit_offset.debit_id )
266 LEFT JOIN accountlines a3 ON ( debit_offset.credit_id = a3.accountlines_id )
268 WHERE a1.date < date_sub(curdate(), INTERVAL ? DAY)
269 AND ( a1.amountoutstanding = 0 OR a1.amountoutstanding IS NULL )
270 AND ( a2.amountoutstanding = 0 OR a2.amountoutstanding IS NULL )
271 AND ( a3.amountoutstanding = 0 OR a3.amountoutstanding IS NULL )
274 $sth->execute($days) or die $dbh->errstr;
277 END { } # module clean-up code here (global destructor)