Bug 25110: (QA follow-up) Add aria-hidden="true" to FA icons
[koha.git] / Koha / Account / Line.pm
1 package Koha::Account::Line;
2
3 # This file is part of Koha.
4 #
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.
9 #
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.
14 #
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>.
17
18 use Modern::Perl;
19
20 use Carp;
21 use Data::Dumper;
22
23 use C4::Log qw(logaction);
24 use C4::Overdues qw(GetFine);
25
26 use Koha::Account::CreditType;
27 use Koha::Account::DebitType;
28 use Koha::Account::Offsets;
29 use Koha::Database;
30 use Koha::Exceptions::Account;
31 use Koha::Items;
32
33 use base qw(Koha::Object);
34
35 =encoding utf8
36
37 =head1 NAME
38
39 Koha::Account::Line - Koha accountline Object class
40
41 =head1 API
42
43 =head2 Class methods
44
45 =cut
46
47 =head3 patron
48
49 Return the patron linked to this account line
50
51 =cut
52
53 sub patron {
54     my ( $self ) = @_;
55     my $rs = $self->_result->borrowernumber;
56     return unless $rs;
57     return Koha::Patron->_new_from_dbic( $rs );
58 }
59
60 =head3 item
61
62 Return the item linked to this account line if exists
63
64 =cut
65
66 sub item {
67     my ( $self ) = @_;
68     my $rs = $self->_result->itemnumber;
69     return unless $rs;
70     return Koha::Item->_new_from_dbic( $rs );
71 }
72
73 =head3 checkout
74
75 Return the checkout linked to this account line if exists
76
77 =cut
78
79 sub checkout {
80     my ( $self ) = @_;
81     return unless $self->issue_id ;
82
83     $self->{_checkout} ||= Koha::Checkouts->find( $self->issue_id );
84     $self->{_checkout} ||= Koha::Old::Checkouts->find( $self->issue_id );
85     return $self->{_checkout};
86 }
87
88 =head3 credit_type
89
90 Return the credit_type linked to this account line
91
92 =cut
93
94 sub credit_type {
95     my ( $self ) = @_;
96     my $rs = $self->_result->credit_type_code;
97     return unless $rs;
98     return Koha::Account::CreditType->_new_from_dbic( $rs );
99 }
100
101 =head3 debit_type
102
103 Return the debit_type linked to this account line
104
105 =cut
106
107 sub debit_type {
108     my ( $self ) = @_;
109     my $rs = $self->_result->debit_type_code;
110     return unless $rs;
111     return Koha::Account::DebitType->_new_from_dbic( $rs );
112 }
113
114 =head3 credit_offsets
115
116 Return the credit_offsets linked to this account line if some exist
117
118 =cut
119
120 sub credit_offsets {
121     my ( $self ) = @_;
122     my $rs = $self->_result->account_offsets_credits;
123     return unless $rs;
124     return Koha::Account::Offsets->_new_from_dbic($rs);
125 }
126
127 =head3 debit_offsets
128
129 Return the debit_offsets linked to this account line if some exist
130
131 =cut
132
133 sub debit_offsets {
134     my ( $self ) = @_;
135     my $rs = $self->_result->account_offsets_debits;
136     return unless $rs;
137     return Koha::Account::Offsets->_new_from_dbic($rs);
138 }
139
140
141 =head3 credits
142
143   my $credits = $accountline->credits;
144   my $credits = $accountline->credits( $cond, $attr );
145
146 Return the credits linked to this account line if some exist.
147 Search conditions and attributes may be passed if you wish to filter
148 the resultant resultant resultset.
149
150 =cut
151
152 sub credits {
153     my ( $self, $cond, $attr ) = @_;
154
155     unless ( $self->is_debit ) {
156         Koha::Exceptions::Account::IsNotCredit->throw(
157             error => 'Account line ' . $self->id . ' is not a debit'
158         );
159     }
160
161     my $rs =
162       $self->_result->search_related('account_offsets_debits')
163       ->search_related( 'credit', $cond, $attr );
164     return unless $rs;
165     return Koha::Account::Lines->_new_from_dbic($rs);
166 }
167
168 =head3 debits
169
170   my $debits = $accountline->debits;
171   my $debits = $accountline->debits( $cond, $attr );
172
173 Return the debits 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.
176
177 =cut
178
179 sub debits {
180     my ( $self, $cond, $attr ) = @_;
181
182     unless ( $self->is_credit ) {
183         Koha::Exceptions::Account::IsNotCredit->throw(
184             error => 'Account line ' . $self->id . ' is not a credit'
185         );
186     }
187
188     my $rs =
189       $self->_result->search_related('account_offsets_credits')
190       ->search_related( 'debit', $cond, $attr );
191     return unless $rs;
192     return Koha::Account::Lines->_new_from_dbic($rs);
193 }
194
195 =head3 void
196
197   $payment_accountline->void();
198
199 Used to 'void' (or reverse) a payment/credit. It will roll back any offsets
200 created by the application of this credit upon any debits and mark the credit
201 as 'void' by updating it's status to "VOID".
202
203 =cut
204
205 sub void {
206     my ($self) = @_;
207
208     # Make sure it is a payment we are voiding
209     return unless $self->amount < 0;
210
211     my @account_offsets =
212       Koha::Account::Offsets->search(
213         { credit_id => $self->id, amount => { '<' => 0 }  } );
214
215     $self->_result->result_source->schema->txn_do(
216         sub {
217             foreach my $account_offset (@account_offsets) {
218                 my $fee_paid =
219                   Koha::Account::Lines->find( $account_offset->debit_id );
220
221                 next unless $fee_paid;
222
223                 my $amount_paid = $account_offset->amount * -1; # amount paid is stored as a negative amount
224                 my $new_amount = $fee_paid->amountoutstanding + $amount_paid;
225                 $fee_paid->amountoutstanding($new_amount);
226                 $fee_paid->store();
227
228                 Koha::Account::Offset->new(
229                     {
230                         credit_id => $self->id,
231                         debit_id  => $fee_paid->id,
232                         amount    => $amount_paid,
233                         type      => 'Void Payment',
234                     }
235                 )->store();
236             }
237
238             if ( C4::Context->preference("FinesLog") ) {
239                 logaction(
240                     "FINES", 'VOID',
241                     $self->borrowernumber,
242                     Dumper(
243                         {
244                             action         => 'void_payment',
245                             borrowernumber => $self->borrowernumber,
246                             amount            => $self->amount,
247                             amountoutstanding => $self->amountoutstanding,
248                             description       => $self->description,
249                             credit_type_code  => $self->credit_type_code,
250                             payment_type      => $self->payment_type,
251                             note              => $self->note,
252                             itemnumber        => $self->itemnumber,
253                             manager_id        => $self->manager_id,
254                             offsets =>
255                               [ map { $_->unblessed } @account_offsets ],
256                         }
257                     )
258                 );
259             }
260
261             $self->set(
262                 {
263                     status            => 'VOID',
264                     amountoutstanding => 0,
265                     amount            => 0,
266                 }
267             );
268             $self->store();
269         }
270     );
271
272 }
273
274 =head3 reduce
275
276   $charge_accountline->reduce({
277       reduction_type => $reduction_type
278   });
279
280 Used to 'reduce' a charge/debit by adding a credit to offset against the amount
281 outstanding.
282
283 May be used to apply a discount whilst retaining the original debit amounts or
284 to apply a full or partial refund for example when a lost item is found and
285 returned.
286
287 It will immediately be applied to the given debit unless the debit has already
288 been paid, in which case a 'zero' offset will be added to maintain a link to
289 the debit but the outstanding credit will be left so it may be applied to other
290 debts.
291
292 Reduction type may be one of:
293
294 * REFUND
295 * DISCOUNT
296
297 Returns the reduction accountline (which will be a credit)
298
299 =cut
300
301 sub reduce {
302     my ( $self, $params ) = @_;
303
304     # Make sure it is a charge we are reducing
305     unless ( $self->is_debit ) {
306         Koha::Exceptions::Account::IsNotDebit->throw(
307             error => 'Account line ' . $self->id . 'is not a debit' );
308     }
309     if ( $self->debit_type_code eq 'PAYOUT' ) {
310         Koha::Exceptions::Account::IsNotDebit->throw(
311             error => 'Account line ' . $self->id . 'is a payout' );
312     }
313
314     # Check for mandatory parameters
315     my @mandatory = ( 'interface', 'reduction_type', 'amount' );
316     for my $param (@mandatory) {
317         unless ( defined( $params->{$param} ) ) {
318             Koha::Exceptions::MissingParameter->throw(
319                 error => "The $param parameter is mandatory" );
320         }
321     }
322
323     # More mandatory parameters
324     if ( $params->{interface} eq 'intranet' ) {
325         my @optional = ( 'staff_id', 'branch' );
326         for my $param (@optional) {
327             unless ( defined( $params->{$param} ) ) {
328                 Koha::Exceptions::MissingParameter->throw( error =>
329 "The $param parameter is mandatory when interface is set to 'intranet'"
330                 );
331             }
332         }
333     }
334
335     # Make sure the reduction isn't more than the original
336     my $original = $self->amount;
337     Koha::Exceptions::Account::AmountNotPositive->throw(
338         error => 'Reduce amount passed is not positive' )
339       unless ( $params->{amount} > 0 );
340     Koha::Exceptions::ParameterTooHigh->throw( error =>
341 "Amount to reduce ($params->{amount}) is higher than original amount ($original)"
342     ) unless ( $original >= $params->{amount} );
343     my $reduced =
344       $self->credits( { credit_type_code => [ 'DISCOUNT', 'REFUND' ] } )->total;
345     Koha::Exceptions::ParameterTooHigh->throw( error =>
346 "Combined reduction ($params->{amount} + $reduced) is higher than original amount ("
347           . abs($original)
348           . ")" )
349       unless ( $original >= ( $params->{amount} + abs($reduced) ) );
350
351     my $status = { 'REFUND' => 'REFUNDED', 'DISCOUNT' => 'DISCOUNTED' };
352
353     my $reduction;
354     $self->_result->result_source->schema->txn_do(
355         sub {
356
357             # A 'reduction' is a 'credit'
358             $reduction = Koha::Account::Line->new(
359                 {
360                     date              => \'NOW()',
361                     amount            => 0 - $params->{amount},
362                     credit_type_code  => $params->{reduction_type},
363                     status            => 'ADDED',
364                     amountoutstanding => 0 - $params->{amount},
365                     manager_id        => $params->{staff_id},
366                     borrowernumber    => $self->borrowernumber,
367                     interface         => $params->{interface},
368                     branchcode        => $params->{branch},
369                 }
370             )->store();
371
372             my $reduction_offset = Koha::Account::Offset->new(
373                 {
374                     credit_id => $reduction->accountlines_id,
375                     type      => uc( $params->{reduction_type} ),
376                     amount    => $params->{amount}
377                 }
378             )->store();
379
380             # Link reduction to charge (and apply as required)
381             my $debit_outstanding = $self->amountoutstanding;
382             if ( $debit_outstanding >= $params->{amount} ) {
383
384                 $reduction->apply(
385                     {
386                         debits      => [$self],
387                         offset_type => uc( $params->{reduction_type} )
388                     }
389                 );
390                 $reduction->status('APPLIED')->store();
391             }
392             else {
393
394         # Zero amount offset used to link original 'debit' to reduction 'credit'
395                 my $link_reduction_offset = Koha::Account::Offset->new(
396                     {
397                         credit_id => $reduction->accountlines_id,
398                         debit_id  => $self->accountlines_id,
399                         type      => uc( $params->{reduction_type} ),
400                         amount    => 0
401                     }
402                 )->store();
403             }
404
405             # Update status of original debit
406             $self->status( $status->{ $params->{reduction_type} } )->store;
407         }
408     );
409
410     $reduction->discard_changes;
411     return $reduction;
412 }
413
414 =head3 apply
415
416     my $debits = $account->outstanding_debits;
417     my $outstanding_amount = $credit->apply( { debits => $debits, [ offset_type => $offset_type ] } );
418
419 Applies the credit to a given debits array reference.
420
421 =head4 arguments hashref
422
423 =over 4
424
425 =item debits - Koha::Account::Lines object set of debits
426
427 =item offset_type (optional) - a string indicating the offset type (valid values are those from
428 the 'account_offset_types' table)
429
430 =back
431
432 =cut
433
434 sub apply {
435     my ( $self, $params ) = @_;
436
437     my $debits      = $params->{debits};
438     my $offset_type = $params->{offset_type} // 'Credit Applied';
439
440     unless ( $self->is_credit ) {
441         Koha::Exceptions::Account::IsNotCredit->throw(
442             error => 'Account line ' . $self->id . ' is not a credit'
443         );
444     }
445
446     my $available_credit = $self->amountoutstanding * -1;
447
448     unless ( $available_credit > 0 ) {
449         Koha::Exceptions::Account::NoAvailableCredit->throw(
450             error => 'Outstanding credit is ' . $available_credit . ' and cannot be applied'
451         );
452     }
453
454     my $schema = Koha::Database->new->schema;
455
456     $schema->txn_do( sub {
457         for my $debit ( @{$debits} ) {
458
459             unless ( $debit->is_debit ) {
460                 Koha::Exceptions::Account::IsNotDebit->throw(
461                     error => 'Account line ' . $debit->id . 'is not a debit'
462                 );
463             }
464             my $amount_to_cancel;
465             my $owed = $debit->amountoutstanding;
466
467             if ( $available_credit >= $owed ) {
468                 $amount_to_cancel = $owed;
469             }
470             else {    # $available_credit < $debit->amountoutstanding
471                 $amount_to_cancel = $available_credit;
472             }
473
474             # record the account offset
475             Koha::Account::Offset->new(
476                 {   credit_id => $self->id,
477                     debit_id  => $debit->id,
478                     amount    => $amount_to_cancel * -1,
479                     type      => $offset_type,
480                 }
481             )->store();
482
483             $available_credit -= $amount_to_cancel;
484
485             $self->amountoutstanding( $available_credit * -1 )->store;
486             $debit->amountoutstanding( $owed - $amount_to_cancel )->store;
487
488             # Attempt to renew the item associated with this debit if
489             # appropriate
490             if ($debit->renewable) {
491                 $debit->renew_item($params->{interface});
492             }
493
494             # Same logic exists in Koha::Account::pay
495             if (
496                 C4::Context->preference('MarkLostItemsAsReturned') =~
497                 m|onpayment|
498                 && $debit->debit_type_code
499                 && $debit->debit_type_code eq 'LOST'
500                 && $debit->amountoutstanding == 0
501                 && $debit->itemnumber
502                 && !(
503                        $self->credit_type_code eq 'LOST_FOUND'
504                     && $self->itemnumber == $debit->itemnumber
505                 )
506               )
507             {
508                 C4::Circulation::ReturnLostItem( $self->borrowernumber,
509                     $debit->itemnumber );
510             }
511         }
512     });
513
514     return $available_credit;
515 }
516
517 =head3 payout
518
519   $credit_accountline->payout(
520     {
521         payout_type => $payout_type,
522         register_id => $register_id,
523         staff_id    => $staff_id,
524         interface   => 'intranet',
525         amount      => $amount
526     }
527   );
528
529 Used to 'pay out' a credit to a user.
530
531 Payout type may be one of any existing payment types
532
533 Returns the payout debit line that is created via this transaction.
534
535 =cut
536
537 sub payout {
538     my ( $self, $params ) = @_;
539
540     # Make sure it is a credit we are paying out
541     unless ( $self->is_credit ) {
542         Koha::Exceptions::Account::IsNotCredit->throw(
543             error => 'Account line ' . $self->id . ' is not a credit' );
544     }
545
546     # Check for mandatory parameters
547     my @mandatory =
548       ( 'interface', 'staff_id', 'branch', 'payout_type', 'amount' );
549     for my $param (@mandatory) {
550         unless ( defined( $params->{$param} ) ) {
551             Koha::Exceptions::MissingParameter->throw(
552                 error => "The $param parameter is mandatory" );
553         }
554     }
555
556     # Make sure there is outstanding credit to pay out
557     my $outstanding = -1 * $self->amountoutstanding;
558     my $amount =
559       $params->{amount} ? $params->{amount} : $outstanding;
560     Koha::Exceptions::Account::AmountNotPositive->throw(
561         error => 'Payout amount passed is not positive' )
562       unless ( $amount > 0 );
563     Koha::Exceptions::ParameterTooHigh->throw(
564         error => "Amount to payout ($amount) is higher than amountoutstanding ($outstanding)" )
565       unless ($outstanding >= $amount );
566
567     # Make sure we record the cash register for cash transactions
568     Koha::Exceptions::Account::RegisterRequired->throw()
569       if ( C4::Context->preference("UseCashRegisters")
570         && defined( $params->{payout_type} )
571         && ( $params->{payout_type} eq 'CASH' )
572         && !defined( $params->{cash_register} ) );
573
574     my $payout;
575     $self->_result->result_source->schema->txn_do(
576         sub {
577
578             # A 'payout' is a 'debit'
579             $payout = Koha::Account::Line->new(
580                 {
581                     date              => \'NOW()',
582                     amount            => $amount,
583                     debit_type_code   => 'PAYOUT',
584                     payment_type      => $params->{payout_type},
585                     amountoutstanding => $amount,
586                     manager_id        => $params->{staff_id},
587                     borrowernumber    => $self->borrowernumber,
588                     interface         => $params->{interface},
589                     branchcode        => $params->{branch},
590                     register_id       => $params->{cash_register}
591                 }
592             )->store();
593
594             my $payout_offset = Koha::Account::Offset->new(
595                 {
596                     debit_id => $payout->accountlines_id,
597                     type     => 'PAYOUT',
598                     amount   => $amount
599                 }
600             )->store();
601
602             $self->apply( { debits => [$payout], offset_type => 'PAYOUT' } );
603             $self->status('PAID')->store;
604         }
605     );
606
607     $payout->discard_changes;
608     return $payout;
609 }
610
611 =head3 adjust
612
613 This method allows updating a debit or credit on a patron's account
614
615     $account_line->adjust(
616         {
617             amount    => $amount,
618             type      => $update_type,
619             interface => $interface
620         }
621     );
622
623 $update_type can be any of:
624   - overdue_update
625
626 Authors Note: The intention here is that this method is only used
627 to adjust accountlines where the final amount is not yet known/fixed.
628 Incrementing fines are the only existing case at the time of writing,
629 all other forms of 'adjustment' should be recorded as distinct credits
630 or debits and applied, via an offset, to the corresponding debit or credit.
631
632 =cut
633
634 sub adjust {
635     my ( $self, $params ) = @_;
636
637     my $amount       = $params->{amount};
638     my $update_type  = $params->{type};
639     my $interface    = $params->{interface};
640
641     unless ( exists($Koha::Account::Line::allowed_update->{$update_type}) ) {
642         Koha::Exceptions::Account::UnrecognisedType->throw(
643             error => 'Update type not recognised'
644         );
645     }
646
647     my $debit_type_code = $self->debit_type_code;
648     my $account_status  = $self->status;
649     unless (
650         (
651             exists(
652                 $Koha::Account::Line::allowed_update->{$update_type}
653                   ->{$debit_type_code}
654             )
655             && ( $Koha::Account::Line::allowed_update->{$update_type}
656                 ->{$debit_type_code} eq $account_status )
657         )
658       )
659     {
660         Koha::Exceptions::Account::UnrecognisedType->throw(
661             error => 'Update type not allowed on this debit_type' );
662     }
663
664     my $schema = Koha::Database->new->schema;
665
666     $schema->txn_do(
667         sub {
668
669             my $amount_before             = $self->amount;
670             my $amount_outstanding_before = $self->amountoutstanding;
671             my $difference                = $amount - $amount_before;
672             my $new_outstanding           = $amount_outstanding_before + $difference;
673
674             my $offset_type = $debit_type_code;
675             $offset_type .= ( $difference > 0 ) ? "_INCREASE" : "_DECREASE";
676
677             # Catch cases that require patron refunds
678             if ( $new_outstanding < 0 ) {
679                 my $account =
680                   Koha::Patrons->find( $self->borrowernumber )->account;
681                 my $credit = $account->add_credit(
682                     {
683                         amount      => $new_outstanding * -1,
684                         description => 'Overpayment refund',
685                         type        => 'CREDIT',
686                         interface   => $interface,
687                         ( $update_type eq 'overdue_update' ? ( item_id => $self->itemnumber ) : ()),
688                     }
689                 );
690                 $new_outstanding = 0;
691             }
692
693             # Update the account line
694             $self->set(
695                 {
696                     date              => \'NOW()',
697                     amount            => $amount,
698                     amountoutstanding => $new_outstanding,
699                 }
700             )->store();
701
702             # Record the account offset
703             my $account_offset = Koha::Account::Offset->new(
704                 {
705                     debit_id => $self->id,
706                     type     => $offset_type,
707                     amount   => $difference
708                 }
709             )->store();
710
711             if ( C4::Context->preference("FinesLog") ) {
712                 logaction(
713                     "FINES", 'UPDATE', #undef becomes UPDATE in UpdateFine
714                     $self->borrowernumber,
715                     Dumper(
716                         {   action            => $update_type,
717                             borrowernumber    => $self->borrowernumber,
718                             amount            => $amount,
719                             description       => undef,
720                             amountoutstanding => $new_outstanding,
721                             debit_type_code   => $self->debit_type_code,
722                             note              => undef,
723                             itemnumber        => $self->itemnumber,
724                             manager_id        => undef,
725                         }
726                     )
727                 ) if ( $update_type eq 'overdue_update' );
728             }
729         }
730     );
731
732     return $self;
733 }
734
735 =head3 is_credit
736
737     my $bool = $line->is_credit;
738
739 =cut
740
741 sub is_credit {
742     my ($self) = @_;
743
744     return ( $self->amount < 0 );
745 }
746
747 =head3 is_debit
748
749     my $bool = $line->is_debit;
750
751 =cut
752
753 sub is_debit {
754     my ($self) = @_;
755
756     return !$self->is_credit;
757 }
758
759 =head3 to_api_mapping
760
761 This method returns the mapping for representing a Koha::Account::Line object
762 on the API.
763
764 =cut
765
766 sub to_api_mapping {
767     return {
768         accountlines_id   => 'account_line_id',
769         credit_type_code  => 'credit_type',
770         debit_type_code   => 'debit_type',
771         amountoutstanding => 'amount_outstanding',
772         borrowernumber    => 'patron_id',
773         branchcode        => 'library_id',
774         issue_id          => 'checkout_id',
775         itemnumber        => 'item_id',
776         manager_id        => 'user_id',
777         note              => 'internal_note',
778     };
779
780 }
781
782 =head3 renewable
783
784     my $bool = $line->renewable;
785
786 =cut
787
788 sub renewable {
789     my ($self) = @_;
790
791     return (
792         $self->amountoutstanding == 0 &&
793         $self->debit_type_code &&
794         $self->debit_type_code eq 'OVERDUE' &&
795         $self->status &&
796         $self->status eq 'UNRETURNED'
797     ) ? 1 : 0;
798 }
799
800 =head3 renew_item
801
802     my $renew_result = $line->renew_item;
803
804 Conditionally attempt to renew an item and return the outcome. This is
805 as a consequence of the fine on an item being fully paid off
806
807 =cut
808
809 sub renew_item {
810     my ($self, $params) = @_;
811
812     my $outcome = {};
813
814     # We want to reject the call to renew if any of these apply:
815     # - The RenewAccruingItemWhenPaid syspref is off
816     # - The line item doesn't have an item attached to it
817     # - The line item doesn't have a patron attached to it
818     #
819     # - The RenewAccruingItemInOpac syspref is off
820     # AND
821     # - There is an interface param passed and it's value is 'opac'
822
823     if (
824         !C4::Context->preference('RenewAccruingItemWhenPaid') ||
825         !$self->item ||
826         !$self->patron ||
827         (
828             !C4::Context->preference('RenewAccruingItemInOpac') &&
829             $params->{interface} &&
830             $params->{interface} eq 'opac'
831         )
832     ) {
833         return;
834     }
835
836     my $itemnumber = $self->item->itemnumber;
837     my $borrowernumber = $self->patron->borrowernumber;
838     my ( $can_renew, $error ) = C4::Circulation::CanBookBeRenewed(
839         $borrowernumber,
840         $itemnumber
841     );
842     if ( $can_renew ) {
843         my $due_date = C4::Circulation::AddRenewal(
844             $borrowernumber,
845             $itemnumber,
846             $self->{branchcode},
847             undef,
848             undef,
849             1
850         );
851         return {
852             itemnumber => $itemnumber,
853             due_date   => $due_date,
854             success    => 1
855         };
856     } else {
857         return {
858             itemnumber => $itemnumber,
859             error      => $error,
860             success    => 0
861         };
862     }
863
864 }
865
866 =head2 Internal methods
867
868 =cut
869
870 =head3 _type
871
872 =cut
873
874 sub _type {
875     return 'Accountline';
876 }
877
878 1;
879
880 =head2 Name mappings
881
882 =head3 $allowed_update
883
884 =cut
885
886 our $allowed_update = { 'overdue_update' => { 'OVERDUE' => 'UNRETURNED' } };
887
888 =head1 AUTHORS
889
890 Kyle M Hall <kyle@bywatersolutions.com >
891 Tomás Cohen Arazi <tomascohen@theke.io>
892 Martin Renvoize <martin.renvoize@ptfs-europe.com>
893
894 =cut