Bug 23012: Set policy for lost item processing fee

Signed-off-by: David Nind <david@davidnind.com>

Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
This commit is contained in:
Aleisha Amohia 2022-10-12 04:22:31 +00:00 committed by Tomas Cohen Arazi
parent 974359ed85
commit ea8c2959da
Signed by: tomascohen
GPG key ID: 0A272EA1B2F3C15F
4 changed files with 310 additions and 7 deletions

View file

@ -51,7 +51,9 @@ our $RULE_KINDS = {
lostreturn => {
scope => [ 'branchcode' ],
},
processingreturn => {
scope => [ 'branchcode' ],
},
patron_maxissueqty => {
scope => [ 'branchcode', 'categorycode' ],
},
@ -617,6 +619,50 @@ sub get_lostreturn_policy {
return $rule ? $rule->rule_value : 'refund';
}
=head3 get_processingreturn_policy
my $processingrefund_policy = Koha::CirculationRules->get_processingreturn_policy( { return_branch => $return_branch, item => $item } );
Return values are:
=over 2
=item '0' - Do not refund
=item 'refund' - Refund the lost item processing charge
=item 'restore' - Refund the lost item processing charge and restore the original overdue fine
=item 'charge' - Refund the lost item processing charge and charge a new overdue fine
=back
=cut
sub get_processingreturn_policy {
my ( $class, $params ) = @_;
my $item = $params->{item};
my $behaviour = C4::Context->preference( 'RefundLostOnReturnControl' ) // 'CheckinLibrary';
my $behaviour_mapping = {
CheckinLibrary => $params->{'return_branch'} // $item->homebranch,
ItemHomeBranch => $item->homebranch,
ItemHoldingBranch => $item->holdingbranch
};
my $branch = $behaviour_mapping->{ $behaviour };
my $rule = Koha::CirculationRules->get_effective_rule(
{
branchcode => $branch,
rule_name => 'processingreturn',
}
);
return $rule ? $rule->rule_value : 'refund';
}
=head3 article_requestable_rules
Return rules that allow article requests, optionally filtered by

View file

@ -654,6 +654,31 @@ elsif ( $op eq 'mod-refund-lost-item-fee-rule' ) {
}
);
}
my $processingreturn = $input->param('processingreturn');
if ( $processingreturn eq '*' ) {
if ( $branch ne '*' ) {
# only do something for $processingreturn eq '*' if branch-specific
Koha::CirculationRules->set_rules(
{
branchcode => $branch,
rules => {
processingreturn => undef
}
}
);
}
} else {
Koha::CirculationRules->set_rules(
{
branchcode => $branch,
rules => {
processingreturn => $processingreturn
}
}
);
}
} elsif ( $op eq "set-waiting-hold-cancellation" ) {
my $category = $input->param('waiting_hold_cancellation_category');
@ -691,9 +716,13 @@ elsif ( $op eq 'mod-refund-lost-item-fee-rule' ) {
my $refundLostItemFeeRule = Koha::CirculationRules->find({ branchcode => ($branch eq '*') ? undef : $branch, rule_name => 'lostreturn' });
my $defaultLostItemFeeRule = Koha::CirculationRules->find({ branchcode => undef, rule_name => 'lostreturn' });
my $refundProcessingFeeRule = Koha::CirculationRules->find({ branchcode => ($branch eq '*') ? undef : $branch, rule_name => 'processingreturn' });
my $defaultProcessingFeeRule = Koha::CirculationRules->find({ branchcode => undef, rule_name => 'processingreturn' });
$template->param(
refundLostItemFeeRule => $refundLostItemFeeRule,
defaultRefundRule => $defaultLostItemFeeRule ? $defaultLostItemFeeRule->rule_value : 'refund'
defaultRefundRule => $defaultLostItemFeeRule ? $defaultLostItemFeeRule->rule_value : 'refund',
refundProcessingFeeRule => $refundProcessingFeeRule,
defaultProcessingRefundRule => $defaultProcessingFeeRule ? $defaultProcessingFeeRule->rule_value : 'refund',
);
my $patron_categories = Koha::Patron::Categories->search({}, { order_by => ['description'] });

View file

@ -1073,7 +1073,8 @@
<input type="hidden" name="branch" value="[% current_branch | html %]" />
<table>
<tr>
<th>Refund lost item fee</th>
<th>Refund lost item replacement fee</th>
<th>Refund lost item processing fee</th>
<th>&nbsp;</th>
</tr>
<tr>
@ -1179,6 +1180,64 @@
[% END %]
</select>
</td>
<td>
<select name="processingreturn">
[%# Default branch %]
[% IF ( current_branch == '*' ) %]
[% IF ( defaultProcessingRefundRule == 'refund' ) %]
<option value="refund" selected="selected">Refund lost item processing charge</option>
<option value="refund_unpaid">Refund lost item processing charge (only if unpaid)</option>
<option value="0">Leave lost item processing charge</option>
[% ELSIF ( defaultProcessingRefundRule == 'refund_unpaid' ) %]
<option value="refund">Refund lost item charge</option>
<option value="refund_unpaid" selected="selected">Refund lost item processing charge (only if unpaid)</option>
<option value="0">Leave lost item processing charge</option>
[% ELSIF ( defaultProcessingRefundRule == 0 ) %]
<option value="refund">Refund lost item processing charge</option>
<option value="refund_unpaid">Refund lost item processing charge (only if unpaid)</option>
<option value="0" selected="selected">Leave lost item processing charge</option>
[% ELSE %]
<option value="refund">Refund lost item processing charge</option>
<option value="refund_unpaid">Refund lost item processing charge (only if unpaid)</option>
<option value="0">Leave lost item processing charge</option>
[% END %]
[% ELSE %]
[%# Branch-specific %]
[% IF ( not refundProcessingFeeRule ) %]
<option value="*" selected="selected">
[% ELSE %]
<option value="*">
[% END %]
[% IF defaultProcessingRefundRule == 'refund' %]
<span>Use default (Refund lost item processing charge)</span>
[% ELSIF defaultProcessingRefundRule == 'refund_unpaid' %]
Use default (Refund lost item processing charge (only if unpaid))
[% ELSE %]
<span>Use default (Leave lost item processing charge)</span>
[% END %]
</option>
[% IF ( not refundProcessingFeeRule ) %]
<option value="refund">Refund lost item processing charge</option>
<option value="refund_unpaid">Refund lost item processing charge (only if unpaid)</option>
<option value="0">Leave lost item processing charge</option>
[% ELSE %]
[% IF ( refundProcessingFeeRule.rule_value == 'refund' ) %]
<option value="refund" selected="selected">Refund lost item processing charge</option>
<option value="refund_unpaid">Refund lost item processing charge (only if unpaid)</option>
<option value="0">Leave lost item processing charge</option>
[% ELSIF ( refundProcessingFeeRule.rule_value == 'refund_unpaid' ) %]
<option value="refund">Refund lost item processing charge</option>
<option value="refund_unpaid" selected="selected">Refund lost item processing charge (only if unpaid)</option>
<option value="0">Leave lost item processing charge</option>
[% ELSIF ( refundProcessingFeeRule.rule_value == 0 ) %]
<option value="refund">Refund lost item processing charge</option>
<option value="refund_unpaid">Refund lost item processing charge (only if unpaid)</option>
<option value="0" selected="selected">Leave lost item processing charge</option>
[% END %]
[% END %]
[% END %]
</select>
</td>
<td class="actions">
<button type="submit" class="btn btn-default btn-xs"><i class="fa fa-save"></i> Save</button>
</td>

View file

@ -20,7 +20,7 @@
use Modern::Perl;
use Benchmark;
use Test::More tests => 7;
use Test::More tests => 8;
use Test::Deep qw( cmp_methods );
use Test::Exception;
@ -161,7 +161,7 @@ subtest 'set_rule' => sub {
my $itemtype = $builder->build({ source => 'Itemtype' })->{'itemtype'};
subtest 'Correct call' => sub {
plan tests => 4;
plan tests => 5;
Koha::CirculationRules->delete;
@ -173,6 +173,14 @@ subtest 'set_rule' => sub {
} );
}, 'setting lostreturn with branch' );
lives_ok( sub {
Koha::CirculationRules->set_rule( {
branchcode => $branchcode,
rule_name => 'processingreturn',
rule_value => '',
} );
}, 'setting processingreturn with branch' );
lives_ok( sub {
Koha::CirculationRules->set_rule( {
branchcode => $branchcode,
@ -203,7 +211,7 @@ subtest 'set_rule' => sub {
};
subtest 'Call with missing params' => sub {
plan tests => 4;
plan tests => 5;
Koha::CirculationRules->delete;
@ -214,6 +222,13 @@ subtest 'set_rule' => sub {
} );
}, qr/branchcode/, 'setting lostreturn without branch fails' );
throws_ok( sub {
Koha::CirculationRules->set_rule( {
rule_name => 'processingreturn',
rule_value => '',
} );
}, qr/branchcode/, 'setting processingreturn without branch fails' );
throws_ok( sub {
Koha::CirculationRules->set_rule( {
branchcode => $branchcode,
@ -241,7 +256,7 @@ subtest 'set_rule' => sub {
};
subtest 'Call with extra params' => sub {
plan tests => 3;
plan tests => 4;
Koha::CirculationRules->delete;
@ -254,6 +269,15 @@ subtest 'set_rule' => sub {
} );
}, qr/categorycode/, 'setting lostreturn with categorycode fails' );
throws_ok( sub {
Koha::CirculationRules->set_rule( {
branchcode => $branchcode,
categorycode => $categorycode,
rule_name => 'processingreturn',
rule_value => '',
} );
}, qr/categorycode/, 'setting processingreturn with categorycode fails' );
throws_ok( sub {
Koha::CirculationRules->set_rule( {
branchcode => $branchcode,
@ -801,6 +825,151 @@ subtest 'get_lostreturn_policy() tests' => sub {
$schema->storage->txn_rollback;
};
subtest 'get_processingreturn_policy() tests' => sub {
plan tests => 7;
$schema->storage->txn_begin;
$schema->resultset('CirculationRule')->search()->delete;
my $default_rule_charge = $builder->build(
{
source => 'CirculationRule',
value => {
branchcode => undef,
categorycode => undef,
itemtype => undef,
rule_name => 'processingreturn',
rule_value => 'charge'
}
}
);
my $branchcode = $builder->build( { source => 'Branch' } )->{branchcode};
my $specific_rule_false = $builder->build(
{
source => 'CirculationRule',
value => {
branchcode => $branchcode,
categorycode => undef,
itemtype => undef,
rule_name => 'processingreturn',
rule_value => 0
}
}
);
my $branchcode2 = $builder->build( { source => 'Branch' } )->{branchcode};
my $specific_rule_refund = $builder->build(
{
source => 'CirculationRule',
value => {
branchcode => $branchcode2,
categorycode => undef,
itemtype => undef,
rule_name => 'processingreturn',
rule_value => 'refund'
}
}
);
my $branchcode3 = $builder->build( { source => 'Branch' } )->{branchcode};
my $specific_rule_restore = $builder->build(
{
source => 'CirculationRule',
value => {
branchcode => $branchcode3,
categorycode => undef,
itemtype => undef,
rule_name => 'processingreturn',
rule_value => 'restore'
}
}
);
# Make sure we have an unused branchcode
my $branchcode4 = $builder->build( { source => 'Branch' } )->{branchcode};
my $specific_rule_dummy = $builder->build(
{
source => 'CirculationRule',
value => {
branchcode => $branchcode4,
categorycode => undef,
itemtype => undef,
rule_name => 'processingreturn',
rule_value => 'refund'
}
}
);
my $branch_without_rule = $specific_rule_dummy->{ branchcode };
Koha::CirculationRules
->search(
{
branchcode => $branch_without_rule,
categorycode => undef,
itemtype => undef,
rule_name => 'processingreturn',
rule_value => 'refund'
}
)
->next
->delete;
my $item = $builder->build_sample_item(
{
homebranch => $specific_rule_restore->{branchcode},
holdingbranch => $specific_rule_false->{branchcode}
}
);
my $params = {
return_branch => $specific_rule_refund->{ branchcode },
item => $item
};
# Specific rules
t::lib::Mocks::mock_preference( 'RefundLostOnReturnControl', 'CheckinLibrary' );
is( Koha::CirculationRules->get_processingreturn_policy( $params ),
'refund','Specific rule for checkin branch is applied (refund)');
t::lib::Mocks::mock_preference( 'RefundLostOnReturnControl', 'ItemHomeBranch' );
is( Koha::CirculationRules->get_processingreturn_policy( $params ),
'restore','Specific rule for home branch is applied (restore)');
t::lib::Mocks::mock_preference( 'RefundLostOnReturnControl', 'ItemHoldingBranch' );
is( Koha::CirculationRules->get_processingreturn_policy( $params ),
0,'Specific rule for holding branch is applied (false)');
# Default rule check
t::lib::Mocks::mock_preference( 'RefundLostOnReturnControl', 'CheckinLibrary' );
$params->{return_branch} = $branch_without_rule;
is( Koha::CirculationRules->get_processingreturn_policy( $params ),
'charge','No rule for branch, global rule applied (charge)');
# Change the default value just to try
Koha::CirculationRules->search({ branchcode => undef, rule_name => 'processingreturn' })->next->rule_value(0)->store;
is( Koha::CirculationRules->get_processingreturn_policy( $params ),
0,'No rule for branch, global rule applied (false)');
# No default rule defined check
Koha::CirculationRules
->search(
{
branchcode => undef,
categorycode => undef,
itemtype => undef,
rule_name => 'processingreturn'
}
)
->next
->delete;
is( Koha::CirculationRules->get_processingreturn_policy( $params ),
'refund','No rule for branch, no default rule, fallback default (refund)');
# Fallback to ItemHoldBranch if CheckinLibrary is undefined
$params->{return_branch} = undef;
is( Koha::CirculationRules->get_processingreturn_policy( $params ),
'restore','return_branch undefined, fallback to ItemHomeBranch rule (restore)');
$schema->storage->txn_rollback;
};
sub _is_row_match {
my ( $rule, $expected, $message ) = @_;