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>.
23 use C4::Log qw(logaction);
24 use C4::Overdues qw(GetFine);
26 use Koha::Account::CreditType;
27 use Koha::Account::DebitType;
28 use Koha::Account::Offsets;
31 use Koha::Exceptions::Account;
34 use base qw(Koha::Object);
40 Koha::Account::Line - Koha accountline Object class
50 Return the patron linked to this account line
56 my $rs = $self->_result->borrowernumber;
58 return Koha::Patron->_new_from_dbic( $rs );
63 Return the item linked to this account line if exists
69 my $rs = $self->_result->itemnumber;
71 return Koha::Item->_new_from_dbic( $rs );
76 Return the checkout linked to this account line if exists
82 return unless $self->issue_id ;
84 $self->{_checkout} ||= Koha::Checkouts->find( $self->issue_id );
85 $self->{_checkout} ||= Koha::Old::Checkouts->find( $self->issue_id );
86 return $self->{_checkout};
91 Returns a Koha::Library object representing where the accountline was recorded
97 my $rs = $self->_result->library;
99 return Koha::Library->_new_from_dbic($rs);
104 Return the credit_type linked to this account line
110 my $rs = $self->_result->credit_type_code;
112 return Koha::Account::CreditType->_new_from_dbic( $rs );
117 Return the debit_type linked to this account line
123 my $rs = $self->_result->debit_type_code;
125 return Koha::Account::DebitType->_new_from_dbic( $rs );
128 =head3 credit_offsets
130 Return the credit_offsets linked to this account line if some exist
135 my ( $self, $cond, $attr ) = @_;
137 unless ( $self->is_credit ) {
138 Koha::Exceptions::Account::IsNotCredit->throw(
139 error => 'Account line ' . $self->id . ' is not a credit'
143 my $rs = $self->_result->search_related( 'account_offsets_credits', $cond, $attr);
145 return Koha::Account::Offsets->_new_from_dbic($rs);
150 Return the debit_offsets linked to this account line if some exist
155 my ( $self, $cond, $attr ) = @_;
157 unless ( $self->is_debit ) {
158 Koha::Exceptions::Account::IsNotDebit->throw(
159 error => 'Account line ' . $self->id . ' is not a debit'
163 my $rs = $self->_result->search_related( 'account_offsets_debits', $cond, $attr);
165 return Koha::Account::Offsets->_new_from_dbic($rs);
170 my $credits = $accountline->credits;
171 my $credits = $accountline->credits( $cond, $attr );
173 Return the credits linked to this account line if some exist.
174 Search conditions and attributes may be passed if you wish to filter
175 the resultant resultant resultset.
180 my ( $self, $cond, $attr ) = @_;
182 unless ( $self->is_debit ) {
183 Koha::Exceptions::Account::IsNotDebit->throw(
184 error => 'Account line ' . $self->id . ' is not a debit'
188 my $cond_m = { map { "credit.".$_ => $cond->{$_} } keys %{$cond}};
190 $self->_result->search_related('account_offsets_debits')
191 ->search_related( 'credit', $cond_m, $attr );
193 return Koha::Account::Lines->_new_from_dbic($rs);
198 my $debits = $accountline->debits;
199 my $debits = $accountline->debits( $cond, $attr );
201 Return the debits linked to this account line if some exist.
202 Search conditions and attributes may be passed if you wish to filter
203 the resultant resultant resultset.
208 my ( $self, $cond, $attr ) = @_;
210 unless ( $self->is_credit ) {
211 Koha::Exceptions::Account::IsNotCredit->throw(
212 error => 'Account line ' . $self->id . ' is not a credit'
216 my $cond_m = { map { "debit.".$_ => $cond->{$_} } keys %{$cond}};
218 $self->_result->search_related('account_offsets_credits')
219 ->search_related( 'debit', $cond_m, $attr );
221 return Koha::Account::Lines->_new_from_dbic($rs);
226 $payment_accountline->void({
227 interface => $interface,
228 [ staff_id => $staff_id, branch => $branchcode ]
231 Used to 'void' (or reverse) a payment/credit. It will roll back any offsets
232 created by the application of this credit upon any debits and mark the credit
233 as 'void' by updating it's status to "VOID".
238 my ($self, $params) = @_;
240 # Make sure it is a credit we are voiding
241 unless ( $self->is_credit ) {
242 Koha::Exceptions::Account::IsNotCredit->throw(
243 error => 'Account line ' . $self->id . 'is not a credit' );
246 # Make sure it is not already voided
247 if ( $self->status && $self->status eq 'VOID' ) {
248 Koha::Exceptions::Account->throw(
249 error => 'Account line ' . $self->id . 'is already void' );
252 # Check for mandatory parameters
253 my @mandatory = ( 'interface' );
254 for my $param (@mandatory) {
255 unless ( defined( $params->{$param} ) ) {
256 Koha::Exceptions::MissingParameter->throw(
257 error => "The $param parameter is mandatory" );
261 # More mandatory parameters
262 if ( $params->{interface} eq 'intranet' ) {
263 my @optional = ( 'staff_id', 'branch' );
264 for my $param (@optional) {
265 unless ( defined( $params->{$param} ) ) {
266 Koha::Exceptions::MissingParameter->throw( error =>
267 "The $param parameter is mandatory when interface is set to 'intranet'"
273 # Find any applied offsets for the credit so we may reverse them
274 my @account_offsets =
275 Koha::Account::Offsets->search(
276 { credit_id => $self->id, amount => { '<' => 0 } } );
279 $self->_result->result_source->schema->txn_do(
282 # A 'void' is a 'debit'
283 $void = Koha::Account::Line->new(
285 borrowernumber => $self->borrowernumber,
287 debit_type_code => 'VOID',
288 amount => $self->amount * -1,
289 amountoutstanding => $self->amount * -1,
290 manager_id => $params->{staff_id},
291 interface => $params->{interface},
292 branchcode => $params->{branch},
296 # Record the creation offset
297 Koha::Account::Offset->new(
299 debit_id => $void->id,
301 amount => $self->amount * -1
305 # Reverse any applied payments
306 foreach my $account_offset (@account_offsets) {
308 Koha::Account::Lines->find( $account_offset->debit_id );
310 next unless $fee_paid;
312 my $amount_paid = $account_offset->amount * -1; # amount paid is stored as a negative amount
313 my $new_amount = $fee_paid->amountoutstanding + $amount_paid;
314 $fee_paid->amountoutstanding($new_amount);
317 Koha::Account::Offset->new(
319 credit_id => $self->id,
320 debit_id => $fee_paid->id,
321 amount => $amount_paid,
327 # Link void to payment
329 amountoutstanding => $self->amount,
332 $self->apply({ debits => [$void]});
334 if ( C4::Context->preference("FinesLog") ) {
337 $self->borrowernumber,
340 action => 'void_payment',
341 borrowernumber => $self->borrowernumber,
342 amount => $self->amount,
343 amountoutstanding => $self->amountoutstanding,
344 description => $self->description,
345 credit_type_code => $self->credit_type_code,
346 payment_type => $self->payment_type,
348 itemnumber => $self->itemnumber,
349 manager_id => $self->manager_id,
351 [ map { $_->unblessed } @account_offsets ],
359 $void->discard_changes;
365 $debit_accountline->cancel();
367 Cancel a charge. It will mark the debit as 'cancelled' by updating its
368 status to 'CANCELLED'.
370 Charges that have been fully or partially paid cannot be cancelled.
372 Returns the cancellation accountline.
377 my ( $self, $params ) = @_;
379 # Make sure it is a charge we are reducing
380 unless ( $self->is_debit ) {
381 Koha::Exceptions::Account::IsNotDebit->throw(
382 error => 'Account line ' . $self->id . 'is not a debit' );
384 if ( $self->debit_type_code eq 'PAYOUT' ) {
385 Koha::Exceptions::Account::IsNotDebit->throw(
386 error => 'Account line ' . $self->id . 'is a payout' );
389 # Make sure it is not already cancelled
390 if ( $self->status && $self->status eq 'CANCELLED' ) {
391 Koha::Exceptions::Account->throw(
392 error => 'Account line ' . $self->id . 'is already cancelled' );
395 # Make sure it has not be paid yet
396 if ( $self->amount != $self->amountoutstanding ) {
397 Koha::Exceptions::Account->throw(
398 error => 'Account line ' . $self->id . 'is already offset' );
401 # Check for mandatory parameters
402 my @mandatory = ( 'staff_id', 'branch' );
403 for my $param (@mandatory) {
404 unless ( defined( $params->{$param} ) ) {
405 Koha::Exceptions::MissingParameter->throw(
406 error => "The $param parameter is mandatory" );
411 $self->_result->result_source->schema->txn_do(
414 # A 'cancellation' is a 'credit'
415 $cancellation = Koha::Account::Line->new(
418 amount => 0 - $self->amount,
419 credit_type_code => 'CANCELLATION',
421 amountoutstanding => 0 - $self->amount,
422 manager_id => $params->{staff_id},
423 borrowernumber => $self->borrowernumber,
424 interface => 'intranet',
425 branchcode => $params->{branch},
429 my $cancellation_offset = Koha::Account::Offset->new(
431 credit_id => $cancellation->accountlines_id,
432 type => 'CANCELLATION',
433 amount => $self->amount
437 # Link cancellation to charge
438 $cancellation->apply(
441 offset_type => 'CANCELLATION'
444 $cancellation->status('APPLIED')->store();
446 # Update status of original debit
447 $self->status('CANCELLED')->store;
451 $cancellation->discard_changes;
452 return $cancellation;
457 $charge_accountline->reduce({
458 reduction_type => $reduction_type
461 Used to 'reduce' a charge/debit by adding a credit to offset against the amount
464 May be used to apply a discount whilst retaining the original debit amounts or
465 to apply a full or partial refund for example when a lost item is found and
468 It will immediately be applied to the given debit unless the debit has already
469 been paid, in which case a 'zero' offset will be added to maintain a link to
470 the debit but the outstanding credit will be left so it may be applied to other
473 Reduction type may be one of:
478 Returns the reduction accountline (which will be a credit)
483 my ( $self, $params ) = @_;
485 # Make sure it is a charge we are reducing
486 unless ( $self->is_debit ) {
487 Koha::Exceptions::Account::IsNotDebit->throw(
488 error => 'Account line ' . $self->id . 'is not a debit' );
490 if ( $self->debit_type_code eq 'PAYOUT' ) {
491 Koha::Exceptions::Account::IsNotDebit->throw(
492 error => 'Account line ' . $self->id . 'is a payout' );
495 # Check for mandatory parameters
496 my @mandatory = ( 'interface', 'reduction_type', 'amount' );
497 for my $param (@mandatory) {
498 unless ( defined( $params->{$param} ) ) {
499 Koha::Exceptions::MissingParameter->throw(
500 error => "The $param parameter is mandatory" );
504 # More mandatory parameters
505 if ( $params->{interface} eq 'intranet' ) {
506 my @optional = ( 'staff_id', 'branch' );
507 for my $param (@optional) {
508 unless ( defined( $params->{$param} ) ) {
509 Koha::Exceptions::MissingParameter->throw( error =>
510 "The $param parameter is mandatory when interface is set to 'intranet'"
516 # Make sure the reduction isn't more than the original
517 my $original = $self->amount;
518 Koha::Exceptions::Account::AmountNotPositive->throw(
519 error => 'Reduce amount passed is not positive' )
520 unless ( $params->{amount} > 0 );
521 Koha::Exceptions::ParameterTooHigh->throw( error =>
522 "Amount to reduce ($params->{amount}) is higher than original amount ($original)"
523 ) unless ( $original >= $params->{amount} );
525 $self->credits( { credit_type_code => [ 'DISCOUNT', 'REFUND' ] } )->total;
526 Koha::Exceptions::ParameterTooHigh->throw( error =>
527 "Combined reduction ($params->{amount} + $reduced) is higher than original amount ("
530 unless ( $original >= ( $params->{amount} + abs($reduced) ) );
532 my $status = { 'REFUND' => 'REFUNDED', 'DISCOUNT' => 'DISCOUNTED' };
535 $self->_result->result_source->schema->txn_do(
538 # A 'reduction' is a 'credit'
539 $reduction = Koha::Account::Line->new(
542 amount => 0 - $params->{amount},
543 credit_type_code => $params->{reduction_type},
545 amountoutstanding => 0 - $params->{amount},
546 manager_id => $params->{staff_id},
547 borrowernumber => $self->borrowernumber,
548 interface => $params->{interface},
549 branchcode => $params->{branch},
553 my $reduction_offset = Koha::Account::Offset->new(
555 credit_id => $reduction->accountlines_id,
556 type => uc( $params->{reduction_type} ),
557 amount => $params->{amount}
561 # Link reduction to charge (and apply as required)
562 my $debit_outstanding = $self->amountoutstanding;
563 if ( $debit_outstanding >= $params->{amount} ) {
568 offset_type => uc( $params->{reduction_type} )
571 $reduction->status('APPLIED')->store();
575 # Zero amount offset used to link original 'debit' to
577 my $link_reduction_offset = Koha::Account::Offset->new(
579 credit_id => $reduction->accountlines_id,
580 debit_id => $self->accountlines_id,
581 type => uc( $params->{reduction_type} ),
587 # Update status of original debit
588 $self->status( $status->{ $params->{reduction_type} } )->store;
592 $reduction->discard_changes;
598 my $debits = $account->outstanding_debits;
599 my $credit = $credit->apply( { debits => $debits, [ offset_type => $offset_type ] } );
601 Applies the credit to a given debits array reference.
603 =head4 arguments hashref
607 =item debits - Koha::Account::Lines object set of debits
609 =item offset_type (optional) - a string indicating the offset type (valid values are those from
610 the 'account_offset_types' table)
617 my ( $self, $params ) = @_;
619 my $debits = $params->{debits};
620 my $offset_type = $params->{offset_type} // 'Credit Applied';
622 unless ( $self->is_credit ) {
623 Koha::Exceptions::Account::IsNotCredit->throw(
624 error => 'Account line ' . $self->id . ' is not a credit'
628 my $available_credit = $self->amountoutstanding * -1;
630 unless ( $available_credit > 0 ) {
631 Koha::Exceptions::Account::NoAvailableCredit->throw(
632 error => 'Outstanding credit is ' . $available_credit . ' and cannot be applied'
636 my $schema = Koha::Database->new->schema;
638 $schema->txn_do( sub {
639 for my $debit ( @{$debits} ) {
641 unless ( $debit->is_debit ) {
642 Koha::Exceptions::Account::IsNotDebit->throw(
643 error => 'Account line ' . $debit->id . 'is not a debit'
646 my $amount_to_cancel;
647 my $owed = $debit->amountoutstanding;
649 if ( $available_credit >= $owed ) {
650 $amount_to_cancel = $owed;
652 else { # $available_credit < $debit->amountoutstanding
653 $amount_to_cancel = $available_credit;
656 # record the account offset
657 Koha::Account::Offset->new(
658 { credit_id => $self->id,
659 debit_id => $debit->id,
660 amount => $amount_to_cancel * -1,
661 type => $offset_type,
665 $available_credit -= $amount_to_cancel;
667 $self->amountoutstanding( $available_credit * -1 )->store;
668 $debit->amountoutstanding( $owed - $amount_to_cancel )->store;
670 # Attempt to renew the item associated with this debit if
672 if ( $self->credit_type_code ne 'FORGIVEN' && $debit->is_renewable ) {
673 my $outcome = $debit->renew_item( { interface => $params->{interface} } );
677 message => 'renewal',
682 $debit->discard_changes; # Refresh values from DB to clear floating point remainders
684 # Same logic exists in Koha::Account::pay
686 C4::Context->preference('MarkLostItemsAsReturned') =~
688 && $debit->debit_type_code
689 && $debit->debit_type_code eq 'LOST'
690 && $debit->amountoutstanding == 0
691 && $debit->itemnumber
693 $self->credit_type_code eq 'LOST_FOUND'
694 && $self->itemnumber == $debit->itemnumber
698 C4::Circulation::ReturnLostItem( $self->borrowernumber,
699 $debit->itemnumber );
702 last if $available_credit == 0;
711 $credit_accountline->payout(
713 payout_type => $payout_type,
714 register_id => $register_id,
715 staff_id => $staff_id,
716 interface => 'intranet',
721 Used to 'pay out' a credit to a user.
723 Payout type may be one of any existing payment types
725 Returns the payout debit line that is created via this transaction.
730 my ( $self, $params ) = @_;
732 # Make sure it is a credit we are paying out
733 unless ( $self->is_credit ) {
734 Koha::Exceptions::Account::IsNotCredit->throw(
735 error => 'Account line ' . $self->id . ' is not a credit' );
738 # Check for mandatory parameters
740 ( 'interface', 'staff_id', 'branch', 'payout_type', 'amount' );
741 for my $param (@mandatory) {
742 unless ( defined( $params->{$param} ) ) {
743 Koha::Exceptions::MissingParameter->throw(
744 error => "The $param parameter is mandatory" );
748 # Make sure there is outstanding credit to pay out
749 my $outstanding = -1 * $self->amountoutstanding;
751 $params->{amount} ? $params->{amount} : $outstanding;
752 Koha::Exceptions::Account::AmountNotPositive->throw(
753 error => 'Payout amount passed is not positive' )
754 unless ( $amount > 0 );
755 Koha::Exceptions::ParameterTooHigh->throw(
756 error => "Amount to payout ($amount) is higher than amountoutstanding ($outstanding)" )
757 unless ($outstanding >= $amount );
759 # Make sure we record the cash register for cash transactions
760 Koha::Exceptions::Account::RegisterRequired->throw()
761 if ( C4::Context->preference("UseCashRegisters")
762 && defined( $params->{payout_type} )
763 && ( $params->{payout_type} eq 'CASH' )
764 && !defined( $params->{cash_register} ) );
767 $self->_result->result_source->schema->txn_do(
770 # A 'payout' is a 'debit'
771 $payout = Koha::Account::Line->new(
775 debit_type_code => 'PAYOUT',
776 payment_type => $params->{payout_type},
777 amountoutstanding => $amount,
778 manager_id => $params->{staff_id},
779 borrowernumber => $self->borrowernumber,
780 interface => $params->{interface},
781 branchcode => $params->{branch},
782 register_id => $params->{cash_register}
786 my $payout_offset = Koha::Account::Offset->new(
788 debit_id => $payout->accountlines_id,
794 $self->apply( { debits => [$payout], offset_type => 'PAYOUT' } );
795 $self->status('PAID')->store;
799 $payout->discard_changes;
805 This method allows updating a debit or credit on a patron's account
807 $account_line->adjust(
810 type => $update_type,
811 interface => $interface
815 $update_type can be any of:
818 Authors Note: The intention here is that this method is only used
819 to adjust accountlines where the final amount is not yet known/fixed.
820 Incrementing fines are the only existing case at the time of writing,
821 all other forms of 'adjustment' should be recorded as distinct credits
822 or debits and applied, via an offset, to the corresponding debit or credit.
827 my ( $self, $params ) = @_;
829 my $amount = $params->{amount};
830 my $update_type = $params->{type};
831 my $interface = $params->{interface};
833 unless ( exists($Koha::Account::Line::allowed_update->{$update_type}) ) {
834 Koha::Exceptions::Account::UnrecognisedType->throw(
835 error => 'Update type not recognised'
839 my $debit_type_code = $self->debit_type_code;
840 my $account_status = $self->status;
844 $Koha::Account::Line::allowed_update->{$update_type}
847 && ( $Koha::Account::Line::allowed_update->{$update_type}
848 ->{$debit_type_code} eq $account_status )
852 Koha::Exceptions::Account::UnrecognisedType->throw(
853 error => 'Update type not allowed on this debit_type' );
856 my $schema = Koha::Database->new->schema;
861 my $amount_before = $self->amount;
862 my $amount_outstanding_before = $self->amountoutstanding;
863 my $difference = $amount - $amount_before;
864 my $new_outstanding = $amount_outstanding_before + $difference;
866 my $offset_type = $debit_type_code;
867 $offset_type .= ( $difference > 0 ) ? "_INCREASE" : "_DECREASE";
869 # Catch cases that require patron refunds
870 if ( $new_outstanding < 0 ) {
872 Koha::Patrons->find( $self->borrowernumber )->account;
873 my $credit = $account->add_credit(
875 amount => $new_outstanding * -1,
876 type => 'OVERPAYMENT',
877 interface => $interface,
878 ( $update_type eq 'overdue_update' ? ( item_id => $self->itemnumber ) : ()),
881 $new_outstanding = 0;
884 # Update the account line
889 amountoutstanding => $new_outstanding,
893 # Record the account offset
894 my $account_offset = Koha::Account::Offset->new(
896 debit_id => $self->id,
897 type => $offset_type,
898 amount => $difference
902 if ( C4::Context->preference("FinesLog") ) {
904 "FINES", 'UPDATE', #undef becomes UPDATE in UpdateFine
905 $self->borrowernumber,
907 { action => $update_type,
908 borrowernumber => $self->borrowernumber,
910 description => undef,
911 amountoutstanding => $new_outstanding,
912 debit_type_code => $self->debit_type_code,
914 itemnumber => $self->itemnumber,
918 ) if ( $update_type eq 'overdue_update' );
928 my $bool = $line->is_credit;
935 return defined $self->credit_type_code;
940 my $bool = $line->is_debit;
947 return !$self->is_credit;
950 =head3 to_api_mapping
952 This method returns the mapping for representing a Koha::Account::Line object
959 accountlines_id => 'account_line_id',
960 credit_number => undef,
961 credit_type_code => 'credit_type',
962 debit_type_code => 'debit_type',
963 amountoutstanding => 'amount_outstanding',
964 borrowernumber => 'patron_id',
965 branchcode => 'library_id',
966 issue_id => 'checkout_id',
967 itemnumber => 'item_id',
968 manager_id => 'user_id',
969 note => 'internal_note',
970 register_id => 'cash_register_id',
977 my $bool = $line->is_renewable;
985 $self->amountoutstanding == 0 &&
986 $self->debit_type_code &&
987 $self->debit_type_code eq 'OVERDUE' &&
989 $self->status eq 'UNRETURNED' &&
997 my $renew_result = $line->renew_item;
999 Conditionally attempt to renew an item and return the outcome. This is
1000 as a consequence of the fine on an item being fully paid off.
1001 Caller must call is_renewable before.
1006 my ($self, $params) = @_;
1010 # We want to reject the call to renew if:
1011 # - The RenewAccruingItemWhenPaid syspref is off
1013 # - The RenewAccruingItemInOpac syspref is off
1014 # - There is an interface param passed and it's value is 'opac'
1017 !C4::Context->preference('RenewAccruingItemWhenPaid') ||
1019 !C4::Context->preference('RenewAccruingItemInOpac') &&
1020 $params->{interface} &&
1021 $params->{interface} eq 'opac'
1027 my $itemnumber = $self->item->itemnumber;
1028 my $borrowernumber = $self->patron->borrowernumber;
1029 my ( $can_renew, $error ) = C4::Circulation::CanBookBeRenewed(
1034 my $due_date = C4::Circulation::AddRenewal(
1037 $self->{branchcode},
1043 itemnumber => $itemnumber,
1044 due_date => $due_date,
1049 itemnumber => $itemnumber,
1059 Specific store method to generate credit number before saving
1066 my $AutoCreditNumber = C4::Context->preference('AutoCreditNumber');
1067 my $credit_number_enabled = $self->is_credit && $self->credit_type->credit_number_enabled;
1069 if ($AutoCreditNumber && $credit_number_enabled && !$self->in_storage) {
1070 if (defined $self->credit_number) {
1071 Koha::Exceptions::Account->throw('AutoCreditNumber is enabled but credit_number is already defined');
1074 my $rs = Koha::Database->new->schema->resultset($self->_type);
1076 if ($AutoCreditNumber eq 'incremental') {
1077 my $max = $rs->search({
1078 credit_number => { -regexp => '^[0-9]+$' }
1080 select => \'CAST(credit_number AS UNSIGNED)',
1081 as => ['credit_number'],
1082 })->get_column('credit_number')->max;
1084 $self->credit_number($max + 1);
1085 } elsif ($AutoCreditNumber eq 'annual') {
1086 my $now = dt_from_string;
1087 my $prefix = sprintf('%d-', $now->year);
1088 my $max = $rs->search({
1090 credit_number => { -regexp => '[0-9]{4}$' },
1091 credit_number => { -like => "$prefix%" },
1093 })->get_column('credit_number')->max;
1094 $max //= $prefix . '0000';
1095 my $incr = substr($max, length $prefix);
1096 $self->credit_number(sprintf('%s%04d', $prefix, $incr + 1));
1097 } elsif ($AutoCreditNumber eq 'branchyyyymmincr') {
1098 my $userenv = C4::Context->userenv;
1100 my $branch = $userenv->{branch};
1101 my $now = dt_from_string;
1102 my $prefix = sprintf('%s%d%02d', $branch, $now->year, $now->month);
1103 my $pattern = $prefix;
1104 $pattern =~ s/([\?%_])/\\$1/g;
1105 my $max = $rs->search({
1107 credit_number => { -regexp => '[0-9]{4}$' },
1108 credit_number => { -like => "$pattern%" },
1110 })->get_column('credit_number')->max;
1111 $max //= $prefix . '0000';
1112 my $incr = substr($max, length $prefix);
1113 $self->credit_number(sprintf('%s%04d', $prefix, $incr + 1));
1118 return $self->SUPER::store();
1121 =head2 Internal methods
1130 return 'Accountline';
1135 =head2 Name mappings
1137 =head3 $allowed_update
1141 our $allowed_update = { 'overdue_update' => { 'OVERDUE' => 'UNRETURNED' } };
1145 Kyle M Hall <kyle@bywatersolutions.com >
1146 Tomás Cohen Arazi <tomascohen@theke.io>
1147 Martin Renvoize <martin.renvoize@ptfs-europe.com>