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

(-)a/C4/Accounts.pm (+183 lines)
Lines 45-50 BEGIN { Link Here
45
      &chargelostitem
45
      &chargelostitem
46
      &ReversePayment
46
      &ReversePayment
47
      &purge_zero_balance_fees
47
      &purge_zero_balance_fees
48
      &updatepayment
48
    );
49
    );
49
}
50
}
50
51
Lines 379-387 sub purge_zero_balance_fees { Link Here
379
    $sth->execute($days) or die $dbh->errstr;
380
    $sth->execute($days) or die $dbh->errstr;
380
}
381
}
381
382
383
sub updatepayment {
384
    my ( $borrowernumber, $account_id, $date, $itemnum, $desc, $type, $amount, $oldamount, $note ) = @_;
385
    my $manager_id = 0;
386
    $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
387
    my $dbh        = C4::Context->dbh;
388
    my $notifyid   = 0;
389
    my $amountleft = $amount;
390
391
    if (   ( $type eq 'L' )
392
        or ( $type eq 'F' )
393
        or ( $type eq 'A' )
394
        or ( $type eq 'N' )
395
        or ( $type eq 'M' ) )
396
    {
397
        $notifyid = 1;
398
    }
399
400
    if ( $type eq 'Pay' ) {
401
        $amountleft = 0.0;
402
        my $amontdif = $amount - $oldamount;
403
404
        if ( $amontdif <= 0 ) {
405
            my $debtamount = abs($amontdif);
406
            $amountleft = addfinetoaccountlines( $borrowernumber, $debtamount );
407
408
        }
409
        else {
410
            $amountleft = reducefinefromaccountlines( $borrowernumber, $amontdif );
411
        }
412
        $amount = -$amount;
413
    }
414
415
    my $sth = $dbh->prepare(
416
     'UPDATE accountlines
417
      SET date=?, amount=?, description=?, accounttype=?, amountoutstanding=?,
418
      itemnumber=?,notify_id=?, note=?, manager_id=?
419
      WHERE accountlines_id=?'
420
    );
421
    $sth->execute( $date, $amount, $desc, $type, $amountleft, $itemnum, $notifyid, $note, $manager_id, $account_id ) || return $sth->errstr;
422
    
423
    if ( C4::Context->preference("FinesLog") ) {
424
        logaction(
425
            "FINES", 'MODIFY',
426
            $borrowernumber,
427
            Dumper(
428
                {   accountno         => $account_id,
429
                    amount            => $amount,
430
                    description       => $desc,
431
                    accounttype       => $type,
432
                    amountoutstanding => $amountleft,
433
                    notify_id         => $notifyid,
434
                    note              => $note,
435
                    itemnumber        => $itemnum,
436
                    manager_id        => $manager_id,
437
                }
438
            )
439
        );
440
    }
441
    return 0;
442
}
443
444
sub addfinetoaccountlines {
445
446
    #here we update the account lines
447
    my ( $borrowernumber, $debtamount ) = @_;
448
    my $newamtos = 0;
449
    my $dbh      = C4::Context->dbh;
450
    my $accdata  = "";
451
452
    # get lines with outstanding amounts to offset
453
    my $sth = $dbh->prepare(
454
     "SELECT * FROM accountlines
455
      WHERE (borrowernumber = ?) AND (amountoutstanding<>amount) and (amountoutstanding>=0) and (accounttype <> 'Pay')
456
      ORDER BY date"
457
    );
458
    $sth->execute($borrowernumber);
459
    my @ids;
460
461
    # offset transactions
462
    while ( ( $accdata = $sth->fetchrow_hashref ) and ( $debtamount > 0 ) ) {
463
        if ( $accdata->{'amount'} - $accdata->{'amountoutstanding'} < $debtamount ) {
464
            $debtamount = $debtamount - ( $accdata->{'amount'} - $accdata->{'amountoutstanding'} );
465
            $newamtos = $accdata->{'amount'};
466
        }
467
        else {
468
            $newamtos   = $accdata->{'amountoutstanding'} + $debtamount;
469
            $debtamount = 0;
470
        }
471
        my $thisacct = $accdata->{accountlines_id};
472
        my $usth     = $dbh->prepare(
473
            "UPDATE accountlines SET amountoutstanding= ?
474
          WHERE (accountlines_id = ?)"
475
        );
476
        $usth->execute( $newamtos, $thisacct );
477
478
        if ( C4::Context->preference("FinesLog") ) {
479
            my $manager_id = 0;
480
            $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
481
            $accdata->{'amountoutstanding_new'} = $newamtos;
482
            logaction(
483
                "FINES", 'MODIFY',
484
                $borrowernumber,
485
                Dumper(
486
                    {   action                => 'fee_payment',
487
                        borrowernumber        => $accdata->{'borrowernumber'},
488
                        old_amountoutstanding => $accdata->{'amountoutstanding'},
489
                        new_amountoutstanding => $newamtos,
490
                        amount_paid           => $accdata->{'amountoutstanding'} - $newamtos,
491
                        accountlines_id       => $accdata->{'accountlines_id'},
492
                        accountno             => $accdata->{'accountno'},
493
                        manager_id            => $manager_id,
494
                    }
495
                )
496
            );
497
            push( @ids, $accdata->{'accountlines_id'} );
498
        }
499
    }
500
    return $debtamount;
501
}
502
503
sub reducefinefromaccountlines {
504
505
    #here we update the account lines
506
    my ( $borrowernumber, $amountpayed ) = @_;
507
    my $amountleft = $amountpayed;
508
    my $newamtos   = 0;
509
    my $dbh        = C4::Context->dbh;
510
    my $accdata    = "";
511
512
    # get lines with outstanding amounts to offset
513
    my $sth = $dbh->prepare(
514
     "SELECT * FROM accountlines
515
      WHERE (borrowernumber = ?) AND (amountoutstanding<>0)
516
      ORDER BY date"
517
    );
518
    $sth->execute($borrowernumber);
519
    my @ids;
520
521
    # offset transactions
522
    while ( ( $accdata = $sth->fetchrow_hashref ) and ( $amountleft > 0 ) ) {
523
        if ( $accdata->{'amountoutstanding'} < $amountleft ) {
524
            $newamtos = 0;
525
            $amountleft -= $accdata->{'amountoutstanding'};
526
        }
527
        else {
528
            $newamtos   = $accdata->{'amountoutstanding'} - $amountleft;
529
            $amountleft = 0;
530
        }
531
        my $thisacct = $accdata->{accountlines_id};
532
        my $usth     = $dbh->prepare(
533
            "UPDATE accountlines SET amountoutstanding= ?
534
          WHERE (accountlines_id = ?)"
535
        );
536
        $usth->execute( $newamtos, $thisacct );
537
538
        if ( C4::Context->preference("FinesLog") ) {
539
            my $manager_id = 0;
540
            $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
541
            $accdata->{'amountoutstanding_new'} = $newamtos;
542
            logaction(
543
                "FINES", 'MODIFY',
544
                $borrowernumber,
545
                Dumper(
546
                    {   action                => 'fee_payment',
547
                        borrowernumber        => $accdata->{'borrowernumber'},
548
                        old_amountoutstanding => $accdata->{'amountoutstanding'},
549
                        new_amountoutstanding => $newamtos,
550
                        amount_paid           => $accdata->{'amountoutstanding'} - $newamtos,
551
                        accountlines_id       => $accdata->{'accountlines_id'},
552
                        accountno             => $accdata->{'accountno'},
553
                        manager_id            => $manager_id,
554
                    }
555
                )
556
            );
557
            push( @ids, $accdata->{'accountlines_id'} );
558
        }
559
    }
560
    return $amountleft;
561
}
562
563
382
END { }    # module clean-up code here (global destructor)
564
END { }    # module clean-up code here (global destructor)
383
565
384
1;
566
1;
567
385
__END__
568
__END__
386
569
387
=head1 SEE ALSO
570
=head1 SEE ALSO
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/members/boraccount.tt (+61 lines)
Lines 61-66 $(document).ready(function() { Link Here
61
	<li><a href="/cgi-bin/koha/members/mancredit.pl?borrowernumber=[% borrowernumber %]" >Create manual credit</a></li>
61
	<li><a href="/cgi-bin/koha/members/mancredit.pl?borrowernumber=[% borrowernumber %]" >Create manual credit</a></li>
62
</ul>
62
</ul>
63
<div class="tabs-container">
63
<div class="tabs-container">
64
  [% IF (edit) %]
65
      [% IF ( ERROR ) %]
66
        ERROR an invalid itemnumber was entered, please hit back and try again
67
      [% ELSE %]
68
        [% IF ( error_over ) %]
69
            <div id="error_message" class="dialog alert">
70
            The amount value must be less than or equal to [% total_due | format('%.2f') %].
71
            </div>
72
        [% END %]
73
      <form action="/cgi-bin/koha/members/boraccount.pl" method="post" id="maninvoice"><input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrowernumber %]" />
74
      <fieldset class="rows">
75
      <legend>Edit</legend>
76
      <ol>
77
      <li><label for="date">Date: </label><input type="text" name="date" id="date" value="[% (accdate) %]"/></li>
78
            <li>
79
      <!--<script type="text/javascript">
80
           var type_fees = new Array();
81
           type_fees['L'] = '';
82
           type_fees['F'] = '';
83
           type_fees['A'] = '';
84
           type_fees['N'] = '';
85
           type_fees['M'] = '';
86
           [% FOREACH invoice_types_loo IN invoice_types_loop %]
87
           type_fees['[% invoice_types_loo.authorised_value %]'] = "[% invoice_types_loo.lib %]";
88
           [% END %]
89
      </script>-->
90
              <label for="type">Type: </label>
91
              <select name="type" id="type">
92
                <option value="L" [% IF (acctype == 'L')%] selected="selected" [% END %]>Lost item</option>
93
                <option value="F" [% IF (acctype == 'F')%] selected="selected" [% END %]>Fine</option>
94
                <option value="A" [% IF (acctype == 'A')%] selected="selected" [% END %]>Account management fee</option>
95
                <option value="N" [% IF (acctype == 'N')%] selected="selected" [% END %]>New card</option>
96
                <option value="M" [% IF (acctype == 'M')%] selected="selected" [% END %]>Sundry</option>
97
                <option value="C" [% IF (acctype == 'C')%] selected="selected" [% END %]>Credit</option>
98
                <option value="FOR" [% IF (acctype == 'FOR' or acctype == 'FFOR')%] selected="selected" [% END %]>Forgiven</option>
99
                <option value="copiers" [% IF (acctype == 'copiers')%] selected="selected" [% END %]>copiers fee</option>
100
                <option value="FU" [% IF (acctype == 'FU')%] selected="selected" [% END %]>Fine Unpaid</option>
101
                <option value="LR" [% IF (acctype == 'LR')%] selected="selected" [% END %]>Lost and returned</option>
102
                <option value="O" [% IF (acctype == 'O')%] selected="selected" [% END %]>Overdue</option>
103
                <option value="Pay" [% IF (acctype == 'Pay')%] selected="selected" [% END %]>Payment</option>
104
                <option value="CR" [% IF (acctype == 'CR')%] selected="selected" [% END %]>Refund</option>
105
                <option value="Rent" [% IF (acctype == 'Rent')%] selected="selected" [% END %]>Rental fee</option>
106
                <option value="W" [% IF (acctype == 'W')%] selected="selected" [% END %]>Writeoff</option>
107
                [% FOREACH invoice_type IN invoice_types_loop %]
108
                  <option value="[% invoice_type.authorised_value %]">[% invoice_type.authorised_value %]</option>
109
                [% END %]
110
              </select>
111
            </li>
112
      <li><label for="barcode">Barcode: </label><input type="text" name="barcode" id="barcode" value="[% accbarcode %]"/></li>
113
      <li><label for="desc">Description: </label><input type="text" name="desc" id="desc" size="50" value="[% (accdescription) %]"/></li>
114
          <li><label for="note">Note: </label><input type="text" name="note" size="50" id="note" value="[% accnote %]"/></li>
115
      <li><label for="amount">Amount: </label><input type="text" name="amount" id="amount" value="[% accamount %]"/> Example: 5.00</li>
116
      <input type="hidden" name="accountlines_id" value="[% accid %]"/>
117
      <input type="hidden" name="accountoldamount" value="[% accamount %]"/>
118
      </ol></fieldset>
119
      <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>
120
      </form>
121
      [% END %]
122
  [% ELSE %]
64
<!-- The table with the account items -->
123
<!-- The table with the account items -->
65
<table id="table_account_fines">
124
<table id="table_account_fines">
66
    <thead>
125
    <thead>
Lines 112-117 $(document).ready(function() { Link Here
112
      [% IF ( account.amountcredit ) %]<td class="credit" style="text-align: right;">[% ELSE %]<td class="debit" style="text-align: right;">[% END %][% account.amount | $Price %]</td>
171
      [% IF ( account.amountcredit ) %]<td class="credit" style="text-align: right;">[% ELSE %]<td class="debit" style="text-align: right;">[% END %][% account.amount | $Price %]</td>
113
      [% IF ( account.amountoutstandingcredit ) %]<td class="credit" style="text-align: right;">[% ELSE %]<td class="debit" style="text-align: right;">[% END %][% account.amountoutstanding | $Price %]</td>
172
      [% IF ( account.amountoutstandingcredit ) %]<td class="credit" style="text-align: right;">[% ELSE %]<td class="debit" style="text-align: right;">[% END %][% account.amountoutstanding | $Price %]</td>
114
      <td class="actions">
173
      <td class="actions">
174
          <a href="boraccount.pl?action=edit&amp;accountlines_id=[% account.accountlines_id %]&amp;borrowernumber=[% account.borrowernumber %]" class="btn btn-default btn-xs"><i class="fa fa-edit"></i> Edit</a>
115
        [% IF ( account.payment ) %]
175
        [% IF ( account.payment ) %]
116
          <a target="_blank" href="printfeercpt.pl?action=print&amp;accountlines_id=[% account.accountlines_id %]&amp;borrowernumber=[% account.borrowernumber %]" class="btn btn-default btn-xs"><i class="fa fa-print"></i> Print</a>
176
          <a target="_blank" href="printfeercpt.pl?action=print&amp;accountlines_id=[% account.accountlines_id %]&amp;borrowernumber=[% account.borrowernumber %]" class="btn btn-default btn-xs"><i class="fa fa-print"></i> Print</a>
117
        [% ELSE %]
177
        [% ELSE %]
Lines 140-145 $(document).ready(function() { Link Here
140
  </tr>
200
  </tr>
141
  </tfoot>
201
  </tfoot>
142
</table>
202
</table>
203
[% END %]
143
</div></div>
204
</div></div>
144
205
145
</div>
206
</div>
(-)a/members/boraccount.pl (-1 / +100 lines)
Lines 31-41 use CGI qw ( -utf8 ); Link Here
31
use C4::Members;
31
use C4::Members;
32
use C4::Accounts;
32
use C4::Accounts;
33
use C4::Members::Attributes qw(GetBorrowerAttributes);
33
use C4::Members::Attributes qw(GetBorrowerAttributes);
34
use C4::Items;
34
use Koha::Patrons;
35
use Koha::Patrons;
35
use Koha::Patron::Categories;
36
use Koha::Patron::Categories;
36
37
37
my $input=new CGI;
38
my $input=new CGI;
38
39
40
my $borrowernumber=$input->param('borrowernumber');
41
my ($total,$accts,$numaccts)=GetMemberAccountRecords($borrowernumber);
39
42
40
my ($template, $loggedinuser, $cookie) = get_template_and_user(
43
my ($template, $loggedinuser, $cookie) = get_template_and_user(
41
    {
44
    {
Lines 62-67 unless ( $patron ) { Link Here
62
if ( $action eq 'reverse' ) {
65
if ( $action eq 'reverse' ) {
63
  ReversePayment( scalar $input->param('accountlines_id') );
66
  ReversePayment( scalar $input->param('accountlines_id') );
64
}
67
}
68
elsif ( $input->param('add') or $action eq 'edit' ) {
69
    my $borrowernumber = $input->param('borrowernumber');
70
71
    #get account details
72
    my ( $total, $accts, $numaccts ) = GetMemberAccountRecords($borrowernumber);
73
    if ( $input->param('add') ) {
74
        my $total_due = $total;
75
        my $barcode   = $input->param('barcode');
76
        my $itemnum;
77
        if ($barcode) {
78
            $itemnum = GetItemnumberFromBarcode($barcode);
79
        }
80
        my $desc      = $input->param('desc');
81
        my $amount    = $input->param('amount');
82
        my $oldamount = $input->param('accountoldamount');
83
        my $type      = $input->param('type');
84
        my $note      = $input->param('note');
85
86
        if ( $type eq "Pay" ) {
87
            if ( $amount <= $total_due + $oldamount or $amount < 0 ) {
88
                my $error = updatepayment( $borrowernumber, $input->param('accountlines_id'), $input->param('date'), $itemnum, $desc, $type, $amount, $oldamount, $note );
89
                if ($error) {
90
                    $template->param( 'ERROR' => $error );
91
                    output_html_with_http_headers $input, $cookie, $template->output;
92
                    exit;
93
                }
94
                else {
95
                    print $input->redirect("/cgi-bin/koha/members/boraccount.pl?borrowernumber=$borrowernumber");
96
                    exit;
97
                }
98
            }
99
            else {
100
                $template->param(
101
                    error_over => 1,
102
                    total_due  => $total_due + $oldamount
103
                );
104
            }
105
        }
106
        else {
107
            if ( $type eq "C" or $type eq "FOR" ) {
108
                $amount = -abs($amount);
109
            }
110
            my $error = updatepayment( $borrowernumber, $input->param('accountlines_id'), $input->param('date'), $itemnum, $desc, $type, $amount, $oldamount, $note );
111
            if ($error) {
112
                $template->param( 'ERROR' => $error );
113
                output_html_with_http_headers $input, $cookie, $template->output;
114
                exit;
115
            }
116
            else {
117
                print $input->redirect("/cgi-bin/koha/members/boraccount.pl?borrowernumber=$borrowernumber");
118
                exit;
119
            }
120
        }
121
    }
122
    my $data = $patron;
123
    my $accountlines_id = $input->param('accountlines_id');
124
125
    #get authorised values with type of MANUAL_INV
126
    my @invoice_types;
127
    my $dbh = C4::Context->dbh;
128
    my $sth = $dbh->prepare('SELECT * FROM authorised_values WHERE category = "MANUAL_INV"');
129
    $sth->execute();
130
    while ( my $row = $sth->fetchrow_hashref() ) {
131
        push @invoice_types, $row;
132
    }
133
    $template->param( invoice_types_loop => \@invoice_types );
134
135
    if ( $data->{'category_type'} eq 'C' ) {
136
        my ( $catcodes, $labels ) = GetborCatFromCatType( 'A', 'WHERE category_type = ?' );
137
        my $cnt = scalar(@$catcodes);
138
        $template->param( 'CATCODE_MULTI' => 1 ) if $cnt > 1;
139
        $template->param( 'catcode' => $catcodes->[0] ) if $cnt == 1;
140
    }
141
142
    for ( my $i = 0; $i < $numaccts; $i++ ) {
143
        next if ( $accts->[$i]{'accountlines_id'} ne $accountlines_id );
144
        my $barcode;
145
        if ( $accts->[$i]{'itemnumber'} ) {
146
            $barcode = GetBarcodeFromItemnumber( $accts->[$i]{'itemnumber'} );
147
        }
148
        my $amount = sprintf '%.2f', $accts->[$i]{'amount'};
149
        if ( $accts->[$i]{'accounttype'} eq "Pay" or $accts->[$i]{'accounttype'} eq "C" or $accts->[$i]{'accounttype'} eq "FOR" ) {
150
            $amount = abs($amount);
151
        }
152
        $template->param(
153
            accbarcode     => $barcode,
154
            accdate        => $accts->[$i]{'date'},
155
            accdescription => $accts->[$i]{'description'},
156
            accnote        => $accts->[$i]{'note'},
157
            acctype        => $accts->[$i]{'accounttype'},
158
            accamount      => $amount,
159
            accid          => $accountlines_id,
160
        );
161
    }
162
163
    $template->param( edit => 1, );
164
}
65
165
66
if ( $patron->category->category_type eq 'C') {
166
if ( $patron->category->category_type eq 'C') {
67
    my $patron_categories = Koha::Patron::Categories->search_limited({ category_type => 'A' }, {order_by => ['categorycode']});
167
    my $patron_categories = Koha::Patron::Categories->search_limited({ category_type => 'A' }, {order_by => ['categorycode']});
68
- 

Return to bug 16820