Bugzilla – Attachment 23276 Details for
Bug 6427
Rewrite of the accounts system
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 6427 - Rewrite of the accounts system
Bug-6427---Rewrite-of-the-accounts-system.patch (text/plain), 375.16 KB, created by
Kyle M Hall (khall)
on 2013-12-03 17:58:31 UTC
(
hide
)
Description:
Bug 6427 - Rewrite of the accounts system
Filename:
MIME Type:
Creator:
Kyle M Hall (khall)
Created:
2013-12-03 17:58:31 UTC
Size:
375.16 KB
patch
obsolete
>From 8ff5357da3c5c741e4e8219647d35946af78ae19 Mon Sep 17 00:00:00 2001 >From: Kyle M Hall <kyle@bywatersolutions.com> >Date: Wed, 9 Oct 2013 10:36:44 -0400 >Subject: [PATCH] Bug 6427 - Rewrite of the accounts system > >This patch re-engineers Koha's accounting system to be faster, more >stable, and have a better historical accounting of fees and payments >while also unifying much of the payment logic and simplifying the code >behind it. > >Three new tables have been created: >account_debits stores fines and fees owed by the patron. > >account_credits stores payments, write-offs, and other line items that >reduce the amount owed by a patron. > >account_offsets stores data about changes to debits and credits, >including which credits paid which debits. > >borrowers.account_balance stores the current balance of the >patron, so it does not have to be calculated each time it needs to be >displayed. > >issues.issue_id has been added so that individual fines can be directly >linked to the issue that caused them without ambiguity. > >The various accounting code strings ( F, FU, Rent, etc ), some of which >have little or no documentation have been replaced by what enumerated >data types which are documented via POD. >There are three, one for each of Debits ( fees/fines ), Credits ( payments ), >and Offsets. > >The system continues to allow custom fee types ( moving MANUAL_INV to MANUAL_DEBIT ) >while additionally allowing custom payment types ( MANUAL_CREDIT ). > >The system also allows for overpayment, the the outstanding credit being >applied to future fees as they are created. > >The system also allows for a librarian to accept a different amount of >money than what is to be paid, and will calculate the change to be >given. > >Test Plan: >1) Apply this patch >2) Create some manual fees >3) Test the fee payments > * Pay one fee > * Pay multiple fees > * Make a partial payment > * Write off a fee >4) View the fees/payments, verify they are correct >5) Check out some items as overdue that should have fines >6) Run fines.pl, verify fines were generated >7) Pay on an accruing fine >8) Run fines.pl again, verify the fine hasn't changed >9) Increase the daily fine in issuing rules >10) Run fines.pl again, verify the fine has increased >11) Decrease the daily fine in issuing rules >12) Run fines.pl again, verify the fine has decreased >13) Test dropbox mode >14) Test WhenLostChargeReplacementFee both ways >15) Test RefundLostItemFeeOnReturn both ways >16) Test WhenLostForgiveFine both ways >17) Test CalculateFinesOnReturn both ways >--- > C4/Accounts.pm | 821 -------------------- > C4/Circulation.pm | 311 ++++---- > C4/Koha.pm | 2 + > C4/Members.pm | 156 +--- > C4/Overdues.pm | 340 +++------ > C4/Reports/Guided.pm | 29 +- > C4/Reserves.pm | 23 +- > C4/SIP/ILS/Patron.pm | 2 +- > Koha/Accounts.pm | 535 +++++++++++++ > Koha/Accounts/CreditTypes.pm | 117 +++ > Koha/Accounts/DebitTypes.pm | 160 ++++ > Koha/Accounts/OffsetTypes.pm | 72 ++ > Koha/DateUtils.pm | 7 +- > Koha/Schema/Result/AccountCredit.pm | 148 ++++ > Koha/Schema/Result/AccountDebit.pm | 207 +++++ > Koha/Schema/Result/AccountOffset.pm | 118 +++ > Koha/Schema/Result/Accountline.pm | 222 ------ > Koha/Schema/Result/Accountoffset.pm | 106 --- > Koha/Schema/Result/Borrower.pm | 137 ++-- > Koha/Schema/Result/Deleteditem.pm | 11 + > Koha/Schema/Result/Issue.pm | 82 +-- > Koha/Schema/Result/OldIssue.pm | 28 +- > Koha/Template/Plugin/Currency.pm | 90 +++ > Koha/Template/Plugin/KohaAuthorisedValues.pm | 5 + > circ/branchoverdues.pl | 3 +- > circ/circulation.pl | 4 +- > installer/data/mysql/kohastructure.sql | 128 ++- > installer/data/mysql/updatedatabase.pl | 177 +++++ > .../prog/en/includes/browser-strings.inc | 27 + > .../intranet-tmpl/prog/en/includes/circ-menu.inc | 2 +- > .../intranet-tmpl/prog/en/includes/circ-menu.tt | 2 +- > .../prog/en/includes/members-menu.inc | 2 +- > .../prog/en/modules/circ/circulation.tt | 7 +- > .../intranet-tmpl/prog/en/modules/circ/returns.tt | 2 +- > .../prog/en/modules/help/reports/guided_reports.tt | 18 - > .../prog/en/modules/members/account.tt | 431 ++++++++++ > .../prog/en/modules/members/account_credit.tt | 92 +++ > .../prog/en/modules/members/account_debit.tt | 109 +++ > .../prog/en/modules/members/account_payment.tt | 226 ++++++ > .../prog/en/modules/members/account_print.tt | 146 ++++ > .../prog/en/modules/members/boraccount.tt | 99 --- > .../prog/en/modules/members/mancredit.tt | 12 +- > .../prog/en/modules/members/maninvoice.tt | 87 -- > .../intranet-tmpl/prog/en/modules/members/pay.tt | 153 ---- > .../prog/en/modules/members/paycollect.tt | 233 ------ > .../prog/en/modules/members/printfeercpt.tt | 63 -- > .../prog/en/modules/members/printinvoice.tt | 65 -- > koha-tmpl/intranet-tmpl/prog/img/details_close.png | Bin 0 -> 841 bytes > koha-tmpl/intranet-tmpl/prog/img/details_open.png | Bin 0 -> 881 bytes > .../bootstrap/en/includes/browser-strings.inc | 34 + > .../opac-tmpl/bootstrap/en/modules/opac-account.tt | 383 +++++++++- > .../opac-tmpl/bootstrap/images/details_close.png | Bin 0 -> 841 bytes > .../opac-tmpl/bootstrap/images/details_open.png | Bin 0 -> 881 bytes > .../opac-tmpl/prog/en/includes/browser-strings.inc | 34 + > .../opac-tmpl/prog/en/modules/opac-account.tt | 433 +++++++++-- > koha-tmpl/opac-tmpl/prog/images/details_close.png | Bin 0 -> 841 bytes > koha-tmpl/opac-tmpl/prog/images/details_open.png | Bin 0 -> 881 bytes > members/account.pl | 112 +++ > members/account_credit.pl | 103 +++ > members/account_credit_do.pl | 68 ++ > members/account_debit.pl | 104 +++ > members/account_debit_do.pl | 69 ++ > members/account_payment.pl | 122 +++ > members/account_payment_do.pl | 66 ++ > members/account_print.pl | 58 ++ > members/boraccount.pl | 135 ---- > members/mancredit.pl | 114 --- > members/maninvoice.pl | 141 ---- > members/moremember.pl | 5 +- > members/pay.pl | 261 ------- > members/paycollect.pl | 179 ----- > members/printfeercpt.pl | 143 ---- > members/printinvoice.pl | 142 ---- > misc/cronjobs/create_koc_db.pl | 41 +- > misc/cronjobs/fines.pl | 10 +- > misc/maintenance/fix_accountlines_date.pl | 171 ---- > misc/release_notes/release_notes_3_10_0.txt | 2 +- > misc/release_notes/release_notes_3_12_0.txt | 2 +- > opac/opac-account.pl | 48 +- > opac/opac-user.pl | 14 +- > t/db_dependent/Accounts.t | 189 +++++- > t/db_dependent/Circulation.t | 22 +- > t/db_dependent/Members/AddEnrolmentFeeIfNeeded.t | 6 +- > 83 files changed, 4956 insertions(+), 4072 deletions(-) > delete mode 100644 C4/Accounts.pm > create mode 100644 Koha/Accounts.pm > create mode 100644 Koha/Accounts/CreditTypes.pm > create mode 100644 Koha/Accounts/DebitTypes.pm > create mode 100644 Koha/Accounts/OffsetTypes.pm > create mode 100644 Koha/Schema/Result/AccountCredit.pm > create mode 100644 Koha/Schema/Result/AccountDebit.pm > create mode 100644 Koha/Schema/Result/AccountOffset.pm > delete mode 100644 Koha/Schema/Result/Accountline.pm > delete mode 100644 Koha/Schema/Result/Accountoffset.pm > create mode 100644 Koha/Template/Plugin/Currency.pm > create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/members/account.tt > create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/members/account_credit.tt > create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/members/account_debit.tt > create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/members/account_payment.tt > create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/members/account_print.tt > delete mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/members/boraccount.tt > delete mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/members/maninvoice.tt > delete mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/members/pay.tt > delete mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/members/paycollect.tt > delete mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/members/printfeercpt.tt > delete mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/members/printinvoice.tt > create mode 100644 koha-tmpl/intranet-tmpl/prog/img/details_close.png > create mode 100644 koha-tmpl/intranet-tmpl/prog/img/details_open.png > create mode 100644 koha-tmpl/opac-tmpl/bootstrap/en/includes/browser-strings.inc > create mode 100644 koha-tmpl/opac-tmpl/bootstrap/images/details_close.png > create mode 100644 koha-tmpl/opac-tmpl/bootstrap/images/details_open.png > create mode 100644 koha-tmpl/opac-tmpl/prog/en/includes/browser-strings.inc > create mode 100644 koha-tmpl/opac-tmpl/prog/images/details_close.png > create mode 100644 koha-tmpl/opac-tmpl/prog/images/details_open.png > create mode 100755 members/account.pl > create mode 100755 members/account_credit.pl > create mode 100755 members/account_credit_do.pl > create mode 100755 members/account_debit.pl > create mode 100755 members/account_debit_do.pl > create mode 100755 members/account_payment.pl > create mode 100755 members/account_payment_do.pl > create mode 100755 members/account_print.pl > delete mode 100755 members/boraccount.pl > delete mode 100755 members/mancredit.pl > delete mode 100755 members/maninvoice.pl > delete mode 100755 members/pay.pl > delete mode 100755 members/paycollect.pl > delete mode 100755 members/printfeercpt.pl > delete mode 100755 members/printinvoice.pl > delete mode 100755 misc/maintenance/fix_accountlines_date.pl > >diff --git a/C4/Accounts.pm b/C4/Accounts.pm >deleted file mode 100644 >index c34b330..0000000 >--- a/C4/Accounts.pm >+++ /dev/null >@@ -1,821 +0,0 @@ >-package C4::Accounts; >- >-# Copyright 2000-2002 Katipo Communications >-# >-# 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; FIXME - Bug 2505 >-use C4::Context; >-use C4::Stats; >-use C4::Members; >-use C4::Circulation qw(ReturnLostItem); >-use C4::Log qw(logaction); >- >-use Data::Dumper qw(Dumper); >- >-use vars qw($VERSION @ISA @EXPORT); >- >-BEGIN { >- # set the version for version checking >- $VERSION = 3.07.00.049; >- require Exporter; >- @ISA = qw(Exporter); >- @EXPORT = qw( >- &recordpayment >- &makepayment >- &manualinvoice >- &getnextacctno >- &getcharges >- &ModNote >- &getcredits >- &getrefunds >- &chargelostitem >- &ReversePayment >- &makepartialpayment >- &recordpayment_selectaccts >- &WriteOffFee >- ); >-} >- >-=head1 NAME >- >-C4::Accounts - Functions for dealing with Koha accounts >- >-=head1 SYNOPSIS >- >-use C4::Accounts; >- >-=head1 DESCRIPTION >- >-The functions in this module deal with the monetary aspect of Koha, >-including looking up and modifying the amount of money owed by a >-patron. >- >-=head1 FUNCTIONS >- >-=head2 recordpayment >- >- &recordpayment($borrowernumber, $payment); >- >-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. >- >-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 { >- >- #here we update the account lines >- my ( $borrowernumber, $data ) = @_; >- my $dbh = C4::Context->dbh; >- my $newamtos = 0; >- my $accdata = ""; >- my $branch = C4::Context->userenv->{'branch'}; >- my $amountleft = $data; >- my $manager_id = 0; >- $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv; >- >- # begin transaction >- my $nextaccntno = getnextacctno($borrowernumber); >- >- # get lines with outstanding amounts to offset >- my $sth = $dbh->prepare( >- "SELECT * FROM accountlines >- WHERE (borrowernumber = ?) AND (amountoutstanding<>0) >- ORDER BY date" >- ); >- $sth->execute($borrowernumber); >- >- # offset transactions >- my @ids; >- while ( ( $accdata = $sth->fetchrow_hashref ) and ( $amountleft > 0 ) ) { >- if ( $accdata->{'amountoutstanding'} < $amountleft ) { >- $newamtos = 0; >- $amountleft -= $accdata->{'amountoutstanding'}; >- } >- else { >- $newamtos = $accdata->{'amountoutstanding'} - $amountleft; >- $amountleft = 0; >- } >- my $thisacct = $accdata->{accountlines_id}; >- my $usth = $dbh->prepare( >- "UPDATE accountlines SET amountoutstanding= ? >- WHERE (accountlines_id = ?)" >- ); >- $usth->execute( $newamtos, $thisacct ); >- >- if ( C4::Context->preference("FinesLog") ) { >- $accdata->{'amountoutstanding_new'} = $newamtos; >- logaction("FINES", 'MODIFY', $borrowernumber, Dumper({ >- action => 'fee_payment', >- borrowernumber => $accdata->{'borrowernumber'}, >- old_amountoutstanding => $accdata->{'amountoutstanding'}, >- new_amountoutstanding => $newamtos, >- amount_paid => $accdata->{'amountoutstanding'} - $newamtos, >- accountlines_id => $accdata->{'accountlines_id'}, >- accountno => $accdata->{'accountno'}, >- manager_id => $manager_id, >- })); >- push( @ids, $accdata->{'accountlines_id'} ); >- } >- } >- >- # create new line >- my $usth = $dbh->prepare( >- "INSERT INTO accountlines >- (borrowernumber, accountno,date,amount,description,accounttype,amountoutstanding,manager_id) >- VALUES (?,?,now(),?,'Payment,thanks','Pay',?,?)" >- ); >- $usth->execute( $borrowernumber, $nextaccntno, 0 - $data, 0 - $amountleft, $manager_id ); >- >- UpdateStats( $branch, 'payment', $data, '', '', '', $borrowernumber, $nextaccntno ); >- >- if ( C4::Context->preference("FinesLog") ) { >- $accdata->{'amountoutstanding_new'} = $newamtos; >- logaction("FINES", 'CREATE',$borrowernumber,Dumper({ >- action => 'create_payment', >- borrowernumber => $borrowernumber, >- accountno => $nextaccntno, >- amount => $data * -1, >- amountoutstanding => $amountleft * -1, >- accounttype => 'Pay', >- accountlines_paid => \@ids, >- manager_id => $manager_id, >- })); >- } >- >-} >- >-=head2 makepayment >- >- &makepayment($accountlines_id, $borrowernumber, $acctnumber, $amount, $branchcode); >- >-Records the fact that a patron has paid off the entire amount he or >-she owes. >- >-C<$borrowernumber> is the patron's borrower number. C<$acctnumber> is >-the account that was credited. C<$amount> is the amount paid (this is >-only used to record the payment. It is assumed to be equal to the >-amount owed). C<$branchcode> is the code of the branch where payment >-was made. >- >-=cut >- >-#' >-# FIXME - I'm not at all sure about the above, because I don't >-# understand what the acct* tables in the Koha database are for. >-sub makepayment { >- >- #here we update both the accountoffsets and the account lines >- #updated to check, if they are paying off a lost item, we return the item >- # from their card, and put a note on the item record >- my ( $accountlines_id, $borrowernumber, $accountno, $amount, $user, $branch, $payment_note ) = @_; >- my $dbh = C4::Context->dbh; >- my $manager_id = 0; >- $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv; >- >- # begin transaction >- my $nextaccntno = getnextacctno($borrowernumber); >- my $newamtos = 0; >- my $sth = $dbh->prepare("SELECT * FROM accountlines WHERE accountlines_id=?"); >- $sth->execute( $accountlines_id ); >- my $data = $sth->fetchrow_hashref; >- >- my $payment; >- if ( $data->{'accounttype'} eq "Pay" ){ >- my $udp = >- $dbh->prepare( >- "UPDATE accountlines >- SET amountoutstanding = 0, description = 'Payment,thanks' >- WHERE accountlines_id = ? >- " >- ); >- $udp->execute($accountlines_id); >- }else{ >- my $udp = >- $dbh->prepare( >- "UPDATE accountlines >- SET amountoutstanding = 0 >- WHERE accountlines_id = ? >- " >- ); >- $udp->execute($accountlines_id); >- >- # create new line >- my $payment = 0 - $amount; >- $payment_note //= ""; >- >- my $ins = >- $dbh->prepare( >- "INSERT >- INTO accountlines (borrowernumber, accountno, date, amount, itemnumber, description, accounttype, amountoutstanding, manager_id, note) >- VALUES ( ?, ?, now(), ?, ?, 'Payment,thanks', 'Pay', 0, ?, ?)" >- ); >- $ins->execute($borrowernumber, $nextaccntno, $payment, $data->{'itemnumber'}, $manager_id, $payment_note); >- } >- >- if ( C4::Context->preference("FinesLog") ) { >- logaction("FINES", 'MODIFY', $borrowernumber, Dumper({ >- action => 'fee_payment', >- borrowernumber => $borrowernumber, >- old_amountoutstanding => $data->{'amountoutstanding'}, >- new_amountoutstanding => 0, >- amount_paid => $data->{'amountoutstanding'}, >- accountlines_id => $data->{'accountlines_id'}, >- accountno => $data->{'accountno'}, >- manager_id => $manager_id, >- })); >- >- >- logaction("FINES", 'CREATE',$borrowernumber,Dumper({ >- action => 'create_payment', >- borrowernumber => $borrowernumber, >- accountno => $nextaccntno, >- amount => $payment, >- amountoutstanding => 0,, >- accounttype => 'Pay', >- accountlines_paid => [$data->{'accountlines_id'}], >- manager_id => $manager_id, >- })); >- } >- >- >- # FIXME - The second argument to &UpdateStats is supposed to be the >- # branch code. >- # UpdateStats is now being passed $accountno too. MTJ >- UpdateStats( $user, 'payment', $amount, '', '', '', $borrowernumber, >- $accountno ); >- >- #check to see what accounttype >- if ( $data->{'accounttype'} eq 'Rep' || $data->{'accounttype'} eq 'L' ) { >- C4::Circulation::ReturnLostItem( $borrowernumber, $data->{'itemnumber'} ); >- } >- my $sthr = $dbh->prepare("SELECT max(accountlines_id) AS lastinsertid FROM accountlines"); >- $sthr->execute(); >- my $datalastinsertid = $sthr->fetchrow_hashref; >- return $datalastinsertid->{'lastinsertid'}; >-} >- >-=head2 getnextacctno >- >- $nextacct = &getnextacctno($borrowernumber); >- >-Returns the next unused account number for the patron with the given >-borrower number. >- >-=cut >- >-#' >-# FIXME - Okay, so what does the above actually _mean_? >-sub getnextacctno { >- my ($borrowernumber) = shift or return; >- my $sth = C4::Context->dbh->prepare( >- "SELECT accountno+1 FROM accountlines >- WHERE (borrowernumber = ?) >- ORDER BY accountno DESC >- LIMIT 1" >- ); >- $sth->execute($borrowernumber); >- return ($sth->fetchrow || 1); >-} >- >-=head2 fixaccounts (removed) >- >- &fixaccounts($accountlines_id, $borrowernumber, $accountnumber, $amount); >- >-#' >-# FIXME - I don't understand what this function does. >-sub fixaccounts { >- my ( $accountlines_id, $borrowernumber, $accountno, $amount ) = @_; >- my $dbh = C4::Context->dbh; >- my $sth = $dbh->prepare( >- "SELECT * FROM accountlines WHERE accountlines_id=?" >- ); >- $sth->execute( $accountlines_id ); >- my $data = $sth->fetchrow_hashref; >- >- # FIXME - Error-checking >- my $diff = $amount - $data->{'amount'}; >- my $outstanding = $data->{'amountoutstanding'} + $diff; >- $sth->finish; >- >- $dbh->do(<<EOT); >- UPDATE accountlines >- SET amount = '$amount', >- amountoutstanding = '$outstanding' >- WHERE accountlines_id = $accountlines_id >-EOT >- # FIXME: exceedingly bad form. Use prepare with placholders ("?") in query and execute args. >-} >- >-=cut >- >-sub chargelostitem{ >-# lost ==1 Lost, lost==2 longoverdue, lost==3 lost and paid for >-# FIXME: itemlost should be set to 3 after payment is made, should be a warning to the interface that >-# a charge has been added >-# FIXME : if no replacement price, borrower just doesn't get charged? >- my $dbh = C4::Context->dbh(); >- my ($borrowernumber, $itemnumber, $amount, $description) = @_; >- >- # first make sure the borrower hasn't already been charged for this item >- my $sth1=$dbh->prepare("SELECT * from accountlines >- WHERE borrowernumber=? AND itemnumber=? and accounttype='L'"); >- $sth1->execute($borrowernumber,$itemnumber); >- my $existing_charge_hashref=$sth1->fetchrow_hashref(); >- >- # OK, they haven't >- unless ($existing_charge_hashref) { >- my $manager_id = 0; >- $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv; >- # This item is on issue ... add replacement cost to the borrower's record and mark it returned >- # Note that we add this to the account even if there's no replacement price, allowing some other >- # process (or person) to update it, since we don't handle any defaults for replacement prices. >- my $accountno = getnextacctno($borrowernumber); >- my $sth2=$dbh->prepare("INSERT INTO accountlines >- (borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding,itemnumber,manager_id) >- VALUES (?,?,now(),?,?,'L',?,?,?)"); >- $sth2->execute($borrowernumber,$accountno,$amount, >- $description,$amount,$itemnumber,$manager_id); >- >- if ( C4::Context->preference("FinesLog") ) { >- logaction("FINES", 'CREATE', $borrowernumber, Dumper({ >- action => 'create_fee', >- borrowernumber => $borrowernumber, >- accountno => $accountno, >- amount => $amount, >- amountoutstanding => $amount, >- description => $description, >- accounttype => 'L', >- itemnumber => $itemnumber, >- manager_id => $manager_id, >- })); >- } >- >- } >-} >- >-=head2 manualinvoice >- >- &manualinvoice($borrowernumber, $itemnumber, $description, $type, >- $amount, $note); >- >-C<$borrowernumber> is the patron's borrower number. >-C<$description> is a description of the transaction. >-C<$type> may be one of C<CS>, C<CB>, C<CW>, C<CF>, C<CL>, C<N>, C<L>, >-or C<REF>. >-C<$itemnumber> is the item involved, if pertinent; otherwise, it >-should be the empty string. >- >-=cut >- >-#' >-# FIXME: In Koha 3.0 , the only account adjustment 'types' passed to this function >-# are : >-# 'C' = CREDIT >-# 'FOR' = FORGIVEN (Formerly 'F', but 'F' is taken to mean 'FINE' elsewhere) >-# 'N' = New Card fee >-# 'F' = Fine >-# 'A' = Account Management fee >-# 'M' = Sundry >-# 'L' = Lost Item >-# >- >-sub manualinvoice { >- my ( $borrowernumber, $itemnum, $desc, $type, $amount, $note ) = @_; >- my $manager_id = 0; >- $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv; >- my $dbh = C4::Context->dbh; >- my $notifyid = 0; >- my $insert; >- my $accountno = getnextacctno($borrowernumber); >- my $amountleft = $amount; >- >- if ( $type eq 'N' ) { >- $desc .= " New Card"; >- } >- if ( $type eq 'F' ) { >- $desc .= " Fine"; >- } >- if ( $type eq 'A' ) { >- $desc .= " Account Management fee"; >- } >- if ( $type eq 'M' ) { >- $desc .= " Sundry"; >- } >- >- if ( $type eq 'L' && $desc eq '' ) { >- >- $desc = " Lost Item"; >- } >- if ( ( $type eq 'L' ) >- or ( $type eq 'F' ) >- or ( $type eq 'A' ) >- or ( $type eq 'N' ) >- or ( $type eq 'M' ) ) >- { >- $notifyid = 1; >- } >- >- if ( $itemnum ) { >- $desc .= ' ' . $itemnum; >- my $sth = $dbh->prepare( >- 'INSERT INTO accountlines >- (borrowernumber, accountno, date, amount, description, accounttype, amountoutstanding, itemnumber,notify_id, note, manager_id) >- 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 >- (borrowernumber, accountno, date, amount, description, accounttype, amountoutstanding,notify_id, note, manager_id) >- VALUES (?, ?, now(), ?, ?, ?, ?,?,?,?)" >- ); >- $sth->execute( $borrowernumber, $accountno, $amount, $desc, $type, >- $amountleft, $notifyid, $note, $manager_id ); >- } >- >- if ( C4::Context->preference("FinesLog") ) { >- logaction("FINES", 'CREATE',$borrowernumber,Dumper({ >- action => 'create_fee', >- borrowernumber => $borrowernumber, >- accountno => $accountno, >- amount => $amount, >- description => $desc, >- accounttype => $type, >- amountoutstanding => $amountleft, >- notify_id => $notifyid, >- note => $note, >- itemnumber => $itemnum, >- manager_id => $manager_id, >- })); >- } >- >- return 0; >-} >- >-sub getcharges { >- my ( $borrowerno, $timestamp, $accountno ) = @_; >- my $dbh = C4::Context->dbh; >- my $timestamp2 = $timestamp - 1; >- my $query = ""; >- my $sth = $dbh->prepare( >- "SELECT * FROM accountlines WHERE borrowernumber=? AND accountno = ?" >- ); >- $sth->execute( $borrowerno, $accountno ); >- >- my @results; >- while ( my $data = $sth->fetchrow_hashref ) { >- push @results,$data; >- } >- return (@results); >-} >- >-sub ModNote { >- my ( $accountlines_id, $note ) = @_; >- my $dbh = C4::Context->dbh; >- my $sth = $dbh->prepare('UPDATE accountlines SET note = ? WHERE accountlines_id = ?'); >- $sth->execute( $note, $accountlines_id ); >-} >- >-sub getcredits { >- my ( $date, $date2 ) = @_; >- my $dbh = C4::Context->dbh; >- my $sth = $dbh->prepare( >- "SELECT * FROM accountlines,borrowers >- WHERE amount < 0 AND accounttype <> 'Pay' AND accountlines.borrowernumber = borrowers.borrowernumber >- AND timestamp >=TIMESTAMP(?) AND timestamp < TIMESTAMP(?)" >- ); >- >- $sth->execute( $date, $date2 ); >- my @results; >- while ( my $data = $sth->fetchrow_hashref ) { >- $data->{'date'} = $data->{'timestamp'}; >- push @results,$data; >- } >- return (@results); >-} >- >- >-sub getrefunds { >- my ( $date, $date2 ) = @_; >- my $dbh = C4::Context->dbh; >- >- my $sth = $dbh->prepare( >- "SELECT *,timestamp AS datetime >- FROM accountlines,borrowers >- WHERE (accounttype = 'REF' >- AND accountlines.borrowernumber = borrowers.borrowernumber >- AND date >=? AND date <?)" >- ); >- >- $sth->execute( $date, $date2 ); >- >- my @results; >- while ( my $data = $sth->fetchrow_hashref ) { >- push @results,$data; >- >- } >- return (@results); >-} >- >-sub ReversePayment { >- my ( $accountlines_id ) = @_; >- my $dbh = C4::Context->dbh; >- >- my $sth = $dbh->prepare('SELECT * FROM accountlines WHERE accountlines_id = ?'); >- $sth->execute( $accountlines_id ); >- my $row = $sth->fetchrow_hashref(); >- my $amount_outstanding = $row->{'amountoutstanding'}; >- >- if ( $amount_outstanding <= 0 ) { >- $sth = $dbh->prepare('UPDATE accountlines SET amountoutstanding = amount * -1, description = CONCAT( description, " Reversed -" ) WHERE accountlines_id = ?'); >- $sth->execute( $accountlines_id ); >- } else { >- $sth = $dbh->prepare('UPDATE accountlines SET amountoutstanding = 0, description = CONCAT( description, " Reversed -" ) WHERE accountlines_id = ?'); >- $sth->execute( $accountlines_id ); >- } >- >- if ( C4::Context->preference("FinesLog") ) { >- my $manager_id = 0; >- $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv; >- >- if ( $amount_outstanding <= 0 ) { >- $row->{'amountoutstanding'} *= -1; >- } else { >- $row->{'amountoutstanding'} = '0'; >- } >- $row->{'description'} .= ' Reversed -'; >- logaction("FINES", 'MODIFY', $row->{'borrowernumber'}, Dumper({ >- action => 'reverse_fee_payment', >- borrowernumber => $row->{'borrowernumber'}, >- old_amountoutstanding => $row->{'amountoutstanding'}, >- new_amountoutstanding => 0 - $amount_outstanding,, >- accountlines_id => $row->{'accountlines_id'}, >- accountno => $row->{'accountno'}, >- manager_id => $manager_id, >- })); >- >- } >- >-} >- >-=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, $note ) = @_; >- >- my $dbh = C4::Context->dbh; >- my $newamtos = 0; >- my $accdata = q{}; >- my $branch = C4::Context->userenv->{branch}; >- my $amountleft = $amount; >- my $manager_id = 0; >- $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv; >- 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 accountlines_id=?'); >- >- my @ids; >- 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->{accountlines_id}; >- $sth->execute( $newamtos, $thisacct ); >- >- if ( C4::Context->preference("FinesLog") ) { >- logaction("FINES", 'MODIFY', $borrowernumber, Dumper({ >- action => 'fee_payment', >- borrowernumber => $borrowernumber, >- old_amountoutstanding => $accdata->{'amountoutstanding'}, >- new_amountoutstanding => $newamtos, >- amount_paid => $accdata->{'amountoutstanding'} - $newamtos, >- accountlines_id => $accdata->{'accountlines_id'}, >- accountno => $accdata->{'accountno'}, >- manager_id => $manager_id, >- })); >- push( @ids, $accdata->{'accountlines_id'} ); >- } >- >- } >- >- # create new line >- $sql = 'INSERT INTO accountlines ' . >- '(borrowernumber, accountno,date,amount,description,accounttype,amountoutstanding,manager_id,note) ' . >- q|VALUES (?,?,now(),?,'Payment,thanks','Pay',?,?,?)|; >- $dbh->do($sql,{},$borrowernumber, $nextaccntno, 0 - $amount, 0 - $amountleft, $manager_id, $note ); >- UpdateStats( $branch, 'payment', $amount, '', '', '', $borrowernumber, $nextaccntno ); >- >- if ( C4::Context->preference("FinesLog") ) { >- logaction("FINES", 'CREATE',$borrowernumber,Dumper({ >- action => 'create_payment', >- borrowernumber => $borrowernumber, >- accountno => $nextaccntno, >- amount => 0 - $amount, >- amountoutstanding => 0 - $amountleft, >- accounttype => 'Pay', >- accountlines_paid => \@ids, >- manager_id => $manager_id, >- })); >- } >- >- return; >-} >- >-# makepayment needs to be fixed to handle partials till then this separate subroutine >-# fills in >-sub makepartialpayment { >- my ( $accountlines_id, $borrowernumber, $accountno, $amount, $user, $branch, $payment_note ) = @_; >- my $manager_id = 0; >- $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv; >- if (!$amount || $amount < 0) { >- return; >- } >- $payment_note //= ""; >- my $dbh = C4::Context->dbh; >- >- my $nextaccntno = getnextacctno($borrowernumber); >- my $newamtos = 0; >- >- my $data = $dbh->selectrow_hashref( >- 'SELECT * FROM accountlines WHERE accountlines_id=?',undef,$accountlines_id); >- my $new_outstanding = $data->{amountoutstanding} - $amount; >- >- my $update = 'UPDATE accountlines SET amountoutstanding = ? WHERE accountlines_id = ? '; >- $dbh->do( $update, undef, $new_outstanding, $accountlines_id); >- >- if ( C4::Context->preference("FinesLog") ) { >- logaction("FINES", 'MODIFY', $borrowernumber, Dumper({ >- action => 'fee_payment', >- borrowernumber => $borrowernumber, >- old_amountoutstanding => $data->{'amountoutstanding'}, >- new_amountoutstanding => $new_outstanding, >- amount_paid => $data->{'amountoutstanding'} - $new_outstanding, >- accountlines_id => $data->{'accountlines_id'}, >- accountno => $data->{'accountno'}, >- manager_id => $manager_id, >- })); >- } >- >- # create new line >- my $insert = 'INSERT INTO accountlines (borrowernumber, accountno, date, amount, ' >- . 'description, accounttype, amountoutstanding, itemnumber, manager_id, note) ' >- . ' VALUES (?, ?, now(), ?, ?, ?, 0, ?, ?, ?)'; >- >- $dbh->do( $insert, undef, $borrowernumber, $nextaccntno, $amount, >- "Payment, thanks - $user", 'Pay', $data->{'itemnumber'}, $manager_id, $payment_note); >- >- UpdateStats( $user, 'payment', $amount, '', '', '', $borrowernumber, $accountno ); >- >- if ( C4::Context->preference("FinesLog") ) { >- logaction("FINES", 'CREATE',$borrowernumber,Dumper({ >- action => 'create_payment', >- borrowernumber => $user, >- accountno => $nextaccntno, >- amount => 0 - $amount, >- accounttype => 'Pay', >- itemnumber => $data->{'itemnumber'}, >- accountlines_paid => [ $data->{'accountlines_id'} ], >- manager_id => $manager_id, >- })); >- } >- >- return; >-} >- >-=head2 WriteOffFee >- >- WriteOffFee( $borrowernumber, $accountline_id, $itemnum, $accounttype, $amount, $branch, $payment_note ); >- >-Write off a fine for a patron. >-C<$borrowernumber> is the patron's borrower number. >-C<$accountline_id> is the accountline_id of the fee to write off. >-C<$itemnum> is the itemnumber of of item whose fine is being written off. >-C<$accounttype> is the account type of the fine being written off. >-C<$amount> is a floating-point number, giving the amount that is being written off. >-C<$branch> is the branchcode of the library where the writeoff occurred. >-C<$payment_note> is the note to attach to this payment >- >-=cut >- >-sub WriteOffFee { >- my ( $borrowernumber, $accountlines_id, $itemnum, $accounttype, $amount, $branch, $payment_note ) = @_; >- $payment_note //= ""; >- $branch ||= C4::Context->userenv->{branch}; >- my $manager_id = 0; >- $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv; >- >- # if no item is attached to fine, make sure to store it as a NULL >- $itemnum ||= undef; >- >- my ( $sth, $query ); >- my $dbh = C4::Context->dbh(); >- >- $query = " >- UPDATE accountlines SET amountoutstanding = 0 >- WHERE accountlines_id = ? AND borrowernumber = ? >- "; >- $sth = $dbh->prepare( $query ); >- $sth->execute( $accountlines_id, $borrowernumber ); >- >- if ( C4::Context->preference("FinesLog") ) { >- logaction("FINES", 'MODIFY', $borrowernumber, Dumper({ >- action => 'fee_writeoff', >- borrowernumber => $borrowernumber, >- accountlines_id => $accountlines_id, >- manager_id => $manager_id, >- })); >- } >- >- $query =" >- INSERT INTO accountlines >- ( borrowernumber, accountno, itemnumber, date, amount, description, accounttype, manager_id, note ) >- VALUES ( ?, ?, ?, NOW(), ?, 'Writeoff', 'W', ?, ? ) >- "; >- $sth = $dbh->prepare( $query ); >- my $acct = getnextacctno($borrowernumber); >- $sth->execute( $borrowernumber, $acct, $itemnum, $amount, $manager_id, $payment_note ); >- >- if ( C4::Context->preference("FinesLog") ) { >- logaction("FINES", 'CREATE',$borrowernumber,Dumper({ >- action => 'create_writeoff', >- borrowernumber => $borrowernumber, >- accountno => $acct, >- amount => 0 - $amount, >- accounttype => 'W', >- itemnumber => $itemnum, >- accountlines_paid => [ $accountlines_id ], >- manager_id => $manager_id, >- })); >- } >- >- UpdateStats( $branch, 'writeoff', $amount, q{}, q{}, q{}, $borrowernumber ); >- >-} >- >-END { } # module clean-up code here (global destructor) >- >-1; >-__END__ >- >-=head1 SEE ALSO >- >-DBI(3) >- >-=cut >- >diff --git a/C4/Circulation.pm b/C4/Circulation.pm >index 0a22b76..7321aad 100644 >--- a/C4/Circulation.pm >+++ b/C4/Circulation.pm >@@ -30,7 +30,7 @@ use C4::Items; > use C4::Members; > use C4::Dates; > use C4::Dates qw(format_date); >-use C4::Accounts; >+use Koha::Accounts; > use C4::ItemCirculationAlertPreference; > use C4::Message; > use C4::Debug; >@@ -48,6 +48,7 @@ use Data::Dumper; > use Koha::DateUtils; > use Koha::Calendar; > use Koha::Borrower::Debarments; >+use Koha::Database; > use Carp; > use Date::Calc qw( > Today >@@ -1275,7 +1276,7 @@ sub AddIssue { > ## If item was lost, it has now been found, reverse any list item charges if neccessary. > if ( $item->{'itemlost'} ) { > if ( C4::Context->preference('RefundLostItemFeeOnReturn' ) ) { >- _FixAccountForLostAndReturned( $item->{'itemnumber'}, undef, $item->{'barcode'} ); >+ _FixAccountForLostAndReturned( $item->{'itemnumber'} ); > } > } > >@@ -1812,9 +1813,15 @@ sub AddReturn { > if ( $amount > 0 > && C4::Context->preference('finesMode') eq 'production' ) > { >- C4::Overdues::UpdateFine( $issue->{itemnumber}, >- $issue->{borrowernumber}, >- $amount, $type, output_pref($datedue) ); >+ C4::Overdues::UpdateFine( >+ { >+ itemnumber => $issue->{itemnumber}, >+ borrowernumber => $issue->{borrowernumber}, >+ amount => $amount, >+ due => output_pref($datedue), >+ issue_id => $issue->{issue_id} >+ } >+ ); > } > } > >@@ -1864,18 +1871,23 @@ sub AddReturn { > $messages->{'WasLost'} = 1; > > if ( C4::Context->preference('RefundLostItemFeeOnReturn' ) ) { >- _FixAccountForLostAndReturned($item->{'itemnumber'}, $borrowernumber, $barcode); # can tolerate undef $borrowernumber >+ _FixAccountForLostAndReturned( $item->{'itemnumber'} ); > $messages->{'LostItemFeeRefunded'} = 1; > } > } > > # fix up the overdues in accounts... > if ($borrowernumber) { >- my $fix = _FixOverduesOnReturn($borrowernumber, $item->{itemnumber}, $exemptfine, $dropbox); >- defined($fix) or warn "_FixOverduesOnReturn($borrowernumber, $item->{itemnumber}...) failed!"; # zero is OK, check defined >+ _FixOverduesOnReturn( >+ { >+ exempt_fine => $exemptfine, >+ dropbox => $dropbox, >+ issue => $issue, >+ } >+ ); > > if ( $issue->{overdue} && $issue->{date_due} ) { >-# fix fine days >+ # fix fine days > my $debardate = > _debar_user_on_return( $borrower, $item, $issue->{date_due}, $today ); > $messages->{Debarred} = $debardate if ($debardate); >@@ -2093,139 +2105,107 @@ Internal function, called only by AddReturn > =cut > > sub _FixOverduesOnReturn { >- my ($borrowernumber, $item); >- unless ($borrowernumber = shift) { >- warn "_FixOverduesOnReturn() not supplied valid borrowernumber"; >- return; >- } >- unless ($item = shift) { >- warn "_FixOverduesOnReturn() not supplied valid itemnumber"; >- return; >- } >- my ($exemptfine, $dropbox) = @_; >+ my ( $params ) = @_; >+ >+ my $exemptfine = $params->{exempt_fine}; >+ my $dropbox = $params->{dropbox}; >+ my $issue = $params->{issue}; >+ > my $dbh = C4::Context->dbh; > >- # check for overdue fine >- my $sth = $dbh->prepare( >-"SELECT * FROM accountlines WHERE (borrowernumber = ?) AND (itemnumber = ?) AND (accounttype='FU' OR accounttype='O')" >- ); >- $sth->execute( $borrowernumber, $item ); >+ my $schema = Koha::Database->new()->schema; >+ my $fine = >+ $schema->resultset('AccountDebit') >+ ->single( { issue_id => $issue->issue_id(), type => Koha::Accounts::DebitTypes::Fine() } ); > >- # alter fine to show that the book has been returned >- my $data = $sth->fetchrow_hashref; >- return 0 unless $data; # no warning, there's just nothing to fix >+ return unless ( $fine ); >+ >+ $fine->accruing(0); > >- my $uquery; >- my @bind = ($data->{'accountlines_id'}); > if ($exemptfine) { >- $uquery = "update accountlines set accounttype='FFOR', amountoutstanding=0"; >- if (C4::Context->preference("FinesLog")) { >- &logaction("FINES", 'MODIFY',$borrowernumber,"Overdue forgiven: item $item"); >- } >- } elsif ($dropbox && $data->{lastincrement}) { >- my $outstanding = $data->{amountoutstanding} - $data->{lastincrement} ; >- my $amt = $data->{amount} - $data->{lastincrement} ; >+ AddCredit( >+ { >+ borrower => $fine->borrowernumber(), >+ amount => $fine->amount_original(), >+ debit_id => $fine->debit_id(), >+ type => Koha::Accounts::CreditTypes::Forgiven(), >+ } >+ ); > if (C4::Context->preference("FinesLog")) { >- &logaction("FINES", 'MODIFY',$borrowernumber,"Dropbox adjustment $amt, item $item"); >+ &logaction( >+ "FINES", 'MODIFY', >+ $issue->borrowernumber(), >+ "Overdue forgiven: item " . $issue->itemnumber() >+ ); > } >- $uquery = "update accountlines set accounttype='F' "; >- if($outstanding >= 0 && $amt >=0) { >- $uquery .= ", amount = ? , amountoutstanding=? "; >- unshift @bind, ($amt, $outstanding) ; >+ } elsif ($dropbox && $fine->amount_last_increment() != $fine->amount_original() ) { >+ if ( C4::Context->preference("FinesLog") ) { >+ &logaction( "FINES", 'MODIFY', $issue->borrowernumber(), >+ "Dropbox adjustment " >+ . $fine->amount_last_increment() >+ . ", item " . $issue->itemnumber() ); > } >- } else { >- $uquery = "update accountlines set accounttype='F' "; >+ $fine->amount_original( >+ $fine->amount_original() - $fine->amount_last_increment() ); >+ $fine->amount_outstanding( >+ $fine->amount_outstanding - $fine->amount_last_increment() ); >+ $schema->resultset('AccountOffset')->create( >+ { >+ debit_id => $fine->debit_id(), >+ type => Koha::Accounts::OffsetTypes::Dropbox(), >+ amount => $fine->amount_last_increment() * -1, >+ } >+ ); > } >- $uquery .= " where (accountlines_id = ?)"; >- my $usth = $dbh->prepare($uquery); >- return $usth->execute(@bind); >+ >+ return $fine->update(); > } > > =head2 _FixAccountForLostAndReturned > >- &_FixAccountForLostAndReturned($itemnumber, [$borrowernumber, $barcode]); >- >-Calculates the charge for a book lost and returned. >+ &_FixAccountForLostAndReturned($itemnumber); > >-Internal function, not exported, called only by AddReturn. >- >-FIXME: This function reflects how inscrutable fines logic is. Fix both. >-FIXME: Give a positive return value on success. It might be the $borrowernumber who received credit, or the amount forgiven. >+ Refunds a lost item fee in necessary > > =cut > > sub _FixAccountForLostAndReturned { >- my $itemnumber = shift or return; >- my $borrowernumber = @_ ? shift : undef; >- my $item_id = @_ ? shift : $itemnumber; # Send the barcode if you want that logged in the description >- my $dbh = C4::Context->dbh; >- # check for charge made for lost book >- my $sth = $dbh->prepare("SELECT * FROM accountlines WHERE itemnumber = ? AND accounttype IN ('L', 'Rep', 'W') ORDER BY date DESC, accountno DESC"); >- $sth->execute($itemnumber); >- my $data = $sth->fetchrow_hashref; >- $data or return; # bail if there is nothing to do >- $data->{accounttype} eq 'W' and return; # Written off >- >- # writeoff this amount >- my $offset; >- my $amount = $data->{'amount'}; >- my $acctno = $data->{'accountno'}; >- my $amountleft; # Starts off undef/zero. >- if ($data->{'amountoutstanding'} == $amount) { >- $offset = $data->{'amount'}; >- $amountleft = 0; # Hey, it's zero here, too. >- } else { >- $offset = $amount - $data->{'amountoutstanding'}; # Um, isn't this the same as ZERO? We just tested those two things are == >- $amountleft = $data->{'amountoutstanding'} - $amount; # Um, isn't this the same as ZERO? We just tested those two things are == >- } >- my $usth = $dbh->prepare("UPDATE accountlines SET accounttype = 'LR',amountoutstanding='0' >- WHERE (accountlines_id = ?)"); >- $usth->execute($data->{'accountlines_id'}); # We might be adjusting an account for some OTHER borrowernumber now. Not the one we passed in. >- #check if any credit is left if so writeoff other accounts >- my $nextaccntno = getnextacctno($data->{'borrowernumber'}); >- $amountleft *= -1 if ($amountleft < 0); >- if ($amountleft > 0) { >- my $msth = $dbh->prepare("SELECT * FROM accountlines WHERE (borrowernumber = ?) >- AND (amountoutstanding >0) ORDER BY date"); # might want to order by amountoustanding ASC (pay smallest first) >- $msth->execute($data->{'borrowernumber'}); >- # offset transactions >- my $newamtos; >- my $accdata; >- while (($accdata=$msth->fetchrow_hashref) and ($amountleft>0)){ >- if ($accdata->{'amountoutstanding'} < $amountleft) { >- $newamtos = 0; >- $amountleft -= $accdata->{'amountoutstanding'}; >- } else { >- $newamtos = $accdata->{'amountoutstanding'} - $amountleft; >- $amountleft = 0; >- } >- my $thisacct = $accdata->{'accountlines_id'}; >- # FIXME: move prepares outside while loop! >- my $usth = $dbh->prepare("UPDATE accountlines SET amountoutstanding= ? >- WHERE (accountlines_id = ?)"); >- $usth->execute($newamtos,$thisacct); >- $usth = $dbh->prepare("INSERT INTO accountoffsets >- (borrowernumber, accountno, offsetaccount, offsetamount) >- VALUES >- (?,?,?,?)"); >- $usth->execute($data->{'borrowernumber'},$accdata->{'accountno'},$nextaccntno,$newamtos); >+ my ( $itemnumber ) = @_; >+ >+ my $schema = Koha::Database->new()->schema; >+ >+ # Find the last issue for this item >+ my $issue = >+ $schema->resultset('Issue')->single( { itemnumber => $itemnumber } ); >+ $issue ||= >+ $schema->resultset('OldIssue')->single( { itemnumber => $itemnumber } ); >+ >+ return unless $issue; >+ >+ # Find a lost fee for this issue >+ my $debit = $schema->resultset('AccountDebit')->single( >+ { >+ issue_id => $issue->issue_id(), >+ type => Koha::Accounts::DebitTypes::Lost() > } >- } >- $amountleft *= -1 if ($amountleft > 0); >- my $desc = "Item Returned " . $item_id; >- $usth = $dbh->prepare("INSERT INTO accountlines >- (borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding) >- VALUES (?,?,now(),?,?,'CR',?)"); >- $usth->execute($data->{'borrowernumber'},$nextaccntno,0-$amount,$desc,$amountleft); >- if ($borrowernumber) { >- # FIXME: same as query above. use 1 sth for both >- $usth = $dbh->prepare("INSERT INTO accountoffsets >- (borrowernumber, accountno, offsetaccount, offsetamount) >- VALUES (?,?,?,?)"); >- $usth->execute($borrowernumber, $data->{'accountno'}, $nextaccntno, $offset); >- } >+ ); >+ >+ return unless $debit; >+ >+ # Check for an existing found credit for this debit, if there is one, the fee has already been refunded and we do nothing >+ my @credits = $debit->account_offsets->search_related('credit', { 'credit.type' => Koha::Accounts::CreditTypes::Found() }); >+ >+ return if @credits; >+ >+ # Ok, so we know we have an unrefunded lost item fee, let's refund it >+ CreditLostItem( >+ { >+ borrower => $issue->borrower(), >+ debit => $debit >+ } >+ ); >+ > ModItem({ paidfor => '' }, undef, $itemnumber); >- return; > } > > =head2 _GetCircControlBranch >@@ -2584,19 +2564,22 @@ sub AddRenewal { > # Charge a new rental fee, if applicable? > my ( $charge, $type ) = GetIssuingCharges( $itemnumber, $borrowernumber ); > if ( $charge > 0 ) { >- my $accountno = getnextacctno( $borrowernumber ); > my $item = GetBiblioFromItemNumber($itemnumber); >- my $manager_id = 0; >- $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv; >- $sth = $dbh->prepare( >- "INSERT INTO accountlines >- (date, borrowernumber, accountno, amount, manager_id, >- description,accounttype, amountoutstanding, itemnumber) >- VALUES (now(),?,?,?,?,?,?,?,?)" >+ >+ my $borrower = >+ Koha::Database->new()->schema->resultset('Borrower') >+ ->find($borrowernumber); >+ >+ AddDebit( >+ { >+ borrower => $borrower, >+ itemnumber => $itemnumber, >+ amount => $charge, >+ type => Koha::Accounts::DebitTypes::Rental(), >+ description => >+ "Renewal of Rental Item $item->{'title'} $item->{'barcode'}" >+ } > ); >- $sth->execute( $borrowernumber, $accountno, $charge, $manager_id, >- "Renewal of Rental Item $item->{'title'} $item->{'barcode'}", >- 'Rent', $charge, $itemnumber ); > } > > # Send a renewal slip according to checkout alert preferencei >@@ -2767,25 +2750,21 @@ sub _get_discount_from_rule { > > =head2 AddIssuingCharge > >- &AddIssuingCharge( $itemno, $borrowernumber, $charge ) >+ &AddIssuingCharge( $itemnumber, $borrowernumber, $amount ) > > =cut > > sub AddIssuingCharge { >- my ( $itemnumber, $borrowernumber, $charge ) = @_; >- my $dbh = C4::Context->dbh; >- my $nextaccntno = getnextacctno( $borrowernumber ); >- my $manager_id = 0; >- $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv; >- my $query =" >- INSERT INTO accountlines >- (borrowernumber, itemnumber, accountno, >- date, amount, description, accounttype, >- amountoutstanding, manager_id) >- VALUES (?, ?, ?,now(), ?, 'Rental', 'Rent',?,?) >- "; >- my $sth = $dbh->prepare($query); >- $sth->execute( $borrowernumber, $itemnumber, $nextaccntno, $charge, $charge, $manager_id ); >+ my ( $itemnumber, $borrowernumber, $amount ) = @_; >+ >+ return AddDebit( >+ { >+ borrower => Koha::Database->new()->schema->resultset('Borrower')->find($borrowernumber), >+ itemnumber => $itemnumber, >+ amount => $amount, >+ type => Koha::Accounts::DebitTypes::Rental(), >+ } >+ ); > } > > =head2 GetTransfers >@@ -3304,30 +3283,30 @@ sub ReturnLostItem{ > sub LostItem{ > my ($itemnumber, $mark_returned) = @_; > >- my $dbh = C4::Context->dbh(); >- my $sth=$dbh->prepare("SELECT issues.*,items.*,biblio.title >- FROM issues >- JOIN items USING (itemnumber) >- JOIN biblio USING (biblionumber) >- WHERE issues.itemnumber=?"); >- $sth->execute($itemnumber); >- my $issues=$sth->fetchrow_hashref(); >+ my $schema = Koha::Database->new()->schema; > >- # If a borrower lost the item, add a replacement cost to the their record >- if ( my $borrowernumber = $issues->{borrowernumber} ){ >- my $borrower = C4::Members::GetMemberDetails( $borrowernumber ); >+ my $issue = >+ $schema->resultset('Issue')->single( { itemnumber => $itemnumber } ); > >+ my $borrower = $issue->borrower(); >+ my $item = $issue->item(); >+ >+ # If a borrower lost the item, add a replacement cost to the their record >+ if ( $borrower ){ > if (C4::Context->preference('WhenLostForgiveFine')){ >- my $fix = _FixOverduesOnReturn($borrowernumber, $itemnumber, 1, 0); # 1, 0 = exemptfine, no-dropbox >- defined($fix) or warn "_FixOverduesOnReturn($borrowernumber, $itemnumber...) failed!"; # zero is OK, check defined >+ _FixOverduesOnReturn( >+ { >+ exempt_fine => 1, >+ dropbox => 0, >+ issue => $issue, >+ } >+ ); > } >- if (C4::Context->preference('WhenLostChargeReplacementFee')){ >- C4::Accounts::chargelostitem($borrowernumber, $itemnumber, $issues->{'replacementprice'}, "Lost Item $issues->{'title'} $issues->{'barcode'}"); >- #FIXME : Should probably have a way to distinguish this from an item that really was returned. >- #warn " $issues->{'borrowernumber'} / $itemnumber "; >+ if ( C4::Context->preference('WhenLostChargeReplacementFee') ) { >+ DebitLostItem( { borrower => $borrower, issue => $issue } ); > } > >- MarkIssueReturned($borrowernumber,$itemnumber,undef,undef,$borrower->{'privacy'}) if $mark_returned; >+ MarkIssueReturned( $borrower->borrowernumber(), $item->itemnumber(), undef, undef, $borrower->privacy() ) if $mark_returned; > } > } > >diff --git a/C4/Koha.pm b/C4/Koha.pm >index 937ac5f..4b9c4c5 100644 >--- a/C4/Koha.pm >+++ b/C4/Koha.pm >@@ -1029,6 +1029,7 @@ C<$opac> If set to a true value, displays OPAC descriptions rather than normal o > > sub GetAuthorisedValues { > my ( $category, $selected, $opac ) = @_; >+ warn "GetAuthorisedValues( $category, $selected, $opac )"; > my $branch_limit = C4::Context->userenv ? C4::Context->userenv->{"branch"} : ""; > my @results; > my $dbh = C4::Context->dbh; >@@ -1075,6 +1076,7 @@ sub GetAuthorisedValues { > push @results, $data; > } > $sth->finish; >+ warn "RET: " . Data::Dumper::Dumper( \@results ); > return \@results; > } > >diff --git a/C4/Members.pm b/C4/Members.pm >index b04cc64..b45147d 100644 >--- a/C4/Members.pm >+++ b/C4/Members.pm >@@ -29,7 +29,6 @@ use Date::Calc qw/Today Add_Delta_YM check_date Date_to_Days/; > use C4::Log; # logaction > use C4::Overdues; > use C4::Reserves; >-use C4::Accounts; > use C4::Biblio; > use C4::Letters; > use C4::SQLHelper qw(InsertInTable UpdateInTable SearchInTable); >@@ -41,6 +40,7 @@ use Koha::DateUtils; > use Koha::Borrower::Debarments qw(IsDebarred); > use Text::Unaccent qw( unac_string ); > use Koha::AuthUtils qw(hash_password); >+use Koha::Accounts::DebitTypes; > > our ($VERSION,@ISA,@EXPORT,@EXPORT_OK,$debug); > >@@ -83,8 +83,6 @@ BEGIN { > &GetHideLostItemsPreference > > &IsMemberBlocked >- &GetMemberAccountRecords >- &GetBorNotifyAcctRecord > > &GetborCatFromCatType > &GetBorrowercategory >@@ -338,9 +336,6 @@ sub GetMemberDetails { > return; > } > my $borrower = $sth->fetchrow_hashref; >- my ($amount) = GetMemberAccountRecords( $borrowernumber); >- $borrower->{'amountoutstanding'} = $amount; >- # FIXME - patronflags calls GetMemberAccountRecords... just have patronflags return $amount > my $flags = patronflags( $borrower); > my $accessflagshash; > >@@ -432,23 +427,20 @@ The "message" field that comes from the DB is OK. > # FIXME rename this function. > sub patronflags { > my %flags; >- my ( $patroninformation) = @_; >- my $dbh=C4::Context->dbh; >- my ($balance, $owing) = GetMemberAccountBalance( $patroninformation->{'borrowernumber'}); >- if ( $owing > 0 ) { >+ my ($patroninformation) = @_; >+ my $dbh = C4::Context->dbh; >+ if ( $patroninformation->{account_balance} > 0 ) { > my %flaginfo; > my $noissuescharge = C4::Context->preference("noissuescharge") || 5; >- $flaginfo{'message'} = sprintf 'Patron owes %.02f', $owing; >- $flaginfo{'amount'} = sprintf "%.02f", $owing; >- if ( $owing > $noissuescharge && !C4::Context->preference("AllowFineOverride") ) { >+ $flaginfo{'amount'} = $patroninformation->{account_balance}; >+ if ( $patroninformation->{account_balance} > $noissuescharge && !C4::Context->preference("AllowFineOverride") ) { > $flaginfo{'noissues'} = 1; > } > $flags{'CHARGES'} = \%flaginfo; > } >- elsif ( $balance < 0 ) { >+ elsif ( $patroninformation->{account_balance} < 0 ) { > my %flaginfo; >- $flaginfo{'message'} = sprintf 'Patron has credit of %.02f', -$balance; >- $flaginfo{'amount'} = sprintf "%.02f", $balance; >+ $flaginfo{'amount'} = $patroninformation->{account_balance}; > $flags{'CREDITS'} = \%flaginfo; > } > if ( $patroninformation->{'gonenoaddress'} >@@ -691,7 +683,7 @@ sub GetMemberIssuesAndFines { > $sth->execute($borrowernumber); > my $overdue_count = $sth->fetchrow_arrayref->[0]; > >- $sth = $dbh->prepare("SELECT SUM(amountoutstanding) FROM accountlines WHERE borrowernumber = ?"); >+ $sth = $dbh->prepare("SELECT account_balance FROM borrowers WHERE borrowernumber = ?"); > $sth->execute($borrowernumber); > my $total_fines = $sth->fetchrow_arrayref->[0]; > >@@ -1167,57 +1159,14 @@ sub GetAllIssues { > } > > >-=head2 GetMemberAccountRecords >- >- ($total, $acctlines, $count) = &GetMemberAccountRecords($borrowernumber); >- >-Looks up accounting data for the patron with the given borrowernumber. >- >-C<&GetMemberAccountRecords> returns a three-element array. C<$acctlines> is a >-reference-to-array, where each element is a reference-to-hash; the >-keys are the fields of the C<accountlines> table in the Koha database. >-C<$count> is the number of elements in C<$acctlines>. C<$total> is the >-total amount outstanding for all of the account lines. >- >-=cut >- >-sub GetMemberAccountRecords { >- my ($borrowernumber) = @_; >- my $dbh = C4::Context->dbh; >- my @acctlines; >- my $numlines = 0; >- my $strsth = qq( >- SELECT * >- FROM accountlines >- WHERE borrowernumber=?); >- $strsth.=" ORDER BY date desc,timestamp DESC"; >- my $sth= $dbh->prepare( $strsth ); >- $sth->execute( $borrowernumber ); >- >- my $total = 0; >- while ( my $data = $sth->fetchrow_hashref ) { >- if ( $data->{itemnumber} ) { >- my $biblio = GetBiblioFromItemNumber( $data->{itemnumber} ); >- $data->{biblionumber} = $biblio->{biblionumber}; >- $data->{title} = $biblio->{title}; >- } >- $acctlines[$numlines] = $data; >- $numlines++; >- $total += int(1000 * $data->{'amountoutstanding'}); # convert float to integer to avoid round-off errors >- } >- $total /= 1000; >- return ( $total, \@acctlines,$numlines); >-} >- > =head2 GetMemberAccountBalance > > ($total_balance, $non_issue_balance, $other_charges) = &GetMemberAccountBalance($borrowernumber); > > Calculates amount immediately owing by the patron - non-issue charges. >-Based on GetMemberAccountRecords. > Charges exempt from non-issue are: >-* Res (reserves) >-* Rent (rental) if RentalsInNoissuesCharge syspref is set to false >+* HOLD fees (reserves) >+* RENTAL if RentalsInNoissuesCharge syspref is set to false > * Manual invoices if ManInvInNoissuesCharge syspref is set to false > > =cut >@@ -1225,70 +1174,41 @@ Charges exempt from non-issue are: > sub GetMemberAccountBalance { > my ($borrowernumber) = @_; > >- my $ACCOUNT_TYPE_LENGTH = 5; # this is plain ridiculous... >+ my $borrower = >+ Koha::Database->new()->schema->resultset('Borrower') >+ ->find($borrowernumber); > >- my @not_fines = ('Res'); >- push @not_fines, 'Rent' unless C4::Context->preference('RentalsInNoissuesCharge'); >- unless ( C4::Context->preference('ManInvInNoissuesCharge') ) { >- my $dbh = C4::Context->dbh; >- my $man_inv_types = $dbh->selectcol_arrayref(qq{SELECT authorised_value FROM authorised_values WHERE category = 'MANUAL_INV'}); >- push @not_fines, map substr($_, 0, $ACCOUNT_TYPE_LENGTH), @$man_inv_types; >- } >- my %not_fine = map {$_ => 1} @not_fines; >+ my @not_fines; > >- my ($total, $acctlines) = GetMemberAccountRecords($borrowernumber); >- my $other_charges = 0; >- foreach (@$acctlines) { >- $other_charges += $_->{amountoutstanding} if $not_fine{ substr($_->{accounttype}, 0, $ACCOUNT_TYPE_LENGTH) }; >- } >- >- return ( $total, $total - $other_charges, $other_charges); >-} >- >-=head2 GetBorNotifyAcctRecord >- >- ($total, $acctlines, $count) = &GetBorNotifyAcctRecord($params,$notifyid); >+ push( @not_fines, Koha::Accounts::DebitTypes::Hold() ); > >-Looks up accounting data for the patron with the given borrowernumber per file number. >+ push( @not_fines, Koha::Accounts::DebitTypes::Rental() ) >+ unless C4::Context->preference('RentalsInNoissuesCharge'); > >-C<&GetBorNotifyAcctRecord> returns a three-element array. C<$acctlines> is a >-reference-to-array, where each element is a reference-to-hash; the >-keys are the fields of the C<accountlines> table in the Koha database. >-C<$count> is the number of elements in C<$acctlines>. C<$total> is the >-total amount outstanding for all of the account lines. >- >-=cut >+ unless ( C4::Context->preference('ManInvInNoissuesCharge') ) { >+ my $dbh = C4::Context->dbh; >+ my $man_inv_types = $dbh->selectcol_arrayref( >+ qq{SELECT authorised_value FROM authorised_values WHERE category = 'MANUAL_INV'} >+ ); >+ push( @not_fines, @$man_inv_types ); >+ } > >-sub GetBorNotifyAcctRecord { >- my ( $borrowernumber, $notifyid ) = @_; >- my $dbh = C4::Context->dbh; >- my @acctlines; >- my $numlines = 0; >- my $sth = $dbh->prepare( >- "SELECT * >- FROM accountlines >- WHERE borrowernumber=? >- AND notify_id=? >- AND amountoutstanding != '0' >- ORDER BY notify_id,accounttype >- "); >- >- $sth->execute( $borrowernumber, $notifyid ); >- my $total = 0; >- while ( my $data = $sth->fetchrow_hashref ) { >- if ( $data->{itemnumber} ) { >- my $biblio = GetBiblioFromItemNumber( $data->{itemnumber} ); >- $data->{biblionumber} = $biblio->{biblionumber}; >- $data->{title} = $biblio->{title}; >+ my $other_charges = >+ Koha::Database->new()->schema->resultset('AccountDebit')->search( >+ { >+ borrowernumber => $borrowernumber, >+ type => { -not_in => \@not_fines } > } >- $acctlines[$numlines] = $data; >- $numlines++; >- $total += int(100 * $data->{'amountoutstanding'}); >- } >- $total /= 100; >- return ( $total, \@acctlines, $numlines ); >+ )->get_column('amount_outstanding')->sum(); >+ >+ return ( >+ $borrower->account_balance(), >+ $borrower->account_balance() - $other_charges, >+ $other_charges >+ ); > } > >+ > =head2 checkuniquemember (OUEST-PROVENCE) > > ($result,$categorycode) = &checkuniquemember($collectivity,$surname,$firstname,$dateofbirth); >diff --git a/C4/Overdues.pm b/C4/Overdues.pm >index 33dbd98..0764dd4 100644 >--- a/C4/Overdues.pm >+++ b/C4/Overdues.pm >@@ -25,9 +25,10 @@ use Date::Calc qw/Today Date_to_Days/; > use Date::Manip qw/UnixDate/; > use C4::Circulation; > use C4::Context; >-use C4::Accounts; > use C4::Log; # logaction > use C4::Debug; >+use Koha::Database; >+use Koha::DateUtils; > > use vars qw($VERSION @ISA @EXPORT); > >@@ -41,12 +42,9 @@ BEGIN { > &CalcFine > &Getoverdues > &checkoverdues >- &NumberNotifyId >- &AmountNotify > &UpdateFine > &GetFine > >- &CheckItemNotify > &GetOverduesForBranch > &RemoveNotifyLine > &AddNotifyLine >@@ -456,154 +454,112 @@ sub GetIssuesIteminfo { > > =head2 UpdateFine > >- &UpdateFine($itemnumber, $borrowernumber, $amount, $type, $description); >+ UpdateFine( >+ { >+ itemnumber => $itemnumber, >+ borrowernumber => $borrowernumber, >+ amount => $amount, >+ due => $due, >+ issue_id => $issue_id >+ } >+ ); > >-(Note: the following is mostly conjecture and guesswork.) >+Updates the fine owed on an overdue item. > >-Updates the fine owed on an overdue book. >+C<$itemnumber> is the items's id. > >-C<$itemnumber> is the book's item number. >+C<$borrowernumber> is the id of the patron who currently >+has the item on loan. > >-C<$borrowernumber> is the borrower number of the patron who currently >-has the book on loan. >+C<$amount> is the total amount of the fine owed by the patron. > >-C<$amount> is the current amount owed by the patron. >+C<&UpdateFine> updates the amount owed for a given fine if an issue_id >+is passed to it. Otherwise, a new fine will be created. > >-C<$type> will be used in the description of the fine. >+=cut > >-C<$description> is a string that must be present in the description of >-the fine. I think this is expected to be a date in DD/MM/YYYY format. >+sub UpdateFine { >+ my ($params) = @_; > >-C<&UpdateFine> looks up the amount currently owed on the given item >-and sets it to C<$amount>, creating, if necessary, a new entry in the >-accountlines table of the Koha database. >+ my $itemnumber = $params->{itemnumber}; >+ my $borrowernumber = $params->{borrowernumber}; >+ my $amount = $params->{amount}; >+ my $due = $params->{due}; >+ my $issue_id = $params->{issue_id}; > >-=cut >+ my $schema = Koha::Database->new()->schema; > >-# >-# Question: Why should the caller have to >-# specify both the item number and the borrower number? A book can't >-# be on loan to two different people, so the item number should be >-# sufficient. >-# >-# Possible Answer: You might update a fine for a damaged item, *after* it is returned. >-# >-sub UpdateFine { >- my ( $itemnum, $borrowernumber, $amount, $type, $due ) = @_; >- $debug and warn "UpdateFine($itemnum, $borrowernumber, $amount, " . ($type||'""') . ", $due) called"; >- my $dbh = C4::Context->dbh; >- # FIXME - What exactly is this query supposed to do? It looks up an >- # entry in accountlines that matches the given item and borrower >- # numbers, where the description contains $due, and where the >- # account type has one of several values, but what does this _mean_? >- # Does it look up existing fines for this item? >- # FIXME - What are these various account types? ("FU", "O", "F", "M") >- # "L" is LOST item >- # "A" is Account Management Fee >- # "N" is New Card >- # "M" is Sundry >- # "O" is Overdue ?? >- # "F" is Fine ?? >- # "FU" is Fine UPDATE?? >- # "Pay" is Payment >- # "REF" is Cash Refund >- my $sth = $dbh->prepare( >- "SELECT * FROM accountlines >- WHERE borrowernumber=? >- AND accounttype IN ('FU','O','F','M')" >- ); >- $sth->execute( $borrowernumber ); >- my $data; >- my $total_amount_other = 0.00; >- my $due_qr = qr/$due/; >- # Cycle through the fines and >- # - find line that relates to the requested $itemnum >- # - accumulate fines for other items >- # so we can update $itemnum fine taking in account fine caps >- while (my $rec = $sth->fetchrow_hashref) { >- if ($rec->{itemnumber} == $itemnum && $rec->{description} =~ /$due_qr/) { >- if ($data) { >- warn "Not a unique accountlines record for item $itemnum borrower $borrowernumber"; >- } else { >- $data = $rec; >- next; >- } >- } >- $total_amount_other += $rec->{'amountoutstanding'}; >- } >+ my $borrower = $schema->resultset('Borrower')->find($borrowernumber); > >- if (my $maxfine = C4::Context->preference('MaxFine')) { >- if ($total_amount_other + $amount > $maxfine) { >- my $new_amount = $maxfine - $total_amount_other; >- return if $new_amount <= 0.00; >- warn "Reducing fine for item $itemnum borrower $borrowernumber from $amount to $new_amount - MaxFine reached"; >+ if ( my $maxfine = C4::Context->preference('MaxFine') ) { >+ if ( $borrower->account_balance() + $amount > $maxfine ) { >+ my $new_amount = $maxfine - $borrower->account_balance(); >+ warn "Reducing fine for item $itemnumber borrower $borrowernumber from $amount to $new_amount - MaxFine reached"; >+ if ( $new_amount <= 0 ) { >+ warn "Fine reduced to a non-positive ammount. Fine not created."; >+ return; >+ } > $amount = $new_amount; > } > } > >- if ( $data ) { >- >- # we're updating an existing fine. Only modify if amount changed >- # Note that in the current implementation, you cannot pay against an accruing fine >- # (i.e. , of accounttype 'FU'). Doing so will break accrual. >- if ( $data->{'amount'} != $amount ) { >- my $diff = $amount - $data->{'amount'}; >- #3341: diff could be positive or negative! >- my $out = $data->{'amountoutstanding'} + $diff; >- my $query = " >- UPDATE accountlines >- SET date=now(), amount=?, amountoutstanding=?, >- lastincrement=?, accounttype='FU' >- WHERE borrowernumber=? >- AND itemnumber=? >- AND accounttype IN ('FU','O') >- AND description LIKE ? >- LIMIT 1 "; >- my $sth2 = $dbh->prepare($query); >- # FIXME: BOGUS query cannot ensure uniqueness w/ LIKE %x% !!! >- # LIMIT 1 added to prevent multiple affected lines >- # FIXME: accountlines table needs unique key!! Possibly a combo of borrowernumber and accountline. >- # But actually, we should just have a regular autoincrementing PK and forget accountline, >- # including the bogus getnextaccountno function (doesn't prevent conflict on simultaneous ops). >- # FIXME: Why only 2 account types here? >- $debug and print STDERR "UpdateFine query: $query\n" . >- "w/ args: $amount, $out, $diff, $data->{'borrowernumber'}, $data->{'itemnumber'}, \"\%$due\%\"\n"; >- $sth2->execute($amount, $out, $diff, $data->{'borrowernumber'}, $data->{'itemnumber'}, "%$due%"); >- } else { >- # print "no update needed $data->{'amount'}" >+ my $timestamp = get_timestamp(); >+ >+ my $fine = >+ $schema->resultset('AccountDebit')->single( { issue_id => $issue_id } ); >+ >+ my $offset = 0; >+ if ($fine) { >+ if ( >+ sprintf( "%.6f", $fine->amount_original() ) >+ ne >+ sprintf( "%.6f", $amount ) ) >+ { >+ my $difference = $amount - $fine->amount_original(); >+ >+ $fine->amount_original( $fine->amount_original() + $difference ); >+ $fine->amount_outstanding( $fine->amount_outstanding() + $difference ); >+ $fine->amount_last_increment($difference); >+ $fine->updated_on($timestamp); >+ $fine->update(); >+ >+ $offset = 1; > } >- } else { >- my $sth4 = $dbh->prepare( >- "SELECT title FROM biblio LEFT JOIN items ON biblio.biblionumber=items.biblionumber WHERE items.itemnumber=?" >+ } >+ else { >+ my $item = $schema->resultset('Item')->find($itemnumber); >+ >+ $fine = $schema->resultset('AccountDebit')->create( >+ { >+ borrowernumber => $borrowernumber, >+ itemnumber => $itemnumber, >+ issue_id => $issue_id, >+ type => Koha::Accounts::DebitTypes::Fine(), >+ accruing => 1, >+ amount_original => $amount, >+ amount_outstanding => $amount, >+ amount_last_increment => $amount, >+ description => $item->biblio()->title() . " / Due:$due", >+ created_on => $timestamp, >+ } > ); >- $sth4->execute($itemnum); >- my $title = $sth4->fetchrow; >- >-# # print "not in account"; >-# my $sth3 = $dbh->prepare("Select max(accountno) from accountlines"); >-# $sth3->execute; >-# >-# # FIXME - Make $accountno a scalar. >-# my @accountno = $sth3->fetchrow_array; >-# $sth3->finish; >-# $accountno[0]++; >-# begin transaction >- my $nextaccntno = C4::Accounts::getnextacctno($borrowernumber); >- my $desc = ($type ? "$type " : '') . "$title $due"; # FIXEDME, avoid whitespace prefix on empty $type >- my $query = "INSERT INTO accountlines >- (borrowernumber,itemnumber,date,amount,description,accounttype,amountoutstanding,lastincrement,accountno) >- VALUES (?,?,now(),?,?,'FU',?,?,?)"; >- my $sth2 = $dbh->prepare($query); >- $debug and print STDERR "UpdateFine query: $query\nw/ args: $borrowernumber, $itemnum, $amount, $desc, $amount, $amount, $nextaccntno\n"; >- $sth2->execute($borrowernumber, $itemnum, $amount, $desc, $amount, $amount, $nextaccntno); >+ >+ $offset = 1; > } >- # logging action >- &logaction( >- "FINES", >- $type, >+ >+ $schema->resultset('AccountOffset')->create( >+ { >+ debit_id => $fine->debit_id(), >+ amount => $fine->amount_last_increment(), >+ created_on => $timestamp, >+ type => Koha::Accounts::OffsetTypes::Fine(), >+ } >+ ) if $offset; >+ >+ logaction( "FINES", Koha::Accounts::DebitTypes::Fine(), > $borrowernumber, >- "due=".$due." amount=".$amount." itemnumber=".$itemnum >- ) if C4::Context->preference("FinesLog"); >+ "due=" . $due . " amount=" . $amount . " itemnumber=" . $itemnumber ) >+ if C4::Context->preference("FinesLog"); > } > > =head2 BorType >@@ -644,70 +600,19 @@ C<$borrowernumber> is the borrowernumber > =cut > > sub GetFine { >- my ( $itemnum, $borrowernumber ) = @_; >- my $dbh = C4::Context->dbh(); >- my $query = q|SELECT sum(amountoutstanding) as fineamount FROM accountlines >- where accounttype like 'F%' >- AND amountoutstanding > 0 AND itemnumber = ? AND borrowernumber=?|; >- my $sth = $dbh->prepare($query); >- $sth->execute( $itemnum, $borrowernumber ); >- my $fine = $sth->fetchrow_hashref(); >- if ($fine->{fineamount}) { >- return $fine->{fineamount}; >- } >- return 0; >-} >- >-=head2 NumberNotifyId >+ my ( $itemnumber, $borrowernumber ) = @_; > >- (@notify) = &NumberNotifyId($borrowernumber); >+ my $schema = Koha::Database->new()->schema; > >-Returns amount for all file per borrowers >-C<@notify> array contains all file per borrowers >+ my $amount_outstanding = $schema->resultset('AccountDebit')->search( >+ { >+ itemnumber => $itemnumber, >+ borrowernumber => $borrowernumber, >+ type => Koha::Accounts::DebitTypes::Fine(), >+ }, >+ )->get_column('amount_outstanding')->sum(); > >-C<$notify_id> contains the file number for the borrower number nad item number >- >-=cut >- >-sub NumberNotifyId{ >- my ($borrowernumber)=@_; >- my $dbh = C4::Context->dbh; >- my $query=qq| SELECT distinct(notify_id) >- FROM accountlines >- WHERE borrowernumber=?|; >- my @notify; >- my $sth = $dbh->prepare($query); >- $sth->execute($borrowernumber); >- while ( my ($numberofnotify) = $sth->fetchrow ) { >- push( @notify, $numberofnotify ); >- } >- return (@notify); >-} >- >-=head2 AmountNotify >- >- ($totalnotify) = &AmountNotify($notifyid); >- >-Returns amount for all file per borrowers >-C<$notifyid> is the file number >- >-C<$totalnotify> contains amount of a file >- >-C<$notify_id> contains the file number for the borrower number and item number >- >-=cut >- >-sub AmountNotify{ >- my ($notifyid,$borrowernumber)=@_; >- my $dbh = C4::Context->dbh; >- my $query=qq| SELECT sum(amountoutstanding) >- FROM accountlines >- WHERE notify_id=? AND borrowernumber = ?|; >- my $sth=$dbh->prepare($query); >- $sth->execute($notifyid,$borrowernumber); >- my $totalnotify=$sth->fetchrow; >- $sth->finish; >- return ($totalnotify); >+ return $amount_outstanding; > } > > =head2 GetItems >@@ -759,27 +664,6 @@ sub GetBranchcodesWithOverdueRules { > return @branches; > } > >-=head2 CheckItemNotify >- >-Sql request to check if the document has alreday been notified >-this function is not exported, only used with GetOverduesForBranch >- >-=cut >- >-sub CheckItemNotify { >- my ($notify_id,$notify_level,$itemnumber) = @_; >- my $dbh = C4::Context->dbh; >- my $sth = $dbh->prepare(" >- SELECT COUNT(*) >- FROM notifys >- WHERE notify_id = ? >- AND notify_level = ? >- AND itemnumber = ? "); >- $sth->execute($notify_id,$notify_level,$itemnumber); >- my $notified = $sth->fetchrow; >- return ($notified); >-} >- > =head2 GetOverduesForBranch > > Sql request for display all information for branchoverdues.pl >@@ -804,6 +688,7 @@ sub GetOverduesForBranch { > biblio.title, > biblio.author, > biblio.biblionumber, >+ issues.issue_id, > issues.date_due, > issues.returndate, > issues.branchcode, >@@ -814,25 +699,23 @@ sub GetOverduesForBranch { > items.location, > items.itemnumber, > itemtypes.description, >- accountlines.notify_id, >- accountlines.notify_level, >- accountlines.amountoutstanding >- FROM accountlines >- LEFT JOIN issues ON issues.itemnumber = accountlines.itemnumber >- AND issues.borrowernumber = accountlines.borrowernumber >- LEFT JOIN borrowers ON borrowers.borrowernumber = accountlines.borrowernumber >+ account_debits.amount_outstanding >+ FROM account_debits >+ LEFT JOIN issues ON issues.itemnumber = account_debits.itemnumber >+ AND issues.borrowernumber = account_debits.borrowernumber >+ LEFT JOIN borrowers ON borrowers.borrowernumber = account_debits.borrowernumber > LEFT JOIN items ON items.itemnumber = issues.itemnumber > LEFT JOIN biblio ON biblio.biblionumber = items.biblionumber > LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber > LEFT JOIN itemtypes ON itemtypes.itemtype = $itype_link > LEFT JOIN branches ON branches.branchcode = issues.branchcode >- WHERE (accountlines.amountoutstanding != '0.000000') >- AND (accountlines.accounttype = 'FU' ) >+ WHERE (account_debits.amount_outstanding != '0.000000') >+ AND (account_debits.type = 'FINE') >+ AND (account_debits.accruing = 1 ) > AND (issues.branchcode = ? ) > AND (issues.date_due < NOW()) > "; > my @getoverdues; >- my $i = 0; > my $sth; > if ($location) { > $sth = $dbh->prepare("$select AND items.location = ? ORDER BY borrowers.surname, borrowers.firstname"); >@@ -842,12 +725,7 @@ sub GetOverduesForBranch { > $sth->execute($branch); > } > while ( my $data = $sth->fetchrow_hashref ) { >- #check if the document has already been notified >- my $countnotify = CheckItemNotify($data->{'notify_id'}, $data->{'notify_level'}, $data->{'itemnumber'}); >- if ($countnotify eq '0') { >- $getoverdues[$i] = $data; >- $i++; >- } >+ push( @getoverdues, $data ); > } > return (@getoverdues); > } >diff --git a/C4/Reports/Guided.pm b/C4/Reports/Guided.pm >index 22a23dd..8440576 100644 >--- a/C4/Reports/Guided.pm >+++ b/C4/Reports/Guided.pm >@@ -92,18 +92,27 @@ my %table_areas = ( > CAT => [ 'items', 'biblioitems', 'biblio' ], > PAT => ['borrowers'], > ACQ => [ 'aqorders', 'biblio', 'items' ], >- ACC => [ 'borrowers', 'accountlines' ], >+ ACC => [ 'borrowers', 'account_credits', 'account_debits' ], > ); > my %keys = ( >- CIRC => [ 'statistics.borrowernumber=borrowers.borrowernumber', >- 'items.itemnumber = statistics.itemnumber', >- 'biblioitems.biblioitemnumber = items.biblioitemnumber' ], >- CAT => [ 'items.biblioitemnumber=biblioitems.biblioitemnumber', >- 'biblioitems.biblionumber=biblio.biblionumber' ], >- PAT => [], >- ACQ => [ 'aqorders.biblionumber=biblio.biblionumber', >- 'biblio.biblionumber=items.biblionumber' ], >- ACC => ['borrowers.borrowernumber=accountlines.borrowernumber'], >+ CIRC => [ >+ 'statistics.borrowernumber=borrowers.borrowernumber', >+ 'items.itemnumber = statistics.itemnumber', >+ 'biblioitems.biblioitemnumber = items.biblioitemnumber' >+ ], >+ CAT => [ >+ 'items.biblioitemnumber=biblioitems.biblioitemnumber', >+ 'biblioitems.biblionumber=biblio.biblionumber' >+ ], >+ PAT => [], >+ ACQ => [ >+ 'aqorders.biblionumber=biblio.biblionumber', >+ 'biblio.biblionumber=items.biblionumber' >+ ], >+ ACC => [ >+ 'borrowers.borrowernumber=account_credits.borrowernumber', >+ 'borrowers.borrowernumber=account_debits.borrowernumber' >+ ], > ); > > # have to do someting here to know if its dropdown, free text, date etc >diff --git a/C4/Reserves.pm b/C4/Reserves.pm >index d1bca25..285ad9a 100644 >--- a/C4/Reserves.pm >+++ b/C4/Reserves.pm >@@ -28,7 +28,6 @@ use C4::Biblio; > use C4::Members; > use C4::Items; > use C4::Circulation; >-use C4::Accounts; > > # for _koha_notify_reserve > use C4::Members::Messaging; >@@ -172,19 +171,17 @@ sub AddReserve { > $waitingdate = $resdate; > } > >- #eval { >- # updates take place here > if ( $fee > 0 ) { >- my $nextacctno = &getnextacctno( $borrowernumber ); >- my $query = qq/ >- INSERT INTO accountlines >- (borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding) >- VALUES >- (?,?,now(),?,?,'Res',?) >- /; >- my $usth = $dbh->prepare($query); >- $usth->execute( $borrowernumber, $nextacctno, $fee, >- "Reserve Charge - $title", $fee ); >+ AddDebit( >+ { >+ borrowernumber => $borrowernumber, >+ itemnumber => $checkitem, >+ amount => $fee, >+ type => Koha::Accounts::DebitTypes::Hold(), >+ description => "Hold fee - $title", >+ notes => "Record ID: $biblionumber", >+ } >+ ); > } > > #if ($const eq 'a'){ >diff --git a/C4/SIP/ILS/Patron.pm b/C4/SIP/ILS/Patron.pm >index 5b835ca..83621d2 100644 >--- a/C4/SIP/ILS/Patron.pm >+++ b/C4/SIP/ILS/Patron.pm >@@ -85,7 +85,7 @@ sub new { > hold_ok => ( !$debarred && !$expired ), > card_lost => ( $kp->{lost} || $kp->{gonenoaddress} || $flags->{LOST} ), > claims_returned => 0, >- fines => $fines_amount, # GetMemberAccountRecords($kp->{borrowernumber}) >+ fines => $fines_amount, > fees => 0, # currently not distinct from fines > recall_overdue => 0, > items_billed => 0, >diff --git a/Koha/Accounts.pm b/Koha/Accounts.pm >new file mode 100644 >index 0000000..37ac26c >--- /dev/null >+++ b/Koha/Accounts.pm >@@ -0,0 +1,535 @@ >+package Koha::Accounts; >+ >+# Copyright 2013 ByWater Solutions >+# >+# 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 Modern::Perl; >+ >+use Carp; >+use Data::Dumper qw(Dumper); >+ >+use C4::Context; >+use C4::Log qw(logaction); >+use Koha::DateUtils qw(get_timestamp); >+ >+use Koha::Accounts::CreditTypes; >+use Koha::Accounts::DebitTypes; >+ >+use vars qw($VERSION @ISA @EXPORT); >+ >+BEGIN { >+ require Exporter; >+ @ISA = qw(Exporter); >+ @EXPORT = qw( >+ AddDebit >+ AddCredit >+ >+ NormalizeBalances >+ >+ RecalculateAccountBalance >+ >+ DebitLostItem >+ CreditLostItem >+ ); >+} >+ >+=head1 NAME >+ >+Koha::Accounts - Functions for dealing with Koha accounts >+ >+=head1 SYNOPSIS >+ >+use Koha::Accounts; >+ >+=head1 DESCRIPTION >+ >+The functions in this module deal with the monetary aspect of Koha, >+including looking up and modifying the amount of money owed by a >+patron. >+ >+=head1 FUNCTIONS >+ >+=head2 AddDebit >+ >+my $debit = AddDebit({ >+ borrower => $borrower, >+ amount => $amount, >+ [ type => $type, ] >+ [ itemnumber => $itemnumber, ] >+ [ issue_id => $issue_id, ] >+ [ description => $description, ] >+ [ notes => $notes, ] >+ [ branchcode => $branchcode, ] >+ [ manager_id => $manager_id, ] >+ [ accruing => $accruing, ] # Default 0 if not accruing, 1 if accruing >+}); >+ >+Create a new debit for a given borrower. To standardize nomenclature, any charge >+against a borrower ( e.g. a fine, a new card charge, the cost of losing an item ) >+will be referred to as a 'debit'. >+ >+=cut >+ >+sub AddDebit { >+ my ($params) = @_; >+ >+ my $borrower = $params->{borrower}; >+ my $amount = $params->{amount}; >+ >+ my $type = $params->{type}; >+ my $itemnumber = $params->{itemnumber}; >+ my $issue_id = $params->{issue_id}; >+ my $description = $params->{description}; >+ my $notes = $params->{notes}; >+ >+ my $branchcode = $params->{branchcode}; >+ $branchcode ||= >+ defined( C4::Context->userenv ) >+ ? C4::Context->userenv->{branch} >+ : undef; >+ >+ my $manager_id = $params->{manager_id}; >+ $manager_id ||= >+ defined( C4::Context->userenv ) >+ ? C4::Context->userenv->{manager_id} >+ : undef; >+ >+ my $accruing = $params->{accruing} || 0; >+ >+ croak("Required parameter 'borrower' not passed in.") >+ unless ($borrower); >+ croak("Required parameter 'amount' not passed in.") >+ unless ($amount); >+ croak("Invalid debit type: '$type'!") >+ unless ( Koha::Accounts::DebitTypes::IsValid($type) ); >+ croak("No issue id passed in for accruing debit!") >+ if ( $accruing && !$issue_id ); >+ >+ my $debit = >+ Koha::Database->new()->schema->resultset('AccountDebit')->create( >+ { >+ borrowernumber => $borrower->borrowernumber(), >+ itemnumber => $itemnumber, >+ issue_id => $issue_id, >+ type => $type, >+ accruing => $accruing, >+ amount_original => $amount, >+ amount_outstanding => $amount, >+ amount_last_increment => $amount, >+ description => $description, >+ notes => $notes, >+ manager_id => $manager_id, >+ created_on => get_timestamp(), >+ } >+ ); >+ >+ if ($debit) { >+ $borrower->account_balance( $borrower->account_balance() + $amount ); >+ $borrower->update(); >+ >+ NormalizeBalances( { borrower => $borrower } ); >+ >+ if ( C4::Context->preference("FinesLog") ) { >+ logaction( "FINES", "CREATE_FEE", $debit->id, >+ Dumper( $debit->get_columns() ) ); >+ } >+ } >+ else { >+ carp("Something went wrong! Debit not created!"); >+ } >+ >+ return $debit; >+} >+ >+=head2 DebitLostItem >+ >+my $debit = DebitLostItem({ >+ borrower => $borrower, >+ issue => $issue, >+}); >+ >+DebitLostItem adds a replacement fee charge for the item >+of the given issue. >+ >+=cut >+ >+sub DebitLostItem { >+ my ($params) = @_; >+ >+ my $borrower = $params->{borrower}; >+ my $issue = $params->{issue}; >+ >+ croak("Required param 'borrower' not passed in!") unless ($borrower); >+ croak("Required param 'issue' not passed in!") unless ($issue); >+ >+# Don't add lost debit if borrower has already been charged for this lost item before, >+# for this issue. It seems reasonable that a borrower could lose an item, find and return it, >+# check it out again, and lose it again, so we should do this based on issue_id, not itemnumber. >+ unless ( >+ Koha::Database->new()->schema->resultset('AccountDebit')->search( >+ { >+ borrowernumber => $borrower->borrowernumber(), >+ issue_id => $issue->issue_id(), >+ type => Koha::Accounts::DebitTypes::Lost >+ } >+ )->count() >+ ) >+ { >+ my $item = $issue->item(); >+ >+ $params->{accruing} = 0; >+ $params->{type} = Koha::Accounts::DebitTypes::Lost; >+ $params->{amount} = $item->replacementprice(); >+ $params->{itemnumber} = $item->itemnumber(); >+ $params->{issue_id} = $issue->issue_id(); >+ >+ #TODO: Shouldn't we have a default replacement price as a syspref? >+ if ( $params->{amount} ) { >+ return AddDebit($params); >+ } >+ else { >+ carp("Cannot add lost debit! Item has no replacement price!"); >+ } >+ } >+} >+ >+=head2 CreditLostItem >+ >+my $debit = CreditLostItem( >+ { >+ borrower => $borrower, >+ debit => $debit, >+ } >+); >+ >+CreditLostItem creates a payment in the amount equal >+to the replacement price charge created by DebitLostItem. >+ >+=cut >+ >+sub CreditLostItem { >+ my ($params) = @_; >+ >+ my $borrower = $params->{borrower}; >+ my $debit = $params->{debit}; >+ >+ croak("Required param 'borrower' not passed in!") unless ($borrower); >+ croak("Required param 'debit' not passed in!") >+ unless ($debit); >+ >+ my $item = >+ Koha::Database->new()->schema->resultset('Item') >+ ->find( $debit->itemnumber() ); >+ carp("No item found!") unless $item; >+ >+ $params->{type} = Koha::Accounts::CreditTypes::Found; >+ $params->{amount} = $debit->amount_original(); >+ $params->{debit_id} = $debit->debit_id(); >+ $params->{notes} = "Lost item found: " . $item->barcode(); >+ >+ return AddCredit($params); >+} >+ >+=head2 AddCredit >+ >+AddCredit({ >+ borrower => $borrower, >+ amount => $amount, >+ [ branchcode => $branchcode, ] >+ [ manager_id => $manager_id, ] >+ [ debit_id => $debit_id, ] # The primary debit to be paid >+ [ notes => $notes, ] >+}); >+ >+Record credit by a patron. C<$borrowernumber> is the patron's >+borrower number. C<$credit> is a floating-point number, giving the >+amount that was paid. >+ >+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 credit >+of $1.50, then the oldest fine will be paid off in full, and $0.50 >+will be credited to the next one. >+ >+debit_id can be passed as a scalar or an array ref to make the passed >+in debit or debits the first to be credited. >+ >+=cut >+ >+sub AddCredit { >+ my ($params) = @_; >+ >+ my $type = $params->{type}; >+ my $borrower = $params->{borrower}; >+ my $amount = $params->{amount}; >+ my $amount_received = $params->{amount_received}; >+ my $debit_id = $params->{debit_id}; >+ my $notes = $params->{notes}; >+ my $branchcode = $params->{branchcode}; >+ my $manager_id = $params->{manager_id}; >+ >+ my $userenv = C4::Context->userenv; >+ >+ unless ( $manager_id || $userenv ) { >+ $manager_id = $userenv->{number}; >+ } >+ >+ unless ( $branchcode || $userenv ) { >+ $branchcode = $userenv->{branch}; >+ } >+ >+ unless ($borrower) { >+ croak("Required parameter 'borrower' not passed in"); >+ } >+ unless ($amount) { >+ croak("Required parameter amount not passed in"); >+ } >+ >+ unless ( Koha::Accounts::CreditTypes::IsValid($type) ) { >+ carp("Invalid credit type! Returning without creating credit."); >+ return; >+ } >+ >+ unless ($type) { >+ carp("No type passed in, assuming Payment"); >+ $type = Koha::Accounts::CreditTypes::Payment; >+ } >+ >+ my $debit = >+ Koha::Database->new()->schema->resultset('AccountDebit')->find($debit_id); >+ >+ # First, we make the credit. We'll worry about what we paid later on >+ my $credit = >+ Koha::Database->new()->schema->resultset('AccountCredit')->create( >+ { >+ borrowernumber => $borrower->borrowernumber(), >+ type => $type, >+ amount_received => $amount_received, >+ amount_paid => $amount, >+ amount_remaining => $amount, >+ notes => $notes, >+ manager_id => $manager_id, >+ created_on => get_timestamp(), >+ } >+ ); >+ >+ if ( C4::Context->preference("FinesLog") ) { >+ logaction( "FINES", "CREATE_PAYMENT", $credit->id, >+ Dumper( $credit->get_columns() ) ); >+ } >+ >+ $borrower->account_balance( $borrower->account_balance() - $amount ); >+ $borrower->update(); >+ >+ # If we are given specific debits, pay those ones first. >+ if ($debit_id) { >+ my @debit_ids = ref($debit_id) eq "ARRAY" ? @$debit_id : $debit_id; >+ foreach my $debit_id (@debit_ids) { >+ my $debit = >+ Koha::Database->new()->schema->resultset('AccountDebit') >+ ->find($debit_id); >+ >+ if ($debit) { >+ CreditDebit( { credit => $credit, debit => $debit } ); >+ } >+ else { >+ carp("Invalid debit_id passed in!"); >+ } >+ } >+ } >+ >+ # We still have leftover money, or we weren't given a specific debit to pay >+ if ( $credit->amount_remaining() > 0 ) { >+ my @debits = >+ Koha::Database->new()->schema->resultset('AccountDebit')->search( >+ { >+ borrowernumber => $borrower->borrowernumber(), >+ amount_outstanding => { '>' => '0' } >+ } >+ ); >+ >+ foreach my $debit (@debits) { >+ if ( $credit->amount_remaining() > 0 ) { >+ CreditDebit( >+ { >+ credit => $credit, >+ debit => $debit, >+ borrower => $borrower, >+ type => $type, >+ } >+ ); >+ } >+ } >+ } >+ >+ return $credit; >+} >+ >+=head2 CreditDebit >+ >+$account_offset = CreditDebit({ >+ credit => $credit, >+ debit => $debit, >+}); >+ >+Given a credit and a debit, this subroutine >+will pay the appropriate amount of the debit, >+update the debit's amount outstanding, the credit's >+amout remaining, and create the appropriate account >+offset. >+ >+=cut >+ >+sub CreditDebit { >+ my ($params) = @_; >+ >+ my $credit = $params->{credit}; >+ my $debit = $params->{debit}; >+ >+ croak("Required parameter 'credit' not passed in!") >+ unless $credit; >+ croak("Required parameter 'debit' not passed in!") unless $debit; >+ >+ my $amount_to_pay = >+ ( $debit->amount_outstanding() > $credit->amount_remaining() ) >+ ? $credit->amount_remaining() >+ : $debit->amount_outstanding(); >+ >+ if ( $amount_to_pay > 0 ) { >+ $debit->amount_outstanding( >+ $debit->amount_outstanding() - $amount_to_pay ); >+ $debit->update(); >+ >+ $credit->amount_remaining( >+ $credit->amount_remaining() - $amount_to_pay ); >+ $credit->update(); >+ >+ my $offset = >+ Koha::Database->new()->schema->resultset('AccountOffset')->create( >+ { >+ amount => $amount_to_pay * -1, >+ debit_id => $debit->id(), >+ credit_id => $credit->id(), >+ created_on => get_timestamp(), >+ } >+ ); >+ >+ if ( C4::Context->preference("FinesLog") ) { >+ logaction( "FINES", "MODIFY", $offset->id, >+ Dumper( $offset->get_columns() ) ); >+ } >+ >+ return $offset; >+ } >+} >+ >+=head2 RecalculateAccountBalance >+ >+$account_balance = RecalculateAccountBalance({ >+ borrower => $borrower >+}); >+ >+Recalculates a borrower's balance based on the >+sum of the amount outstanding for the borrower's >+debits minus the sum of the amount remaining for >+the borrowers credits. >+ >+TODO: Would it be better to use af.amount_original - ap.amount_paid for any reason? >+ Or, perhaps calculate both and compare the two, for error checking purposes. >+=cut >+ >+sub RecalculateAccountBalance { >+ my ($params) = @_; >+ >+ my $borrower = $params->{borrower}; >+ croak("Requred paramter 'borrower' not passed in!") >+ unless ($borrower); >+ >+ my $debits = >+ Koha::Database->new()->schema->resultset('AccountDebit') >+ ->search( { borrowernumber => $borrower->borrowernumber() } ); >+ my $amount_outstanding = $debits->get_column('amount_outstanding')->sum(); >+ >+ my $credits = >+ Koha::Database->new()->schema->resultset('AccountCredit') >+ ->search( { borrowernumber => $borrower->borrowernumber() } ); >+ my $amount_remaining = $credits->get_column('amount_remaining')->sum(); >+ >+ my $account_balance = $amount_outstanding - $amount_remaining; >+ $borrower->account_balance($account_balance); >+ $borrower->update(); >+ >+ return $account_balance; >+} >+ >+=head2 NormalizeBalances >+ >+ $account_balance = NormalizeBalances({ borrower => $borrower }); >+ >+ For a given borrower, this subroutine will find all debits >+ with an outstanding balance and all credits with an unused >+ amount remaining and will pay those debits with those credits. >+ >+=cut >+ >+sub NormalizeBalances { >+ my ($params) = @_; >+ >+ my $borrower = $params->{borrower}; >+ >+ croak("Required param 'borrower' not passed in!") unless $borrower; >+ >+ my @credits = >+ Koha::Database->new()->schema->resultset('AccountCredit')->search( >+ { >+ borrowernumber => $borrower->borrowernumber(), >+ amount_remaining => { '>' => '0' } >+ } >+ ); >+ >+ return unless @credits; >+ >+ my @debits = >+ Koha::Database->new()->schema->resultset('AccountDebit')->search( >+ { >+ borrowernumber => $borrower->borrowernumber(), >+ amount_outstanding => { '>' => '0' } >+ } >+ ); >+ >+ return unless @debits; >+ >+ foreach my $credit (@credits) { >+ foreach my $debit (@debits) { >+ if ( $credit->amount_remaining() >+ && $debit->amount_outstanding() ) >+ { >+ CreditDebit( { credit => $credit, debit => $debit } ); >+ } >+ } >+ } >+ >+ return RecalculateAccountBalance( { borrower => $borrower } ); >+} >+ >+1; >+__END__ >+ >+=head1 AUTHOR >+ >+Kyle M Hall <kyle@bywatersolutions.com> >+ >+=cut >diff --git a/Koha/Accounts/CreditTypes.pm b/Koha/Accounts/CreditTypes.pm >new file mode 100644 >index 0000000..d51ec93 >--- /dev/null >+++ b/Koha/Accounts/CreditTypes.pm >@@ -0,0 +1,117 @@ >+package Koha::Accounts::CreditTypes; >+ >+# Copyright 2013 ByWater Solutions >+# >+# 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 Modern::Perl; >+ >+=head1 NAME >+ >+Koha::AccountsCreditTypes - Module representing the enumerated data types for account fees >+ >+=head1 SYNOPSIS >+ >+use Koha::Accounts::CreditTypes; >+ >+my $type = Koha::Accounts::CreditTypes::Payment; >+ >+=head1 DESCRIPTION >+ >+The subroutines in this modules act as enumerated data types for the >+different credit types in Koha ( i.e. payments, writeoffs, etc. ) >+ >+=head1 FUNCTIONS >+ >+=head2 IsValid >+ >+This subroutine takes a given string and returns 1 if >+the string matches one of the data types, and 0 if not. >+ >+FIXME: Perhaps we should use Class::Inspector instead of hard >+coding the subs? It seems like it would be a major trade off >+of speed just so we don't update something in two separate places >+in the same file. >+ >+=cut >+ >+sub IsValid { >+ my ($string) = @_; >+ >+ my $is_valid = >+ ( $string eq Koha::Accounts::CreditTypes::Payment() >+ || $string eq Koha::Accounts::CreditTypes::WriteOff() >+ || $string eq Koha::Accounts::CreditTypes::Found() >+ || $string eq Koha::Accounts::CreditTypes::Credit() >+ || $string eq Koha::Accounts::CreditTypes::Forgiven() ); >+ >+ unless ($is_valid) { >+ $is_valid = >+ Koha::Database->new()->schema->resultset('AuthorisedValue') >+ ->count( >+ { category => 'ACCOUNT_CREDIT', authorised_value => $string } ); >+ } >+ >+ return $is_valid; >+} >+ >+=head2 Credit >+ >+=cut >+ >+sub Credit { >+ return 'CREDIT'; >+} >+ >+=head2 Payment >+ >+=cut >+ >+sub Payment { >+ return 'PAYMENT'; >+} >+ >+=head2 Writeoff >+ >+=cut >+ >+sub WriteOff { >+ return 'WRITEOFF'; >+} >+ >+=head2 Writeoff >+ >+=cut >+ >+sub Found { >+ return 'FOUND'; >+} >+ >+=head2 Forgiven >+ >+=cut >+ >+sub Forgiven { >+ return 'FORGIVEN'; >+} >+ >+1; >+ >+=head1 AUTHOR >+ >+Kyle M Hall <kyle@bywatersolutions.com> >+ >+=cut >diff --git a/Koha/Accounts/DebitTypes.pm b/Koha/Accounts/DebitTypes.pm >new file mode 100644 >index 0000000..3f30392 >--- /dev/null >+++ b/Koha/Accounts/DebitTypes.pm >@@ -0,0 +1,160 @@ >+package Koha::Accounts::DebitTypes; >+ >+# Copyright 2013 ByWater Solutions >+# >+# 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 Modern::Perl; >+ >+=head1 NAME >+ >+Koha::Accounts::DebitTypes - Module representing an enumerated data type for account fees >+ >+=head1 SYNOPSIS >+ >+use Koha::Accounts::DebitTypes; >+ >+my $type = Koha::Accounts::DebitTypes::Fine; >+ >+=head1 DESCRIPTION >+ >+The subroutines in this modules act as an enumerated data type >+for debit types ( stored in account_debits.type ) in Koha. >+ >+=head1 FUNCTIONS >+ >+=head2 IsValid >+ >+This subroutine takes a given string and returns 1 if >+the string matches one of the data types, and 0 if not. >+ >+=cut >+ >+sub IsValid { >+ my ($string) = @_; >+ >+ my $is_valid = >+ ( $string eq Koha::Accounts::DebitTypes::Fine() >+ || $string eq Koha::Accounts::DebitTypes::AccountManagementFee() >+ || $string eq Koha::Accounts::DebitTypes::Sundry() >+ || $string eq Koha::Accounts::DebitTypes::Lost() >+ || $string eq Koha::Accounts::DebitTypes::Hold() >+ || $string eq Koha::Accounts::DebitTypes::Rental() >+ || $string eq Koha::Accounts::DebitTypes::NewCard() ); >+ >+ unless ($is_valid) { >+ $is_valid = >+ Koha::Database->new()->schema->resultset('AuthorisedValue') >+ ->count( { category => 'MANUAL_INV', authorised_value => $string } ); >+ } >+ >+ return $is_valid; >+} >+ >+=head2 Fine >+ >+This data type represents a standard fine within Koha. >+ >+A fine still accruing no longer needs to be differiated by type >+from a fine done accuring. Instead, that differentication is made >+by which table the fine exists in, account_fees_accruing vs account_fees_accrued. >+ >+In addition, fines can be checked for correctness based on the issue_id >+they have. A fine in account_fees_accruing should always have a matching >+issue_id in the issues table. A fine done accruing will almost always have >+a matching issue_id in the old_issues table. However, in the case of an overdue >+item with fines that has been renewed, and becomes overdue again, you may have >+a case where a given issue may have a matching fine in account_fees_accruing and >+one or more matching fines in account_fees_accrued ( one for each for the first >+checkout and one each for any subsequent renewals ) >+ >+=cut >+ >+sub Fine { >+ return 'FINE'; >+} >+ >+=head2 AccountManagementFee >+ >+This fee type is usually reserved for payments for library cards, >+in cases where a library must charge a patron for the ability to >+check out items. >+ >+=cut >+ >+sub AccountManagementFee { >+ return 'ACCOUNT_MANAGEMENT_FEE'; >+} >+ >+=head2 Sundry >+ >+This fee type is basically a 'misc' type, and should be used >+when no other fee type is more appropriate. >+ >+=cut >+ >+sub Sundry { >+ return 'SUNDRY'; >+} >+ >+=head2 Lost >+ >+This fee type is used when a library charges for lost items. >+ >+=cut >+ >+sub Lost { >+ return 'LOST'; >+} >+ >+=head2 Hold >+ >+This fee type is used when a library charges for holds. >+ >+=cut >+ >+sub Hold { >+ return 'HOLD'; >+} >+ >+=head2 Rental >+ >+This fee type is used when a library charges a rental fee for the item type. >+ >+=cut >+ >+sub Rental { >+ return 'RENTAL'; >+} >+ >+=head2 NewCard >+ >+This fee type is used when a library charges for replacement >+library cards. >+ >+=cut >+ >+sub NewCard { >+ return 'NEW_CARD'; >+} >+ >+1; >+ >+=head1 AUTHOR >+ >+Kyle M Hall <kyle@bywatersolutions.com> >+ >+=cut >diff --git a/Koha/Accounts/OffsetTypes.pm b/Koha/Accounts/OffsetTypes.pm >new file mode 100644 >index 0000000..1a5aabb >--- /dev/null >+++ b/Koha/Accounts/OffsetTypes.pm >@@ -0,0 +1,72 @@ >+package Koha::Accounts::OffsetTypes; >+ >+# Copyright 2013 ByWater Solutions >+# >+# 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 Modern::Perl; >+ >+=head1 NAME >+ >+Koha::AccountsOffsetTypes - Module representing the enumerated data types for account fees >+ >+=head1 SYNOPSIS >+ >+use Koha::Accounts::OffsetTypes; >+ >+my $type = Koha::Accounts::OffsetTypes::Dropbox; >+ >+=head1 DESCRIPTION >+ >+The subroutines in this modules act as enumerated data types for the >+different automatic offset types in Koha ( i.e. forgiveness, dropbox mode, etc ) >+ >+These types are used for account offsets that have no corrosponding account credit, >+e.g. automatic fine increments, dropbox mode, etc. >+ >+=head1 FUNCTIONS >+ >+=cut >+ >+=head2 Dropbox >+ >+Offset type for automatic fine reductions >+via dropbox mode. >+ >+=cut >+ >+sub Dropbox { >+ return 'DROPBOX'; >+} >+ >+=head2 Fine >+ >+Indicates this offset was an automatically >+generated fine increment/decrement. >+ >+=cut >+ >+sub Fine { >+ return 'FINE'; >+} >+ >+1; >+ >+=head1 AUTHOR >+ >+Kyle M Hall <kyle@bywatersolutions.com> >+ >+=cut >diff --git a/Koha/DateUtils.pm b/Koha/DateUtils.pm >index 4ae0d0c..6dbc979 100644 >--- a/Koha/DateUtils.pm >+++ b/Koha/DateUtils.pm >@@ -21,13 +21,14 @@ use warnings; > use 5.010; > use DateTime; > use DateTime::Format::DateParse; >+use DateTime::Format::MySQL; > use C4::Context; > > use base 'Exporter'; > use version; our $VERSION = qv('1.0.0'); > > our @EXPORT = ( >- qw( dt_from_string output_pref format_sqldatetime output_pref_due format_sqlduedatetime) >+ qw( dt_from_string output_pref format_sqldatetime output_pref_due format_sqlduedatetime get_timestamp ) > ); > > =head1 DateUtils >@@ -239,4 +240,8 @@ sub format_sqlduedatetime { > return q{}; > } > >+sub get_timestamp { >+ return DateTime::Format::MySQL->format_datetime( dt_from_string() ); >+} >+ > 1; >diff --git a/Koha/Schema/Result/AccountCredit.pm b/Koha/Schema/Result/AccountCredit.pm >new file mode 100644 >index 0000000..d56b659 >--- /dev/null >+++ b/Koha/Schema/Result/AccountCredit.pm >@@ -0,0 +1,148 @@ >+package Koha::Schema::Result::AccountCredit; >+ >+# Created by DBIx::Class::Schema::Loader >+# DO NOT MODIFY THE FIRST PART OF THIS FILE >+ >+use strict; >+use warnings; >+ >+use base 'DBIx::Class::Core'; >+ >+ >+=head1 NAME >+ >+Koha::Schema::Result::AccountCredit >+ >+=cut >+ >+__PACKAGE__->table("account_credits"); >+ >+=head1 ACCESSORS >+ >+=head2 credit_id >+ >+ data_type: 'integer' >+ is_auto_increment: 1 >+ is_nullable: 0 >+ >+=head2 borrowernumber >+ >+ data_type: 'integer' >+ is_foreign_key: 1 >+ is_nullable: 0 >+ >+=head2 type >+ >+ data_type: 'varchar' >+ is_nullable: 0 >+ size: 255 >+ >+=head2 amount_received >+ >+ data_type: 'decimal' >+ is_nullable: 1 >+ size: [28,6] >+ >+=head2 amount_paid >+ >+ data_type: 'decimal' >+ is_nullable: 0 >+ size: [28,6] >+ >+=head2 amount_remaining >+ >+ data_type: 'decimal' >+ is_nullable: 0 >+ size: [28,6] >+ >+=head2 notes >+ >+ data_type: 'text' >+ is_nullable: 1 >+ >+=head2 manager_id >+ >+ data_type: 'integer' >+ is_nullable: 1 >+ >+=head2 created_on >+ >+ data_type: 'timestamp' >+ is_nullable: 1 >+ >+=head2 updated_on >+ >+ data_type: 'timestamp' >+ is_nullable: 1 >+ >+=cut >+ >+__PACKAGE__->add_columns( >+ "credit_id", >+ { data_type => "integer", is_auto_increment => 1, is_nullable => 0 }, >+ "borrowernumber", >+ { data_type => "integer", is_foreign_key => 1, is_nullable => 0 }, >+ "type", >+ { data_type => "varchar", is_nullable => 0, size => 255 }, >+ "amount_received", >+ { data_type => "decimal", is_nullable => 1, size => [28, 6] }, >+ "amount_paid", >+ { data_type => "decimal", is_nullable => 0, size => [28, 6] }, >+ "amount_remaining", >+ { data_type => "decimal", is_nullable => 0, size => [28, 6] }, >+ "notes", >+ { data_type => "text", is_nullable => 1 }, >+ "manager_id", >+ { data_type => "integer", is_nullable => 1 }, >+ "created_on", >+ { data_type => "timestamp", is_nullable => 1 }, >+ "updated_on", >+ { data_type => "timestamp", is_nullable => 1 }, >+); >+__PACKAGE__->set_primary_key("credit_id"); >+ >+=head1 RELATIONS >+ >+=head2 borrowernumber >+ >+Type: belongs_to >+ >+Related object: L<Koha::Schema::Result::Borrower> >+ >+=cut >+ >+__PACKAGE__->belongs_to( >+ "borrowernumber", >+ "Koha::Schema::Result::Borrower", >+ { borrowernumber => "borrowernumber" }, >+ { on_delete => "CASCADE", on_update => "CASCADE" }, >+); >+ >+=head2 account_offsets >+ >+Type: has_many >+ >+Related object: L<Koha::Schema::Result::AccountOffset> >+ >+=cut >+ >+__PACKAGE__->has_many( >+ "account_offsets", >+ "Koha::Schema::Result::AccountOffset", >+ { "foreign.credit_id" => "self.credit_id" }, >+ { cascade_copy => 0, cascade_delete => 0 }, >+); >+ >+ >+# Created by DBIx::Class::Schema::Loader v0.07000 @ 2013-11-25 14:00:11 >+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:UA9pxIe/9NzHIESDZqCpVw >+ >+__PACKAGE__->belongs_to( >+ "borrower", >+ "Koha::Schema::Result::Borrower", >+ { borrowernumber => "borrowernumber" }, >+); >+ >+ >+# You can replace this text with custom content, and it will be preserved on regeneration >+1; >diff --git a/Koha/Schema/Result/AccountDebit.pm b/Koha/Schema/Result/AccountDebit.pm >new file mode 100644 >index 0000000..e57347d >--- /dev/null >+++ b/Koha/Schema/Result/AccountDebit.pm >@@ -0,0 +1,207 @@ >+package Koha::Schema::Result::AccountDebit; >+ >+# Created by DBIx::Class::Schema::Loader >+# DO NOT MODIFY THE FIRST PART OF THIS FILE >+ >+use strict; >+use warnings; >+ >+use base 'DBIx::Class::Core'; >+ >+ >+=head1 NAME >+ >+Koha::Schema::Result::AccountDebit >+ >+=cut >+ >+__PACKAGE__->table("account_debits"); >+ >+=head1 ACCESSORS >+ >+=head2 debit_id >+ >+ data_type: 'integer' >+ is_auto_increment: 1 >+ is_nullable: 0 >+ >+=head2 borrowernumber >+ >+ data_type: 'integer' >+ default_value: 0 >+ is_foreign_key: 1 >+ is_nullable: 0 >+ >+=head2 itemnumber >+ >+ data_type: 'integer' >+ is_nullable: 1 >+ >+=head2 issue_id >+ >+ data_type: 'integer' >+ is_nullable: 1 >+ >+=head2 type >+ >+ data_type: 'varchar' >+ is_nullable: 0 >+ size: 255 >+ >+=head2 accruing >+ >+ data_type: 'tinyint' >+ default_value: 0 >+ is_nullable: 0 >+ >+=head2 amount_original >+ >+ data_type: 'decimal' >+ is_nullable: 1 >+ size: [28,6] >+ >+=head2 amount_outstanding >+ >+ data_type: 'decimal' >+ is_nullable: 1 >+ size: [28,6] >+ >+=head2 amount_last_increment >+ >+ data_type: 'decimal' >+ is_nullable: 1 >+ size: [28,6] >+ >+=head2 description >+ >+ data_type: 'mediumtext' >+ is_nullable: 1 >+ >+=head2 notes >+ >+ data_type: 'text' >+ is_nullable: 1 >+ >+=head2 manager_id >+ >+ data_type: 'integer' >+ is_nullable: 1 >+ >+=head2 created_on >+ >+ data_type: 'timestamp' >+ is_nullable: 1 >+ >+=head2 updated_on >+ >+ data_type: 'timestamp' >+ is_nullable: 1 >+ >+=cut >+ >+__PACKAGE__->add_columns( >+ "debit_id", >+ { data_type => "integer", is_auto_increment => 1, is_nullable => 0 }, >+ "borrowernumber", >+ { >+ data_type => "integer", >+ default_value => 0, >+ is_foreign_key => 1, >+ is_nullable => 0, >+ }, >+ "itemnumber", >+ { data_type => "integer", is_nullable => 1 }, >+ "issue_id", >+ { data_type => "integer", is_nullable => 1 }, >+ "type", >+ { data_type => "varchar", is_nullable => 0, size => 255 }, >+ "accruing", >+ { data_type => "tinyint", default_value => 0, is_nullable => 0 }, >+ "amount_original", >+ { data_type => "decimal", is_nullable => 1, size => [28, 6] }, >+ "amount_outstanding", >+ { data_type => "decimal", is_nullable => 1, size => [28, 6] }, >+ "amount_last_increment", >+ { data_type => "decimal", is_nullable => 1, size => [28, 6] }, >+ "description", >+ { data_type => "mediumtext", is_nullable => 1 }, >+ "notes", >+ { data_type => "text", is_nullable => 1 }, >+ "manager_id", >+ { data_type => "integer", is_nullable => 1 }, >+ "created_on", >+ { data_type => "timestamp", is_nullable => 1 }, >+ "updated_on", >+ { data_type => "timestamp", is_nullable => 1 }, >+); >+__PACKAGE__->set_primary_key("debit_id"); >+ >+=head1 RELATIONS >+ >+=head2 borrowernumber >+ >+Type: belongs_to >+ >+Related object: L<Koha::Schema::Result::Borrower> >+ >+=cut >+ >+__PACKAGE__->belongs_to( >+ "borrowernumber", >+ "Koha::Schema::Result::Borrower", >+ { borrowernumber => "borrowernumber" }, >+ { on_delete => "CASCADE", on_update => "CASCADE" }, >+); >+ >+=head2 account_offsets >+ >+Type: has_many >+ >+Related object: L<Koha::Schema::Result::AccountOffset> >+ >+=cut >+ >+__PACKAGE__->has_many( >+ "account_offsets", >+ "Koha::Schema::Result::AccountOffset", >+ { "foreign.debit_id" => "self.debit_id" }, >+ { cascade_copy => 0, cascade_delete => 0 }, >+); >+ >+ >+# Created by DBIx::Class::Schema::Loader v0.07000 @ 2013-11-05 08:09:09 >+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ulQStZJSzcD4hvrPbtew4g >+ >+__PACKAGE__->belongs_to( >+ "item", >+ "Koha::Schema::Result::Item", >+ { itemnumber => "itemnumber" } >+); >+ >+__PACKAGE__->belongs_to( >+ "deleted_item", >+ "Koha::Schema::Result::Deleteditem", >+ { itemnumber => "itemnumber" } >+); >+ >+__PACKAGE__->belongs_to( >+ "issue", >+ "Koha::Schema::Result::Issue", >+ { issue_id => "issue_id" } >+); >+ >+__PACKAGE__->belongs_to( >+ "old_issue", >+ "Koha::Schema::Result::OldIssue", >+ { issue_id => "issue_id" } >+); >+ >+__PACKAGE__->belongs_to( >+ "borrower", >+ "Koha::Schema::Result::Borrower", >+ { borrowernumber => "borrowernumber" }, >+ { on_delete => "CASCADE", on_update => "CASCADE" }, >+); >+ >+# You can replace this text with custom content, and it will be preserved on regeneration >+1; >diff --git a/Koha/Schema/Result/AccountOffset.pm b/Koha/Schema/Result/AccountOffset.pm >new file mode 100644 >index 0000000..179392f >--- /dev/null >+++ b/Koha/Schema/Result/AccountOffset.pm >@@ -0,0 +1,118 @@ >+package Koha::Schema::Result::AccountOffset; >+ >+# Created by DBIx::Class::Schema::Loader >+# DO NOT MODIFY THE FIRST PART OF THIS FILE >+ >+use strict; >+use warnings; >+ >+use base 'DBIx::Class::Core'; >+ >+ >+=head1 NAME >+ >+Koha::Schema::Result::AccountOffset >+ >+=cut >+ >+__PACKAGE__->table("account_offsets"); >+ >+=head1 ACCESSORS >+ >+=head2 offset_id >+ >+ data_type: 'integer' >+ is_auto_increment: 1 >+ is_nullable: 0 >+ >+=head2 debit_id >+ >+ data_type: 'integer' >+ is_foreign_key: 1 >+ is_nullable: 1 >+ >+=head2 credit_id >+ >+ data_type: 'integer' >+ is_foreign_key: 1 >+ is_nullable: 1 >+ >+=head2 type >+ >+ data_type: 'varchar' >+ is_nullable: 1 >+ size: 255 >+ >+=head2 amount >+ >+ data_type: 'decimal' >+ is_nullable: 0 >+ size: [28,6] >+ >+=head2 created_on >+ >+ data_type: 'timestamp' >+ default_value: current_timestamp >+ is_nullable: 0 >+ >+=cut >+ >+__PACKAGE__->add_columns( >+ "offset_id", >+ { data_type => "integer", is_auto_increment => 1, is_nullable => 0 }, >+ "debit_id", >+ { data_type => "integer", is_foreign_key => 1, is_nullable => 1 }, >+ "credit_id", >+ { data_type => "integer", is_foreign_key => 1, is_nullable => 1 }, >+ "type", >+ { data_type => "varchar", is_nullable => 1, size => 255 }, >+ "amount", >+ { data_type => "decimal", is_nullable => 0, size => [28, 6] }, >+ "created_on", >+ { >+ data_type => "timestamp", >+ default_value => \"current_timestamp", >+ is_nullable => 0, >+ }, >+); >+__PACKAGE__->set_primary_key("offset_id"); >+ >+=head1 RELATIONS >+ >+=head2 debit >+ >+Type: belongs_to >+ >+Related object: L<Koha::Schema::Result::AccountDebit> >+ >+=cut >+ >+__PACKAGE__->belongs_to( >+ "debit", >+ "Koha::Schema::Result::AccountDebit", >+ { debit_id => "debit_id" }, >+ { join_type => "LEFT", on_delete => "CASCADE", on_update => "CASCADE" }, >+); >+ >+=head2 credit >+ >+Type: belongs_to >+ >+Related object: L<Koha::Schema::Result::AccountCredit> >+ >+=cut >+ >+__PACKAGE__->belongs_to( >+ "credit", >+ "Koha::Schema::Result::AccountCredit", >+ { credit_id => "credit_id" }, >+ { join_type => "LEFT", on_delete => "CASCADE", on_update => "CASCADE" }, >+); >+ >+ >+# Created by DBIx::Class::Schema::Loader v0.07000 @ 2013-11-05 08:47:10 >+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:BLjpL8skXmzxOQ/J0jzdvw >+ >+ >+# You can replace this text with custom content, and it will be preserved on regeneration >+1; >diff --git a/Koha/Schema/Result/Accountline.pm b/Koha/Schema/Result/Accountline.pm >deleted file mode 100644 >index 3b977fa..0000000 >--- a/Koha/Schema/Result/Accountline.pm >+++ /dev/null >@@ -1,222 +0,0 @@ >-use utf8; >-package Koha::Schema::Result::Accountline; >- >-# Created by DBIx::Class::Schema::Loader >-# DO NOT MODIFY THE FIRST PART OF THIS FILE >- >-=head1 NAME >- >-Koha::Schema::Result::Accountline >- >-=cut >- >-use strict; >-use warnings; >- >-use base 'DBIx::Class::Core'; >- >-=head1 TABLE: C<accountlines> >- >-=cut >- >-__PACKAGE__->table("accountlines"); >- >-=head1 ACCESSORS >- >-=head2 accountlines_id >- >- data_type: 'integer' >- is_auto_increment: 1 >- is_nullable: 0 >- >-=head2 borrowernumber >- >- data_type: 'integer' >- default_value: 0 >- is_foreign_key: 1 >- is_nullable: 0 >- >-=head2 accountno >- >- data_type: 'smallint' >- default_value: 0 >- is_nullable: 0 >- >-=head2 itemnumber >- >- data_type: 'integer' >- is_foreign_key: 1 >- is_nullable: 1 >- >-=head2 date >- >- data_type: 'date' >- datetime_undef_if_invalid: 1 >- is_nullable: 1 >- >-=head2 amount >- >- data_type: 'decimal' >- is_nullable: 1 >- size: [28,6] >- >-=head2 description >- >- data_type: 'mediumtext' >- is_nullable: 1 >- >-=head2 dispute >- >- data_type: 'mediumtext' >- is_nullable: 1 >- >-=head2 accounttype >- >- data_type: 'varchar' >- is_nullable: 1 >- size: 5 >- >-=head2 amountoutstanding >- >- data_type: 'decimal' >- is_nullable: 1 >- size: [28,6] >- >-=head2 lastincrement >- >- data_type: 'decimal' >- is_nullable: 1 >- size: [28,6] >- >-=head2 timestamp >- >- data_type: 'timestamp' >- datetime_undef_if_invalid: 1 >- default_value: current_timestamp >- is_nullable: 0 >- >-=head2 notify_id >- >- data_type: 'integer' >- default_value: 0 >- is_nullable: 0 >- >-=head2 notify_level >- >- data_type: 'integer' >- default_value: 0 >- is_nullable: 0 >- >-=head2 note >- >- data_type: 'text' >- is_nullable: 1 >- >-=head2 manager_id >- >- data_type: 'integer' >- is_nullable: 1 >- >-=cut >- >-__PACKAGE__->add_columns( >- "accountlines_id", >- { data_type => "integer", is_auto_increment => 1, is_nullable => 0 }, >- "borrowernumber", >- { >- data_type => "integer", >- default_value => 0, >- is_foreign_key => 1, >- is_nullable => 0, >- }, >- "accountno", >- { data_type => "smallint", default_value => 0, is_nullable => 0 }, >- "itemnumber", >- { data_type => "integer", is_foreign_key => 1, is_nullable => 1 }, >- "date", >- { data_type => "date", datetime_undef_if_invalid => 1, is_nullable => 1 }, >- "amount", >- { data_type => "decimal", is_nullable => 1, size => [28, 6] }, >- "description", >- { data_type => "mediumtext", is_nullable => 1 }, >- "dispute", >- { data_type => "mediumtext", is_nullable => 1 }, >- "accounttype", >- { data_type => "varchar", is_nullable => 1, size => 5 }, >- "amountoutstanding", >- { data_type => "decimal", is_nullable => 1, size => [28, 6] }, >- "lastincrement", >- { data_type => "decimal", is_nullable => 1, size => [28, 6] }, >- "timestamp", >- { >- data_type => "timestamp", >- datetime_undef_if_invalid => 1, >- default_value => \"current_timestamp", >- is_nullable => 0, >- }, >- "notify_id", >- { data_type => "integer", default_value => 0, is_nullable => 0 }, >- "notify_level", >- { data_type => "integer", default_value => 0, is_nullable => 0 }, >- "note", >- { data_type => "text", is_nullable => 1 }, >- "manager_id", >- { data_type => "integer", is_nullable => 1 }, >-); >- >-=head1 PRIMARY KEY >- >-=over 4 >- >-=item * L</accountlines_id> >- >-=back >- >-=cut >- >-__PACKAGE__->set_primary_key("accountlines_id"); >- >-=head1 RELATIONS >- >-=head2 borrowernumber >- >-Type: belongs_to >- >-Related object: L<Koha::Schema::Result::Borrower> >- >-=cut >- >-__PACKAGE__->belongs_to( >- "borrowernumber", >- "Koha::Schema::Result::Borrower", >- { borrowernumber => "borrowernumber" }, >- { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" }, >-); >- >-=head2 itemnumber >- >-Type: belongs_to >- >-Related object: L<Koha::Schema::Result::Item> >- >-=cut >- >-__PACKAGE__->belongs_to( >- "itemnumber", >- "Koha::Schema::Result::Item", >- { itemnumber => "itemnumber" }, >- { >- is_deferrable => 1, >- join_type => "LEFT", >- on_delete => "CASCADE", >- on_update => "CASCADE", >- }, >-); >- >- >-# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-10-14 20:56:21 >-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:VLEuOBmnS+xgk7LXAqxtLw >- >- >-# You can replace this text with custom content, and it will be preserved on regeneration >-1; >diff --git a/Koha/Schema/Result/Accountoffset.pm b/Koha/Schema/Result/Accountoffset.pm >deleted file mode 100644 >index e9d8c2f..0000000 >--- a/Koha/Schema/Result/Accountoffset.pm >+++ /dev/null >@@ -1,106 +0,0 @@ >-use utf8; >-package Koha::Schema::Result::Accountoffset; >- >-# Created by DBIx::Class::Schema::Loader >-# DO NOT MODIFY THE FIRST PART OF THIS FILE >- >-=head1 NAME >- >-Koha::Schema::Result::Accountoffset >- >-=cut >- >-use strict; >-use warnings; >- >-use base 'DBIx::Class::Core'; >- >-=head1 TABLE: C<accountoffsets> >- >-=cut >- >-__PACKAGE__->table("accountoffsets"); >- >-=head1 ACCESSORS >- >-=head2 borrowernumber >- >- data_type: 'integer' >- default_value: 0 >- is_foreign_key: 1 >- is_nullable: 0 >- >-=head2 accountno >- >- data_type: 'smallint' >- default_value: 0 >- is_nullable: 0 >- >-=head2 offsetaccount >- >- data_type: 'smallint' >- default_value: 0 >- is_nullable: 0 >- >-=head2 offsetamount >- >- data_type: 'decimal' >- is_nullable: 1 >- size: [28,6] >- >-=head2 timestamp >- >- data_type: 'timestamp' >- datetime_undef_if_invalid: 1 >- default_value: current_timestamp >- is_nullable: 0 >- >-=cut >- >-__PACKAGE__->add_columns( >- "borrowernumber", >- { >- data_type => "integer", >- default_value => 0, >- is_foreign_key => 1, >- is_nullable => 0, >- }, >- "accountno", >- { data_type => "smallint", default_value => 0, is_nullable => 0 }, >- "offsetaccount", >- { data_type => "smallint", default_value => 0, is_nullable => 0 }, >- "offsetamount", >- { data_type => "decimal", is_nullable => 1, size => [28, 6] }, >- "timestamp", >- { >- data_type => "timestamp", >- datetime_undef_if_invalid => 1, >- default_value => \"current_timestamp", >- is_nullable => 0, >- }, >-); >- >-=head1 RELATIONS >- >-=head2 borrowernumber >- >-Type: belongs_to >- >-Related object: L<Koha::Schema::Result::Borrower> >- >-=cut >- >-__PACKAGE__->belongs_to( >- "borrowernumber", >- "Koha::Schema::Result::Borrower", >- { borrowernumber => "borrowernumber" }, >- { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" }, >-); >- >- >-# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-10-14 20:56:21 >-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:OTfcUiJCPb5aU/gjqAb/bA >- >- >-# You can replace this text with custom content, and it will be preserved on regeneration >-1; >diff --git a/Koha/Schema/Result/Borrower.pm b/Koha/Schema/Result/Borrower.pm >index 3d9f9ae..580bbec 100644 >--- a/Koha/Schema/Result/Borrower.pm >+++ b/Koha/Schema/Result/Borrower.pm >@@ -1,21 +1,17 @@ >-use utf8; > package Koha::Schema::Result::Borrower; > > # Created by DBIx::Class::Schema::Loader > # DO NOT MODIFY THE FIRST PART OF THIS FILE > >-=head1 NAME >- >-Koha::Schema::Result::Borrower >- >-=cut >- > use strict; > use warnings; > > use base 'DBIx::Class::Core'; > >-=head1 TABLE: C<borrowers> >+ >+=head1 NAME >+ >+Koha::Schema::Result::Borrower > > =cut > >@@ -191,7 +187,6 @@ __PACKAGE__->table("borrowers"); > =head2 dateofbirth > > data_type: 'date' >- datetime_undef_if_invalid: 1 > is_nullable: 1 > > =head2 branchcode >@@ -213,13 +208,11 @@ __PACKAGE__->table("borrowers"); > =head2 dateenrolled > > data_type: 'date' >- datetime_undef_if_invalid: 1 > is_nullable: 1 > > =head2 dateexpiry > > data_type: 'date' >- datetime_undef_if_invalid: 1 > is_nullable: 1 > > =head2 gonenoaddress >@@ -235,7 +228,6 @@ __PACKAGE__->table("borrowers"); > =head2 debarred > > data_type: 'date' >- datetime_undef_if_invalid: 1 > is_nullable: 1 > > =head2 debarredcomment >@@ -397,6 +389,13 @@ __PACKAGE__->table("borrowers"); > default_value: 1 > is_nullable: 0 > >+=head2 account_balance >+ >+ data_type: 'decimal' >+ default_value: 0.000000 >+ is_nullable: 0 >+ size: [28,6] >+ > =cut > > __PACKAGE__->add_columns( >@@ -463,7 +462,7 @@ __PACKAGE__->add_columns( > "b_phone", > { data_type => "mediumtext", is_nullable => 1 }, > "dateofbirth", >- { data_type => "date", datetime_undef_if_invalid => 1, is_nullable => 1 }, >+ { data_type => "date", is_nullable => 1 }, > "branchcode", > { > data_type => "varchar", >@@ -481,15 +480,15 @@ __PACKAGE__->add_columns( > size => 10, > }, > "dateenrolled", >- { data_type => "date", datetime_undef_if_invalid => 1, is_nullable => 1 }, >+ { data_type => "date", is_nullable => 1 }, > "dateexpiry", >- { data_type => "date", datetime_undef_if_invalid => 1, is_nullable => 1 }, >+ { data_type => "date", is_nullable => 1 }, > "gonenoaddress", > { data_type => "tinyint", is_nullable => 1 }, > "lost", > { data_type => "tinyint", is_nullable => 1 }, > "debarred", >- { data_type => "date", datetime_undef_if_invalid => 1, is_nullable => 1 }, >+ { data_type => "date", is_nullable => 1 }, > "debarredcomment", > { data_type => "varchar", is_nullable => 1, size => 255 }, > "contactname", >@@ -546,35 +545,48 @@ __PACKAGE__->add_columns( > { data_type => "varchar", is_nullable => 1, size => 50 }, > "privacy", > { data_type => "integer", default_value => 1, is_nullable => 0 }, >+ "account_balance", >+ { >+ data_type => "decimal", >+ default_value => "0.000000", >+ is_nullable => 0, >+ size => [28, 6], >+ }, > ); >+__PACKAGE__->set_primary_key("borrowernumber"); >+__PACKAGE__->add_unique_constraint("cardnumber", ["cardnumber"]); > >-=head1 PRIMARY KEY >+=head1 RELATIONS > >-=over 4 >+=head2 account_credits > >-=item * L</borrowernumber> >+Type: has_many > >-=back >+Related object: L<Koha::Schema::Result::AccountCredit> > > =cut > >-__PACKAGE__->set_primary_key("borrowernumber"); >- >-=head1 UNIQUE CONSTRAINTS >- >-=head2 C<cardnumber> >+__PACKAGE__->has_many( >+ "account_credits", >+ "Koha::Schema::Result::AccountCredit", >+ { "foreign.borrowernumber" => "self.borrowernumber" }, >+ { cascade_copy => 0, cascade_delete => 0 }, >+); > >-=over 4 >+=head2 account_debits > >-=item * L</cardnumber> >+Type: has_many > >-=back >+Related object: L<Koha::Schema::Result::AccountDebit> > > =cut > >-__PACKAGE__->add_unique_constraint("cardnumber", ["cardnumber"]); >- >-=head1 RELATIONS >+__PACKAGE__->has_many( >+ "account_debits", >+ "Koha::Schema::Result::AccountDebit", >+ { "foreign.borrowernumber" => "self.borrowernumber" }, >+ { cascade_copy => 0, cascade_delete => 0 }, >+); > > =head2 accountlines > >@@ -696,34 +708,34 @@ __PACKAGE__->has_many( > { cascade_copy => 0, cascade_delete => 0 }, > ); > >-=head2 branchcode >+=head2 categorycode > > Type: belongs_to > >-Related object: L<Koha::Schema::Result::Branch> >+Related object: L<Koha::Schema::Result::Category> > > =cut > > __PACKAGE__->belongs_to( >- "branchcode", >- "Koha::Schema::Result::Branch", >- { branchcode => "branchcode" }, >- { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" }, >+ "categorycode", >+ "Koha::Schema::Result::Category", >+ { categorycode => "categorycode" }, >+ { on_delete => "CASCADE", on_update => "CASCADE" }, > ); > >-=head2 categorycode >+=head2 branchcode > > Type: belongs_to > >-Related object: L<Koha::Schema::Result::Category> >+Related object: L<Koha::Schema::Result::Branch> > > =cut > > __PACKAGE__->belongs_to( >- "categorycode", >- "Koha::Schema::Result::Category", >- { categorycode => "categorycode" }, >- { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" }, >+ "branchcode", >+ "Koha::Schema::Result::Branch", >+ { branchcode => "branchcode" }, >+ { on_delete => "CASCADE", on_update => "CASCADE" }, > ); > > =head2 course_instructors >@@ -1041,40 +1053,15 @@ __PACKAGE__->has_many( > { cascade_copy => 0, cascade_delete => 0 }, > ); > >-=head2 basketnoes >- >-Type: many_to_many >- >-Composing rels: L</aqbasketusers> -> basketno >- >-=cut >- >-__PACKAGE__->many_to_many("basketnoes", "aqbasketusers", "basketno"); >- >-=head2 budgets >- >-Type: many_to_many >- >-Composing rels: L</aqbudgetborrowers> -> budget >- >-=cut >- >-__PACKAGE__->many_to_many("budgets", "aqbudgetborrowers", "budget"); >- >-=head2 courses >- >-Type: many_to_many > >-Composing rels: L</course_instructors> -> course >- >-=cut >- >-__PACKAGE__->many_to_many("courses", "course_instructors", "course"); >- >- >-# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-10-31 16:31:19 >-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:z4kW3xYX1CyrwvGdZu32nA >+# Created by DBIx::Class::Schema::Loader v0.07000 @ 2013-11-12 08:27:25 >+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:CcXsGi7pVHQtO+YH3pY/1A > >+__PACKAGE__->belongs_to( >+ "branch", >+ "Koha::Schema::Result::Branch", >+ { branchcode => "branchcode" }, >+); > > # You can replace this text with custom content, and it will be preserved on regeneration > 1; >diff --git a/Koha/Schema/Result/Deleteditem.pm b/Koha/Schema/Result/Deleteditem.pm >index 7beae1b..b001381 100644 >--- a/Koha/Schema/Result/Deleteditem.pm >+++ b/Koha/Schema/Result/Deleteditem.pm >@@ -366,6 +366,17 @@ __PACKAGE__->set_primary_key("itemnumber"); > # Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-11-27 17:52:57 > # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:VssrrcYczPsiDBrtbsipIw > >+__PACKAGE__->belongs_to( >+ "biblio", >+ "Koha::Schema::Result::Biblio", >+ { biblionumber => "biblionumber" } >+); >+ >+__PACKAGE__->belongs_to( >+ "deleted_biblio", >+ "Koha::Schema::Result::Deletedbiblio", >+ { biblionumber => "biblionumber" } >+); > > # You can replace this text with custom content, and it will be preserved on regeneration > 1; >diff --git a/Koha/Schema/Result/Issue.pm b/Koha/Schema/Result/Issue.pm >index 282c802..d5ee1b1 100644 >--- a/Koha/Schema/Result/Issue.pm >+++ b/Koha/Schema/Result/Issue.pm >@@ -1,21 +1,17 @@ >-use utf8; > package Koha::Schema::Result::Issue; > > # Created by DBIx::Class::Schema::Loader > # DO NOT MODIFY THE FIRST PART OF THIS FILE > >-=head1 NAME >- >-Koha::Schema::Result::Issue >- >-=cut >- > use strict; > use warnings; > > use base 'DBIx::Class::Core'; > >-=head1 TABLE: C<issues> >+ >+=head1 NAME >+ >+Koha::Schema::Result::Issue > > =cut > >@@ -23,6 +19,12 @@ __PACKAGE__->table("issues"); > > =head1 ACCESSORS > >+=head2 issue_id >+ >+ data_type: 'integer' >+ is_auto_increment: 1 >+ is_nullable: 0 >+ > =head2 borrowernumber > > data_type: 'integer' >@@ -38,7 +40,6 @@ __PACKAGE__->table("issues"); > =head2 date_due > > data_type: 'datetime' >- datetime_undef_if_invalid: 1 > is_nullable: 1 > > =head2 branchcode >@@ -56,13 +57,11 @@ __PACKAGE__->table("issues"); > =head2 returndate > > data_type: 'datetime' >- datetime_undef_if_invalid: 1 > is_nullable: 1 > > =head2 lastreneweddate > > data_type: 'datetime' >- datetime_undef_if_invalid: 1 > is_nullable: 1 > > =head2 return >@@ -79,63 +78,47 @@ __PACKAGE__->table("issues"); > =head2 timestamp > > data_type: 'timestamp' >- datetime_undef_if_invalid: 1 > default_value: current_timestamp > is_nullable: 0 > > =head2 issuedate > > data_type: 'datetime' >- datetime_undef_if_invalid: 1 > is_nullable: 1 > > =cut > > __PACKAGE__->add_columns( >+ "issue_id", >+ { data_type => "integer", is_auto_increment => 1, is_nullable => 0 }, > "borrowernumber", > { data_type => "integer", is_foreign_key => 1, is_nullable => 1 }, > "itemnumber", > { data_type => "integer", is_foreign_key => 1, is_nullable => 1 }, > "date_due", >- { >- data_type => "datetime", >- datetime_undef_if_invalid => 1, >- is_nullable => 1, >- }, >+ { data_type => "datetime", is_nullable => 1 }, > "branchcode", > { data_type => "varchar", is_nullable => 1, size => 10 }, > "issuingbranch", > { data_type => "varchar", is_nullable => 1, size => 18 }, > "returndate", >- { >- data_type => "datetime", >- datetime_undef_if_invalid => 1, >- is_nullable => 1, >- }, >+ { data_type => "datetime", is_nullable => 1 }, > "lastreneweddate", >- { >- data_type => "datetime", >- datetime_undef_if_invalid => 1, >- is_nullable => 1, >- }, >+ { data_type => "datetime", is_nullable => 1 }, > "return", > { data_type => "varchar", is_nullable => 1, size => 4 }, > "renewals", > { data_type => "tinyint", is_nullable => 1 }, > "timestamp", > { >- data_type => "timestamp", >- datetime_undef_if_invalid => 1, >+ data_type => "timestamp", > default_value => \"current_timestamp", >- is_nullable => 0, >+ is_nullable => 0, > }, > "issuedate", >- { >- data_type => "datetime", >- datetime_undef_if_invalid => 1, >- is_nullable => 1, >- }, >+ { data_type => "datetime", is_nullable => 1 }, > ); >+__PACKAGE__->set_primary_key("issue_id"); > > =head1 RELATIONS > >@@ -151,12 +134,7 @@ __PACKAGE__->belongs_to( > "borrowernumber", > "Koha::Schema::Result::Borrower", > { borrowernumber => "borrowernumber" }, >- { >- is_deferrable => 1, >- join_type => "LEFT", >- on_delete => "CASCADE", >- on_update => "CASCADE", >- }, >+ { join_type => "LEFT", on_delete => "CASCADE", on_update => "CASCADE" }, > ); > > =head2 itemnumber >@@ -171,23 +149,25 @@ __PACKAGE__->belongs_to( > "itemnumber", > "Koha::Schema::Result::Item", > { itemnumber => "itemnumber" }, >- { >- is_deferrable => 1, >- join_type => "LEFT", >- on_delete => "CASCADE", >- on_update => "CASCADE", >- }, >+ { join_type => "LEFT", on_delete => "CASCADE", on_update => "CASCADE" }, > ); > > >-# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-10-14 20:56:21 >-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ZEh31EKBmURMKxDxI+H3EA >+# Created by DBIx::Class::Schema::Loader v0.07000 @ 2013-11-12 09:32:52 >+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:zBewWFig+yZYtSkcIxCZpg > > __PACKAGE__->belongs_to( > "borrower", > "Koha::Schema::Result::Borrower", > { borrowernumber => "borrowernumber" }, >- { join_type => "LEFT", on_delete => "CASCADE", on_update => "CASCADE" }, >+ { join_type => "LEFT" }, >+); >+ >+__PACKAGE__->belongs_to( >+ "item", >+ "Koha::Schema::Result::Item", >+ { itemnumber => "itemnumber" }, >+ { join_type => "LEFT" }, > ); > > 1; >diff --git a/Koha/Schema/Result/OldIssue.pm b/Koha/Schema/Result/OldIssue.pm >index 4050f06..e1e7e69 100644 >--- a/Koha/Schema/Result/OldIssue.pm >+++ b/Koha/Schema/Result/OldIssue.pm >@@ -183,6 +183,32 @@ __PACKAGE__->belongs_to( > # Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-10-14 20:56:21 > # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:uPOxNROoMMRZ0qZsXsxEjA > >+__PACKAGE__->belongs_to( >+ "borrower", >+ "Koha::Schema::Result::Borrower", >+ { borrowernumber => "borrowernumber" }, >+ { join_type => "LEFT" }, >+); >+ >+__PACKAGE__->belongs_to( >+ "item", >+ "Koha::Schema::Result::Item", >+ { itemnumber => "itemnumber" }, >+ { join_type => "LEFT" }, >+); >+ >+__PACKAGE__->belongs_to( >+ "deletedborrower", >+ "Koha::Schema::Result::Deletedborrower", >+ { borrowernumber => "borrowernumber" }, >+ { join_type => "LEFT" }, >+); >+ >+__PACKAGE__->belongs_to( >+ "deleteditem", >+ "Koha::Schema::Result::Deleteditem", >+ { itemnumber => "itemnumber" }, >+ { join_type => "LEFT" }, >+); > >-# You can replace this text with custom content, and it will be preserved on regeneration > 1; >diff --git a/Koha/Template/Plugin/Currency.pm b/Koha/Template/Plugin/Currency.pm >new file mode 100644 >index 0000000..dbd6ac8 >--- /dev/null >+++ b/Koha/Template/Plugin/Currency.pm >@@ -0,0 +1,90 @@ >+package Koha::Template::Plugin::Currency; >+ >+# Copyright ByWater Solutions 2013 >+ >+# 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 Modern::Perl; >+ >+use base qw( Template::Plugin::Filter ); >+ >+use Locale::Currency::Format; >+ >+use C4::Context; >+use Koha::DateUtils; >+ >+sub init { >+ my $self = shift; >+ $self->{ _DYNAMIC } = 1; >+ >+ my $active_currency = C4::Context->dbh->selectrow_hashref( >+ 'SELECT * FROM currency WHERE active = 1', {} ); >+ $self->{active_currency} = $active_currency; >+ >+ return $self; >+} >+ >+sub filter { >+ my ( $self, $amount, $args, $conf ) = @_; >+ >+ return $self->format( $amount, undef, $conf->{highlight} ); >+} >+ >+sub format { >+ my ( $self, $amount, $format, $highlight ) = @_; >+ >+ my $is_negative = $amount < 0; >+ $amount = abs( $amount ) if $highlight; >+ >+ # A negative debit is a credit and visa versa >+ if ($highlight) { >+ if ( $highlight eq 'debit' ) { >+ if ($is_negative) { >+ $highlight = 'credit'; >+ } >+ } >+ elsif ( $highlight eq 'credit' ) { >+ if ($is_negative) { >+ $highlight = 'debit'; >+ } >+ >+ } >+ elsif ( $highlight eq 'offset' ) { >+ $highlight = $is_negative ? 'credit' : 'debit'; >+ } >+ } >+ >+ my $formatted = currency_format( $self->{active_currency}->{currency}, >+ $amount, $format || FMT_HTML ); >+ >+ $formatted = "<span class='$highlight'>$formatted</span>" if ( $highlight && $amount ); >+ >+ return $formatted; >+} >+ >+sub format_without_symbol { >+ my ( $self, $amount ) = @_; >+ >+ return substr( $self->format( $amount, FMT_SYMBOL ), 1 ); >+} >+ >+sub symbol { >+ my ($self) = @_; >+ >+ return currency_symbol( $self->{active_currency}->{'currency'}, SYM_HTML ); >+} >+ >+1; >diff --git a/Koha/Template/Plugin/KohaAuthorisedValues.pm b/Koha/Template/Plugin/KohaAuthorisedValues.pm >index 68b1347..315b679 100644 >--- a/Koha/Template/Plugin/KohaAuthorisedValues.pm >+++ b/Koha/Template/Plugin/KohaAuthorisedValues.pm >@@ -47,4 +47,9 @@ sub GetByCode { > return GetAuthorisedValueByCode( $category, $code, $opac ); > } > >+sub Get { >+ my ( $self, $category, $selected, $opac ) = @_; >+ return GetAuthorisedValues( $category, $selected, $opac ); >+} >+ > 1; >diff --git a/circ/branchoverdues.pl b/circ/branchoverdues.pl >index c81547e..1cb3eb4 100755 >--- a/circ/branchoverdues.pl >+++ b/circ/branchoverdues.pl >@@ -49,9 +49,8 @@ use Data::Dumper; > level 3 : only methode is possible : - Considered Lost > > the documents displayed on this interface, are checked on three points >- - 1) the document must be on accountlines (Type 'FU') >+ - 1) the document must be overdue with fines > - 2) item issues is not returned >- - 3) this item as not been already notify > > FIXME: who is the author? > FIXME: No privisions (i.e. "actions") for handling notices are implemented. >diff --git a/circ/circulation.pl b/circ/circulation.pl >index 9769731..4a53286 100755 >--- a/circ/circulation.pl >+++ b/circ/circulation.pl >@@ -648,8 +648,6 @@ foreach my $flag ( sort keys %$flags ) { > my $amountold = $borrower->{flags}->{'CHARGES'}->{'message'} || 0; > $amountold =~ s/^.*\$//; # remove upto the $, if any > >-my ( $total, $accts, $numaccts) = GetMemberAccountRecords( $borrowernumber ); >- > if ( $borrower->{'category_type'} eq 'C') { > my ( $catcodes, $labels ) = GetborCatFromCatType( 'A', 'WHERE category_type = ?' ); > my $cnt = scalar(@$catcodes); >@@ -739,7 +737,7 @@ $template->param( > message => $message, > CGIselectborrower => $CGIselectborrower, > totalprice => sprintf('%.2f', $totalprice), >- totaldue => sprintf('%.2f', $total), >+ totaldue => sprintf('%.2f', $borrower->{account_balance}), > todayissues => \@todaysissues, > previssues => \@previousissues, > relissues => \@relissues, >diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql >index 07160c8..1cd0d95 100644 >--- a/installer/data/mysql/kohastructure.sql >+++ b/installer/data/mysql/kohastructure.sql >@@ -265,6 +265,7 @@ CREATE TABLE `borrowers` ( -- this table includes information about your patrons > `altcontactphone` varchar(50) default NULL, -- the phone number for the alternate contact for the patron/borrower > `smsalertnumber` varchar(50) default NULL, -- the mobile phone number where the patron/borrower would like to receive notices (if SNS turned on) > `privacy` integer(11) DEFAULT '1' NOT NULL, -- patron/borrower's privacy settings related to their reading history >+ `account_balance` decimal(28,6) NOT NULL, > UNIQUE KEY `cardnumber` (`cardnumber`), > PRIMARY KEY `borrowernumber` (`borrowernumber`), > KEY `categorycode` (`categorycode`), >@@ -2678,50 +2679,6 @@ CREATE TABLE `messages` ( -- circulation messages left via the patron's check ou > ) ENGINE=InnoDB DEFAULT CHARSET=utf8; > > -- >--- Table structure for table `accountlines` >--- >- >-DROP TABLE IF EXISTS `accountlines`; >-CREATE TABLE `accountlines` ( >- `accountlines_id` int(11) NOT NULL AUTO_INCREMENT, >- `borrowernumber` int(11) NOT NULL default 0, >- `accountno` smallint(6) NOT NULL default 0, >- `itemnumber` int(11) default NULL, >- `date` date default NULL, >- `amount` decimal(28,6) default NULL, >- `description` mediumtext, >- `dispute` mediumtext, >- `accounttype` varchar(5) default NULL, >- `amountoutstanding` decimal(28,6) default NULL, >- `lastincrement` decimal(28,6) default NULL, >- `timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, >- `notify_id` int(11) NOT NULL default 0, >- `notify_level` int(2) NOT NULL default 0, >- `note` text NULL default NULL, >- `manager_id` int(11) NULL, >- PRIMARY KEY (`accountlines_id`), >- KEY `acctsborridx` (`borrowernumber`), >- KEY `timeidx` (`timestamp`), >- KEY `itemnumber` (`itemnumber`), >- CONSTRAINT `accountlines_ibfk_1` FOREIGN KEY (`borrowernumber`) REFERENCES `borrowers` (`borrowernumber`) ON DELETE CASCADE ON UPDATE CASCADE, >- CONSTRAINT `accountlines_ibfk_2` FOREIGN KEY (`itemnumber`) REFERENCES `items` (`itemnumber`) ON DELETE SET NULL ON UPDATE SET NULL >-) ENGINE=InnoDB DEFAULT CHARSET=utf8; >- >--- >--- Table structure for table `accountoffsets` >--- >- >-DROP TABLE IF EXISTS `accountoffsets`; >-CREATE TABLE `accountoffsets` ( >- `borrowernumber` int(11) NOT NULL default 0, >- `accountno` smallint(6) NOT NULL default 0, >- `offsetaccount` smallint(6) NOT NULL default 0, >- `offsetamount` decimal(28,6) default NULL, >- `timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, >- CONSTRAINT `accountoffsets_ibfk_1` FOREIGN KEY (`borrowernumber`) REFERENCES `borrowers` (`borrowernumber`) ON DELETE CASCADE ON UPDATE CASCADE >-) ENGINE=InnoDB DEFAULT CHARSET=utf8; >- >--- > -- Table structure for table `action_logs` > -- > >@@ -3387,6 +3344,89 @@ CREATE TABLE IF NOT EXISTS marc_modification_template_actions ( > CONSTRAINT `mmta_ibfk_1` FOREIGN KEY (`template_id`) REFERENCES `marc_modification_templates` (`template_id`) ON DELETE CASCADE ON UPDATE CASCADE > ) ENGINE=InnoDB DEFAULT CHARSET=utf8; > >+-- >+-- Table structure for table 'account_credits' >+-- >+DROP TABLE IF EXISTS account_credits; >+CREATE TABLE IF account_credits ( >+ credit_id int(11) NOT NULL AUTO_INCREMENT, -- The unique id for this credit >+ borrowernumber int(11) NOT NULL, -- The borrower this credit applies to >+ `type` varchar(255) NOT NULL, -- The type of credit this is ( defined by Koha::Accounts::CreditTypes ) >+ amount_received decimal(28,6) DEFAULT NULL, -- If this was a cash payment, the amount of money given >+ amount_paid decimal(28,6) NOT NULL, -- The actual ammount paid, if less than amount_recieved, change was given back >+ amount_remaining decimal(28,6) NOT NULL, -- The amount of this credit that has not been applied to outstanding debits >+ notes text, -- Misc notes for this credit >+ manager_id int(11) DEFAULT NULL, -- The borrowernumber of the user who created this credit ( if any ) >+ created_on timestamp NULL DEFAULT NULL, -- Timestamp for when this credit was created >+ updated_on timestamp NULL DEFAULT NULL, -- Timestamp for when this credit was last modified >+ PRIMARY KEY (credit_id), >+ KEY borrowernumber (borrowernumber) >+) ENGINE=InnoDB DEFAULT CHARSET=utf8; >+ >+-- >+-- Constraints for table `account_credits` >+-- >+ALTER TABLE `account_credits` >+ ADD CONSTRAINT account_credits_ibfk_1 FOREIGN KEY (borrowernumber) REFERENCES borrowers (borrowernumber) ON DELETE CASCADE ON UPDATE CASCADE; >+ >+-- >+-- Table structure for table 'account_debits' >+-- >+ >+DROP TABLE IF EXISTS account_debits; >+CREATE TABLE account_debits ( >+ debit_id int(11) NOT NULL AUTO_INCREMENT, -- The unique id for this debit >+ borrowernumber int(11) NOT NULL DEFAULT '0', -- The borrower this debit applies to >+ itemnumber int(11) DEFAULT NULL, -- The item related to this debit ( for fines, lost fees, etc ) >+ issue_id int(11) DEFAULT NULL, -- The checkout this debit is related to ( again, for fines, lost fees, etc ) >+ `type` varchar(255) NOT NULL, -- The type of debit this is ( defined by Koha::Accounts::DebitTypes ) >+ accruing tinyint(1) NOT NULL DEFAULT '0', -- Boolean flag, tells of if this is a fine that is still accruing >+ amount_original decimal(28,6) DEFAULT NULL, -- The total amount of this debit >+ amount_outstanding decimal(28,6) DEFAULT NULL, -- The amount still owed on this debit >+ amount_last_increment decimal(28,6) DEFAULT NULL, -- The amount by which this debit last changed >+ description mediumtext, -- The description for this debit >+ notes text, -- Misc notes for this debit >+ manager_id int(11) DEFAULT NULL, -- The borrowernumber of the user who created this debit ( if any ) >+ created_on timestamp NULL DEFAULT NULL, -- Timestamp for when this credit was created >+ updated_on timestamp NULL DEFAULT NULL, -- Timestamp for when this credit was last modified >+ PRIMARY KEY (debit_id), >+ KEY acctsborridx (borrowernumber), >+ KEY itemnumber (itemnumber), >+ KEY borrowernumber (borrowernumber), >+ KEY issue_id (issue_id) >+) ENGINE=InnoDB DEFAULT CHARSET=utf8; >+ >+-- >+-- Constraints for table `account_debits` >+-- >+ALTER TABLE `account_debits` >+ ADD CONSTRAINT account_debits_ibfk_1 FOREIGN KEY (borrowernumber) REFERENCES borrowers (borrowernumber) ON DELETE CASCADE ON UPDATE CASCADE; >+ >+-- >+-- Table structure for table 'account_offsets' >+-- >+ >+DROP TABLE IF EXISTS account_offsets; >+CREATE TABLE account_offsets ( >+ offset_id int(11) NOT NULL AUTO_INCREMENT, -- Unique id for this offset >+ debit_id int(11) DEFAULT NULL, -- Related debit >+ credit_id int(11) DEFAULT NULL, -- Related credit ( if any ) >+ `type` varchar(255) DEFAULT NULL, -- The type of this offset ( defined by Koha::Accounts::OffsetTypes ), if any >+ amount decimal(28,6) NOT NULL, -- The amount of the offset, positive means patron owes more, negative means patron owes less >+ created_on timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- Timestamp for when this offset was created >+ PRIMARY KEY (offset_id), >+ KEY fee_id (debit_id), >+ KEY payment_id (credit_id) >+) ENGINE=InnoDB DEFAULT CHARSET=utf8; >+ >+-- >+-- Constraints for table `account_offsets` >+-- >+ALTER TABLE `account_offsets` >+ ADD CONSTRAINT account_offsets_ibfk_1 FOREIGN KEY (debit_id) REFERENCES account_debits (debit_id) ON DELETE CASCADE ON UPDATE CASCADE, >+ ADD CONSTRAINT account_offsets_ibfk_2 FOREIGN KEY (credit_id) REFERENCES account_credits (credit_id) ON DELETE CASCADE ON UPDATE CASCADE; >+ >+ > /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; > /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; > /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; >diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl >index a9bfbbf..bfa35bc 100755 >--- a/installer/data/mysql/updatedatabase.pl >+++ b/installer/data/mysql/updatedatabase.pl >@@ -37,6 +37,7 @@ use Getopt::Long; > use C4::Context; > use C4::Installer; > use C4::Dates; >+use Koha::Database; > > use MARC::Record; > use MARC::File::XML ( BinaryEncoding => 'utf8' ); >@@ -7259,6 +7260,7 @@ if ( CheckVersion($DBversion) ) { > > $dbh->{AutoCommit} = 1; > $dbh->{RaiseError} = 0; >+ SetVersion ($DBversion); > } > > $DBversion = "3.13.00.031"; >@@ -7778,6 +7780,181 @@ if(CheckVersion($DBversion)) { > SetVersion($DBversion); > } > >+$DBversion = "3.15.00.XXX"; >+if ( CheckVersion($DBversion) ) { >+ $dbh->do(q{ >+ ALTER TABLE old_issues ADD issue_id INT( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST >+ }); >+ $dbh->do(q{ >+ ALTER TABLE issues ADD issue_id INT( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST; >+ }); >+ $dbh->do(q{ >+ UPDATE issues SET issue_id = issue_id + ( SELECT COUNT(*) FROM old_issues ) ORDER BY issue_id DESC >+ }); >+ >+ $dbh->do(" >+ CREATE TABLE IF NOT EXISTS account_credits ( >+ credit_id int(11) NOT NULL AUTO_INCREMENT, >+ borrowernumber int(11) NOT NULL, >+ `type` varchar(255) NOT NULL, >+ amount_received decimal(28,6) DEFAULT NULL, >+ amount_paid decimal(28,6) NOT NULL, >+ amount_remaining decimal(28,6) NOT NULL, >+ notes text, >+ manager_id int(11) DEFAULT NULL, >+ created_on timestamp NULL DEFAULT NULL, >+ updated_on timestamp NULL DEFAULT NULL, >+ PRIMARY KEY (credit_id), >+ KEY borrowernumber (borrowernumber) >+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8; >+ "); >+ $dbh->do(" >+ CREATE TABLE IF NOT EXISTS account_debits ( >+ debit_id int(11) NOT NULL AUTO_INCREMENT, >+ borrowernumber int(11) NOT NULL DEFAULT '0', >+ itemnumber int(11) DEFAULT NULL, >+ issue_id int(11) DEFAULT NULL, >+ `type` varchar(255) NOT NULL, >+ accruing tinyint(1) NOT NULL DEFAULT '0', >+ amount_original decimal(28,6) DEFAULT NULL, >+ amount_outstanding decimal(28,6) DEFAULT NULL, >+ amount_last_increment decimal(28,6) DEFAULT NULL, >+ description mediumtext, >+ notes text, >+ manager_id int(11) DEFAULT NULL, >+ created_on timestamp NULL DEFAULT NULL, >+ updated_on timestamp NULL DEFAULT NULL, >+ PRIMARY KEY (debit_id), >+ KEY acctsborridx (borrowernumber), >+ KEY itemnumber (itemnumber), >+ KEY borrowernumber (borrowernumber), >+ KEY issue_id (issue_id) >+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8; >+ "); >+ >+ $dbh->do(" >+ CREATE TABLE account_offsets ( >+ offset_id int(11) NOT NULL AUTO_INCREMENT, >+ debit_id int(11) DEFAULT NULL, >+ credit_id int(11) DEFAULT NULL, >+ `type` varchar(255) DEFAULT NULL, >+ amount decimal(28,6) NOT NULL COMMENT 'A positive number here represents a payment, a negative is a increase in a fine.', >+ created_on timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, >+ PRIMARY KEY (offset_id), >+ KEY fee_id (debit_id), >+ KEY payment_id (credit_id) >+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8; >+ "); >+ >+ $dbh->do(" >+ ALTER TABLE `account_credits` >+ ADD CONSTRAINT account_credits_ibfk_1 FOREIGN KEY (borrowernumber) REFERENCES borrowers (borrowernumber) ON DELETE CASCADE ON UPDATE CASCADE; >+ "); >+ $dbh->do(" >+ ALTER TABLE `account_debits` >+ ADD CONSTRAINT account_debits_ibfk_1 FOREIGN KEY (borrowernumber) REFERENCES borrowers (borrowernumber) ON DELETE CASCADE ON UPDATE CASCADE; >+ "); >+ $dbh->do(" >+ ALTER TABLE `account_offsets` >+ ADD CONSTRAINT account_offsets_ibfk_1 FOREIGN KEY (debit_id) REFERENCES account_debits (debit_id) ON DELETE CASCADE ON UPDATE CASCADE, >+ ADD CONSTRAINT account_offsets_ibfk_2 FOREIGN KEY (credit_id) REFERENCES account_credits (credit_id) ON DELETE CASCADE ON UPDATE CASCADE; >+ "); >+ >+ $dbh->do(" >+ ALTER TABLE borrowers ADD account_balance DECIMAL( 28, 6 ) NOT NULL; >+ "); >+ >+ my $schema = Koha::Database->new()->schema; >+ my $debit_rs = $schema->resultset('AccountDebit'); >+ my $credit_rs = $schema->resultset('AccountCredit'); >+ my $issues_rs = $schema->resultset('Issue'); >+ >+ use Koha::Accounts::DebitTypes; >+ use Koha::Accounts::CreditTypes; >+ >+ my $debit_types_map = { >+ 'A' => Koha::Accounts::DebitTypes::AccountManagementFee, >+ 'F' => Koha::Accounts::DebitTypes::Fine, >+ 'FU' => Koha::Accounts::DebitTypes::Fine, >+ 'L' => Koha::Accounts::DebitTypes::Lost, >+ 'M' => Koha::Accounts::DebitTypes::Sundry, >+ 'N' => Koha::Accounts::DebitTypes::NewCard, >+ 'Rent' => Koha::Accounts::DebitTypes::Rental, >+ }; >+ >+ my $credit_types_map = { >+ 'FOR' => Koha::Accounts::CreditTypes::Forgiven, >+ 'LR' => Koha::Accounts::CreditTypes::Found, >+ 'Pay' => Koha::Accounts::CreditTypes::Payment, >+ 'PAY' => Koha::Accounts::CreditTypes::Payment, >+ 'WO' => Koha::Accounts::CreditTypes::WriteOff, >+ 'W' => Koha::Accounts::CreditTypes::WriteOff, >+ 'C' => Koha::Accounts::CreditTypes::Credit, >+ 'CR' => Koha::Accounts::CreditTypes::Credit, >+ }; >+ >+ my $sth = $dbh->prepare("SELECT * FROM accountlines"); >+ $sth->execute(); >+ while ( my $a = $sth->fetchrow_hashref() ) { >+ if ( $debit_types_map->{ $a->{accounttype} } ) { >+ $debit_rs->create( >+ { >+ borrowernumber => $a->{borrowernumber}, >+ itemnumber => $a->{itemnumber}, >+ amount_original => $a->{amount}, >+ amount_outstanding => $a->{amountoutstanding}, >+ created_on => $a->{timestamp}, >+ description => $a->{description}, >+ notes => $a->{note}, >+ manager_id => $a->{manager_id}, >+ accruing => $a->{accounttype} eq 'FU', >+ type => $debit_types_map->{ $a->{accounttype} }, >+ issue_id => $a->{accounttype} eq 'FU' >+ ? $issues_rs->single( >+ { >+ borrowernumber => $a->{borrowernumber}, >+ itemnumber => $a->{itemnumber}, >+ } >+ )->issue_id() >+ : undef, >+ } >+ ); >+ } >+ elsif ( $credit_types_map->{ $a->{accounttype} } ) { >+ $credit_rs->create( >+ { >+ borrowernumber => $a->{borrowernumber}, >+ amount_paid => $a->{amount} * -1, >+ amount_remaining => $a->{amountoutstanding} * -1, >+ created_on => $a->{timestamp}, >+ notes => $a->{note}, >+ manager_id => $a->{manager_id}, >+ type => $credit_types_map->{ $a->{accounttype} }, >+ } >+ ); >+ } >+ else { >+ # Everything else must be a MANUAL_INV >+ $debit_rs->create( >+ { >+ borrowernumber => $a->{borrowernumber}, >+ itemnumber => $a->{itemnumber}, >+ amount_original => $a->{amount}, >+ amount_outstanding => $a->{amountoutstanding}, >+ created_on => $a->{timestamp}, >+ description => $a->{description}, >+ notes => $a->{note}, >+ manager_id => $a->{manager_id}, >+ type => Koha::Accounts::DebitTypes::Sundry, >+ } >+ ); >+ } >+ } >+ >+ print "Upgrade to $DBversion done ( Bug 6427 - Rewrite of the accounts system )\n"; >+ SetVersion ($DBversion); >+} >+ > =head1 FUNCTIONS > > =head2 TableExists($table) >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/browser-strings.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/browser-strings.inc >index 3dda230..f6c74f6 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/browser-strings.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/browser-strings.inc >@@ -1,7 +1,34 @@ >+[% USE KohaAuthorisedValues %] > <script type="text/javascript"> > //<![CDATA[ > var BROWSER_RETURN_TO_SEARCH = _("Return to results"); > var BROWSER_PREVIOUS = _("Previous"); > var BROWSER_NEXT = _("Next"); >+ >+ var STRINGS = { >+ "DebitTypes": { >+ "FINE" : _("Fine"), >+ "ACCOUNT_MANAGEMENT_FEE" : _("Account management fee"), >+ "SUNDRY" : _("Sundry"), >+ "LOST" : _("Lost item"), >+ "HOLD" : _("Hold fee"), >+ "RENTAL" : _("Rental fee"), >+ "NEW_CARD" : _("New card"), >+ [% FOREACH a IN KohaAuthorisedValues.Get('MANUAL_INV') %] >+ "[% a.authorised_value %]" : "[% a.lib %]", >+ [% END %] >+ }, >+ >+ "CreditTypes": { >+ "CREDIT" : _("Credit"), >+ "PAYMENT" : _("Payment"), >+ "WRITEOFF" : _("Writeoff"), >+ "FOUND" : _("Lost item found"), >+ "FORGIVEN" : _("Forgiven"), >+ [% FOREACH a IN KohaAuthorisedValues.Get('MANUAL_CREDIT') %] >+ "[% a.authorised_value %]" : "[% a.lib %]", >+ [% END %] >+ } >+ } > //]]> > </script> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.inc >index 5687d01..c375ec5 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.inc >@@ -67,7 +67,7 @@ > [% IF ( detailview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">Details</a></li> > [% END %] > [% IF ( CAN_user_updatecharges ) %] >- [% IF ( finesview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrowernumber %]">Fines</a></li> >+ [% IF ( accounts_view ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Fines</a></li> > [% END %] > [% 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 %] > [% IF ( intranetreadinghistory ) %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.tt b/koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.tt >index 7f8cb48..456d52d 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.tt >@@ -70,7 +70,7 @@ in the global namespace %] > [% IF ( detailview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrower.borrowernumber %]">Details</a></li> > [% END %] > [% IF ( CAN_user_updatecharges ) %] >- [% IF ( finesview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrower.borrowernumber %]">Fines</a></li> >+ [% IF ( accounts_view ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrower.borrowernumber %]">Fines</a></li> > [% END %] > [% 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 %] > [% 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 %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/members-menu.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/members-menu.inc >index 9bd5285..9208e17 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/members-menu.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/members-menu.inc >@@ -4,7 +4,7 @@ > [% IF ( circview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/circ/circulation.pl?borrowernumber=[% borrowernumber %]">Check out</a></li> > [% IF ( detailview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">Details</a></li> > [% IF ( CAN_user_updatecharges ) %] >- [% IF ( finesview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrowernumber %]">Fines</a></li> >+ [% IF ( finesview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Fines</a></li> > [% END %] > [% IF ( intranetreadinghistory ) %] > [% IF ( readingrecordview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/readingrec.pl?borrowernumber=[% borrowernumber %]">Circulation history</a></li> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt >index 81ea2b6..75613f8 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt >@@ -1,5 +1,6 @@ > [% USE KohaBranchName %] > [% USE KohaDates %] >+[% USE Currency %] > [% IF ( export_remove_fields OR export_with_csv_profile ) %] > [% SET exports_enabled = 1 %] > [% END %] >@@ -577,16 +578,16 @@ No patron matched <span class="ex">[% message %]</span> > > [% IF ( charges ) %] > <li> >- <span class="circ-hlt">Fees & Charges:</span> Patron has <a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrowernumber %]">Outstanding fees & charges[% IF ( chargesamount ) %] of [% chargesamount %][% END %]</a>. >+ <span class="circ-hlt">Fees & Charges:</span> Patron has <a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Outstanding fees & charges[% IF ( chargesamount ) %] of [% chargesamount | $Currency %][% END %]</a>. > [% IF ( charges_is_blocker ) %] > Checkouts are <span class="circ-hlt">BLOCKED</span> because fine balance is <span class="circ-hlt">OVER THE LIMIT</span>. > [% END %] >- <a href="/cgi-bin/koha/members/pay.pl?borrowernumber=[% borrowernumber %]">Make payment</a></li> >+ <a href="/cgi-bin/koha/members/account_payment.pl?borrowernumber=[% borrowernumber %]">Make payment</a></li> > [% END %] > > [% IF ( credits ) %] > <li> >- <span class="circ-hlt">Credits:</span> Patron has a credit[% IF ( creditsamount ) %] of [% creditsamount %][% END %] >+ <span class="circ-hlt">Credits:</span> Patron has a credit[% IF ( creditsamount ) %] of [% creditsamount | $Currency %][% END %] > </li> > [% END %] > >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/returns.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/returns.tt >index fb30311..ffe4e0d 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/returns.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/returns.tt >@@ -74,7 +74,7 @@ $(document).ready(function () { > [% IF ( fines ) %] > <div class="dialog alert"> > <h3>Patron has outstanding fines of [% fines %].</h3> >- <p><a href="/cgi-bin/koha/members/pay.pl?borrowernumber=[% fineborrowernumber %]">Make payment</a>.</p> >+ <p><a href="/cgi-bin/koha/members/account_payment.pl?borrowernumber=[% fineborrowernumber %]">Make payment</a>.</p> > </div> > [% END %] > >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/help/reports/guided_reports.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/help/reports/guided_reports.tt >index 2af7d47..29d96ba 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/help/reports/guided_reports.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/help/reports/guided_reports.tt >@@ -108,24 +108,6 @@ > > <h3>DB table value for reports</h3> > >-<p><strong>Question:</strong> What do the codes in the accounttype field in the accountlines table stand for?</p> >- >-<p><strong>Answer:</strong></p> >- >-<ul> >- <li>A = Account management fee</li> >- <li>C = Credit</li> >- <li>F = Overdue fine</li> >- <li>FOR = Forgiven</li> >- <li>FU = Overdue, still acccruing</li> >- <li>L = Lost item</li> >- <li>LR = Lost item returned/refunded</li> >- <li>M = Sundry</li> >- <li>N = New card</li> >- <li>PAY = Payment</li> >- <li>W = Writeoff</li> >-</ul> >- > <p><strong>Question:</strong> What are the possible codes for the type field in the statistics table?</p> > > <p><strong>Answer:</strong></p> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/account.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/account.tt >new file mode 100644 >index 0000000..0562bba >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/account.tt >@@ -0,0 +1,431 @@ >+[% SET accounts_view = 1 %] >+[% USE KohaDates %] >+[% USE Currency %] >+[% INCLUDE 'doc-head-open.inc' %] >+<title>Koha › Patrons › Account for [% INCLUDE 'patron-title.inc' %]</title> >+[% INCLUDE 'doc-head-close.inc' %] >+ >+<link rel="stylesheet" type="text/css" href="[% interface %]/[% theme %]/en/css/datatables.css" /> >+<script type="text/javascript" src="[% interface %]/[% theme %]/en/lib/jquery/plugins/jquery.dataTables.min.js"></script> >+[% INCLUDE 'datatables-strings.inc' %] >+[% INCLUDE 'browser-strings.inc' %] >+<script type="text/javascript" src="[% interface %]/[% theme %]/en/js/datatables.js"></script> >+<script type="text/javascript" src="[% interface %]/[% theme %]/en/js/strings.js"></script> >+ >+<script type="text/javascript"> >+//<![CDATA[ >+$(document).ready(function() { >+ $('#account-credits').hide(); >+ $('#account-debits-switcher').click(function() { >+ $('#account-debits').slideUp(); >+ $('#account-credits').slideDown(); >+ }); >+ $('#account-credits-switcher').click(function() { >+ $('#account-credits').slideUp(); >+ $('#account-debits').slideDown(); >+ }); >+ >+ var anOpen = []; >+ var sImageUrl = "[% interface %]/[% theme %]/img/"; >+ >+ var debitsTable = $('#debits-table').dataTable( { >+ "bProcessing": true, >+ "aoColumns": [ >+ { >+ "mDataProp": null, >+ "sClass": "control center", >+ "sDefaultContent": '<img src="'+sImageUrl+'details_open.png'+'">' >+ }, >+ { "mDataProp": "debit_id" }, >+ { "mDataProp": "description" }, >+ { >+ "mDataProp": "type", >+ "fnRender": function ( o, val ) { >+ return STRINGS['DebitTypes'][val]; >+ }, >+ }, >+ { "mDataProp": "amount_original" }, >+ { "mDataProp": "amount_outstanding" }, >+ { "mDataProp": "created_on" }, >+ { "mDataProp": "updated_on" } >+ ], >+ "aaData": [ >+ [% FOREACH d IN debits %] >+ { >+ [% PROCESS format_data data=d highlight='debit' %] >+ >+ // Data for related item if there is one linked >+ "title": "[% d.item.biblio.title || d.deleted_item.biblio.title || d.deleted_item.deleted_biblio.title %]", >+ "biblionumber": "[% d.item.biblio.biblionumber || d.deleted_item.biblio.biblionumber %]", >+ "barcode": "[% d.item.barcode || d.deleted_item.barcode %]", >+ "itemnumber": "[% d.item.itemnumber %]", //This way itemnumber will be undef if deleted >+ >+ >+ // Data for related issue if there is one linked >+ [% IF d.issue %] >+ [% SET table = 'issue' %] >+ [% ELSIF d.old_issue %] >+ [% SET table = 'old_issue' %] >+ [% END %] >+ >+ [% IF table %] >+ "issue": { >+ [% PROCESS format_data data=d.$table %] >+ }, >+ [% END %] >+ >+ >+ "account_offsets": [ >+ [% FOREACH ao IN d.account_offsets %] >+ { >+ [% PROCESS format_data data=ao highlight='offset'%] >+ >+ "credit": { >+ [% PROCESS format_data data=ao.credit highlight='credit' %] >+ } >+ }, >+ [% END %] >+ ] >+ >+ }, >+ [% END %] >+ ] >+ } ); >+ >+ $('#debits-table td.control').live( 'click', function () { >+ var nTr = this.parentNode; >+ var i = $.inArray( nTr, anOpen ); >+ >+ if ( i === -1 ) { >+ $('img', this).attr( 'src', sImageUrl+"details_close.png" ); >+ var nDetailsRow = debitsTable.fnOpen( nTr, fnFormatDebitDetails(debitsTable, nTr), 'details' ); >+ $('div.innerDetails', nDetailsRow).slideDown(); >+ anOpen.push( nTr ); >+ } >+ else { >+ $('img', this).attr( 'src', sImageUrl+"details_open.png" ); >+ $('div.innerDetails', $(nTr).next()[0]).slideUp( function () { >+ debitsTable.fnClose( nTr ); >+ anOpen.splice( i, 1 ); >+ } ); >+ } >+ } ); >+ >+ var creditsTable = $('#credits-table').dataTable( { >+ "bProcessing": true, >+ "aoColumns": [ >+ { >+ "mDataProp": null, >+ "sClass": "control center", >+ "sDefaultContent": '<img src="'+sImageUrl+'details_open.png'+'">' >+ }, >+ { "mDataProp": "credit_id" }, >+ { "mDataProp": "notes" }, >+ { >+ "mDataProp": "type", >+ "fnRender": function ( o, val ) { >+ return STRINGS['CreditTypes'][val]; >+ }, >+ }, >+ { "mDataProp": "amount_paid" }, >+ { "mDataProp": "amount_remaining" }, >+ { "mDataProp": "created_on" }, >+ { "mDataProp": "updated_on" } >+ ], >+ "aaData": [ >+ [% FOREACH c IN credits %] >+ { >+ [% PROCESS format_data data=c highlight='credit' %] >+ >+ "account_offsets": [ >+ [% FOREACH ao IN c.account_offsets %] >+ { >+ [% PROCESS format_data data=ao highlight='offset' %] >+ >+ "debit": { >+ [% PROCESS format_data data=ao.debit highlight='debit' %] >+ } >+ }, >+ [% END %] >+ ] >+ >+ }, >+ [% END %] >+ ] >+ } ); >+ >+ $('#credits-table td.control').live( 'click', function () { >+ var nTr = this.parentNode; >+ var i = $.inArray( nTr, anOpen ); >+ >+ if ( i === -1 ) { >+ $('img', this).attr( 'src', sImageUrl+"details_close.png" ); >+ var nDetailsRow = creditsTable.fnOpen( nTr, fnFormatCreditDetails(creditsTable, nTr), 'details' ); >+ $('div.innerDetails', nDetailsRow).slideDown(); >+ anOpen.push( nTr ); >+ } >+ else { >+ $('img', this).attr( 'src', sImageUrl+"details_open.png" ); >+ $('div.innerDetails', $(nTr).next()[0]).slideUp( function () { >+ creditsTable.fnClose( nTr ); >+ anOpen.splice( i, 1 ); >+ } ); >+ } >+ } ); >+ >+} ); >+ >+function fnFormatDebitDetails( debitsTable, nTr ) { >+ var oData = debitsTable.fnGetData( nTr ); >+ >+ var sOut = '<div class="innerDetails" style="display:none;">'; >+ >+ var account_offsets = oData.account_offsets; >+ >+ sOut += '<a class="debit_print btn btn-small" style="margin:5px;" onclick="accountPrint(\'debit\',' + oData.debit_id + ')">' + >+ '<i class="icon-print"></i> ' + _('Print receipt') + >+ '</a>'; >+ >+ sOut += '<ul>'; >+ if ( oData.title ) { >+ sOut += '<li>' + _('Title: '); >+ if ( oData.biblionumber ) { >+ sOut += '<a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=' + oData.biblionumber + '">'; >+ } >+ >+ sOut += oData.title; >+ >+ if ( oData.biblionumber ) { >+ sOut += '</a>'; >+ } >+ >+ sOut += '</li>'; >+ } >+ >+ if ( oData.barcode ) { >+ sOut += '<li>' + _('Barcode: '); >+ if ( oData.itemnumber ) { >+ sOut += '<a href="/cgi-bin/koha/catalogue/moredetail.pl?itemnumber=11&biblionumber=' + oData.biblionumber + '&bi=' + oData.biblionumber + '#item' + oData.itemnumber + '' + oData.biblionumber + '">'; >+ } >+ >+ sOut += oData.barcode; >+ >+ if ( oData.itemnumber ) { >+ sOut += '</a>'; >+ } >+ >+ sOut += '</li>'; >+ } >+ >+ if ( oData.notes ) { >+ sOut += '<li>' + _('Notes: ') + oData.notes + '</li>'; >+ } >+ >+ sOut += '</ul>'; >+ >+ if ( account_offsets.length ) { >+ sOut += >+ '<div class="innerDetails">' + >+ '<table cellpadding="5" cellspacing="0" border="0" style="margin:10px;">' + >+ '<thead>' + >+ '<tr><th colspan="99">' + _('Payments applied') + '</th></tr>' + >+ '<tr>' + >+ '<th>' + _('ID') + '</th>' + >+ '<th>' + _('Created on') + '</th>' + >+ '<th>' + _('Payment amount') + '</th>' + >+ '<th>' + _('Applied amount') + '</th>' + >+ '<th>' + _('Type') + '</th>' + >+ '<th>' + _('Notes') + '</th>' + >+ '</tr>' + >+ '</thead>' + >+ '<tbody>'; >+ >+ for ( var i = 0; i < account_offsets.length; i++ ) { >+ ao = account_offsets[i]; >+ sOut += >+ '<tr>' + >+ '<td>' + ao.credit_id + '</td>' + >+ '<td>' + ao.created_on + '</td>' + >+ '<td>' + ao.credit.amount_paid + '</td>' + >+ '<td>' + ao.amount + '</td>' + >+ '<td>' + STRINGS['CreditTypes'][ao.credit.type] + '</td>' + >+ '<td>' + ao.credit.notes + '</td>' + >+ '</tr>'; >+ } >+ >+ sOut += >+ '</tbody>'+ >+ '</table>'; >+ } >+ >+ sOut += >+ '</div>'; >+ >+ return sOut; >+} >+ >+function fnFormatCreditDetails( creditsTable, nTr ) { >+ var oData = creditsTable.fnGetData( nTr ); >+ >+ var sOut = '<div class="innerDetails" style="display:none;">'; >+ >+ sOut += '<button class="credit_print btn btn-small" style="margin:5px;" onclick="accountPrint(\'credit\',' + oData.credit_id + ')">' + >+ '<i class="icon-print"></i> ' + _('Print receipt') + >+ '</button>'; >+ >+ var account_offsets = oData.account_offsets; >+ >+ if ( account_offsets.length ) { >+ sOut += >+ '<table cellpadding="5" cellspacing="0" border="0" style="margin:10px;">' + >+ '<thead>' + >+ '<tr><th colspan="99">' + _('Fees paid') + '</th></tr>' + >+ '<tr>' + >+ '<th>' + _('ID') + '</th>' + >+ '<th>' + _('Description') + '</th>' + >+ '<th>' + _('Type') + '</th>' + >+ '<th>' + _('Amount') + '</th>' + >+ '<th>' + _('Remaining') + '</th>' + >+ '<th>' + _('Created on') + '</th>' + >+ '<th>' + _('Updated on') + '</th>' + >+ '<th>' + _('Notes') + '</th>' + >+ '</tr>' + >+ '</thead>' + >+ '<tbody>'; >+ >+ for ( var i = 0; i < account_offsets.length; i++ ) { >+ ao = account_offsets[i]; >+ sOut += >+ '<tr>' + >+ '<td>' + ao.debit.debit_id + '</td>' + >+ '<td>' + ao.debit.description + '</td>' + >+ '<td>' + STRINGS['DebitTypes'][ao.debit.type] + '</td>' + >+ '<td>' + ao.debit.amount_original + '</td>' + >+ '<td>' + ao.debit.amount_outstanding + '</td>' + >+ '<td>' + ao.debit.created_on + '</td>' + >+ '<td>' + ao.debit.updated_on + '</td>' + >+ '<td>' + ao.debit.notes + '</td>' + >+ '</tr>'; >+ } >+ >+ sOut += >+ '</tbody>'+ >+ '</table>'; >+ } >+ >+ sOut += >+ '</div>'; >+ >+ return sOut; >+} >+ >+function accountPrint( type, id ) { >+ window.open( '/cgi-bin/koha/members/account_print.pl?type=' + type + '&id=' + id ); >+} >+//]]> >+</script> >+</head> >+<body> >+[% INCLUDE 'header.inc' %] >+[% INCLUDE 'patron-search.inc' %] >+ >+<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a> › Account for [% INCLUDE 'patron-title.inc' %]</div> >+ >+<div id="doc3" class="yui-t2"> >+ <div id="bd"> >+ <div id="yui-main"> >+ <div class="yui-b"> >+ [% INCLUDE 'members-toolbar.inc' %] >+ >+ <div class="statictabs"> >+ <ul> >+ <li class="active"> >+ <a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Account</a> >+ </li> >+ >+ <li> >+ <a href="/cgi-bin/koha/members/account_payment.pl?borrowernumber=[% borrowernumber %]" >Pay fines</a> >+ </li> >+ >+ <li> >+ <a href="/cgi-bin/koha/members/account_debit.pl?borrowernumber=[% borrowernumber %]" >Create manual invoice</a> >+ </li> >+ >+ <li> >+ <a href="/cgi-bin/koha/members/account_credit.pl?borrowernumber=[% borrowernumber %]" >Create manual credit</a> >+ </li> >+ </ul> >+ </div> >+ >+ <div class="tabs-container"> >+ >+ <p> >+ <h3>Account balance: [% borrower.account_balance | $Currency %]</h3> >+ </p> >+ >+ <div> >+ <div id="account-debits"> >+ <a id="account-debits-switcher" href="#" onclick="return false">View payments</a> >+ <table cellpadding="0" cellspacing="0" border="0" class="display" id="debits-table"> >+ <thead> >+ <tr> >+ <th colspan="99">Fees</th> >+ </tr> >+ <tr> >+ <th></th> >+ <th>ID</th> >+ <th>Description</th> >+ <th>Type</th> >+ <th>Amount</th> >+ <th>Outsanding</th> >+ <th>Created on</th> >+ <th>Updated on</th> >+ </tr> >+ </thead> >+ <tbody></tbody> >+ </table> >+ </div> >+ >+ <div id="account-credits"> >+ <a id="account-credits-switcher" href="#" onclick="return false">View fees</a> >+ <table cellpadding="0" cellspacing="0" border="0" class="display" id="credits-table"> >+ <thead> >+ <tr> >+ <th colspan="99">Payments</th> >+ </tr> >+ <tr> >+ <th></th> >+ <th>ID</th> >+ <th>Notes</th> >+ <th>Type</th> >+ <th>Amount</th> >+ <th>Remaining</th> >+ <th>Created on</th> >+ <th>Updated on</th> >+ </tr> >+ </thead> >+ <tbody></tbody> >+ </table> >+ </div> >+ </div> >+ </div> >+ </div> >+ </div> >+ >+ <div class="yui-b"> >+ [% INCLUDE 'circ-menu.inc' %] >+ </div> >+</div> >+[% INCLUDE 'intranet-bottom.inc' %] >+ >+[% BLOCK format_data %] >+ [% FOREACH key IN data.result_source.columns %] >+ [% IF key.match('^amount') %] >+ "[% key %]": "[% data.$key FILTER $Currency highlight => highlight %]", >+ [% ELSIF key.match('_on$') %] >+ "[% key %]": "[% data.$key | $KohaDates %]", >+ [% ELSE %] >+ "[% key %]": "[% data.$key %]", >+ [% END %] >+ [% END %] >+[% END %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_credit.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_credit.tt >new file mode 100644 >index 0000000..d8e8883 >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_credit.tt >@@ -0,0 +1,92 @@ >+[% SET accounts_view = 1 %] >+[% INCLUDE 'doc-head-open.inc' %] >+<title>Koha › Borrowers › Create manual credit</title> >+[% INCLUDE 'doc-head-close.inc' %] >+<script type="text/javascript"> >+//<![CDATA[ >+$(document).ready(function(){ >+ $('#account_credit').preventDoubleFormSubmit(); >+ $("fieldset.rows input").addClass("noEnterSubmit"); >+}); >+//]]> >+</script> >+</head> >+<body id="pat_account_credit" class="pat"> >+ [% INCLUDE 'header.inc' %] >+ [% INCLUDE 'patron-search.inc' %] >+ >+ <div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a> › Manual credit</div> >+ >+ <div id="doc3" class="yui-t2"> >+ <div id="bd"> >+ <div id="yui-main"> >+ <div class="yui-b"> >+ [% INCLUDE 'members-toolbar.inc' %] >+ >+ <div class="statictabs"> >+ <ul> >+ <li><a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Account</a></li> >+ <li><a href="/cgi-bin/koha/members/account_payment.pl?borrowernumber=[% borrowernumber %]" >Pay fines</a></li> >+ <li><a href="/cgi-bin/koha/members/account_debit.pl?borrowernumber=[% borrowernumber %]" >Create manual invoice</a></li> >+ <li class="active"><a href="/cgi-bin/koha/members/account_credit.pl?borrowernumber=[% borrowernumber %]" >Create manual credit</a></li> >+ </ul> >+ >+ <div class="tabs-container"> >+ >+ <form action="/cgi-bin/koha/members/account_credit_do.pl" method="post" id="account_credit"> >+ <input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrowernumber %]" /> >+ >+ <fieldset class="rows"> >+ <legend>Manual credit</legend> >+ >+ <ol> >+ <li> >+ <label for="type">Credit Type: </label> >+ <select name="type" id="type"> >+ <option value="CREDIT">Credit</option> >+ <option value="FORGIVEN">Forgiven</option> >+ [% FOREACH c IN credit_types_loop %] >+ <option value="[% c.authorised_value %]">[% c.lib %]</option> >+ [% END %] >+ </select> >+ </li> >+ >+ <li> >+ <label for="barcode">Barcode: </label> >+ <input type="text" name="barcode" id="barcode" /> >+ </li> >+ >+ <li> >+ <label for="desc">Description: </label> >+ <input type="text" name="desc" size="50" id="desc" /> >+ </li> >+ >+ <li> >+ <label for="note">Note: </label> >+ <input type="text" name="note" size="50" id="note" /> >+ </li> >+ >+ <li> >+ <label for="amount">Amount: </label> >+ <input type="text" name="amount" id="amount" /> >+ Example: 5.00 >+ </li> >+ </ol> >+ >+ </fieldset> >+ >+ <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> >+ </form> >+ >+ </div> >+ </div> >+ </div> >+ </div> >+ <div class="yui-b"> >+ [% INCLUDE 'circ-menu.inc' %] >+ </div> >+ </div> >+[% INCLUDE 'intranet-bottom.inc' %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_debit.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_debit.tt >new file mode 100644 >index 0000000..4055fd9 >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_debit.tt >@@ -0,0 +1,109 @@ >+[% SET accounts_view = 1 %] >+[% INCLUDE 'doc-head-open.inc' %] >+<title>Koha › Borrowers › Create manual invoice</title> >+[% INCLUDE 'doc-head-close.inc' %] >+<script type="text/javascript"> >+//<![CDATA[ >+$(document).ready(function(){ >+ $('#maninvoice').preventDoubleFormSubmit(); >+ $("fieldset.rows input").addClass("noEnterSubmit"); >+ >+ var type_fees = new Array(); >+ type_fees['L'] = ''; >+ type_fees['F'] = ''; >+ type_fees['A'] = ''; >+ type_fees['N'] = ''; >+ type_fees['M'] = ''; >+ [% FOREACH invoice_types_loo IN invoice_types_loop %] >+ type_fees['[% invoice_types_loo.authorised_value %]'] = "[% invoice_types_loo.lib %]"; >+ [% END %] >+}); >+//]]> >+</script> >+</head> >+ >+<body> >+ [% INCLUDE 'header.inc' %] >+ [% INCLUDE 'patron-search.inc' %] >+ >+ <div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a> › Manual invoice</div> >+ >+ <div id="doc3" class="yui-t2"> >+ <div id="bd"> >+ <div id="yui-main"> >+ <div class="yui-b"> >+ [% INCLUDE 'members-toolbar.inc' %] >+ >+ <div class="statictabs"> >+ <ul> >+ <li><a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Account</a></li> >+ <li><a href="/cgi-bin/koha/members/account_payment.pl?borrowernumber=[% borrowernumber %]" >Pay fines</a></li> >+ <li class="active"><a href="/cgi-bin/koha/members/account_debit.pl?borrowernumber=[% borrowernumber %]" >Create manual invoice</a></li> >+ <li><a href="/cgi-bin/koha/members/account_credit.pl?borrowernumber=[% borrowernumber %]" >Create manual credit</a></li> >+ </ul> >+ <div class="tabs-container"> >+ >+ <form action="/cgi-bin/koha/members/account_debit_do.pl" method="post" id="account_debit"> >+ <input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrowernumber %]" /> >+ >+ <fieldset class="rows"> >+ <legend>Manual Invoice</legend> >+ >+ <ol> >+ <li> >+ <label for="type">Type: </label> >+ <select name="type" id="type"> >+ <option value="LOST">Lost item</option> >+ <option value="FINE">Fine</option> >+ <option value="ACCOUNT_MANAGEMENT_FEE">Account management fee</option> >+ <option value="NEW_CARD">New card</option> >+ <option value="SUNDRY">Sundry</option> >+ >+ [% FOREACH invoice_types_loo IN invoice_types_loop %] >+ <option value="[% invoice_types_loo.authorised_value %]">[% invoice_types_loo.lib %]</option> >+ [% END %] >+ </select> >+ </li> >+ >+ <!-- TODO: Write ajax barcode validator that appends the itemnumber for this form in a hidden input --> >+ <li> >+ <label for="barcode">Barcode: </label> >+ <input type="text" name="barcode" id="barcode" /> >+ </li> >+ >+ <li> >+ <label for="description">Description: </label> >+ <input type="text" name="description" id="description" size="50" /> >+ </li> >+ >+ <li> >+ <label for="notes">Notes: </label> >+ <input type="text" name="notes" size="50" id="notes" /> >+ </li> >+ >+ <li> >+ <label for="amount">Amount: </label> >+ <input type="text" name="amount" id="amount" /> Example: 5.00 >+ </li> >+ >+ </ol> >+ </fieldset> >+ >+ <fieldset class="action"> >+ <input type="submit" name="add" value="Save" /> >+ <a class="cancel" href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Cancel</a> >+ </fieldset> >+ >+ </form> >+ >+ </div> >+ </div> >+ </div> >+ </div> >+ >+<div class="yui-b"> >+ [% INCLUDE 'circ-menu.inc' %] >+</div> >+ >+</div> >+[% INCLUDE 'intranet-bottom.inc' %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_payment.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_payment.tt >new file mode 100644 >index 0000000..4bd1f0c >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_payment.tt >@@ -0,0 +1,226 @@ >+[% SET accounts_view = 1 %] >+[% USE Currency %] >+[% INCLUDE 'doc-head-open.inc' %] >+<title>Koha › Patrons › Pay Fines for [% borrower.firstname %] [% borrower.surname %]</title> >+[% INCLUDE 'doc-head-close.inc' %] >+[% INCLUDE 'browser-strings.inc' %] >+<script type="text/javascript" src="[% themelang %]/lib/jquery/plugins/jquery.checkboxes.min.js"></script> >+<script type= "text/javascript"> >+//<![CDATA[ >+$( document ).ready(function() { >+ // Convert codes to translated strings >+ $(".debit-type").each(function() { >+ $(this).html( STRINGS['DebitTypes'][ $(this).html() ] ); >+ }); >+ >+ // Show amount recieved only if the "Receive different amount" checkbox is checked >+ $("#amount-received-p").hide(); >+ $("#receive_different_amount").click(function() { >+ if( $(this).is(':checked')) { >+ $("#amount-received-p").show(); >+ $("#amount_received").focus(); >+ } else { >+ $("#amount-received-p").hide(); >+ } >+ }); >+ >+ $("#amount_received").keyup(function() { >+ // Allow only numbers in ammount received >+ $(this).val($(this).val().replace(/[^\d.]/g, '')); >+ >+ // Make sure the amount recieved is greater than the amount to pay if it is being used >+ if ( $("#amount_to_pay").val() && parseFloat( $("#amount_received").val() ) < parseFloat( $("#amount_to_pay").val() ) ) { >+ $("#process").attr('disabled','disabled'); >+ } else { >+ $("#process").removeAttr('disabled'); >+ } >+ }); >+ >+ // Allow only numbers in ammount to pay >+ $("#amount_to_pay").keyup(function() { >+ var $this = $(this); >+ $this.val($this.val().replace(/[^\d.]/g, '')); >+ }); >+ >+ // Enable the "Select all/Clear all" links >+ $('#CheckAll').click(function() { >+ $("input[name='debit_id']" ).prop('checked', true).trigger("change"); >+ }); >+ $('#ClearAll').click(function() { >+ $("input[name='debit_id']" ).prop('checked', false).trigger("change"); >+ }); >+ >+ // Update the "amount to pay" field whenever a fee checkbox is changed >+ // Note, this is just a payment suggestion and can be changed to any amount >+ $("input[name='debit_id']" ).change(function() { >+ var sum = 0; >+ $("input[name='debit_id']:checked" ).each(function(i,n){ >+ sum += parseFloat( $( "#amount_outstanding_" + $(this).val() ).val() ); >+ }); >+ $('#amount_to_pay').val( sum ); >+ }); >+}); >+ >+function checkForm(){ >+ // If using the "amount to receive" field, make sure the librarian is recieving at >+ // least enough to pay those fees. >+ if ( $('#amount_received').val() ) { >+ if ( parseFloat( $('#amount_received').val() ) < parseFloat( $('#amount_to_pay').val() ) ) { >+ alert( _("Cannot pay more than receieved!") ); >+ return false; >+ } >+ } >+ >+ return true; >+} >+//]]> >+</script> >+</head> >+<body id="pat_pay" class="pat"> >+ [% INCLUDE 'header.inc' %] >+ [% INCLUDE 'patron-search.inc' %] >+ >+ <div id="breadcrumbs"> >+ <a href="/cgi-bin/koha/mainpage.pl">Home</a> >+ › <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a> >+ › Pay fines for [% borrower.firstname %] [% borrower.surname %] >+ </div> >+ >+ <div id="doc3" class="yui-t2"> >+ <div id="bd"> >+ <div id="yui-main"> >+ <div class="yui-b"> >+ [% INCLUDE 'members-toolbar.inc' borrowernumber=borrower.borrowernumber %] >+ >+ <div class="statictabs"> >+ <ul> >+ <li><a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrower.borrowernumber %]">Account</a></li> >+ <li class="active"><a href="/cgi-bin/koha/members/account_payment.pl?borrowernumber=[% borrower.borrowernumber %]" >Pay fines</a></li> >+ <li><a href="/cgi-bin/koha/members/account_debit.pl?borrowernumber=[% borrower.borrowernumber %]" >Create manual invoice</a></li> >+ <li><a href="/cgi-bin/koha/members/account_credit.pl?borrowernumber=[% borrower.borrowernumber %]" >Create manual credit</a></li> >+ </ul> >+ >+ <div class="tabs-container"> >+ >+ [% IF ( debits ) %] >+ <form action="/cgi-bin/koha/members/account_payment_do.pl" method="post" id="account-payment-form" onsubmit="return checkForm()"> >+ >+ <input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrower.borrowernumber %]" /> >+ >+ <p> >+ <span class="checkall"> >+ <a id="CheckAll" href="#">Select all</a> >+ </span> >+ >+ | >+ >+ <span class="clearall"> >+ <a id="ClearAll" href="#">Clear all</a> >+ </span> >+ </p> >+ >+ <table id="finest"> >+ <thead> >+ <tr> >+ <th> </th> >+ <th>Description</th> >+ <th>Account type</th> >+ <th>Original amount</th> >+ <th>Amount outstanding</th> >+ </tr> >+ </thead> >+ >+ <tbody> >+ [% SET total_due = 0 %] >+ [% FOREACH d IN debits %] >+ [% SET total_due = total_due + d.amount_outstanding %] >+ <tr> >+ <td> >+ <input type="checkbox" checked="checked" name="debit_id" value="[% d.debit_id %]" /> >+ </td> >+ >+ <td> >+ [% d.description %] >+ >+ [% IF d.notes %] >+ ( <i>[% d.notes %]</i> ) >+ [% END %] >+ </td> >+ >+ <td> >+ <span class="debit-type">[% d.type %]</span> >+ </td> >+ >+ <td class="debit"> >+ [% d.amount_original | $Currency %] >+ <input type="hidden" id="amount_original_[% d.debit_id %]" value="[% Currency.format_without_symbol( d.amount_original ) %]" /> >+ </td> >+ >+ <td class="debit"> >+ [% d.amount_outstanding | $Currency %] >+ <input type="hidden" id="amount_outstanding_[% d.debit_id %]" value="[% Currency.format_without_symbol( d.amount_outstanding ) %]" /> >+ </td> >+ </tr> >+ [% END %] >+ </tbody> >+ >+ <tfoot> >+ <tr> >+ <td class="total" colspan="4">Total Due:</td> >+ <td>[% total_due | $Currency %]</td> >+ </tr> >+ </tfoot> >+ >+ </table> >+ >+ <fieldset> >+ <p> >+ <label for="amount_to_pay">Amount to pay: [% Currency.symbol() %]</label> >+ <input type="text" name="amount_to_pay" id="amount_to_pay" value="[% Currency.format_without_symbol( total_due ) %]" /> >+ >+ <input type="checkbox" id="receive_different_amount" /> >+ <label for="receive_different_amount"><i>Receive different amount</i></label> >+ </p> >+ >+ <p id="amount-received-p"> >+ <label for="amount_received">Amount recieved: [% Currency.symbol() %]</label> >+ <input type="text" name="amount_received" id="amount_received" /> >+ </p> >+ >+ <p> >+ <label for="type">Type:</label> >+ <select id="type" name="type"> >+ <option value="PAYMENT">Payment</option> >+ <option value="WRITEOFF">Writeoff</option> >+ </select> >+ </p> >+ >+ <p> >+ <label for="notes">Payment notes:</label> >+ <input type="textbox" name="notes" id="notes" /> >+ <p> >+ </fieldset> >+ >+ <fieldset class="action"> >+ <input type="submit" id="process" value="Process" class="submit" /> >+ <a class="cancel" href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrower.borrowernumber %]">Cancel</a> >+ </fieldset> >+ >+ </form> >+ >+ [% ELSE %] >+ <p> >+ [% borrower.firstname %] [% borrower.surname %] has no outstanding fines. >+ </p> >+ [% END %] >+ >+ </div> >+ </div> >+ </div> >+ </div> >+ >+ <div class="yui-b"> >+ [% INCLUDE 'circ-menu.tt' %] >+ </div> >+ </div> >+[% INCLUDE 'intranet-bottom.inc' %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_print.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_print.tt >new file mode 100644 >index 0000000..88fd030 >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_print.tt >@@ -0,0 +1,146 @@ >+[% USE KohaDates %] >+[% USE Currency %] >+[% USE EncodeUTF8 %] >+[% INCLUDE 'doc-head-open.inc' %] >+<title>Print Receipt for [% cardnumber %]</title> >+[% INCLUDE 'doc-head-close.inc' %] >+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> >+<link rel="shortcut icon" href="[% IF ( IntranetFavicon ) %][% IntranetFavicon %][% ELSE %][% interface %]/[% theme %]/img/favicon.ico[% END %]" type="image/x-icon" /> >+<script type="text/javascript"> >+ function printThenClose() { >+ window.print(); >+ window.close(); >+ } >+</script> >+</head> >+ >+[% SET account = debit || credit %] >+[% SET borrower = account.borrower %] >+ >+<body id="account-print-body" onload="printThenClose();"> >+ >+ <table> >+ <thead> >+ <tr> >+ <th colspan="99"> >+ [% IF debit %] >+ Invoice >+ [% ELSIF credit %] >+ Payment receipt >+ [% END %] >+ </th> >+ </tr> >+ >+ <tr> >+ <th colspan="99"> >+ [% borrower.branch.branchname | $EncodeUTF8 %] >+ </th> >+ </tr> >+ >+ <tr> >+ <th>Name:</th> >+ <th colspan="99">[% borrower.firstname | $EncodeUTF8 %] [% borrower.surname | $EncodeUTF8 %]</th> >+ </tr> >+ >+ <tr> >+ <th>Card number:</th> >+ <th colspan="99">[% borrower.cardnumber %]</th> >+ </tr> >+ >+ <tr> >+ <th>Date:</th> >+ <th colspan="99">[% account.created_on | $KohaDates %]</th> >+ </tr> >+ >+ [% IF account.description %] >+ <tr> >+ <th>Description:</th> >+ <th colspan="99">[% account.description | $EncodeUTF8 %]</th> >+ </tr> >+ [% END %] >+ >+ [% IF credit %] >+ <tr> >+ <th>Amount paid:</th> >+ <th colspan="99">[% credit.amount_paid | $Currency highlight => type %]</th> >+ </tr> >+ [% IF credit.amount_received %] >+ <tr> >+ <th>Amount received:</th> >+ <th colspan="99">[% credit.amount_received | $Currency highlight => type %]</th> >+ </tr> >+ <tr> >+ <th>Change due:</th> >+ <th colspan="99">[% credit.amount_received - credit.amount_paid | $Currency highlight => type %]</th> >+ </tr> >+ [% END %] >+ <tr> >+ <th>Balance:</th> >+ <th colspan="99">[% credit.amount_remaining | $Currency highlight => type %]</th> >+ </tr> >+ [% IF credit.account_offsets %] >+ <tr> >+ <th colspan="99">Fees paid</th> >+ </tr> >+ <tr> >+ <th>Description</th> >+ <th>Type</th> >+ <th>Amount</th> >+ <th>Paid</th> >+ <th>Outstanding</th> >+ <th>Date</th> >+ </tr> >+ [% END %] >+ [% ELSIF debit %] >+ <tr> >+ <th>Amount:</th> >+ <th colspan="99">[% debit.amount_original | $Currency highlight => type %]</th> >+ </tr> >+ <tr> >+ <th>Outstanding:</th> >+ <th colspan="99">[% debit.amount_outstanding | $Currency highlight => type %]</th> >+ </tr> >+ [% IF debit.account_offsets %] >+ <tr> >+ <th colspan="99">Payments applied</th> >+ </tr> >+ <tr> >+ <th>Date</th> >+ <th>Type</th> >+ <th>Payment</th> >+ <th>Applied</th> >+ <th>Balance</th> >+ <th>Notes</th> >+ </tr> >+ [% END %] >+ [% END %] >+ </thead> >+ >+ <tbody> >+ [% IF credit.account_offsets %] >+ [% FOREACH ao IN credit.account_offsets %] >+ <tr> >+ <td>[% ao.debit.description %]</td> >+ <td>[% ao.debit.type %]</td> >+ <td>[% ao.debit.amount_original | $Currency highlight => 'debit' %]</td> >+ <td>[% ao.amount | $Currency highlight => 'offset' %]</td> >+ <td>[% ao.debit.amount_outstanding | $Currency highlight => 'debit' %]</td> >+ <td>[% ao.debit.created_on | $KohaDates %]</td> >+ </tr> >+ [% END %] >+ [% ELSIF debit.account_offsets %] >+ [% FOREACH ao IN debit.account_offsets %] >+ <tr> >+ <td>[% ao.credit.type %]</td> >+ <td>[% ao.credit.created_on | $KohaDates %]</td> >+ <td>[% ao.credit.amount_paid | $Currency highlight => 'credit' %]</td> >+ <td>[% ao.amount | $Currency highlight => 'offset' %]</td> >+ <td>[% ao.credit.amount_remaining | $Currency highlight => 'credit' %]</td> >+ <td>[% ao.credit.notes %]</td> >+ </tr> >+ [% END %] >+ [% END %] >+ </tbody> >+ </table> >+ >+[% INCLUDE 'intranet-bottom.inc' %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/boraccount.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/boraccount.tt >deleted file mode 100644 >index d64c63b..0000000 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/boraccount.tt >+++ /dev/null >@@ -1,99 +0,0 @@ >-[% INCLUDE 'doc-head-open.inc' %] >-<title>Koha › Patrons › Account for [% INCLUDE 'patron-title.inc' %]</title> >-[% INCLUDE 'doc-head-close.inc' %] >-</head> >-<body id="pat_borraccount" class="pat"> >-[% INCLUDE 'header.inc' %] >-[% INCLUDE 'patron-search.inc' %] >- >-<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a> › Account for [% INCLUDE 'patron-title.inc' %]</div> >- >-<div id="doc3" class="yui-t2"> >- >- <div id="bd"> >- <div id="yui-main"> >- <div class="yui-b"> >-[% INCLUDE 'members-toolbar.inc' %] >-<form action="/cgi-bin/koha/members/boraccount.pl" method="get"><input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrowernumber %]" /></form> >- >-<!-- The manual invoice and credit buttons --> >-<div class="statictabs"> >-<ul> >- <li class="active"><a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrowernumber %]">Account</a></li> >- <li><a href="/cgi-bin/koha/members/pay.pl?borrowernumber=[% borrowernumber %]" >Pay fines</a></li> >- <li><a href="/cgi-bin/koha/members/maninvoice.pl?borrowernumber=[% borrowernumber %]" >Create manual invoice</a></li> >- <li><a href="/cgi-bin/koha/members/mancredit.pl?borrowernumber=[% borrowernumber %]" >Create manual credit</a></li> >-</ul> >-<div class="tabs-container"> >-<!-- The table with the account items --> >-<table> >- <tr> >- <th>Date</th> >- <th>Description of charges</th> >- <th>Note</th> >- <th>Amount</th> >- <th>Outstanding</th> >- [% IF ( reverse_col ) %] >- <th> </th> >- [% END %] >- <th>Print</th> >- </tr> >- >- <!-- FIXME: Shouldn't hardcode dollar signs, since Euro or Pound might be needed --> >- [% FOREACH account IN accounts %] >- >- [% IF ( loop.odd ) %]<tr>[% ELSE %]<tr class="highlight">[% END %] >- <td>[% account.date %]</td> >- <td>[% account.description %] [% IF ( account.itemnumber ) %]<a href="/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=[% account.biblionumber %]&itemnumber=[% account.itemnumber %]">View item</a> [% END %][% account.title |html %]</td> >- <td>[% account.note | html_line_break %]</td> >- [% IF ( account.amountcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% account.amount %]</td> >- [% IF ( account.amountoutstandingcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% account.amountoutstanding %]</td> >- [% IF ( reverse_col ) %] >- <td> >- [% IF ( account.payment ) %] >- <a href="boraccount.pl?action=reverse&accountlines_id=[% account.accountlines_id %]&borrowernumber=[% account.borrowernumber %]">Reverse</a> >- [% ELSE %] >- >- [% END %] >- </td> >- [% END %] >-<td> >- [% IF ( account.payment ) %] >- <a target="_blank" href="printfeercpt.pl?action=print&accountlines_id=[% account.accountlines_id %]&borrowernumber=[% account.borrowernumber %]">Print</a> >- [% ELSE %] >- <a target="_blank" href="printinvoice.pl?action=print&accountlines_id=[% account.accountlines_id %]&borrowernumber=[% account.borrowernumber %]">Print</a> >- [% END %] >- </td> >- </tr> >- >- [% END %] >-<tfoot> >- <tr> >- <td colspan="4">Total due</td> >- [% IF ( totalcredit ) %] >- [% IF ( reverse_col ) %] >- <td colspan="3" class="credit"> >- [% ELSE %] >- <td colspan="2" class="credit"> >- [% END %] >- [% ELSE %] >- [% IF ( reverse_col ) %] >- <td colspan="3" class="debit"> >- [% ELSE %] >- <td colspan="2" class="credit"> >- [% END %] >- [% END %] >- [% total %]</td> >- </tr> >- </tfoot> >-</table> >-</div></div> >- >-</div> >-</div> >- >-<div class="yui-b"> >-[% INCLUDE 'circ-menu.inc' %] >-</div> >-</div> >-[% INCLUDE 'intranet-bottom.inc' %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/mancredit.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/mancredit.tt >index ff2b6b6..48d10ac 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/mancredit.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/mancredit.tt >@@ -26,14 +26,14 @@ $(document).ready(function(){ > <!-- The manual invoice and credit buttons --> > <div class="statictabs"> > <ul> >- <li><a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrowernumber %]">Account</a></li> >- <li><a href="/cgi-bin/koha/members/pay.pl?borrowernumber=[% borrowernumber %]" >Pay fines</a></li> >- <li><a href="/cgi-bin/koha/members/maninvoice.pl?borrowernumber=[% borrowernumber %]" >Create manual invoice</a></li> >- <li class="active"><a href="/cgi-bin/koha/members/mancredit.pl?borrowernumber=[% borrowernumber %]" >Create manual credit</a></li> >+ <li><a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Account</a></li> >+ <li><a href="/cgi-bin/koha/members/account_payment.pl?borrowernumber=[% borrowernumber %]" >Pay fines</a></li> >+ <li><a href="/cgi-bin/koha/members/account_debit.pl?borrowernumber=[% borrowernumber %]" >Create manual invoice</a></li> >+ <li class="active"><a href="/cgi-bin/koha/members/account_credit.pl?borrowernumber=[% borrowernumber %]" >Create manual credit</a></li> > </ul> > <div class="tabs-container"> > >-<form action="/cgi-bin/koha/members/mancredit.pl" method="post" id="mancredit"> >+<form action="/cgi-bin/koha/members/account_credit.pl" method="post" id="mancredit"> > <input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrowernumber %]" /> > > <fieldset class="rows"> >@@ -48,7 +48,7 @@ $(document).ready(function(){ > <li><label for="amount">Amount: </label><input type="text" name="amount" id="amount" /> Example: 5.00</li> > </ol></fieldset> > >-<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> >+<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> > </form> > > </div></div> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/maninvoice.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/maninvoice.tt >deleted file mode 100644 >index 30a4e20..0000000 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/maninvoice.tt >+++ /dev/null >@@ -1,87 +0,0 @@ >-[% INCLUDE 'doc-head-open.inc' %] >-<title>Koha › Borrowers › Create manual invoice</title> >-[% INCLUDE 'doc-head-close.inc' %] >-<script type="text/javascript"> >-//<![CDATA[ >-$(document).ready(function(){ >- $('#maninvoice').preventDoubleFormSubmit(); >- $("fieldset.rows input").addClass("noEnterSubmit"); >-}); >-//]]> >-</script> >-</head> >-<body id="pat_maninvoice" class="pat"> >-[% INCLUDE 'header.inc' %] >-[% INCLUDE 'patron-search.inc' %] >- >-<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a> › Manual Invoice</div> >- >-<div id="doc3" class="yui-t2"> >- >- <div id="bd"> >- <div id="yui-main"> >- <div class="yui-b"> >-[% INCLUDE 'members-toolbar.inc' %] >- >-<!-- The manual invoice and credit buttons --> >-<div class="statictabs"> >-<ul> >- <li><a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrowernumber %]">Account</a></li> >- <li><a href="/cgi-bin/koha/members/pay.pl?borrowernumber=[% borrowernumber %]" >Pay fines</a></li> >- <li class="active"><a href="/cgi-bin/koha/members/maninvoice.pl?borrowernumber=[% borrowernumber %]" >Create manual invoice</a></li> >- <li><a href="/cgi-bin/koha/members/mancredit.pl?borrowernumber=[% borrowernumber %]" >Create manual credit</a></li> >-</ul> >-<div class="tabs-container"> >- >-[% IF ( ERROR ) %] >-[% IF ( ITEMNUMBER ) %] >- ERROR an invalid itemnumber was entered, please hit back and try again >-[% END %] >-[% ELSE %] >-<form action="/cgi-bin/koha/members/maninvoice.pl" method="post" id="maninvoice"><input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrowernumber %]" /> >- <fieldset class="rows"> >- <legend>Manual Invoice</legend> >- <ol> >- <li> >-<script type="text/javascript"> >-var type_fees = new Array(); >-type_fees['L'] = ''; >-type_fees['F'] = ''; >-type_fees['A'] = ''; >-type_fees['N'] = ''; >-type_fees['M'] = ''; >-[% FOREACH invoice_types_loo IN invoice_types_loop %] >-type_fees['[% invoice_types_loo.authorised_value %]'] = "[% invoice_types_loo.lib %]"; >-[% END %] >-</script> >- <label for="type">Type: </label> >- <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];"> >- <option value="L">Lost item</option> >- <option value="F">Fine</option> >- <option value="A">Account management fee</option> >- <option value="N">New card</option> >- <option value="M">Sundry</option> >- [% FOREACH invoice_types_loo IN invoice_types_loop %] >- <option value="[% invoice_types_loo.authorised_value %]">[% invoice_types_loo.authorised_value %]</option> >- [% END %] >- </select> >- </li> >- <li><label for="barcode">Barcode: </label><input type="text" name="barcode" id="barcode" /></li> >- <li><label for="desc">Description: </label><input type="text" name="desc" id="desc" size="50" /></li> >- <li><label for="note">Note: </label><input type="text" name="note" size="50" id="note" /></li> >- <li><label for="amount">Amount: </label><input type="text" name="amount" id="amount" /> Example: 5.00</li> >- </ol></fieldset> >-<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> >-</form> >- >-[% END %] >-</div></div> >- >-</div> >-</div> >- >-<div class="yui-b"> >-[% INCLUDE 'circ-menu.inc' %] >-</div> >-</div> >-[% INCLUDE 'intranet-bottom.inc' %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/pay.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/pay.tt >deleted file mode 100644 >index 91f1609..0000000 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/pay.tt >+++ /dev/null >@@ -1,153 +0,0 @@ >-[% INCLUDE 'doc-head-open.inc' %] >-<title>Koha › Patrons › Pay Fines for [% borrower.firstname %] [% borrower.surname %]</title> >-[% INCLUDE 'doc-head-close.inc' %] >-<script type="text/javascript" src="[% themelang %]/lib/jquery/plugins/jquery.checkboxes.min.js"></script> >-<script type= "text/javascript"> >-//<![CDATA[ >-function enableCheckboxActions(){ >- // Enable/disable controls if checkboxes are checked >- var checkedBoxes = $("input.cb:checked"); >- if ($(checkedBoxes).size()) { >- $("#payselected").prop("disabled",false); >- } else { >- $("#payselected").prop("disabled",true); >- } >-} >- $(document).ready(function(){ >- $('#pay-fines-form').preventDoubleFormSubmit(); >- $("#woall").click(function(event){ >- var answer = confirm(_("Are you sure you want to write off [% total | format('%.2f') %] in outstanding fines? This cannot be undone!")); >- if (!answer){ >- event.preventDefault(); >- } >- }); >- $('#CheckAll').click(function(){ >- $("#finest").checkCheckboxes(); >- enableCheckboxActions(); >- return false; >- }); >- $('#CheckNone').click(function(){ >- $("#finest").unCheckCheckboxes(); >- enableCheckboxActions(); >- return false; >- }); >- $(".cb").change(function(){ >- enableCheckboxActions(); >- }); >- enableCheckboxActions(); >- }); >-//]]> >-</script> >-</head> >-<body id="pat_pay" class="pat"> >-[% INCLUDE 'header.inc' %] >-[% INCLUDE 'patron-search.inc' %] >- >-<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a> › Pay fines for [% borrower.firstname %] [% borrower.surname %]</div> >- >-<div id="doc3" class="yui-t2"> >- >- <div id="bd"> >- <div id="yui-main"> >- <div class="yui-b"> >-[% INCLUDE 'members-toolbar.inc' borrowernumber=borrower.borrowernumber %] >- >-<!-- The manual invoice and credit buttons --> >-<div class="statictabs"> >-<ul> >- <li><a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrower.borrowernumber %]">Account</a></li> >- <li class="active"><a href="/cgi-bin/koha/members/pay.pl?borrowernumber=[% borrower.borrowernumber %]" >Pay fines</a></li> >- <li><a href="/cgi-bin/koha/members/maninvoice.pl?borrowernumber=[% borrower.borrowernumber %]" >Create manual invoice</a></li> >- <li><a href="/cgi-bin/koha/members/mancredit.pl?borrowernumber=[% borrower.borrowernumber %]" >Create manual credit</a></li> >-</ul> >-<div class="tabs-container"> >- >-[% IF ( accounts ) %] >- <form action="/cgi-bin/koha/members/pay.pl" method="post" id="pay-fines-form"> >- <input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrower.borrowernumber %]" /> >-<p><span class="checkall"><a id="CheckAll" href="#">Select all</a></span> | <span class="clearall"><a id="CheckNone" href="#">Clear all</a></span></p> >-<table id="finest"> >-<thead> >-<tr> >- <th> </th> >- <th>Fines & charges</th> >- <th>Description</th> >- <th>Payment note</th> >- <th>Account type</th> >- <th>Notify id</th> >- <th>Level</th> >- <th>Amount</th> >- <th>Amount outstanding</th> >-</tr> >-</thead> >-<tfoot> >-<tr> >- <td class="total" colspan="8">Total Due:</td> >- <td>[% total | format('%.2f') %]</td> >-</tr> >-</tfoot> >-<tbody> >-[% FOREACH account_grp IN accounts %] >- [% FOREACH line IN account_grp.accountlines %] >-<tr> >- <td> >- [% IF ( line.amountoutstanding > 0 ) %] >- <input class="cb" type="checkbox" checked="checked" name="incl_par_[% line.accountno %]" /> >- [% END %] >- </td> >- <td> >- [% IF ( line.amountoutstanding > 0 ) %] >- <input type="submit" name="pay_indiv_[% line.accountno %]" value="Pay" /> >- <input type="submit" name="wo_indiv_[% line.accountno %]" value="Write off" /> >- [% END %] >- <input type="hidden" name="itemnumber[% line.accountno %]" value="[% line.itemnumber %]" /> >- <input type="hidden" name="description[% line.accountno %]" value="[% line.description %]" /> >- <input type="hidden" name="accounttype[% line.accountno %]" value="[% line.accounttype %]" /> >- <input type="hidden" name="amount[% line.accountno %]" value="[% line.amount %]" /> >- <input type="hidden" name="accountlines_id[% line.accountno %]" value="[% line.accountlines_id %]" /> >- <input type="hidden" name="amountoutstanding[% line.accountno %]" value="[% line.amountoutstanding %]" /> >- <input type="hidden" name="borrowernumber[% line.accountno %]" value="[% line.borrowernumber %]" /> >- <input type="hidden" name="accountno[% line.accountno %]" value="[% line.accountno %]" /> >- <input type="hidden" name="notify_id[% line.accountno %]" value="[% line.notify_id %]" /> >- <input type="hidden" name="notify_level[% line.accountno %]" value="[% line.notify_level %]" /> >- <input type="hidden" name="totals[% line.accountno %]" value="[% line.totals %]" /> >- </td> >- <td>[% line.description %] ([% line.title |html_entity %])</td> >- <td><input type="text" name="payment_note_[% line.accountno %]" /></td> >- <td>[% line.accounttype %]</td> >- <td>[% line.notify_id %]</td> >- <td>[% line.notify_level %]</td> >- <td class="debit">[% line.amount | format('%.2f') %]</td> >- <td class="debit">[% line.amountoutstanding | format('%.2f') %]</td> >-</tr> >-[% END %] >-[% IF ( account_grp.total ) %] >-<tr> >- >- <td class="total" colspan="8">Sub total:</td> >- <td>[% account_grp.total | format('%.2f') %]</td> >-</tr> >-[% END %] >-[% END %] >-</tbody> >-</table> >-<fieldset class="action"> >-<input type="submit" id="paycollect" name="paycollect" value="Pay amount" class="submit" /> >-<input type="submit" name="woall" id="woall" value="Write off all" class="submit" /> >-<input type="submit" id="payselected" name="payselected" value="Pay selected" class="submit" /> >-<a class="cancel" href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrower.borrowernumber %]">Cancel</a> >-</fieldset> >-</form> >-[% ELSE %] >- <p>[% borrower.firstname %] [% borrower.surname %] has no outstanding fines.</p> >-[% END %] >-</div></div> >- >-</div> >-</div> >- >-<div class="yui-b"> >-[% INCLUDE 'circ-menu.tt' %] >-</div> >-</div> >-[% INCLUDE 'intranet-bottom.inc' %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/paycollect.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/paycollect.tt >deleted file mode 100644 >index 9cec275..0000000 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/paycollect.tt >+++ /dev/null >@@ -1,233 +0,0 @@ >-[% INCLUDE 'doc-head-open.inc' %] >-<title>Koha › Patrons › Collect fine payment for [% borrower.firstname %] [% borrower.surname %]</title> >-[% INCLUDE 'doc-head-close.inc' %] >-<script type= "text/javascript"> >-//<![CDATA[ >-$(document).ready(function() { >- $('#payindivfine, #woindivfine, #payfine').preventDoubleFormSubmit(); >-}); >-//]]> >-</script> >-<script type= "text/javascript"> >-//<![CDATA[ >-function moneyFormat(textObj) { >- var newValue = textObj.value; >- var decAmount = ""; >- var dolAmount = ""; >- var decFlag = false; >- var aChar = ""; >- >- for(i=0; i < newValue.length; i++) { >- aChar = newValue.substring(i, i+1); >- if (aChar >= "0" && aChar <= "9") { >- if(decFlag) { >- decAmount = "" + decAmount + aChar; >- } >- else { >- dolAmount = "" + dolAmount + aChar; >- } >- } >- if (aChar == ".") { >- if (decFlag) { >- dolAmount = ""; >- break; >- } >- decFlag = true; >- } >- } >- >- if (dolAmount == "") { >- dolAmount = "0"; >- } >-// Strip leading 0s >- if (dolAmount.length > 1) { >- while(dolAmount.length > 1 && dolAmount.substring(0,1) == "0") { >- dolAmount = dolAmount.substring(1,dolAmount.length); >- } >- } >- if (decAmount.length > 2) { >- decAmount = decAmount.substring(0,2); >- } >-// Pad right side >- if (decAmount.length == 1) { >- decAmount = decAmount + "0"; >- } >- if (decAmount.length == 0) { >- decAmount = decAmount + "00"; >- } >- >- textObj.value = dolAmount + "." + decAmount; >-} >-//]]> >-</script> >-</head> >-<body id="pat_paycollect" class="pat"> >-[% INCLUDE 'header.inc' %] >-[% INCLUDE 'patron-search.inc' %] >-<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a> › <a href="/cgi-bin/koha/members/pay.pl?borrowernumber=[% borrower.borrowernumber %]">Pay fines for [% borrower.firstname %] [% borrower.surname %]</a> › [% 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> >- >-<div id="doc3" class="yui-t2"> >- >-<div id="bd"> >-<div id="yui-main"> >-<div class="yui-b"> >-[% INCLUDE 'members-toolbar.inc' borrowernumber=borrower.borrowernumber %] >- >- >-<!-- The manual invoice and credit buttons --> >-<div class="statictabs"> >-<ul> >- <li> >- <a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrower.borrowernumber %]">Account</a> >- </li> >- <li class="active"> >- <a href="/cgi-bin/koha/members/pay.pl?borrowernumber=[% borrower.borrowernumber %]" >Pay fines</a> >- </li> >- <li> >- <a href="/cgi-bin/koha/members/maninvoice.pl?borrowernumber=[% borrower.borrowernumber %]" >Create manual invoice</a> >- </li> >- <li> >- <a href="/cgi-bin/koha/members/mancredit.pl?borrowernumber=[% borrower.borrowernumber %]" >Create manual credit</a> >- </li> >-</ul> >-<div class="tabs-container"> >-[% IF ( error_over ) %] >- <div id="error_message" class="dialog alert"> >- You must pay a value less than or equal to [% total_due | format('%.2f') %]. >- </div> >-[% END %] >- >-[% IF ( pay_individual ) %] >- <form name="payindivfine" id="payindivfine" onsubmit="return validatePayment(this);" method="post" action="/cgi-bin/koha/members/paycollect.pl"> >- <input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrower.borrowernumber %]" /> >- <input type="hidden" name="pay_individual" id="pay_individual" value="[% pay_individual %]" /> >- <input type="hidden" name="itemnumber" id="itemnumber" value="[% itemnumber %]" /> >- <input type="hidden" name="description" id="description" value="[% description %]" /> >- <input type="hidden" name="accounttype" id="accounttype" value="[% accounttype %]" /> >- <input type="hidden" name="notify_id" id="notify_id" value="[% notify_id %]" /> >- <input type="hidden" name="notify_level" id="notify_level" value="[% notify_level %]" /> >- <input type="hidden" name="amount" id="amount" value="[% amount %]" /> >- <input type="hidden" name="amountoutstanding" id="amountoutstanding" value="[% amountoutstanding %]" /> >- <input type="hidden" name="accountno" id="accountno" value="[% accountno %]" /> >- <input type="hidden" name="accountlines_id" id="accountlines_id" value="[% accountlines_id %]" /> >- <input type="hidden" name="title" id="title" value="[% title %]" /> >- >-<fieldset class="rows"> >- <legend>Pay an individual fine</legend> >- <input type="hidden" name="payment_note" id="payment_note" value="[% payment_note %]" /> >- <table> >- <thead><tr> >- <th>Description</th> >- <th>Account type</th> >- <th>Notify id</th> >- <th>Level</th> >- <th>Amount</th> >- <th>Amount outstanding</th> >- </tr></thead> >- <tfoot> >- <td colspan="5">Total amount payable:</td><td>[% amountoutstanding | format('%.2f') %]</td> >- </tfoot> >- <tbody><tr> >- <td> >- [% description %] [% title %] >- </td> >- <td>[% accounttype %]</td> >- <td>[% notify_id %]</td> >- <td>[% notify_level %]</td> >- <td class="debit">[% amount | format('%.2f') %]</td> >- <td class="debit">[% amountoutstanding | format('%.2f') %]</td> >- </tr></tbody> >-</table> >- >-<ol> >- >- <li> >- <label for="paid">Collect from patron: </label> >- <!-- default to paying all --> >- <input name="paid" id="paid" value="[% amountoutstanding | format('%.2f') %]" onchange="moneyFormat(document.payindivfine.paid)"/> >- </li> >-</ol> >-</fieldset> >- >- <div class="action"><input type="submit" name="submitbutton" value="Confirm" /> >- <a class="cancel" href="/cgi-bin/koha/members/pay.pl?borrowernumber=[% borrower.borrowernumber %]">Cancel</a></div> >- </form> >-[% ELSIF ( writeoff_individual ) %] >- <form name="woindivfine" id="woindivfine" action="/cgi-bin/koha/members/pay.pl" method="post" > >- <fieldset class="rows"> >- <legend>Write off an individual fine</legend> >- <input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrower.borrowernumber %]" /> >- <input type="hidden" name="pay_individual" id="pay_individual" value="[% pay_individual %]" /> >- <input type="hidden" name="itemnumber" id="itemnumber" value="[% itemnumber %]" /> >- <input type="hidden" name="description" id="description" value="[% description %]" /> >- <input type="hidden" name="accounttype" id="accounttype" value="[% accounttype %]" /> >- <input type="hidden" name="notify_id" id="notify_id" value="[% notify_id %]" /> >- <input type="hidden" name="notify_level" id="notify_level" value="[% notify_level %]" /> >- <input type="hidden" name="amount" id="amount" value="[% amount %]" /> >- <input type="hidden" name="amountoutstanding" id="amountoutstanding" value="[% amountoutstanding %]" /> >- <input type="hidden" name="accountno" id="accountno" value="[% accountno %]" /> >- <input type="hidden" name="accountlines_id" id="accountlines_id" value="[% accountlines_id %]" /> >- <input type="hidden" name="title" id="title" value="[% title %]" /> >- <input type="hidden" name="payment_note" id="payment_note" value="[% payment_note %]" /> >- <table> >- <thead><tr> >- <th>Description</th> >- <th>Account type</th> >- <th>Notify id</th> >- <th>Level</th> >- <th>Amount</th> >- <th>Amount outstanding</th> >- </tr></thead> >- <tfoot><td colspan="5">Total amount to be written off:</td><td>[% amountoutstanding | format('%.2f') %]</td></tfoot> >- <tbody><tr> >- <td>[% description %] [% title %]</td> >- <td>[% accounttype %]</td> >- <td>[% notify_id %]</td> >- <td>[% notify_level %]</td> >- <td class="debit">[% amount | format('%.2f') %]</td> >- <td class="debit">[% amountoutstanding | format('%.2f') %]</td> >- </tr></tbody> >- </table> >- </fieldset> >- <div class="action"><input type="submit" name="confirm_writeoff" id="confirm_writeoff" value="Write off this charge" /> >- <a class="cancel" href="/cgi-bin/koha/members/pay.pl?borrowernumber=[% borrower.borrowernumber %]">Cancel</a></div> >- </form> >-[% ELSE %] >- >- <form name="payfine" id="payfine" onsubmit="return validatePayment(this);" method="post" action="/cgi-bin/koha/members/paycollect.pl"> >- <input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrower.borrowernumber %]" /> >- <input type="hidden" name="selected_accts" id="selected_accts" value="[% selected_accts %]" /> >- <input type="hidden" name="total" id="total" value="[% total %]" /> >- >- <fieldset class="rows"> >- [% IF ( selected_accts ) %]<legend>Pay an amount toward selected fines</legend>[% ELSE %]<legend>Pay an amount toward all fines</legend>[% END %] >- <ol> >- <li> >- <span class="label">Total amount outstanding: </span> >- <span class="debit">[% total | format('%.2f') %]</span> >- </li> >- <li> >- <label for="paid">Collect from patron: </label> >- <!-- default to paying all --> >- <input name="paid" id="paid" value="[% total | format('%.2f') %]" onchange="moneyFormat(document.payfine.paid)"/> >- </li> >- <li> >- <label for="selected_accts_notes">Note: </label> >- <textarea name="selected_accts_notes" id="selected_accts_notes">[% selected_accts_notes %]</textarea> >- </li> >- </ol> >- </fieldset> >- <div class="action"><input type="submit" name="submitbutton" value="Confirm" /> >- <a class="cancel" href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrower.borrowernumber %]">Cancel</a></div> >- </form> >-[% END %] >-</div></div> >-</div> >-</div> >- >-<div class="yui-b"> >-[% INCLUDE 'circ-menu.tt' %] >-</div> >-</div> >-[% INCLUDE 'intranet-bottom.inc' %] >- >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/printfeercpt.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/printfeercpt.tt >deleted file mode 100644 >index 26be3f4..0000000 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/printfeercpt.tt >+++ /dev/null >@@ -1,63 +0,0 @@ >-[% INCLUDE 'doc-head-open.inc' %] >-<title>Print Receipt for [% cardnumber %]</title> >-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> >-<link rel="shortcut icon" href="[% IF ( IntranetFavicon ) %][% IntranetFavicon %][% ELSE %][% interface %]/[% theme %]/img/favicon.ico[% END %]" type="image/x-icon" /> >-<link rel="stylesheet" type="text/css" href="[% themelang %]/css/printreceiptinvoice.css" /> >-<script type="text/javascript"> >- function printThenClose() { >- window.print(); >- window.close(); >- } >-</script> >-</head> >-<body id="pat_printfeercpt" class="pat" onload="printThenClose();"> >- >-<div id="receipt"> >-<!-- The table with the account items --> >-<table> >-[% IF ( LibraryName ) %] >- <tr> >- <th colspan=3 class="centerednames"> >- <h3>[% LibraryName %]</h3> >- </th> >- </tr> >-[% END %] >- <tr> >- <th colspan=3 class="centerednames"> >- <h2><u>Fee receipt</u></h2> >- </th> >- </tr> >- <tr> >- <th colspan=3 class="centerednames"> >- [% IF ( branchname ) %]<h2>[% branchname %]</h2>[% END %] >- </th> >- </tr> >- <tr> >- <th colspan=3 > >- Received with thanks from [% firstname %] [% surname %] <br /> >- Card number : [% cardnumber %]<br /> >- </th> >- </tr> >- <tr> >- <th>Date</th> >- <th>Description of charges</th> >- <th>Amount</th> >- </tr> >- >- [% FOREACH account IN accounts %] >-<tr class="highlight"> >- <td>[% account.date %]</td> >- <td>[% account.description %]</td> >- [% IF ( account.amountcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% account.amount %]</td> >- </tr> >- >- [% END %] >-<tfoot> >- <tr> >- <td colspan="2">Total outstanding dues as on date : </td> >- [% IF ( totalcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% total %]</td> >- </tr> >- </tfoot> >-</table> >-</div> >-[% INCLUDE 'intranet-bottom.inc' %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/printinvoice.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/printinvoice.tt >deleted file mode 100644 >index 8a19918..0000000 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/printinvoice.tt >+++ /dev/null >@@ -1,65 +0,0 @@ >-[% INCLUDE 'doc-head-open.inc' %] >-<title>Print Receipt for [% cardnumber %]</title> >-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> >-<link rel="shortcut icon" href="[% IF ( IntranetFavicon ) %][% IntranetFavicon %][% ELSE %][% interface %]/[% theme %]/img/favicon.ico[% END %]" type="image/x-icon" /> >-<link rel="stylesheet" type="text/css" href="[% themelang %]/css/printreceiptinvoice.css" /> >-<script type="text/javascript"> >- function printThenClose() { >- window.print(); >- window.close(); >- } >-</script> >-</head> >-<body id="printinvoice" class="pat" onload="printThenClose();"> >- >-<div id="receipt"> >-<!-- The table with the account items --> >-<table> >-[% IF ( LibraryName ) %] >- <tr> >- <th colspan="4" class="centerednames"> >- <h3>[% LibraryName %]</h3> >- </th> >- </tr> >-[% END %] >- <tr> >- <th colspan="4" class="centerednames"> >- <h2><u>INVOICE</u></h2> >- </th> >- </tr> >- <tr> >- <th colspan="4" class="centerednames"> >- [% IF ( branchname ) %]<h2>[% branchname %]</h2>[% END %] >- </th> >- </tr> >- <tr> >- <th colspan="4" > >- Bill to: [% firstname %] [% surname %] <br /> >- Card number: [% cardnumber %]<br /> >- </th> >- </tr> >- <tr> >- <th>Date</th> >- <th>Description of charges</th> >- <th style="text-align:right;">Amount</th> >- <th style="text-align:right;">Amount outstanding</th> >- </tr> >- >- [% FOREACH account IN accounts %] >-<tr class="highlight"> >- <td>[% account.date %]</td> >- <td>[% account.description %]</td> >- [% IF ( account.amountcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% account.amount %]</td> >- [% IF ( account.amountoutstandingcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% account.amountoutstanding %]</td> >- </tr> >- >- [% END %] >-<tfoot> >- <tr> >- <td colspan="3">Total outstanding dues as on date: </td> >- [% IF ( totalcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% total %]</td> >- </tr> >- </tfoot> >-</table> >-</div> >-[% INCLUDE 'intranet-bottom.inc' %] >diff --git a/koha-tmpl/intranet-tmpl/prog/img/details_close.png b/koha-tmpl/intranet-tmpl/prog/img/details_close.png >new file mode 100644 >index 0000000000000000000000000000000000000000..fcc23c63e22f9883bef72c9e3adae3d5ddfb35cc >GIT binary patch >literal 841 >zcmV-P1GfB$P)<h;3K|Lk000e1NJLTq000yK000yS1^@s6jfou%00004XF*Lt007q5 >z)K6G40000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!+et)0RCwB~ >zRZUD&K@grT6<e^<2BXxNUgYOsC0<Bt4}us23L()G;V2>DA_on|3pY;aiIaw_AzX~% >z0wEzG!5U~A62!y<6#_3!Y0@BA($@0c+jVBUFF+~kfo;CbzTKH`cV=g%b|^n=hzi67 >zM5UV3FcF6cUCnu^p}pjrsWm6Ug}98UR-~ZFvWN`g0Fg%+2vP1<MCL$TMcf(~7<d*A >zhi8+?q{cZn2{flQ+9MsM>rl3*$mmwr5rOIH=?}WDABr;u?U4@YDw`9eOu1C&^?L7Z >zY;1fZBc9KT-2A-Q9Uc}tJv}1T-7R)sycF4)8NstzNldzAgSOWc2V?31C|17Z<>j$J >zAke}0_aQSe0l9^R;<1c^#DEC_0!<vD5Y!9~LPc#YEG;d~hC-p&sI^UTwO-OQG&J;} >zzrX)Em?qnMGX}ZE&w!UeCJtN*B%>d$>Do3Jo15TlYl9m;-_3M7y&8+fG<qbPBCP4{ >z?R~-+v*p8K$cDcFH%$rC<VDG8ZmM+-xs??>bP>p=udnZ^^3rY*Ry8&@-XZS}=H{ef >zDUJ>}0_oCdYHA|eDvG0BC2ghK?XIQGd^|3d(Ko2a8<ZPAT3e+oY;8&Da=F}A0hA`T >zOnuWd;BUh;4Eaz@*NbU_ZXd4{Sx%WuX3yjCT&eJS;dde-pZ0t3u1YLb2*-r10&kuC >zM%$mNicFiT%iQ|<`l`Hsd%KE}aRfufjdK;xqP%p!T@uFQ@ipQgE{pKj<mBW>%4c^+ >z2RQuxqA|Bf6p=-Yhg8<rgXi%hN+UisHT6l=w|*kAqtWQwmX?->1x*8ObQBJv5%iB0 >zU9{XrXRDi=!8bAj&V~kvL?Uy+VDJ@gXo|Fa=^duiBKhvUSnKK%G5>85_4~!w&Q6gS >z9~Xt4ozl{)vr6y0nuGJKj&rJgrBbPcMMU#|wJ-Lc4fdkiFZ`>)vh)56_#?mow%h=n >ThIkt{00000NkvXXu0mjfW_^Rc > >literal 0 >HcmV?d00001 > >diff --git a/koha-tmpl/intranet-tmpl/prog/img/details_open.png b/koha-tmpl/intranet-tmpl/prog/img/details_open.png >new file mode 100644 >index 0000000000000000000000000000000000000000..6f034d0f2d5c7902dce190355b12defdc07d6c9a >GIT binary patch >literal 881 >zcmV-%1CIQOP)<h;3K|Lk000e1NJLTq000yK000yS1^@s6jfou%00004XF*Lt007q5 >z)K6G40000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU#14%?dRCwB~ >zRozRIQ5b*Tx%`URmR7!^qREsHr4L~=rAQr;^QNxE%fy>P5xVIgh(4gM3Zjdy!n~2N >zjD^FnHQ1(tR(9cJl^-l~RyvtO-;dMt9M4;+6T9$?ALpFs<F|93kMl~9dYBMthy#dp >zv8JIRHV}$f>)Rcr6nirw3t>UzAPx#r5M&8N9I=W>B2)xRbt)puL>xs_c64-H@%#Or >zXf!&j>$*muHOWXvHo`VD#lg6MPE~+#^!N8aRTO1|?J`J5He@S&wvbBVO8K%ZpNm8y >zAIT}HC7Cxi$gY3tW-XzMtU1`kx+go?tM3CWp(Z#n*^&?X9upjrBoaWeDh>vNcO4E# >z)3UM*kH0>GH%mi2IAp}6%}CKyd$<m+mR^J0^gIXz0v@N+c>~2W6jvjYwyv(OhW7UM >zP7O5aPWUzq$A-}#e>#Hw16_xi<P1dCB5>hIJroxfm&IbSiP6!~SxS;g5FTo6ZM`H( >zlIh)&4}38nXc|&$DyX^!-nt?1)(-JKW(QQ%jr|ydxA>>z)7I8@S=`cW5N4N`m!G77 >zdZMpERgp|rK~d3JRsUp;<Xne@3X*%idAPiyqJn(0DUN1QwCPr>HJ6lA@hNmr@UjvF >zT!Ag6;H&rZ+37vY=g+HO_-wIQtVRQvx7QEFj83+*vi=TLQ+cY^m5t3Z!D|~jv(ZlR >zc>I^mX3LW^WSCo>=P5lkaGKBKE#utS*o(YFK~4deqwi1AMVd+U<ytr#o*<<w-^Js$ >z884M5z!-{%A)S!cjdCNGPft&OAPzDy2v>S~dit;|^yb25sIpdZA`Wys(O1dAvo2(I >ziyc~u+*C?>Z*T8&(cem%afeVS6nDGb_L8EKvNL%#5MBx6)#tX<qR#jZs%_P9tL7%i >z*)oibj0|FLKS7R|cq~%4-ePi*J(zsR8eY2C@n?2cia7tGp51$YpG6bV?X8z@wBCL_ >z4q3asI6I!Ng@uKAgNW99JzxL(z-9>j`d$yLwBMhA-vSH(T>k(8(cOU?00000NkvXX >Hu0mjf8E%<j > >literal 0 >HcmV?d00001 > >diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/includes/browser-strings.inc b/koha-tmpl/opac-tmpl/bootstrap/en/includes/browser-strings.inc >new file mode 100644 >index 0000000..f6c74f6 >--- /dev/null >+++ b/koha-tmpl/opac-tmpl/bootstrap/en/includes/browser-strings.inc >@@ -0,0 +1,34 @@ >+[% USE KohaAuthorisedValues %] >+<script type="text/javascript"> >+//<![CDATA[ >+ var BROWSER_RETURN_TO_SEARCH = _("Return to results"); >+ var BROWSER_PREVIOUS = _("Previous"); >+ var BROWSER_NEXT = _("Next"); >+ >+ var STRINGS = { >+ "DebitTypes": { >+ "FINE" : _("Fine"), >+ "ACCOUNT_MANAGEMENT_FEE" : _("Account management fee"), >+ "SUNDRY" : _("Sundry"), >+ "LOST" : _("Lost item"), >+ "HOLD" : _("Hold fee"), >+ "RENTAL" : _("Rental fee"), >+ "NEW_CARD" : _("New card"), >+ [% FOREACH a IN KohaAuthorisedValues.Get('MANUAL_INV') %] >+ "[% a.authorised_value %]" : "[% a.lib %]", >+ [% END %] >+ }, >+ >+ "CreditTypes": { >+ "CREDIT" : _("Credit"), >+ "PAYMENT" : _("Payment"), >+ "WRITEOFF" : _("Writeoff"), >+ "FOUND" : _("Lost item found"), >+ "FORGIVEN" : _("Forgiven"), >+ [% FOREACH a IN KohaAuthorisedValues.Get('MANUAL_CREDIT') %] >+ "[% a.authorised_value %]" : "[% a.lib %]", >+ [% END %] >+ } >+ } >+//]]> >+</script> >diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-account.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-account.tt >index aa70431..b5614c2 100644 >--- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-account.tt >+++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-account.tt >@@ -1,9 +1,12 @@ > [% USE Koha %] > [% USE KohaDates %] >+[% USE Currency %] > > [% INCLUDE 'doc-head-open.inc' %][% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog › Your fines and charges > [% INCLUDE 'doc-head-close.inc' %] > [% BLOCK cssinclude %][% END %] >+ >+ > </head> > <body id="opac-account" class="scrollto"> > [% INCLUDE 'masthead.inc' %] >@@ -11,7 +14,7 @@ > <div class="main"> > <ul class="breadcrumb"> > <li><a href="/cgi-bin/koha/opac-main.pl">Home</a> <span class="divider">›</span></li> >- <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">›</span></li> >+ <li><a href="/cgi-bin/koha/opac-user.pl">[% borrower.firstname %] [% borrower.surname %]</a> <span class="divider">›</span></li> > <li><a href="#">Your fines and charges</a></li> > </ul> > >@@ -25,38 +28,57 @@ > <div class="span10"> > <div id="useraccount" class="maincontent"> > <h3>Fines and charges</h3> >+ [% IF credits || debits %] >+ >+ <p> >+ <h3>Account balance: [% borrower.account_balance | $Currency %]</h3> >+ </p> >+ >+ <div> >+ <div id="account-debits"> >+ <a id="account-debits-switcher" href="#" onclick="return false">View payments</a> >+ <table cellpadding="0" cellspacing="0" border="0" class="display" id="debits-table"> >+ <thead> >+ <tr> >+ <th colspan="99">Fees</th> >+ </tr> >+ <tr> >+ <th></th> >+ <th>ID</th> >+ <th>Description</th> >+ <th>Type</th> >+ <th>Amount</th> >+ <th>Outsanding</th> >+ <th>Created on</th> >+ <th>Updated on</th> >+ </tr> >+ </thead> >+ <tbody></tbody> >+ </table> >+ </div> > >- [% IF ( ACCOUNT_LINES ) %] >- <table class="table table-bordered table-striped"> >- <thead> >- <tr> >- <th>Date</th> >- <th>Description</th> >- <th>Fine amount</th> >- <th>Amount outstanding</th> >- </tr> >- </thead> >- >- <tfoot> >- <tr> >- <th class="sum" colspan="3">Total due</th> >- <td class="sum">[% total %]</td> >- </tr> >- </tfoot> >- >- <tbody> >- [% FOREACH ACCOUNT_LINE IN ACCOUNT_LINES %] >- [% IF ( ACCOUNT_LINE.odd ) %]<tr class="highlight">[% ELSE %]<tr>[% END %] >- <td>[% ACCOUNT_LINE.date | $KohaDates %]</td> >- <td>[% ACCOUNT_LINE.description %] >- [% IF ( ACCOUNT_LINE.title ) %][% ACCOUNT_LINE.title |html %][% END %]</td> >- [% IF ( ACCOUNT_LINE.amountcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% ACCOUNT_LINE.amount %]</td> >- [% IF ( ACCOUNT_LINE.amountoutstandingcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% ACCOUNT_LINE.amountoutstanding %]</td> >- </tr> >- [% END %] >- </tbody> >- >- </table> >+ <div id="account-credits"> >+ <a id="account-credits-switcher" href="#" onclick="return false">View fees</a> >+ <table cellpadding="0" cellspacing="0" border="0" class="display" id="credits-table"> >+ <thead> >+ <tr> >+ <th colspan="99">Payments</th> >+ </tr> >+ <tr> >+ <th></th> >+ <th>ID</th> >+ <th>Notes</th> >+ <th>Type</th> >+ <th>Amount</th> >+ <th>Remaining</th> >+ <th>Created on</th> >+ <th>Updated on</th> >+ </tr> >+ </thead> >+ <tbody></tbody> >+ </table> >+ </div> >+ </div> > [% ELSE %] > <h4>You have no fines or charges</h4> > [% END %] >@@ -67,4 +89,299 @@ > </div> <!-- / .main --> > > [% INCLUDE 'opac-bottom.inc' %] >-[% BLOCK jsinclude %][% END %] >\ No newline at end of file >+[% INCLUDE 'datatables.inc' %] >+ >+<script type="text/javascript"> >+//<![CDATA[ >+$(document).ready(function() { >+ $('#account-credits').hide(); >+ $('#account-debits-switcher').click(function() { >+ $('#account-debits').slideUp(); >+ $('#account-credits').slideDown(); >+ }); >+ $('#account-credits-switcher').click(function() { >+ $('#account-credits').slideUp(); >+ $('#account-debits').slideDown(); >+ }); >+ >+ var anOpen = []; >+ var sImageUrl = "[% interface %]/[% theme %]/images/"; >+ >+ var debitsTable = $('#debits-table').dataTable( { >+ "bProcessing": true, >+ "aoColumns": [ >+ { >+ "mDataProp": null, >+ "sClass": "control center", >+ "sDefaultContent": '<img src="'+sImageUrl+'details_open.png'+'">' >+ }, >+ { "mDataProp": "debit_id" }, >+ { "mDataProp": "description" }, >+ { "mDataProp": "type" }, >+ { "mDataProp": "amount_original" }, >+ { "mDataProp": "amount_outstanding" }, >+ { "mDataProp": "created_on" }, >+ { "mDataProp": "updated_on" } >+ ], >+ "aaData": [ >+ [% FOREACH d IN debits %] >+ { >+ [% PROCESS format_data data=d highlight='debit' %] >+ >+ // Data for related item if there is one linked >+ "title": "[% d.item.biblio.title || d.deleted_item.biblio.title || d.deleted_item.deleted_biblio.title %]", >+ "biblionumber": "[% d.item.biblio.biblionumber || d.deleted_item.biblio.biblionumber %]", >+ "barcode": "[% d.item.barcode || d.deleted_item.barcode %]", >+ "itemnumber": "[% d.item.itemnumber %]", //This way itemnumber will be undef if deleted >+ >+ >+ // Data for related issue if there is one linked >+ [% IF d.issue %] >+ [% SET table = 'issue' %] >+ [% ELSIF d.old_issue %] >+ [% SET table = 'old_issue' %] >+ [% END %] >+ >+ [% IF table %] >+ "issue": { >+ [% PROCESS format_data data=d.$table %] >+ }, >+ [% END %] >+ >+ >+ "account_offsets": [ >+ [% FOREACH ao IN d.account_offsets %] >+ { >+ [% PROCESS format_data data=ao highlight='offset'%] >+ >+ "credit": { >+ [% PROCESS format_data data=ao.credit highlight='credit' %] >+ } >+ }, >+ [% END %] >+ ] >+ >+ }, >+ [% END %] >+ ] >+ } ); >+ >+ $('#debits-table td.control').live( 'click', function () { >+ var nTr = this.parentNode; >+ var i = $.inArray( nTr, anOpen ); >+ >+ if ( i === -1 ) { >+ $('img', this).attr( 'src', sImageUrl+"details_close.png" ); >+ var nDetailsRow = debitsTable.fnOpen( nTr, fnFormatDebitDetails(debitsTable, nTr), 'details' ); >+ $('div.innerDetails', nDetailsRow).slideDown(); >+ anOpen.push( nTr ); >+ } >+ else { >+ $('img', this).attr( 'src', sImageUrl+"details_open.png" ); >+ $('div.innerDetails', $(nTr).next()[0]).slideUp( function () { >+ debitsTable.fnClose( nTr ); >+ anOpen.splice( i, 1 ); >+ } ); >+ } >+ } ); >+ >+ var creditsTable = $('#credits-table').dataTable( { >+ "bProcessing": true, >+ "aoColumns": [ >+ { >+ "mDataProp": null, >+ "sClass": "control center", >+ "sDefaultContent": '<img src="'+sImageUrl+'details_open.png'+'">' >+ }, >+ { "mDataProp": "credit_id" }, >+ { "mDataProp": "notes" }, >+ { "mDataProp": "type" }, >+ { "mDataProp": "amount_paid" }, >+ { "mDataProp": "amount_remaining" }, >+ { "mDataProp": "created_on" }, >+ { "mDataProp": "updated_on" } >+ ], >+ "aaData": [ >+ [% FOREACH c IN credits %] >+ { >+ [% PROCESS format_data data=c highlight='credit' %] >+ >+ "account_offsets": [ >+ [% FOREACH ao IN c.account_offsets %] >+ { >+ [% PROCESS format_data data=ao highlight='offset' %] >+ >+ "debit": { >+ [% PROCESS format_data data=ao.debit highlight='debit' %] >+ } >+ }, >+ [% END %] >+ ] >+ >+ }, >+ [% END %] >+ ] >+ } ); >+ >+ $('#credits-table td.control').live( 'click', function () { >+ var nTr = this.parentNode; >+ var i = $.inArray( nTr, anOpen ); >+ >+ if ( i === -1 ) { >+ $('img', this).attr( 'src', sImageUrl+"details_close.png" ); >+ var nDetailsRow = creditsTable.fnOpen( nTr, fnFormatCreditDetails(creditsTable, nTr), 'details' ); >+ $('div.innerDetails', nDetailsRow).slideDown(); >+ anOpen.push( nTr ); >+ } >+ else { >+ $('img', this).attr( 'src', sImageUrl+"details_open.png" ); >+ $('div.innerDetails', $(nTr).next()[0]).slideUp( function () { >+ creditsTable.fnClose( nTr ); >+ anOpen.splice( i, 1 ); >+ } ); >+ } >+ } ); >+ >+} ); >+ >+function fnFormatDebitDetails( debitsTable, nTr ) { >+ var oData = debitsTable.fnGetData( nTr ); >+ >+ var sOut = '<div class="innerDetails" style="display:none;">'; >+ >+ var account_offsets = oData.account_offsets; >+ >+ sOut += '<ul>'; >+ if ( oData.title ) { >+ sOut += '<li>' + _('Title: '); >+ if ( oData.biblionumber ) { >+ sOut += '<a href="/cgi-bin/koha/opac-detail.pl?biblionumber=' + oData.biblionumber + '">'; >+ } >+ >+ sOut += oData.title; >+ >+ if ( oData.biblionumber ) { >+ sOut += '</a>'; >+ } >+ >+ sOut += '</li>'; >+ } >+ >+ if ( oData.barcode ) { >+ sOut += '<li>' + _('Barcode: ') + oData.barcode + '</li>'; >+ } >+ >+ if ( oData.notes ) { >+ sOut += '<li>' + _('Notes: ') + oData.notes + '</li>'; >+ } >+ >+ sOut += '</ul>'; >+ >+ if ( account_offsets.length ) { >+ sOut += >+ '<div class="innerDetails">' + >+ '<table cellpadding="5" cellspacing="0" border="0" style="margin:10px;">' + >+ '<thead>' + >+ '<tr><th colspan="99">' + _('Payments applied') + '</th></tr>' + >+ '<tr>' + >+ '<th>' + _('ID') + '</th>' + >+ '<th>' + _('Created on') + '</th>' + >+ '<th>' + _('Payment amount') + '</th>' + >+ '<th>' + _('Applied amount') + '</th>' + >+ '<th>' + _('Type') + '</th>' + >+ '<th>' + _('Notes') + '</th>' + >+ '</tr>' + >+ '</thead>' + >+ '<tbody>'; >+ >+ for ( var i = 0; i < account_offsets.length; i++ ) { >+ ao = account_offsets[i]; >+ sOut += >+ '<tr>' + >+ '<td>' + ao.credit_id + '</td>' + >+ '<td>' + ao.created_on + '</td>' + >+ '<td>' + ao.credit.amount_paid + '</td>' + >+ '<td>' + ao.amount + '</td>' + >+ '<td>' + ao.credit.type + '</td>' + >+ '<td>' + ao.credit.notes + '</td>' + >+ '</tr>'; >+ } >+ >+ sOut += >+ '</tbody>'+ >+ '</table>'; >+ } >+ >+ sOut += >+ '</div>'; >+ >+ return sOut; >+} >+ >+function fnFormatCreditDetails( creditsTable, nTr ) { >+ var oData = creditsTable.fnGetData( nTr ); >+ >+ var sOut = '<div class="innerDetails" style="display:none;">'; >+ >+ var account_offsets = oData.account_offsets; >+ >+ if ( account_offsets.length ) { >+ sOut += >+ '<table cellpadding="5" cellspacing="0" border="0" style="margin:10px;">' + >+ '<thead>' + >+ '<tr><th colspan="99">' + _('Fees paid') + '</th></tr>' + >+ '<tr>' + >+ '<th>' + _('ID') + '</th>' + >+ '<th>' + _('Description') + '</th>' + >+ '<th>' + _('Type') + '</th>' + >+ '<th>' + _('Amount') + '</th>' + >+ '<th>' + _('Remaining') + '</th>' + >+ '<th>' + _('Created on') + '</th>' + >+ '<th>' + _('Updated on') + '</th>' + >+ '<th>' + _('Notes') + '</th>' + >+ '</tr>' + >+ '</thead>' + >+ '<tbody>'; >+ >+ for ( var i = 0; i < account_offsets.length; i++ ) { >+ ao = account_offsets[i]; >+ sOut += >+ '<tr>' + >+ '<td>' + ao.debit.debit_id + '</td>' + >+ '<td>' + ao.debit.description + '</td>' + >+ '<td>' + ao.debit.type + '</td>' + >+ '<td>' + ao.debit.amount_original + '</td>' + >+ '<td>' + ao.debit.amount_outstanding + '</td>' + >+ '<td>' + ao.debit.created_on + '</td>' + >+ '<td>' + ao.debit.updated_on + '</td>' + >+ '<td>' + ao.debit.notes + '</td>' + >+ '</tr>'; >+ } >+ >+ sOut += >+ '</tbody>'+ >+ '</table>'; >+ } >+ >+ sOut += >+ '</div>'; >+ >+ return sOut; >+} >+ >+//]]> >+</script> >+ >+[% BLOCK jsinclude %][% END %] >+ >+[% BLOCK format_data %] >+ [% FOREACH key IN data.result_source.columns %] >+ [% IF key.match('^amount') %] >+ "[% key %]": "[% data.$key FILTER $Currency %]", >+ [% ELSIF key.match('_on$') %] >+ "[% key %]": "[% data.$key | $KohaDates %]", >+ [% ELSE %] >+ "[% key %]": "[% data.$key %]", >+ [% END %] >+ [% END %] >+[% END %] >diff --git a/koha-tmpl/opac-tmpl/bootstrap/images/details_close.png b/koha-tmpl/opac-tmpl/bootstrap/images/details_close.png >new file mode 100644 >index 0000000000000000000000000000000000000000..fcc23c63e22f9883bef72c9e3adae3d5ddfb35cc >GIT binary patch >literal 841 >zcmV-P1GfB$P)<h;3K|Lk000e1NJLTq000yK000yS1^@s6jfou%00004XF*Lt007q5 >z)K6G40000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!+et)0RCwB~ >zRZUD&K@grT6<e^<2BXxNUgYOsC0<Bt4}us23L()G;V2>DA_on|3pY;aiIaw_AzX~% >z0wEzG!5U~A62!y<6#_3!Y0@BA($@0c+jVBUFF+~kfo;CbzTKH`cV=g%b|^n=hzi67 >zM5UV3FcF6cUCnu^p}pjrsWm6Ug}98UR-~ZFvWN`g0Fg%+2vP1<MCL$TMcf(~7<d*A >zhi8+?q{cZn2{flQ+9MsM>rl3*$mmwr5rOIH=?}WDABr;u?U4@YDw`9eOu1C&^?L7Z >zY;1fZBc9KT-2A-Q9Uc}tJv}1T-7R)sycF4)8NstzNldzAgSOWc2V?31C|17Z<>j$J >zAke}0_aQSe0l9^R;<1c^#DEC_0!<vD5Y!9~LPc#YEG;d~hC-p&sI^UTwO-OQG&J;} >zzrX)Em?qnMGX}ZE&w!UeCJtN*B%>d$>Do3Jo15TlYl9m;-_3M7y&8+fG<qbPBCP4{ >z?R~-+v*p8K$cDcFH%$rC<VDG8ZmM+-xs??>bP>p=udnZ^^3rY*Ry8&@-XZS}=H{ef >zDUJ>}0_oCdYHA|eDvG0BC2ghK?XIQGd^|3d(Ko2a8<ZPAT3e+oY;8&Da=F}A0hA`T >zOnuWd;BUh;4Eaz@*NbU_ZXd4{Sx%WuX3yjCT&eJS;dde-pZ0t3u1YLb2*-r10&kuC >zM%$mNicFiT%iQ|<`l`Hsd%KE}aRfufjdK;xqP%p!T@uFQ@ipQgE{pKj<mBW>%4c^+ >z2RQuxqA|Bf6p=-Yhg8<rgXi%hN+UisHT6l=w|*kAqtWQwmX?->1x*8ObQBJv5%iB0 >zU9{XrXRDi=!8bAj&V~kvL?Uy+VDJ@gXo|Fa=^duiBKhvUSnKK%G5>85_4~!w&Q6gS >z9~Xt4ozl{)vr6y0nuGJKj&rJgrBbPcMMU#|wJ-Lc4fdkiFZ`>)vh)56_#?mow%h=n >ThIkt{00000NkvXXu0mjfW_^Rc > >literal 0 >HcmV?d00001 > >diff --git a/koha-tmpl/opac-tmpl/bootstrap/images/details_open.png b/koha-tmpl/opac-tmpl/bootstrap/images/details_open.png >new file mode 100644 >index 0000000000000000000000000000000000000000..6f034d0f2d5c7902dce190355b12defdc07d6c9a >GIT binary patch >literal 881 >zcmV-%1CIQOP)<h;3K|Lk000e1NJLTq000yK000yS1^@s6jfou%00004XF*Lt007q5 >z)K6G40000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU#14%?dRCwB~ >zRozRIQ5b*Tx%`URmR7!^qREsHr4L~=rAQr;^QNxE%fy>P5xVIgh(4gM3Zjdy!n~2N >zjD^FnHQ1(tR(9cJl^-l~RyvtO-;dMt9M4;+6T9$?ALpFs<F|93kMl~9dYBMthy#dp >zv8JIRHV}$f>)Rcr6nirw3t>UzAPx#r5M&8N9I=W>B2)xRbt)puL>xs_c64-H@%#Or >zXf!&j>$*muHOWXvHo`VD#lg6MPE~+#^!N8aRTO1|?J`J5He@S&wvbBVO8K%ZpNm8y >zAIT}HC7Cxi$gY3tW-XzMtU1`kx+go?tM3CWp(Z#n*^&?X9upjrBoaWeDh>vNcO4E# >z)3UM*kH0>GH%mi2IAp}6%}CKyd$<m+mR^J0^gIXz0v@N+c>~2W6jvjYwyv(OhW7UM >zP7O5aPWUzq$A-}#e>#Hw16_xi<P1dCB5>hIJroxfm&IbSiP6!~SxS;g5FTo6ZM`H( >zlIh)&4}38nXc|&$DyX^!-nt?1)(-JKW(QQ%jr|ydxA>>z)7I8@S=`cW5N4N`m!G77 >zdZMpERgp|rK~d3JRsUp;<Xne@3X*%idAPiyqJn(0DUN1QwCPr>HJ6lA@hNmr@UjvF >zT!Ag6;H&rZ+37vY=g+HO_-wIQtVRQvx7QEFj83+*vi=TLQ+cY^m5t3Z!D|~jv(ZlR >zc>I^mX3LW^WSCo>=P5lkaGKBKE#utS*o(YFK~4deqwi1AMVd+U<ytr#o*<<w-^Js$ >z884M5z!-{%A)S!cjdCNGPft&OAPzDy2v>S~dit;|^yb25sIpdZA`Wys(O1dAvo2(I >ziyc~u+*C?>Z*T8&(cem%afeVS6nDGb_L8EKvNL%#5MBx6)#tX<qR#jZs%_P9tL7%i >z*)oibj0|FLKS7R|cq~%4-ePi*J(zsR8eY2C@n?2cia7tGp51$YpG6bV?X8z@wBCL_ >z4q3asI6I!Ng@uKAgNW99JzxL(z-9>j`d$yLwBMhA-vSH(T>k(8(cOU?00000NkvXX >Hu0mjf8E%<j > >literal 0 >HcmV?d00001 > >diff --git a/koha-tmpl/opac-tmpl/prog/en/includes/browser-strings.inc b/koha-tmpl/opac-tmpl/prog/en/includes/browser-strings.inc >new file mode 100644 >index 0000000..f6c74f6 >--- /dev/null >+++ b/koha-tmpl/opac-tmpl/prog/en/includes/browser-strings.inc >@@ -0,0 +1,34 @@ >+[% USE KohaAuthorisedValues %] >+<script type="text/javascript"> >+//<![CDATA[ >+ var BROWSER_RETURN_TO_SEARCH = _("Return to results"); >+ var BROWSER_PREVIOUS = _("Previous"); >+ var BROWSER_NEXT = _("Next"); >+ >+ var STRINGS = { >+ "DebitTypes": { >+ "FINE" : _("Fine"), >+ "ACCOUNT_MANAGEMENT_FEE" : _("Account management fee"), >+ "SUNDRY" : _("Sundry"), >+ "LOST" : _("Lost item"), >+ "HOLD" : _("Hold fee"), >+ "RENTAL" : _("Rental fee"), >+ "NEW_CARD" : _("New card"), >+ [% FOREACH a IN KohaAuthorisedValues.Get('MANUAL_INV') %] >+ "[% a.authorised_value %]" : "[% a.lib %]", >+ [% END %] >+ }, >+ >+ "CreditTypes": { >+ "CREDIT" : _("Credit"), >+ "PAYMENT" : _("Payment"), >+ "WRITEOFF" : _("Writeoff"), >+ "FOUND" : _("Lost item found"), >+ "FORGIVEN" : _("Forgiven"), >+ [% FOREACH a IN KohaAuthorisedValues.Get('MANUAL_CREDIT') %] >+ "[% a.authorised_value %]" : "[% a.lib %]", >+ [% END %] >+ } >+ } >+//]]> >+</script> >diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-account.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-account.tt >index bb858e8..27e1606 100644 >--- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-account.tt >+++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-account.tt >@@ -1,64 +1,393 @@ >+[% SET accountview = 1 %] >+ > [% USE Koha %] > [% USE KohaDates %] >+[% USE Currency %] > > [% INCLUDE 'doc-head-open.inc' %][% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog › Your fines and charges > [% INCLUDE 'doc-head-close.inc' %] > </head> > <body id="opac-account"> > <div id="doc3" class="yui-t1"> >- <div id="bd"> >-[% INCLUDE 'masthead.inc' %] >- >+ <div id="bd"> >+ [% INCLUDE 'masthead.inc' %] > <div id="yui-main"> >- <div class="yui-b"><div class="yui-g"> >- <div id="useraccount" class="container"> >-<!--CONTENT--> >- [% FOREACH BORROWER_INF IN BORROWER_INFO %] >- <h3><a href="/cgi-bin/koha/opac-user.pl">[% BORROWER_INF.firstname %] [% BORROWER_INF.surname %]'s account</a> ⇢ Fines and charges</h3> >- [% END %] >+ <div class="yui-b"> >+ <div class="yui-g"> >+ <div id="useraccount" class="container"> >+ <h3><a href="/cgi-bin/koha/opac-user.pl">[% borrower.firstname %] [% borrower.surname %]'s account</a> ⇢ Fines and charges</h3> > >- [% IF ( ACCOUNT_LINES ) %] >- <table> >- <thead> >- <tr> >- <th>Date</th> >- <th>Description</th> >- <th>Fine amount</th> >- <th>Amount outstanding</th> >- </tr> >- </thead> >- >- <tfoot> >- <tr> >- <th class="sum" colspan="3">Total due</th> >- <td class="sum">[% total %]</td> >- </tr> >- </tfoot> >- >- <tbody> >- [% FOREACH ACCOUNT_LINE IN ACCOUNT_LINES %] >- [% IF ( ACCOUNT_LINE.odd ) %]<tr class="highlight">[% ELSE %]<tr>[% END %] >- <td>[% ACCOUNT_LINE.date | $KohaDates %]</td> >- <td>[% ACCOUNT_LINE.description %] >- [% IF ( ACCOUNT_LINE.title ) %][% ACCOUNT_LINE.title |html %][% END %]</td> >- [% IF ( ACCOUNT_LINE.amountcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% ACCOUNT_LINE.amount %]</td> >- [% IF ( ACCOUNT_LINE.amountoutstandingcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% ACCOUNT_LINE.amountoutstanding %]</td> >- </tr> >- [% END %] >- </tbody> >- >- </table> >- [% ELSE %] >- <h4>You have no fines or charges</h4> >- [% END %] >-</div> >-</div> >-</div> >-</div> >-<div class="yui-b"> >-<div id="leftmenus" class="container"> >-[% INCLUDE 'navigation.inc' IsPatronPage=1 %] >-</div> >-</div> >+ [% IF credits || debits %] >+ >+ <p> >+ <h3>Account balance: [% borrower.account_balance | $Currency %]</h3> >+ </p> >+ >+ <div> >+ <div id="account-debits"> >+ <a id="account-debits-switcher" href="#" onclick="return false">View payments</a> >+ <table cellpadding="0" cellspacing="0" border="0" class="display" id="debits-table"> >+ <thead> >+ <tr> >+ <th colspan="99">Fees</th> >+ </tr> >+ <tr> >+ <th></th> >+ <th>ID</th> >+ <th>Description</th> >+ <th>Type</th> >+ <th>Amount</th> >+ <th>Outsanding</th> >+ <th>Created on</th> >+ <th>Updated on</th> >+ </tr> >+ </thead> >+ <tbody></tbody> >+ </table> >+ </div> >+ >+ <div id="account-credits"> >+ <a id="account-credits-switcher" href="#" onclick="return false">View fees</a> >+ <table cellpadding="0" cellspacing="0" border="0" class="display" id="credits-table"> >+ <thead> >+ <tr> >+ <th colspan="99">Payments</th> >+ </tr> >+ <tr> >+ <th></th> >+ <th>ID</th> >+ <th>Notes</th> >+ <th>Type</th> >+ <th>Amount</th> >+ <th>Remaining</th> >+ <th>Created on</th> >+ <th>Updated on</th> >+ </tr> >+ </thead> >+ <tbody></tbody> >+ </table> >+ </div> >+ </div> >+ [% ELSE %] >+ <h4>You have no fines or charges</h4> >+ [% END %] >+ </div> >+ </div> >+ </div> >+ </div> >+ >+ <div class="yui-b"> >+ <div id="leftmenus" class="container"> >+ [% INCLUDE 'navigation.inc' IsPatronPage=1 %] >+ </div> >+ </div> > </div> > [% INCLUDE 'opac-bottom.inc' %] >+ >+[% INCLUDE 'datatables.inc' %] >+[% INCLUDE 'browser-strings.inc' %] >+ >+<script type="text/javascript"> >+//<![CDATA[ >+$(document).ready(function() { >+ $('#account-credits').hide(); >+ $('#account-debits-switcher').click(function() { >+ $('#account-debits').slideUp(); >+ $('#account-credits').slideDown(); >+ }); >+ $('#account-credits-switcher').click(function() { >+ $('#account-credits').slideUp(); >+ $('#account-debits').slideDown(); >+ }); >+ >+ var anOpen = []; >+ var sImageUrl = "[% interface %]/[% theme %]/images/"; >+ >+ var debitsTable = $('#debits-table').dataTable( { >+ "bProcessing": true, >+ "aoColumns": [ >+ { >+ "mDataProp": null, >+ "sClass": "control center", >+ "sDefaultContent": '<img src="'+sImageUrl+'details_open.png'+'">' >+ }, >+ { "mDataProp": "debit_id" }, >+ { "mDataProp": "description" }, >+ { >+ "mDataProp": "type", >+ "fnRender": function ( o, val ) { >+ return STRINGS['DebitTypes'][val]; >+ }, >+ }, >+ { "mDataProp": "amount_original" }, >+ { "mDataProp": "amount_outstanding" }, >+ { "mDataProp": "created_on" }, >+ { "mDataProp": "updated_on" } >+ ], >+ "aaData": [ >+ [% FOREACH d IN debits %] >+ { >+ [% PROCESS format_data data=d highlight='debit' %] >+ >+ // Data for related item if there is one linked >+ "title": "[% d.item.biblio.title || d.deleted_item.biblio.title || d.deleted_item.deleted_biblio.title %]", >+ "biblionumber": "[% d.item.biblio.biblionumber || d.deleted_item.biblio.biblionumber %]", >+ "barcode": "[% d.item.barcode || d.deleted_item.barcode %]", >+ "itemnumber": "[% d.item.itemnumber %]", //This way itemnumber will be undef if deleted >+ >+ >+ // Data for related issue if there is one linked >+ [% IF d.issue %] >+ [% SET table = 'issue' %] >+ [% ELSIF d.old_issue %] >+ [% SET table = 'old_issue' %] >+ [% END %] >+ >+ [% IF table %] >+ "issue": { >+ [% PROCESS format_data data=d.$table %] >+ }, >+ [% END %] >+ >+ >+ "account_offsets": [ >+ [% FOREACH ao IN d.account_offsets %] >+ { >+ [% PROCESS format_data data=ao highlight='offset'%] >+ >+ "credit": { >+ [% PROCESS format_data data=ao.credit highlight='credit' %] >+ } >+ }, >+ [% END %] >+ ] >+ >+ }, >+ [% END %] >+ ] >+ } ); >+ >+ $('#debits-table td.control').live( 'click', function () { >+ var nTr = this.parentNode; >+ var i = $.inArray( nTr, anOpen ); >+ >+ if ( i === -1 ) { >+ $('img', this).attr( 'src', sImageUrl+"details_close.png" ); >+ var nDetailsRow = debitsTable.fnOpen( nTr, fnFormatDebitDetails(debitsTable, nTr), 'details' ); >+ $('div.innerDetails', nDetailsRow).slideDown(); >+ anOpen.push( nTr ); >+ } >+ else { >+ $('img', this).attr( 'src', sImageUrl+"details_open.png" ); >+ $('div.innerDetails', $(nTr).next()[0]).slideUp( function () { >+ debitsTable.fnClose( nTr ); >+ anOpen.splice( i, 1 ); >+ } ); >+ } >+ } ); >+ >+ var creditsTable = $('#credits-table').dataTable( { >+ "bProcessing": true, >+ "aoColumns": [ >+ { >+ "mDataProp": null, >+ "sClass": "control center", >+ "sDefaultContent": '<img src="'+sImageUrl+'details_open.png'+'">' >+ }, >+ { "mDataProp": "credit_id" }, >+ { "mDataProp": "notes" }, >+ { >+ "mDataProp": "type", >+ "fnRender": function ( o, val ) { >+ return STRINGS['CreditTypes'][val]; >+ }, >+ }, >+ { "mDataProp": "amount_paid" }, >+ { "mDataProp": "amount_remaining" }, >+ { "mDataProp": "created_on" }, >+ { "mDataProp": "updated_on" } >+ ], >+ "aaData": [ >+ [% FOREACH c IN credits %] >+ { >+ [% PROCESS format_data data=c highlight='credit' %] >+ >+ "account_offsets": [ >+ [% FOREACH ao IN c.account_offsets %] >+ { >+ [% PROCESS format_data data=ao highlight='offset' %] >+ >+ "debit": { >+ [% PROCESS format_data data=ao.debit highlight='debit' %] >+ } >+ }, >+ [% END %] >+ ] >+ >+ }, >+ [% END %] >+ ] >+ } ); >+ >+ $('#credits-table td.control').live( 'click', function () { >+ var nTr = this.parentNode; >+ var i = $.inArray( nTr, anOpen ); >+ >+ if ( i === -1 ) { >+ $('img', this).attr( 'src', sImageUrl+"details_close.png" ); >+ var nDetailsRow = creditsTable.fnOpen( nTr, fnFormatCreditDetails(creditsTable, nTr), 'details' ); >+ $('div.innerDetails', nDetailsRow).slideDown(); >+ anOpen.push( nTr ); >+ } >+ else { >+ $('img', this).attr( 'src', sImageUrl+"details_open.png" ); >+ $('div.innerDetails', $(nTr).next()[0]).slideUp( function () { >+ creditsTable.fnClose( nTr ); >+ anOpen.splice( i, 1 ); >+ } ); >+ } >+ } ); >+ >+} ); >+ >+function fnFormatDebitDetails( debitsTable, nTr ) { >+ var oData = debitsTable.fnGetData( nTr ); >+ >+ var sOut = '<div class="innerDetails" style="display:none;">'; >+ >+ var account_offsets = oData.account_offsets; >+ >+ sOut += '<ul>'; >+ if ( oData.title ) { >+ sOut += '<li>' + _('Title: '); >+ if ( oData.biblionumber ) { >+ sOut += '<a href="/cgi-bin/koha/opac-detail.pl?biblionumber=' + oData.biblionumber + '">'; >+ } >+ >+ sOut += oData.title; >+ >+ if ( oData.biblionumber ) { >+ sOut += '</a>'; >+ } >+ >+ sOut += '</li>'; >+ } >+ >+ if ( oData.barcode ) { >+ sOut += '<li>' + _('Barcode: ') + oData.barcode + '</li>'; >+ } >+ >+ if ( oData.notes ) { >+ sOut += '<li>' + _('Notes: ') + oData.notes + '</li>'; >+ } >+ >+ sOut += '</ul>'; >+ >+ if ( account_offsets.length ) { >+ sOut += >+ '<div class="innerDetails">' + >+ '<table cellpadding="5" cellspacing="0" border="0" style="margin:10px;">' + >+ '<thead>' + >+ '<tr><th colspan="99">' + _('Payments applied') + '</th></tr>' + >+ '<tr>' + >+ '<th>' + _('ID') + '</th>' + >+ '<th>' + _('Created on') + '</th>' + >+ '<th>' + _('Payment amount') + '</th>' + >+ '<th>' + _('Applied amount') + '</th>' + >+ '<th>' + _('Type') + '</th>' + >+ '<th>' + _('Notes') + '</th>' + >+ '</tr>' + >+ '</thead>' + >+ '<tbody>'; >+ >+ for ( var i = 0; i < account_offsets.length; i++ ) { >+ ao = account_offsets[i]; >+ sOut += >+ '<tr>' + >+ '<td>' + ao.credit_id + '</td>' + >+ '<td>' + ao.created_on + '</td>' + >+ '<td>' + ao.credit.amount_paid + '</td>' + >+ '<td>' + ao.amount + '</td>' + >+ '<td>' + ao.credit.type + '</td>' + >+ '<td>' + ao.credit.notes + '</td>' + >+ '</tr>'; >+ } >+ >+ sOut += >+ '</tbody>'+ >+ '</table>'; >+ } >+ >+ sOut += >+ '</div>'; >+ >+ return sOut; >+} >+ >+function fnFormatCreditDetails( creditsTable, nTr ) { >+ var oData = creditsTable.fnGetData( nTr ); >+ >+ var sOut = '<div class="innerDetails" style="display:none;">'; >+ >+ var account_offsets = oData.account_offsets; >+ >+ if ( account_offsets.length ) { >+ sOut += >+ '<table cellpadding="5" cellspacing="0" border="0" style="margin:10px;">' + >+ '<thead>' + >+ '<tr><th colspan="99">' + _('Fees paid') + '</th></tr>' + >+ '<tr>' + >+ '<th>' + _('ID') + '</th>' + >+ '<th>' + _('Description') + '</th>' + >+ '<th>' + _('Type') + '</th>' + >+ '<th>' + _('Amount') + '</th>' + >+ '<th>' + _('Remaining') + '</th>' + >+ '<th>' + _('Created on') + '</th>' + >+ '<th>' + _('Updated on') + '</th>' + >+ '<th>' + _('Notes') + '</th>' + >+ '</tr>' + >+ '</thead>' + >+ '<tbody>'; >+ >+ for ( var i = 0; i < account_offsets.length; i++ ) { >+ ao = account_offsets[i]; >+ sOut += >+ '<tr>' + >+ '<td>' + ao.debit.debit_id + '</td>' + >+ '<td>' + ao.debit.description + '</td>' + >+ '<td>' + ao.debit.type + '</td>' + >+ '<td>' + ao.debit.amount_original + '</td>' + >+ '<td>' + ao.debit.amount_outstanding + '</td>' + >+ '<td>' + ao.debit.created_on + '</td>' + >+ '<td>' + ao.debit.updated_on + '</td>' + >+ '<td>' + ao.debit.notes + '</td>' + >+ '</tr>'; >+ } >+ >+ sOut += >+ '</tbody>'+ >+ '</table>'; >+ } >+ >+ sOut += >+ '</div>'; >+ >+ return sOut; >+} >+ >+//]]> >+</script> >+ >+[% BLOCK jsinclude %][% END %] >+ >+[% BLOCK format_data %] >+ [% FOREACH key IN data.result_source.columns %] >+ [% IF key.match('^amount') %] >+ "[% key %]": "[% data.$key FILTER $Currency %]", >+ [% ELSIF key.match('_on$') %] >+ "[% key %]": "[% data.$key | $KohaDates %]", >+ [% ELSE %] >+ "[% key %]": "[% data.$key %]", >+ [% END %] >+ [% END %] >+[% END %] >diff --git a/koha-tmpl/opac-tmpl/prog/images/details_close.png b/koha-tmpl/opac-tmpl/prog/images/details_close.png >new file mode 100644 >index 0000000000000000000000000000000000000000..fcc23c63e22f9883bef72c9e3adae3d5ddfb35cc >GIT binary patch >literal 841 >zcmV-P1GfB$P)<h;3K|Lk000e1NJLTq000yK000yS1^@s6jfou%00004XF*Lt007q5 >z)K6G40000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!+et)0RCwB~ >zRZUD&K@grT6<e^<2BXxNUgYOsC0<Bt4}us23L()G;V2>DA_on|3pY;aiIaw_AzX~% >z0wEzG!5U~A62!y<6#_3!Y0@BA($@0c+jVBUFF+~kfo;CbzTKH`cV=g%b|^n=hzi67 >zM5UV3FcF6cUCnu^p}pjrsWm6Ug}98UR-~ZFvWN`g0Fg%+2vP1<MCL$TMcf(~7<d*A >zhi8+?q{cZn2{flQ+9MsM>rl3*$mmwr5rOIH=?}WDABr;u?U4@YDw`9eOu1C&^?L7Z >zY;1fZBc9KT-2A-Q9Uc}tJv}1T-7R)sycF4)8NstzNldzAgSOWc2V?31C|17Z<>j$J >zAke}0_aQSe0l9^R;<1c^#DEC_0!<vD5Y!9~LPc#YEG;d~hC-p&sI^UTwO-OQG&J;} >zzrX)Em?qnMGX}ZE&w!UeCJtN*B%>d$>Do3Jo15TlYl9m;-_3M7y&8+fG<qbPBCP4{ >z?R~-+v*p8K$cDcFH%$rC<VDG8ZmM+-xs??>bP>p=udnZ^^3rY*Ry8&@-XZS}=H{ef >zDUJ>}0_oCdYHA|eDvG0BC2ghK?XIQGd^|3d(Ko2a8<ZPAT3e+oY;8&Da=F}A0hA`T >zOnuWd;BUh;4Eaz@*NbU_ZXd4{Sx%WuX3yjCT&eJS;dde-pZ0t3u1YLb2*-r10&kuC >zM%$mNicFiT%iQ|<`l`Hsd%KE}aRfufjdK;xqP%p!T@uFQ@ipQgE{pKj<mBW>%4c^+ >z2RQuxqA|Bf6p=-Yhg8<rgXi%hN+UisHT6l=w|*kAqtWQwmX?->1x*8ObQBJv5%iB0 >zU9{XrXRDi=!8bAj&V~kvL?Uy+VDJ@gXo|Fa=^duiBKhvUSnKK%G5>85_4~!w&Q6gS >z9~Xt4ozl{)vr6y0nuGJKj&rJgrBbPcMMU#|wJ-Lc4fdkiFZ`>)vh)56_#?mow%h=n >ThIkt{00000NkvXXu0mjfW_^Rc > >literal 0 >HcmV?d00001 > >diff --git a/koha-tmpl/opac-tmpl/prog/images/details_open.png b/koha-tmpl/opac-tmpl/prog/images/details_open.png >new file mode 100644 >index 0000000000000000000000000000000000000000..6f034d0f2d5c7902dce190355b12defdc07d6c9a >GIT binary patch >literal 881 >zcmV-%1CIQOP)<h;3K|Lk000e1NJLTq000yK000yS1^@s6jfou%00004XF*Lt007q5 >z)K6G40000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU#14%?dRCwB~ >zRozRIQ5b*Tx%`URmR7!^qREsHr4L~=rAQr;^QNxE%fy>P5xVIgh(4gM3Zjdy!n~2N >zjD^FnHQ1(tR(9cJl^-l~RyvtO-;dMt9M4;+6T9$?ALpFs<F|93kMl~9dYBMthy#dp >zv8JIRHV}$f>)Rcr6nirw3t>UzAPx#r5M&8N9I=W>B2)xRbt)puL>xs_c64-H@%#Or >zXf!&j>$*muHOWXvHo`VD#lg6MPE~+#^!N8aRTO1|?J`J5He@S&wvbBVO8K%ZpNm8y >zAIT}HC7Cxi$gY3tW-XzMtU1`kx+go?tM3CWp(Z#n*^&?X9upjrBoaWeDh>vNcO4E# >z)3UM*kH0>GH%mi2IAp}6%}CKyd$<m+mR^J0^gIXz0v@N+c>~2W6jvjYwyv(OhW7UM >zP7O5aPWUzq$A-}#e>#Hw16_xi<P1dCB5>hIJroxfm&IbSiP6!~SxS;g5FTo6ZM`H( >zlIh)&4}38nXc|&$DyX^!-nt?1)(-JKW(QQ%jr|ydxA>>z)7I8@S=`cW5N4N`m!G77 >zdZMpERgp|rK~d3JRsUp;<Xne@3X*%idAPiyqJn(0DUN1QwCPr>HJ6lA@hNmr@UjvF >zT!Ag6;H&rZ+37vY=g+HO_-wIQtVRQvx7QEFj83+*vi=TLQ+cY^m5t3Z!D|~jv(ZlR >zc>I^mX3LW^WSCo>=P5lkaGKBKE#utS*o(YFK~4deqwi1AMVd+U<ytr#o*<<w-^Js$ >z884M5z!-{%A)S!cjdCNGPft&OAPzDy2v>S~dit;|^yb25sIpdZA`Wys(O1dAvo2(I >ziyc~u+*C?>Z*T8&(cem%afeVS6nDGb_L8EKvNL%#5MBx6)#tX<qR#jZs%_P9tL7%i >z*)oibj0|FLKS7R|cq~%4-ePi*J(zsR8eY2C@n?2cia7tGp51$YpG6bV?X8z@wBCL_ >z4q3asI6I!Ng@uKAgNW99JzxL(z-9>j`d$yLwBMhA-vSH(T>k(8(cOU?00000NkvXX >Hu0mjf8E%<j > >literal 0 >HcmV?d00001 > >diff --git a/members/account.pl b/members/account.pl >new file mode 100755 >index 0000000..ee2b09a >--- /dev/null >+++ b/members/account.pl >@@ -0,0 +1,112 @@ >+#!/usr/bin/perl >+ >+# Copyright 2000-2002 Katipo Communications >+# Copyright 2013 ByWater Solutions >+# >+# 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 Modern::Perl; >+ >+use CGI; >+ >+use C4::Auth; >+use C4::Output; >+use C4::Dates qw/format_date/; >+use C4::Members; >+use C4::Branch; >+use C4::Members::Attributes qw(GetBorrowerAttributes); >+use Koha::Database; >+ >+my $cgi = new CGI; >+ >+my ( $template, $loggedinuser, $cookie ) = get_template_and_user( >+ { >+ template_name => "members/account.tt", >+ query => $cgi, >+ type => "intranet", >+ authnotrequired => 0, >+ flagsrequired => { borrowers => 1, updatecharges => 1 }, >+ debug => 1, >+ } >+); >+ >+my $borrowernumber = $cgi->param('borrowernumber'); >+ >+my $borrower = GetMember( 'borrowernumber' => $borrowernumber ); >+ >+my @debits = Koha::Database->new()->schema->resultset('AccountDebit')->search( >+ { 'me.borrowernumber' => $borrowernumber }, >+ { prefetch => { account_offsets => 'credit' } } >+); >+ >+my @credits = Koha::Database->new()->schema->resultset('AccountCredit')->search( >+ { 'me.borrowernumber' => $borrowernumber }, >+ { prefetch => { account_offsets => 'debit' } } >+); >+ >+$template->param( >+ debits => \@debits, >+ credits => \@credits, >+ borrower => $borrower, >+); >+ >+# Standard /members/ borrower details data >+## FIXME: This code is in every /members/ script and should be unified >+ >+if ( $borrower->{'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; >+} >+ >+my ( $picture, $dberror ) = GetPatronImage( $borrower->{'borrowernumber'} ); >+$template->param( picture => 1 ) if $picture; >+ >+if ( C4::Context->preference('ExtendedPatronAttributes') ) { >+ my $attributes = GetBorrowerAttributes($borrowernumber); >+ $template->param( >+ ExtendedPatronAttributes => 1, >+ extendedattributes => $attributes >+ ); >+} >+ >+$template->param( >+ borrowernumber => $borrowernumber, >+ firstname => $borrower->{'firstname'}, >+ surname => $borrower->{'surname'}, >+ cardnumber => $borrower->{'cardnumber'}, >+ categorycode => $borrower->{'categorycode'}, >+ category_type => $borrower->{'category_type'}, >+ categoryname => $borrower->{'description'}, >+ address => $borrower->{'address'}, >+ address2 => $borrower->{'address2'}, >+ city => $borrower->{'city'}, >+ state => $borrower->{'state'}, >+ zipcode => $borrower->{'zipcode'}, >+ country => $borrower->{'country'}, >+ phone => $borrower->{'phone'}, >+ email => $borrower->{'email'}, >+ branchcode => $borrower->{'branchcode'}, >+ branchname => GetBranchName( $borrower->{'branchcode'} ), >+ is_child => ( $borrower->{'category_type'} eq 'C' ), >+ activeBorrowerRelationship => >+ ( C4::Context->preference('borrowerRelationship') ne '' ), >+ RoutingSerials => C4::Context->preference('RoutingSerials'), >+); >+ >+output_html_with_http_headers $cgi, $cookie, $template->output; >diff --git a/members/account_credit.pl b/members/account_credit.pl >new file mode 100755 >index 0000000..e3aceda >--- /dev/null >+++ b/members/account_credit.pl >@@ -0,0 +1,103 @@ >+#!/usr/bin/perl >+ >+#written 11/1/2000 by chris@katipo.oc.nz >+#script to display borrowers account details >+ >+# Copyright 2000-2002 Katipo Communications >+# Copyright 2010 BibLibre >+# >+# 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::Auth; >+use C4::Output; >+use CGI; >+ >+use C4::Koha; >+use C4::Members; >+use C4::Branch; >+use C4::Items; >+use C4::Members::Attributes qw(GetBorrowerAttributes); >+use Koha::Database; >+ >+my $cgi = new CGI; >+ >+my $borrowernumber = $cgi->param('borrowernumber'); >+ >+my $borrower = GetMember( 'borrowernumber' => $borrowernumber ); >+ >+my ( $template, $loggedinuser, $cookie ) = get_template_and_user( >+ { >+ template_name => "members/account_credit.tt", >+ query => $cgi, >+ type => "intranet", >+ authnotrequired => 0, >+ flagsrequired => { borrowers => 1, updatecharges => 1 }, >+ debug => 1, >+ } >+); >+ >+$template->param( credit_types_loop => GetAuthorisedValues('ACCOUNT_CREDIT') ); >+ >+# Standard /members/ borrower details data >+## FIXME: This code is in every /members/ script and should be unified >+ >+if ( $borrower->{'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; >+} >+ >+my ( $picture, $dberror ) = GetPatronImage( $borrower->{'borrowernumber'} ); >+$template->param( picture => 1 ) if $picture; >+ >+if ( C4::Context->preference('ExtendedPatronAttributes') ) { >+ my $attributes = GetBorrowerAttributes($borrowernumber); >+ $template->param( >+ ExtendedPatronAttributes => 1, >+ extendedattributes => $attributes >+ ); >+} >+ >+$template->param( >+ borrowernumber => $borrowernumber, >+ firstname => $borrower->{'firstname'}, >+ surname => $borrower->{'surname'}, >+ cardnumber => $borrower->{'cardnumber'}, >+ categorycode => $borrower->{'categorycode'}, >+ category_type => $borrower->{'category_type'}, >+ categoryname => $borrower->{'description'}, >+ address => $borrower->{'address'}, >+ address2 => $borrower->{'address2'}, >+ city => $borrower->{'city'}, >+ state => $borrower->{'state'}, >+ zipcode => $borrower->{'zipcode'}, >+ country => $borrower->{'country'}, >+ phone => $borrower->{'phone'}, >+ email => $borrower->{'email'}, >+ branchcode => $borrower->{'branchcode'}, >+ branchname => GetBranchName( $borrower->{'branchcode'} ), >+ is_child => ( $borrower->{'category_type'} eq 'C' ), >+ activeBorrowerRelationship => >+ ( C4::Context->preference('borrowerRelationship') ne '' ), >+ RoutingSerials => C4::Context->preference('RoutingSerials'), >+); >+ >+output_html_with_http_headers $cgi, $cookie, $template->output; >diff --git a/members/account_credit_do.pl b/members/account_credit_do.pl >new file mode 100755 >index 0000000..c1979e8 >--- /dev/null >+++ b/members/account_credit_do.pl >@@ -0,0 +1,68 @@ >+#!/usr/bin/perl >+ >+# Copyright 2000-2002 Katipo Communications >+# Copyright 2010 BibLibre >+# Copyright 2013 ByWater Solutions >+# >+# 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 Modern::Perl; >+ >+use CGI; >+ >+use C4::Auth; >+use C4::Output; >+use C4::Members; >+use C4::Items; >+use C4::Branch; >+use C4::Members::Attributes qw(GetBorrowerAttributes); >+use Koha::Accounts; >+use Koha::Database; >+ >+my $cgi = new CGI; >+ >+my $borrowernumber = $cgi->param('borrowernumber'); >+my $borrower = >+ Koha::Database->new()->schema->resultset('Borrower')->find($borrowernumber); >+ >+if ( checkauth( $cgi, 0, { borrowers => 1 }, 'intranet' ) ) { >+ >+ my $barcode = $cgi->param('barcode'); >+ my $itemnumber = $cgi->param('itemnumber'); >+ my $description = $cgi->param('description'); >+ my $amount = $cgi->param('amount'); >+ my $type = $cgi->param('type'); >+ my $notes = $cgi->param('notes'); >+ >+ if ( !$itemnumber && $barcode ) { >+ $itemnumber = GetItemnumberFromBarcode($barcode); >+ } >+ >+ my $debit = AddCredit( >+ { >+ borrower => $borrower, >+ amount => $amount, >+ type => $type, >+ itemnumber => $itemnumber, >+ description => $description, >+ notes => $notes, >+ >+ } >+ ); >+ >+ print $cgi->redirect( >+ "/cgi-bin/koha/members/account.pl?borrowernumber=$borrowernumber"); >+} >diff --git a/members/account_debit.pl b/members/account_debit.pl >new file mode 100755 >index 0000000..41d78c6 >--- /dev/null >+++ b/members/account_debit.pl >@@ -0,0 +1,104 @@ >+#!/usr/bin/perl >+ >+#written 11/1/2000 by chris@katipo.oc.nz >+#script to display borrowers account details >+ >+# Copyright 2000-2002 Katipo Communications >+# Copyright 2010 BibLibre >+# >+# 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 CGI; >+ >+use C4::Auth; >+use C4::Output; >+use C4::Members; >+use C4::Items; >+use C4::Branch; >+use C4::Members::Attributes qw(GetBorrowerAttributes); >+use C4::Koha; >+use Koha::Accounts; >+use Koha::Database; >+ >+my $input = new CGI; >+ >+my $borrowernumber = $input->param('borrowernumber'); >+ >+my $borrower = GetMember( 'borrowernumber' => $borrowernumber ); >+ >+my ( $template, $loggedinuser, $cookie ) = get_template_and_user( >+ { >+ template_name => "members/account_debit.tt", >+ query => $input, >+ type => "intranet", >+ authnotrequired => 0, >+ flagsrequired => { borrowers => 1, updatecharges => 1 }, >+ debug => 1, >+ } >+); >+ >+$template->param( invoice_types_loop => GetAuthorisedValues('MANUAL_INV') ); >+ >+# Standard /members/ borrower details data >+## FIXME: This code is in every /members/ script and should be unified >+ >+if ( $borrower->{'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; >+} >+ >+my ( $picture, $dberror ) = GetPatronImage( $borrower->{'borrowernumber'} ); >+$template->param( picture => 1 ) if $picture; >+ >+if ( C4::Context->preference('ExtendedPatronAttributes') ) { >+ my $attributes = GetBorrowerAttributes($borrowernumber); >+ $template->param( >+ ExtendedPatronAttributes => 1, >+ extendedattributes => $attributes >+ ); >+} >+ >+$template->param( >+ borrowernumber => $borrowernumber, >+ firstname => $borrower->{'firstname'}, >+ surname => $borrower->{'surname'}, >+ cardnumber => $borrower->{'cardnumber'}, >+ categorycode => $borrower->{'categorycode'}, >+ category_type => $borrower->{'category_type'}, >+ categoryname => $borrower->{'description'}, >+ address => $borrower->{'address'}, >+ address2 => $borrower->{'address2'}, >+ city => $borrower->{'city'}, >+ state => $borrower->{'state'}, >+ zipcode => $borrower->{'zipcode'}, >+ country => $borrower->{'country'}, >+ phone => $borrower->{'phone'}, >+ email => $borrower->{'email'}, >+ branchcode => $borrower->{'branchcode'}, >+ branchname => GetBranchName( $borrower->{'branchcode'} ), >+ is_child => ( $borrower->{'category_type'} eq 'C' ), >+ activeBorrowerRelationship => >+ ( C4::Context->preference('borrowerRelationship') ne '' ), >+ RoutingSerials => C4::Context->preference('RoutingSerials'), >+); >+ >+output_html_with_http_headers $input, $cookie, $template->output; >diff --git a/members/account_debit_do.pl b/members/account_debit_do.pl >new file mode 100755 >index 0000000..c9878fa >--- /dev/null >+++ b/members/account_debit_do.pl >@@ -0,0 +1,69 @@ >+#!/usr/bin/perl >+ >+# Copyright 2000-2002 Katipo Communications >+# Copyright 2010 BibLibre >+# Copyright 2013 ByWater Solutions >+# >+# 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 Modern::Perl; >+ >+use CGI; >+ >+use C4::Auth; >+use C4::Output; >+use C4::Members; >+use C4::Items; >+use C4::Branch; >+use C4::Members::Attributes qw(GetBorrowerAttributes); >+use Koha::Accounts; >+use Koha::Database; >+ >+my $cgi = new CGI; >+ >+my $borrowernumber = $cgi->param('borrowernumber'); >+my $borrower = >+ Koha::Database->new()->schema->resultset('Borrower')->find($borrowernumber); >+ >+if ( checkauth( $cgi, 0, { borrowers => 1 }, 'intranet' ) ) { >+ >+ # print $cgi->header; >+ my $barcode = $cgi->param('barcode'); >+ my $itemnumber = $cgi->param('itemnumber'); >+ my $description = $cgi->param('description'); >+ my $amount = $cgi->param('amount'); >+ my $type = $cgi->param('type'); >+ my $notes = $cgi->param('notes'); >+ >+ if ( !$itemnumber && $barcode ) { >+ $itemnumber = GetItemnumberFromBarcode($barcode); >+ } >+ >+ my $debit = AddDebit( >+ { >+ borrower => $borrower, >+ amount => $amount, >+ type => $type, >+ itemnumber => $itemnumber, >+ description => $description, >+ notes => $notes, >+ >+ } >+ ); >+ >+ print $cgi->redirect( >+ "/cgi-bin/koha/members/account.pl?borrowernumber=$borrowernumber"); >+} >diff --git a/members/account_payment.pl b/members/account_payment.pl >new file mode 100755 >index 0000000..403481a >--- /dev/null >+++ b/members/account_payment.pl >@@ -0,0 +1,122 @@ >+#!/usr/bin/perl >+ >+# Copyright 2000-2002 Katipo Communications >+# Copyright 2010 BibLibre >+# Copyright 2010,2011 PTFS-Europe Ltd >+# Copyright 2013 ByWater Solutions >+# >+# 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. >+ >+=head1 account_payment.pl >+ >+ written 11/1/2000 by chris@katipo.oc.nz >+ part of the koha library system, script to facilitate paying off fines >+ >+=cut >+ >+use Modern::Perl; >+ >+use CGI; >+ >+use URI::Escape; >+ >+use C4::Context; >+use C4::Auth; >+use C4::Output; >+use C4::Members; >+use C4::Stats; >+use C4::Koha; >+use C4::Overdues; >+use C4::Branch; >+use C4::Members::Attributes qw(GetBorrowerAttributes); >+use Koha::Database; >+ >+our $cgi = CGI->new; >+ >+our ( $template, $loggedinuser, $cookie ) = get_template_and_user( >+ { >+ template_name => 'members/account_payment.tt', >+ query => $cgi, >+ type => 'intranet', >+ authnotrequired => 0, >+ flagsrequired => { borrowers => 1, updatecharges => 1 }, >+ debug => 1, >+ } >+); >+ >+my $borrowernumber = $cgi->param('borrowernumber'); >+ >+my $borrower = GetMember( borrowernumber => $borrowernumber ); >+ >+my @debits = Koha::Database->new()->schema->resultset('AccountDebit')->search( >+ { >+ 'me.borrowernumber' => $borrowernumber, >+ amount_outstanding => { '>' => 0 } >+ } >+); >+ >+$template->param( >+ debits => \@debits, >+ borrower => $borrower, >+); >+ >+# Standard /members/ borrower details data >+## FIXME: This code is in every /members/ script and should be unified >+ >+if ( $borrower->{'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; >+} >+ >+my ( $picture, $dberror ) = GetPatronImage( $borrower->{'borrowernumber'} ); >+$template->param( picture => 1 ) if $picture; >+ >+if ( C4::Context->preference('ExtendedPatronAttributes') ) { >+ my $attributes = GetBorrowerAttributes($borrowernumber); >+ $template->param( >+ ExtendedPatronAttributes => 1, >+ extendedattributes => $attributes >+ ); >+} >+ >+$template->param( >+ borrowernumber => $borrowernumber, >+ firstname => $borrower->{'firstname'}, >+ surname => $borrower->{'surname'}, >+ cardnumber => $borrower->{'cardnumber'}, >+ categorycode => $borrower->{'categorycode'}, >+ category_type => $borrower->{'category_type'}, >+ categoryname => $borrower->{'description'}, >+ address => $borrower->{'address'}, >+ address2 => $borrower->{'address2'}, >+ city => $borrower->{'city'}, >+ state => $borrower->{'state'}, >+ zipcode => $borrower->{'zipcode'}, >+ country => $borrower->{'country'}, >+ phone => $borrower->{'phone'}, >+ email => $borrower->{'email'}, >+ branchcode => $borrower->{'branchcode'}, >+ branchname => GetBranchName( $borrower->{'branchcode'} ), >+ is_child => ( $borrower->{'category_type'} eq 'C' ), >+ activeBorrowerRelationship => >+ ( C4::Context->preference('borrowerRelationship') ne '' ), >+ RoutingSerials => C4::Context->preference('RoutingSerials'), >+); >+ >+output_html_with_http_headers $cgi, $cookie, $template->output; >diff --git a/members/account_payment_do.pl b/members/account_payment_do.pl >new file mode 100755 >index 0000000..a5ebe6f >--- /dev/null >+++ b/members/account_payment_do.pl >@@ -0,0 +1,66 @@ >+#!/usr/bin/perl >+ >+# Copyright 2000-2002 Katipo Communications >+# Copyright 2010 BibLibre >+# Copyright 2013 ByWater Solutions >+# >+# 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 Modern::Perl; >+ >+use CGI; >+ >+use C4::Auth; >+use C4::Members; >+use C4::Items; >+use C4::Branch; >+use C4::Members::Attributes qw(GetBorrowerAttributes); >+use Koha::Accounts; >+use Koha::Database; >+ >+my $cgi = new CGI; >+ >+if ( checkauth( $cgi, 0, { borrowers => 1 }, 'intranet' ) ) { >+ my $borrowernumber = $cgi->param('borrowernumber'); >+ >+ my $borrower = >+ Koha::Database->new()->schema->resultset('Borrower') >+ ->find($borrowernumber); >+ >+ my $amount_to_pay = $cgi->param('amount_to_pay'); >+ my $amount_received = $cgi->param('amount_received'); >+ my $type = $cgi->param('type'); >+ my $notes = $cgi->param('notes'); >+ my @debit_id = $cgi->param('debit_id'); >+ >+ $amount_received ||= $amount_to_pay >+ if $type eq Koha::Accounts::CreditTypes::Payment(); >+ >+ my $debit = AddCredit( >+ { >+ borrower => $borrower, >+ amount_received => $amount_received, >+ amount => $amount_to_pay, >+ type => $type, >+ notes => $notes, >+ debit_id => \@debit_id, >+ >+ } >+ ); >+ >+ print $cgi->redirect( >+ "/cgi-bin/koha/members/account.pl?borrowernumber=$borrowernumber"); >+} >diff --git a/members/account_print.pl b/members/account_print.pl >new file mode 100755 >index 0000000..0f02ca9 >--- /dev/null >+++ b/members/account_print.pl >@@ -0,0 +1,58 @@ >+#!/usr/bin/perl >+ >+# 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 Modern::Perl; >+ >+use CGI; >+ >+use C4::Auth; >+use C4::Output; >+use Koha::Database; >+ >+my $cgi = new CGI; >+ >+my ( $template, $loggedinuser, $cookie ) = get_template_and_user( >+ { >+ template_name => "members/account_print.tt", >+ query => $cgi, >+ type => "intranet", >+ authnotrequired => 0, >+ flagsrequired => { borrowers => 1, updatecharges => 1 }, >+ debug => 1, >+ } >+); >+ >+my $type = $cgi->param('type'); >+my $id = $cgi->param('id'); >+ >+warn "No type passed in!" unless $type; >+warn "No id passed in!" unless $id; >+ >+if ( $type eq 'debit' ) { >+ my $debit = >+ Koha::Database->new()->schema->resultset('AccountDebit')->find($id); >+ $template->param( debit => $debit ); >+} >+elsif ( $type eq 'credit' ) { >+ my $credit = >+ Koha::Database->new()->schema->resultset('AccountCredit')->find($id); >+ $template->param( credit => $credit ); >+} >+ >+$template->param( type => $type ); >+ >+output_html_with_http_headers $cgi, $cookie, $template->output; >diff --git a/members/boraccount.pl b/members/boraccount.pl >deleted file mode 100755 >index 255b1ff..0000000 >--- a/members/boraccount.pl >+++ /dev/null >@@ -1,135 +0,0 @@ >-#!/usr/bin/perl >- >- >-#writen 11/1/2000 by chris@katipo.oc.nz >-#script to display borrowers account details >- >- >-# Copyright 2000-2002 Katipo Communications >-# >-# 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::Auth; >-use C4::Output; >-use C4::Dates qw/format_date/; >-use CGI; >-use C4::Members; >-use C4::Branch; >-use C4::Accounts; >-use C4::Members::Attributes qw(GetBorrowerAttributes); >- >-my $input=new CGI; >- >- >-my ($template, $loggedinuser, $cookie) >- = get_template_and_user({template_name => "members/boraccount.tmpl", >- query => $input, >- type => "intranet", >- authnotrequired => 0, >- flagsrequired => {borrowers => 1, updatecharges => 1}, >- debug => 1, >- }); >- >-my $borrowernumber=$input->param('borrowernumber'); >-my $action = $input->param('action') || ''; >- >-#get borrower details >-my $data=GetMember('borrowernumber' => $borrowernumber); >- >-if ( $action eq 'reverse' ) { >- ReversePayment( $input->param('accountlines_id') ); >-} >- >-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; >-} >- >-#get account details >-my ($total,$accts,undef)=GetMemberAccountRecords($borrowernumber); >-my $totalcredit; >-if($total <= 0){ >- $totalcredit = 1; >-} >- >-my $reverse_col = 0; # Flag whether we need to show the reverse column >-foreach my $accountline ( @{$accts}) { >- $accountline->{amount} += 0.00; >- if ($accountline->{amount} <= 0 ) { >- $accountline->{amountcredit} = 1; >- } >- $accountline->{amountoutstanding} += 0.00; >- if ( $accountline->{amountoutstanding} <= 0 ) { >- $accountline->{amountoutstandingcredit} = 1; >- } >- >- $accountline->{date} = format_date($accountline->{date}); >- $accountline->{amount} = sprintf '%.2f', $accountline->{amount}; >- $accountline->{amountoutstanding} = sprintf '%.2f', $accountline->{amountoutstanding}; >- if ($accountline->{accounttype} eq 'Pay') { >- $accountline->{payment} = 1; >- $reverse_col = 1; >- } >-} >- >-$template->param( adultborrower => 1 ) if ( $data->{'category_type'} eq 'A' ); >- >-my ($picture, $dberror) = GetPatronImage($data->{'borrowernumber'}); >-$template->param( picture => 1 ) if $picture; >- >-if (C4::Context->preference('ExtendedPatronAttributes')) { >- my $attributes = GetBorrowerAttributes($borrowernumber); >- $template->param( >- ExtendedPatronAttributes => 1, >- extendedattributes => $attributes >- ); >-} >- >-$template->param( >- finesview => 1, >- firstname => $data->{'firstname'}, >- surname => $data->{'surname'}, >- othernames => $data->{'othernames'}, >- 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'}), >- total => sprintf("%.2f",$total), >- totalcredit => $totalcredit, >- is_child => ($data->{'category_type'} eq 'C'), >- reverse_col => $reverse_col, >- accounts => $accts, >- activeBorrowerRelationship => (C4::Context->preference('borrowerRelationship') ne ''), >- RoutingSerials => C4::Context->preference('RoutingSerials'), >-); >- >-output_html_with_http_headers $input, $cookie, $template->output; >diff --git a/members/mancredit.pl b/members/mancredit.pl >deleted file mode 100755 >index a2c2258..0000000 >--- a/members/mancredit.pl >+++ /dev/null >@@ -1,114 +0,0 @@ >-#!/usr/bin/perl >- >-#written 11/1/2000 by chris@katipo.oc.nz >-#script to display borrowers account details >- >- >-# Copyright 2000-2002 Katipo Communications >-# Copyright 2010 BibLibre >-# >-# 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::Auth; >-use C4::Output; >-use CGI; >- >-use C4::Members; >-use C4::Branch; >-use C4::Accounts; >-use C4::Items; >-use C4::Members::Attributes qw(GetBorrowerAttributes); >- >-my $input=new CGI; >-my $flagsrequired = { borrowers => 1, updatecharges => 1 }; >- >-my $borrowernumber=$input->param('borrowernumber'); >- >-#get borrower details >-my $data=GetMember('borrowernumber' => $borrowernumber); >-my $add=$input->param('add'); >- >-if ($add){ >- if ( checkauth( $input, 0, $flagsrequired, 'intranet' ) ) { >- my $barcode = $input->param('barcode'); >- my $itemnum; >- if ($barcode) { >- $itemnum = GetItemnumberFromBarcode($barcode); >- } >- my $desc = $input->param('desc'); >- my $note = $input->param('note'); >- my $amount = $input->param('amount') || 0; >- $amount = -$amount; >- my $type = $input->param('type'); >- manualinvoice( $borrowernumber, $itemnum, $desc, $type, $amount, $note ); >- print $input->redirect("/cgi-bin/koha/members/boraccount.pl?borrowernumber=$borrowernumber"); >- } >-} else { >- my ($template, $loggedinuser, $cookie) >- = get_template_and_user({template_name => "members/mancredit.tmpl", >- query => $input, >- type => "intranet", >- authnotrequired => 0, >- flagsrequired => $flagsrequired, >- debug => 1, >- }); >- >- 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; >- } >- >- $template->param( adultborrower => 1 ) if ( $data->{category_type} eq 'A' ); >- my ($picture, $dberror) = GetPatronImage($data->{'borrowernumber'}); >- $template->param( picture => 1 ) if $picture; >- >-if (C4::Context->preference('ExtendedPatronAttributes')) { >- my $attributes = GetBorrowerAttributes($borrowernumber); >- $template->param( >- ExtendedPatronAttributes => 1, >- extendedattributes => $attributes >- ); >-} >- >- $template->param( >- borrowernumber => $borrowernumber, >- firstname => $data->{'firstname'}, >- surname => $data->{'surname'}, >- 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'), >- activeBorrowerRelationship => (C4::Context->preference('borrowerRelationship') ne ''), >- RoutingSerials => C4::Context->preference('RoutingSerials'), >- ); >- output_html_with_http_headers $input, $cookie, $template->output; >-} >diff --git a/members/maninvoice.pl b/members/maninvoice.pl >deleted file mode 100755 >index c4a9294..0000000 >--- a/members/maninvoice.pl >+++ /dev/null >@@ -1,141 +0,0 @@ >-#!/usr/bin/perl >- >-#written 11/1/2000 by chris@katipo.oc.nz >-#script to display borrowers account details >- >- >-# Copyright 2000-2002 Katipo Communications >-# Copyright 2010 BibLibre >-# >-# 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::Auth; >-use C4::Output; >-use CGI; >-use C4::Members; >-use C4::Accounts; >-use C4::Items; >-use C4::Branch; >-use C4::Members::Attributes qw(GetBorrowerAttributes); >- >-my $input=new CGI; >-my $flagsrequired = { borrowers => 1 }; >- >-my $borrowernumber=$input->param('borrowernumber'); >- >- >-# get borrower details >-my $data=GetMember('borrowernumber'=>$borrowernumber); >-my $add=$input->param('add'); >-if ($add){ >- if ( checkauth( $input, 0, $flagsrequired, 'intranet' ) ) { >- # print $input->header; >- my $barcode=$input->param('barcode'); >- my $itemnum; >- if ($barcode) { >- $itemnum = GetItemnumberFromBarcode($barcode); >- } >- my $desc=$input->param('desc'); >- my $amount=$input->param('amount'); >- my $type=$input->param('type'); >- my $note = $input->param('note'); >- my $error = manualinvoice( $borrowernumber, $itemnum, $desc, $type, $amount, $note ); >- if ($error) { >- my ( $template, $loggedinuser, $cookie ) = get_template_and_user( >- { template_name => "members/maninvoice.tmpl", >- query => $input, >- type => "intranet", >- authnotrequired => 0, >- flagsrequired => $flagsrequired, >- debug => 1, >- } >- ); >- if ( $error =~ /FOREIGN KEY/ && $error =~ /itemnumber/ ) { >- $template->param( 'ITEMNUMBER' => 1 ); >- } >- $template->param( 'ERROR' => $error ); >- output_html_with_http_headers $input, $cookie, $template->output; >- } else { >- print $input->redirect("/cgi-bin/koha/members/boraccount.pl?borrowernumber=$borrowernumber"); >- exit; >- } >- } >-} else { >- >- my ($template, $loggedinuser, $cookie) >- = get_template_and_user({template_name => "members/maninvoice.tmpl", >- query => $input, >- type => "intranet", >- authnotrequired => 0, >- flagsrequired => {borrowers => 1, updatecharges => 1}, >- debug => 1, >- }); >- >- # get authorised values with type of MANUAL_INV >- my @invoice_types; >- my $dbh = C4::Context->dbh; >- my $sth = $dbh->prepare('SELECT * FROM authorised_values WHERE category = "MANUAL_INV"'); >- $sth->execute(); >- while ( my $row = $sth->fetchrow_hashref() ) { >- push @invoice_types, $row; >- } >- $template->param( invoice_types_loop => \@invoice_types ); >- >- 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; >- } >- >- $template->param( adultborrower => 1 ) if ( $data->{'category_type'} eq 'A' ); >- my ($picture, $dberror) = GetPatronImage($data->{'borrowernumber'}); >- $template->param( picture => 1 ) if $picture; >- >-if (C4::Context->preference('ExtendedPatronAttributes')) { >- my $attributes = GetBorrowerAttributes($borrowernumber); >- $template->param( >- ExtendedPatronAttributes => 1, >- extendedattributes => $attributes >- ); >-} >- $template->param( >- borrowernumber => $borrowernumber, >- firstname => $data->{'firstname'}, >- surname => $data->{'surname'}, >- 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'), >- activeBorrowerRelationship => (C4::Context->preference('borrowerRelationship') ne ''), >- RoutingSerials => C4::Context->preference('RoutingSerials'), >- ); >- output_html_with_http_headers $input, $cookie, $template->output; >-} >diff --git a/members/moremember.pl b/members/moremember.pl >index 86c61c1..40e7601 100755 >--- a/members/moremember.pl >+++ b/members/moremember.pl >@@ -223,7 +223,6 @@ if ( C4::Context->preference("IndependentBranches") ) { > my $branchdetail = GetBranchDetail( $data->{'branchcode'}); > @{$data}{keys %$branchdetail} = values %$branchdetail; # merge in all branch columns > >-my ( $total, $accts, $numaccts) = GetMemberAccountRecords( $borrowernumber ); > my $lib1 = &GetSortDetails( "Bsort1", $data->{'sort1'} ); > my $lib2 = &GetSortDetails( "Bsort2", $data->{'sort2'} ); > $template->param( lib1 => $lib1 ) if ($lib1); >@@ -414,8 +413,8 @@ $template->param( > branch => $branch, > todaysdate => C4::Dates->today(), > totalprice => sprintf("%.2f", $totalprice), >- totaldue => sprintf("%.2f", $total), >- totaldue_raw => $total, >+ totaldue => sprintf("%.2f", $data->{account_balance}), >+ totaldue_raw => $data->{account_balance}, > issueloop => @issuedata, > relissueloop => @relissuedata, > overdues_exist => $overdues_exist, >diff --git a/members/pay.pl b/members/pay.pl >deleted file mode 100755 >index 8a8e902..0000000 >--- a/members/pay.pl >+++ /dev/null >@@ -1,261 +0,0 @@ >-#!/usr/bin/perl >- >-# Copyright 2000-2002 Katipo Communications >-# Copyright 2010 BibLibre >-# Copyright 2010,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. >- >-=head1 pay.pl >- >- written 11/1/2000 by chris@katipo.oc.nz >- part of the koha library system, script to facilitate paying off fines >- >-=cut >- >-use strict; >-use warnings; >- >-use URI::Escape; >-use C4::Context; >-use C4::Auth; >-use C4::Output; >-use CGI; >-use C4::Members; >-use C4::Accounts; >-use C4::Stats; >-use C4::Koha; >-use C4::Overdues; >-use C4::Branch; >-use C4::Members::Attributes qw(GetBorrowerAttributes); >- >-our $input = CGI->new; >- >-our ( $template, $loggedinuser, $cookie ) = get_template_and_user( >- { template_name => 'members/pay.tmpl', >- query => $input, >- type => 'intranet', >- authnotrequired => 0, >- flagsrequired => { borrowers => 1, updatecharges => 1 }, >- debug => 1, >- } >-); >- >-my @names = $input->param; >- >-our $borrowernumber = $input->param('borrowernumber'); >-if ( !$borrowernumber ) { >- $borrowernumber = $input->param('borrowernumber0'); >-} >- >-# get borrower details >-our $borrower = GetMember( borrowernumber => $borrowernumber ); >-our $user = $input->remote_user; >-$user ||= q{}; >- >-my $branches = GetBranches(); >-our $branch = GetBranch( $input, $branches ); >- >-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 $writeoff_all = $input->param('woall'); # writeoff all fines >-if ($writeoff_all) { >- writeoff_all(@names); >-} elsif ($writeoff_item) { >- my $accountlines_id = $input->param('accountlines_id'); >- my $itemno = $input->param('itemnumber'); >- my $account_type = $input->param('accounttype'); >- my $amount = $input->param('amountoutstanding'); >- my $payment_note = $input->param("payment_note"); >- WriteOffFee( $borrowernumber, $accountlines_id, $itemno, $account_type, $amount, $branch, $payment_note ); >-} >- >-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 ); >- } >-} >- >-$template->param( >- activeBorrowerRelationship => (C4::Context->preference('borrowerRelationship') ne ''), >- RoutingSerials => C4::Context->preference('RoutingSerials'), >-); >- >-add_accounts_to_template(); >- >-output_html_with_http_headers $input, $cookie, $template->output; >- >-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( >- accounts => $accounts, >- borrower => $borrower, >- total => $total, >- ); >- return; >- >-} >- >-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; >- } >- 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( '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 .= get_for_redirect( 'accountlines_id', "accountlines_id$line_no", 0 ); >- $redirect .= q{&} . 'payment_note' . q{=} . uri_escape( $input->param("payment_note_$line_no") ); >- $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("amountoutstanding$value"); >- my $accountno = $input->param("accountno$value"); >- my $accountlines_id = $input->param("accountlines_id$value"); >- my $payment_note = $input->param("payment_note_$value"); >- WriteOffFee( $borrowernumber, $accountlines_id, $itemno, $accounttype, $amount, $branch, $payment_note ); >- } >- } >- >- $borrowernumber = $input->param('borrowernumber'); >- print $input->redirect( >- "/cgi-bin/koha/members/boraccount.pl?borrowernumber=$borrowernumber"); >- return; >-} >- >-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->{borrowernumber} ); >- if ($picture) { >- $b_ref->{has_picture} = 1; >- } >- >- if (C4::Context->preference('ExtendedPatronAttributes')) { >- $b_ref->{extendedattributes} = GetBorrowerAttributes($borrowernumber); >- $template->param( >- ExtendedPatronAttributes => 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 $notes = '¬es=' . join("%0A", map { $input->param("payment_note_$_") } @lines_to_pay ); >- my $redirect = >- "/cgi-bin/koha/members/paycollect.pl?borrowernumber=$borrowernumber" >- . $amt >- . $sel >- . $notes; >- >- print $input->redirect($redirect); >- return; >-} >diff --git a/members/paycollect.pl b/members/paycollect.pl >deleted file mode 100755 >index 96ca0fb..0000000 >--- a/members/paycollect.pl >+++ /dev/null >@@ -1,179 +0,0 @@ >-#!/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 URI::Escape; >-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 $payment_note = uri_unescape $input->param('payment_note'); >-my $accountno; >-my $accountlines_id; >-if ( $individual || $writeoff ) { >- if ($individual) { >- $template->param( pay_individual => 1 ); >- } elsif ($writeoff) { >- $template->param( writeoff_individual => 1 ); >- } >- my $accounttype = $input->param('accounttype'); >- $accountlines_id = $input->param('accountlines_id'); >- my $amount = $input->param('amount'); >- my $amountoutstanding = $input->param('amountoutstanding'); >- $accountno = $input->param('accountno'); >- my $itemnumber = $input->param('itemnumber'); >- 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, >- accountlines_id => $accountlines_id, >- accountno => $accountno, >- amount => $amount, >- amountoutstanding => $amountoutstanding, >- title => $title, >- itemnumber => $itemnumber, >- description => $description, >- notify_id => $notify_id, >- notify_level => $notify_level, >- payment_note => $payment_note, >- ); >-} elsif ($select_lines) { >- $total_due = $input->param('amt'); >- $template->param( >- selected_accts => $select_lines, >- amt => $total_due, >- selected_accts_notes => $input->param('notes'), >- ); >-} >- >-if ( $total_paid and $total_paid ne '0.00' ) { >- if ( $total_paid < 0 or $total_paid > $total_due ) { >- $template->param( >- error_over => 1, >- total_due => $total_due >- ); >- } else { >- if ($individual) { >- if ( $total_paid == $total_due ) { >- makepayment( $accountlines_id, $borrowernumber, $accountno, $total_paid, $user, >- $branch, $payment_note ); >- } else { >- makepartialpayment( $accountlines_id, $borrowernumber, $accountno, $total_paid, >- $user, $branch, $payment_note ); >- } >- 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; >- my $note = $input->param('selected_accts_notes'); >- recordpayment_selectaccts( $borrowernumber, $total_paid, \@acc, $note ); >- } 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( >- borrowernumber => $borrowernumber, # some templates require global >- borrower => $borrower, >- total => $total_due, >- activeBorrowerRelationship => (C4::Context->preference('borrowerRelationship') ne ''), >- RoutingSerials => C4::Context->preference('RoutingSerials'), >-); >- >-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->{borrowernumber} ); >- if ($picture) { >- $b_ref->{has_picture} = 1; >- } >- >- $b_ref->{branchname} = GetBranchName( $b_ref->{branchcode} ); >- return; >-} >diff --git a/members/printfeercpt.pl b/members/printfeercpt.pl >deleted file mode 100755 >index 6a86bc3..0000000 >--- a/members/printfeercpt.pl >+++ /dev/null >@@ -1,143 +0,0 @@ >-#!/usr/bin/perl >- >- >-#writen 3rd May 2010 by kmkale@anantcorp.com adapted from boraccount.pl by chris@katipo.oc.nz >-#script to print fee receipts >- >- >-# Copyright Koustubha Kale >-# >-# 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::Auth; >-use C4::Output; >-use C4::Dates qw/format_date/; >-use CGI; >-use C4::Members; >-use C4::Branch; >-use C4::Accounts; >- >-my $input=new CGI; >- >- >-my ($template, $loggedinuser, $cookie) >- = get_template_and_user({template_name => "members/printfeercpt.tmpl", >- query => $input, >- type => "intranet", >- authnotrequired => 0, >- flagsrequired => {borrowers => 1, updatecharges => 1}, >- debug => 1, >- }); >- >-my $borrowernumber=$input->param('borrowernumber'); >-my $action = $input->param('action') || ''; >-my $accountlines_id = $input->param('accountlines_id'); >- >-#get borrower details >-my $data=GetMember('borrowernumber' => $borrowernumber); >- >-if ( $action eq 'print' ) { >-# ReversePayment( $borrowernumber, $input->param('accountno') ); >-} >- >-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; >-} >- >-#get account details >-my ($total,$accts,$numaccts)=GetMemberAccountRecords($borrowernumber); >-my $totalcredit; >-if($total <= 0){ >- $totalcredit = 1; >-} >-my @accountrows; # this is for the tmpl-loop >- >-my $toggle; >-for (my $i=0;$i<$numaccts;$i++){ >- next if ( $accts->[$i]{'accountlines_id'} ne $accountlines_id ); >- if($i%2){ >- $toggle = 0; >- } else { >- $toggle = 1; >- } >- $accts->[$i]{'toggle'} = $toggle; >- $accts->[$i]{'amount'}+=0.00; >- if($accts->[$i]{'amount'} <= 0){ >- $accts->[$i]{'amountcredit'} = 1; >- $accts->[$i]{'amount'}*=-1.00; >- } >- $accts->[$i]{'amountoutstanding'}+=0.00; >- if($accts->[$i]{'amountoutstanding'} <= 0){ >- $accts->[$i]{'amountoutstandingcredit'} = 1; >- } >- my %row = ( 'date' => format_date($accts->[$i]{'date'}), >- 'amountcredit' => $accts->[$i]{'amountcredit'}, >- 'amountoutstandingcredit' => $accts->[$i]{'amountoutstandingcredit'}, >- 'toggle' => $accts->[$i]{'toggle'}, >- 'description' => $accts->[$i]{'description'}, >- 'itemnumber' => $accts->[$i]{'itemnumber'}, >- 'biblionumber' => $accts->[$i]{'biblionumber'}, >- 'amount' => sprintf("%.2f",$accts->[$i]{'amount'}), >- 'amountoutstanding' => sprintf("%.2f",$accts->[$i]{'amountoutstanding'}), >- 'accountno' => $accts->[$i]{'accountno'}, >- 'payment' => ( $accts->[$i]{'accounttype'} eq 'Pay' ), >- >- ); >- >- if ($accts->[$i]{'accounttype'} ne 'F' && $accts->[$i]{'accounttype'} ne 'FU'){ >- $row{'printtitle'}=1; >- $row{'title'} = $accts->[$i]{'title'}; >- } >- >- push(@accountrows, \%row); >-} >- >-$template->param( adultborrower => 1 ) if ( $data->{'category_type'} eq 'A' ); >- >-my ($picture, $dberror) = GetPatronImage($data->{'borrowernumber'}); >-$template->param( picture => 1 ) if $picture; >- >-$template->param( >- finesview => 1, >- firstname => $data->{'firstname'}, >- surname => $data->{'surname'}, >- borrowernumber => $borrowernumber, >- cardnumber => $data->{'cardnumber'}, >- categorycode => $data->{'categorycode'}, >- category_type => $data->{'category_type'}, >- # category_description => $data->{'description'}, >- categoryname => $data->{'description'}, >- address => $data->{'address'}, >- address2 => $data->{'address2'}, >- city => $data->{'city'}, >- zipcode => $data->{'zipcode'}, >- country => $data->{'country'}, >- phone => $data->{'phone'}, >- email => $data->{'email'}, >- branchcode => $data->{'branchcode'}, >- branchname => GetBranchName($data->{'branchcode'}), >- total => sprintf("%.2f",$total), >- totalcredit => $totalcredit, >- is_child => ($data->{'category_type'} eq 'C'), >- accounts => \@accountrows ); >- >-output_html_with_http_headers $input, $cookie, $template->output; >diff --git a/members/printinvoice.pl b/members/printinvoice.pl >deleted file mode 100755 >index 10ae114..0000000 >--- a/members/printinvoice.pl >+++ /dev/null >@@ -1,142 +0,0 @@ >-#!/usr/bin/perl >- >-#writen 3rd May 2010 by kmkale@anantcorp.com adapted from boraccount.pl by chris@katipo.oc.nz >-#script to print fee receipts >- >-# Copyright Koustubha Kale >-# >-# 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::Auth; >-use C4::Output; >-use C4::Dates qw/format_date/; >-use CGI; >-use C4::Members; >-use C4::Branch; >-use C4::Accounts; >- >-my $input = new CGI; >- >-my ( $template, $loggedinuser, $cookie ) = get_template_and_user( >- { template_name => "members/printinvoice.tmpl", >- query => $input, >- type => "intranet", >- authnotrequired => 0, >- flagsrequired => { borrowers => 1, updatecharges => 1 }, >- debug => 1, >- } >-); >- >-my $borrowernumber = $input->param('borrowernumber'); >-my $action = $input->param('action') || ''; >-my $accountlines_id = $input->param('accountlines_id'); >- >-#get borrower details >-my $data = GetMember( 'borrowernumber' => $borrowernumber ); >- >-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; >-} >- >-#get account details >-my ( $total, $accts, $numaccts ) = GetMemberAccountRecords($borrowernumber); >-my $totalcredit; >-if ( $total <= 0 ) { >- $totalcredit = 1; >-} >- >-my @accountrows; # this is for the tmpl-loop >- >-my $toggle; >-for ( my $i = 0 ; $i < $numaccts ; $i++ ) { >- next if ( $accts->[$i]{'accountlines_id'} ne $accountlines_id ); >- >- if ( $i % 2 ) { >- $toggle = 0; >- } else { >- $toggle = 1; >- } >- >- $accts->[$i]{'toggle'} = $toggle; >- $accts->[$i]{'amount'} += 0.00; >- >- if ( $accts->[$i]{'amount'} <= 0 ) { >- $accts->[$i]{'amountcredit'} = 1; >- } >- >- $accts->[$i]{'amountoutstanding'} += 0.00; >- if ( $accts->[$i]{'amountoutstanding'} <= 0 ) { >- $accts->[$i]{'amountoutstandingcredit'} = 1; >- } >- >- my %row = ( >- 'date' => format_date( $accts->[$i]{'date'} ), >- 'amountcredit' => $accts->[$i]{'amountcredit'}, >- 'amountoutstandingcredit' => $accts->[$i]{'amountoutstandingcredit'}, >- 'toggle' => $accts->[$i]{'toggle'}, >- 'description' => $accts->[$i]{'description'}, >- 'itemnumber' => $accts->[$i]{'itemnumber'}, >- 'biblionumber' => $accts->[$i]{'biblionumber'}, >- 'amount' => sprintf( "%.2f", $accts->[$i]{'amount'} ), >- 'amountoutstanding' => sprintf( "%.2f", $accts->[$i]{'amountoutstanding'} ), >- 'accountno' => $accts->[$i]{'accountno'}, >- 'payment' => ( $accts->[$i]{'accounttype'} eq 'Pay' ), >- ); >- >- if ( $accts->[$i]{'accounttype'} ne 'F' && $accts->[$i]{'accounttype'} ne 'FU' ) { >- $row{'printtitle'} = 1; >- $row{'title'} = $accts->[$i]{'title'}; >- } >- >- push( @accountrows, \%row ); >-} >- >-$template->param( adultborrower => 1 ) if ( $data->{'category_type'} eq 'A' ); >- >-my ( $picture, $dberror ) = GetPatronImage( $data->{'borrowernumber'} ); >-$template->param( picture => 1 ) if $picture; >- >-$template->param( >- finesview => 1, >- 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'}, >- zipcode => $data->{'zipcode'}, >- country => $data->{'country'}, >- phone => $data->{'phone'}, >- email => $data->{'email'}, >- branchcode => $data->{'branchcode'}, >- branchname => GetBranchName( $data->{'branchcode'} ), >- total => sprintf( "%.2f", $total ), >- totalcredit => $totalcredit, >- is_child => ( $data->{'category_type'} eq 'C' ), >- accounts => \@accountrows >-); >- >-output_html_with_http_headers $input, $cookie, $template->output; >diff --git a/misc/cronjobs/create_koc_db.pl b/misc/cronjobs/create_koc_db.pl >index ccc4a5b..f49519e 100755 >--- a/misc/cronjobs/create_koc_db.pl >+++ b/misc/cronjobs/create_koc_db.pl >@@ -256,10 +256,8 @@ SELECT borrowernumber, > city, > phone, > dateofbirth, >- sum( accountlines.amountoutstanding ) as total_fines >+ account_balance as total_fines > FROM borrowers >-LEFT JOIN accountlines USING (borrowernumber) >-GROUP BY borrowernumber; > END_SQL > > my $fields_count = $sth_mysql->execute(); >@@ -278,43 +276,6 @@ END_SQL > } > $dbh_sqlite->commit(); > print "inserted $count borrowers\n" if $verbose; >- # add_fines_to_borrowers_table(); >-} >- >-=head2 add_fines_to_borrowers_table >- >-Import the fines from koha.accountlines into the sqlite db >- >-=cut >- >-sub add_fines_to_borrowers_table { >- >- print "preparing to update borrowers\n" if $verbose; >- my $sth_mysql = $dbh_mysql->prepare( >- "SELECT DISTINCT borrowernumber, SUM( amountoutstanding ) AS total_fines >- FROM accountlines >- GROUP BY borrowernumber" >- ); >- $sth_mysql->execute(); >- my $count; >- while ( my $result = $sth_mysql->fetchrow_hashref() ) { >- $count++; >- if ( $verbose ) { >- print '.' unless ( $count % 10 ); >- print "$count\n" unless ( $count % 1000 ); >- } >- >- my $borrowernumber = $result->{'borrowernumber'}; >- my $total_fines = $result->{'total_fines'}; >- >- # warn "Fines for Borrower # $borrowernumber are \$ $total_fines \n" if $verbose; >- my $sql = "UPDATE borrowers SET total_fines = ? WHERE borrowernumber = ?"; >- >- my $sth_sqlite = $dbh_sqlite->prepare($sql); >- $sth_sqlite->execute( $total_fines, $borrowernumber ); >- $sth_sqlite->finish(); >- } >- print "updated $count borrowers\n" if ( $verbose && $count ); > } > > =head2 create_issue_table >diff --git a/misc/cronjobs/fines.pl b/misc/cronjobs/fines.pl >index 02bde14..f85b898 100755 >--- a/misc/cronjobs/fines.pl >+++ b/misc/cronjobs/fines.pl >@@ -127,9 +127,13 @@ for my $overdue ( @{$overdues} ) { > if ( $mode eq 'production' && !$is_holiday{$branchcode} ) { > if ( $amount > 0 ) { > UpdateFine( >- $overdue->{itemnumber}, >- $overdue->{borrowernumber}, >- $amount, $type, output_pref($datedue) >+ { >+ itemnumber => $overdue->{itemnumber}, >+ borrowernumber => $overdue->{borrowernumber}, >+ amount => $amount, >+ due => output_pref($datedue), >+ issue_id => $overdue->{issue_id} >+ } > ); > } > } >diff --git a/misc/maintenance/fix_accountlines_date.pl b/misc/maintenance/fix_accountlines_date.pl >deleted file mode 100755 >index 2956f57..0000000 >--- a/misc/maintenance/fix_accountlines_date.pl >+++ /dev/null >@@ -1,171 +0,0 @@ >-#!/usr/bin/perl >-# >-# Copyright (C) 2008 LibLime >-# >-# 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; >-BEGIN { >- # find Koha's Perl modules >- # test carefully before changing this >- use FindBin; >- eval { require "$FindBin::Bin/../kohalib.pl" }; >-} >- >-use C4::Context; >-use C4::Dates; >-use Getopt::Long; >-use Pod::Usage; >- >-=head1 NAME >- >-fix_accountlines_date.pl - Fix date code in the description of fines >- >-=head1 SYNOPSIS >- >-fix_accountlines_date.pl -m date_format [ -n fines_to_process ] [ -d ] [ --help or -h ] >- >- Options: >- --help or -h Brief usage message >- --man Full documentation >- -n fines_to_process How many fines to process; if left off will >- process all >- -m date_format What format the dates are currently in; 'us' >- or 'metric' (REQUIRED) >- -d Run in debugging mode >- >-=head1 DESCRIPTION >- >-This script fixes the date code in the description of fines. Previously, the >-format of this was determined by which script you were using to update fines (see the -m option) >- >-=over 8 >- >-=item B<--help> >- >-Prints a brief usage message and exits. >- >-=item B<--man> >- >-Prints a full manual page and exits. >- >-=item B<-n> >- >-Process only a certain amount of fines. If this option is left off, this script >-will process everything. >- >-=item B<-m> >- >-This required option tells the script what format your dates are currently in. >-If you were previously using the fines2.pl or fines-sanop.pl script to update >-your fines, they will be in 'metric' format. If you were using the fines-ll.pl >-script, they will be in 'us' format. After this script is finished, they will >-be in whatever format your 'dateformat' system preference specifies. >- >-=item B<-d> >- >-Run in debugging mode; this prints out a lot of information and should be used >-only if there is a problem and with the '-n' option. >- >-=back >- >-=cut >- >-my $mode = ''; >-my $want_help = 0; >-my $limit = -1; >-my $done = 0; >-my $DEBUG = 0; >- >-# Regexes for the two date formats >-our $US_DATE = '((0\d|1[0-2])\/([0-2]\d|3[01])\/(\d{4}))'; >-our $METRIC_DATE = '(([0-2]\d|3[01])\/(0\d|1[0-2])\/(\d{4}))'; >- >-sub print_usage { >- print <<_USAGE_ >-$0: Fix the date code in the description of fines >- >-Due to the multiple scripts used to update fines in earlier versions of Koha, >-this script should be used to change the format of the date codes in the >-accountlines table before you start using Koha 3.0. >- >-Parameters: >- --mode or -m This should be 'us' or 'metric', and tells the script >- what format your old dates are in. >- --debug or -d Run this script in debug mode. >- --limit or -n How many accountlines rows to fix; useful for testing. >- --help or -h Print out this help message. >-_USAGE_ >-} >- >-my $result = GetOptions( >- 'm=s' => \$mode, >- 'd' => \$DEBUG, >- 'n=i' => \$limit, >- 'help|h' => \$want_help, >-); >- >-if (not $result or $want_help or ($mode ne 'us' and $mode ne 'metric')) { >- print_usage(); >- exit 0; >-} >- >-our $dbh = C4::Context->dbh; >-$dbh->{AutoCommit} = 0; >-my $sth = $dbh->prepare(" >-SELECT borrowernumber, itemnumber, accountno, description >- FROM accountlines >- WHERE accounttype in ('FU', 'F', 'O', 'M') >-;"); >-$sth->execute(); >- >-my $update_sth = $dbh->prepare(' >-UPDATE accountlines >- SET description = ? >- WHERE borrowernumber = ? AND itemnumber = ? AND accountno = ? >-;'); >- >- >-while (my $accountline = $sth->fetchrow_hashref) { >- my $description = $accountline->{'description'}; >- my $updated = 0; >- >- if ($mode eq 'us') { >- if ($description =~ /$US_DATE/) { # mm/dd/yyyy >- my $date = C4::Dates->new($1, 'us'); >- print "Converting $1 (us) to " . $date->output() . "\n" if $DEBUG; >- $description =~ s/$US_DATE/$date->output()/; >- $updated = 1; >- } >- } elsif ($mode eq 'metric') { >- if ($description =~ /$METRIC_DATE/) { # dd/mm/yyyy >- my $date = C4::Dates->new($1, 'metric'); >- print "Converting $1 (metric) to " . $date->output() . "\n" if $DEBUG; >- $description =~ s/$METRIC_DATE/$date->output()/; >- $updated = 2; >- } >- } >- >- print "Changing description from '" . $accountline->{'description'} . "' to '" . $description . "'\n" if $DEBUG; >- $update_sth->execute($description, $accountline->{'borrowernumber'}, $accountline->{'itemnumber'}, $accountline->{'accountno'}); >- >- $done++; >- >- last if ($done == $limit); # $done can't be -1, so this works >-} >- >-$dbh->commit(); >diff --git a/misc/release_notes/release_notes_3_10_0.txt b/misc/release_notes/release_notes_3_10_0.txt >index a1ebdef..5a44aaf 100644 >--- a/misc/release_notes/release_notes_3_10_0.txt >+++ b/misc/release_notes/release_notes_3_10_0.txt >@@ -1762,7 +1762,7 @@ Staff Client > 8996 normal In result page items with negative notforloan are available > 9017 normal Quote of the day: Table footer not translated > 5312 minor XHTML correction in authority summary >- 8009 minor Item descriptive data not populated on pay.pl >+ 8009 minor Item descriptive data not populated on account_payment.pl > 8593 minor Add unique IDs to pending approval markup on staff client home page > 8646 minor Certain search terms cause browser "script taking too long" error > 8793 minor Fix materialTypeCode/typeOf008 icons for NORMARC XSLT >diff --git a/misc/release_notes/release_notes_3_12_0.txt b/misc/release_notes/release_notes_3_12_0.txt >index 68d19e5..7a6db13 100644 >--- a/misc/release_notes/release_notes_3_12_0.txt >+++ b/misc/release_notes/release_notes_3_12_0.txt >@@ -579,7 +579,7 @@ Architecture, internals, and plumbing > 8429 minor Unnecessary use of Exporter in SIP/ILS objects > 9292 minor Remove dead code related to 'publictype' > 9401 minor Javascript used for tags handling wants access to CGISESSID cookie >- 9582 minor Unused code in members/pay.pl >+ 9582 minor Unused code in members/account_payment.pl > 10054 minor When SingleBranchMode is enabled, allow superlibrarians to set logged in library > 10143 minor Fix FSF address in license headers > 9609 trivial Rebuild zebra reports double numbers for exported records with -z option >diff --git a/opac/opac-account.pl b/opac/opac-account.pl >index c3cb9b4..4ff1554 100755 >--- a/opac/opac-account.pl >+++ b/opac/opac-account.pl >@@ -18,7 +18,6 @@ > # with Koha; if not, write to the Free Software Foundation, Inc., > # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. > >- > use strict; > use CGI; > use C4::Members; >@@ -30,7 +29,7 @@ use warnings; > my $query = new CGI; > my ( $template, $borrowernumber, $cookie ) = get_template_and_user( > { >- template_name => "opac-account.tmpl", >+ template_name => "opac-account.tt", > query => $query, > type => "opac", > authnotrequired => 0, >@@ -39,40 +38,21 @@ my ( $template, $borrowernumber, $cookie ) = get_template_and_user( > } > ); > >-# get borrower information .... >-my $borr = GetMemberDetails( $borrowernumber ); >-my @bordat; >-$bordat[0] = $borr; >- >-$template->param( BORROWER_INFO => \@bordat ); >- >-#get account details >-my ( $total , $accts, $numaccts) = GetMemberAccountRecords( $borrowernumber ); >- >-for ( my $i = 0 ; $i < $numaccts ; $i++ ) { >- $accts->[$i]{'amount'} = sprintf( "%.2f", $accts->[$i]{'amount'} || '0.00'); >- if ( $accts->[$i]{'amount'} >= 0 ) { >- $accts->[$i]{'amountcredit'} = 1; >- } >- $accts->[$i]{'amountoutstanding'} = >- sprintf( "%.2f", $accts->[$i]{'amountoutstanding'} || '0.00' ); >- if ( $accts->[$i]{'amountoutstanding'} >= 0 ) { >- $accts->[$i]{'amountoutstandingcredit'} = 1; >- } >-} >+my @debits = Koha::Database->new()->schema->resultset('AccountDebit')->search( >+ { 'me.borrowernumber' => $borrowernumber }, >+ { prefetch => { account_offsets => 'credit' } } >+); > >-# add the row parity >-my $num = 0; >-foreach my $row (@$accts) { >- $row->{'even'} = 1 if $num % 2 == 0; >- $row->{'odd'} = 1 if $num % 2 == 1; >- $num++; >-} >+my @credits = Koha::Database->new()->schema->resultset('AccountCredit')->search( >+ { 'me.borrowernumber' => $borrowernumber }, >+ { prefetch => { account_offsets => 'debit' } } >+); > >-$template->param ( >- ACCOUNT_LINES => $accts, >- total => sprintf( "%.2f", $total ), >- accountview => 1 >+$template->param( >+ borrower => GetMemberDetails($borrowernumber), >+ debits => \@debits, >+ credits => \@credits, >+ accountview => 1 > ); > > output_html_with_http_headers $query, $cookie, $template->output; >diff --git a/opac/opac-user.pl b/opac/opac-user.pl >index 02002a3..3754dc9 100755 >--- a/opac/opac-user.pl >+++ b/opac/opac-user.pl >@@ -162,19 +162,7 @@ if ($issues){ > $issue->{'reserved'} = 1; > } > >- my ( $total , $accts, $numaccts) = GetMemberAccountRecords( $borrowernumber ); >- my $charges = 0; >- foreach my $ac (@$accts) { >- if ( $ac->{'itemnumber'} == $issue->{'itemnumber'} ) { >- $charges += $ac->{'amountoutstanding'} >- if $ac->{'accounttype'} eq 'F'; >- $charges += $ac->{'amountoutstanding'} >- if $ac->{'accounttype'} eq 'FU'; >- $charges += $ac->{'amountoutstanding'} >- if $ac->{'accounttype'} eq 'L'; >- } >- } >- $issue->{'charges'} = $charges; >+ $issue->{'charges'} = $borr->{account_balance}; > $issue->{'subtitle'} = GetRecordValue('subtitle', GetMarcBiblio($issue->{'biblionumber'}), GetFrameworkCode($issue->{'biblionumber'})); > # check if item is renewable > my ($status,$renewerror) = CanBookBeRenewed( $borrowernumber, $issue->{'itemnumber'} ); >diff --git a/t/db_dependent/Accounts.t b/t/db_dependent/Accounts.t >index 1c2dd5a..7957cbe 100644 >--- a/t/db_dependent/Accounts.t >+++ b/t/db_dependent/Accounts.t >@@ -1,16 +1,199 @@ > #!/usr/bin/perl > # >-# This Koha test module is a stub! >+# This Koha test module is a stub! > # Add more tests here!!! > > use strict; > use warnings; > >-use Test::More tests => 1; >+use Test::More tests => 19; >+ >+use C4::Context; > > BEGIN { >- use_ok('C4::Accounts'); >+ use_ok('Koha::Database'); >+ use_ok('Koha::Accounts'); >+ use_ok('Koha::Accounts::DebitTypes'); >+ use_ok('Koha::Accounts::CreditTypes'); > } > >+## Intial Setup ## >+my $borrower = Koha::Database->new()->schema->resultset('Borrower')->create( >+ { >+ surname => 'Test', >+ categorycode => 'S', >+ branchcode => 'MPL', >+ account_balance => 0, >+ } >+); >+ >+my $biblio = >+ Koha::Database->new()->schema->resultset('Biblio') >+ ->create( { title => "Test Record" } ); >+my $biblioitem = >+ Koha::Database->new()->schema->resultset('Biblioitem') >+ ->create( { biblionumber => $biblio->biblionumber() } ); >+my $item = Koha::Database->new()->schema->resultset('Item')->create( >+ { >+ biblionumber => $biblio->biblionumber(), >+ biblioitemnumber => $biblioitem->biblioitemnumber(), >+ replacementprice => 25.00, >+ barcode => q{TEST_ITEM_BARCODE} >+ } >+); >+ >+my $issue = Koha::Database->new()->schema->resultset('Issue')->create( >+ { >+ borrowernumber => $borrower->borrowernumber(), >+ itemnumber => $item->itemnumber(), >+ } >+); >+## END initial setup >+ >+ok( Koha::Accounts::DebitTypes::Fine eq 'FINE', 'Test DebitTypes::Fine' ); >+ok( Koha::Accounts::DebitTypes::Lost eq 'LOST', 'Test DebitTypes::Lost' ); >+ok( >+ Koha::Accounts::DebitTypes::IsValid('FINE'), >+ 'Test DebitTypes::IsValid with valid debit type' >+); >+ok( >+ !Koha::Accounts::DebitTypes::IsValid('Not A Valid Fee Type'), >+ 'Test DebitTypes::IsValid with an invalid debit type' >+); >+my $authorised_value = >+ Koha::Database->new()->schema->resultset('AuthorisedValue')->create( >+ { >+ category => 'MANUAL_INV', >+ authorised_value => 'TEST', >+ lib => 'Test', >+ } >+ ); >+ok( Koha::Accounts::DebitTypes::IsValid('TEST'), >+ 'Test DebitTypes::IsValid with valid authorised value debit type' ); >+$authorised_value->delete(); >+ >+my $debit = AddDebit( >+ { >+ borrower => $borrower, >+ amount => 5.00, >+ type => Koha::Accounts::DebitTypes::Fine, >+ branchcode => 'MPL', >+ } >+); >+ok( $debit, "AddDebit returned a valid debit id " . $debit->id() ); >+ >+ok( >+ $borrower->account_balance() == 5.00, >+ "Borrower's account balance updated correctly" >+); >+ >+my $debit2 = AddDebit( >+ { >+ borrower => $borrower, >+ amount => 7.00, >+ type => Koha::Accounts::DebitTypes::Fine, >+ branchcode => 'MPL', >+ } >+); >+ >+my $credit = AddCredit( >+ { >+ borrower => $borrower, >+ type => Koha::Accounts::CreditTypes::Payment, >+ amount => 9.00, >+ branchcode => 'MPL', >+ } >+); >+ >+RecalculateAccountBalance( { borrower => $borrower } ); >+ok( >+ sprintf( "%.2f", $borrower->account_balance() ) eq "3.00", >+ "RecalculateAccountBalance updated balance correctly." >+); >+ >+Koha::Database->new()->schema->resultset('AccountCredit')->create( >+ { >+ borrowernumber => $borrower->borrowernumber(), >+ type => Koha::Accounts::CreditTypes::Payment, >+ amount_paid => 3.00, >+ amount_remaining => 3.00, >+ } >+); >+NormalizeBalances( { borrower => $borrower } ); >+ok( >+ $borrower->account_balance() == 0.00, >+ "NormalizeBalances updated balance correctly." >+); >+ >+# Adding advance credit with no balance due >+$credit = AddCredit( >+ { >+ borrower => $borrower, >+ type => Koha::Accounts::CreditTypes::Payment, >+ amount => 9.00, >+ branchcode => 'MPL', >+ } >+); >+ok( >+ $borrower->account_balance() == -9, >+'Adding a $9 credit for borrower with 0 balance results in a -9 dollar account balance' >+); >+ >+my $debit3 = AddDebit( >+ { >+ borrower => $borrower, >+ amount => 5.00, >+ type => Koha::Accounts::DebitTypes::Fine, >+ branchcode => 'MPL', >+ } >+); >+ok( >+ $borrower->account_balance() == -4, >+'Adding a $5 debit when the balance is negative results in the debit being automatically paid, resulting in a balance of -4' >+); >+ >+my $debit4 = AddDebit( >+ { >+ borrower => $borrower, >+ amount => 6.00, >+ type => Koha::Accounts::DebitTypes::Fine, >+ branchcode => 'MPL', >+ } >+); >+ok( >+ $borrower->account_balance() == 2, >+'Adding another debit ( 6.00 ) more than the negative account balance results in a partial credit and a balance due of 2.00' >+); >+$credit = AddCredit( >+ { >+ borrower => $borrower, >+ type => Koha::Accounts::CreditTypes::WriteOff, >+ amount => 2.00, >+ branchcode => 'MPL', >+ debit_id => $debit4->debit_id(), >+ } >+); >+ok( $borrower->account_balance() == 0, >+ 'WriteOff of remaining 2.00 balance succeeds' ); >+ >+my $debit5 = DebitLostItem( >+ { >+ borrower => $borrower, >+ issue => $issue, >+ } >+); >+ok( $borrower->account_balance() == 25, >+ 'DebitLostItem adds debit for replacement price of item' ); > >+my $lost_credit = >+ CreditLostItem( { borrower => $borrower, debit => $debit5 } ); >+ok( >+ $borrower->account_balance() == 0, >+ 'CreditLostItem adds credit for same about as the debit for the lost tiem' >+); > >+## Post test cleanup ## >+$issue->delete(); >+$item->delete(); >+$biblio->delete(); >+$borrower->delete(); >diff --git a/t/db_dependent/Circulation.t b/t/db_dependent/Circulation.t >index aa2a969..f60145b 100755 >--- a/t/db_dependent/Circulation.t >+++ b/t/db_dependent/Circulation.t >@@ -302,8 +302,15 @@ C4::Context->dbh->do("DELETE FROM accountlines"); > C4::Context->set_preference('WhenLostForgiveFine','1'); > C4::Context->set_preference('WhenLostChargeReplacementFee','1'); > >- C4::Overdues::UpdateFine( $itemnumber, $renewing_borrower->{borrowernumber}, >- 15.00, q{}, Koha::DateUtils::output_pref($datedue) ); >+ C4::Overdues::UpdateFine( >+ { >+ itemnumber => $itemnumber, >+ borrowernumber => $renewing_borrower->{borrowernumber}, >+ amount => 15.00, >+ due => Koha::DateUtils::output_pref($datedue), >+ issue_id => GetItemIssue($itemnumber)->{issue_id} >+ } >+ ); > > LostItem( $itemnumber, 1 ); > >@@ -319,8 +326,15 @@ C4::Context->dbh->do("DELETE FROM accountlines"); > C4::Context->set_preference('WhenLostForgiveFine','0'); > C4::Context->set_preference('WhenLostChargeReplacementFee','0'); > >- C4::Overdues::UpdateFine( $itemnumber2, $renewing_borrower->{borrowernumber}, >- 15.00, q{}, Koha::DateUtils::output_pref($datedue) ); >+ C4::Overdues::UpdateFine( >+ { >+ itemnumber => $itemnumber2, >+ borrowernumber => $renewing_borrower->{borrowernumber}, >+ amount => 15.00, >+ due => Koha::DateUtils::output_pref($datedue), >+ issue_id => GetItemIssue($itemnumber2)->{issue_id}, >+ } >+ ); > > LostItem( $itemnumber2, 1 ); > >diff --git a/t/db_dependent/Members/AddEnrolmentFeeIfNeeded.t b/t/db_dependent/Members/AddEnrolmentFeeIfNeeded.t >index 46d9ec1..b8f0708 100644 >--- a/t/db_dependent/Members/AddEnrolmentFeeIfNeeded.t >+++ b/t/db_dependent/Members/AddEnrolmentFeeIfNeeded.t >@@ -40,17 +40,17 @@ my %borrower_data = ( > my $borrowernumber = C4::Members::AddMember( %borrower_data ); > $borrower_data{borrowernumber} = $borrowernumber; > >-my ( $total ) = C4::Members::GetMemberAccountRecords( $borrowernumber ); >+my ( $total ) = C4::Members::GetMemberAccountBalance( $borrowernumber ); > is( $total, $enrolmentfee_K, "New kid pay $enrolmentfee_K" ); > > $borrower_data{categorycode} = 'J'; > C4::Members::ModMember( %borrower_data ); >-( $total ) = C4::Members::GetMemberAccountRecords( $borrowernumber ); >+( $total ) = C4::Members::GetMemberAccountBalance( $borrowernumber ); > is( $total, $enrolmentfee_K + $enrolmentfee_J, "Kid growing and become a juvenile, he should pay " . ( $enrolmentfee_K + $enrolmentfee_J ) ); > > # Check with calling directly AddEnrolmentFeeIfNeeded > C4::Members::AddEnrolmentFeeIfNeeded( 'YA', $borrowernumber ); >-( $total ) = C4::Members::GetMemberAccountRecords( $borrowernumber ); >+( $total ) = C4::Members::GetMemberAccountBalance( $borrowernumber ); > is( $total, $enrolmentfee_K + $enrolmentfee_J + $enrolmentfee_YA, "Juvenile growing and become an young adult, he should pay " . ( $enrolmentfee_K + $enrolmentfee_J + $enrolmentfee_YA ) ); > > $dbh->rollback; >-- >1.7.2.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 6427
:
21922
|
22704
|
22705
|
22708
|
22709
|
22710
|
22741
|
22870
|
22871
|
22872
|
22873
|
22874
|
22875
|
22876
|
22881
|
22889
|
22940
|
22948
|
22949
|
22995
|
23000
|
23137
|
23158
|
23161
|
23171
|
23186
|
23269
|
23275
|
23276
|
23391
|
23392
|
23400
|
23401
|
23402
|
23403
|
23404
|
23405
|
23406
|
23407
|
23408
|
23409
|
23410
|
23411
|
23412
|
23413
|
23420
|
23421
|
23422
|
23423
|
23424
|
23425
|
23426
|
23427
|
23428
|
23429
|
23430
|
23431
|
23432
|
23433
|
23440
|
23441
|
23442
|
23443
|
23444
|
23445
|
23446
|
23447
|
23448
|
23449
|
23450
|
23451
|
23452
|
23453
|
23454
|
23458
|
23459
|
23460
|
23461
|
23462
|
23463
|
23464
|
23465
|
23466
|
23467
|
23468
|
23469
|
23470
|
23471
|
23603
|
23643
|
23644
|
23645
|
23646
|
23647
|
23648
|
23649
|
23650
|
23651
|
23652
|
23653
|
23654
|
23655
|
23656
|
23657
|
23937
|
23938
|
23939
|
23940
|
23941
|
23942
|
23943
|
23944
|
23945
|
23946
|
23947
|
23948
|
23949
|
23950
|
23951
|
24612
|
24613
|
24614
|
24615
|
24616
|
24617
|
24618
|
24619
|
24620
|
24621
|
24622
|
24623
|
24624
|
24625
|
24626
|
24627
|
24628
|
24757
|
24758
|
24759
|
24760
|
24761
|
24762
|
24763
|
24764
|
24765
|
24766
|
24767
|
24768
|
24769
|
24770
|
24771
|
24772
|
24777
|
24792
|
24793
|
24794
|
24795
|
24796
|
24797
|
24798
|
24799
|
24800
|
24801
|
24802
|
24803
|
24804
|
24805
|
24806
|
24807
|
24808
|
24809
|
24810
|
24811
|
24812
|
24813
|
24814
|
24815
|
24816
|
24817
|
24818
|
24819
|
24820
|
24821
|
24822
|
24823
|
24824
|
24825
|
24826
|
24827
|
24828
|
24829
|
24830
|
24831
|
24832
|
24833
|
24834
|
24835
|
24836
|
24837
|
24838
|
24839
|
24840
|
24841
|
24842
|
24843
|
24844
|
25777
|
25778
|
25779
|
25780
|
25781
|
25782
|
25783
|
25784
|
25785
|
25786
|
25787
|
25788
|
25789
|
25790
|
25791
|
25792
|
25793
|
25794
|
25795
|
25796
|
25797
|
25798
|
25799
|
25800
|
25801
|
25802
|
25803
|
25804
|
25805
|
25806
|
25807
|
25808
|
25809
|
25810
|
25811
|
25812
|
25813
|
25814
|
25815
|
25816
|
25930
|
25932
|
25933
|
25934
|
26033
|
26034
|
26035
|
26036
|
26107
|
27167
|
27168
|
27169
|
27170
|
27171
|
27172
|
27173
|
27174
|
27175
|
27176
|
27177
|
27178
|
27179
|
27180
|
27181
|
27182
|
27183
|
27184
|
27185
|
27186
|
27187
|
27189
|
27190
|
27197
|
28067
|
28068
|
28069
|
28070
|
28071
|
28072
|
28073
|
28074
|
28075
|
28076
|
28077
|
28078
|
28079
|
28080
|
28081
|
28082
|
28083
|
28084
|
28085
|
28086
|
28087
|
28088
|
28089
|
28090
|
28091
|
28527
|
28528
|
28529
|
28530
|
28531
|
28532
|
28533
|
28534
|
28535
|
28536
|
28537
|
28538
|
28539
|
28540
|
28541
|
28542
|
28543
|
28544
|
28545
|
28546
|
28547
|
28548
|
28549
|
28550
|
28551
|
28552
|
28553
|
28555
|
28556
|
28561
|
28563
|
28564
|
28795
|
28796
|
28797
|
28798
|
28799
|
28800
|
28801
|
28802
|
28803
|
28804
|
28805
|
28806
|
28807
|
28808
|
28809
|
28810
|
28811
|
28812
|
28813
|
28814
|
28815
|
28816
|
28817
|
28818
|
28819
|
28820
|
28821
|
28822
|
28887
|
28888
|
28889
|
28890
|
28909
|
29176
|
29230
|
29231
|
29232
|
29233
|
29234
|
29235
|
29236
|
29237
|
29238
|
29239
|
29240
|
29241
|
29242
|
29243
|
29244
|
29245
|
29246
|
29247
|
29248
|
29249
|
29250
|
29251
|
29252
|
29253
|
29254
|
29255
|
29256
|
29257
|
29258
|
29259
|
29260
|
29261
|
29262
|
29263
|
29264
|
29265
|
29706
|
29707
|
29708
|
29709
|
29710
|
29711
|
29712
|
29713
|
29714
|
29715
|
29716
|
29717
|
29719
|
29720
|
29721
|
29722
|
29723
|
29724
|
29725
|
29726
|
29727
|
29728
|
29729
|
29730
|
30271
|
30272
|
30273
|
30274
|
30275
|
30276
|
30277
|
30278
|
30279
|
30280
|
30281
|
30282
|
30320
|
30321
|
30322
|
30323
|
30324
|
30325
|
30326
|
30327
|
30328
|
30329
|
30330
|
30331
|
30416
|
30417
|
30418
|
30419
|
30420
|
30421
|
30422
|
30423
|
30424
|
30425
|
30426
|
30427
|
31477
|
31478
|
31479
|
31480
|
31481
|
31482
|
31483
|
31484
|
31485
|
31486
|
31487
|
31488
|
31754
|
31755
|
31756
|
31757
|
31758
|
31759
|
31760
|
31761
|
31762
|
31763
|
31764
|
31765
|
31766
|
31767
|
31768
|
31769
|
31770
|
31771
|
31772
|
31773
|
31774
|
31775
|
31776
|
31777
|
32478
|
32479
|
32480
|
32481
|
32482
|
32483
|
32484
|
32485
|
32486
|
32487
|
32488
|
32489
|
32591
|
32592
|
32593
|
32594
|
32595
|
32596
|
32597
|
32598
|
32599
|
32600
|
32601
|
32602
|
32827
|
32828
|
32829
|
32830
|
32831
|
32832
|
32833
|
32834
|
32835
|
32836
|
32837
|
32838
|
33251
|
33252
|
33253
|
33254
|
33255
|
33256
|
33257
|
33258
|
33259
|
33260
|
33261
|
33262
|
34096
|
34097
|
34098
|
34099
|
34100
|
34101
|
34102
|
34103
|
34104
|
34105
|
34106
|
34107
|
34204
|
34205
|
34206
|
34207
|
34208
|
34209
|
34210
|
34211
|
34212
|
34213
|
34214
|
34215
|
35196
|
35197
|
35198
|
35199
|
35200
|
35201
|
35202
|
35203
|
35204
|
35205
|
35206
|
35207
|
35208
|
35302
|
36324
|
36326
|
36327
|
36328
|
36329
|
36330
|
36331
|
36332
|
36333
|
36334
|
36335
|
36337
|
36338
|
36340
|
36380
|
36391
|
36393
|
37127
|
37128
|
37129
|
37130
|
37131
|
37133
|
37134
|
37135
|
37136
|
37137
|
37138
|
37139
|
37140
|
37141
|
37142
|
37143
|
37147
|
37148
|
37149
|
37150
|
37151
|
37152
|
37153
|
37154
|
37155
|
37156
|
37157
|
37158
|
37159
|
37160
|
37161
|
37162
|
37229
|
37230
|
37231
|
37232
|
37233
|
37234
|
37235
|
37236
|
37237
|
37238
|
37239
|
37240
|
37241
|
37242
|
37243
|
37244
|
38247
|
38248
|
38249
|
38250
|
38251
|
38252
|
38253
|
38254
|
38255
|
38256
|
38257
|
38258
|
38259
|
38260
|
38261
|
38262
|
39063
|
39064
|
39065
|
39066
|
39067
|
39069
|
39070
|
39071
|
39072
|
39073
|
39074
|
39075
|
39076
|
39077
|
39078
|
39079
|
39671
|
39672
|
39673
|
39674
|
39675
|
39676
|
39677
|
39678
|
39679
|
39680
|
39681
|
39682
|
39683
|
39684
|
39685
|
39686