Bug 21909: Make Koha::Account::outstanding_* preserve context
[srvgit] / Koha / Account.pm
index 1541998..304d0e2 100644 (file)
@@ -23,9 +23,12 @@ use Carp;
 use Data::Dumper;
 use List::MoreUtils qw( uniq );
 
+use C4::Circulation qw( ReturnLostItem );
+use C4::Letters;
 use C4::Log qw( logaction );
 use C4::Stats qw( UpdateStats );
 
+use Koha::Patrons;
 use Koha::Account::Lines;
 use Koha::Account::Offsets;
 use Koha::DateUtils qw( dt_from_string );
@@ -79,15 +82,12 @@ sub pay {
 
     my $userenv = C4::Context->userenv;
 
+    my $patron = Koha::Patrons->find( $self->{patron_id} );
+
     # We should remove accountno, it is no longer needed
-    my $last = Koha::Account::Lines->search(
-        {
-            borrowernumber => $self->{patron_id}
-        },
-        {
-            order_by => 'accountno'
-        }
-    )->next();
+    my $last = $self->lines->search(
+        {},
+        { order_by => 'accountno' } )->next();
     my $accountno = $last ? $last->accountno + 1 : 1;
 
     my $manager_id = $userenv ? $userenv->{number} : 0;
@@ -151,9 +151,8 @@ sub pay {
     # than the what was owed on the given line. In that case pay down other
     # lines with remaining balance.
     my @outstanding_fines;
-    @outstanding_fines = Koha::Account::Lines->search(
+    @outstanding_fines = $self->lines->search(
         {
-            borrowernumber    => $self->{patron_id},
             amountoutstanding => { '>' => 0 },
         }
     ) if $balance_remaining > 0;
@@ -260,6 +259,34 @@ sub pay {
         );
     }
 
+    if ( C4::Context->preference('UseEmailReceipts') ) {
+        if (
+            my $letter = C4::Letters::GetPreparedLetter(
+                module                 => 'circulation',
+                letter_code            => uc("ACCOUNT_$type"),
+                message_transport_type => 'email',
+                lang    => $patron->lang,
+                tables => {
+                    borrowers       => $self->{patron_id},
+                    branches        => $self->{library_id},
+                },
+                substitute => {
+                    credit => $payment,
+                    offsets => \@account_offsets,
+                },
+              )
+          )
+        {
+            C4::Letters::EnqueueLetter(
+                {
+                    letter                 => $letter,
+                    borrowernumber         => $self->{patron_id},
+                    message_transport_type => 'email',
+                }
+            ) or warn "can't enqueue letter $letter";
+        }
+    }
+
     return $payment->id;
 }
 
@@ -317,7 +344,8 @@ sub add_credit {
     $schema->txn_do(
         sub {
             # We should remove accountno, it is no longer needed
-            my $last = Koha::Account::Lines->search( { borrowernumber => $self->{patron_id} },
+            my $last = $self->lines->search(
+                {},
                 { order_by => 'accountno' } )->next();
             my $accountno = $last ? $last->accountno + 1 : 1;
 
@@ -388,19 +416,7 @@ Return the balance (sum of amountoutstanding columns)
 
 sub balance {
     my ($self) = @_;
-    my $fines = Koha::Account::Lines->search(
-        {
-            borrowernumber => $self->{patron_id},
-        },
-        {
-            select => [ { sum => 'amountoutstanding' } ],
-            as => ['total_amountoutstanding'],
-        }
-    );
-
-    return ( $fines->count )
-      ? $fines->next->get_column('total_amountoutstanding') + 0
-      : 0;
+    return $self->lines->total_outstanding;
 }
 
 =head3 outstanding_debits
@@ -412,14 +428,29 @@ my $lines = Koha::Account->new({ patron_id => $patron_id })->outstanding_debits;
 sub outstanding_debits {
     my ($self) = @_;
 
-    my $lines = Koha::Account::Lines->search(
+    return $self->lines->search(
         {
-            borrowernumber    => $self->{patron_id},
+            amount            => { '>' => 0 },
             amountoutstanding => { '>' => 0 }
         }
     );
+}
 
-    return $lines;
+=head3 outstanding_credits
+
+my $lines = Koha::Account->new({ patron_id => $patron_id })->outstanding_credits;
+
+=cut
+
+sub outstanding_credits {
+    my ($self) = @_;
+
+    return $self->lines->search(
+        {
+            amount            => { '<' => 0 },
+            amountoutstanding => { '<' => 0 }
+        }
+    );
 }
 
 =head3 non_issues_charges
@@ -457,19 +488,58 @@ sub non_issues_charges {
     }
     @not_fines = map { substr( $_, 0, $ACCOUNT_TYPE_LENGTH ) } uniq(@not_fines);
 
-    my $non_issues_charges = Koha::Account::Lines->search(
+    return $self->lines->search(
         {
-            borrowernumber => $self->{patron_id},
             accounttype    => { -not_in => \@not_fines }
         },
+    )->total_outstanding;
+}
+
+=head3 lines
+
+my $lines = $self->lines;
+
+Return all credits and debits for the user, outstanding or otherwise
+
+=cut
+
+sub lines {
+    my ($self) = @_;
+
+    return Koha::Account::Lines->search(
         {
-            select => [ { sum => 'amountoutstanding' } ],
-            as     => ['non_issues_charges'],
+            borrowernumber => $self->{patron_id},
         }
     );
-    return $non_issues_charges->count
-      ? $non_issues_charges->next->get_column('non_issues_charges') + 0
-      : 0;
+}
+
+=head3 reconcile_balance
+
+$account->reconcile_balance();
+
+Find outstanding credits and use them to pay outstanding debits.
+Currently, this implicitly uses the 'First In First Out' rule for
+applying credits against debits.
+
+=cut
+
+sub reconcile_balance {
+    my ($self) = @_;
+
+    my $outstanding_debits  = $self->outstanding_debits;
+    my $outstanding_credits = $self->outstanding_credits;
+
+    while (     $outstanding_debits->total_outstanding > 0
+            and my $credit = $outstanding_credits->next )
+    {
+        # there's both outstanding debits and credits
+        $credit->apply( { debits => $outstanding_debits } );    # applying credit, no special offset
+
+        $outstanding_debits = $self->outstanding_debits;
+
+    }
+
+    return $self;
 }
 
 1;
@@ -481,9 +551,9 @@ sub non_issues_charges {
 =cut
 
 our $offset_type = {
-    'credit'           => 'Payment',
+    'credit'           => 'Manual Credit',
     'forgiven'         => 'Writeoff',
-    'lost_item_return' => 'Lost Item Return',
+    'lost_item_return' => 'Lost Item',
     'payment'          => 'Payment',
     'writeoff'         => 'Writeoff'
 };