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

(-)a/Koha/Account/Line.pm (-1 / +49 lines)
Lines 270-275 sub void { Link Here
270
270
271
}
271
}
272
272
273
=head3 cancel
274
275
  $debit_accountline->cancel();
276
277
Cancel a charge. It will mark the debit as 'cancelled' by updating its
278
status to 'CANCELLED'.
279
Charges that have been fully or partially paid cannot be cancelled.
280
281
Return self in case of success, undef otherwise
282
283
=cut
284
285
sub cancel {
286
    my ($self) = @_;
287
288
    # Make sure it is a charge we are cancelling
289
    return unless $self->is_debit;
290
291
    # Make sure it is not already cancelled
292
    return if $self->status && $self->status eq 'CANCELLED';
293
294
    # Make sure it has not be paid yet
295
    return if $self->amount != $self->amountoutstanding;
296
297
    if ( C4::Context->preference("FinesLog") ) {
298
        logaction('FINES', 'CANCEL', $self->borrowernumber, Dumper({
299
            action => 'cancel_charge',
300
            borrowernumber => $self->borrowernumber,
301
            amount => $self->amount,
302
            amountoutstanding => $self->amountoutstanding,
303
            description => $self->description,
304
            debit_type_code => $self->debit_type_code,
305
            note => $self->note,
306
            itemnumber => $self->itemnumber,
307
            manager_id => $self->manager_id,
308
        }));
309
    }
310
311
    $self->set({
312
        status => 'CANCELLED',
313
        amountoutstanding => 0,
314
        amount => 0,
315
    });
316
    $self->store();
317
318
    return $self;
319
}
320
273
=head3 reduce
321
=head3 reduce
274
322
275
  $charge_accountline->reduce({
323
  $charge_accountline->reduce({
Lines 725-731 sub adjust { Link Here
725
sub is_credit {
773
sub is_credit {
726
    my ($self) = @_;
774
    my ($self) = @_;
727
775
728
    return ( $self->amount < 0 );
776
    return defined $self->credit_type_code;
729
}
777
}
730
778
731
=head3 is_debit
779
=head3 is_debit
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/accounts.inc (+1 lines)
Lines 55-60 Link Here
55
        [%- CASE 'FORGIVEN'   -%]<span> (Forgiven)</span>
55
        [%- CASE 'FORGIVEN'   -%]<span> (Forgiven)</span>
56
        [%- CASE 'VOID'       -%]<span> (Voided)</span>
56
        [%- CASE 'VOID'       -%]<span> (Voided)</span>
57
        [%- CASE 'LOST'       -%]<span> (Lost)</span>
57
        [%- CASE 'LOST'       -%]<span> (Lost)</span>
58
        [%- CASE 'CANCELLED'  -%]<span> (Cancelled)</span>
58
        [%- CASE              -%]
59
        [%- CASE              -%]
59
    [%- END -%]
60
    [%- END -%]
60
[%- END -%]
61
[%- END -%]
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/members/boraccount.tt (-2 / +13 lines)
Lines 81-88 Link Here
81
          <a target="_blank" href="printinvoice.pl?action=print&amp;accountlines_id=[% account.accountlines_id | uri %]&amp;borrowernumber=[% account.borrowernumber | uri %]" class="btn btn-default btn-xs"><i class="fa fa-print"></i> Print</a>
81
          <a target="_blank" href="printinvoice.pl?action=print&amp;accountlines_id=[% account.accountlines_id | uri %]&amp;borrowernumber=[% account.borrowernumber | uri %]" class="btn btn-default btn-xs"><i class="fa fa-print"></i> Print</a>
82
        [% END %]
82
        [% END %]
83
        <a href="accountline-details.pl?accountlines_id=[% account.accountlines_id | uri %]" class="btn btn-default btn-xs"><i class="fa fa-list"></i> Details</a>
83
        <a href="accountline-details.pl?accountlines_id=[% account.accountlines_id | uri %]" class="btn btn-default btn-xs"><i class="fa fa-list"></i> Details</a>
84
        [% IF account.is_credit %]
84
        [% IF account.is_credit && account.status != 'VOID' %]
85
          <a href="boraccount.pl?action=void&amp;accountlines_id=[% account.accountlines_id | uri %]&amp;borrowernumber=[% account.borrowernumber | uri %]" class="btn btn-default btn-xs void"><i class="fa fa-ban"></i> Void</a>
85
          <a href="boraccount.pl?action=void&amp;accountlines_id=[% account.accountlines_id | uri %]&amp;borrowernumber=[% account.borrowernumber | uri %]" class="btn btn-default btn-xs void"><i class="fa fa-ban"></i> Void payment</a>
86
        [% END %]
87
        [% IF account.is_debit && account.amount == account.amountoutstanding && account.status != 'CANCELLED' %]
88
          <form method="post" action="/cgi-bin/koha/members/cancel-charge.pl">
89
            <input type="hidden" name="csrf_token" value="[% csrf_token | html %]">
90
            <input type="hidden" name="borrowernumber" value="[% patron.borrowernumber | html %]">
91
            <input type="hidden" name="accountlines_id" value="[% account.accountlines_id | html %]">
92
            <button type="submit" class="btn btn-default btn-xs">
93
                <i class="fa fa-ban"></i>
94
                Cancel charge
95
            </button>
96
          </form>
86
        [% END %]
97
        [% END %]
87
        [% IF CAN_user_updatecharges_payout && account.is_credit && ( account.amountoutstanding < 0 ) %]
98
        [% IF CAN_user_updatecharges_payout && account.is_credit && ( account.amountoutstanding < 0 ) %]
88
          <button type="button" data-toggle="modal" data-target="#issuePayoutModal" data-account="[%- PROCESS account_type_description account=account -%]" data-accountline="[% account.accountlines_id | html %]" data-amount="[% account.amountoutstanding | $Price %]" class="btn btn-default btn-xs"><i class="fa fa-money"></i> Issue payout</button>
99
          <button type="button" data-toggle="modal" data-target="#issuePayoutModal" data-account="[%- PROCESS account_type_description account=account -%]" data-accountline="[% account.accountlines_id | html %]" data-amount="[% account.amountoutstanding | $Price %]" class="btn btn-default btn-xs"><i class="fa fa-money"></i> Issue payout</button>
(-)a/members/boraccount.pl (+6 lines)
Lines 32-37 use C4::Accounts; Link Here
32
use Koha::Cash::Registers;
32
use Koha::Cash::Registers;
33
use Koha::Patrons;
33
use Koha::Patrons;
34
use Koha::Patron::Categories;
34
use Koha::Patron::Categories;
35
use Koha::Token;
35
36
36
my $input=new CGI;
37
my $input=new CGI;
37
38
Lines 164-169 if($total <= 0){ Link Here
164
        $totalcredit = 1;
165
        $totalcredit = 1;
165
}
166
}
166
167
168
my $csrf_token = Koha::Token->new->generate_csrf({
169
    session_id => scalar $input->cookie('CGISESSID'),
170
});
171
167
$template->param(
172
$template->param(
168
    patron              => $patron,
173
    patron              => $patron,
169
    finesview           => 1,
174
    finesview           => 1,
Lines 172-177 $template->param( Link Here
172
    accounts            => \@accountlines,
177
    accounts            => \@accountlines,
173
    payment_id          => $payment_id,
178
    payment_id          => $payment_id,
174
    change_given        => $change_given,
179
    change_given        => $change_given,
180
    csrf_token          => $csrf_token,
175
);
181
);
176
182
177
output_html_with_http_headers $input, $cookie, $template->output;
183
output_html_with_http_headers $input, $cookie, $template->output;
(-)a/members/cancel-charge.pl (+48 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
6
# under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 3 of the License, or
8
# (at your option) any later version.
9
#
10
# Koha is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18
use Modern::Perl;
19
20
use CGI;
21
22
use C4::Auth;
23
use Koha::Token;
24
25
my $cgi = CGI->new;
26
27
my $authnotrequired = 0;
28
my $flags = { updatecharges => 'remaining_permissions' };
29
my $type = 'intranet';
30
my ($user, $cookie) = C4::Auth::checkauth($cgi, $authnotrequired, $flags, $type);
31
32
my $csrf_token_is_valid = Koha::Token->new->check_csrf( {
33
    session_id => scalar $cgi->cookie('CGISESSID'),
34
    token  => scalar $cgi->param('csrf_token'),
35
});
36
unless ($csrf_token_is_valid) {
37
    print $cgi->header('text/plain', '403 Forbidden');
38
    print 'Wrong CSRF token';
39
    exit;
40
}
41
42
my $borrowernumber = $cgi->param('borrowernumber');
43
my $accountlines_id = $cgi->param('accountlines_id');
44
45
my $line = Koha::Account::Lines->find($accountlines_id);
46
$line->cancel();
47
48
print $cgi->redirect('/cgi-bin/koha/members/boraccount.pl?borrowernumber=' . $borrowernumber);
(-)a/t/db_dependent/Koha/Account/Lines.t (-2 / +69 lines)
Lines 19-25 Link Here
19
19
20
use Modern::Perl;
20
use Modern::Perl;
21
21
22
use Test::More tests => 15;
22
use Test::More tests => 16;
23
use Test::Exception;
23
use Test::Exception;
24
24
25
use C4::Circulation qw/AddIssue AddReturn/;
25
use C4::Circulation qw/AddIssue AddReturn/;
Lines 824-829 subtest "void() tests" => sub { Link Here
824
    $borrower->branchcode( $branchcode );
824
    $borrower->branchcode( $branchcode );
825
    $borrower->store;
825
    $borrower->store;
826
826
827
    t::lib::Mocks::mock_userenv({ branchcode => $branchcode, borrowernumber => $borrower->borrowernumber });
828
827
    my $account = Koha::Account->new({ patron_id => $borrower->id });
829
    my $account = Koha::Account->new({ patron_id => $borrower->id });
828
830
829
    my $line1 = Koha::Account::Line->new(
831
    my $line1 = Koha::Account::Line->new(
Lines 893-898 subtest "void() tests" => sub { Link Here
893
    $schema->storage->txn_rollback;
895
    $schema->storage->txn_rollback;
894
};
896
};
895
897
898
subtest "cancel() tests" => sub {
899
    plan tests => 9;
900
901
    $schema->storage->txn_begin;
902
903
    # Create a borrower
904
    my $categorycode = $builder->build({ source => 'Category' })->{ categorycode };
905
    my $branchcode   = $builder->build({ source => 'Branch' })->{ branchcode };
906
907
    my $borrower = Koha::Patron->new( {
908
        cardnumber => 'dariahall',
909
        surname => 'Hall',
910
        firstname => 'Daria',
911
    } );
912
    $borrower->categorycode( $categorycode );
913
    $borrower->branchcode( $branchcode );
914
    $borrower->store;
915
916
    t::lib::Mocks::mock_userenv({ branchcode => $branchcode, borrowernumber => $borrower->borrowernumber });
917
918
    my $account = Koha::Account->new({ patron_id => $borrower->id });
919
920
    my $line1 = Koha::Account::Line->new(
921
        {
922
            borrowernumber    => $borrower->borrowernumber,
923
            amount            => 10,
924
            amountoutstanding => 10,
925
            interface         => 'commandline',
926
            debit_type_code   => 'OVERDUE',
927
        }
928
    )->store();
929
    my $line2 = Koha::Account::Line->new(
930
        {
931
            borrowernumber    => $borrower->borrowernumber,
932
            amount            => 20,
933
            amountoutstanding => 20,
934
            interface         => 'commandline',
935
            debit_type_code   => 'OVERDUE',
936
        }
937
    )->store();
938
939
    my $id = $account->pay({
940
        lines  => [$line2],
941
        amount => 5,
942
    });
943
944
    is( $account->balance(), 25, "Account balance is 25" );
945
    is( $line1->amountoutstanding+0, 10, 'First fee has amount outstanding of 10' );
946
    is( $line2->amountoutstanding+0, 15, 'Second fee has amount outstanding of 15' );
947
948
    my $ret = $line1->cancel();
949
    is( ref($ret), 'Koha::Account::Line', 'Cancel returns the account line' );
950
    is( $account->balance(), 15, "Account balance is 15" );
951
    is( $line1->amount+0, 0, 'First fee has amount of 0' );
952
    is( $line1->amountoutstanding+0, 0, 'First fee has amount outstanding of 0' );
953
954
    $ret = $line2->cancel();
955
    is ($ret, undef, 'cancel returns undef when line cannot be cancelled');
956
957
    my $account_payment = Koha::Account::Lines->find($id);
958
    $ret = $account_payment->cancel();
959
    is ($ret, undef, 'payment cannot be cancelled');
960
961
    $schema->storage->txn_rollback;
962
};
963
896
subtest "payout() tests" => sub {
964
subtest "payout() tests" => sub {
897
965
898
    plan tests => 18;
966
    plan tests => 18;
899
- 

Return to bug 24603