Bugzilla – Attachment 2193 Details for
Bug 2169
Paying only partial fines
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Fines System Updates - Code Cleanup & Additional Features
0001-Fines-System-Updates-Code-Cleanup-Additional-Fea.patch (text/plain), 19.63 KB, created by
Kyle M Hall
on 2010-06-02 12:02:44 UTC
(
hide
)
Description:
Fines System Updates - Code Cleanup & Additional Features
Filename:
MIME Type:
Creator:
Kyle M Hall
Created:
2010-06-02 12:02:44 UTC
Size:
19.63 KB
patch
obsolete
>From 182a6af80df72a181b4d0894cb6bb56380529d1c Mon Sep 17 00:00:00 2001 >From: Kyle M Hall <kyle.m.hall@gmail.com> >Date: Tue, 16 Mar 2010 13:52:31 +0000 >Subject: [PATCH] Fines System Updates - Code Cleanup & Additional Features > > * Major code cleanup for pay.pl > * Added ability to negotiate fines ( i.e. Change the fine amount ) > * Added ability to pay, writeoff, and negotiate partial amounts. > * Moved additional functions from pay.pl to Accounts.pm >--- > C4/Accounts.pm | 57 ++++++- > .../intranet-tmpl/prog/en/modules/members/pay.tmpl | 147 ++++++++++++++- > members/pay.pl | 196 +++++++------------- > 3 files changed, 261 insertions(+), 139 deletions(-) > >diff --git a/C4/Accounts.pm b/C4/Accounts.pm >index ff2188b..1d6160b 100644 >--- a/C4/Accounts.pm >+++ b/C4/Accounts.pm >@@ -36,7 +36,7 @@ BEGIN { > @EXPORT = qw( > &recordpayment &makepayment &manualinvoice > &getnextacctno &reconcileaccount &getcharges &getcredits >- &getrefunds &chargelostitem >+ &getrefunds &chargelostitem &writeoff &negotiate > &ReversePayment > ); # removed &fixaccounts > } >@@ -171,7 +171,7 @@ sub makepayment { > > $dbh->do( > "UPDATE accountlines >- SET amountoutstanding = 0 >+ SET amountoutstanding = amountoutstanding - $amount > WHERE borrowernumber = $borrowernumber > AND accountno = $accountno > " >@@ -649,6 +649,59 @@ sub getrefunds { > return (@results); > } > >+sub writeoff { >+ my ( $borrowernumber, $accountnum, $itemnum, $accounttype, $amount ) = @_; >+ 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 $query = "UPDATE accountlines SET amountoutstanding = amountoutstanding - $amount WHERE accountno = ? AND borrowernumber = ?"; >+ my $sth = $dbh->prepare( $query ); >+ $sth->execute( $accountnum, $borrowernumber ); >+ >+ my $next_accountno = getnextacctno( $borrowernumber ); >+ >+ $query = "INSERT INTO accountlines >+ ( borrowernumber, accountno, itemnumber, date, amount, description, accounttype ) >+ VALUES >+ ( ?, ?, ?, NOW(), ?, 'Writeoff', 'W' ) >+ "; >+ $sth = $dbh->prepare( $query ); >+ $sth->execute( $borrowernumber, $next_accountno, $itemnum, $amount ); >+ >+ UpdateStats( C4::Context->userenv->{branch}, 'writeoff', $amount, '', '', '', $borrowernumber ); >+} >+ >+sub negotiate { >+ my ( $borrowernumber, $accountno, $amount, $itemnumber ) = @_; >+ my $dbh = C4::Context->dbh; >+ >+ my $query = " >+ UPDATE >+ accountlines >+ SET >+ amount = amount - ?, >+ description = CONCAT( description, '*' ), >+ amountoutstanding = amountoutstanding - ?, >+ timestamp = NOW() >+ WHERE >+ accountno = ? >+ AND >+ borrowernumber = ? >+ "; >+ my $sth = $dbh->prepare( $query ); >+ $sth->execute( $amount, $amount, $accountno, $borrowernumber ); >+ >+ my $next_accountno = getnextacctno( $borrowernumber ); >+ >+ $query = "INSERT INTO accountlines >+ ( borrowernumber, accountno, itemnumber, date, amount, description, accounttype ) >+ VALUES >+ ( ?, ?, ?, NOW(), ?, 'Negotiated', 'N' ) >+ "; >+ $sth = $dbh->prepare( $query ); >+ $sth->execute( $borrowernumber, $next_accountno, $itemnumber, $amount ); >+} >+ > sub ReversePayment { > my ( $borrowernumber, $accountno ) = @_; > my $dbh = C4::Context->dbh; >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/pay.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/members/pay.tmpl >index 1177ba2..79fab31 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/pay.tmpl >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/pay.tmpl >@@ -1,6 +1,104 @@ > <!-- TMPL_INCLUDE NAME="doc-head-open.inc" --> > <title>Koha › Patrons › Pay Fines for <!-- TMPL_VAR NAME="firstname" --> <!-- TMPL_VAR NAME="surname" --></title> > <!-- TMPL_INCLUDE NAME="doc-head-close.inc" --> >+ >+<script type='text/javascript'> >+ function payfineOnChange( id, amount ) { >+ var selectName = "payfine" + id; >+ var inputName = "amount_to_pay" + id; >+ >+ var mySelect = document.getElementsByName( selectName )[0]; >+ var myInput = document.getElementsByName( inputName )[0]; >+ >+ if ( mySelect.value == "no" ) { >+ myInput.value = ''; >+ } else { >+ if ( myInput.value == '' ) { >+ myInput.value = amount; >+ myInput.select().focus(); >+ } >+ } >+ } >+ >+ function amountOnChange( id ) { >+ var selectName = "payfine" + id; >+ var inputName = "amount_to_pay" + id; >+ >+ var mySelect = document.getElementsByName( selectName )[0]; >+ var myInput = document.getElementsByName( inputName )[0]; >+ >+ if ( myInput.value == '' ) { >+ mySelect.selectedIndex = 0; >+ } else { >+ if ( mySelect.selectedIndex == 0 ) { >+ mySelect.selectedIndex = 1; >+ } >+ } >+ } >+ >+ function checkField( fieldname, total ){ >+ >+ var myInput = document.getElementsByName( fieldname )[0]; >+ total = parseFloat( total ); >+ >+ if ( myInput.value != '' ) { >+ var regExp = /^\d*(\.\d{2})?$/; // This regular express only accepts floating point numbers ex. 5, 5.30, .80, etc... >+ if ( ! regExp.test( myInput.value ) ) { >+ alert("Invalid Amount: " + myInput.value ); >+ myInput.focus(); >+ myInput.select(); >+ return false; >+ } >+ >+ >+ if ( myInput.value > total ) { >+ if ( confirm("You are trying to make a payment larger then the Amount Outstanding.\n\nAre you sure you want to do this?") ) { >+ return true; >+ } else { >+ myInput.focus(); >+ myInput.select(); >+ return false; >+ } >+ } >+ >+ if ( myInput.value.indexOf('.') < 0 ) { >+ if ( confirm("The amount you've entered has no '.'\n\nAre you sure you want to do this?") ) { >+ return true; >+ } else { >+ myInput.focus(); >+ myInput.select(); >+ >+ return false; >+ } >+ } >+ >+ } >+ >+ return true; >+ } >+ >+ function formatField( myInput ) { >+ if ( myInput.value && !isNaN( myInput.value ) ) { >+ myInput.value = formatAsCurrency( myInput.value ); >+ } >+ } >+ >+ function formatAsCurrency(number) { >+ number = number.toString().replace(/\$|\,/g,''); >+ if ( isNaN( number ) ) number = "0"; >+ number = Math.floor( number * 100 + 0.50000000001 ); >+ cents = number % 100; >+ number = Math.floor(number/100).toString(); >+ >+ if( cents < 10 ) cents = "0" + cents; >+ >+ for (var i = 0; i < Math.floor((number.length-(1+i))/3); i++) { >+ number = number.substring( 0, number.length - ( 4 * i + 3 ) ) + ',' + number.substring( number.length - ( 4 * i + 3 ) ); >+ } >+ return number + '.' + cents; >+ } >+</script> >+ > </head> > <body> > <!-- TMPL_INCLUDE NAME="header.inc" --> >@@ -30,12 +128,13 @@ > > <table> > <tr> >- <th>Fines & Charges</th> >+ <th>Action</th> >+ <th>Amount</th> > <th>Description</th> > <th>Account Type</th> > <th>Notify id</th> > <th>Level</th> >- <th>Amount</th> >+ <th>Fine Amount</th> > <th>Amount Outstanding</th> > </tr> > >@@ -43,13 +142,14 @@ > <!-- TMPL_LOOP name="loop_pay" --> > <tr> > <td> >- <!-- TMPL_IF NAME="net_balance" --> >- <select name="payfine<!-- TMPL_VAR name="i" -->"> >- <option value="no">Unpaid</option> >- <option value="yes">Paid</option> >- <option value="wo">Writeoff</option> >+ >+ <select name="payfine<!-- TMPL_VAR name="i" -->" onchange="payfineOnChange('<!-- TMPL_VAR name="i" -->', '<!-- TMPL_VAR name="amountoutstanding" -->')" > >+ <option value="no">Don't Pay</option> >+ <option value="yes">Pay</option> >+ <option value="wo">Writeoff</option> >+ <option value="ng">Negotiate</option> > </select> >- <!-- /TMPL_IF --> >+ > <input type="hidden" name="itemnumber<!-- TMPL_VAR name="i" -->" value="<!-- TMPL_VAR name="itemnumber" -->" /> > <input type="hidden" name="accounttype<!-- TMPL_VAR name="i" -->" value="<!-- TMPL_VAR name="accounttype" -->" /> > <input type="hidden" name="amount<!-- TMPL_VAR name="i" -->" value="<!-- TMPL_VAR name="amount" -->" /> >@@ -60,6 +160,16 @@ > <input type="hidden" name="notify_level<!-- TMPL_VAR name="i" -->" value="<!-- TMPL_VAR name="notify_level" -->" /> > <input type="hidden" name="totals<!-- TMPL_VAR name="i" -->" value="<!-- TMPL_VAR name="totals" -->" /> > </td> >+ <td> >+ <input >+ type="text" >+ name="amount_to_pay<!-- TMPL_VAR name="i" -->" >+ size="6" >+ onkeyup="amountOnChange('<!-- TMPL_VAR name="i" -->')" >+ onchange="formatField( this )"; >+ onblur="return checkField( 'amount_to_pay<!-- TMPL_VAR name="i" -->', '<!-- TMPL_VAR name="amountoutstanding" -->')" >+ /> >+ </td> > <td><!-- TMPL_VAR name="description" --> <!-- TMPL_VAR name="title" escape="html" --></td> > <td><!-- TMPL_VAR name="accounttype" --></td> > <td><!-- TMPL_VAR name="notify_id" --></td> >@@ -71,19 +181,34 @@ > <!-- TMPL_IF NAME="total"--> > <tr> > >- <td colspan="6">Sub Total</td> >+ <td colspan="7">Sub Total</td> > <td><!-- TMPL_VAR name="total" --></td> > </tr> > <!--/TMPL_IF--> > <!-- /TMPL_LOOP --> > <tr> >- <td colspan="6">Total Due</td> >+ <td colspan="7">Total Due</td> > <td><!-- TMPL_VAR name="total" --></td> > </tr> > </table> >-<fieldset class="action"><input type="submit" name="submit" value="Make Payment" class="submit" /> <a class="cancel" href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=<!-- TMPL_VAR NAME="borrowernumber" -->">Cancel</a></fieldset></form><!-- TMPL_ELSE --><p><!-- TMPL_VAR NAME="firstname" --> <!-- TMPL_VAR NAME="surname" --> has no outstanding fines.</p><!-- /TMPL_IF --> >+<fieldset class="action"><input type="submit" name="submit" value="Update Fines & Charges" class="submit" /> <a class="cancel" href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=<!-- TMPL_VAR NAME="borrowernumber" -->">Cancel</a></fieldset></form> >+ >+<fieldset> >+ <legend>Pay Fines by Amount</legend> >+ <form class="inline" action="pay.pl" method="post" onsubmit="return checkField( 'pay_by_amount', '<!-- TMPL_VAR name="total" -->')"> >+ <input type="hidden" name="borrowernumber" value="<!-- TMPL_VAR name="borrowernumber" -->" /> >+ <label for="pay_by_amount">Amount to be paid:</label> >+ <input id="pay_by_amount" name="pay_by_amount" type="text" /> >+ <input type="submit" name="submit" value="Make Partial Payment" class="submit"/> >+ </form> >+</fieldset> > </div></div> > >+<!-- TMPL_ELSE --> >+ <p><!-- TMPL_VAR NAME="firstname" --> <!-- TMPL_VAR NAME="surname" --> has no outstanding fines.</p> >+<!-- /TMPL_IF --> >+ >+ > </div> > </div> > >diff --git a/members/pay.pl b/members/pay.pl >index 5a36bd7..c931a02 100755 >--- a/members/pay.pl >+++ b/members/pay.pl >@@ -52,86 +52,84 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user( > } > ); > >-my $borrowernumber = $input->param('borrowernumber'); >-if ( $borrowernumber eq '' ) { >- $borrowernumber = $input->param('borrowernumber0'); >-} >+my $borrowernumber = $input->param('borrowernumber') || $input->param('borrowernumber00'); > > # get borrower details > my $data = GetMember( borrowernumber => $borrowernumber ); >-my $user = $input->remote_user; > > # get account details > my $branches = GetBranches(); >-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; >+my $branch = GetBranch( $input, $branches ); >+ >+my $index = '0'; >+while ( $input->param( "payfine$index") ) { >+ my $payfine = $input->param( "payfine$index" ); >+ my $amount = $input->param( "amount$index" ); >+ my $accountno = $input->param( "accountno$index" ); >+ my $amount_to_pay = $input->param( "amount_to_pay$index" ); >+ my $itemnumber = $input->param( "itemnumber$index" ); >+ my $accounttype = $input->param( "accounttype$index" ); >+ $amount = $amount_to_pay if ( $amount_to_pay ); >+ >+ if ( $payfine eq 'yes' ) { ## Standard Fine Payment >+ makepayment( $borrowernumber, $accountno, $amount, '', $branch ); >+ } elsif ( $payfine eq 'wo' ) { ## Writeoff >+ writeoff( $borrowernumber, $accountno, $itemnumber, $accounttype, $amount ); >+ } elsif ( $payfine eq 'ng' ) { ## Negotiate Fine >+ negotiate( $borrowernumber, $accountno, $amount, $itemnumber ); > } >+ >+ $index++; > } >-my $total = $input->param('total') || ''; >-if ( $check == 0 ) { >- if ( $total ne '' ) { >- recordpayment( $borrowernumber, $total ); >- } > >- 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{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 ); >- } >- } >+## Pay by Amount >+my $total_to_pay = $input->param('pay_by_amount'); >+if ( $total_to_pay ) { >+ recordpayment( $borrowernumber, $total_to_pay ); >+} > >- 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), >- >- }; >+## Get Fine Details >+my ( $total, $accts, $numaccts) = GetMemberAccountRecords( $borrowernumber ); >+ >+my @allfile; >+my @notify = NumberNotifyId($borrowernumber); >+ >+my $numberofnotify = scalar(@notify); >+my $k = 0; >+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} = $k; >+ $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{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 ); >+ $k++; >+ } > } >+ >+ 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 = ?' ); >@@ -144,7 +142,7 @@ $template->param( adultborrower => 1 ) if ( $data->{'category_type'} eq 'A' ); > my ($picture, $dberror) = GetPatronImage($data->{'cardnumber'}); > $template->param( picture => 1 ) if $picture; > >- $template->param( >+$template->param( > allfile => \@allfile, > firstname => $data->{'firstname'}, > surname => $data->{'surname'}, >@@ -164,60 +162,6 @@ $template->param( picture => 1 ) if $picture; > branchname => GetBranchName($data->{'branchcode'}), > is_child => ($data->{'category_type'} eq 'C'), > total => sprintf( "%.2f", $total ) >- ); >- output_html_with_http_headers $input, $cookie, $template->output; >- >-} >-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; >- } >- } >- 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 ); >- } >- $borrowernumber = $input->param('borrowernumber'); >- print $input->redirect( >- "/cgi-bin/koha/members/boraccount.pl?borrowernumber=$borrowernumber"); >-} >+); > >-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 ); >-} >+output_html_with_http_headers $input, $cookie, $template->output; >-- >1.5.6.5 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 2169
: 2193