Browse Source

Bug 18936: (follow-up) Add foreign key and scope enhancement to circ rules

This necessitates moving the circ rules from using '*' to using
undef/NULL.

Signed-off-by: Minna Kivinen <minna.kivinen@hamk.fi>
Signed-off-by: Joonas Kylmälä <joonas.kylmala@helsinki.fi>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
20.05.x
Jesse Weaver 5 years ago
committed by Martin Renvoize
parent
commit
f2dfa17f0e
Signed by: martin.renvoize GPG Key ID: 422B469130441A0F
  1. 28
      C4/Circulation.pm
  2. 10
      C4/Reserves.pm
  3. 153
      Koha/CirculationRules.pm
  4. 32
      Koha/REST/V1/CirculationRules.pm
  5. 154
      admin/smart-rules.pl
  6. 3
      api/v1/swagger/definitions.json
  7. 15
      api/v1/swagger/definitions/circ-rule-kind.json
  8. 3
      api/v1/swagger/paths.json
  9. 35
      api/v1/swagger/paths/circulation-rules.json
  10. 19
      koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt
  11. 24
      t/db_dependent/ArticleRequests.t
  12. 171
      t/db_dependent/Circulation.t
  13. 31
      t/db_dependent/Circulation/Branch.t
  14. 12
      t/db_dependent/Circulation/CalcFine.t
  15. 31
      t/db_dependent/Circulation/GetHardDueDate.t
  16. 12
      t/db_dependent/Circulation/IssuingRules/maxsuspensiondays.t
  17. 12
      t/db_dependent/Circulation/Returns.t
  18. 11
      t/db_dependent/Circulation/SwitchOnSiteCheckouts.t
  19. 8
      t/db_dependent/Circulation/TooMany.t
  20. 6
      t/db_dependent/Circulation/issue.t
  21. 5
      t/db_dependent/DecreaseLoanHighHolds.t
  22. 14
      t/db_dependent/Fines.t
  23. 30
      t/db_dependent/Holds.t
  24. 4
      t/db_dependent/Holds/DisallowHoldIfItemsAvailable.t
  25. 3
      t/db_dependent/Holds/HoldFulfillmentPolicy.t
  26. 1
      t/db_dependent/Holds/HoldItemtypeLimit.t
  27. 8
      t/db_dependent/HoldsQueue.t
  28. 363
      t/db_dependent/Koha/IssuingRules.t
  29. 14
      t/db_dependent/RefundLostItemFeeRule.t
  30. 8
      t/db_dependent/Reserves.t
  31. 34
      t/db_dependent/Reserves/MultiplePerRecord.t
  32. 2
      t/db_dependent/TestBuilder.t
  33. 6
      t/db_dependent/api/v1/holds.t

28
C4/Circulation.pm

@ -425,7 +425,7 @@ sub TooMany {
SELECT itemtype FROM circulation_rules
WHERE branchcode = ?
AND (categorycode = ? OR categorycode = ?)
AND itemtype <> '*'
AND itemtype IS NOT NULL
AND rule_name = 'maxissueqty'
) ";
} else {
@ -434,7 +434,7 @@ sub TooMany {
SELECT itemtype FROM circulation_rules
WHERE branchcode = ?
AND (categorycode = ? OR categorycode = ?)
AND itemtype <> '*'
AND itemtype IS NOT NULL
AND rule_name = 'maxissueqty'
) ";
}
@ -1553,38 +1553,38 @@ sub GetLoanLength {
},
{
categorycode => $categorycode,
itemtype => '*',
itemtype => undef,
branchcode => $branchcode,
},
{
categorycode => '*',
categorycode => undef,
itemtype => $itemtype,
branchcode => $branchcode,
},
{
categorycode => '*',
itemtype => '*',
categorycode => undef,
itemtype => undef,
branchcode => $branchcode,
},
{
categorycode => $categorycode,
itemtype => $itemtype,
branchcode => '*',
branchcode => undef,
},
{
categorycode => $categorycode,
itemtype => '*',
branchcode => '*',
itemtype => undef,
branchcode => undef,
},
{
categorycode => '*',
categorycode => undef,
itemtype => $itemtype,
branchcode => '*',
branchcode => undef,
},
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
categorycode => undef,
itemtype => undef,
branchcode => undef,
},
);

10
C4/Reserves.pm

@ -384,7 +384,7 @@ sub CanItemBeReserved {
$holds_per_day = $rights->{holds_per_day};
}
else {
$ruleitemtype = '*';
$ruleitemtype = undef;
}
my $holds = Koha::Holds->search(
@ -419,15 +419,15 @@ sub CanItemBeReserved {
C4::Context->preference('item-level_itypes')
? " AND COALESCE( items.itype, biblioitems.itemtype ) = ?"
: " AND biblioitems.itemtype = ?"
if ( $ruleitemtype ne "*" );
if defined $ruleitemtype;
my $sthcount = $dbh->prepare($querycount);
if ( $ruleitemtype eq "*" ) {
$sthcount->execute( $borrowernumber, $branchcode );
if ( defined $ruleitemtype ) {
$sthcount->execute( $borrowernumber, $branchcode, $ruleitemtype );
}
else {
$sthcount->execute( $borrowernumber, $branchcode, $ruleitemtype );
$sthcount->execute( $borrowernumber, $branchcode );
}
my $reservecount = "0";

153
Koha/CirculationRules.pm

@ -34,6 +34,128 @@ Koha::CirculationRules - Koha CirculationRule Object set class
=cut
=head3 rule_kinds
This structure describes the possible rules that may be set, and what scopes they can be set at.
Any attempt to set a rule with a nonsensical scope (for instance, setting the C<patron_maxissueqty> for a branchcode and itemtype), is an error.
=cut
our $RULE_KINDS = {
refund => {
scope => [ 'branchcode' ],
},
patron_maxissueqty => {
scope => [ 'branchcode', 'categorycode' ],
},
patron_maxonsiteissueqty => {
scope => [ 'branchcode', 'categorycode' ],
},
max_holds => {
scope => [ 'branchcode', 'categorycode' ],
},
holdallowed => {
scope => [ 'branchcode', 'itemtype' ],
},
hold_fulfillment_policy => {
scope => [ 'branchcode', 'itemtype' ],
},
returnbranch => {
scope => [ 'branchcode', 'itemtype' ],
},
article_requests => {
scope => [ 'branchcode', 'categorycode', 'itemtype' ],
},
auto_renew => {
scope => [ 'branchcode', 'categorycode', 'itemtype' ],
},
cap_fine_to_replacement_price => {
scope => [ 'branchcode', 'categorycode', 'itemtype' ],
},
chargeperiod => {
scope => [ 'branchcode', 'categorycode', 'itemtype' ],
},
chargeperiod_charge_at => {
scope => [ 'branchcode', 'categorycode', 'itemtype' ],
},
fine => {
scope => [ 'branchcode', 'categorycode', 'itemtype' ],
},
finedays => {
scope => [ 'branchcode', 'categorycode', 'itemtype' ],
},
firstremind => {
scope => [ 'branchcode', 'categorycode', 'itemtype' ],
},
hardduedate => {
scope => [ 'branchcode', 'categorycode', 'itemtype' ],
},
hardduedatecompare => {
scope => [ 'branchcode', 'categorycode', 'itemtype' ],
},
holds_per_record => {
scope => [ 'branchcode', 'categorycode', 'itemtype' ],
},
issuelength => {
scope => [ 'branchcode', 'categorycode', 'itemtype' ],
},
lengthunit => {
scope => [ 'branchcode', 'categorycode', 'itemtype' ],
},
maxissueqty => {
scope => [ 'branchcode', 'categorycode', 'itemtype' ],
},
maxonsiteissueqty => {
scope => [ 'branchcode', 'categorycode', 'itemtype' ],
},
maxsuspensiondays => {
scope => [ 'branchcode', 'categorycode', 'itemtype' ],
},
no_auto_renewal_after => {
scope => [ 'branchcode', 'categorycode', 'itemtype' ],
},
no_auto_renewal_after_hard_limit => {
scope => [ 'branchcode', 'categorycode', 'itemtype' ],
},
norenewalbefore => {
scope => [ 'branchcode', 'categorycode', 'itemtype' ],
},
onshelfholds => {
scope => [ 'branchcode', 'categorycode', 'itemtype' ],
},
opacitemholds => {
scope => [ 'branchcode', 'categorycode', 'itemtype' ],
},
overduefinescap => {
scope => [ 'branchcode', 'categorycode', 'itemtype' ],
},
renewalperiod => {
scope => [ 'branchcode', 'categorycode', 'itemtype' ],
},
renewalsallowed => {
scope => [ 'branchcode', 'categorycode', 'itemtype' ],
},
rentaldiscount => {
scope => [ 'branchcode', 'categorycode', 'itemtype' ],
},
reservesallowed => {
scope => [ 'branchcode', 'categorycode', 'itemtype' ],
},
# Not included (deprecated?):
# * accountsent
# * chargename
# * reservecharge
# * restrictedtype
};
sub rule_kinds {
return $RULE_KINDS;
}
=head3 get_effective_rule
=cut
@ -41,9 +163,9 @@ Koha::CirculationRules - Koha CirculationRule Object set class
sub get_effective_rule {
my ( $self, $params ) = @_;
$params->{categorycode} = '*' if exists($params->{categorycode}) && !defined($params->{categorycode});
$params->{branchcode} = '*' if exists($params->{branchcode}) && !defined($params->{branchcode});
$params->{itemtype} = '*' if exists($params->{itemtype}) && !defined($params->{itemtype});
$params->{categorycode} //= undef;
$params->{branchcode} //= undef;
$params->{itemtype} //= undef;
my $rule_name = $params->{rule_name};
my $categorycode = $params->{categorycode};
@ -119,6 +241,20 @@ sub set_rule {
Koha::Exceptions::MissingParameter->throw(
"Required parameter 'branchcode' missing")
unless exists $params->{$mandatory_parameter};
my $kind_info = $RULE_KINDS->{ $params->{rule_name} };
croak "set_rule given unknown rule '$params->{rule_name}'!"
unless defined $kind_info;
# Enforce scope; a rule should be set for its defined scope, no more, no less.
foreach my $scope_level ( qw( branchcode categorycode itemtype ) ) {
if ( grep /$scope_level/, @{ $kind_info->{scope} } ) {
croak "set_rule needs '$scope_level' to set '$params->{rule_name}'!"
unless exists $params->{$scope_level};
} else {
croak "set_rule cannot set '$params->{rule_name}' for a '$scope_level'!"
if exists $params->{$scope_level};
}
}
my $branchcode = $params->{branchcode};
@ -173,18 +309,17 @@ sub set_rule {
sub set_rules {
my ( $self, $params ) = @_;
my $branchcode = $params->{branchcode};
my $categorycode = $params->{categorycode};
my $itemtype = $params->{itemtype};
my %set_params;
$set_params{branchcode} = $params->{branchcode} if exists $params->{branchcode};
$set_params{categorycode} = $params->{categorycode} if exists $params->{categorycode};
$set_params{itemtype} = $params->{itemtype} if exists $params->{itemtype};
my $rules = $params->{rules};
my $rule_objects = [];
while ( my ( $rule_name, $rule_value ) = each %$rules ) {
my $rule_object = Koha::CirculationRules->set_rule(
{
branchcode => $branchcode,
categorycode => $categorycode,
itemtype => $itemtype,
%set_params,
rule_name => $rule_name,
rule_value => $rule_value,
}

32
Koha/REST/V1/CirculationRules.pm

@ -0,0 +1,32 @@
package Koha::REST::V1::CirculationRules;
# This file is part of Koha.
#
# Koha is free software; you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation; either version 3 of the License, or (at your option) any later
# version.
#
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with Koha; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
use Modern::Perl;
use Mojo::Base 'Mojolicious::Controller';
use Koha::CirculationRules;
use Try::Tiny;
sub get_kinds {
my ( $c, $args, $cb ) = @_;
return $c->$cb( Koha::CirculationRules->rule_kinds, 200 );
}
1;

154
admin/smart-rules.pl

@ -81,9 +81,9 @@ if ($op eq 'delete') {
Koha::CirculationRules->set_rules(
{
categorycode => $categorycode,
branchcode => $branch,
itemtype => $itemtype,
categorycode => $categorycode eq '*' ? undef : $categorycode,
branchcode => $branch eq '*' ? undef : $branch,
itemtype => $itemtype eq '*' ? undef : $itemtype,
rules => {
restrictedtype => undef,
rentaldiscount => undef,
@ -119,44 +119,56 @@ elsif ($op eq 'delete-branch-cat') {
my $categorycode = $input->param('categorycode');
if ($branch eq "*") {
if ($categorycode eq "*") {
Koha::CirculationRules->set_rules(
{
categorycode => undef,
branchcode => undef,
itemtype => undef,
rules => {
patron_maxissueqty => undef,
patron_maxonsiteissueqty => undef,
holdallowed => undef,
hold_fulfillment_policy => undef,
returnbranch => undef,
max_holds => undef,
}
}
);
} else {
Koha::CirculationRules->set_rules(
{
categorycode => $categorycode,
branchcode => undef,
itemtype => undef,
rules => {
max_holds => undef,
patron_maxissueqty => undef,
patron_maxonsiteissueqty => undef,
}
}
);
Koha::CirculationRules->set_rules(
{
branchcode => undef,
categorycode => undef,
rules => {
max_holds => undef,
patron_maxissueqty => undef,
patron_maxonsiteissueqty => undef,
}
}
);
Koha::CirculationRules->set_rules(
{
branchcode => undef,
itemtype => undef,
rules => {
holdallowed => undef,
hold_fulfillment_policy => undef,
returnbranch => undef,
}
}
);
} else {
Koha::CirculationRules->set_rules(
{
categorycode => $categorycode,
branchcode => undef,
rules => {
max_holds => undef,
patron_maxissueqty => undef,
patron_maxonsiteissueqty => undef,
}
}
);
}
} elsif ($categorycode eq "*") {
Koha::CirculationRules->set_rules(
{
branchcode => $branch,
categorycode => undef,
rules => {
patron_maxissueqty => undef,
patron_maxonsiteissueqty => undef,
}
}
);
Koha::CirculationRules->set_rules(
{
branchcode => $branch,
itemtype => undef,
rules => {
patron_maxissueqty => undef,
patron_maxonsiteissueqty => undef,
holdallowed => undef,
hold_fulfillment_policy => undef,
returnbranch => undef,
@ -169,7 +181,6 @@ elsif ($op eq 'delete-branch-cat') {
{
categorycode => $categorycode,
branchcode => $branch,
itemtype => undef,
rules => {
max_holds => undef,
patron_maxissueqty => undef,
@ -185,12 +196,9 @@ elsif ($op eq 'delete-branch-item') {
if ($itemtype eq "*") {
Koha::CirculationRules->set_rules(
{
categorycode => undef,
branchcode => undef,
itemtype => undef,
rules => {
patron_maxissueqty => undef,
patron_maxonsiteissueqty => undef,
holdallowed => undef,
hold_fulfillment_policy => undef,
returnbranch => undef,
@ -200,7 +208,6 @@ elsif ($op eq 'delete-branch-item') {
} else {
Koha::CirculationRules->set_rules(
{
categorycode => undef,
branchcode => undef,
itemtype => $itemtype,
rules => {
@ -214,12 +221,9 @@ elsif ($op eq 'delete-branch-item') {
} elsif ($itemtype eq "*") {
Koha::CirculationRules->set_rules(
{
categorycode => undef,
branchcode => $branch,
itemtype => undef,
rules => {
maxissueqty => undef,
maxonsiteissueqty => undef,
holdallowed => undef,
hold_fulfillment_policy => undef,
returnbranch => undef,
@ -229,7 +233,6 @@ elsif ($op eq 'delete-branch-item') {
} else {
Koha::CirculationRules->set_rules(
{
categorycode => undef,
branchcode => $branch,
itemtype => $itemtype,
rules => {
@ -325,9 +328,9 @@ elsif ($op eq 'add') {
Koha::CirculationRules->set_rules(
{
categorycode => $bor,
itemtype => $itemtype,
branchcode => $br,
categorycode => $bor eq '*' ? undef : $bor,
itemtype => $itemtype eq '*' ? undef : $itemtype,
branchcode => $br eq '*' ? undef : $br,
rules => $rules,
}
);
@ -353,30 +356,44 @@ elsif ($op eq "set-branch-defaults") {
if ($branch eq "*") {
Koha::CirculationRules->set_rules(
{
categorycode => undef,
itemtype => undef,
branchcode => undef,
rules => {
patron_maxissueqty => $patron_maxissueqty,
patron_maxonsiteissueqty => $patron_maxonsiteissueqty,
holdallowed => $holdallowed,
hold_fulfillment_policy => $hold_fulfillment_policy,
returnbranch => $returnbranch,
holdallowed => $holdallowed,
hold_fulfillment_policy => $hold_fulfillment_policy,
returnbranch => $returnbranch,
}
}
);
} else {
Koha::CirculationRules->set_rules(
{
categorycode => undef,
branchcode => undef,
rules => {
patron_maxissueqty => $patron_maxissueqty,
patron_maxonsiteissueqty => $patron_maxonsiteissueqty,
}
}
);
} else {
Koha::CirculationRules->set_rules(
{
itemtype => undef,
branchcode => $branch,
rules => {
patron_maxissueqty => $patron_maxissueqty,
patron_maxonsiteissueqty => $patron_maxonsiteissueqty,
holdallowed => $holdallowed,
hold_fulfillment_policy => $hold_fulfillment_policy,
returnbranch => $returnbranch,
holdallowed => $holdallowed,
hold_fulfillment_policy => $hold_fulfillment_policy,
returnbranch => $returnbranch,
}
}
);
Koha::CirculationRules->set_rules(
{
categorycode => undef,
branchcode => $branch,
rules => {
patron_maxissueqty => $patron_maxissueqty,
patron_maxonsiteissueqty => $patron_maxonsiteissueqty,
}
}
);
@ -408,7 +425,6 @@ elsif ($op eq "add-branch-cat") {
Koha::CirculationRules->set_rules(
{
categorycode => undef,
itemtype => undef,
branchcode => undef,
rules => {
max_holds => $max_holds,
@ -420,9 +436,8 @@ elsif ($op eq "add-branch-cat") {
} else {
Koha::CirculationRules->set_rules(
{
branchcode => undef,
categorycode => $categorycode,
itemtype => undef,
branchcode => undef,
rules => {
max_holds => $max_holds,
patron_maxissueqty => $patron_maxissueqty,
@ -435,7 +450,6 @@ elsif ($op eq "add-branch-cat") {
Koha::CirculationRules->set_rules(
{
categorycode => undef,
itemtype => undef,
branchcode => $branch,
rules => {
max_holds => $max_holds,
@ -448,7 +462,6 @@ elsif ($op eq "add-branch-cat") {
Koha::CirculationRules->set_rules(
{
categorycode => $categorycode,
itemtype => undef,
branchcode => $branch,
rules => {
max_holds => $max_holds,
@ -472,7 +485,6 @@ elsif ($op eq "add-branch-item") {
if ($itemtype eq "*") {
Koha::CirculationRules->set_rules(
{
categorycode => undef,
itemtype => undef,
branchcode => undef,
rules => {
@ -485,7 +497,6 @@ elsif ($op eq "add-branch-item") {
} else {
Koha::CirculationRules->set_rules(
{
categorycode => undef,
itemtype => $itemtype,
branchcode => undef,
rules => {
@ -499,7 +510,6 @@ elsif ($op eq "add-branch-item") {
} elsif ($itemtype eq "*") {
Koha::CirculationRules->set_rules(
{
categorycode => undef,
itemtype => undef,
branchcode => $branch,
rules => {
@ -512,7 +522,6 @@ elsif ($op eq "add-branch-item") {
} else {
Koha::CirculationRules->set_rules(
{
categorycode => undef,
itemtype => $itemtype,
branchcode => $branch,
rules => {
@ -533,8 +542,6 @@ elsif ( $op eq 'mod-refund-lost-item-fee-rule' ) {
# only do something for $refund eq '*' if branch-specific
Koha::CirculationRules->set_rules(
{
categorycode => undef,
itemtype => undef,
branchcode => $branch,
rules => {
refund => undef
@ -545,9 +552,7 @@ elsif ( $op eq 'mod-refund-lost-item-fee-rule' ) {
} else {
Koha::CirculationRules->set_rules(
{
categorycode => undef,
itemtype => undef,
branchcode => $branch,
branchcode => undef,
rules => {
refund => $refund
}
@ -556,8 +561,7 @@ elsif ( $op eq 'mod-refund-lost-item-fee-rule' ) {
}
}
my $refundLostItemFeeRule = Koha::RefundLostItemFeeRules->find({ branchcode => ($branch eq '*') ? undef:$branch });
my $refundLostItemFeeRule = Koha::RefundLostItemFeeRules->find({ branchcode => ($branch eq '*') ? undef : $branch });
$template->param(
refundLostItemFeeRule => $refundLostItemFeeRule,
defaultRefundRule => Koha::RefundLostItemFeeRules->_default_rule
@ -572,7 +576,7 @@ $template->param(show_branch_cat_rule_form => 1);
$template->param(
patron_categories => $patron_categories,
itemtypeloop => $itemtypes,
humanbranch => ( $branch ne '*' ? $branch : '' ),
humanbranch => ( $branch ne '*' ? $branch : undef ),
current_branch => $branch,
);
output_html_with_http_headers $input, $cookie, $template->output;

3
api/v1/swagger/definitions.json

@ -5,6 +5,9 @@
"basket": {
"$ref": "definitions/basket.json"
},
"circ-rule-kind": {
"$ref": "definitions/circ-rule-kind.json"
},
"city": {
"$ref": "definitions/city.json"
},

15
api/v1/swagger/definitions/circ-rule-kind.json

@ -0,0 +1,15 @@
{
"type": "object",
"properties": {
"scope": {
"description": "levels that this rule kind can be set for",
"type": "array",
"items": {
"type": "string",
"enum": [ "branchcode", "categorycode", "itemtype" ]
}
}
},
"additionalProperties": false,
"required": ["scope"]
}

3
api/v1/swagger/paths.json

@ -26,6 +26,9 @@
"/checkouts/{checkout_id}/renewal": {
"$ref": "paths/checkouts.json#/~1checkouts~1{checkout_id}~1renewal"
},
"/circulation-rules/kinds": {
"$ref": "paths/circulation-rules.json#/~1circulation-rules~1kinds"
},
"/cities": {
"$ref": "paths/cities.json#/~1cities"
},

35
api/v1/swagger/paths/circulation-rules.json

@ -0,0 +1,35 @@
{
"/circulation-rules/kinds": {
"get": {
"x-mojo-controller": "Koha::REST::V1::CirculationRules",
"operationId": "get_kinds",
"tags": ["cities"],
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "A map of rule kind information",
"schema": {
"type": "object",
"additionalProperties": {
"$ref": "../definitions.json#/circ-rule-kind"
}
}
},
"403": {
"description": "Access forbidden",
"schema": {
"$ref": "../definitions.json#/error"
}
},
"500": {
"description": "Internal error",
"schema": {
"$ref": "../definitions.json#/error"
}
}
}
}
}
}

19
koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt

@ -8,19 +8,19 @@
[% USE CirculationRules %]
[% SET footerjs = 1 %]
[% SET branchcode = humanbranch || '*' %]
[% SET branchcode = humanbranch || undef %]
[% SET categorycodes = [] %]
[% FOREACH pc IN patron_categories %]
[% categorycodes.push( pc.id ) %]
[% END %]
[% categorycodes.push('*') %]
[% categorycodes.push(undef) %]
[% SET itemtypes = [] %]
[% FOREACH i IN itemtypeloop %]
[% itemtypes.push( i.itemtype ) %]
[% END %]
[% itemtypes.push('*') %]
[% itemtypes.push(undef) %]
[% INCLUDE 'doc-head-open.inc' %]
<title>Koha &rsaquo; Administration &rsaquo; Circulation and fine rules</title>
@ -162,19 +162,23 @@
[% SET row_count = row_count + 1 %]
<tr row_countd="row_[% row_count %]">
<td>
[% IF c == '*' %]
[% IF c == undef %]
<em>All</em>
[% ELSE %]
[% Categories.GetName(c) %]
[% END %]
</td>
<td>
[% IF i == '*' %]
[% IF i == undef %]
<em>All</em>
[% ELSE %]
[% ItemTypes.GetDescription(i) %]
[% END %]
</td>
<td class="actions">
<a href="#" class="editrule btn btn-default btn-xs"><i class="fa fa-pencil"></i> Edit</a>
<a class="btn btn-default btn-xs delete" href="/cgi-bin/koha/admin/smart-rules.pl?op=delete&amp;itemtype=[% rule.itemtype || '*' %]&amp;categorycode=[% rule.categorycode || '*' %]&amp;branch=[% current_branch %]"><i class="fa fa-trash"></i> Delete</a>
</td>
<td>
[% IF rule.note %]
<a name="viewnote" data-toggle="popover" title="Note" data-content="[% rule.note | html %]" data-placement="top" data-trigger="hover">View note</a>
@ -288,7 +292,7 @@
<td>[% rentaldiscount %]</td>
<td class="actions">
<a href="#" class="editrule btn btn-default btn-xs"><i class="fa fa-pencil"></i> Edit</a>
<a class="btn btn-default btn-xs delete" href="/cgi-bin/koha/admin/smart-rules.pl?op=delete&amp;itemtype=[% rule.itemtype | uri %]&amp;categorycode=[% rule.categorycode | uri %]&amp;branch=[% rule.current_branch | uri %]"><i class="fa fa-trash"></i> Delete</a>
<a class="btn btn-default btn-xs delete" href="/cgi-bin/koha/admin/smart-rules.pl?op=delete&amp;itemtype=[% rule.itemtype || '*' | uri %]&amp;categorycode=[% rule.categorycode || '*' | uri %]&amp;branch=[% rule.current_branch | uri %]"><i class="fa fa-trash"></i> Delete</a>
</td>
</tr>
[% END %]
@ -625,6 +629,7 @@
<th>&nbsp;</th>
</tr>
[% FOREACH c IN categorycodes %]
[% NEXT UNLESS c %]
[% SET patron_maxissueqty = CirculationRules.Search( branchcode, c, undef, 'patron_maxissueqty' ) %]
[% SET patron_maxonsiteissueqty = CirculationRules.Search( branchcode, c, undef, 'patron_maxonsiteissueqty' ) %]
[% SET max_holds = CirculationRules.Search( branchcode, c, undef, 'max_holds' ) %]
@ -632,7 +637,7 @@
[% IF ( patron_maxissueqty.defined && patron_maxissueqty != '' ) || ( patron_maxonsiteissueqty.defined && patron_maxonsiteissueqty != '' ) || ( max_holds.defined && max_holds != '' ) %]
<tr>
<td>
[% IF c == '*'%]
[% IF c == undef %]
<em>Default</em>
[% ELSE %]
[% Categories.GetName(c) | html %]

24
t/db_dependent/ArticleRequests.t

@ -174,9 +174,9 @@ is( $biblio->article_requests_finished()->count(), 1, 'Canceled request not retu
my $rule = Koha::CirculationRules->set_rule(
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
categorycode => undef,
itemtype => undef,
branchcode => undef,
rule_name => 'article_requests',
rule_value => 'yes',
}
@ -189,9 +189,9 @@ $rule->delete();
$rule = Koha::CirculationRules->set_rule(
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
categorycode => undef,
itemtype => undef,
branchcode => undef,
rule_name => 'article_requests',
rule_value => 'bib_only',
}
@ -204,9 +204,9 @@ $rule->delete();
$rule = Koha::CirculationRules->set_rule(
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
categorycode => undef,
itemtype => undef,
branchcode => undef,
rule_name => 'article_requests',
rule_value => 'item_only',
}
@ -219,9 +219,9 @@ $rule->delete();
$rule = Koha::CirculationRules->set_rule(
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
categorycode => undef,
itemtype => undef,
branchcode => undef,
rule_name => 'article_requests',
rule_value => 'no',
}

171
t/db_dependent/Circulation.t

@ -20,6 +20,7 @@ use utf8;
use Test::More tests => 46;
use Test::MockModule;
use Test::Deep qw( cmp_deeply );
use Data::Dumper;
use DateTime;
@ -254,9 +255,9 @@ is(
$dbh->do('DELETE FROM circulation_rules');
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
categorycode => undef,
branchcode => undef,
itemtype => undef,
rules => {
reservesallowed => 25,
issuelength => 14,
@ -392,9 +393,9 @@ subtest "CanBookBeRenewed tests" => sub {
# Testing of feature to allow the renewal of reserved items if other items on the record can fill all needed holds
Koha::CirculationRules->set_rule(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
categorycode => undef,
branchcode => undef,
itemtype => undef,
rule_name => 'onshelfholds',
rule_value => '1',
}
@ -615,9 +616,9 @@ subtest "CanBookBeRenewed tests" => sub {
# Test premature manual renewal
Koha::CirculationRules->set_rule(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
categorycode => undef,
branchcode => undef,
itemtype => undef,
rule_name => 'norenewalbefore',
rule_value => '7',
}
@ -692,9 +693,9 @@ subtest "CanBookBeRenewed tests" => sub {
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
categorycode => undef,
branchcode => undef,
itemtype => undef,
rules => {
norenewalbefore => '7',
no_auto_renewal_after => '9',
@ -708,9 +709,9 @@ subtest "CanBookBeRenewed tests" => sub {
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
categorycode => undef,
branchcode => undef,
itemtype => undef,
rules => {
norenewalbefore => '7',
no_auto_renewal_after => '10',
@ -724,9 +725,9 @@ subtest "CanBookBeRenewed tests" => sub {
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
categorycode => undef,
branchcode => undef,
itemtype => undef,
rules => {
norenewalbefore => '7',
no_auto_renewal_after => '11',
@ -740,9 +741,9 @@ subtest "CanBookBeRenewed tests" => sub {
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
categorycode => undef,
branchcode => undef,
itemtype => undef,
rules => {
norenewalbefore => '10',
no_auto_renewal_after => '11',
@ -756,9 +757,9 @@ subtest "CanBookBeRenewed tests" => sub {
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
categorycode => undef,
branchcode => undef,
itemtype => undef,
rules => {
norenewalbefore => '10',
no_auto_renewal_after => undef,
@ -773,9 +774,9 @@ subtest "CanBookBeRenewed tests" => sub {
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
categorycode => undef,
branchcode => undef,
itemtype => undef,
rules => {
norenewalbefore => '7',
no_auto_renewal_after => '15',
@ -790,9 +791,9 @@ subtest "CanBookBeRenewed tests" => sub {
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
categorycode => undef,
branchcode => undef,
itemtype => undef,
rules => {
norenewalbefore => '10',
no_auto_renewal_after => undef,
@ -823,9 +824,9 @@ subtest "CanBookBeRenewed tests" => sub {
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
categorycode => undef,
branchcode => undef,
itemtype => undef,
rules => {
norenewalbefore => '10',
no_auto_renewal_after => '11',
@ -971,9 +972,9 @@ subtest "CanBookBeRenewed tests" => sub {
AddIssue( $renewing_borrower, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
categorycode => undef,
branchcode => undef,
itemtype => undef,
rules => {
norenewalbefore => '7',
no_auto_renewal_after => '',
@ -986,9 +987,9 @@ subtest "CanBookBeRenewed tests" => sub {
my $five_days_before = dt_from_string->add( days => -5 );
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
categorycode => undef,
branchcode => undef,
itemtype => undef,
rules => {
norenewalbefore => '10',
no_auto_renewal_after => '5',
@ -1007,9 +1008,9 @@ subtest "CanBookBeRenewed tests" => sub {
$dbh->do(q{UPDATE circulation_rules SET rule_value = NULL WHERE rule_name = 'no_auto_renewal_after_hard_limit'});
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
categorycode => undef,
branchcode => undef,
itemtype => undef,
rules => {
norenewalbefore => '10',
no_auto_renewal_after => '15',
@ -1025,9 +1026,9 @@ subtest "CanBookBeRenewed tests" => sub {
my $two_days_ahead = dt_from_string->add( days => 2 );
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
categorycode => undef,
branchcode => undef,
itemtype => undef,
rules => {
norenewalbefore => '10',
no_auto_renewal_after => '',
@ -1042,9 +1043,9 @@ subtest "CanBookBeRenewed tests" => sub {
);
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
categorycode => undef,
branchcode => undef,
itemtype => undef,
rules => {
norenewalbefore => '10',
no_auto_renewal_after => '15',
@ -1064,9 +1065,9 @@ subtest "CanBookBeRenewed tests" => sub {
# set policy to forbid renewals
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
categorycode => undef,
branchcode => undef,
itemtype => undef,
rules => {
norenewalbefore => undef,
renewalsallowed => 0,
@ -1310,9 +1311,9 @@ subtest "AllowRenewalIfOtherItemsAvailable tests" => sub {
$dbh->do('DELETE FROM circulation_rules');
Koha::CirculationRules->set_rules(
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
categorycode => undef,
itemtype => undef,
branchcode => undef,
rules => {
reservesallowed => 25,
issuelength => 14,
@ -1374,9 +1375,9 @@ subtest "AllowRenewalIfOtherItemsAvailable tests" => sub {
Koha::CirculationRules->set_rules(
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
categorycode => undef,
itemtype => undef,
branchcode => undef,
rules => {
onshelfholds => 0,
}
@ -1388,9 +1389,9 @@ subtest "AllowRenewalIfOtherItemsAvailable tests" => sub {
Koha::CirculationRules->set_rules(
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
categorycode => undef,
itemtype => undef,
branchcode => undef,
rules => {
onshelfholds => 0,
}
@ -1402,9 +1403,9 @@ subtest "AllowRenewalIfOtherItemsAvailable tests" => sub {
Koha::CirculationRules->set_rules(
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
categorycode => undef,
itemtype => undef,
branchcode => undef,
rules => {
onshelfholds => 1,
}
@ -1416,9 +1417,9 @@ subtest "AllowRenewalIfOtherItemsAvailable tests" => sub {
Koha::CirculationRules->set_rules(
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
categorycode => undef,
itemtype => undef,
branchcode => undef,
rules => {
onshelfholds => 1,
}
@ -1856,23 +1857,39 @@ subtest 'CanBookBeIssued + AllowMultipleIssuesOnABiblio' => sub {
t::lib::Mocks::mock_preference('AllowMultipleIssuesOnABiblio', 0);
( $error, $question, $alerts ) = CanBookBeIssued( $patron, $item_2->{barcode} );
is( keys(%$error) + keys(%$alerts), 0, 'No error or alert should be raised' . str($error, $question, $alerts) );
is( $question->{BIBLIO_ALREADY_ISSUED}, 1, 'BIBLIO_ALREADY_ISSUED question flag should be set if AllowMultipleIssuesOnABiblio=0 and issue already exists' . str($error, $question, $alerts) );
cmp_deeply(
{ error => $error, alerts => $alerts },
{ error => {}, alerts => {} },
'No error or alert should be raised'
);
is( $question->{BIBLIO_ALREADY_ISSUED}, 1, 'BIBLIO_ALREADY_ISSUED question flag should be set if AllowMultipleIssuesOnABiblio=0 and issue already exists' );
t::lib::Mocks::mock_preference('AllowMultipleIssuesOnABiblio', 1);
( $error, $question, $alerts ) = CanBookBeIssued( $patron, $item_2->{barcode} );
is( keys(%$error) + keys(%$question) + keys(%$alerts), 0, 'No BIBLIO_ALREADY_ISSUED flag should be set if AllowMultipleIssuesOnABiblio=1' . str($error, $question, $alerts) );
cmp_deeply(
{ error => $error, question => $question, alerts => $alerts },
{ error => {}, question => {}, alerts => {} },
'No BIBLIO_ALREADY_ISSUED flag should be set if AllowMultipleIssuesOnABiblio=1'
);
# Add a subscription
Koha::Subscription->new({ biblionumber => $biblionumber })->store;
t::lib::Mocks::mock_preference('AllowMultipleIssuesOnABiblio', 0);
( $error, $question, $alerts ) = CanBookBeIssued( $patron, $item_2->{barcode} );
is( keys(%$error) + keys(%$question) + keys(%$alerts), 0, 'No BIBLIO_ALREADY_ISSUED flag should be set if it is a subscription' . str($error, $question, $alerts) );
cmp_deeply(
{ error => $error, question => $question, alerts => $alerts },
{ error => {}, question => {}, alerts => {} },
'No BIBLIO_ALREADY_ISSUED flag should be set if it is a subscription'
);
t::lib::Mocks::mock_preference('AllowMultipleIssuesOnABiblio', 1);
( $error, $question, $alerts ) = CanBookBeIssued( $patron, $item_2->{barcode} );
is( keys(%$error) + keys(%$question) + keys(%$alerts), 0, 'No BIBLIO_ALREADY_ISSUED flag should be set if it is a subscription' . str($error, $question, $alerts) );
cmp_deeply(
{ error => $error, question => $question, alerts => $alerts },
{ error => {}, question => {}, alerts => {} },
'No BIBLIO_ALREADY_ISSUED flag should be set if it is a subscription'
);
};
subtest 'AddReturn + CumulativeRestrictionPeriods' => sub {
@ -1904,9 +1921,9 @@ subtest 'AddReturn + CumulativeRestrictionPeriods' => sub {
Koha::CirculationRules->search->delete;
Koha::CirculationRules->set_rules(
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
categorycode => undef,
itemtype => undef,
branchcode => undef,
rules => {
issuelength => 1,
firstremind => 1, # 1 day of grace
@ -2215,9 +2232,9 @@ subtest 'AddReturn | is_overdue' => sub {
Koha::CirculationRules->search->delete;
my $rule = Koha::CirculationRules->set_rules(
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
categorycode => undef,
itemtype => undef,
branchcode => undef,
rules => {
issuelength => 6,
lengthunit => 'days',

31
t/db_dependent/Circulation/Branch.t

@ -154,7 +154,6 @@ Koha::CirculationRules->set_rules(
{
branchcode => $samplebranch1->{branchcode},
categorycode => $samplecat->{categorycode},
itemtype => undef,
rules => {
patron_maxissueqty => 5,
patron_maxonsiteissueqty => 6,
@ -162,16 +161,24 @@ Koha::CirculationRules->set_rules(
}
);
Koha::CirculationRules->set_rules(
{
branchcode => $samplebranch2->{branchcode},
categorycode => undef,
itemtype => undef,
rules => {
patron_maxissueqty => 3,
patron_maxonsiteissueqty => 2,
holdallowed => 1,
returnbranch => 'holdingbranch',
}
}
);
Koha::CirculationRules->set_rules(
{
branchcode => $samplebranch2->{branchcode},
itemtype => undef,
rules => {
holdallowed => 1,
returnbranch => 'holdingbranch',
}
}
);
@ -180,12 +187,19 @@ Koha::CirculationRules->set_rules(
{
branchcode => undef,
categorycode => undef,
itemtype => undef,
rules => {
patron_maxissueqty => 4,
patron_maxonsiteissueqty => 5,
holdallowed => 3,
returnbranch => 'homebranch',
}
}
);
Koha::CirculationRules->set_rules(
{
branchcode => undef,
itemtype => undef,
rules => {
holdallowed => 3,
returnbranch => 'homebranch',
}
}
);
@ -193,7 +207,6 @@ Koha::CirculationRules->set_rules(
Koha::CirculationRules->set_rules(
{
branchcode => $samplebranch1->{branchcode},
categorycode => undef,
itemtype => $sampleitemtype1->{itemtype},
rules => {
holdallowed => 5,
@ -204,7 +217,6 @@ Koha::CirculationRules->set_rules(
Koha::CirculationRules->set_rules(
{
branchcode => $samplebranch2->{branchcode},
categorycode => undef,
itemtype => $sampleitemtype1->{itemtype},
rules => {
holdallowed => 5,
@ -215,7 +227,6 @@ Koha::CirculationRules->set_rules(
Koha::CirculationRules->set_rules(
{
branchcode => $samplebranch2->{branchcode},
categorycode => undef,
itemtype => $sampleitemtype2->{itemtype},
rules => {
holdallowed => 5,

12
t/db_dependent/Circulation/CalcFine.t

@ -80,9 +80,9 @@ subtest 'Test basic functionality' => sub {
Koha::CirculationRules->set_rules(
{
branchcode => '*',
categorycode => '*',
itemtype => '*',
branchcode => undef,
categorycode => undef,
itemtype => undef,
rules => {
fine => '1.00',
lengthunit => 'days',
@ -120,9 +120,9 @@ subtest 'Test cap_fine_to_replacement_price' => sub {
t::lib::Mocks::mock_preference('useDefaultReplacementCost', '1');
Koha::CirculationRules->set_rules(
{
branchcode => '*',
categorycode => '*',
itemtype => '*',
branchcode => undef,
categorycode => undef,
itemtype => undef,
rules => {
fine => '1.00',
lengthunit => 'days',

31
t/db_dependent/Circulation/GetHardDueDate.t

@ -8,7 +8,9 @@ use Koha::DateUtils;
use Koha::CirculationRules;
use Koha::Library;
use Test::More tests => 8;
use t::lib::TestBuilder;