@@ -, +, @@
Click "Pay" next to the fine you want to pay in full
The full amount of the fine will be populated for you in the "Collect From Patron" box
Click "Confirm"
The fine will be removed from outstanding fines, and displayed as fully paid.
Click "Pay" next to the fine you want to partially pay
Enter the amount you are collecting from the patron in the "Collect From Patron" box
Click "Confirm"
The fine will be updated to show the original Amount, and the current Amount Outstanding
Click "Writeoff" next to the fine you wish to writeoff.
The fine will be removed from outstanding fines, and displayed as fully paid.
Click the "Pay Amount" button
Enter the amount you are collecting from the patron in "Collect from Patron." The sum of all fines is shown in "Total Amount Outstanding"
Click "Confirm"
The fine totals will be updated with the payment applied to oldest fines first.
Click the "Writeoff All" button
All fines will be removed from outstanding fines, and displayed as written off.
Check the selection boxes next to the fines you wish to pay, click "Pay Selected"
Enter an amount to pay towards the fines.
Click "Confirm"
The fine totals will be updated with the payment applied to the oldest selected fines first.
---
C4/Accounts.pm | 113 ++++++-
.../intranet-tmpl/prog/en/includes/circ-menu.tt | 73 ++++
.../prog/en/modules/help/members/pay.tt | 51 +++-
.../intranet-tmpl/prog/en/modules/members/pay.tt | 102 +++---
.../prog/en/modules/members/paycollect.tt | 227 ++++++++++++
members/pay.pl | 361 +++++++++++---------
members/paycollect.pl | 171 +++++++++
7 files changed, 878 insertions(+), 220 deletions(-)
create mode 100644 koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.tt
create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/members/paycollect.tt
create mode 100755 members/paycollect.pl
--- a/C4/Accounts.pm
+++ a/C4/Accounts.pm
@@ -38,7 +38,9 @@ BEGIN {
&getnextacctno &reconcileaccount &getcharges &ModNote &getcredits
&getrefunds &chargelostitem
&ReversePayment
- ); # removed &fixaccounts
+ makepartialpayment
+ recordpayment_selectaccts
+ );
}
=head1 NAME
@@ -369,7 +371,6 @@ sub manualinvoice {
my $dbh = C4::Context->dbh;
my $notifyid = 0;
my $insert;
- $itemnum =~ s/ //g;
my $accountno = getnextacctno($borrowernumber);
my $amountleft = $amount;
@@ -413,12 +414,12 @@ sub manualinvoice {
$notifyid = 1;
}
- if ( $itemnum ne '' ) {
- $desc .= " " . $itemnum;
+ if ( $itemnum ) {
+ $desc .= ' ' . $itemnum;
my $sth = $dbh->prepare(
- "INSERT INTO accountlines
+ 'INSERT INTO accountlines
(borrowernumber, accountno, date, amount, description, accounttype, amountoutstanding, itemnumber,notify_id, note, manager_id)
- VALUES (?, ?, now(), ?,?, ?,?,?,?,?,?)");
+ VALUES (?, ?, now(), ?,?, ?,?,?,?,?,?)');
$sth->execute($borrowernumber, $accountno, $amount, $desc, $type, $amountleft, $itemnum,$notifyid, $note, $manager_id) || return $sth->errstr;
} else {
my $sth=$dbh->prepare("INSERT INTO accountlines
@@ -686,6 +687,106 @@ sub ReversePayment {
}
}
+=head2 recordpayment_selectaccts
+
+ recordpayment_selectaccts($borrowernumber, $payment,$accts);
+
+Record payment by a patron. C<$borrowernumber> is the patron's
+borrower number. C<$payment> is a floating-point number, giving the
+amount that was paid. C<$accts> is an array ref to a list of
+accountnos which the payment can be recorded against
+
+Amounts owed are paid off oldest first. That is, if the patron has a
+$1 fine from Feb. 1, another $1 fine from Mar. 1, and makes a payment
+of $1.50, then the oldest fine will be paid off in full, and $0.50
+will be credited to the next one.
+
+=cut
+
+sub recordpayment_selectaccts {
+ my ( $borrowernumber, $amount, $accts ) = @_;
+
+ my $dbh = C4::Context->dbh;
+ my $newamtos = 0;
+ my $accdata = q{};
+ my $branch = C4::Context->userenv->{branch};
+ my $amountleft = $amount;
+ my $sql = 'SELECT * FROM accountlines WHERE (borrowernumber = ?) ' .
+ 'AND (amountoutstanding<>0) ';
+ if (@{$accts} ) {
+ $sql .= ' AND accountno IN ( ' . join ',', @{$accts};
+ $sql .= ' ) ';
+ }
+ $sql .= ' ORDER BY date';
+ # begin transaction
+ my $nextaccntno = getnextacctno($borrowernumber);
+
+ # get lines with outstanding amounts to offset
+ my $rows = $dbh->selectall_arrayref($sql, { Slice => {} }, $borrowernumber);
+
+ # offset transactions
+ my $sth = $dbh->prepare('UPDATE accountlines SET amountoutstanding= ? ' .
+ 'WHERE (borrowernumber = ?) AND (accountno=?)');
+ for my $accdata ( @{$rows} ) {
+ if ($amountleft == 0) {
+ last;
+ }
+ if ( $accdata->{amountoutstanding} < $amountleft ) {
+ $newamtos = 0;
+ $amountleft -= $accdata->{amountoutstanding};
+ }
+ else {
+ $newamtos = $accdata->{amountoutstanding} - $amountleft;
+ $amountleft = 0;
+ }
+ my $thisacct = $accdata->{accountno};
+ $sth->execute( $newamtos, $borrowernumber, $thisacct );
+ }
+
+ # create new line
+ $sql = 'INSERT INTO accountlines ' .
+ '(borrowernumber, accountno,date,amount,description,accounttype,amountoutstanding) ' .
+ q|VALUES (?,?,now(),?,'Payment,thanks','Pay',?)|;
+ $dbh->do($sql,{},$borrowernumber, $nextaccntno, 0 - $amount, 0 - $amountleft );
+ UpdateStats( $branch, 'payment', $amount, '', '', '', $borrowernumber, $nextaccntno );
+ return;
+}
+
+# makepayment needs to be fixed to handle partials till then this separate subroutine
+# fills in
+sub makepartialpayment {
+ my ( $borrowernumber, $accountno, $amount, $user, $branch ) = @_;
+ if (!$amount || $amount < 0) {
+ return;
+ }
+ my $dbh = C4::Context->dbh;
+
+ my $nextaccntno = getnextacctno($borrowernumber);
+ my $newamtos = 0;
+
+ my $data = $dbh->selectrow_hashref(
+ 'SELECT * FROM accountlines WHERE borrowernumber=? AND accountno=?',undef,$borrowernumber,$accountno);
+ my $new_outstanding = $data->{amountoutstanding} - $amount;
+
+ my $update = 'UPDATE accountlines SET amountoutstanding = ? WHERE borrowernumber = ? '
+ . ' AND accountno = ?';
+ $dbh->do( $update, undef, $new_outstanding, $borrowernumber, $accountno);
+
+ # create new line
+ my $insert = 'INSERT INTO accountlines (borrowernumber, accountno, date, amount, '
+ . 'description, accounttype, amountoutstanding) '
+ . ' VALUES (?, ?, now(), ?, ?, ?, 0)';
+
+ $dbh->do( $insert, undef, $borrowernumber, $nextaccntno, $amount,
+ "Payment, thanks - $user", 'Pay');
+
+ UpdateStats( $user, 'payment', $amount, '', '', '', $borrowernumber, $accountno );
+
+ return;
+}
+
+
+
END { } # module clean-up code here (global destructor)
1;
--- a/koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.tt
+++ a/koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.tt
@@ -0,0 +1,73 @@
+[%# duplicates circ-menu.inc but assumes all borrower attributes are in a borrower variable rather than
+in the global namespace %]
+[% IF borrower %]
+
[% borrower.firstname %] [% borrower.surname %] ([% borrower.cardnumber %])
+
+
+[% IF ( patronimages ) %]
+[% IF borrower.has_picture %]
+
+[% ELSE %]
+
+[% END %]
+[% END %]
+ - [% IF borrower.address %]
+ [% borrower.address %]
+ [% ELSE %]
+ No address stored.
+ [% END %]
+ [% IF borrower.address2 %]
+ - [% borrower.address2 %]
+ [% END %]-
+ [% IF borrower.city %]
+ [% borrower.city %][% IF borrower.state %], [% borrower.state %][% END %]
+ [% borrower.zipcode %][% IF ( borrower.country ) %], [% borrower.country %][% END %]
+ [% ELSE %]
+ No city stored.
+ [% END %]
+ - [% IF borrower.phone %]
+ [% borrower.phone %]
+ [% ELSE %]
+ [% IF borrower.mobile %]
+ [% borrower.mobile %]
+ [% ELSE %]
+ [% IF borrower.phonepro %]
+ [% borrower.phonepro %]
+ [% ELSE %]
+ No phone stored.
+ [% END %]
+ [% END %]
+ [% END %]
+ [% IF borrower.email %]
+ - [% borrower.email %]
+ [% ELSE %]
+ [% IF borrower.emailpro %]
+ - [% borrower.emailpro %]
+ [% ELSE %]
+ - No email stored.
+ [% END %]
+ [% END %]
+ - Category: [% borrower.description %] ([% borrower.categorycode %])
+ - Home Library: [% IF ( borrower.branchname ) %][% borrower.branchname %][% ELSE %][% borrower.branch %][% END %]
+
+
+[% END %]
+
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/help/members/pay.tt
+++ a/koha-tmpl/intranet-tmpl/prog/en/modules/help/members/pay.tt
@@ -1,18 +1,51 @@
[% INCLUDE 'help-top.inc' %]
-Pay/Reverse Fines
+Pay and Writeoff Fines
-Each line item can be paid in full (or written off) using the 'Pay Fines' tab.
+Each line item can be paid in full, partially paid, or written off.
+Pay a fine in full
- - Choose the payment type (Unpaid, Paid, Writeoff) from the pull down menu
- - Click 'Make Payment'
- - A line item will be added to the account information showing the fee paid in full (or written off)
- - If you accidentally mark and item as paid, you can reverse that line item by clicking 'Reverse' to the right of the line
+
- Click "Pay" next to the fine you want to pay in full
+ - The full amount of the fine will be populated for you in the "Collect From Patron" box
+ - Click "Confirm"
+ - The fine will be removed from outstanding fines, and displayed as fully paid.
+
+
+Pay a partial fine
+
+ - Click "Pay" next to the fine you want to partially pay
+ - Enter the amount you are collecting from the patron in the "Collect From Patron" box
+ - Click "Confirm"
+ - The fine will be updated to show the original Amount, and the current Amount Outstanding
+
+
+Writeoff a single fine
+
+ - Click "Writeoff" next to the fine you wish to writeoff.
+ - The fine will be removed from outstanding fines, and displayed as fully paid.
+
+
+Pay an amount towards all fines
- - Once clicked a new line item will be added to the account, showing the payment as reversed
+ - Click the "Pay Amount" button
+ - Enter the amount you are collecting from the patron in "Collect from Patron." The sum of all fines is shown in "Total Amount Outstanding"
+ - Click "Confirm"
+ - The fine totals will be updated with the payment applied to oldest fines first.
-
+
+Writeoff All fines
+
+ - Click the "Writeoff All" button
+ - All fines will be removed from outstanding fines, and displayed as written off.
+
+
+Pay Selected fines
+
+ - Check the selection boxes next to the fines you wish to pay, click "Pay Selected"
+ - Enter an amount to pay towards the fines.
+ - Click "Confirm"
+ - The fine totals will be updated with the payment applied to the oldest selected fines first.
-[% INCLUDE 'help-bottom.inc' %]
+[% INCLUDE 'help-bottom.inc' %]
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/pay.tt
+++ a/koha-tmpl/intranet-tmpl/prog/en/modules/members/pay.tt
@@ -1,12 +1,12 @@
[% INCLUDE 'doc-head-open.inc' %]
-Koha › Patrons › Pay Fines for [% firstname %] [% surname %]
+Koha › Patrons › Pay Fines for [% borrower.firstname %] [% borrower.surname %]
[% INCLUDE 'doc-head-close.inc' %]
[% INCLUDE 'header.inc' %]
[% INCLUDE 'patron-search.inc' %]
-Home ›
Patrons › Pay Fines for [% firstname %] [% surname %]
+Home ›
Patrons › Pay Fines for [% borrower.firstname %] [% borrower.surname %]
-[% INCLUDE 'circ-menu.inc' %]
+[% INCLUDE 'circ-menu.tt' %]
[% INCLUDE 'intranet-bottom.inc' %]
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/paycollect.tt
+++ a/koha-tmpl/intranet-tmpl/prog/en/modules/members/paycollect.tt
@@ -0,0 +1,227 @@
+[% INCLUDE 'doc-head-open.inc' %]
+Koha › Patrons › Collect Fine Payment for [% borrower.firstname %] [% borrower.surname %]
+[% INCLUDE 'doc-head-close.inc' %]
+
+
+
+[% INCLUDE 'header.inc' %]
+[% INCLUDE 'patron-search.inc' %]
+Home ›
Patrons › Pay Fines for [% borrower.firstname %] [% borrower.surname %]
+
+
+
+
+
+
+[% INCLUDE 'members-toolbar.inc' %]
+
+
+
+
+
+
+[% IF ( error ) %]
+
+ [% error %]
+
+[% END %]
+
+[% IF ( pay_individual ) %]
+
+[% ELSIF ( writeoff_individual ) %]
+
+[% ELSE %]
+
+
+[% END %]
+
+
+
+
+
+[% INCLUDE 'circ-menu.tt' %]
+
+
+[% INCLUDE 'intranet-bottom.inc' %]
+
--- a/members/pay.pl
+++ a/members/pay.pl
@@ -2,6 +2,7 @@
# Copyright 2000-2002 Katipo Communications
# Copyright 2010 BibLibre
+# Copyright 2010,2011 PTFS-Europe Ltd
#
# This file is part of Koha.
#
@@ -18,7 +19,6 @@
# with Koha; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
=head1 pay.pl
written 11/1/2000 by chris@katipo.oc.nz
@@ -38,196 +38,243 @@ use C4::Accounts;
use C4::Stats;
use C4::Koha;
use C4::Overdues;
-use C4::Branch; # GetBranches
+use C4::Branch;
-my $input = new CGI;
+my $input = CGI->new;
my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
- {
- template_name => "members/pay.tmpl",
+ { template_name => 'members/pay.tmpl',
query => $input,
- type => "intranet",
+ type => 'intranet',
authnotrequired => 0,
flagsrequired => { borrowers => 1, updatecharges => 1 },
debug => 1,
}
);
+my $writeoff_sth;
+my $add_writeoff_sth;
+
+my @names = $input->param;
+
my $borrowernumber = $input->param('borrowernumber');
-if ( $borrowernumber eq '' ) {
+if ( !$borrowernumber ) {
$borrowernumber = $input->param('borrowernumber0');
}
# get borrower details
-my $data = GetMember( borrowernumber => $borrowernumber );
+my $borrower = GetMember( borrowernumber => $borrowernumber );
my $user = $input->remote_user;
+$user ||= q{};
-# get account details
my $branches = GetBranches();
-my $branch = GetBranch( $input, $branches );
+my $branch = GetBranch( $input, $branches );
-my @names = $input->param;
-my %inp;
-my $check = 0;
-for ( my $i = 0 ; $i < @names ; $i++ ) {
- my $temp = $input->param( $names[$i] );
- if ( $temp eq 'wo' ) {
- $inp{ $names[$i] } = $temp;
- $check = 1;
- }
- if ( $temp eq 'yes' ) {
-
-# FIXME : using array +4, +5, +6 is dirty. Should use arrays for each accountline
- my $amount = $input->param( $names[ $i + 4 ] );
- my $borrowernumber = $input->param( $names[ $i + 5 ] );
- my $accountno = $input->param( $names[ $i + 6 ] );
- makepayment( $borrowernumber, $accountno, $amount, $user, $branch );
- $check = 2;
- }
- if ( $temp eq 'no'||$temp eq 'yes'||$temp eq 'wo') {
- my $borrowernumber = $input->param( $names[ $i + 5 ] );
- my $accountno = $input->param( $names[ $i + 6 ] );
- my $note = $input->param( $names[ $i + 10 ] );
- ModNote( $borrowernumber, $accountno, $note );
- }
+my $writeoff_item = $input->param('confirm_writeoff');
+my $paycollect = $input->param('paycollect');
+if ($paycollect) {
+ print $input->redirect(
+ "/cgi-bin/koha/members/paycollect.pl?borrowernumber=$borrowernumber");
+}
+my $payselected = $input->param('payselected');
+if ($payselected) {
+ payselected(@names);
}
-my $total = $input->param('total') || '';
-if ( $check == 0 ) {
- if ( $total ne '' ) {
- recordpayment( $borrowernumber, $total );
+my $writeoff_all = $input->param('woall'); # writeoff all fines
+if ($writeoff_all) {
+ writeoff_all(@names);
+} elsif ($writeoff_item) {
+ my $accountno = $input->param('accountno');
+ my $itemno = $input->param('itemnumber');
+ my $account_type = $input->param('accounttype');
+ my $amount = $input->param('amount');
+ writeoff( $accountno, $itemno, $account_type, $amount );
+}
+
+for (@names) {
+ if (/^pay_indiv_(\d+)$/) {
+ my $line_no = $1;
+ redirect_to_paycollect( 'pay_individual', $line_no );
+ } elsif (/^wo_indiv_(\d+)$/) {
+ my $line_no = $1;
+ redirect_to_paycollect( 'writeoff_individual', $line_no );
}
+}
- my ( $total, $accts, $numaccts) = GetMemberAccountRecords( $borrowernumber );
-
- my @allfile;
- my @notify = NumberNotifyId($borrowernumber);
-
- my $numberofnotify = scalar(@notify);
- for ( my $j = 0 ; $j < scalar(@notify) ; $j++ ) {
- my @loop_pay;
- my ( $total , $accts, $numaccts) =
- GetBorNotifyAcctRecord( $borrowernumber, $notify[$j] );
- for ( my $i = 0 ; $i < $numaccts ; $i++ ) {
- my %line;
- if ( $accts->[$i]{'amountoutstanding'} != 0 ) {
- $accts->[$i]{'amount'} += 0.00;
- $accts->[$i]{'amountoutstanding'} += 0.00;
- $line{i} = $j . "" . $i;
- $line{itemnumber} = $accts->[$i]{'itemnumber'};
- $line{accounttype} = $accts->[$i]{'accounttype'};
- $line{amount} = sprintf( "%.2f", $accts->[$i]{'amount'} );
- $line{amountoutstanding} =
- sprintf( "%.2f", $accts->[$i]{'amountoutstanding'} );
- $line{borrowernumber} = $borrowernumber;
- $line{accountno} = $accts->[$i]{'accountno'};
- $line{description} = $accts->[$i]{'description'};
- $line{note} = $accts->[$i]{'note'};
- $line{title} = $accts->[$i]{'title'};
- $line{notify_id} = $accts->[$i]{'notify_id'};
- $line{notify_level} = $accts->[$i]{'notify_level'};
- $line{net_balance} = 1 if($accts->[$i]{'amountoutstanding'} > 0); # you can't pay a credit.
- push( @loop_pay, \%line );
- }
- }
+add_accounts_to_template();
- my $totalnotify = AmountNotify( $notify[$j], $borrowernumber );
- ( $totalnotify = '0' ) if ( $totalnotify =~ /^0.00/ );
- push @allfile,
- {
- 'loop_pay' => \@loop_pay,
- 'notify' => $notify[$j],
- 'total' => sprintf( "%.2f",$totalnotify),
-
- };
- }
-
-if ( $data->{'category_type'} eq 'C') {
- my ( $catcodes, $labels ) = GetborCatFromCatType( 'A', 'WHERE category_type = ?' );
- my $cnt = scalar(@$catcodes);
- $template->param( 'CATCODE_MULTI' => 1) if $cnt > 1;
- $template->param( 'catcode' => $catcodes->[0]) if $cnt == 1;
+output_html_with_http_headers $input, $cookie, $template->output;
+
+sub writeoff {
+ my ( $accountnum, $itemnum, $accounttype, $amount ) = @_;
+
+ # if no item is attached to fine, make sure to store it as a NULL
+ $itemnum ||= undef;
+ get_writeoff_sth();
+ $writeoff_sth->execute( $accountnum, $borrowernumber );
+
+ my $acct = getnextacctno($borrowernumber);
+ $add_writeoff_sth->execute( $borrowernumber, $acct, $itemnum, $amount );
+
+ UpdateStats( $branch, 'writeoff', $amount, q{}, q{}, q{}, $borrowernumber );
+
+ return;
}
-
-$template->param( adultborrower => 1 ) if ( $data->{'category_type'} eq 'A' );
-my ($picture, $dberror) = GetPatronImage($data->{'cardnumber'});
-$template->param( picture => 1 ) if $picture;
-
+
+sub add_accounts_to_template {
+
+ my ( $total, undef, undef ) = GetMemberAccountRecords($borrowernumber);
+ my $accounts = [];
+ my @notify = NumberNotifyId($borrowernumber);
+
+ my $notify_groups = [];
+ for my $notify_id (@notify) {
+ my ( $acct_total, $accountlines, undef ) =
+ GetBorNotifyAcctRecord( $borrowernumber, $notify_id );
+ if ( @{$accountlines} ) {
+ my $totalnotify = AmountNotify( $notify_id, $borrowernumber );
+ push @{$accounts},
+ { accountlines => $accountlines,
+ notify => $notify_id,
+ total => $totalnotify,
+ };
+ }
+ }
+ borrower_add_additional_fields($borrower);
$template->param(
- allfile => \@allfile,
- firstname => $data->{'firstname'},
- surname => $data->{'surname'},
- borrowernumber => $borrowernumber,
- cardnumber => $data->{'cardnumber'},
- categorycode => $data->{'categorycode'},
- category_type => $data->{'category_type'},
- categoryname => $data->{'description'},
- address => $data->{'address'},
- address2 => $data->{'address2'},
- city => $data->{'city'},
- state => $data->{'state'},
- zipcode => $data->{'zipcode'},
- country => $data->{'country'},
- phone => $data->{'phone'},
- email => $data->{'email'},
- branchcode => $data->{'branchcode'},
- branchname => GetBranchName($data->{'branchcode'}),
- is_child => ($data->{'category_type'} eq 'C'),
- total => sprintf( "%.2f", $total )
+ accounts => $accounts,
+ borrower => $borrower,
+ total => $total,
);
- output_html_with_http_headers $input, $cookie, $template->output;
+ return;
}
-else {
-
- my %inp;
- my @name = $input->param;
- for ( my $i = 0 ; $i < @name ; $i++ ) {
- my $test = $input->param( $name[$i] );
- if ( $test eq 'wo' ) {
- my $temp = $name[$i];
- $temp =~ s/payfine//;
- $inp{ $name[$i] } = $temp;
- }
+
+sub get_for_redirect {
+ my ( $name, $name_in, $money ) = @_;
+ my $s = q{&} . $name . q{=};
+ my $value = $input->param($name_in);
+ if ( !defined $value ) {
+ $value = ( $money == 1 ) ? 0 : q{};
+ }
+ if ($money) {
+ $s .= sprintf '%.2f', $value;
+ } else {
+ $s .= $value;
}
- my $borrowernumber;
- while ( my ( $key, $value ) = each %inp ) {
-
- my $accounttype = $input->param("accounttype$value");
- $borrowernumber = $input->param("borrowernumber$value");
- my $itemno = $input->param("itemnumber$value");
- my $amount = $input->param("amount$value");
- my $accountno = $input->param("accountno$value");
- writeoff( $borrowernumber, $accountno, $itemno, $accounttype, $amount );
+ return $s;
+}
+
+sub redirect_to_paycollect {
+ my ( $action, $line_no ) = @_;
+ my $redirect =
+ "/cgi-bin/koha/members/paycollect.pl?borrowernumber=$borrowernumber";
+ $redirect .= q{&};
+ $redirect .= "$action=1";
+ $redirect .= get_for_redirect( 'accounttype', "accounttype$line_no", 0 );
+ $redirect .= get_for_redirect( 'amount', "amount$line_no", 1 );
+ $redirect .=
+ get_for_redirect( 'amountoutstanding', "amountoutstanding$line_no", 1 );
+ $redirect .= get_for_redirect( 'accountno', "accountno$line_no", 0 );
+ $redirect .= get_for_redirect( 'description', "description$line_no", 0 );
+ $redirect .= get_for_redirect( 'title', "title$line_no", 0 );
+ $redirect .= get_for_redirect( 'itemnumber', "itemnumber$line_no", 0 );
+ $redirect .= get_for_redirect( 'notify_id', "notify_id$line_no", 0 );
+ $redirect .= get_for_redirect( 'notify_level', "notify_level$line_no", 0 );
+ $redirect .= '&remote_user=';
+ $redirect .= $user;
+ return print $input->redirect($redirect);
+}
+
+sub writeoff_all {
+ my @params = @_;
+ my @wo_lines = grep { /^accountno\d+$/ } @params;
+ for (@wo_lines) {
+ if (/(\d+)/) {
+ my $value = $1;
+ my $accounttype = $input->param("accounttype$value");
+
+ # my $borrowernum = $input->param("borrowernumber$value");
+ my $itemno = $input->param("itemnumber$value");
+ my $amount = $input->param("amount$value");
+ my $accountno = $input->param("accountno$value");
+ writeoff( $accountno, $itemno, $accounttype, $amount );
+ }
}
+
$borrowernumber = $input->param('borrowernumber');
print $input->redirect(
"/cgi-bin/koha/members/boraccount.pl?borrowernumber=$borrowernumber");
+ return;
}
-sub writeoff {
- my ( $borrowernumber, $accountnum, $itemnum, $accounttype, $amount ) = @_;
- my $user = $input->remote_user;
- my $dbh = C4::Context->dbh;
- undef $itemnum unless $itemnum; # if no item is attached to fine, make sure to store it as a NULL
- my $sth =
- $dbh->prepare(
-"Update accountlines set amountoutstanding=0 where accountno=? and borrowernumber=?"
- );
- $sth->execute( $accountnum, $borrowernumber );
- $sth->finish;
- $sth = $dbh->prepare("select max(accountno) from accountlines");
- $sth->execute;
- my $account = $sth->fetchrow_hashref;
- $sth->finish;
- $account->{'max(accountno)'}++;
- $sth = $dbh->prepare(
-"insert into accountlines (borrowernumber,accountno,itemnumber,date,amount,description,accounttype)
- values (?,?,?,now(),?,'Writeoff','W')"
- );
- $sth->execute( $borrowernumber, $account->{'max(accountno)'},
- $itemnum, $amount );
- $sth->finish;
- UpdateStats( $branch, 'writeoff', $amount, '', '', '',
- $borrowernumber );
+sub borrower_add_additional_fields {
+ my $b_ref = shift;
+
+# some borrower info is not returned in the standard call despite being assumed
+# in a number of templates. It should not be the business of this script but in lieu of
+# a revised api here it is ...
+ if ( $b_ref->{category_type} eq 'C' ) {
+ my ( $catcodes, $labels ) =
+ GetborCatFromCatType( 'A', 'WHERE category_type = ?' );
+ if ( @{$catcodes} ) {
+ if ( @{$catcodes} > 1 ) {
+ $b_ref->{CATCODE_MULTI} = 1;
+ } elsif ( @{$catcodes} == 1 ) {
+ $b_ref->{catcode} = $catcodes->[0];
+ }
+ }
+ } elsif ( $b_ref->{category_type} eq 'A' ) {
+ $b_ref->{adultborrower} = 1;
+ }
+ my ( $picture, $dberror ) = GetPatronImage( $b_ref->{cardnumber} );
+ if ($picture) {
+ $b_ref->{has_picture} = 1;
+ }
+
+ $b_ref->{branchname} = GetBranchName( $b_ref->{branchcode} );
+ return;
+}
+
+sub payselected {
+ my @params = @_;
+ my $amt = 0;
+ my @lines_to_pay;
+ foreach (@params) {
+ if (/^incl_par_(\d+)$/) {
+ my $index = $1;
+ push @lines_to_pay, $input->param("accountno$index");
+ $amt += $input->param("amountoutstanding$index");
+ }
+ }
+ $amt = '&amt=' . $amt;
+ my $sel = '&selected=' . join ',', @lines_to_pay;
+ my $redirect =
+ "/cgi-bin/koha/members/paycollect.pl?borrowernumber=$borrowernumber"
+ . $amt
+ . $sel;
+
+ print $input->redirect($redirect);
+ return;
+}
+
+sub get_writeoff_sth {
+
+ # lets prepare these statement handles only once
+ if ($writeoff_sth) {
+ return;
+ } else {
+ my $dbh = C4::Context->dbh;
+
+ # Do we need to validate accounttype
+ my $sql = 'Update accountlines set amountoutstanding=0 '
+ . 'WHERE accountno=? and borrowernumber=?';
+ $writeoff_sth = $dbh->prepare($sql);
+ my $insert =
+q{insert into accountlines (borrowernumber,accountno,itemnumber,date,amount,description,accounttype)}
+ . q{values (?,?,?,now(),?,'Writeoff','W')};
+ $add_writeoff_sth = $dbh->prepare($insert);
+ }
+ return;
}
--- a/members/paycollect.pl
+++ a/members/paycollect.pl
@@ -0,0 +1,171 @@
+#!/usr/bin/perl
+# Copyright 2009,2010 PTFS Inc.
+# Copyright 2011 PTFS-Europe Ltd
+#
+# This file is part of Koha.
+#
+# Koha is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2 of the License, or (at your option) any later
+# version.
+#
+# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with Koha; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+use strict;
+use warnings;
+use C4::Context;
+use C4::Auth;
+use C4::Output;
+use CGI;
+use C4::Members;
+use C4::Accounts;
+use C4::Koha;
+use C4::Branch;
+
+my $input = CGI->new();
+
+my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
+ { template_name => 'members/paycollect.tmpl',
+ query => $input,
+ type => 'intranet',
+ authnotrequired => 0,
+ flagsrequired => { borrowers => 1, updatecharges => 1 },
+ debug => 1,
+ }
+);
+
+# get borrower details
+my $borrowernumber = $input->param('borrowernumber');
+my $borrower = GetMember( borrowernumber => $borrowernumber );
+my $user = $input->remote_user;
+
+# get account details
+my $branch = GetBranch( $input, GetBranches() );
+
+my ( $total_due, $accts, $numaccts ) = GetMemberAccountRecords($borrowernumber);
+my $total_paid = $input->param('paid');
+
+my $individual = $input->param('pay_individual');
+my $writeoff = $input->param('writeoff_individual');
+my $select_lines = $input->param('selected');
+my $select = $input->param('selected_accts');
+my $accountno;
+
+if ( $individual || $writeoff ) {
+ if ($individual) {
+ $template->param( pay_individual => 1 );
+ } elsif ($writeoff) {
+ $template->param( writeoff_individual => 1 );
+ }
+ my $accounttype = $input->param('accounttype');
+ my $amount = $input->param('amount');
+ my $amountoutstanding = $input->param('amountoutstanding');
+ $accountno = $input->param('accountno');
+ my $description = $input->param('description');
+ my $title = $input->param('title');
+ my $notify_id = $input->param('notify_id');
+ my $notify_level = $input->param('notify_level');
+ $total_due = $amountoutstanding;
+ $template->param(
+ accounttype => $accounttype,
+ accountno => $accountno,
+ amount => $amount,
+ amountoutstanding => $amountoutstanding,
+ title => $title,
+ description => $description,
+ notify_id => $notify_id,
+ notify_level => $notify_level,
+ );
+} elsif ($select_lines) {
+ $total_due = $input->param('amt');
+ $template->param(
+ selected_accts => $select_lines,
+ amt => $total_due
+ );
+}
+
+if ( $total_paid and $total_paid ne '0.00' ) {
+ if ( $total_paid < 0 or $total_paid > $total_due ) {
+ $template->param(
+ error => sprintf( 'You must pay a value less than or equal to %f.2',
+ $total_due )
+ );
+ } else {
+ if ($individual) {
+ if ( $total_paid == $total_due ) {
+ makepayment( $borrowernumber, $accountno, $total_paid, $user,
+ $branch );
+ } else {
+ makepartialpayment( $borrowernumber, $accountno, $total_paid,
+ $user, $branch );
+ }
+ print $input->redirect(
+ "/cgi-bin/koha/members/pay.pl?borrowernumber=$borrowernumber");
+ } else {
+ if ($select) {
+ if ( $select =~ /^([\d,]*).*/ ) {
+ $select = $1; # ensure passing no junk
+ }
+ my @acc = split /,/, $select;
+ recordpayment_selectaccts( $borrowernumber, $total_paid,
+ \@acc );
+ } else {
+ recordpayment( $borrowernumber, $total_paid );
+ }
+
+# recordpayment does not return success or failure so lets redisplay the boraccount
+
+ print $input->redirect(
+"/cgi-bin/koha/members/boraccount.pl?borrowernumber=$borrowernumber"
+ );
+ }
+ }
+} else {
+ $total_paid = '0.00'; #TODO not right with pay_individual
+}
+
+borrower_add_additional_fields($borrower);
+
+$template->param(
+
+ #borrowenumber => $borrower->{borrowernumber}, # some templates require global
+ borrowenumber => $borrowernumber, # some templates require global
+ borrower => $borrower,
+ total => $total_due
+);
+
+output_html_with_http_headers $input, $cookie, $template->output;
+
+sub borrower_add_additional_fields {
+ my $b_ref = shift;
+
+# some borrower info is not returned in the standard call despite being assumed
+# in a number of templates. It should not be the business of this script but in lieu of
+# a revised api here it is ...
+ if ( $b_ref->{category_type} eq 'C' ) {
+ my ( $catcodes, $labels ) =
+ GetborCatFromCatType( 'A', 'WHERE category_type = ?' );
+ if ( @{$catcodes} ) {
+ if ( @{$catcodes} > 1 ) {
+ $b_ref->{CATCODE_MULTI} = 1;
+ } elsif ( @{$catcodes} == 1 ) {
+ $b_ref->{catcode} = $catcodes->[0];
+ }
+ }
+ } elsif ( $b_ref->{category_type} eq 'A' ) {
+ $b_ref->{adultborrower} = 1;
+ }
+ my ( $picture, $dberror ) = GetPatronImage( $b_ref->{cardnumber} );
+ if ($picture) {
+ $b_ref->{has_picture} = 1;
+ }
+
+ $b_ref->{branchname} = GetBranchName( $b_ref->{branchcode} );
+ return;
+}
--