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;
110 # first make sure the borrower hasn't already been charged for this item
111 # FIXME this should be more exact
112 # there is no reason a user can't lose an item, find and return it, and lost it again
113 my $existing_charges = Koha
::Account
::Lines
->search(
115 borrowernumber
=> $borrowernumber,
116 itemnumber
=> $itemnumber,
122 unless ($existing_charges) {
123 my $checkout = Koha
::Checkouts
->find({ itemnumber
=> $itemnumber });
124 my $issue_id = $checkout ?
$checkout->issue_id : undef;
126 if ($processfee && $processfee > 0){
127 my $accountline = Koha
::Account
::Line
->new(
129 borrowernumber
=> $borrowernumber,
130 issue_id
=> $issue_id,
131 accountno
=> getnextacctno
($borrowernumber),
133 amount => $processfee,
134 description => $description,
136 amountoutstanding => $processfee,
137 itemnumber => $itemnumber,
138 note => $processingfeenote,
139 manager_id => C4::Context->userenv ? C4::Context->userenv->{'number
'} : 0,
143 my $account_offset = Koha::Account::Offset->new(
145 debit_id => $accountline->id,
146 type => 'Processing Fee
',
147 amount => $accountline->amount,
151 if ( C4::Context->preference("FinesLog") ) {
152 logaction("FINES", 'CREATE
',$borrowernumber,Dumper({
153 action => 'create_fee
',
154 borrowernumber => $accountline->borrowernumber,,
155 accountno => $accountline->accountno,
156 amount => $accountline->amount,
157 description => $accountline->description,
158 accounttype => $accountline->accounttype,
159 amountoutstanding => $accountline->amountoutstanding,
160 note => $accountline->note,
161 itemnumber => $accountline->itemnumber,
162 manager_id => $accountline->manager_id,
167 if ($replacementprice > 0){
168 my $accountline = Koha::Account::Line->new(
170 borrowernumber => $borrowernumber,
171 issue_id => $issue_id,
172 accountno => getnextacctno($borrowernumber),
174 amount
=> $replacementprice,
175 description
=> $description,
177 amountoutstanding
=> $replacementprice,
178 itemnumber
=> $itemnumber,
179 manager_id
=> C4
::Context
->userenv ? C4
::Context
->userenv->{'number'} : 0,
183 my $account_offset = Koha
::Account
::Offset
->new(
185 debit_id
=> $accountline->id,
187 amount
=> $accountline->amount,
191 if ( C4
::Context
->preference("FinesLog") ) {
192 logaction
("FINES", 'CREATE',$borrowernumber,Dumper
({
193 action
=> 'create_fee',
194 borrowernumber
=> $accountline->borrowernumber,,
195 accountno
=> $accountline->accountno,
196 amount
=> $accountline->amount,
197 description
=> $accountline->description,
198 accounttype
=> $accountline->accounttype,
199 amountoutstanding
=> $accountline->amountoutstanding,
200 note
=> $accountline->note,
201 itemnumber
=> $accountline->itemnumber,
202 manager_id
=> $accountline->manager_id,
211 &manualinvoice($borrowernumber, $itemnumber, $description, $type,
214 C<$borrowernumber> is the patron's borrower number.
215 C<$description> is a description of the transaction.
216 C<$type> may be one of C<CS>, C<CB>, C<CW>, C<CF>, C<CL>, C<N>, C<L>,
218 C<$itemnumber> is the item involved, if pertinent; otherwise, it
219 should be the empty string.
224 # FIXME: In Koha 3.0 , the only account adjustment 'types' passed to this function
227 # 'FOR' = FORGIVEN (Formerly 'F', but 'F' is taken to mean 'FINE' elsewhere)
230 # 'A' = Account Management fee
236 my ( $borrowernumber, $itemnum, $desc, $type, $amount, $note ) = @_;
238 $manager_id = C4
::Context
->userenv->{'number'} if C4
::Context
->userenv;
239 my $dbh = C4
::Context
->dbh;
241 my $accountno = getnextacctno
($borrowernumber);
242 my $amountleft = $amount;
244 my $accountline = Koha
::Account
::Line
->new(
246 borrowernumber
=> $borrowernumber,
247 accountno
=> $accountno,
250 description => $desc,
251 accounttype => $type,
252 amountoutstanding => $amountleft,
253 itemnumber => $itemnum || undef,
255 manager_id => $manager_id,
259 my $account_offset = Koha::Account::Offset->new(
261 debit_id => $accountline->id,
262 type => 'Manual Debit
',
267 if ( C4::Context->preference("FinesLog") ) {
268 logaction("FINES", 'CREATE
',$borrowernumber,Dumper({
269 action => 'create_fee
',
270 borrowernumber => $borrowernumber,
271 accountno => $accountno,
273 description => $desc,
274 accounttype => $type,
275 amountoutstanding => $amountleft,
277 itemnumber => $itemnum,
278 manager_id => $manager_id,
285 =head2 purge_zero_balance_fees
287 purge_zero_balance_fees( $days );
289 Delete accountlines entries where amountoutstanding is 0 or NULL which are more than a given number of days old.
291 B<$days> -- Zero balance fees older than B<$days> days old will be deleted.
293 B<Warning:> Because fines and payments are not linked in accountlines, it is
294 possible for a fine to be deleted without the accompanying payment,
295 or vise versa. This won't affect the account balance
, but might be
300 sub purge_zero_balance_fees
{
304 my $dbh = C4
::Context
->dbh;
305 my $sth = $dbh->prepare(
307 DELETE a1 FROM accountlines a1
309 LEFT JOIN account_offsets credit_offset ON ( a1.accountlines_id = credit_offset.credit_id )
310 LEFT JOIN accountlines a2 ON ( credit_offset.debit_id = a2.accountlines_id )
312 LEFT JOIN account_offsets debit_offset ON ( a1.accountlines_id = debit_offset.debit_id )
313 LEFT JOIN accountlines a3 ON ( debit_offset.credit_id = a3.accountlines_id )
315 WHERE a1.date < date_sub(curdate(), INTERVAL ? DAY)
316 AND ( a1.amountoutstanding = 0 OR a1.amountoutstanding IS NULL )
317 AND ( a2.amountoutstanding = 0 OR a2.amountoutstanding IS NULL )
318 AND ( a3.amountoutstanding = 0 OR a3.amountoutstanding IS NULL )
321 $sth->execute($days) or die $dbh->errstr;
324 END { } # module clean-up code here (global destructor)