From 51a5a22addb9499f354812e3a7784d27e8a102b3 Mon Sep 17 00:00:00 2001 From: Kyle M Hall Date: Wed, 9 Oct 2013 10:36:44 -0400 Subject: [PATCH] Bug 6427 - Rewrite of the accounts system - WIP --- C4/Accounts.pm | 821 -------------------- C4/Circulation.pm | 311 ++++---- C4/Koha.pm | 2 + C4/Members.pm | 112 +-- C4/Overdues.pm | 292 +++----- 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/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/circulation.pl | 4 +- installer/data/mysql/kohastructure.sql | 83 ++ installer/data/mysql/updatedatabase.pl | 88 +++ .../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/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/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 +- 77 files changed, 4849 insertions(+), 3404 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 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 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(<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, C, C, C, C, C, C, -or C. -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 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..e4123ad 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,7 +83,6 @@ BEGIN { &GetHideLostItemsPreference &IsMemberBlocked - &GetMemberAccountRecords &GetBorNotifyAcctRecord &GetborCatFromCatType @@ -338,9 +337,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 +428,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 +684,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 +1160,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 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,24 +1175,38 @@ 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; + + push( @not_fines, Koha::Accounts::DebitTypes::Hold() ); + + push( @not_fines, Koha::Accounts::DebitTypes::Rental() ) + unless C4::Context->preference('RentalsInNoissuesCharge'); - 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 $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 ); } - my %not_fine = map {$_ => 1} @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) }; - } + my $other_charges = + Koha::Database->new()->schema->resultset('AccountDebit')->search( + { + borrowernumber => $borrowernumber, + type => { -not_in => \@not_fines } + } + )->get_column('amount_outstanding')->sum(); - return ( $total, $total - $other_charges, $other_charges); + return ( + $borrower->account_balance(), + $borrower->account_balance() - $other_charges, + $other_charges + ); } =head2 GetBorNotifyAcctRecord diff --git a/C4/Overdues.pm b/C4/Overdues.pm index 33dbd98..a690b6e 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); @@ -46,7 +47,6 @@ BEGIN { &UpdateFine &GetFine - &CheckItemNotify &GetOverduesForBranch &RemoveNotifyLine &AddNotifyLine @@ -456,154 +456,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,18 +602,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; + my ( $itemnumber, $borrowernumber ) = @_; + + my $schema = Koha::Database->new()->schema; + + my $amount_outstanding = $schema->resultset('AccountDebit')->search( + { + itemnumber => $itemnumber, + borrowernumber => $borrowernumber, + type => Koha::Accounts::DebitTypes::Fine(), + }, + )->get_column('amount_outstanding')->sum(); + + return $amount_outstanding; } =head2 NumberNotifyId @@ -759,27 +718,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 +742,7 @@ sub GetOverduesForBranch { biblio.title, biblio.author, biblio.biblionumber, + issues.issue_id, issues.date_due, issues.returndate, issues.branchcode, @@ -814,25 +753,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 +779,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/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 + +=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 + +=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 + +=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 + +=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 + +=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 + +=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 + +=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 + +=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 + +=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 + +=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/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 + +=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 +Type: has_many -=back +Related object: L =cut -__PACKAGE__->set_primary_key("borrowernumber"); - -=head1 UNIQUE CONSTRAINTS - -=head2 C +__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 +Type: has_many -=back +Related object: L =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 +Related object: L =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 +Related object: L =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 -> basketno - -=cut - -__PACKAGE__->many_to_many("basketnoes", "aqbasketusers", "basketno"); - -=head2 budgets - -Type: many_to_many - -Composing rels: L -> budget - -=cut - -__PACKAGE__->many_to_many("budgets", "aqbudgetborrowers", "budget"); - -=head2 courses - -Type: many_to_many -Composing rels: L -> 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 be28986..9112ff2 100644 --- a/Koha/Schema/Result/Deleteditem.pm +++ b/Koha/Schema/Result/Deleteditem.pm @@ -367,6 +367,17 @@ __PACKAGE__->set_primary_key("itemnumber"); # Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-10-14 20:56:21 # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:dfUPy7ijJ/uh9+0AqKjSBw +__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 + +=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 = "$formatted" 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/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 fefc985..6449da2 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`), @@ -3387,6 +3388,88 @@ 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, + borrowernumber int(11) NOT NULL, + `type` varchar(255) NOT 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; + +-- +-- 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, + 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; + +-- +-- 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, + debit_id int(11) DEFAULT NULL, + credit_id int(11) DEFAULT NULL, + `type` varchar(255) DEFAULT NULL, + amount decimal(28,6) NOT NULL, + 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; + +-- +-- 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 a9e08e3..b5d94a9 100755 --- a/installer/data/mysql/updatedatabase.pl +++ b/installer/data/mysql/updatedatabase.pl @@ -7259,6 +7259,7 @@ if ( CheckVersion($DBversion) ) { $dbh->{AutoCommit} = 1; $dbh->{RaiseError} = 0; + SetVersion ($DBversion); } $DBversion = "3.13.00.031"; @@ -7771,6 +7772,93 @@ 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_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; + "); + + 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 %] 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 ) %]
  • [% ELSE %]
  • [% END %]Details
  • [% END %] [% IF ( CAN_user_updatecharges ) %] - [% IF ( finesview ) %]
  • [% ELSE %]
  • [% END %]Fines
  • + [% IF ( accounts_view ) %]
  • [% ELSE %]
  • [% END %]Fines
  • [% END %] [% IF ( RoutingSerials ) %][% IF ( routinglistview ) %]
  • [% ELSE %]
  • [% END %]Routing lists
  • [% 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 ) %]
  • [% ELSE %]
  • [% END %]Details
  • [% END %] [% IF ( CAN_user_updatecharges ) %] - [% IF ( finesview ) %]
  • [% ELSE %]
  • [% END %]Fines
  • + [% IF ( accounts_view ) %]
  • [% ELSE %]
  • [% END %]Fines
  • [% END %] [% IF ( RoutingSerials ) %][% IF ( routinglistview ) %]
  • [% ELSE %]
  • [% END %]Routing lists
  • [% END %] [% IF ( intranetreadinghistory ) %][% IF ( readingrecordview ) %]
  • [% ELSE %]
  • [% END %]Circulation history
  • [% 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 ) %]
  • [% ELSE %]
  • [% END %]Check out
  • [% IF ( detailview ) %]
  • [% ELSE %]
  • [% END %]Details
  • [% IF ( CAN_user_updatecharges ) %] - [% IF ( finesview ) %]
  • [% ELSE %]
  • [% END %]Fines
  • + [% IF ( finesview ) %]
  • [% ELSE %]
  • [% END %]Fines
  • [% END %] [% IF ( intranetreadinghistory ) %] [% IF ( readingrecordview ) %]
  • [% ELSE %]
  • [% END %]Circulation history
  • 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 [% message %] [% IF ( charges ) %]
  • - Fees & Charges: Patron has Outstanding fees & charges[% IF ( chargesamount ) %] of [% chargesamount %][% END %]. + Fees & Charges: Patron has Outstanding fees & charges[% IF ( chargesamount ) %] of [% chargesamount | $Currency %][% END %]. [% IF ( charges_is_blocker ) %] Checkouts are BLOCKED because fine balance is OVER THE LIMIT. [% END %] - Make payment
  • + Make payment [% END %] [% IF ( credits ) %]
  • - Credits: Patron has a credit[% IF ( creditsamount ) %] of [% creditsamount %][% END %] + Credits: Patron has a credit[% IF ( creditsamount ) %] of [% creditsamount | $Currency %][% END %]
  • [% 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 ) %]

    Patron has outstanding fines of [% fines %].

    -

    Make payment.

    +

    Make payment.

    [% END %] 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..9ed736f --- /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' %] +Koha › Patrons › Account for [% INCLUDE 'patron-title.inc' %] +[% INCLUDE 'doc-head-close.inc' %] + + + +[% INCLUDE 'datatables-strings.inc' %] +[% INCLUDE 'browser-strings.inc' %] + + + + + + +[% INCLUDE 'header.inc' %] +[% INCLUDE 'patron-search.inc' %] + + + +
    +
    +
    +
    + [% INCLUDE 'members-toolbar.inc' %] + +
    + +
    + +
    + +

    +

    Account balance: [% borrower.account_balance | $Currency %]

    +

    + +
    +
    + View payments + + + + + + + + + + + + + + + + + +
    Fees
    IDDescriptionTypeAmountOutsandingCreated onUpdated on
    +
    + +
    + View fees + + + + + + + + + + + + + + + + + +
    Payments
    IDNotesTypeAmountRemainingCreated onUpdated on
    +
    +
    +
    +
    +
    + +
    + [% INCLUDE 'circ-menu.inc' %] +
    +
    +[% 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' %] +Koha › Borrowers › Create manual credit +[% INCLUDE 'doc-head-close.inc' %] + + + + [% INCLUDE 'header.inc' %] + [% INCLUDE 'patron-search.inc' %] + + + +
    +
    +
    +
    + [% INCLUDE 'members-toolbar.inc' %] + +
    + + +
    + +
    + + +
    + Manual credit + +
      +
    1. + + +
    2. + +
    3. + + +
    4. + +
    5. + + +
    6. + +
    7. + + +
    8. + +
    9. + + + Example: 5.00 +
    10. +
    + +
    + +
    + + Cancel +
    +
    + +
    +
    +
    +
    +
    + [% INCLUDE 'circ-menu.inc' %] +
    +
    +[% 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' %] +Koha › Borrowers › Create manual invoice +[% INCLUDE 'doc-head-close.inc' %] + + + + + [% INCLUDE 'header.inc' %] + [% INCLUDE 'patron-search.inc' %] + + + +
    +
    +
    +
    + [% INCLUDE 'members-toolbar.inc' %] + +
    + +
    + +
    + + +
    + Manual Invoice + +
      +
    1. + + +
    2. + + +
    3. + + +
    4. + +
    5. + + +
    6. + +
    7. + + +
    8. + +
    9. + + Example: 5.00 +
    10. + +
    +
    + +
    + + Cancel +
    + +
    + +
    +
    +
    +
    + +
    + [% INCLUDE 'circ-menu.inc' %] +
    + +
    +[% 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..2d0754d --- /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' %] +Koha › Patrons › Pay Fines for [% borrower.firstname %] [% borrower.surname %] +[% INCLUDE 'doc-head-close.inc' %] +[% INCLUDE 'browser-strings.inc' %] + + + + + [% INCLUDE 'header.inc' %] + [% INCLUDE 'patron-search.inc' %] + + + +
    +
    +
    +
    + [% INCLUDE 'members-toolbar.inc' borrowernumber=borrower.borrowernumber %] + +
    + + +
    + + [% IF ( debits ) %] +
    + + + +

    + + Select all + + + | + + + Clear all + +

    + + + + + + + + + + + + + + [% SET total_due = 0 %] + [% FOREACH d IN debits %] + [% SET total_due = total_due + d.amount_outstanding %] + + + + + + + + + + + + [% END %] + + + + + + + + + +
     DescriptionAccount typeOriginal amountAmount outstanding
    + + + [% d.description %] + + [% IF d.notes %] + ( [% d.notes %] ) + [% END %] + + [% d.type %] + + [% d.amount_original | $Currency %] + + + [% d.amount_outstanding | $Currency %] + +
    Total Due:[% total_due | $Currency %]
    + +
    +

    + + + + + +

    + +

    + + +

    + +

    + + +

    + +

    + + +

    +

    + +
    + + Cancel +
    + +
    + + [% ELSE %] +

    + [% borrower.firstname %] [% borrower.surname %] has no outstanding fines. +

    + [% END %] + +
    +
    +
    +
    + +
    + [% INCLUDE 'circ-menu.tt' %] +
    +
    +[% 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' %] +Print Receipt for [% cardnumber %] +[% INCLUDE 'doc-head-close.inc' %] + + + + + +[% SET account = debit || credit %] +[% SET borrower = account.borrower %] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [% IF account.description %] + + + + + [% END %] + + [% IF credit %] + + + + + [% IF credit.amount_received %] + + + + + + + + + [% END %] + + + + + [% IF credit.account_offsets %] + + + + + + + + + + + + [% END %] + [% ELSIF debit %] + + + + + + + + + [% IF debit.account_offsets %] + + + + + + + + + + + + [% END %] + [% END %] + + + + [% IF credit.account_offsets %] + [% FOREACH ao IN credit.account_offsets %] + + + + + + + + + [% END %] + [% ELSIF debit.account_offsets %] + [% FOREACH ao IN debit.account_offsets %] + + + + + + + + + [% END %] + [% END %] + +
    + [% IF debit %] + Invoice + [% ELSIF credit %] + Payment receipt + [% END %] +
    + [% borrower.branch.branchname | $EncodeUTF8 %] +
    Name:[% borrower.firstname | $EncodeUTF8 %] [% borrower.surname | $EncodeUTF8 %]
    Card number:[% borrower.cardnumber %]
    Date:[% account.created_on | $KohaDates %]
    Description:[% account.description | $EncodeUTF8 %]
    Amount paid:[% credit.amount_paid | $Currency highlight => type %]
    Amount received:[% credit.amount_received | $Currency highlight => type %]
    Change due:[% credit.amount_received - credit.amount_paid | $Currency highlight => type %]
    Balance:[% credit.amount_remaining | $Currency highlight => type %]
    Fees paid
    DescriptionTypeAmountPaidOutstandingDate
    Amount:[% debit.amount_original | $Currency highlight => type %]
    Outstanding:[% debit.amount_outstanding | $Currency highlight => type %]
    Payments applied
    DateTypePaymentAppliedBalanceNotes
    [% ao.debit.description %][% ao.debit.type %][% ao.debit.amount_original | $Currency highlight => 'debit' %][% ao.amount | $Currency highlight => 'offset' %][% ao.debit.amount_outstanding | $Currency highlight => 'debit' %][% ao.debit.created_on | $KohaDates %]
    [% ao.credit.type %][% ao.credit.created_on | $KohaDates %][% ao.credit.amount_paid | $Currency highlight => 'credit' %][% ao.amount | $Currency highlight => 'offset' %][% ao.credit.amount_remaining | $Currency highlight => 'credit' %][% ao.credit.notes %]
    + +[% 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' %] -Koha › Patrons › Account for [% INCLUDE 'patron-title.inc' %] -[% INCLUDE 'doc-head-close.inc' %] - - -[% INCLUDE 'header.inc' %] -[% INCLUDE 'patron-search.inc' %] - - - -
    - -
    -
    -
    -[% INCLUDE 'members-toolbar.inc' %] -
    - - -
    - -
    - - - - - - - - - [% IF ( reverse_col ) %] - - [% END %] - - - - - [% FOREACH account IN accounts %] - - [% IF ( loop.odd ) %][% ELSE %][% END %] - - - - [% IF ( account.amountcredit ) %] - [% IF ( account.amountoutstandingcredit ) %] - [% IF ( reverse_col ) %] - - [% END %] - - - - [% END %] - - - - [% IF ( totalcredit ) %] - [% IF ( reverse_col ) %] - - - -
    DateDescription of chargesNoteAmountOutstanding Print
    [% account.date %][% account.description %] [% IF ( account.itemnumber ) %]View item [% END %][% account.title |html %][% account.note | html_line_break %][% ELSE %][% END %][% account.amount %][% ELSE %][% END %][% account.amountoutstanding %] - [% IF ( account.payment ) %] - Reverse - [% ELSE %] -   - [% END %] - - [% IF ( account.payment ) %] - Print - [% ELSE %] - Print - [% END %] -
    Total due - [% ELSE %] - - [% END %] - [% ELSE %] - [% IF ( reverse_col ) %] - - [% ELSE %] - - [% END %] - [% END %] - [% total %]
    -
    - -
    -
    - -
    -[% INCLUDE 'circ-menu.inc' %] -
    -
    -[% 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(){
    -
    +
    @@ -48,7 +48,7 @@ $(document).ready(function(){
  • Example: 5.00
  • -
    Cancel
    +
    Cancel
    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' %] -Koha › Borrowers › Create manual invoice -[% INCLUDE 'doc-head-close.inc' %] - - - -[% INCLUDE 'header.inc' %] -[% INCLUDE 'patron-search.inc' %] - - - -
    - -
    -
    -
    -[% INCLUDE 'members-toolbar.inc' %] - - -
    - -
    - -[% IF ( ERROR ) %] -[% IF ( ITEMNUMBER ) %] - ERROR an invalid itemnumber was entered, please hit back and try again -[% END %] -[% ELSE %] -
    -
    - Manual Invoice -
      -
    1. - - - -
    2. -
    3. -
    4. -
    5. -
    6. Example: 5.00
    7. -
    -
    Cancel
    -
    - -[% END %] -
    - -
    -
    - -
    -[% INCLUDE 'circ-menu.inc' %] -
    -
    -[% 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' %] -Koha › Patrons › Pay Fines for [% borrower.firstname %] [% borrower.surname %] -[% INCLUDE 'doc-head-close.inc' %] - - - - -[% INCLUDE 'header.inc' %] -[% INCLUDE 'patron-search.inc' %] - - - -
    - -
    -
    -
    -[% INCLUDE 'members-toolbar.inc' borrowernumber=borrower.borrowernumber %] - - -
    - -
    - -[% IF ( accounts ) %] -
    - -

    Select all | Clear all

    - - - - - - - - - - - - - - - - - - - - - -[% FOREACH account_grp IN accounts %] - [% FOREACH line IN account_grp.accountlines %] - - - - - - - - - - - -[% END %] -[% IF ( account_grp.total ) %] - - - - - -[% END %] -[% END %] - -
     Fines & chargesDescriptionPayment noteAccount typeNotify idLevelAmountAmount outstanding
    Total Due:[% total | format('%.2f') %]
    - [% IF ( line.amountoutstanding > 0 ) %] - - [% END %] - - [% IF ( line.amountoutstanding > 0 ) %] - - - [% END %] - - - - - - - - - - - - [% line.description %] ([% line.title |html_entity %])[% line.accounttype %][% line.notify_id %][% line.notify_level %][% line.amount | format('%.2f') %][% line.amountoutstanding | format('%.2f') %]
    Sub total:[% account_grp.total | format('%.2f') %]
    -
    - - - -Cancel -
    -
    -[% ELSE %] -

    [% borrower.firstname %] [% borrower.surname %] has no outstanding fines.

    -[% END %] -
    - -
    -
    - -
    -[% INCLUDE 'circ-menu.tt' %] -
    -
    -[% 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' %] -Koha › Patrons › Collect fine payment for [% borrower.firstname %] [% borrower.surname %] -[% INCLUDE 'doc-head-close.inc' %] - - - - -[% INCLUDE 'header.inc' %] -[% INCLUDE 'patron-search.inc' %] - - -
    - -
    -
    -
    -[% INCLUDE 'members-toolbar.inc' borrowernumber=borrower.borrowernumber %] - - - -
    - -
    -[% IF ( error_over ) %] -
    - You must pay a value less than or equal to [% total_due | format('%.2f') %]. -
    -[% END %] - -[% IF ( pay_individual ) %] -
    - - - - - - - - - - - - - -
    - Pay an individual fine - - - - - - - - - - - - - - - - - - - - - -
    DescriptionAccount typeNotify idLevelAmountAmount outstanding
    Total amount payable:[% amountoutstanding | format('%.2f') %]
    - [% description %] [% title %] - [% accounttype %][% notify_id %][% notify_level %][% amount | format('%.2f') %][% amountoutstanding | format('%.2f') %]
    - -
      - -
    1. - - - -
    2. -
    -
    - - -
    -[% ELSIF ( writeoff_individual ) %] -
    -
    - Write off an individual fine - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    DescriptionAccount typeNotify idLevelAmountAmount outstanding
    Total amount to be written off:[% amountoutstanding | format('%.2f') %]
    [% description %] [% title %][% accounttype %][% notify_id %][% notify_level %][% amount | format('%.2f') %][% amountoutstanding | format('%.2f') %]
    -
    - -
    -[% ELSE %] - -
    - - - - -
    - [% IF ( selected_accts ) %]Pay an amount toward selected fines[% ELSE %]Pay an amount toward all fines[% END %] -
      -
    1. - Total amount outstanding: - [% total | format('%.2f') %] -
    2. -
    3. - - - -
    4. -
    5. - - -
    6. -
    -
    - -
    -[% END %] -
    -
    -
    - -
    -[% INCLUDE 'circ-menu.tt' %] -
    -
    -[% 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' %] -Print Receipt for [% cardnumber %] - - - - - - - -
    - - -[% IF ( LibraryName ) %] - - - -[% END %] - - - - - - - - - - - - - - - - [% FOREACH account IN accounts %] - - - - [% IF ( account.amountcredit ) %] - - - [% END %] - - - - [% IF ( totalcredit ) %] - - -
    -

    [% LibraryName %]

    -
    -

    Fee receipt

    -
    - [% IF ( branchname ) %]

    [% branchname %]

    [% END %] -
    - Received with thanks from [% firstname %] [% surname %]
    - Card number : [% cardnumber %]
    -
    DateDescription of chargesAmount
    [% account.date %][% account.description %][% ELSE %][% END %][% account.amount %]
    Total outstanding dues as on date : [% ELSE %][% END %][% total %]
    -
    -[% 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' %] -Print Receipt for [% cardnumber %] - - - - - - - -
    - - -[% IF ( LibraryName ) %] - - - -[% END %] - - - - - - - - - - - - - - - - - [% FOREACH account IN accounts %] - - - - [% IF ( account.amountcredit ) %] - [% IF ( account.amountoutstandingcredit ) %] - - - [% END %] - - - - [% IF ( totalcredit ) %] - - -
    -

    [% LibraryName %]

    -
    -

    INVOICE

    -
    - [% IF ( branchname ) %]

    [% branchname %]

    [% END %] -
    - Bill to: [% firstname %] [% surname %]
    - Card number: [% cardnumber %]
    -
    DateDescription of chargesAmountAmount outstanding
    [% account.date %][% account.description %][% ELSE %][% END %][% account.amount %][% ELSE %][% END %][% account.amountoutstanding %]
    Total outstanding dues as on date: [% ELSE %][% END %][% total %]
    -
    -[% 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)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%+2vP1rl3*$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!d$>Do3Jo15TlYl9m;-_3M7y&8+fGbP>p=udnZ^^3rY*Ry8&@-XZS}=H{ef zDUJ>}0_oCdYHA|eDvG0BC2ghK?XIQGd^|3d(Ko2a8%4c^+ z2RQuxqA|Bf6p=-Yhg81x*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)P5xVIgh(4gM3Zjdy!n~2N zjD^FnHQ1(tR(9cJl^-l~RyvtO-;dMt9M4;+6T9$?ALpFs)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$~2W6jvjYwyv(OhW7UM zP7O5aPWUzq$A-}#e>#Hw16_xihIJroxfm&IbSiP6!~SxS;g5FTo6ZM`H( zlIh)&4}38nXc|&$DyX^!-nt?1)(-JKW(QQ%jr|ydxA>>z)7I8@S=`cW5N4N`m!G77 zdZMpERgp|rK~d3JRsUp;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+US~dit;|^yb25sIpdZA`Wys(O1dAvo2(I ziyc~u+*C?>Z*T8&(cem%afeVS6nDGb_L8EKvNL%#5MBx6)#tXj`d$yLwBMhA-vSH(T>k(8(cOU?00000NkvXX Hu0mjf8E% +// + 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 %] + + [% INCLUDE 'masthead.inc' %] @@ -11,7 +14,7 @@
    @@ -25,38 +28,57 @@

    Fines and charges

    + [% IF credits || debits %] + +

    +

    Account balance: [% borrower.account_balance | $Currency %]

    +

    + +
    +
    + View payments + + + + + + + + + + + + + + + + + +
    Fees
    IDDescriptionTypeAmountOutsandingCreated onUpdated on
    +
    - [% IF ( ACCOUNT_LINES ) %] - - - - - - - - - - - - - - - - - - - [% FOREACH ACCOUNT_LINE IN ACCOUNT_LINES %] - [% IF ( ACCOUNT_LINE.odd ) %][% ELSE %][% END %] - - - [% IF ( ACCOUNT_LINE.amountcredit ) %] - [% IF ( ACCOUNT_LINE.amountoutstandingcredit ) %] - - [% END %] - - -
    DateDescriptionFine amountAmount outstanding
    Total due[% total %]
    [% ACCOUNT_LINE.date | $KohaDates %][% ACCOUNT_LINE.description %] - [% IF ( ACCOUNT_LINE.title ) %][% ACCOUNT_LINE.title |html %][% END %][% ELSE %][% END %][% ACCOUNT_LINE.amount %][% ELSE %][% END %][% ACCOUNT_LINE.amountoutstanding %]
    +
    + View fees + + + + + + + + + + + + + + + + + +
    Payments
    IDNotesTypeAmountRemainingCreated onUpdated on
    +
    +
    [% ELSE %]

    You have no fines or charges

    [% END %] @@ -67,4 +89,299 @@
    [% INCLUDE 'opac-bottom.inc' %] -[% BLOCK jsinclude %][% END %] \ No newline at end of file +[% INCLUDE 'datatables.inc' %] + + + +[% 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)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%+2vP1rl3*$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!d$>Do3Jo15TlYl9m;-_3M7y&8+fGbP>p=udnZ^^3rY*Ry8&@-XZS}=H{ef zDUJ>}0_oCdYHA|eDvG0BC2ghK?XIQGd^|3d(Ko2a8%4c^+ z2RQuxqA|Bf6p=-Yhg81x*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)P5xVIgh(4gM3Zjdy!n~2N zjD^FnHQ1(tR(9cJl^-l~RyvtO-;dMt9M4;+6T9$?ALpFs)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$~2W6jvjYwyv(OhW7UM zP7O5aPWUzq$A-}#e>#Hw16_xihIJroxfm&IbSiP6!~SxS;g5FTo6ZM`H( zlIh)&4}38nXc|&$DyX^!-nt?1)(-JKW(QQ%jr|ydxA>>z)7I8@S=`cW5N4N`m!G77 zdZMpERgp|rK~d3JRsUp;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+US~dit;|^yb25sIpdZA`Wys(O1dAvo2(I ziyc~u+*C?>Z*T8&(cem%afeVS6nDGb_L8EKvNL%#5MBx6)#tXj`d$yLwBMhA-vSH(T>k(8(cOU?00000NkvXX Hu0mjf8E% +// + 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..215936c 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' %]
    -
    -[% INCLUDE 'masthead.inc' %] - +
    + [% INCLUDE 'masthead.inc' %]
    -
    -
    - - [% FOREACH BORROWER_INF IN BORROWER_INFO %] -

    [% BORROWER_INF.firstname %] [% BORROWER_INF.surname %]'s account ⇢ Fines and charges

    - [% END %] +
    +
    +
    +

    [% borrower.firstname %] [% borrower.surname %]'s account ⇢ Fines and charges

    - [% IF ( ACCOUNT_LINES ) %] - - - - - - - - - - - - - - - - - - - [% FOREACH ACCOUNT_LINE IN ACCOUNT_LINES %] - [% IF ( ACCOUNT_LINE.odd ) %][% ELSE %][% END %] - - - [% IF ( ACCOUNT_LINE.amountcredit ) %] - [% IF ( ACCOUNT_LINE.amountoutstandingcredit ) %] - - [% END %] - - -
    DateDescriptionFine amountAmount outstanding
    Total due[% total %]
    [% ACCOUNT_LINE.date | $KohaDates %][% ACCOUNT_LINE.description %] - [% IF ( ACCOUNT_LINE.title ) %][% ACCOUNT_LINE.title |html %][% END %][% ELSE %][% END %][% ACCOUNT_LINE.amount %][% ELSE %][% END %][% ACCOUNT_LINE.amountoutstanding %]
    - [% ELSE %] -

    You have no fines or charges

    - [% END %] -
    -
    -
    -
    -
    -
    -[% INCLUDE 'navigation.inc' IsPatronPage=1 %] -
    -
    + [% IF credits || debits %] + +

    +

    Account balance: [% borrower.account_balance | $Currency %]

    +

    + +
    +
    + View payments + + + + + + + + + + + + + + + + + +
    Fees
    IDDescriptionTypeAmountOutsandingCreated onUpdated on
    +
    + +
    + View fees + + + + + + + + + + + + + + + + + +
    Payments
    IDNotesTypeAmountRemainingCreated onUpdated on
    +
    +
    + [% ELSE %] +

    You have no fines or charges

    + [% END %] +
    +
    +
    +
    + +
    +
    + [% INCLUDE 'navigation.inc' IsPatronPage=1 %] +
    +
    [% INCLUDE 'opac-bottom.inc' %] + +[% INCLUDE 'datatables.inc' %] +[% INCLUDE 'browser-strings.inc' %] + + + +[% 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)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%+2vP1rl3*$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!d$>Do3Jo15TlYl9m;-_3M7y&8+fGbP>p=udnZ^^3rY*Ry8&@-XZS}=H{ef zDUJ>}0_oCdYHA|eDvG0BC2ghK?XIQGd^|3d(Ko2a8%4c^+ z2RQuxqA|Bf6p=-Yhg81x*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)P5xVIgh(4gM3Zjdy!n~2N zjD^FnHQ1(tR(9cJl^-l~RyvtO-;dMt9M4;+6T9$?ALpFs)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$~2W6jvjYwyv(OhW7UM zP7O5aPWUzq$A-}#e>#Hw16_xihIJroxfm&IbSiP6!~SxS;g5FTo6ZM`H( zlIh)&4}38nXc|&$DyX^!-nt?1)(-JKW(QQ%jr|ydxA>>z)7I8@S=`cW5N4N`m!G77 zdZMpERgp|rK~d3JRsUp;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+US~dit;|^yb25sIpdZA`Wys(O1dAvo2(I ziyc~u+*C?>Z*T8&(cem%afeVS6nDGb_L8EKvNL%#5MBx6)#tXj`d$yLwBMhA-vSH(T>k(8(cOU?00000NkvXX Hu0mjf8E% "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/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