View | Details | Raw Unified | Return to bug 17599
Collapse All | Expand All

(-)a/C4/Circulation.pm (-103 / +44 lines)
Lines 43-48 use Koha::Account; Link Here
43
use Koha::AuthorisedValues;
43
use Koha::AuthorisedValues;
44
use Koha::DateUtils;
44
use Koha::DateUtils;
45
use Koha::Calendar;
45
use Koha::Calendar;
46
use Koha::IssuingRules;
46
use Koha::Items;
47
use Koha::Items;
47
use Koha::Patrons;
48
use Koha::Patrons;
48
use Koha::Patron::Debarments;
49
use Koha::Patron::Debarments;
Lines 89-95 BEGIN { Link Here
89
		&GetItemIssue
90
		&GetItemIssue
90
		&GetItemIssues
91
		&GetItemIssues
91
		&GetIssuingCharges
92
		&GetIssuingCharges
92
		&GetIssuingRule
93
        &GetBranchBorrowerCircRule
93
        &GetBranchBorrowerCircRule
94
        &GetBranchItemRule
94
        &GetBranchItemRule
95
		&GetBiblioIssues
95
		&GetBiblioIssues
Lines 397-408 sub TooMany { Link Here
397
 
397
 
398
    # given branch, patron category, and item type, determine
398
    # given branch, patron category, and item type, determine
399
    # applicable issuing rule
399
    # applicable issuing rule
400
    my $issuing_rule = GetIssuingRule($cat_borrower, $type, $branch);
400
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $cat_borrower, itemtype => $type, branchcode => $branch });
401
401
402
    # if a rule is found and has a loan limit set, count
402
    # if a rule is found and has a loan limit set, count
403
    # how many loans the patron already has that meet that
403
    # how many loans the patron already has that meet that
404
    # rule
404
    # rule
405
    if (defined($issuing_rule) and defined($issuing_rule->{'maxissueqty'})) {
405
    if (defined($issuing_rule) and defined($issuing_rule->maxissueqty)) {
406
        my @bind_params;
406
        my @bind_params;
407
        my $count_query = q|
407
        my $count_query = q|
408
            SELECT COUNT(*) AS total, COALESCE(SUM(onsite_checkout), 0) AS onsite_checkouts
408
            SELECT COUNT(*) AS total, COALESCE(SUM(onsite_checkout), 0) AS onsite_checkouts
Lines 410-416 sub TooMany { Link Here
410
            JOIN items USING (itemnumber)
410
            JOIN items USING (itemnumber)
411
        |;
411
        |;
412
412
413
        my $rule_itemtype = $issuing_rule->{itemtype};
413
        my $rule_itemtype = $issuing_rule->itemtype;
414
        if ($rule_itemtype eq "*") {
414
        if ($rule_itemtype eq "*") {
415
            # matching rule has the default item type, so count only
415
            # matching rule has the default item type, so count only
416
            # those existing loans that don't fall under a more
416
            # those existing loans that don't fall under a more
Lines 431-438 sub TooMany { Link Here
431
                                    AND   itemtype <> '*'
431
                                    AND   itemtype <> '*'
432
                                  ) ";
432
                                  ) ";
433
            }
433
            }
434
            push @bind_params, $issuing_rule->{branchcode};
434
            push @bind_params, $issuing_rule->branchcode;
435
            push @bind_params, $issuing_rule->{categorycode};
435
            push @bind_params, $issuing_rule->categorycode;
436
            push @bind_params, $cat_borrower;
436
            push @bind_params, $cat_borrower;
437
        } else {
437
        } else {
438
            # rule has specific item type, so count loans of that
438
            # rule has specific item type, so count loans of that
Lines 448-454 sub TooMany { Link Here
448
448
449
        $count_query .= " AND borrowernumber = ? ";
449
        $count_query .= " AND borrowernumber = ? ";
450
        push @bind_params, $borrower->{'borrowernumber'};
450
        push @bind_params, $borrower->{'borrowernumber'};
451
        my $rule_branch = $issuing_rule->{branchcode};
451
        my $rule_branch = $issuing_rule->branchcode;
452
        if ($rule_branch ne "*") {
452
        if ($rule_branch ne "*") {
453
            if (C4::Context->preference('CircControl') eq 'PickupLibrary') {
453
            if (C4::Context->preference('CircControl') eq 'PickupLibrary') {
454
                $count_query .= " AND issues.branchcode = ? ";
454
                $count_query .= " AND issues.branchcode = ? ";
Lines 463-470 sub TooMany { Link Here
463
463
464
        my ( $checkout_count, $onsite_checkout_count ) = $dbh->selectrow_array( $count_query, {}, @bind_params );
464
        my ( $checkout_count, $onsite_checkout_count ) = $dbh->selectrow_array( $count_query, {}, @bind_params );
465
465
466
        my $max_checkouts_allowed = $issuing_rule->{maxissueqty};
466
        my $max_checkouts_allowed = $issuing_rule->maxissueqty;
467
        my $max_onsite_checkouts_allowed = $issuing_rule->{maxonsiteissueqty};
467
        my $max_onsite_checkouts_allowed = $issuing_rule->maxonsiteissueqty;
468
468
469
        if ( $onsite_checkout ) {
469
        if ( $onsite_checkout ) {
470
            if ( $onsite_checkout_count >= $max_onsite_checkouts_allowed )  {
470
            if ( $onsite_checkout_count >= $max_onsite_checkouts_allowed )  {
Lines 1333-1340 sub AddIssue { Link Here
1333
1333
1334
            # If automatic renewal wasn't selected while issuing, set the value according to the issuing rule.
1334
            # If automatic renewal wasn't selected while issuing, set the value according to the issuing rule.
1335
            unless ($auto_renew) {
1335
            unless ($auto_renew) {
1336
                my $issuingrule = GetIssuingRule( $borrower->{categorycode}, $item->{itype}, $branch );
1336
                my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $borrower->{categorycode}, itemtype => $item->{itype}, branchcode => $branch });
1337
                $auto_renew = $issuingrule->{auto_renew};
1337
                $auto_renew = $issuing_rule->auto_renew if $issuing_rule;
1338
            }
1338
            }
1339
1339
1340
            # Record in the database the fact that the book was issued.
1340
            # Record in the database the fact that the book was issued.
Lines 1533-1604 Get the Hard Due Date and it's comparison for an itemtype, a borrower type and a Link Here
1533
sub GetHardDueDate {
1533
sub GetHardDueDate {
1534
    my ( $borrowertype, $itemtype, $branchcode ) = @_;
1534
    my ( $borrowertype, $itemtype, $branchcode ) = @_;
1535
1535
1536
    my $rule = GetIssuingRule( $borrowertype, $itemtype, $branchcode );
1536
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $borrowertype, itemtype => $itemtype, branchcode => $branchcode });
1537
1537
1538
    if ( defined( $rule ) ) {
1538
    if ( defined( $issuing_rule ) ) {
1539
        if ( $rule->{hardduedate} ) {
1539
        if ( $issuing_rule->hardduedate ) {
1540
            return (dt_from_string($rule->{hardduedate}, 'iso'),$rule->{hardduedatecompare});
1540
            return (dt_from_string($issuing_rule->hardduedate, 'iso'),$issuing_rule->hardduedatecompare);
1541
        } else {
1541
        } else {
1542
            return (undef, undef);
1542
            return (undef, undef);
1543
        }
1543
        }
1544
    }
1544
    }
1545
}
1545
}
1546
1546
1547
=head2 GetIssuingRule
1548
1549
  my $irule = &GetIssuingRule($borrowertype,$itemtype,branchcode)
1550
1551
FIXME - This is a copy-paste of GetLoanLength
1552
as a stop-gap.  Do not wish to change API for GetLoanLength 
1553
this close to release.
1554
1555
Get the issuing rule for an itemtype, a borrower type and a branch
1556
Returns a hashref from the issuingrules table.
1557
1558
=cut
1559
1560
sub GetIssuingRule {
1561
    my ( $borrowertype, $itemtype, $branchcode ) = @_;
1562
    my $dbh = C4::Context->dbh;
1563
    my $sth =  $dbh->prepare( "select * from issuingrules where categorycode=? and itemtype=? and branchcode=?"  );
1564
    my $irule;
1565
1566
    $sth->execute( $borrowertype, $itemtype, $branchcode );
1567
    $irule = $sth->fetchrow_hashref;
1568
    return $irule if defined($irule) ;
1569
1570
    $sth->execute( $borrowertype, "*", $branchcode );
1571
    $irule = $sth->fetchrow_hashref;
1572
    return $irule if defined($irule) ;
1573
1574
    $sth->execute( "*", $itemtype, $branchcode );
1575
    $irule = $sth->fetchrow_hashref;
1576
    return $irule if defined($irule) ;
1577
1578
    $sth->execute( "*", "*", $branchcode );
1579
    $irule = $sth->fetchrow_hashref;
1580
    return $irule if defined($irule) ;
1581
1582
    $sth->execute( $borrowertype, $itemtype, "*" );
1583
    $irule = $sth->fetchrow_hashref;
1584
    return $irule if defined($irule) ;
1585
1586
    $sth->execute( $borrowertype, "*", "*" );
1587
    $irule = $sth->fetchrow_hashref;
1588
    return $irule if defined($irule) ;
1589
1590
    $sth->execute( "*", $itemtype, "*" );
1591
    $irule = $sth->fetchrow_hashref;
1592
    return $irule if defined($irule) ;
1593
1594
    $sth->execute( "*", "*", "*" );
1595
    $irule = $sth->fetchrow_hashref;
1596
    return $irule if defined($irule) ;
1597
1598
    # if no rule matches,
1599
    return;
1600
}
1601
1602
=head2 GetBranchBorrowerCircRule
1547
=head2 GetBranchBorrowerCircRule
1603
1548
1604
  my $branch_cat_rule = GetBranchBorrowerCircRule($branchcode, $categorycode);
1549
  my $branch_cat_rule = GetBranchBorrowerCircRule($branchcode, $categorycode);
Lines 2240-2249 sub _debar_user_on_return { Link Here
2240
    my $branchcode = _GetCircControlBranch( $item, $borrower );
2185
    my $branchcode = _GetCircControlBranch( $item, $borrower );
2241
2186
2242
    my $circcontrol = C4::Context->preference('CircControl');
2187
    my $circcontrol = C4::Context->preference('CircControl');
2243
    my $issuingrule =
2188
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $borrower->{categorycode}, itemtype => $item->{itype}, branchcode => $branchcode });
2244
      GetIssuingRule( $borrower->{categorycode}, $item->{itype}, $branchcode );
2189
    my $finedays = $issuing_rule ? $issuing_rule->finedays : undef;
2245
    my $finedays = $issuingrule->{finedays};
2190
    my $unit     = $issuing_rule ? $issuing_rule->lengthunit : undef;
2246
    my $unit     = $issuingrule->{lengthunit};
2247
    my $chargeable_units = C4::Overdues::get_chargeable_units($unit, $dt_due, $dt_today, $branchcode);
2191
    my $chargeable_units = C4::Overdues::get_chargeable_units($unit, $dt_due, $dt_today, $branchcode);
2248
2192
2249
    if ($finedays) {
2193
    if ($finedays) {
Lines 2254-2260 sub _debar_user_on_return { Link Here
2254
2198
2255
        # grace period is measured in the same units as the loan
2199
        # grace period is measured in the same units as the loan
2256
        my $grace =
2200
        my $grace =
2257
          DateTime::Duration->new( $unit => $issuingrule->{firstremind} );
2201
          DateTime::Duration->new( $unit => $issuing_rule->firstremind );
2258
2202
2259
        my $deltadays = DateTime::Duration->new(
2203
        my $deltadays = DateTime::Duration->new(
2260
            days => $chargeable_units
2204
            days => $chargeable_units
Lines 2264-2270 sub _debar_user_on_return { Link Here
2264
2208
2265
            # If the max suspension days is < than the suspension days
2209
            # If the max suspension days is < than the suspension days
2266
            # the suspension days is limited to this maximum period.
2210
            # the suspension days is limited to this maximum period.
2267
            my $max_sd = $issuingrule->{maxsuspensiondays};
2211
            my $max_sd = $issuing_rule->maxsuspensiondays;
2268
            if ( defined $max_sd ) {
2212
            if ( defined $max_sd ) {
2269
                $max_sd = DateTime::Duration->new( days => $max_sd );
2213
                $max_sd = DateTime::Duration->new( days => $max_sd );
2270
                $suspension_days = $max_sd
2214
                $suspension_days = $max_sd
Lines 2836-2846 sub CanBookBeRenewed { Link Here
2836
    return ( 1, undef ) if $override_limit;
2780
    return ( 1, undef ) if $override_limit;
2837
2781
2838
    my $branchcode = _GetCircControlBranch( $item, $borrower );
2782
    my $branchcode = _GetCircControlBranch( $item, $borrower );
2839
    my $issuingrule =
2783
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $borrower->{categorycode}, itemtype => $item->{itype}, branchcode => $branchcode });
2840
      GetIssuingRule( $borrower->{categorycode}, $item->{itype}, $branchcode );
2841
2784
2842
    return ( 0, "too_many" )
2785
    return ( 0, "too_many" )
2843
      if $issuingrule->{renewalsallowed} <= $itemissue->{renewals};
2786
      if not $issuing_rule or $issuing_rule->renewalsallowed <= $itemissue->{renewals};
2844
2787
2845
    my $overduesblockrenewing = C4::Context->preference('OverduesBlockRenewing');
2788
    my $overduesblockrenewing = C4::Context->preference('OverduesBlockRenewing');
2846
    my $restrictionblockrenewing = C4::Context->preference('RestrictionBlockRenewing');
2789
    my $restrictionblockrenewing = C4::Context->preference('RestrictionBlockRenewing');
Lines 2855-2868 sub CanBookBeRenewed { Link Here
2855
    }
2798
    }
2856
2799
2857
    if ( $itemissue->{auto_renew}
2800
    if ( $itemissue->{auto_renew}
2858
        and defined $issuingrule->{no_auto_renewal_after}
2801
        and defined $issuing_rule->no_auto_renewal_after
2859
                and $issuingrule->{no_auto_renewal_after} ne "" ) {
2802
                and $issuing_rule->no_auto_renewal_after ne "" ) {
2860
2803
2861
        # Get issue_date and add no_auto_renewal_after
2804
        # Get issue_date and add no_auto_renewal_after
2862
        # If this is greater than today, it's too late for renewal.
2805
        # If this is greater than today, it's too late for renewal.
2863
        my $maximum_renewal_date = dt_from_string($itemissue->{issuedate});
2806
        my $maximum_renewal_date = dt_from_string($itemissue->{issuedate});
2864
        $maximum_renewal_date->add(
2807
        $maximum_renewal_date->add(
2865
            $issuingrule->{lengthunit} => $issuingrule->{no_auto_renewal_after}
2808
            $issuing_rule->lengthunit => $issuing_rule->no_auto_renewal_after
2866
        );
2809
        );
2867
        my $now = dt_from_string;
2810
        my $now = dt_from_string;
2868
        if ( $now >= $maximum_renewal_date ) {
2811
        if ( $now >= $maximum_renewal_date ) {
Lines 2870-2888 sub CanBookBeRenewed { Link Here
2870
        }
2813
        }
2871
    }
2814
    }
2872
2815
2873
    if ( defined $issuingrule->{norenewalbefore}
2816
    if ( defined $issuing_rule->norenewalbefore
2874
        and $issuingrule->{norenewalbefore} ne "" )
2817
        and $issuing_rule->norenewalbefore ne "" )
2875
    {
2818
    {
2876
2819
2877
        # Calculate soonest renewal by subtracting 'No renewal before' from due date
2820
        # Calculate soonest renewal by subtracting 'No renewal before' from due date
2878
        my $soonestrenewal =
2821
        my $soonestrenewal =
2879
          $itemissue->{date_due}->clone()
2822
          $itemissue->{date_due}->clone()
2880
          ->subtract(
2823
          ->subtract(
2881
            $issuingrule->{lengthunit} => $issuingrule->{norenewalbefore} );
2824
            $issuing_rule->lengthunit => $issuing_rule->norenewalbefore );
2882
2825
2883
        # Depending on syspref reset the exact time, only check the date
2826
        # Depending on syspref reset the exact time, only check the date
2884
        if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
2827
        if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
2885
            and $issuingrule->{lengthunit} eq 'days' )
2828
            and $issuing_rule->lengthunit eq 'days' )
2886
        {
2829
        {
2887
            $soonestrenewal->truncate( to => 'day' );
2830
            $soonestrenewal->truncate( to => 'day' );
2888
        }
2831
        }
Lines 3078-3087 sub GetRenewCount { Link Here
3078
    $renewcount = $data->{'renewals'} if $data->{'renewals'};
3021
    $renewcount = $data->{'renewals'} if $data->{'renewals'};
3079
    # $item and $borrower should be calculated
3022
    # $item and $borrower should be calculated
3080
    my $branchcode = _GetCircControlBranch($item, $borrower);
3023
    my $branchcode = _GetCircControlBranch($item, $borrower);
3081
    
3024
3082
    my $issuingrule = GetIssuingRule($borrower->{categorycode}, $item->{itype}, $branchcode);
3025
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $borrower->{categorycode}, itemtype => $item->{itype}, branchcode => $branchcode });
3083
    
3026
3084
    $renewsallowed = $issuingrule->{'renewalsallowed'};
3027
    $renewsallowed = $issuing_rule ? $issuing_rule->renewalsallowed : undef; # FIXME Just replace undef with 0 to get what we expected. But what about the side-effects? TODO LATER
3085
    $renewsleft    = $renewsallowed - $renewcount;
3028
    $renewsleft    = $renewsallowed - $renewcount;
3086
    if($renewsleft < 0){ $renewsleft = 0; }
3029
    if($renewsleft < 0){ $renewsleft = 0; }
3087
    return ( $renewcount, $renewsallowed, $renewsleft );
3030
    return ( $renewcount, $renewsallowed, $renewsleft );
Lines 3119-3139 sub GetSoonestRenewDate { Link Here
3119
      or return;
3062
      or return;
3120
3063
3121
    my $branchcode = _GetCircControlBranch( $item, $borrower );
3064
    my $branchcode = _GetCircControlBranch( $item, $borrower );
3122
    my $issuingrule =
3065
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $borrower->{categorycode}, itemtype => $item->{itype}, branchcode => $branchcode });
3123
      GetIssuingRule( $borrower->{categorycode}, $item->{itype}, $branchcode );
3124
3066
3125
    my $now = dt_from_string;
3067
    my $now = dt_from_string;
3068
    return $now unless $issuing_rule;
3126
3069
3127
    if ( defined $issuingrule->{norenewalbefore}
3070
    if ( defined $issuing_rule->norenewalbefore
3128
        and $issuingrule->{norenewalbefore} ne "" )
3071
        and $issuing_rule->norenewalbefore ne "" )
3129
    {
3072
    {
3130
        my $soonestrenewal =
3073
        my $soonestrenewal =
3131
          $itemissue->{date_due}->clone()
3074
          $itemissue->{date_due}->clone()
3132
          ->subtract(
3075
          ->subtract(
3133
            $issuingrule->{lengthunit} => $issuingrule->{norenewalbefore} );
3076
            $issuing_rule->lengthunit => $issuing_rule->norenewalbefore );
3134
3077
3135
        if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
3078
        if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
3136
            and $issuingrule->{lengthunit} eq 'days' )
3079
            and $issuing_rule->lengthunit eq 'days' )
3137
        {
3080
        {
3138
            $soonestrenewal->truncate( to => 'day' );
3081
            $soonestrenewal->truncate( to => 'day' );
3139
        }
3082
        }
Lines 3174-3190 sub GetLatestAutoRenewDate { Link Here
3174
      or return;
3117
      or return;
3175
3118
3176
    my $branchcode = _GetCircControlBranch( $item, $borrower );
3119
    my $branchcode = _GetCircControlBranch( $item, $borrower );
3177
    my $issuingrule =
3120
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $borrower->{categorycode}, itemtype => $item->{itype}, branchcode => $branchcode });
3178
      GetIssuingRule( $borrower->{categorycode}, $item->{itype}, $branchcode );
3179
3180
    my $now = dt_from_string;
3181
3121
3182
    return if not $issuingrule->{no_auto_renewal_after}
3122
    return unless $issuing_rule;
3183
               or $issuingrule->{no_auto_renewal_after} eq '';
3123
    return if not $issuing_rule->no_auto_renewal_after
3124
               or $issuing_rule->no_auto_renewal_after eq '';
3184
3125
3185
    my $maximum_renewal_date = dt_from_string($itemissue->{issuedate});
3126
    my $maximum_renewal_date = dt_from_string($itemissue->{issuedate});
3186
    $maximum_renewal_date->add(
3127
    $maximum_renewal_date->add(
3187
        $issuingrule->{lengthunit} => $issuingrule->{no_auto_renewal_after}
3128
        $issuing_rule->lengthunit => $issuing_rule->no_auto_renewal_after
3188
    );
3129
    );
3189
3130
3190
    return $maximum_renewal_date;
3131
    return $maximum_renewal_date;
(-)a/C4/Overdues.pm (-15 / +15 lines)
Lines 36-41 use C4::Debug; Link Here
36
use Koha::DateUtils;
36
use Koha::DateUtils;
37
use Koha::Account::Line;
37
use Koha::Account::Line;
38
use Koha::Account::Lines;
38
use Koha::Account::Lines;
39
use Koha::IssuingRules;
39
use Koha::Libraries;
40
use Koha::Libraries;
40
41
41
use vars qw(@ISA @EXPORT);
42
use vars qw(@ISA @EXPORT);
Lines 74-82 BEGIN { Link Here
74
      &GetIssuesIteminfo
75
      &GetIssuesIteminfo
75
    );
76
    );
76
77
77
    # &GetIssuingRules - delete.
78
    # use C4::Circulation::GetIssuingRule instead.
79
80
    # subs to move to Biblio.pm
78
    # subs to move to Biblio.pm
81
    push @EXPORT, qw(
79
    push @EXPORT, qw(
82
      &GetItems
80
      &GetItems
Lines 251-276 sub CalcFine { Link Here
251
    my $start_date = $due_dt->clone();
249
    my $start_date = $due_dt->clone();
252
    # get issuingrules (fines part will be used)
250
    # get issuingrules (fines part will be used)
253
    my $itemtype = $item->{itemtype} || $item->{itype};
251
    my $itemtype = $item->{itemtype} || $item->{itype};
254
    my $data = C4::Circulation::GetIssuingRule($bortype, $itemtype, $branchcode);
252
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $bortype, itemtype => $itemtype, branchcode => $branchcode });
255
    my $fine_unit = $data->{lengthunit};
253
256
    $fine_unit ||= 'days';
254
    return unless $issuing_rule; # If not rule exist, there is no fine
255
256
    my $fine_unit = $issuing_rule->lengthunit || 'days';
257
257
258
    my $chargeable_units = get_chargeable_units($fine_unit, $start_date, $end_date, $branchcode);
258
    my $chargeable_units = get_chargeable_units($fine_unit, $start_date, $end_date, $branchcode);
259
    my $units_minus_grace = $chargeable_units - $data->{firstremind};
259
    my $units_minus_grace = $chargeable_units - $issuing_rule->firstremind;
260
    my $amount = 0;
260
    my $amount = 0;
261
    if ( $data->{'chargeperiod'} && ( $units_minus_grace > 0 ) ) {
261
    if ( $issuing_rule->chargeperiod && ( $units_minus_grace > 0 ) ) {
262
        my $units = C4::Context->preference('FinesIncludeGracePeriod') ? $chargeable_units : $units_minus_grace;
262
        my $units = C4::Context->preference('FinesIncludeGracePeriod') ? $chargeable_units : $units_minus_grace;
263
        my $charge_periods = $units / $data->{'chargeperiod'};
263
        my $charge_periods = $units / $issuing_rule->chargeperiod;
264
        # If chargeperiod_charge_at = 1, we charge a fine at the start of each charge period
264
        # If chargeperiod_charge_at = 1, we charge a fine at the start of each charge period
265
        # if chargeperiod_charge_at = 0, we charge at the end of each charge period
265
        # if chargeperiod_charge_at = 0, we charge at the end of each charge period
266
        $charge_periods = $data->{'chargeperiod_charge_at'} == 1 ? ceil($charge_periods) : floor($charge_periods);
266
        $charge_periods = $issuing_rule->chargeperiod_charge_at == 1 ? ceil($charge_periods) : floor($charge_periods);
267
        $amount = $charge_periods * $data->{'fine'};
267
        $amount = $charge_periods * $issuing_rule->fine;
268
    } # else { # a zero (or null) chargeperiod or negative units_minus_grace value means no charge. }
268
    } # else { # a zero (or null) chargeperiod or negative units_minus_grace value means no charge. }
269
269
270
    $amount = $data->{overduefinescap} if $data->{overduefinescap} && $amount > $data->{overduefinescap};
270
    $amount = $issuing_rule->overduefinescap if $issuing_rule->overduefinescap && $amount > $issuing_rule->overduefinescap;
271
    $amount = $item->{replacementprice} if ( $data->{cap_fine_to_replacement_price} && $item->{replacementprice} && $amount > $item->{replacementprice} );
271
    $amount = $item->{replacementprice} if ( $issuing_rule->cap_fine_to_replacement_price && $item->{replacementprice} && $amount > $item->{replacementprice} );
272
    $debug and warn sprintf("CalcFine returning (%s, %s, %s, %s)", $amount, $data->{'chargename'}, $units_minus_grace, $chargeable_units);
272
    $debug and warn sprintf("CalcFine returning (%s, %s, %s, %s)", $amount, $issuing_rule->chargename, $units_minus_grace, $chargeable_units);
273
    return ($amount, $data->{'chargename'}, $units_minus_grace, $chargeable_units);
273
    return ($amount, $issuing_rule->chargename, $units_minus_grace, $chargeable_units);
274
    # FIXME: chargename is NEVER populated anywhere.
274
    # FIXME: chargename is NEVER populated anywhere.
275
}
275
}
276
276
(-)a/C4/Reserves.pm (-2 / +3 lines)
Lines 43-48 use Koha::Hold; Link Here
43
use Koha::Old::Hold;
43
use Koha::Old::Hold;
44
use Koha::Holds;
44
use Koha::Holds;
45
use Koha::Libraries;
45
use Koha::Libraries;
46
use Koha::IssuingRules;
46
use Koha::Items;
47
use Koha::Items;
47
use Koha::ItemTypes;
48
use Koha::ItemTypes;
48
use Koha::Patrons;
49
use Koha::Patrons;
Lines 1579-1586 sub _get_itype { Link Here
1579
sub _OnShelfHoldsAllowed {
1580
sub _OnShelfHoldsAllowed {
1580
    my ($itype,$borrowercategory,$branchcode) = @_;
1581
    my ($itype,$borrowercategory,$branchcode) = @_;
1581
1582
1582
    my $rule = C4::Circulation::GetIssuingRule($borrowercategory, $itype, $branchcode);
1583
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $borrowercategory, itemtype => $itype, branchcode => $branchcode });
1583
    return $rule->{onshelfholds};
1584
    return $issuing_rule ? $issuing_rule->onshelfholds : undef;
1584
}
1585
}
1585
1586
1586
=head2 AlterPriority
1587
=head2 AlterPriority
(-)a/Koha/Biblio.pm (-3 / +4 lines)
Lines 27-37 use Koha::Database; Link Here
27
27
28
use base qw(Koha::Object);
28
use base qw(Koha::Object);
29
29
30
use C4::Circulation qw(GetIssuingRule);
31
use Koha::Items;
30
use Koha::Items;
32
use Koha::Biblioitems;
31
use Koha::Biblioitems;
33
use Koha::ArticleRequests;
32
use Koha::ArticleRequests;
34
use Koha::ArticleRequest::Status;
33
use Koha::ArticleRequest::Status;
34
use Koha::IssuingRules;
35
35
36
=head1 NAME
36
=head1 NAME
37
37
Lines 121-129 sub article_request_type_for_bib { Link Here
121
    my $borrowertype = $borrower->categorycode;
121
    my $borrowertype = $borrower->categorycode;
122
    my $itemtype     = $self->itemtype();
122
    my $itemtype     = $self->itemtype();
123
123
124
    my $rules        = C4::Circulation::GetIssuingRule( $borrowertype, $itemtype );
124
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $borrowertype, itemtype => $itemtype });
125
125
126
    return $rules->{article_requests} || q{};
126
    return q{} unless $issuing_rule;
127
    return $issuing_rule->article_requests || q{}
127
}
128
}
128
129
129
=head3 article_request_type_for_items
130
=head3 article_request_type_for_items
(-)a/Koha/IssuingRules.pm (-6 / +84 lines)
Lines 1-6 Link Here
1
package Koha::IssuingRules;
1
package Koha::IssuingRules;
2
2
3
# Copyright Vaara-kirjastot 2015
3
# Copyright Vaara-kirjastot 2015
4
# Copyright Koha Development Team 2016
4
#
5
#
5
# This file is part of Koha.
6
# This file is part of Koha.
6
#
7
#
Lines 18-29 package Koha::IssuingRules; Link Here
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
20
use Modern::Perl;
21
use Modern::Perl;
22
21
use Koha::Database;
23
use Koha::Database;
24
25
use Koha::IssuingRule;
26
22
use base qw(Koha::Objects);
27
use base qw(Koha::Objects);
23
28
24
=head1 NAME
29
=head1 NAME
25
30
26
Koha::IssuingRules - Koha IssuingRules object set class
31
Koha::IssuingRules - Koha IssuingRule Object set class
27
32
28
=head1 API
33
=head1 API
29
34
Lines 31-36 Koha::IssuingRules - Koha IssuingRules object set class Link Here
31
36
32
=cut
37
=cut
33
38
39
sub get_effective_issuing_rule {
40
    my ( $self, $params ) = @_;
41
42
    my $default      = '*';
43
    my $categorycode = $params->{categorycode};
44
    my $itemtype     = $params->{itemtype};
45
    my $branchcode   = $params->{branchcode};
46
47
    my $rule = $self->find($params);
48
    return $rule if $rule;
49
50
    $rule = $self->find(
51
        {
52
            categorycode => $categorycode,
53
            itemtype     => $default,
54
            branchcode   => $branchcode
55
        }
56
    );
57
    return $rule if $rule;
58
59
    $rule = $self->find(
60
        {
61
            categorycode => $default,
62
            itemtype     => $itemtype,
63
            branchcode   => $branchcode
64
        }
65
    );
66
    return $rule if $rule;
67
68
    $rule = $self->find(
69
        {
70
            categorycode => $default,
71
            itemtype     => $default,
72
            branchcode   => $branchcode
73
        }
74
    );
75
    return $rule if $rule;
76
77
    $rule = $self->find(
78
        {
79
            categorycode => $categorycode,
80
            itemtype     => $itemtype,
81
            branchcode   => $default
82
        }
83
    );
84
    return $rule if $rule;
85
86
    $rule = $self->find(
87
        {
88
            categorycode => $categorycode,
89
            itemtype     => $default,
90
            branchcode   => $default
91
        }
92
    );
93
    return $rule if $rule;
94
95
    $rule = $self->find(
96
        {
97
            categorycode => $default,
98
            itemtype     => $itemtype,
99
            branchcode   => $default
100
        }
101
    );
102
    return $rule if $rule;
103
104
    $rule = $self->find(
105
        {
106
            categorycode => $default,
107
            itemtype     => $default,
108
            branchcode   => $default
109
        }
110
    );
111
    return $rule if $rule;
112
113
    return;
114
}
115
34
=head3 type
116
=head3 type
35
117
36
=cut
118
=cut
Lines 39-50 sub _type { Link Here
39
    return 'Issuingrule';
121
    return 'Issuingrule';
40
}
122
}
41
123
42
=head3 object_class
43
44
=cut
45
46
sub object_class {
124
sub object_class {
47
    return 'Koha::IssuingRule';
125
    return 'Koha::IssuingRule';
48
}
126
}
49
127
50
1;
128
1;
(-)a/Koha/Item.pm (-3 / +4 lines)
Lines 24-30 use Carp; Link Here
24
use Koha::Database;
24
use Koha::Database;
25
25
26
use C4::Context;
26
use C4::Context;
27
use C4::Circulation qw(GetIssuingRule);
27
use Koha::IssuingRules;
28
use Koha::Item::Transfer;
28
use Koha::Item::Transfer;
29
use Koha::Patrons;
29
use Koha::Patrons;
30
use Koha::Libraries;
30
use Koha::Libraries;
Lines 164-172 sub article_request_type { Link Here
164
      :                                      undef;
164
      :                                      undef;
165
    my $borrowertype = $borrower->categorycode;
165
    my $borrowertype = $borrower->categorycode;
166
    my $itemtype = $self->effective_itemtype();
166
    my $itemtype = $self->effective_itemtype();
167
    my $rules = C4::Circulation::GetIssuingRule( $borrowertype, $itemtype, $branchcode );
167
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $borrowertype, itemtype => $itemtype, branchcode => $branchcode });
168
168
169
    return $rules->{article_requests} || q{};
169
    return q{} unless $issuing_rule;
170
    return $issuing_rule->article_requests || q{}
170
}
171
}
171
172
172
=head3 type
173
=head3 type
(-)a/t/db_dependent/Circulation/Branch.t (-1 lines)
Lines 36-42 can_ok( 'C4::Circulation', qw( Link Here
36
    AddReturn
36
    AddReturn
37
    GetBranchBorrowerCircRule
37
    GetBranchBorrowerCircRule
38
    GetBranchItemRule
38
    GetBranchItemRule
39
    GetIssuingRule
40
    )
39
    )
41
);
40
);
42
41
(-)a/t/db_dependent/Circulation/GetHardDueDate.t (-7 / +12 lines)
Lines 4-9 use Modern::Perl; Link Here
4
use C4::Context;
4
use C4::Context;
5
use DateTime;
5
use DateTime;
6
use Koha::DateUtils;
6
use Koha::DateUtils;
7
use Koha::IssuingRules;
7
use Koha::Library;
8
use Koha::Library;
8
9
9
use Test::More tests => 10;
10
use Test::More tests => 10;
Lines 15-21 can_ok( Link Here
15
    'C4::Circulation',
16
    'C4::Circulation',
16
    qw(
17
    qw(
17
      GetHardDueDate
18
      GetHardDueDate
18
      GetIssuingRule
19
      GetLoanLength
19
      GetLoanLength
20
      )
20
      )
21
);
21
);
Lines 143-148 my $sampleissuingrule1 = { Link Here
143
    opacitemholds      => 'N',
143
    opacitemholds      => 'N',
144
    cap_fine_to_replacement_price => 0,
144
    cap_fine_to_replacement_price => 0,
145
    holds_per_record   => 1,
145
    holds_per_record   => 1,
146
    article_requests   => 'yes',
147
    no_auto_renewal_after => undef,
146
};
148
};
147
my $sampleissuingrule2 = {
149
my $sampleissuingrule2 = {
148
    branchcode         => $samplebranch2->{branchcode},
150
    branchcode         => $samplebranch2->{branchcode},
Lines 175-180 my $sampleissuingrule2 = { Link Here
175
    opacitemholds      => 'Y',
177
    opacitemholds      => 'Y',
176
    cap_fine_to_replacement_price => 0,
178
    cap_fine_to_replacement_price => 0,
177
    holds_per_record   => 1,
179
    holds_per_record   => 1,
180
    article_requests   => 'yes',
178
};
181
};
179
my $sampleissuingrule3 = {
182
my $sampleissuingrule3 = {
180
    branchcode         => $samplebranch1->{branchcode},
183
    branchcode         => $samplebranch1->{branchcode},
Lines 207-212 my $sampleissuingrule3 = { Link Here
207
    opacitemholds      => 'F',
210
    opacitemholds      => 'F',
208
    cap_fine_to_replacement_price => 0,
211
    cap_fine_to_replacement_price => 0,
209
    holds_per_record   => 1,
212
    holds_per_record   => 1,
213
    article_requests   => 'yes',
210
};
214
};
211
215
212
$query = 'INSERT INTO issuingrules (
216
$query = 'INSERT INTO issuingrules (
Lines 238-245 $query = 'INSERT INTO issuingrules ( Link Here
238
                maxsuspensiondays,
242
                maxsuspensiondays,
239
                onshelfholds,
243
                onshelfholds,
240
                opacitemholds,
244
                opacitemholds,
241
                cap_fine_to_replacement_price
245
                cap_fine_to_replacement_price,
242
                ) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)';
246
                article_requests
247
                ) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)';
243
my $sth = $dbh->prepare($query);
248
my $sth = $dbh->prepare($query);
244
$sth->execute(
249
$sth->execute(
245
    $sampleissuingrule1->{branchcode},
250
    $sampleissuingrule1->{branchcode},
Lines 271-276 $sth->execute( Link Here
271
    $sampleissuingrule1->{onshelfholds},
276
    $sampleissuingrule1->{onshelfholds},
272
    $sampleissuingrule1->{opacitemholds},
277
    $sampleissuingrule1->{opacitemholds},
273
    $sampleissuingrule1->{cap_fine_to_replacement_price},
278
    $sampleissuingrule1->{cap_fine_to_replacement_price},
279
    $sampleissuingrule1->{article_requests},
274
);
280
);
275
$sth->execute(
281
$sth->execute(
276
    $sampleissuingrule2->{branchcode},
282
    $sampleissuingrule2->{branchcode},
Lines 302-307 $sth->execute( Link Here
302
    $sampleissuingrule2->{onshelfholds},
308
    $sampleissuingrule2->{onshelfholds},
303
    $sampleissuingrule2->{opacitemholds},
309
    $sampleissuingrule2->{opacitemholds},
304
    $sampleissuingrule2->{cap_fine_to_replacement_price},
310
    $sampleissuingrule2->{cap_fine_to_replacement_price},
311
    $sampleissuingrule2->{article_requests},
305
);
312
);
306
$sth->execute(
313
$sth->execute(
307
    $sampleissuingrule3->{branchcode},
314
    $sampleissuingrule3->{branchcode},
Lines 333-345 $sth->execute( Link Here
333
    $sampleissuingrule3->{onshelfholds},
340
    $sampleissuingrule3->{onshelfholds},
334
    $sampleissuingrule3->{opacitemholds},
341
    $sampleissuingrule3->{opacitemholds},
335
    $sampleissuingrule3->{cap_fine_to_replacement_price},
342
    $sampleissuingrule3->{cap_fine_to_replacement_price},
343
    $sampleissuingrule3->{article_requests},
336
);
344
);
337
345
338
is_deeply(
346
is_deeply(
339
    GetIssuingRule(
347
    Koha::IssuingRules->find({ categorycode => $samplecat->{categorycode}, itemtype => 'Book', branchcode => $samplebranch1->{branchcode} })->unblessed,
340
        $samplecat->{categorycode},
341
        'Book', $samplebranch1->{branchcode}
342
    ),
343
    $sampleissuingrule1,
348
    $sampleissuingrule1,
344
    "GetIssuingCharge returns issuingrule1's informations"
349
    "GetIssuingCharge returns issuingrule1's informations"
345
);
350
);
(-)a/t/db_dependent/Circulation/IssuingRules/maxsuspensiondays.t (-17 / +16 lines)
Lines 3-9 use Test::More tests => 2; Link Here
3
3
4
use MARC::Record;
4
use MARC::Record;
5
use MARC::Field;
5
use MARC::Field;
6
use Test::MockModule;
7
use C4::Context;
6
use C4::Context;
8
7
9
use C4::Biblio qw( AddBiblio );
8
use C4::Biblio qw( AddBiblio );
Lines 29-44 local $SIG{__WARN__} = sub { warn $_[0] unless $_[0] =~ /redefined/ }; Link Here
29
my $userenv->{branch} = $branchcode;
28
my $userenv->{branch} = $branchcode;
30
*C4::Context::userenv = \&Mock_userenv;
29
*C4::Context::userenv = \&Mock_userenv;
31
30
32
my $circulation_module = Test::MockModule->new('C4::Circulation');
33
34
# Test without maxsuspensiondays set
31
# Test without maxsuspensiondays set
35
$circulation_module->mock('GetIssuingRule', sub {
32
Koha::IssuingRules->search->delete;
36
        return {
33
$builder->build(
37
            firstremind => 0,
34
    {
38
            finedays => 2,
35
        source => 'Issuingrule',
39
            lengthunit => 'days',
36
        value  => {
37
            categorycode => '*',
38
            itemtype     => '*',
39
            branchcode   => '*',
40
            firstremind  => 0,
41
            finedays     => 2,
42
            lengthunit   => 'days',
40
        }
43
        }
41
});
44
    }
45
);
42
46
43
my $borrowernumber = AddMember(
47
my $borrowernumber = AddMember(
44
    firstname =>  'my firstname',
48
    firstname =>  'my firstname',
Lines 82-95 is( Link Here
82
DelDebarment( $debarments->[0]->{borrower_debarment_id} );
86
DelDebarment( $debarments->[0]->{borrower_debarment_id} );
83
87
84
# Test with maxsuspensiondays = 10 days
88
# Test with maxsuspensiondays = 10 days
85
$circulation_module->mock('GetIssuingRule', sub {
89
my $issuing_rule = Koha::IssuingRules->search->next;
86
        return {
90
$issuing_rule->maxsuspensiondays( 10 )->store;
87
            firstremind => 0,
91
88
            finedays => 2,
89
            maxsuspensiondays => 10,
90
            lengthunit => 'days',
91
        }
92
});
93
my $daysafter10 = dt_from_string->add_duration(DateTime::Duration->new(days => 10));
92
my $daysafter10 = dt_from_string->add_duration(DateTime::Duration->new(days => 10));
94
AddIssue( $borrower, $barcode, $daysago20 );
93
AddIssue( $borrower, $barcode, $daysago20 );
95
AddReturn( $barcode, $branchcode );
94
AddReturn( $barcode, $branchcode );
(-)a/t/db_dependent/Circulation/issue.t (-2 / +1 lines)
Lines 45-51 can_ok( Link Here
45
      AddReturn
45
      AddReturn
46
      GetBiblioIssues
46
      GetBiblioIssues
47
      GetIssuingCharges
47
      GetIssuingCharges
48
      GetIssuingRule
49
      GetItemIssue
48
      GetItemIssue
50
      GetItemIssues
49
      GetItemIssues
51
      GetOpenIssue
50
      GetOpenIssue
Lines 242-248 my $issue3 = C4::Circulation::AddIssue( $borrower_1, $barcode_1 ); Link Here
242
@renewcount = C4::Circulation::GetRenewCount();
241
@renewcount = C4::Circulation::GetRenewCount();
243
is_deeply(
242
is_deeply(
244
    \@renewcount,
243
    \@renewcount,
245
    [ 0, undef, 0 ], # FIXME Need to be fixed
244
    [ 0, undef, 0 ], # FIXME Need to be fixed, see FIXME in GetRenewCount
246
    "Without issuing rules and without parameter, GetRenewCount returns renewcount = 0, renewsallowed = undef, renewsleft = 0"
245
    "Without issuing rules and without parameter, GetRenewCount returns renewcount = 0, renewsallowed = undef, renewsleft = 0"
247
);
246
);
248
@renewcount = C4::Circulation::GetRenewCount(-1);
247
@renewcount = C4::Circulation::GetRenewCount(-1);
(-)a/t/db_dependent/Reserves.t (-4 / +9 lines)
Lines 551-568 ok( C4::Reserves::IsAvailableForItemLevelRequest($item, $borrower), "Reserving a Link Here
551
my $itype = C4::Reserves::_get_itype($item);
551
my $itype = C4::Reserves::_get_itype($item);
552
my $categorycode = $borrower->{categorycode};
552
my $categorycode = $borrower->{categorycode};
553
my $holdingbranch = $item->{holdingbranch};
553
my $holdingbranch = $item->{holdingbranch};
554
my $rule = C4::Circulation::GetIssuingRule($categorycode, $itype, $holdingbranch);
554
my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
555
    {
556
        categorycode => $categorycode,
557
        itemtype     => $itype,
558
        branchcode   => $holdingbranch
559
    }
560
);
555
561
556
$dbh->do(
562
$dbh->do(
557
    "UPDATE issuingrules SET onshelfholds = 1 WHERE categorycode = ? AND itemtype= ? and branchcode = ?",
563
    "UPDATE issuingrules SET onshelfholds = 1 WHERE categorycode = ? AND itemtype= ? and branchcode = ?",
558
    undef,
564
    undef,
559
    $rule->{categorycode}, $rule->{itemtype}, $rule->{branchcode}
565
    $issuing_rule->categorycode, $issuing_rule->itemtype, $issuing_rule->branchcode
560
);
566
);
561
ok( C4::Reserves::OnShelfHoldsAllowed($item, $borrower), "OnShelfHoldsAllowed() allowed" );
567
ok( C4::Reserves::OnShelfHoldsAllowed($item, $borrower), "OnShelfHoldsAllowed() allowed" );
562
$dbh->do(
568
$dbh->do(
563
    "UPDATE issuingrules SET onshelfholds = 0 WHERE categorycode = ? AND itemtype= ? and branchcode = ?",
569
    "UPDATE issuingrules SET onshelfholds = 0 WHERE categorycode = ? AND itemtype= ? and branchcode = ?",
564
    undef,
570
    undef,
565
    $rule->{categorycode}, $rule->{itemtype}, $rule->{branchcode}
571
    $issuing_rule->categorycode, $issuing_rule->itemtype, $issuing_rule->branchcode
566
);
572
);
567
ok( !C4::Reserves::OnShelfHoldsAllowed($item, $borrower), "OnShelfHoldsAllowed() disallowed" );
573
ok( !C4::Reserves::OnShelfHoldsAllowed($item, $borrower), "OnShelfHoldsAllowed() disallowed" );
568
574
569
- 

Return to bug 17599