Bugzilla – Attachment 22995 Details for
Bug 6427
Rewrite of the accounts system
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 6427 - Rewrite of the accounts system - WIP
Bug-6427---Rewrite-of-the-accounts-system---WIP.patch (text/plain), 240.78 KB, created by
Kyle M Hall
on 2013-11-18 14:16:33 UTC
(
hide
)
Description:
Bug 6427 - Rewrite of the accounts system - WIP
Filename:
MIME Type:
Creator:
Kyle M Hall
Created:
2013-11-18 14:16:33 UTC
Size:
240.78 KB
patch
obsolete
>From f2c108c325888dcd9f0e813e7024f54e635b8bb2 Mon Sep 17 00:00:00 2001 >From: Kyle M Hall <kyle@bywatersolutions.com> >Date: Wed, 9 Oct 2013 10:36:44 -0400 >Subject: [PATCH] Bug 6427 - Rewrite of the accounts system - WIP > >--- > C4/Circulation.pm | 311 ++++++------- > C4/Members.pm | 67 ++-- > C4/Overdues.pm | 219 ++++----- > C4/Reserves.pm | 22 +- > Koha/Accounts.pm | 515 ++++++++++++++++++++ > Koha/Accounts/CreditTypes.pm | 117 +++++ > Koha/Accounts/DebitTypes.pm | 160 ++++++ > Koha/Accounts/OffsetTypes.pm | 72 +++ > Koha/DateUtils.pm | 7 +- > Koha/Schema/Result/AccountCredit.pm | 140 ++++++ > 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 ++++ > installer/data/mysql/kohastructure.sql | 84 ++++ > installer/data/mysql/updatedatabase.pl | 80 +++ > .../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 | 419 ++++++++++++++++ > .../prog/en/modules/members/account_credit.tt | 92 ++++ > .../prog/en/modules/members/account_debit.tt | 109 ++++ > .../prog/en/modules/members/account_payment.tt | 201 ++++++++ > .../prog/en/modules/members/account_print.tt | 136 +++++ > .../prog/en/modules/members/boraccount.tt | 12 +- > .../prog/en/modules/members/mancredit.tt | 12 +- > .../prog/en/modules/members/maninvoice.tt | 12 +- > .../intranet-tmpl/prog/en/modules/members/pay.tt | 12 +- > .../prog/en/modules/members/paycollect.tt | 18 +- > 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 > .../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/modules/opac-account.tt | 424 ++++++++++++++-- > 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 | 113 +++++ > members/account_credit.pl | 104 ++++ > members/account_credit_do.pl | 68 +++ > members/account_debit.pl | 104 ++++ > members/account_debit_do.pl | 69 +++ > members/account_payment.pl | 123 +++++ > members/account_payment_do.pl | 62 +++ > members/account_print.pl | 58 +++ > members/mancredit.pl | 2 +- > members/maninvoice.pl | 2 +- > members/pay.pl | 4 +- > members/paycollect.pl | 4 +- > members/printfeercpt.pl | 2 +- > members/printinvoice.pl | 2 +- > 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 | 49 +-- > t/db_dependent/Accounts.t | 189 +++++++- > t/db_dependent/Circulation.t | 22 +- > 63 files changed, 4660 insertions(+), 684 deletions(-) > 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 > 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/images/details_close.png > create mode 100644 koha-tmpl/opac-tmpl/bootstrap/images/details_open.png > 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 > >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/Members.pm b/C4/Members.pm >index b04cc64..387ee89 100644 >--- a/C4/Members.pm >+++ b/C4/Members.pm >@@ -41,6 +41,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); > >@@ -338,9 +339,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 +430,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 +686,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]; > >@@ -1216,8 +1211,8 @@ sub GetMemberAccountRecords { > 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 +1220,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..58aca1a 100644 >--- a/C4/Overdues.pm >+++ b/C4/Overdues.pm >@@ -28,6 +28,8 @@ 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); > >@@ -456,154 +458,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 >@@ -804,6 +764,7 @@ sub GetOverduesForBranch { > biblio.title, > biblio.author, > biblio.biblionumber, >+ issues.issue_id, > issues.date_due, > issues.returndate, > issues.branchcode, >diff --git a/C4/Reserves.pm b/C4/Reserves.pm >index d1bca25..3b8e77b 100644 >--- a/C4/Reserves.pm >+++ b/C4/Reserves.pm >@@ -172,19 +172,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/Koha/Accounts.pm b/Koha/Accounts.pm >new file mode 100644 >index 0000000..7cb0a80 >--- /dev/null >+++ b/Koha/Accounts.pm >@@ -0,0 +1,515 @@ >+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(), accruing => $accruing } ) ); >+ } >+ } >+ 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 $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_paid => $amount, >+ amount_remaining => $amount, >+ notes => $notes, >+ manager_id => $manager_id, >+ created_on => get_timestamp(), >+ } >+ ); >+ >+ $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(), >+ } >+ ); >+ >+ return $offset; >+ } >+} >+ >+=head2 RecalculateAccountBalance >+ >+$account_balance = RecalculateAccountBalance({ >+ borrower => $borrower >+}); >+ >+Recalculates a borrower's balance based on the >+sum of the amount outstanding for the borrower's >+debits minus the sum of the amount remaining for >+the borrowers credits. >+ >+TODO: Would it be better to use af.amount_original - ap.amount_paid for any reason? >+ Or, perhaps calculate both and compare the two, for error checking purposes. >+=cut >+ >+sub RecalculateAccountBalance { >+ my ($params) = @_; >+ >+ my $borrower = $params->{borrower}; >+ croak("Requred paramter 'borrower' not passed in!") >+ unless ($borrower); >+ >+ my $debits = >+ Koha::Database->new()->schema->resultset('AccountDebit') >+ ->search( { borrowernumber => $borrower->borrowernumber() } ); >+ my $amount_outstanding = $debits->get_column('amount_outstanding')->sum(); >+ >+ my $credits = >+ Koha::Database->new()->schema->resultset('AccountCredit') >+ ->search( { borrowernumber => $borrower->borrowernumber() } ); >+ my $amount_remaining = $credits->get_column('amount_remaining')->sum(); >+ >+ my $account_balance = $amount_outstanding - $amount_remaining; >+ $borrower->account_balance($account_balance); >+ $borrower->update(); >+ >+ return $account_balance; >+} >+ >+=head2 NormalizeBalances >+ >+ $account_balance = NormalizeBalances({ borrower => $borrower }); >+ >+ For a given borrower, this subroutine will find all debits >+ with an outstanding balance and all credits with an unused >+ amount remaining and will pay those debits with those credits. >+ >+=cut >+ >+sub NormalizeBalances { >+ my ($params) = @_; >+ >+ my $borrower = $params->{borrower}; >+ >+ croak("Required param 'borrower' not passed in!") unless $borrower; >+ >+ my @credits = Koha::Database->new()->schema->resultset('AccountCredit')->search( >+ { >+ borrowernumber => $borrower->borrowernumber(), >+ amount_remaining => { '>' => '0' } >+ } >+ ); >+ >+ return unless @credits; >+ >+ my @debits = Koha::Database->new()->schema->resultset('AccountDebit')->search( >+ { >+ borrowernumber => $borrower->borrowernumber(), >+ amount_outstanding => { '>' => '0' } >+ } >+ ); >+ >+ return unless @debits; >+ >+ foreach my $credit (@credits) { >+ foreach my $debit (@debits) { >+ if ( $credit->amount_remaining() >+ && $debit->amount_outstanding() ) >+ { >+ CreditDebit( { credit => $credit, debit => $debit } ); >+ } >+ } >+ } >+ >+ return RecalculateAccountBalance( { borrower => $borrower } ); >+} >+ >+1; >+__END__ >+ >+=head1 AUTHOR >+ >+Kyle M Hall <kyle@bywatersolutions.com> >+ >+=cut >diff --git a/Koha/Accounts/CreditTypes.pm b/Koha/Accounts/CreditTypes.pm >new file mode 100644 >index 0000000..d51ec93 >--- /dev/null >+++ b/Koha/Accounts/CreditTypes.pm >@@ -0,0 +1,117 @@ >+package Koha::Accounts::CreditTypes; >+ >+# Copyright 2013 ByWater Solutions >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it under the >+# terms of the GNU General Public License as published by the Free Software >+# Foundation; either version 2 of the License, or (at your option) any later >+# version. >+# >+# Koha is distributed in the hope that it will be useful, but WITHOUT ANY >+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR >+# A PARTICULAR PURPOSE. See the GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License along >+# with Koha; if not, write to the Free Software Foundation, Inc., >+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. >+ >+use Modern::Perl; >+ >+=head1 NAME >+ >+Koha::AccountsCreditTypes - Module representing the enumerated data types for account fees >+ >+=head1 SYNOPSIS >+ >+use Koha::Accounts::CreditTypes; >+ >+my $type = Koha::Accounts::CreditTypes::Payment; >+ >+=head1 DESCRIPTION >+ >+The subroutines in this modules act as enumerated data types for the >+different credit types in Koha ( i.e. payments, writeoffs, etc. ) >+ >+=head1 FUNCTIONS >+ >+=head2 IsValid >+ >+This subroutine takes a given string and returns 1 if >+the string matches one of the data types, and 0 if not. >+ >+FIXME: Perhaps we should use Class::Inspector instead of hard >+coding the subs? It seems like it would be a major trade off >+of speed just so we don't update something in two separate places >+in the same file. >+ >+=cut >+ >+sub IsValid { >+ my ($string) = @_; >+ >+ my $is_valid = >+ ( $string eq Koha::Accounts::CreditTypes::Payment() >+ || $string eq Koha::Accounts::CreditTypes::WriteOff() >+ || $string eq Koha::Accounts::CreditTypes::Found() >+ || $string eq Koha::Accounts::CreditTypes::Credit() >+ || $string eq Koha::Accounts::CreditTypes::Forgiven() ); >+ >+ unless ($is_valid) { >+ $is_valid = >+ Koha::Database->new()->schema->resultset('AuthorisedValue') >+ ->count( >+ { category => 'ACCOUNT_CREDIT', authorised_value => $string } ); >+ } >+ >+ return $is_valid; >+} >+ >+=head2 Credit >+ >+=cut >+ >+sub Credit { >+ return 'CREDIT'; >+} >+ >+=head2 Payment >+ >+=cut >+ >+sub Payment { >+ return 'PAYMENT'; >+} >+ >+=head2 Writeoff >+ >+=cut >+ >+sub WriteOff { >+ return 'WRITEOFF'; >+} >+ >+=head2 Writeoff >+ >+=cut >+ >+sub Found { >+ return 'FOUND'; >+} >+ >+=head2 Forgiven >+ >+=cut >+ >+sub Forgiven { >+ return 'FORGIVEN'; >+} >+ >+1; >+ >+=head1 AUTHOR >+ >+Kyle M Hall <kyle@bywatersolutions.com> >+ >+=cut >diff --git a/Koha/Accounts/DebitTypes.pm b/Koha/Accounts/DebitTypes.pm >new file mode 100644 >index 0000000..3f30392 >--- /dev/null >+++ b/Koha/Accounts/DebitTypes.pm >@@ -0,0 +1,160 @@ >+package Koha::Accounts::DebitTypes; >+ >+# Copyright 2013 ByWater Solutions >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it under the >+# terms of the GNU General Public License as published by the Free Software >+# Foundation; either version 2 of the License, or (at your option) any later >+# version. >+# >+# Koha is distributed in the hope that it will be useful, but WITHOUT ANY >+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR >+# A PARTICULAR PURPOSE. See the GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License along >+# with Koha; if not, write to the Free Software Foundation, Inc., >+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. >+ >+use Modern::Perl; >+ >+=head1 NAME >+ >+Koha::Accounts::DebitTypes - Module representing an enumerated data type for account fees >+ >+=head1 SYNOPSIS >+ >+use Koha::Accounts::DebitTypes; >+ >+my $type = Koha::Accounts::DebitTypes::Fine; >+ >+=head1 DESCRIPTION >+ >+The subroutines in this modules act as an enumerated data type >+for debit types ( stored in account_debits.type ) in Koha. >+ >+=head1 FUNCTIONS >+ >+=head2 IsValid >+ >+This subroutine takes a given string and returns 1 if >+the string matches one of the data types, and 0 if not. >+ >+=cut >+ >+sub IsValid { >+ my ($string) = @_; >+ >+ my $is_valid = >+ ( $string eq Koha::Accounts::DebitTypes::Fine() >+ || $string eq Koha::Accounts::DebitTypes::AccountManagementFee() >+ || $string eq Koha::Accounts::DebitTypes::Sundry() >+ || $string eq Koha::Accounts::DebitTypes::Lost() >+ || $string eq Koha::Accounts::DebitTypes::Hold() >+ || $string eq Koha::Accounts::DebitTypes::Rental() >+ || $string eq Koha::Accounts::DebitTypes::NewCard() ); >+ >+ unless ($is_valid) { >+ $is_valid = >+ Koha::Database->new()->schema->resultset('AuthorisedValue') >+ ->count( { category => 'MANUAL_INV', authorised_value => $string } ); >+ } >+ >+ return $is_valid; >+} >+ >+=head2 Fine >+ >+This data type represents a standard fine within Koha. >+ >+A fine still accruing no longer needs to be differiated by type >+from a fine done accuring. Instead, that differentication is made >+by which table the fine exists in, account_fees_accruing vs account_fees_accrued. >+ >+In addition, fines can be checked for correctness based on the issue_id >+they have. A fine in account_fees_accruing should always have a matching >+issue_id in the issues table. A fine done accruing will almost always have >+a matching issue_id in the old_issues table. However, in the case of an overdue >+item with fines that has been renewed, and becomes overdue again, you may have >+a case where a given issue may have a matching fine in account_fees_accruing and >+one or more matching fines in account_fees_accrued ( one for each for the first >+checkout and one each for any subsequent renewals ) >+ >+=cut >+ >+sub Fine { >+ return 'FINE'; >+} >+ >+=head2 AccountManagementFee >+ >+This fee type is usually reserved for payments for library cards, >+in cases where a library must charge a patron for the ability to >+check out items. >+ >+=cut >+ >+sub AccountManagementFee { >+ return 'ACCOUNT_MANAGEMENT_FEE'; >+} >+ >+=head2 Sundry >+ >+This fee type is basically a 'misc' type, and should be used >+when no other fee type is more appropriate. >+ >+=cut >+ >+sub Sundry { >+ return 'SUNDRY'; >+} >+ >+=head2 Lost >+ >+This fee type is used when a library charges for lost items. >+ >+=cut >+ >+sub Lost { >+ return 'LOST'; >+} >+ >+=head2 Hold >+ >+This fee type is used when a library charges for holds. >+ >+=cut >+ >+sub Hold { >+ return 'HOLD'; >+} >+ >+=head2 Rental >+ >+This fee type is used when a library charges a rental fee for the item type. >+ >+=cut >+ >+sub Rental { >+ return 'RENTAL'; >+} >+ >+=head2 NewCard >+ >+This fee type is used when a library charges for replacement >+library cards. >+ >+=cut >+ >+sub NewCard { >+ return 'NEW_CARD'; >+} >+ >+1; >+ >+=head1 AUTHOR >+ >+Kyle M Hall <kyle@bywatersolutions.com> >+ >+=cut >diff --git a/Koha/Accounts/OffsetTypes.pm b/Koha/Accounts/OffsetTypes.pm >new file mode 100644 >index 0000000..1a5aabb >--- /dev/null >+++ b/Koha/Accounts/OffsetTypes.pm >@@ -0,0 +1,72 @@ >+package Koha::Accounts::OffsetTypes; >+ >+# Copyright 2013 ByWater Solutions >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it under the >+# terms of the GNU General Public License as published by the Free Software >+# Foundation; either version 2 of the License, or (at your option) any later >+# version. >+# >+# Koha is distributed in the hope that it will be useful, but WITHOUT ANY >+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR >+# A PARTICULAR PURPOSE. See the GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License along >+# with Koha; if not, write to the Free Software Foundation, Inc., >+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. >+ >+use Modern::Perl; >+ >+=head1 NAME >+ >+Koha::AccountsOffsetTypes - Module representing the enumerated data types for account fees >+ >+=head1 SYNOPSIS >+ >+use Koha::Accounts::OffsetTypes; >+ >+my $type = Koha::Accounts::OffsetTypes::Dropbox; >+ >+=head1 DESCRIPTION >+ >+The subroutines in this modules act as enumerated data types for the >+different automatic offset types in Koha ( i.e. forgiveness, dropbox mode, etc ) >+ >+These types are used for account offsets that have no corrosponding account credit, >+e.g. automatic fine increments, dropbox mode, etc. >+ >+=head1 FUNCTIONS >+ >+=cut >+ >+=head2 Dropbox >+ >+Offset type for automatic fine reductions >+via dropbox mode. >+ >+=cut >+ >+sub Dropbox { >+ return 'DROPBOX'; >+} >+ >+=head2 Fine >+ >+Indicates this offset was an automatically >+generated fine increment/decrement. >+ >+=cut >+ >+sub Fine { >+ return 'FINE'; >+} >+ >+1; >+ >+=head1 AUTHOR >+ >+Kyle M Hall <kyle@bywatersolutions.com> >+ >+=cut >diff --git a/Koha/DateUtils.pm b/Koha/DateUtils.pm >index 4ae0d0c..6dbc979 100644 >--- a/Koha/DateUtils.pm >+++ b/Koha/DateUtils.pm >@@ -21,13 +21,14 @@ use warnings; > use 5.010; > use DateTime; > use DateTime::Format::DateParse; >+use DateTime::Format::MySQL; > use C4::Context; > > use base 'Exporter'; > use version; our $VERSION = qv('1.0.0'); > > our @EXPORT = ( >- qw( dt_from_string output_pref format_sqldatetime output_pref_due format_sqlduedatetime) >+ qw( dt_from_string output_pref format_sqldatetime output_pref_due format_sqlduedatetime get_timestamp ) > ); > > =head1 DateUtils >@@ -239,4 +240,8 @@ sub format_sqlduedatetime { > return q{}; > } > >+sub get_timestamp { >+ return DateTime::Format::MySQL->format_datetime( dt_from_string() ); >+} >+ > 1; >diff --git a/Koha/Schema/Result/AccountCredit.pm b/Koha/Schema/Result/AccountCredit.pm >new file mode 100644 >index 0000000..df612ff >--- /dev/null >+++ b/Koha/Schema/Result/AccountCredit.pm >@@ -0,0 +1,140 @@ >+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_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_paid", >+ { data_type => "decimal", is_nullable => 0, size => [28, 6] }, >+ "amount_remaining", >+ { data_type => "decimal", is_nullable => 0, size => [28, 6] }, >+ "notes", >+ { data_type => "text", is_nullable => 1 }, >+ "manager_id", >+ { data_type => "integer", is_nullable => 1 }, >+ "created_on", >+ { data_type => "timestamp", is_nullable => 1 }, >+ "updated_on", >+ { data_type => "timestamp", is_nullable => 1 }, >+); >+__PACKAGE__->set_primary_key("credit_id"); >+ >+=head1 RELATIONS >+ >+=head2 borrowernumber >+ >+Type: belongs_to >+ >+Related object: L<Koha::Schema::Result::Borrower> >+ >+=cut >+ >+__PACKAGE__->belongs_to( >+ "borrowernumber", >+ "Koha::Schema::Result::Borrower", >+ { borrowernumber => "borrowernumber" }, >+ { on_delete => "CASCADE", on_update => "CASCADE" }, >+); >+ >+=head2 account_offsets >+ >+Type: has_many >+ >+Related object: L<Koha::Schema::Result::AccountOffset> >+ >+=cut >+ >+__PACKAGE__->has_many( >+ "account_offsets", >+ "Koha::Schema::Result::AccountOffset", >+ { "foreign.credit_id" => "self.credit_id" }, >+ { cascade_copy => 0, cascade_delete => 0 }, >+); >+ >+ >+# Created by DBIx::Class::Schema::Loader v0.07000 @ 2013-10-09 10:37:23 >+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:uvt4OuaJxv4jk08zJsKouw >+ >+__PACKAGE__->belongs_to( >+ "borrower", >+ "Koha::Schema::Result::Borrower", >+ { borrowernumber => "borrowernumber" }, >+); >+ >+ >+# You can replace this text with custom content, and it will be preserved on regeneration >+1; >diff --git a/Koha/Schema/Result/AccountDebit.pm b/Koha/Schema/Result/AccountDebit.pm >new file mode 100644 >index 0000000..e57347d >--- /dev/null >+++ b/Koha/Schema/Result/AccountDebit.pm >@@ -0,0 +1,207 @@ >+package Koha::Schema::Result::AccountDebit; >+ >+# Created by DBIx::Class::Schema::Loader >+# DO NOT MODIFY THE FIRST PART OF THIS FILE >+ >+use strict; >+use warnings; >+ >+use base 'DBIx::Class::Core'; >+ >+ >+=head1 NAME >+ >+Koha::Schema::Result::AccountDebit >+ >+=cut >+ >+__PACKAGE__->table("account_debits"); >+ >+=head1 ACCESSORS >+ >+=head2 debit_id >+ >+ data_type: 'integer' >+ is_auto_increment: 1 >+ is_nullable: 0 >+ >+=head2 borrowernumber >+ >+ data_type: 'integer' >+ default_value: 0 >+ is_foreign_key: 1 >+ is_nullable: 0 >+ >+=head2 itemnumber >+ >+ data_type: 'integer' >+ is_nullable: 1 >+ >+=head2 issue_id >+ >+ data_type: 'integer' >+ is_nullable: 1 >+ >+=head2 type >+ >+ data_type: 'varchar' >+ is_nullable: 0 >+ size: 255 >+ >+=head2 accruing >+ >+ data_type: 'tinyint' >+ default_value: 0 >+ is_nullable: 0 >+ >+=head2 amount_original >+ >+ data_type: 'decimal' >+ is_nullable: 1 >+ size: [28,6] >+ >+=head2 amount_outstanding >+ >+ data_type: 'decimal' >+ is_nullable: 1 >+ size: [28,6] >+ >+=head2 amount_last_increment >+ >+ data_type: 'decimal' >+ is_nullable: 1 >+ size: [28,6] >+ >+=head2 description >+ >+ data_type: 'mediumtext' >+ is_nullable: 1 >+ >+=head2 notes >+ >+ data_type: 'text' >+ is_nullable: 1 >+ >+=head2 manager_id >+ >+ data_type: 'integer' >+ is_nullable: 1 >+ >+=head2 created_on >+ >+ data_type: 'timestamp' >+ is_nullable: 1 >+ >+=head2 updated_on >+ >+ data_type: 'timestamp' >+ is_nullable: 1 >+ >+=cut >+ >+__PACKAGE__->add_columns( >+ "debit_id", >+ { data_type => "integer", is_auto_increment => 1, is_nullable => 0 }, >+ "borrowernumber", >+ { >+ data_type => "integer", >+ default_value => 0, >+ is_foreign_key => 1, >+ is_nullable => 0, >+ }, >+ "itemnumber", >+ { data_type => "integer", is_nullable => 1 }, >+ "issue_id", >+ { data_type => "integer", is_nullable => 1 }, >+ "type", >+ { data_type => "varchar", is_nullable => 0, size => 255 }, >+ "accruing", >+ { data_type => "tinyint", default_value => 0, is_nullable => 0 }, >+ "amount_original", >+ { data_type => "decimal", is_nullable => 1, size => [28, 6] }, >+ "amount_outstanding", >+ { data_type => "decimal", is_nullable => 1, size => [28, 6] }, >+ "amount_last_increment", >+ { data_type => "decimal", is_nullable => 1, size => [28, 6] }, >+ "description", >+ { data_type => "mediumtext", is_nullable => 1 }, >+ "notes", >+ { data_type => "text", is_nullable => 1 }, >+ "manager_id", >+ { data_type => "integer", is_nullable => 1 }, >+ "created_on", >+ { data_type => "timestamp", is_nullable => 1 }, >+ "updated_on", >+ { data_type => "timestamp", is_nullable => 1 }, >+); >+__PACKAGE__->set_primary_key("debit_id"); >+ >+=head1 RELATIONS >+ >+=head2 borrowernumber >+ >+Type: belongs_to >+ >+Related object: L<Koha::Schema::Result::Borrower> >+ >+=cut >+ >+__PACKAGE__->belongs_to( >+ "borrowernumber", >+ "Koha::Schema::Result::Borrower", >+ { borrowernumber => "borrowernumber" }, >+ { on_delete => "CASCADE", on_update => "CASCADE" }, >+); >+ >+=head2 account_offsets >+ >+Type: has_many >+ >+Related object: L<Koha::Schema::Result::AccountOffset> >+ >+=cut >+ >+__PACKAGE__->has_many( >+ "account_offsets", >+ "Koha::Schema::Result::AccountOffset", >+ { "foreign.debit_id" => "self.debit_id" }, >+ { cascade_copy => 0, cascade_delete => 0 }, >+); >+ >+ >+# Created by DBIx::Class::Schema::Loader v0.07000 @ 2013-11-05 08:09:09 >+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ulQStZJSzcD4hvrPbtew4g >+ >+__PACKAGE__->belongs_to( >+ "item", >+ "Koha::Schema::Result::Item", >+ { itemnumber => "itemnumber" } >+); >+ >+__PACKAGE__->belongs_to( >+ "deleted_item", >+ "Koha::Schema::Result::Deleteditem", >+ { itemnumber => "itemnumber" } >+); >+ >+__PACKAGE__->belongs_to( >+ "issue", >+ "Koha::Schema::Result::Issue", >+ { issue_id => "issue_id" } >+); >+ >+__PACKAGE__->belongs_to( >+ "old_issue", >+ "Koha::Schema::Result::OldIssue", >+ { issue_id => "issue_id" } >+); >+ >+__PACKAGE__->belongs_to( >+ "borrower", >+ "Koha::Schema::Result::Borrower", >+ { borrowernumber => "borrowernumber" }, >+ { on_delete => "CASCADE", on_update => "CASCADE" }, >+); >+ >+# You can replace this text with custom content, and it will be preserved on regeneration >+1; >diff --git a/Koha/Schema/Result/AccountOffset.pm b/Koha/Schema/Result/AccountOffset.pm >new file mode 100644 >index 0000000..179392f >--- /dev/null >+++ b/Koha/Schema/Result/AccountOffset.pm >@@ -0,0 +1,118 @@ >+package Koha::Schema::Result::AccountOffset; >+ >+# Created by DBIx::Class::Schema::Loader >+# DO NOT MODIFY THE FIRST PART OF THIS FILE >+ >+use strict; >+use warnings; >+ >+use base 'DBIx::Class::Core'; >+ >+ >+=head1 NAME >+ >+Koha::Schema::Result::AccountOffset >+ >+=cut >+ >+__PACKAGE__->table("account_offsets"); >+ >+=head1 ACCESSORS >+ >+=head2 offset_id >+ >+ data_type: 'integer' >+ is_auto_increment: 1 >+ is_nullable: 0 >+ >+=head2 debit_id >+ >+ data_type: 'integer' >+ is_foreign_key: 1 >+ is_nullable: 1 >+ >+=head2 credit_id >+ >+ data_type: 'integer' >+ is_foreign_key: 1 >+ is_nullable: 1 >+ >+=head2 type >+ >+ data_type: 'varchar' >+ is_nullable: 1 >+ size: 255 >+ >+=head2 amount >+ >+ data_type: 'decimal' >+ is_nullable: 0 >+ size: [28,6] >+ >+=head2 created_on >+ >+ data_type: 'timestamp' >+ default_value: current_timestamp >+ is_nullable: 0 >+ >+=cut >+ >+__PACKAGE__->add_columns( >+ "offset_id", >+ { data_type => "integer", is_auto_increment => 1, is_nullable => 0 }, >+ "debit_id", >+ { data_type => "integer", is_foreign_key => 1, is_nullable => 1 }, >+ "credit_id", >+ { data_type => "integer", is_foreign_key => 1, is_nullable => 1 }, >+ "type", >+ { data_type => "varchar", is_nullable => 1, size => 255 }, >+ "amount", >+ { data_type => "decimal", is_nullable => 0, size => [28, 6] }, >+ "created_on", >+ { >+ data_type => "timestamp", >+ default_value => \"current_timestamp", >+ is_nullable => 0, >+ }, >+); >+__PACKAGE__->set_primary_key("offset_id"); >+ >+=head1 RELATIONS >+ >+=head2 debit >+ >+Type: belongs_to >+ >+Related object: L<Koha::Schema::Result::AccountDebit> >+ >+=cut >+ >+__PACKAGE__->belongs_to( >+ "debit", >+ "Koha::Schema::Result::AccountDebit", >+ { debit_id => "debit_id" }, >+ { join_type => "LEFT", on_delete => "CASCADE", on_update => "CASCADE" }, >+); >+ >+=head2 credit >+ >+Type: belongs_to >+ >+Related object: L<Koha::Schema::Result::AccountCredit> >+ >+=cut >+ >+__PACKAGE__->belongs_to( >+ "credit", >+ "Koha::Schema::Result::AccountCredit", >+ { credit_id => "credit_id" }, >+ { join_type => "LEFT", on_delete => "CASCADE", on_update => "CASCADE" }, >+); >+ >+ >+# Created by DBIx::Class::Schema::Loader v0.07000 @ 2013-11-05 08:47:10 >+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:BLjpL8skXmzxOQ/J0jzdvw >+ >+ >+# You can replace this text with custom content, and it will be preserved on regeneration >+1; >diff --git a/Koha/Schema/Result/Borrower.pm b/Koha/Schema/Result/Borrower.pm >index 3d9f9ae..580bbec 100644 >--- a/Koha/Schema/Result/Borrower.pm >+++ b/Koha/Schema/Result/Borrower.pm >@@ -1,21 +1,17 @@ >-use utf8; > package Koha::Schema::Result::Borrower; > > # Created by DBIx::Class::Schema::Loader > # DO NOT MODIFY THE FIRST PART OF THIS FILE > >-=head1 NAME >- >-Koha::Schema::Result::Borrower >- >-=cut >- > use strict; > use warnings; > > use base 'DBIx::Class::Core'; > >-=head1 TABLE: C<borrowers> >+ >+=head1 NAME >+ >+Koha::Schema::Result::Borrower > > =cut > >@@ -191,7 +187,6 @@ __PACKAGE__->table("borrowers"); > =head2 dateofbirth > > data_type: 'date' >- datetime_undef_if_invalid: 1 > is_nullable: 1 > > =head2 branchcode >@@ -213,13 +208,11 @@ __PACKAGE__->table("borrowers"); > =head2 dateenrolled > > data_type: 'date' >- datetime_undef_if_invalid: 1 > is_nullable: 1 > > =head2 dateexpiry > > data_type: 'date' >- datetime_undef_if_invalid: 1 > is_nullable: 1 > > =head2 gonenoaddress >@@ -235,7 +228,6 @@ __PACKAGE__->table("borrowers"); > =head2 debarred > > data_type: 'date' >- datetime_undef_if_invalid: 1 > is_nullable: 1 > > =head2 debarredcomment >@@ -397,6 +389,13 @@ __PACKAGE__->table("borrowers"); > default_value: 1 > is_nullable: 0 > >+=head2 account_balance >+ >+ data_type: 'decimal' >+ default_value: 0.000000 >+ is_nullable: 0 >+ size: [28,6] >+ > =cut > > __PACKAGE__->add_columns( >@@ -463,7 +462,7 @@ __PACKAGE__->add_columns( > "b_phone", > { data_type => "mediumtext", is_nullable => 1 }, > "dateofbirth", >- { data_type => "date", datetime_undef_if_invalid => 1, is_nullable => 1 }, >+ { data_type => "date", is_nullable => 1 }, > "branchcode", > { > data_type => "varchar", >@@ -481,15 +480,15 @@ __PACKAGE__->add_columns( > size => 10, > }, > "dateenrolled", >- { data_type => "date", datetime_undef_if_invalid => 1, is_nullable => 1 }, >+ { data_type => "date", is_nullable => 1 }, > "dateexpiry", >- { data_type => "date", datetime_undef_if_invalid => 1, is_nullable => 1 }, >+ { data_type => "date", is_nullable => 1 }, > "gonenoaddress", > { data_type => "tinyint", is_nullable => 1 }, > "lost", > { data_type => "tinyint", is_nullable => 1 }, > "debarred", >- { data_type => "date", datetime_undef_if_invalid => 1, is_nullable => 1 }, >+ { data_type => "date", is_nullable => 1 }, > "debarredcomment", > { data_type => "varchar", is_nullable => 1, size => 255 }, > "contactname", >@@ -546,35 +545,48 @@ __PACKAGE__->add_columns( > { data_type => "varchar", is_nullable => 1, size => 50 }, > "privacy", > { data_type => "integer", default_value => 1, is_nullable => 0 }, >+ "account_balance", >+ { >+ data_type => "decimal", >+ default_value => "0.000000", >+ is_nullable => 0, >+ size => [28, 6], >+ }, > ); >+__PACKAGE__->set_primary_key("borrowernumber"); >+__PACKAGE__->add_unique_constraint("cardnumber", ["cardnumber"]); > >-=head1 PRIMARY KEY >+=head1 RELATIONS > >-=over 4 >+=head2 account_credits > >-=item * L</borrowernumber> >+Type: has_many > >-=back >+Related object: L<Koha::Schema::Result::AccountCredit> > > =cut > >-__PACKAGE__->set_primary_key("borrowernumber"); >- >-=head1 UNIQUE CONSTRAINTS >- >-=head2 C<cardnumber> >+__PACKAGE__->has_many( >+ "account_credits", >+ "Koha::Schema::Result::AccountCredit", >+ { "foreign.borrowernumber" => "self.borrowernumber" }, >+ { cascade_copy => 0, cascade_delete => 0 }, >+); > >-=over 4 >+=head2 account_debits > >-=item * L</cardnumber> >+Type: has_many > >-=back >+Related object: L<Koha::Schema::Result::AccountDebit> > > =cut > >-__PACKAGE__->add_unique_constraint("cardnumber", ["cardnumber"]); >- >-=head1 RELATIONS >+__PACKAGE__->has_many( >+ "account_debits", >+ "Koha::Schema::Result::AccountDebit", >+ { "foreign.borrowernumber" => "self.borrowernumber" }, >+ { cascade_copy => 0, cascade_delete => 0 }, >+); > > =head2 accountlines > >@@ -696,34 +708,34 @@ __PACKAGE__->has_many( > { cascade_copy => 0, cascade_delete => 0 }, > ); > >-=head2 branchcode >+=head2 categorycode > > Type: belongs_to > >-Related object: L<Koha::Schema::Result::Branch> >+Related object: L<Koha::Schema::Result::Category> > > =cut > > __PACKAGE__->belongs_to( >- "branchcode", >- "Koha::Schema::Result::Branch", >- { branchcode => "branchcode" }, >- { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" }, >+ "categorycode", >+ "Koha::Schema::Result::Category", >+ { categorycode => "categorycode" }, >+ { on_delete => "CASCADE", on_update => "CASCADE" }, > ); > >-=head2 categorycode >+=head2 branchcode > > Type: belongs_to > >-Related object: L<Koha::Schema::Result::Category> >+Related object: L<Koha::Schema::Result::Branch> > > =cut > > __PACKAGE__->belongs_to( >- "categorycode", >- "Koha::Schema::Result::Category", >- { categorycode => "categorycode" }, >- { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" }, >+ "branchcode", >+ "Koha::Schema::Result::Branch", >+ { branchcode => "branchcode" }, >+ { on_delete => "CASCADE", on_update => "CASCADE" }, > ); > > =head2 course_instructors >@@ -1041,40 +1053,15 @@ __PACKAGE__->has_many( > { cascade_copy => 0, cascade_delete => 0 }, > ); > >-=head2 basketnoes >- >-Type: many_to_many >- >-Composing rels: L</aqbasketusers> -> basketno >- >-=cut >- >-__PACKAGE__->many_to_many("basketnoes", "aqbasketusers", "basketno"); >- >-=head2 budgets >- >-Type: many_to_many >- >-Composing rels: L</aqbudgetborrowers> -> budget >- >-=cut >- >-__PACKAGE__->many_to_many("budgets", "aqbudgetborrowers", "budget"); >- >-=head2 courses >- >-Type: many_to_many > >-Composing rels: L</course_instructors> -> course >- >-=cut >- >-__PACKAGE__->many_to_many("courses", "course_instructors", "course"); >- >- >-# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-10-31 16:31:19 >-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:z4kW3xYX1CyrwvGdZu32nA >+# Created by DBIx::Class::Schema::Loader v0.07000 @ 2013-11-12 08:27:25 >+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:CcXsGi7pVHQtO+YH3pY/1A > >+__PACKAGE__->belongs_to( >+ "branch", >+ "Koha::Schema::Result::Branch", >+ { branchcode => "branchcode" }, >+); > > # You can replace this text with custom content, and it will be preserved on regeneration > 1; >diff --git a/Koha/Schema/Result/Deleteditem.pm b/Koha/Schema/Result/Deleteditem.pm >index 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<issues> >+ >+=head1 NAME >+ >+Koha::Schema::Result::Issue > > =cut > >@@ -23,6 +19,12 @@ __PACKAGE__->table("issues"); > > =head1 ACCESSORS > >+=head2 issue_id >+ >+ data_type: 'integer' >+ is_auto_increment: 1 >+ is_nullable: 0 >+ > =head2 borrowernumber > > data_type: 'integer' >@@ -38,7 +40,6 @@ __PACKAGE__->table("issues"); > =head2 date_due > > data_type: 'datetime' >- datetime_undef_if_invalid: 1 > is_nullable: 1 > > =head2 branchcode >@@ -56,13 +57,11 @@ __PACKAGE__->table("issues"); > =head2 returndate > > data_type: 'datetime' >- datetime_undef_if_invalid: 1 > is_nullable: 1 > > =head2 lastreneweddate > > data_type: 'datetime' >- datetime_undef_if_invalid: 1 > is_nullable: 1 > > =head2 return >@@ -79,63 +78,47 @@ __PACKAGE__->table("issues"); > =head2 timestamp > > data_type: 'timestamp' >- datetime_undef_if_invalid: 1 > default_value: current_timestamp > is_nullable: 0 > > =head2 issuedate > > data_type: 'datetime' >- datetime_undef_if_invalid: 1 > is_nullable: 1 > > =cut > > __PACKAGE__->add_columns( >+ "issue_id", >+ { data_type => "integer", is_auto_increment => 1, is_nullable => 0 }, > "borrowernumber", > { data_type => "integer", is_foreign_key => 1, is_nullable => 1 }, > "itemnumber", > { data_type => "integer", is_foreign_key => 1, is_nullable => 1 }, > "date_due", >- { >- data_type => "datetime", >- datetime_undef_if_invalid => 1, >- is_nullable => 1, >- }, >+ { data_type => "datetime", is_nullable => 1 }, > "branchcode", > { data_type => "varchar", is_nullable => 1, size => 10 }, > "issuingbranch", > { data_type => "varchar", is_nullable => 1, size => 18 }, > "returndate", >- { >- data_type => "datetime", >- datetime_undef_if_invalid => 1, >- is_nullable => 1, >- }, >+ { data_type => "datetime", is_nullable => 1 }, > "lastreneweddate", >- { >- data_type => "datetime", >- datetime_undef_if_invalid => 1, >- is_nullable => 1, >- }, >+ { data_type => "datetime", is_nullable => 1 }, > "return", > { data_type => "varchar", is_nullable => 1, size => 4 }, > "renewals", > { data_type => "tinyint", is_nullable => 1 }, > "timestamp", > { >- data_type => "timestamp", >- datetime_undef_if_invalid => 1, >+ data_type => "timestamp", > default_value => \"current_timestamp", >- is_nullable => 0, >+ is_nullable => 0, > }, > "issuedate", >- { >- data_type => "datetime", >- datetime_undef_if_invalid => 1, >- is_nullable => 1, >- }, >+ { data_type => "datetime", is_nullable => 1 }, > ); >+__PACKAGE__->set_primary_key("issue_id"); > > =head1 RELATIONS > >@@ -151,12 +134,7 @@ __PACKAGE__->belongs_to( > "borrowernumber", > "Koha::Schema::Result::Borrower", > { borrowernumber => "borrowernumber" }, >- { >- is_deferrable => 1, >- join_type => "LEFT", >- on_delete => "CASCADE", >- on_update => "CASCADE", >- }, >+ { join_type => "LEFT", on_delete => "CASCADE", on_update => "CASCADE" }, > ); > > =head2 itemnumber >@@ -171,23 +149,25 @@ __PACKAGE__->belongs_to( > "itemnumber", > "Koha::Schema::Result::Item", > { itemnumber => "itemnumber" }, >- { >- is_deferrable => 1, >- join_type => "LEFT", >- on_delete => "CASCADE", >- on_update => "CASCADE", >- }, >+ { join_type => "LEFT", on_delete => "CASCADE", on_update => "CASCADE" }, > ); > > >-# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-10-14 20:56:21 >-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ZEh31EKBmURMKxDxI+H3EA >+# Created by DBIx::Class::Schema::Loader v0.07000 @ 2013-11-12 09:32:52 >+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:zBewWFig+yZYtSkcIxCZpg > > __PACKAGE__->belongs_to( > "borrower", > "Koha::Schema::Result::Borrower", > { borrowernumber => "borrowernumber" }, >- { join_type => "LEFT", on_delete => "CASCADE", on_update => "CASCADE" }, >+ { join_type => "LEFT" }, >+); >+ >+__PACKAGE__->belongs_to( >+ "item", >+ "Koha::Schema::Result::Item", >+ { itemnumber => "itemnumber" }, >+ { join_type => "LEFT" }, > ); > > 1; >diff --git a/Koha/Schema/Result/OldIssue.pm b/Koha/Schema/Result/OldIssue.pm >index 4050f06..e1e7e69 100644 >--- a/Koha/Schema/Result/OldIssue.pm >+++ b/Koha/Schema/Result/OldIssue.pm >@@ -183,6 +183,32 @@ __PACKAGE__->belongs_to( > # Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-10-14 20:56:21 > # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:uPOxNROoMMRZ0qZsXsxEjA > >+__PACKAGE__->belongs_to( >+ "borrower", >+ "Koha::Schema::Result::Borrower", >+ { borrowernumber => "borrowernumber" }, >+ { join_type => "LEFT" }, >+); >+ >+__PACKAGE__->belongs_to( >+ "item", >+ "Koha::Schema::Result::Item", >+ { itemnumber => "itemnumber" }, >+ { join_type => "LEFT" }, >+); >+ >+__PACKAGE__->belongs_to( >+ "deletedborrower", >+ "Koha::Schema::Result::Deletedborrower", >+ { borrowernumber => "borrowernumber" }, >+ { join_type => "LEFT" }, >+); >+ >+__PACKAGE__->belongs_to( >+ "deleteditem", >+ "Koha::Schema::Result::Deleteditem", >+ { itemnumber => "itemnumber" }, >+ { join_type => "LEFT" }, >+); > >-# You can replace this text with custom content, and it will be preserved on regeneration > 1; >diff --git a/Koha/Template/Plugin/Currency.pm b/Koha/Template/Plugin/Currency.pm >new file mode 100644 >index 0000000..7c0b19c >--- /dev/null >+++ b/Koha/Template/Plugin/Currency.pm >@@ -0,0 +1,90 @@ >+package Koha::Template::Plugin::Currency; >+ >+# Copyright ByWater Solutions 2013 >+ >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it under the >+# terms of the GNU General Public License as published by the Free Software >+# Foundation; either version 2 of the License, or (at your option) any later >+# version. >+# >+# Koha is distributed in the hope that it will be useful, but WITHOUT ANY >+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR >+# A PARTICULAR PURPOSE. See the GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License along >+# with Koha; if not, write to the Free Software Foundation, Inc., >+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. >+ >+use Modern::Perl; >+ >+use base qw( Template::Plugin::Filter ); >+ >+use Locale::Currency::Format; >+ >+use C4::Context; >+use Koha::DateUtils; >+ >+sub init { >+ my $self = shift; >+ $self->{ _DYNAMIC } = 1; >+ >+ my $active_currency = C4::Context->dbh->selectrow_hashref( >+ 'SELECT * FROM currency WHERE active = 1', {} ); >+ $self->{active_currency} = $active_currency; >+ >+ return $self; >+} >+ >+sub filter { >+ my ( $self, $amount, $args, $conf ) = @_; >+ >+ return $self->format( $amount, undef, $conf->{highlight} ); >+} >+ >+sub format { >+ my ( $self, $amount, $format, $highlight ) = @_; >+ >+ my $is_negative = $amount < 0; >+ $amount = abs( $amount ) if $highlight; >+ >+ # A negative debit is a credit and visa versa >+ if ($highlight) { >+ if ( $highlight eq 'debit' ) { >+ if ($is_negative) { >+ $highlight = 'credit'; >+ } >+ } >+ elsif ( $highlight eq 'credit' ) { >+ if ($is_negative) { >+ $highlight = 'debit'; >+ } >+ >+ } >+ elsif ( $highlight eq 'offset' ) { >+ $highlight = $is_negative ? 'credit' : 'debit'; >+ } >+ } >+ >+ my $formatted = currency_format( $self->{active_currency}->{currency}, >+ $amount, $format || FMT_HTML ); >+ >+ $formatted = "<span class='$highlight'>$formatted</span>" if ( $highlight && $amount ); >+ >+ return $formatted; >+} >+ >+sub format_without_symbol { >+ my ( $self, $amount ) = @_; >+ >+ return substr( $self->format( $amount, FMT_SYMBOL ), 1, 0 ); >+} >+ >+sub symbol { >+ my ($self) = @_; >+ >+ return currency_symbol( $self->{active_currency}->{'currency'}, SYM_HTML ); >+} >+ >+1; >diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql >index fefc985..4d5ec7b 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,89 @@ CREATE TABLE IF NOT EXISTS marc_modification_template_actions ( > CONSTRAINT `mmta_ibfk_1` FOREIGN KEY (`template_id`) REFERENCES `marc_modification_templates` (`template_id`) ON DELETE CASCADE ON UPDATE CASCADE > ) ENGINE=InnoDB DEFAULT CHARSET=utf8; > >+-- >+-- Table structure for table 'account_credits' >+-- >+DROP TABLE IF EXISTS account_credits; >+CREATE TABLE IF account_credits ( >+ credit_id int(11) NOT NULL AUTO_INCREMENT, >+ 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; >+ >+>>>>>>> 0c386fa... Bug 6427 - Rewrite of the accounts system - WIP >+ > /*!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 6162bc5..5c16574 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"; >@@ -7743,6 +7744,85 @@ if(CheckVersion($DBversion)) { > SetVersion($DBversion); > } > >+$DBversion = "3.15.00.XXX"; >+if ( CheckVersion($DBversion) ) { >+ $dbh->do("ALTER TABLE issues ADD issue_id INT( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST"); >+ $dbh->do("ALTER TABLE old_issues ADD issue_id INT( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST"); >+ $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/circ-menu.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.inc >index 62db1c5..c486a1f 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.inc >@@ -67,7 +67,7 @@ > [% IF ( detailview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">Details</a></li> > [% END %] > [% IF ( CAN_user_updatecharges ) %] >- [% IF ( finesview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrowernumber %]">Fines</a></li> >+ [% IF ( accounts_view ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Fines</a></li> > [% END %] > [% IF ( RoutingSerials ) %][% IF ( routinglistview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/routing-lists.pl?borrowernumber=[% borrowernumber %]">Routing lists</a></li>[% END %] > [% IF ( intranetreadinghistory ) %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.tt b/koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.tt >index 7f8cb48..456d52d 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.tt >@@ -70,7 +70,7 @@ in the global namespace %] > [% IF ( detailview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrower.borrowernumber %]">Details</a></li> > [% END %] > [% IF ( CAN_user_updatecharges ) %] >- [% IF ( finesview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrower.borrowernumber %]">Fines</a></li> >+ [% IF ( accounts_view ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrower.borrowernumber %]">Fines</a></li> > [% END %] > [% IF ( RoutingSerials ) %][% IF ( routinglistview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/routing-lists.pl?borrowernumber=[% borrower.borrowernumber %]">Routing lists</a></li>[% END %] > [% IF ( intranetreadinghistory ) %][% IF ( readingrecordview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/readingrec.pl?borrowernumber=[% borrower.borrowernumber %]">Circulation history</a></li>[% END %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/members-menu.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/members-menu.inc >index 9bd5285..9208e17 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/members-menu.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/members-menu.inc >@@ -4,7 +4,7 @@ > [% IF ( circview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/circ/circulation.pl?borrowernumber=[% borrowernumber %]">Check out</a></li> > [% IF ( detailview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">Details</a></li> > [% IF ( CAN_user_updatecharges ) %] >- [% IF ( finesview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrowernumber %]">Fines</a></li> >+ [% IF ( finesview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Fines</a></li> > [% END %] > [% IF ( intranetreadinghistory ) %] > [% IF ( readingrecordview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/readingrec.pl?borrowernumber=[% borrowernumber %]">Circulation history</a></li> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt >index 46b82a8..5bfbd58 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt >@@ -1,5 +1,6 @@ > [% USE KohaBranchName %] > [% USE KohaDates %] >+[% USE Currency %] > [% IF ( export_remove_fields OR export_with_csv_profile ) %] > [% SET exports_enabled = 1 %] > [% END %] >@@ -577,16 +578,16 @@ No patron matched <span class="ex">[% message %]</span> > > [% IF ( charges ) %] > <li> >- <span class="circ-hlt">Fees & Charges:</span> Patron has <a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrowernumber %]">Outstanding fees & charges[% IF ( chargesamount ) %] of [% chargesamount %][% END %]</a>. >+ <span class="circ-hlt">Fees & Charges:</span> Patron has <a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Outstanding fees & charges[% IF ( chargesamount ) %] of [% chargesamount | $Currency %][% END %]</a>. > [% IF ( charges_is_blocker ) %] > Checkouts are <span class="circ-hlt">BLOCKED</span> because fine balance is <span class="circ-hlt">OVER THE LIMIT</span>. > [% END %] >- <a href="/cgi-bin/koha/members/pay.pl?borrowernumber=[% borrowernumber %]">Make payment</a></li> >+ <a href="/cgi-bin/koha/members/account_payment.pl?borrowernumber=[% borrowernumber %]">Make payment</a></li> > [% END %] > > [% IF ( credits ) %] > <li> >- <span class="circ-hlt">Credits:</span> Patron has a credit[% IF ( creditsamount ) %] of [% creditsamount %][% END %] >+ <span class="circ-hlt">Credits:</span> Patron has a credit[% IF ( creditsamount ) %] of [% creditsamount | $Currency %][% END %] > </li> > [% END %] > >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/returns.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/returns.tt >index fb30311..ffe4e0d 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/returns.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/returns.tt >@@ -74,7 +74,7 @@ $(document).ready(function () { > [% IF ( fines ) %] > <div class="dialog alert"> > <h3>Patron has outstanding fines of [% fines %].</h3> >- <p><a href="/cgi-bin/koha/members/pay.pl?borrowernumber=[% fineborrowernumber %]">Make payment</a>.</p> >+ <p><a href="/cgi-bin/koha/members/account_payment.pl?borrowernumber=[% fineborrowernumber %]">Make payment</a>.</p> > </div> > [% END %] > >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/account.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/account.tt >new file mode 100644 >index 0000000..29040b8 >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/account.tt >@@ -0,0 +1,419 @@ >+[% SET accounts_view = 1 %] >+[% USE KohaDates %] >+[% USE Currency %] >+[% INCLUDE 'doc-head-open.inc' %] >+<title>Koha › Patrons › Account for [% INCLUDE 'patron-title.inc' %]</title> >+[% INCLUDE 'doc-head-close.inc' %] >+ >+<link rel="stylesheet" type="text/css" href="[% interface %]/[% theme %]/en/css/datatables.css" /> >+<script type="text/javascript" src="[% interface %]/[% theme %]/en/lib/jquery/plugins/jquery.dataTables.min.js"></script> >+[% INCLUDE 'datatables-strings.inc' %] >+<script type="text/javascript" src="[% interface %]/[% theme %]/en/js/datatables.js"></script> >+ >+<script type="text/javascript"> >+//<![CDATA[ >+$(document).ready(function() { >+ $('#account-credits').hide(); >+ $('#account-debits-switcher').click(function() { >+ $('#account-debits').slideUp(); >+ $('#account-credits').slideDown(); >+ }); >+ $('#account-credits-switcher').click(function() { >+ $('#account-credits').slideUp(); >+ $('#account-debits').slideDown(); >+ }); >+ >+ var anOpen = []; >+ var sImageUrl = "[% interface %]/[% theme %]/img/"; >+ >+ var debitsTable = $('#debits-table').dataTable( { >+ "bProcessing": true, >+ "aoColumns": [ >+ { >+ "mDataProp": null, >+ "sClass": "control center", >+ "sDefaultContent": '<img src="'+sImageUrl+'details_open.png'+'">' >+ }, >+ { "mDataProp": "debit_id" }, >+ { "mDataProp": "description" }, >+ { "mDataProp": "type" }, >+ { "mDataProp": "amount_original" }, >+ { "mDataProp": "amount_outstanding" }, >+ { "mDataProp": "created_on" }, >+ { "mDataProp": "updated_on" } >+ ], >+ "aaData": [ >+ [% FOREACH d IN debits %] >+ { >+ [% PROCESS format_data data=d highlight='debit' %] >+ >+ // Data for related item if there is one linked >+ "title": "[% d.item.biblio.title || d.deleted_item.biblio.title || d.deleted_item.deleted_biblio.title %]", >+ "biblionumber": "[% d.item.biblio.biblionumber || d.deleted_item.biblio.biblionumber %]", >+ "barcode": "[% d.item.barcode || d.deleted_item.barcode %]", >+ "itemnumber": "[% d.item.itemnumber %]", //This way itemnumber will be undef if deleted >+ >+ >+ // Data for related issue if there is one linked >+ [% IF d.issue %] >+ [% SET table = 'issue' %] >+ [% ELSIF d.old_issue %] >+ [% SET table = 'old_issue' %] >+ [% END %] >+ >+ [% IF table %] >+ "issue": { >+ [% PROCESS format_data data=d.$table %] >+ }, >+ [% END %] >+ >+ >+ "account_offsets": [ >+ [% FOREACH ao IN d.account_offsets %] >+ { >+ [% PROCESS format_data data=ao highlight='offset'%] >+ >+ "credit": { >+ [% PROCESS format_data data=ao.credit highlight='credit' %] >+ } >+ }, >+ [% END %] >+ ] >+ >+ }, >+ [% END %] >+ ] >+ } ); >+ >+ $('#debits-table td.control').live( 'click', function () { >+ var nTr = this.parentNode; >+ var i = $.inArray( nTr, anOpen ); >+ >+ if ( i === -1 ) { >+ $('img', this).attr( 'src', sImageUrl+"details_close.png" ); >+ var nDetailsRow = debitsTable.fnOpen( nTr, fnFormatDebitDetails(debitsTable, nTr), 'details' ); >+ $('div.innerDetails', nDetailsRow).slideDown(); >+ anOpen.push( nTr ); >+ } >+ else { >+ $('img', this).attr( 'src', sImageUrl+"details_open.png" ); >+ $('div.innerDetails', $(nTr).next()[0]).slideUp( function () { >+ debitsTable.fnClose( nTr ); >+ anOpen.splice( i, 1 ); >+ } ); >+ } >+ } ); >+ >+ var creditsTable = $('#credits-table').dataTable( { >+ "bProcessing": true, >+ "aoColumns": [ >+ { >+ "mDataProp": null, >+ "sClass": "control center", >+ "sDefaultContent": '<img src="'+sImageUrl+'details_open.png'+'">' >+ }, >+ { "mDataProp": "credit_id" }, >+ { "mDataProp": "notes" }, >+ { "mDataProp": "type" }, >+ { "mDataProp": "amount_paid" }, >+ { "mDataProp": "amount_remaining" }, >+ { "mDataProp": "created_on" }, >+ { "mDataProp": "updated_on" } >+ ], >+ "aaData": [ >+ [% FOREACH c IN credits %] >+ { >+ [% PROCESS format_data data=c highlight='credit' %] >+ >+ "account_offsets": [ >+ [% FOREACH ao IN c.account_offsets %] >+ { >+ [% PROCESS format_data data=ao highlight='offset' %] >+ >+ "debit": { >+ [% PROCESS format_data data=ao.debit highlight='debit' %] >+ } >+ }, >+ [% END %] >+ ] >+ >+ }, >+ [% END %] >+ ] >+ } ); >+ >+ $('#credits-table td.control').live( 'click', function () { >+ var nTr = this.parentNode; >+ var i = $.inArray( nTr, anOpen ); >+ >+ if ( i === -1 ) { >+ $('img', this).attr( 'src', sImageUrl+"details_close.png" ); >+ var nDetailsRow = creditsTable.fnOpen( nTr, fnFormatCreditDetails(creditsTable, nTr), 'details' ); >+ $('div.innerDetails', nDetailsRow).slideDown(); >+ anOpen.push( nTr ); >+ } >+ else { >+ $('img', this).attr( 'src', sImageUrl+"details_open.png" ); >+ $('div.innerDetails', $(nTr).next()[0]).slideUp( function () { >+ creditsTable.fnClose( nTr ); >+ anOpen.splice( i, 1 ); >+ } ); >+ } >+ } ); >+ >+} ); >+ >+function fnFormatDebitDetails( debitsTable, nTr ) { >+ var oData = debitsTable.fnGetData( nTr ); >+ >+ var sOut = '<div class="innerDetails" style="display:none;">'; >+ >+ var account_offsets = oData.account_offsets; >+ >+ sOut += '<a class="debit_print btn btn-small" style="margin:5px;" onclick="accountPrint(\'debit\',' + oData.debit_id + ')">' + >+ '<i class="icon-print"></i> ' + _('Print receipt') + >+ '</a>'; >+ >+ sOut += '<ul>'; >+ if ( oData.title ) { >+ sOut += '<li>' + _('Title: '); >+ if ( oData.biblionumber ) { >+ sOut += '<a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=' + oData.biblionumber + '">'; >+ } >+ >+ sOut += oData.title; >+ >+ if ( oData.biblionumber ) { >+ sOut += '</a>'; >+ } >+ >+ sOut += '</li>'; >+ } >+ >+ if ( oData.barcode ) { >+ sOut += '<li>' + _('Barcode: '); >+ if ( oData.itemnumber ) { >+ sOut += '<a href="/cgi-bin/koha/catalogue/moredetail.pl?itemnumber=11&biblionumber=' + oData.biblionumber + '&bi=' + oData.biblionumber + '#item' + oData.itemnumber + '' + oData.biblionumber + '">'; >+ } >+ >+ sOut += oData.barcode; >+ >+ if ( oData.itemnumber ) { >+ sOut += '</a>'; >+ } >+ >+ sOut += '</li>'; >+ } >+ >+ if ( oData.notes ) { >+ sOut += '<li>' + _('Notes: ') + oData.notes + '</li>'; >+ } >+ >+ sOut += '</ul>'; >+ >+ if ( account_offsets.length ) { >+ sOut += >+ '<div class="innerDetails">' + >+ '<table cellpadding="5" cellspacing="0" border="0" style="margin:10px;">' + >+ '<thead>' + >+ '<tr><th colspan="99">' + _('Payments applied') + '</th></tr>' + >+ '<tr>' + >+ '<th>' + _('ID') + '</th>' + >+ '<th>' + _('Created on') + '</th>' + >+ '<th>' + _('Payment amount') + '</th>' + >+ '<th>' + _('Applied amount') + '</th>' + >+ '<th>' + _('Type') + '</th>' + >+ '<th>' + _('Notes') + '</th>' + >+ '</tr>' + >+ '</thead>' + >+ '<tbody>'; >+ >+ for ( var i = 0; i < account_offsets.length; i++ ) { >+ ao = account_offsets[i]; >+ sOut += >+ '<tr>' + >+ '<td>' + ao.credit_id + '</td>' + >+ '<td>' + ao.created_on + '</td>' + >+ '<td>' + ao.credit.amount_paid + '</td>' + >+ '<td>' + ao.amount + '</td>' + >+ '<td>' + ao.credit.type + '</td>' + >+ '<td>' + ao.credit.notes + '</td>' + >+ '</tr>'; >+ } >+ >+ sOut += >+ '</tbody>'+ >+ '</table>'; >+ } >+ >+ sOut += >+ '</div>'; >+ >+ return sOut; >+} >+ >+function fnFormatCreditDetails( creditsTable, nTr ) { >+ var oData = creditsTable.fnGetData( nTr ); >+ >+ var sOut = '<div class="innerDetails" style="display:none;">'; >+ >+ sOut += '<button class="credit_print btn btn-small" style="margin:5px;" onclick="accountPrint(\'credit\',' + oData.credit_id + ')">' + >+ '<i class="icon-print"></i> ' + _('Print receipt') + >+ '</button>'; >+ >+ var account_offsets = oData.account_offsets; >+ >+ if ( account_offsets.length ) { >+ sOut += >+ '<table cellpadding="5" cellspacing="0" border="0" style="margin:10px;">' + >+ '<thead>' + >+ '<tr><th colspan="99">' + _('Fees paid') + '</th></tr>' + >+ '<tr>' + >+ '<th>' + _('ID') + '</th>' + >+ '<th>' + _('Description') + '</th>' + >+ '<th>' + _('Type') + '</th>' + >+ '<th>' + _('Amount') + '</th>' + >+ '<th>' + _('Remaining') + '</th>' + >+ '<th>' + _('Created on') + '</th>' + >+ '<th>' + _('Updated on') + '</th>' + >+ '<th>' + _('Notes') + '</th>' + >+ '</tr>' + >+ '</thead>' + >+ '<tbody>'; >+ >+ for ( var i = 0; i < account_offsets.length; i++ ) { >+ ao = account_offsets[i]; >+ sOut += >+ '<tr>' + >+ '<td>' + ao.debit.debit_id + '</td>' + >+ '<td>' + ao.debit.description + '</td>' + >+ '<td>' + ao.debit.type + '</td>' + >+ '<td>' + ao.debit.amount_original + '</td>' + >+ '<td>' + ao.debit.amount_outstanding + '</td>' + >+ '<td>' + ao.debit.created_on + '</td>' + >+ '<td>' + ao.debit.updated_on + '</td>' + >+ '<td>' + ao.debit.notes + '</td>' + >+ '</tr>'; >+ } >+ >+ sOut += >+ '</tbody>'+ >+ '</table>'; >+ } >+ >+ sOut += >+ '</div>'; >+ >+ return sOut; >+} >+ >+function accountPrint( type, id ) { >+ window.open( '/cgi-bin/koha/members/account_print.pl?type=' + type + '&id=' + id ); >+} >+//]]> >+</script> >+</head> >+<body> >+[% INCLUDE 'header.inc' %] >+[% INCLUDE 'patron-search.inc' %] >+ >+<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a> › Account for [% INCLUDE 'patron-title.inc' %]</div> >+ >+<div id="doc3" class="yui-t2"> >+ <div id="bd"> >+ <div id="yui-main"> >+ <div class="yui-b"> >+ [% INCLUDE 'members-toolbar.inc' %] >+ >+ <div class="statictabs"> >+ <ul> >+ <li class="active"> >+ <a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Account</a> >+ </li> >+ >+ <li> >+ <a href="/cgi-bin/koha/members/account_payment.pl?borrowernumber=[% borrowernumber %]" >Pay fines</a> >+ </li> >+ >+ <li> >+ <a href="/cgi-bin/koha/members/account_debit.pl?borrowernumber=[% borrowernumber %]" >Create manual invoice</a> >+ </li> >+ >+ <li> >+ <a href="/cgi-bin/koha/members/account_credit.pl?borrowernumber=[% borrowernumber %]" >Create manual credit</a> >+ </li> >+ </ul> >+ </div> >+ >+ <div class="tabs-container"> >+ >+ <p> >+ <h3>Account balance: [% borrower.account_balance | $Currency %]</h3> >+ </p> >+ >+ <div> >+ <div id="account-debits"> >+ <a id="account-debits-switcher" href="#" onclick="return false">View payments</a> >+ <table cellpadding="0" cellspacing="0" border="0" class="display" id="debits-table"> >+ <thead> >+ <tr> >+ <th colspan="99">Fees</th> >+ </tr> >+ <tr> >+ <th></th> >+ <th>ID</th> >+ <th>Description</th> >+ <th>Type</th> >+ <th>Amount</th> >+ <th>Outsanding</th> >+ <th>Created on</th> >+ <th>Updated on</th> >+ </tr> >+ </thead> >+ <tbody></tbody> >+ </table> >+ </div> >+ >+ <div id="account-credits"> >+ <a id="account-credits-switcher" href="#" onclick="return false">View fees</a> >+ <table cellpadding="0" cellspacing="0" border="0" class="display" id="credits-table"> >+ <thead> >+ <tr> >+ <th colspan="99">Payments</th> >+ </tr> >+ <tr> >+ <th></th> >+ <th>ID</th> >+ <th>Notes</th> >+ <th>Type</th> >+ <th>Amount</th> >+ <th>Remaining</th> >+ <th>Created on</th> >+ <th>Updated on</th> >+ </tr> >+ </thead> >+ <tbody></tbody> >+ </table> >+ </div> >+ </div> >+ </div> >+ </div> >+ </div> >+ >+ <div class="yui-b"> >+ [% INCLUDE 'circ-menu.inc' %] >+ </div> >+</div> >+[% INCLUDE 'intranet-bottom.inc' %] >+ >+[% BLOCK format_data %] >+ [% FOREACH key IN data.result_source.columns %] >+ [% IF key.match('^amount') %] >+ "[% key %]": "[% data.$key FILTER $Currency highlight => highlight %]", >+ [% ELSIF key.match('_on$') %] >+ "[% key %]": "[% data.$key | $KohaDates %]", >+ [% ELSE %] >+ "[% key %]": "[% data.$key %]", >+ [% END %] >+ [% END %] >+[% END %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_credit.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_credit.tt >new file mode 100644 >index 0000000..d8e8883 >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_credit.tt >@@ -0,0 +1,92 @@ >+[% SET accounts_view = 1 %] >+[% INCLUDE 'doc-head-open.inc' %] >+<title>Koha › Borrowers › Create manual credit</title> >+[% INCLUDE 'doc-head-close.inc' %] >+<script type="text/javascript"> >+//<![CDATA[ >+$(document).ready(function(){ >+ $('#account_credit').preventDoubleFormSubmit(); >+ $("fieldset.rows input").addClass("noEnterSubmit"); >+}); >+//]]> >+</script> >+</head> >+<body id="pat_account_credit" class="pat"> >+ [% INCLUDE 'header.inc' %] >+ [% INCLUDE 'patron-search.inc' %] >+ >+ <div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a> › Manual credit</div> >+ >+ <div id="doc3" class="yui-t2"> >+ <div id="bd"> >+ <div id="yui-main"> >+ <div class="yui-b"> >+ [% INCLUDE 'members-toolbar.inc' %] >+ >+ <div class="statictabs"> >+ <ul> >+ <li><a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Account</a></li> >+ <li><a href="/cgi-bin/koha/members/account_payment.pl?borrowernumber=[% borrowernumber %]" >Pay fines</a></li> >+ <li><a href="/cgi-bin/koha/members/account_debit.pl?borrowernumber=[% borrowernumber %]" >Create manual invoice</a></li> >+ <li class="active"><a href="/cgi-bin/koha/members/account_credit.pl?borrowernumber=[% borrowernumber %]" >Create manual credit</a></li> >+ </ul> >+ >+ <div class="tabs-container"> >+ >+ <form action="/cgi-bin/koha/members/account_credit_do.pl" method="post" id="account_credit"> >+ <input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrowernumber %]" /> >+ >+ <fieldset class="rows"> >+ <legend>Manual credit</legend> >+ >+ <ol> >+ <li> >+ <label for="type">Credit Type: </label> >+ <select name="type" id="type"> >+ <option value="CREDIT">Credit</option> >+ <option value="FORGIVEN">Forgiven</option> >+ [% FOREACH c IN credit_types_loop %] >+ <option value="[% c.authorised_value %]">[% c.lib %]</option> >+ [% END %] >+ </select> >+ </li> >+ >+ <li> >+ <label for="barcode">Barcode: </label> >+ <input type="text" name="barcode" id="barcode" /> >+ </li> >+ >+ <li> >+ <label for="desc">Description: </label> >+ <input type="text" name="desc" size="50" id="desc" /> >+ </li> >+ >+ <li> >+ <label for="note">Note: </label> >+ <input type="text" name="note" size="50" id="note" /> >+ </li> >+ >+ <li> >+ <label for="amount">Amount: </label> >+ <input type="text" name="amount" id="amount" /> >+ Example: 5.00 >+ </li> >+ </ol> >+ >+ </fieldset> >+ >+ <fieldset class="action"> >+ <input type="submit" name="add" value="Add credit" /> >+ <a class="cancel" href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Cancel</a> >+ </fieldset> >+ </form> >+ >+ </div> >+ </div> >+ </div> >+ </div> >+ <div class="yui-b"> >+ [% INCLUDE 'circ-menu.inc' %] >+ </div> >+ </div> >+[% INCLUDE 'intranet-bottom.inc' %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_debit.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_debit.tt >new file mode 100644 >index 0000000..4055fd9 >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_debit.tt >@@ -0,0 +1,109 @@ >+[% SET accounts_view = 1 %] >+[% INCLUDE 'doc-head-open.inc' %] >+<title>Koha › Borrowers › Create manual invoice</title> >+[% INCLUDE 'doc-head-close.inc' %] >+<script type="text/javascript"> >+//<![CDATA[ >+$(document).ready(function(){ >+ $('#maninvoice').preventDoubleFormSubmit(); >+ $("fieldset.rows input").addClass("noEnterSubmit"); >+ >+ var type_fees = new Array(); >+ type_fees['L'] = ''; >+ type_fees['F'] = ''; >+ type_fees['A'] = ''; >+ type_fees['N'] = ''; >+ type_fees['M'] = ''; >+ [% FOREACH invoice_types_loo IN invoice_types_loop %] >+ type_fees['[% invoice_types_loo.authorised_value %]'] = "[% invoice_types_loo.lib %]"; >+ [% END %] >+}); >+//]]> >+</script> >+</head> >+ >+<body> >+ [% INCLUDE 'header.inc' %] >+ [% INCLUDE 'patron-search.inc' %] >+ >+ <div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a> › Manual invoice</div> >+ >+ <div id="doc3" class="yui-t2"> >+ <div id="bd"> >+ <div id="yui-main"> >+ <div class="yui-b"> >+ [% INCLUDE 'members-toolbar.inc' %] >+ >+ <div class="statictabs"> >+ <ul> >+ <li><a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Account</a></li> >+ <li><a href="/cgi-bin/koha/members/account_payment.pl?borrowernumber=[% borrowernumber %]" >Pay fines</a></li> >+ <li class="active"><a href="/cgi-bin/koha/members/account_debit.pl?borrowernumber=[% borrowernumber %]" >Create manual invoice</a></li> >+ <li><a href="/cgi-bin/koha/members/account_credit.pl?borrowernumber=[% borrowernumber %]" >Create manual credit</a></li> >+ </ul> >+ <div class="tabs-container"> >+ >+ <form action="/cgi-bin/koha/members/account_debit_do.pl" method="post" id="account_debit"> >+ <input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrowernumber %]" /> >+ >+ <fieldset class="rows"> >+ <legend>Manual Invoice</legend> >+ >+ <ol> >+ <li> >+ <label for="type">Type: </label> >+ <select name="type" id="type"> >+ <option value="LOST">Lost item</option> >+ <option value="FINE">Fine</option> >+ <option value="ACCOUNT_MANAGEMENT_FEE">Account management fee</option> >+ <option value="NEW_CARD">New card</option> >+ <option value="SUNDRY">Sundry</option> >+ >+ [% FOREACH invoice_types_loo IN invoice_types_loop %] >+ <option value="[% invoice_types_loo.authorised_value %]">[% invoice_types_loo.lib %]</option> >+ [% END %] >+ </select> >+ </li> >+ >+ <!-- TODO: Write ajax barcode validator that appends the itemnumber for this form in a hidden input --> >+ <li> >+ <label for="barcode">Barcode: </label> >+ <input type="text" name="barcode" id="barcode" /> >+ </li> >+ >+ <li> >+ <label for="description">Description: </label> >+ <input type="text" name="description" id="description" size="50" /> >+ </li> >+ >+ <li> >+ <label for="notes">Notes: </label> >+ <input type="text" name="notes" size="50" id="notes" /> >+ </li> >+ >+ <li> >+ <label for="amount">Amount: </label> >+ <input type="text" name="amount" id="amount" /> Example: 5.00 >+ </li> >+ >+ </ol> >+ </fieldset> >+ >+ <fieldset class="action"> >+ <input type="submit" name="add" value="Save" /> >+ <a class="cancel" href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Cancel</a> >+ </fieldset> >+ >+ </form> >+ >+ </div> >+ </div> >+ </div> >+ </div> >+ >+<div class="yui-b"> >+ [% INCLUDE 'circ-menu.inc' %] >+</div> >+ >+</div> >+[% INCLUDE 'intranet-bottom.inc' %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_payment.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_payment.tt >new file mode 100644 >index 0000000..bff4e29 >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_payment.tt >@@ -0,0 +1,201 @@ >+[% SET accounts_view = 1 %] >+[% USE Currency %] >+[% INCLUDE 'doc-head-open.inc' %] >+<title>Koha › Patrons › Pay Fines for [% borrower.firstname %] [% borrower.surname %]</title> >+[% INCLUDE 'doc-head-close.inc' %] >+<script type="text/javascript" src="[% themelang %]/lib/jquery/plugins/jquery.checkboxes.min.js"></script> >+<script type= "text/javascript"> >+//<![CDATA[ >+$( document ).ready(function() { >+ // Show amount recieved only if the "Receive different amount" checkbox is checked >+ $("#amount-received-p").hide(); >+ $('#receive_different_amount').click(function() { >+ if( $(this).is(':checked')) { >+ $("#amount-received-p").show(); >+ } else { >+ $("#amount-received-p").hide(); >+ } >+ }); >+ >+ // Enable the "Select all/Clear all" links >+ $('#CheckAll').click(function() { >+ $("input[name='debit_id']" ).prop('checked', true); >+ }); >+ $('#ClearAll').click(function() { >+ $("input[name='debit_id']" ).prop('checked', false); >+ }); >+ >+ // Update the "amount to pay" field whenever a fee checkbox is changed >+ // Note, this is just a payment suggestion and can be changed to any amount >+ $("input[name='debit_id']" ).change(function() { >+ var sum = 0; >+ $("input[name='debit_id']:checked" ).each(function(i,n){ >+ sum += parseFloat( $( "#amount_outstanding_" + $(this).val() ).val() ); >+ }); >+ $('#amount_to_pay').val( sum ); >+ }); >+}); >+ >+function checkForm(){ >+ // If using the "amount to receive" field, make sure the librarian is recieving at >+ // least enough to pay those fees. >+ if ( $('#amount_to_receive').val() ) { >+ if ( parseFloat( $('#amount_to_receive').val() ) < parseFloat( $('#amount_to_pay').val() ) ) { >+ alert( _("Cannot pay more than receieved!") ); >+ return false; >+ } >+ } >+ >+ return true; >+} >+//]]> >+</script> >+</head> >+<body id="pat_pay" class="pat"> >+ [% INCLUDE 'header.inc' %] >+ [% INCLUDE 'patron-search.inc' %] >+ >+ <div id="breadcrumbs"> >+ <a href="/cgi-bin/koha/mainpage.pl">Home</a> >+ › <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a> >+ › Pay fines for [% borrower.firstname %] [% borrower.surname %] >+ </div> >+ >+ <div id="doc3" class="yui-t2"> >+ <div id="bd"> >+ <div id="yui-main"> >+ <div class="yui-b"> >+ [% INCLUDE 'members-toolbar.inc' borrowernumber=borrower.borrowernumber %] >+ >+ <div class="statictabs"> >+ <ul> >+ <li><a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrower.borrowernumber %]">Account</a></li> >+ <li class="active"><a href="/cgi-bin/koha/members/account_payment.pl?borrowernumber=[% borrower.borrowernumber %]" >Pay fines</a></li> >+ <li><a href="/cgi-bin/koha/members/account_debit.pl?borrowernumber=[% borrower.borrowernumber %]" >Create manual invoice</a></li> >+ <li><a href="/cgi-bin/koha/members/account_credit.pl?borrowernumber=[% borrower.borrowernumber %]" >Create manual credit</a></li> >+ </ul> >+ >+ <div class="tabs-container"> >+ >+ [% IF ( debits ) %] >+ <form action="/cgi-bin/koha/members/account_payment_do.pl" method="post" id="account-payment-form" onsubmit="return checkForm()"> >+ >+ <input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrower.borrowernumber %]" /> >+ >+ <p> >+ <span class="checkall"> >+ <a id="CheckAll" href="#">Select all</a> >+ </span> >+ >+ | >+ >+ <span class="clearall"> >+ <a id="ClearAll" href="#">Clear all</a> >+ </span> >+ </p> >+ >+ <table id="finest"> >+ <thead> >+ <tr> >+ <th> </th> >+ <th>Description</th> >+ <th>Account type</th> >+ <th>Original amount</th> >+ <th>Amount outstanding</th> >+ </tr> >+ </thead> >+ >+ <tbody> >+ [% SET total_due = 0 %] >+ [% FOREACH d IN debits %] >+ [% SET total_due = total_due + d.amount_outstanding %] >+ <tr> >+ <td> >+ <input type="checkbox" checked="checked" name="debit_id" value="[% d.debit_id %]" /> >+ </td> >+ >+ <td> >+ [% d.description %] >+ >+ [% IF d.notes %] >+ ( <i>[% d.notes %]</i> ) >+ [% END %] >+ </td> >+ >+ <td> >+ [% d.type %] >+ </td> >+ >+ <td class="debit"> >+ [% d.amount_original | $Currency %] >+ <input type="hidden" id="amount_original_[% d.debit_id %]" value="[% Currency.format_without_symbol( d.amount_original ) %]" /> >+ </td> >+ >+ <td class="debit"> >+ [% d.amount_outstanding | $Currency %] >+ <input type="hidden" id="amount_outstanding_[% d.debit_id %]" value="[% Currency.format_without_symbol( d.amount_outstanding ) %]" /> >+ </td> >+ </tr> >+ [% END %] >+ </tbody> >+ >+ <tfoot> >+ <tr> >+ <td class="total" colspan="4">Total Due:</td> >+ <td>[% total_due | $Currency %]</td> >+ </tr> >+ </tfoot> >+ >+ </table> >+ >+ <fieldset> >+ <p> >+ <label for="amount_to_pay">Amount to pay: [% Currency.symbol() %]</label> >+ <input type="text" name="amount_to_pay" id="amount_to_pay" value="[% Currency.format_without_symbol( total_due ) %]" /> >+ >+ <input type="checkbox" id="receive_different_amount" /> >+ <label for="receive_different_amount"><i>Receive different amount</i></label> >+ </p> >+ >+ <p id="amount-received-p"> >+ <label for="amount_to_receive">Amount recieved: [% Currency.symbol() %]</label> >+ <input type="text" name="amount_to_receive" id="amount_to_receive" /> >+ </p> >+ >+ <p> >+ <label for="type">Type:</label> >+ <select id="type" name="type"> >+ <option value="PAYMENT">Payment</option> >+ <option value="WRITEOFF">Write-off</option> >+ </select> >+ </p> >+ >+ <p> >+ <label for="notes">Payment notes:</label> >+ <input type="textbox" name="notes" id="notes" /> >+ <p> >+ </fieldset> >+ >+ <fieldset class="action"> >+ <input type="submit" value="Process" class="submit" /> >+ <a class="cancel" href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrower.borrowernumber %]">Cancel</a> >+ </fieldset> >+ >+ </form> >+ >+ [% ELSE %] >+ <p> >+ [% borrower.firstname %] [% borrower.surname %] has no outstanding fines. >+ </p> >+ [% END %] >+ >+ </div> >+ </div> >+ </div> >+ </div> >+ >+ <div class="yui-b"> >+ [% INCLUDE 'circ-menu.tt' %] >+ </div> >+ </div> >+[% INCLUDE 'intranet-bottom.inc' %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_print.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_print.tt >new file mode 100644 >index 0000000..9845f64 >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_print.tt >@@ -0,0 +1,136 @@ >+[% USE KohaDates %] >+[% USE Currency %] >+[% USE EncodeUTF8 %] >+[% INCLUDE 'doc-head-open.inc' %] >+<title>Print Receipt for [% cardnumber %]</title> >+[% INCLUDE 'doc-head-close.inc' %] >+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> >+<link rel="shortcut icon" href="[% IF ( IntranetFavicon ) %][% IntranetFavicon %][% ELSE %][% interface %]/[% theme %]/img/favicon.ico[% END %]" type="image/x-icon" /> >+<script type="text/javascript"> >+ function printThenClose() { >+ window.print(); >+ window.close(); >+ } >+</script> >+</head> >+ >+[% SET account = debit || credit %] >+[% SET borrower = account.borrower %] >+ >+<body id="account-print-body" onload="printThenClose();"> >+ >+ <table> >+ <thead> >+ <tr> >+ <th colspan="99"> >+ [% IF debit %] >+ Invoice >+ [% ELSIF credit %] >+ Payment receipt >+ [% END %] >+ </th> >+ </tr> >+ >+ <tr> >+ <th colspan="99"> >+ [% borrower.branch.branchname | $EncodeUTF8 %] >+ </th> >+ </tr> >+ >+ <tr> >+ <th>Name:</th> >+ <th colspan="99">[% borrower.firstname | $EncodeUTF8 %] [% borrower.surname | $EncodeUTF8 %]</th> >+ </tr> >+ >+ <tr> >+ <th>Card number:</th> >+ <th colspan="99">[% borrower.cardnumber %]</th> >+ </tr> >+ >+ <tr> >+ <th>Date:</th> >+ <th colspan="99">[% account.created_on | $KohaDates %]</th> >+ </tr> >+ >+ [% IF account.description %] >+ <tr> >+ <th>Description:</th> >+ <th colspan="99">[% account.description | $EncodeUTF8 %]</th> >+ </tr> >+ [% END %] >+ >+ [% IF credit %] >+ <tr> >+ <th>Amount:</th> >+ <th colspan="99">[% credit.amount_paid | $Currency highlight => type %]</th> >+ </tr> >+ <tr> >+ <th>Balance:</th> >+ <th colspan="99">[% credit.amount_remaining | $Currency highlight => type %]</th> >+ </tr> >+ [% IF credit.account_offsets %] >+ <tr> >+ <th colspan="99">Fees paid</th> >+ </tr> >+ <tr> >+ <th>Description</th> >+ <th>Type</th> >+ <th>Amount</th> >+ <th>Paid</th> >+ <th>Outstanding</th> >+ <th>Date</th> >+ </tr> >+ [% END %] >+ [% ELSIF debit %] >+ <tr> >+ <th>Amount:</th> >+ <th colspan="99">[% debit.amount_original | $Currency highlight => type %]</th> >+ </tr> >+ <tr> >+ <th>Outstanding:</th> >+ <th colspan="99">[% debit.amount_outstanding | $Currency highlight => type %]</th> >+ </tr> >+ [% IF debit.account_offsets %] >+ <tr> >+ <th colspan="99">Payments applied</th> >+ </tr> >+ <tr> >+ <th>Date</th> >+ <th>Type</th> >+ <th>Payment</th> >+ <th>Applied</th> >+ <th>Balance</th> >+ <th>Notes</th> >+ </tr> >+ [% END %] >+ [% END %] >+ </thead> >+ >+ <tbody> >+ [% IF credit.account_offsets %] >+ [% FOREACH ao IN credit.account_offsets %] >+ <tr> >+ <td>[% ao.debit.description %]</td> >+ <td>[% ao.debit.type %]</td> >+ <td>[% ao.debit.amount_original | $Currency highlight => 'debit' %]</td> >+ <td>[% ao.amount | $Currency highlight => 'offset' %]</td> >+ <td>[% ao.debit.amount_outstanding | $Currency highlight => 'debit' %]</td> >+ <td>[% ao.debit.created_on | $KohaDates %]</td> >+ </tr> >+ [% END %] >+ [% ELSIF debit.account_offsets %] >+ [% FOREACH ao IN debit.account_offsets %] >+ <tr> >+ <td>[% ao.credit.type %]</td> >+ <td>[% ao.credit.created_on | $KohaDates %]</td> >+ <td>[% ao.credit.amount_paid | $Currency highlight => 'credit' %]</td> >+ <td>[% ao.amount | $Currency highlight => 'offset' %]</td> >+ <td>[% ao.credit.amount_remaining | $Currency highlight => 'credit' %]</td> >+ <td>[% ao.credit.notes %]</td> >+ </tr> >+ [% END %] >+ [% END %] >+ </tbody> >+ </table> >+ >+[% INCLUDE 'intranet-bottom.inc' %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/boraccount.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/boraccount.tt >index d64c63b..e4d3500 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/boraccount.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/boraccount.tt >@@ -14,15 +14,15 @@ > <div id="yui-main"> > <div class="yui-b"> > [% INCLUDE 'members-toolbar.inc' %] >-<form action="/cgi-bin/koha/members/boraccount.pl" method="get"><input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrowernumber %]" /></form> >+<form action="/cgi-bin/koha/members/account.pl" method="get"><input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrowernumber %]" /></form> > > <!-- The manual invoice and credit buttons --> > <div class="statictabs"> > <ul> >- <li class="active"><a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrowernumber %]">Account</a></li> >- <li><a href="/cgi-bin/koha/members/pay.pl?borrowernumber=[% borrowernumber %]" >Pay fines</a></li> >- <li><a href="/cgi-bin/koha/members/maninvoice.pl?borrowernumber=[% borrowernumber %]" >Create manual invoice</a></li> >- <li><a href="/cgi-bin/koha/members/mancredit.pl?borrowernumber=[% borrowernumber %]" >Create manual credit</a></li> >+ <li class="active"><a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Account</a></li> >+ <li><a href="/cgi-bin/koha/members/account_payment.pl?borrowernumber=[% borrowernumber %]" >Pay fines</a></li> >+ <li><a href="/cgi-bin/koha/members/account_debit.pl?borrowernumber=[% borrowernumber %]" >Create manual invoice</a></li> >+ <li><a href="/cgi-bin/koha/members/account_credit.pl?borrowernumber=[% borrowernumber %]" >Create manual credit</a></li> > </ul> > <div class="tabs-container"> > <!-- The table with the account items --> >@@ -51,7 +51,7 @@ > [% IF ( reverse_col ) %] > <td> > [% IF ( account.payment ) %] >- <a href="boraccount.pl?action=reverse&accountlines_id=[% account.accountlines_id %]&borrowernumber=[% account.borrowernumber %]">Reverse</a> >+ <a href="account.pl?action=reverse&accountlines_id=[% account.accountlines_id %]&borrowernumber=[% account.borrowernumber %]">Reverse</a> > [% ELSE %] > > [% END %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/mancredit.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/mancredit.tt >index ff2b6b6..48d10ac 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/mancredit.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/mancredit.tt >@@ -26,14 +26,14 @@ $(document).ready(function(){ > <!-- The manual invoice and credit buttons --> > <div class="statictabs"> > <ul> >- <li><a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrowernumber %]">Account</a></li> >- <li><a href="/cgi-bin/koha/members/pay.pl?borrowernumber=[% borrowernumber %]" >Pay fines</a></li> >- <li><a href="/cgi-bin/koha/members/maninvoice.pl?borrowernumber=[% borrowernumber %]" >Create manual invoice</a></li> >- <li class="active"><a href="/cgi-bin/koha/members/mancredit.pl?borrowernumber=[% borrowernumber %]" >Create manual credit</a></li> >+ <li><a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Account</a></li> >+ <li><a href="/cgi-bin/koha/members/account_payment.pl?borrowernumber=[% borrowernumber %]" >Pay fines</a></li> >+ <li><a href="/cgi-bin/koha/members/account_debit.pl?borrowernumber=[% borrowernumber %]" >Create manual invoice</a></li> >+ <li class="active"><a href="/cgi-bin/koha/members/account_credit.pl?borrowernumber=[% borrowernumber %]" >Create manual credit</a></li> > </ul> > <div class="tabs-container"> > >-<form action="/cgi-bin/koha/members/mancredit.pl" method="post" id="mancredit"> >+<form action="/cgi-bin/koha/members/account_credit.pl" method="post" id="mancredit"> > <input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrowernumber %]" /> > > <fieldset class="rows"> >@@ -48,7 +48,7 @@ $(document).ready(function(){ > <li><label for="amount">Amount: </label><input type="text" name="amount" id="amount" /> Example: 5.00</li> > </ol></fieldset> > >-<fieldset class="action"><input type="submit" name="add" value="Add credit" /> <a class="cancel" href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrowernumber %]">Cancel</a></fieldset> >+<fieldset class="action"><input type="submit" name="add" value="Add credit" /> <a class="cancel" href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Cancel</a></fieldset> > </form> > > </div></div> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/maninvoice.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/maninvoice.tt >index 30a4e20..cb6f1cf 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/maninvoice.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/maninvoice.tt >@@ -26,10 +26,10 @@ $(document).ready(function(){ > <!-- The manual invoice and credit buttons --> > <div class="statictabs"> > <ul> >- <li><a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrowernumber %]">Account</a></li> >- <li><a href="/cgi-bin/koha/members/pay.pl?borrowernumber=[% borrowernumber %]" >Pay fines</a></li> >- <li class="active"><a href="/cgi-bin/koha/members/maninvoice.pl?borrowernumber=[% borrowernumber %]" >Create manual invoice</a></li> >- <li><a href="/cgi-bin/koha/members/mancredit.pl?borrowernumber=[% borrowernumber %]" >Create manual credit</a></li> >+ <li><a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Account</a></li> >+ <li><a href="/cgi-bin/koha/members/account_payment.pl?borrowernumber=[% borrowernumber %]" >Pay fines</a></li> >+ <li class="active"><a href="/cgi-bin/koha/members/account_debit.pl?borrowernumber=[% borrowernumber %]" >Create manual invoice</a></li> >+ <li><a href="/cgi-bin/koha/members/account_credit.pl?borrowernumber=[% borrowernumber %]" >Create manual credit</a></li> > </ul> > <div class="tabs-container"> > >@@ -38,7 +38,7 @@ $(document).ready(function(){ > ERROR an invalid itemnumber was entered, please hit back and try again > [% END %] > [% ELSE %] >-<form action="/cgi-bin/koha/members/maninvoice.pl" method="post" id="maninvoice"><input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrowernumber %]" /> >+<form action="/cgi-bin/koha/members/account_debit.pl" method="post" id="maninvoice"><input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrowernumber %]" /> > <fieldset class="rows"> > <legend>Manual Invoice</legend> > <ol> >@@ -71,7 +71,7 @@ type_fees['[% invoice_types_loo.authorised_value %]'] = "[% invoice_types_loo.li > <li><label for="note">Note: </label><input type="text" name="note" size="50" id="note" /></li> > <li><label for="amount">Amount: </label><input type="text" name="amount" id="amount" /> Example: 5.00</li> > </ol></fieldset> >-<fieldset class="action"><input type="submit" name="add" value="Save" /> <a class="cancel" href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrowernumber %]">Cancel</a></fieldset> >+<fieldset class="action"><input type="submit" name="add" value="Save" /> <a class="cancel" href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Cancel</a></fieldset> > </form> > > [% END %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/pay.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/pay.tt >index 91f1609..da4599e 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/pay.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/pay.tt >@@ -55,15 +55,15 @@ function enableCheckboxActions(){ > <!-- The manual invoice and credit buttons --> > <div class="statictabs"> > <ul> >- <li><a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrower.borrowernumber %]">Account</a></li> >- <li class="active"><a href="/cgi-bin/koha/members/pay.pl?borrowernumber=[% borrower.borrowernumber %]" >Pay fines</a></li> >- <li><a href="/cgi-bin/koha/members/maninvoice.pl?borrowernumber=[% borrower.borrowernumber %]" >Create manual invoice</a></li> >- <li><a href="/cgi-bin/koha/members/mancredit.pl?borrowernumber=[% borrower.borrowernumber %]" >Create manual credit</a></li> >+ <li><a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrower.borrowernumber %]">Account</a></li> >+ <li class="active"><a href="/cgi-bin/koha/members/account_payment.pl?borrowernumber=[% borrower.borrowernumber %]" >Pay fines</a></li> >+ <li><a href="/cgi-bin/koha/members/account_debit.pl?borrowernumber=[% borrower.borrowernumber %]" >Create manual invoice</a></li> >+ <li><a href="/cgi-bin/koha/members/account_credit.pl?borrowernumber=[% borrower.borrowernumber %]" >Create manual credit</a></li> > </ul> > <div class="tabs-container"> > > [% IF ( accounts ) %] >- <form action="/cgi-bin/koha/members/pay.pl" method="post" id="pay-fines-form"> >+ <form action="/cgi-bin/koha/members/account_payment.pl" method="post" id="pay-fines-form"> > <input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrower.borrowernumber %]" /> > <p><span class="checkall"><a id="CheckAll" href="#">Select all</a></span> | <span class="clearall"><a id="CheckNone" href="#">Clear all</a></span></p> > <table id="finest"> >@@ -135,7 +135,7 @@ function enableCheckboxActions(){ > <input type="submit" id="paycollect" name="paycollect" value="Pay amount" class="submit" /> > <input type="submit" name="woall" id="woall" value="Write off all" class="submit" /> > <input type="submit" id="payselected" name="payselected" value="Pay selected" class="submit" /> >-<a class="cancel" href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrower.borrowernumber %]">Cancel</a> >+<a class="cancel" href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrower.borrowernumber %]">Cancel</a> > </fieldset> > </form> > [% ELSE %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/paycollect.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/paycollect.tt >index 9cec275..369b9ec 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/paycollect.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/paycollect.tt >@@ -64,7 +64,7 @@ function moneyFormat(textObj) { > <body id="pat_paycollect" class="pat"> > [% INCLUDE 'header.inc' %] > [% INCLUDE 'patron-search.inc' %] >-<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a> › <a href="/cgi-bin/koha/members/pay.pl?borrowernumber=[% borrower.borrowernumber %]">Pay fines for [% borrower.firstname %] [% borrower.surname %]</a> › [% IF ( pay_individual ) %]Pay an individual fine[% ELSIF ( writeoff_individual ) %]Write off an individual fine[% ELSE %][% IF ( selected_accts ) %]Pay an amount toward selected fines[% ELSE %]Pay an amount toward all fines[% END %][% END %]</div> >+<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a> › <a href="/cgi-bin/koha/members/account_payment.pl?borrowernumber=[% borrower.borrowernumber %]">Pay fines for [% borrower.firstname %] [% borrower.surname %]</a> › [% IF ( pay_individual ) %]Pay an individual fine[% ELSIF ( writeoff_individual ) %]Write off an individual fine[% ELSE %][% IF ( selected_accts ) %]Pay an amount toward selected fines[% ELSE %]Pay an amount toward all fines[% END %][% END %]</div> > > <div id="doc3" class="yui-t2"> > >@@ -78,16 +78,16 @@ function moneyFormat(textObj) { > <div class="statictabs"> > <ul> > <li> >- <a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrower.borrowernumber %]">Account</a> >+ <a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrower.borrowernumber %]">Account</a> > </li> > <li class="active"> >- <a href="/cgi-bin/koha/members/pay.pl?borrowernumber=[% borrower.borrowernumber %]" >Pay fines</a> >+ <a href="/cgi-bin/koha/members/account_payment.pl?borrowernumber=[% borrower.borrowernumber %]" >Pay fines</a> > </li> > <li> >- <a href="/cgi-bin/koha/members/maninvoice.pl?borrowernumber=[% borrower.borrowernumber %]" >Create manual invoice</a> >+ <a href="/cgi-bin/koha/members/account_debit.pl?borrowernumber=[% borrower.borrowernumber %]" >Create manual invoice</a> > </li> > <li> >- <a href="/cgi-bin/koha/members/mancredit.pl?borrowernumber=[% borrower.borrowernumber %]" >Create manual credit</a> >+ <a href="/cgi-bin/koha/members/account_credit.pl?borrowernumber=[% borrower.borrowernumber %]" >Create manual credit</a> > </li> > </ul> > <div class="tabs-container"> >@@ -150,10 +150,10 @@ function moneyFormat(textObj) { > </fieldset> > > <div class="action"><input type="submit" name="submitbutton" value="Confirm" /> >- <a class="cancel" href="/cgi-bin/koha/members/pay.pl?borrowernumber=[% borrower.borrowernumber %]">Cancel</a></div> >+ <a class="cancel" href="/cgi-bin/koha/members/account_payment.pl?borrowernumber=[% borrower.borrowernumber %]">Cancel</a></div> > </form> > [% ELSIF ( writeoff_individual ) %] >- <form name="woindivfine" id="woindivfine" action="/cgi-bin/koha/members/pay.pl" method="post" > >+ <form name="woindivfine" id="woindivfine" action="/cgi-bin/koha/members/account_payment.pl" method="post" > > <fieldset class="rows"> > <legend>Write off an individual fine</legend> > <input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrower.borrowernumber %]" /> >@@ -190,7 +190,7 @@ function moneyFormat(textObj) { > </table> > </fieldset> > <div class="action"><input type="submit" name="confirm_writeoff" id="confirm_writeoff" value="Write off this charge" /> >- <a class="cancel" href="/cgi-bin/koha/members/pay.pl?borrowernumber=[% borrower.borrowernumber %]">Cancel</a></div> >+ <a class="cancel" href="/cgi-bin/koha/members/account_payment.pl?borrowernumber=[% borrower.borrowernumber %]">Cancel</a></div> > </form> > [% ELSE %] > >@@ -218,7 +218,7 @@ function moneyFormat(textObj) { > </ol> > </fieldset> > <div class="action"><input type="submit" name="submitbutton" value="Confirm" /> >- <a class="cancel" href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrower.borrowernumber %]">Cancel</a></div> >+ <a class="cancel" href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrower.borrowernumber %]">Cancel</a></div> > </form> > [% END %] > </div></div> >diff --git a/koha-tmpl/intranet-tmpl/prog/img/details_close.png b/koha-tmpl/intranet-tmpl/prog/img/details_close.png >new file mode 100644 >index 0000000000000000000000000000000000000000..fcc23c63e22f9883bef72c9e3adae3d5ddfb35cc >GIT binary patch >literal 841 >zcmV-P1GfB$P)<h;3K|Lk000e1NJLTq000yK000yS1^@s6jfou%00004XF*Lt007q5 >z)K6G40000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!+et)0RCwB~ >zRZUD&K@grT6<e^<2BXxNUgYOsC0<Bt4}us23L()G;V2>DA_on|3pY;aiIaw_AzX~% >z0wEzG!5U~A62!y<6#_3!Y0@BA($@0c+jVBUFF+~kfo;CbzTKH`cV=g%b|^n=hzi67 >zM5UV3FcF6cUCnu^p}pjrsWm6Ug}98UR-~ZFvWN`g0Fg%+2vP1<MCL$TMcf(~7<d*A >zhi8+?q{cZn2{flQ+9MsM>rl3*$mmwr5rOIH=?}WDABr;u?U4@YDw`9eOu1C&^?L7Z >zY;1fZBc9KT-2A-Q9Uc}tJv}1T-7R)sycF4)8NstzNldzAgSOWc2V?31C|17Z<>j$J >zAke}0_aQSe0l9^R;<1c^#DEC_0!<vD5Y!9~LPc#YEG;d~hC-p&sI^UTwO-OQG&J;} >zzrX)Em?qnMGX}ZE&w!UeCJtN*B%>d$>Do3Jo15TlYl9m;-_3M7y&8+fG<qbPBCP4{ >z?R~-+v*p8K$cDcFH%$rC<VDG8ZmM+-xs??>bP>p=udnZ^^3rY*Ry8&@-XZS}=H{ef >zDUJ>}0_oCdYHA|eDvG0BC2ghK?XIQGd^|3d(Ko2a8<ZPAT3e+oY;8&Da=F}A0hA`T >zOnuWd;BUh;4Eaz@*NbU_ZXd4{Sx%WuX3yjCT&eJS;dde-pZ0t3u1YLb2*-r10&kuC >zM%$mNicFiT%iQ|<`l`Hsd%KE}aRfufjdK;xqP%p!T@uFQ@ipQgE{pKj<mBW>%4c^+ >z2RQuxqA|Bf6p=-Yhg8<rgXi%hN+UisHT6l=w|*kAqtWQwmX?->1x*8ObQBJv5%iB0 >zU9{XrXRDi=!8bAj&V~kvL?Uy+VDJ@gXo|Fa=^duiBKhvUSnKK%G5>85_4~!w&Q6gS >z9~Xt4ozl{)vr6y0nuGJKj&rJgrBbPcMMU#|wJ-Lc4fdkiFZ`>)vh)56_#?mow%h=n >ThIkt{00000NkvXXu0mjfW_^Rc > >literal 0 >HcmV?d00001 > >diff --git a/koha-tmpl/intranet-tmpl/prog/img/details_open.png b/koha-tmpl/intranet-tmpl/prog/img/details_open.png >new file mode 100644 >index 0000000000000000000000000000000000000000..6f034d0f2d5c7902dce190355b12defdc07d6c9a >GIT binary patch >literal 881 >zcmV-%1CIQOP)<h;3K|Lk000e1NJLTq000yK000yS1^@s6jfou%00004XF*Lt007q5 >z)K6G40000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU#14%?dRCwB~ >zRozRIQ5b*Tx%`URmR7!^qREsHr4L~=rAQr;^QNxE%fy>P5xVIgh(4gM3Zjdy!n~2N >zjD^FnHQ1(tR(9cJl^-l~RyvtO-;dMt9M4;+6T9$?ALpFs<F|93kMl~9dYBMthy#dp >zv8JIRHV}$f>)Rcr6nirw3t>UzAPx#r5M&8N9I=W>B2)xRbt)puL>xs_c64-H@%#Or >zXf!&j>$*muHOWXvHo`VD#lg6MPE~+#^!N8aRTO1|?J`J5He@S&wvbBVO8K%ZpNm8y >zAIT}HC7Cxi$gY3tW-XzMtU1`kx+go?tM3CWp(Z#n*^&?X9upjrBoaWeDh>vNcO4E# >z)3UM*kH0>GH%mi2IAp}6%}CKyd$<m+mR^J0^gIXz0v@N+c>~2W6jvjYwyv(OhW7UM >zP7O5aPWUzq$A-}#e>#Hw16_xi<P1dCB5>hIJroxfm&IbSiP6!~SxS;g5FTo6ZM`H( >zlIh)&4}38nXc|&$DyX^!-nt?1)(-JKW(QQ%jr|ydxA>>z)7I8@S=`cW5N4N`m!G77 >zdZMpERgp|rK~d3JRsUp;<Xne@3X*%idAPiyqJn(0DUN1QwCPr>HJ6lA@hNmr@UjvF >zT!Ag6;H&rZ+37vY=g+HO_-wIQtVRQvx7QEFj83+*vi=TLQ+cY^m5t3Z!D|~jv(ZlR >zc>I^mX3LW^WSCo>=P5lkaGKBKE#utS*o(YFK~4deqwi1AMVd+U<ytr#o*<<w-^Js$ >z884M5z!-{%A)S!cjdCNGPft&OAPzDy2v>S~dit;|^yb25sIpdZA`Wys(O1dAvo2(I >ziyc~u+*C?>Z*T8&(cem%afeVS6nDGb_L8EKvNL%#5MBx6)#tX<qR#jZs%_P9tL7%i >z*)oibj0|FLKS7R|cq~%4-ePi*J(zsR8eY2C@n?2cia7tGp51$YpG6bV?X8z@wBCL_ >z4q3asI6I!Ng@uKAgNW99JzxL(z-9>j`d$yLwBMhA-vSH(T>k(8(cOU?00000NkvXX >Hu0mjf8E%<j > >literal 0 >HcmV?d00001 > >diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-account.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-account.tt >index aa70431..382afb2 100644 >--- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-account.tt >+++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-account.tt >@@ -1,9 +1,12 @@ > [% USE Koha %] > [% USE KohaDates %] >+[% USE Currency %] > > [% INCLUDE 'doc-head-open.inc' %][% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog › Your fines and charges > [% INCLUDE 'doc-head-close.inc' %] > [% BLOCK cssinclude %][% END %] >+ >+ > </head> > <body id="opac-account" class="scrollto"> > [% INCLUDE 'masthead.inc' %] >@@ -11,7 +14,7 @@ > <div class="main"> > <ul class="breadcrumb"> > <li><a href="/cgi-bin/koha/opac-main.pl">Home</a> <span class="divider">›</span></li> >- <li>[% FOREACH BORROWER_INF IN BORROWER_INFO %]<a href="/cgi-bin/koha/opac-user.pl">[% BORROWER_INF.firstname %] [% BORROWER_INF.surname %]</a>[% END %] <span class="divider">›</span></li> >+ <li><a href="/cgi-bin/koha/opac-user.pl">[% borrower.firstname %] [% borrower.surname %]</a> <span class="divider">›</span></li> > <li><a href="#">Your fines and charges</a></li> > </ul> > >@@ -25,38 +28,57 @@ > <div class="span10"> > <div id="useraccount" class="maincontent"> > <h3>Fines and charges</h3> >+ [% IF credits || debits %] >+ >+ <p> >+ <h3>Account balance: [% borrower.account_balance | $Currency %]</h3> >+ </p> >+ >+ <div> >+ <div id="account-debits"> >+ <a id="account-debits-switcher" href="#" onclick="return false">View payments</a> >+ <table cellpadding="0" cellspacing="0" border="0" class="display" id="debits-table"> >+ <thead> >+ <tr> >+ <th colspan="99">Fees</th> >+ </tr> >+ <tr> >+ <th></th> >+ <th>ID</th> >+ <th>Description</th> >+ <th>Type</th> >+ <th>Amount</th> >+ <th>Outsanding</th> >+ <th>Created on</th> >+ <th>Updated on</th> >+ </tr> >+ </thead> >+ <tbody></tbody> >+ </table> >+ </div> > >- [% IF ( ACCOUNT_LINES ) %] >- <table class="table table-bordered table-striped"> >- <thead> >- <tr> >- <th>Date</th> >- <th>Description</th> >- <th>Fine amount</th> >- <th>Amount outstanding</th> >- </tr> >- </thead> >- >- <tfoot> >- <tr> >- <th class="sum" colspan="3">Total due</th> >- <td class="sum">[% total %]</td> >- </tr> >- </tfoot> >- >- <tbody> >- [% FOREACH ACCOUNT_LINE IN ACCOUNT_LINES %] >- [% IF ( ACCOUNT_LINE.odd ) %]<tr class="highlight">[% ELSE %]<tr>[% END %] >- <td>[% ACCOUNT_LINE.date | $KohaDates %]</td> >- <td>[% ACCOUNT_LINE.description %] >- [% IF ( ACCOUNT_LINE.title ) %][% ACCOUNT_LINE.title |html %][% END %]</td> >- [% IF ( ACCOUNT_LINE.amountcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% ACCOUNT_LINE.amount %]</td> >- [% IF ( ACCOUNT_LINE.amountoutstandingcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% ACCOUNT_LINE.amountoutstanding %]</td> >- </tr> >- [% END %] >- </tbody> >- >- </table> >+ <div id="account-credits"> >+ <a id="account-credits-switcher" href="#" onclick="return false">View fees</a> >+ <table cellpadding="0" cellspacing="0" border="0" class="display" id="credits-table"> >+ <thead> >+ <tr> >+ <th colspan="99">Payments</th> >+ </tr> >+ <tr> >+ <th></th> >+ <th>ID</th> >+ <th>Notes</th> >+ <th>Type</th> >+ <th>Amount</th> >+ <th>Remaining</th> >+ <th>Created on</th> >+ <th>Updated on</th> >+ </tr> >+ </thead> >+ <tbody></tbody> >+ </table> >+ </div> >+ </div> > [% ELSE %] > <h4>You have no fines or charges</h4> > [% END %] >@@ -67,4 +89,299 @@ > </div> <!-- / .main --> > > [% INCLUDE 'opac-bottom.inc' %] >-[% BLOCK jsinclude %][% END %] >\ No newline at end of file >+[% INCLUDE 'datatables.inc' %] >+ >+<script type="text/javascript"> >+//<![CDATA[ >+$(document).ready(function() { >+ $('#account-credits').hide(); >+ $('#account-debits-switcher').click(function() { >+ $('#account-debits').slideUp(); >+ $('#account-credits').slideDown(); >+ }); >+ $('#account-credits-switcher').click(function() { >+ $('#account-credits').slideUp(); >+ $('#account-debits').slideDown(); >+ }); >+ >+ var anOpen = []; >+ var sImageUrl = "[% interface %]/[% theme %]/images/"; >+ >+ var debitsTable = $('#debits-table').dataTable( { >+ "bProcessing": true, >+ "aoColumns": [ >+ { >+ "mDataProp": null, >+ "sClass": "control center", >+ "sDefaultContent": '<img src="'+sImageUrl+'details_open.png'+'">' >+ }, >+ { "mDataProp": "debit_id" }, >+ { "mDataProp": "description" }, >+ { "mDataProp": "type" }, >+ { "mDataProp": "amount_original" }, >+ { "mDataProp": "amount_outstanding" }, >+ { "mDataProp": "created_on" }, >+ { "mDataProp": "updated_on" } >+ ], >+ "aaData": [ >+ [% FOREACH d IN debits %] >+ { >+ [% PROCESS format_data data=d highlight='debit' %] >+ >+ // Data for related item if there is one linked >+ "title": "[% d.item.biblio.title || d.deleted_item.biblio.title || d.deleted_item.deleted_biblio.title %]", >+ "biblionumber": "[% d.item.biblio.biblionumber || d.deleted_item.biblio.biblionumber %]", >+ "barcode": "[% d.item.barcode || d.deleted_item.barcode %]", >+ "itemnumber": "[% d.item.itemnumber %]", //This way itemnumber will be undef if deleted >+ >+ >+ // Data for related issue if there is one linked >+ [% IF d.issue %] >+ [% SET table = 'issue' %] >+ [% ELSIF d.old_issue %] >+ [% SET table = 'old_issue' %] >+ [% END %] >+ >+ [% IF table %] >+ "issue": { >+ [% PROCESS format_data data=d.$table %] >+ }, >+ [% END %] >+ >+ >+ "account_offsets": [ >+ [% FOREACH ao IN d.account_offsets %] >+ { >+ [% PROCESS format_data data=ao highlight='offset'%] >+ >+ "credit": { >+ [% PROCESS format_data data=ao.credit highlight='credit' %] >+ } >+ }, >+ [% END %] >+ ] >+ >+ }, >+ [% END %] >+ ] >+ } ); >+ >+ $('#debits-table td.control').live( 'click', function () { >+ var nTr = this.parentNode; >+ var i = $.inArray( nTr, anOpen ); >+ >+ if ( i === -1 ) { >+ $('img', this).attr( 'src', sImageUrl+"details_close.png" ); >+ var nDetailsRow = debitsTable.fnOpen( nTr, fnFormatDebitDetails(debitsTable, nTr), 'details' ); >+ $('div.innerDetails', nDetailsRow).slideDown(); >+ anOpen.push( nTr ); >+ } >+ else { >+ $('img', this).attr( 'src', sImageUrl+"details_open.png" ); >+ $('div.innerDetails', $(nTr).next()[0]).slideUp( function () { >+ debitsTable.fnClose( nTr ); >+ anOpen.splice( i, 1 ); >+ } ); >+ } >+ } ); >+ >+ var creditsTable = $('#credits-table').dataTable( { >+ "bProcessing": true, >+ "aoColumns": [ >+ { >+ "mDataProp": null, >+ "sClass": "control center", >+ "sDefaultContent": '<img src="'+sImageUrl+'details_open.png'+'">' >+ }, >+ { "mDataProp": "credit_id" }, >+ { "mDataProp": "notes" }, >+ { "mDataProp": "type" }, >+ { "mDataProp": "amount_paid" }, >+ { "mDataProp": "amount_remaining" }, >+ { "mDataProp": "created_on" }, >+ { "mDataProp": "updated_on" } >+ ], >+ "aaData": [ >+ [% FOREACH c IN credits %] >+ { >+ [% PROCESS format_data data=c highlight='credit' %] >+ >+ "account_offsets": [ >+ [% FOREACH ao IN c.account_offsets %] >+ { >+ [% PROCESS format_data data=ao highlight='offset' %] >+ >+ "debit": { >+ [% PROCESS format_data data=ao.debit highlight='debit' %] >+ } >+ }, >+ [% END %] >+ ] >+ >+ }, >+ [% END %] >+ ] >+ } ); >+ >+ $('#credits-table td.control').live( 'click', function () { >+ var nTr = this.parentNode; >+ var i = $.inArray( nTr, anOpen ); >+ >+ if ( i === -1 ) { >+ $('img', this).attr( 'src', sImageUrl+"details_close.png" ); >+ var nDetailsRow = creditsTable.fnOpen( nTr, fnFormatCreditDetails(creditsTable, nTr), 'details' ); >+ $('div.innerDetails', nDetailsRow).slideDown(); >+ anOpen.push( nTr ); >+ } >+ else { >+ $('img', this).attr( 'src', sImageUrl+"details_open.png" ); >+ $('div.innerDetails', $(nTr).next()[0]).slideUp( function () { >+ creditsTable.fnClose( nTr ); >+ anOpen.splice( i, 1 ); >+ } ); >+ } >+ } ); >+ >+} ); >+ >+function fnFormatDebitDetails( debitsTable, nTr ) { >+ var oData = debitsTable.fnGetData( nTr ); >+ >+ var sOut = '<div class="innerDetails" style="display:none;">'; >+ >+ var account_offsets = oData.account_offsets; >+ >+ sOut += '<ul>'; >+ if ( oData.title ) { >+ sOut += '<li>' + _('Title: '); >+ if ( oData.biblionumber ) { >+ sOut += '<a href="/cgi-bin/koha/opac-detail.pl?biblionumber=' + oData.biblionumber + '">'; >+ } >+ >+ sOut += oData.title; >+ >+ if ( oData.biblionumber ) { >+ sOut += '</a>'; >+ } >+ >+ sOut += '</li>'; >+ } >+ >+ if ( oData.barcode ) { >+ sOut += '<li>' + _('Barcode: ') + oData.barcode + '</li>'; >+ } >+ >+ if ( oData.notes ) { >+ sOut += '<li>' + _('Notes: ') + oData.notes + '</li>'; >+ } >+ >+ sOut += '</ul>'; >+ >+ if ( account_offsets.length ) { >+ sOut += >+ '<div class="innerDetails">' + >+ '<table cellpadding="5" cellspacing="0" border="0" style="margin:10px;">' + >+ '<thead>' + >+ '<tr><th colspan="99">' + _('Payments applied') + '</th></tr>' + >+ '<tr>' + >+ '<th>' + _('ID') + '</th>' + >+ '<th>' + _('Created on') + '</th>' + >+ '<th>' + _('Payment amount') + '</th>' + >+ '<th>' + _('Applied amount') + '</th>' + >+ '<th>' + _('Type') + '</th>' + >+ '<th>' + _('Notes') + '</th>' + >+ '</tr>' + >+ '</thead>' + >+ '<tbody>'; >+ >+ for ( var i = 0; i < account_offsets.length; i++ ) { >+ ao = account_offsets[i]; >+ sOut += >+ '<tr>' + >+ '<td>' + ao.credit_id + '</td>' + >+ '<td>' + ao.created_on + '</td>' + >+ '<td>' + ao.credit.amount_paid + '</td>' + >+ '<td>' + ao.amount + '</td>' + >+ '<td>' + ao.credit.type + '</td>' + >+ '<td>' + ao.credit.notes + '</td>' + >+ '</tr>'; >+ } >+ >+ sOut += >+ '</tbody>'+ >+ '</table>'; >+ } >+ >+ sOut += >+ '</div>'; >+ >+ return sOut; >+} >+ >+function fnFormatCreditDetails( creditsTable, nTr ) { >+ var oData = creditsTable.fnGetData( nTr ); >+ >+ var sOut = '<div class="innerDetails" style="display:none;">'; >+ >+ var account_offsets = oData.account_offsets; >+ >+ if ( account_offsets.length ) { >+ sOut += >+ '<table cellpadding="5" cellspacing="0" border="0" style="margin:10px;">' + >+ '<thead>' + >+ '<tr><th colspan="99">' + _('Fees paid') + '</th></tr>' + >+ '<tr>' + >+ '<th>' + _('ID') + '</th>' + >+ '<th>' + _('Description') + '</th>' + >+ '<th>' + _('Type') + '</th>' + >+ '<th>' + _('Amount') + '</th>' + >+ '<th>' + _('Remaining') + '</th>' + >+ '<th>' + _('Created on') + '</th>' + >+ '<th>' + _('Updated on') + '</th>' + >+ '<th>' + _('Notes') + '</th>' + >+ '</tr>' + >+ '</thead>' + >+ '<tbody>'; >+ >+ for ( var i = 0; i < account_offsets.length; i++ ) { >+ ao = account_offsets[i]; >+ sOut += >+ '<tr>' + >+ '<td>' + ao.debit.debit_id + '</td>' + >+ '<td>' + ao.debit.description + '</td>' + >+ '<td>' + ao.debit.type + '</td>' + >+ '<td>' + ao.debit.amount_original + '</td>' + >+ '<td>' + ao.debit.amount_outstanding + '</td>' + >+ '<td>' + ao.debit.created_on + '</td>' + >+ '<td>' + ao.debit.updated_on + '</td>' + >+ '<td>' + ao.debit.notes + '</td>' + >+ '</tr>'; >+ } >+ >+ sOut += >+ '</tbody>'+ >+ '</table>'; >+ } >+ >+ sOut += >+ '</div>'; >+ >+ return sOut; >+} >+ >+//]]> >+</script> >+ >+[% BLOCK jsinclude %][% END %] >+ >+[% BLOCK format_data %] >+ [% FOREACH key IN data.result_source.columns %] >+ [% IF key.match('^amount') %] >+ "[% key %]": "[% data.$key FILTER $Currency %]", >+ [% ELSIF key.match('_on$') %] >+ "[% key %]": "[% data.$key | $KohaDates %]", >+ [% ELSE %] >+ "[% key %]": "[% data.$key %]", >+ [% END %] >+ [% END %] >+[% END %] >diff --git a/koha-tmpl/opac-tmpl/bootstrap/images/details_close.png b/koha-tmpl/opac-tmpl/bootstrap/images/details_close.png >new file mode 100644 >index 0000000000000000000000000000000000000000..fcc23c63e22f9883bef72c9e3adae3d5ddfb35cc >GIT binary patch >literal 841 >zcmV-P1GfB$P)<h;3K|Lk000e1NJLTq000yK000yS1^@s6jfou%00004XF*Lt007q5 >z)K6G40000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!+et)0RCwB~ >zRZUD&K@grT6<e^<2BXxNUgYOsC0<Bt4}us23L()G;V2>DA_on|3pY;aiIaw_AzX~% >z0wEzG!5U~A62!y<6#_3!Y0@BA($@0c+jVBUFF+~kfo;CbzTKH`cV=g%b|^n=hzi67 >zM5UV3FcF6cUCnu^p}pjrsWm6Ug}98UR-~ZFvWN`g0Fg%+2vP1<MCL$TMcf(~7<d*A >zhi8+?q{cZn2{flQ+9MsM>rl3*$mmwr5rOIH=?}WDABr;u?U4@YDw`9eOu1C&^?L7Z >zY;1fZBc9KT-2A-Q9Uc}tJv}1T-7R)sycF4)8NstzNldzAgSOWc2V?31C|17Z<>j$J >zAke}0_aQSe0l9^R;<1c^#DEC_0!<vD5Y!9~LPc#YEG;d~hC-p&sI^UTwO-OQG&J;} >zzrX)Em?qnMGX}ZE&w!UeCJtN*B%>d$>Do3Jo15TlYl9m;-_3M7y&8+fG<qbPBCP4{ >z?R~-+v*p8K$cDcFH%$rC<VDG8ZmM+-xs??>bP>p=udnZ^^3rY*Ry8&@-XZS}=H{ef >zDUJ>}0_oCdYHA|eDvG0BC2ghK?XIQGd^|3d(Ko2a8<ZPAT3e+oY;8&Da=F}A0hA`T >zOnuWd;BUh;4Eaz@*NbU_ZXd4{Sx%WuX3yjCT&eJS;dde-pZ0t3u1YLb2*-r10&kuC >zM%$mNicFiT%iQ|<`l`Hsd%KE}aRfufjdK;xqP%p!T@uFQ@ipQgE{pKj<mBW>%4c^+ >z2RQuxqA|Bf6p=-Yhg8<rgXi%hN+UisHT6l=w|*kAqtWQwmX?->1x*8ObQBJv5%iB0 >zU9{XrXRDi=!8bAj&V~kvL?Uy+VDJ@gXo|Fa=^duiBKhvUSnKK%G5>85_4~!w&Q6gS >z9~Xt4ozl{)vr6y0nuGJKj&rJgrBbPcMMU#|wJ-Lc4fdkiFZ`>)vh)56_#?mow%h=n >ThIkt{00000NkvXXu0mjfW_^Rc > >literal 0 >HcmV?d00001 > >diff --git a/koha-tmpl/opac-tmpl/bootstrap/images/details_open.png b/koha-tmpl/opac-tmpl/bootstrap/images/details_open.png >new file mode 100644 >index 0000000000000000000000000000000000000000..6f034d0f2d5c7902dce190355b12defdc07d6c9a >GIT binary patch >literal 881 >zcmV-%1CIQOP)<h;3K|Lk000e1NJLTq000yK000yS1^@s6jfou%00004XF*Lt007q5 >z)K6G40000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU#14%?dRCwB~ >zRozRIQ5b*Tx%`URmR7!^qREsHr4L~=rAQr;^QNxE%fy>P5xVIgh(4gM3Zjdy!n~2N >zjD^FnHQ1(tR(9cJl^-l~RyvtO-;dMt9M4;+6T9$?ALpFs<F|93kMl~9dYBMthy#dp >zv8JIRHV}$f>)Rcr6nirw3t>UzAPx#r5M&8N9I=W>B2)xRbt)puL>xs_c64-H@%#Or >zXf!&j>$*muHOWXvHo`VD#lg6MPE~+#^!N8aRTO1|?J`J5He@S&wvbBVO8K%ZpNm8y >zAIT}HC7Cxi$gY3tW-XzMtU1`kx+go?tM3CWp(Z#n*^&?X9upjrBoaWeDh>vNcO4E# >z)3UM*kH0>GH%mi2IAp}6%}CKyd$<m+mR^J0^gIXz0v@N+c>~2W6jvjYwyv(OhW7UM >zP7O5aPWUzq$A-}#e>#Hw16_xi<P1dCB5>hIJroxfm&IbSiP6!~SxS;g5FTo6ZM`H( >zlIh)&4}38nXc|&$DyX^!-nt?1)(-JKW(QQ%jr|ydxA>>z)7I8@S=`cW5N4N`m!G77 >zdZMpERgp|rK~d3JRsUp;<Xne@3X*%idAPiyqJn(0DUN1QwCPr>HJ6lA@hNmr@UjvF >zT!Ag6;H&rZ+37vY=g+HO_-wIQtVRQvx7QEFj83+*vi=TLQ+cY^m5t3Z!D|~jv(ZlR >zc>I^mX3LW^WSCo>=P5lkaGKBKE#utS*o(YFK~4deqwi1AMVd+U<ytr#o*<<w-^Js$ >z884M5z!-{%A)S!cjdCNGPft&OAPzDy2v>S~dit;|^yb25sIpdZA`Wys(O1dAvo2(I >ziyc~u+*C?>Z*T8&(cem%afeVS6nDGb_L8EKvNL%#5MBx6)#tX<qR#jZs%_P9tL7%i >z*)oibj0|FLKS7R|cq~%4-ePi*J(zsR8eY2C@n?2cia7tGp51$YpG6bV?X8z@wBCL_ >z4q3asI6I!Ng@uKAgNW99JzxL(z-9>j`d$yLwBMhA-vSH(T>k(8(cOU?00000NkvXX >Hu0mjf8E%<j > >literal 0 >HcmV?d00001 > >diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-account.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-account.tt >index bb858e8..64cb370 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,382 @@ >+[% SET accountview = 1 %] >+ > [% USE Koha %] > [% USE KohaDates %] >+[% USE Currency %] > > [% INCLUDE 'doc-head-open.inc' %][% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog › Your fines and charges > [% INCLUDE 'doc-head-close.inc' %] > </head> > <body id="opac-account"> > <div id="doc3" class="yui-t1"> >- <div id="bd"> >-[% INCLUDE 'masthead.inc' %] >- >- <div id="yui-main"> >- <div class="yui-b"><div class="yui-g"> >- <div id="useraccount" class="container"> >-<!--CONTENT--> >- [% FOREACH BORROWER_INF IN BORROWER_INFO %] >- <h3><a href="/cgi-bin/koha/opac-user.pl">[% BORROWER_INF.firstname %] [% BORROWER_INF.surname %]'s account</a> ⇢ Fines and charges</h3> >- [% END %] >+ <div id="bd"> > >- [% IF ( ACCOUNT_LINES ) %] >- <table> >- <thead> >- <tr> >- <th>Date</th> >- <th>Description</th> >- <th>Fine amount</th> >- <th>Amount outstanding</th> >- </tr> >- </thead> >- >- <tfoot> >- <tr> >- <th class="sum" colspan="3">Total due</th> >- <td class="sum">[% total %]</td> >- </tr> >- </tfoot> >- >- <tbody> >- [% FOREACH ACCOUNT_LINE IN ACCOUNT_LINES %] >- [% IF ( ACCOUNT_LINE.odd ) %]<tr class="highlight">[% ELSE %]<tr>[% END %] >- <td>[% ACCOUNT_LINE.date | $KohaDates %]</td> >- <td>[% ACCOUNT_LINE.description %] >- [% IF ( ACCOUNT_LINE.title ) %][% ACCOUNT_LINE.title |html %][% END %]</td> >- [% IF ( ACCOUNT_LINE.amountcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% ACCOUNT_LINE.amount %]</td> >- [% IF ( ACCOUNT_LINE.amountoutstandingcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% ACCOUNT_LINE.amountoutstanding %]</td> >- </tr> >- [% END %] >- </tbody> >- >- </table> >- [% ELSE %] >- <h4>You have no fines or charges</h4> >- [% END %] >-</div> >-</div> >-</div> >-</div> >-<div class="yui-b"> >-<div id="leftmenus" class="container"> >-[% INCLUDE 'navigation.inc' IsPatronPage=1 %] >-</div> >-</div> >+ <div id="yui-main"> >+ <div class="yui-b"> >+ <div class="yui-g"> >+ <div id="useraccount" class="container"> >+ <h3><a href="/cgi-bin/koha/opac-user.pl">[% borrower.firstname %] [% borrower.surname %]'s account</a> ⇢ Fines and charges</h3> >+ >+ [% IF credits || debits %] >+ >+ <p> >+ <h3>Account balance: [% borrower.account_balance | $Currency %]</h3> >+ </p> >+ >+ <div> >+ <div id="account-debits"> >+ <a id="account-debits-switcher" href="#" onclick="return false">View payments</a> >+ <table cellpadding="0" cellspacing="0" border="0" class="display" id="debits-table"> >+ <thead> >+ <tr> >+ <th colspan="99">Fees</th> >+ </tr> >+ <tr> >+ <th></th> >+ <th>ID</th> >+ <th>Description</th> >+ <th>Type</th> >+ <th>Amount</th> >+ <th>Outsanding</th> >+ <th>Created on</th> >+ <th>Updated on</th> >+ </tr> >+ </thead> >+ <tbody></tbody> >+ </table> >+ </div> >+ >+ <div id="account-credits"> >+ <a id="account-credits-switcher" href="#" onclick="return false">View fees</a> >+ <table cellpadding="0" cellspacing="0" border="0" class="display" id="credits-table"> >+ <thead> >+ <tr> >+ <th colspan="99">Payments</th> >+ </tr> >+ <tr> >+ <th></th> >+ <th>ID</th> >+ <th>Notes</th> >+ <th>Type</th> >+ <th>Amount</th> >+ <th>Remaining</th> >+ <th>Created on</th> >+ <th>Updated on</th> >+ </tr> >+ </thead> >+ <tbody></tbody> >+ </table> >+ </div> >+ </div> >+ [% ELSE %] >+ <h4>You have no fines or charges</h4> >+ [% END %] >+ </div> >+ </div> >+ </div> >+ </div> >+ >+ <div class="yui-b"> >+ <div id="leftmenus" class="container"> >+ [% INCLUDE 'navigation.inc' IsPatronPage=1 %] >+ </div> >+ </div> > </div> > [% INCLUDE 'opac-bottom.inc' %] >+ >+[% INCLUDE 'datatables.inc' %] >+ >+<script type="text/javascript"> >+//<![CDATA[ >+$(document).ready(function() { >+ $('#account-credits').hide(); >+ $('#account-debits-switcher').click(function() { >+ $('#account-debits').slideUp(); >+ $('#account-credits').slideDown(); >+ }); >+ $('#account-credits-switcher').click(function() { >+ $('#account-credits').slideUp(); >+ $('#account-debits').slideDown(); >+ }); >+ >+ var anOpen = []; >+ var sImageUrl = "[% interface %]/[% theme %]/images/"; >+ >+ var debitsTable = $('#debits-table').dataTable( { >+ "bProcessing": true, >+ "aoColumns": [ >+ { >+ "mDataProp": null, >+ "sClass": "control center", >+ "sDefaultContent": '<img src="'+sImageUrl+'details_open.png'+'">' >+ }, >+ { "mDataProp": "debit_id" }, >+ { "mDataProp": "description" }, >+ { "mDataProp": "type" }, >+ { "mDataProp": "amount_original" }, >+ { "mDataProp": "amount_outstanding" }, >+ { "mDataProp": "created_on" }, >+ { "mDataProp": "updated_on" } >+ ], >+ "aaData": [ >+ [% FOREACH d IN debits %] >+ { >+ [% PROCESS format_data data=d highlight='debit' %] >+ >+ // Data for related item if there is one linked >+ "title": "[% d.item.biblio.title || d.deleted_item.biblio.title || d.deleted_item.deleted_biblio.title %]", >+ "biblionumber": "[% d.item.biblio.biblionumber || d.deleted_item.biblio.biblionumber %]", >+ "barcode": "[% d.item.barcode || d.deleted_item.barcode %]", >+ "itemnumber": "[% d.item.itemnumber %]", //This way itemnumber will be undef if deleted >+ >+ >+ // Data for related issue if there is one linked >+ [% IF d.issue %] >+ [% SET table = 'issue' %] >+ [% ELSIF d.old_issue %] >+ [% SET table = 'old_issue' %] >+ [% END %] >+ >+ [% IF table %] >+ "issue": { >+ [% PROCESS format_data data=d.$table %] >+ }, >+ [% END %] >+ >+ >+ "account_offsets": [ >+ [% FOREACH ao IN d.account_offsets %] >+ { >+ [% PROCESS format_data data=ao highlight='offset'%] >+ >+ "credit": { >+ [% PROCESS format_data data=ao.credit highlight='credit' %] >+ } >+ }, >+ [% END %] >+ ] >+ >+ }, >+ [% END %] >+ ] >+ } ); >+ >+ $('#debits-table td.control').live( 'click', function () { >+ var nTr = this.parentNode; >+ var i = $.inArray( nTr, anOpen ); >+ >+ if ( i === -1 ) { >+ $('img', this).attr( 'src', sImageUrl+"details_close.png" ); >+ var nDetailsRow = debitsTable.fnOpen( nTr, fnFormatDebitDetails(debitsTable, nTr), 'details' ); >+ $('div.innerDetails', nDetailsRow).slideDown(); >+ anOpen.push( nTr ); >+ } >+ else { >+ $('img', this).attr( 'src', sImageUrl+"details_open.png" ); >+ $('div.innerDetails', $(nTr).next()[0]).slideUp( function () { >+ debitsTable.fnClose( nTr ); >+ anOpen.splice( i, 1 ); >+ } ); >+ } >+ } ); >+ >+ var creditsTable = $('#credits-table').dataTable( { >+ "bProcessing": true, >+ "aoColumns": [ >+ { >+ "mDataProp": null, >+ "sClass": "control center", >+ "sDefaultContent": '<img src="'+sImageUrl+'details_open.png'+'">' >+ }, >+ { "mDataProp": "credit_id" }, >+ { "mDataProp": "notes" }, >+ { "mDataProp": "type" }, >+ { "mDataProp": "amount_paid" }, >+ { "mDataProp": "amount_remaining" }, >+ { "mDataProp": "created_on" }, >+ { "mDataProp": "updated_on" } >+ ], >+ "aaData": [ >+ [% FOREACH c IN credits %] >+ { >+ [% PROCESS format_data data=c highlight='credit' %] >+ >+ "account_offsets": [ >+ [% FOREACH ao IN c.account_offsets %] >+ { >+ [% PROCESS format_data data=ao highlight='offset' %] >+ >+ "debit": { >+ [% PROCESS format_data data=ao.debit highlight='debit' %] >+ } >+ }, >+ [% END %] >+ ] >+ >+ }, >+ [% END %] >+ ] >+ } ); >+ >+ $('#credits-table td.control').live( 'click', function () { >+ var nTr = this.parentNode; >+ var i = $.inArray( nTr, anOpen ); >+ >+ if ( i === -1 ) { >+ $('img', this).attr( 'src', sImageUrl+"details_close.png" ); >+ var nDetailsRow = creditsTable.fnOpen( nTr, fnFormatCreditDetails(creditsTable, nTr), 'details' ); >+ $('div.innerDetails', nDetailsRow).slideDown(); >+ anOpen.push( nTr ); >+ } >+ else { >+ $('img', this).attr( 'src', sImageUrl+"details_open.png" ); >+ $('div.innerDetails', $(nTr).next()[0]).slideUp( function () { >+ creditsTable.fnClose( nTr ); >+ anOpen.splice( i, 1 ); >+ } ); >+ } >+ } ); >+ >+} ); >+ >+function fnFormatDebitDetails( debitsTable, nTr ) { >+ var oData = debitsTable.fnGetData( nTr ); >+ >+ var sOut = '<div class="innerDetails" style="display:none;">'; >+ >+ var account_offsets = oData.account_offsets; >+ >+ sOut += '<ul>'; >+ if ( oData.title ) { >+ sOut += '<li>' + _('Title: '); >+ if ( oData.biblionumber ) { >+ sOut += '<a href="/cgi-bin/koha/opac-detail.pl?biblionumber=' + oData.biblionumber + '">'; >+ } >+ >+ sOut += oData.title; >+ >+ if ( oData.biblionumber ) { >+ sOut += '</a>'; >+ } >+ >+ sOut += '</li>'; >+ } >+ >+ if ( oData.barcode ) { >+ sOut += '<li>' + _('Barcode: ') + oData.barcode + '</li>'; >+ } >+ >+ if ( oData.notes ) { >+ sOut += '<li>' + _('Notes: ') + oData.notes + '</li>'; >+ } >+ >+ sOut += '</ul>'; >+ >+ if ( account_offsets.length ) { >+ sOut += >+ '<div class="innerDetails">' + >+ '<table cellpadding="5" cellspacing="0" border="0" style="margin:10px;">' + >+ '<thead>' + >+ '<tr><th colspan="99">' + _('Payments applied') + '</th></tr>' + >+ '<tr>' + >+ '<th>' + _('ID') + '</th>' + >+ '<th>' + _('Created on') + '</th>' + >+ '<th>' + _('Payment amount') + '</th>' + >+ '<th>' + _('Applied amount') + '</th>' + >+ '<th>' + _('Type') + '</th>' + >+ '<th>' + _('Notes') + '</th>' + >+ '</tr>' + >+ '</thead>' + >+ '<tbody>'; >+ >+ for ( var i = 0; i < account_offsets.length; i++ ) { >+ ao = account_offsets[i]; >+ sOut += >+ '<tr>' + >+ '<td>' + ao.credit_id + '</td>' + >+ '<td>' + ao.created_on + '</td>' + >+ '<td>' + ao.credit.amount_paid + '</td>' + >+ '<td>' + ao.amount + '</td>' + >+ '<td>' + ao.credit.type + '</td>' + >+ '<td>' + ao.credit.notes + '</td>' + >+ '</tr>'; >+ } >+ >+ sOut += >+ '</tbody>'+ >+ '</table>'; >+ } >+ >+ sOut += >+ '</div>'; >+ >+ return sOut; >+} >+ >+function fnFormatCreditDetails( creditsTable, nTr ) { >+ var oData = creditsTable.fnGetData( nTr ); >+ >+ var sOut = '<div class="innerDetails" style="display:none;">'; >+ >+ var account_offsets = oData.account_offsets; >+ >+ if ( account_offsets.length ) { >+ sOut += >+ '<table cellpadding="5" cellspacing="0" border="0" style="margin:10px;">' + >+ '<thead>' + >+ '<tr><th colspan="99">' + _('Fees paid') + '</th></tr>' + >+ '<tr>' + >+ '<th>' + _('ID') + '</th>' + >+ '<th>' + _('Description') + '</th>' + >+ '<th>' + _('Type') + '</th>' + >+ '<th>' + _('Amount') + '</th>' + >+ '<th>' + _('Remaining') + '</th>' + >+ '<th>' + _('Created on') + '</th>' + >+ '<th>' + _('Updated on') + '</th>' + >+ '<th>' + _('Notes') + '</th>' + >+ '</tr>' + >+ '</thead>' + >+ '<tbody>'; >+ >+ for ( var i = 0; i < account_offsets.length; i++ ) { >+ ao = account_offsets[i]; >+ sOut += >+ '<tr>' + >+ '<td>' + ao.debit.debit_id + '</td>' + >+ '<td>' + ao.debit.description + '</td>' + >+ '<td>' + ao.debit.type + '</td>' + >+ '<td>' + ao.debit.amount_original + '</td>' + >+ '<td>' + ao.debit.amount_outstanding + '</td>' + >+ '<td>' + ao.debit.created_on + '</td>' + >+ '<td>' + ao.debit.updated_on + '</td>' + >+ '<td>' + ao.debit.notes + '</td>' + >+ '</tr>'; >+ } >+ >+ sOut += >+ '</tbody>'+ >+ '</table>'; >+ } >+ >+ sOut += >+ '</div>'; >+ >+ return sOut; >+} >+ >+//]]> >+</script> >+ >+[% BLOCK jsinclude %][% END %] >+ >+[% BLOCK format_data %] >+ [% FOREACH key IN data.result_source.columns %] >+ [% IF key.match('^amount') %] >+ "[% key %]": "[% data.$key FILTER $Currency %]", >+ [% ELSIF key.match('_on$') %] >+ "[% key %]": "[% data.$key | $KohaDates %]", >+ [% ELSE %] >+ "[% key %]": "[% data.$key %]", >+ [% END %] >+ [% END %] >+[% END %] >diff --git a/koha-tmpl/opac-tmpl/prog/images/details_close.png b/koha-tmpl/opac-tmpl/prog/images/details_close.png >new file mode 100644 >index 0000000000000000000000000000000000000000..fcc23c63e22f9883bef72c9e3adae3d5ddfb35cc >GIT binary patch >literal 841 >zcmV-P1GfB$P)<h;3K|Lk000e1NJLTq000yK000yS1^@s6jfou%00004XF*Lt007q5 >z)K6G40000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!+et)0RCwB~ >zRZUD&K@grT6<e^<2BXxNUgYOsC0<Bt4}us23L()G;V2>DA_on|3pY;aiIaw_AzX~% >z0wEzG!5U~A62!y<6#_3!Y0@BA($@0c+jVBUFF+~kfo;CbzTKH`cV=g%b|^n=hzi67 >zM5UV3FcF6cUCnu^p}pjrsWm6Ug}98UR-~ZFvWN`g0Fg%+2vP1<MCL$TMcf(~7<d*A >zhi8+?q{cZn2{flQ+9MsM>rl3*$mmwr5rOIH=?}WDABr;u?U4@YDw`9eOu1C&^?L7Z >zY;1fZBc9KT-2A-Q9Uc}tJv}1T-7R)sycF4)8NstzNldzAgSOWc2V?31C|17Z<>j$J >zAke}0_aQSe0l9^R;<1c^#DEC_0!<vD5Y!9~LPc#YEG;d~hC-p&sI^UTwO-OQG&J;} >zzrX)Em?qnMGX}ZE&w!UeCJtN*B%>d$>Do3Jo15TlYl9m;-_3M7y&8+fG<qbPBCP4{ >z?R~-+v*p8K$cDcFH%$rC<VDG8ZmM+-xs??>bP>p=udnZ^^3rY*Ry8&@-XZS}=H{ef >zDUJ>}0_oCdYHA|eDvG0BC2ghK?XIQGd^|3d(Ko2a8<ZPAT3e+oY;8&Da=F}A0hA`T >zOnuWd;BUh;4Eaz@*NbU_ZXd4{Sx%WuX3yjCT&eJS;dde-pZ0t3u1YLb2*-r10&kuC >zM%$mNicFiT%iQ|<`l`Hsd%KE}aRfufjdK;xqP%p!T@uFQ@ipQgE{pKj<mBW>%4c^+ >z2RQuxqA|Bf6p=-Yhg8<rgXi%hN+UisHT6l=w|*kAqtWQwmX?->1x*8ObQBJv5%iB0 >zU9{XrXRDi=!8bAj&V~kvL?Uy+VDJ@gXo|Fa=^duiBKhvUSnKK%G5>85_4~!w&Q6gS >z9~Xt4ozl{)vr6y0nuGJKj&rJgrBbPcMMU#|wJ-Lc4fdkiFZ`>)vh)56_#?mow%h=n >ThIkt{00000NkvXXu0mjfW_^Rc > >literal 0 >HcmV?d00001 > >diff --git a/koha-tmpl/opac-tmpl/prog/images/details_open.png b/koha-tmpl/opac-tmpl/prog/images/details_open.png >new file mode 100644 >index 0000000000000000000000000000000000000000..6f034d0f2d5c7902dce190355b12defdc07d6c9a >GIT binary patch >literal 881 >zcmV-%1CIQOP)<h;3K|Lk000e1NJLTq000yK000yS1^@s6jfou%00004XF*Lt007q5 >z)K6G40000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU#14%?dRCwB~ >zRozRIQ5b*Tx%`URmR7!^qREsHr4L~=rAQr;^QNxE%fy>P5xVIgh(4gM3Zjdy!n~2N >zjD^FnHQ1(tR(9cJl^-l~RyvtO-;dMt9M4;+6T9$?ALpFs<F|93kMl~9dYBMthy#dp >zv8JIRHV}$f>)Rcr6nirw3t>UzAPx#r5M&8N9I=W>B2)xRbt)puL>xs_c64-H@%#Or >zXf!&j>$*muHOWXvHo`VD#lg6MPE~+#^!N8aRTO1|?J`J5He@S&wvbBVO8K%ZpNm8y >zAIT}HC7Cxi$gY3tW-XzMtU1`kx+go?tM3CWp(Z#n*^&?X9upjrBoaWeDh>vNcO4E# >z)3UM*kH0>GH%mi2IAp}6%}CKyd$<m+mR^J0^gIXz0v@N+c>~2W6jvjYwyv(OhW7UM >zP7O5aPWUzq$A-}#e>#Hw16_xi<P1dCB5>hIJroxfm&IbSiP6!~SxS;g5FTo6ZM`H( >zlIh)&4}38nXc|&$DyX^!-nt?1)(-JKW(QQ%jr|ydxA>>z)7I8@S=`cW5N4N`m!G77 >zdZMpERgp|rK~d3JRsUp;<Xne@3X*%idAPiyqJn(0DUN1QwCPr>HJ6lA@hNmr@UjvF >zT!Ag6;H&rZ+37vY=g+HO_-wIQtVRQvx7QEFj83+*vi=TLQ+cY^m5t3Z!D|~jv(ZlR >zc>I^mX3LW^WSCo>=P5lkaGKBKE#utS*o(YFK~4deqwi1AMVd+U<ytr#o*<<w-^Js$ >z884M5z!-{%A)S!cjdCNGPft&OAPzDy2v>S~dit;|^yb25sIpdZA`Wys(O1dAvo2(I >ziyc~u+*C?>Z*T8&(cem%afeVS6nDGb_L8EKvNL%#5MBx6)#tX<qR#jZs%_P9tL7%i >z*)oibj0|FLKS7R|cq~%4-ePi*J(zsR8eY2C@n?2cia7tGp51$YpG6bV?X8z@wBCL_ >z4q3asI6I!Ng@uKAgNW99JzxL(z-9>j`d$yLwBMhA-vSH(T>k(8(cOU?00000NkvXX >Hu0mjf8E%<j > >literal 0 >HcmV?d00001 > >diff --git a/members/account.pl b/members/account.pl >new file mode 100755 >index 0000000..ad754f3 >--- /dev/null >+++ b/members/account.pl >@@ -0,0 +1,113 @@ >+#!/usr/bin/perl >+ >+# Copyright 2000-2002 Katipo Communications >+# Copyright 2013 ByWater Solutions >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it under the >+# terms of the GNU General Public License as published by the Free Software >+# Foundation; either version 2 of the License, or (at your option) any later >+# version. >+# >+# Koha is distributed in the hope that it will be useful, but WITHOUT ANY >+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR >+# A PARTICULAR PURPOSE. See the GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License along >+# with Koha; if not, write to the Free Software Foundation, Inc., >+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. >+ >+use Modern::Perl; >+ >+use CGI; >+ >+use C4::Auth; >+use C4::Output; >+use C4::Dates qw/format_date/; >+use C4::Members; >+use C4::Branch; >+use C4::Accounts; >+use C4::Members::Attributes qw(GetBorrowerAttributes); >+use Koha::Database; >+ >+my $cgi = new CGI; >+ >+my ( $template, $loggedinuser, $cookie ) = get_template_and_user( >+ { >+ template_name => "members/account.tt", >+ query => $cgi, >+ type => "intranet", >+ authnotrequired => 0, >+ flagsrequired => { borrowers => 1, updatecharges => 1 }, >+ debug => 1, >+ } >+); >+ >+my $borrowernumber = $cgi->param('borrowernumber'); >+ >+my $borrower = GetMember( 'borrowernumber' => $borrowernumber ); >+ >+my @debits = Koha::Database->new()->schema->resultset('AccountDebit')->search( >+ { 'me.borrowernumber' => $borrowernumber }, >+ { prefetch => { account_offsets => 'credit' } } >+); >+ >+my @credits = Koha::Database->new()->schema->resultset('AccountCredit')->search( >+ { 'me.borrowernumber' => $borrowernumber }, >+ { prefetch => { account_offsets => 'debit' } } >+); >+ >+$template->param( >+ debits => \@debits, >+ credits => \@credits, >+ borrower => $borrower, >+); >+ >+# Standard /members/ borrower details data >+## FIXME: This code is in every /members/ script and should be unified >+ >+if ( $borrower->{'category_type'} eq 'C' ) { >+ my ( $catcodes, $labels ) = >+ GetborCatFromCatType( 'A', 'WHERE category_type = ?' ); >+ my $cnt = scalar(@$catcodes); >+ $template->param( 'CATCODE_MULTI' => 1 ) if $cnt > 1; >+ $template->param( 'catcode' => $catcodes->[0] ) if $cnt == 1; >+} >+ >+my ( $picture, $dberror ) = GetPatronImage( $borrower->{'borrowernumber'} ); >+$template->param( picture => 1 ) if $picture; >+ >+if ( C4::Context->preference('ExtendedPatronAttributes') ) { >+ my $attributes = GetBorrowerAttributes($borrowernumber); >+ $template->param( >+ ExtendedPatronAttributes => 1, >+ extendedattributes => $attributes >+ ); >+} >+ >+$template->param( >+ borrowernumber => $borrowernumber, >+ firstname => $borrower->{'firstname'}, >+ surname => $borrower->{'surname'}, >+ cardnumber => $borrower->{'cardnumber'}, >+ categorycode => $borrower->{'categorycode'}, >+ category_type => $borrower->{'category_type'}, >+ categoryname => $borrower->{'description'}, >+ address => $borrower->{'address'}, >+ address2 => $borrower->{'address2'}, >+ city => $borrower->{'city'}, >+ state => $borrower->{'state'}, >+ zipcode => $borrower->{'zipcode'}, >+ country => $borrower->{'country'}, >+ phone => $borrower->{'phone'}, >+ email => $borrower->{'email'}, >+ branchcode => $borrower->{'branchcode'}, >+ branchname => GetBranchName( $borrower->{'branchcode'} ), >+ is_child => ( $borrower->{'category_type'} eq 'C' ), >+ activeBorrowerRelationship => >+ ( C4::Context->preference('borrowerRelationship') ne '' ), >+ RoutingSerials => C4::Context->preference('RoutingSerials'), >+); >+ >+output_html_with_http_headers $cgi, $cookie, $template->output; >diff --git a/members/account_credit.pl b/members/account_credit.pl >new file mode 100755 >index 0000000..976232a >--- /dev/null >+++ b/members/account_credit.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 C4::Auth; >+use C4::Output; >+use CGI; >+ >+use C4::Koha; >+use C4::Members; >+use C4::Branch; >+use C4::Accounts; >+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..32fec34 >--- /dev/null >+++ b/members/account_payment.pl >@@ -0,0 +1,123 @@ >+#!/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::Accounts; >+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..cc60099 >--- /dev/null >+++ b/members/account_payment_do.pl >@@ -0,0 +1,62 @@ >+#!/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'); >+ >+ my $debit = AddCredit( >+ { >+ borrower => $borrower, >+ 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/mancredit.pl b/members/mancredit.pl >index a2c2258..03079ae 100755 >--- a/members/mancredit.pl >+++ b/members/mancredit.pl >@@ -57,7 +57,7 @@ if ($add){ > $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"); >+ print $input->redirect("/cgi-bin/koha/members/account.pl?borrowernumber=$borrowernumber"); > } > } else { > my ($template, $loggedinuser, $cookie) >diff --git a/members/maninvoice.pl b/members/maninvoice.pl >index c4a9294..4a7cce5 100755 >--- a/members/maninvoice.pl >+++ b/members/maninvoice.pl >@@ -72,7 +72,7 @@ if ($add){ > $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"); >+ print $input->redirect("/cgi-bin/koha/members/account.pl?borrowernumber=$borrowernumber"); > exit; > } > } >diff --git a/members/pay.pl b/members/pay.pl >index 8a8e902..5c95c5e 100755 >--- a/members/pay.pl >+++ b/members/pay.pl >@@ -19,7 +19,7 @@ > # with Koha; if not, write to the Free Software Foundation, Inc., > # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. > >-=head1 pay.pl >+=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 >@@ -197,7 +197,7 @@ sub writeoff_all { > > $borrowernumber = $input->param('borrowernumber'); > print $input->redirect( >- "/cgi-bin/koha/members/boraccount.pl?borrowernumber=$borrowernumber"); >+ "/cgi-bin/koha/members/account.pl?borrowernumber=$borrowernumber"); > return; > } > >diff --git a/members/paycollect.pl b/members/paycollect.pl >index 96ca0fb..48f1d0a 100755 >--- a/members/paycollect.pl >+++ b/members/paycollect.pl >@@ -114,7 +114,7 @@ if ( $total_paid and $total_paid ne '0.00' ) { > $user, $branch, $payment_note ); > } > print $input->redirect( >- "/cgi-bin/koha/members/pay.pl?borrowernumber=$borrowernumber"); >+ "/cgi-bin/koha/members/account_payment.pl?borrowernumber=$borrowernumber"); > } else { > if ($select) { > if ( $select =~ /^([\d,]*).*/ ) { >@@ -130,7 +130,7 @@ if ( $total_paid and $total_paid ne '0.00' ) { > # recordpayment does not return success or failure so lets redisplay the boraccount > > print $input->redirect( >-"/cgi-bin/koha/members/boraccount.pl?borrowernumber=$borrowernumber" >+"/cgi-bin/koha/members/account.pl?borrowernumber=$borrowernumber" > ); > } > } >diff --git a/members/printfeercpt.pl b/members/printfeercpt.pl >index 6a86bc3..8410944 100755 >--- a/members/printfeercpt.pl >+++ b/members/printfeercpt.pl >@@ -1,7 +1,7 @@ > #!/usr/bin/perl > > >-#writen 3rd May 2010 by kmkale@anantcorp.com adapted from boraccount.pl by chris@katipo.oc.nz >+#writen 3rd May 2010 by kmkale@anantcorp.com adapted from account.pl by chris@katipo.oc.nz > #script to print fee receipts > > >diff --git a/members/printinvoice.pl b/members/printinvoice.pl >index 10ae114..cdbaa14 100755 >--- a/members/printinvoice.pl >+++ b/members/printinvoice.pl >@@ -1,6 +1,6 @@ > #!/usr/bin/perl > >-#writen 3rd May 2010 by kmkale@anantcorp.com adapted from boraccount.pl by chris@katipo.oc.nz >+#writen 3rd May 2010 by kmkale@anantcorp.com adapted from account.pl by chris@katipo.oc.nz > #script to print fee receipts > > # Copyright Koustubha Kale >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..9a32c60 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,22 @@ 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; >- } >-} >+warn Data::Dumper::Dumper( $template ); >+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/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 ); > >-- >1.7.2.5
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 6427
:
21922
|
22704
|
22705
|
22708
|
22709
|
22710
|
22741
|
22870
|
22871
|
22872
|
22873
|
22874
|
22875
|
22876
|
22881
|
22889
|
22940
|
22948
|
22949
|
22995
|
23000
|
23137
|
23158
|
23161
|
23171
|
23186
|
23269
|
23275
|
23276
|
23391
|
23392
|
23400
|
23401
|
23402
|
23403
|
23404
|
23405
|
23406
|
23407
|
23408
|
23409
|
23410
|
23411
|
23412
|
23413
|
23420
|
23421
|
23422
|
23423
|
23424
|
23425
|
23426
|
23427
|
23428
|
23429
|
23430
|
23431
|
23432
|
23433
|
23440
|
23441
|
23442
|
23443
|
23444
|
23445
|
23446
|
23447
|
23448
|
23449
|
23450
|
23451
|
23452
|
23453
|
23454
|
23458
|
23459
|
23460
|
23461
|
23462
|
23463
|
23464
|
23465
|
23466
|
23467
|
23468
|
23469
|
23470
|
23471
|
23603
|
23643
|
23644
|
23645
|
23646
|
23647
|
23648
|
23649
|
23650
|
23651
|
23652
|
23653
|
23654
|
23655
|
23656
|
23657
|
23937
|
23938
|
23939
|
23940
|
23941
|
23942
|
23943
|
23944
|
23945
|
23946
|
23947
|
23948
|
23949
|
23950
|
23951
|
24612
|
24613
|
24614
|
24615
|
24616
|
24617
|
24618
|
24619
|
24620
|
24621
|
24622
|
24623
|
24624
|
24625
|
24626
|
24627
|
24628
|
24757
|
24758
|
24759
|
24760
|
24761
|
24762
|
24763
|
24764
|
24765
|
24766
|
24767
|
24768
|
24769
|
24770
|
24771
|
24772
|
24777
|
24792
|
24793
|
24794
|
24795
|
24796
|
24797
|
24798
|
24799
|
24800
|
24801
|
24802
|
24803
|
24804
|
24805
|
24806
|
24807
|
24808
|
24809
|
24810
|
24811
|
24812
|
24813
|
24814
|
24815
|
24816
|
24817
|
24818
|
24819
|
24820
|
24821
|
24822
|
24823
|
24824
|
24825
|
24826
|
24827
|
24828
|
24829
|
24830
|
24831
|
24832
|
24833
|
24834
|
24835
|
24836
|
24837
|
24838
|
24839
|
24840
|
24841
|
24842
|
24843
|
24844
|
25777
|
25778
|
25779
|
25780
|
25781
|
25782
|
25783
|
25784
|
25785
|
25786
|
25787
|
25788
|
25789
|
25790
|
25791
|
25792
|
25793
|
25794
|
25795
|
25796
|
25797
|
25798
|
25799
|
25800
|
25801
|
25802
|
25803
|
25804
|
25805
|
25806
|
25807
|
25808
|
25809
|
25810
|
25811
|
25812
|
25813
|
25814
|
25815
|
25816
|
25930
|
25932
|
25933
|
25934
|
26033
|
26034
|
26035
|
26036
|
26107
|
27167
|
27168
|
27169
|
27170
|
27171
|
27172
|
27173
|
27174
|
27175
|
27176
|
27177
|
27178
|
27179
|
27180
|
27181
|
27182
|
27183
|
27184
|
27185
|
27186
|
27187
|
27189
|
27190
|
27197
|
28067
|
28068
|
28069
|
28070
|
28071
|
28072
|
28073
|
28074
|
28075
|
28076
|
28077
|
28078
|
28079
|
28080
|
28081
|
28082
|
28083
|
28084
|
28085
|
28086
|
28087
|
28088
|
28089
|
28090
|
28091
|
28527
|
28528
|
28529
|
28530
|
28531
|
28532
|
28533
|
28534
|
28535
|
28536
|
28537
|
28538
|
28539
|
28540
|
28541
|
28542
|
28543
|
28544
|
28545
|
28546
|
28547
|
28548
|
28549
|
28550
|
28551
|
28552
|
28553
|
28555
|
28556
|
28561
|
28563
|
28564
|
28795
|
28796
|
28797
|
28798
|
28799
|
28800
|
28801
|
28802
|
28803
|
28804
|
28805
|
28806
|
28807
|
28808
|
28809
|
28810
|
28811
|
28812
|
28813
|
28814
|
28815
|
28816
|
28817
|
28818
|
28819
|
28820
|
28821
|
28822
|
28887
|
28888
|
28889
|
28890
|
28909
|
29176
|
29230
|
29231
|
29232
|
29233
|
29234
|
29235
|
29236
|
29237
|
29238
|
29239
|
29240
|
29241
|
29242
|
29243
|
29244
|
29245
|
29246
|
29247
|
29248
|
29249
|
29250
|
29251
|
29252
|
29253
|
29254
|
29255
|
29256
|
29257
|
29258
|
29259
|
29260
|
29261
|
29262
|
29263
|
29264
|
29265
|
29706
|
29707
|
29708
|
29709
|
29710
|
29711
|
29712
|
29713
|
29714
|
29715
|
29716
|
29717
|
29719
|
29720
|
29721
|
29722
|
29723
|
29724
|
29725
|
29726
|
29727
|
29728
|
29729
|
29730
|
30271
|
30272
|
30273
|
30274
|
30275
|
30276
|
30277
|
30278
|
30279
|
30280
|
30281
|
30282
|
30320
|
30321
|
30322
|
30323
|
30324
|
30325
|
30326
|
30327
|
30328
|
30329
|
30330
|
30331
|
30416
|
30417
|
30418
|
30419
|
30420
|
30421
|
30422
|
30423
|
30424
|
30425
|
30426
|
30427
|
31477
|
31478
|
31479
|
31480
|
31481
|
31482
|
31483
|
31484
|
31485
|
31486
|
31487
|
31488
|
31754
|
31755
|
31756
|
31757
|
31758
|
31759
|
31760
|
31761
|
31762
|
31763
|
31764
|
31765
|
31766
|
31767
|
31768
|
31769
|
31770
|
31771
|
31772
|
31773
|
31774
|
31775
|
31776
|
31777
|
32478
|
32479
|
32480
|
32481
|
32482
|
32483
|
32484
|
32485
|
32486
|
32487
|
32488
|
32489
|
32591
|
32592
|
32593
|
32594
|
32595
|
32596
|
32597
|
32598
|
32599
|
32600
|
32601
|
32602
|
32827
|
32828
|
32829
|
32830
|
32831
|
32832
|
32833
|
32834
|
32835
|
32836
|
32837
|
32838
|
33251
|
33252
|
33253
|
33254
|
33255
|
33256
|
33257
|
33258
|
33259
|
33260
|
33261
|
33262
|
34096
|
34097
|
34098
|
34099
|
34100
|
34101
|
34102
|
34103
|
34104
|
34105
|
34106
|
34107
|
34204
|
34205
|
34206
|
34207
|
34208
|
34209
|
34210
|
34211
|
34212
|
34213
|
34214
|
34215
|
35196
|
35197
|
35198
|
35199
|
35200
|
35201
|
35202
|
35203
|
35204
|
35205
|
35206
|
35207
|
35208
|
35302
|
36324
|
36326
|
36327
|
36328
|
36329
|
36330
|
36331
|
36332
|
36333
|
36334
|
36335
|
36337
|
36338
|
36340
|
36380
|
36391
|
36393
|
37127
|
37128
|
37129
|
37130
|
37131
|
37133
|
37134
|
37135
|
37136
|
37137
|
37138
|
37139
|
37140
|
37141
|
37142
|
37143
|
37147
|
37148
|
37149
|
37150
|
37151
|
37152
|
37153
|
37154
|
37155
|
37156
|
37157
|
37158
|
37159
|
37160
|
37161
|
37162
|
37229
|
37230
|
37231
|
37232
|
37233
|
37234
|
37235
|
37236
|
37237
|
37238
|
37239
|
37240
|
37241
|
37242
|
37243
|
37244
|
38247
|
38248
|
38249
|
38250
|
38251
|
38252
|
38253
|
38254
|
38255
|
38256
|
38257
|
38258
|
38259
|
38260
|
38261
|
38262
|
39063
|
39064
|
39065
|
39066
|
39067
|
39069
|
39070
|
39071
|
39072
|
39073
|
39074
|
39075
|
39076
|
39077
|
39078
|
39079
|
39671
|
39672
|
39673
|
39674
|
39675
|
39676
|
39677
|
39678
|
39679
|
39680
|
39681
|
39682
|
39683
|
39684
|
39685
|
39686