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

(-)a/C4/Circulation.pm (-20 / +35 lines)
Lines 2889-2907 sub CanBookBeRenewed { Link Here
2889
        return ( 0, 'overdue');
2889
        return ( 0, 'overdue');
2890
    }
2890
    }
2891
2891
2892
    if ( $itemissue->{auto_renew}
2892
    if ( $itemissue->{auto_renew} ) {
2893
        and defined $issuingrule->{no_auto_renewal_after}
2893
        if ( defined $issuingrule->{no_auto_renewal_after}
2894
                and $issuingrule->{no_auto_renewal_after} ne "" ) {
2894
                and $issuingrule->{no_auto_renewal_after} ne "" ) {
2895
2895
            # Get issue_date and add no_auto_renewal_after
2896
        # Get issue_date and add no_auto_renewal_after
2896
            # If this is greater than today, it's too late for renewal.
2897
        # If this is greater than today, it's too late for renewal.
2897
            my $maximum_renewal_date = dt_from_string($itemissue->{issuedate});
2898
        my $maximum_renewal_date = dt_from_string($itemissue->{issuedate});
2898
            $maximum_renewal_date->add(
2899
        $maximum_renewal_date->add(
2899
                $issuingrule->{lengthunit} => $issuingrule->{no_auto_renewal_after}
2900
            $issuingrule->{lengthunit} => $issuingrule->{no_auto_renewal_after}
2900
            );
2901
        );
2901
            my $now = dt_from_string;
2902
        my $now = dt_from_string;
2902
            if ( $now >= $maximum_renewal_date ) {
2903
        if ( $now >= $maximum_renewal_date ) {
2903
                return ( 0, "auto_too_late" );
2904
            return ( 0, "auto_too_late" );
2904
            }
2905
        }
2906
        if ( defined $issuingrule->{no_auto_renewal_after_hard_limit}
2907
                      and $issuingrule->{no_auto_renewal_after_hard_limit} ne "" ) {
2908
            # If no_auto_renewal_after_hard_limit is >= today, it's also too late for renewal
2909
            if ( dt_from_string >= dt_from_string( $issuingrule->{no_auto_renewal_after_hard_limit} ) ) {
2910
                return ( 0, "auto_too_late" );
2911
            }
2905
        }
2912
        }
2906
    }
2913
    }
2907
2914
Lines 3184-3191 has the item on loan. Link Here
3184
C<$itemnumber> is the number of the item to renew.
3191
C<$itemnumber> is the number of the item to renew.
3185
3192
3186
C<$GetLatestAutoRenewDate> returns the DateTime of the latest possible
3193
C<$GetLatestAutoRenewDate> returns the DateTime of the latest possible
3187
auto renew date, based on the value "No auto renewal after" of the applicable
3194
auto renew date, based on the value "No auto renewal after" and the "No auto
3188
issuing rule.
3195
renewal after (hard limit) of the applicable issuing rule.
3189
Returns undef if there is no date specify in the circ rules or if the patron, loan,
3196
Returns undef if there is no date specify in the circ rules or if the patron, loan,
3190
or item cannot be found.
3197
or item cannot be found.
3191
3198
Lines 3209-3222 sub GetLatestAutoRenewDate { Link Here
3209
3216
3210
    my $now = dt_from_string;
3217
    my $now = dt_from_string;
3211
3218
3212
    return if not $issuingrule->{no_auto_renewal_after}
3219
    return if ( not $issuingrule->{no_auto_renewal_after} or $issuingrule->{no_auto_renewal_after} eq '' )
3213
               or $issuingrule->{no_auto_renewal_after} eq '';
3220
        and   ( not $issuingrule->{no_auto_renewal_after_hard_limit} or $issuingrule->{no_auto_renewal_after_hard_limit} eq '' );
3214
3221
3215
    my $maximum_renewal_date = dt_from_string($itemissue->{issuedate});
3216
    $maximum_renewal_date->add(
3217
        $issuingrule->{lengthunit} => $issuingrule->{no_auto_renewal_after}
3218
    );
3219
3222
3223
    my $maximum_renewal_date;
3224
    if ( $issuingrule->{no_auto_renewal_after} ) {
3225
        $maximum_renewal_date = dt_from_string($itemissue->{issuedate});
3226
        $maximum_renewal_date->add(
3227
            $issuingrule->{lengthunit} => $issuingrule->{no_auto_renewal_after}
3228
        );
3229
    }
3230
3231
    if ( $issuingrule->{no_auto_renewal_after_hard_limit} ) {
3232
        my $dt = dt_from_string( $issuingrule->{no_auto_renewal_after_hard_limit} );
3233
        $maximum_renewal_date = $dt if not $maximum_renewal_date or $maximum_renewal_date > $dt;
3234
    }
3220
    return $maximum_renewal_date;
3235
    return $maximum_renewal_date;
3221
}
3236
}
3222
3237
(-)a/admin/smart-rules.pl (+9 lines)
Lines 135-140 elsif ($op eq 'add') { Link Here
135
    my $auto_renew = $input->param('auto_renew') eq 'yes' ? 1 : 0;
135
    my $auto_renew = $input->param('auto_renew') eq 'yes' ? 1 : 0;
136
    my $no_auto_renewal_after = $input->param('no_auto_renewal_after');
136
    my $no_auto_renewal_after = $input->param('no_auto_renewal_after');
137
    $no_auto_renewal_after = undef if $no_auto_renewal_after =~ /^\s*$/;
137
    $no_auto_renewal_after = undef if $no_auto_renewal_after =~ /^\s*$/;
138
    my $no_auto_renewal_after_hard_limit = $input->param('no_auto_renewal_after_hard_limit') || undef;
139
    $no_auto_renewal_after_hard_limit = eval { dt_from_string( $input->param('no_auto_renewal_after_hard_limit') ) } if ( $no_auto_renewal_after_hard_limit );
140
    $no_auto_renewal_after_hard_limit = output_pref( { dt => $no_auto_renewal_after_hard_limit, dateonly => 1, dateformat => 'iso' } ) if ( $no_auto_renewal_after_hard_limit );
138
    my $reservesallowed  = $input->param('reservesallowed');
141
    my $reservesallowed  = $input->param('reservesallowed');
139
    my $onshelfholds     = $input->param('onshelfholds') || 0;
142
    my $onshelfholds     = $input->param('onshelfholds') || 0;
140
    $maxissueqty =~ s/\s//g;
143
    $maxissueqty =~ s/\s//g;
Lines 171-176 elsif ($op eq 'add') { Link Here
171
        norenewalbefore               => $norenewalbefore,
174
        norenewalbefore               => $norenewalbefore,
172
        auto_renew                    => $auto_renew,
175
        auto_renew                    => $auto_renew,
173
        no_auto_renewal_after         => $no_auto_renewal_after,
176
        no_auto_renewal_after         => $no_auto_renewal_after,
177
        no_auto_renewal_after_hard_limit => $no_auto_renewal_after_hard_limit,
174
        reservesallowed               => $reservesallowed,
178
        reservesallowed               => $reservesallowed,
175
        issuelength                   => $issuelength,
179
        issuelength                   => $issuelength,
176
        lengthunit                    => $lengthunit,
180
        lengthunit                    => $lengthunit,
Lines 479-484 while (my $row = $sth2->fetchrow_hashref) { Link Here
479
    } else {
483
    } else {
480
       $row->{'hardduedate'} = 0;
484
       $row->{'hardduedate'} = 0;
481
    }
485
    }
486
    if ($row->{no_auto_renewal_after_hard_limit}) {
487
       my $dt = eval { dt_from_string( $row->{no_auto_renewal_after_hard_limit} ) };
488
       $row->{no_auto_renewal_after_hard_limit} = eval { output_pref( { dt => $dt, dateonly => 1 } ) } if $dt;
489
    }
490
482
    push @row_loop, $row;
491
    push @row_loop, $row;
483
}
492
}
484
$sth->finish;
493
$sth->finish;
(-)a/installer/data/mysql/atomicupdate/bug_16344.sql (+1 lines)
Line 0 Link Here
1
ALTER TABLE issuingrules ADD COLUMN no_auto_renewal_after_hard_limit DATE DEFAULT NULL AFTER no_auto_renewal_after;
(-)a/installer/data/mysql/kohastructure.sql (+1 lines)
Lines 1207-1212 CREATE TABLE `issuingrules` ( -- circulation and fine rules Link Here
1207
  `norenewalbefore` int(4) default NULL, -- no renewal allowed until X days or hours before due date.
1207
  `norenewalbefore` int(4) default NULL, -- no renewal allowed until X days or hours before due date.
1208
  `auto_renew` BOOLEAN default FALSE, -- automatic renewal
1208
  `auto_renew` BOOLEAN default FALSE, -- automatic renewal
1209
  `no_auto_renewal_after` int(4) default NULL, -- no auto renewal allowed after X days or hours after the issue date
1209
  `no_auto_renewal_after` int(4) default NULL, -- no auto renewal allowed after X days or hours after the issue date
1210
  `no_auto_renewal_after_hard_limit` date default NULL, -- no auto renewal allowed after a given date
1210
  `reservesallowed` smallint(6) NOT NULL default "0", -- how many holds are allowed
1211
  `reservesallowed` smallint(6) NOT NULL default "0", -- how many holds are allowed
1211
  `branchcode` varchar(10) NOT NULL default '', -- the branch this rule is for (branches.branchcode)
1212
  `branchcode` varchar(10) NOT NULL default '', -- the branch this rule is for (branches.branchcode)
1212
  overduefinescap decimal(28,6) default NULL, -- the maximum amount of an overdue fine
1213
  overduefinescap decimal(28,6) default NULL, -- the maximum amount of an overdue fine
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt (+6 lines)
Lines 170-175 for="tobranch"><strong>Clone these rules to:</strong></label> <input type="hidde Link Here
170
                <th>No renewal before</th>
170
                <th>No renewal before</th>
171
                <th>Automatic renewal</th>
171
                <th>Automatic renewal</th>
172
                <th>No automatic renewal after</th>
172
                <th>No automatic renewal after</th>
173
                <th>No automatic renewal after (hard limit)</th>
173
                <th>Holds allowed (count)</th>
174
                <th>Holds allowed (count)</th>
174
                <th>On shelf holds allowed</th>
175
                <th>On shelf holds allowed</th>
175
                <th>Item level holds</th>
176
                <th>Item level holds</th>
Lines 249-254 for="tobranch"><strong>Clone these rules to:</strong></label> <input type="hidde Link Here
249
                                [% END %]
250
                                [% END %]
250
                            </td>
251
                            </td>
251
                            <td>[% rule.no_auto_renewal_after %]</td>
252
                            <td>[% rule.no_auto_renewal_after %]</td>
253
                            <td>[% rule.no_auto_renewal_after_hard_limit %]</td>
252
							<td>[% rule.reservesallowed %]</td>
254
							<td>[% rule.reservesallowed %]</td>
253
                                                        <td>[% IF rule.onshelfholds %]Yes[% ELSE %]No[% END %]</td>
255
                                                        <td>[% IF rule.onshelfholds %]Yes[% ELSE %]No[% END %]</td>
254
                                                        <td>[% IF rule.opacitemholds == 'F'%]Force[% ELSIF rule.opacitemholds == 'Y'%]Allow[% ELSE %]Don't allow[% END %]</td>
256
                                                        <td>[% IF rule.opacitemholds == 'F'%]Force[% ELSIF rule.opacitemholds == 'Y'%]Allow[% ELSE %]Don't allow[% END %]</td>
Lines 317-322 for="tobranch"><strong>Clone these rules to:</strong></label> <input type="hidde Link Here
317
                        </select>
319
                        </select>
318
                    </td>
320
                    </td>
319
                    <td><input type="text" name="no_auto_renewal_after" id="no_auto_renewal_after" size="3" /></td>
321
                    <td><input type="text" name="no_auto_renewal_after" id="no_auto_renewal_after" size="3" /></td>
322
                    <td>
323
                        <input type="text" size="10" name="no_auto_renewal_after_hard_limit" id="no_auto_renewal_after_hard_limit" value="[% no_auto_renewal_after_hard_limit %]" class="datepicker"/>
324
                        <div class="hint">[% INCLUDE 'date-format.inc' %]</div>
325
                    </td>
320
                    <td><input type="text" name="reservesallowed" id="reservesallowed" size="2" /></td>
326
                    <td><input type="text" name="reservesallowed" id="reservesallowed" size="2" /></td>
321
                    <td>
327
                    <td>
322
                        <select name="onshelfholds" id="onshelfholds">
328
                        <select name="onshelfholds" id="onshelfholds">
(-)a/t/db_dependent/Circulation.t (-8 / +39 lines)
Lines 30-36 use Koha::Database; Link Here
30
30
31
use t::lib::TestBuilder;
31
use t::lib::TestBuilder;
32
32
33
use Test::More tests => 84;
33
use Test::More tests => 85;
34
34
35
BEGIN {
35
BEGIN {
36
    use_ok('C4::Circulation');
36
    use_ok('C4::Circulation');
Lines 533-539 C4::Context->dbh->do("DELETE FROM accountlines"); Link Here
533
    );
533
    );
534
534
535
    subtest "too_late_renewal / no_auto_renewal_after" => sub {
535
    subtest "too_late_renewal / no_auto_renewal_after" => sub {
536
        plan tests => 8;
536
        plan tests => 14;
537
        my $item_to_auto_renew = $builder->build(
537
        my $item_to_auto_renew = $builder->build(
538
            {   source => 'Item',
538
            {   source => 'Item',
539
                value  => {
539
                value  => {
Lines 571-580 C4::Context->dbh->do("DELETE FROM accountlines"); Link Here
571
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
571
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
572
        is( $renewokay, 0,            'Do not renew, renewal is automatic' );
572
        is( $renewokay, 0,            'Do not renew, renewal is automatic' );
573
        is( $error,     'auto_renew', 'Cannot renew, renew is automatic' );
573
        is( $error,     'auto_renew', 'Cannot renew, renew is automatic' );
574
575
        $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 ) );
576
        ( $renewokay, $error ) =
577
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
578
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
579
        is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
580
581
        $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 ) );
582
        ( $renewokay, $error ) =
583
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
584
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
585
        is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
586
587
        $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 ) );
588
        ( $renewokay, $error ) =
589
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
590
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
591
        is( $error, 'auto_renew', 'Cannot renew, renew is automatic' );
574
    };
592
    };
575
593
576
    subtest "GetLatestAutoRenewDate" => sub {
594
    subtest "GetLatestAutoRenewDate" => sub {
577
        plan tests => 3;
595
        plan tests => 5;
578
        my $item_to_auto_renew = $builder->build(
596
        my $item_to_auto_renew = $builder->build(
579
            {   source => 'Item',
597
            {   source => 'Item',
580
                value  => {
598
                value  => {
Lines 588-610 C4::Context->dbh->do("DELETE FROM accountlines"); Link Here
588
        my $ten_days_before = dt_from_string->add( days => -10 );
606
        my $ten_days_before = dt_from_string->add( days => -10 );
589
        my $ten_days_ahead  = dt_from_string->add( days => 10 );
607
        my $ten_days_ahead  = dt_from_string->add( days => 10 );
590
        AddIssue( $renewing_borrower, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
608
        AddIssue( $renewing_borrower, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
591
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 7, no_auto_renewal_after = ""');
609
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 7, no_auto_renewal_after = "", no_auto_renewal_after_hard_limit = NULL');
592
        my $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
610
        my $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
593
        is( $latest_auto_renew_date, undef, 'GetLatestAutoRenewDate should return undef if no_auto_renewal_after is not defined' );
611
        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' );
594
        my $five_days_before = dt_from_string->add( days => -5 );
612
        my $five_days_before = dt_from_string->add( days => -5 );
595
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = 5');
613
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = 5, no_auto_renewal_after_hard_limit = NULL');
596
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
614
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
597
        is( $latest_auto_renew_date->truncate( to => 'minute' ),
615
        is( $latest_auto_renew_date->truncate( to => 'minute' ),
598
            $five_days_before->truncate( to => 'minute' ),
616
            $five_days_before->truncate( to => 'minute' ),
599
            'GetLatestAutoRenewDate should return -5 days if no_auto_renewal_after = 5 and date_due is 10 days before'
617
            'GetLatestAutoRenewDate should return -5 days if no_auto_renewal_after = 5 and date_due is 10 days before'
600
        );
618
        );
601
        my $five_days_ahead = dt_from_string->add( days => 5 );
619
        my $five_days_ahead = dt_from_string->add( days => 5 );
602
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = 15');
620
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = 15, no_auto_renewal_after_hard_limit = NULL');
603
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
621
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
604
        is( $latest_auto_renew_date->truncate( to => 'minute' ),
622
        is( $latest_auto_renew_date->truncate( to => 'minute' ),
605
            $five_days_ahead->truncate( to => 'minute' ),
623
            $five_days_ahead->truncate( to => 'minute' ),
606
            'GetLatestAutoRenewDate should return +5 days if no_auto_renewal_after = 15 and date_due is 10 days before'
624
            'GetLatestAutoRenewDate should return +5 days if no_auto_renewal_after = 15 and date_due is 10 days before'
607
        );
625
        );
626
        my $two_days_ahead = dt_from_string->add( days => 2 );
627
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = "", no_auto_renewal_after_hard_limit = ?', undef, dt_from_string->add( days => 2 ) );
628
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
629
        is( $latest_auto_renew_date->truncate( to => 'day' ),
630
            $two_days_ahead->truncate( to => 'day' ),
631
            'GetLatestAutoRenewDate should return +2 days if no_auto_renewal_after_hard_limit is defined and not no_auto_renewal_after'
632
        );
633
        $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 ) );
634
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
635
        is( $latest_auto_renew_date->truncate( to => 'day' ),
636
            $two_days_ahead->truncate( to => 'day' ),
637
            'GetLatestAutoRenewDate should return +2 days if no_auto_renewal_after_hard_limit is < no_auto_renewal_after'
638
        );
639
608
    };
640
    };
609
641
610
    # Too many renewals
642
    # Too many renewals
611
- 

Return to bug 16344