X-Git-Url: http://koha-dev.rot13.org:8081/gitweb/?a=blobdiff_plain;f=Koha%2FAccount.pm;h=304d0e2743cbfd49ade62ebe9550b2038d740173;hb=d3ff671f215398ad51a6ce550c33c0c6ca3aa30a;hp=3e3d76adeb7abfc49afb256c32b4db3ef2b84153;hpb=6355791848585f7ef490b1c63f64790b9a783e73;p=srvgit diff --git a/Koha/Account.pm b/Koha/Account.pm index 3e3d76adeb..304d0e2743 100644 --- a/Koha/Account.pm +++ b/Koha/Account.pm @@ -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 ); @@ -73,20 +76,18 @@ sub pay { my $library_id = $params->{library_id}; my $lines = $params->{lines}; my $type = $params->{type} || 'payment'; + my $payment_type = $params->{payment_type} || undef; my $account_type = $params->{account_type}; my $offset_type = $params->{offset_type} || $type eq 'writeoff' ? 'Writeoff' : 'Payment'; 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; @@ -150,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; @@ -216,6 +216,7 @@ sub pay { amount => 0 - $amount, description => $description, accounttype => $account_type, + payment_type => $payment_type, amountoutstanding => 0 - $balance_remaining, manager_id => $manager_id, note => $note, @@ -258,9 +259,153 @@ 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; } +=head3 add_credit + +This method allows adding credits to a patron's account + +my $credit_line = Koha::Account->new({ patron_id => $patron_id })->add_credit( + { + amount => $amount, + description => $description, + note => $note, + user_id => $user_id, + library_id => $library_id, + sip => $sip, + payment_type => $payment_type, + type => $credit_type, + item_id => $item_id + } +); + +$credit_type can be any of: + - 'credit' + - 'payment' + - 'forgiven' + - 'lost_item_return' + - 'writeoff' + +=cut + +sub add_credit { + + my ( $self, $params ) = @_; + + # amount is passed as a positive value, but we store credit as negative values + my $amount = $params->{amount} * -1; + my $description = $params->{description} // q{}; + my $note = $params->{note} // q{}; + my $user_id = $params->{user_id}; + my $library_id = $params->{library_id}; + my $sip = $params->{sip}; + my $payment_type = $params->{payment_type}; + my $type = $params->{type} || 'payment'; + my $item_id = $params->{item_id}; + + my $schema = Koha::Database->new->schema; + + my $account_type = $Koha::Account::account_type->{$type}; + $account_type .= $sip + if defined $sip && + $type eq 'payment'; + + my $line; + + $schema->txn_do( + sub { + # We should remove accountno, it is no longer needed + my $last = $self->lines->search( + {}, + { order_by => 'accountno' } )->next(); + my $accountno = $last ? $last->accountno + 1 : 1; + + # Insert the account line + $line = Koha::Account::Line->new( + { borrowernumber => $self->{patron_id}, + date => \'NOW()', + amount => $amount, + description => $description, + accounttype => $account_type, + amountoutstanding => $amount, + payment_type => $payment_type, + note => $note, + manager_id => $user_id, + itemnumber => $item_id + } + )->store(); + + # Record the account offset + my $account_offset = Koha::Account::Offset->new( + { credit_id => $line->id, + type => $Koha::Account::offset_type->{$type}, + amount => $amount + } + )->store(); + + UpdateStats( + { branch => $library_id, + type => $type, + amount => $amount, + borrowernumber => $self->{patron_id}, + accountno => $accountno, + } + ) if grep { $type eq $_ } ('payment', 'writeoff') ; + + if ( C4::Context->preference("FinesLog") ) { + logaction( + "FINES", 'CREATE', + $self->{patron_id}, + Dumper( + { action => "create_$type", + borrowernumber => $self->{patron_id}, + accountno => $accountno, + amount => $amount, + description => $description, + amountoutstanding => $amount, + accounttype => $account_type, + note => $note, + itemnumber => $item_id, + manager_id => $user_id, + } + ) + ); + } + } + ); + + return $line; +} + =head3 balance my $balance = $self->balance @@ -271,19 +416,41 @@ Return the balance (sum of amountoutstanding columns) sub balance { my ($self) = @_; - my $fines = Koha::Account::Lines->search( - { - borrowernumber => $self->{patron_id}, - }, + return $self->lines->total_outstanding; +} + +=head3 outstanding_debits + +my $lines = Koha::Account->new({ patron_id => $patron_id })->outstanding_debits; + +=cut + +sub outstanding_debits { + my ($self) = @_; + + return $self->lines->search( { - select => [ { sum => 'amountoutstanding' } ], - as => ['total_amountoutstanding'], + amount => { '>' => 0 }, + amountoutstanding => { '>' => 0 } } ); +} + +=head3 outstanding_credits + +my $lines = Koha::Account->new({ patron_id => $patron_id })->outstanding_credits; + +=cut + +sub outstanding_credits { + my ($self) = @_; - my $total = $fines->count - ? $fines->next->get_column('total_amountoutstanding') + 0 - : 0; + return $self->lines->search( + { + amount => { '<' => 0 }, + amountoutstanding => { '<' => 0 } + } + ); } =head3 non_issues_charges @@ -321,23 +488,88 @@ 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; +=head2 Name mappings + +=head3 $offset_type + +=cut + +our $offset_type = { + 'credit' => 'Manual Credit', + 'forgiven' => 'Writeoff', + 'lost_item_return' => 'Lost Item', + 'payment' => 'Payment', + 'writeoff' => 'Writeoff' +}; + +=head3 $account_type + +=cut + +our $account_type = { + 'credit' => 'C', + 'forgiven' => 'FOR', + 'lost_item_return' => 'CR', + 'payment' => 'Pay', + 'writeoff' => 'W' +}; + =head1 AUTHOR Kyle M Hall