@@ -, +, @@ lose. dated for a return on the date the item is 'found' fine (dated for a 'return' on the date the item was 'lost' --- C4/Circulation.pm | 157 ++++++++++++++++++--- Koha/CirculationRules.pm | 19 ++- admin/smart-rules.pl | 16 +-- .../prog/en/modules/admin/smart-rules.tt | 87 ++++++++---- 4 files changed, 213 insertions(+), 66 deletions(-) --- a/C4/Circulation.pm +++ a/C4/Circulation.pm @@ -1453,19 +1453,45 @@ sub AddIssue { UpdateTotalIssues( $item_object->biblionumber, 1 ); } - ## If item was lost, it has now been found, reverse any list item charges if necessary. + ## If item was lost, it has now been found, reverse any lost item charges if necessary. if ( $item_object->itemlost ) { - if ( - Koha::CirculationRules->get_lostreturn_policy( - { - return_branch => C4::Context->userenv->{branch}, - item => $item_object - } - ) - ) - { + my $lostreturn_policy = + Koha::CirculationRules->get_lostreturn_policy( + { + return_branch => C4::Context->userenv->{branch}, + item => $item_object + } + ); + + if ($lostreturn_policy) { _FixAccountForLostAndFound( $item_object->itemnumber, undef, $item_object->barcode ); + + if ( $lostreturn_policy eq 'charge' ) { + $actualissue //= Koha::Old::Checkouts->search( + { itemnumber => $item_unblessed->{itemnumber} }, + { + order_by => { '-desc' => 'returndate' }, + rows => 1 + } + )->single; + + _CalculateAndUpdateFine( + { + issue => $actualissue, + item => $item_unblessed, + borrower => $borrower + } + ); + _FixOverduesOnReturn( $borrower->{borrowernumber}, + $item_object->itemnumber, undef, 'RENEWED' ); + } + elsif ( $lostreturn_policy eq 'restore' ) { + _RestoreOverdueForLostAndFound( + $borrower->{'borrowernumber'}, + $item_object->itemnumber + ); + } } } @@ -2038,18 +2064,39 @@ sub AddReturn { if ( $item->itemlost ) { $messages->{'WasLost'} = 1; unless ( C4::Context->preference("BlockReturnOfLostItems") ) { - if ( - Koha::CirculationRules->get_lostreturn_policy( - { - return_branch => C4::Context->userenv->{branch}, - item => $item, - } - ) - ) - { + my $lostreturn_policy = + Koha::CirculationRules->get_lostreturn_policy( + { + return_branch => C4::Context->userenv->{branch}, + item => $item + } + ); + + if ($lostreturn_policy) { _FixAccountForLostAndFound( $item->itemnumber, $borrowernumber, $barcode ); $messages->{'LostItemFeeRefunded'} = 1; + + if ( $lostreturn_policy eq 'charge' ) { + $issue //= Koha::Old::Checkouts->search( + { itemnumber => $item->itemnumber }, + { order_by => { '-desc' => 'returndate' }, rows => 1 } + )->single; + _CalculateAndUpdateFine( + { + issue => $issue, + item => $item->unblessed, + borrower => $patron_unblessed, + return_date => $return_date + } + ); + $messages->{'LostItemFeeCharged'} = 1; + } + elsif ( $lostreturn_policy eq 'restore' ) { + _RestoreOverdueForLostAndFound( $borrowernumber, + $item->itemnumber ); + $messages->{'LostItemFeeRestored'} = 1; + } } } } @@ -2454,15 +2501,12 @@ sub _FixOverduesOnReturn { $credit->apply({ debits => [ $accountline ], offset_type => 'Forgiven' }); - $accountline->status('FORGIVEN'); - if (C4::Context->preference("FinesLog")) { &logaction("FINES", 'MODIFY',$borrowernumber,"Overdue forgiven: item $item"); } - } else { - $accountline->status($status); } + $accountline->status($status); return $accountline->store(); } ); @@ -2559,6 +2603,73 @@ sub _FixAccountForLostAndFound { return ($credit) ? $credit->id : undef; } +=head2 _RestoreOverdueForLostAndFound + + &_RestoreOverdueForLostAndFound($borrowernumber, $itemnumber ); + +C<$borrowernumber> borrowernumber + +C<$itemnumber> itemnumber + +Internal function + +=cut + +sub _RestoreOverdueForLostAndFound { + my ( $borrowernumber, $item ) = @_; + + unless( $borrowernumber ) { + warn "_RestoreOverdueForLostAndFound() not supplied valid borrowernumber"; + return; + } + unless( $item ) { + warn "_RestoreOverdueForLostAndFound() not supplied valid itemnumber"; + return; + } + + my $schema = Koha::Database->schema; + + my $result = $schema->txn_do( + sub { + # check for lost overdue fine + my $accountlines = Koha::Account::Lines->search( + { + borrowernumber => $borrowernumber, + itemnumber => $item, + debit_type_code => 'OVERDUE', + status => 'LOST' + }, + { + order_by => { '-desc' => 'date' }, + rows => 1 + } + ); + return 0 unless $accountlines->count; # no warning, there's just nothing to fix + + # Update status of fine + my $overdue = $accountlines->next; + $overdue->status('RETURNED')->store(); + + # Find related forgive credit + my $refunds = $overdue->credits( + { + credit_type_code => 'FORGIVEN', + itemnumber => $item, + status => [ { '!=' => 'VOID' }, undef ] + }, + { order_by => { '-desc' => 'date' }, rows => 1 } + ); + return 0 unless $refunds->count; # no warning, there's just nothing to fix + + # Revert the forgive credit + my $refund = $refunds->next; + return $refund->void(); + } + ); + + return $result; +} + =head2 _GetCircControlBranch my $circ_control_branch = _GetCircControlBranch($iteminfos, $borrower); --- a/Koha/CirculationRules.pm +++ a/Koha/CirculationRules.pm @@ -46,7 +46,7 @@ Any attempt to set a rule with a nonsensical scope (for instance, setting the C< =cut our $RULE_KINDS = { - refund => { + lostreturn => { scope => [ 'branchcode' ], }, @@ -428,7 +428,18 @@ sub get_onshelfholds_policy { =head3 get_lostreturn_policy - my $refund = Koha::CirculationRules->get_lostreturn_policy( { return_branch => $return_branch, item => $item } ); + my $lostrefund_policy = Koha::CirculationRules->get_lostreturn_policy( { return_branch => $return_branch, item => $item } ); + +Return values are: + +=over 2 + +=item 0 - Do not refund +=item refund - Refund the lost item charge +=item restore - Refund the lost item charge and restore the original overdue fine +=item charge - Refund the lost item charge and charge a new overdue fine + +=back =cut @@ -449,11 +460,11 @@ sub get_lostreturn_policy { my $rule = Koha::CirculationRules->get_effective_rule( { branchcode => $branch, - rule_name => 'refund', + rule_name => 'lostreturn', } ); - return $rule ? $rule->rule_value : 1; + return $rule ? $rule->rule_value : 'refund'; } =head3 article_requestable_rules --- a/admin/smart-rules.pl +++ a/admin/smart-rules.pl @@ -523,16 +523,16 @@ elsif ($op eq "add-branch-item") { } elsif ( $op eq 'mod-refund-lost-item-fee-rule' ) { - my $refund = $input->param('refund'); + my $lostreturn = $input->param('lostreturn'); - if ( $refund eq '*' ) { + if ( $lostreturn eq '*' ) { if ( $branch ne '*' ) { - # only do something for $refund eq '*' if branch-specific + # only do something for $lostreturn eq '*' if branch-specific Koha::CirculationRules->set_rules( { branchcode => $branch, rules => { - refund => undef + lostreturn => undef } } ); @@ -542,18 +542,18 @@ elsif ( $op eq 'mod-refund-lost-item-fee-rule' ) { { branchcode => $branch, rules => { - refund => $refund + lostreturn => $lostreturn } } ); } } -my $refundLostItemFeeRule = Koha::CirculationRules->find({ branchcode => ($branch eq '*') ? undef : $branch, rule_name => 'refund' }); -my $defaultLostItemFeeRule = Koha::CirculationRules->find({ branchcode => undef, rule_name => 'refund' }); +my $refundLostItemFeeRule = Koha::CirculationRules->find({ branchcode => ($branch eq '*') ? undef : $branch, rule_name => 'lostreturn' }); +my $defaultLostItemFeeRule = Koha::CirculationRules->find({ branchcode => undef, rule_name => 'lostreturn' }); $template->param( refundLostItemFeeRule => $refundLostItemFeeRule, - defaultRefundRule => $defaultLostItemFeeRule ? $defaultLostItemFeeRule->rule_value : 1 + defaultRefundRule => $defaultLostItemFeeRule ? $defaultLostItemFeeRule->rule_value : 'refund' ); my $patron_categories = Koha::Patron::Categories->search({}, { order_by => ['description'] }); --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt @@ -739,23 +739,35 @@ - [%# Default branch %] [% IF ( current_branch == '*' ) %] - [% IF ( defaultRefundRule ) %] - + + + + [% ELSIF ( defaultRefundRule == 'charge' ) %] + + + + + [% ELSIF ( defaultRefundRule == 'restore' ) %] + + + + + [% ELSIF ( defaultRefundRule == 0 ) %] + + + + [% ELSE %] - + + + [% END %] - Yes - - [% IF ( not defaultRefundRule ) %] - [% ELSE %] [%# Branch-specific %] [% IF ( not refundLostItemFeeRule ) %] @@ -763,30 +775,43 @@ [% ELSE %] [% IF ( not refundLostItemFeeRule ) %] - - + + + + [% ELSE %] - [% IF ( refundLostItemFeeRule.rule_value ) %] - + + + + [% ELSIF ( refundLostItemFeeRule.rule_value == 'charge' ) %] + + + + + [% ELSIF ( refundLostItemFeeRule.rule_value == 'restore' ) %] + + + + + [% ELSIF ( refundLostItemFeeRule.rule_value == 0 ) %] + + + + [% END %] - Yes - - [% IF ( not refundLostItemFeeRule.rule_value ) %] - [% END %] [% END %] --