1 package Koha::Account::Line;
3 # This file is part of Koha.
5 # Koha is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
10 # Koha is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with Koha; if not, see <http://www.gnu.org/licenses>.
20 use Data::Dumper qw( Dumper );
22 use C4::Log qw( logaction );
24 use Koha::Account::CreditType;
25 use Koha::Account::DebitType;
26 use Koha::Account::Offsets;
28 use Koha::DateUtils qw( dt_from_string );
29 use Koha::Exceptions::Account;
31 use Koha::Patron::Debarments;
33 use base qw(Koha::Object Koha::Object::Mixin::AdditionalFields);
39 Koha::Account::Line - Koha accountline Object class
49 Return the patron linked to this account line
55 my $rs = $self->_result->patron;
57 return Koha::Patron->_new_from_dbic( $rs );
62 Return the manager linked to this account line
68 my $rs = $self->_result->manager;
70 return Koha::Patron->_new_from_dbic( $rs );
75 Return the item linked to this account line if exists
81 my $rs = $self->_result->itemnumber;
83 return Koha::Item->_new_from_dbic( $rs );
88 Return the checkout linked to this account line if exists
94 return unless $self->issue_id;
96 return Koha::Checkouts->find( $self->issue_id )
97 || Koha::Old::Checkouts->find( $self->issue_id );
102 Returns a Koha::Library object representing where the accountline was recorded
108 my $rs = $self->_result->library;
110 return Koha::Library->_new_from_dbic($rs);
115 Return the credit_type linked to this account line
121 my $rs = $self->_result->credit_type_code;
123 return Koha::Account::CreditType->_new_from_dbic( $rs );
128 Return the debit_type linked to this account line
134 my $rs = $self->_result->debit_type_code;
136 return Koha::Account::DebitType->_new_from_dbic( $rs );
139 =head3 credit_offsets
141 Return the credit_offsets linked to this account line if some exist
146 my ( $self, $cond, $attr ) = @_;
148 unless ( $self->is_credit ) {
149 Koha::Exceptions::Account::IsNotCredit->throw(
150 error => 'Account line ' . $self->id . ' is not a credit'
154 my $rs = $self->_result->search_related( 'account_offsets_credits', $cond, $attr);
156 return Koha::Account::Offsets->_new_from_dbic($rs);
161 Return the debit_offsets linked to this account line if some exist
166 my ( $self, $cond, $attr ) = @_;
168 unless ( $self->is_debit ) {
169 Koha::Exceptions::Account::IsNotDebit->throw(
170 error => 'Account line ' . $self->id . ' is not a debit'
174 my $rs = $self->_result->search_related( 'account_offsets_debits', $cond, $attr);
176 return Koha::Account::Offsets->_new_from_dbic($rs);
181 my $credits = $accountline->credits;
182 my $credits = $accountline->credits( $cond, $attr );
184 Return the credits linked to this account line if some exist.
185 Search conditions and attributes may be passed if you wish to filter
186 the resultant resultant resultset.
191 my ( $self, $cond, $attr ) = @_;
193 unless ( $self->is_debit ) {
194 Koha::Exceptions::Account::IsNotDebit->throw(
195 error => 'Account line ' . $self->id . ' is not a debit'
199 my $cond_m = { map { "credit.".$_ => $cond->{$_} } keys %{$cond}};
201 $self->_result->search_related('account_offsets_debits')
202 ->search_related( 'credit', $cond_m, $attr );
204 return Koha::Account::Lines->_new_from_dbic($rs);
209 my $debits = $accountline->debits;
210 my $debits = $accountline->debits( $cond, $attr );
212 Return the debits linked to this account line if some exist.
213 Search conditions and attributes may be passed if you wish to filter
214 the resultant resultant resultset.
219 my ( $self, $cond, $attr ) = @_;
221 unless ( $self->is_credit ) {
222 Koha::Exceptions::Account::IsNotCredit->throw(
223 error => 'Account line ' . $self->id . ' is not a credit'
227 my $cond_m = { map { "debit.".$_ => $cond->{$_} } keys %{$cond}};
229 $self->_result->search_related('account_offsets_credits')
230 ->search_related( 'debit', $cond_m, $attr );
232 return Koha::Account::Lines->_new_from_dbic($rs);
237 $payment_accountline->void({
238 interface => $interface,
239 [ staff_id => $staff_id, branch => $branchcode ]
242 Used to 'void' (or reverse) a payment/credit. It will roll back any offsets
243 created by the application of this credit upon any debits and mark the credit
244 as 'void' by updating it's status to "VOID".
249 my ($self, $params) = @_;
251 # Make sure it is a credit we are voiding
252 unless ( $self->is_credit ) {
253 Koha::Exceptions::Account::IsNotCredit->throw(
254 error => 'Account line ' . $self->id . 'is not a credit' );
257 # Make sure it is not already voided
258 if ( $self->status && $self->status eq 'VOID' ) {
259 Koha::Exceptions::Account->throw(
260 error => 'Account line ' . $self->id . 'is already void' );
263 # Check for mandatory parameters
264 my @mandatory = ( 'interface' );
265 for my $param (@mandatory) {
266 unless ( defined( $params->{$param} ) ) {
267 Koha::Exceptions::MissingParameter->throw(
268 error => "The $param parameter is mandatory" );
272 # More mandatory parameters
273 if ( $params->{interface} eq 'intranet' ) {
274 my @optional = ( 'staff_id', 'branch' );
275 for my $param (@optional) {
276 unless ( defined( $params->{$param} ) ) {
277 Koha::Exceptions::MissingParameter->throw( error =>
278 "The $param parameter is mandatory when interface is set to 'intranet'"
284 # Find any applied offsets for the credit so we may reverse them
285 my @account_offsets =
286 Koha::Account::Offsets->search(
287 { credit_id => $self->id, amount => { '<' => 0 } } )->as_list;
290 $self->_result->result_source->schema->txn_do(
293 # A 'void' is a 'debit'
294 $void = Koha::Account::Line->new(
296 borrowernumber => $self->borrowernumber,
298 debit_type_code => 'VOID',
299 amount => $self->amount * -1,
300 amountoutstanding => $self->amount * -1,
301 manager_id => $params->{staff_id},
302 interface => $params->{interface},
303 branchcode => $params->{branch},
307 # Record the creation offset
308 Koha::Account::Offset->new(
310 debit_id => $void->id,
312 amount => $self->amount * -1
316 # Link void to payment
318 amountoutstanding => $self->amount,
321 $self->apply( { debits => [$void] } );
323 # Reverse any applied payments
324 foreach my $account_offset (@account_offsets) {
326 Koha::Account::Lines->find( $account_offset->debit_id );
328 next unless $fee_paid;
330 my $amount_paid = $account_offset->amount * -1; # amount paid is stored as a negative amount
331 my $new_amount = $fee_paid->amountoutstanding + $amount_paid;
332 $fee_paid->amountoutstanding($new_amount);
335 Koha::Account::Offset->new(
337 credit_id => $self->id,
338 debit_id => $fee_paid->id,
339 amount => $amount_paid,
345 if ( C4::Context->preference("FinesLog") ) {
348 $self->borrowernumber,
351 action => 'void_payment',
352 borrowernumber => $self->borrowernumber,
353 amount => $self->amount,
354 amountoutstanding => $self->amountoutstanding,
355 description => $self->description,
356 credit_type_code => $self->credit_type_code,
357 payment_type => $self->payment_type,
359 itemnumber => $self->itemnumber,
360 manager_id => $self->manager_id,
362 [ map { $_->unblessed } @account_offsets ],
370 $void->discard_changes;
376 $debit_accountline->cancel();
378 Cancel a charge. It will mark the debit as 'cancelled' by updating its
379 status to 'CANCELLED'.
381 Charges that have been fully or partially paid cannot be cancelled.
383 Returns the cancellation accountline.
388 my ( $self, $params ) = @_;
390 # Make sure it is a charge we are reducing
391 unless ( $self->is_debit ) {
392 Koha::Exceptions::Account::IsNotDebit->throw(
393 error => 'Account line ' . $self->id . 'is not a debit' );
395 if ( $self->debit_type_code eq 'PAYOUT' ) {
396 Koha::Exceptions::Account::IsNotDebit->throw(
397 error => 'Account line ' . $self->id . 'is a payout' );
400 # Make sure it is not already cancelled
401 if ( $self->status && $self->status eq 'CANCELLED' ) {
402 Koha::Exceptions::Account->throw(
403 error => 'Account line ' . $self->id . 'is already cancelled' );
406 # Make sure it has not be paid yet
407 if ( $self->amount != $self->amountoutstanding ) {
408 Koha::Exceptions::Account->throw(
409 error => 'Account line ' . $self->id . 'is already offset' );
412 # Check for mandatory parameters
413 my @mandatory = ( 'staff_id', 'branch' );
414 for my $param (@mandatory) {
415 unless ( defined( $params->{$param} ) ) {
416 Koha::Exceptions::MissingParameter->throw(
417 error => "The $param parameter is mandatory" );
422 $self->_result->result_source->schema->txn_do(
425 # A 'cancellation' is a 'credit'
426 $cancellation = Koha::Account::Line->new(
429 amount => 0 - $self->amount,
430 credit_type_code => 'CANCELLATION',
432 amountoutstanding => 0 - $self->amount,
433 manager_id => $params->{staff_id},
434 borrowernumber => $self->borrowernumber,
435 interface => 'intranet',
436 branchcode => $params->{branch},
440 my $cancellation_offset = Koha::Account::Offset->new(
442 credit_id => $cancellation->accountlines_id,
444 amount => 0 - $self->amount
448 # Link cancellation to charge
449 $cancellation->apply( { debits => [$self] } );
450 $cancellation->status('APPLIED')->store();
452 # Update status of original debit
453 $self->status('CANCELLED')->store;
457 $cancellation->discard_changes;
458 return $cancellation;
463 $charge_accountline->reduce({
464 reduction_type => $reduction_type
467 Used to 'reduce' a charge/debit by adding a credit to offset against the amount
470 May be used to apply a discount whilst retaining the original debit amounts or
471 to apply a full or partial refund for example when a lost item is found and
474 It will immediately be applied to the given debit unless the debit has already
475 been paid, in which case a 'zero' offset will be added to maintain a link to
476 the debit but the outstanding credit will be left so it may be applied to other
479 Reduction type may be one of:
484 Returns the reduction accountline (which will be a credit)
489 my ( $self, $params ) = @_;
491 # Make sure it is a charge we are reducing
492 unless ( $self->is_debit ) {
493 Koha::Exceptions::Account::IsNotDebit->throw(
494 error => 'Account line ' . $self->id . 'is not a debit' );
496 if ( $self->debit_type_code eq 'PAYOUT' ) {
497 Koha::Exceptions::Account::IsNotDebit->throw(
498 error => 'Account line ' . $self->id . 'is a payout' );
501 # Check for mandatory parameters
502 my @mandatory = ( 'interface', 'reduction_type', 'amount' );
503 for my $param (@mandatory) {
504 unless ( defined( $params->{$param} ) ) {
505 Koha::Exceptions::MissingParameter->throw(
506 error => "The $param parameter is mandatory" );
510 # More mandatory parameters
511 if ( $params->{interface} eq 'intranet' ) {
512 my @optional = ( 'staff_id', 'branch' );
513 for my $param (@optional) {
514 unless ( defined( $params->{$param} ) ) {
515 Koha::Exceptions::MissingParameter->throw( error =>
516 "The $param parameter is mandatory when interface is set to 'intranet'"
522 # Make sure the reduction isn't more than the original
523 my $original = $self->amount;
524 Koha::Exceptions::Account::AmountNotPositive->throw(
525 error => 'Reduce amount passed is not positive' )
526 unless ( $params->{amount} > 0 );
527 Koha::Exceptions::ParameterTooHigh->throw( error =>
528 "Amount to reduce ($params->{amount}) is higher than original amount ($original)"
529 ) unless ( $original >= $params->{amount} );
531 $self->credits( { credit_type_code => [ 'DISCOUNT', 'REFUND' ] } )->total;
532 Koha::Exceptions::ParameterTooHigh->throw( error =>
533 "Combined reduction ($params->{amount} + $reduced) is higher than original amount ("
536 unless ( $original >= ( $params->{amount} + abs($reduced) ) );
538 my $status = { 'REFUND' => 'REFUNDED', 'DISCOUNT' => 'DISCOUNTED' };
541 $self->_result->result_source->schema->txn_do(
544 # A 'reduction' is a 'credit'
545 $reduction = Koha::Account::Line->new(
548 amount => 0 - $params->{amount},
549 credit_type_code => $params->{reduction_type},
551 amountoutstanding => 0 - $params->{amount},
552 manager_id => $params->{staff_id},
553 borrowernumber => $self->borrowernumber,
554 interface => $params->{interface},
555 branchcode => $params->{branch},
559 my $reduction_offset = Koha::Account::Offset->new(
561 credit_id => $reduction->accountlines_id,
563 amount => 0 - $params->{amount}
567 # Link reduction to charge (and apply as required)
568 my $debit_outstanding = $self->amountoutstanding;
569 if ( $debit_outstanding >= $params->{amount} ) {
571 $reduction->apply( { debits => [$self] } );
572 $reduction->status('APPLIED')->store();
576 # Zero amount offset used to link original 'debit' to
578 my $link_reduction_offset = Koha::Account::Offset->new(
580 credit_id => $reduction->accountlines_id,
581 debit_id => $self->accountlines_id,
588 # Update status of original debit
589 $self->status( $status->{ $params->{reduction_type} } )->store;
593 $reduction->discard_changes;
599 my $debits = $account->outstanding_debits;
600 my $credit = $credit->apply( { debits => $debits } );
602 Applies the credit to a given debits array reference.
604 =head4 arguments hashref
608 =item debits - Koha::Account::Lines object set of debits
615 my ( $self, $params ) = @_;
617 my $debits = $params->{debits};
619 unless ( $self->is_credit ) {
620 Koha::Exceptions::Account::IsNotCredit->throw(
621 error => 'Account line ' . $self->id . ' is not a credit'
625 my $available_credit = $self->amountoutstanding * -1;
627 unless ( $available_credit > 0 ) {
628 Koha::Exceptions::Account::NoAvailableCredit->throw(
629 error => 'Outstanding credit is ' . $available_credit . ' and cannot be applied'
633 my $schema = Koha::Database->new->schema;
635 $schema->txn_do( sub {
636 for my $debit ( @{$debits} ) {
638 unless ( $debit->is_debit ) {
639 Koha::Exceptions::Account::IsNotDebit->throw(
640 error => 'Account line ' . $debit->id . 'is not a debit'
643 my $amount_to_cancel;
644 my $owed = $debit->amountoutstanding;
646 if ( $available_credit >= $owed ) {
647 $amount_to_cancel = $owed;
649 else { # $available_credit < $debit->amountoutstanding
650 $amount_to_cancel = $available_credit;
653 # record the account offset
654 Koha::Account::Offset->new(
655 { credit_id => $self->id,
656 debit_id => $debit->id,
657 amount => $amount_to_cancel * -1,
662 $available_credit -= $amount_to_cancel;
664 $self->amountoutstanding( $available_credit * -1 )->store;
665 $debit->amountoutstanding( $owed - $amount_to_cancel )->store;
667 # Attempt to renew the item associated with this debit if
669 if ( $self->credit_type_code ne 'FORGIVEN' && $debit->is_renewable ) {
670 my $outcome = $debit->renew_item( { interface => $params->{interface} } );
674 message => 'renewal',
679 $debit->discard_changes; # Refresh values from DB to clear floating point remainders
681 # Same logic exists in Koha::Account::pay
683 C4::Context->preference('MarkLostItemsAsReturned') =~
685 && $debit->debit_type_code
686 && $debit->debit_type_code eq 'LOST'
687 && $debit->amountoutstanding == 0
688 && $debit->itemnumber
690 $self->credit_type_code eq 'LOST_FOUND'
691 && $self->itemnumber == $debit->itemnumber
695 C4::Circulation::ReturnLostItem( $self->borrowernumber,
696 $debit->itemnumber );
699 last if $available_credit == 0;
703 Koha::Patron::Debarments::del_restrictions_after_payment( { borrowernumber => $self->borrowernumber } );
710 $credit_accountline->payout(
712 payout_type => $payout_type,
713 register_id => $register_id,
714 staff_id => $staff_id,
715 interface => 'intranet',
720 Used to 'pay out' a credit to a user.
722 Payout type may be one of any existing payment types
724 Returns the payout debit line that is created via this transaction.
729 my ( $self, $params ) = @_;
731 # Make sure it is a credit we are paying out
732 unless ( $self->is_credit ) {
733 Koha::Exceptions::Account::IsNotCredit->throw(
734 error => 'Account line ' . $self->id . ' is not a credit' );
737 # Check for mandatory parameters
739 ( 'interface', 'staff_id', 'branch', 'payout_type', 'amount' );
740 for my $param (@mandatory) {
741 unless ( defined( $params->{$param} ) ) {
742 Koha::Exceptions::MissingParameter->throw(
743 error => "The $param parameter is mandatory" );
747 # Make sure there is outstanding credit to pay out
748 my $outstanding = -1 * $self->amountoutstanding;
750 $params->{amount} ? $params->{amount} : $outstanding;
751 Koha::Exceptions::Account::AmountNotPositive->throw(
752 error => 'Payout amount passed is not positive' )
753 unless ( $amount > 0 );
754 Koha::Exceptions::ParameterTooHigh->throw(
755 error => "Amount to payout ($amount) is higher than amountoutstanding ($outstanding)" )
756 unless ($outstanding >= $amount );
758 # Make sure we record the cash register for cash transactions
759 Koha::Exceptions::Account::RegisterRequired->throw()
760 if ( C4::Context->preference("UseCashRegisters")
761 && defined( $params->{payout_type} )
762 && ( $params->{payout_type} eq 'CASH' || $params->{payout_type} eq 'SIP00' )
763 && !defined( $params->{cash_register} ) );
766 $self->_result->result_source->schema->txn_do(
769 # A 'payout' is a 'debit'
770 $payout = Koha::Account::Line->new(
774 debit_type_code => 'PAYOUT',
775 payment_type => $params->{payout_type},
776 amountoutstanding => $amount,
777 manager_id => $params->{staff_id},
778 borrowernumber => $self->borrowernumber,
779 interface => $params->{interface},
780 branchcode => $params->{branch},
781 register_id => $params->{cash_register}
785 my $payout_offset = Koha::Account::Offset->new(
787 debit_id => $payout->accountlines_id,
793 $self->apply( { debits => [$payout] } );
794 $self->status('PAID')->store;
798 $payout->discard_changes;
804 This method allows updating a debit or credit on a patron's account
806 $account_line->adjust(
809 type => $update_type,
810 interface => $interface
814 $update_type can be any of:
817 Authors Note: The intention here is that this method is only used
818 to adjust accountlines where the final amount is not yet known/fixed.
819 Incrementing fines are the only existing case at the time of writing,
820 all other forms of 'adjustment' should be recorded as distinct credits
821 or debits and applied, via an offset, to the corresponding debit or credit.
826 my ( $self, $params ) = @_;
828 my $amount = $params->{amount};
829 my $update_type = $params->{type};
830 my $interface = $params->{interface};
832 unless ( exists($Koha::Account::Line::allowed_update->{$update_type}) ) {
833 Koha::Exceptions::Account::UnrecognisedType->throw(
834 error => 'Update type not recognised'
838 my $debit_type_code = $self->debit_type_code;
839 my $account_status = $self->status;
843 $Koha::Account::Line::allowed_update->{$update_type}
846 && ( $Koha::Account::Line::allowed_update->{$update_type}
847 ->{$debit_type_code} eq $account_status )
851 Koha::Exceptions::Account::UnrecognisedType->throw(
852 error => 'Update type not allowed on this debit_type' );
855 my $schema = Koha::Database->new->schema;
860 my $amount_before = $self->amount;
861 my $amount_outstanding_before = $self->amountoutstanding;
862 my $difference = $amount - $amount_before;
863 my $new_outstanding = $amount_outstanding_before + $difference;
865 my $offset_type = $debit_type_code;
866 $offset_type .= ( $difference > 0 ) ? "_INCREASE" : "_DECREASE";
868 # Catch cases that require patron refunds
869 if ( $new_outstanding < 0 ) {
871 Koha::Patrons->find( $self->borrowernumber )->account;
872 my $credit = $account->add_credit(
874 amount => $new_outstanding * -1,
875 type => 'OVERPAYMENT',
876 interface => $interface,
877 ( $update_type eq 'overdue_update' ? ( item_id => $self->itemnumber ) : ()),
880 $new_outstanding = 0;
883 # Update the account line
888 amountoutstanding => $new_outstanding,
892 # Record the account offset
893 my $account_offset = Koha::Account::Offset->new(
895 debit_id => $self->id,
896 type => $offset_type,
897 amount => $difference
901 if ( C4::Context->preference("FinesLog") ) {
903 "FINES", 'UPDATE', #undef becomes UPDATE in UpdateFine
904 $self->borrowernumber,
906 { action => $update_type,
907 borrowernumber => $self->borrowernumber,
909 description => undef,
910 amountoutstanding => $new_outstanding,
911 debit_type_code => $self->debit_type_code,
913 itemnumber => $self->itemnumber,
917 ) if ( $update_type eq 'overdue_update' );
927 my $bool = $line->is_credit;
934 return defined $self->credit_type_code;
939 my $bool = $line->is_debit;
946 return !$self->is_credit;
949 =head3 to_api_mapping
951 This method returns the mapping for representing a Koha::Account::Line object
958 accountlines_id => 'account_line_id',
959 credit_type_code => 'credit_type',
960 debit_type_code => 'debit_type',
961 amountoutstanding => 'amount_outstanding',
962 borrowernumber => 'patron_id',
963 branchcode => 'library_id',
964 issue_id => 'checkout_id',
965 itemnumber => 'item_id',
966 manager_id => 'user_id',
967 note => 'internal_note',
968 register_id => 'cash_register_id',
975 my $bool = $line->is_renewable;
983 $self->amountoutstanding == 0 &&
984 $self->debit_type_code &&
985 $self->debit_type_code eq 'OVERDUE' &&
987 $self->status eq 'UNRETURNED' &&
995 my $renew_result = $line->renew_item;
997 Conditionally attempt to renew an item and return the outcome. This is
998 as a consequence of the fine on an item being fully paid off.
999 Caller must call is_renewable before.
1004 my ($self, $params) = @_;
1008 # We want to reject the call to renew if:
1009 # - The RenewAccruingItemWhenPaid syspref is off
1011 # - The RenewAccruingItemInOpac syspref is off
1012 # - There is an interface param passed and it's value is 'opac'
1015 !C4::Context->preference('RenewAccruingItemWhenPaid') ||
1017 !C4::Context->preference('RenewAccruingItemInOpac') &&
1018 $params->{interface} &&
1019 $params->{interface} eq 'opac'
1025 my $itemnumber = $self->item->itemnumber;
1026 my ( $can_renew, $error ) = C4::Circulation::CanBookBeRenewed(
1028 $self->item->checkout
1031 my $borrowernumber = $self->patron->borrowernumber;
1032 my $due_date = C4::Circulation::AddRenewal(
1034 borrowernumber => $borrowernumber,
1035 itemnumber => $itemnumber,
1036 branch => $self->{branchcode},
1041 itemnumber => $itemnumber,
1042 due_date => $due_date,
1047 itemnumber => $itemnumber,
1057 Specific store method to generate credit number before saving
1064 my $AutoCreditNumber = C4::Context->preference('AutoCreditNumber');
1065 my $credit_number_enabled = $self->is_credit && $self->credit_type->credit_number_enabled;
1067 if ($AutoCreditNumber && $credit_number_enabled && !$self->in_storage) {
1068 if (defined $self->credit_number) {
1069 Koha::Exceptions::Account->throw('AutoCreditNumber is enabled but credit_number is already defined');
1072 my $rs = Koha::Database->new->schema->resultset($self->_type);
1074 if ($AutoCreditNumber eq 'incremental') {
1075 my $max = $rs->search({
1076 credit_number => { -regexp => '^[0-9]+$' }
1078 select => \'CAST(credit_number AS UNSIGNED)',
1079 as => ['credit_number'],
1080 })->get_column('credit_number')->max;
1082 $self->credit_number($max + 1);
1083 } elsif ($AutoCreditNumber eq 'annual') {
1084 my $now = dt_from_string;
1085 my $prefix = sprintf('%d-', $now->year);
1086 my $max = $rs->search({
1088 credit_number => { -regexp => '[0-9]{4}$' },
1089 credit_number => { -like => "$prefix%" },
1091 })->get_column('credit_number')->max;
1092 $max //= $prefix . '0000';
1093 my $incr = substr($max, length $prefix);
1094 $self->credit_number(sprintf('%s%04d', $prefix, $incr + 1));
1095 } elsif ($AutoCreditNumber eq 'branchyyyymmincr') {
1096 my $userenv = C4::Context->userenv;
1098 my $branch = $userenv->{branch};
1099 my $now = dt_from_string;
1100 my $prefix = sprintf('%s%d%02d', $branch, $now->year, $now->month);
1101 my $pattern = $prefix;
1102 $pattern =~ s/([\?%_])/\\$1/g;
1103 my $max = $rs->search({
1105 credit_number => { -regexp => '[0-9]{4}$' },
1106 credit_number => { -like => "$pattern%" },
1108 })->get_column('credit_number')->max;
1109 $max //= $prefix . '0000';
1110 my $incr = substr($max, length $prefix);
1111 $self->credit_number(sprintf('%s%04d', $prefix, $incr + 1));
1116 return $self->SUPER::store();
1119 =head2 Internal methods
1128 return 'Accountline';
1133 =head2 Name mappings
1135 =head3 $allowed_update
1139 our $allowed_update = { 'overdue_update' => { 'OVERDUE' => 'UNRETURNED' } };
1143 Kyle M Hall <kyle@bywatersolutions.com >
1144 Tomás Cohen Arazi <tomascohen@theke.io>
1145 Martin Renvoize <martin.renvoize@ptfs-europe.com>