Browse Source

Bug 18936: Convert issuingrules fields to circulation_rules

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
Kyle Hall 7 years ago
committed by Martin Renvoize
parent
commit
58fda20e85
Signed by: martin.renvoize GPG Key ID: 422B469130441A0F
  1. 358
      C4/Circulation.pm
  2. 35
      C4/Overdues.pm
  3. 45
      C4/Reserves.pm
  4. 14
      Koha/Biblio.pm
  5. 43
      Koha/CirculationRules.pm
  6. 68
      Koha/IssuingRule.pm
  7. 15
      Koha/Item.pm
  8. 327
      Koha/Schema/Result/Issuingrule.pm
  9. 115
      admin/smart-rules.pl
  10. 45
      installer/data/mysql/atomicupdate/bug_18936.perl
  11. 330
      koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt
  12. 49
      t/db_dependent/ArticleRequests.t
  13. 346
      t/db_dependent/Circulation.t
  14. 23
      t/db_dependent/Circulation/CalcDateDue.t
  15. 34
      t/db_dependent/Circulation/CalcFine.t
  16. 314
      t/db_dependent/Circulation/GetHardDueDate.t
  17. 31
      t/db_dependent/Circulation/IssuingRules/maxsuspensiondays.t
  18. 21
      t/db_dependent/Circulation/Returns.t
  19. 21
      t/db_dependent/Circulation/SwitchOnSiteCheckouts.t
  20. 14
      t/db_dependent/Circulation/TooMany.t
  21. 16
      t/db_dependent/Circulation/issue.t
  22. 16
      t/db_dependent/DecreaseLoanHighHolds.t
  23. 35
      t/db_dependent/Fines.t
  24. 87
      t/db_dependent/Holds.t
  25. 22
      t/db_dependent/Holds/DisallowHoldIfItemsAvailable.t
  26. 87
      t/db_dependent/Koha/IssuingRules.t
  27. 9
      t/db_dependent/Koha/Objects.t
  28. 44
      t/db_dependent/Reserves.t
  29. 105
      t/db_dependent/Reserves/MultiplePerRecord.t
  30. 4
      t/db_dependent/TestBuilder.t
  31. 16
      t/db_dependent/api/v1/holds.t

358
C4/Circulation.pm

@ -44,7 +44,6 @@ use Koha::Biblioitems;
use Koha::DateUtils;
use Koha::Calendar;
use Koha::Checkouts;
use Koha::IssuingRules;
use Koha::Items;
use Koha::Patrons;
use Koha::Patron::Debarments;
@ -423,18 +422,20 @@ sub TooMany {
# specific rule
if (C4::Context->preference('item-level_itypes')) {
$count_query .= " WHERE items.itype NOT IN (
SELECT itemtype FROM issuingrules
SELECT itemtype FROM circulation_rules
WHERE branchcode = ?
AND (categorycode = ? OR categorycode = ?)
AND itemtype <> '*'
AND rule_name = 'maxissueqty'
) ";
} else {
$count_query .= " JOIN biblioitems USING (biblionumber)
} else {
$count_query .= " JOIN biblioitems USING (biblionumber)
WHERE biblioitems.itemtype NOT IN (
SELECT itemtype FROM issuingrules
SELECT itemtype FROM circulation_rules
WHERE branchcode = ?
AND (categorycode = ? OR categorycode = ?)
AND itemtype <> '*'
AND rule_name = 'maxissueqty'
) ";
}
push @bind_params, $maxissueqty_rule->branchcode;
@ -1391,14 +1392,16 @@ sub AddIssue {
# If automatic renewal wasn't selected while issuing, set the value according to the issuing rule.
unless ($auto_renew) {
my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
{ categorycode => $borrower->{categorycode},
my $rule = Koha::CirculationRules->get_effective_rule(
{
categorycode => $borrower->{categorycode},
itemtype => $item_object->effective_itemtype,
branchcode => $branchcode
branchcode => $branchcode,
rule_name => 'auto_renew'
}
);
$auto_renew = $issuing_rule->auto_renew if $issuing_rule;
$auto_renew = $rule->rule_value if $rule;
}
# Record in the database the fact that the book was issued.
@ -1539,67 +1542,77 @@ Get loan length for an itemtype, a borrower type and a branch
=cut
sub GetLoanLength {
my ( $borrowertype, $itemtype, $branchcode ) = @_;
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare(qq{
SELECT issuelength, lengthunit, renewalperiod
FROM issuingrules
WHERE categorycode=?
AND itemtype=?
AND branchcode=?
AND issuelength IS NOT NULL
});
my ( $categorycode, $itemtype, $branchcode ) = @_;
# Set search precedences
my @params = (
{
categorycode => $categorycode,
itemtype => $itemtype,
branchcode => $branchcode,
},
{
categorycode => $categorycode,
itemtype => '*',
branchcode => $branchcode,
},
{
categorycode => '*',
itemtype => $itemtype,
branchcode => $branchcode,
},
{
categorycode => '*',
itemtype => '*',
branchcode => $branchcode,
},
{
categorycode => $categorycode,
itemtype => $itemtype,
branchcode => '*',
},
{
categorycode => $categorycode,
itemtype => '*',
branchcode => '*',
},
{
categorycode => '*',
itemtype => $itemtype,
branchcode => '*',
},
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
},
);
# try to find issuelength & return the 1st available.
# check with borrowertype, itemtype and branchcode, then without one of those parameters
$sth->execute( $borrowertype, $itemtype, $branchcode );
my $loanlength = $sth->fetchrow_hashref;
return $loanlength
if defined($loanlength) && defined $loanlength->{issuelength};
$sth->execute( $borrowertype, '*', $branchcode );
$loanlength = $sth->fetchrow_hashref;
return $loanlength
if defined($loanlength) && defined $loanlength->{issuelength};
$sth->execute( '*', $itemtype, $branchcode );
$loanlength = $sth->fetchrow_hashref;
return $loanlength
if defined($loanlength) && defined $loanlength->{issuelength};
$sth->execute( '*', '*', $branchcode );
$loanlength = $sth->fetchrow_hashref;
return $loanlength
if defined($loanlength) && defined $loanlength->{issuelength};
$sth->execute( $borrowertype, $itemtype, '*' );
$loanlength = $sth->fetchrow_hashref;
return $loanlength
if defined($loanlength) && defined $loanlength->{issuelength};
$sth->execute( $borrowertype, '*', '*' );
$loanlength = $sth->fetchrow_hashref;
return $loanlength
if defined($loanlength) && defined $loanlength->{issuelength};
$sth->execute( '*', $itemtype, '*' );
$loanlength = $sth->fetchrow_hashref;
return $loanlength
if defined($loanlength) && defined $loanlength->{issuelength};
$sth->execute( '*', '*', '*' );
$loanlength = $sth->fetchrow_hashref;
return $loanlength
if defined($loanlength) && defined $loanlength->{issuelength};
# if no rule is set => 0 day (hardcoded)
return {
issuelength => 0,
# Initialize default values
my $rules = {
issuelength => 0,
renewalperiod => 0,
lengthunit => 'days',
lengthunit => 'days',
};
# Search for rules!
foreach my $rule_name (qw( issuelength renewalperiod lengthunit )) {
foreach my $params (@params) {
my $rule = Koha::CirculationRules->search(
{
rule_name => $rule_name,
%$params,
}
)->next();
if ($rule) {
$rules->{$rule_name} = $rule->rule_value;
last;
}
}
}
return $rules;
}
@ -1614,19 +1627,21 @@ Get the Hard Due Date and it's comparison for an itemtype, a borrower type and a
sub GetHardDueDate {
my ( $borrowertype, $itemtype, $branchcode ) = @_;
my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
{ categorycode => $borrowertype,
my $rules = Koha::CirculationRules->get_effective_rules(
{
categorycode => $borrowertype,
itemtype => $itemtype,
branchcode => $branchcode
branchcode => $branchcode,
rules => [ 'hardduedate', 'hardduedatecompare' ],
}
);
if ( defined( $issuing_rule ) ) {
if ( $issuing_rule->hardduedate ) {
return (dt_from_string($issuing_rule->hardduedate, 'iso'),$issuing_rule->hardduedatecompare);
} else {
return (undef, undef);
if ( defined( $rules->{hardduedate} ) ) {
if ( $rules->{hardduedate} ) {
return ( dt_from_string( $rules->{hardduedate}, 'iso' ), $rules->{hardduedatecompare} );
}
else {
return ( undef, undef );
}
}
}
@ -2245,14 +2260,20 @@ sub _calculate_new_debar_dt {
my $branchcode = _GetCircControlBranch( $item, $borrower );
my $circcontrol = C4::Context->preference('CircControl');
my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
my $issuing_rule = Koha::CirculationRules->get_effective_rules(
{ categorycode => $borrower->{categorycode},
itemtype => $item->{itype},
branchcode => $branchcode
branchcode => $branchcode,
rules => [
'finedays',
'lengthunit',
'firstremind',
'maxsuspensiondays',
]
}
);
my $finedays = $issuing_rule ? $issuing_rule->finedays : undef;
my $unit = $issuing_rule ? $issuing_rule->lengthunit : undef;
my $finedays = $issuing_rule ? $issuing_rule->{finedays} : undef;
my $unit = $issuing_rule ? $issuing_rule->{lengthunit} : undef;
my $chargeable_units = C4::Overdues::get_chargeable_units($unit, $dt_due, $return_date, $branchcode);
return unless $finedays;
@ -2263,7 +2284,7 @@ sub _calculate_new_debar_dt {
# grace period is measured in the same units as the loan
my $grace =
DateTime::Duration->new( $unit => $issuing_rule->firstremind );
DateTime::Duration->new( $unit => $issuing_rule->{firstremind} );
my $deltadays = DateTime::Duration->new(
days => $chargeable_units
@ -2272,16 +2293,16 @@ sub _calculate_new_debar_dt {
if ( $deltadays->subtract($grace)->is_positive() ) {
my $suspension_days = $deltadays * $finedays;
if ( $issuing_rule->suspension_chargeperiod > 1 ) {
if ( $issuing_rule->{suspension_chargeperiod} > 1 ) {
# No need to / 1 and do not consider / 0
$suspension_days = DateTime::Duration->new(
days => floor( $suspension_days->in_units('days') / $issuing_rule->suspension_chargeperiod )
days => floor( $suspension_days->in_units('days') / $issuing_rule->{suspension_chargeperiod} )
);
}
# If the max suspension days is < than the suspension days
# the suspension days is limited to this maximum period.
my $max_sd = $issuing_rule->maxsuspensiondays;
my $max_sd = $issuing_rule->{maxsuspensiondays};
if ( defined $max_sd ) {
$max_sd = DateTime::Duration->new( days => $max_sd );
$suspension_days = $max_sd
@ -2749,15 +2770,23 @@ sub CanBookBeRenewed {
return ( 1, undef ) if $override_limit;
my $branchcode = _GetCircControlBranch( $item->unblessed, $patron->unblessed );
my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
{ categorycode => $patron->categorycode,
my $issuing_rule = Koha::CirculationRules->get_effective_rules(
{
categorycode => $patron->categorycode,
itemtype => $item->effective_itemtype,
branchcode => $branchcode
branchcode => $branchcode,
rules => [
'renewalsallowed',
'no_auto_renewal_after',
'no_auto_renewal_after_hard_limit',
'lengthunit',
'norenewalbefore',
]
}
);
return ( 0, "too_many" )
if not $issuing_rule or $issuing_rule->renewalsallowed <= $issue->renewals;
if not $issuing_rule->{renewalsallowed} or $issuing_rule->{renewalsallowed} <= $issue->renewals;
my $overduesblockrenewing = C4::Context->preference('OverduesBlockRenewing');
my $restrictionblockrenewing = C4::Context->preference('RestrictionBlockRenewing');
@ -2777,23 +2806,23 @@ sub CanBookBeRenewed {
return ( 0, 'auto_account_expired' );
}
if ( defined $issuing_rule->no_auto_renewal_after
and $issuing_rule->no_auto_renewal_after ne "" ) {
if ( defined $issuing_rule->{no_auto_renewal_after}
and $issuing_rule->{no_auto_renewal_after} ne "" ) {
# Get issue_date and add no_auto_renewal_after
# If this is greater than today, it's too late for renewal.
my $maximum_renewal_date = dt_from_string($issue->issuedate, 'sql');
$maximum_renewal_date->add(
$issuing_rule->lengthunit => $issuing_rule->no_auto_renewal_after
$issuing_rule->{lengthunit} => $issuing_rule->{no_auto_renewal_after}
);
my $now = dt_from_string;
if ( $now >= $maximum_renewal_date ) {
return ( 0, "auto_too_late" );
}
}
if ( defined $issuing_rule->no_auto_renewal_after_hard_limit
and $issuing_rule->no_auto_renewal_after_hard_limit ne "" ) {
if ( defined $issuing_rule->{no_auto_renewal_after_hard_limit}
and $issuing_rule->{no_auto_renewal_after_hard_limit} ne "" ) {
# If no_auto_renewal_after_hard_limit is >= today, it's also too late for renewal
if ( dt_from_string >= dt_from_string( $issuing_rule->no_auto_renewal_after_hard_limit ) ) {
if ( dt_from_string >= dt_from_string( $issuing_rule->{no_auto_renewal_after_hard_limit} ) ) {
return ( 0, "auto_too_late" );
}
}
@ -2810,17 +2839,17 @@ sub CanBookBeRenewed {
}
}
if ( defined $issuing_rule->norenewalbefore
and $issuing_rule->norenewalbefore ne "" )
if ( defined $issuing_rule->{norenewalbefore}
and $issuing_rule->{norenewalbefore} ne "" )
{
# Calculate soonest renewal by subtracting 'No renewal before' from due date
my $soonestrenewal = dt_from_string( $issue->date_due, 'sql' )->subtract(
$issuing_rule->lengthunit => $issuing_rule->norenewalbefore );
$issuing_rule->{lengthunit} => $issuing_rule->{norenewalbefore} );
# Depending on syspref reset the exact time, only check the date
if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
and $issuing_rule->lengthunit eq 'days' )
and $issuing_rule->{lengthunit} eq 'days' )
{
$soonestrenewal->truncate( to => 'day' );
}
@ -3042,14 +3071,16 @@ sub GetRenewCount {
# $item and $borrower should be calculated
my $branchcode = _GetCircControlBranch($item->unblessed, $patron->unblessed);
my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
{ categorycode => $patron->categorycode,
my $rule = Koha::CirculationRules->get_effective_rule(
{
categorycode => $patron->categorycode,
itemtype => $item->effective_itemtype,
branchcode => $branchcode
branchcode => $branchcode,
rule_name => 'renewalsallowed',
}
);
$renewsallowed = $issuing_rule ? $issuing_rule->renewalsallowed : 0;
$renewsallowed = $rule ? $rule->rule_value : 0;
$renewsleft = $renewsallowed - $renewcount;
if($renewsleft < 0){ $renewsleft = 0; }
return ( $renewcount, $renewsallowed, $renewsleft );
@ -3087,25 +3118,29 @@ sub GetSoonestRenewDate {
or return;
my $branchcode = _GetCircControlBranch( $item->unblessed, $patron->unblessed );
my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
my $issuing_rule = Koha::CirculationRules->get_effective_rules(
{ categorycode => $patron->categorycode,
itemtype => $item->effective_itemtype,
branchcode => $branchcode
branchcode => $branchcode,
rules => [
'norenewalbefore',
'lengthunit',
]
}
);
my $now = dt_from_string;
return $now unless $issuing_rule;
if ( defined $issuing_rule->norenewalbefore
and $issuing_rule->norenewalbefore ne "" )
if ( defined $issuing_rule->{norenewalbefore}
and $issuing_rule->{norenewalbefore} ne "" )
{
my $soonestrenewal =
dt_from_string( $itemissue->date_due )->subtract(
$issuing_rule->lengthunit => $issuing_rule->norenewalbefore );
$issuing_rule->{lengthunit} => $issuing_rule->{norenewalbefore} );
if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
and $issuing_rule->lengthunit eq 'days' )
and $issuing_rule->{lengthunit} eq 'days' )
{
$soonestrenewal->truncate( to => 'day' );
}
@ -3146,30 +3181,36 @@ sub GetLatestAutoRenewDate {
or return;
my $branchcode = _GetCircControlBranch( $item->unblessed, $patron->unblessed );
my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
{ categorycode => $patron->categorycode,
my $circulation_rules = Koha::CirculationRules->get_effective_rules(
{
categorycode => $patron->categorycode,
itemtype => $item->effective_itemtype,
branchcode => $branchcode
branchcode => $branchcode,
rules => [
'no_auto_renewal_after',
'no_auto_renewal_after_hard_limit',
'lengthunit',
]
}
);
return unless $issuing_rule;
return unless $circulation_rules;
return
if ( not $issuing_rule->no_auto_renewal_after
or $issuing_rule->no_auto_renewal_after eq '' )
and ( not $issuing_rule->no_auto_renewal_after_hard_limit
or $issuing_rule->no_auto_renewal_after_hard_limit eq '' );
if ( not $circulation_rules->{no_auto_renewal_after}
or $circulation_rules->{no_auto_renewal_after} eq '' )
and ( not $circulation_rules->{no_auto_renewal_after_hard_limit}
or $circulation_rules->{no_auto_renewal_after_hard_limit} eq '' );
my $maximum_renewal_date;
if ( $issuing_rule->no_auto_renewal_after ) {
if ( $circulation_rules->{no_auto_renewal_after} ) {
$maximum_renewal_date = dt_from_string($itemissue->issuedate);
$maximum_renewal_date->add(
$issuing_rule->lengthunit => $issuing_rule->no_auto_renewal_after
$circulation_rules->{lengthunit} => $circulation_rules->{no_auto_renewal_after}
);
}
if ( $issuing_rule->no_auto_renewal_after_hard_limit ) {
my $dt = dt_from_string( $issuing_rule->no_auto_renewal_after_hard_limit );
if ( $circulation_rules->{no_auto_renewal_after_hard_limit} ) {
my $dt = dt_from_string( $circulation_rules->{no_auto_renewal_after_hard_limit} );
$maximum_renewal_date = $dt if not $maximum_renewal_date or $maximum_renewal_date > $dt;
}
return $maximum_renewal_date;
@ -3216,19 +3257,10 @@ sub GetIssuingCharges {
$item_type = $item_data->{itemtype};
$charge = $item_data->{rentalcharge};
my $branch = C4::Context::mybranch();
my $discount_query = q|SELECT rentaldiscount,
issuingrules.itemtype, issuingrules.branchcode
FROM borrowers
LEFT JOIN issuingrules ON borrowers.categorycode = issuingrules.categorycode
WHERE borrowers.borrowernumber = ?
AND (issuingrules.itemtype = ? OR issuingrules.itemtype = '*')
AND (issuingrules.branchcode = ? OR issuingrules.branchcode = '*')|;
my $discount_sth = $dbh->prepare($discount_query);
$discount_sth->execute( $borrowernumber, $item_type, $branch );
my $discount_rules = $discount_sth->fetchall_arrayref({});
if (@{$discount_rules}) {
my $patron = Koha::Patrons->find( $borrowernumber );
my $discount = _get_discount_from_rule($patron->categorycode, $branch, $item_type);
if ($discount) {
# We may have multiple rules so get the most specific
my $discount = _get_discount_from_rule($discount_rules, $branch, $item_type);
$charge = ( $charge * ( 100 - $discount ) ) / 100;
}
if ($charge) {
@ -3241,37 +3273,43 @@ sub GetIssuingCharges {
# Select most appropriate discount rule from those returned
sub _get_discount_from_rule {
my ($rules_ref, $branch, $itemtype) = @_;
my $discount;
my ($categorycode, $branchcode, $itemtype) = @_;
if (@{$rules_ref} == 1) { # only 1 applicable rule use it
$discount = $rules_ref->[0]->{rentaldiscount};
return (defined $discount) ? $discount : 0;
}
# could have up to 4 does one match $branch and $itemtype
my @d = grep { $_->{branchcode} eq $branch && $_->{itemtype} eq $itemtype } @{$rules_ref};
if (@d) {
$discount = $d[0]->{rentaldiscount};
return (defined $discount) ? $discount : 0;
}
# do we have item type + all branches
@d = grep { $_->{branchcode} eq q{*} && $_->{itemtype} eq $itemtype } @{$rules_ref};
if (@d) {
$discount = $d[0]->{rentaldiscount};
return (defined $discount) ? $discount : 0;
}
# do we all item types + this branch
@d = grep { $_->{branchcode} eq $branch && $_->{itemtype} eq q{*} } @{$rules_ref};
if (@d) {
$discount = $d[0]->{rentaldiscount};
return (defined $discount) ? $discount : 0;
}
# so all and all (surely we wont get here)
@d = grep { $_->{branchcode} eq q{*} && $_->{itemtype} eq q{*} } @{$rules_ref};
if (@d) {
$discount = $d[0]->{rentaldiscount};
return (defined $discount) ? $discount : 0;
# Set search precedences
my @params = (
{
branchcode => $branchcode,
itemtype => $itemtype,
categorycode => $categorycode,
},
{
branchcode => '*',
categorycode => $categorycode,
itemtype => $itemtype,
},
{
branchcode => $branchcode,
categorycode => $categorycode,
itemtype => '*',
},
{
branchcode => '*',
categorycode => $categorycode,
itemtype => '*',
},
);
foreach my $params (@params) {
my $rule = Koha::CirculationRules->search(
{
rule_name => 'rentaldiscount',
%$params,
}
)->next();
return $rule->rule_value if $rule;
}
# none of the above
return 0;
}

35
C4/Overdues.pm

@ -35,7 +35,6 @@ use C4::Debug;
use Koha::DateUtils;
use Koha::Account::Lines;
use Koha::Account::Offsets;
use Koha::IssuingRules;
use Koha::Libraries;
use vars qw(@ISA @EXPORT);
@ -238,27 +237,43 @@ sub CalcFine {
my $start_date = $due_dt->clone();
# get issuingrules (fines part will be used)
my $itemtype = $item->{itemtype} || $item->{itype};
my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $bortype, itemtype => $itemtype, branchcode => $branchcode });
my $issuing_rule = Koha::CirculationRules->get_effective_rules(
{
categorycode => $bortype,
itemtype => $itemtype,
branchcode => $branchcode,
rules => [
'lengthunit',
'firstremind',
'chargeperiod',
'chargeperiod_charge_at',
'fine',
'overduefinescap',
'cap_fine_to_replacement_price',
'chargename',
]
}
);
$itemtype = Koha::ItemTypes->find($itemtype);
return unless $issuing_rule; # If not rule exist, there is no fine
my $fine_unit = $issuing_rule->lengthunit || 'days';
my $fine_unit = $issuing_rule->{lengthunit} || 'days';
my $chargeable_units = get_chargeable_units($fine_unit, $start_date, $end_date, $branchcode);
my $units_minus_grace = $chargeable_units - ($issuing_rule->firstremind || 0);
my $units_minus_grace = $chargeable_units - ($issuing_rule->{firstremind} || 0);
my $amount = 0;
if ( $issuing_rule->chargeperiod && ( $units_minus_grace > 0 ) ) {
if ( $issuing_rule->{chargeperiod} && ( $units_minus_grace > 0 ) ) {
my $units = C4::Context->preference('FinesIncludeGracePeriod') ? $chargeable_units : $units_minus_grace;
my $charge_periods = $units / $issuing_rule->chargeperiod;
my $charge_periods = $units / $issuing_rule->{chargeperiod};
# If chargeperiod_charge_at = 1, we charge a fine at the start of each charge period
# if chargeperiod_charge_at = 0, we charge at the end of each charge period
$charge_periods = $issuing_rule->chargeperiod_charge_at == 1 ? ceil($charge_periods) : floor($charge_periods);
$amount = $charge_periods * $issuing_rule->fine;
$charge_periods = $issuing_rule->{chargeperiod_charge_at} == 1 ? ceil($charge_periods) : floor($charge_periods);
$amount = $charge_periods * $issuing_rule->{fine};
} # else { # a zero (or null) chargeperiod or negative units_minus_grace value means no charge. }
$amount = $issuing_rule->overduefinescap if $issuing_rule->overduefinescap && $amount > $issuing_rule->overduefinescap;
$amount = $issuing_rule->{overduefinescap} if $issuing_rule->{overduefinescap} && $amount > $issuing_rule->{overduefinescap};
# This must be moved to Koha::Item (see also similar code in C4::Accounts::chargelostitem
$item->{replacementprice} ||= $itemtype->defaultreplacecost
@ -266,7 +281,7 @@ sub CalcFine {
&& ( ! defined $item->{replacementprice} || $item->{replacementprice} == 0 )
&& C4::Context->preference("useDefaultReplacementCost");
$amount = $item->{replacementprice} if ( $issuing_rule->cap_fine_to_replacement_price && $item->{replacementprice} && $amount > $item->{replacementprice} );
$amount = $item->{replacementprice} if ( $issuing_rule->{cap_fine_to_replacement_price} && $item->{replacementprice} && $amount > $item->{replacementprice} );
$debug and warn sprintf("CalcFine returning (%s, %s, %s)", $amount, $units_minus_grace, $chargeable_units);
return ($amount, $units_minus_grace, $chargeable_units);

45
C4/Reserves.pm

@ -40,7 +40,6 @@ use Koha::Database;
use Koha::DateUtils;
use Koha::Hold;
use Koha::Holds;
use Koha::IssuingRules;
use Koha::ItemTypes;
use Koha::Items;
use Koha::Libraries;
@ -2206,24 +2205,40 @@ patron category, itemtype, and library.
sub GetHoldRule {
my ( $categorycode, $itemtype, $branchcode ) = @_;
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare(
q{
SELECT categorycode, itemtype, branchcode, reservesallowed, holds_per_record, holds_per_day
FROM issuingrules
WHERE (categorycode in (?,'*') )
AND (itemtype IN (?,'*'))
AND (branchcode IN (?,'*'))
ORDER BY categorycode DESC,
itemtype DESC,
branchcode DESC
my $reservesallowed = Koha::CirculationRules->get_effective_rule(
{
itemtype => $itemtype,
categorycode => $categorycode,
branchcode => $branchcode,
rule_name => 'reservesallowed',
order_by => {
-desc => [ 'categorycode', 'itemtype', 'branchcode' ]
}
}
);
return unless $reservesallowed;;
$sth->execute( $categorycode, $itemtype, $branchcode );
my $rules;
$rules->{reservesallowed} = $reservesallowed->rule_value;
$rules->{itemtype} = $reservesallowed->itemtype;
$rules->{categorycode} = $reservesallowed->categorycode;
$rules->{branchcode} = $reservesallowed->branchcode;
my $holds_per_x_rules = Koha::CirculationRules->get_effective_rules(
{
itemtype => $itemtype,
categorycode => $categorycode,
branchcode => $branchcode,
rules => ['holds_per_record', 'holds_per_day'],
order_by => {
-desc => [ 'categorycode', 'itemtype', 'branchcode' ]
}
}
);
$rules->{holds_per_record} = $holds_per_x_rules->{holds_per_record};
$rules->{holds_per_day} = $holds_per_x_rules->{holds_per_day};
return $sth->fetchrow_hashref();
return $rules;
}
=head1 AUTHOR

14
Koha/Biblio.pm

@ -37,7 +37,7 @@ use Koha::ArticleRequest::Status;
use Koha::ArticleRequests;
use Koha::Biblio::Metadatas;
use Koha::Biblioitems;
use Koha::IssuingRules;
use Koha::CirculationRules;
use Koha::Item::Transfer::Limits;
use Koha::Items;
use Koha::Libraries;
@ -299,10 +299,16 @@ sub article_request_type_for_bib {
my $borrowertype = $borrower->categorycode;
my $itemtype = $self->itemtype();
my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $borrowertype, itemtype => $itemtype });
my $rule = Koha::CirculationRules->get_effective_rule(
{
rule_name => 'article_requests',
categorycode => $borrowertype,
itemtype => $itemtype,
}
);
return q{} unless $issuing_rule;
return $issuing_rule->article_requests || q{}
return q{} unless $rule;
return $rule->rule_value || q{}
}
=head3 article_request_type_for_items

43
Koha/CirculationRules.pm

@ -1,7 +1,6 @@
package Koha::CirculationRules;
# Copyright Vaara-kirjastot 2015
# Copyright Koha Development Team 2016
# Copyright ByWater Solutions 2017
#
# This file is part of Koha.
#
@ -42,6 +41,10 @@ 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});
my $rule_name = $params->{rule_name};
my $categorycode = $params->{categorycode};
my $itemtype = $params->{itemtype};
@ -55,6 +58,9 @@ sub get_effective_rule {
$v = undef if $v and $v eq '*';
}
my $order_by = $params->{order_by}
// { -desc => [ 'branchcode', 'categorycode', 'itemtype' ] };
my $search_params;
$search_params->{rule_name} = $rule_name;
@ -65,9 +71,7 @@ sub get_effective_rule {
my $rule = $self->search(
$search_params,
{
order_by => {
-desc => [ 'branchcode', 'categorycode', 'itemtype' ]
},
order_by => $order_by,
rows => 1,
}
)->single;
@ -75,6 +79,35 @@ sub get_effective_rule {
return $rule;
}
=head3 get_effective_rule
=cut
sub get_effective_rules {
my ( $self, $params ) = @_;
my $rules = $params->{rules};
my $categorycode = $params->{categorycode};
my $itemtype = $params->{itemtype};
my $branchcode = $params->{branchcode};
my $r;
foreach my $rule (@$rules) {
my $effective_rule = $self->get_effective_rule(
{
rule_name => $rule,
categorycode => $categorycode,
itemtype => $itemtype,
branchcode => $branchcode,
}
);
$r->{$rule} = $effective_rule->rule_value if $effective_rule;
}
return $r;
}
=head3 set_rule
=cut

68
Koha/IssuingRule.pm

@ -1,68 +0,0 @@
package Koha::IssuingRule;
# Copyright Vaara-kirjastot 2015
#
# 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 Koha::Database;
use base qw(Koha::Object);
=head1 NAME
Koha::Hold - Koha Hold object class
=head1 API
=head2 Class Methods
=cut
=head3 delete
=cut
sub delete {
my ($self) = @_;
my $branchcode = $self->branchcode eq '*' ? undef : $self->branchcode;
my $categorycode = $self->categorycode eq '*' ? undef : $self->categorycode;
my $itemtype = $self->itemtype eq '*' ? undef : $self->itemtype;
Koha::CirculationRules->search({
branchcode => $branchcode,
itemtype => $itemtype,
categorycode => $categorycode,
rule_name => [qw(
maxissueqty
maxonsiteissueqty
max_holds
)],
})->delete;
$self->SUPER::delete;
}
=head3 type
=cut
sub _type {
return 'Issuingrule';
}
1;

15
Koha/Item.pm

@ -29,7 +29,7 @@ use C4::Context;
use C4::Circulation;
use C4::Reserves;
use Koha::Checkouts;
use Koha::IssuingRules;
use Koha::CirculationRules;
use Koha::Item::Transfer::Limits;
use Koha::Item::Transfers;
use Koha::Patrons;
@ -369,10 +369,17 @@ sub article_request_type {
: undef;
my $borrowertype = $borrower->categorycode;
my $itemtype = $self->effective_itemtype();
my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $borrowertype, itemtype => $itemtype, branchcode => $branchcode });
my $rule = Koha::CirculationRules->get_effective_rule(
{
rule_name => 'article_requests',
categorycode => $borrowertype,
itemtype => $itemtype,
branchcode => $branchcode
}
);
return q{} unless $issuing_rule;
return $issuing_rule->article_requests || q{}
return q{} unless $rule;
return $rule->rule_value || q{}
}
=head3 current_holds

327
Koha/Schema/Result/Issuingrule.pm

@ -1,327 +0,0 @@
use utf8;
package Koha::Schema::Result::Issuingrule;
# Created by DBIx::Class::Schema::Loader
# DO NOT MODIFY THE FIRST PART OF THIS FILE
=head1 NAME
Koha::Schema::Result::Issuingrule
=cut
use strict;
use warnings;
use base 'DBIx::Class::Core';
=head1 TABLE: C<issuingrules>
=cut
__PACKAGE__->table("issuingrules");
=head1 ACCESSORS
=head2 categorycode
data_type: 'varchar'
default_value: (empty string)
is_nullable: 0
size: 10
=head2 itemtype
data_type: 'varchar'
default_value: (empty string)
is_nullable: 0
size: 10
=head2 restrictedtype
data_type: 'tinyint'
is_nullable: 1
=head2 rentaldiscount
data_type: 'decimal'
is_nullable: 1
size: [28,6]
=head2 reservecharge
data_type: 'decimal'
is_nullable: 1
size: [28,6]
=head2 fine
data_type: 'decimal'
is_nullable: 1
size: [28,6]
=head2 finedays
data_type: 'integer'
is_nullable: 1
=head2 maxsuspensiondays
data_type: 'integer'
is_nullable: 1
=head2 suspension_chargeperiod
data_type: 'integer'
default_value: 1
is_nullable: 1
=head2 firstremind
data_type: 'integer'
is_nullable: 1
=head2 chargeperiod
data_type: 'integer'
is_nullable: 1
=head2 chargeperiod_charge_at
data_type: 'tinyint'
default_value: 0
is_nullable: 0
=head2 accountsent
data_type: 'integer'
is_nullable: 1
=head2 issuelength
data_type: 'integer'
is_nullable: 1
=head2 lengthunit
data_type: 'varchar'
default_value: 'days'
is_nullable: 1
size: 10
=head2 hardduedate
data_type: 'date'
datetime_undef_if_invalid: 1
is_nullable: 1
=head2 hardduedatecompare
data_type: 'tinyint'
default_value: 0
is_nullable: 0
=head2 renewalsallowed
data_type: 'smallint'
default_value: 0
is_nullable: 0
=head2 renewalperiod
data_type: 'integer'
is_nullable: 1
=head2 norenewalbefore
data_type: 'integer'
is_nullable: 1
=head2 auto_renew
data_type: 'tinyint'
default_value: 0
is_nullable: 1
=head2 no_auto_renewal_after
data_type: 'integer'
is_nullable: 1
=head2 no_auto_renewal_after_hard_limit
data_type: 'date'
datetime_undef_if_invalid: 1
is_nullable: 1
=head2 reservesallowed
data_type: 'smallint'
default_value: 0
is_nullable: 0
=head2 holds_per_record
data_type: 'smallint'
default_value: 1
is_nullable: 0
=head2 holds_per_day
data_type: 'smallint'
is_nullable: 1
=head2 branchcode
data_type: 'varchar'
default_value: (empty string)
is_nullable: 0
size: 10
=head2 overduefinescap
data_type: 'decimal'
is_nullable: 1
size: [28,6]
=head2 cap_fine_to_replacement_price
data_type: 'tinyint'
default_value: 0
is_nullable: 0
=head2 onshelfholds
data_type: 'tinyint'
default_value: 0
is_nullable: 0
=head2 opacitemholds
data_type: 'char'
default_value: 'N'
is_nullable: 0
size: 1
=head2 article_requests
data_type: 'enum'
default_value: 'no'
extra: {list => ["no","yes","bib_only","item_only"]}
is_nullable: 0
=head2 note
data_type: 'varchar'
is_nullable: 1
size: 100
=cut
__PACKAGE__->add_columns(
"categorycode",
{ data_type => "varchar", default_value => "", is_nullable => 0, size => 10 },
"itemtype",
{ data_type => "varchar", default_value => "", is_nullable => 0, size => 10 },
"restrictedtype",
{ data_type => "tinyint", is_nullable => 1 },
"rentaldiscount",
{ data_type => "decimal", is_nullable => 1, size => [28, 6] },
"reservecharge",
{ data_type => "decimal", is_nullable => 1, size => [28, 6] },
"fine",
{ data_type => "decimal", is_nullable => 1, size => [28, 6] },
"finedays",
{ data_type => "integer", is_nullable => 1 },
"maxsuspensiondays",
{ data_type => "integer", is_nullable => 1 },
"suspension_chargeperiod",
{ data_type => "integer", default_value => 1, is_nullable => 1 },
"firstremind",
{ data_type => "integer", is_nullable => 1 },
"chargeperiod",
{ data_type => "integer", is_nullable => 1 },
"chargeperiod_charge_at",
{ data_type => "tinyint", default_value => 0, is_nullable => 0 },
"accountsent",
{ data_type => "integer", is_nullable => 1 },
"issuelength",
{ data_type => "integer", is_nullable => 1 },
"lengthunit",
{
data_type => "varchar",
default_value => "days",
is_nullable => 1,
size => 10,
},
"hardduedate",
{ data_type => "date", datetime_undef_if_invalid => 1, is_nullable => 1 },
"hardduedatecompare",
{ data_type => "tinyint", default_value => 0, is_nullable => 0 },
"renewalsallowed",
{ data_type => "smallint", default_value => 0, is_nullable => 0 },
"renewalperiod",
{ data_type => "integer", is_nullable => 1 },
"norenewalbefore",
{ data_type => "integer", is_nullable => 1 },
"auto_renew",
{ data_type => "tinyint", default_value => 0, is_nullable => 1 },
"no_auto_renewal_after",
{ data_type => "integer", is_nullable => 1 },
"no_auto_renewal_after_hard_limit",
{ data_type => "date", datetime_undef_if_invalid => 1, is_nullable => 1 },
"reservesallowed",
{ data_type => "smallint", default_value => 0, is_nullable => 0 },
"holds_per_record",
{ data_type => "smallint", default_value => 1, is_nullable => 0 },
"holds_per_day",
{ data_type => "smallint", is_nullable => 1 },
"branchcode",
{ data_type => "varchar", default_value => "", is_nullable => 0, size => 10 },
"overduefinescap",
{ data_type => "decimal", is_nullable => 1, size => [28, 6] },
"cap_fine_to_replacement_price",
{ data_type => "tinyint", default_value => 0, is_nullable => 0 },
"onshelfholds",
{ data_type => "tinyint", default_value => 0, is_nullable => 0 },
"opacitemholds",
{ data_type => "char", default_value => "N", is_nullable => 0, size => 1 },
"article_requests",
{
data_type => "enum",
default_value => "no",
extra => { list => ["no", "yes", "bib_only", "item_only"] },
is_nullable => 0,
},
"note",
{ data_type => "varchar", is_nullable => 1, size => 100 },
);
=head1 PRIMARY KEY
=over 4
=item * L</branchcode>
=item * L</categorycode>
=item * L</itemtype>
=back
=cut
__PACKAGE__->set_primary_key("branchcode", "categorycode", "itemtype");
# Created by DBIx::Class::Schema::Loader v0.07046 @ 2019-03-05 20:49:11
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:6bPX0BRWWQZrWFun3GP86Q
sub koha_object_class {
'Koha::IssuingRule';
}
sub koha_objects_class {
'Koha::IssuingRules';
}
1;

115
admin/smart-rules.pl

@ -26,8 +26,6 @@ use C4::Koha;
use C4::Debug;
use Koha::DateUtils;
use Koha::Database;
use Koha::IssuingRule;
use Koha::IssuingRules;
use Koha::Logger;
use Koha::RefundLostItemFeeRules;
use Koha::Libraries;
@ -81,12 +79,41 @@ if ($op eq 'delete') {
my $categorycode = $input->param('categorycode');
$debug and warn "deleting $1 $2 $branch";
Koha::IssuingRules->find({
branchcode => $branch,
categorycode => $categorycode,
itemtype => $itemtype
})->delete;
Koha::CirculationRules->set_rules(
{
categorycode => $categorycode,
branchcode => $branch,
itemtype => $itemtype,
rules => {
restrictedtype => undef,
rentaldiscount => undef,
fine => undef,
finedays => undef,
maxsuspensiondays => undef,
firstremind => undef,
chargeperiod => undef,
chargeperiod_charge_at => undef,
accountsent => undef,
issuelength => undef,
lengthunit => undef,
hardduedate => undef,
hardduedatecompare => undef,
renewalsallowed => undef,
renewalperiod => undef,
norenewalbefore => undef,
auto_renew => undef,
no_auto_renewal_after => undef,
no_auto_renewal_after_hard_limit => undef,
reservesallowed => undef,
holds_per_record => undef,
overduefinescap => undef,
cap_fine_to_replacement_price => undef,
onshelfholds => undef,
opacitemholds => undef,
article_requests => undef,
}
}
);
}
elsif ($op eq 'delete-branch-cat') {
my $categorycode = $input->param('categorycode');
@ -264,10 +291,9 @@ elsif ($op eq 'add') {
my $note = $input->param('note');
$debug and warn "Adding $br, $bor, $itemtype, $fine, $maxissueqty, $maxonsiteissueqty, $cap_fine_to_replacement_price";
my $params = {
branchcode => $br,
categorycode => $bor,
itemtype => $itemtype,
my $rules = {
maxissueqty => $maxissueqty,
maxonsiteissueqty => $maxonsiteissueqty,
fine => $fine,
finedays => $finedays,
maxsuspensiondays => $maxsuspensiondays,
@ -297,21 +323,12 @@ elsif ($op eq 'add') {
note => $note,
};
my $issuingrule = Koha::IssuingRules->find({categorycode => $bor, itemtype => $itemtype, branchcode => $br});
if ($issuingrule) {
$issuingrule->set($params)->store();
} else {
Koha::IssuingRule->new()->set($params)->store();
}
Koha::CirculationRules->set_rules(
{
categorycode => $bor,
itemtype => $itemtype,
branchcode => $br,
rules => {
maxissueqty => $maxissueqty,
maxonsiteissueqty => $maxonsiteissueqty,
}
rules => $rules,
}
);
@ -548,62 +565,16 @@ $template->param(
my $patron_categories = Koha::Patron::Categories->search({}, { order_by => ['description'] });
my @row_loop;
my $itemtypes = Koha::ItemTypes->search_with_localization;
my $sth2 = $dbh->prepare("
SELECT issuingrules.*,
itemtypes.description AS humanitemtype,
categories.description AS humancategorycode,
COALESCE( localization.translation, itemtypes.description ) AS translated_description
FROM issuingrules
LEFT JOIN itemtypes
ON (itemtypes.itemtype = issuingrules.itemtype)
LEFT JOIN categories
ON (categories.categorycode = issuingrules.categorycode)
LEFT JOIN localization ON issuingrules.itemtype = localization.code
AND localization.entity = 'itemtypes'
AND localization.lang = ?
WHERE issuingrules.branchcode = ?
");
$sth2->execute($language, $branch);
while (my $row = $sth2->fetchrow_hashref) {
$row->{'current_branch'} ||= $row->{'branchcode'};
$row->{humanitemtype} ||= $row->{itemtype};
$row->{default_translated_description} = 1 if $row->{humanitemtype} eq '*';
$row->{'humancategorycode'} ||= $row->{'categorycode'};
$row->{'default_humancategorycode'} = 1 if $row->{'humancategorycode'} eq '*';
$row->{'fine'} = sprintf('%.2f', $row->{'fine'});
if ($row->{'hardduedate'} && $row->{'hardduedate'} ne '0000-00-00') {
my $harddue_dt = eval { dt_from_string( $row->{'hardduedate'} ) };
$row->{'hardduedate'} = eval { output_pref( { dt => $harddue_dt, dateonly => 1 } ) } if ( $harddue_dt );
$row->{'hardduedatebefore'} = 1 if ($row->{'hardduedatecompare'} == -1);
$row->{'hardduedateexact'} = 1 if ($row->{'hardduedatecompare'} == 0);
$row->{'hardduedateafter'} = 1 if ($row->{'hardduedatecompare'} == 1);
} else {
$row->{'hardduedate'} = 0;
}
if ($row->{no_auto_renewal_after_hard_limit}) {
my $dt = eval { dt_from_string( $row->{no_auto_renewal_after_hard_limit} ) };
$row->{no_auto_renewal_after_hard_limit} = eval { output_pref( { dt => $dt, dateonly => 1 } ) } if $dt;
}
push @row_loop, $row;
}
my @sorted_row_loop = sort by_category_and_itemtype @row_loop;
$template->param(show_branch_cat_rule_form => 1);
$template->param(
patron_categories => $patron_categories,
itemtypeloop => $itemtypes,
rules => \@sorted_row_loop,
humanbranch => ($branch ne '*' ? $branch : ''),
current_branch => $branch,
definedbranch => scalar(@sorted_row_loop)>0
);
itemtypeloop => $itemtypes,
humanbranch => ( $branch ne '*' ? $branch : '' ),
current_branch => $branch,
);
output_html_with_http_headers $input, $cookie, $template->output;
exit 0;

45
installer/data/mysql/atomicupdate/bug_18936.perl

@ -0,0 +1,45 @@
$DBversion = 'XXX'; # will be replaced by the RM
if( CheckVersion( $DBversion ) ) {
my @columns = qw(
restrictedtype
rentaldiscount
fine
finedays
maxsuspensiondays
firstremind
chargeperiod
chargeperiod_charge_at
accountsent
issuelength
lengthunit
hardduedate
hardduedatecompare
renewalsallowed
renewalperiod
norenewalbefore
auto_renew
no_auto_renewal_after
no_auto_renewal_after_hard_limit
reservesallowed
holds_per_record
overduefinescap
cap_fine_to_replacement_price
onshelfholds
opacitemholds
article_requests
);
if ( column_exists( 'issuingrules', 'categorycode' ) ) {
foreach my $column ( @columns ) {
$dbh->do("
INSERT INTO circulation_rules ( categorycode, branchcode, itemtype, rule_name, rule_value )
SELECT categorycode, branchcode, itemtype, 'column', $column
FROM issuingrules
");
}
$dbh->do("DROP TABLE issuingrules");
}
SetVersion( $DBversion );
print "Upgrade to $DBversion done (Bug 18930 - Move lost item refund rules to circulation_rules table)\n";
}

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

@ -1,17 +1,26 @@
[% USE raw %]
[% USE Asset %]
[% USE Koha %]
[% USE KohaDates %]
[% USE Branches %]
[% USE Categories %]
[% USE ItemTypes %]
[% USE CirculationRules %]
[% SET footerjs = 1 %]
[% SET branchcode = humanbranch %]
[% SET branchcode = humanbranch || '*' %]
[% SET categorycodes = ['*'] %]
[% SET categorycodes = [] %]
[% FOREACH pc IN patron_categories %]
[% categorycodes.push( pc.id ) %]
[% END %]
[% categorycodes.push('*') %]
[% SET itemtypes = [] %]
[% FOREACH i IN itemtypeloop %]
[% itemtypes.push( i.itemtype ) %]
[% END %]
[% itemtypes.push('*') %]
[% INCLUDE 'doc-head-open.inc' %]
<title>Koha &rsaquo; Administration &rsaquo; Circulation and fine rules</title>
@ -112,150 +121,179 @@
</tr>
</thead>
<tbody>
[% FOREACH rule IN rules %]
<tr id="row_[% loop.count | html %]">
<td>[% IF ( rule.default_humancategorycode ) %]
<em>All</em>
[% ELSE %]
[% rule.humancategorycode | html %]
[% END %]
</td>
<td>[% IF rule.default_translated_description %]
<em>All</em>
[% ELSE %]
[% rule.translated_description | html %]
[% 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 | html %]&amp;categorycode=[% rule.categorycode | html %]&amp;branch=[% rule.current_branch | html %]"><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>
[% ELSE %]&nbsp;[% END %]
</td>
<td>
[% SET rule_value = CirculationRules.Search( rule.branchcode, rule.categorycode, rule.itemtype, 'maxissueqty' ) %]
[% IF rule_value || rule_value == "0" %]
[% rule_value | html %]
[% ELSE %]
<span>Unlimited</span>
[% END %]
</td>
<td>
[% SET rule_value = CirculationRules.Search( rule.branchcode, rule.categorycode, rule.itemtype, 'maxonsiteissueqty' ) %]
[% IF rule_value || rule_value == "0" %]
[% rule_value | html %]
[% ELSE %]
<span>Unlimited</span>
[% END %]
</td>
<td>[% rule.issuelength | html %]</td>
<td>
[% IF ( rule.lengthunit == 'days' ) %]
Days
[% ELSIF ( rule.lengthunit == 'hours') %]
Hours
[% ELSE %]
Undefined
[% END %]
</td>
<td>
[% IF ( rule.hardduedate ) %]
[% IF ( rule.hardduedatebefore ) %]
before [% rule.hardduedate | html %]
<input type="hidden" name="hardduedatecomparebackup" value="-1" />
[% ELSIF ( rule.hardduedateexact ) %]
on [% rule.hardduedate | html %]
<input type="hidden" name="hardduedatecomparebackup" value="0" />
[% ELSIF ( rule.hardduedateafter ) %]
after [% rule.hardduedate | html %]
<input type="hidden" name="hardduedatecomparebackup" value="1" />
[% END %]
[% ELSE %]
<span>None defined</span>
[% END %]
</td>
<td>[% rule.fine | html %]</td>
<td>[% rule.chargeperiod | html %]</td>
<td>
[% IF rule.chargeperiod_charge_at %]
<span>Start of interval</span>
[% ELSE %]
<span>End of interval</span>
[% END %]
</td>
<td>[% rule.firstremind | html %]</td>
<td>[% rule.overduefinescap FILTER format("%.2f") %]</td>
<td>
[% IF rule.cap_fine_to_replacement_price %]
<input type="checkbox" checked="checked" disabled="disabled" />
[% ELSE %]
<input type="checkbox" disabled="disabled" />
[% END %]
</td>
<td>[% rule.finedays | html %]</td>
<td>[% rule.maxsuspensiondays | html %]</td>
<td>[% rule.suspension_chargeperiod | html %]</td>
<td>[% rule.renewalsallowed | html %]</td>
<td>[% rule.renewalperiod | html %]</td>
<td>[% rule.norenewalbefore | html %]</td>
<td>
[% IF ( rule.auto_renew ) %]
<span>Yes</span>
[% ELSE %]
<span>No</span>
[% END %]
</td>
<td>[% rule.no_auto_renewal_after | html %]</td>
<td>[% rule.no_auto_renewal_after_hard_limit | html %]</td>
<td>[% rule.reservesallowed | html %]</td>
<td>[% IF rule.unlimited_holds_per_day %]
<span>Unlimited</span>
[% ELSE %]
[% rule.holds_per_day | html %]
[% END %]
</td>
<td>[% rule.holds_per_record | html %]</td>
<td>
[% IF rule.onshelfholds == 1 %]
<span>Yes</span>
[% ELSIF rule.onshelfholds == 2 %]
<span>If all unavailable</span>
[% ELSE %]
<span>If any unavailable</span>
[% END %]
</td>
<td>
[% IF rule.opacitemholds == 'F'%]
<span>Force</span>
[% ELSIF rule.opacitemholds == 'Y'%]
<span>Allow</span>
[% ELSE %]
<span>Don't allow</span>
[% END %]
</td>
<td>
[% IF rule.article_requests == 'no' %]
<span>No</span>
[% ELSIF rule.article_requests == 'yes' %]
<span>Yes</span>
[% ELSIF rule.article_requests == 'bib_only' %]
<span>Record only</span>
[% ELSIF rule.article_requests == 'item_only' %]
<span>Item only</span>
[% END %]
</td>
<td>[% rule.rentaldiscount | html %]</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 | html %]&amp;categorycode=[% rule.categorycode | html %]&amp;branch=[% rule.current_branch | html %]"><i class="fa fa-trash"></i> Delete</a>
</td>
</tr>
[% END %]
[% SET row_count = 0 %]
[% FOREACH c IN categorycodes %]
[% FOREACH i IN itemtypes %]
[% SET note = CirculationRules.Get( branchcode, c, i, 'note' ) %]
[% SET maxissueqty = CirculationRules.Get( branchcode, c, i, 'maxissueqty' ) %]
[% SET maxonsiteissueqty = CirculationRules.Get( branchcode, c, i, 'maxonsiteissueqty' ) %]
[% SET issuelength = CirculationRules.Get( branchcode, c, i, 'issuelength' ) %]
[% SET lengthunit = CirculationRules.Get( branchcode, c, i, 'lengthunit' ) %]
[% SET hardduedate = CirculationRules.Get( branchcode, c, i, 'hardduedate' ) %]
[% SET hardduedatecompare = CirculationRules.Get( branchcode, c, i, 'hardduedatecompare' ) %]
[% SET fine = CirculationRules.Get( branchcode, c, i, 'fine' ) %]
[% SET chargeperiod = CirculationRules.Get( branchcode, c, i, 'chargeperiod' ) %]
[% SET chargeperiod_charge_at = CirculationRules.Get( branchcode, c, i, 'chargeperiod_charge_at' ) %]
[% SET firstremind = CirculationRules.Get( branchcode, c, i, 'firstremind' ) %]
[% SET overduefinescap = CirculationRules.Get( branchcode, c, i, 'overduefinescap' ) %]
[% SET cap_fine_to_replacement_price = CirculationRules.Get( branchcode, c, i, 'cap_fine_to_replacement_price' ) %]
[% SET finedays = CirculationRules.Get( branchcode, c, i, 'finedays' ) %]
[% SET maxsuspensiondays = CirculationRules.Get( branchcode, c, i, 'maxsuspensiondays' ) %]
[% SET suspension_chargeperiod = CirculationRules.Get( branchcode, c, i, 'suspension_chargeperiod' ) %]
[% SET renewalsallowed = CirculationRules.Get( branchcode, c, i, 'renewalsallowed' ) %]
[% SET renewalperiod = CirculationRules.Get( branchcode, c, i, 'renewalperiod' ) %]
[% SET norenewalbefore = CirculationRules.Get( branchcode, c, i, 'norenewalbefore' ) %]
[% SET auto_renew = CirculationRules.Get( branchcode, c, i, 'auto_renew' ) %]
[% SET no_auto_renewal_after = CirculationRules.Get( branchcode, c, i, 'no_auto_renewal_after' ) %]
[% SET no_auto_renewal_after_hard_limit = CirculationRules.Get( branchcode, c, i, 'no_auto_renewal_after_hard_limit' ) %]
[% SET reservesallowed = CirculationRules.Get( branchcode, c, i, 'reservesallowed' ) %]
[% SET holds_per_day = CirculationRules.Get( branchcode, c, i, 'holds_per_day' ) %]
[% SET holds_per_record = CirculationRules.Get( branchcode, c, i, 'holds_per_record' ) %]
[% SET onshelfholds = CirculationRules.Get( branchcode, c, i, 'onshelfholds' ) %]
[% SET opacitemholds = CirculationRules.Get( branchcode, c, i, 'opacitemholds' ) %]
[% SET article_requests = CirculationRules.Get( branchcode, c, i, 'article_requests' ) %]
[% SET rentaldiscount = CirculationRules.Get( branchcode, c, i, 'rentaldiscount' ) %]
[% SET show_rule = maxissueqty || maxonsiteissueqty || issuelength || lengthunit || hardduedate || hardduedatebefore || hardduedateexact || fine || chargeperiod
|| chargeperiod_charge_at || firstremind || overduefinescap || cap_fine_to_replacement_price || finedays || maxsuspensiondays || suspension_chargeperiod || renewalsallowed
|| renewalsallowed || norenewalbefore || auto_renew || no_auto_renewal_after || no_auto_renewal_after_hard_limit || reservesallowed
|| holds_per_day || holds_per_record || onshelfholds || opacitemholds || article_requests || article_requests %]
[% IF show_rule %]
[% SET row_count = row_count + 1 %]
<tr row_countd="row_[% row_count %]">
<td>
[% IF c == '*' %]
<em>All</em>
[% ELSE %]
[% Categories.GetName(c) %]
[% END %]
</td>
<td>
[% IF i == '*' %]
<em>All</em>
[% ELSE %]
[% ItemTypes.GetDescription(i) %]
[% END %]
</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>
[% ELSE %]<span>&nbsp;</span>[% END %]
</td>
<td>
[% IF maxissueqty %]
[% maxissueqty %]
[% ELSE %]
<span>Unlimited</span>
[% END %]
</td>
<td>
[% IF maxonsiteissueqty %]
[% maxonsiteissueqty %]
[% ELSE %]
<span>Unlimited</span>
[% END %]
</td>
<td>[% issuelength %]</td>
<td>
[% IF ( lengthunit == 'days' ) %]
Days
[% ELSIF ( lengthunit == 'hours') %]
Hours
[% ELSE %]
Undefined
[% END %]
</td>
<td>
[% IF ( hardduedate ) %]
[% IF ( hardduedatecompare == '-1' ) %]
before [% hardduedate | $KohaDates %]
<input type="hidden" name="hardduedatecomparebackup" value="-1" />
[% ELSIF ( hardduedatecompare == '0' ) %]
on [% hardduedate | $KohaDates %]
<input type="hidden" name="hardduedatecomparebackup" value="0" />
[% ELSIF ( hardduedatecompare == '1' ) %]
after [% hardduedate | $KohaDates %]
<input type="hidden" name="hardduedatecomparebackup" value="1" />
[% END %]
[% ELSE %]
<span>None defined</span>
[% END %]
</td>
<td>[% fine %]</td>
<td>[% chargeperiod %]</td>
<td>[% IF chargeperiod_charge_at %]Start of interval[% ELSE %]End of interval[% END %]</td>
<td>[% firstremind %]</td>
<td>[% overduefinescap FILTER format("%.2f") %]</td>
<td>
[% IF cap_fine_to_replacement_price %]
<input type="checkbox" checked="checked" disabled="disabled" />
[% ELSE %]
<input type="checkbox" disabled="disabled" />
[% END %]
</td>
<td>[% finedays %]</td>
<td>[% maxsuspensiondays %]</td>
<td>[% suspension_chargeperiod %]</td>
<td>[% renewalsallowed %]</td>
<td>[% renewalperiod %]</td>
<td>[% norenewalbefore %]</td>
<td>
[% IF auto_renew %]
<span>Yes</span>
[% ELSE %]
<span>No</span>
[% END %]
</td>
<td>[% no_auto_renewal_after %]</td>
<td>[% no_auto_renewal_after_hard_limit %]</td>
<td>[% reservesallowed %]</td>
<td>
[% IF holds_per_day.defined && holds != '' %]
[% holds_per_day %]
[% ELSE %]
<span>Unlimited</span>
[% END %]
</td>
<td>[% holds_per_record %]</td>
<td>
[% IF onshelfholds == 1 %]
<span>Yes</span>
[% ELSIF onshelfholds == 2 %]
<span>If all unavailable</span>
[% ELSE %]
<span>If any unavailable</span>
[% END %]
</td>
<td>
[% IF opacitemholds == 'F'%]
<span>Force</span>
[% ELSIF opacitemholds == 'Y'%]
<span>Allow</span>
[% ELSE %]
<span>Don't allow</span>
[% END %]
</td>
<td>
[% IF article_requests == 'no' %]
<span>No</span>
[% ELSIF article_requests == 'yes' %]
<span>Yes</span>
[% ELSIF article_requests == 'bib_only' %]
<span>Record only</span>
[% ELSIF article_requests == 'item_only' %]
<span>Item only</span>
[% END %]
</td>
<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>
</td>
</tr>
[% END %]
[% END %]
[% END %]
<tr id="edit_row">
<td>
<select name="categorycode" id="categorycode">

49
t/db_dependent/ArticleRequests.t

@ -29,7 +29,7 @@ use Koha::Biblio;
use Koha::Notice::Messages;
use Koha::Patron;
use Koha::Library::Group;
use Koha::IssuingRules;
use Koha::CirculationRules;
use Koha::Caches;
BEGIN {
@ -46,7 +46,7 @@ our $cache = Koha::Caches->get_instance;
my $dbh = C4::Context->dbh;
$dbh->{RaiseError} = 1;
$dbh->do("DELETE FROM issuingrules");
$dbh->do("DELETE FROM circulation_rules");
my $biblio = Koha::Biblio->new()->store();
ok( $biblio->id, 'Koha::Biblio created' );
@ -172,33 +172,60 @@ $article_request->complete();
$article_request->cancel();
is( $biblio->article_requests_finished()->count(), 1, 'Canceled request not returned for article_requests_finished' );
my $rule;
$rule = $schema->resultset('Issuingrule')
->new( { categorycode => '*', itemtype => '*', branchcode => '*', article_requests => 'yes' } )->insert();
my $rule = Koha::CirculationRules->set_rule(
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
rule_name => 'article_requests',
rule_value => 'yes',
}
);
ok( $biblio->can_article_request($patron), 'Record is requestable with rule type yes' );
is( $biblio->article_request_type($patron), 'yes', 'Biblio article request type is yes' );
ok( $item->can_article_request($patron), 'Item is requestable with rule type yes' );
is( $item->article_request_type($patron), 'yes', 'Item article request type is yes' );
$rule->delete();
$rule = $schema->resultset('Issuingrule')
->new( { categorycode => '*', itemtype => '*', branchcode => '*', article_requests => 'bib_only' } )->insert();
$rule = Koha::CirculationRules->set_rule(
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
rule_name => 'article_requests',
rule_value => 'bib_only',
}
);
ok( $biblio->can_article_request($patron), 'Record is requestable with rule type bib_only' );
is( $biblio->article_request_type($patron), 'bib_only', 'Biblio article request type is bib_only' );
ok( !$item->can_article_request($patron), 'Item is not requestable with rule type bib_only' );
is( $item->article_request_type($patron), 'bib_only', 'Item article request type is bib_only' );
$rule->delete();
$rule = $schema->resultset('Issuingrule')
->new( { categorycode => '*', itemtype => '*', branchcode => '*', article_requests => 'item_only' } )->insert();
$rule = Koha::CirculationRules->set_rule(
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
rule_name => 'article_requests',
rule_value => 'item_only',
}
);
ok( $biblio->can_article_request($patron), 'Record is requestable with rule type item_only' );
is( $biblio->article_request_type($patron), 'item_only', 'Biblio article request type is item_only' );
ok( $item->can_article_request($patron), 'Item is not requestable with rule type item_only' );
is( $item->article_request_type($patron), 'item_only', 'Item article request type is item_only' );
$rule->delete();
$rule = $schema->resultset('Issuingrule')
->new( { categorycode => '*', itemtype => '*', branchcode => '*', article_requests => 'no' } )->insert();
$rule = Koha::CirculationRules->set_rule(
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
rule_name => 'article_requests',
rule_value => 'no',
}
);
ok( !$biblio->can_article_request($patron), 'Record is requestable with rule type no' );
is( $biblio->article_request_type($patron), 'no', 'Biblio article request type is no' );
ok( !$item->can_article_request($patron), 'Item is not requestable with rule type no' );

346
t/db_dependent/Circulation.t

@ -38,7 +38,6 @@ use C4::Reserves;
use C4::Overdues qw(UpdateFine CalcFine);
use Koha::DateUtils;
use Koha::Database;
use Koha::IssuingRules;
use Koha::Items;
use Koha::Checkouts;
use Koha::Patrons;
@ -252,27 +251,24 @@ is(
);
# Set a simple circ policy
$dbh->do('DELETE FROM issuingrules');
Koha::CirculationRules->search()->delete();
$dbh->do(
q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed,
issuelength, lengthunit,
renewalsallowed, renewalperiod,
norenewalbefore, auto_renew,
fine, chargeperiod)
VALUES (?, ?, ?, ?,
?, ?,
?, ?,
?, ?,
?, ?
)
},
{},
'*', '*', '*', 25,
14, 'days',
1, 7,
undef, 0,
.10, 1
$dbh->do('DELETE FROM circulation_rules');
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
rules => {
reservesallowed => 25,
issuelength => 14,
lengthunit => 'days',
renewalsallowed => 1,
renewalperiod => 7,
norenewalbefore => undef,
auto_renew => 0,
fine => .10,
chargeperiod => 1,
}
}
);
my ( $reused_itemnumber_1, $reused_itemnumber_2 );
@ -394,7 +390,15 @@ 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
C4::Context->dbh->do("UPDATE issuingrules SET onshelfholds = 1");
Koha::CirculationRules->set_rule(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
rule_name => 'onshelfholds',
rule_value => '1',
}
);
t::lib::Mocks::mock_preference('AllowRenewalIfOtherItemsAvailable', 1 );
( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber);
is( $renewokay, 1, 'Bug 11634 - Allow renewal of item with unfilled holds if other available items can fill those holds');
@ -609,7 +613,15 @@ subtest "CanBookBeRenewed tests" => sub {
# Bug 7413
# Test premature manual renewal
$dbh->do('UPDATE issuingrules SET norenewalbefore = 7');
Koha::CirculationRules->set_rule(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
rule_name => 'norenewalbefore',
rule_value => '7',
}
);
( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber);
is( $renewokay, 0, 'Bug 7413: Cannot renew, renewal is premature');
@ -644,7 +656,7 @@ subtest "CanBookBeRenewed tests" => sub {
# Change policy so that loans can only be renewed exactly on due date (0 days prior to due date)
# and test automatic renewal again
$dbh->do('UPDATE issuingrules SET norenewalbefore = 0');
$dbh->do(q{UPDATE circulation_rules SET rule_value = '0' WHERE rule_name = 'norenewalbefore'});
( $renewokay, $error ) =
CanBookBeRenewed( $renewing_borrowernumber, $item_4->itemnumber );
is( $renewokay, 0, 'Bug 14101: Cannot renew, renewal is automatic and premature' );
@ -654,7 +666,7 @@ subtest "CanBookBeRenewed tests" => sub {
# Change policy so that loans can be renewed 99 days prior to the due date
# and test automatic renewal again
$dbh->do('UPDATE issuingrules SET norenewalbefore = 99');
$dbh->do(q{UPDATE circulation_rules SET rule_value = '99' WHERE rule_name = 'norenewalbefore'});
( $renewokay, $error ) =
CanBookBeRenewed( $renewing_borrowernumber, $item_4->itemnumber );
is( $renewokay, 0, 'Bug 14101: Cannot renew, renewal is automatic' );
@ -678,43 +690,116 @@ subtest "CanBookBeRenewed tests" => sub {
my $ten_days_ahead = dt_from_string->add( days => 10 );
AddIssue( $renewing_borrower, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
$dbh->do('UPDATE issuingrules SET norenewalbefore = 7, no_auto_renewal_after = 9');
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
rules => {
norenewalbefore => '7',
no_auto_renewal_after => '9',
}
}
);
( $renewokay, $error ) =
CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
is( $renewokay, 0, 'Do not renew, renewal is automatic' );
is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
$dbh->do('UPDATE issuingrules SET norenewalbefore = 7, no_auto_renewal_after = 10');
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
rules => {
norenewalbefore => '7',
no_auto_renewal_after => '10',
}
}
);
( $renewokay, $error ) =
CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
is( $renewokay, 0, 'Do not renew, renewal is automatic' );
is( $error, 'auto_too_late', 'Cannot auto renew, too late - no_auto_renewal_after is inclusive(returned code is auto_too_late)' );
$dbh->do('UPDATE issuingrules SET norenewalbefore = 7, no_auto_renewal_after = 11');
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
rules => {
norenewalbefore => '7',
no_auto_renewal_after => '11',
}
}
);
( $renewokay, $error ) =
CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
is( $renewokay, 0, 'Do not renew, renewal is automatic' );
is( $error, 'auto_too_soon', 'Cannot auto renew, too soon - no_auto_renewal_after is defined(returned code is auto_too_soon)' );
$dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = 11');
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
rules => {
norenewalbefore => '10',
no_auto_renewal_after => '11',
}
}
);
( $renewokay, $error ) =
CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
is( $renewokay, 0, 'Do not renew, renewal is automatic' );
is( $error, 'auto_renew', 'Cannot renew, renew is automatic' );
$dbh->do('UPDATE issuingrules SET norenewalbefore = 7, no_auto_renewal_after = NULL, no_auto_renewal_after_hard_limit = ?', undef, dt_from_string->add( days => -1 ) );
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
rules => {
norenewalbefore => '10',
no_auto_renewal_after => undef,
no_auto_renewal_after_hard_limit => dt_from_string->add( days => -1 ),
}
}
);
( $renewokay, $error ) =
CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
is( $renewokay, 0, 'Do not renew, renewal is automatic' );
is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
$dbh->do('UPDATE issuingrules SET norenewalbefore = 7, no_auto_renewal_after = 15, no_auto_renewal_after_hard_limit = ?', undef, dt_from_string->add( days => -1 ) );
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
rules => {
norenewalbefore => '7',
no_auto_renewal_after => '15',
no_auto_renewal_after_hard_limit => dt_from_string->add( days => -1 ),
}
}
);
( $renewokay, $error ) =
CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
is( $renewokay, 0, 'Do not renew, renewal is automatic' );
is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
$dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = NULL, no_auto_renewal_after_hard_limit = ?', undef, dt_from_string->add( days => 1 ) );
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
rules => {
norenewalbefore => '10',
no_auto_renewal_after => undef,
no_auto_renewal_after_hard_limit => dt_from_string->add( days => 1 ),
}
}
);
( $renewokay, $error ) =
CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
is( $renewokay, 0, 'Do not renew, renewal is automatic' );
@ -736,7 +821,17 @@ subtest "CanBookBeRenewed tests" => sub {
my $ten_days_ahead = dt_from_string->add( days => 10 );
AddIssue( $renewing_borrower, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
$dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = 11');
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
rules => {
norenewalbefore => '10',
no_auto_renewal_after => '11',
}
}
);
C4::Context->set_preference('OPACFineNoRenewalsBlockAutoRenew','1');
C4::Context->set_preference('OPACFineNoRenewals','10');
C4::Context->set_preference('OPACFineNoRenewalsIncludeCredit','1');
@ -874,31 +969,89 @@ subtest "CanBookBeRenewed tests" => sub {
my $ten_days_before = dt_from_string->add( days => -10 );
my $ten_days_ahead = dt_from_string->add( days => 10 );
AddIssue( $renewing_borrower, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
$dbh->do('UPDATE issuingrules SET norenewalbefore = 7, no_auto_renewal_after = NULL, no_auto_renewal_after_hard_limit = NULL');
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
rules => {
norenewalbefore => '7',
no_auto_renewal_after => '',
no_auto_renewal_after_hard_limit => undef,
}
}
);
my $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
is( $latest_auto_renew_date, undef, 'GetLatestAutoRenewDate should return undef if no_auto_renewal_after or no_auto_renewal_after_hard_limit are not defined' );
my $five_days_before = dt_from_string->add( days => -5 );
$dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = 5, no_auto_renewal_after_hard_limit = NULL');
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
rules => {
norenewalbefore => '10',
no_auto_renewal_after => '5',
no_auto_renewal_after_hard_limit => undef,
}
}
);
$latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
is( $latest_auto_renew_date->truncate( to => 'minute' ),
$five_days_before->truncate( to => 'minute' ),
'GetLatestAutoRenewDate should return -5 days if no_auto_renewal_after = 5 and date_due is 10 days before'
);
my $five_days_ahead = dt_from_string->add( days => 5 );
$dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = 15, no_auto_renewal_after_hard_limit = NULL');
$dbh->do(q{UPDATE circulation_rules SET rule_value = '10' WHERE rule_name = 'norenewalbefore'});
$dbh->do(q{UPDATE circulation_rules SET rule_value = '15' WHERE rule_name = 'no_auto_renewal_after'});
$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 => '*',
rules => {
norenewalbefore => '10',
no_auto_renewal_after => '15',
no_auto_renewal_after_hard_limit => undef,
}
}
);
$latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
is( $latest_auto_renew_date->truncate( to => 'minute' ),
$five_days_ahead->truncate( to => 'minute' ),
'GetLatestAutoRenewDate should return +5 days if no_auto_renewal_after = 15 and date_due is 10 days before'
);
my $two_days_ahead = dt_from_string->add( days => 2 );
$dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = NULL, no_auto_renewal_after_hard_limit = ?', undef, dt_from_string->add( days => 2 ) );
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
rules => {
norenewalbefore => '10',
no_auto_renewal_after => '',
no_auto_renewal_after_hard_limit => dt_from_string->add( days => 2 ),
}
}
);
$latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
is( $latest_auto_renew_date->truncate( to => 'day' ),
$two_days_ahead->truncate( to => 'day' ),
'GetLatestAutoRenewDate should return +2 days if no_auto_renewal_after_hard_limit is defined and not no_auto_renewal_after'
);
$dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = 15, no_auto_renewal_after_hard_limit = ?', undef, dt_from_string->add( days => 2 ) );
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
rules => {
norenewalbefore => '10',
no_auto_renewal_after => '15',
no_auto_renewal_after_hard_limit => dt_from_string->add( days => 2 ),
}
}
);
$latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
is( $latest_auto_renew_date->truncate( to => 'day' ),
$two_days_ahead->truncate( to => 'day' ),
@ -906,11 +1059,20 @@ subtest "CanBookBeRenewed tests" => sub {
);
};
# Too many renewals
# set policy to forbid renewals
$dbh->do('UPDATE issuingrules SET norenewalbefore = NULL, renewalsallowed = 0');
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
rules => {
norenewalbefore => undef,
renewalsallowed => 0,
}
}
);
( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber);
is( $renewokay, 0, 'Cannot renew, 0 renewals allowed');
@ -1145,27 +1307,23 @@ subtest "Bug 13841 - Do not create new 0 amount fines" => sub {
subtest "AllowRenewalIfOtherItemsAvailable tests" => sub {
$dbh->do('DELETE FROM issues');
$dbh->do('DELETE FROM items');
$dbh->do('DELETE FROM issuingrules');
Koha::CirculationRules->search()->delete();
$dbh->do(
q{
INSERT INTO issuingrules ( categorycode, branchcode, itemtype, reservesallowed, issuelength, lengthunit, renewalsallowed, renewalperiod,
norenewalbefore, auto_renew, fine, chargeperiod ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )
},
{},
'*', '*', '*', 25,
14, 'days',
1, 7,
undef, 0,
.10, 1
);
$dbh->do('DELETE FROM circulation_rules');
Koha::CirculationRules->set_rules(
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
rules => {
maxissueqty => 20
reservesallowed => 25,
issuelength => 14,
lengthunit => 'days',
renewalsallowed => 1,
renewalperiod => 7,
norenewalbefore => undef,
auto_renew => 0,
fine => .10,
chargeperiod => 1,
maxissueqty => 20
}
}
);
@ -1214,22 +1372,58 @@ subtest "AllowRenewalIfOtherItemsAvailable tests" => sub {
undef, undef, undef
);
C4::Context->dbh->do("UPDATE issuingrules SET onshelfholds = 0");
Koha::CirculationRules->set_rules(
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
rules => {
onshelfholds => 0,
}
}
);
t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 0 );
( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable and onshelfholds are disabled' );
C4::Context->dbh->do("UPDATE issuingrules SET onshelfholds = 0");
Koha::CirculationRules->set_rules(
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
rules => {
onshelfholds => 0,
}
}
);
t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 1 );
( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable is enabled and onshelfholds is disabled' );
C4::Context->dbh->do("UPDATE issuingrules SET onshelfholds = 1");
Koha::CirculationRules->set_rules(
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
rules => {
onshelfholds => 1,
}
}
);
t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 0 );
( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable is disabled and onshelfhold is enabled' );
C4::Context->dbh->do("UPDATE issuingrules SET onshelfholds = 1");
Koha::CirculationRules->set_rules(
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
rules => {
onshelfholds => 1,
}
}
);
t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 1 );
( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
is( $renewokay, 1, 'Bug 14337 - Verify the borrower can renew with a hold on the record if AllowRenewalIfOtherItemsAvailable and onshelfhold are enabled' );
@ -1706,20 +1900,21 @@ subtest 'AddReturn + CumulativeRestrictionPeriods' => sub {
}
)->unblessed;
# And the issuing rule
Koha::IssuingRules->search->delete;
my $rule = Koha::IssuingRule->new(
# And the circulation rule
Koha::CirculationRules->search->delete;
Koha::CirculationRules->set_rules(
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
issuelength => 1,
firstremind => 1, # 1 day of grace
finedays => 2, # 2 days of fine per day of overdue
lengthunit => 'days',
rules => {
issuelength => 1,
firstremind => 1, # 1 day of grace
finedays => 2, # 2 days of fine per day of overdue
lengthunit => 'days',
}
}
);
$rule->store();
# Patron cannot issue item_1, they have overdues
my $five_days_ago = dt_from_string->subtract( days => 5 );
@ -2017,19 +2212,20 @@ subtest 'AddReturn | is_overdue' => sub {
}
)->unblessed;
Koha::IssuingRules->search->delete;
my $rule = Koha::IssuingRule->new(
Koha::CirculationRules->search->delete;
my $rule = Koha::CirculationRules->set_rules(
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
issuelength => 6,
lengthunit => 'days',
fine => 1, # Charge 1 every day of overdue
chargeperiod => 1,
rules => {
issuelength => 6,
lengthunit => 'days',
fine => 1, # Charge 1 every day of overdue
chargeperiod => 1,
}
}
);
$rule->store();
my $now = dt_from_string;
my $one_day_ago = dt_from_string->subtract( days => 1 );

23
t/db_dependent/Circulation/CalcDateDue.t

@ -10,6 +10,8 @@ use t::lib::Mocks;
use t::lib::TestBuilder;
use C4::Calendar;
use Koha::CirculationRules;
use_ok('C4::Circulation');
my $schema = Koha::Database->new->schema;
@ -23,14 +25,19 @@ my $issuelength = 10;
my $renewalperiod = 5;
my $lengthunit = 'days';
Koha::Database->schema->resultset('Issuingrule')->create({
categorycode => $categorycode,
itemtype => $itemtype,
branchcode => $branchcode,
issuelength => $issuelength,
renewalperiod => $renewalperiod,
lengthunit => $lengthunit,
});
Koha::CirculationRules->search()->delete();
Koha::CirculationRules->set_rules(
{
categorycode => $categorycode,
itemtype => $itemtype,
branchcode => $branchcode,
rules => {
issuelength => $issuelength,
renewalperiod => $renewalperiod,
lengthunit => $lengthunit,
}
}
);
#Set syspref ReturnBeforeExpiry = 1 and useDaysMode = 'Days'
t::lib::Mocks::mock_preference('ReturnBeforeExpiry', 1);

34
t/db_dependent/Circulation/CalcFine.t

@ -78,19 +78,12 @@ my $item = $builder->build(
subtest 'Test basic functionality' => sub {
plan tests => 1;
my $rule = $builder->schema->resultset('Issuingrule')->find({
branchcode => '*',
categorycode => '*',
itemtype => '*',
});
$rule->delete if $rule;
my $issuingrule = $builder->build(
Koha::CirculationRules->set_rules(
{
source => 'Issuingrule',
value => {
branchcode => '*',
categorycode => '*',
itemtype => '*',
branchcode => '*',
categorycode => '*',
itemtype => '*',
rules => {
fine => '1.00',
lengthunit => 'days',
finedays => 0,
@ -98,8 +91,8 @@ subtest 'Test basic functionality' => sub {
chargeperiod => 1,
overduefinescap => undef,
cap_fine_to_replacement_price => 0,
},
}
}
},
);
my $start_dt = DateTime->new(
@ -125,13 +118,12 @@ subtest 'Test cap_fine_to_replacement_price' => sub {
plan tests => 2;
t::lib::Mocks::mock_preference('useDefaultReplacementCost', '1');
my $issuingrule = $builder->build(
Koha::CirculationRules->set_rules(
{
source => 'Issuingrule',
value => {
branchcode => '*',
categorycode => '*',
itemtype => '*',
branchcode => '*',
categorycode => '*',
itemtype => '*',
rules => {
fine => '1.00',
lengthunit => 'days',
finedays => 0,
@ -214,5 +206,5 @@ subtest 'Test cap_fine_to_replacement_pricew with overduefinescap' => sub {
};
sub teardown {
$dbh->do(q|DELETE FROM issuingrules|);
$dbh->do(q|DELETE FROM circulation_rules|);
}

314
t/db_dependent/Circulation/GetHardDueDate.t

@ -5,10 +5,10 @@ use C4::Context;
use DateTime;
use Koha::Database;
use Koha::DateUtils;
use Koha::IssuingRules;
use Koha::CirculationRules;
use Koha::Library;
use Test::More tests => 9;
use Test::More tests => 8;
BEGIN {
use_ok('C4::Circulation');
@ -31,7 +31,7 @@ $dbh->do(q|DELETE FROM borrowers|);
$dbh->do(q|DELETE FROM edifact_ean|);
$dbh->do(q|DELETE FROM branches|);
$dbh->do(q|DELETE FROM categories|);
$dbh->do(q|DELETE FROM issuingrules|);
$dbh->do(q|DELETE FROM circulation_rules|);
#Add sample datas
@ -111,219 +111,111 @@ my $default = {
lengthunit => 'days'
};
#Test GetIssuingRule
#Test get_effective_rules
my $sampleissuingrule1 = {
reservecharge => 0,
restrictedtype => 0,
accountsent => 0,
finedays => 0,
lengthunit => 'days',
renewalperiod => 5,
norenewalbefore => 6,
auto_renew => 0,
issuelength => 5,
chargeperiod => 0,
chargeperiod_charge_at => 0,
rentaldiscount => 2,
reservesallowed => 0,
hardduedate => '2013-01-01',
branchcode => $samplebranch1->{branchcode},
fine => 0,
hardduedatecompare => 0,
overduefinescap => 0,
renewalsallowed => 0,
firstremind => 0,
itemtype => 'BOOK',
categorycode => $samplecat->{categorycode},
maxsuspensiondays => 0,
onshelfholds => 0,
opacitemholds => 'N',
cap_fine_to_replacement_price => 0,
holds_per_record => 1,
article_requests => 'yes',
no_auto_renewal_after => undef,
no_auto_renewal_after_hard_limit => undef,
suspension_chargeperiod => 1,
holds_per_day => undef,
branchcode => $samplebranch1->{branchcode},
categorycode => $samplecat->{categorycode},
itemtype => 'BOOK',
rules => {
reservecharge => 0,
restrictedtype => 0,
accountsent => 0,
finedays => 0,
lengthunit => 'days',
renewalperiod => 5,
norenewalbefore => 6,
auto_renew => 0,
issuelength => 5,
chargeperiod => 0,
chargeperiod_charge_at => 0,
rentaldiscount => 2,
reservesallowed => 0,
hardduedate => '2013-01-01',
fine => 0,
hardduedatecompare => 5,
overduefinescap => 0,
renewalsallowed => 0,
firstremind => 0,
maxsuspensiondays => 0,
onshelfholds => 0,
opacitemholds => 'N',
cap_fine_to_replacement_price => 0,
holds_per_record => 1,
article_requests => 'yes',
no_auto_renewal_after => undef,
no_auto_renewal_after_hard_limit => undef,
suspension_chargeperiod => 1,
holds_per_day => undef,
}
};
my $sampleissuingrule2 = {
branchcode => $samplebranch2->{branchcode},
categorycode => $samplecat->{categorycode},
itemtype => 'BOOK',
renewalsallowed => 0,
renewalperiod => 2,
norenewalbefore => 7,
auto_renew => 0,
reservesallowed => 0,
issuelength => 2,
lengthunit => 'days',
hardduedate => undef,
hardduedatecompare => 0,
fine => undef,
finedays => undef,
firstremind => undef,
chargeperiod => undef,
chargeperiod_charge_at => 0,
rentaldiscount => 2.00,
overduefinescap => undef,
accountsent => undef,
reservecharge => undef,
restrictedtype => undef,
maxsuspensiondays => 0,
onshelfholds => 1,
opacitemholds => 'Y',
cap_fine_to_replacement_price => 0,
holds_per_record => 1,
article_requests => 'yes',
branchcode => $samplebranch2->{branchcode},
categorycode => $samplecat->{categorycode},
itemtype => 'BOOK',
rules => {
renewalsallowed => 0,
renewalperiod => 2,
norenewalbefore => 7,
auto_renew => 0,
reservesallowed => 0,
issuelength => 2,
lengthunit => 'days',
hardduedate => 2,
hardduedatecompare => undef,
fine => undef,
finedays => undef,
firstremind => undef,
chargeperiod => undef,
chargeperiod_charge_at => 0,
rentaldiscount => 2.00,
overduefinescap => undef,
accountsent => undef,
reservecharge => undef,
restrictedtype => undef,
maxsuspensiondays => 0,
onshelfholds => 1,
opacitemholds => 'Y',
cap_fine_to_replacement_price => 0,
holds_per_record => 1,
article_requests => 'yes',
}
};
my $sampleissuingrule3 = {
branchcode => $samplebranch1->{branchcode},
categorycode => $samplecat->{categorycode},
itemtype => 'DVD',
renewalsallowed => 0,
renewalperiod => 3,
norenewalbefore => 8,
auto_renew => 0,
reservesallowed => 0,
issuelength => 3,
lengthunit => 'days',
hardduedate => undef,
hardduedatecompare => 0,
fine => undef,
finedays => undef,
firstremind => undef,
chargeperiod => undef,
chargeperiod_charge_at => 0,
rentaldiscount => 3.00,
overduefinescap => undef,
accountsent => undef,
reservecharge => undef,
restrictedtype => undef,
maxsuspensiondays => 0,
onshelfholds => 1,
opacitemholds => 'F',
cap_fine_to_replacement_price => 0,
holds_per_record => 1,
article_requests => 'yes',
branchcode => $samplebranch1->{branchcode},
categorycode => $samplecat->{categorycode},
itemtype => 'DVD',
rules => {
renewalsallowed => 0,
renewalperiod => 3,
norenewalbefore => 8,
auto_renew => 0,
reservesallowed => 0,
issuelength => 3,
lengthunit => 'days',
hardduedate => 3,
hardduedatecompare => undef,
fine => undef,
finedays => undef,
firstremind => undef,
chargeperiod => undef,
chargeperiod_charge_at => 0,
rentaldiscount => 3.00,
overduefinescap => undef,
accountsent => undef,
reservecharge => undef,
restrictedtype => undef,
maxsuspensiondays => 0,
onshelfholds => 1,
opacitemholds => 'F',
cap_fine_to_replacement_price => 0,
holds_per_record => 1,
article_requests => 'yes',
}
};
$query = 'INSERT INTO issuingrules (
branchcode,
categorycode,
itemtype,
renewalsallowed,
renewalperiod,
norenewalbefore,
auto_renew,
reservesallowed,
issuelength,
lengthunit,
hardduedate,
hardduedatecompare,
fine,
finedays,
firstremind,
chargeperiod,
chargeperiod_charge_at,
rentaldiscount,
overduefinescap,
accountsent,
reservecharge,
restrictedtype,
maxsuspensiondays,
onshelfholds,
opacitemholds,
cap_fine_to_replacement_price,
article_requests
) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)';
my $sth = $dbh->prepare($query);
$sth->execute(
$sampleissuingrule1->{branchcode},
$sampleissuingrule1->{categorycode},
$sampleissuingrule1->{itemtype},
$sampleissuingrule1->{renewalsallowed},
$sampleissuingrule1->{renewalperiod},
$sampleissuingrule1->{norenewalbefore},
$sampleissuingrule1->{auto_renew},
$sampleissuingrule1->{reservesallowed},
$sampleissuingrule1->{issuelength},
$sampleissuingrule1->{lengthunit},
$sampleissuingrule1->{hardduedate},
$sampleissuingrule1->{hardduedatecompare},
$sampleissuingrule1->{fine},
$sampleissuingrule1->{finedays},
$sampleissuingrule1->{firstremind},
$sampleissuingrule1->{chargeperiod},
$sampleissuingrule1->{chargeperiod_charge_at},
$sampleissuingrule1->{rentaldiscount},
$sampleissuingrule1->{overduefinescap},
$sampleissuingrule1->{accountsent},
$sampleissuingrule1->{reservecharge},
$sampleissuingrule1->{restrictedtype},
$sampleissuingrule1->{maxsuspensiondays},
$sampleissuingrule1->{onshelfholds},
$sampleissuingrule1->{opacitemholds},
$sampleissuingrule1->{cap_fine_to_replacement_price},
$sampleissuingrule1->{article_requests},
);
$sth->execute(
$sampleissuingrule2->{branchcode},
$sampleissuingrule2->{categorycode},
$sampleissuingrule2->{itemtype},
$sampleissuingrule2->{renewalsallowed},
$sampleissuingrule2->{renewalperiod},
$sampleissuingrule2->{norenewalbefore},
$sampleissuingrule2->{auto_renew},
$sampleissuingrule2->{reservesallowed},
$sampleissuingrule2->{issuelength},
$sampleissuingrule2->{lengthunit},
$sampleissuingrule2->{hardduedate},
$sampleissuingrule2->{hardduedatecompare},
$sampleissuingrule2->{fine},
$sampleissuingrule2->{finedays},
$sampleissuingrule2->{firstremind},
$sampleissuingrule2->{chargeperiod},
$sampleissuingrule2->{chargeperiod_charge_at},
$sampleissuingrule2->{rentaldiscount},
$sampleissuingrule2->{overduefinescap},
$sampleissuingrule2->{accountsent},
$sampleissuingrule2->{reservecharge},
$sampleissuingrule2->{restrictedtype},
$sampleissuingrule2->{maxsuspensiondays},
$sampleissuingrule2->{onshelfholds},
$sampleissuingrule2->{opacitemholds},
$sampleissuingrule2->{cap_fine_to_replacement_price},
$sampleissuingrule2->{article_requests},
);
$sth->execute(
$sampleissuingrule3->{branchcode},
$sampleissuingrule3->{categorycode},
$sampleissuingrule3->{itemtype},
$sampleissuingrule3->{renewalsallowed},
$sampleissuingrule3->{renewalperiod},
$sampleissuingrule3->{norenewalbefore},
$sampleissuingrule3->{auto_renew},
$sampleissuingrule3->{reservesallowed},
$sampleissuingrule3->{issuelength},
$sampleissuingrule3->{lengthunit},
$sampleissuingrule3->{hardduedate},
$sampleissuingrule3->{hardduedatecompare},
$sampleissuingrule3->{fine},
$sampleissuingrule3->{finedays},
$sampleissuingrule3->{firstremind},
$sampleissuingrule3->{chargeperiod},
$sampleissuingrule3->{chargeperiod_charge_at},
$sampleissuingrule3->{rentaldiscount},
$sampleissuingrule3->{overduefinescap},
$sampleissuingrule3->{accountsent},
$sampleissuingrule3->{reservecharge},
$sampleissuingrule3->{restrictedtype},
$sampleissuingrule3->{maxsuspensiondays},
$sampleissuingrule3->{onshelfholds},
$sampleissuingrule3->{opacitemholds},
$sampleissuingrule3->{cap_fine_to_replacement_price},
$sampleissuingrule3->{article_requests},
);
Koha::CirculationRules->set_rules( $sampleissuingrule1 );
Koha::CirculationRules->set_rules( $sampleissuingrule2 );
Koha::CirculationRules->set_rules( $sampleissuingrule3 );
#Test GetLoanLength
is_deeply(
@ -371,8 +263,8 @@ my @hardduedate = C4::Circulation::GetHardDueDate( $samplecat->{categorycode},
is_deeply(
\@hardduedate,
[
dt_from_string( $sampleissuingrule1->{hardduedate}, 'iso' ),
$sampleissuingrule1->{hardduedatecompare}
dt_from_string( $sampleissuingrule1->{rules}->{hardduedate}, 'iso' ),
$sampleissuingrule1->{rules}->{hardduedatecompare}
],
"GetHardDueDate returns the duedate and the duedatecompare"
);

31
t/db_dependent/Circulation/IssuingRules/maxsuspensiondays.t

@ -29,17 +29,16 @@ my $patron_category = $builder->build({ source => 'Category' });
t::lib::Mocks::mock_userenv({ branchcode => $branchcode });
# Test without maxsuspensiondays set
Koha::IssuingRules->search->delete;
$builder->build(
Koha::CirculationRules->search->delete;
Koha::CirculationRules->set_rules(
{
source => 'Issuingrule',
value => {
categorycode => '*',
itemtype => '*',
branchcode => '*',
firstremind => 0,
finedays => 2,
lengthunit => 'days',
categorycode => '*',
itemtype => '*',
branchcode => '*',
rules => {
firstremind => 0,
finedays => 2,
lengthunit => 'days',
suspension_chargeperiod => 1,
}
}
@ -87,8 +86,16 @@ is(
DelDebarment( $debarments->[0]->{borrower_debarment_id} );
# Test with maxsuspensiondays = 10 days
my $issuing_rule = Koha::IssuingRules->search->next;
$issuing_rule->maxsuspensiondays( 10 )->store;
Koha::CirculationRules->set_rules(
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
rules => {
maxsuspensiondays => 10,
}
}
);
my $daysafter10 = dt_from_string->add_duration(DateTime::Duration->new(days => 10));
AddIssue( $borrower, $barcode, $daysago20 );

21
t/db_dependent/Circulation/Returns.t

@ -57,16 +57,16 @@ my $schema = Koha::Database->schema;
$schema->storage->txn_begin;
my $builder = t::lib::TestBuilder->new();
Koha::IssuingRules->search->delete;
my $rule = Koha::IssuingRule->new(
Koha::CirculationRules->search->delete;
Koha::CirculationRules->set_rule(
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
issuelength => 1,
rule_name => 'issuelength',
rule_value => 1,
}
);
$rule->store();
subtest "AddReturn logging on statistics table (item-level_itypes=1)" => sub {
@ -254,7 +254,18 @@ subtest 'Handle ids duplication' => sub {
t::lib::Mocks::mock_preference( 'item-level_itypes', 1 );
t::lib::Mocks::mock_preference( 'CalculateFinesOnReturn', 1 );
t::lib::Mocks::mock_preference( 'finesMode', 'production' );
Koha::IssuingRules->search->update({ chargeperiod => 1, fine => 1, firstremind => 1, });
Koha::CirculationRules->set_rules(
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
rules => {
chargeperiod => 1,
fine => 1,
firstremind => 1,
}
}
);
my $biblio = $builder->build( { source => 'Biblio' } );
my $itemtype = $builder->build( { source => 'Itemtype', value => { rentalcharge => 5 } } );

21
t/db_dependent/Circulation/SwitchOnSiteCheckouts.t

@ -38,7 +38,7 @@ $schema->storage->txn_begin;
our $dbh = C4::Context->dbh;
$dbh->do(q|DELETE FROM issues|);
$dbh->do(q|DELETE FROM issuingrules|);
$dbh->do(q|DELETE FROM circulation_rules|);
my $builder = t::lib::TestBuilder->new();
@ -81,18 +81,6 @@ my $item = $builder->build({
},
});
my $issuingrule = $builder->build({
source => 'Issuingrule',
value => {
branchcode => $branch->{branchcode},
categorycode => '*',
itemtype => '*',
lengthunit => 'days',
issuelength => 5,
hardduedate => undef,
hardduedatecompare => 0,
},
});
Koha::CirculationRules->search()->delete();
Koha::CirculationRules->set_rules(
{
@ -102,6 +90,13 @@ Koha::CirculationRules->set_rules(
rules => {
maxissueqty => 2,
maxonsiteissueqty => 1,
branchcode => $branch->{branchcode},
categorycode => '*',
itemtype => '*',
lengthunit => 'days',
issuelength => 5,
hardduedate => undef,
hardduedatecompare => 0,
}
}
);

14
t/db_dependent/Circulation/TooMany.t

@ -43,7 +43,6 @@ $dbh->do(q|DELETE FROM branches|);
$dbh->do(q|DELETE FROM categories|);
$dbh->do(q|DELETE FROM accountlines|);
$dbh->do(q|DELETE FROM itemtypes|);
$dbh->do(q|DELETE FROM issuingrules|);
Koha::CirculationRules->search()->delete();
my $builder = t::lib::TestBuilder->new();
@ -423,6 +422,17 @@ subtest '1 BranchBorrowerCircRule exist: 1 CO allowed, 1 OSCO allowed' => sub {
);
teardown();
Koha::CirculationRules->set_rules(
{
branchcode => $branch->{branchcode},
categorycode => $category->{categorycode},
itemtype => undef,
rules => {
maxissueqty => 1,
maxonsiteissueqty => 1,
}
}
);
$issue = C4::Circulation::AddIssue( $patron, $item->{barcode}, dt_from_string(), undef, undef, undef, { onsite_checkout => 1 } );
like( $issue->issue_id, qr|^\d+$|, 'The issue should have been inserted' );
@ -705,6 +715,6 @@ $schema->storage->txn_rollback;
sub teardown {
$dbh->do(q|DELETE FROM issues|);
$dbh->do(q|DELETE FROM issuingrules|);
$dbh->do(q|DELETE FROM circulation_rules|);
}

16
t/db_dependent/Circulation/issue.t

@ -35,6 +35,7 @@ use Koha::Holds;
use Koha::Items;
use Koha::Library;
use Koha::Patrons;
use Koha::CirculationRules;
BEGIN {
require_ok('C4::Circulation');
@ -66,7 +67,7 @@ $dbh->do(q|DELETE FROM items|);
$dbh->do(q|DELETE FROM borrowers|);
$dbh->do(q|DELETE FROM categories|);
$dbh->do(q|DELETE FROM accountlines|);
$dbh->do(q|DELETE FROM issuingrules|);
$dbh->do(q|DELETE FROM circulation_rules|);
$dbh->do(q|DELETE FROM reserves|);
$dbh->do(q|DELETE FROM old_reserves|);
$dbh->do(q|DELETE FROM statistics|);
@ -316,9 +317,16 @@ is_deeply(
);
# Add a default rule: renewal is allowed
$dbh->do(q|
UPDATE issuingrules SET renewalsallowed = 3
|);
Koha::CirculationRules->set_rules(
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
rules => {
renewalsallowed => 3,
}
}
);
@renewcount = C4::Circulation::GetRenewCount($borrower_id1, $item_id1);
is_deeply(
\@renewcount,

16
t/db_dependent/DecreaseLoanHighHolds.t

@ -25,6 +25,7 @@ use Koha::Biblio;
use Koha::Item;
use Koha::Holds;
use Koha::Hold;
use Koha::CirculationRules;
use t::lib::TestBuilder;
use t::lib::Mocks;
@ -96,15 +97,14 @@ for my $i ( 0 .. 5 ) {
my $item = pop(@items);
my $patron = pop(@patrons);
$builder->build(
Koha::CirculationRules->set_rules(
{
source => 'Issuingrule',
value => {
branchcode => '*',
categorycode => '*',
itemtype => $item->itype,
issuelength => '14',
lengthunit => 'days',
branchcode => '*',
categorycode => '*',
itemtype => $item->itype,
rules => {
issuelength => '14',
lengthunit => 'days',
reservesallowed => '99',
}
}

35
t/db_dependent/Fines.t

@ -13,19 +13,21 @@ my $schema = Koha::Database->new->schema;
$schema->storage->txn_begin;
my $dbh = C4::Context->dbh;
$dbh->do(q|DELETE FROM issuingrules|);
$dbh->do(q|DELETE FROM circulation_rules|);
my $issuingrule = $schema->resultset('Issuingrule')->create(
my $issuingrule = Koha::CirculationRules->set_rules(
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
fine => 1,
finedays => 0,
chargeperiod => 7,
chargeperiod_charge_at => 0,
lengthunit => 'days',
issuelength => 1,
categorycode => '*',
itemtype => '*',
branchcode => '*',
rules => {
fine => 1,
finedays => 0,
chargeperiod => 7,
chargeperiod_charge_at => 0,
lengthunit => 'days',
issuelength => 1,
}
}
);
@ -42,7 +44,16 @@ $period_end = dt_from_string('2000-01-10');
is( $fine, 1, '9 days overdue, charge period 7 days, charge at end of interval gives fine of $1' );
# Test charging fine at the *beginning* of each charge period
$issuingrule->update( { chargeperiod_charge_at => 1 } );
my $issuingrule = Koha::CirculationRules->set_rules(
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
rules => {
chargeperiod_charge_at => 1,
}
}
);
$period_end = dt_from_string('2000-01-05');
( $fine ) = CalcFine( {}, q{}, q{}, $period_start, $period_end );

87
t/db_dependent/Holds.t

@ -244,19 +244,27 @@ is( $hold->priority, '6', "Test AlterPriority(), move to bottom" );
my $foreign_biblio = $builder->build_sample_biblio({ itemtype => 'DUMMY' });
my ($foreign_item_bibnum, $foreign_item_bibitemnum, $foreign_itemnumber)
= AddItem({ homebranch => $branch_2, holdingbranch => $branch_2 } , $foreign_biblio->biblionumber);
# Cleanup circulation rules
$dbh->do('DELETE FROM circulation_rules');
# $dbh->do(
# q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_record)
# VALUES (?, ?, ?, ?, ?)},
# {},
# '*', '*', '*', 25, 99
# );
$dbh->do(
q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_record)
VALUES (?, ?, ?, ?, ?)},
{},
'*', '*', 'CANNOT', 0, 99
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
rules => {
reservesallowed => 25,
holds_per_record => 99,
}
}
);
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => 'CANNOT',
rules => {
reservesallowed => 0,
holds_per_record => 99,
}
}
);
# make sure some basic sysprefs are set
@ -266,8 +274,8 @@ t::lib::Mocks::mock_preference('item-level_itypes', 1);
# if IndependentBranches is OFF, a $branch_1 patron can reserve an $branch_2 item
t::lib::Mocks::mock_preference('IndependentBranches', 0);
ok(
CanItemBeReserved($borrowernumbers[0], $foreign_itemnumber)->{status} eq 'OK',
is(
CanItemBeReserved($borrowernumbers[0], $foreign_itemnumber)->{status}, 'OK',
'$branch_1 patron allowed to reserve $branch_2 item with IndependentBranches OFF (bug 2394)'
);
@ -354,13 +362,17 @@ ok(
# Test branch item rules
$dbh->do('DELETE FROM issuingrules');
$dbh->do('DELETE FROM circulation_rules');
$dbh->do(
q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed)
VALUES (?, ?, ?, ?)},
{},
'*', '*', '*', 25
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
rules => {
reservesallowed => 25,
holds_per_record => 99,
}
}
);
Koha::CirculationRules->set_rules(
{
@ -419,11 +431,16 @@ $biblio = $builder->build_sample_biblio({ itemtype => 'ONLY1' });
( $item_bibnum, $item_bibitemnum, $itemnumber )
= AddItem( { homebranch => $branch_1, holdingbranch => $branch_1 }, $biblio->biblionumber );
$dbh->do(
q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_record)
VALUES (?, ?, ?, ?, ?)},
{},
'*', '*', 'ONLY1', 1, 99
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => 'ONLY1',
rules => {
reservesallowed => 1,
holds_per_record => 99,
}
}
);
is( CanItemBeReserved( $borrowernumbers[0], $itemnumber )->{status},
'OK', 'Patron can reserve item with hold limit of 1, no holds placed' );
@ -444,20 +461,22 @@ subtest 'Test max_holds per library/patron category' => sub {
plan tests => 6;
$dbh->do('DELETE FROM reserves');
$dbh->do('DELETE FROM issuingrules');
$dbh->do('DELETE FROM circulation_rules');
$biblio = $builder->build_sample_biblio({ itemtype => 'TEST' });
( $item_bibnum, $item_bibitemnum, $itemnumber ) =
AddItem( { homebranch => $branch_1, holdingbranch => $branch_1 },
$biblio->biblionumber );
$dbh->do(
q{
INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_record)
VALUES (?, ?, ?, ?, ?)
},
{},
'*', '*', 'TEST', 99, 99
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => 'TEST',
rules => {
reservesallowed => 99,
holds_per_record => 99,
}
}
);
AddReserve( $branch_1, $borrowernumbers[0], $biblio->biblionumber, '', 1, );
AddReserve( $branch_1, $borrowernumbers[0], $biblio->biblionumber, '', 1, );

22
t/db_dependent/Holds/DisallowHoldIfItemsAvailable.t

@ -5,8 +5,9 @@ use Modern::Perl;
use C4::Context;
use C4::Circulation;
use C4::Items;
use Koha::IssuingRule;
use Koha::Items;
use Koha::CirculationRules;
use Test::More tests => 6;
use t::lib::TestBuilder;
@ -80,18 +81,20 @@ my $item2 = $builder->build_sample_item({
});
# Test hold_fulfillment_policy
my $rule = Koha::IssuingRule->new(
$dbh->do("DELETE FROM circulation_rules");
Koha::CirculationRules->set_rules(
{
categorycode => '*',
itemtype => $itemtype,
branchcode => '*',
issuelength => 7,
lengthunit => 8,
reservesallowed => 99,
onshelfholds => 2,
rules => {
issuelength => 7,
lengthunit => 8,
reservesallowed => 99,
onshelfholds => 2,
}
}
);
$rule->store();
my $is = IsAvailableForItemLevelRequest( $item1, $patron1);
is( $is, 0, "Item cannot be held, 2 items available" );
@ -213,7 +216,7 @@ my $hold = $builder->build({
}
});
$rule = Koha::IssuingRule->new(
Koha::IssuingRule->new(
{
categorycode => '*',
itemtype => $itemtype2,
@ -223,8 +226,7 @@ $rule = Koha::IssuingRule->new(
reservesallowed => 99,
onshelfholds => 0,
}
);
$rule->store();
)->store();
$is = IsAvailableForItemLevelRequest( $item3, $patron1);
is( $is, 1, "Item can be held, items in transit are not available" );

87
t/db_dependent/Koha/IssuingRules.t

@ -23,7 +23,6 @@ use Test::More tests => 4;
use Benchmark;
use Koha::IssuingRules;
use Koha::CirculationRules;
use t::lib::TestBuilder;
@ -48,26 +47,29 @@ subtest 'get_effective_issuing_rule' => sub {
plan tests => 4;
my $rule;
Koha::IssuingRules->delete;
Koha::CirculationRules->delete;
is(Koha::IssuingRules->search->count, 0, 'There are no issuing rules.');
$rule = Koha::IssuingRules->get_effective_issuing_rule({
is(Koha::CirculationRules->search->count, 0, 'There are no issuing rules.');
$rule = Koha::CirculationRules->get_effective_rule({
branchcode => undef,
categorycode => undef,
itemtype => undef,
rule_name => 'fine',
});
is($rule, undef, 'When I attempt to get effective issuing rule by'
.' providing undefined values, then undef is returned.');
ok(Koha::IssuingRule->new({
ok(Koha::CirculationRule->new({
branchcode => '*',
categorycode => '*',
itemtype => '*',
rule_name => 'fine',
})->store, 'Given I added an issuing rule branchcode => *,'
.' categorycode => *, itemtype => *,');
$rule = Koha::IssuingRules->get_effective_issuing_rule({
branchcode => undef,
categorycode => undef,
itemtype => undef,
$rule = Koha::CirculationRules->get_effective_rule({
branchcode => '*',
categorycode => '*',
itemtype => '*',
rule_name => 'fine',
});
ok(_row_match($rule, '*', '*', '*'), 'When I attempt to get effective'
.' issuing rule by providing undefined values, then the above one is'
@ -78,116 +80,133 @@ subtest 'get_effective_issuing_rule' => sub {
plan tests => 18;
my $rule;
Koha::IssuingRules->delete;
is(Koha::IssuingRules->search->count, 0, 'There are no issuing rules.');
$rule = Koha::IssuingRules->get_effective_issuing_rule({
Koha::CirculationRules->delete;
is(Koha::CirculationRules->search->count, 0, 'There are no issuing rules.');
$rule = Koha::CirculationRules->get_effective_rule({
branchcode => $branchcode,
categorycode => $categorycode,
itemtype => $itemtype,
rule_name => 'fine',
});
is($rule, undef, 'When I attempt to get effective issuing rule, then undef'
.' is returned.');
ok(Koha::IssuingRule->new({
ok(Koha::CirculationRule->new({
branchcode => '*',
categorycode => '*',
itemtype => '*',
rule_name => 'fine',
})->store, 'Given I added an issuing rule branchcode => *, categorycode => *, itemtype => *,');
$rule = Koha::IssuingRules->get_effective_issuing_rule({
$rule = Koha::CirculationRules->get_effective_rule({
branchcode => $branchcode,
categorycode => $categorycode,
itemtype => $itemtype,
rule_name => 'fine',
});
ok(_row_match($rule, '*', '*', '*'), 'When I attempt to get effective issuing rule,'
.' then the above one is returned.');
ok(Koha::IssuingRule->new({
ok(Koha::CirculationRule->new({
branchcode => '*',
categorycode => '*',
itemtype => $itemtype,
rule_name => 'fine',
})->store, "Given I added an issuing rule branchcode => *, categorycode => *, itemtype => $itemtype,");
$rule = Koha::IssuingRules->get_effective_issuing_rule({
$rule = Koha::CirculationRules->get_effective_rule({
branchcode => $branchcode,
categorycode => $categorycode,
itemtype => $itemtype,
rule_name => 'fine',
});
ok(_row_match($rule, '*', '*', $itemtype), 'When I attempt to get effective issuing rule,'
.' then the above one is returned.');
ok(Koha::IssuingRule->new({
ok(Koha::CirculationRule->new({
branchcode => '*',
categorycode => $categorycode,
itemtype => '*',
rule_name => 'fine',
})->store, "Given I added an issuing rule branchcode => *, categorycode => $categorycode, itemtype => *,");
$rule = Koha::IssuingRules->get_effective_issuing_rule({
$rule = Koha::CirculationRules->get_effective_rule({
branchcode => $branchcode,
categorycode => $categorycode,
itemtype => $itemtype,
rule_name => 'fine',
});
ok(_row_match($rule, '*', $categorycode, '*'), 'When I attempt to get effective issuing rule,'
.' then the above one is returned.');
ok(Koha::IssuingRule->new({
ok(Koha::CirculationRule->new({
branchcode => '*',
categorycode => $categorycode,
itemtype => $itemtype,
rule_name => 'fine',
})->store, "Given I added an issuing rule branchcode => *, categorycode => $categorycode, itemtype => $itemtype,");
$rule = Koha::IssuingRules->get_effective_issuing_rule({
$rule = Koha::CirculationRules->get_effective_rule({
branchcode => $branchcode,
categorycode => $categorycode,
itemtype => $itemtype,
rule_name => 'fine',
});
ok(_row_match($rule, '*', $categorycode, $itemtype), 'When I attempt to get effective issuing rule,'
.' then the above one is returned.');
ok(Koha::IssuingRule->new({
ok(Koha::CirculationRule->new({
branchcode => $branchcode,
categorycode => '*',
itemtype => '*',
rule_name => 'fine',
})->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => '*', itemtype => '*',");
$rule = Koha::IssuingRules->get_effective_issuing_rule({
$rule = Koha::CirculationRules->get_effective_rule({
branchcode => $branchcode,
categorycode => $categorycode,
itemtype => $itemtype,
rule_name => 'fine',
});
ok(_row_match($rule, $branchcode, '*', '*'), 'When I attempt to get effective issuing rule,'
.' then the above one is returned.');
ok(Koha::IssuingRule->new({
ok(Koha::CirculationRule->new({
branchcode => $branchcode,
categorycode => '*',
itemtype => $itemtype,
rule_name => 'fine',
})->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => '*', itemtype => $itemtype,");
$rule = Koha::IssuingRules->get_effective_issuing_rule({
$rule = Koha::CirculationRules->get_effective_rule({
branchcode => $branchcode,
categorycode => $categorycode,
itemtype => $itemtype,
rule_name => 'fine',
});
ok(_row_match($rule, $branchcode, '*', $itemtype), 'When I attempt to get effective issuing rule,'
.' then the above one is returned.');
ok(Koha::IssuingRule->new({
ok(Koha::CirculationRule->new({
branchcode => $branchcode,
categorycode => $categorycode,
itemtype => '*',
rule_name => 'fine',
})->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => $categorycode, itemtype => '*',");
$rule = Koha::IssuingRules->get_effective_issuing_rule({
$rule = Koha::CirculationRules->get_effective_rule({
branchcode => $branchcode,
categorycode => $categorycode,
itemtype => $itemtype,
rule_name => 'fine',
});
ok(_row_match($rule, $branchcode, $categorycode, '*'), 'When I attempt to get effective issuing rule,'
.' then the above one is returned.');
ok(Koha::IssuingRule->new({
ok(Koha::CirculationRule->new({
branchcode => $branchcode,
categorycode => $categorycode,
itemtype => $itemtype,
rule_name => 'fine',
})->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => $categorycode, itemtype => $itemtype,");
$rule = Koha::IssuingRules->get_effective_issuing_rule({
$rule = Koha::CirculationRules->get_effective_rule({
branchcode => $branchcode,
categorycode => $categorycode,
itemtype => $itemtype,
rule_name => 'fine',
});
ok(_row_match($rule, $branchcode, $categorycode, $itemtype), 'When I attempt to get effective issuing rule,'
.' then the above one is returned.');
@ -197,34 +216,38 @@ subtest 'get_effective_issuing_rule' => sub {
plan tests => 4;
my $worst_case = timethis(500,
sub { Koha::IssuingRules->get_effective_issuing_rule({
sub { Koha::CirculationRules->get_effective_rule({
branchcode => 'nonexistent',
categorycode => 'nonexistent',
itemtype => 'nonexistent',
rule_name => 'nonexistent',
});
}
);
my $mid_case = timethis(500,
sub { Koha::IssuingRules->get_effective_issuing_rule({
sub { Koha::CirculationRules->get_effective_rule({
branchcode => $branchcode,
categorycode => 'nonexistent',
itemtype => 'nonexistent',
rule_name => 'nonexistent',
});
}
);
my $sec_best_case = timethis(500,
sub { Koha::IssuingRules->get_effective_issuing_rule({
sub { Koha::CirculationRules->get_effective_rule({
branchcode => $branchcode,
categorycode => $categorycode,
itemtype => 'nonexistent',
rule_name => 'nonexistent',
});
}
);
my $best_case = timethis(500,
sub { Koha::IssuingRules->get_effective_issuing_rule({
sub { Koha::CirculationRules->get_effective_rule({
branchcode => $branchcode,
categorycode => $categorycode,
itemtype => $itemtype,
rule_name => 'nonexistent',
});
}
);

9
t/db_dependent/Koha/Objects.t

@ -25,7 +25,6 @@ use Test::Warn;
use Koha::Authority::Types;
use Koha::Cities;
use Koha::IssuingRules;
use Koha::Patron::Category;
use Koha::Patron::Categories;
use Koha::Patrons;
@ -114,7 +113,7 @@ subtest 'new' => sub {
};
subtest 'find' => sub {
plan tests => 5;
plan tests => 4;
# check find on a single PK
my $patron = $builder->build({ source => 'Borrower' });
@ -132,12 +131,6 @@ subtest 'find' => sub {
{ where => { surname => { '!=', $patron->{surname} }}},
), undef, 'Additional where clause in find call' );
# check find with a composite FK
my $rule = $builder->build({ source => 'Issuingrule' });
my @pk = ( $rule->{branchcode}, $rule->{categorycode}, $rule->{itemtype} );
is( ref(Koha::IssuingRules->find(@pk)), "Koha::IssuingRule",
'Find returned a Koha object for composite primary key' );
is( Koha::Patrons->find(), undef, 'Find returns undef if no params passed' );
};

44
t/db_dependent/Reserves.t

@ -190,12 +190,17 @@ $requesters{$branch_3} = Koha::Patron->new({
# to request its items, while $branch_2 will allow its items
# to fill holds from anywhere.
$dbh->do('DELETE FROM issuingrules');
$dbh->do(
q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed)
VALUES (?, ?, ?, ?)},
{},
'*', '*', '*', 25
$dbh->do('DELETE FROM circulation_rules');
Koha::CirculationRules->set_rules(
{
branchcode => '*',
categorycode => '*',
itemtype => '*',
rules => {
reservesallowed => 25,
holds_per_record => 1,
}
}
);
# CPL allows only its own patrons to request its items
@ -546,6 +551,33 @@ my $limit = Koha::Item::Transfer::Limit->new(
is( C4::Reserves::IsAvailableForItemLevelRequest($item, $patron, $pickup_branch), 0, "Item level request not available due to transfer limit" );
t::lib::Mocks::mock_preference( 'UseBranchTransferLimits', '0' );
my $itype = C4::Reserves::_get_itype($item);
my $categorycode = $borrower->{categorycode};
my $holdingbranch = $item->{holdingbranch};
Koha::CirculationRules->set_rules(
{
categorycode => $categorycode,
itemtype => $itype,
branchcode => $holdingbranch,
rules => {
onshelfholds => 1,
}
}
);
ok( C4::Reserves::OnShelfHoldsAllowed($item, $borrower), "OnShelfHoldsAllowed() allowed" );
Koha::CirculationRules->set_rules(
{
categorycode => $categorycode,
itemtype => $itype,
branchcode => $holdingbranch,
rules => {
onshelfholds => 0,
}
}
);
ok( !C4::Reserves::OnShelfHoldsAllowed($item, $borrower), "OnShelfHoldsAllowed() disallowed" );
# tests for MoveReserve in relation to ConfirmFutureHolds (BZ 14526)
# hold from A pos 1, today, no fut holds: MoveReserve should fill it
$dbh->do('DELETE FROM reserves', undef, ($bibnum));

105
t/db_dependent/Reserves/MultiplePerRecord.t

@ -115,19 +115,20 @@ my $item3 = $builder->build(
}
);
my $rules_rs = Koha::Database->new()->schema()->resultset('Issuingrule');
$rules_rs->delete();
Koha::CirculationRules->delete();
# Test GetMaxPatronHoldsForRecord and GetHoldRule
my $rule1 = $rules_rs->new(
Koha::CirculationRules->set_rules(
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
reservesallowed => 1,
holds_per_record => 1,
categorycode => '*',
itemtype => '*',
branchcode => '*',
rules => {
reservesallowed => 1,
holds_per_record => 1,
}
}
)->insert();
);
t::lib::Mocks::mock_preference('item-level_itypes', 1); # Assuming the item type is defined at item level
@ -144,15 +145,17 @@ is( $rule->{branchcode}, '*', 'Got rule with universal branchcode' );
is( $rule->{reservesallowed}, 1, 'Got reservesallowed of 1' );
is( $rule->{holds_per_record}, 1, 'Got holds_per_record of 1' );
my $rule2 = $rules_rs->new(
Koha::CirculationRules->set_rules(
{
categorycode => $category->{categorycode},
itemtype => '*',
branchcode => '*',
reservesallowed => 2,
holds_per_record => 2,
categorycode => $category->{categorycode},
itemtype => '*',
branchcode => '*',
rules => {
reservesallowed => 2,
holds_per_record => 2,
}
}
)->insert();
);
$max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
is( $max, 2, 'GetMaxPatronHoldsForRecord returns max of 2' );
@ -167,15 +170,17 @@ is( $rule->{branchcode}, '*', 'Got rule with univers
is( $rule->{reservesallowed}, 2, 'Got reservesallowed of 2' );
is( $rule->{holds_per_record}, 2, 'Got holds_per_record of 2' );
my $rule3 = $rules_rs->new(
Koha::CirculationRules->set_rules(
{
categorycode => $category->{categorycode},
itemtype => $itemtype1->{itemtype},
branchcode => '*',
reservesallowed => 3,
holds_per_record => 3,
categorycode => $category->{categorycode},
itemtype => $itemtype1->{itemtype},
branchcode => '*',
rules => {
reservesallowed => 3,
holds_per_record => 3,
}
}
)->insert();
);
$max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
is( $max, 3, 'GetMaxPatronHoldsForRecord returns max of 3' );
@ -190,15 +195,17 @@ is( $rule->{branchcode}, '*', 'Got rule with univers
is( $rule->{reservesallowed}, 3, 'Got reservesallowed of 3' );
is( $rule->{holds_per_record}, 3, 'Got holds_per_record of 3' );
my $rule4 = $rules_rs->new(
Koha::CirculationRules->set_rules(
{
categorycode => $category->{categorycode},
itemtype => $itemtype2->{itemtype},
branchcode => '*',
reservesallowed => 4,
holds_per_record => 4,
categorycode => $category->{categorycode},
itemtype => $itemtype2->{itemtype},
branchcode => '*',
rules => {
reservesallowed => 4,
holds_per_record => 4,
}
}
)->insert();
);
$max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
is( $max, 4, 'GetMaxPatronHoldsForRecord returns max of 4' );
@ -213,15 +220,17 @@ is( $rule->{branchcode}, '*', 'Got rule with univers
is( $rule->{reservesallowed}, 4, 'Got reservesallowed of 4' );
is( $rule->{holds_per_record}, 4, 'Got holds_per_record of 4' );
my $rule5 = $rules_rs->new(
Koha::CirculationRules->set_rules(
{
categorycode => $category->{categorycode},
itemtype => $itemtype2->{itemtype},
branchcode => $library->{branchcode},
reservesallowed => 5,
holds_per_record => 5,
categorycode => $category->{categorycode},
itemtype => $itemtype2->{itemtype},
branchcode => $library->{branchcode},
rules => {
reservesallowed => 5,
holds_per_record => 5,
}
}
)->insert();
);
$max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
is( $max, 5, 'GetMaxPatronHoldsForRecord returns max of 1' );
@ -236,11 +245,7 @@ is( $rule->{branchcode}, $library->{branchcode}, 'Got rule with specifi
is( $rule->{reservesallowed}, 5, 'Got reservesallowed of 5' );
is( $rule->{holds_per_record}, 5, 'Got holds_per_record of 5' );
$rule1->delete();
$rule2->delete();
$rule3->delete();
$rule4->delete();
$rule5->delete();
Koha::CirculationRules->delete();
my $holds = Koha::Holds->search( { borrowernumber => $patron->{borrowernumber} } );
is( $holds->forced_hold_level, undef, "No holds does not force an item or record level hold" );
@ -266,15 +271,17 @@ is( $holds->forced_hold_level, 'item', "Item level hold forces item level holds"
$hold->delete();
# Test multi-hold via AddReserve
$rule = $rules_rs->new(
Koha::CirculationRules->set_rules(
{
categorycode => '*',
itemtype => '*',
branchcode => '*',
reservesallowed => 2,
holds_per_record => 2,
categorycode => '*',
itemtype => '*',
branchcode => '*',
rules => {
reservesallowed => 2,
holds_per_record => 2,
}
}
)->insert();
);
my $can = CanBookBeReserved($patron->{borrowernumber}, $biblio->{biblionumber});
is( $can->{status}, 'OK', 'Hold can be placed with 0 holds' );

4
t/db_dependent/TestBuilder.t

@ -368,7 +368,7 @@ subtest 'build_object() tests' => sub {
my $itemtype = $builder->build( { source => 'Itemtype' } )->{itemtype};
my $issuing_rule = $builder->build_object(
{ class => 'Koha::IssuingRules',
{ class => 'Koha::CirculationRules',
value => {
categorycode => $categorycode,
itemtype => $itemtype
@ -376,7 +376,7 @@ subtest 'build_object() tests' => sub {
}
);
is( ref($issuing_rule), 'Koha::IssuingRule', 'Type is correct' );
is( ref($issuing_rule), 'Koha::CirculationRule', 'Type is correct' );
is( $issuing_rule->categorycode,
$categorycode, 'Category code correctly set' );
is( $issuing_rule->itemtype, $itemtype, 'Item type correctly set' );

16
t/db_dependent/api/v1/holds.t

@ -114,11 +114,17 @@ my $item_2 = $builder->build_sample_item({ biblionumber => $biblio_2->biblionu
my $dbh = C4::Context->dbh;
$dbh->do('DELETE FROM reserves');
$dbh->do('DELETE FROM issuingrules');
$dbh->do(q{
INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed)
VALUES (?, ?, ?, ?)
}, {}, '*', '*', '*', 1);
$dbh->do('DELETE FROM circulation_rules');
Koha::CirculationRules->set_rules(
{
categorycode => '*',
branchcode => '*',
itemtype => '*',
rules => {
reservesallowed => 1
}
}
);
my $reserve_id = C4::Reserves::AddReserve($branchcode, $patron_1->borrowernumber,
$biblio_1->biblionumber, undef, 1, undef, undef, undef, '', $item_1->itemnumber);

Loading…
Cancel
Save