View | Details | Raw Unified | Return to bug 6427
Collapse All | Expand All

(-)a/C4/Accounts.pm (-821 lines)
Lines 1-821 Link Here
1
package C4::Accounts;
2
3
# Copyright 2000-2002 Katipo Communications
4
#
5
# This file is part of Koha.
6
#
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.
11
#
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.
15
#
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.
19
20
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);
27
use C4::Log qw(logaction);
28
29
use Data::Dumper qw(Dumper);
30
31
use vars qw($VERSION @ISA @EXPORT);
32
33
BEGIN {
34
	# set the version for version checking
35
    $VERSION = 3.07.00.049;
36
	require Exporter;
37
	@ISA    = qw(Exporter);
38
	@EXPORT = qw(
39
		&recordpayment
40
		&makepayment
41
		&manualinvoice
42
		&getnextacctno
43
		&getcharges
44
		&ModNote
45
		&getcredits
46
		&getrefunds
47
		&chargelostitem
48
		&ReversePayment
49
                &makepartialpayment
50
                &recordpayment_selectaccts
51
                &WriteOffFee
52
	);
53
}
54
55
=head1 NAME
56
57
C4::Accounts - Functions for dealing with Koha accounts
58
59
=head1 SYNOPSIS
60
61
use C4::Accounts;
62
63
=head1 DESCRIPTION
64
65
The functions in this module deal with the monetary aspect of Koha,
66
including looking up and modifying the amount of money owed by a
67
patron.
68
69
=head1 FUNCTIONS
70
71
=head2 recordpayment
72
73
  &recordpayment($borrowernumber, $payment);
74
75
Record payment by a patron. C<$borrowernumber> is the patron's
76
borrower number. C<$payment> is a floating-point number, giving the
77
amount that was paid.
78
79
Amounts owed are paid off oldest first. That is, if the patron has a
80
$1 fine from Feb. 1, another $1 fine from Mar. 1, and makes a payment
81
of $1.50, then the oldest fine will be paid off in full, and $0.50
82
will be credited to the next one.
83
84
=cut
85
86
#'
87
sub recordpayment {
88
89
    #here we update the account lines
90
    my ( $borrowernumber, $data ) = @_;
91
    my $dbh        = C4::Context->dbh;
92
    my $newamtos   = 0;
93
    my $accdata    = "";
94
    my $branch     = C4::Context->userenv->{'branch'};
95
    my $amountleft = $data;
96
    my $manager_id = 0;
97
    $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
98
99
    # begin transaction
100
    my $nextaccntno = getnextacctno($borrowernumber);
101
102
    # get lines with outstanding amounts to offset
103
    my $sth = $dbh->prepare(
104
        "SELECT * FROM accountlines
105
  WHERE (borrowernumber = ?) AND (amountoutstanding<>0)
106
  ORDER BY date"
107
    );
108
    $sth->execute($borrowernumber);
109
110
    # offset transactions
111
    my @ids;
112
    while ( ( $accdata = $sth->fetchrow_hashref ) and ( $amountleft > 0 ) ) {
113
        if ( $accdata->{'amountoutstanding'} < $amountleft ) {
114
            $newamtos = 0;
115
            $amountleft -= $accdata->{'amountoutstanding'};
116
        }
117
        else {
118
            $newamtos   = $accdata->{'amountoutstanding'} - $amountleft;
119
            $amountleft = 0;
120
        }
121
        my $thisacct = $accdata->{accountlines_id};
122
        my $usth     = $dbh->prepare(
123
            "UPDATE accountlines SET amountoutstanding= ?
124
     WHERE (accountlines_id = ?)"
125
        );
126
        $usth->execute( $newamtos, $thisacct );
127
128
        if ( C4::Context->preference("FinesLog") ) {
129
            $accdata->{'amountoutstanding_new'} = $newamtos;
130
            logaction("FINES", 'MODIFY', $borrowernumber, Dumper({
131
                action                => 'fee_payment',
132
                borrowernumber        => $accdata->{'borrowernumber'},
133
                old_amountoutstanding => $accdata->{'amountoutstanding'},
134
                new_amountoutstanding => $newamtos,
135
                amount_paid           => $accdata->{'amountoutstanding'} - $newamtos,
136
                accountlines_id       => $accdata->{'accountlines_id'},
137
                accountno             => $accdata->{'accountno'},
138
                manager_id            => $manager_id,
139
            }));
140
            push( @ids, $accdata->{'accountlines_id'} );
141
        }
142
    }
143
144
    # create new line
145
    my $usth = $dbh->prepare(
146
        "INSERT INTO accountlines
147
  (borrowernumber, accountno,date,amount,description,accounttype,amountoutstanding,manager_id)
148
  VALUES (?,?,now(),?,'Payment,thanks','Pay',?,?)"
149
    );
150
    $usth->execute( $borrowernumber, $nextaccntno, 0 - $data, 0 - $amountleft, $manager_id );
151
152
    UpdateStats( $branch, 'payment', $data, '', '', '', $borrowernumber, $nextaccntno );
153
154
    if ( C4::Context->preference("FinesLog") ) {
155
        $accdata->{'amountoutstanding_new'} = $newamtos;
156
        logaction("FINES", 'CREATE',$borrowernumber,Dumper({
157
            action            => 'create_payment',
158
            borrowernumber    => $borrowernumber,
159
            accountno         => $nextaccntno,
160
            amount            => $data * -1,
161
            amountoutstanding => $amountleft * -1,
162
            accounttype       => 'Pay',
163
            accountlines_paid => \@ids,
164
            manager_id        => $manager_id,
165
        }));
166
    }
167
168
}
169
170
=head2 makepayment
171
172
  &makepayment($accountlines_id, $borrowernumber, $acctnumber, $amount, $branchcode);
173
174
Records the fact that a patron has paid off the entire amount he or
175
she owes.
176
177
C<$borrowernumber> is the patron's borrower number. C<$acctnumber> is
178
the account that was credited. C<$amount> is the amount paid (this is
179
only used to record the payment. It is assumed to be equal to the
180
amount owed). C<$branchcode> is the code of the branch where payment
181
was made.
182
183
=cut
184
185
#'
186
# FIXME - I'm not at all sure about the above, because I don't
187
# understand what the acct* tables in the Koha database are for.
188
sub makepayment {
189
190
    #here we update both the accountoffsets and the account lines
191
    #updated to check, if they are paying off a lost item, we return the item
192
    # from their card, and put a note on the item record
193
    my ( $accountlines_id, $borrowernumber, $accountno, $amount, $user, $branch, $payment_note ) = @_;
194
    my $dbh = C4::Context->dbh;
195
    my $manager_id = 0;
196
    $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv; 
197
198
    # begin transaction
199
    my $nextaccntno = getnextacctno($borrowernumber);
200
    my $newamtos    = 0;
201
    my $sth         = $dbh->prepare("SELECT * FROM accountlines WHERE accountlines_id=?");
202
    $sth->execute( $accountlines_id );
203
    my $data = $sth->fetchrow_hashref;
204
205
    my $payment;
206
    if ( $data->{'accounttype'} eq "Pay" ){
207
        my $udp = 		
208
            $dbh->prepare(
209
                "UPDATE accountlines
210
                    SET amountoutstanding = 0, description = 'Payment,thanks'
211
                    WHERE accountlines_id = ?
212
                "
213
            );
214
        $udp->execute($accountlines_id);
215
    }else{
216
        my $udp = 		
217
            $dbh->prepare(
218
                "UPDATE accountlines
219
                    SET amountoutstanding = 0
220
                    WHERE accountlines_id = ?
221
                "
222
            );
223
        $udp->execute($accountlines_id);
224
225
         # create new line
226
        my $payment = 0 - $amount;
227
        $payment_note //= "";
228
        
229
        my $ins = 
230
            $dbh->prepare( 
231
                "INSERT 
232
                    INTO accountlines (borrowernumber, accountno, date, amount, itemnumber, description, accounttype, amountoutstanding, manager_id, note)
233
                    VALUES ( ?, ?, now(), ?, ?, 'Payment,thanks', 'Pay', 0, ?, ?)"
234
            );
235
        $ins->execute($borrowernumber, $nextaccntno, $payment, $data->{'itemnumber'}, $manager_id, $payment_note);
236
    }
237
238
    if ( C4::Context->preference("FinesLog") ) {
239
        logaction("FINES", 'MODIFY', $borrowernumber, Dumper({
240
            action                => 'fee_payment',
241
            borrowernumber        => $borrowernumber,
242
            old_amountoutstanding => $data->{'amountoutstanding'},
243
            new_amountoutstanding => 0,
244
            amount_paid           => $data->{'amountoutstanding'},
245
            accountlines_id       => $data->{'accountlines_id'},
246
            accountno             => $data->{'accountno'},
247
            manager_id            => $manager_id,
248
        }));
249
250
251
        logaction("FINES", 'CREATE',$borrowernumber,Dumper({
252
            action            => 'create_payment',
253
            borrowernumber    => $borrowernumber,
254
            accountno         => $nextaccntno,
255
            amount            => $payment,
256
            amountoutstanding => 0,,
257
            accounttype       => 'Pay',
258
            accountlines_paid => [$data->{'accountlines_id'}],
259
            manager_id        => $manager_id,
260
        }));
261
    }
262
263
264
    # FIXME - The second argument to &UpdateStats is supposed to be the
265
    # branch code.
266
    # UpdateStats is now being passed $accountno too. MTJ
267
    UpdateStats( $user, 'payment', $amount, '', '', '', $borrowernumber,
268
        $accountno );
269
270
    #check to see what accounttype
271
    if ( $data->{'accounttype'} eq 'Rep' || $data->{'accounttype'} eq 'L' ) {
272
        C4::Circulation::ReturnLostItem( $borrowernumber, $data->{'itemnumber'} );
273
    }
274
    my $sthr = $dbh->prepare("SELECT max(accountlines_id) AS lastinsertid FROM accountlines");
275
    $sthr->execute();
276
    my $datalastinsertid = $sthr->fetchrow_hashref;
277
    return $datalastinsertid->{'lastinsertid'};
278
}
279
280
=head2 getnextacctno
281
282
  $nextacct = &getnextacctno($borrowernumber);
283
284
Returns the next unused account number for the patron with the given
285
borrower number.
286
287
=cut
288
289
#'
290
# FIXME - Okay, so what does the above actually _mean_?
291
sub getnextacctno {
292
    my ($borrowernumber) = shift or return;
293
    my $sth = C4::Context->dbh->prepare(
294
        "SELECT accountno+1 FROM accountlines
295
            WHERE    (borrowernumber = ?)
296
            ORDER BY accountno DESC
297
            LIMIT 1"
298
    );
299
    $sth->execute($borrowernumber);
300
    return ($sth->fetchrow || 1);
301
}
302
303
=head2 fixaccounts (removed)
304
305
  &fixaccounts($accountlines_id, $borrowernumber, $accountnumber, $amount);
306
307
#'
308
# FIXME - I don't understand what this function does.
309
sub fixaccounts {
310
    my ( $accountlines_id, $borrowernumber, $accountno, $amount ) = @_;
311
    my $dbh = C4::Context->dbh;
312
    my $sth = $dbh->prepare(
313
        "SELECT * FROM accountlines WHERE accountlines_id=?"
314
    );
315
    $sth->execute( $accountlines_id );
316
    my $data = $sth->fetchrow_hashref;
317
318
    # FIXME - Error-checking
319
    my $diff        = $amount - $data->{'amount'};
320
    my $outstanding = $data->{'amountoutstanding'} + $diff;
321
    $sth->finish;
322
323
    $dbh->do(<<EOT);
324
        UPDATE  accountlines
325
        SET     amount = '$amount',
326
                amountoutstanding = '$outstanding'
327
        WHERE   accountlines_id = $accountlines_id
328
EOT
329
	# FIXME: exceedingly bad form.  Use prepare with placholders ("?") in query and execute args.
330
}
331
332
=cut
333
334
sub chargelostitem{
335
# lost ==1 Lost, lost==2 longoverdue, lost==3 lost and paid for
336
# FIXME: itemlost should be set to 3 after payment is made, should be a warning to the interface that
337
# a charge has been added
338
# FIXME : if no replacement price, borrower just doesn't get charged?
339
    my $dbh = C4::Context->dbh();
340
    my ($borrowernumber, $itemnumber, $amount, $description) = @_;
341
342
    # first make sure the borrower hasn't already been charged for this item
343
    my $sth1=$dbh->prepare("SELECT * from accountlines
344
    WHERE borrowernumber=? AND itemnumber=? and accounttype='L'");
345
    $sth1->execute($borrowernumber,$itemnumber);
346
    my $existing_charge_hashref=$sth1->fetchrow_hashref();
347
348
    # OK, they haven't
349
    unless ($existing_charge_hashref) {
350
        my $manager_id = 0;
351
        $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
352
        # This item is on issue ... add replacement cost to the borrower's record and mark it returned
353
        #  Note that we add this to the account even if there's no replacement price, allowing some other
354
        #  process (or person) to update it, since we don't handle any defaults for replacement prices.
355
        my $accountno = getnextacctno($borrowernumber);
356
        my $sth2=$dbh->prepare("INSERT INTO accountlines
357
        (borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding,itemnumber,manager_id)
358
        VALUES (?,?,now(),?,?,'L',?,?,?)");
359
        $sth2->execute($borrowernumber,$accountno,$amount,
360
        $description,$amount,$itemnumber,$manager_id);
361
362
        if ( C4::Context->preference("FinesLog") ) {
363
            logaction("FINES", 'CREATE', $borrowernumber, Dumper({
364
                action            => 'create_fee',
365
                borrowernumber    => $borrowernumber,
366
                accountno         => $accountno,
367
                amount            => $amount,
368
                amountoutstanding => $amount,
369
                description       => $description,
370
                accounttype       => 'L',
371
                itemnumber        => $itemnumber,
372
                manager_id        => $manager_id,
373
            }));
374
        }
375
376
    }
377
}
378
379
=head2 manualinvoice
380
381
  &manualinvoice($borrowernumber, $itemnumber, $description, $type,
382
                 $amount, $note);
383
384
C<$borrowernumber> is the patron's borrower number.
385
C<$description> is a description of the transaction.
386
C<$type> may be one of C<CS>, C<CB>, C<CW>, C<CF>, C<CL>, C<N>, C<L>,
387
or C<REF>.
388
C<$itemnumber> is the item involved, if pertinent; otherwise, it
389
should be the empty string.
390
391
=cut
392
393
#'
394
# FIXME: In Koha 3.0 , the only account adjustment 'types' passed to this function
395
# are :  
396
# 		'C' = CREDIT
397
# 		'FOR' = FORGIVEN  (Formerly 'F', but 'F' is taken to mean 'FINE' elsewhere)
398
# 		'N' = New Card fee
399
# 		'F' = Fine
400
# 		'A' = Account Management fee
401
# 		'M' = Sundry
402
# 		'L' = Lost Item
403
#
404
405
sub manualinvoice {
406
    my ( $borrowernumber, $itemnum, $desc, $type, $amount, $note ) = @_;
407
    my $manager_id = 0;
408
    $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
409
    my $dbh      = C4::Context->dbh;
410
    my $notifyid = 0;
411
    my $insert;
412
    my $accountno  = getnextacctno($borrowernumber);
413
    my $amountleft = $amount;
414
415
    if ( $type eq 'N' ) {
416
        $desc .= " New Card";
417
    }
418
    if ( $type eq 'F' ) {
419
        $desc .= " Fine";
420
    }
421
    if ( $type eq 'A' ) {
422
        $desc .= " Account Management fee";
423
    }
424
    if ( $type eq 'M' ) {
425
        $desc .= " Sundry";
426
    }
427
428
    if ( $type eq 'L' && $desc eq '' ) {
429
430
        $desc = " Lost Item";
431
    }
432
    if (   ( $type eq 'L' )
433
        or ( $type eq 'F' )
434
        or ( $type eq 'A' )
435
        or ( $type eq 'N' )
436
        or ( $type eq 'M' ) )
437
    {
438
        $notifyid = 1;
439
    }
440
441
    if ( $itemnum ) {
442
        $desc .= ' ' . $itemnum;
443
        my $sth = $dbh->prepare(
444
            'INSERT INTO  accountlines
445
                        (borrowernumber, accountno, date, amount, description, accounttype, amountoutstanding, itemnumber,notify_id, note, manager_id)
446
        VALUES (?, ?, now(), ?,?, ?,?,?,?,?,?)');
447
     $sth->execute($borrowernumber, $accountno, $amount, $desc, $type, $amountleft, $itemnum,$notifyid, $note, $manager_id) || return $sth->errstr;
448
  } else {
449
    my $sth=$dbh->prepare("INSERT INTO  accountlines
450
            (borrowernumber, accountno, date, amount, description, accounttype, amountoutstanding,notify_id, note, manager_id)
451
            VALUES (?, ?, now(), ?, ?, ?, ?,?,?,?)"
452
        );
453
        $sth->execute( $borrowernumber, $accountno, $amount, $desc, $type,
454
            $amountleft, $notifyid, $note, $manager_id );
455
    }
456
457
    if ( C4::Context->preference("FinesLog") ) {
458
        logaction("FINES", 'CREATE',$borrowernumber,Dumper({
459
            action            => 'create_fee',
460
            borrowernumber    => $borrowernumber,
461
            accountno         => $accountno,
462
            amount            => $amount,
463
            description       => $desc,
464
            accounttype       => $type,
465
            amountoutstanding => $amountleft,
466
            notify_id         => $notifyid,
467
            note              => $note,
468
            itemnumber        => $itemnum,
469
            manager_id        => $manager_id,
470
        }));
471
    }
472
473
    return 0;
474
}
475
476
sub getcharges {
477
	my ( $borrowerno, $timestamp, $accountno ) = @_;
478
	my $dbh        = C4::Context->dbh;
479
	my $timestamp2 = $timestamp - 1;
480
	my $query      = "";
481
	my $sth = $dbh->prepare(
482
			"SELECT * FROM accountlines WHERE borrowernumber=? AND accountno = ?"
483
          );
484
	$sth->execute( $borrowerno, $accountno );
485
	
486
    my @results;
487
    while ( my $data = $sth->fetchrow_hashref ) {
488
		push @results,$data;
489
	}
490
    return (@results);
491
}
492
493
sub ModNote {
494
    my ( $accountlines_id, $note ) = @_;
495
    my $dbh = C4::Context->dbh;
496
    my $sth = $dbh->prepare('UPDATE accountlines SET note = ? WHERE accountlines_id = ?');
497
    $sth->execute( $note, $accountlines_id );
498
}
499
500
sub getcredits {
501
	my ( $date, $date2 ) = @_;
502
	my $dbh = C4::Context->dbh;
503
	my $sth = $dbh->prepare(
504
			        "SELECT * FROM accountlines,borrowers
505
      WHERE amount < 0 AND accounttype <> 'Pay' AND accountlines.borrowernumber = borrowers.borrowernumber
506
	  AND timestamp >=TIMESTAMP(?) AND timestamp < TIMESTAMP(?)"
507
      );  
508
509
    $sth->execute( $date, $date2 );                                                                                                              
510
    my @results;          
511
    while ( my $data = $sth->fetchrow_hashref ) {
512
		$data->{'date'} = $data->{'timestamp'};
513
		push @results,$data;
514
	}
515
    return (@results);
516
} 
517
518
519
sub getrefunds {
520
	my ( $date, $date2 ) = @_;
521
	my $dbh = C4::Context->dbh;
522
	
523
	my $sth = $dbh->prepare(
524
			        "SELECT *,timestamp AS datetime                                                                                      
525
                  FROM accountlines,borrowers
526
                  WHERE (accounttype = 'REF'
527
					  AND accountlines.borrowernumber = borrowers.borrowernumber
528
					                  AND date  >=?  AND date  <?)"
529
    );
530
531
    $sth->execute( $date, $date2 );
532
533
    my @results;
534
    while ( my $data = $sth->fetchrow_hashref ) {
535
		push @results,$data;
536
		
537
	}
538
    return (@results);
539
}
540
541
sub ReversePayment {
542
    my ( $accountlines_id ) = @_;
543
    my $dbh = C4::Context->dbh;
544
545
    my $sth = $dbh->prepare('SELECT * FROM accountlines WHERE accountlines_id = ?');
546
    $sth->execute( $accountlines_id );
547
    my $row = $sth->fetchrow_hashref();
548
    my $amount_outstanding = $row->{'amountoutstanding'};
549
550
    if ( $amount_outstanding <= 0 ) {
551
        $sth = $dbh->prepare('UPDATE accountlines SET amountoutstanding = amount * -1, description = CONCAT( description, " Reversed -" ) WHERE accountlines_id = ?');
552
        $sth->execute( $accountlines_id );
553
    } else {
554
        $sth = $dbh->prepare('UPDATE accountlines SET amountoutstanding = 0, description = CONCAT( description, " Reversed -" ) WHERE accountlines_id = ?');
555
        $sth->execute( $accountlines_id );
556
    }
557
558
    if ( C4::Context->preference("FinesLog") ) {
559
        my $manager_id = 0;
560
        $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
561
562
        if ( $amount_outstanding <= 0 ) {
563
            $row->{'amountoutstanding'} *= -1;
564
        } else {
565
            $row->{'amountoutstanding'} = '0';
566
        }
567
        $row->{'description'} .= ' Reversed -';
568
        logaction("FINES", 'MODIFY', $row->{'borrowernumber'}, Dumper({
569
            action                => 'reverse_fee_payment',
570
            borrowernumber        => $row->{'borrowernumber'},
571
            old_amountoutstanding => $row->{'amountoutstanding'},
572
            new_amountoutstanding => 0 - $amount_outstanding,,
573
            accountlines_id       => $row->{'accountlines_id'},
574
            accountno             => $row->{'accountno'},
575
            manager_id            => $manager_id,
576
        }));
577
578
    }
579
580
}
581
582
=head2 recordpayment_selectaccts
583
584
  recordpayment_selectaccts($borrowernumber, $payment,$accts);
585
586
Record payment by a patron. C<$borrowernumber> is the patron's
587
borrower number. C<$payment> is a floating-point number, giving the
588
amount that was paid. C<$accts> is an array ref to a list of
589
accountnos which the payment can be recorded against
590
591
Amounts owed are paid off oldest first. That is, if the patron has a
592
$1 fine from Feb. 1, another $1 fine from Mar. 1, and makes a payment
593
of $1.50, then the oldest fine will be paid off in full, and $0.50
594
will be credited to the next one.
595
596
=cut
597
598
sub recordpayment_selectaccts {
599
    my ( $borrowernumber, $amount, $accts, $note ) = @_;
600
601
    my $dbh        = C4::Context->dbh;
602
    my $newamtos   = 0;
603
    my $accdata    = q{};
604
    my $branch     = C4::Context->userenv->{branch};
605
    my $amountleft = $amount;
606
    my $manager_id = 0;
607
    $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
608
    my $sql = 'SELECT * FROM accountlines WHERE (borrowernumber = ?) ' .
609
    'AND (amountoutstanding<>0) ';
610
    if (@{$accts} ) {
611
        $sql .= ' AND accountno IN ( ' .  join ',', @{$accts};
612
        $sql .= ' ) ';
613
    }
614
    $sql .= ' ORDER BY date';
615
    # begin transaction
616
    my $nextaccntno = getnextacctno($borrowernumber);
617
618
    # get lines with outstanding amounts to offset
619
    my $rows = $dbh->selectall_arrayref($sql, { Slice => {} }, $borrowernumber);
620
621
    # offset transactions
622
    my $sth     = $dbh->prepare('UPDATE accountlines SET amountoutstanding= ? ' .
623
        'WHERE accountlines_id=?');
624
625
    my @ids;
626
    for my $accdata ( @{$rows} ) {
627
        if ($amountleft == 0) {
628
            last;
629
        }
630
        if ( $accdata->{amountoutstanding} < $amountleft ) {
631
            $newamtos = 0;
632
            $amountleft -= $accdata->{amountoutstanding};
633
        }
634
        else {
635
            $newamtos   = $accdata->{amountoutstanding} - $amountleft;
636
            $amountleft = 0;
637
        }
638
        my $thisacct = $accdata->{accountlines_id};
639
        $sth->execute( $newamtos, $thisacct );
640
641
        if ( C4::Context->preference("FinesLog") ) {
642
            logaction("FINES", 'MODIFY', $borrowernumber, Dumper({
643
                action                => 'fee_payment',
644
                borrowernumber        => $borrowernumber,
645
                old_amountoutstanding => $accdata->{'amountoutstanding'},
646
                new_amountoutstanding => $newamtos,
647
                amount_paid           => $accdata->{'amountoutstanding'} - $newamtos,
648
                accountlines_id       => $accdata->{'accountlines_id'},
649
                accountno             => $accdata->{'accountno'},
650
                manager_id            => $manager_id,
651
            }));
652
            push( @ids, $accdata->{'accountlines_id'} );
653
        }
654
655
    }
656
657
    # create new line
658
    $sql = 'INSERT INTO accountlines ' .
659
    '(borrowernumber, accountno,date,amount,description,accounttype,amountoutstanding,manager_id,note) ' .
660
    q|VALUES (?,?,now(),?,'Payment,thanks','Pay',?,?,?)|;
661
    $dbh->do($sql,{},$borrowernumber, $nextaccntno, 0 - $amount, 0 - $amountleft, $manager_id, $note );
662
    UpdateStats( $branch, 'payment', $amount, '', '', '', $borrowernumber, $nextaccntno );
663
664
    if ( C4::Context->preference("FinesLog") ) {
665
        logaction("FINES", 'CREATE',$borrowernumber,Dumper({
666
            action            => 'create_payment',
667
            borrowernumber    => $borrowernumber,
668
            accountno         => $nextaccntno,
669
            amount            => 0 - $amount,
670
            amountoutstanding => 0 - $amountleft,
671
            accounttype       => 'Pay',
672
            accountlines_paid => \@ids,
673
            manager_id        => $manager_id,
674
        }));
675
    }
676
677
    return;
678
}
679
680
# makepayment needs to be fixed to handle partials till then this separate subroutine
681
# fills in
682
sub makepartialpayment {
683
    my ( $accountlines_id, $borrowernumber, $accountno, $amount, $user, $branch, $payment_note ) = @_;
684
    my $manager_id = 0;
685
    $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
686
    if (!$amount || $amount < 0) {
687
        return;
688
    }
689
    $payment_note //= "";
690
    my $dbh = C4::Context->dbh;
691
692
    my $nextaccntno = getnextacctno($borrowernumber);
693
    my $newamtos    = 0;
694
695
    my $data = $dbh->selectrow_hashref(
696
        'SELECT * FROM accountlines WHERE  accountlines_id=?',undef,$accountlines_id);
697
    my $new_outstanding = $data->{amountoutstanding} - $amount;
698
699
    my $update = 'UPDATE  accountlines SET amountoutstanding = ?  WHERE   accountlines_id = ? ';
700
    $dbh->do( $update, undef, $new_outstanding, $accountlines_id);
701
702
    if ( C4::Context->preference("FinesLog") ) {
703
        logaction("FINES", 'MODIFY', $borrowernumber, Dumper({
704
            action                => 'fee_payment',
705
            borrowernumber        => $borrowernumber,
706
            old_amountoutstanding => $data->{'amountoutstanding'},
707
            new_amountoutstanding => $new_outstanding,
708
            amount_paid           => $data->{'amountoutstanding'} - $new_outstanding,
709
            accountlines_id       => $data->{'accountlines_id'},
710
            accountno             => $data->{'accountno'},
711
            manager_id            => $manager_id,
712
        }));
713
    }
714
715
    # create new line
716
    my $insert = 'INSERT INTO accountlines (borrowernumber, accountno, date, amount, '
717
    .  'description, accounttype, amountoutstanding, itemnumber, manager_id, note) '
718
    . ' VALUES (?, ?, now(), ?, ?, ?, 0, ?, ?, ?)';
719
720
    $dbh->do(  $insert, undef, $borrowernumber, $nextaccntno, $amount,
721
        "Payment, thanks - $user", 'Pay', $data->{'itemnumber'}, $manager_id, $payment_note);
722
723
    UpdateStats( $user, 'payment', $amount, '', '', '', $borrowernumber, $accountno );
724
725
    if ( C4::Context->preference("FinesLog") ) {
726
        logaction("FINES", 'CREATE',$borrowernumber,Dumper({
727
            action            => 'create_payment',
728
            borrowernumber    => $user,
729
            accountno         => $nextaccntno,
730
            amount            => 0 - $amount,
731
            accounttype       => 'Pay',
732
            itemnumber        => $data->{'itemnumber'},
733
            accountlines_paid => [ $data->{'accountlines_id'} ],
734
            manager_id        => $manager_id,
735
        }));
736
    }
737
738
    return;
739
}
740
741
=head2 WriteOffFee
742
743
  WriteOffFee( $borrowernumber, $accountline_id, $itemnum, $accounttype, $amount, $branch, $payment_note );
744
745
Write off a fine for a patron.
746
C<$borrowernumber> is the patron's borrower number.
747
C<$accountline_id> is the accountline_id of the fee to write off.
748
C<$itemnum> is the itemnumber of of item whose fine is being written off.
749
C<$accounttype> is the account type of the fine being written off.
750
C<$amount> is a floating-point number, giving the amount that is being written off.
751
C<$branch> is the branchcode of the library where the writeoff occurred.
752
C<$payment_note> is the note to attach to this payment
753
754
=cut
755
756
sub WriteOffFee {
757
    my ( $borrowernumber, $accountlines_id, $itemnum, $accounttype, $amount, $branch, $payment_note ) = @_;
758
    $payment_note //= "";
759
    $branch ||= C4::Context->userenv->{branch};
760
    my $manager_id = 0;
761
    $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
762
763
    # if no item is attached to fine, make sure to store it as a NULL
764
    $itemnum ||= undef;
765
766
    my ( $sth, $query );
767
    my $dbh = C4::Context->dbh();
768
769
    $query = "
770
        UPDATE accountlines SET amountoutstanding = 0
771
        WHERE accountlines_id = ? AND borrowernumber = ?
772
    ";
773
    $sth = $dbh->prepare( $query );
774
    $sth->execute( $accountlines_id, $borrowernumber );
775
776
    if ( C4::Context->preference("FinesLog") ) {
777
        logaction("FINES", 'MODIFY', $borrowernumber, Dumper({
778
            action                => 'fee_writeoff',
779
            borrowernumber        => $borrowernumber,
780
            accountlines_id       => $accountlines_id,
781
            manager_id            => $manager_id,
782
        }));
783
    }
784
785
    $query ="
786
        INSERT INTO accountlines
787
        ( borrowernumber, accountno, itemnumber, date, amount, description, accounttype, manager_id, note )
788
        VALUES ( ?, ?, ?, NOW(), ?, 'Writeoff', 'W', ?, ? )
789
    ";
790
    $sth = $dbh->prepare( $query );
791
    my $acct = getnextacctno($borrowernumber);
792
    $sth->execute( $borrowernumber, $acct, $itemnum, $amount, $manager_id, $payment_note );
793
794
    if ( C4::Context->preference("FinesLog") ) {
795
        logaction("FINES", 'CREATE',$borrowernumber,Dumper({
796
            action            => 'create_writeoff',
797
            borrowernumber    => $borrowernumber,
798
            accountno         => $acct,
799
            amount            => 0 - $amount,
800
            accounttype       => 'W',
801
            itemnumber        => $itemnum,
802
            accountlines_paid => [ $accountlines_id ],
803
            manager_id        => $manager_id,
804
        }));
805
    }
806
807
    UpdateStats( $branch, 'writeoff', $amount, q{}, q{}, q{}, $borrowernumber );
808
809
}
810
811
END { }    # module clean-up code here (global destructor)
812
813
1;
814
__END__
815
816
=head1 SEE ALSO
817
818
DBI(3)
819
820
=cut
821
(-)a/C4/Circulation.pm (-166 / +145 lines)
Lines 30-36 use C4::Items; Link Here
30
use C4::Members;
30
use C4::Members;
31
use C4::Dates;
31
use C4::Dates;
32
use C4::Dates qw(format_date);
32
use C4::Dates qw(format_date);
33
use C4::Accounts;
33
use Koha::Accounts;
34
use C4::ItemCirculationAlertPreference;
34
use C4::ItemCirculationAlertPreference;
35
use C4::Message;
35
use C4::Message;
36
use C4::Debug;
36
use C4::Debug;
Lines 48-53 use Data::Dumper; Link Here
48
use Koha::DateUtils;
48
use Koha::DateUtils;
49
use Koha::Calendar;
49
use Koha::Calendar;
50
use Koha::Borrower::Debarments;
50
use Koha::Borrower::Debarments;
51
use Koha::Database;
51
use Carp;
52
use Carp;
52
use Date::Calc qw(
53
use Date::Calc qw(
53
  Today
54
  Today
Lines 1275-1281 sub AddIssue { Link Here
1275
        ## If item was lost, it has now been found, reverse any list item charges if neccessary.
1276
        ## If item was lost, it has now been found, reverse any list item charges if neccessary.
1276
        if ( $item->{'itemlost'} ) {
1277
        if ( $item->{'itemlost'} ) {
1277
            if ( C4::Context->preference('RefundLostItemFeeOnReturn' ) ) {
1278
            if ( C4::Context->preference('RefundLostItemFeeOnReturn' ) ) {
1278
                _FixAccountForLostAndReturned( $item->{'itemnumber'}, undef, $item->{'barcode'} );
1279
                _FixAccountForLostAndReturned( $item->{'itemnumber'} );
1279
            }
1280
            }
1280
        }
1281
        }
1281
1282
Lines 1812-1820 sub AddReturn { Link Here
1812
                if ( $amount > 0
1813
                if ( $amount > 0
1813
                    && C4::Context->preference('finesMode') eq 'production' )
1814
                    && C4::Context->preference('finesMode') eq 'production' )
1814
                {
1815
                {
1815
                    C4::Overdues::UpdateFine( $issue->{itemnumber},
1816
                    C4::Overdues::UpdateFine(
1816
                        $issue->{borrowernumber},
1817
                        {
1817
                        $amount, $type, output_pref($datedue) );
1818
                            itemnumber     => $issue->{itemnumber},
1819
                            borrowernumber => $issue->{borrowernumber},
1820
                            amount         => $amount,
1821
                            due            => output_pref($datedue),
1822
                            issue_id       => $issue->{issue_id}
1823
                        }
1824
                    );
1818
                }
1825
                }
1819
            }
1826
            }
1820
1827
Lines 1864-1881 sub AddReturn { Link Here
1864
        $messages->{'WasLost'} = 1;
1871
        $messages->{'WasLost'} = 1;
1865
1872
1866
        if ( C4::Context->preference('RefundLostItemFeeOnReturn' ) ) {
1873
        if ( C4::Context->preference('RefundLostItemFeeOnReturn' ) ) {
1867
            _FixAccountForLostAndReturned($item->{'itemnumber'}, $borrowernumber, $barcode);    # can tolerate undef $borrowernumber
1874
            _FixAccountForLostAndReturned( $item->{'itemnumber'} );
1868
            $messages->{'LostItemFeeRefunded'} = 1;
1875
            $messages->{'LostItemFeeRefunded'} = 1;
1869
        }
1876
        }
1870
    }
1877
    }
1871
1878
1872
    # fix up the overdues in accounts...
1879
    # fix up the overdues in accounts...
1873
    if ($borrowernumber) {
1880
    if ($borrowernumber) {
1874
        my $fix = _FixOverduesOnReturn($borrowernumber, $item->{itemnumber}, $exemptfine, $dropbox);
1881
        _FixOverduesOnReturn(
1875
        defined($fix) or warn "_FixOverduesOnReturn($borrowernumber, $item->{itemnumber}...) failed!";  # zero is OK, check defined
1882
            {
1883
                exempt_fine => $exemptfine,
1884
                dropbox     => $dropbox,
1885
                issue       => $issue,
1886
            }
1887
        );
1876
        
1888
        
1877
        if ( $issue->{overdue} && $issue->{date_due} ) {
1889
        if ( $issue->{overdue} && $issue->{date_due} ) {
1878
# fix fine days
1890
            # fix fine days
1879
            my $debardate =
1891
            my $debardate =
1880
              _debar_user_on_return( $borrower, $item, $issue->{date_due}, $today );
1892
              _debar_user_on_return( $borrower, $item, $issue->{date_due}, $today );
1881
            $messages->{Debarred} = $debardate if ($debardate);
1893
            $messages->{Debarred} = $debardate if ($debardate);
Lines 2093-2231 Internal function, called only by AddReturn Link Here
2093
=cut
2105
=cut
2094
2106
2095
sub _FixOverduesOnReturn {
2107
sub _FixOverduesOnReturn {
2096
    my ($borrowernumber, $item);
2108
    my ( $params ) = @_;
2097
    unless ($borrowernumber = shift) {
2109
2098
        warn "_FixOverduesOnReturn() not supplied valid borrowernumber";
2110
    my $exemptfine = $params->{exempt_fine};
2099
        return;
2111
    my $dropbox    = $params->{dropbox};
2100
    }
2112
    my $issue      = $params->{issue};
2101
    unless ($item = shift) {
2113
2102
        warn "_FixOverduesOnReturn() not supplied valid itemnumber";
2103
        return;
2104
    }
2105
    my ($exemptfine, $dropbox) = @_;
2106
    my $dbh = C4::Context->dbh;
2114
    my $dbh = C4::Context->dbh;
2107
2115
2108
    # check for overdue fine
2116
    my $schema = Koha::Database->new()->schema;
2109
    my $sth = $dbh->prepare(
2117
    my $fine =
2110
"SELECT * FROM accountlines WHERE (borrowernumber = ?) AND (itemnumber = ?) AND (accounttype='FU' OR accounttype='O')"
2118
      $schema->resultset('AccountDebit')
2111
    );
2119
      ->single( { issue_id => $issue->issue_id(), type => Koha::Accounts::DebitTypes::Fine() } );
2112
    $sth->execute( $borrowernumber, $item );
2113
2120
2114
    # alter fine to show that the book has been returned
2121
    return unless ( $fine );
2115
    my $data = $sth->fetchrow_hashref;
2122
2116
    return 0 unless $data;    # no warning, there's just nothing to fix
2123
    $fine->accruing(0);
2117
2124
2118
    my $uquery;
2119
    my @bind = ($data->{'accountlines_id'});
2120
    if ($exemptfine) {
2125
    if ($exemptfine) {
2121
        $uquery = "update accountlines set accounttype='FFOR', amountoutstanding=0";
2126
        AddCredit(
2122
        if (C4::Context->preference("FinesLog")) {
2127
            {
2123
            &logaction("FINES", 'MODIFY',$borrowernumber,"Overdue forgiven: item $item");
2128
                borrower => $fine->borrowernumber(),
2124
        }
2129
                amount   => $fine->amount_original(),
2125
    } elsif ($dropbox && $data->{lastincrement}) {
2130
                debit_id => $fine->debit_id(),
2126
        my $outstanding = $data->{amountoutstanding} - $data->{lastincrement} ;
2131
                type     => Koha::Accounts::CreditTypes::Forgiven(),
2127
        my $amt = $data->{amount} - $data->{lastincrement} ;
2132
            }
2133
        );
2128
        if (C4::Context->preference("FinesLog")) {
2134
        if (C4::Context->preference("FinesLog")) {
2129
            &logaction("FINES", 'MODIFY',$borrowernumber,"Dropbox adjustment $amt, item $item");
2135
            &logaction(
2136
                "FINES", 'MODIFY',
2137
                $issue->borrowernumber(),
2138
                "Overdue forgiven: item " . $issue->itemnumber()
2139
            );
2130
        }
2140
        }
2131
         $uquery = "update accountlines set accounttype='F' ";
2141
    } elsif ($dropbox && $fine->amount_last_increment() != $fine->amount_original() ) {
2132
         if($outstanding  >= 0 && $amt >=0) {
2142
        if ( C4::Context->preference("FinesLog") ) {
2133
            $uquery .= ", amount = ? , amountoutstanding=? ";
2143
            &logaction( "FINES", 'MODIFY', $issue->borrowernumber(),
2134
            unshift @bind, ($amt, $outstanding) ;
2144
                    "Dropbox adjustment "
2145
                  . $fine->amount_last_increment()
2146
                  . ", item " . $issue->itemnumber() );
2135
        }
2147
        }
2136
    } else {
2148
        $fine->amount_original(
2137
        $uquery = "update accountlines set accounttype='F' ";
2149
            $fine->amount_original() - $fine->amount_last_increment() );
2150
        $fine->amount_outstanding(
2151
            $fine->amount_outstanding - $fine->amount_last_increment() );
2152
        $schema->resultset('AccountOffset')->create(
2153
            {
2154
                debit_id => $fine->debit_id(),
2155
                type     => Koha::Accounts::OffsetTypes::Dropbox(),
2156
                amount   => $fine->amount_last_increment() * -1,
2157
            }
2158
        );
2138
    }
2159
    }
2139
    $uquery .= " where (accountlines_id = ?)";
2160
2140
    my $usth = $dbh->prepare($uquery);
2161
    return $fine->update();
2141
    return $usth->execute(@bind);
2142
}
2162
}
2143
2163
2144
=head2 _FixAccountForLostAndReturned
2164
=head2 _FixAccountForLostAndReturned
2145
2165
2146
  &_FixAccountForLostAndReturned($itemnumber, [$borrowernumber, $barcode]);
2166
  &_FixAccountForLostAndReturned($itemnumber);
2147
2148
Calculates the charge for a book lost and returned.
2149
2167
2150
Internal function, not exported, called only by AddReturn.
2168
  Refunds a lost item fee in necessary
2151
2152
FIXME: This function reflects how inscrutable fines logic is.  Fix both.
2153
FIXME: Give a positive return value on success.  It might be the $borrowernumber who received credit, or the amount forgiven.
2154
2169
2155
=cut
2170
=cut
2156
2171
2157
sub _FixAccountForLostAndReturned {
2172
sub _FixAccountForLostAndReturned {
2158
    my $itemnumber     = shift or return;
2173
    my ( $itemnumber ) = @_;
2159
    my $borrowernumber = @_ ? shift : undef;
2174
2160
    my $item_id        = @_ ? shift : $itemnumber;  # Send the barcode if you want that logged in the description
2175
    my $schema = Koha::Database->new()->schema;
2161
    my $dbh = C4::Context->dbh;
2176
2162
    # check for charge made for lost book
2177
    # Find the last issue for this item
2163
    my $sth = $dbh->prepare("SELECT * FROM accountlines WHERE itemnumber = ? AND accounttype IN ('L', 'Rep', 'W') ORDER BY date DESC, accountno DESC");
2178
    my $issue =
2164
    $sth->execute($itemnumber);
2179
      $schema->resultset('Issue')->single( { itemnumber => $itemnumber } );
2165
    my $data = $sth->fetchrow_hashref;
2180
    $issue ||=
2166
    $data or return;    # bail if there is nothing to do
2181
      $schema->resultset('OldIssue')->single( { itemnumber => $itemnumber } );
2167
    $data->{accounttype} eq 'W' and return;    # Written off
2182
2168
2183
    return unless $issue;
2169
    # writeoff this amount
2184
2170
    my $offset;
2185
    # Find a lost fee for this issue
2171
    my $amount = $data->{'amount'};
2186
    my $debit = $schema->resultset('AccountDebit')->single(
2172
    my $acctno = $data->{'accountno'};
2187
        {
2173
    my $amountleft;                                             # Starts off undef/zero.
2188
            issue_id => $issue->issue_id(),
2174
    if ($data->{'amountoutstanding'} == $amount) {
2189
            type     => Koha::Accounts::DebitTypes::Lost()
2175
        $offset     = $data->{'amount'};
2176
        $amountleft = 0;                                        # Hey, it's zero here, too.
2177
    } else {
2178
        $offset     = $amount - $data->{'amountoutstanding'};   # Um, isn't this the same as ZERO?  We just tested those two things are ==
2179
        $amountleft = $data->{'amountoutstanding'} - $amount;   # Um, isn't this the same as ZERO?  We just tested those two things are ==
2180
    }
2181
    my $usth = $dbh->prepare("UPDATE accountlines SET accounttype = 'LR',amountoutstanding='0'
2182
        WHERE (accountlines_id = ?)");
2183
    $usth->execute($data->{'accountlines_id'});      # We might be adjusting an account for some OTHER borrowernumber now.  Not the one we passed in.
2184
    #check if any credit is left if so writeoff other accounts
2185
    my $nextaccntno = getnextacctno($data->{'borrowernumber'});
2186
    $amountleft *= -1 if ($amountleft < 0);
2187
    if ($amountleft > 0) {
2188
        my $msth = $dbh->prepare("SELECT * FROM accountlines WHERE (borrowernumber = ?)
2189
                            AND (amountoutstanding >0) ORDER BY date");     # might want to order by amountoustanding ASC (pay smallest first)
2190
        $msth->execute($data->{'borrowernumber'});
2191
        # offset transactions
2192
        my $newamtos;
2193
        my $accdata;
2194
        while (($accdata=$msth->fetchrow_hashref) and ($amountleft>0)){
2195
            if ($accdata->{'amountoutstanding'} < $amountleft) {
2196
                $newamtos = 0;
2197
                $amountleft -= $accdata->{'amountoutstanding'};
2198
            }  else {
2199
                $newamtos = $accdata->{'amountoutstanding'} - $amountleft;
2200
                $amountleft = 0;
2201
            }
2202
            my $thisacct = $accdata->{'accountlines_id'};
2203
            # FIXME: move prepares outside while loop!
2204
            my $usth = $dbh->prepare("UPDATE accountlines SET amountoutstanding= ?
2205
                    WHERE (accountlines_id = ?)");
2206
            $usth->execute($newamtos,$thisacct);
2207
            $usth = $dbh->prepare("INSERT INTO accountoffsets
2208
                (borrowernumber, accountno, offsetaccount,  offsetamount)
2209
                VALUES
2210
                (?,?,?,?)");
2211
            $usth->execute($data->{'borrowernumber'},$accdata->{'accountno'},$nextaccntno,$newamtos);
2212
        }
2190
        }
2213
    }
2191
    );
2214
    $amountleft *= -1 if ($amountleft > 0);
2192
2215
    my $desc = "Item Returned " . $item_id;
2193
    return unless $debit;
2216
    $usth = $dbh->prepare("INSERT INTO accountlines
2194
2217
        (borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding)
2195
    # Check for an existing found credit for this debit, if there is one, the fee has already been refunded and we do nothing
2218
        VALUES (?,?,now(),?,?,'CR',?)");
2196
    my @credits = $debit->account_offsets->search_related('credit', { 'credit.type' => Koha::Accounts::CreditTypes::Found() });
2219
    $usth->execute($data->{'borrowernumber'},$nextaccntno,0-$amount,$desc,$amountleft);
2197
2220
    if ($borrowernumber) {
2198
    return if @credits;
2221
        # FIXME: same as query above.  use 1 sth for both
2199
2222
        $usth = $dbh->prepare("INSERT INTO accountoffsets
2200
    # Ok, so we know we have an unrefunded lost item fee, let's refund it
2223
            (borrowernumber, accountno, offsetaccount,  offsetamount)
2201
    CreditLostItem(
2224
            VALUES (?,?,?,?)");
2202
        {
2225
        $usth->execute($borrowernumber, $data->{'accountno'}, $nextaccntno, $offset);
2203
            borrower => $issue->borrower(),
2226
    }
2204
            debit    => $debit
2205
        }
2206
    );
2207
2227
    ModItem({ paidfor => '' }, undef, $itemnumber);
2208
    ModItem({ paidfor => '' }, undef, $itemnumber);
2228
    return;
2229
}
2209
}
2230
2210
2231
=head2 _GetCircControlBranch
2211
=head2 _GetCircControlBranch
Lines 2584-2602 sub AddRenewal { Link Here
2584
    # Charge a new rental fee, if applicable?
2564
    # Charge a new rental fee, if applicable?
2585
    my ( $charge, $type ) = GetIssuingCharges( $itemnumber, $borrowernumber );
2565
    my ( $charge, $type ) = GetIssuingCharges( $itemnumber, $borrowernumber );
2586
    if ( $charge > 0 ) {
2566
    if ( $charge > 0 ) {
2587
        my $accountno = getnextacctno( $borrowernumber );
2588
        my $item = GetBiblioFromItemNumber($itemnumber);
2567
        my $item = GetBiblioFromItemNumber($itemnumber);
2589
        my $manager_id = 0;
2568
2590
        $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv; 
2569
        my $borrower =
2591
        $sth = $dbh->prepare(
2570
          Koha::Database->new()->schema->resultset('Borrower')
2592
                "INSERT INTO accountlines
2571
          ->find($borrowernumber);
2593
                    (date, borrowernumber, accountno, amount, manager_id,
2572
2594
                    description,accounttype, amountoutstanding, itemnumber)
2573
        AddDebit(
2595
                    VALUES (now(),?,?,?,?,?,?,?,?)"
2574
            {
2575
                borrower   => $borrower,
2576
                itemnumber => $itemnumber,
2577
                amount     => $charge,
2578
                type       => Koha::Accounts::DebitTypes::Rental(),
2579
                description =>
2580
                  "Renewal of Rental Item $item->{'title'} $item->{'barcode'}"
2581
            }
2596
        );
2582
        );
2597
        $sth->execute( $borrowernumber, $accountno, $charge, $manager_id,
2598
            "Renewal of Rental Item $item->{'title'} $item->{'barcode'}",
2599
            'Rent', $charge, $itemnumber );
2600
    }
2583
    }
2601
2584
2602
    # Send a renewal slip according to checkout alert preferencei
2585
    # Send a renewal slip according to checkout alert preferencei
Lines 2767-2791 sub _get_discount_from_rule { Link Here
2767
2750
2768
=head2 AddIssuingCharge
2751
=head2 AddIssuingCharge
2769
2752
2770
  &AddIssuingCharge( $itemno, $borrowernumber, $charge )
2753
  &AddIssuingCharge( $itemnumber, $borrowernumber, $amount )
2771
2754
2772
=cut
2755
=cut
2773
2756
2774
sub AddIssuingCharge {
2757
sub AddIssuingCharge {
2775
    my ( $itemnumber, $borrowernumber, $charge ) = @_;
2758
    my ( $itemnumber, $borrowernumber, $amount ) = @_;
2776
    my $dbh = C4::Context->dbh;
2759
2777
    my $nextaccntno = getnextacctno( $borrowernumber );
2760
    return AddDebit(
2778
    my $manager_id = 0;
2761
        {
2779
    $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
2762
            borrower       => Koha::Database->new()->schema->resultset('Borrower')->find($borrowernumber),
2780
    my $query ="
2763
            itemnumber     => $itemnumber,
2781
        INSERT INTO accountlines
2764
            amount         => $amount,
2782
            (borrowernumber, itemnumber, accountno,
2765
            type           => Koha::Accounts::DebitTypes::Rental(),
2783
            date, amount, description, accounttype,
2766
        }
2784
            amountoutstanding, manager_id)
2767
    );
2785
        VALUES (?, ?, ?,now(), ?, 'Rental', 'Rent',?,?)
2786
    ";
2787
    my $sth = $dbh->prepare($query);
2788
    $sth->execute( $borrowernumber, $itemnumber, $nextaccntno, $charge, $charge, $manager_id );
2789
}
2768
}
2790
2769
2791
=head2 GetTransfers
2770
=head2 GetTransfers
Lines 3304-3333 sub ReturnLostItem{ Link Here
3304
sub LostItem{
3283
sub LostItem{
3305
    my ($itemnumber, $mark_returned) = @_;
3284
    my ($itemnumber, $mark_returned) = @_;
3306
3285
3307
    my $dbh = C4::Context->dbh();
3286
    my $schema = Koha::Database->new()->schema;
3308
    my $sth=$dbh->prepare("SELECT issues.*,items.*,biblio.title 
3309
                           FROM issues 
3310
                           JOIN items USING (itemnumber) 
3311
                           JOIN biblio USING (biblionumber)
3312
                           WHERE issues.itemnumber=?");
3313
    $sth->execute($itemnumber);
3314
    my $issues=$sth->fetchrow_hashref();
3315
3287
3316
    # If a borrower lost the item, add a replacement cost to the their record
3288
    my $issue =
3317
    if ( my $borrowernumber = $issues->{borrowernumber} ){
3289
      $schema->resultset('Issue')->single( { itemnumber => $itemnumber } );
3318
        my $borrower = C4::Members::GetMemberDetails( $borrowernumber );
3319
3290
3291
    my $borrower = $issue->borrower();
3292
    my $item     = $issue->item();
3293
3294
    # If a borrower lost the item, add a replacement cost to the their record
3295
    if ( $borrower ){
3320
        if (C4::Context->preference('WhenLostForgiveFine')){
3296
        if (C4::Context->preference('WhenLostForgiveFine')){
3321
            my $fix = _FixOverduesOnReturn($borrowernumber, $itemnumber, 1, 0); # 1, 0 = exemptfine, no-dropbox
3297
            _FixOverduesOnReturn(
3322
            defined($fix) or warn "_FixOverduesOnReturn($borrowernumber, $itemnumber...) failed!";  # zero is OK, check defined
3298
                {
3299
                    exempt_fine => 1,
3300
                    dropbox     => 0,
3301
                    issue       => $issue,
3302
                }
3303
            );
3323
        }
3304
        }
3324
        if (C4::Context->preference('WhenLostChargeReplacementFee')){
3305
        if ( C4::Context->preference('WhenLostChargeReplacementFee') ) {
3325
            C4::Accounts::chargelostitem($borrowernumber, $itemnumber, $issues->{'replacementprice'}, "Lost Item $issues->{'title'} $issues->{'barcode'}");
3306
            DebitLostItem( { borrower => $borrower, issue => $issue } );
3326
            #FIXME : Should probably have a way to distinguish this from an item that really was returned.
3327
            #warn " $issues->{'borrowernumber'}  /  $itemnumber ";
3328
        }
3307
        }
3329
3308
3330
        MarkIssueReturned($borrowernumber,$itemnumber,undef,undef,$borrower->{'privacy'}) if $mark_returned;
3309
        MarkIssueReturned( $borrower->borrowernumber(), $item->itemnumber(), undef, undef, $borrower->privacy() ) if $mark_returned;
3331
    }
3310
    }
3332
}
3311
}
3333
3312
(-)a/C4/Members.pm (-74 / +38 lines)
Lines 29-35 use Date::Calc qw/Today Add_Delta_YM check_date Date_to_Days/; Link Here
29
use C4::Log; # logaction
29
use C4::Log; # logaction
30
use C4::Overdues;
30
use C4::Overdues;
31
use C4::Reserves;
31
use C4::Reserves;
32
use C4::Accounts;
33
use C4::Biblio;
32
use C4::Biblio;
34
use C4::Letters;
33
use C4::Letters;
35
use C4::SQLHelper qw(InsertInTable UpdateInTable SearchInTable);
34
use C4::SQLHelper qw(InsertInTable UpdateInTable SearchInTable);
Lines 41-46 use Koha::DateUtils; Link Here
41
use Koha::Borrower::Debarments qw(IsDebarred);
40
use Koha::Borrower::Debarments qw(IsDebarred);
42
use Text::Unaccent qw( unac_string );
41
use Text::Unaccent qw( unac_string );
43
use Koha::AuthUtils qw(hash_password);
42
use Koha::AuthUtils qw(hash_password);
43
use Koha::Accounts::DebitTypes;
44
44
45
our ($VERSION,@ISA,@EXPORT,@EXPORT_OK,$debug);
45
our ($VERSION,@ISA,@EXPORT,@EXPORT_OK,$debug);
46
46
Lines 83-89 BEGIN { Link Here
83
        &GetHideLostItemsPreference
83
        &GetHideLostItemsPreference
84
84
85
        &IsMemberBlocked
85
        &IsMemberBlocked
86
        &GetMemberAccountRecords
87
        &GetBorNotifyAcctRecord
86
        &GetBorNotifyAcctRecord
88
87
89
        &GetborCatFromCatType
88
        &GetborCatFromCatType
Lines 338-346 sub GetMemberDetails { Link Here
338
        return;
337
        return;
339
    }
338
    }
340
    my $borrower = $sth->fetchrow_hashref;
339
    my $borrower = $sth->fetchrow_hashref;
341
    my ($amount) = GetMemberAccountRecords( $borrowernumber);
342
    $borrower->{'amountoutstanding'} = $amount;
343
    # FIXME - patronflags calls GetMemberAccountRecords... just have patronflags return $amount
344
    my $flags = patronflags( $borrower);
340
    my $flags = patronflags( $borrower);
345
    my $accessflagshash;
341
    my $accessflagshash;
346
342
Lines 432-454 The "message" field that comes from the DB is OK. Link Here
432
# FIXME rename this function.
428
# FIXME rename this function.
433
sub patronflags {
429
sub patronflags {
434
    my %flags;
430
    my %flags;
435
    my ( $patroninformation) = @_;
431
    my ($patroninformation) = @_;
436
    my $dbh=C4::Context->dbh;
432
    my $dbh = C4::Context->dbh;
437
    my ($balance, $owing) = GetMemberAccountBalance( $patroninformation->{'borrowernumber'});
433
    if ( $patroninformation->{account_balance} > 0 ) {
438
    if ( $owing > 0 ) {
439
        my %flaginfo;
434
        my %flaginfo;
440
        my $noissuescharge = C4::Context->preference("noissuescharge") || 5;
435
        my $noissuescharge = C4::Context->preference("noissuescharge") || 5;
441
        $flaginfo{'message'} = sprintf 'Patron owes %.02f', $owing;
436
        $flaginfo{'amount'}  = $patroninformation->{account_balance};
442
        $flaginfo{'amount'}  = sprintf "%.02f", $owing;
437
        if (  $patroninformation->{account_balance} > $noissuescharge && !C4::Context->preference("AllowFineOverride") ) {
443
        if ( $owing > $noissuescharge && !C4::Context->preference("AllowFineOverride") ) {
444
            $flaginfo{'noissues'} = 1;
438
            $flaginfo{'noissues'} = 1;
445
        }
439
        }
446
        $flags{'CHARGES'} = \%flaginfo;
440
        $flags{'CHARGES'} = \%flaginfo;
447
    }
441
    }
448
    elsif ( $balance < 0 ) {
442
    elsif ( $patroninformation->{account_balance} < 0 ) {
449
        my %flaginfo;
443
        my %flaginfo;
450
        $flaginfo{'message'} = sprintf 'Patron has credit of %.02f', -$balance;
444
        $flaginfo{'amount'}  = $patroninformation->{account_balance};
451
        $flaginfo{'amount'}  = sprintf "%.02f", $balance;
452
        $flags{'CREDITS'} = \%flaginfo;
445
        $flags{'CREDITS'} = \%flaginfo;
453
    }
446
    }
454
    if (   $patroninformation->{'gonenoaddress'}
447
    if (   $patroninformation->{'gonenoaddress'}
Lines 691-697 sub GetMemberIssuesAndFines { Link Here
691
    $sth->execute($borrowernumber);
684
    $sth->execute($borrowernumber);
692
    my $overdue_count = $sth->fetchrow_arrayref->[0];
685
    my $overdue_count = $sth->fetchrow_arrayref->[0];
693
686
694
    $sth = $dbh->prepare("SELECT SUM(amountoutstanding) FROM accountlines WHERE borrowernumber = ?");
687
    $sth = $dbh->prepare("SELECT account_balance FROM borrowers WHERE borrowernumber = ?");
695
    $sth->execute($borrowernumber);
688
    $sth->execute($borrowernumber);
696
    my $total_fines = $sth->fetchrow_arrayref->[0];
689
    my $total_fines = $sth->fetchrow_arrayref->[0];
697
690
Lines 1167-1223 sub GetAllIssues { Link Here
1167
}
1160
}
1168
1161
1169
1162
1170
=head2 GetMemberAccountRecords
1171
1172
  ($total, $acctlines, $count) = &GetMemberAccountRecords($borrowernumber);
1173
1174
Looks up accounting data for the patron with the given borrowernumber.
1175
1176
C<&GetMemberAccountRecords> returns a three-element array. C<$acctlines> is a
1177
reference-to-array, where each element is a reference-to-hash; the
1178
keys are the fields of the C<accountlines> table in the Koha database.
1179
C<$count> is the number of elements in C<$acctlines>. C<$total> is the
1180
total amount outstanding for all of the account lines.
1181
1182
=cut
1183
1184
sub GetMemberAccountRecords {
1185
    my ($borrowernumber) = @_;
1186
    my $dbh = C4::Context->dbh;
1187
    my @acctlines;
1188
    my $numlines = 0;
1189
    my $strsth      = qq(
1190
                        SELECT * 
1191
                        FROM accountlines 
1192
                        WHERE borrowernumber=?);
1193
    $strsth.=" ORDER BY date desc,timestamp DESC";
1194
    my $sth= $dbh->prepare( $strsth );
1195
    $sth->execute( $borrowernumber );
1196
1197
    my $total = 0;
1198
    while ( my $data = $sth->fetchrow_hashref ) {
1199
        if ( $data->{itemnumber} ) {
1200
            my $biblio = GetBiblioFromItemNumber( $data->{itemnumber} );
1201
            $data->{biblionumber} = $biblio->{biblionumber};
1202
            $data->{title}        = $biblio->{title};
1203
        }
1204
        $acctlines[$numlines] = $data;
1205
        $numlines++;
1206
        $total += int(1000 * $data->{'amountoutstanding'}); # convert float to integer to avoid round-off errors
1207
    }
1208
    $total /= 1000;
1209
    return ( $total, \@acctlines,$numlines);
1210
}
1211
1212
=head2 GetMemberAccountBalance
1163
=head2 GetMemberAccountBalance
1213
1164
1214
  ($total_balance, $non_issue_balance, $other_charges) = &GetMemberAccountBalance($borrowernumber);
1165
  ($total_balance, $non_issue_balance, $other_charges) = &GetMemberAccountBalance($borrowernumber);
1215
1166
1216
Calculates amount immediately owing by the patron - non-issue charges.
1167
Calculates amount immediately owing by the patron - non-issue charges.
1217
Based on GetMemberAccountRecords.
1218
Charges exempt from non-issue are:
1168
Charges exempt from non-issue are:
1219
* Res (reserves)
1169
* HOLD fees (reserves)
1220
* Rent (rental) if RentalsInNoissuesCharge syspref is set to false
1170
* RENTAL if RentalsInNoissuesCharge syspref is set to false
1221
* Manual invoices if ManInvInNoissuesCharge syspref is set to false
1171
* Manual invoices if ManInvInNoissuesCharge syspref is set to false
1222
1172
1223
=cut
1173
=cut
Lines 1225-1248 Charges exempt from non-issue are: Link Here
1225
sub GetMemberAccountBalance {
1175
sub GetMemberAccountBalance {
1226
    my ($borrowernumber) = @_;
1176
    my ($borrowernumber) = @_;
1227
1177
1228
    my $ACCOUNT_TYPE_LENGTH = 5; # this is plain ridiculous...
1178
    my $borrower =
1179
      Koha::Database->new()->schema->resultset('Borrower')
1180
      ->find($borrowernumber);
1181
1182
    my @not_fines;
1183
1184
    push( @not_fines, Koha::Accounts::DebitTypes::Hold() );
1185
1186
    push( @not_fines, Koha::Accounts::DebitTypes::Rental() )
1187
      unless C4::Context->preference('RentalsInNoissuesCharge');
1229
1188
1230
    my @not_fines = ('Res');
1231
    push @not_fines, 'Rent' unless C4::Context->preference('RentalsInNoissuesCharge');
1232
    unless ( C4::Context->preference('ManInvInNoissuesCharge') ) {
1189
    unless ( C4::Context->preference('ManInvInNoissuesCharge') ) {
1233
        my $dbh = C4::Context->dbh;
1190
        my $dbh           = C4::Context->dbh;
1234
        my $man_inv_types = $dbh->selectcol_arrayref(qq{SELECT authorised_value FROM authorised_values WHERE category = 'MANUAL_INV'});
1191
        my $man_inv_types = $dbh->selectcol_arrayref(
1235
        push @not_fines, map substr($_, 0, $ACCOUNT_TYPE_LENGTH), @$man_inv_types;
1192
            qq{SELECT authorised_value FROM authorised_values WHERE category = 'MANUAL_INV'}
1193
        );
1194
        push( @not_fines, @$man_inv_types );
1236
    }
1195
    }
1237
    my %not_fine = map {$_ => 1} @not_fines;
1238
1196
1239
    my ($total, $acctlines) = GetMemberAccountRecords($borrowernumber);
1197
    my $other_charges =
1240
    my $other_charges = 0;
1198
      Koha::Database->new()->schema->resultset('AccountDebit')->search(
1241
    foreach (@$acctlines) {
1199
        {
1242
        $other_charges += $_->{amountoutstanding} if $not_fine{ substr($_->{accounttype}, 0, $ACCOUNT_TYPE_LENGTH) };
1200
            borrowernumber => $borrowernumber,
1243
    }
1201
            type           => { -not_in => \@not_fines }
1202
        }
1203
      )->get_column('amount_outstanding')->sum();
1244
1204
1245
    return ( $total, $total - $other_charges, $other_charges);
1205
    return (
1206
        $borrower->account_balance(),
1207
        $borrower->account_balance() - $other_charges,
1208
        $other_charges
1209
    );
1246
}
1210
}
1247
1211
1248
=head2 GetBorNotifyAcctRecord
1212
=head2 GetBorNotifyAcctRecord
(-)a/C4/Overdues.pm (-180 / +112 lines)
Lines 25-33 use Date::Calc qw/Today Date_to_Days/; Link Here
25
use Date::Manip qw/UnixDate/;
25
use Date::Manip qw/UnixDate/;
26
use C4::Circulation;
26
use C4::Circulation;
27
use C4::Context;
27
use C4::Context;
28
use C4::Accounts;
29
use C4::Log; # logaction
28
use C4::Log; # logaction
30
use C4::Debug;
29
use C4::Debug;
30
use Koha::Database;
31
use Koha::DateUtils;
31
32
32
use vars qw($VERSION @ISA @EXPORT);
33
use vars qw($VERSION @ISA @EXPORT);
33
34
Lines 46-52 BEGIN { Link Here
46
        &UpdateFine
47
        &UpdateFine
47
        &GetFine
48
        &GetFine
48
        
49
        
49
        &CheckItemNotify
50
        &GetOverduesForBranch
50
        &GetOverduesForBranch
51
        &RemoveNotifyLine
51
        &RemoveNotifyLine
52
        &AddNotifyLine
52
        &AddNotifyLine
Lines 456-609 sub GetIssuesIteminfo { Link Here
456
456
457
=head2 UpdateFine
457
=head2 UpdateFine
458
458
459
    &UpdateFine($itemnumber, $borrowernumber, $amount, $type, $description);
459
    UpdateFine(
460
        {
461
            itemnumber     => $itemnumber,
462
            borrowernumber => $borrowernumber,
463
            amount         => $amount,
464
            due            => $due,
465
            issue_id       => $issue_id
466
        }
467
    );
460
468
461
(Note: the following is mostly conjecture and guesswork.)
469
Updates the fine owed on an overdue item.
462
470
463
Updates the fine owed on an overdue book.
471
C<$itemnumber> is the items's id.
464
472
465
C<$itemnumber> is the book's item number.
473
C<$borrowernumber> is the id of the patron who currently
474
has the item on loan.
466
475
467
C<$borrowernumber> is the borrower number of the patron who currently
476
C<$amount> is the total amount of the fine owed by the patron.
468
has the book on loan.
469
477
470
C<$amount> is the current amount owed by the patron.
478
C<&UpdateFine> updates the amount owed for a given fine if an issue_id
479
is passed to it. Otherwise, a new fine will be created.
471
480
472
C<$type> will be used in the description of the fine.
481
=cut
473
482
474
C<$description> is a string that must be present in the description of
483
sub UpdateFine {
475
the fine. I think this is expected to be a date in DD/MM/YYYY format.
484
    my ($params) = @_;
476
485
477
C<&UpdateFine> looks up the amount currently owed on the given item
486
    my $itemnumber     = $params->{itemnumber};
478
and sets it to C<$amount>, creating, if necessary, a new entry in the
487
    my $borrowernumber = $params->{borrowernumber};
479
accountlines table of the Koha database.
488
    my $amount         = $params->{amount};
489
    my $due            = $params->{due};
490
    my $issue_id       = $params->{issue_id};
480
491
481
=cut
492
    my $schema = Koha::Database->new()->schema;
482
493
483
#
494
    my $borrower = $schema->resultset('Borrower')->find($borrowernumber);
484
# Question: Why should the caller have to
485
# specify both the item number and the borrower number? A book can't
486
# be on loan to two different people, so the item number should be
487
# sufficient.
488
#
489
# Possible Answer: You might update a fine for a damaged item, *after* it is returned.
490
#
491
sub UpdateFine {
492
    my ( $itemnum, $borrowernumber, $amount, $type, $due ) = @_;
493
	$debug and warn "UpdateFine($itemnum, $borrowernumber, $amount, " . ($type||'""') . ", $due) called";
494
    my $dbh = C4::Context->dbh;
495
    # FIXME - What exactly is this query supposed to do? It looks up an
496
    # entry in accountlines that matches the given item and borrower
497
    # numbers, where the description contains $due, and where the
498
    # account type has one of several values, but what does this _mean_?
499
    # Does it look up existing fines for this item?
500
    # FIXME - What are these various account types? ("FU", "O", "F", "M")
501
	#	"L"   is LOST item
502
	#   "A"   is Account Management Fee
503
	#   "N"   is New Card
504
	#   "M"   is Sundry
505
	#   "O"   is Overdue ??
506
	#   "F"   is Fine ??
507
	#   "FU"  is Fine UPDATE??
508
	#	"Pay" is Payment
509
	#   "REF" is Cash Refund
510
    my $sth = $dbh->prepare(
511
        "SELECT * FROM accountlines
512
        WHERE borrowernumber=?
513
        AND   accounttype IN ('FU','O','F','M')"
514
    );
515
    $sth->execute( $borrowernumber );
516
    my $data;
517
    my $total_amount_other = 0.00;
518
    my $due_qr = qr/$due/;
519
    # Cycle through the fines and
520
    # - find line that relates to the requested $itemnum
521
    # - accumulate fines for other items
522
    # so we can update $itemnum fine taking in account fine caps
523
    while (my $rec = $sth->fetchrow_hashref) {
524
        if ($rec->{itemnumber} == $itemnum && $rec->{description} =~ /$due_qr/) {
525
            if ($data) {
526
                warn "Not a unique accountlines record for item $itemnum borrower $borrowernumber";
527
            } else {
528
                $data = $rec;
529
                next;
530
            }
531
        }
532
        $total_amount_other += $rec->{'amountoutstanding'};
533
    }
534
495
535
    if (my $maxfine = C4::Context->preference('MaxFine')) {
496
    if ( my $maxfine = C4::Context->preference('MaxFine') ) {
536
        if ($total_amount_other + $amount > $maxfine) {
497
        if ( $borrower->account_balance() + $amount > $maxfine ) {
537
            my $new_amount = $maxfine - $total_amount_other;
498
            my $new_amount = $maxfine - $borrower->account_balance();
538
            return if $new_amount <= 0.00;
499
            warn "Reducing fine for item $itemnumber borrower $borrowernumber from $amount to $new_amount - MaxFine reached";
539
            warn "Reducing fine for item $itemnum borrower $borrowernumber from $amount to $new_amount - MaxFine reached";
500
            if ( $new_amount <= 0 ) {
501
                warn "Fine reduced to a non-positive ammount. Fine not created.";
502
                return;
503
            }
540
            $amount = $new_amount;
504
            $amount = $new_amount;
541
        }
505
        }
542
    }
506
    }
543
507
544
    if ( $data ) {
508
    my $timestamp = get_timestamp();
545
509
546
		# we're updating an existing fine.  Only modify if amount changed
510
    my $fine =
547
        # Note that in the current implementation, you cannot pay against an accruing fine
511
      $schema->resultset('AccountDebit')->single( { issue_id => $issue_id } );
548
        # (i.e. , of accounttype 'FU').  Doing so will break accrual.
512
549
    	if ( $data->{'amount'} != $amount ) {
513
    my $offset = 0;
550
            my $diff = $amount - $data->{'amount'};
514
    if ($fine) {
551
	    #3341: diff could be positive or negative!
515
        if (
552
            my $out  = $data->{'amountoutstanding'} + $diff;
516
            sprintf( "%.6f", $fine->amount_original() )
553
            my $query = "
517
            ne
554
                UPDATE accountlines
518
            sprintf( "%.6f", $amount ) )
555
				SET date=now(), amount=?, amountoutstanding=?,
519
        {
556
					lastincrement=?, accounttype='FU'
520
            my $difference = $amount - $fine->amount_original();
557
	  			WHERE borrowernumber=?
521
558
				AND   itemnumber=?
522
            $fine->amount_original( $fine->amount_original() + $difference );
559
				AND   accounttype IN ('FU','O')
523
            $fine->amount_outstanding( $fine->amount_outstanding() + $difference );
560
				AND   description LIKE ?
524
            $fine->amount_last_increment($difference);
561
				LIMIT 1 ";
525
            $fine->updated_on($timestamp);
562
            my $sth2 = $dbh->prepare($query);
526
            $fine->update();
563
			# FIXME: BOGUS query cannot ensure uniqueness w/ LIKE %x% !!!
527
564
			# 		LIMIT 1 added to prevent multiple affected lines
528
            $offset = 1;
565
			# FIXME: accountlines table needs unique key!! Possibly a combo of borrowernumber and accountline.  
566
			# 		But actually, we should just have a regular autoincrementing PK and forget accountline,
567
			# 		including the bogus getnextaccountno function (doesn't prevent conflict on simultaneous ops).
568
			# FIXME: Why only 2 account types here?
569
			$debug and print STDERR "UpdateFine query: $query\n" .
570
				"w/ args: $amount, $out, $diff, $data->{'borrowernumber'}, $data->{'itemnumber'}, \"\%$due\%\"\n";
571
            $sth2->execute($amount, $out, $diff, $data->{'borrowernumber'}, $data->{'itemnumber'}, "%$due%");
572
        } else {
573
            #      print "no update needed $data->{'amount'}"
574
        }
529
        }
575
    } else {
530
    }
576
        my $sth4 = $dbh->prepare(
531
    else {
577
            "SELECT title FROM biblio LEFT JOIN items ON biblio.biblionumber=items.biblionumber WHERE items.itemnumber=?"
532
        my $item = $schema->resultset('Item')->find($itemnumber);
533
534
        $fine = $schema->resultset('AccountDebit')->create(
535
            {
536
                borrowernumber        => $borrowernumber,
537
                itemnumber            => $itemnumber,
538
                issue_id              => $issue_id,
539
                type                  => Koha::Accounts::DebitTypes::Fine(),
540
                accruing              => 1,
541
                amount_original       => $amount,
542
                amount_outstanding    => $amount,
543
                amount_last_increment => $amount,
544
                description           => $item->biblio()->title() . " / Due:$due",
545
                created_on            => $timestamp,
546
            }
578
        );
547
        );
579
        $sth4->execute($itemnum);
548
580
        my $title = $sth4->fetchrow;
549
        $offset = 1;
581
582
#         #   print "not in account";
583
#         my $sth3 = $dbh->prepare("Select max(accountno) from accountlines");
584
#         $sth3->execute;
585
# 
586
#         # FIXME - Make $accountno a scalar.
587
#         my @accountno = $sth3->fetchrow_array;
588
#         $sth3->finish;
589
#         $accountno[0]++;
590
# begin transaction
591
		my $nextaccntno = C4::Accounts::getnextacctno($borrowernumber);
592
		my $desc = ($type ? "$type " : '') . "$title $due";	# FIXEDME, avoid whitespace prefix on empty $type
593
		my $query = "INSERT INTO accountlines
594
		    (borrowernumber,itemnumber,date,amount,description,accounttype,amountoutstanding,lastincrement,accountno)
595
			    VALUES (?,?,now(),?,?,'FU',?,?,?)";
596
		my $sth2 = $dbh->prepare($query);
597
		$debug and print STDERR "UpdateFine query: $query\nw/ args: $borrowernumber, $itemnum, $amount, $desc, $amount, $amount, $nextaccntno\n";
598
        $sth2->execute($borrowernumber, $itemnum, $amount, $desc, $amount, $amount, $nextaccntno);
599
    }
550
    }
600
    # logging action
551
601
    &logaction(
552
    $schema->resultset('AccountOffset')->create(
602
        "FINES",
553
        {
603
        $type,
554
            debit_id   => $fine->debit_id(),
555
            amount     => $fine->amount_last_increment(),
556
            created_on => $timestamp,
557
            type       => Koha::Accounts::OffsetTypes::Fine(),
558
        }
559
    ) if $offset;
560
561
    logaction( "FINES", Koha::Accounts::DebitTypes::Fine(),
604
        $borrowernumber,
562
        $borrowernumber,
605
        "due=".$due."  amount=".$amount." itemnumber=".$itemnum
563
        "due=" . $due . "  amount=" . $amount . " itemnumber=" . $itemnumber )
606
        ) if C4::Context->preference("FinesLog");
564
      if C4::Context->preference("FinesLog");
607
}
565
}
608
566
609
=head2 BorType
567
=head2 BorType
Lines 644-661 C<$borrowernumber> is the borrowernumber Link Here
644
=cut 
602
=cut 
645
603
646
sub GetFine {
604
sub GetFine {
647
    my ( $itemnum, $borrowernumber ) = @_;
605
    my ( $itemnumber, $borrowernumber ) = @_;
648
    my $dbh   = C4::Context->dbh();
606
649
    my $query = q|SELECT sum(amountoutstanding) as fineamount FROM accountlines
607
    my $schema = Koha::Database->new()->schema;
650
    where accounttype like 'F%'
608
651
  AND amountoutstanding > 0 AND itemnumber = ? AND borrowernumber=?|;
609
    my $amount_outstanding = $schema->resultset('AccountDebit')->search(
652
    my $sth = $dbh->prepare($query);
610
        {
653
    $sth->execute( $itemnum, $borrowernumber );
611
            itemnumber     => $itemnumber,
654
    my $fine = $sth->fetchrow_hashref();
612
            borrowernumber => $borrowernumber,
655
    if ($fine->{fineamount}) {
613
            type           => Koha::Accounts::DebitTypes::Fine(),
656
        return $fine->{fineamount};
614
        },
657
    }
615
    )->get_column('amount_outstanding')->sum();
658
    return 0;
616
617
    return $amount_outstanding;
659
}
618
}
660
619
661
=head2 NumberNotifyId
620
=head2 NumberNotifyId
Lines 759-785 sub GetBranchcodesWithOverdueRules { Link Here
759
    return @branches;
718
    return @branches;
760
}
719
}
761
720
762
=head2 CheckItemNotify
763
764
Sql request to check if the document has alreday been notified
765
this function is not exported, only used with GetOverduesForBranch
766
767
=cut
768
769
sub CheckItemNotify {
770
    my ($notify_id,$notify_level,$itemnumber) = @_;
771
    my $dbh = C4::Context->dbh;
772
    my $sth = $dbh->prepare("
773
    SELECT COUNT(*)
774
     FROM notifys
775
    WHERE notify_id    = ?
776
     AND  notify_level = ? 
777
     AND  itemnumber   = ? ");
778
    $sth->execute($notify_id,$notify_level,$itemnumber);
779
    my $notified = $sth->fetchrow;
780
    return ($notified);
781
}
782
783
=head2 GetOverduesForBranch
721
=head2 GetOverduesForBranch
784
722
785
Sql request for display all information for branchoverdues.pl
723
Sql request for display all information for branchoverdues.pl
Lines 804-809 sub GetOverduesForBranch { Link Here
804
               biblio.title,
742
               biblio.title,
805
               biblio.author,
743
               biblio.author,
806
               biblio.biblionumber,
744
               biblio.biblionumber,
745
               issues.issue_id,
807
               issues.date_due,
746
               issues.date_due,
808
               issues.returndate,
747
               issues.returndate,
809
               issues.branchcode,
748
               issues.branchcode,
Lines 814-838 sub GetOverduesForBranch { Link Here
814
                items.location,
753
                items.location,
815
                items.itemnumber,
754
                items.itemnumber,
816
            itemtypes.description,
755
            itemtypes.description,
817
         accountlines.notify_id,
756
            account_debits.amount_outstanding
818
         accountlines.notify_level,
757
    FROM  account_debits
819
         accountlines.amountoutstanding
758
    LEFT JOIN issues      ON    issues.itemnumber     = account_debits.itemnumber
820
    FROM  accountlines
759
                          AND   issues.borrowernumber = account_debits.borrowernumber
821
    LEFT JOIN issues      ON    issues.itemnumber     = accountlines.itemnumber
760
    LEFT JOIN borrowers   ON borrowers.borrowernumber = account_debits.borrowernumber
822
                          AND   issues.borrowernumber = accountlines.borrowernumber
823
    LEFT JOIN borrowers   ON borrowers.borrowernumber = accountlines.borrowernumber
824
    LEFT JOIN items       ON     items.itemnumber     = issues.itemnumber
761
    LEFT JOIN items       ON     items.itemnumber     = issues.itemnumber
825
    LEFT JOIN biblio      ON      biblio.biblionumber =  items.biblionumber
762
    LEFT JOIN biblio      ON      biblio.biblionumber =  items.biblionumber
826
    LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber
763
    LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber
827
    LEFT JOIN itemtypes   ON itemtypes.itemtype       = $itype_link
764
    LEFT JOIN itemtypes   ON itemtypes.itemtype       = $itype_link
828
    LEFT JOIN branches    ON  branches.branchcode     = issues.branchcode
765
    LEFT JOIN branches    ON  branches.branchcode     = issues.branchcode
829
    WHERE (accountlines.amountoutstanding  != '0.000000')
766
    WHERE (account_debits.amount_outstanding  != '0.000000')
830
      AND (accountlines.accounttype         = 'FU'      )
767
      AND (account_debits.type = 'FINE')
768
      AND (account_debits.accruing = 1 )
831
      AND (issues.branchcode =  ?   )
769
      AND (issues.branchcode =  ?   )
832
      AND (issues.date_due  < NOW())
770
      AND (issues.date_due  < NOW())
833
    ";
771
    ";
834
    my @getoverdues;
772
    my @getoverdues;
835
    my $i = 0;
836
    my $sth;
773
    my $sth;
837
    if ($location) {
774
    if ($location) {
838
        $sth = $dbh->prepare("$select AND items.location = ? ORDER BY borrowers.surname, borrowers.firstname");
775
        $sth = $dbh->prepare("$select AND items.location = ? ORDER BY borrowers.surname, borrowers.firstname");
Lines 842-853 sub GetOverduesForBranch { Link Here
842
        $sth->execute($branch);
779
        $sth->execute($branch);
843
    }
780
    }
844
    while ( my $data = $sth->fetchrow_hashref ) {
781
    while ( my $data = $sth->fetchrow_hashref ) {
845
    #check if the document has already been notified
782
        push( @getoverdues, $data );
846
        my $countnotify = CheckItemNotify($data->{'notify_id'}, $data->{'notify_level'}, $data->{'itemnumber'});
847
        if ($countnotify eq '0') {
848
            $getoverdues[$i] = $data;
849
            $i++;
850
        }
851
    }
783
    }
852
    return (@getoverdues);
784
    return (@getoverdues);
853
}
785
}
(-)a/C4/Reserves.pm (-13 / +10 lines)
Lines 28-34 use C4::Biblio; Link Here
28
use C4::Members;
28
use C4::Members;
29
use C4::Items;
29
use C4::Items;
30
use C4::Circulation;
30
use C4::Circulation;
31
use C4::Accounts;
32
31
33
# for _koha_notify_reserve
32
# for _koha_notify_reserve
34
use C4::Members::Messaging;
33
use C4::Members::Messaging;
Lines 172-190 sub AddReserve { Link Here
172
        $waitingdate = $resdate;
171
        $waitingdate = $resdate;
173
    }
172
    }
174
173
175
    #eval {
176
    # updates take place here
177
    if ( $fee > 0 ) {
174
    if ( $fee > 0 ) {
178
        my $nextacctno = &getnextacctno( $borrowernumber );
175
        AddDebit(
179
        my $query      = qq/
176
            {
180
        INSERT INTO accountlines
177
                borrowernumber => $borrowernumber,
181
            (borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding)
178
                itemnumber     => $checkitem,
182
        VALUES
179
                amount         => $fee,
183
            (?,?,now(),?,?,'Res',?)
180
                type           => Koha::Accounts::DebitTypes::Hold(),
184
    /;
181
                description    => "Hold fee - $title",
185
        my $usth = $dbh->prepare($query);
182
                notes          => "Record ID: $biblionumber",
186
        $usth->execute( $borrowernumber, $nextacctno, $fee,
183
            }
187
            "Reserve Charge - $title", $fee );
184
        );
188
    }
185
    }
189
186
190
    #if ($const eq 'a'){
187
    #if ($const eq 'a'){
(-)a/C4/SIP/ILS/Patron.pm (-1 / +1 lines)
Lines 85-91 sub new { Link Here
85
        hold_ok         => ( !$debarred && !$expired ),
85
        hold_ok         => ( !$debarred && !$expired ),
86
        card_lost       => ( $kp->{lost} || $kp->{gonenoaddress} || $flags->{LOST} ),
86
        card_lost       => ( $kp->{lost} || $kp->{gonenoaddress} || $flags->{LOST} ),
87
        claims_returned => 0,
87
        claims_returned => 0,
88
        fines           => $fines_amount, # GetMemberAccountRecords($kp->{borrowernumber})
88
        fines           => $fines_amount, 
89
        fees            => 0,             # currently not distinct from fines
89
        fees            => 0,             # currently not distinct from fines
90
        recall_overdue  => 0,
90
        recall_overdue  => 0,
91
        items_billed    => 0,
91
        items_billed    => 0,
(-)a/Koha/Accounts.pm (+525 lines)
Line 0 Link Here
1
package Koha::Accounts;
2
3
# Copyright 2013 ByWater Solutions
4
#
5
# This file is part of Koha.
6
#
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.
11
#
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.
15
#
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.
19
20
use Modern::Perl;
21
22
use Carp;
23
use Data::Dumper qw(Dumper);
24
25
use C4::Context;
26
use C4::Log qw(logaction);
27
use Koha::DateUtils qw(get_timestamp);
28
29
use Koha::Accounts::CreditTypes;
30
use Koha::Accounts::DebitTypes;
31
32
use vars qw($VERSION @ISA @EXPORT);
33
34
BEGIN {
35
    require Exporter;
36
    @ISA    = qw(Exporter);
37
    @EXPORT = qw(
38
      AddDebit
39
      AddCredit
40
41
      NormalizeBalances
42
43
      RecalculateAccountBalance
44
45
      DebitLostItem
46
      CreditLostItem
47
    );
48
}
49
50
=head1 NAME
51
52
Koha::Accounts - Functions for dealing with Koha accounts
53
54
=head1 SYNOPSIS
55
56
use Koha::Accounts;
57
58
=head1 DESCRIPTION
59
60
The functions in this module deal with the monetary aspect of Koha,
61
including looking up and modifying the amount of money owed by a
62
patron.
63
64
=head1 FUNCTIONS
65
66
=head2 AddDebit
67
68
my $debit = AddDebit({
69
    borrower       => $borrower,
70
    amount         => $amount,
71
    [ type         => $type,        ]
72
    [ itemnumber   => $itemnumber,  ]
73
    [ issue_id     => $issue_id,    ]
74
    [ description  => $description, ]
75
    [ notes        => $notes,       ]
76
    [ branchcode   => $branchcode,  ]
77
    [ manager_id   => $manager_id,  ]
78
    [ accruing     => $accruing,    ] # Default 0 if not accruing, 1 if accruing
79
});
80
81
Create a new debit for a given borrower. To standardize nomenclature, any charge
82
against a borrower ( e.g. a fine, a new card charge, the cost of losing an item )
83
will be referred to as a 'debit'.
84
85
=cut
86
87
sub AddDebit {
88
    my ($params) = @_;
89
90
    my $borrower = $params->{borrower};
91
    my $amount   = $params->{amount};
92
93
    my $type        = $params->{type};
94
    my $itemnumber  = $params->{itemnumber};
95
    my $issue_id    = $params->{issue_id};
96
    my $description = $params->{description};
97
    my $notes       = $params->{notes};
98
99
    my $branchcode = $params->{branchcode};
100
    $branchcode ||=
101
      defined( C4::Context->userenv )
102
      ? C4::Context->userenv->{branch}
103
      : undef;
104
105
    my $manager_id = $params->{manager_id};
106
    $manager_id ||=
107
      defined( C4::Context->userenv )
108
      ? C4::Context->userenv->{manager_id}
109
      : undef;
110
111
    my $accruing = $params->{accruing} || 0;
112
113
    croak("Required parameter 'borrower' not passed in.")
114
      unless ($borrower);
115
    croak("Required parameter 'amount' not passed in.")
116
      unless ($amount);
117
    croak("Invalid debit type: '$type'!")
118
      unless ( Koha::Accounts::DebitTypes::IsValid($type) );
119
    croak("No issue id passed in for accruing debit!")
120
      if ( $accruing && !$issue_id );
121
122
    my $debit = Koha::Database->new()->schema->resultset('AccountDebit')->create(
123
        {
124
            borrowernumber        => $borrower->borrowernumber(),
125
            itemnumber            => $itemnumber,
126
            issue_id              => $issue_id,
127
            type                  => $type,
128
            accruing              => $accruing,
129
            amount_original       => $amount,
130
            amount_outstanding    => $amount,
131
            amount_last_increment => $amount,
132
            description           => $description,
133
            notes                 => $notes,
134
            manager_id            => $manager_id,
135
            created_on            => get_timestamp(),
136
        }
137
    );
138
139
    if ($debit) {
140
        $borrower->account_balance( $borrower->account_balance() + $amount );
141
        $borrower->update();
142
143
        NormalizeBalances( { borrower => $borrower } );
144
145
        if ( C4::Context->preference("FinesLog") ) {
146
            logaction( "FINES", "CREATE_FEE", $debit->id,
147
                Dumper( $debit->get_columns() ) );
148
        }
149
    }
150
    else {
151
        carp("Something went wrong! Debit not created!");
152
    }
153
154
    return $debit;
155
}
156
157
=head2 DebitLostItem
158
159
my $debit = DebitLostItem({
160
    borrower       => $borrower,
161
    issue          => $issue,
162
});
163
164
DebitLostItem adds a replacement fee charge for the item
165
of the given issue.
166
167
=cut
168
169
sub DebitLostItem {
170
    my ($params) = @_;
171
172
    my $borrower = $params->{borrower};
173
    my $issue    = $params->{issue};
174
175
    croak("Required param 'borrower' not passed in!") unless ($borrower);
176
    croak("Required param 'issue' not passed in!")    unless ($issue);
177
178
    # Don't add lost debit if borrower has already been charged for this lost item before,
179
    # for this issue. It seems reasonable that a borrower could lose an item, find and return it,
180
    # check it out again, and lose it again, so we should do this based on issue_id, not itemnumber.
181
    unless (
182
        Koha::Database->new()->schema->resultset('AccountDebit')->search(
183
            {
184
                borrowernumber => $borrower->borrowernumber(),
185
                issue_id       => $issue->issue_id(),
186
                type           => Koha::Accounts::DebitTypes::Lost
187
            }
188
        )->count()
189
      )
190
    {
191
        my $item = $issue->item();
192
193
        $params->{accruing}   = 0;
194
        $params->{type}       = Koha::Accounts::DebitTypes::Lost;
195
        $params->{amount}     = $item->replacementprice();
196
        $params->{itemnumber} = $item->itemnumber();
197
        $params->{issue_id}   = $issue->issue_id();
198
199
        #TODO: Shouldn't we have a default replacement price as a syspref?
200
        if ( $params->{amount} ) {
201
            return AddDebit($params);
202
        }
203
        else {
204
            carp("Cannot add lost debit! Item has no replacement price!");
205
        }
206
    }
207
}
208
209
=head2 CreditLostItem
210
211
my $debit = CreditLostItem(
212
    {
213
        borrower => $borrower,
214
        debit    => $debit,
215
    }
216
);
217
218
CreditLostItem creates a payment in the amount equal
219
to the replacement price charge created by DebitLostItem.
220
221
=cut
222
223
sub CreditLostItem {
224
    my ($params) = @_;
225
226
    my $borrower = $params->{borrower};
227
    my $debit    = $params->{debit};
228
229
    croak("Required param 'borrower' not passed in!") unless ($borrower);
230
    croak("Required param 'debit' not passed in!")
231
      unless ($debit);
232
233
    my $item =
234
      Koha::Database->new()->schema->resultset('Item')
235
      ->find( $debit->itemnumber() );
236
    carp("No item found!") unless $item;
237
238
    $params->{type}     = Koha::Accounts::CreditTypes::Found;
239
    $params->{amount}   = $debit->amount_original();
240
    $params->{debit_id} = $debit->debit_id();
241
    $params->{notes}    = "Lost item found: " . $item->barcode();
242
243
    return AddCredit($params);
244
}
245
246
=head2 AddCredit
247
248
AddCredit({
249
    borrower       => $borrower,
250
    amount         => $amount,
251
    [ branchcode   => $branchcode, ]
252
    [ manager_id   => $manager_id, ]
253
    [ debit_id     => $debit_id, ] # The primary debit to be paid
254
    [ notes        => $notes, ]
255
});
256
257
Record credit by a patron. C<$borrowernumber> is the patron's
258
borrower number. C<$credit> is a floating-point number, giving the
259
amount that was paid.
260
261
Amounts owed are paid off oldest first. That is, if the patron has a
262
$1 fine from Feb. 1, another $1 fine from Mar. 1, and makes a credit
263
of $1.50, then the oldest fine will be paid off in full, and $0.50
264
will be credited to the next one.
265
266
debit_id can be passed as a scalar or an array ref to make the passed
267
in debit or debits the first to be credited.
268
269
=cut
270
271
sub AddCredit {
272
    my ($params) = @_;
273
274
    my $type       = $params->{type};
275
    my $borrower   = $params->{borrower};
276
    my $amount     = $params->{amount};
277
    my $debit_id   = $params->{debit_id};
278
    my $notes      = $params->{notes};
279
    my $branchcode = $params->{branchcode};
280
    my $manager_id = $params->{manager_id};
281
282
    my $userenv = C4::Context->userenv;
283
284
    unless ( $manager_id || $userenv ) {
285
        $manager_id = $userenv->{number};
286
    }
287
288
    unless ( $branchcode || $userenv ) {
289
        $branchcode = $userenv->{branch};
290
    }
291
292
    unless ($borrower) {
293
        croak("Required parameter 'borrower' not passed in");
294
    }
295
    unless ($amount) {
296
        croak("Required parameter amount not passed in");
297
    }
298
299
    unless ( Koha::Accounts::CreditTypes::IsValid($type) ) {
300
        carp("Invalid credit type! Returning without creating credit.");
301
        return;
302
    }
303
304
    unless ($type) {
305
        carp("No type passed in, assuming Payment");
306
        $type = Koha::Accounts::CreditTypes::Payment;
307
    }
308
309
    my $debit = Koha::Database->new()->schema->resultset('AccountDebit')->find($debit_id);
310
311
    # First, we make the credit. We'll worry about what we paid later on
312
    my $credit = Koha::Database->new()->schema->resultset('AccountCredit')->create(
313
        {
314
            borrowernumber   => $borrower->borrowernumber(),
315
            type             => $type,
316
            amount_paid      => $amount,
317
            amount_remaining => $amount,
318
            notes            => $notes,
319
            manager_id       => $manager_id,
320
            created_on       => get_timestamp(),
321
        }
322
    );
323
324
    if ( C4::Context->preference("FinesLog") ) {
325
        logaction( "FINES", "CREATE_PAYMENT", $credit->id,
326
            Dumper( $credit->get_columns() ) );
327
    }
328
329
    $borrower->account_balance( $borrower->account_balance() - $amount );
330
    $borrower->update();
331
332
    # If we are given specific debits, pay those ones first.
333
    if ( $debit_id ) {
334
        my @debit_ids = ref( $debit_id ) eq "ARRAY" ? @$debit_id : $debit_id;
335
        foreach my $debit_id (@debit_ids) {
336
            my $debit =
337
              Koha::Database->new()->schema->resultset('AccountDebit')->find($debit_id);
338
339
            if ($debit) {
340
                CreditDebit( { credit => $credit, debit => $debit } );
341
            }
342
            else {
343
                carp("Invalid debit_id passed in!");
344
            }
345
        }
346
    }
347
348
    # We still have leftover money, or we weren't given a specific debit to pay
349
    if ( $credit->amount_remaining() > 0 ) {
350
        my @debits = Koha::Database->new()->schema->resultset('AccountDebit')->search(
351
            {
352
                borrowernumber     => $borrower->borrowernumber(),
353
                amount_outstanding => { '>' => '0' }
354
            }
355
        );
356
357
        foreach my $debit (@debits) {
358
            if ( $credit->amount_remaining() > 0 ) {
359
                CreditDebit(
360
                    {
361
                        credit   => $credit,
362
                        debit    => $debit,
363
                        borrower => $borrower,
364
                        type     => $type,
365
                    }
366
                );
367
            }
368
        }
369
    }
370
371
    return $credit;
372
}
373
374
=head2 CreditDebit
375
376
$account_offset = CreditDebit({
377
    credit => $credit,
378
    debit => $debit,
379
});
380
381
Given a credit and a debit, this subroutine
382
will pay the appropriate amount of the debit,
383
update the debit's amount outstanding, the credit's
384
amout remaining, and create the appropriate account
385
offset.
386
387
=cut
388
389
sub CreditDebit {
390
    my ($params) = @_;
391
392
    my $credit = $params->{credit};
393
    my $debit  = $params->{debit};
394
395
    croak("Required parameter 'credit' not passed in!")
396
      unless $credit;
397
    croak("Required parameter 'debit' not passed in!") unless $debit;
398
399
    my $amount_to_pay =
400
      ( $debit->amount_outstanding() > $credit->amount_remaining() )
401
      ? $credit->amount_remaining()
402
      : $debit->amount_outstanding();
403
404
    if ( $amount_to_pay > 0 ) {
405
        $debit->amount_outstanding(
406
            $debit->amount_outstanding() - $amount_to_pay );
407
        $debit->update();
408
409
        $credit->amount_remaining(
410
            $credit->amount_remaining() - $amount_to_pay );
411
        $credit->update();
412
413
        my $offset = Koha::Database->new()->schema->resultset('AccountOffset')->create(
414
            {
415
                amount     => $amount_to_pay * -1,
416
                debit_id   => $debit->id(),
417
                credit_id  => $credit->id(),
418
                created_on => get_timestamp(),
419
            }
420
        );
421
422
        if ( C4::Context->preference("FinesLog") ) {
423
            logaction( "FINES", "MODIFY", $offset->id,
424
                Dumper( $offset->get_columns() ) );
425
        }
426
427
        return $offset;
428
    }
429
}
430
431
=head2 RecalculateAccountBalance
432
433
$account_balance = RecalculateAccountBalance({
434
    borrower => $borrower
435
});
436
437
Recalculates a borrower's balance based on the
438
sum of the amount outstanding for the borrower's
439
debits minus the sum of the amount remaining for
440
the borrowers credits.
441
442
TODO: Would it be better to use af.amount_original - ap.amount_paid for any reason?
443
      Or, perhaps calculate both and compare the two, for error checking purposes.
444
=cut
445
446
sub RecalculateAccountBalance {
447
    my ($params) = @_;
448
449
    my $borrower = $params->{borrower};
450
    croak("Requred paramter 'borrower' not passed in!")
451
      unless ($borrower);
452
453
    my $debits =
454
      Koha::Database->new()->schema->resultset('AccountDebit')
455
      ->search( { borrowernumber => $borrower->borrowernumber() } );
456
    my $amount_outstanding = $debits->get_column('amount_outstanding')->sum();
457
458
    my $credits =
459
      Koha::Database->new()->schema->resultset('AccountCredit')
460
      ->search( { borrowernumber => $borrower->borrowernumber() } );
461
    my $amount_remaining = $credits->get_column('amount_remaining')->sum();
462
463
    my $account_balance = $amount_outstanding - $amount_remaining;
464
    $borrower->account_balance($account_balance);
465
    $borrower->update();
466
467
    return $account_balance;
468
}
469
470
=head2 NormalizeBalances
471
472
    $account_balance = NormalizeBalances({ borrower => $borrower });
473
474
    For a given borrower, this subroutine will find all debits
475
    with an outstanding balance and all credits with an unused
476
    amount remaining and will pay those debits with those credits.
477
478
=cut
479
480
sub NormalizeBalances {
481
    my ($params) = @_;
482
483
    my $borrower = $params->{borrower};
484
485
    croak("Required param 'borrower' not passed in!") unless $borrower;
486
487
    my @credits = Koha::Database->new()->schema->resultset('AccountCredit')->search(
488
        {
489
            borrowernumber   => $borrower->borrowernumber(),
490
            amount_remaining => { '>' => '0' }
491
        }
492
    );
493
494
    return unless @credits;
495
496
    my @debits = Koha::Database->new()->schema->resultset('AccountDebit')->search(
497
        {
498
            borrowernumber     => $borrower->borrowernumber(),
499
            amount_outstanding => { '>' => '0' }
500
        }
501
    );
502
503
    return unless @debits;
504
505
    foreach my $credit (@credits) {
506
        foreach my $debit (@debits) {
507
            if (   $credit->amount_remaining()
508
                && $debit->amount_outstanding() )
509
            {
510
                CreditDebit( { credit => $credit, debit => $debit } );
511
            }
512
        }
513
    }
514
515
    return RecalculateAccountBalance( { borrower => $borrower } );
516
}
517
518
1;
519
__END__
520
521
=head1 AUTHOR
522
523
Kyle M Hall <kyle@bywatersolutions.com>
524
525
=cut
(-)a/Koha/Accounts/CreditTypes.pm (+117 lines)
Line 0 Link Here
1
package Koha::Accounts::CreditTypes;
2
3
# Copyright 2013 ByWater Solutions
4
#
5
# This file is part of Koha.
6
#
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.
11
#
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.
15
#
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.
19
20
use Modern::Perl;
21
22
=head1 NAME
23
24
Koha::AccountsCreditTypes - Module representing the enumerated data types for account fees
25
26
=head1 SYNOPSIS
27
28
use Koha::Accounts::CreditTypes;
29
30
my $type = Koha::Accounts::CreditTypes::Payment;
31
32
=head1 DESCRIPTION
33
34
The subroutines in this modules act as enumerated data types for the
35
different credit types in Koha ( i.e. payments, writeoffs, etc. )
36
37
=head1 FUNCTIONS
38
39
=head2 IsValid
40
41
This subroutine takes a given string and returns 1 if
42
the string matches one of the data types, and 0 if not.
43
44
FIXME: Perhaps we should use Class::Inspector instead of hard
45
coding the subs? It seems like it would be a major trade off
46
of speed just so we don't update something in two separate places
47
in the same file.
48
49
=cut
50
51
sub IsValid {
52
    my ($string) = @_;
53
54
    my $is_valid =
55
      (      $string eq Koha::Accounts::CreditTypes::Payment()
56
          || $string eq Koha::Accounts::CreditTypes::WriteOff()
57
          || $string eq Koha::Accounts::CreditTypes::Found()
58
          || $string eq Koha::Accounts::CreditTypes::Credit()
59
          || $string eq Koha::Accounts::CreditTypes::Forgiven() );
60
61
    unless ($is_valid) {
62
        $is_valid =
63
          Koha::Database->new()->schema->resultset('AuthorisedValue')
64
          ->count(
65
            { category => 'ACCOUNT_CREDIT', authorised_value => $string } );
66
    }
67
68
    return $is_valid;
69
}
70
71
=head2 Credit
72
73
=cut
74
75
sub Credit {
76
    return 'CREDIT';
77
}
78
79
=head2 Payment
80
81
=cut
82
83
sub Payment {
84
    return 'PAYMENT';
85
}
86
87
=head2 Writeoff
88
89
=cut
90
91
sub WriteOff {
92
    return 'WRITEOFF';
93
}
94
95
=head2 Writeoff
96
97
=cut
98
99
sub Found {
100
    return 'FOUND';
101
}
102
103
=head2 Forgiven
104
105
=cut
106
107
sub Forgiven {
108
    return 'FORGIVEN';
109
}
110
111
1;
112
113
=head1 AUTHOR
114
115
Kyle M Hall <kyle@bywatersolutions.com>
116
117
=cut
(-)a/Koha/Accounts/DebitTypes.pm (+160 lines)
Line 0 Link Here
1
package Koha::Accounts::DebitTypes;
2
3
# Copyright 2013 ByWater Solutions
4
#
5
# This file is part of Koha.
6
#
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.
11
#
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.
15
#
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.
19
20
use Modern::Perl;
21
22
=head1 NAME
23
24
Koha::Accounts::DebitTypes - Module representing an enumerated data type for account fees
25
26
=head1 SYNOPSIS
27
28
use Koha::Accounts::DebitTypes;
29
30
my $type = Koha::Accounts::DebitTypes::Fine;
31
32
=head1 DESCRIPTION
33
34
The subroutines in this modules act as an enumerated data type
35
for debit types ( stored in account_debits.type ) in Koha.
36
37
=head1 FUNCTIONS
38
39
=head2 IsValid
40
41
This subroutine takes a given string and returns 1 if
42
the string matches one of the data types, and 0 if not.
43
44
=cut
45
46
sub IsValid {
47
    my ($string) = @_;
48
49
    my $is_valid =
50
      (      $string eq Koha::Accounts::DebitTypes::Fine()
51
          || $string eq Koha::Accounts::DebitTypes::AccountManagementFee()
52
          || $string eq Koha::Accounts::DebitTypes::Sundry()
53
          || $string eq Koha::Accounts::DebitTypes::Lost()
54
          || $string eq Koha::Accounts::DebitTypes::Hold()
55
          || $string eq Koha::Accounts::DebitTypes::Rental()
56
          || $string eq Koha::Accounts::DebitTypes::NewCard() );
57
58
    unless ($is_valid) {
59
        $is_valid =
60
          Koha::Database->new()->schema->resultset('AuthorisedValue')
61
          ->count( { category => 'MANUAL_INV', authorised_value => $string } );
62
    }
63
64
    return $is_valid;
65
}
66
67
=head2 Fine
68
69
This data type represents a standard fine within Koha.
70
71
A fine still accruing no longer needs to be differiated by type
72
from a fine done accuring. Instead, that differentication is made
73
by which table the fine exists in, account_fees_accruing vs account_fees_accrued.
74
75
In addition, fines can be checked for correctness based on the issue_id
76
they have. A fine in account_fees_accruing should always have a matching
77
issue_id in the issues table. A fine done accruing will almost always have
78
a matching issue_id in the old_issues table. However, in the case of an overdue
79
item with fines that has been renewed, and becomes overdue again, you may have
80
a case where a given issue may have a matching fine in account_fees_accruing and
81
one or more matching fines in account_fees_accrued ( one for each for the first
82
checkout and one each for any subsequent renewals )
83
84
=cut
85
86
sub Fine {
87
    return 'FINE';
88
}
89
90
=head2 AccountManagementFee
91
92
This fee type is usually reserved for payments for library cards,
93
in cases where a library must charge a patron for the ability to
94
check out items.
95
96
=cut
97
98
sub AccountManagementFee {
99
    return 'ACCOUNT_MANAGEMENT_FEE';
100
}
101
102
=head2 Sundry
103
104
This fee type is basically a 'misc' type, and should be used
105
when no other fee type is more appropriate.
106
107
=cut
108
109
sub Sundry {
110
    return 'SUNDRY';
111
}
112
113
=head2 Lost
114
115
This fee type is used when a library charges for lost items.
116
117
=cut
118
119
sub Lost {
120
    return 'LOST';
121
}
122
123
=head2 Hold
124
125
This fee type is used when a library charges for holds.
126
127
=cut
128
129
sub Hold {
130
    return 'HOLD';
131
}
132
133
=head2 Rental
134
135
This fee type is used when a library charges a rental fee for the item type.
136
137
=cut
138
139
sub Rental {
140
    return 'RENTAL';
141
}
142
143
=head2 NewCard
144
145
This fee type is used when a library charges for replacement
146
library cards.
147
148
=cut
149
150
sub NewCard {
151
    return 'NEW_CARD';
152
}
153
154
1;
155
156
=head1 AUTHOR
157
158
Kyle M Hall <kyle@bywatersolutions.com>
159
160
=cut
(-)a/Koha/Accounts/OffsetTypes.pm (+72 lines)
Line 0 Link Here
1
package Koha::Accounts::OffsetTypes;
2
3
# Copyright 2013 ByWater Solutions
4
#
5
# This file is part of Koha.
6
#
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.
11
#
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.
15
#
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.
19
20
use Modern::Perl;
21
22
=head1 NAME
23
24
Koha::AccountsOffsetTypes - Module representing the enumerated data types for account fees
25
26
=head1 SYNOPSIS
27
28
use Koha::Accounts::OffsetTypes;
29
30
my $type = Koha::Accounts::OffsetTypes::Dropbox;
31
32
=head1 DESCRIPTION
33
34
The subroutines in this modules act as enumerated data types for the
35
different automatic offset types in Koha ( i.e. forgiveness, dropbox mode, etc )
36
37
These types are used for account offsets that have no corrosponding account credit,
38
e.g. automatic fine increments, dropbox mode, etc.
39
40
=head1 FUNCTIONS
41
42
=cut
43
44
=head2 Dropbox
45
46
Offset type for automatic fine reductions
47
via dropbox mode.
48
49
=cut
50
51
sub Dropbox {
52
    return 'DROPBOX';
53
}
54
55
=head2 Fine
56
57
Indicates this offset was an automatically
58
generated fine increment/decrement.
59
60
=cut
61
62
sub Fine {
63
    return 'FINE';
64
}
65
66
1;
67
68
=head1 AUTHOR
69
70
Kyle M Hall <kyle@bywatersolutions.com>
71
72
=cut
(-)a/Koha/DateUtils.pm (-1 / +6 lines)
Lines 21-33 use warnings; Link Here
21
use 5.010;
21
use 5.010;
22
use DateTime;
22
use DateTime;
23
use DateTime::Format::DateParse;
23
use DateTime::Format::DateParse;
24
use DateTime::Format::MySQL;
24
use C4::Context;
25
use C4::Context;
25
26
26
use base 'Exporter';
27
use base 'Exporter';
27
use version; our $VERSION = qv('1.0.0');
28
use version; our $VERSION = qv('1.0.0');
28
29
29
our @EXPORT = (
30
our @EXPORT = (
30
    qw( dt_from_string output_pref format_sqldatetime output_pref_due format_sqlduedatetime)
31
    qw( dt_from_string output_pref format_sqldatetime output_pref_due format_sqlduedatetime get_timestamp )
31
);
32
);
32
33
33
=head1 DateUtils
34
=head1 DateUtils
Lines 239-242 sub format_sqlduedatetime { Link Here
239
    return q{};
240
    return q{};
240
}
241
}
241
242
243
sub get_timestamp {
244
    return DateTime::Format::MySQL->format_datetime( dt_from_string() );
245
}
246
242
1;
247
1;
(-)a/Koha/Schema/Result/AccountCredit.pm (+140 lines)
Line 0 Link Here
1
package Koha::Schema::Result::AccountCredit;
2
3
# Created by DBIx::Class::Schema::Loader
4
# DO NOT MODIFY THE FIRST PART OF THIS FILE
5
6
use strict;
7
use warnings;
8
9
use base 'DBIx::Class::Core';
10
11
12
=head1 NAME
13
14
Koha::Schema::Result::AccountCredit
15
16
=cut
17
18
__PACKAGE__->table("account_credits");
19
20
=head1 ACCESSORS
21
22
=head2 credit_id
23
24
  data_type: 'integer'
25
  is_auto_increment: 1
26
  is_nullable: 0
27
28
=head2 borrowernumber
29
30
  data_type: 'integer'
31
  is_foreign_key: 1
32
  is_nullable: 0
33
34
=head2 type
35
36
  data_type: 'varchar'
37
  is_nullable: 0
38
  size: 255
39
40
=head2 amount_paid
41
42
  data_type: 'decimal'
43
  is_nullable: 0
44
  size: [28,6]
45
46
=head2 amount_remaining
47
48
  data_type: 'decimal'
49
  is_nullable: 0
50
  size: [28,6]
51
52
=head2 notes
53
54
  data_type: 'text'
55
  is_nullable: 1
56
57
=head2 manager_id
58
59
  data_type: 'integer'
60
  is_nullable: 1
61
62
=head2 created_on
63
64
  data_type: 'timestamp'
65
  is_nullable: 1
66
67
=head2 updated_on
68
69
  data_type: 'timestamp'
70
  is_nullable: 1
71
72
=cut
73
74
__PACKAGE__->add_columns(
75
  "credit_id",
76
  { data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
77
  "borrowernumber",
78
  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
79
  "type",
80
  { data_type => "varchar", is_nullable => 0, size => 255 },
81
  "amount_paid",
82
  { data_type => "decimal", is_nullable => 0, size => [28, 6] },
83
  "amount_remaining",
84
  { data_type => "decimal", is_nullable => 0, size => [28, 6] },
85
  "notes",
86
  { data_type => "text", is_nullable => 1 },
87
  "manager_id",
88
  { data_type => "integer", is_nullable => 1 },
89
  "created_on",
90
  { data_type => "timestamp", is_nullable => 1 },
91
  "updated_on",
92
  { data_type => "timestamp", is_nullable => 1 },
93
);
94
__PACKAGE__->set_primary_key("credit_id");
95
96
=head1 RELATIONS
97
98
=head2 borrowernumber
99
100
Type: belongs_to
101
102
Related object: L<Koha::Schema::Result::Borrower>
103
104
=cut
105
106
__PACKAGE__->belongs_to(
107
  "borrowernumber",
108
  "Koha::Schema::Result::Borrower",
109
  { borrowernumber => "borrowernumber" },
110
  { on_delete => "CASCADE", on_update => "CASCADE" },
111
);
112
113
=head2 account_offsets
114
115
Type: has_many
116
117
Related object: L<Koha::Schema::Result::AccountOffset>
118
119
=cut
120
121
__PACKAGE__->has_many(
122
  "account_offsets",
123
  "Koha::Schema::Result::AccountOffset",
124
  { "foreign.credit_id" => "self.credit_id" },
125
  { cascade_copy => 0, cascade_delete => 0 },
126
);
127
128
129
# Created by DBIx::Class::Schema::Loader v0.07000 @ 2013-10-09 10:37:23
130
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:uvt4OuaJxv4jk08zJsKouw
131
132
__PACKAGE__->belongs_to(
133
  "borrower",
134
  "Koha::Schema::Result::Borrower",
135
  { borrowernumber => "borrowernumber" },
136
);
137
138
139
# You can replace this text with custom content, and it will be preserved on regeneration
140
1;
(-)a/Koha/Schema/Result/AccountDebit.pm (+207 lines)
Line 0 Link Here
1
package Koha::Schema::Result::AccountDebit;
2
3
# Created by DBIx::Class::Schema::Loader
4
# DO NOT MODIFY THE FIRST PART OF THIS FILE
5
6
use strict;
7
use warnings;
8
9
use base 'DBIx::Class::Core';
10
11
12
=head1 NAME
13
14
Koha::Schema::Result::AccountDebit
15
16
=cut
17
18
__PACKAGE__->table("account_debits");
19
20
=head1 ACCESSORS
21
22
=head2 debit_id
23
24
  data_type: 'integer'
25
  is_auto_increment: 1
26
  is_nullable: 0
27
28
=head2 borrowernumber
29
30
  data_type: 'integer'
31
  default_value: 0
32
  is_foreign_key: 1
33
  is_nullable: 0
34
35
=head2 itemnumber
36
37
  data_type: 'integer'
38
  is_nullable: 1
39
40
=head2 issue_id
41
42
  data_type: 'integer'
43
  is_nullable: 1
44
45
=head2 type
46
47
  data_type: 'varchar'
48
  is_nullable: 0
49
  size: 255
50
51
=head2 accruing
52
53
  data_type: 'tinyint'
54
  default_value: 0
55
  is_nullable: 0
56
57
=head2 amount_original
58
59
  data_type: 'decimal'
60
  is_nullable: 1
61
  size: [28,6]
62
63
=head2 amount_outstanding
64
65
  data_type: 'decimal'
66
  is_nullable: 1
67
  size: [28,6]
68
69
=head2 amount_last_increment
70
71
  data_type: 'decimal'
72
  is_nullable: 1
73
  size: [28,6]
74
75
=head2 description
76
77
  data_type: 'mediumtext'
78
  is_nullable: 1
79
80
=head2 notes
81
82
  data_type: 'text'
83
  is_nullable: 1
84
85
=head2 manager_id
86
87
  data_type: 'integer'
88
  is_nullable: 1
89
90
=head2 created_on
91
92
  data_type: 'timestamp'
93
  is_nullable: 1
94
95
=head2 updated_on
96
97
  data_type: 'timestamp'
98
  is_nullable: 1
99
100
=cut
101
102
__PACKAGE__->add_columns(
103
  "debit_id",
104
  { data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
105
  "borrowernumber",
106
  {
107
    data_type      => "integer",
108
    default_value  => 0,
109
    is_foreign_key => 1,
110
    is_nullable    => 0,
111
  },
112
  "itemnumber",
113
  { data_type => "integer", is_nullable => 1 },
114
  "issue_id",
115
  { data_type => "integer", is_nullable => 1 },
116
  "type",
117
  { data_type => "varchar", is_nullable => 0, size => 255 },
118
  "accruing",
119
  { data_type => "tinyint", default_value => 0, is_nullable => 0 },
120
  "amount_original",
121
  { data_type => "decimal", is_nullable => 1, size => [28, 6] },
122
  "amount_outstanding",
123
  { data_type => "decimal", is_nullable => 1, size => [28, 6] },
124
  "amount_last_increment",
125
  { data_type => "decimal", is_nullable => 1, size => [28, 6] },
126
  "description",
127
  { data_type => "mediumtext", is_nullable => 1 },
128
  "notes",
129
  { data_type => "text", is_nullable => 1 },
130
  "manager_id",
131
  { data_type => "integer", is_nullable => 1 },
132
  "created_on",
133
  { data_type => "timestamp", is_nullable => 1 },
134
  "updated_on",
135
  { data_type => "timestamp", is_nullable => 1 },
136
);
137
__PACKAGE__->set_primary_key("debit_id");
138
139
=head1 RELATIONS
140
141
=head2 borrowernumber
142
143
Type: belongs_to
144
145
Related object: L<Koha::Schema::Result::Borrower>
146
147
=cut
148
149
__PACKAGE__->belongs_to(
150
  "borrowernumber",
151
  "Koha::Schema::Result::Borrower",
152
  { borrowernumber => "borrowernumber" },
153
  { on_delete => "CASCADE", on_update => "CASCADE" },
154
);
155
156
=head2 account_offsets
157
158
Type: has_many
159
160
Related object: L<Koha::Schema::Result::AccountOffset>
161
162
=cut
163
164
__PACKAGE__->has_many(
165
  "account_offsets",
166
  "Koha::Schema::Result::AccountOffset",
167
  { "foreign.debit_id" => "self.debit_id" },
168
  { cascade_copy => 0, cascade_delete => 0 },
169
);
170
171
172
# Created by DBIx::Class::Schema::Loader v0.07000 @ 2013-11-05 08:09:09
173
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ulQStZJSzcD4hvrPbtew4g
174
175
__PACKAGE__->belongs_to(
176
  "item",
177
  "Koha::Schema::Result::Item",
178
  { itemnumber => "itemnumber" }
179
);
180
181
__PACKAGE__->belongs_to(
182
  "deleted_item",
183
  "Koha::Schema::Result::Deleteditem",
184
  { itemnumber => "itemnumber" }
185
);
186
187
__PACKAGE__->belongs_to(
188
  "issue",
189
  "Koha::Schema::Result::Issue",
190
  { issue_id => "issue_id" }
191
);
192
193
__PACKAGE__->belongs_to(
194
  "old_issue",
195
  "Koha::Schema::Result::OldIssue",
196
  { issue_id => "issue_id" }
197
);
198
199
__PACKAGE__->belongs_to(
200
  "borrower",
201
  "Koha::Schema::Result::Borrower",
202
  { borrowernumber => "borrowernumber" },
203
  { on_delete => "CASCADE", on_update => "CASCADE" },
204
);
205
206
# You can replace this text with custom content, and it will be preserved on regeneration
207
1;
(-)a/Koha/Schema/Result/AccountOffset.pm (+118 lines)
Line 0 Link Here
1
package Koha::Schema::Result::AccountOffset;
2
3
# Created by DBIx::Class::Schema::Loader
4
# DO NOT MODIFY THE FIRST PART OF THIS FILE
5
6
use strict;
7
use warnings;
8
9
use base 'DBIx::Class::Core';
10
11
12
=head1 NAME
13
14
Koha::Schema::Result::AccountOffset
15
16
=cut
17
18
__PACKAGE__->table("account_offsets");
19
20
=head1 ACCESSORS
21
22
=head2 offset_id
23
24
  data_type: 'integer'
25
  is_auto_increment: 1
26
  is_nullable: 0
27
28
=head2 debit_id
29
30
  data_type: 'integer'
31
  is_foreign_key: 1
32
  is_nullable: 1
33
34
=head2 credit_id
35
36
  data_type: 'integer'
37
  is_foreign_key: 1
38
  is_nullable: 1
39
40
=head2 type
41
42
  data_type: 'varchar'
43
  is_nullable: 1
44
  size: 255
45
46
=head2 amount
47
48
  data_type: 'decimal'
49
  is_nullable: 0
50
  size: [28,6]
51
52
=head2 created_on
53
54
  data_type: 'timestamp'
55
  default_value: current_timestamp
56
  is_nullable: 0
57
58
=cut
59
60
__PACKAGE__->add_columns(
61
  "offset_id",
62
  { data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
63
  "debit_id",
64
  { data_type => "integer", is_foreign_key => 1, is_nullable => 1 },
65
  "credit_id",
66
  { data_type => "integer", is_foreign_key => 1, is_nullable => 1 },
67
  "type",
68
  { data_type => "varchar", is_nullable => 1, size => 255 },
69
  "amount",
70
  { data_type => "decimal", is_nullable => 0, size => [28, 6] },
71
  "created_on",
72
  {
73
    data_type     => "timestamp",
74
    default_value => \"current_timestamp",
75
    is_nullable   => 0,
76
  },
77
);
78
__PACKAGE__->set_primary_key("offset_id");
79
80
=head1 RELATIONS
81
82
=head2 debit
83
84
Type: belongs_to
85
86
Related object: L<Koha::Schema::Result::AccountDebit>
87
88
=cut
89
90
__PACKAGE__->belongs_to(
91
  "debit",
92
  "Koha::Schema::Result::AccountDebit",
93
  { debit_id => "debit_id" },
94
  { join_type => "LEFT", on_delete => "CASCADE", on_update => "CASCADE" },
95
);
96
97
=head2 credit
98
99
Type: belongs_to
100
101
Related object: L<Koha::Schema::Result::AccountCredit>
102
103
=cut
104
105
__PACKAGE__->belongs_to(
106
  "credit",
107
  "Koha::Schema::Result::AccountCredit",
108
  { credit_id => "credit_id" },
109
  { join_type => "LEFT", on_delete => "CASCADE", on_update => "CASCADE" },
110
);
111
112
113
# Created by DBIx::Class::Schema::Loader v0.07000 @ 2013-11-05 08:47:10
114
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:BLjpL8skXmzxOQ/J0jzdvw
115
116
117
# You can replace this text with custom content, and it will be preserved on regeneration
118
1;
(-)a/Koha/Schema/Result/Borrower.pm (-75 / +62 lines)
Lines 1-21 Link Here
1
use utf8;
2
package Koha::Schema::Result::Borrower;
1
package Koha::Schema::Result::Borrower;
3
2
4
# Created by DBIx::Class::Schema::Loader
3
# Created by DBIx::Class::Schema::Loader
5
# DO NOT MODIFY THE FIRST PART OF THIS FILE
4
# DO NOT MODIFY THE FIRST PART OF THIS FILE
6
5
7
=head1 NAME
8
9
Koha::Schema::Result::Borrower
10
11
=cut
12
13
use strict;
6
use strict;
14
use warnings;
7
use warnings;
15
8
16
use base 'DBIx::Class::Core';
9
use base 'DBIx::Class::Core';
17
10
18
=head1 TABLE: C<borrowers>
11
12
=head1 NAME
13
14
Koha::Schema::Result::Borrower
19
15
20
=cut
16
=cut
21
17
Lines 191-197 __PACKAGE__->table("borrowers"); Link Here
191
=head2 dateofbirth
187
=head2 dateofbirth
192
188
193
  data_type: 'date'
189
  data_type: 'date'
194
  datetime_undef_if_invalid: 1
195
  is_nullable: 1
190
  is_nullable: 1
196
191
197
=head2 branchcode
192
=head2 branchcode
Lines 213-225 __PACKAGE__->table("borrowers"); Link Here
213
=head2 dateenrolled
208
=head2 dateenrolled
214
209
215
  data_type: 'date'
210
  data_type: 'date'
216
  datetime_undef_if_invalid: 1
217
  is_nullable: 1
211
  is_nullable: 1
218
212
219
=head2 dateexpiry
213
=head2 dateexpiry
220
214
221
  data_type: 'date'
215
  data_type: 'date'
222
  datetime_undef_if_invalid: 1
223
  is_nullable: 1
216
  is_nullable: 1
224
217
225
=head2 gonenoaddress
218
=head2 gonenoaddress
Lines 235-241 __PACKAGE__->table("borrowers"); Link Here
235
=head2 debarred
228
=head2 debarred
236
229
237
  data_type: 'date'
230
  data_type: 'date'
238
  datetime_undef_if_invalid: 1
239
  is_nullable: 1
231
  is_nullable: 1
240
232
241
=head2 debarredcomment
233
=head2 debarredcomment
Lines 397-402 __PACKAGE__->table("borrowers"); Link Here
397
  default_value: 1
389
  default_value: 1
398
  is_nullable: 0
390
  is_nullable: 0
399
391
392
=head2 account_balance
393
394
  data_type: 'decimal'
395
  default_value: 0.000000
396
  is_nullable: 0
397
  size: [28,6]
398
400
=cut
399
=cut
401
400
402
__PACKAGE__->add_columns(
401
__PACKAGE__->add_columns(
Lines 463-469 __PACKAGE__->add_columns( Link Here
463
  "b_phone",
462
  "b_phone",
464
  { data_type => "mediumtext", is_nullable => 1 },
463
  { data_type => "mediumtext", is_nullable => 1 },
465
  "dateofbirth",
464
  "dateofbirth",
466
  { data_type => "date", datetime_undef_if_invalid => 1, is_nullable => 1 },
465
  { data_type => "date", is_nullable => 1 },
467
  "branchcode",
466
  "branchcode",
468
  {
467
  {
469
    data_type => "varchar",
468
    data_type => "varchar",
Lines 481-495 __PACKAGE__->add_columns( Link Here
481
    size => 10,
480
    size => 10,
482
  },
481
  },
483
  "dateenrolled",
482
  "dateenrolled",
484
  { data_type => "date", datetime_undef_if_invalid => 1, is_nullable => 1 },
483
  { data_type => "date", is_nullable => 1 },
485
  "dateexpiry",
484
  "dateexpiry",
486
  { data_type => "date", datetime_undef_if_invalid => 1, is_nullable => 1 },
485
  { data_type => "date", is_nullable => 1 },
487
  "gonenoaddress",
486
  "gonenoaddress",
488
  { data_type => "tinyint", is_nullable => 1 },
487
  { data_type => "tinyint", is_nullable => 1 },
489
  "lost",
488
  "lost",
490
  { data_type => "tinyint", is_nullable => 1 },
489
  { data_type => "tinyint", is_nullable => 1 },
491
  "debarred",
490
  "debarred",
492
  { data_type => "date", datetime_undef_if_invalid => 1, is_nullable => 1 },
491
  { data_type => "date", is_nullable => 1 },
493
  "debarredcomment",
492
  "debarredcomment",
494
  { data_type => "varchar", is_nullable => 1, size => 255 },
493
  { data_type => "varchar", is_nullable => 1, size => 255 },
495
  "contactname",
494
  "contactname",
Lines 546-580 __PACKAGE__->add_columns( Link Here
546
  { data_type => "varchar", is_nullable => 1, size => 50 },
545
  { data_type => "varchar", is_nullable => 1, size => 50 },
547
  "privacy",
546
  "privacy",
548
  { data_type => "integer", default_value => 1, is_nullable => 0 },
547
  { data_type => "integer", default_value => 1, is_nullable => 0 },
548
  "account_balance",
549
  {
550
    data_type => "decimal",
551
    default_value => "0.000000",
552
    is_nullable => 0,
553
    size => [28, 6],
554
  },
549
);
555
);
556
__PACKAGE__->set_primary_key("borrowernumber");
557
__PACKAGE__->add_unique_constraint("cardnumber", ["cardnumber"]);
550
558
551
=head1 PRIMARY KEY
559
=head1 RELATIONS
552
560
553
=over 4
561
=head2 account_credits
554
562
555
=item * L</borrowernumber>
563
Type: has_many
556
564
557
=back
565
Related object: L<Koha::Schema::Result::AccountCredit>
558
566
559
=cut
567
=cut
560
568
561
__PACKAGE__->set_primary_key("borrowernumber");
569
__PACKAGE__->has_many(
562
570
  "account_credits",
563
=head1 UNIQUE CONSTRAINTS
571
  "Koha::Schema::Result::AccountCredit",
564
572
  { "foreign.borrowernumber" => "self.borrowernumber" },
565
=head2 C<cardnumber>
573
  { cascade_copy => 0, cascade_delete => 0 },
574
);
566
575
567
=over 4
576
=head2 account_debits
568
577
569
=item * L</cardnumber>
578
Type: has_many
570
579
571
=back
580
Related object: L<Koha::Schema::Result::AccountDebit>
572
581
573
=cut
582
=cut
574
583
575
__PACKAGE__->add_unique_constraint("cardnumber", ["cardnumber"]);
584
__PACKAGE__->has_many(
576
585
  "account_debits",
577
=head1 RELATIONS
586
  "Koha::Schema::Result::AccountDebit",
587
  { "foreign.borrowernumber" => "self.borrowernumber" },
588
  { cascade_copy => 0, cascade_delete => 0 },
589
);
578
590
579
=head2 accountlines
591
=head2 accountlines
580
592
Lines 696-729 __PACKAGE__->has_many( Link Here
696
  { cascade_copy => 0, cascade_delete => 0 },
708
  { cascade_copy => 0, cascade_delete => 0 },
697
);
709
);
698
710
699
=head2 branchcode
711
=head2 categorycode
700
712
701
Type: belongs_to
713
Type: belongs_to
702
714
703
Related object: L<Koha::Schema::Result::Branch>
715
Related object: L<Koha::Schema::Result::Category>
704
716
705
=cut
717
=cut
706
718
707
__PACKAGE__->belongs_to(
719
__PACKAGE__->belongs_to(
708
  "branchcode",
720
  "categorycode",
709
  "Koha::Schema::Result::Branch",
721
  "Koha::Schema::Result::Category",
710
  { branchcode => "branchcode" },
722
  { categorycode => "categorycode" },
711
  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
723
  { on_delete => "CASCADE", on_update => "CASCADE" },
712
);
724
);
713
725
714
=head2 categorycode
726
=head2 branchcode
715
727
716
Type: belongs_to
728
Type: belongs_to
717
729
718
Related object: L<Koha::Schema::Result::Category>
730
Related object: L<Koha::Schema::Result::Branch>
719
731
720
=cut
732
=cut
721
733
722
__PACKAGE__->belongs_to(
734
__PACKAGE__->belongs_to(
723
  "categorycode",
735
  "branchcode",
724
  "Koha::Schema::Result::Category",
736
  "Koha::Schema::Result::Branch",
725
  { categorycode => "categorycode" },
737
  { branchcode => "branchcode" },
726
  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
738
  { on_delete => "CASCADE", on_update => "CASCADE" },
727
);
739
);
728
740
729
=head2 course_instructors
741
=head2 course_instructors
Lines 1041-1080 __PACKAGE__->has_many( Link Here
1041
  { cascade_copy => 0, cascade_delete => 0 },
1053
  { cascade_copy => 0, cascade_delete => 0 },
1042
);
1054
);
1043
1055
1044
=head2 basketnoes
1045
1046
Type: many_to_many
1047
1048
Composing rels: L</aqbasketusers> -> basketno
1049
1050
=cut
1051
1052
__PACKAGE__->many_to_many("basketnoes", "aqbasketusers", "basketno");
1053
1054
=head2 budgets
1055
1056
Type: many_to_many
1057
1058
Composing rels: L</aqbudgetborrowers> -> budget
1059
1060
=cut
1061
1062
__PACKAGE__->many_to_many("budgets", "aqbudgetborrowers", "budget");
1063
1064
=head2 courses
1065
1066
Type: many_to_many
1067
1056
1068
Composing rels: L</course_instructors> -> course
1057
# Created by DBIx::Class::Schema::Loader v0.07000 @ 2013-11-12 08:27:25
1069
1058
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:CcXsGi7pVHQtO+YH3pY/1A
1070
=cut
1071
1072
__PACKAGE__->many_to_many("courses", "course_instructors", "course");
1073
1074
1075
# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-10-31 16:31:19
1076
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:z4kW3xYX1CyrwvGdZu32nA
1077
1059
1060
__PACKAGE__->belongs_to(
1061
  "branch",
1062
  "Koha::Schema::Result::Branch",
1063
  { branchcode => "branchcode" },
1064
);
1078
1065
1079
# You can replace this text with custom content, and it will be preserved on regeneration
1066
# You can replace this text with custom content, and it will be preserved on regeneration
1080
1;
1067
1;
(-)a/Koha/Schema/Result/Deleteditem.pm (+11 lines)
Lines 367-372 __PACKAGE__->set_primary_key("itemnumber"); Link Here
367
# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-10-14 20:56:21
367
# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-10-14 20:56:21
368
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:dfUPy7ijJ/uh9+0AqKjSBw
368
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:dfUPy7ijJ/uh9+0AqKjSBw
369
369
370
__PACKAGE__->belongs_to(
371
  "biblio",
372
  "Koha::Schema::Result::Biblio",
373
  { biblionumber => "biblionumber" }
374
);
375
376
__PACKAGE__->belongs_to(
377
  "deleted_biblio",
378
  "Koha::Schema::Result::Deletedbiblio",
379
  { biblionumber => "biblionumber" }
380
);
370
381
371
# You can replace this text with custom content, and it will be preserved on regeneration
382
# You can replace this text with custom content, and it will be preserved on regeneration
372
1;
383
1;
(-)a/Koha/Schema/Result/Issue.pm (-51 / +31 lines)
Lines 1-21 Link Here
1
use utf8;
2
package Koha::Schema::Result::Issue;
1
package Koha::Schema::Result::Issue;
3
2
4
# Created by DBIx::Class::Schema::Loader
3
# Created by DBIx::Class::Schema::Loader
5
# DO NOT MODIFY THE FIRST PART OF THIS FILE
4
# DO NOT MODIFY THE FIRST PART OF THIS FILE
6
5
7
=head1 NAME
8
9
Koha::Schema::Result::Issue
10
11
=cut
12
13
use strict;
6
use strict;
14
use warnings;
7
use warnings;
15
8
16
use base 'DBIx::Class::Core';
9
use base 'DBIx::Class::Core';
17
10
18
=head1 TABLE: C<issues>
11
12
=head1 NAME
13
14
Koha::Schema::Result::Issue
19
15
20
=cut
16
=cut
21
17
Lines 23-28 __PACKAGE__->table("issues"); Link Here
23
19
24
=head1 ACCESSORS
20
=head1 ACCESSORS
25
21
22
=head2 issue_id
23
24
  data_type: 'integer'
25
  is_auto_increment: 1
26
  is_nullable: 0
27
26
=head2 borrowernumber
28
=head2 borrowernumber
27
29
28
  data_type: 'integer'
30
  data_type: 'integer'
Lines 38-44 __PACKAGE__->table("issues"); Link Here
38
=head2 date_due
40
=head2 date_due
39
41
40
  data_type: 'datetime'
42
  data_type: 'datetime'
41
  datetime_undef_if_invalid: 1
42
  is_nullable: 1
43
  is_nullable: 1
43
44
44
=head2 branchcode
45
=head2 branchcode
Lines 56-68 __PACKAGE__->table("issues"); Link Here
56
=head2 returndate
57
=head2 returndate
57
58
58
  data_type: 'datetime'
59
  data_type: 'datetime'
59
  datetime_undef_if_invalid: 1
60
  is_nullable: 1
60
  is_nullable: 1
61
61
62
=head2 lastreneweddate
62
=head2 lastreneweddate
63
63
64
  data_type: 'datetime'
64
  data_type: 'datetime'
65
  datetime_undef_if_invalid: 1
66
  is_nullable: 1
65
  is_nullable: 1
67
66
68
=head2 return
67
=head2 return
Lines 79-141 __PACKAGE__->table("issues"); Link Here
79
=head2 timestamp
78
=head2 timestamp
80
79
81
  data_type: 'timestamp'
80
  data_type: 'timestamp'
82
  datetime_undef_if_invalid: 1
83
  default_value: current_timestamp
81
  default_value: current_timestamp
84
  is_nullable: 0
82
  is_nullable: 0
85
83
86
=head2 issuedate
84
=head2 issuedate
87
85
88
  data_type: 'datetime'
86
  data_type: 'datetime'
89
  datetime_undef_if_invalid: 1
90
  is_nullable: 1
87
  is_nullable: 1
91
88
92
=cut
89
=cut
93
90
94
__PACKAGE__->add_columns(
91
__PACKAGE__->add_columns(
92
  "issue_id",
93
  { data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
95
  "borrowernumber",
94
  "borrowernumber",
96
  { data_type => "integer", is_foreign_key => 1, is_nullable => 1 },
95
  { data_type => "integer", is_foreign_key => 1, is_nullable => 1 },
97
  "itemnumber",
96
  "itemnumber",
98
  { data_type => "integer", is_foreign_key => 1, is_nullable => 1 },
97
  { data_type => "integer", is_foreign_key => 1, is_nullable => 1 },
99
  "date_due",
98
  "date_due",
100
  {
99
  { data_type => "datetime", is_nullable => 1 },
101
    data_type => "datetime",
102
    datetime_undef_if_invalid => 1,
103
    is_nullable => 1,
104
  },
105
  "branchcode",
100
  "branchcode",
106
  { data_type => "varchar", is_nullable => 1, size => 10 },
101
  { data_type => "varchar", is_nullable => 1, size => 10 },
107
  "issuingbranch",
102
  "issuingbranch",
108
  { data_type => "varchar", is_nullable => 1, size => 18 },
103
  { data_type => "varchar", is_nullable => 1, size => 18 },
109
  "returndate",
104
  "returndate",
110
  {
105
  { data_type => "datetime", is_nullable => 1 },
111
    data_type => "datetime",
112
    datetime_undef_if_invalid => 1,
113
    is_nullable => 1,
114
  },
115
  "lastreneweddate",
106
  "lastreneweddate",
116
  {
107
  { data_type => "datetime", is_nullable => 1 },
117
    data_type => "datetime",
118
    datetime_undef_if_invalid => 1,
119
    is_nullable => 1,
120
  },
121
  "return",
108
  "return",
122
  { data_type => "varchar", is_nullable => 1, size => 4 },
109
  { data_type => "varchar", is_nullable => 1, size => 4 },
123
  "renewals",
110
  "renewals",
124
  { data_type => "tinyint", is_nullable => 1 },
111
  { data_type => "tinyint", is_nullable => 1 },
125
  "timestamp",
112
  "timestamp",
126
  {
113
  {
127
    data_type => "timestamp",
114
    data_type     => "timestamp",
128
    datetime_undef_if_invalid => 1,
129
    default_value => \"current_timestamp",
115
    default_value => \"current_timestamp",
130
    is_nullable => 0,
116
    is_nullable   => 0,
131
  },
117
  },
132
  "issuedate",
118
  "issuedate",
133
  {
119
  { data_type => "datetime", is_nullable => 1 },
134
    data_type => "datetime",
135
    datetime_undef_if_invalid => 1,
136
    is_nullable => 1,
137
  },
138
);
120
);
121
__PACKAGE__->set_primary_key("issue_id");
139
122
140
=head1 RELATIONS
123
=head1 RELATIONS
141
124
Lines 151-162 __PACKAGE__->belongs_to( Link Here
151
  "borrowernumber",
134
  "borrowernumber",
152
  "Koha::Schema::Result::Borrower",
135
  "Koha::Schema::Result::Borrower",
153
  { borrowernumber => "borrowernumber" },
136
  { borrowernumber => "borrowernumber" },
154
  {
137
  { join_type => "LEFT", on_delete => "CASCADE", on_update => "CASCADE" },
155
    is_deferrable => 1,
156
    join_type     => "LEFT",
157
    on_delete     => "CASCADE",
158
    on_update     => "CASCADE",
159
  },
160
);
138
);
161
139
162
=head2 itemnumber
140
=head2 itemnumber
Lines 171-193 __PACKAGE__->belongs_to( Link Here
171
  "itemnumber",
149
  "itemnumber",
172
  "Koha::Schema::Result::Item",
150
  "Koha::Schema::Result::Item",
173
  { itemnumber => "itemnumber" },
151
  { itemnumber => "itemnumber" },
174
  {
152
  { join_type => "LEFT", on_delete => "CASCADE", on_update => "CASCADE" },
175
    is_deferrable => 1,
176
    join_type     => "LEFT",
177
    on_delete     => "CASCADE",
178
    on_update     => "CASCADE",
179
  },
180
);
153
);
181
154
182
155
183
# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-10-14 20:56:21
156
# Created by DBIx::Class::Schema::Loader v0.07000 @ 2013-11-12 09:32:52
184
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ZEh31EKBmURMKxDxI+H3EA
157
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:zBewWFig+yZYtSkcIxCZpg
185
158
186
__PACKAGE__->belongs_to(
159
__PACKAGE__->belongs_to(
187
  "borrower",
160
  "borrower",
188
  "Koha::Schema::Result::Borrower",
161
  "Koha::Schema::Result::Borrower",
189
  { borrowernumber => "borrowernumber" },
162
  { borrowernumber => "borrowernumber" },
190
  { join_type => "LEFT", on_delete => "CASCADE", on_update => "CASCADE" },
163
  { join_type => "LEFT" },
164
);
165
166
__PACKAGE__->belongs_to(
167
  "item",
168
  "Koha::Schema::Result::Item",
169
  { itemnumber => "itemnumber" },
170
  { join_type => "LEFT" },
191
);
171
);
192
172
193
1;
173
1;
(-)a/Koha/Schema/Result/OldIssue.pm (-1 / +27 lines)
Lines 183-188 __PACKAGE__->belongs_to( Link Here
183
# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-10-14 20:56:21
183
# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-10-14 20:56:21
184
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:uPOxNROoMMRZ0qZsXsxEjA
184
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:uPOxNROoMMRZ0qZsXsxEjA
185
185
186
__PACKAGE__->belongs_to(
187
  "borrower",
188
  "Koha::Schema::Result::Borrower",
189
  { borrowernumber => "borrowernumber" },
190
  { join_type => "LEFT" },
191
);
192
193
__PACKAGE__->belongs_to(
194
  "item",
195
  "Koha::Schema::Result::Item",
196
  { itemnumber => "itemnumber" },
197
  { join_type => "LEFT" },
198
);
199
200
__PACKAGE__->belongs_to(
201
  "deletedborrower",
202
  "Koha::Schema::Result::Deletedborrower",
203
  { borrowernumber => "borrowernumber" },
204
  { join_type => "LEFT" },
205
);
206
207
__PACKAGE__->belongs_to(
208
  "deleteditem",
209
  "Koha::Schema::Result::Deleteditem",
210
  { itemnumber => "itemnumber" },
211
  { join_type => "LEFT" },
212
);
186
213
187
# You can replace this text with custom content, and it will be preserved on regeneration
188
1;
214
1;
(-)a/Koha/Template/Plugin/Currency.pm (+90 lines)
Line 0 Link Here
1
package Koha::Template::Plugin::Currency;
2
3
# Copyright ByWater Solutions 2013
4
5
# This file is part of Koha.
6
#
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.
11
#
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.
15
#
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.
19
20
use Modern::Perl;
21
22
use base qw( Template::Plugin::Filter );
23
24
use Locale::Currency::Format;
25
26
use C4::Context;
27
use Koha::DateUtils;
28
29
sub init {
30
    my $self = shift;
31
    $self->{ _DYNAMIC } = 1;
32
33
    my $active_currency = C4::Context->dbh->selectrow_hashref(
34
        'SELECT * FROM currency WHERE active = 1', {} );
35
    $self->{active_currency} = $active_currency;
36
37
    return $self;
38
}
39
40
sub filter {
41
    my ( $self, $amount, $args, $conf ) = @_;
42
43
    return $self->format( $amount, undef, $conf->{highlight} );
44
}
45
46
sub format {
47
    my ( $self, $amount, $format, $highlight ) = @_;
48
49
    my $is_negative = $amount < 0;
50
    $amount = abs( $amount ) if $highlight;
51
52
    # A negative debit is a credit and visa versa
53
    if ($highlight) {
54
        if ( $highlight eq 'debit' ) {
55
            if ($is_negative) {
56
                $highlight = 'credit';
57
            }
58
        }
59
        elsif ( $highlight eq 'credit' ) {
60
            if ($is_negative) {
61
                $highlight = 'debit';
62
            }
63
64
        }
65
        elsif ( $highlight eq 'offset' ) {
66
            $highlight = $is_negative ? 'credit' : 'debit';
67
        }
68
    }
69
70
    my $formatted = currency_format( $self->{active_currency}->{currency},
71
        $amount, $format || FMT_HTML );
72
73
    $formatted = "<span class='$highlight'>$formatted</span>" if ( $highlight && $amount );
74
75
    return $formatted;
76
}
77
78
sub format_without_symbol {
79
    my ( $self, $amount ) = @_;
80
81
    return substr( $self->format( $amount, FMT_SYMBOL ), 1, 0 );
82
}
83
84
sub symbol {
85
    my ($self) = @_;
86
87
    return currency_symbol( $self->{active_currency}->{'currency'}, SYM_HTML );
88
}
89
90
1;
(-)a/circ/circulation.pl (-3 / +1 lines)
Lines 648-655 foreach my $flag ( sort keys %$flags ) { Link Here
648
my $amountold = $borrower->{flags}->{'CHARGES'}->{'message'} || 0;
648
my $amountold = $borrower->{flags}->{'CHARGES'}->{'message'} || 0;
649
$amountold =~ s/^.*\$//;    # remove upto the $, if any
649
$amountold =~ s/^.*\$//;    # remove upto the $, if any
650
650
651
my ( $total, $accts, $numaccts) = GetMemberAccountRecords( $borrowernumber );
652
653
if ( $borrower->{'category_type'} eq 'C') {
651
if ( $borrower->{'category_type'} eq 'C') {
654
    my  ( $catcodes, $labels ) =  GetborCatFromCatType( 'A', 'WHERE category_type = ?' );
652
    my  ( $catcodes, $labels ) =  GetborCatFromCatType( 'A', 'WHERE category_type = ?' );
655
    my $cnt = scalar(@$catcodes);
653
    my $cnt = scalar(@$catcodes);
Lines 739-745 $template->param( Link Here
739
    message           => $message,
737
    message           => $message,
740
    CGIselectborrower => $CGIselectborrower,
738
    CGIselectborrower => $CGIselectborrower,
741
    totalprice        => sprintf('%.2f', $totalprice),
739
    totalprice        => sprintf('%.2f', $totalprice),
742
    totaldue          => sprintf('%.2f', $total),
740
    totaldue          => sprintf('%.2f', $borrower->{account_balance}),
743
    todayissues       => \@todaysissues,
741
    todayissues       => \@todaysissues,
744
    previssues        => \@previousissues,
742
    previssues        => \@previousissues,
745
    relissues			=> \@relissues,
743
    relissues			=> \@relissues,
(-)a/installer/data/mysql/kohastructure.sql (+83 lines)
Lines 265-270 CREATE TABLE `borrowers` ( -- this table includes information about your patrons Link Here
265
  `altcontactphone` varchar(50) default NULL, -- the phone number for the alternate contact for the patron/borrower
265
  `altcontactphone` varchar(50) default NULL, -- the phone number for the alternate contact for the patron/borrower
266
  `smsalertnumber` varchar(50) default NULL, -- the mobile phone number where the patron/borrower would like to receive notices (if SNS turned on)
266
  `smsalertnumber` varchar(50) default NULL, -- the mobile phone number where the patron/borrower would like to receive notices (if SNS turned on)
267
  `privacy` integer(11) DEFAULT '1' NOT NULL, -- patron/borrower's privacy settings related to their reading history
267
  `privacy` integer(11) DEFAULT '1' NOT NULL, -- patron/borrower's privacy settings related to their reading history
268
  `account_balance` decimal(28,6) NOT NULL,
268
  UNIQUE KEY `cardnumber` (`cardnumber`),
269
  UNIQUE KEY `cardnumber` (`cardnumber`),
269
  PRIMARY KEY `borrowernumber` (`borrowernumber`),
270
  PRIMARY KEY `borrowernumber` (`borrowernumber`),
270
  KEY `categorycode` (`categorycode`),
271
  KEY `categorycode` (`categorycode`),
Lines 3387-3392 CREATE TABLE IF NOT EXISTS marc_modification_template_actions ( Link Here
3387
  CONSTRAINT `mmta_ibfk_1` FOREIGN KEY (`template_id`) REFERENCES `marc_modification_templates` (`template_id`) ON DELETE CASCADE ON UPDATE CASCADE
3388
  CONSTRAINT `mmta_ibfk_1` FOREIGN KEY (`template_id`) REFERENCES `marc_modification_templates` (`template_id`) ON DELETE CASCADE ON UPDATE CASCADE
3388
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
3389
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
3389
3390
3391
--
3392
-- Table structure for table 'account_credits'
3393
--
3394
DROP TABLE IF EXISTS account_credits;
3395
CREATE TABLE IF account_credits (
3396
    credit_id int(11) NOT NULL AUTO_INCREMENT,
3397
    borrowernumber int(11) NOT NULL,
3398
    `type` varchar(255) NOT NULL,
3399
    amount_paid decimal(28,6) NOT NULL,
3400
    amount_remaining decimal(28,6) NOT NULL,
3401
    notes text,
3402
    manager_id int(11) DEFAULT NULL,
3403
    created_on timestamp NULL DEFAULT NULL,
3404
    updated_on timestamp NULL DEFAULT NULL,
3405
    PRIMARY KEY (credit_id),
3406
    KEY borrowernumber (borrowernumber)
3407
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
3408
3409
--
3410
-- Constraints for table `account_credits`
3411
--
3412
ALTER TABLE `account_credits`
3413
  ADD CONSTRAINT account_credits_ibfk_1 FOREIGN KEY (borrowernumber) REFERENCES borrowers (borrowernumber) ON DELETE CASCADE ON UPDATE CASCADE;
3414
3415
--
3416
-- Table structure for table 'account_debits'
3417
--
3418
3419
DROP TABLE IF EXISTS account_debits;
3420
CREATE TABLE account_debits (
3421
    debit_id int(11) NOT NULL AUTO_INCREMENT,
3422
    borrowernumber int(11) NOT NULL DEFAULT '0',
3423
    itemnumber int(11) DEFAULT NULL,
3424
    issue_id int(11) DEFAULT NULL,
3425
    `type` varchar(255) NOT NULL,
3426
    accruing tinyint(1) NOT NULL DEFAULT '0',
3427
    amount_original decimal(28,6) DEFAULT NULL,
3428
    amount_outstanding decimal(28,6) DEFAULT NULL,
3429
    amount_last_increment decimal(28,6) DEFAULT NULL,
3430
    description mediumtext,
3431
    notes text,
3432
    manager_id int(11) DEFAULT NULL,
3433
    created_on timestamp NULL DEFAULT NULL,
3434
    updated_on timestamp NULL DEFAULT NULL,
3435
    PRIMARY KEY (debit_id),
3436
    KEY acctsborridx (borrowernumber),
3437
    KEY itemnumber (itemnumber),
3438
    KEY borrowernumber (borrowernumber),
3439
    KEY issue_id (issue_id)
3440
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
3441
3442
--
3443
-- Constraints for table `account_debits`
3444
--
3445
ALTER TABLE `account_debits`
3446
    ADD CONSTRAINT account_debits_ibfk_1 FOREIGN KEY (borrowernumber) REFERENCES borrowers (borrowernumber) ON DELETE CASCADE ON UPDATE CASCADE;
3447
3448
--
3449
-- Table structure for table 'account_offsets'
3450
--
3451
3452
DROP TABLE IF EXISTS account_offsets;
3453
CREATE TABLE account_offsets (
3454
    offset_id int(11) NOT NULL AUTO_INCREMENT,
3455
    debit_id int(11) DEFAULT NULL,
3456
    credit_id int(11) DEFAULT NULL,
3457
    `type` varchar(255) DEFAULT NULL,
3458
    amount decimal(28,6) NOT NULL,
3459
    created_on timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
3460
    PRIMARY KEY (offset_id),
3461
    KEY fee_id (debit_id),
3462
    KEY payment_id (credit_id)
3463
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
3464
3465
--
3466
-- Constraints for table `account_offsets`
3467
--
3468
ALTER TABLE `account_offsets`
3469
    ADD CONSTRAINT account_offsets_ibfk_1 FOREIGN KEY (debit_id) REFERENCES account_debits (debit_id) ON DELETE CASCADE ON UPDATE CASCADE,
3470
    ADD CONSTRAINT account_offsets_ibfk_2 FOREIGN KEY (credit_id) REFERENCES account_credits (credit_id) ON DELETE CASCADE ON UPDATE CASCADE;
3471
3472
3390
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
3473
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
3391
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
3474
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
3392
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
3475
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
(-)a/installer/data/mysql/updatedatabase.pl (+88 lines)
Lines 7259-7264 if ( CheckVersion($DBversion) ) { Link Here
7259
7259
7260
    $dbh->{AutoCommit} = 1;
7260
    $dbh->{AutoCommit} = 1;
7261
    $dbh->{RaiseError} = 0;
7261
    $dbh->{RaiseError} = 0;
7262
   SetVersion ($DBversion);
7262
}
7263
}
7263
7264
7264
$DBversion = "3.13.00.031";
7265
$DBversion = "3.13.00.031";
Lines 7743-7748 if(CheckVersion($DBversion)) { Link Here
7743
    SetVersion($DBversion);
7744
    SetVersion($DBversion);
7744
}
7745
}
7745
7746
7747
$DBversion = "3.15.00.XXX";
7748
if ( CheckVersion($DBversion) ) {
7749
    $dbh->do(q{
7750
        ALTER TABLE old_issues ADD issue_id INT( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST
7751
    });
7752
    $dbh->do(q{
7753
        ALTER TABLE issues ADD issue_id INT( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST;
7754
    });
7755
    $dbh->do(q{
7756
        UPDATE issues SET issue_id = issue_id + ( SELECT COUNT(*) FROM old_issues ) ORDER BY issue_id DESC
7757
    });
7758
7759
    $dbh->do("
7760
        CREATE TABLE IF NOT EXISTS account_credits (
7761
            credit_id int(11) NOT NULL AUTO_INCREMENT,
7762
            borrowernumber int(11) NOT NULL,
7763
            `type` varchar(255) NOT NULL,
7764
            amount_paid decimal(28,6) NOT NULL,
7765
            amount_remaining decimal(28,6) NOT NULL,
7766
            notes text,
7767
            manager_id int(11) DEFAULT NULL,
7768
            created_on timestamp NULL DEFAULT NULL,
7769
            updated_on timestamp NULL DEFAULT NULL,
7770
            PRIMARY KEY (credit_id),
7771
            KEY borrowernumber (borrowernumber)
7772
        ) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
7773
    ");
7774
    $dbh->do("
7775
        CREATE TABLE IF NOT EXISTS account_debits (
7776
            debit_id int(11) NOT NULL AUTO_INCREMENT,
7777
            borrowernumber int(11) NOT NULL DEFAULT '0',
7778
            itemnumber int(11) DEFAULT NULL,
7779
            issue_id int(11) DEFAULT NULL,
7780
            `type` varchar(255) NOT NULL,
7781
            accruing tinyint(1) NOT NULL DEFAULT '0',
7782
            amount_original decimal(28,6) DEFAULT NULL,
7783
            amount_outstanding decimal(28,6) DEFAULT NULL,
7784
            amount_last_increment decimal(28,6) DEFAULT NULL,
7785
            description mediumtext,
7786
            notes text,
7787
            manager_id int(11) DEFAULT NULL,
7788
            created_on timestamp NULL DEFAULT NULL,
7789
            updated_on timestamp NULL DEFAULT NULL,
7790
            PRIMARY KEY (debit_id),
7791
            KEY acctsborridx (borrowernumber),
7792
            KEY itemnumber (itemnumber),
7793
            KEY borrowernumber (borrowernumber),
7794
            KEY issue_id (issue_id)
7795
        ) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
7796
    ");
7797
7798
    $dbh->do("
7799
        CREATE TABLE account_offsets (
7800
            offset_id int(11) NOT NULL AUTO_INCREMENT,
7801
            debit_id int(11) DEFAULT NULL,
7802
            credit_id int(11) DEFAULT NULL,
7803
            `type` varchar(255) DEFAULT NULL,
7804
            amount decimal(28,6) NOT NULL COMMENT 'A positive number here represents a payment, a negative is a increase in a fine.',
7805
            created_on timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
7806
            PRIMARY KEY (offset_id),
7807
            KEY fee_id (debit_id),
7808
            KEY payment_id (credit_id)
7809
        ) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
7810
    ");
7811
7812
    $dbh->do("
7813
        ALTER TABLE `account_credits`
7814
          ADD CONSTRAINT account_credits_ibfk_1 FOREIGN KEY (borrowernumber) REFERENCES borrowers (borrowernumber) ON DELETE CASCADE ON UPDATE CASCADE;
7815
    ");
7816
    $dbh->do("
7817
        ALTER TABLE `account_debits`
7818
          ADD CONSTRAINT account_debits_ibfk_1 FOREIGN KEY (borrowernumber) REFERENCES borrowers (borrowernumber) ON DELETE CASCADE ON UPDATE CASCADE;
7819
    ");
7820
    $dbh->do("
7821
        ALTER TABLE `account_offsets`
7822
          ADD CONSTRAINT account_offsets_ibfk_1 FOREIGN KEY (debit_id) REFERENCES account_debits (debit_id) ON DELETE CASCADE ON UPDATE CASCADE,
7823
          ADD CONSTRAINT account_offsets_ibfk_2 FOREIGN KEY (credit_id) REFERENCES account_credits (credit_id) ON DELETE CASCADE ON UPDATE CASCADE;
7824
    ");
7825
7826
    $dbh->do("
7827
        ALTER TABLE borrowers ADD account_balance DECIMAL( 28, 6 ) NOT NULL;
7828
    ");
7829
7830
    print "Upgrade to $DBversion done ( Bug 6427 - Rewrite of the accounts system )\n";
7831
    SetVersion ($DBversion);
7832
}
7833
7746
=head1 FUNCTIONS
7834
=head1 FUNCTIONS
7747
7835
7748
=head2 TableExists($table)
7836
=head2 TableExists($table)
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.inc (-1 / +1 lines)
Lines 67-73 Link Here
67
        [% IF ( detailview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">Details</a></li>
67
        [% IF ( detailview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">Details</a></li>
68
    [% END %]
68
    [% END %]
69
    [% IF ( CAN_user_updatecharges ) %]
69
    [% IF ( CAN_user_updatecharges ) %]
70
        [% IF ( finesview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrowernumber %]">Fines</a></li>
70
        [% IF ( accounts_view ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Fines</a></li>
71
    [% END %]
71
    [% END %]
72
    [% IF ( RoutingSerials ) %][% IF ( routinglistview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/routing-lists.pl?borrowernumber=[% borrowernumber %]">Routing lists</a></li>[% END %]
72
    [% IF ( RoutingSerials ) %][% IF ( routinglistview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/routing-lists.pl?borrowernumber=[% borrowernumber %]">Routing lists</a></li>[% END %]
73
    [% IF ( intranetreadinghistory ) %]
73
    [% IF ( intranetreadinghistory ) %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.tt (-1 / +1 lines)
Lines 70-76 in the global namespace %] Link Here
70
	[% IF ( detailview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrower.borrowernumber %]">Details</a></li>
70
	[% IF ( detailview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrower.borrowernumber %]">Details</a></li>
71
	[% END %]
71
	[% END %]
72
	 [% IF ( CAN_user_updatecharges ) %]
72
	 [% IF ( CAN_user_updatecharges ) %]
73
	[% IF ( finesview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrower.borrowernumber %]">Fines</a></li>
73
 [% IF ( accounts_view ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrower.borrowernumber %]">Fines</a></li>
74
	[% END %]
74
	[% END %]
75
    [% IF ( RoutingSerials ) %][% IF ( routinglistview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/routing-lists.pl?borrowernumber=[% borrower.borrowernumber %]">Routing lists</a></li>[% END %]
75
    [% IF ( RoutingSerials ) %][% IF ( routinglistview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/routing-lists.pl?borrowernumber=[% borrower.borrowernumber %]">Routing lists</a></li>[% END %]
76
    [% IF ( intranetreadinghistory ) %][% IF ( readingrecordview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/readingrec.pl?borrowernumber=[% borrower.borrowernumber %]">Circulation history</a></li>[% END %]
76
    [% IF ( intranetreadinghistory ) %][% IF ( readingrecordview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/readingrec.pl?borrowernumber=[% borrower.borrowernumber %]">Circulation history</a></li>[% END %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/members-menu.inc (-1 / +1 lines)
Lines 4-10 Link Here
4
    [% IF ( circview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/circ/circulation.pl?borrowernumber=[% borrowernumber %]">Check out</a></li>
4
    [% IF ( circview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/circ/circulation.pl?borrowernumber=[% borrowernumber %]">Check out</a></li>
5
    [% IF ( detailview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">Details</a></li>
5
    [% IF ( detailview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">Details</a></li>
6
    [% IF ( CAN_user_updatecharges ) %]
6
    [% IF ( CAN_user_updatecharges ) %]
7
        [% IF ( finesview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrowernumber %]">Fines</a></li>
7
        [% IF ( finesview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Fines</a></li>
8
    [% END %]
8
    [% END %]
9
    [% IF ( intranetreadinghistory ) %]
9
    [% IF ( intranetreadinghistory ) %]
10
        [% IF ( readingrecordview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/readingrec.pl?borrowernumber=[% borrowernumber %]">Circulation history</a></li>
10
        [% IF ( readingrecordview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/readingrec.pl?borrowernumber=[% borrowernumber %]">Circulation history</a></li>
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt (-3 / +4 lines)
Lines 1-5 Link Here
1
[% USE KohaBranchName %]
1
[% USE KohaBranchName %]
2
[% USE KohaDates %]
2
[% USE KohaDates %]
3
[% USE Currency %]
3
[% IF ( export_remove_fields OR export_with_csv_profile ) %]
4
[% IF ( export_remove_fields OR export_with_csv_profile ) %]
4
   [% SET exports_enabled = 1 %]
5
   [% SET exports_enabled = 1 %]
5
[% END %]
6
[% END %]
Lines 577-592 No patron matched <span class="ex">[% message %]</span> Link Here
577
578
578
        	[% IF ( charges ) %]
579
        	[% IF ( charges ) %]
579
			    <li>
580
			    <li>
580
            <span class="circ-hlt">Fees &amp; Charges:</span> Patron has  <a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrowernumber %]">Outstanding fees &amp; charges[% IF ( chargesamount ) %] of [% chargesamount %][% END %]</a>.
581
            <span class="circ-hlt">Fees &amp; Charges:</span> Patron has  <a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Outstanding fees &amp; charges[% IF ( chargesamount ) %] of [% chargesamount | $Currency %][% END %]</a>.
581
                [% IF ( charges_is_blocker ) %]
582
                [% IF ( charges_is_blocker ) %]
582
                    Checkouts are <span class="circ-hlt">BLOCKED</span> because fine balance is <span class="circ-hlt">OVER THE LIMIT</span>.
583
                    Checkouts are <span class="circ-hlt">BLOCKED</span> because fine balance is <span class="circ-hlt">OVER THE LIMIT</span>.
583
                [% END %]
584
                [% END %]
584
            <a href="/cgi-bin/koha/members/pay.pl?borrowernumber=[% borrowernumber %]">Make payment</a></li>
585
            <a href="/cgi-bin/koha/members/account_payment.pl?borrowernumber=[% borrowernumber %]">Make payment</a></li>
585
			[% END %]
586
			[% END %]
586
587
587
        	[% IF ( credits ) %]
588
        	[% IF ( credits ) %]
588
			<li>
589
			<li>
589
                <span class="circ-hlt">Credits:</span> Patron has a credit[% IF ( creditsamount ) %] of [% creditsamount %][% END %]
590
                <span class="circ-hlt">Credits:</span> Patron has a credit[% IF ( creditsamount ) %] of [% creditsamount | $Currency %][% END %]
590
            </li>
591
            </li>
591
			[% END %]
592
			[% END %]
592
593
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/returns.tt (-1 / +1 lines)
Lines 74-80 $(document).ready(function () { Link Here
74
[% IF ( fines ) %]
74
[% IF ( fines ) %]
75
    <div class="dialog alert">
75
    <div class="dialog alert">
76
        <h3>Patron has outstanding fines of [% fines %].</h3>
76
        <h3>Patron has outstanding fines of [% fines %].</h3>
77
        <p><a href="/cgi-bin/koha/members/pay.pl?borrowernumber=[% fineborrowernumber %]">Make payment</a>.</p>
77
        <p><a href="/cgi-bin/koha/members/account_payment.pl?borrowernumber=[% fineborrowernumber %]">Make payment</a>.</p>
78
    </div>
78
    </div>
79
[% END %]
79
[% END %]
80
80
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/members/account.tt (+419 lines)
Line 0 Link Here
1
[% SET accounts_view = 1 %]
2
[% USE KohaDates %]
3
[% USE Currency %]
4
[% INCLUDE 'doc-head-open.inc' %]
5
<title>Koha &rsaquo; Patrons &rsaquo; Account for [% INCLUDE 'patron-title.inc' %]</title>
6
[% INCLUDE 'doc-head-close.inc' %]
7
8
<link rel="stylesheet" type="text/css" href="[% interface %]/[% theme %]/en/css/datatables.css" />
9
<script type="text/javascript" src="[% interface %]/[% theme %]/en/lib/jquery/plugins/jquery.dataTables.min.js"></script>
10
[% INCLUDE 'datatables-strings.inc' %]
11
<script type="text/javascript" src="[% interface %]/[% theme %]/en/js/datatables.js"></script>
12
13
<script type="text/javascript">
14
//<![CDATA[
15
$(document).ready(function() {
16
    $('#account-credits').hide();    
17
    $('#account-debits-switcher').click(function() {
18
         $('#account-debits').slideUp();
19
         $('#account-credits').slideDown();
20
    });
21
    $('#account-credits-switcher').click(function() {
22
         $('#account-credits').slideUp();
23
         $('#account-debits').slideDown();
24
    });
25
26
    var anOpen = [];
27
    var sImageUrl = "[% interface %]/[% theme %]/img/";
28
29
    var debitsTable = $('#debits-table').dataTable( {
30
        "bProcessing": true,
31
        "aoColumns": [
32
            {
33
                "mDataProp": null,
34
                "sClass": "control center",
35
                "sDefaultContent": '<img src="'+sImageUrl+'details_open.png'+'">'
36
            },
37
            { "mDataProp": "debit_id" },
38
            { "mDataProp": "description" },
39
            { "mDataProp": "type" },
40
            { "mDataProp": "amount_original" },
41
            { "mDataProp": "amount_outstanding" },
42
            { "mDataProp": "created_on" },
43
            { "mDataProp": "updated_on" }
44
        ],
45
        "aaData": [
46
            [% FOREACH d IN debits %]
47
                {
48
                    [% PROCESS format_data data=d highlight='debit' %]
49
50
                    // Data for related item if there is one linked
51
                    "title": "[% d.item.biblio.title || d.deleted_item.biblio.title || d.deleted_item.deleted_biblio.title %]",
52
                    "biblionumber": "[% d.item.biblio.biblionumber || d.deleted_item.biblio.biblionumber %]",
53
                    "barcode": "[% d.item.barcode || d.deleted_item.barcode %]",
54
                    "itemnumber": "[% d.item.itemnumber %]", //This way itemnumber will be undef if deleted
55
56
57
                    // Data for related issue if there is one linked
58
                    [% IF d.issue %]
59
                        [% SET table = 'issue' %]
60
                    [% ELSIF d.old_issue %]
61
                        [% SET table = 'old_issue' %]
62
                    [% END %]
63
64
                    [% IF table %]
65
                        "issue": {
66
                            [% PROCESS format_data data=d.$table %]
67
                        },
68
                    [% END %]
69
70
71
                    "account_offsets": [
72
                        [% FOREACH ao IN d.account_offsets %]
73
                            {
74
                                [% PROCESS format_data data=ao highlight='offset'%]
75
76
                                "credit": {
77
                                    [% PROCESS format_data data=ao.credit highlight='credit' %]
78
                                } 
79
                            },
80
                        [% END %]
81
                    ] 
82
83
                },
84
            [% END %]
85
        ] 
86
    } );
87
88
    $('#debits-table td.control').live( 'click', function () {
89
        var nTr = this.parentNode;
90
        var i = $.inArray( nTr, anOpen );
91
92
        if ( i === -1 ) {
93
            $('img', this).attr( 'src', sImageUrl+"details_close.png" );
94
            var nDetailsRow = debitsTable.fnOpen( nTr, fnFormatDebitDetails(debitsTable, nTr), 'details' );
95
            $('div.innerDetails', nDetailsRow).slideDown();
96
            anOpen.push( nTr );
97
        } 
98
        else {
99
            $('img', this).attr( 'src', sImageUrl+"details_open.png" );
100
            $('div.innerDetails', $(nTr).next()[0]).slideUp( function () {
101
                debitsTable.fnClose( nTr );
102
                anOpen.splice( i, 1 );
103
            } );
104
        }
105
    } );
106
107
    var creditsTable = $('#credits-table').dataTable( {
108
        "bProcessing": true,
109
        "aoColumns": [
110
            {
111
                "mDataProp": null,
112
                "sClass": "control center",
113
                "sDefaultContent": '<img src="'+sImageUrl+'details_open.png'+'">'
114
            },
115
            { "mDataProp": "credit_id" },
116
            { "mDataProp": "notes" },
117
            { "mDataProp": "type" },
118
            { "mDataProp": "amount_paid" },
119
            { "mDataProp": "amount_remaining" },
120
            { "mDataProp": "created_on" },
121
            { "mDataProp": "updated_on" }
122
        ],
123
        "aaData": [
124
            [% FOREACH c IN credits %]
125
                {
126
                    [% PROCESS format_data data=c highlight='credit' %]
127
128
                    "account_offsets": [
129
                        [% FOREACH ao IN c.account_offsets %]
130
                            {
131
                                [% PROCESS format_data data=ao highlight='offset' %]
132
133
                                "debit": {
134
                                    [% PROCESS format_data data=ao.debit highlight='debit' %]
135
                                } 
136
                            },
137
                        [% END %]
138
                    ] 
139
140
                },
141
            [% END %]
142
        ] 
143
    } );
144
145
    $('#credits-table td.control').live( 'click', function () {
146
        var nTr = this.parentNode;
147
        var i = $.inArray( nTr, anOpen );
148
149
        if ( i === -1 ) {
150
            $('img', this).attr( 'src', sImageUrl+"details_close.png" );
151
            var nDetailsRow = creditsTable.fnOpen( nTr, fnFormatCreditDetails(creditsTable, nTr), 'details' );
152
            $('div.innerDetails', nDetailsRow).slideDown();
153
            anOpen.push( nTr );
154
        } 
155
        else {
156
            $('img', this).attr( 'src', sImageUrl+"details_open.png" );
157
            $('div.innerDetails', $(nTr).next()[0]).slideUp( function () {
158
                creditsTable.fnClose( nTr );
159
                anOpen.splice( i, 1 );
160
            } );
161
        }
162
    } );
163
164
} );
165
166
function fnFormatDebitDetails( debitsTable, nTr ) {
167
    var oData = debitsTable.fnGetData( nTr );
168
169
    var sOut = '<div class="innerDetails" style="display:none;">';
170
171
    var account_offsets = oData.account_offsets;
172
173
    sOut += '<a class="debit_print btn btn-small" style="margin:5px;" onclick="accountPrint(\'debit\',' + oData.debit_id + ')">' + 
174
                '<i class="icon-print"></i> ' + _('Print receipt') + 
175
            '</a>';
176
177
    sOut += '<ul>';
178
    if ( oData.title ) {
179
        sOut += '<li>' + _('Title: ');
180
        if ( oData.biblionumber ) {
181
            sOut += '<a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=' + oData.biblionumber + '">';
182
        }
183
184
        sOut += oData.title;
185
186
        if ( oData.biblionumber ) {
187
            sOut += '</a>';
188
        }
189
            
190
        sOut += '</li>';
191
    }
192
193
    if ( oData.barcode ) {
194
        sOut += '<li>' + _('Barcode: ');
195
        if ( oData.itemnumber ) {
196
            sOut += '<a href="/cgi-bin/koha/catalogue/moredetail.pl?itemnumber=11&biblionumber=' + oData.biblionumber + '&bi=' + oData.biblionumber + '#item' + oData.itemnumber + '' + oData.biblionumber + '">';
197
        }
198
199
        sOut += oData.barcode;
200
201
        if ( oData.itemnumber ) {
202
            sOut += '</a>';
203
        }
204
            
205
        sOut += '</li>';
206
    }
207
208
    if ( oData.notes ) {
209
        sOut += '<li>' + _('Notes: ') + oData.notes + '</li>';
210
    }
211
212
    sOut += '</ul>';
213
214
    if ( account_offsets.length ) {
215
        sOut +=
216
            '<div class="innerDetails">' +
217
                '<table cellpadding="5" cellspacing="0" border="0" style="margin:10px;">' +
218
                    '<thead>' +
219
                        '<tr><th colspan="99">' + _('Payments applied') + '</th></tr>' +
220
                        '<tr>' +
221
                            '<th>' + _('ID') + '</th>' +
222
                            '<th>' + _('Created on') + '</th>' +
223
                            '<th>' + _('Payment amount') + '</th>' +
224
                            '<th>' + _('Applied amount') + '</th>' +
225
                            '<th>' + _('Type') + '</th>' +
226
                            '<th>' + _('Notes') + '</th>' +
227
                        '</tr>' +
228
                    '</thead>' +
229
                    '<tbody>';
230
231
        for ( var i = 0; i < account_offsets.length; i++ ) {
232
            ao = account_offsets[i];
233
            sOut +=
234
            '<tr>' +
235
                '<td>' + ao.credit_id + '</td>' +
236
                '<td>' + ao.created_on + '</td>' +
237
                '<td>' + ao.credit.amount_paid + '</td>' +
238
                '<td>' + ao.amount + '</td>' +
239
                '<td>' + ao.credit.type + '</td>' +
240
                '<td>' + ao.credit.notes + '</td>' +
241
            '</tr>';
242
        }
243
244
        sOut +=
245
            '</tbody>'+
246
            '</table>';
247
    }
248
249
    sOut +=
250
        '</div>';
251
252
    return sOut;
253
}
254
255
function fnFormatCreditDetails( creditsTable, nTr ) {
256
    var oData = creditsTable.fnGetData( nTr );
257
258
    var sOut = '<div class="innerDetails" style="display:none;">';
259
260
    sOut += '<button class="credit_print btn btn-small" style="margin:5px;" onclick="accountPrint(\'credit\',' + oData.credit_id + ')">' + 
261
                '<i class="icon-print"></i> ' + _('Print receipt') + 
262
            '</button>';
263
264
    var account_offsets = oData.account_offsets;
265
266
    if ( account_offsets.length ) {
267
        sOut +=
268
                '<table cellpadding="5" cellspacing="0" border="0" style="margin:10px;">' +
269
                    '<thead>' +
270
                        '<tr><th colspan="99">' + _('Fees paid') + '</th></tr>' +
271
                        '<tr>' +
272
                            '<th>' + _('ID') + '</th>' +
273
                            '<th>' + _('Description') + '</th>' +
274
                            '<th>' + _('Type') + '</th>' +
275
                            '<th>' + _('Amount') + '</th>' +
276
                            '<th>' + _('Remaining') + '</th>' +
277
                            '<th>' + _('Created on') + '</th>' +
278
                            '<th>' + _('Updated on') + '</th>' +
279
                            '<th>' + _('Notes') + '</th>' +
280
                        '</tr>' +
281
                    '</thead>' +
282
                    '<tbody>';
283
284
        for ( var i = 0; i < account_offsets.length; i++ ) {
285
            ao = account_offsets[i];
286
            sOut +=
287
            '<tr>' +
288
                '<td>' + ao.debit.debit_id + '</td>' +
289
                '<td>' + ao.debit.description + '</td>' +
290
                '<td>' + ao.debit.type + '</td>' +
291
                '<td>' + ao.debit.amount_original + '</td>' +
292
                '<td>' + ao.debit.amount_outstanding + '</td>' +
293
                '<td>' + ao.debit.created_on + '</td>' +
294
                '<td>' + ao.debit.updated_on + '</td>' +
295
                '<td>' + ao.debit.notes + '</td>' +
296
            '</tr>';
297
        }
298
299
        sOut +=
300
            '</tbody>'+
301
            '</table>';
302
    }
303
304
    sOut +=
305
        '</div>';
306
307
    return sOut;
308
}
309
310
function accountPrint( type, id ) {
311
    window.open( '/cgi-bin/koha/members/account_print.pl?type=' + type + '&id=' + id );
312
}
313
//]]>
314
</script>
315
</head>
316
<body>
317
[% INCLUDE 'header.inc' %]
318
[% INCLUDE 'patron-search.inc' %]
319
320
<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a>  &rsaquo; Account for [% INCLUDE 'patron-title.inc' %]</div>
321
322
<div id="doc3" class="yui-t2">
323
    <div id="bd">
324
           <div id="yui-main">
325
                <div class="yui-b">
326
                [% INCLUDE 'members-toolbar.inc' %]
327
328
                <div class="statictabs">
329
                    <ul>
330
                        <li class="active">
331
                            <a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Account</a>
332
                        </li>
333
334
                        <li>
335
                            <a href="/cgi-bin/koha/members/account_payment.pl?borrowernumber=[% borrowernumber %]" >Pay fines</a>
336
                        </li>
337
338
                        <li>
339
                            <a href="/cgi-bin/koha/members/account_debit.pl?borrowernumber=[% borrowernumber %]" >Create manual invoice</a>
340
                        </li>
341
342
                        <li>
343
                            <a href="/cgi-bin/koha/members/account_credit.pl?borrowernumber=[% borrowernumber %]" >Create manual credit</a>
344
                        </li>
345
                    </ul>
346
                </div>
347
348
                <div class="tabs-container">
349
350
                    <p>
351
                        <h3>Account balance: [% borrower.account_balance | $Currency %]</h3>
352
                    </p>
353
354
                    <div>
355
                        <div id="account-debits">
356
                            <a id="account-debits-switcher" href="#" onclick="return false">View payments</a>
357
                            <table cellpadding="0" cellspacing="0" border="0" class="display" id="debits-table">
358
                                <thead>
359
                                    <tr>
360
                                        <th colspan="99">Fees</th>
361
                                    </tr>
362
                                    <tr>
363
                                        <th></th>
364
                                        <th>ID</th>
365
                                        <th>Description</th>
366
                                        <th>Type</th>
367
                                        <th>Amount</th>
368
                                        <th>Outsanding</th>
369
                                        <th>Created on</th>
370
                                        <th>Updated on</th>
371
                                    </tr>
372
                                </thead>
373
                                <tbody></tbody>
374
                            </table>
375
                        </div>
376
377
                        <div id="account-credits">
378
                            <a id="account-credits-switcher" href="#"  onclick="return false">View fees</a>
379
                            <table cellpadding="0" cellspacing="0" border="0" class="display" id="credits-table">
380
                                <thead>
381
                                    <tr>
382
                                        <th colspan="99">Payments</th>
383
                                    </tr>
384
                                    <tr>
385
                                        <th></th>
386
                                        <th>ID</th>
387
                                        <th>Notes</th>
388
                                        <th>Type</th>
389
                                        <th>Amount</th>
390
                                        <th>Remaining</th>
391
                                        <th>Created on</th>
392
                                        <th>Updated on</th>
393
                                    </tr>
394
                                </thead>
395
                                <tbody></tbody>
396
                            </table>
397
                        </div>
398
                    </div>
399
                </div>
400
            </div>
401
        </div>
402
403
    <div class="yui-b">
404
        [% INCLUDE 'circ-menu.inc' %]
405
    </div>
406
</div>
407
[% INCLUDE 'intranet-bottom.inc' %]
408
409
[% BLOCK format_data %]
410
    [% FOREACH key IN data.result_source.columns %]
411
        [% IF key.match('^amount') %]
412
            "[% key %]": "[% data.$key FILTER $Currency highlight => highlight %]",
413
        [% ELSIF key.match('_on$') %]
414
            "[% key %]": "[% data.$key | $KohaDates %]",
415
        [% ELSE %]
416
            "[% key %]": "[% data.$key %]",
417
        [% END %]
418
    [% END %]
419
[% END %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_credit.tt (+92 lines)
Line 0 Link Here
1
[% SET accounts_view = 1 %]
2
[% INCLUDE 'doc-head-open.inc' %]
3
<title>Koha &rsaquo; Borrowers &rsaquo; Create manual credit</title>
4
[% INCLUDE 'doc-head-close.inc' %]
5
<script type="text/javascript">
6
//<![CDATA[
7
$(document).ready(function(){
8
        $('#account_credit').preventDoubleFormSubmit();
9
        $("fieldset.rows input").addClass("noEnterSubmit");
10
});
11
//]]>
12
</script>
13
</head>
14
<body id="pat_account_credit" class="pat">
15
    [% INCLUDE 'header.inc' %]
16
    [% INCLUDE 'patron-search.inc' %]
17
18
    <div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a>  &rsaquo; Manual credit</div>
19
20
    <div id="doc3" class="yui-t2">
21
        <div id="bd">
22
               <div id="yui-main">
23
            <div class="yui-b">
24
                    [% INCLUDE 'members-toolbar.inc' %]
25
26
                    <div class="statictabs">
27
                        <ul>
28
                            <li><a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Account</a></li>
29
                            <li><a href="/cgi-bin/koha/members/account_payment.pl?borrowernumber=[% borrowernumber %]" >Pay fines</a></li>
30
                            <li><a href="/cgi-bin/koha/members/account_debit.pl?borrowernumber=[% borrowernumber %]" >Create manual invoice</a></li>
31
                            <li class="active"><a href="/cgi-bin/koha/members/account_credit.pl?borrowernumber=[% borrowernumber %]" >Create manual credit</a></li>
32
                        </ul>
33
34
                        <div class="tabs-container">
35
36
                            <form action="/cgi-bin/koha/members/account_credit_do.pl" method="post" id="account_credit">
37
                                <input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrowernumber %]" />
38
39
                                <fieldset class="rows">
40
                                    <legend>Manual credit</legend>
41
42
                                    <ol>
43
                                        <li>
44
                                            <label for="type">Credit Type: </label>
45
                                            <select name="type" id="type">
46
                                                <option value="CREDIT">Credit</option>
47
                                                <option value="FORGIVEN">Forgiven</option>
48
                                                [% FOREACH c IN credit_types_loop %]
49
                                                    <option value="[% c.authorised_value %]">[% c.lib %]</option>
50
                                                [% END %]
51
                                            </select>
52
                                        </li>
53
54
                                        <li>
55
                                            <label for="barcode">Barcode: </label>
56
                                            <input type="text" name="barcode" id="barcode" />
57
                                        </li>
58
59
                                        <li>
60
                                            <label for="desc">Description: </label>
61
                                            <input type="text" name="desc" size="50" id="desc" />
62
                                        </li>
63
64
                                        <li>
65
                                            <label for="note">Note: </label>
66
                                            <input type="text" name="note" size="50" id="note" />
67
                                        </li>
68
69
                                        <li>
70
                                            <label for="amount">Amount: </label>
71
                                            <input type="text" name="amount" id="amount" />
72
                                            Example: 5.00
73
                                        </li>
74
                                    </ol>
75
76
                                </fieldset>
77
78
                                <fieldset class="action">
79
                                    <input type="submit" name="add" value="Add credit" />
80
                                    <a class="cancel" href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Cancel</a>
81
                                </fieldset>
82
                            </form>
83
84
                        </div>
85
                    </div>
86
                </div>
87
            </div>
88
        <div class="yui-b">
89
            [% INCLUDE 'circ-menu.inc' %]
90
        </div>
91
    </div>
92
[% INCLUDE 'intranet-bottom.inc' %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_debit.tt (+109 lines)
Line 0 Link Here
1
[% SET accounts_view = 1 %]
2
[% INCLUDE 'doc-head-open.inc' %]
3
<title>Koha &rsaquo; Borrowers &rsaquo; Create manual invoice</title>
4
[% INCLUDE 'doc-head-close.inc' %]
5
<script type="text/javascript">
6
//<![CDATA[
7
$(document).ready(function(){
8
    $('#maninvoice').preventDoubleFormSubmit();
9
    $("fieldset.rows input").addClass("noEnterSubmit");
10
11
    var type_fees = new Array();
12
    type_fees['L'] = '';
13
    type_fees['F'] = '';
14
    type_fees['A'] = '';
15
    type_fees['N'] = '';
16
    type_fees['M'] = '';
17
    [% FOREACH invoice_types_loo IN invoice_types_loop %]
18
        type_fees['[% invoice_types_loo.authorised_value %]'] = "[% invoice_types_loo.lib %]";
19
    [% END %]
20
});
21
//]]>
22
</script>
23
</head>
24
25
<body>
26
    [% INCLUDE 'header.inc' %]
27
    [% INCLUDE 'patron-search.inc' %]
28
29
    <div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a>  &rsaquo; Manual invoice</div>
30
31
    <div id="doc3" class="yui-t2">
32
        <div id="bd">
33
            <div id="yui-main">
34
                <div class="yui-b">
35
                    [% INCLUDE 'members-toolbar.inc' %]
36
37
                    <div class="statictabs">
38
                    <ul>
39
                        <li><a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Account</a></li>
40
                        <li><a href="/cgi-bin/koha/members/account_payment.pl?borrowernumber=[% borrowernumber %]" >Pay fines</a></li>
41
                        <li class="active"><a href="/cgi-bin/koha/members/account_debit.pl?borrowernumber=[% borrowernumber %]" >Create manual invoice</a></li>
42
                        <li><a href="/cgi-bin/koha/members/account_credit.pl?borrowernumber=[% borrowernumber %]" >Create manual credit</a></li>
43
                    </ul>
44
                    <div class="tabs-container">
45
46
                    <form action="/cgi-bin/koha/members/account_debit_do.pl" method="post" id="account_debit">
47
                        <input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrowernumber %]" />
48
49
                        <fieldset class="rows">
50
                            <legend>Manual Invoice</legend>
51
52
                            <ol>
53
                                <li>
54
                                    <label for="type">Type: </label>
55
                                    <select name="type" id="type">
56
                                        <option value="LOST">Lost item</option>
57
                                        <option value="FINE">Fine</option>
58
                                        <option value="ACCOUNT_MANAGEMENT_FEE">Account management fee</option>
59
                                        <option value="NEW_CARD">New card</option>
60
                                        <option value="SUNDRY">Sundry</option>
61
62
                                        [% FOREACH invoice_types_loo IN invoice_types_loop %]
63
                                            <option value="[% invoice_types_loo.authorised_value %]">[% invoice_types_loo.lib %]</option>
64
                                        [% END %]
65
                                    </select>
66
                                </li>
67
68
                                <!-- TODO: Write ajax barcode validator that appends the itemnumber for this form in a hidden input -->
69
                                 <li>
70
                                    <label for="barcode">Barcode: </label>
71
                                    <input type="text" name="barcode" id="barcode" />
72
                                </li>
73
74
                                <li>
75
                                    <label for="description">Description: </label>
76
                                    <input type="text" name="description" id="description" size="50" />
77
                                </li>
78
79
                                <li>
80
                                    <label for="notes">Notes: </label>
81
                                    <input type="text" name="notes" size="50" id="notes" />
82
                                </li>
83
84
                                <li>
85
                                    <label for="amount">Amount: </label>
86
                                    <input type="text" name="amount" id="amount" /> Example: 5.00
87
                                </li>
88
89
                            </ol>
90
                        </fieldset>
91
92
                        <fieldset class="action">
93
                            <input type="submit" name="add" value="Save" />
94
                            <a class="cancel" href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Cancel</a>
95
                        </fieldset>
96
97
                    </form>
98
99
                </div>
100
            </div>
101
        </div>
102
    </div>
103
104
<div class="yui-b">
105
  [% INCLUDE 'circ-menu.inc' %]
106
</div>
107
108
</div>
109
[% INCLUDE 'intranet-bottom.inc' %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_payment.tt (+201 lines)
Line 0 Link Here
1
[% SET accounts_view = 1 %]
2
[% USE Currency %]
3
[% INCLUDE 'doc-head-open.inc' %]
4
<title>Koha &rsaquo; Patrons &rsaquo; Pay Fines for  [% borrower.firstname %] [% borrower.surname %]</title>
5
[% INCLUDE 'doc-head-close.inc' %]
6
<script type="text/javascript" src="[% themelang %]/lib/jquery/plugins/jquery.checkboxes.min.js"></script>
7
<script type= "text/javascript">
8
//<![CDATA[
9
$( document ).ready(function() {
10
    // Show amount recieved only if the "Receive different amount" checkbox is checked
11
    $("#amount-received-p").hide();
12
    $('#receive_different_amount').click(function() {
13
        if( $(this).is(':checked')) {
14
            $("#amount-received-p").show();
15
        } else {
16
            $("#amount-received-p").hide();
17
        }
18
    });
19
20
    // Enable the "Select all/Clear all" links
21
    $('#CheckAll').click(function() {
22
        $("input[name='debit_id']" ).prop('checked', true);
23
    });
24
    $('#ClearAll').click(function() {
25
        $("input[name='debit_id']" ).prop('checked', false);
26
    });
27
28
    // Update the "amount to pay" field whenever a fee checkbox is changed
29
    // Note, this is just a payment suggestion and can be changed to any amount
30
    $("input[name='debit_id']" ).change(function() {
31
        var sum = 0;
32
        $("input[name='debit_id']:checked" ).each(function(i,n){
33
            sum += parseFloat( $( "#amount_outstanding_" + $(this).val() ).val() );
34
        });
35
        $('#amount_to_pay').val( sum );
36
    });
37
});
38
39
function checkForm(){
40
    // If using the "amount to receive" field, make sure the librarian is recieving at
41
    // least enough to pay those fees.
42
    if ( $('#amount_to_receive').val() ) {
43
        if ( parseFloat( $('#amount_to_receive').val() ) < parseFloat( $('#amount_to_pay').val() ) ) {
44
            alert( _("Cannot pay more than receieved!") );
45
            return false;
46
        }
47
    }
48
49
    return true;
50
}
51
//]]>
52
</script>
53
</head>
54
<body id="pat_pay" class="pat">
55
    [% INCLUDE 'header.inc' %]
56
    [% INCLUDE 'patron-search.inc' %]
57
58
    <div id="breadcrumbs">
59
        <a href="/cgi-bin/koha/mainpage.pl">Home</a>
60
        &rsaquo; <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a>
61
        &rsaquo; Pay fines for [% borrower.firstname %] [% borrower.surname %]
62
    </div>
63
64
    <div id="doc3" class="yui-t2">
65
        <div id="bd">
66
            <div id="yui-main">
67
                <div class="yui-b">
68
                    [% INCLUDE 'members-toolbar.inc' borrowernumber=borrower.borrowernumber %]
69
70
                    <div class="statictabs">
71
                        <ul>
72
                            <li><a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrower.borrowernumber %]">Account</a></li>
73
                            <li class="active"><a href="/cgi-bin/koha/members/account_payment.pl?borrowernumber=[% borrower.borrowernumber %]" >Pay fines</a></li>
74
                            <li><a href="/cgi-bin/koha/members/account_debit.pl?borrowernumber=[% borrower.borrowernumber %]" >Create manual invoice</a></li>
75
                            <li><a href="/cgi-bin/koha/members/account_credit.pl?borrowernumber=[% borrower.borrowernumber %]" >Create manual credit</a></li>
76
                        </ul>
77
78
                        <div class="tabs-container">
79
80
                        [% IF ( debits ) %]
81
                            <form action="/cgi-bin/koha/members/account_payment_do.pl" method="post" id="account-payment-form" onsubmit="return checkForm()">
82
83
                                <input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrower.borrowernumber %]" />
84
85
                                <p>
86
                                    <span class="checkall">
87
                                        <a id="CheckAll" href="#">Select all</a>
88
                                    </span>
89
90
                                    |
91
92
                                    <span class="clearall">
93
                                        <a id="ClearAll" href="#">Clear all</a>
94
                                    </span>
95
                                </p>
96
97
                                <table id="finest">
98
                                    <thead>
99
                                        <tr>
100
                                            <th>&nbsp;</th>
101
                                            <th>Description</th>
102
                                            <th>Account type</th>
103
                                            <th>Original amount</th>
104
                                            <th>Amount outstanding</th>
105
                                        </tr>
106
                                    </thead>
107
108
                                    <tbody>
109
                                        [% SET total_due = 0 %]
110
                                        [% FOREACH d IN debits %]
111
                                            [% SET total_due = total_due + d.amount_outstanding %]
112
                                            <tr>
113
                                                <td>
114
                                                    <input type="checkbox" checked="checked" name="debit_id" value="[% d.debit_id %]" />
115
                                                </td>
116
117
                                                <td>
118
                                                    [% d.description %]
119
120
                                                    [% IF d.notes %]
121
                                                        ( <i>[% d.notes %]</i> )
122
                                                    [% END %]
123
                                                </td>
124
125
                                                <td>
126
                                                    [% d.type %]
127
                                                </td>
128
129
                                                <td class="debit">
130
                                                    [% d.amount_original | $Currency %]
131
                                                    <input type="hidden" id="amount_original_[% d.debit_id %]" value="[% Currency.format_without_symbol( d.amount_original ) %]" />
132
                                                </td>
133
134
                                                <td class="debit">
135
                                                    [% d.amount_outstanding | $Currency %]
136
                                                    <input type="hidden" id="amount_outstanding_[% d.debit_id %]" value="[% Currency.format_without_symbol( d.amount_outstanding ) %]" />
137
                                                </td>
138
                                            </tr>
139
                                        [% END %]
140
                                    </tbody>
141
142
                                    <tfoot>
143
                                        <tr>
144
                                            <td class="total" colspan="4">Total Due:</td>
145
                                            <td>[% total_due | $Currency %]</td>
146
                                        </tr>
147
                                    </tfoot>
148
149
                                </table>
150
151
                                <fieldset>
152
                                    <p>
153
                                        <label for="amount_to_pay">Amount to pay: [% Currency.symbol() %]</label>
154
                                        <input type="text" name="amount_to_pay" id="amount_to_pay" value="[% Currency.format_without_symbol( total_due ) %]" />
155
156
                                        <input type="checkbox" id="receive_different_amount" />
157
                                        <label for="receive_different_amount"><i>Receive different amount</i></label>
158
                                    </p>
159
160
                                    <p id="amount-received-p">
161
                                        <label for="amount_to_receive">Amount recieved: [% Currency.symbol() %]</label>
162
                                        <input type="text" name="amount_to_receive" id="amount_to_receive" />
163
                                    </p>
164
165
                                    <p>
166
                                        <label for="type">Type:</label>
167
                                        <select id="type" name="type">
168
                                            <option value="PAYMENT">Payment</option>
169
                                            <option value="WRITEOFF">Write-off</option>
170
                                        </select>
171
                                    </p>
172
173
                                    <p>
174
                                        <label for="notes">Payment notes:</label>
175
                                        <input type="textbox" name="notes" id="notes" />
176
                                    <p>
177
                                </fieldset>
178
179
                                <fieldset class="action">
180
                                    <input type="submit" value="Process" class="submit" />
181
                                    <a class="cancel" href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrower.borrowernumber %]">Cancel</a>
182
                                </fieldset>
183
184
                            </form>
185
186
                        [% ELSE %]
187
                            <p>
188
                                [% borrower.firstname %] [% borrower.surname %] has no outstanding fines.
189
                            </p>
190
                        [% END %]
191
192
                    </div>
193
                </div>
194
            </div>
195
        </div>
196
197
        <div class="yui-b">
198
            [% INCLUDE 'circ-menu.tt' %]
199
        </div>
200
    </div>
201
[% INCLUDE 'intranet-bottom.inc' %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_print.tt (+136 lines)
Line 0 Link Here
1
[% USE KohaDates %]
2
[% USE Currency %]
3
[% USE EncodeUTF8 %]
4
[% INCLUDE 'doc-head-open.inc' %]
5
<title>Print Receipt for [% cardnumber %]</title>
6
[% INCLUDE 'doc-head-close.inc' %]
7
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
8
<link rel="shortcut icon" href="[% IF ( IntranetFavicon ) %][% IntranetFavicon %][% ELSE %][% interface %]/[% theme %]/img/favicon.ico[% END %]" type="image/x-icon" />
9
<script type="text/javascript">
10
    function printThenClose() {
11
        window.print();
12
        window.close();
13
    }
14
</script>
15
</head>
16
17
[% SET account = debit || credit %]
18
[% SET borrower = account.borrower %]
19
20
<body id="account-print-body" onload="printThenClose();">
21
22
    <table>
23
        <thead>
24
            <tr>
25
                <th colspan="99">
26
                    [% IF debit %]
27
                        Invoice
28
                    [% ELSIF credit %]
29
                        Payment receipt
30
                    [% END %]
31
                </th>
32
            </tr>
33
            
34
            <tr>
35
                <th colspan="99">
36
                    [% borrower.branch.branchname | $EncodeUTF8 %]
37
                </th>
38
            </tr>
39
40
            <tr>
41
                <th>Name:</th>
42
                <th colspan="99">[% borrower.firstname | $EncodeUTF8 %] [% borrower.surname | $EncodeUTF8 %]</th>
43
            </tr>
44
45
            <tr>
46
                <th>Card number:</th>
47
                <th colspan="99">[% borrower.cardnumber %]</th>
48
            </tr>
49
50
            <tr>
51
                <th>Date:</th>
52
                <th colspan="99">[% account.created_on | $KohaDates %]</th>
53
            </tr>
54
55
            [% IF account.description %]
56
                <tr>
57
                    <th>Description:</th>
58
                    <th colspan="99">[% account.description | $EncodeUTF8 %]</th>
59
                </tr>
60
            [% END %]
61
62
            [% IF credit %]
63
                <tr>
64
                    <th>Amount:</th>
65
                    <th colspan="99">[% credit.amount_paid | $Currency highlight => type %]</th>
66
                </tr>
67
                <tr>
68
                    <th>Balance:</th>
69
                    <th colspan="99">[% credit.amount_remaining | $Currency highlight => type %]</th>
70
                </tr>
71
                [% IF credit.account_offsets %]
72
                    <tr>
73
                        <th colspan="99">Fees paid</th>
74
                    </tr>
75
                    <tr>
76
                        <th>Description</th>
77
                        <th>Type</th>
78
                        <th>Amount</th>
79
                        <th>Paid</th>
80
                        <th>Outstanding</th>
81
                        <th>Date</th>
82
                    </tr>
83
                [% END %]
84
            [% ELSIF debit %]
85
                <tr>
86
                    <th>Amount:</th>
87
                    <th colspan="99">[% debit.amount_original | $Currency highlight => type %]</th>
88
                </tr>
89
                <tr>
90
                    <th>Outstanding:</th>
91
                    <th colspan="99">[% debit.amount_outstanding | $Currency highlight => type %]</th>
92
                </tr>
93
                [% IF debit.account_offsets %]
94
                    <tr>
95
                        <th colspan="99">Payments applied</th>
96
                    </tr>
97
                    <tr>
98
                        <th>Date</th>
99
                        <th>Type</th>
100
                        <th>Payment</th>
101
                        <th>Applied</th>
102
                        <th>Balance</th>
103
                        <th>Notes</th>
104
                    </tr>
105
                [% END %]
106
            [% END %]
107
        </thead>
108
109
        <tbody>
110
            [% IF credit.account_offsets %]
111
                [% FOREACH ao IN credit.account_offsets %]
112
                    <tr>
113
                        <td>[% ao.debit.description %]</td>
114
                        <td>[% ao.debit.type %]</td>
115
                        <td>[% ao.debit.amount_original | $Currency highlight => 'debit' %]</td>
116
                        <td>[% ao.amount | $Currency highlight => 'offset' %]</td>
117
                        <td>[% ao.debit.amount_outstanding | $Currency highlight => 'debit' %]</td>
118
                        <td>[% ao.debit.created_on | $KohaDates %]</td>
119
                    </tr>
120
                [% END %]
121
            [% ELSIF debit.account_offsets %]
122
                [% FOREACH ao IN debit.account_offsets %]
123
                    <tr>
124
                        <td>[% ao.credit.type %]</td>
125
                        <td>[% ao.credit.created_on | $KohaDates %]</td>
126
                        <td>[% ao.credit.amount_paid | $Currency highlight => 'credit' %]</td>
127
                        <td>[% ao.amount | $Currency highlight => 'offset' %]</td>
128
                        <td>[% ao.credit.amount_remaining | $Currency highlight => 'credit' %]</td>
129
                        <td>[% ao.credit.notes %]</td>
130
                    </tr>
131
                [% END %]
132
            [% END %]
133
        </tbody>
134
    </table>
135
136
[% INCLUDE 'intranet-bottom.inc' %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/members/boraccount.tt (-99 lines)
Lines 1-99 Link Here
1
[% INCLUDE 'doc-head-open.inc' %]
2
<title>Koha &rsaquo; Patrons &rsaquo; Account for [% INCLUDE 'patron-title.inc' %]</title>
3
[% INCLUDE 'doc-head-close.inc' %]
4
</head>
5
<body id="pat_borraccount" class="pat">
6
[% INCLUDE 'header.inc' %]
7
[% INCLUDE 'patron-search.inc' %]
8
9
<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a>  &rsaquo; Account for [% INCLUDE 'patron-title.inc' %]</div>
10
11
<div id="doc3" class="yui-t2">
12
   
13
   <div id="bd">
14
	<div id="yui-main">
15
	<div class="yui-b">
16
[% INCLUDE 'members-toolbar.inc' %]
17
<form action="/cgi-bin/koha/members/boraccount.pl" method="get"><input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrowernumber %]" /></form>
18
19
<!-- The manual invoice and credit buttons -->
20
<div class="statictabs">
21
<ul>
22
    <li class="active"><a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrowernumber %]">Account</a></li>
23
	<li><a href="/cgi-bin/koha/members/pay.pl?borrowernumber=[% borrowernumber %]" >Pay fines</a></li>
24
	<li><a href="/cgi-bin/koha/members/maninvoice.pl?borrowernumber=[% borrowernumber %]" >Create manual invoice</a></li>
25
	<li><a href="/cgi-bin/koha/members/mancredit.pl?borrowernumber=[% borrowernumber %]" >Create manual credit</a></li>
26
</ul>
27
<div class="tabs-container">
28
<!-- The table with the account items -->
29
<table>
30
  <tr>
31
  	<th>Date</th>
32
    <th>Description of charges</th>
33
    <th>Note</th>
34
    <th>Amount</th>
35
    <th>Outstanding</th>
36
    [% IF ( reverse_col ) %]
37
    <th>&nbsp;</th>
38
    [% END %]
39
    <th>Print</th>
40
  </tr>
41
42
	<!-- FIXME: Shouldn't hardcode dollar signs, since Euro or Pound might be needed -->
43
  [% FOREACH account IN accounts %]
44
45
   [% IF ( loop.odd ) %]<tr>[% ELSE %]<tr class="highlight">[% END %]
46
      <td>[% account.date %]</td>
47
      <td>[% account.description %]&nbsp;[% IF ( account.itemnumber ) %]<a href="/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=[% account.biblionumber %]&amp;itemnumber=[% account.itemnumber %]">View item</a>&nbsp;[% END %][% account.title |html %]</td>
48
      <td>[% account.note | html_line_break %]</td>
49
      [% IF ( account.amountcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% account.amount %]</td>
50
      [% IF ( account.amountoutstandingcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% account.amountoutstanding %]</td>
51
    [% IF ( reverse_col ) %]
52
      <td>
53
	[% IF ( account.payment ) %]
54
		<a href="boraccount.pl?action=reverse&amp;accountlines_id=[% account.accountlines_id %]&amp;borrowernumber=[% account.borrowernumber %]">Reverse</a>
55
	[% ELSE %]
56
		&nbsp;
57
	[% END %]
58
      </td>
59
	[% END %]
60
<td>
61
	[% IF ( account.payment ) %]
62
		<a target="_blank" href="printfeercpt.pl?action=print&amp;accountlines_id=[% account.accountlines_id %]&amp;borrowernumber=[% account.borrowernumber %]">Print</a>
63
	[% ELSE %]
64
		<a target="_blank" href="printinvoice.pl?action=print&amp;accountlines_id=[% account.accountlines_id %]&amp;borrowernumber=[% account.borrowernumber %]">Print</a>
65
	[% END %]
66
      </td>
67
    </tr>
68
69
  [% END %]
70
<tfoot>
71
  <tr>
72
    <td colspan="4">Total due</td>
73
    [% IF ( totalcredit ) %]
74
      [% IF ( reverse_col ) %]
75
        <td colspan="3" class="credit">
76
      [% ELSE %]
77
        <td colspan="2" class="credit">
78
      [% END %]
79
    [% ELSE %]
80
      [% IF ( reverse_col ) %]
81
        <td colspan="3" class="debit">
82
      [% ELSE %]
83
        <td colspan="2" class="credit">
84
      [% END %]
85
    [% END %]
86
    [% total %]</td>
87
  </tr>
88
  </tfoot>
89
</table>
90
</div></div>
91
92
</div>
93
</div>
94
95
<div class="yui-b">
96
[% INCLUDE 'circ-menu.inc' %]
97
</div>
98
</div>
99
[% INCLUDE 'intranet-bottom.inc' %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/members/mancredit.tt (-6 / +6 lines)
Lines 26-39 $(document).ready(function(){ Link Here
26
<!-- The manual invoice and credit buttons -->
26
<!-- The manual invoice and credit buttons -->
27
<div class="statictabs">
27
<div class="statictabs">
28
<ul>
28
<ul>
29
	<li><a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrowernumber %]">Account</a></li>
29
   <li><a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Account</a></li>
30
	<li><a href="/cgi-bin/koha/members/pay.pl?borrowernumber=[% borrowernumber %]" >Pay fines</a></li>
30
    <li><a href="/cgi-bin/koha/members/account_payment.pl?borrowernumber=[% borrowernumber %]" >Pay fines</a></li>
31
	<li><a href="/cgi-bin/koha/members/maninvoice.pl?borrowernumber=[% borrowernumber %]" >Create manual invoice</a></li>
31
 <li><a href="/cgi-bin/koha/members/account_debit.pl?borrowernumber=[% borrowernumber %]" >Create manual invoice</a></li>
32
    <li class="active"><a href="/cgi-bin/koha/members/mancredit.pl?borrowernumber=[% borrowernumber %]" >Create manual credit</a></li>
32
    <li class="active"><a href="/cgi-bin/koha/members/account_credit.pl?borrowernumber=[% borrowernumber %]" >Create manual credit</a></li>
33
</ul>
33
</ul>
34
<div class="tabs-container">
34
<div class="tabs-container">
35
35
36
<form action="/cgi-bin/koha/members/mancredit.pl" method="post" id="mancredit">
36
<form action="/cgi-bin/koha/members/account_credit.pl" method="post" id="mancredit">
37
<input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrowernumber %]" />
37
<input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrowernumber %]" />
38
38
39
<fieldset class="rows">
39
<fieldset class="rows">
Lines 48-54 $(document).ready(function(){ Link Here
48
	<li><label for="amount">Amount: </label><input type="text" name="amount" id="amount" /> Example: 5.00</li>
48
	<li><label for="amount">Amount: </label><input type="text" name="amount" id="amount" /> Example: 5.00</li>
49
</ol></fieldset>
49
</ol></fieldset>
50
50
51
<fieldset class="action"><input type="submit" name="add" value="Add credit" /> <a class="cancel" href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrowernumber %]">Cancel</a></fieldset>
51
<fieldset class="action"><input type="submit" name="add" value="Add credit" /> <a class="cancel" href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Cancel</a></fieldset>
52
</form>
52
</form>
53
53
54
</div></div>
54
</div></div>
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/members/maninvoice.tt (-87 lines)
Lines 1-87 Link Here
1
[% INCLUDE 'doc-head-open.inc' %]
2
<title>Koha &rsaquo; Borrowers &rsaquo; Create manual invoice</title>
3
[% INCLUDE 'doc-head-close.inc' %]
4
<script type="text/javascript">
5
//<![CDATA[
6
$(document).ready(function(){
7
        $('#maninvoice').preventDoubleFormSubmit();
8
        $("fieldset.rows input").addClass("noEnterSubmit");
9
});
10
//]]>
11
</script>
12
</head>
13
<body id="pat_maninvoice" class="pat">
14
[% INCLUDE 'header.inc' %]
15
[% INCLUDE 'patron-search.inc' %]
16
17
<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a>  &rsaquo; Manual Invoice</div>
18
19
<div id="doc3" class="yui-t2">
20
   
21
   <div id="bd">
22
	<div id="yui-main">
23
	<div class="yui-b">
24
[% INCLUDE 'members-toolbar.inc' %]
25
26
<!-- The manual invoice and credit buttons -->
27
<div class="statictabs">
28
<ul>
29
	<li><a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrowernumber %]">Account</a></li>
30
	<li><a href="/cgi-bin/koha/members/pay.pl?borrowernumber=[% borrowernumber %]" >Pay fines</a></li>
31
    <li class="active"><a href="/cgi-bin/koha/members/maninvoice.pl?borrowernumber=[% borrowernumber %]" >Create manual invoice</a></li>
32
	<li><a href="/cgi-bin/koha/members/mancredit.pl?borrowernumber=[% borrowernumber %]" >Create manual credit</a></li>
33
</ul>
34
<div class="tabs-container">
35
36
[% IF ( ERROR ) %]
37
[% IF ( ITEMNUMBER ) %]
38
  ERROR an invalid itemnumber was entered, please hit back and try again
39
[% END %]
40
[% ELSE %]
41
<form action="/cgi-bin/koha/members/maninvoice.pl" method="post" id="maninvoice"><input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrowernumber %]" />
42
	<fieldset class="rows">
43
	<legend>Manual Invoice</legend>
44
	<ol>
45
      <li>
46
<script type="text/javascript">
47
var type_fees = new Array();
48
type_fees['L'] = '';
49
type_fees['F'] = '';
50
type_fees['A'] = '';
51
type_fees['N'] = '';
52
type_fees['M'] = '';
53
[% FOREACH invoice_types_loo IN invoice_types_loop %]
54
type_fees['[% invoice_types_loo.authorised_value %]'] = "[% invoice_types_loo.lib %]";
55
[% END %]
56
</script>
57
        <label for="type">Type: </label>
58
        <select name="type" id="type" onchange="this.form.desc.value=this.options[this.selectedIndex].value; this.form.amount.value=type_fees[this.options[this.selectedIndex].value];">
59
          <option value="L">Lost item</option>
60
          <option value="F">Fine</option>
61
          <option value="A">Account management fee</option>
62
          <option value="N">New card</option>
63
          <option value="M">Sundry</option>
64
          [% FOREACH invoice_types_loo IN invoice_types_loop %]
65
            <option value="[% invoice_types_loo.authorised_value %]">[% invoice_types_loo.authorised_value %]</option>
66
          [% END %]
67
        </select>
68
      </li>
69
	<li><label for="barcode">Barcode: </label><input type="text" name="barcode" id="barcode" /></li>
70
	<li><label for="desc">Description: </label><input type="text" name="desc" id="desc" size="50" /></li>
71
    <li><label for="note">Note: </label><input type="text" name="note" size="50" id="note" /></li>
72
	<li><label for="amount">Amount: </label><input type="text" name="amount" id="amount" /> Example: 5.00</li>
73
	</ol></fieldset>
74
<fieldset class="action"><input type="submit" name="add" value="Save" /> <a class="cancel" href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrowernumber %]">Cancel</a></fieldset>
75
</form>
76
77
[% END %]
78
</div></div>
79
80
</div>
81
</div>
82
83
<div class="yui-b">
84
[% INCLUDE 'circ-menu.inc' %]
85
</div>
86
</div>
87
[% INCLUDE 'intranet-bottom.inc' %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/members/pay.tt (-153 lines)
Lines 1-153 Link Here
1
[% INCLUDE 'doc-head-open.inc' %]
2
<title>Koha &rsaquo; Patrons &rsaquo; Pay Fines for  [% borrower.firstname %] [% borrower.surname %]</title>
3
[% INCLUDE 'doc-head-close.inc' %]
4
<script type="text/javascript" src="[% themelang %]/lib/jquery/plugins/jquery.checkboxes.min.js"></script>
5
<script type= "text/javascript">
6
//<![CDATA[
7
function enableCheckboxActions(){
8
    // Enable/disable controls if checkboxes are checked
9
    var checkedBoxes = $("input.cb:checked");
10
    if ($(checkedBoxes).size()) {
11
      $("#payselected").prop("disabled",false);
12
    } else {
13
      $("#payselected").prop("disabled",true);
14
    }
15
}
16
    $(document).ready(function(){
17
 $('#pay-fines-form').preventDoubleFormSubmit();
18
        $("#woall").click(function(event){
19
            var answer = confirm(_("Are you sure you want to write off [% total | format('%.2f') %] in outstanding fines? This cannot be undone!"));
20
                if (!answer){
21
                    event.preventDefault();
22
                }
23
        });
24
        $('#CheckAll').click(function(){
25
            $("#finest").checkCheckboxes();
26
            enableCheckboxActions();
27
            return false;
28
        });
29
        $('#CheckNone').click(function(){
30
            $("#finest").unCheckCheckboxes();
31
            enableCheckboxActions();
32
            return false;
33
        });
34
        $(".cb").change(function(){
35
            enableCheckboxActions();
36
        });
37
        enableCheckboxActions();
38
    });
39
//]]>
40
</script>
41
</head>
42
<body id="pat_pay" class="pat">
43
[% INCLUDE 'header.inc' %]
44
[% INCLUDE 'patron-search.inc' %]
45
46
<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a>  &rsaquo; Pay fines for [% borrower.firstname %] [% borrower.surname %]</div>
47
48
<div id="doc3" class="yui-t2">
49
   
50
   <div id="bd">
51
	<div id="yui-main">
52
	<div class="yui-b">
53
[% INCLUDE 'members-toolbar.inc' borrowernumber=borrower.borrowernumber %]
54
55
<!-- The manual invoice and credit buttons -->
56
<div class="statictabs">
57
<ul>
58
	<li><a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrower.borrowernumber %]">Account</a></li>
59
    <li class="active"><a href="/cgi-bin/koha/members/pay.pl?borrowernumber=[% borrower.borrowernumber %]" >Pay fines</a></li>
60
	<li><a href="/cgi-bin/koha/members/maninvoice.pl?borrowernumber=[% borrower.borrowernumber %]" >Create manual invoice</a></li>
61
	<li><a href="/cgi-bin/koha/members/mancredit.pl?borrowernumber=[% borrower.borrowernumber %]" >Create manual credit</a></li>
62
</ul>
63
<div class="tabs-container">
64
65
[% IF ( accounts ) %]
66
    <form action="/cgi-bin/koha/members/pay.pl" method="post" id="pay-fines-form">
67
	<input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrower.borrowernumber %]" />
68
<p><span class="checkall"><a id="CheckAll" href="#">Select all</a></span> | <span class="clearall"><a id="CheckNone" href="#">Clear all</a></span></p>
69
<table id="finest">
70
<thead>
71
<tr>
72
    <th>&nbsp;</th>
73
    <th>Fines &amp; charges</th>
74
    <th>Description</th>
75
    <th>Payment note</th>
76
    <th>Account type</th>
77
    <th>Notify id</th>
78
    <th>Level</th>
79
    <th>Amount</th>
80
    <th>Amount outstanding</th>
81
</tr>
82
</thead>
83
<tfoot>
84
<tr>
85
    <td class="total" colspan="8">Total Due:</td>
86
    <td>[% total | format('%.2f') %]</td>
87
</tr>
88
</tfoot>
89
<tbody>
90
[% FOREACH account_grp IN accounts %]
91
    [% FOREACH line IN account_grp.accountlines %]
92
<tr>
93
    <td>
94
    [% IF ( line.amountoutstanding > 0 ) %]
95
        <input class="cb" type="checkbox" checked="checked" name="incl_par_[% line.accountno %]" />
96
    [% END %]
97
    </td>
98
    <td>
99
    [% IF ( line.amountoutstanding > 0 ) %]
100
        <input type="submit" name="pay_indiv_[% line.accountno %]" value="Pay" />
101
        <input type="submit" name="wo_indiv_[% line.accountno %]" value="Write off" />
102
    [% END %]
103
    <input type="hidden" name="itemnumber[% line.accountno %]" value="[% line.itemnumber %]" />
104
    <input type="hidden" name="description[% line.accountno %]" value="[% line.description %]" />
105
    <input type="hidden" name="accounttype[% line.accountno %]" value="[% line.accounttype %]" />
106
    <input type="hidden" name="amount[% line.accountno %]" value="[% line.amount %]" />
107
    <input type="hidden" name="accountlines_id[% line.accountno %]" value="[% line.accountlines_id %]" />
108
    <input type="hidden" name="amountoutstanding[% line.accountno %]" value="[% line.amountoutstanding %]" />
109
    <input type="hidden" name="borrowernumber[% line.accountno %]" value="[% line.borrowernumber %]" />
110
    <input type="hidden" name="accountno[% line.accountno %]" value="[% line.accountno %]" />
111
    <input type="hidden" name="notify_id[% line.accountno %]" value="[% line.notify_id %]" />
112
    <input type="hidden" name="notify_level[% line.accountno %]" value="[% line.notify_level %]" />
113
    <input type="hidden" name="totals[% line.accountno %]" value="[% line.totals %]" />
114
    </td>
115
    <td>[% line.description %] ([% line.title |html_entity %])</td>
116
    <td><input type="text" name="payment_note_[% line.accountno %]" /></td>
117
    <td>[% line.accounttype %]</td>
118
    <td>[% line.notify_id %]</td>
119
    <td>[% line.notify_level %]</td>
120
    <td class="debit">[% line.amount | format('%.2f') %]</td>
121
    <td class="debit">[% line.amountoutstanding | format('%.2f') %]</td>
122
</tr>
123
[% END %]
124
[% IF ( account_grp.total ) %]
125
<tr>
126
127
    <td class="total" colspan="8">Sub total:</td>
128
    <td>[% account_grp.total | format('%.2f') %]</td>
129
</tr>
130
[% END %]
131
[% END %]
132
</tbody>
133
</table>
134
<fieldset class="action">
135
<input type="submit" id="paycollect" name="paycollect"  value="Pay amount" class="submit" />
136
<input type="submit" name="woall"  id="woall" value="Write off all" class="submit" />
137
<input type="submit" id="payselected" name="payselected"  value="Pay selected" class="submit" />
138
<a class="cancel" href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrower.borrowernumber %]">Cancel</a>
139
</fieldset>
140
</form>
141
[% ELSE %]
142
    <p>[% borrower.firstname %] [% borrower.surname %] has no outstanding fines.</p>
143
[% END %]
144
</div></div>
145
146
</div>
147
</div>
148
149
<div class="yui-b">
150
[% INCLUDE 'circ-menu.tt' %]
151
</div>
152
</div>
153
[% INCLUDE 'intranet-bottom.inc' %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/members/paycollect.tt (-233 lines)
Lines 1-233 Link Here
1
[% INCLUDE 'doc-head-open.inc' %]
2
<title>Koha &rsaquo; Patrons &rsaquo; Collect fine payment for  [% borrower.firstname %] [% borrower.surname %]</title>
3
[% INCLUDE 'doc-head-close.inc' %]
4
<script type= "text/javascript">
5
//<![CDATA[
6
$(document).ready(function() {
7
    $('#payindivfine, #woindivfine, #payfine').preventDoubleFormSubmit();
8
});
9
//]]>
10
</script>
11
<script type= "text/javascript">
12
//<![CDATA[
13
function moneyFormat(textObj) {
14
    var newValue = textObj.value;
15
    var decAmount = "";
16
    var dolAmount = "";
17
    var decFlag   = false;
18
    var aChar     = "";
19
20
    for(i=0; i < newValue.length; i++) {
21
        aChar = newValue.substring(i, i+1);
22
        if (aChar >= "0" && aChar <= "9") {
23
            if(decFlag) {
24
                decAmount = "" + decAmount + aChar;
25
            }
26
            else {
27
                dolAmount = "" + dolAmount + aChar;
28
            }
29
        }
30
        if (aChar == ".") {
31
            if (decFlag) {
32
                dolAmount = "";
33
                break;
34
            }
35
            decFlag = true;
36
        }
37
    }
38
39
    if (dolAmount == "") {
40
        dolAmount = "0";
41
    }
42
// Strip leading 0s
43
    if (dolAmount.length > 1) {
44
        while(dolAmount.length > 1 && dolAmount.substring(0,1) == "0") {
45
            dolAmount = dolAmount.substring(1,dolAmount.length);
46
        }
47
    }
48
    if (decAmount.length > 2) {
49
        decAmount = decAmount.substring(0,2);
50
    }
51
// Pad right side
52
    if (decAmount.length == 1) {
53
       decAmount = decAmount + "0";
54
    }
55
    if (decAmount.length == 0) {
56
       decAmount = decAmount + "00";
57
    }
58
59
    textObj.value = dolAmount + "." + decAmount;
60
}
61
//]]>
62
</script>
63
</head>
64
<body id="pat_paycollect" class="pat">
65
[% INCLUDE 'header.inc' %]
66
[% INCLUDE 'patron-search.inc' %]
67
<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a>  &rsaquo; <a href="/cgi-bin/koha/members/pay.pl?borrowernumber=[% borrower.borrowernumber %]">Pay fines for [% borrower.firstname %] [% borrower.surname %]</a> &rsaquo; [% IF ( pay_individual ) %]Pay an individual fine[% ELSIF ( writeoff_individual ) %]Write off an individual fine[% ELSE %][% IF ( selected_accts ) %]Pay an amount toward selected fines[% ELSE %]Pay an amount toward all fines[% END %][% END %]</div>
68
69
<div id="doc3" class="yui-t2">
70
71
<div id="bd">
72
<div id="yui-main">
73
<div class="yui-b">
74
[% INCLUDE 'members-toolbar.inc' borrowernumber=borrower.borrowernumber %]
75
76
77
<!-- The manual invoice and credit buttons -->
78
<div class="statictabs">
79
<ul>
80
    <li>
81
    <a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrower.borrowernumber %]">Account</a>
82
    </li>
83
    <li class="active">
84
    <a href="/cgi-bin/koha/members/pay.pl?borrowernumber=[% borrower.borrowernumber %]" >Pay fines</a>
85
    </li>
86
    <li>
87
    <a href="/cgi-bin/koha/members/maninvoice.pl?borrowernumber=[% borrower.borrowernumber %]" >Create manual invoice</a>
88
    </li>
89
    <li>
90
    <a href="/cgi-bin/koha/members/mancredit.pl?borrowernumber=[% borrower.borrowernumber %]" >Create manual credit</a>
91
    </li>
92
</ul>
93
<div class="tabs-container">
94
[% IF ( error_over ) %]
95
    <div id="error_message" class="dialog alert">
96
    You must pay a value less than or equal to [% total_due | format('%.2f') %].
97
    </div>
98
[% END %]
99
100
[% IF ( pay_individual ) %]
101
    <form name="payindivfine" id="payindivfine" onsubmit="return validatePayment(this);" method="post" action="/cgi-bin/koha/members/paycollect.pl">
102
    <input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrower.borrowernumber %]" />
103
    <input type="hidden" name="pay_individual" id="pay_individual" value="[% pay_individual %]" />
104
    <input type="hidden" name="itemnumber" id="itemnumber" value="[% itemnumber %]" />
105
    <input type="hidden" name="description" id="description" value="[% description %]" />
106
    <input type="hidden" name="accounttype" id="accounttype" value="[% accounttype %]" />
107
    <input type="hidden" name="notify_id" id="notify_id" value="[% notify_id %]" />
108
    <input type="hidden" name="notify_level" id="notify_level" value="[% notify_level %]" />
109
    <input type="hidden" name="amount" id="amount" value="[% amount %]" />
110
    <input type="hidden" name="amountoutstanding" id="amountoutstanding" value="[% amountoutstanding %]" />
111
    <input type="hidden" name="accountno" id="accountno" value="[% accountno %]" />
112
    <input type="hidden" name="accountlines_id" id="accountlines_id" value="[% accountlines_id %]" />
113
    <input type="hidden" name="title" id="title" value="[% title %]" />
114
115
<fieldset class="rows">
116
    <legend>Pay an individual fine</legend>
117
    <input type="hidden" name="payment_note" id="payment_note" value="[% payment_note %]" />
118
    <table>
119
    <thead><tr>
120
            <th>Description</th>
121
            <th>Account type</th>
122
            <th>Notify id</th>
123
            <th>Level</th>
124
            <th>Amount</th>
125
            <th>Amount outstanding</th>
126
        </tr></thead>
127
    <tfoot>
128
        <td colspan="5">Total amount payable:</td><td>[% amountoutstanding | format('%.2f') %]</td>
129
    </tfoot>
130
    <tbody><tr>
131
            <td>
132
                [% description %] [% title  %]
133
            </td>
134
            <td>[% accounttype %]</td>
135
            <td>[% notify_id %]</td>
136
            <td>[% notify_level %]</td>
137
            <td class="debit">[% amount | format('%.2f') %]</td>
138
            <td class="debit">[% amountoutstanding | format('%.2f') %]</td>
139
        </tr></tbody>
140
</table>
141
142
<ol>
143
144
    <li>
145
        <label for="paid">Collect from patron: </label>
146
            <!-- default to paying all -->
147
        <input name="paid" id="paid" value="[% amountoutstanding | format('%.2f') %]" onchange="moneyFormat(document.payindivfine.paid)"/>
148
    </li>
149
</ol>
150
</fieldset>
151
152
    <div class="action"><input type="submit" name="submitbutton" value="Confirm" />
153
        <a class="cancel" href="/cgi-bin/koha/members/pay.pl?borrowernumber=[% borrower.borrowernumber %]">Cancel</a></div>
154
    </form>
155
[% ELSIF ( writeoff_individual ) %]
156
    <form name="woindivfine" id="woindivfine" action="/cgi-bin/koha/members/pay.pl" method="post" >
157
    <fieldset class="rows">
158
    <legend>Write off an individual fine</legend>
159
    <input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrower.borrowernumber %]" />
160
    <input type="hidden" name="pay_individual" id="pay_individual" value="[% pay_individual %]" />
161
    <input type="hidden" name="itemnumber" id="itemnumber" value="[% itemnumber %]" />
162
    <input type="hidden" name="description" id="description" value="[% description %]" />
163
    <input type="hidden" name="accounttype" id="accounttype" value="[% accounttype %]" />
164
    <input type="hidden" name="notify_id" id="notify_id" value="[% notify_id %]" />
165
    <input type="hidden" name="notify_level" id="notify_level" value="[% notify_level %]" />
166
    <input type="hidden" name="amount" id="amount" value="[% amount %]" />
167
    <input type="hidden" name="amountoutstanding" id="amountoutstanding" value="[% amountoutstanding %]" />
168
    <input type="hidden" name="accountno" id="accountno" value="[% accountno %]" />
169
    <input type="hidden" name="accountlines_id" id="accountlines_id" value="[% accountlines_id %]" />
170
    <input type="hidden" name="title" id="title" value="[% title %]" />
171
    <input type="hidden" name="payment_note" id="payment_note" value="[% payment_note %]" />
172
    <table>
173
    <thead><tr>
174
            <th>Description</th>
175
            <th>Account type</th>
176
            <th>Notify id</th>
177
            <th>Level</th>
178
            <th>Amount</th>
179
            <th>Amount outstanding</th>
180
        </tr></thead>
181
    <tfoot><td colspan="5">Total amount to be written off:</td><td>[% amountoutstanding | format('%.2f') %]</td></tfoot>
182
    <tbody><tr>
183
            <td>[% description %] [% title %]</td>
184
            <td>[% accounttype %]</td>
185
            <td>[% notify_id %]</td>
186
            <td>[% notify_level %]</td>
187
            <td class="debit">[% amount | format('%.2f') %]</td>
188
            <td class="debit">[% amountoutstanding | format('%.2f') %]</td>
189
        </tr></tbody>
190
    </table>
191
    </fieldset>
192
    <div class="action"><input type="submit" name="confirm_writeoff" id="confirm_writeoff" value="Write off this charge" />
193
        <a class="cancel" href="/cgi-bin/koha/members/pay.pl?borrowernumber=[% borrower.borrowernumber %]">Cancel</a></div>
194
    </form>
195
[% ELSE %]
196
197
    <form name="payfine" id="payfine" onsubmit="return validatePayment(this);" method="post" action="/cgi-bin/koha/members/paycollect.pl">
198
    <input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrower.borrowernumber %]" />
199
    <input type="hidden" name="selected_accts" id="selected_accts" value="[% selected_accts %]" />
200
    <input type="hidden" name="total" id="total" value="[% total %]" />
201
202
    <fieldset class="rows">
203
    [% IF ( selected_accts ) %]<legend>Pay an amount toward selected fines</legend>[% ELSE %]<legend>Pay an amount toward all fines</legend>[% END %]
204
    <ol>
205
        <li>
206
            <span class="label">Total amount outstanding: </span>
207
            <span class="debit">[% total | format('%.2f') %]</span>
208
        </li>
209
    <li>
210
        <label for="paid">Collect from patron: </label>
211
        <!-- default to paying all -->
212
        <input name="paid" id="paid" value="[% total | format('%.2f') %]" onchange="moneyFormat(document.payfine.paid)"/>
213
    </li>
214
    <li>
215
        <label for="selected_accts_notes">Note: </label>
216
        <textarea name="selected_accts_notes" id="selected_accts_notes">[% selected_accts_notes %]</textarea>
217
    </li>
218
    </ol>
219
    </fieldset>
220
    <div class="action"><input type="submit" name="submitbutton" value="Confirm" />
221
        <a class="cancel" href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrower.borrowernumber %]">Cancel</a></div>
222
    </form>
223
[% END %]
224
</div></div>
225
</div>
226
</div>
227
228
<div class="yui-b">
229
[% INCLUDE 'circ-menu.tt' %]
230
</div>
231
</div>
232
[% INCLUDE 'intranet-bottom.inc' %]
233
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/members/printfeercpt.tt (-63 lines)
Lines 1-63 Link Here
1
[% INCLUDE 'doc-head-open.inc' %]
2
<title>Print Receipt for [% cardnumber %]</title>
3
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
4
<link rel="shortcut icon" href="[% IF ( IntranetFavicon ) %][% IntranetFavicon %][% ELSE %][% interface %]/[% theme %]/img/favicon.ico[% END %]" type="image/x-icon" />
5
<link rel="stylesheet" type="text/css" href="[% themelang %]/css/printreceiptinvoice.css" />
6
<script type="text/javascript">
7
    function printThenClose() {
8
        window.print();
9
        window.close();
10
    }
11
</script>
12
</head>
13
<body id="pat_printfeercpt" class="pat" onload="printThenClose();">
14
15
<div id="receipt">
16
<!-- The table with the account items -->
17
<table>
18
[% IF ( LibraryName ) %]
19
 <tr>
20
	<th colspan=3 class="centerednames">
21
		<h3>[% LibraryName %]</h3>
22
	</th>
23
 </tr>
24
[% END %]
25
 <tr>
26
	<th colspan=3 class="centerednames">
27
        <h2><u>Fee receipt</u></h2>
28
	</th>
29
 </tr>
30
 <tr>
31
	<th colspan=3 class="centerednames">
32
		[% IF ( branchname ) %]<h2>[% branchname %]</h2>[% END %]
33
	</th>
34
 </tr>
35
 <tr>
36
	<th colspan=3 >
37
		Received with thanks from  [% firstname %] [% surname %] <br />
38
        Card number : [% cardnumber %]<br />
39
	</th>
40
 </tr>
41
  <tr>
42
	<th>Date</th>
43
    <th>Description of charges</th>
44
    <th>Amount</th>
45
 </tr>
46
47
  [% FOREACH account IN accounts %]
48
<tr class="highlight">
49
      <td>[% account.date %]</td>
50
      <td>[% account.description %]</td>
51
      [% IF ( account.amountcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% account.amount %]</td>
52
    </tr>
53
54
  [% END %]
55
<tfoot>
56
  <tr>
57
    <td colspan="2">Total outstanding dues as on date : </td>
58
    [% IF ( totalcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% total %]</td>
59
  </tr>
60
  </tfoot>
61
</table>
62
</div>
63
[% INCLUDE 'intranet-bottom.inc' %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/members/printinvoice.tt (-65 lines)
Lines 1-65 Link Here
1
[% INCLUDE 'doc-head-open.inc' %]
2
<title>Print Receipt for [% cardnumber %]</title>
3
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
4
<link rel="shortcut icon" href="[% IF ( IntranetFavicon ) %][% IntranetFavicon %][% ELSE %][% interface %]/[% theme %]/img/favicon.ico[% END %]" type="image/x-icon" />
5
<link rel="stylesheet" type="text/css" href="[% themelang %]/css/printreceiptinvoice.css" />
6
<script type="text/javascript">
7
    function printThenClose() {
8
        window.print();
9
        window.close();
10
    }
11
</script>
12
</head>
13
<body id="printinvoice" class="pat" onload="printThenClose();">
14
15
<div id="receipt">
16
<!-- The table with the account items -->
17
<table>
18
[% IF ( LibraryName ) %]
19
  <tr>
20
    <th colspan="4" class="centerednames">
21
		<h3>[% LibraryName %]</h3>
22
	</th>
23
  </tr>
24
[% END %]
25
  <tr>
26
    <th colspan="4" class="centerednames">
27
		<h2><u>INVOICE</u></h2>
28
	</th>
29
  </tr>
30
  <tr>
31
    <th colspan="4" class="centerednames">
32
		[% IF ( branchname ) %]<h2>[% branchname %]</h2>[% END %]
33
	</th>
34
  </tr>
35
  <tr>
36
    <th colspan="4" >
37
        Bill to: [% firstname %] [% surname %] <br />
38
        Card number: [% cardnumber %]<br />
39
	</th>
40
  </tr>
41
  <tr>
42
	<th>Date</th>
43
    <th>Description of charges</th>
44
    <th style="text-align:right;">Amount</th>
45
    <th style="text-align:right;">Amount outstanding</th>
46
 </tr>
47
48
  [% FOREACH account IN accounts %]
49
<tr class="highlight">
50
      <td>[% account.date %]</td>
51
      <td>[% account.description %]</td>
52
      [% IF ( account.amountcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% account.amount %]</td>
53
      [% IF ( account.amountoutstandingcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% account.amountoutstanding %]</td>
54
    </tr>
55
56
  [% END %]
57
<tfoot>
58
  <tr>
59
    <td colspan="3">Total outstanding dues as on date: </td>
60
    [% IF ( totalcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% total %]</td>
61
  </tr>
62
  </tfoot>
63
</table>
64
</div>
65
[% INCLUDE 'intranet-bottom.inc' %]
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-account.tt (-33 / +350 lines)
Lines 1-9 Link Here
1
[% USE Koha %]
1
[% USE Koha %]
2
[% USE KohaDates %]
2
[% USE KohaDates %]
3
[% USE Currency %]
3
4
4
[% INCLUDE 'doc-head-open.inc' %][% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog &rsaquo; Your fines and charges
5
[% INCLUDE 'doc-head-open.inc' %][% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog &rsaquo; Your fines and charges
5
[% INCLUDE 'doc-head-close.inc' %]
6
[% INCLUDE 'doc-head-close.inc' %]
6
[% BLOCK cssinclude %][% END %]
7
[% BLOCK cssinclude %][% END %]
8
9
7
</head>
10
</head>
8
<body id="opac-account" class="scrollto">
11
<body id="opac-account" class="scrollto">
9
[% INCLUDE 'masthead.inc' %]
12
[% INCLUDE 'masthead.inc' %]
Lines 11-17 Link Here
11
<div class="main">
14
<div class="main">
12
    <ul class="breadcrumb">
15
    <ul class="breadcrumb">
13
        <li><a href="/cgi-bin/koha/opac-main.pl">Home</a> <span class="divider">&rsaquo;</span></li>
16
        <li><a href="/cgi-bin/koha/opac-main.pl">Home</a> <span class="divider">&rsaquo;</span></li>
14
        <li>[% FOREACH BORROWER_INF IN BORROWER_INFO %]<a href="/cgi-bin/koha/opac-user.pl">[% BORROWER_INF.firstname %] [% BORROWER_INF.surname %]</a>[% END %] <span class="divider">&rsaquo;</span></li>
17
        <li><a href="/cgi-bin/koha/opac-user.pl">[% borrower.firstname %] [% borrower.surname %]</a> <span class="divider">&rsaquo;</span></li>
15
        <li><a href="#">Your fines and charges</a></li>
18
        <li><a href="#">Your fines and charges</a></li>
16
    </ul>
19
    </ul>
17
20
Lines 25-62 Link Here
25
            <div class="span10">
28
            <div class="span10">
26
                <div id="useraccount" class="maincontent">
29
                <div id="useraccount" class="maincontent">
27
                    <h3>Fines and charges</h3>
30
                    <h3>Fines and charges</h3>
31
                    [% IF credits || debits %]
32
33
                        <p>
34
                            <h3>Account balance: [% borrower.account_balance | $Currency %]</h3>
35
                        </p>
36
37
                        <div>
38
                            <div id="account-debits">
39
                                <a id="account-debits-switcher" href="#" onclick="return false">View payments</a>
40
                                <table cellpadding="0" cellspacing="0" border="0" class="display" id="debits-table">
41
                                    <thead>
42
                                        <tr>
43
                                            <th colspan="99">Fees</th>
44
                                        </tr>
45
                                        <tr>
46
                                            <th></th>
47
                                            <th>ID</th>
48
                                            <th>Description</th>
49
                                            <th>Type</th>
50
                                            <th>Amount</th>
51
                                            <th>Outsanding</th>
52
                                            <th>Created on</th>
53
                                            <th>Updated on</th>
54
                                        </tr>
55
                                    </thead>
56
                                    <tbody></tbody>
57
                                </table>
58
                            </div>
28
59
29
                    [% IF ( ACCOUNT_LINES ) %]
60
                            <div id="account-credits">
30
                        <table class="table table-bordered table-striped">
61
                                <a id="account-credits-switcher" href="#"  onclick="return false">View fees</a>
31
                            <thead>
62
                                <table cellpadding="0" cellspacing="0" border="0" class="display" id="credits-table">
32
                                <tr>
63
                                    <thead>
33
                                    <th>Date</th>
64
                                        <tr>
34
                                    <th>Description</th>
65
                                            <th colspan="99">Payments</th>
35
                                    <th>Fine amount</th>
66
                                        </tr>
36
                                    <th>Amount outstanding</th>
67
                                        <tr>
37
                                </tr>
68
                                            <th></th>
38
                            </thead>
69
                                            <th>ID</th>
39
70
                                            <th>Notes</th>
40
                            <tfoot>
71
                                            <th>Type</th>
41
                            <tr>
72
                                            <th>Amount</th>
42
                                <th class="sum" colspan="3">Total due</th>
73
                                            <th>Remaining</th>
43
                                <td class="sum">[% total %]</td>
74
                                            <th>Created on</th>
44
                            </tr>
75
                                            <th>Updated on</th>
45
                            </tfoot>
76
                                        </tr>
46
77
                                    </thead>
47
                            <tbody>
78
                                    <tbody></tbody>
48
                                [% FOREACH ACCOUNT_LINE IN ACCOUNT_LINES %]
79
                                </table>
49
                                    [% IF ( ACCOUNT_LINE.odd ) %]<tr class="highlight">[% ELSE %]<tr>[% END %]
80
                            </div>
50
                                        <td>[% ACCOUNT_LINE.date | $KohaDates %]</td>
81
                        </div>
51
                                        <td>[% ACCOUNT_LINE.description %]
52
                                        [% IF ( ACCOUNT_LINE.title ) %][% ACCOUNT_LINE.title |html %][% END %]</td>
53
                                        [% IF ( ACCOUNT_LINE.amountcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% ACCOUNT_LINE.amount %]</td>
54
                                        [% IF ( ACCOUNT_LINE.amountoutstandingcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% ACCOUNT_LINE.amountoutstanding %]</td>
55
                                    </tr>
56
                                [% END %]
57
                            </tbody>
58
59
                        </table>
60
                    [% ELSE %]
82
                    [% ELSE %]
61
                        <h4>You have no fines or charges</h4>
83
                        <h4>You have no fines or charges</h4>
62
                    [% END %]
84
                    [% END %]
Lines 67-70 Link Here
67
</div> <!-- / .main -->
89
</div> <!-- / .main -->
68
90
69
[% INCLUDE 'opac-bottom.inc' %]
91
[% INCLUDE 'opac-bottom.inc' %]
70
[% BLOCK jsinclude %][% END %]
92
[% INCLUDE 'datatables.inc' %]
93
94
<script type="text/javascript">
95
//<![CDATA[
96
$(document).ready(function() {
97
    $('#account-credits').hide();    
98
    $('#account-debits-switcher').click(function() {
99
         $('#account-debits').slideUp();
100
         $('#account-credits').slideDown();
101
    });
102
    $('#account-credits-switcher').click(function() {
103
         $('#account-credits').slideUp();
104
         $('#account-debits').slideDown();
105
    });
106
107
    var anOpen = [];
108
    var sImageUrl = "[% interface %]/[% theme %]/images/";
109
110
    var debitsTable = $('#debits-table').dataTable( {
111
        "bProcessing": true,
112
        "aoColumns": [
113
            {
114
                "mDataProp": null,
115
                "sClass": "control center",
116
                "sDefaultContent": '<img src="'+sImageUrl+'details_open.png'+'">'
117
            },
118
            { "mDataProp": "debit_id" },
119
            { "mDataProp": "description" },
120
            { "mDataProp": "type" },
121
            { "mDataProp": "amount_original" },
122
            { "mDataProp": "amount_outstanding" },
123
            { "mDataProp": "created_on" },
124
            { "mDataProp": "updated_on" }
125
        ],
126
        "aaData": [
127
            [% FOREACH d IN debits %]
128
                {
129
                    [% PROCESS format_data data=d highlight='debit' %]
130
131
                    // Data for related item if there is one linked
132
                    "title": "[% d.item.biblio.title || d.deleted_item.biblio.title || d.deleted_item.deleted_biblio.title %]",
133
                    "biblionumber": "[% d.item.biblio.biblionumber || d.deleted_item.biblio.biblionumber %]",
134
                    "barcode": "[% d.item.barcode || d.deleted_item.barcode %]",
135
                    "itemnumber": "[% d.item.itemnumber %]", //This way itemnumber will be undef if deleted
136
137
138
                    // Data for related issue if there is one linked
139
                    [% IF d.issue %]
140
                        [% SET table = 'issue' %]
141
                    [% ELSIF d.old_issue %]
142
                        [% SET table = 'old_issue' %]
143
                    [% END %]
144
145
                    [% IF table %]
146
                        "issue": {
147
                            [% PROCESS format_data data=d.$table %]
148
                        },
149
                    [% END %]
150
151
152
                    "account_offsets": [
153
                        [% FOREACH ao IN d.account_offsets %]
154
                            {
155
                                [% PROCESS format_data data=ao highlight='offset'%]
156
157
                                "credit": {
158
                                    [% PROCESS format_data data=ao.credit highlight='credit' %]
159
                                } 
160
                            },
161
                        [% END %]
162
                    ] 
163
164
                },
165
            [% END %]
166
        ] 
167
    } );
168
169
    $('#debits-table td.control').live( 'click', function () {
170
        var nTr = this.parentNode;
171
        var i = $.inArray( nTr, anOpen );
172
173
        if ( i === -1 ) {
174
            $('img', this).attr( 'src', sImageUrl+"details_close.png" );
175
            var nDetailsRow = debitsTable.fnOpen( nTr, fnFormatDebitDetails(debitsTable, nTr), 'details' );
176
            $('div.innerDetails', nDetailsRow).slideDown();
177
            anOpen.push( nTr );
178
        } 
179
        else {
180
            $('img', this).attr( 'src', sImageUrl+"details_open.png" );
181
            $('div.innerDetails', $(nTr).next()[0]).slideUp( function () {
182
                debitsTable.fnClose( nTr );
183
                anOpen.splice( i, 1 );
184
            } );
185
        }
186
    } );
187
188
    var creditsTable = $('#credits-table').dataTable( {
189
        "bProcessing": true,
190
        "aoColumns": [
191
            {
192
                "mDataProp": null,
193
                "sClass": "control center",
194
                "sDefaultContent": '<img src="'+sImageUrl+'details_open.png'+'">'
195
            },
196
            { "mDataProp": "credit_id" },
197
            { "mDataProp": "notes" },
198
            { "mDataProp": "type" },
199
            { "mDataProp": "amount_paid" },
200
            { "mDataProp": "amount_remaining" },
201
            { "mDataProp": "created_on" },
202
            { "mDataProp": "updated_on" }
203
        ],
204
        "aaData": [
205
            [% FOREACH c IN credits %]
206
                {
207
                    [% PROCESS format_data data=c highlight='credit' %]
208
209
                    "account_offsets": [
210
                        [% FOREACH ao IN c.account_offsets %]
211
                            {
212
                                [% PROCESS format_data data=ao highlight='offset' %]
213
214
                                "debit": {
215
                                    [% PROCESS format_data data=ao.debit highlight='debit' %]
216
                                } 
217
                            },
218
                        [% END %]
219
                    ] 
220
221
                },
222
            [% END %]
223
        ] 
224
    } );
225
226
    $('#credits-table td.control').live( 'click', function () {
227
        var nTr = this.parentNode;
228
        var i = $.inArray( nTr, anOpen );
229
230
        if ( i === -1 ) {
231
            $('img', this).attr( 'src', sImageUrl+"details_close.png" );
232
            var nDetailsRow = creditsTable.fnOpen( nTr, fnFormatCreditDetails(creditsTable, nTr), 'details' );
233
            $('div.innerDetails', nDetailsRow).slideDown();
234
            anOpen.push( nTr );
235
        } 
236
        else {
237
            $('img', this).attr( 'src', sImageUrl+"details_open.png" );
238
            $('div.innerDetails', $(nTr).next()[0]).slideUp( function () {
239
                creditsTable.fnClose( nTr );
240
                anOpen.splice( i, 1 );
241
            } );
242
        }
243
    } );
244
245
} );
246
247
function fnFormatDebitDetails( debitsTable, nTr ) {
248
    var oData = debitsTable.fnGetData( nTr );
249
250
    var sOut = '<div class="innerDetails" style="display:none;">';
251
252
    var account_offsets = oData.account_offsets;
253
254
    sOut += '<ul>';
255
    if ( oData.title ) {
256
        sOut += '<li>' + _('Title: ');
257
        if ( oData.biblionumber ) {
258
            sOut += '<a href="/cgi-bin/koha/opac-detail.pl?biblionumber=' + oData.biblionumber + '">';
259
        }
260
261
        sOut += oData.title;
262
263
        if ( oData.biblionumber ) {
264
            sOut += '</a>';
265
        }
266
            
267
        sOut += '</li>';
268
    }
269
270
    if ( oData.barcode ) {
271
        sOut += '<li>' + _('Barcode: ') + oData.barcode + '</li>';
272
    }
273
274
    if ( oData.notes ) {
275
        sOut += '<li>' + _('Notes: ') + oData.notes + '</li>';
276
    }
277
278
    sOut += '</ul>';
279
280
    if ( account_offsets.length ) {
281
        sOut +=
282
            '<div class="innerDetails">' +
283
                '<table cellpadding="5" cellspacing="0" border="0" style="margin:10px;">' +
284
                    '<thead>' +
285
                        '<tr><th colspan="99">' + _('Payments applied') + '</th></tr>' +
286
                        '<tr>' +
287
                            '<th>' + _('ID') + '</th>' +
288
                            '<th>' + _('Created on') + '</th>' +
289
                            '<th>' + _('Payment amount') + '</th>' +
290
                            '<th>' + _('Applied amount') + '</th>' +
291
                            '<th>' + _('Type') + '</th>' +
292
                            '<th>' + _('Notes') + '</th>' +
293
                        '</tr>' +
294
                    '</thead>' +
295
                    '<tbody>';
296
297
        for ( var i = 0; i < account_offsets.length; i++ ) {
298
            ao = account_offsets[i];
299
            sOut +=
300
            '<tr>' +
301
                '<td>' + ao.credit_id + '</td>' +
302
                '<td>' + ao.created_on + '</td>' +
303
                '<td>' + ao.credit.amount_paid + '</td>' +
304
                '<td>' + ao.amount + '</td>' +
305
                '<td>' + ao.credit.type + '</td>' +
306
                '<td>' + ao.credit.notes + '</td>' +
307
            '</tr>';
308
        }
309
310
        sOut +=
311
            '</tbody>'+
312
            '</table>';
313
    }
314
315
    sOut +=
316
        '</div>';
317
318
    return sOut;
319
}
320
321
function fnFormatCreditDetails( creditsTable, nTr ) {
322
    var oData = creditsTable.fnGetData( nTr );
323
324
    var sOut = '<div class="innerDetails" style="display:none;">';
325
326
    var account_offsets = oData.account_offsets;
327
328
    if ( account_offsets.length ) {
329
        sOut +=
330
                '<table cellpadding="5" cellspacing="0" border="0" style="margin:10px;">' +
331
                    '<thead>' +
332
                        '<tr><th colspan="99">' + _('Fees paid') + '</th></tr>' +
333
                        '<tr>' +
334
                            '<th>' + _('ID') + '</th>' +
335
                            '<th>' + _('Description') + '</th>' +
336
                            '<th>' + _('Type') + '</th>' +
337
                            '<th>' + _('Amount') + '</th>' +
338
                            '<th>' + _('Remaining') + '</th>' +
339
                            '<th>' + _('Created on') + '</th>' +
340
                            '<th>' + _('Updated on') + '</th>' +
341
                            '<th>' + _('Notes') + '</th>' +
342
                        '</tr>' +
343
                    '</thead>' +
344
                    '<tbody>';
345
346
        for ( var i = 0; i < account_offsets.length; i++ ) {
347
            ao = account_offsets[i];
348
            sOut +=
349
            '<tr>' +
350
                '<td>' + ao.debit.debit_id + '</td>' +
351
                '<td>' + ao.debit.description + '</td>' +
352
                '<td>' + ao.debit.type + '</td>' +
353
                '<td>' + ao.debit.amount_original + '</td>' +
354
                '<td>' + ao.debit.amount_outstanding + '</td>' +
355
                '<td>' + ao.debit.created_on + '</td>' +
356
                '<td>' + ao.debit.updated_on + '</td>' +
357
                '<td>' + ao.debit.notes + '</td>' +
358
            '</tr>';
359
        }
360
361
        sOut +=
362
            '</tbody>'+
363
            '</table>';
364
    }
365
366
    sOut +=
367
        '</div>';
368
369
    return sOut;
370
}
371
372
//]]>
373
</script>
374
375
[% BLOCK jsinclude %][% END %]
376
377
[% BLOCK format_data %]
378
    [% FOREACH key IN data.result_source.columns %]
379
        [% IF key.match('^amount') %]
380
            "[% key %]": "[% data.$key FILTER $Currency %]",
381
        [% ELSIF key.match('_on$') %]
382
            "[% key %]": "[% data.$key | $KohaDates %]",
383
        [% ELSE %]
384
            "[% key %]": "[% data.$key %]",
385
        [% END %]
386
    [% END %]
387
[% END %]
(-)a/koha-tmpl/opac-tmpl/prog/en/modules/opac-account.tt (-53 / +371 lines)
Lines 1-64 Link Here
1
[% SET accountview = 1 %]
2
1
[% USE Koha %]
3
[% USE Koha %]
2
[% USE KohaDates %]
4
[% USE KohaDates %]
5
[% USE Currency %]
3
6
4
[% INCLUDE 'doc-head-open.inc' %][% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog &rsaquo; Your fines and charges
7
[% INCLUDE 'doc-head-open.inc' %][% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog &rsaquo; Your fines and charges
5
[% INCLUDE 'doc-head-close.inc' %]
8
[% INCLUDE 'doc-head-close.inc' %]
6
</head>
9
</head>
7
<body id="opac-account">
10
<body id="opac-account">
8
<div id="doc3" class="yui-t1">
11
<div id="doc3" class="yui-t1">
9
   <div id="bd">
12
    <div id="bd">
10
[% INCLUDE 'masthead.inc' %]
13
        [% INCLUDE 'masthead.inc' %]
11
14
    	<div id="yui-main">
12
	<div id="yui-main">
15
	        <div class="yui-b">
13
	<div class="yui-b"><div class="yui-g">
16
                <div class="yui-g">
14
		<div id="useraccount" class="container">
17
            		<div id="useraccount" class="container">
15
<!--CONTENT-->
18
                        <h3><a href="/cgi-bin/koha/opac-user.pl">[% borrower.firstname %] [% borrower.surname %]'s account</a> &#8674; Fines and charges</h3>
16
    [% FOREACH BORROWER_INF IN BORROWER_INFO %]
17
        <h3><a href="/cgi-bin/koha/opac-user.pl">[% BORROWER_INF.firstname %] [% BORROWER_INF.surname %]'s account</a> &#8674; Fines and charges</h3>
18
    [% END %]
19
19
20
    [% IF ( ACCOUNT_LINES ) %]
20
                        [% IF credits || debits %]
21
        <table>
21
22
            <thead>
22
                            <p>
23
                <tr>
23
                                <h3>Account balance: [% borrower.account_balance | $Currency %]</h3>
24
                    <th>Date</th>
24
                            </p>
25
                    <th>Description</th>
25
26
                    <th>Fine amount</th>
26
                            <div>
27
                    <th>Amount outstanding</th>
27
                                <div id="account-debits">
28
                </tr>
28
                                    <a id="account-debits-switcher" href="#" onclick="return false">View payments</a>
29
            </thead>
29
                                    <table cellpadding="0" cellspacing="0" border="0" class="display" id="debits-table">
30
30
                                        <thead>
31
            <tfoot>
31
                                            <tr>
32
            <tr>
32
                                                <th colspan="99">Fees</th>
33
                <th class="sum" colspan="3">Total due</th>
33
                                            </tr>
34
                <td class="sum">[% total %]</td>
34
                                            <tr>
35
            </tr>
35
                                                <th></th>
36
            </tfoot>
36
                                                <th>ID</th>
37
37
                                                <th>Description</th>
38
            <tbody>
38
                                                <th>Type</th>
39
                [% FOREACH ACCOUNT_LINE IN ACCOUNT_LINES %]
39
                                                <th>Amount</th>
40
                    [% IF ( ACCOUNT_LINE.odd ) %]<tr class="highlight">[% ELSE %]<tr>[% END %]
40
                                                <th>Outsanding</th>
41
                        <td>[% ACCOUNT_LINE.date | $KohaDates %]</td>
41
                                                <th>Created on</th>
42
                        <td>[% ACCOUNT_LINE.description %]
42
                                                <th>Updated on</th>
43
                        [% IF ( ACCOUNT_LINE.title ) %][% ACCOUNT_LINE.title |html %][% END %]</td>
43
                                            </tr>
44
                        [% IF ( ACCOUNT_LINE.amountcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% ACCOUNT_LINE.amount %]</td>
44
                                        </thead>
45
                        [% IF ( ACCOUNT_LINE.amountoutstandingcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% ACCOUNT_LINE.amountoutstanding %]</td>
45
                                        <tbody></tbody>
46
                    </tr>
46
                                    </table>
47
                [% END %]
47
                                </div>
48
            </tbody>
48
49
49
                                <div id="account-credits">
50
        </table>
50
                                    <a id="account-credits-switcher" href="#"  onclick="return false">View fees</a>
51
    [% ELSE %]
51
                                    <table cellpadding="0" cellspacing="0" border="0" class="display" id="credits-table">
52
        <h4>You have no fines or charges</h4>
52
                                        <thead>
53
    [% END %]
53
                                            <tr>
54
</div>
54
                                                <th colspan="99">Payments</th>
55
</div>
55
                                            </tr>
56
</div>
56
                                            <tr>
57
</div>
57
                                                <th></th>
58
<div class="yui-b">
58
                                                <th>ID</th>
59
<div id="leftmenus" class="container">
59
                                                <th>Notes</th>
60
[% INCLUDE 'navigation.inc' IsPatronPage=1 %]
60
                                                <th>Type</th>
61
</div>
61
                                                <th>Amount</th>
62
</div>
62
                                                <th>Remaining</th>
63
                                                <th>Created on</th>
64
                                                <th>Updated on</th>
65
                                            </tr>
66
                                        </thead>
67
                                        <tbody></tbody>
68
                                    </table>
69
                                </div>
70
                            </div>
71
                        [% ELSE %]
72
                            <h4>You have no fines or charges</h4>
73
                        [% END %]
74
                    </div>
75
                </div>
76
            </div>
77
        </div>
78
79
    <div class="yui-b">
80
        <div id="leftmenus" class="container">
81
            [% INCLUDE 'navigation.inc' IsPatronPage=1 %]
82
        </div>
83
    </div>
63
</div>
84
</div>
64
[% INCLUDE 'opac-bottom.inc' %]
85
[% INCLUDE 'opac-bottom.inc' %]
86
87
[% INCLUDE 'datatables.inc' %]
88
89
<script type="text/javascript">
90
//<![CDATA[
91
$(document).ready(function() {
92
    $('#account-credits').hide();    
93
    $('#account-debits-switcher').click(function() {
94
         $('#account-debits').slideUp();
95
         $('#account-credits').slideDown();
96
    });
97
    $('#account-credits-switcher').click(function() {
98
         $('#account-credits').slideUp();
99
         $('#account-debits').slideDown();
100
    });
101
102
    var anOpen = [];
103
    var sImageUrl = "[% interface %]/[% theme %]/images/";
104
105
    var debitsTable = $('#debits-table').dataTable( {
106
        "bProcessing": true,
107
        "aoColumns": [
108
            {
109
                "mDataProp": null,
110
                "sClass": "control center",
111
                "sDefaultContent": '<img src="'+sImageUrl+'details_open.png'+'">'
112
            },
113
            { "mDataProp": "debit_id" },
114
            { "mDataProp": "description" },
115
            { "mDataProp": "type" },
116
            { "mDataProp": "amount_original" },
117
            { "mDataProp": "amount_outstanding" },
118
            { "mDataProp": "created_on" },
119
            { "mDataProp": "updated_on" }
120
        ],
121
        "aaData": [
122
            [% FOREACH d IN debits %]
123
                {
124
                    [% PROCESS format_data data=d highlight='debit' %]
125
126
                    // Data for related item if there is one linked
127
                    "title": "[% d.item.biblio.title || d.deleted_item.biblio.title || d.deleted_item.deleted_biblio.title %]",
128
                    "biblionumber": "[% d.item.biblio.biblionumber || d.deleted_item.biblio.biblionumber %]",
129
                    "barcode": "[% d.item.barcode || d.deleted_item.barcode %]",
130
                    "itemnumber": "[% d.item.itemnumber %]", //This way itemnumber will be undef if deleted
131
132
133
                    // Data for related issue if there is one linked
134
                    [% IF d.issue %]
135
                        [% SET table = 'issue' %]
136
                    [% ELSIF d.old_issue %]
137
                        [% SET table = 'old_issue' %]
138
                    [% END %]
139
140
                    [% IF table %]
141
                        "issue": {
142
                            [% PROCESS format_data data=d.$table %]
143
                        },
144
                    [% END %]
145
146
147
                    "account_offsets": [
148
                        [% FOREACH ao IN d.account_offsets %]
149
                            {
150
                                [% PROCESS format_data data=ao highlight='offset'%]
151
152
                                "credit": {
153
                                    [% PROCESS format_data data=ao.credit highlight='credit' %]
154
                                } 
155
                            },
156
                        [% END %]
157
                    ] 
158
159
                },
160
            [% END %]
161
        ] 
162
    } );
163
164
    $('#debits-table td.control').live( 'click', function () {
165
        var nTr = this.parentNode;
166
        var i = $.inArray( nTr, anOpen );
167
168
        if ( i === -1 ) {
169
            $('img', this).attr( 'src', sImageUrl+"details_close.png" );
170
            var nDetailsRow = debitsTable.fnOpen( nTr, fnFormatDebitDetails(debitsTable, nTr), 'details' );
171
            $('div.innerDetails', nDetailsRow).slideDown();
172
            anOpen.push( nTr );
173
        } 
174
        else {
175
            $('img', this).attr( 'src', sImageUrl+"details_open.png" );
176
            $('div.innerDetails', $(nTr).next()[0]).slideUp( function () {
177
                debitsTable.fnClose( nTr );
178
                anOpen.splice( i, 1 );
179
            } );
180
        }
181
    } );
182
183
    var creditsTable = $('#credits-table').dataTable( {
184
        "bProcessing": true,
185
        "aoColumns": [
186
            {
187
                "mDataProp": null,
188
                "sClass": "control center",
189
                "sDefaultContent": '<img src="'+sImageUrl+'details_open.png'+'">'
190
            },
191
            { "mDataProp": "credit_id" },
192
            { "mDataProp": "notes" },
193
            { "mDataProp": "type" },
194
            { "mDataProp": "amount_paid" },
195
            { "mDataProp": "amount_remaining" },
196
            { "mDataProp": "created_on" },
197
            { "mDataProp": "updated_on" }
198
        ],
199
        "aaData": [
200
            [% FOREACH c IN credits %]
201
                {
202
                    [% PROCESS format_data data=c highlight='credit' %]
203
204
                    "account_offsets": [
205
                        [% FOREACH ao IN c.account_offsets %]
206
                            {
207
                                [% PROCESS format_data data=ao highlight='offset' %]
208
209
                                "debit": {
210
                                    [% PROCESS format_data data=ao.debit highlight='debit' %]
211
                                } 
212
                            },
213
                        [% END %]
214
                    ] 
215
216
                },
217
            [% END %]
218
        ] 
219
    } );
220
221
    $('#credits-table td.control').live( 'click', function () {
222
        var nTr = this.parentNode;
223
        var i = $.inArray( nTr, anOpen );
224
225
        if ( i === -1 ) {
226
            $('img', this).attr( 'src', sImageUrl+"details_close.png" );
227
            var nDetailsRow = creditsTable.fnOpen( nTr, fnFormatCreditDetails(creditsTable, nTr), 'details' );
228
            $('div.innerDetails', nDetailsRow).slideDown();
229
            anOpen.push( nTr );
230
        } 
231
        else {
232
            $('img', this).attr( 'src', sImageUrl+"details_open.png" );
233
            $('div.innerDetails', $(nTr).next()[0]).slideUp( function () {
234
                creditsTable.fnClose( nTr );
235
                anOpen.splice( i, 1 );
236
            } );
237
        }
238
    } );
239
240
} );
241
242
function fnFormatDebitDetails( debitsTable, nTr ) {
243
    var oData = debitsTable.fnGetData( nTr );
244
245
    var sOut = '<div class="innerDetails" style="display:none;">';
246
247
    var account_offsets = oData.account_offsets;
248
249
    sOut += '<ul>';
250
    if ( oData.title ) {
251
        sOut += '<li>' + _('Title: ');
252
        if ( oData.biblionumber ) {
253
            sOut += '<a href="/cgi-bin/koha/opac-detail.pl?biblionumber=' + oData.biblionumber + '">';
254
        }
255
256
        sOut += oData.title;
257
258
        if ( oData.biblionumber ) {
259
            sOut += '</a>';
260
        }
261
            
262
        sOut += '</li>';
263
    }
264
265
    if ( oData.barcode ) {
266
        sOut += '<li>' + _('Barcode: ') + oData.barcode + '</li>';
267
    }
268
269
    if ( oData.notes ) {
270
        sOut += '<li>' + _('Notes: ') + oData.notes + '</li>';
271
    }
272
273
    sOut += '</ul>';
274
275
    if ( account_offsets.length ) {
276
        sOut +=
277
            '<div class="innerDetails">' +
278
                '<table cellpadding="5" cellspacing="0" border="0" style="margin:10px;">' +
279
                    '<thead>' +
280
                        '<tr><th colspan="99">' + _('Payments applied') + '</th></tr>' +
281
                        '<tr>' +
282
                            '<th>' + _('ID') + '</th>' +
283
                            '<th>' + _('Created on') + '</th>' +
284
                            '<th>' + _('Payment amount') + '</th>' +
285
                            '<th>' + _('Applied amount') + '</th>' +
286
                            '<th>' + _('Type') + '</th>' +
287
                            '<th>' + _('Notes') + '</th>' +
288
                        '</tr>' +
289
                    '</thead>' +
290
                    '<tbody>';
291
292
        for ( var i = 0; i < account_offsets.length; i++ ) {
293
            ao = account_offsets[i];
294
            sOut +=
295
            '<tr>' +
296
                '<td>' + ao.credit_id + '</td>' +
297
                '<td>' + ao.created_on + '</td>' +
298
                '<td>' + ao.credit.amount_paid + '</td>' +
299
                '<td>' + ao.amount + '</td>' +
300
                '<td>' + ao.credit.type + '</td>' +
301
                '<td>' + ao.credit.notes + '</td>' +
302
            '</tr>';
303
        }
304
305
        sOut +=
306
            '</tbody>'+
307
            '</table>';
308
    }
309
310
    sOut +=
311
        '</div>';
312
313
    return sOut;
314
}
315
316
function fnFormatCreditDetails( creditsTable, nTr ) {
317
    var oData = creditsTable.fnGetData( nTr );
318
319
    var sOut = '<div class="innerDetails" style="display:none;">';
320
321
    var account_offsets = oData.account_offsets;
322
323
    if ( account_offsets.length ) {
324
        sOut +=
325
                '<table cellpadding="5" cellspacing="0" border="0" style="margin:10px;">' +
326
                    '<thead>' +
327
                        '<tr><th colspan="99">' + _('Fees paid') + '</th></tr>' +
328
                        '<tr>' +
329
                            '<th>' + _('ID') + '</th>' +
330
                            '<th>' + _('Description') + '</th>' +
331
                            '<th>' + _('Type') + '</th>' +
332
                            '<th>' + _('Amount') + '</th>' +
333
                            '<th>' + _('Remaining') + '</th>' +
334
                            '<th>' + _('Created on') + '</th>' +
335
                            '<th>' + _('Updated on') + '</th>' +
336
                            '<th>' + _('Notes') + '</th>' +
337
                        '</tr>' +
338
                    '</thead>' +
339
                    '<tbody>';
340
341
        for ( var i = 0; i < account_offsets.length; i++ ) {
342
            ao = account_offsets[i];
343
            sOut +=
344
            '<tr>' +
345
                '<td>' + ao.debit.debit_id + '</td>' +
346
                '<td>' + ao.debit.description + '</td>' +
347
                '<td>' + ao.debit.type + '</td>' +
348
                '<td>' + ao.debit.amount_original + '</td>' +
349
                '<td>' + ao.debit.amount_outstanding + '</td>' +
350
                '<td>' + ao.debit.created_on + '</td>' +
351
                '<td>' + ao.debit.updated_on + '</td>' +
352
                '<td>' + ao.debit.notes + '</td>' +
353
            '</tr>';
354
        }
355
356
        sOut +=
357
            '</tbody>'+
358
            '</table>';
359
    }
360
361
    sOut +=
362
        '</div>';
363
364
    return sOut;
365
}
366
367
//]]>
368
</script>
369
370
[% BLOCK jsinclude %][% END %]
371
372
[% BLOCK format_data %]
373
    [% FOREACH key IN data.result_source.columns %]
374
        [% IF key.match('^amount') %]
375
            "[% key %]": "[% data.$key FILTER $Currency %]",
376
        [% ELSIF key.match('_on$') %]
377
            "[% key %]": "[% data.$key | $KohaDates %]",
378
        [% ELSE %]
379
            "[% key %]": "[% data.$key %]",
380
        [% END %]
381
    [% END %]
382
[% END %]
(-)a/members/account.pl (+113 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# Copyright 2000-2002 Katipo Communications
4
# Copyright 2013 ByWater Solutions
5
#
6
# This file is part of Koha.
7
#
8
# Koha is free software; you can redistribute it and/or modify it under the
9
# terms of the GNU General Public License as published by the Free Software
10
# Foundation; either version 2 of the License, or (at your option) any later
11
# version.
12
#
13
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
14
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License along
18
# with Koha; if not, write to the Free Software Foundation, Inc.,
19
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
21
use Modern::Perl;
22
23
use CGI;
24
25
use C4::Auth;
26
use C4::Output;
27
use C4::Dates qw/format_date/;
28
use C4::Members;
29
use C4::Branch;
30
use C4::Accounts;
31
use C4::Members::Attributes qw(GetBorrowerAttributes);
32
use Koha::Database;
33
34
my $cgi = new CGI;
35
36
my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
37
    {
38
        template_name   => "members/account.tt",
39
        query           => $cgi,
40
        type            => "intranet",
41
        authnotrequired => 0,
42
        flagsrequired   => { borrowers => 1, updatecharges => 1 },
43
        debug           => 1,
44
    }
45
);
46
47
my $borrowernumber = $cgi->param('borrowernumber');
48
49
my $borrower = GetMember( 'borrowernumber' => $borrowernumber );
50
51
my @debits = Koha::Database->new()->schema->resultset('AccountDebit')->search(
52
    { 'me.borrowernumber' => $borrowernumber },
53
    { prefetch            => { account_offsets => 'credit' } }
54
);
55
56
my @credits = Koha::Database->new()->schema->resultset('AccountCredit')->search(
57
    { 'me.borrowernumber' => $borrowernumber },
58
    { prefetch            => { account_offsets => 'debit' } }
59
);
60
61
$template->param(
62
    debits   => \@debits,
63
    credits  => \@credits,
64
    borrower => $borrower,
65
);
66
67
# Standard /members/ borrower details data
68
## FIXME: This code is in every /members/ script and should be unified
69
70
if ( $borrower->{'category_type'} eq 'C' ) {
71
    my ( $catcodes, $labels ) =
72
      GetborCatFromCatType( 'A', 'WHERE category_type = ?' );
73
    my $cnt = scalar(@$catcodes);
74
    $template->param( 'CATCODE_MULTI' => 1 ) if $cnt > 1;
75
    $template->param( 'catcode' => $catcodes->[0] ) if $cnt == 1;
76
}
77
78
my ( $picture, $dberror ) = GetPatronImage( $borrower->{'borrowernumber'} );
79
$template->param( picture => 1 ) if $picture;
80
81
if ( C4::Context->preference('ExtendedPatronAttributes') ) {
82
    my $attributes = GetBorrowerAttributes($borrowernumber);
83
    $template->param(
84
        ExtendedPatronAttributes => 1,
85
        extendedattributes       => $attributes
86
    );
87
}
88
89
$template->param(
90
    borrowernumber => $borrowernumber,
91
    firstname      => $borrower->{'firstname'},
92
    surname        => $borrower->{'surname'},
93
    cardnumber     => $borrower->{'cardnumber'},
94
    categorycode   => $borrower->{'categorycode'},
95
    category_type  => $borrower->{'category_type'},
96
    categoryname   => $borrower->{'description'},
97
    address        => $borrower->{'address'},
98
    address2       => $borrower->{'address2'},
99
    city           => $borrower->{'city'},
100
    state          => $borrower->{'state'},
101
    zipcode        => $borrower->{'zipcode'},
102
    country        => $borrower->{'country'},
103
    phone          => $borrower->{'phone'},
104
    email          => $borrower->{'email'},
105
    branchcode     => $borrower->{'branchcode'},
106
    branchname     => GetBranchName( $borrower->{'branchcode'} ),
107
    is_child       => ( $borrower->{'category_type'} eq 'C' ),
108
    activeBorrowerRelationship =>
109
      ( C4::Context->preference('borrowerRelationship') ne '' ),
110
    RoutingSerials => C4::Context->preference('RoutingSerials'),
111
);
112
113
output_html_with_http_headers $cgi, $cookie, $template->output;
(-)a/members/account_credit.pl (+104 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
#written 11/1/2000 by chris@katipo.oc.nz
4
#script to display borrowers account details
5
6
# Copyright 2000-2002 Katipo Communications
7
# Copyright 2010 BibLibre
8
#
9
# This file is part of Koha.
10
#
11
# Koha is free software; you can redistribute it and/or modify it under the
12
# terms of the GNU General Public License as published by the Free Software
13
# Foundation; either version 2 of the License, or (at your option) any later
14
# version.
15
#
16
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
17
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
18
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
19
#
20
# You should have received a copy of the GNU General Public License along
21
# with Koha; if not, write to the Free Software Foundation, Inc.,
22
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23
24
use strict;
25
use warnings;
26
27
use C4::Auth;
28
use C4::Output;
29
use CGI;
30
31
use C4::Koha;
32
use C4::Members;
33
use C4::Branch;
34
use C4::Accounts;
35
use C4::Items;
36
use C4::Members::Attributes qw(GetBorrowerAttributes);
37
use Koha::Database;
38
39
my $cgi = new CGI;
40
41
my $borrowernumber = $cgi->param('borrowernumber');
42
43
my $borrower = GetMember( 'borrowernumber' => $borrowernumber );
44
45
my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
46
    {
47
        template_name   => "members/account_credit.tt",
48
        query           => $cgi,
49
        type            => "intranet",
50
        authnotrequired => 0,
51
        flagsrequired   => { borrowers => 1, updatecharges => 1 },
52
        debug           => 1,
53
    }
54
);
55
56
$template->param( credit_types_loop => GetAuthorisedValues('ACCOUNT_CREDIT') );
57
58
# Standard /members/ borrower details data
59
## FIXME: This code is in every /members/ script and should be unified
60
61
if ( $borrower->{'category_type'} eq 'C' ) {
62
    my ( $catcodes, $labels ) =
63
      GetborCatFromCatType( 'A', 'WHERE category_type = ?' );
64
    my $cnt = scalar(@$catcodes);
65
    $template->param( 'CATCODE_MULTI' => 1 ) if $cnt > 1;
66
    $template->param( 'catcode' => $catcodes->[0] ) if $cnt == 1;
67
}
68
69
my ( $picture, $dberror ) = GetPatronImage( $borrower->{'borrowernumber'} );
70
$template->param( picture => 1 ) if $picture;
71
72
if ( C4::Context->preference('ExtendedPatronAttributes') ) {
73
    my $attributes = GetBorrowerAttributes($borrowernumber);
74
    $template->param(
75
        ExtendedPatronAttributes => 1,
76
        extendedattributes       => $attributes
77
    );
78
}
79
80
$template->param(
81
    borrowernumber => $borrowernumber,
82
    firstname      => $borrower->{'firstname'},
83
    surname        => $borrower->{'surname'},
84
    cardnumber     => $borrower->{'cardnumber'},
85
    categorycode   => $borrower->{'categorycode'},
86
    category_type  => $borrower->{'category_type'},
87
    categoryname   => $borrower->{'description'},
88
    address        => $borrower->{'address'},
89
    address2       => $borrower->{'address2'},
90
    city           => $borrower->{'city'},
91
    state          => $borrower->{'state'},
92
    zipcode        => $borrower->{'zipcode'},
93
    country        => $borrower->{'country'},
94
    phone          => $borrower->{'phone'},
95
    email          => $borrower->{'email'},
96
    branchcode     => $borrower->{'branchcode'},
97
    branchname     => GetBranchName( $borrower->{'branchcode'} ),
98
    is_child       => ( $borrower->{'category_type'} eq 'C' ),
99
    activeBorrowerRelationship =>
100
      ( C4::Context->preference('borrowerRelationship') ne '' ),
101
    RoutingSerials => C4::Context->preference('RoutingSerials'),
102
);
103
104
output_html_with_http_headers $cgi, $cookie, $template->output;
(-)a/members/account_credit_do.pl (+68 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# Copyright 2000-2002 Katipo Communications
4
# Copyright 2010 BibLibre
5
# Copyright 2013 ByWater Solutions
6
#
7
# This file is part of Koha.
8
#
9
# Koha is free software; you can redistribute it and/or modify it under the
10
# terms of the GNU General Public License as published by the Free Software
11
# Foundation; either version 2 of the License, or (at your option) any later
12
# version.
13
#
14
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
15
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
17
#
18
# You should have received a copy of the GNU General Public License along
19
# with Koha; if not, write to the Free Software Foundation, Inc.,
20
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
22
use Modern::Perl;
23
24
use CGI;
25
26
use C4::Auth;
27
use C4::Output;
28
use C4::Members;
29
use C4::Items;
30
use C4::Branch;
31
use C4::Members::Attributes qw(GetBorrowerAttributes);
32
use Koha::Accounts;
33
use Koha::Database;
34
35
my $cgi = new CGI;
36
37
my $borrowernumber = $cgi->param('borrowernumber');
38
my $borrower =
39
  Koha::Database->new()->schema->resultset('Borrower')->find($borrowernumber);
40
41
if ( checkauth( $cgi, 0, { borrowers => 1 }, 'intranet' ) ) {
42
43
    my $barcode     = $cgi->param('barcode');
44
    my $itemnumber  = $cgi->param('itemnumber');
45
    my $description = $cgi->param('description');
46
    my $amount      = $cgi->param('amount');
47
    my $type        = $cgi->param('type');
48
    my $notes       = $cgi->param('notes');
49
50
    if ( !$itemnumber && $barcode ) {
51
        $itemnumber = GetItemnumberFromBarcode($barcode);
52
    }
53
54
    my $debit = AddCredit(
55
        {
56
            borrower    => $borrower,
57
            amount      => $amount,
58
            type        => $type,
59
            itemnumber  => $itemnumber,
60
            description => $description,
61
            notes       => $notes,
62
63
        }
64
    );
65
66
    print $cgi->redirect(
67
        "/cgi-bin/koha/members/account.pl?borrowernumber=$borrowernumber");
68
}
(-)a/members/account_debit.pl (+104 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
#written 11/1/2000 by chris@katipo.oc.nz
4
#script to display borrowers account details
5
6
# Copyright 2000-2002 Katipo Communications
7
# Copyright 2010 BibLibre
8
#
9
# This file is part of Koha.
10
#
11
# Koha is free software; you can redistribute it and/or modify it under the
12
# terms of the GNU General Public License as published by the Free Software
13
# Foundation; either version 2 of the License, or (at your option) any later
14
# version.
15
#
16
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
17
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
18
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
19
#
20
# You should have received a copy of the GNU General Public License along
21
# with Koha; if not, write to the Free Software Foundation, Inc.,
22
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23
24
use strict;
25
use warnings;
26
27
use CGI;
28
29
use C4::Auth;
30
use C4::Output;
31
use C4::Members;
32
use C4::Items;
33
use C4::Branch;
34
use C4::Members::Attributes qw(GetBorrowerAttributes);
35
use C4::Koha;
36
use Koha::Accounts;
37
use Koha::Database;
38
39
my $input = new CGI;
40
41
my $borrowernumber = $input->param('borrowernumber');
42
43
my $borrower = GetMember( 'borrowernumber' => $borrowernumber );
44
45
my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
46
    {
47
        template_name   => "members/account_debit.tt",
48
        query           => $input,
49
        type            => "intranet",
50
        authnotrequired => 0,
51
        flagsrequired   => { borrowers => 1, updatecharges => 1 },
52
        debug           => 1,
53
    }
54
);
55
56
$template->param( invoice_types_loop => GetAuthorisedValues('MANUAL_INV') );
57
58
# Standard /members/ borrower details data
59
## FIXME: This code is in every /members/ script and should be unified
60
61
if ( $borrower->{'category_type'} eq 'C' ) {
62
    my ( $catcodes, $labels ) =
63
      GetborCatFromCatType( 'A', 'WHERE category_type = ?' );
64
    my $cnt = scalar(@$catcodes);
65
    $template->param( 'CATCODE_MULTI' => 1 ) if $cnt > 1;
66
    $template->param( 'catcode' => $catcodes->[0] ) if $cnt == 1;
67
}
68
69
my ( $picture, $dberror ) = GetPatronImage( $borrower->{'borrowernumber'} );
70
$template->param( picture => 1 ) if $picture;
71
72
if ( C4::Context->preference('ExtendedPatronAttributes') ) {
73
    my $attributes = GetBorrowerAttributes($borrowernumber);
74
    $template->param(
75
        ExtendedPatronAttributes => 1,
76
        extendedattributes       => $attributes
77
    );
78
}
79
80
$template->param(
81
    borrowernumber => $borrowernumber,
82
    firstname      => $borrower->{'firstname'},
83
    surname        => $borrower->{'surname'},
84
    cardnumber     => $borrower->{'cardnumber'},
85
    categorycode   => $borrower->{'categorycode'},
86
    category_type  => $borrower->{'category_type'},
87
    categoryname   => $borrower->{'description'},
88
    address        => $borrower->{'address'},
89
    address2       => $borrower->{'address2'},
90
    city           => $borrower->{'city'},
91
    state          => $borrower->{'state'},
92
    zipcode        => $borrower->{'zipcode'},
93
    country        => $borrower->{'country'},
94
    phone          => $borrower->{'phone'},
95
    email          => $borrower->{'email'},
96
    branchcode     => $borrower->{'branchcode'},
97
    branchname     => GetBranchName( $borrower->{'branchcode'} ),
98
    is_child       => ( $borrower->{'category_type'} eq 'C' ),
99
    activeBorrowerRelationship =>
100
      ( C4::Context->preference('borrowerRelationship') ne '' ),
101
    RoutingSerials => C4::Context->preference('RoutingSerials'),
102
);
103
104
output_html_with_http_headers $input, $cookie, $template->output;
(-)a/members/account_debit_do.pl (+69 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# Copyright 2000-2002 Katipo Communications
4
# Copyright 2010 BibLibre
5
# Copyright 2013 ByWater Solutions
6
#
7
# This file is part of Koha.
8
#
9
# Koha is free software; you can redistribute it and/or modify it under the
10
# terms of the GNU General Public License as published by the Free Software
11
# Foundation; either version 2 of the License, or (at your option) any later
12
# version.
13
#
14
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
15
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
17
#
18
# You should have received a copy of the GNU General Public License along
19
# with Koha; if not, write to the Free Software Foundation, Inc.,
20
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
22
use Modern::Perl;
23
24
use CGI;
25
26
use C4::Auth;
27
use C4::Output;
28
use C4::Members;
29
use C4::Items;
30
use C4::Branch;
31
use C4::Members::Attributes qw(GetBorrowerAttributes);
32
use Koha::Accounts;
33
use Koha::Database;
34
35
my $cgi = new CGI;
36
37
my $borrowernumber = $cgi->param('borrowernumber');
38
my $borrower =
39
  Koha::Database->new()->schema->resultset('Borrower')->find($borrowernumber);
40
41
if ( checkauth( $cgi, 0, { borrowers => 1 }, 'intranet' ) ) {
42
43
    #  print $cgi->header;
44
    my $barcode     = $cgi->param('barcode');
45
    my $itemnumber  = $cgi->param('itemnumber');
46
    my $description = $cgi->param('description');
47
    my $amount      = $cgi->param('amount');
48
    my $type        = $cgi->param('type');
49
    my $notes       = $cgi->param('notes');
50
51
    if ( !$itemnumber && $barcode ) {
52
        $itemnumber = GetItemnumberFromBarcode($barcode);
53
    }
54
55
    my $debit = AddDebit(
56
        {
57
            borrower    => $borrower,
58
            amount      => $amount,
59
            type        => $type,
60
            itemnumber  => $itemnumber,
61
            description => $description,
62
            notes       => $notes,
63
64
        }
65
    );
66
67
    print $cgi->redirect(
68
        "/cgi-bin/koha/members/account.pl?borrowernumber=$borrowernumber");
69
}
(-)a/members/account_payment.pl (+123 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# Copyright 2000-2002 Katipo Communications
4
# Copyright 2010 BibLibre
5
# Copyright 2010,2011 PTFS-Europe Ltd
6
# Copyright 2013 ByWater Solutions
7
#
8
# This file is part of Koha.
9
#
10
# Koha is free software; you can redistribute it and/or modify it under the
11
# terms of the GNU General Public License as published by the Free Software
12
# Foundation; either version 2 of the License, or (at your option) any later
13
# version.
14
#
15
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
16
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
17
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
18
#
19
# You should have received a copy of the GNU General Public License along
20
# with Koha; if not, write to the Free Software Foundation, Inc.,
21
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22
23
=head1 account_payment.pl
24
25
 written 11/1/2000 by chris@katipo.oc.nz
26
 part of the koha library system, script to facilitate paying off fines
27
28
=cut
29
30
use Modern::Perl;
31
32
use CGI;
33
34
use URI::Escape;
35
36
use C4::Context;
37
use C4::Auth;
38
use C4::Output;
39
use C4::Members;
40
use C4::Accounts;
41
use C4::Stats;
42
use C4::Koha;
43
use C4::Overdues;
44
use C4::Branch;
45
use C4::Members::Attributes qw(GetBorrowerAttributes);
46
use Koha::Database;
47
48
our $cgi = CGI->new;
49
50
our ( $template, $loggedinuser, $cookie ) = get_template_and_user(
51
    {
52
        template_name   => 'members/account_payment.tt',
53
        query           => $cgi,
54
        type            => 'intranet',
55
        authnotrequired => 0,
56
        flagsrequired   => { borrowers => 1, updatecharges => 1 },
57
        debug           => 1,
58
    }
59
);
60
61
my $borrowernumber = $cgi->param('borrowernumber');
62
63
my $borrower = GetMember( borrowernumber => $borrowernumber );
64
65
my @debits = Koha::Database->new()->schema->resultset('AccountDebit')->search(
66
    {
67
        'me.borrowernumber' => $borrowernumber,
68
        amount_outstanding  => { '>' => 0 }
69
    }
70
);
71
72
$template->param(
73
    debits   => \@debits,
74
    borrower => $borrower,
75
);
76
77
# Standard /members/ borrower details data
78
## FIXME: This code is in every /members/ script and should be unified
79
80
if ( $borrower->{'category_type'} eq 'C' ) {
81
    my ( $catcodes, $labels ) =
82
      GetborCatFromCatType( 'A', 'WHERE category_type = ?' );
83
    my $cnt = scalar(@$catcodes);
84
    $template->param( 'CATCODE_MULTI' => 1 ) if $cnt > 1;
85
    $template->param( 'catcode' => $catcodes->[0] ) if $cnt == 1;
86
}
87
88
my ( $picture, $dberror ) = GetPatronImage( $borrower->{'borrowernumber'} );
89
$template->param( picture => 1 ) if $picture;
90
91
if ( C4::Context->preference('ExtendedPatronAttributes') ) {
92
    my $attributes = GetBorrowerAttributes($borrowernumber);
93
    $template->param(
94
        ExtendedPatronAttributes => 1,
95
        extendedattributes       => $attributes
96
    );
97
}
98
99
$template->param(
100
    borrowernumber => $borrowernumber,
101
    firstname      => $borrower->{'firstname'},
102
    surname        => $borrower->{'surname'},
103
    cardnumber     => $borrower->{'cardnumber'},
104
    categorycode   => $borrower->{'categorycode'},
105
    category_type  => $borrower->{'category_type'},
106
    categoryname   => $borrower->{'description'},
107
    address        => $borrower->{'address'},
108
    address2       => $borrower->{'address2'},
109
    city           => $borrower->{'city'},
110
    state          => $borrower->{'state'},
111
    zipcode        => $borrower->{'zipcode'},
112
    country        => $borrower->{'country'},
113
    phone          => $borrower->{'phone'},
114
    email          => $borrower->{'email'},
115
    branchcode     => $borrower->{'branchcode'},
116
    branchname     => GetBranchName( $borrower->{'branchcode'} ),
117
    is_child       => ( $borrower->{'category_type'} eq 'C' ),
118
    activeBorrowerRelationship =>
119
      ( C4::Context->preference('borrowerRelationship') ne '' ),
120
    RoutingSerials => C4::Context->preference('RoutingSerials'),
121
);
122
123
output_html_with_http_headers $cgi, $cookie, $template->output;
(-)a/members/account_payment_do.pl (+62 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# Copyright 2000-2002 Katipo Communications
4
# Copyright 2010 BibLibre
5
# Copyright 2013 ByWater Solutions
6
#
7
# This file is part of Koha.
8
#
9
# Koha is free software; you can redistribute it and/or modify it under the
10
# terms of the GNU General Public License as published by the Free Software
11
# Foundation; either version 2 of the License, or (at your option) any later
12
# version.
13
#
14
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
15
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
17
#
18
# You should have received a copy of the GNU General Public License along
19
# with Koha; if not, write to the Free Software Foundation, Inc.,
20
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
22
use Modern::Perl;
23
24
use CGI;
25
26
use C4::Auth;
27
use C4::Members;
28
use C4::Items;
29
use C4::Branch;
30
use C4::Members::Attributes qw(GetBorrowerAttributes);
31
use Koha::Accounts;
32
use Koha::Database;
33
34
my $cgi = new CGI;
35
36
if ( checkauth( $cgi, 0, { borrowers => 1 }, 'intranet' ) ) {
37
    my $borrowernumber = $cgi->param('borrowernumber');
38
39
    my $borrower =
40
      Koha::Database->new()->schema->resultset('Borrower')
41
      ->find($borrowernumber);
42
43
    my $amount_to_pay   = $cgi->param('amount_to_pay');
44
    my $amount_received = $cgi->param('amount_received');
45
    my $type            = $cgi->param('type');
46
    my $notes           = $cgi->param('notes');
47
    my @debit_id        = $cgi->param('debit_id');
48
49
    my $debit = AddCredit(
50
        {
51
            borrower => $borrower,
52
            amount   => $amount_to_pay,
53
            type     => $type,
54
            notes    => $notes,
55
            debit_id => \@debit_id,
56
57
        }
58
    );
59
60
    print $cgi->redirect(
61
        "/cgi-bin/koha/members/account.pl?borrowernumber=$borrowernumber");
62
}
(-)a/members/account_print.pl (+58 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# This file is part of Koha.
4
#
5
# Koha is free software; you can redistribute it and/or modify it under the
6
# terms of the GNU General Public License as published by the Free Software
7
# Foundation; either version 2 of the License, or (at your option) any later
8
# version.
9
#
10
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
11
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License along
15
# with Koha; if not, write to the Free Software Foundation, Inc.,
16
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
18
use Modern::Perl;
19
20
use CGI;
21
22
use C4::Auth;
23
use C4::Output;
24
use Koha::Database;
25
26
my $cgi = new CGI;
27
28
my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
29
    {
30
        template_name   => "members/account_print.tt",
31
        query           => $cgi,
32
        type            => "intranet",
33
        authnotrequired => 0,
34
        flagsrequired   => { borrowers => 1, updatecharges => 1 },
35
        debug           => 1,
36
    }
37
);
38
39
my $type = $cgi->param('type');
40
my $id   = $cgi->param('id');
41
42
warn "No type passed in!" unless $type;
43
warn "No id passed in!"   unless $id;
44
45
if ( $type eq 'debit' ) {
46
    my $debit =
47
      Koha::Database->new()->schema->resultset('AccountDebit')->find($id);
48
    $template->param( debit => $debit );
49
}
50
elsif ( $type eq 'credit' ) {
51
    my $credit =
52
      Koha::Database->new()->schema->resultset('AccountCredit')->find($id);
53
    $template->param( credit => $credit );
54
}
55
56
$template->param( type => $type );
57
58
output_html_with_http_headers $cgi, $cookie, $template->output;
(-)a/members/boraccount.pl (-135 lines)
Lines 1-135 Link Here
1
#!/usr/bin/perl
2
3
4
#writen 11/1/2000 by chris@katipo.oc.nz
5
#script to display borrowers account details
6
7
8
# Copyright 2000-2002 Katipo Communications
9
#
10
# This file is part of Koha.
11
#
12
# Koha is free software; you can redistribute it and/or modify it under the
13
# terms of the GNU General Public License as published by the Free Software
14
# Foundation; either version 2 of the License, or (at your option) any later
15
# version.
16
#
17
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
18
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
19
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
20
#
21
# You should have received a copy of the GNU General Public License along
22
# with Koha; if not, write to the Free Software Foundation, Inc.,
23
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24
25
use strict;
26
use warnings;
27
28
use C4::Auth;
29
use C4::Output;
30
use C4::Dates qw/format_date/;
31
use CGI;
32
use C4::Members;
33
use C4::Branch;
34
use C4::Accounts;
35
use C4::Members::Attributes qw(GetBorrowerAttributes);
36
37
my $input=new CGI;
38
39
40
my ($template, $loggedinuser, $cookie)
41
    = get_template_and_user({template_name => "members/boraccount.tmpl",
42
                            query => $input,
43
                            type => "intranet",
44
                            authnotrequired => 0,
45
                            flagsrequired => {borrowers => 1, updatecharges => 1},
46
                            debug => 1,
47
                            });
48
49
my $borrowernumber=$input->param('borrowernumber');
50
my $action = $input->param('action') || '';
51
52
#get borrower details
53
my $data=GetMember('borrowernumber' => $borrowernumber);
54
55
if ( $action eq 'reverse' ) {
56
  ReversePayment( $input->param('accountlines_id') );
57
}
58
59
if ( $data->{'category_type'} eq 'C') {
60
   my  ( $catcodes, $labels ) =  GetborCatFromCatType( 'A', 'WHERE category_type = ?' );
61
   my $cnt = scalar(@$catcodes);
62
   $template->param( 'CATCODE_MULTI' => 1) if $cnt > 1;
63
   $template->param( 'catcode' =>    $catcodes->[0])  if $cnt == 1;
64
}
65
66
#get account details
67
my ($total,$accts,undef)=GetMemberAccountRecords($borrowernumber);
68
my $totalcredit;
69
if($total <= 0){
70
        $totalcredit = 1;
71
}
72
73
my $reverse_col = 0; # Flag whether we need to show the reverse column
74
foreach my $accountline ( @{$accts}) {
75
    $accountline->{amount} += 0.00;
76
    if ($accountline->{amount} <= 0 ) {
77
        $accountline->{amountcredit} = 1;
78
    }
79
    $accountline->{amountoutstanding} += 0.00;
80
    if ( $accountline->{amountoutstanding} <= 0 ) {
81
        $accountline->{amountoutstandingcredit} = 1;
82
    }
83
84
    $accountline->{date} = format_date($accountline->{date});
85
    $accountline->{amount} = sprintf '%.2f', $accountline->{amount};
86
    $accountline->{amountoutstanding} = sprintf '%.2f', $accountline->{amountoutstanding};
87
    if ($accountline->{accounttype} eq 'Pay') {
88
        $accountline->{payment} = 1;
89
        $reverse_col = 1;
90
    }
91
}
92
93
$template->param( adultborrower => 1 ) if ( $data->{'category_type'} eq 'A' );
94
95
my ($picture, $dberror) = GetPatronImage($data->{'borrowernumber'});
96
$template->param( picture => 1 ) if $picture;
97
98
if (C4::Context->preference('ExtendedPatronAttributes')) {
99
    my $attributes = GetBorrowerAttributes($borrowernumber);
100
    $template->param(
101
        ExtendedPatronAttributes => 1,
102
        extendedattributes => $attributes
103
    );
104
}
105
106
$template->param(
107
    finesview           => 1,
108
    firstname           => $data->{'firstname'},
109
    surname             => $data->{'surname'},
110
    othernames          => $data->{'othernames'},
111
    borrowernumber      => $borrowernumber,
112
    cardnumber          => $data->{'cardnumber'},
113
    categorycode        => $data->{'categorycode'},
114
    category_type       => $data->{'category_type'},
115
    categoryname		=> $data->{'description'},
116
    address             => $data->{'address'},
117
    address2            => $data->{'address2'},
118
    city                => $data->{'city'},
119
    state               => $data->{'state'},
120
    zipcode             => $data->{'zipcode'},
121
    country             => $data->{'country'},
122
    phone               => $data->{'phone'},
123
    email               => $data->{'email'},
124
    branchcode          => $data->{'branchcode'},
125
	branchname			=> GetBranchName($data->{'branchcode'}),
126
    total               => sprintf("%.2f",$total),
127
    totalcredit         => $totalcredit,
128
    is_child            => ($data->{'category_type'} eq 'C'),
129
    reverse_col         => $reverse_col,
130
    accounts            => $accts,
131
	activeBorrowerRelationship => (C4::Context->preference('borrowerRelationship') ne ''),
132
    RoutingSerials => C4::Context->preference('RoutingSerials'),
133
);
134
135
output_html_with_http_headers $input, $cookie, $template->output;
(-)a/members/mancredit.pl (-114 lines)
Lines 1-114 Link Here
1
#!/usr/bin/perl
2
3
#written 11/1/2000 by chris@katipo.oc.nz
4
#script to display borrowers account details
5
6
7
# Copyright 2000-2002 Katipo Communications
8
# Copyright 2010 BibLibre
9
#
10
# This file is part of Koha.
11
#
12
# Koha is free software; you can redistribute it and/or modify it under the
13
# terms of the GNU General Public License as published by the Free Software
14
# Foundation; either version 2 of the License, or (at your option) any later
15
# version.
16
#
17
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
18
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
19
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
20
#
21
# You should have received a copy of the GNU General Public License along
22
# with Koha; if not, write to the Free Software Foundation, Inc.,
23
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24
25
use strict;
26
use warnings;
27
28
use C4::Auth;
29
use C4::Output;
30
use CGI;
31
32
use C4::Members;
33
use C4::Branch;
34
use C4::Accounts;
35
use C4::Items;
36
use C4::Members::Attributes qw(GetBorrowerAttributes);
37
38
my $input=new CGI;
39
my $flagsrequired = { borrowers => 1, updatecharges => 1 };
40
41
my $borrowernumber=$input->param('borrowernumber');
42
43
#get borrower details
44
my $data=GetMember('borrowernumber' => $borrowernumber);
45
my $add=$input->param('add');
46
47
if ($add){
48
    if ( checkauth( $input, 0, $flagsrequired, 'intranet' ) ) {
49
        my $barcode = $input->param('barcode');
50
        my $itemnum;
51
        if ($barcode) {
52
            $itemnum = GetItemnumberFromBarcode($barcode);
53
        }
54
        my $desc    = $input->param('desc');
55
        my $note    = $input->param('note');
56
        my $amount  = $input->param('amount') || 0;
57
        $amount = -$amount;
58
        my $type = $input->param('type');
59
        manualinvoice( $borrowernumber, $itemnum, $desc, $type, $amount, $note );
60
        print $input->redirect("/cgi-bin/koha/members/boraccount.pl?borrowernumber=$borrowernumber");
61
    }
62
} else {
63
	my ($template, $loggedinuser, $cookie)
64
	  = get_template_and_user({template_name => "members/mancredit.tmpl",
65
					  query => $input,
66
					  type => "intranet",
67
					  authnotrequired => 0,
68
                      flagsrequired => $flagsrequired,
69
					  debug => 1,
70
					  });
71
					  
72
    if ( $data->{'category_type'} eq 'C') {
73
        my  ( $catcodes, $labels ) =  GetborCatFromCatType( 'A', 'WHERE category_type = ?' );
74
        my $cnt = scalar(@$catcodes);
75
        $template->param( 'CATCODE_MULTI' => 1) if $cnt > 1;
76
        $template->param( 'catcode' =>    $catcodes->[0])  if $cnt == 1;
77
    }
78
79
    $template->param( adultborrower => 1 ) if ( $data->{category_type} eq 'A' );
80
    my ($picture, $dberror) = GetPatronImage($data->{'borrowernumber'});
81
    $template->param( picture => 1 ) if $picture;
82
83
if (C4::Context->preference('ExtendedPatronAttributes')) {
84
    my $attributes = GetBorrowerAttributes($borrowernumber);
85
    $template->param(
86
        ExtendedPatronAttributes => 1,
87
        extendedattributes => $attributes
88
    );
89
}
90
    
91
    $template->param(
92
        borrowernumber => $borrowernumber,
93
        firstname => $data->{'firstname'},
94
        surname  => $data->{'surname'},
95
		    cardnumber => $data->{'cardnumber'},
96
		    categorycode => $data->{'categorycode'},
97
		    category_type => $data->{'category_type'},
98
		    categoryname  => $data->{'description'},
99
		    address => $data->{'address'},
100
		    address2 => $data->{'address2'},
101
		    city => $data->{'city'},
102
		    state => $data->{'state'},
103
		    zipcode => $data->{'zipcode'},
104
		    country => $data->{'country'},
105
		    phone => $data->{'phone'},
106
		    email => $data->{'email'},
107
		    branchcode => $data->{'branchcode'},
108
		    branchname => GetBranchName($data->{'branchcode'}),
109
		    is_child        => ($data->{'category_type'} eq 'C'),
110
			activeBorrowerRelationship => (C4::Context->preference('borrowerRelationship') ne ''),
111
            RoutingSerials => C4::Context->preference('RoutingSerials'),
112
        );
113
    output_html_with_http_headers $input, $cookie, $template->output;
114
}
(-)a/members/maninvoice.pl (-141 lines)
Lines 1-141 Link Here
1
#!/usr/bin/perl
2
3
#written 11/1/2000 by chris@katipo.oc.nz
4
#script to display borrowers account details
5
6
7
# Copyright 2000-2002 Katipo Communications
8
# Copyright 2010 BibLibre
9
#
10
# This file is part of Koha.
11
#
12
# Koha is free software; you can redistribute it and/or modify it under the
13
# terms of the GNU General Public License as published by the Free Software
14
# Foundation; either version 2 of the License, or (at your option) any later
15
# version.
16
#
17
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
18
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
19
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
20
#
21
# You should have received a copy of the GNU General Public License along
22
# with Koha; if not, write to the Free Software Foundation, Inc.,
23
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24
25
use strict;
26
use warnings;
27
28
use C4::Auth;
29
use C4::Output;
30
use CGI;
31
use C4::Members;
32
use C4::Accounts;
33
use C4::Items;
34
use C4::Branch;
35
use C4::Members::Attributes qw(GetBorrowerAttributes);
36
37
my $input=new CGI;
38
my $flagsrequired = { borrowers => 1 };
39
40
my $borrowernumber=$input->param('borrowernumber');
41
42
43
# get borrower details
44
my $data=GetMember('borrowernumber'=>$borrowernumber);
45
my $add=$input->param('add');
46
if ($add){
47
    if ( checkauth( $input, 0, $flagsrequired, 'intranet' ) ) {
48
        #  print $input->header;
49
        my $barcode=$input->param('barcode');
50
        my $itemnum;
51
        if ($barcode) {
52
            $itemnum = GetItemnumberFromBarcode($barcode);
53
        }
54
        my $desc=$input->param('desc');
55
        my $amount=$input->param('amount');
56
        my $type=$input->param('type');
57
        my $note    = $input->param('note');
58
        my $error   = manualinvoice( $borrowernumber, $itemnum, $desc, $type, $amount, $note );
59
        if ($error) {
60
            my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
61
                {   template_name   => "members/maninvoice.tmpl",
62
                    query           => $input,
63
                    type            => "intranet",
64
                    authnotrequired => 0,
65
                    flagsrequired   => $flagsrequired,
66
                    debug           => 1,
67
                }
68
            );
69
            if ( $error =~ /FOREIGN KEY/ && $error =~ /itemnumber/ ) {
70
                $template->param( 'ITEMNUMBER' => 1 );
71
            }
72
            $template->param( 'ERROR' => $error );
73
            output_html_with_http_headers $input, $cookie, $template->output;
74
        } else {
75
            print $input->redirect("/cgi-bin/koha/members/boraccount.pl?borrowernumber=$borrowernumber");
76
            exit;
77
        }
78
    }
79
} else {
80
81
	my ($template, $loggedinuser, $cookie)
82
	= get_template_and_user({template_name => "members/maninvoice.tmpl",
83
					query => $input,
84
					type => "intranet",
85
					authnotrequired => 0,
86
					flagsrequired => {borrowers => 1, updatecharges => 1},
87
					debug => 1,
88
					});
89
					
90
  # get authorised values with type of MANUAL_INV
91
  my @invoice_types;
92
  my $dbh = C4::Context->dbh;
93
  my $sth = $dbh->prepare('SELECT * FROM authorised_values WHERE category = "MANUAL_INV"');
94
  $sth->execute();
95
  while ( my $row = $sth->fetchrow_hashref() ) {
96
    push @invoice_types, $row;
97
  }
98
  $template->param( invoice_types_loop => \@invoice_types );
99
100
    if ( $data->{'category_type'} eq 'C') {
101
        my  ( $catcodes, $labels ) =  GetborCatFromCatType( 'A', 'WHERE category_type = ?' );
102
        my $cnt = scalar(@$catcodes);
103
        $template->param( 'CATCODE_MULTI' => 1) if $cnt > 1;
104
        $template->param( 'catcode' =>    $catcodes->[0])  if $cnt == 1;
105
    }
106
107
    $template->param( adultborrower => 1 ) if ( $data->{'category_type'} eq 'A' );
108
    my ($picture, $dberror) = GetPatronImage($data->{'borrowernumber'});
109
    $template->param( picture => 1 ) if $picture;
110
111
if (C4::Context->preference('ExtendedPatronAttributes')) {
112
    my $attributes = GetBorrowerAttributes($borrowernumber);
113
    $template->param(
114
        ExtendedPatronAttributes => 1,
115
        extendedattributes => $attributes
116
    );
117
}
118
	$template->param(
119
                borrowernumber => $borrowernumber,
120
		firstname => $data->{'firstname'},
121
                surname  => $data->{'surname'},
122
		cardnumber => $data->{'cardnumber'},
123
		categorycode => $data->{'categorycode'},
124
		category_type => $data->{'category_type'},
125
		categoryname  => $data->{'description'},
126
		address => $data->{'address'},
127
		address2 => $data->{'address2'},
128
		city => $data->{'city'},
129
		state => $data->{'state'},
130
		zipcode => $data->{'zipcode'},
131
		country => $data->{'country'},
132
		phone => $data->{'phone'},
133
		email => $data->{'email'},
134
		branchcode => $data->{'branchcode'},
135
		branchname => GetBranchName($data->{'branchcode'}),
136
		is_child        => ($data->{'category_type'} eq 'C'),
137
		activeBorrowerRelationship => (C4::Context->preference('borrowerRelationship') ne ''),
138
        RoutingSerials => C4::Context->preference('RoutingSerials'),
139
    );
140
    output_html_with_http_headers $input, $cookie, $template->output;
141
}
(-)a/members/moremember.pl (-3 / +2 lines)
Lines 223-229 if ( C4::Context->preference("IndependentBranches") ) { Link Here
223
my $branchdetail = GetBranchDetail( $data->{'branchcode'});
223
my $branchdetail = GetBranchDetail( $data->{'branchcode'});
224
@{$data}{keys %$branchdetail} = values %$branchdetail; # merge in all branch columns
224
@{$data}{keys %$branchdetail} = values %$branchdetail; # merge in all branch columns
225
225
226
my ( $total, $accts, $numaccts) = GetMemberAccountRecords( $borrowernumber );
227
my $lib1 = &GetSortDetails( "Bsort1", $data->{'sort1'} );
226
my $lib1 = &GetSortDetails( "Bsort1", $data->{'sort1'} );
228
my $lib2 = &GetSortDetails( "Bsort2", $data->{'sort2'} );
227
my $lib2 = &GetSortDetails( "Bsort2", $data->{'sort2'} );
229
$template->param( lib1 => $lib1 ) if ($lib1);
228
$template->param( lib1 => $lib1 ) if ($lib1);
Lines 414-421 $template->param( Link Here
414
    branch          => $branch,
413
    branch          => $branch,
415
    todaysdate      => C4::Dates->today(),
414
    todaysdate      => C4::Dates->today(),
416
    totalprice      => sprintf("%.2f", $totalprice),
415
    totalprice      => sprintf("%.2f", $totalprice),
417
    totaldue        => sprintf("%.2f", $total),
416
    totaldue        => sprintf("%.2f", $data->{account_balance}),
418
    totaldue_raw    => $total,
417
    totaldue_raw    => $data->{account_balance},
419
    issueloop       => @issuedata,
418
    issueloop       => @issuedata,
420
    relissueloop    => @relissuedata,
419
    relissueloop    => @relissuedata,
421
    overdues_exist  => $overdues_exist,
420
    overdues_exist  => $overdues_exist,
(-)a/members/pay.pl (-261 lines)
Lines 1-261 Link Here
1
#!/usr/bin/perl
2
3
# Copyright 2000-2002 Katipo Communications
4
# Copyright 2010 BibLibre
5
# Copyright 2010,2011 PTFS-Europe Ltd
6
#
7
# This file is part of Koha.
8
#
9
# Koha is free software; you can redistribute it and/or modify it under the
10
# terms of the GNU General Public License as published by the Free Software
11
# Foundation; either version 2 of the License, or (at your option) any later
12
# version.
13
#
14
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
15
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
17
#
18
# You should have received a copy of the GNU General Public License along
19
# with Koha; if not, write to the Free Software Foundation, Inc.,
20
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
22
=head1 pay.pl
23
24
 written 11/1/2000 by chris@katipo.oc.nz
25
 part of the koha library system, script to facilitate paying off fines
26
27
=cut
28
29
use strict;
30
use warnings;
31
32
use URI::Escape;
33
use C4::Context;
34
use C4::Auth;
35
use C4::Output;
36
use CGI;
37
use C4::Members;
38
use C4::Accounts;
39
use C4::Stats;
40
use C4::Koha;
41
use C4::Overdues;
42
use C4::Branch;
43
use C4::Members::Attributes qw(GetBorrowerAttributes);
44
45
our $input = CGI->new;
46
47
our ( $template, $loggedinuser, $cookie ) = get_template_and_user(
48
    {   template_name   => 'members/pay.tmpl',
49
        query           => $input,
50
        type            => 'intranet',
51
        authnotrequired => 0,
52
        flagsrequired   => { borrowers => 1, updatecharges => 1 },
53
        debug           => 1,
54
    }
55
);
56
57
my @names = $input->param;
58
59
our $borrowernumber = $input->param('borrowernumber');
60
if ( !$borrowernumber ) {
61
    $borrowernumber = $input->param('borrowernumber0');
62
}
63
64
# get borrower details
65
our $borrower = GetMember( borrowernumber => $borrowernumber );
66
our $user = $input->remote_user;
67
$user ||= q{};
68
69
my $branches = GetBranches();
70
our $branch = GetBranch( $input, $branches );
71
72
my $writeoff_item = $input->param('confirm_writeoff');
73
my $paycollect    = $input->param('paycollect');
74
if ($paycollect) {
75
    print $input->redirect(
76
        "/cgi-bin/koha/members/paycollect.pl?borrowernumber=$borrowernumber");
77
}
78
my $payselected = $input->param('payselected');
79
if ($payselected) {
80
    payselected(@names);
81
}
82
83
my $writeoff_all = $input->param('woall');    # writeoff all fines
84
if ($writeoff_all) {
85
    writeoff_all(@names);
86
} elsif ($writeoff_item) {
87
    my $accountlines_id = $input->param('accountlines_id');
88
    my $itemno       = $input->param('itemnumber');
89
    my $account_type = $input->param('accounttype');
90
    my $amount       = $input->param('amountoutstanding');
91
    my $payment_note = $input->param("payment_note");
92
    WriteOffFee( $borrowernumber, $accountlines_id, $itemno, $account_type, $amount, $branch, $payment_note );
93
}
94
95
for (@names) {
96
    if (/^pay_indiv_(\d+)$/) {
97
        my $line_no = $1;
98
        redirect_to_paycollect( 'pay_individual', $line_no );
99
    } elsif (/^wo_indiv_(\d+)$/) {
100
        my $line_no = $1;
101
        redirect_to_paycollect( 'writeoff_individual', $line_no );
102
    }
103
}
104
105
$template->param(
106
    activeBorrowerRelationship => (C4::Context->preference('borrowerRelationship') ne ''),
107
    RoutingSerials => C4::Context->preference('RoutingSerials'),
108
);
109
110
add_accounts_to_template();
111
112
output_html_with_http_headers $input, $cookie, $template->output;
113
114
sub add_accounts_to_template {
115
116
    my ( $total, undef, undef ) = GetMemberAccountRecords($borrowernumber);
117
    my $accounts = [];
118
    my @notify   = NumberNotifyId($borrowernumber);
119
120
    my $notify_groups = [];
121
    for my $notify_id (@notify) {
122
        my ( $acct_total, $accountlines, undef ) =
123
          GetBorNotifyAcctRecord( $borrowernumber, $notify_id );
124
        if ( @{$accountlines} ) {
125
            my $totalnotify = AmountNotify( $notify_id, $borrowernumber );
126
            push @{$accounts},
127
              { accountlines => $accountlines,
128
                notify       => $notify_id,
129
                total        => $totalnotify,
130
              };
131
        }
132
    }
133
    borrower_add_additional_fields($borrower);
134
    $template->param(
135
        accounts => $accounts,
136
        borrower => $borrower,
137
        total    => $total,
138
    );
139
    return;
140
141
}
142
143
sub get_for_redirect {
144
    my ( $name, $name_in, $money ) = @_;
145
    my $s     = q{&} . $name . q{=};
146
    my $value = $input->param($name_in);
147
    if ( !defined $value ) {
148
        $value = ( $money == 1 ) ? 0 : q{};
149
    }
150
    if ($money) {
151
        $s .= sprintf '%.2f', $value;
152
    } else {
153
        $s .= $value;
154
    }
155
    return $s;
156
}
157
158
sub redirect_to_paycollect {
159
    my ( $action, $line_no ) = @_;
160
    my $redirect =
161
      "/cgi-bin/koha/members/paycollect.pl?borrowernumber=$borrowernumber";
162
    $redirect .= q{&};
163
    $redirect .= "$action=1";
164
    $redirect .= get_for_redirect( 'accounttype', "accounttype$line_no", 0 );
165
    $redirect .= get_for_redirect( 'amount', "amount$line_no", 1 );
166
    $redirect .=
167
      get_for_redirect( 'amountoutstanding', "amountoutstanding$line_no", 1 );
168
    $redirect .= get_for_redirect( 'accountno',    "accountno$line_no",    0 );
169
    $redirect .= get_for_redirect( 'title',        "title$line_no",        0 );
170
    $redirect .= get_for_redirect( 'itemnumber',   "itemnumber$line_no",   0 );
171
    $redirect .= get_for_redirect( 'notify_id',    "notify_id$line_no",    0 );
172
    $redirect .= get_for_redirect( 'notify_level', "notify_level$line_no", 0 );
173
    $redirect .= get_for_redirect( 'accountlines_id', "accountlines_id$line_no", 0 );
174
    $redirect .= q{&} . 'payment_note' . q{=} . uri_escape( $input->param("payment_note_$line_no") );
175
    $redirect .= '&remote_user=';
176
    $redirect .= $user;
177
    return print $input->redirect($redirect);
178
}
179
180
sub writeoff_all {
181
    my @params = @_;
182
    my @wo_lines = grep { /^accountno\d+$/ } @params;
183
    for (@wo_lines) {
184
        if (/(\d+)/) {
185
            my $value       = $1;
186
            my $accounttype = $input->param("accounttype$value");
187
188
            #    my $borrowernum    = $input->param("borrowernumber$value");
189
            my $itemno    = $input->param("itemnumber$value");
190
            my $amount    = $input->param("amountoutstanding$value");
191
            my $accountno = $input->param("accountno$value");
192
            my $accountlines_id = $input->param("accountlines_id$value");
193
            my $payment_note = $input->param("payment_note_$value");
194
            WriteOffFee( $borrowernumber, $accountlines_id, $itemno, $accounttype, $amount, $branch, $payment_note );
195
        }
196
    }
197
198
    $borrowernumber = $input->param('borrowernumber');
199
    print $input->redirect(
200
        "/cgi-bin/koha/members/boraccount.pl?borrowernumber=$borrowernumber");
201
    return;
202
}
203
204
sub borrower_add_additional_fields {
205
    my $b_ref = shift;
206
207
# some borrower info is not returned in the standard call despite being assumed
208
# in a number of templates. It should not be the business of this script but in lieu of
209
# a revised api here it is ...
210
    if ( $b_ref->{category_type} eq 'C' ) {
211
        my ( $catcodes, $labels ) =
212
          GetborCatFromCatType( 'A', 'WHERE category_type = ?' );
213
        if ( @{$catcodes} ) {
214
            if ( @{$catcodes} > 1 ) {
215
                $b_ref->{CATCODE_MULTI} = 1;
216
            } elsif ( @{$catcodes} == 1 ) {
217
                $b_ref->{catcode} = $catcodes->[0];
218
            }
219
        }
220
    } elsif ( $b_ref->{category_type} eq 'A' ) {
221
        $b_ref->{adultborrower} = 1;
222
    }
223
    my ( $picture, $dberror ) = GetPatronImage( $b_ref->{borrowernumber} );
224
    if ($picture) {
225
        $b_ref->{has_picture} = 1;
226
    }
227
228
    if (C4::Context->preference('ExtendedPatronAttributes')) {
229
        $b_ref->{extendedattributes} = GetBorrowerAttributes($borrowernumber);
230
        $template->param(
231
            ExtendedPatronAttributes => 1,
232
        );
233
    }
234
235
    $b_ref->{branchname} = GetBranchName( $b_ref->{branchcode} );
236
    return;
237
}
238
239
sub payselected {
240
    my @params = @_;
241
    my $amt    = 0;
242
    my @lines_to_pay;
243
    foreach (@params) {
244
        if (/^incl_par_(\d+)$/) {
245
            my $index = $1;
246
            push @lines_to_pay, $input->param("accountno$index");
247
            $amt += $input->param("amountoutstanding$index");
248
        }
249
    }
250
    $amt = '&amt=' . $amt;
251
    my $sel = '&selected=' . join ',', @lines_to_pay;
252
    my $notes = '&notes=' . join("%0A", map { $input->param("payment_note_$_") } @lines_to_pay );
253
    my $redirect =
254
        "/cgi-bin/koha/members/paycollect.pl?borrowernumber=$borrowernumber"
255
      . $amt
256
      . $sel
257
      . $notes;
258
259
    print $input->redirect($redirect);
260
    return;
261
}
(-)a/members/paycollect.pl (-179 lines)
Lines 1-179 Link Here
1
#!/usr/bin/perl
2
# Copyright 2009,2010 PTFS Inc.
3
# Copyright 2011 PTFS-Europe Ltd
4
#
5
# This file is part of Koha.
6
#
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.
11
#
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.
15
#
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.
19
20
use strict;
21
use warnings;
22
use URI::Escape;
23
use C4::Context;
24
use C4::Auth;
25
use C4::Output;
26
use CGI;
27
use C4::Members;
28
use C4::Accounts;
29
use C4::Koha;
30
use C4::Branch;
31
32
my $input = CGI->new();
33
34
my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
35
    {   template_name   => 'members/paycollect.tmpl',
36
        query           => $input,
37
        type            => 'intranet',
38
        authnotrequired => 0,
39
        flagsrequired   => { borrowers => 1, updatecharges => 1 },
40
        debug           => 1,
41
    }
42
);
43
44
# get borrower details
45
my $borrowernumber = $input->param('borrowernumber');
46
my $borrower       = GetMember( borrowernumber => $borrowernumber );
47
my $user           = $input->remote_user;
48
49
# get account details
50
my $branch = GetBranch( $input, GetBranches() );
51
52
my ( $total_due, $accts, $numaccts ) = GetMemberAccountRecords($borrowernumber);
53
my $total_paid = $input->param('paid');
54
55
my $individual   = $input->param('pay_individual');
56
my $writeoff     = $input->param('writeoff_individual');
57
my $select_lines = $input->param('selected');
58
my $select       = $input->param('selected_accts');
59
my $payment_note = uri_unescape $input->param('payment_note');
60
my $accountno;
61
my $accountlines_id;
62
if ( $individual || $writeoff ) {
63
    if ($individual) {
64
        $template->param( pay_individual => 1 );
65
    } elsif ($writeoff) {
66
        $template->param( writeoff_individual => 1 );
67
    }
68
    my $accounttype       = $input->param('accounttype');
69
    $accountlines_id       = $input->param('accountlines_id');
70
    my $amount            = $input->param('amount');
71
    my $amountoutstanding = $input->param('amountoutstanding');
72
    $accountno = $input->param('accountno');
73
    my $itemnumber  = $input->param('itemnumber');
74
    my $description  = $input->param('description');
75
    my $title        = $input->param('title');
76
    my $notify_id    = $input->param('notify_id');
77
    my $notify_level = $input->param('notify_level');
78
    $total_due = $amountoutstanding;
79
    $template->param(
80
        accounttype       => $accounttype,
81
        accountlines_id    => $accountlines_id,
82
        accountno         => $accountno,
83
        amount            => $amount,
84
        amountoutstanding => $amountoutstanding,
85
        title             => $title,
86
        itemnumber        => $itemnumber,
87
        description       => $description,
88
        notify_id         => $notify_id,
89
        notify_level      => $notify_level,
90
        payment_note    => $payment_note,
91
    );
92
} elsif ($select_lines) {
93
    $total_due = $input->param('amt');
94
    $template->param(
95
        selected_accts => $select_lines,
96
        amt            => $total_due,
97
        selected_accts_notes => $input->param('notes'),
98
    );
99
}
100
101
if ( $total_paid and $total_paid ne '0.00' ) {
102
    if ( $total_paid < 0 or $total_paid > $total_due ) {
103
        $template->param(
104
            error_over => 1,
105
            total_due => $total_due
106
        );
107
    } else {
108
        if ($individual) {
109
            if ( $total_paid == $total_due ) {
110
                makepayment( $accountlines_id, $borrowernumber, $accountno, $total_paid, $user,
111
                    $branch, $payment_note );
112
            } else {
113
                makepartialpayment( $accountlines_id, $borrowernumber, $accountno, $total_paid,
114
                    $user, $branch, $payment_note );
115
            }
116
            print $input->redirect(
117
                "/cgi-bin/koha/members/pay.pl?borrowernumber=$borrowernumber");
118
        } else {
119
            if ($select) {
120
                if ( $select =~ /^([\d,]*).*/ ) {
121
                    $select = $1;    # ensure passing no junk
122
                }
123
                my @acc = split /,/, $select;
124
                my $note = $input->param('selected_accts_notes');
125
                recordpayment_selectaccts( $borrowernumber, $total_paid, \@acc, $note );
126
            } else {
127
                recordpayment( $borrowernumber, $total_paid );
128
            }
129
130
# recordpayment does not return success or failure so lets redisplay the boraccount
131
132
            print $input->redirect(
133
"/cgi-bin/koha/members/boraccount.pl?borrowernumber=$borrowernumber"
134
            );
135
        }
136
    }
137
} else {
138
    $total_paid = '0.00';    #TODO not right with pay_individual
139
}
140
141
borrower_add_additional_fields($borrower);
142
143
$template->param(
144
    borrowernumber => $borrowernumber,    # some templates require global
145
    borrower      => $borrower,
146
    total         => $total_due,
147
    activeBorrowerRelationship => (C4::Context->preference('borrowerRelationship') ne ''),
148
    RoutingSerials => C4::Context->preference('RoutingSerials'),
149
);
150
151
output_html_with_http_headers $input, $cookie, $template->output;
152
153
sub borrower_add_additional_fields {
154
    my $b_ref = shift;
155
156
# some borrower info is not returned in the standard call despite being assumed
157
# in a number of templates. It should not be the business of this script but in lieu of
158
# a revised api here it is ...
159
    if ( $b_ref->{category_type} eq 'C' ) {
160
        my ( $catcodes, $labels ) =
161
          GetborCatFromCatType( 'A', 'WHERE category_type = ?' );
162
        if ( @{$catcodes} ) {
163
            if ( @{$catcodes} > 1 ) {
164
                $b_ref->{CATCODE_MULTI} = 1;
165
            } elsif ( @{$catcodes} == 1 ) {
166
                $b_ref->{catcode} = $catcodes->[0];
167
            }
168
        }
169
    } elsif ( $b_ref->{category_type} eq 'A' ) {
170
        $b_ref->{adultborrower} = 1;
171
    }
172
    my ( $picture, $dberror ) = GetPatronImage( $b_ref->{borrowernumber} );
173
    if ($picture) {
174
        $b_ref->{has_picture} = 1;
175
    }
176
177
    $b_ref->{branchname} = GetBranchName( $b_ref->{branchcode} );
178
    return;
179
}
(-)a/members/printfeercpt.pl (-143 lines)
Lines 1-143 Link Here
1
#!/usr/bin/perl
2
3
4
#writen 3rd May 2010 by kmkale@anantcorp.com adapted from boraccount.pl by chris@katipo.oc.nz
5
#script to print fee receipts
6
7
8
# Copyright Koustubha Kale
9
#
10
# This file is part of Koha.
11
#
12
# Koha is free software; you can redistribute it and/or modify it under the
13
# terms of the GNU General Public License as published by the Free Software
14
# Foundation; either version 2 of the License, or (at your option) any later
15
# version.
16
#
17
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
18
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
19
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
20
#
21
# You should have received a copy of the GNU General Public License along
22
# with Koha; if not, write to the Free Software Foundation, Inc.,
23
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24
25
use strict;
26
use warnings;
27
28
use C4::Auth;
29
use C4::Output;
30
use C4::Dates qw/format_date/;
31
use CGI;
32
use C4::Members;
33
use C4::Branch;
34
use C4::Accounts;
35
36
my $input=new CGI;
37
38
39
my ($template, $loggedinuser, $cookie)
40
    = get_template_and_user({template_name => "members/printfeercpt.tmpl",
41
                            query => $input,
42
                            type => "intranet",
43
                            authnotrequired => 0,
44
                            flagsrequired => {borrowers => 1, updatecharges => 1},
45
                            debug => 1,
46
                            });
47
48
my $borrowernumber=$input->param('borrowernumber');
49
my $action = $input->param('action') || '';
50
my $accountlines_id = $input->param('accountlines_id');
51
52
#get borrower details
53
my $data=GetMember('borrowernumber' => $borrowernumber);
54
55
if ( $action eq 'print' ) {
56
#  ReversePayment( $borrowernumber, $input->param('accountno') );
57
}
58
59
if ( $data->{'category_type'} eq 'C') {
60
   my  ( $catcodes, $labels ) =  GetborCatFromCatType( 'A', 'WHERE category_type = ?' );
61
   my $cnt = scalar(@$catcodes);
62
   $template->param( 'CATCODE_MULTI' => 1) if $cnt > 1;
63
   $template->param( 'catcode' =>    $catcodes->[0])  if $cnt == 1;
64
}
65
66
#get account details
67
my ($total,$accts,$numaccts)=GetMemberAccountRecords($borrowernumber);
68
my $totalcredit;
69
if($total <= 0){
70
        $totalcredit = 1;
71
}
72
my @accountrows; # this is for the tmpl-loop
73
74
my $toggle;
75
for (my $i=0;$i<$numaccts;$i++){
76
    next if ( $accts->[$i]{'accountlines_id'} ne $accountlines_id );
77
    if($i%2){
78
            $toggle = 0;
79
    } else {
80
            $toggle = 1;
81
    }
82
    $accts->[$i]{'toggle'} = $toggle;
83
    $accts->[$i]{'amount'}+=0.00;
84
    if($accts->[$i]{'amount'} <= 0){
85
        $accts->[$i]{'amountcredit'} = 1;
86
	$accts->[$i]{'amount'}*=-1.00;
87
    }
88
    $accts->[$i]{'amountoutstanding'}+=0.00;
89
    if($accts->[$i]{'amountoutstanding'} <= 0){
90
        $accts->[$i]{'amountoutstandingcredit'} = 1;
91
    }
92
    my %row = ( 'date'              => format_date($accts->[$i]{'date'}),
93
                'amountcredit' => $accts->[$i]{'amountcredit'},
94
                'amountoutstandingcredit' => $accts->[$i]{'amountoutstandingcredit'},
95
                'toggle' => $accts->[$i]{'toggle'},
96
                'description'       => $accts->[$i]{'description'},
97
				'itemnumber'       => $accts->[$i]{'itemnumber'},
98
				'biblionumber'       => $accts->[$i]{'biblionumber'},
99
                'amount'            => sprintf("%.2f",$accts->[$i]{'amount'}),
100
                'amountoutstanding' => sprintf("%.2f",$accts->[$i]{'amountoutstanding'}),
101
                'accountno' => $accts->[$i]{'accountno'},
102
                'payment' => ( $accts->[$i]{'accounttype'} eq 'Pay' ),
103
104
                );
105
106
    if ($accts->[$i]{'accounttype'} ne 'F' && $accts->[$i]{'accounttype'} ne 'FU'){
107
        $row{'printtitle'}=1;
108
        $row{'title'} = $accts->[$i]{'title'};
109
    }
110
111
    push(@accountrows, \%row);
112
}
113
114
$template->param( adultborrower => 1 ) if ( $data->{'category_type'} eq 'A' );
115
116
my ($picture, $dberror) = GetPatronImage($data->{'borrowernumber'});
117
$template->param( picture => 1 ) if $picture;
118
119
$template->param(
120
    finesview           => 1,
121
    firstname           => $data->{'firstname'},
122
    surname             => $data->{'surname'},
123
    borrowernumber      => $borrowernumber,
124
    cardnumber          => $data->{'cardnumber'},
125
    categorycode        => $data->{'categorycode'},
126
    category_type       => $data->{'category_type'},
127
 #   category_description => $data->{'description'},
128
    categoryname		 => $data->{'description'},
129
    address             => $data->{'address'},
130
    address2            => $data->{'address2'},
131
    city                => $data->{'city'},
132
    zipcode             => $data->{'zipcode'},
133
    country             => $data->{'country'},
134
    phone               => $data->{'phone'},
135
    email               => $data->{'email'},
136
    branchcode          => $data->{'branchcode'},
137
	branchname			=> GetBranchName($data->{'branchcode'}),
138
    total               => sprintf("%.2f",$total),
139
    totalcredit         => $totalcredit,
140
	is_child        => ($data->{'category_type'} eq 'C'),
141
    accounts            => \@accountrows );
142
143
output_html_with_http_headers $input, $cookie, $template->output;
(-)a/members/printinvoice.pl (-142 lines)
Lines 1-142 Link Here
1
#!/usr/bin/perl
2
3
#writen 3rd May 2010 by kmkale@anantcorp.com adapted from boraccount.pl by chris@katipo.oc.nz
4
#script to print fee receipts
5
6
# Copyright Koustubha Kale
7
#
8
# This file is part of Koha.
9
#
10
# Koha is free software; you can redistribute it and/or modify it under the
11
# terms of the GNU General Public License as published by the Free Software
12
# Foundation; either version 2 of the License, or (at your option) any later
13
# version.
14
#
15
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
16
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
17
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
18
#
19
# You should have received a copy of the GNU General Public License along
20
# with Koha; if not, write to the Free Software Foundation, Inc.,
21
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22
23
use strict;
24
use warnings;
25
26
use C4::Auth;
27
use C4::Output;
28
use C4::Dates qw/format_date/;
29
use CGI;
30
use C4::Members;
31
use C4::Branch;
32
use C4::Accounts;
33
34
my $input = new CGI;
35
36
my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
37
    {   template_name   => "members/printinvoice.tmpl",
38
        query           => $input,
39
        type            => "intranet",
40
        authnotrequired => 0,
41
        flagsrequired   => { borrowers => 1, updatecharges => 1 },
42
        debug           => 1,
43
    }
44
);
45
46
my $borrowernumber  = $input->param('borrowernumber');
47
my $action          = $input->param('action') || '';
48
my $accountlines_id = $input->param('accountlines_id');
49
50
#get borrower details
51
my $data = GetMember( 'borrowernumber' => $borrowernumber );
52
53
if ( $data->{'category_type'} eq 'C' ) {
54
    my ( $catcodes, $labels ) = GetborCatFromCatType( 'A', 'WHERE category_type = ?' );
55
    my $cnt = scalar(@$catcodes);
56
    $template->param( 'CATCODE_MULTI' => 1 ) if $cnt > 1;
57
    $template->param( 'catcode' => $catcodes->[0] ) if $cnt == 1;
58
}
59
60
#get account details
61
my ( $total, $accts, $numaccts ) = GetMemberAccountRecords($borrowernumber);
62
my $totalcredit;
63
if ( $total <= 0 ) {
64
    $totalcredit = 1;
65
}
66
67
my @accountrows;    # this is for the tmpl-loop
68
69
my $toggle;
70
for ( my $i = 0 ; $i < $numaccts ; $i++ ) {
71
    next if ( $accts->[$i]{'accountlines_id'} ne $accountlines_id );
72
73
    if ( $i % 2 ) {
74
        $toggle = 0;
75
    } else {
76
        $toggle = 1;
77
    }
78
79
    $accts->[$i]{'toggle'} = $toggle;
80
    $accts->[$i]{'amount'} += 0.00;
81
82
    if ( $accts->[$i]{'amount'} <= 0 ) {
83
        $accts->[$i]{'amountcredit'} = 1;
84
    }
85
86
    $accts->[$i]{'amountoutstanding'} += 0.00;
87
    if ( $accts->[$i]{'amountoutstanding'} <= 0 ) {
88
        $accts->[$i]{'amountoutstandingcredit'} = 1;
89
    }
90
91
    my %row = (
92
        'date'                    => format_date( $accts->[$i]{'date'} ),
93
        'amountcredit'            => $accts->[$i]{'amountcredit'},
94
        'amountoutstandingcredit' => $accts->[$i]{'amountoutstandingcredit'},
95
        'toggle'                  => $accts->[$i]{'toggle'},
96
        'description'             => $accts->[$i]{'description'},
97
        'itemnumber'              => $accts->[$i]{'itemnumber'},
98
        'biblionumber'            => $accts->[$i]{'biblionumber'},
99
        'amount'                  => sprintf( "%.2f", $accts->[$i]{'amount'} ),
100
        'amountoutstanding'       => sprintf( "%.2f", $accts->[$i]{'amountoutstanding'} ),
101
        'accountno'               => $accts->[$i]{'accountno'},
102
        'payment'                 => ( $accts->[$i]{'accounttype'} eq 'Pay' ),
103
    );
104
105
    if ( $accts->[$i]{'accounttype'} ne 'F' && $accts->[$i]{'accounttype'} ne 'FU' ) {
106
        $row{'printtitle'} = 1;
107
        $row{'title'}      = $accts->[$i]{'title'};
108
    }
109
110
    push( @accountrows, \%row );
111
}
112
113
$template->param( adultborrower => 1 ) if ( $data->{'category_type'} eq 'A' );
114
115
my ( $picture, $dberror ) = GetPatronImage( $data->{'borrowernumber'} );
116
$template->param( picture => 1 ) if $picture;
117
118
$template->param(
119
    finesview      => 1,
120
    firstname      => $data->{'firstname'},
121
    surname        => $data->{'surname'},
122
    borrowernumber => $borrowernumber,
123
    cardnumber     => $data->{'cardnumber'},
124
    categorycode   => $data->{'categorycode'},
125
    category_type  => $data->{'category_type'},
126
    categoryname   => $data->{'description'},
127
    address        => $data->{'address'},
128
    address2       => $data->{'address2'},
129
    city           => $data->{'city'},
130
    zipcode        => $data->{'zipcode'},
131
    country        => $data->{'country'},
132
    phone          => $data->{'phone'},
133
    email          => $data->{'email'},
134
    branchcode     => $data->{'branchcode'},
135
    branchname     => GetBranchName( $data->{'branchcode'} ),
136
    total          => sprintf( "%.2f", $total ),
137
    totalcredit    => $totalcredit,
138
    is_child       => ( $data->{'category_type'} eq 'C' ),
139
    accounts       => \@accountrows
140
);
141
142
output_html_with_http_headers $input, $cookie, $template->output;
(-)a/misc/cronjobs/create_koc_db.pl (-40 / +1 lines)
Lines 256-265 SELECT borrowernumber, Link Here
256
       city,
256
       city,
257
       phone,
257
       phone,
258
       dateofbirth,
258
       dateofbirth,
259
       sum( accountlines.amountoutstanding ) as total_fines
259
       account_balance as total_fines
260
FROM borrowers
260
FROM borrowers
261
LEFT JOIN accountlines USING (borrowernumber)
262
GROUP BY borrowernumber;
263
END_SQL
261
END_SQL
264
262
265
    my $fields_count = $sth_mysql->execute();
263
    my $fields_count = $sth_mysql->execute();
Lines 278-320 END_SQL Link Here
278
    }
276
    }
279
    $dbh_sqlite->commit();
277
    $dbh_sqlite->commit();
280
    print "inserted $count borrowers\n" if $verbose;
278
    print "inserted $count borrowers\n" if $verbose;
281
    # add_fines_to_borrowers_table();
282
}
283
284
=head2 add_fines_to_borrowers_table
285
286
Import the fines from koha.accountlines into the sqlite db
287
288
=cut
289
290
sub add_fines_to_borrowers_table {
291
292
    print "preparing to update borrowers\n" if $verbose;
293
    my $sth_mysql = $dbh_mysql->prepare(
294
        "SELECT DISTINCT borrowernumber, SUM( amountoutstanding ) AS total_fines
295
                                    FROM accountlines
296
                                    GROUP BY borrowernumber"
297
    );
298
    $sth_mysql->execute();
299
    my $count;
300
    while ( my $result = $sth_mysql->fetchrow_hashref() ) {
301
        $count++;
302
        if ( $verbose ) {
303
            print '.' unless ( $count % 10 );
304
            print "$count\n" unless ( $count % 1000 );
305
        }
306
307
        my $borrowernumber = $result->{'borrowernumber'};
308
        my $total_fines    = $result->{'total_fines'};
309
310
        # warn "Fines for Borrower # $borrowernumber are \$ $total_fines \n" if $verbose;
311
        my $sql = "UPDATE borrowers SET total_fines = ? WHERE borrowernumber = ?";
312
313
        my $sth_sqlite = $dbh_sqlite->prepare($sql);
314
        $sth_sqlite->execute( $total_fines, $borrowernumber );
315
        $sth_sqlite->finish();
316
    }
317
    print "updated $count borrowers\n" if ( $verbose && $count );
318
}
279
}
319
280
320
=head2 create_issue_table
281
=head2 create_issue_table
(-)a/misc/cronjobs/fines.pl (-3 / +7 lines)
Lines 127-135 for my $overdue ( @{$overdues} ) { Link Here
127
    if ( $mode eq 'production' && !$is_holiday{$branchcode} ) {
127
    if ( $mode eq 'production' && !$is_holiday{$branchcode} ) {
128
        if ( $amount > 0 ) {
128
        if ( $amount > 0 ) {
129
            UpdateFine(
129
            UpdateFine(
130
                $overdue->{itemnumber},
130
                {
131
                $overdue->{borrowernumber},
131
                    itemnumber     => $overdue->{itemnumber},
132
                $amount, $type, output_pref($datedue)
132
                    borrowernumber => $overdue->{borrowernumber},
133
                    amount         => $amount,
134
                    due            => output_pref($datedue),
135
                    issue_id       => $overdue->{issue_id}
136
                }
133
            );
137
            );
134
        }
138
        }
135
    }
139
    }
(-)a/misc/release_notes/release_notes_3_10_0.txt (-1 / +1 lines)
Lines 1762-1768 Staff Client Link Here
1762
	8996	normal	In result page items with negative notforloan are available
1762
	8996	normal	In result page items with negative notforloan are available
1763
	9017	normal	Quote of the day: Table footer not translated
1763
	9017	normal	Quote of the day: Table footer not translated
1764
	5312	minor	XHTML correction in authority summary
1764
	5312	minor	XHTML correction in authority summary
1765
	8009	minor	Item descriptive data not populated on pay.pl
1765
  8009	minor	Item descriptive data not populated on account_payment.pl
1766
	8593	minor	Add unique IDs to pending approval markup on staff client home page
1766
	8593	minor	Add unique IDs to pending approval markup on staff client home page
1767
	8646	minor	Certain search terms cause browser "script taking too long" error
1767
	8646	minor	Certain search terms cause browser "script taking too long" error
1768
	8793	minor	Fix materialTypeCode/typeOf008 icons for NORMARC XSLT
1768
	8793	minor	Fix materialTypeCode/typeOf008 icons for NORMARC XSLT
(-)a/misc/release_notes/release_notes_3_12_0.txt (-1 / +1 lines)
Lines 579-585 Architecture, internals, and plumbing Link Here
579
	8429	minor	Unnecessary use of Exporter in SIP/ILS objects
579
	8429	minor	Unnecessary use of Exporter in SIP/ILS objects
580
	9292	minor	Remove dead code related to 'publictype'
580
	9292	minor	Remove dead code related to 'publictype'
581
	9401	minor	Javascript used for tags handling wants access to CGISESSID cookie
581
	9401	minor	Javascript used for tags handling wants access to CGISESSID cookie
582
	9582	minor	Unused code in members/pay.pl
582
 9582	minor	Unused code in members/account_payment.pl
583
	10054	minor	When SingleBranchMode is enabled, allow superlibrarians to set logged in library
583
	10054	minor	When SingleBranchMode is enabled, allow superlibrarians to set logged in library
584
	10143	minor	Fix FSF address in license headers
584
	10143	minor	Fix FSF address in license headers
585
	9609	trivial	Rebuild zebra reports double numbers for exported records with -z option
585
	9609	trivial	Rebuild zebra reports double numbers for exported records with -z option
(-)a/opac/opac-account.pl (-34 / +14 lines)
Lines 18-24 Link Here
18
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# with Koha; if not, write to the Free Software Foundation, Inc.,
19
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
20
21
22
use strict;
21
use strict;
23
use CGI;
22
use CGI;
24
use C4::Members;
23
use C4::Members;
Lines 30-36 use warnings; Link Here
30
my $query = new CGI;
29
my $query = new CGI;
31
my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
30
my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
32
    {
31
    {
33
        template_name   => "opac-account.tmpl",
32
        template_name   => "opac-account.tt",
34
        query           => $query,
33
        query           => $query,
35
        type            => "opac",
34
        type            => "opac",
36
        authnotrequired => 0,
35
        authnotrequired => 0,
Lines 39-78 my ( $template, $borrowernumber, $cookie ) = get_template_and_user( Link Here
39
    }
38
    }
40
);
39
);
41
40
42
# get borrower information ....
41
my @debits = Koha::Database->new()->schema->resultset('AccountDebit')->search(
43
my $borr = GetMemberDetails( $borrowernumber );
42
    { 'me.borrowernumber' => $borrowernumber },
44
my @bordat;
43
    { prefetch            => { account_offsets => 'credit' } }
45
$bordat[0] = $borr;
44
);
46
47
$template->param( BORROWER_INFO => \@bordat );
48
49
#get account details
50
my ( $total , $accts, $numaccts) = GetMemberAccountRecords( $borrowernumber );
51
52
for ( my $i = 0 ; $i < $numaccts ; $i++ ) {
53
    $accts->[$i]{'amount'} = sprintf( "%.2f", $accts->[$i]{'amount'} || '0.00');
54
    if ( $accts->[$i]{'amount'} >= 0 ) {
55
        $accts->[$i]{'amountcredit'} = 1;
56
    }
57
    $accts->[$i]{'amountoutstanding'} =
58
      sprintf( "%.2f", $accts->[$i]{'amountoutstanding'} || '0.00' );
59
    if ( $accts->[$i]{'amountoutstanding'} >= 0 ) {
60
        $accts->[$i]{'amountoutstandingcredit'} = 1;
61
    }
62
}
63
45
64
# add the row parity
46
my @credits = Koha::Database->new()->schema->resultset('AccountCredit')->search(
65
my $num = 0;
47
    { 'me.borrowernumber' => $borrowernumber },
66
foreach my $row (@$accts) {
48
    { prefetch            => { account_offsets => 'debit' } }
67
    $row->{'even'} = 1 if $num % 2 == 0;
49
);
68
    $row->{'odd'}  = 1 if $num % 2 == 1;
69
    $num++;
70
}
71
50
72
$template->param (
51
$template->param(
73
    ACCOUNT_LINES => $accts,
52
    borrower    => GetMemberDetails($borrowernumber),
74
    total => sprintf( "%.2f", $total ),
53
    debits      => \@debits,
75
	accountview => 1
54
    credits     => \@credits,
55
    accountview => 1
76
);
56
);
77
57
78
output_html_with_http_headers $query, $cookie, $template->output;
58
output_html_with_http_headers $query, $cookie, $template->output;
(-)a/opac/opac-user.pl (-13 / +1 lines)
Lines 162-180 if ($issues){ Link Here
162
            $issue->{'reserved'} = 1;
162
            $issue->{'reserved'} = 1;
163
        }
163
        }
164
164
165
        my ( $total , $accts, $numaccts) = GetMemberAccountRecords( $borrowernumber );
165
        $issue->{'charges'} = $borr->{account_balance};
166
        my $charges = 0;
167
        foreach my $ac (@$accts) {
168
            if ( $ac->{'itemnumber'} == $issue->{'itemnumber'} ) {
169
                $charges += $ac->{'amountoutstanding'}
170
                  if $ac->{'accounttype'} eq 'F';
171
                $charges += $ac->{'amountoutstanding'}
172
                  if $ac->{'accounttype'} eq 'FU';
173
                $charges += $ac->{'amountoutstanding'}
174
                  if $ac->{'accounttype'} eq 'L';
175
            }
176
        }
177
        $issue->{'charges'} = $charges;
178
        $issue->{'subtitle'} = GetRecordValue('subtitle', GetMarcBiblio($issue->{'biblionumber'}), GetFrameworkCode($issue->{'biblionumber'}));
166
        $issue->{'subtitle'} = GetRecordValue('subtitle', GetMarcBiblio($issue->{'biblionumber'}), GetFrameworkCode($issue->{'biblionumber'}));
179
        # check if item is renewable
167
        # check if item is renewable
180
        my ($status,$renewerror) = CanBookBeRenewed( $borrowernumber, $issue->{'itemnumber'} );
168
        my ($status,$renewerror) = CanBookBeRenewed( $borrowernumber, $issue->{'itemnumber'} );
(-)a/t/db_dependent/Accounts.t (-3 / +186 lines)
Lines 1-16 Link Here
1
#!/usr/bin/perl
1
#!/usr/bin/perl
2
#
2
#
3
# This Koha test module is a stub!  
3
# This Koha test module is a stub!
4
# Add more tests here!!!
4
# Add more tests here!!!
5
5
6
use strict;
6
use strict;
7
use warnings;
7
use warnings;
8
8
9
use Test::More tests => 1;
9
use Test::More tests => 19;
10
11
use C4::Context;
10
12
11
BEGIN {
13
BEGIN {
12
        use_ok('C4::Accounts');
14
    use_ok('Koha::Database');
15
    use_ok('Koha::Accounts');
16
    use_ok('Koha::Accounts::DebitTypes');
17
    use_ok('Koha::Accounts::CreditTypes');
13
}
18
}
14
19
20
## Intial Setup ##
21
my $borrower = Koha::Database->new()->schema->resultset('Borrower')->create(
22
    {
23
        surname         => 'Test',
24
        categorycode    => 'S',
25
        branchcode      => 'MPL',
26
        account_balance => 0,
27
    }
28
);
29
30
my $biblio =
31
  Koha::Database->new()->schema->resultset('Biblio')
32
  ->create( { title => "Test Record" } );
33
my $biblioitem =
34
  Koha::Database->new()->schema->resultset('Biblioitem')
35
  ->create( { biblionumber => $biblio->biblionumber() } );
36
my $item = Koha::Database->new()->schema->resultset('Item')->create(
37
    {
38
        biblionumber     => $biblio->biblionumber(),
39
        biblioitemnumber => $biblioitem->biblioitemnumber(),
40
        replacementprice => 25.00,
41
        barcode          => q{TEST_ITEM_BARCODE}
42
    }
43
);
44
45
my $issue = Koha::Database->new()->schema->resultset('Issue')->create(
46
    {
47
        borrowernumber => $borrower->borrowernumber(),
48
        itemnumber     => $item->itemnumber(),
49
    }
50
);
51
## END initial setup
52
53
ok( Koha::Accounts::DebitTypes::Fine eq 'FINE', 'Test DebitTypes::Fine' );
54
ok( Koha::Accounts::DebitTypes::Lost eq 'LOST', 'Test DebitTypes::Lost' );
55
ok(
56
    Koha::Accounts::DebitTypes::IsValid('FINE'),
57
    'Test DebitTypes::IsValid with valid debit type'
58
);
59
ok(
60
    !Koha::Accounts::DebitTypes::IsValid('Not A Valid Fee Type'),
61
    'Test DebitTypes::IsValid with an invalid debit type'
62
);
63
my $authorised_value =
64
  Koha::Database->new()->schema->resultset('AuthorisedValue')->create(
65
    {
66
        category         => 'MANUAL_INV',
67
        authorised_value => 'TEST',
68
        lib              => 'Test',
69
    }
70
  );
71
ok( Koha::Accounts::DebitTypes::IsValid('TEST'),
72
    'Test DebitTypes::IsValid with valid authorised value debit type' );
73
$authorised_value->delete();
74
75
my $debit = AddDebit(
76
    {
77
        borrower   => $borrower,
78
        amount     => 5.00,
79
        type       => Koha::Accounts::DebitTypes::Fine,
80
        branchcode => 'MPL',
81
    }
82
);
83
ok( $debit, "AddDebit returned a valid debit id " . $debit->id() );
84
85
ok(
86
    $borrower->account_balance() == 5.00,
87
    "Borrower's account balance updated correctly"
88
);
89
90
my $debit2 = AddDebit(
91
    {
92
        borrower   => $borrower,
93
        amount     => 7.00,
94
        type       => Koha::Accounts::DebitTypes::Fine,
95
        branchcode => 'MPL',
96
    }
97
);
98
99
my $credit = AddCredit(
100
    {
101
        borrower   => $borrower,
102
        type       => Koha::Accounts::CreditTypes::Payment,
103
        amount     => 9.00,
104
        branchcode => 'MPL',
105
    }
106
);
107
108
RecalculateAccountBalance( { borrower => $borrower } );
109
ok(
110
    sprintf( "%.2f", $borrower->account_balance() ) eq "3.00",
111
    "RecalculateAccountBalance updated balance correctly."
112
);
113
114
Koha::Database->new()->schema->resultset('AccountCredit')->create(
115
    {
116
        borrowernumber   => $borrower->borrowernumber(),
117
        type             => Koha::Accounts::CreditTypes::Payment,
118
        amount_paid      => 3.00,
119
        amount_remaining => 3.00,
120
    }
121
);
122
NormalizeBalances( { borrower => $borrower } );
123
ok(
124
    $borrower->account_balance() == 0.00,
125
    "NormalizeBalances updated balance correctly."
126
);
127
128
# Adding advance credit with no balance due
129
$credit = AddCredit(
130
    {
131
        borrower   => $borrower,
132
        type       => Koha::Accounts::CreditTypes::Payment,
133
        amount     => 9.00,
134
        branchcode => 'MPL',
135
    }
136
);
137
ok(
138
    $borrower->account_balance() == -9,
139
'Adding a $9 credit for borrower with 0 balance results in a -9 dollar account balance'
140
);
141
142
my $debit3 = AddDebit(
143
    {
144
        borrower   => $borrower,
145
        amount     => 5.00,
146
        type       => Koha::Accounts::DebitTypes::Fine,
147
        branchcode => 'MPL',
148
    }
149
);
150
ok(
151
    $borrower->account_balance() == -4,
152
'Adding a $5 debit when the balance is negative results in the debit being automatically paid, resulting in a balance of -4'
153
);
154
155
my $debit4 = AddDebit(
156
    {
157
        borrower   => $borrower,
158
        amount     => 6.00,
159
        type       => Koha::Accounts::DebitTypes::Fine,
160
        branchcode => 'MPL',
161
    }
162
);
163
ok(
164
    $borrower->account_balance() == 2,
165
'Adding another debit ( 6.00 ) more than the negative account balance results in a partial credit and a balance due of 2.00'
166
);
167
$credit = AddCredit(
168
    {
169
        borrower   => $borrower,
170
        type       => Koha::Accounts::CreditTypes::WriteOff,
171
        amount     => 2.00,
172
        branchcode => 'MPL',
173
        debit_id   => $debit4->debit_id(),
174
    }
175
);
176
ok( $borrower->account_balance() == 0,
177
    'WriteOff of remaining 2.00 balance succeeds' );
178
179
my $debit5 = DebitLostItem(
180
    {
181
        borrower => $borrower,
182
        issue    => $issue,
183
    }
184
);
185
ok( $borrower->account_balance() == 25,
186
    'DebitLostItem adds debit for replacement price of item' );
15
187
188
my $lost_credit =
189
  CreditLostItem( { borrower => $borrower, debit => $debit5 } );
190
ok(
191
    $borrower->account_balance() == 0,
192
    'CreditLostItem adds credit for same about as the debit for the lost tiem'
193
);
16
194
195
## Post test cleanup ##
196
$issue->delete();
197
$item->delete();
198
$biblio->delete();
199
$borrower->delete();
(-)a/t/db_dependent/Circulation.t (-4 / +18 lines)
Lines 302-309 C4::Context->dbh->do("DELETE FROM accountlines"); Link Here
302
    C4::Context->set_preference('WhenLostForgiveFine','1');
302
    C4::Context->set_preference('WhenLostForgiveFine','1');
303
    C4::Context->set_preference('WhenLostChargeReplacementFee','1');
303
    C4::Context->set_preference('WhenLostChargeReplacementFee','1');
304
304
305
    C4::Overdues::UpdateFine( $itemnumber, $renewing_borrower->{borrowernumber},
305
    C4::Overdues::UpdateFine(
306
        15.00, q{}, Koha::DateUtils::output_pref($datedue) );
306
        {
307
            itemnumber     => $itemnumber,
308
            borrowernumber => $renewing_borrower->{borrowernumber},
309
            amount         => 15.00,
310
            due            => Koha::DateUtils::output_pref($datedue),
311
            issue_id       => GetItemIssue($itemnumber)->{issue_id}
312
        }
313
    );
307
314
308
    LostItem( $itemnumber, 1 );
315
    LostItem( $itemnumber, 1 );
309
316
Lines 319-326 C4::Context->dbh->do("DELETE FROM accountlines"); Link Here
319
    C4::Context->set_preference('WhenLostForgiveFine','0');
326
    C4::Context->set_preference('WhenLostForgiveFine','0');
320
    C4::Context->set_preference('WhenLostChargeReplacementFee','0');
327
    C4::Context->set_preference('WhenLostChargeReplacementFee','0');
321
328
322
    C4::Overdues::UpdateFine( $itemnumber2, $renewing_borrower->{borrowernumber},
329
    C4::Overdues::UpdateFine(
323
        15.00, q{}, Koha::DateUtils::output_pref($datedue) );
330
        {
331
            itemnumber     => $itemnumber2,
332
            borrowernumber => $renewing_borrower->{borrowernumber},
333
            amount         => 15.00,
334
            due            => Koha::DateUtils::output_pref($datedue),
335
            issue_id       => GetItemIssue($itemnumber2)->{issue_id},
336
        }
337
    );
324
338
325
    LostItem( $itemnumber2, 1 );
339
    LostItem( $itemnumber2, 1 );
326
340
(-)a/t/db_dependent/Members/AddEnrolmentFeeIfNeeded.t (-4 / +3 lines)
Lines 40-56 my %borrower_data = ( Link Here
40
my $borrowernumber = C4::Members::AddMember( %borrower_data );
40
my $borrowernumber = C4::Members::AddMember( %borrower_data );
41
$borrower_data{borrowernumber} = $borrowernumber;
41
$borrower_data{borrowernumber} = $borrowernumber;
42
42
43
my ( $total ) = C4::Members::GetMemberAccountRecords( $borrowernumber );
43
my ( $total ) = C4::Members::GetMemberAccountBalance( $borrowernumber );
44
is( $total, $enrolmentfee_K, "New kid pay $enrolmentfee_K" );
44
is( $total, $enrolmentfee_K, "New kid pay $enrolmentfee_K" );
45
45
46
$borrower_data{categorycode} = 'J';
46
$borrower_data{categorycode} = 'J';
47
C4::Members::ModMember( %borrower_data );
47
C4::Members::ModMember( %borrower_data );
48
( $total ) = C4::Members::GetMemberAccountRecords( $borrowernumber );
48
( $total ) = C4::Members::GetMemberAccountBalance( $borrowernumber );
49
is( $total, $enrolmentfee_K + $enrolmentfee_J, "Kid growing and become a juvenile, he should pay " . ( $enrolmentfee_K + $enrolmentfee_J ) );
49
is( $total, $enrolmentfee_K + $enrolmentfee_J, "Kid growing and become a juvenile, he should pay " . ( $enrolmentfee_K + $enrolmentfee_J ) );
50
50
51
# Check with calling directly AddEnrolmentFeeIfNeeded
51
# Check with calling directly AddEnrolmentFeeIfNeeded
52
C4::Members::AddEnrolmentFeeIfNeeded( 'YA', $borrowernumber );
52
C4::Members::AddEnrolmentFeeIfNeeded( 'YA', $borrowernumber );
53
( $total ) = C4::Members::GetMemberAccountRecords( $borrowernumber );
53
( $total ) = C4::Members::GetMemberAccountBalance( $borrowernumber );
54
is( $total, $enrolmentfee_K + $enrolmentfee_J + $enrolmentfee_YA, "Juvenile growing and become an young adult, he should pay " . ( $enrolmentfee_K + $enrolmentfee_J + $enrolmentfee_YA ) );
54
is( $total, $enrolmentfee_K + $enrolmentfee_J + $enrolmentfee_YA, "Juvenile growing and become an young adult, he should pay " . ( $enrolmentfee_K + $enrolmentfee_J + $enrolmentfee_YA ) );
55
55
56
$dbh->rollback;
56
$dbh->rollback;
57
- 

Return to bug 6427