From 86ee0a0abdf00a0a974741bd8b9f596bca71fb7e 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                                  |  313 ++++++-------
 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                |  134 +++++
 Koha/Schema/Result/AccountDebit.pm                 |  177 +++++++
 Koha/Schema/Result/AccountOffset.pm                |  118 +++++
 Koha/Schema/Result/Borrower.pm                     |  132 +++---
 Koha/Schema/Result/Issue.pm                        |    9 +-
 Koha/Schema/Result/OldIssue.pm                     |   28 +-
 Koha/Template/Plugin/Currency.pm                   |   64 +++
 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             |  166 +++++++
 .../prog/en/modules/members/account_credit.tt      |   91 ++++
 .../prog/en/modules/members/account_debit.tt       |  108 ++++
 .../prog/en/modules/members/account_payment.tt     |  200 ++++++++
 .../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 +-
 members/account.pl                                 |  111 +++++
 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/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 +-
 t/db_dependent/Accounts.t                          |  189 +++++++-
 t/db_dependent/Circulation.t                       |   22 +-
 51 files changed, 3372 insertions(+), 515 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 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

diff --git a/C4/Circulation.pm b/C4/Circulation.pm
index 0a22b76..0e26358 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' ";
-    }
-    $uquery .= " where (accountlines_id = ?)";
-    my $usth = $dbh->prepare($uquery);
-    return $usth->execute(@bind);
+        $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,
+            }
+        );
+    } 
+
+    return $fine->update();
 }
 
 =head2 _FixAccountForLostAndReturned
 
-  &_FixAccountForLostAndReturned($itemnumber, [$borrowernumber, $barcode]);
+  &_FixAccountForLostAndReturned($itemnumber);
 
-Calculates the charge for a book lost and returned.
-
-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..3c55dce 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..56b57ed
--- /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..bf8e076
--- /dev/null
+++ b/Koha/Schema/Result/AccountCredit.pm
@@ -0,0 +1,134 @@
+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
+
+
+# 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..8206c2b
--- /dev/null
+++ b/Koha/Schema/Result/AccountDebit.pm
@@ -0,0 +1,177 @@
+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
+
+
+# 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..a3946b4 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,39 +1053,9 @@ __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
 
 
 # You can replace this text with custom content, and it will be preserved on regeneration
diff --git a/Koha/Schema/Result/Issue.pm b/Koha/Schema/Result/Issue.pm
index 282c802..99274ea 100644
--- a/Koha/Schema/Result/Issue.pm
+++ b/Koha/Schema/Result/Issue.pm
@@ -187,7 +187,14 @@ __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..fb24f93
--- /dev/null
+++ b/Koha/Template/Plugin/Currency.pm
@@ -0,0 +1,64 @@
+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;
+
+    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 ) = @_;
+
+    return $self->format($amount);
+}
+
+sub format {
+    my ( $self, $amount, $format ) = @_;
+
+    return currency_format( $self->{active_currency}->{currency},
+        $amount, $format || FMT_HTML );
+}
+
+sub format_without_symbol {
+    my ( $self, $amount ) = @_;
+
+    return substr( $self->format( $amount, FMT_SYMBOL ), 1 );
+}
+
+sub symbol {
+    my ($self) = @_;
+
+    return currency_symbol( $self->{active_currency}->{'currency'}, SYM_HTML );
+}
+
+1;
diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql
index fefc985..81aa284 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..db6df4e 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..f5b2706 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 ( finesview ) %]<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..fbaea81 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 ( finesview ) %]<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 &amp; Charges:</span> Patron has  <a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrowernumber %]">Outstanding fees &amp; charges[% IF ( chargesamount ) %] of [% chargesamount %][% END %]</a>.
+            <span class="circ-hlt">Fees &amp; Charges:</span> Patron has  <a href="/cgi-bin/koha/members/account.pl?borrowernumber=[% borrowernumber %]">Outstanding fees &amp; 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..a12337d
--- /dev/null
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/account.tt
@@ -0,0 +1,166 @@
+[% USE KohaDates %]
+[% USE Currency %]
+[% INCLUDE 'doc-head-open.inc' %]
+<title>Koha &rsaquo; Patrons &rsaquo; Account for [% INCLUDE 'patron-title.inc' %]</title>
+[% INCLUDE 'doc-head-close.inc' %]
+<style type="text/css">
+#account-tabs-debits, #account-tabs-credits {
+    min-height:100px;
+}
+#account-tabs { 
+    position: relative; 
+    padding-right: 6.5em; 
+} 
+#account-tabs .ui-tabs-nav { 
+    position: absolute; 
+    right: 0.25em; 
+    top: 1em; 
+    bottom: 0.25em; 
+    width: 6em; 
+    padding: 0.2em 0.2em 0.2em 0em; 
+} 
+#account-tabs .ui-tabs-nav li { 
+    width: 100%; 
+    border-left: none; 
+    border-bottom-width: 1px !important; 
+    -moz-border-radius: 0px 4px 4px 0px; 
+    -webkit-border-radius: 0px 4px 4px 0px; 
+    border-radius: 0px 4px 4px 0px; 
+    overflow: hidden; 
+} 
+#account-tabs .ui-tabs-nav li.ui-tabs-selected, 
+#account-tabs .ui-tabs-nav li.ui-state-active { 
+    left: -1px; 
+    border-left: 1px solid transparent; 
+} 
+#account-tabs .ui-tabs-nav li a { 
+    width: 100%; 
+} 
+</style>
+<script>
+$(function() {
+    $( "#account-tabs" ).tabs();
+    $( "#debits-accordion" ).accordion();
+});
+</script>
+</head>
+<body id="pat_borraccount" class="pat">
+[% INCLUDE 'header.inc' %]
+[% INCLUDE 'patron-search.inc' %]
+
+<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a>  &rsaquo; 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 class="tabs-container">
+
+                        <p>
+                            <h3>Account balance: [% borrower.account_balance | $Currency %]</h3>
+                        </p>
+
+                        <div>
+                            <div id="account-tabs">
+                                <ul>
+                                    <li>
+                                        <a href="#account-tabs-debits">Fees</a>
+                                    </li>
+                                    <li>
+                                     <a href="#account-tabs-credits">Payments</a>
+                                    </li>
+                                </ul>
+
+                                <div id="account-tabs-debits">
+                                    <div id="debits-accordion">
+                                        [% FOREACH d IN debits %]
+                                            <h3>
+                                                &nbsp;&nbsp;&nbsp;&nbsp;
+                                                [% d.amount_outstanding | $Currency %] ( [% d.amount_original | $Currency %] )
+                                                [% d.created_on | $KohaDates %]
+
+                                                [% d.description %]
+                                            </h3>
+
+                                            <div>
+                                                [% IF d.notes %]
+                                                    <p>
+                                                        Notes: <i>[% d.notes %]</i>
+                                                    </p>
+                                                [% END %]
+
+                                                [% IF d.updated_on %]
+                                                    <p>
+                                                        Last modified: [% d.updated_on | $KohaDates %]
+                                                    </p>
+                                                [% END %]
+
+                                                [% IF d.account_offsets %]
+                                                    <table>
+                                                        <thead>
+                                                            <tr>
+                                                                <th colspan="5">Offsets</th>
+                                                            </tr>
+                                                            <tr>
+                                                                <th>ID</td>
+                                                                <th>Date applied</th>
+                                                                <th>Amount applied</th>
+                                                                <th>Type</th>
+                                                                <th>Notes</th>
+                                                            </tr>
+                                                        </thead>
+                                                                    
+                                                        <tbody>
+                                                            [% FOREACH ao IN d.account_offsets %]
+                                                                <tr>
+                                                                    <td>[% ao.credit.credit_id %]</td>
+                                                                    <td>[% ao.created_on | $KohaDates %]</td>
+                                                                    <td>[% ao.amount | $Currency %]</td>
+                                                                    <td>[% ao.credit.type %]</td>
+                                                                    <td>[% ao.credit.notes %]</td>
+                                                                </tr>
+                                                            [% END %]
+                                                        </tbody>
+                                                    </table>
+                                                [% END %]
+                                            </div>
+                                        [% END %]
+                                    </div>
+                                </div>
+
+                                <div id="account-tabs-credits">
+                                    Payments
+                                </div>
+                            </div>
+                        </div>
+                    </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_credit.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_credit.tt
new file mode 100644
index 0000000..10abb1d
--- /dev/null
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_credit.tt
@@ -0,0 +1,91 @@
+[% INCLUDE 'doc-head-open.inc' %]
+<title>Koha &rsaquo; Borrowers &rsaquo; 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> &rsaquo; <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a>  &rsaquo; 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..6bdff70
--- /dev/null
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_debit.tt
@@ -0,0 +1,108 @@
+[% INCLUDE 'doc-head-open.inc' %]
+<title>Koha &rsaquo; Borrowers &rsaquo; 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> &rsaquo; <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a>  &rsaquo; 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..766c001
--- /dev/null
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/account_payment.tt
@@ -0,0 +1,200 @@
+[% USE Currency %]
+[% INCLUDE 'doc-head-open.inc' %]
+<title>Koha &rsaquo; Patrons &rsaquo; 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> 
+        &rsaquo; <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a>  
+        &rsaquo; 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>&nbsp;</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/boraccount.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/boraccount.tt
index d64c63b..48730b5 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&amp;accountlines_id=[% account.accountlines_id %]&amp;borrowernumber=[% account.borrowernumber %]">Reverse</a>
+		<a href="account.pl?action=reverse&amp;accountlines_id=[% account.accountlines_id %]&amp;borrowernumber=[% account.borrowernumber %]">Reverse</a>
 	[% ELSE %]
 		&nbsp;
 	[% 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..b7e4396 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..d9ef1f7 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..96202df 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> &rsaquo; <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a>  &rsaquo; <a href="/cgi-bin/koha/members/pay.pl?borrowernumber=[% borrower.borrowernumber %]">Pay fines for [% borrower.firstname %] [% borrower.surname %]</a> &rsaquo; [% 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> &rsaquo; <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a>  &rsaquo; <a href="/cgi-bin/koha/members/account_payment.pl?borrowernumber=[% borrower.borrowernumber %]">Pay fines for [% borrower.firstname %] [% borrower.surname %]</a> &rsaquo; [% 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/members/account.pl b/members/account.pl
new file mode 100755
index 0000000..87507dc
--- /dev/null
+++ b/members/account.pl
@@ -0,0 +1,111 @@
+#!/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( { borrowernumber => $borrowernumber } );
+
+$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/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..2f36dd2 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..f8be9b8 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/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