+ return $self;
+}
+
+=head3 payout
+
+ $credit_accountline->payout(
+ {
+ payout_type => $payout_type,
+ register_id => $register_id,
+ staff_id => $staff_id,
+ interface => 'intranet',
+ amount => $amount
+ }
+ );
+
+Used to 'pay out' a credit to a user.
+
+Payout type may be one of any existing payment types
+
+Returns the payout debit line that is created via this transaction.
+
+=cut
+
+sub payout {
+ my ( $self, $params ) = @_;
+
+ # Make sure it is a credit we are paying out
+ unless ( $self->is_credit ) {
+ Koha::Exceptions::Account::IsNotCredit->throw(
+ error => 'Account line ' . $self->id . ' is not a credit' );
+ }
+
+ # Check for mandatory parameters
+ my @mandatory =
+ ( 'interface', 'staff_id', 'branch', 'payout_type', 'amount' );
+ for my $param (@mandatory) {
+ unless ( defined( $params->{$param} ) ) {
+ Koha::Exceptions::MissingParameter->throw(
+ error => "The $param parameter is mandatory" );
+ }
+ }
+
+ # Make sure there is outstanding credit to pay out
+ my $outstanding = -1 * $self->amountoutstanding;
+ my $amount =
+ $params->{amount} ? $params->{amount} : $outstanding;
+ Koha::Exceptions::Account::AmountNotPositive->throw(
+ error => 'Payout amount passed is not positive' )
+ unless ( $amount > 0 );
+ Koha::Exceptions::ParameterTooHigh->throw(
+ error => "Amount to payout ($amount) is higher than amountoutstanding ($outstanding)" )
+ unless ($outstanding >= $amount );
+
+ # Make sure we record the cash register for cash transactions
+ Koha::Exceptions::Account::RegisterRequired->throw()
+ if ( C4::Context->preference("UseCashRegisters")
+ && defined( $params->{payout_type} )
+ && ( $params->{payout_type} eq 'CASH' )
+ && !defined( $params->{cash_register} ) );
+
+ my $payout;
+ $self->_result->result_source->schema->txn_do(
+ sub {
+
+ # A 'payout' is a 'debit'
+ $payout = Koha::Account::Line->new(
+ {
+ date => \'NOW()',
+ amount => $amount,
+ debit_type_code => 'PAYOUT',
+ payment_type => $params->{payout_type},
+ amountoutstanding => $amount,
+ manager_id => $params->{staff_id},
+ borrowernumber => $self->borrowernumber,
+ interface => $params->{interface},
+ branchcode => $params->{branch},
+ register_id => $params->{cash_register}
+ }
+ )->store();
+
+ my $payout_offset = Koha::Account::Offset->new(
+ {
+ debit_id => $payout->accountlines_id,
+ type => 'CREATE',
+ amount => $amount
+ }
+ )->store();
+
+ $self->apply( { debits => [$payout] } );
+ $self->status('PAID')->store;
+ }
+ );
+
+ $payout->discard_changes;
+ return $payout;
+}
+
+=head3 adjust
+
+This method allows updating a debit or credit on a patron's account
+
+ $account_line->adjust(
+ {
+ amount => $amount,
+ type => $update_type,
+ interface => $interface
+ }
+ );
+
+$update_type can be any of:
+ - overdue_update
+
+Authors Note: The intention here is that this method is only used
+to adjust accountlines where the final amount is not yet known/fixed.
+Incrementing fines are the only existing case at the time of writing,
+all other forms of 'adjustment' should be recorded as distinct credits
+or debits and applied, via an offset, to the corresponding debit or credit.
+
+=cut
+
+sub adjust {
+ my ( $self, $params ) = @_;
+
+ my $amount = $params->{amount};
+ my $update_type = $params->{type};
+ my $interface = $params->{interface};
+
+ unless ( exists($Koha::Account::Line::allowed_update->{$update_type}) ) {
+ Koha::Exceptions::Account::UnrecognisedType->throw(
+ error => 'Update type not recognised'
+ );
+ }
+
+ my $debit_type_code = $self->debit_type_code;
+ my $account_status = $self->status;
+ unless (
+ (
+ exists(
+ $Koha::Account::Line::allowed_update->{$update_type}
+ ->{$debit_type_code}
+ )
+ && ( $Koha::Account::Line::allowed_update->{$update_type}
+ ->{$debit_type_code} eq $account_status )
+ )
+ )
+ {
+ Koha::Exceptions::Account::UnrecognisedType->throw(
+ error => 'Update type not allowed on this debit_type' );
+ }
+
+ my $schema = Koha::Database->new->schema;
+
+ $schema->txn_do(
+ sub {
+
+ my $amount_before = $self->amount;
+ my $amount_outstanding_before = $self->amountoutstanding;
+ my $difference = $amount - $amount_before;
+ my $new_outstanding = $amount_outstanding_before + $difference;
+
+ my $offset_type = $debit_type_code;
+ $offset_type .= ( $difference > 0 ) ? "_INCREASE" : "_DECREASE";
+
+ # Catch cases that require patron refunds
+ if ( $new_outstanding < 0 ) {
+ my $account =
+ Koha::Patrons->find( $self->borrowernumber )->account;
+ my $credit = $account->add_credit(
+ {
+ amount => $new_outstanding * -1,
+ type => 'OVERPAYMENT',
+ interface => $interface,
+ ( $update_type eq 'overdue_update' ? ( item_id => $self->itemnumber ) : ()),
+ }
+ );
+ $new_outstanding = 0;
+ }
+
+ # Update the account line
+ $self->set(
+ {
+ date => \'NOW()',
+ amount => $amount,
+ amountoutstanding => $new_outstanding,
+ }
+ )->store();
+
+ # Record the account offset
+ my $account_offset = Koha::Account::Offset->new(
+ {
+ debit_id => $self->id,
+ type => $offset_type,
+ amount => $difference
+ }
+ )->store();
+
+ if ( C4::Context->preference("FinesLog") ) {
+ logaction(
+ "FINES", 'UPDATE', #undef becomes UPDATE in UpdateFine
+ $self->borrowernumber,
+ Dumper(
+ { action => $update_type,
+ borrowernumber => $self->borrowernumber,
+ amount => $amount,
+ description => undef,
+ amountoutstanding => $new_outstanding,
+ debit_type_code => $self->debit_type_code,
+ note => undef,
+ itemnumber => $self->itemnumber,
+ manager_id => undef,
+ }
+ )
+ ) if ( $update_type eq 'overdue_update' );
+ }
+ }
+ );
+
+ return $self;