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

(-)a/Koha/CirculationRules.pm (+3 lines)
Lines 213-218 our $RULE_KINDS = { Link Here
213
    recall_shelf_time => {
213
    recall_shelf_time => {
214
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
214
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
215
    },
215
    },
216
    holds_pickup_period => {
217
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
218
    },
216
    # Not included (deprecated?):
219
    # Not included (deprecated?):
217
    #   * accountsent
220
    #   * accountsent
218
    #   * reservecharge
221
    #   * reservecharge
(-)a/Koha/Hold.pm (+11 lines)
Lines 233-238 sub set_waiting { Link Here
233
233
234
    my $new_expiration_date = dt_from_string($self->waitingdate)->clone->add( days => $max_pickup_delay );
234
    my $new_expiration_date = dt_from_string($self->waitingdate)->clone->add( days => $max_pickup_delay );
235
235
236
    my $rule = Koha::CirculationRules->get_effective_rule({
237
        categorycode => $self->borrower->categorycode,
238
        itemtype => $self->item->effective_itemtype,
239
        branchcode => $self->branchcode,
240
        rule_name => 'holds_pickup_period',
241
    });
242
    if ( defined($rule) and $rule->rule_value ne '' ){
243
        # circulation rule overrides ReservesMaxPickUpDelay
244
        $max_pickup_delay = $rule->rule_value;
245
    }
246
236
    if ( C4::Context->preference("ExcludeHolidaysFromMaxPickUpDelay") ) {
247
    if ( C4::Context->preference("ExcludeHolidaysFromMaxPickUpDelay") ) {
237
        my $itemtype = $self->item ? $self->item->effective_itemtype : $self->biblio->itemtype;
248
        my $itemtype = $self->item ? $self->item->effective_itemtype : $self->biblio->itemtype;
238
        my $daysmode = Koha::CirculationRules->get_effective_daysmode(
249
        my $daysmode = Koha::CirculationRules->get_effective_daysmode(
(-)a/admin/smart-rules.pl (-39 / +38 lines)
Lines 298-344 elsif ($op eq 'add') { Link Here
298
    my $recall_due_date_interval = $input->param('recall_due_date_interval');
298
    my $recall_due_date_interval = $input->param('recall_due_date_interval');
299
    my $recall_overdue_fine = $input->param('recall_overdue_fine');
299
    my $recall_overdue_fine = $input->param('recall_overdue_fine');
300
    my $recall_shelf_time = $input->param('recall_shelf_time');
300
    my $recall_shelf_time = $input->param('recall_shelf_time');
301
    my $holds_pickup_period = strip_non_numeric($input->param('holds_pickup_period'));
301
302
302
    my $rules = {
303
    my $rules = {
303
        maxissueqty                      => $maxissueqty,
304
        maxissueqty                          => $maxissueqty,
304
        maxonsiteissueqty                => $maxonsiteissueqty,
305
            maxonsiteissueqty                => $maxonsiteissueqty,
305
        rentaldiscount                   => $rentaldiscount,
306
            rentaldiscount                   => $rentaldiscount,
306
        fine                             => $fine,
307
            fine                             => $fine,
307
        finedays                         => $finedays,
308
            finedays                         => $finedays,
308
        maxsuspensiondays                => $maxsuspensiondays,
309
            maxsuspensiondays                => $maxsuspensiondays,
309
        suspension_chargeperiod          => $suspension_chargeperiod,
310
            suspension_chargeperiod          => $suspension_chargeperiod,
310
        firstremind                      => $firstremind,
311
            firstremind                      => $firstremind,
311
        chargeperiod                     => $chargeperiod,
312
            chargeperiod                     => $chargeperiod,
312
        chargeperiod_charge_at           => $chargeperiod_charge_at,
313
            chargeperiod_charge_at           => $chargeperiod_charge_at,
313
        issuelength                      => $issuelength,
314
            issuelength                      => $issuelength,
314
        daysmode                         => $daysmode,
315
            daysmode                         => $daysmode,
315
        lengthunit                       => $lengthunit,
316
            lengthunit                       => $lengthunit,
316
        hardduedate                      => $hardduedate,
317
            hardduedate                      => $hardduedate,
317
        hardduedatecompare               => $hardduedatecompare,
318
            hardduedatecompare               => $hardduedatecompare,
318
        renewalsallowed                  => $renewalsallowed,
319
            renewalsallowed                  => $renewalsallowed,
319
        unseen_renewals_allowed          => $unseen_renewals_allowed,
320
            unseen_renewals_allowed          => $unseen_renewals_allowed,
320
        renewalperiod                    => $renewalperiod,
321
            renewalperiod                    => $renewalperiod,
321
        norenewalbefore                  => $norenewalbefore,
322
            norenewalbefore                  => $norenewalbefore,
322
        noautorenewalbefore              => $noautorenewalbefore,
323
            noautorenewalbefore              => $noautorenewalbefore,
323
        auto_renew                       => $auto_renew,
324
            auto_renew                       => $auto_renew,
324
        no_auto_renewal_after            => $no_auto_renewal_after,
325
            no_auto_renewal_after            => $no_auto_renewal_after,
325
        no_auto_renewal_after_hard_limit => $no_auto_renewal_after_hard_limit,
326
            no_auto_renewal_after_hard_limit => $no_auto_renewal_after_hard_limit,
326
        reservesallowed                  => $reservesallowed,
327
            onshelfholds                     => $onshelfholds,
327
        holds_per_record                 => $holds_per_record,
328
            opacitemholds                    => $opacitemholds,
328
        holds_per_day                    => $holds_per_day,
329
            overduefinescap                  => $overduefinescap,
329
        onshelfholds                     => $onshelfholds,
330
            cap_fine_to_replacement_price    => $cap_fine_to_replacement_price,
330
        opacitemholds                    => $opacitemholds,
331
            article_requests                 => $article_requests,
331
        overduefinescap                  => $overduefinescap,
332
            note                             => $note,
332
        cap_fine_to_replacement_price    => $cap_fine_to_replacement_price,
333
            decreaseloanholds                => $decreaseloanholds,
333
        article_requests                 => $article_requests,
334
            recalls_allowed                  => $recalls_allowed,
334
        note                             => $note,
335
            recalls_per_record               => $recalls_per_record,
335
        decreaseloanholds                => $decreaseloanholds,
336
            on_shelf_recalls                 => $on_shelf_recalls,
336
        recalls_allowed                  => $recalls_allowed,
337
            recall_due_date_interval         => $recall_due_date_interval,
337
        recalls_per_record               => $recalls_per_record,
338
            recall_overdue_fine              => $recall_overdue_fine,
338
        on_shelf_recalls                 => $on_shelf_recalls,
339
            recall_shelf_time                => $recall_shelf_time,
339
        recall_due_date_interval         => $recall_due_date_interval,
340
            holds_pickup_period              => $holds_pickup_period,
340
        recall_overdue_fine              => $recall_overdue_fine,
341
        recall_shelf_time                => $recall_shelf_time,
342
    };
341
    };
343
342
344
    Koha::CirculationRules->set_rules(
343
    Koha::CirculationRules->set_rules(
(-)a/installer/data/mysql/atomicupdate/bug_8367-add_holds_pickup_period_circrule.perl (+6 lines)
Line 0 Link Here
1
$DBversion = 'XXX';
2
if( CheckVersion( $DBversion ) ) {
3
    $dbh->do(q{INSERT IGNORE INTO circulation_rules (branchcode, categorycode, itemtype, rule_name, rule_value) VALUES (NULL, NULL, NULL, 'holds_pickup_period', NULL) });
4
5
    NewVersion( $DBversion, 8367, "Add holds_pickup_period circulation rule" );
6
}
(-)a/installer/onboarding.pl (+1 lines)
Lines 287-292 if ( $step == 5 ) { Link Here
287
                recall_due_date_interval         => undef,
287
                recall_due_date_interval         => undef,
288
                recall_overdue_fine              => undef,
288
                recall_overdue_fine              => undef,
289
                recall_shelf_time                => undef,
289
                recall_shelf_time                => undef,
290
                holds_pickup_period              => undef,
290
              }
291
              }
291
        };
292
        };
292
293
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt (-1 / +6 lines)
Lines 146-151 Link Here
146
                            <th>Holds per record (count)</th>
146
                            <th>Holds per record (count)</th>
147
                            <th>On shelf holds allowed</th>
147
                            <th>On shelf holds allowed</th>
148
                            <th>OPAC item level holds</th>
148
                            <th>OPAC item level holds</th>
149
                            <th>Holds pickup period (day)</th>
149
                            [% IF Koha.Preference('ArticleRequests') %]
150
                            [% IF Koha.Preference('ArticleRequests') %]
150
                            <th>Article requests</th>
151
                            <th>Article requests</th>
151
                            [% END %]
152
                            [% END %]
Lines 206-213 Link Here
206
                                    [% SET recall_due_date_interval = all_rules.$c.$i.recall_due_date_interval %]
207
                                    [% SET recall_due_date_interval = all_rules.$c.$i.recall_due_date_interval %]
207
                                    [% SET recall_overdue_fine = all_rules.$c.$i.recall_overdue_fine %]
208
                                    [% SET recall_overdue_fine = all_rules.$c.$i.recall_overdue_fine %]
208
                                    [% SET recall_shelf_time = all_rules.$c.$i.recall_shelf_time %]
209
                                    [% SET recall_shelf_time = all_rules.$c.$i.recall_shelf_time %]
210
                                    [% SET holds_pickup_period = all_rules.$c.$i.holds_pickup_period %]
209
211
210
                                    [% SET show_rule = note || maxissueqty || maxonsiteissueqty || issuelength || daysmode || lengthunit || hardduedate || hardduedatecompare || fine || chargeperiod || chargeperiod_charge_at || firstremind || overduefinescap || cap_fine_to_replacement_price || finedays || maxsuspensiondays || suspension_chargeperiod || renewalsallowed || unseenrenewalsallowed || renewalperiod || norenewalbefore || noautorenewalbefore || auto_renew || no_auto_renewal_after || no_auto_renewal_after_hard_limit || reservesallowed || holds_per_day || holds_per_record || onshelfholds || opacitemholds || article_requests || rentaldiscount || decreaseloanholds || recalls_allowed || recalls_per_record || on_shelf_recalls || recall_due_date_interval || recall_overdue_fine || recall_shelf_time %]
212
                                    [% SET show_rule = note || maxissueqty || maxonsiteissueqty || issuelength || daysmode || lengthunit || hardduedate || hardduedatecompare || fine || chargeperiod || chargeperiod_charge_at || firstremind || overduefinescap || cap_fine_to_replacement_price || finedays || maxsuspensiondays || suspension_chargeperiod || renewalsallowed || unseenrenewalsallowed || renewalperiod || norenewalbefore || noautorenewalbefore || auto_renew || no_auto_renewal_after || no_auto_renewal_after_hard_limit || reservesallowed || holds_per_day || holds_per_record || onshelfholds || opacitemholds || article_requests || rentaldiscount || decreaseloanholds || recalls_allowed || recalls_per_record || on_shelf_recalls || recall_due_date_interval || recall_overdue_fine || recall_shelf_time || holds_pickup_period %]
211
                                    [% IF show_rule %]
213
                                    [% IF show_rule %]
212
                                        [% SET row_count = row_count + 1 %]
214
                                        [% SET row_count = row_count + 1 %]
213
                                        <tr row_countd="row_[% row_count | html %]">
215
                                        <tr row_countd="row_[% row_count | html %]">
Lines 370-375 Link Here
370
                                                        <span>Don't allow</span>
372
                                                        <span>Don't allow</span>
371
                                                    [% END %]
373
                                                    [% END %]
372
                                                </td>
374
                                                </td>
375
                                                <td>[% holds_pickup_period | html %]</td>
373
                                                [% IF Koha.Preference('ArticleRequests') %]
376
                                                [% IF Koha.Preference('ArticleRequests') %]
374
                                                <td data-code="[% article_requests | html %]">
377
                                                <td data-code="[% article_requests | html %]">
375
                                                    [% IF article_requests == 'no' %]
378
                                                    [% IF article_requests == 'no' %]
Lines 519-524 Link Here
519
                                        <option value="F">Force</option>
522
                                        <option value="F">Force</option>
520
                                    </select>
523
                                    </select>
521
                                </td>
524
                                </td>
525
                                <td><input type="text" name="holds_pickup_period" id="holds_pickup_period" size="2" /></td>
522
                                [% IF Koha.Preference('ArticleRequests') %]
526
                                [% IF Koha.Preference('ArticleRequests') %]
523
                                <td>
527
                                <td>
524
                                    <select id="article_requests" name="article_requests">
528
                                    <select id="article_requests" name="article_requests">
Lines 589-594 Link Here
589
                                  <th>Holds per record (count)</th>
593
                                  <th>Holds per record (count)</th>
590
                                  <th>On shelf holds allowed</th>
594
                                  <th>On shelf holds allowed</th>
591
                                  <th>OPAC item level holds</th>
595
                                  <th>OPAC item level holds</th>
596
                                  <th>Holds pickup period (day)</th>
592
                                  [% IF Koha.Preference('ArticleRequests') %]
597
                                  [% IF Koha.Preference('ArticleRequests') %]
593
                                  <th>Article requests</th>
598
                                  <th>Article requests</th>
594
                                  [% END %]
599
                                  [% END %]
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-reserve.tt (+20 lines)
Lines 283-288 Link Here
283
                                            [% END # / UNLESS singleBranchMode %]
283
                                            [% END # / UNLESS singleBranchMode %]
284
                                        </ul>
284
                                        </ul>
285
285
286
                                        [% IF pickup_delays %]
287
                                            <p id="pickup_delay" style="display:none;">When your item is ready for pickup, you will have <span id="pickup_delay_days"></span> days to pick it up from this library.</p>
288
                                        [% END %]
289
286
                                        <a class="toggle-hold-options" id="toggle-hold-options-[% bibitemloo.biblionumber | html %]" style="display:none;" href="#">Show more options</a>
290
                                        <a class="toggle-hold-options" id="toggle-hold-options-[% bibitemloo.biblionumber | html %]" style="display:none;" href="#">Show more options</a>
287
291
288
                                        <div id="hold-options-[% bibitemloo.biblionumber | html %]" class="hold-options">
292
                                        <div id="hold-options-[% bibitemloo.biblionumber | html %]" class="hold-options">
Lines 506-511 Link Here
506
    var MSG_EMPTY_START_DATE = _("Hold start date should be filled.");
510
    var MSG_EMPTY_START_DATE = _("Hold start date should be filled.");
507
    var MSG_EMPTY_END_DATE   = _("Hold expiration date should be filled.");
511
    var MSG_EMPTY_END_DATE   = _("Hold expiration date should be filled.");
508
512
513
    function calculate_delay_days(){
514
        var selected_branch = $("#branch_1").val();
515
        [% FOREACH branchcode IN pickup_delays.keys %]
516
            var branchcode = "[% branchcode | html %]";
517
            if ( branchcode == selected_branch ) {
518
                $("#pickup_delay_days").text([% pickup_delays.$branchcode | html %]);
519
            }
520
        [% END %]
521
    }
522
509
    $(document).ready(function() {
523
    $(document).ready(function() {
510
524
511
        $(".toggle_unholdable").click(function(e){
525
        $(".toggle_unholdable").click(function(e){
Lines 513-518 Link Here
513
            $(this).parent('div').find(".unholdable").toggle();
527
            $(this).parent('div').find(".unholdable").toggle();
514
        });
528
        });
515
529
530
        calculate_delay_days();
531
        $("#pickup_delay").show();
532
        $("#branch_1").change(function(){
533
            calculate_delay_days();
534
        });
535
516
        $("#hold-request-form").preventDoubleFormSubmit();
536
        $("#hold-request-form").preventDoubleFormSubmit();
517
        var copiesRowId = null;
537
        var copiesRowId = null;
518
        var wasSpecific = false;
538
        var wasSpecific = false;
(-)a/misc/cronjobs/thirdparty/TalkingTech_itiva_outbound.pl (+11 lines)
Lines 339-344 sub GetWaitingHolds { Link Here
339
339
340
        my $waiting_date = dt_from_string( $issue->{waitingdate}, 'sql' );
340
        my $waiting_date = dt_from_string( $issue->{waitingdate}, 'sql' );
341
341
342
        my $rule = Koha::CirculationRules->get_effective_rule({
343
            categorycode => $issue->{categorycode},
344
            itemtype => $item->effective_itemtype,
345
            branchcode => $issue->{branchcode},
346
            rule_name => 'holds_pickup_period',
347
        });
348
        if ( defined($rule) and $rule->rule_value ne '' ){
349
            # circulation rule overrides ReservesMaxPickUpDelay
350
            $pickupdelay = $rule->rule_value;
351
        }
352
342
        $issue->{'date_due'} = output_pref({dt => dt_from_string($issue->{expirationdate}), dateformat => 'iso' });
353
        $issue->{'date_due'} = output_pref({dt => dt_from_string($issue->{expirationdate}), dateformat => 'iso' });
343
        $issue->{'level'} = 1;    # only one level for Hold Waiting notifications
354
        $issue->{'level'} = 1;    # only one level for Hold Waiting notifications
344
355
(-)a/opac/opac-reserve.pl (+15 lines)
Lines 626-629 if ( Link Here
626
    );
626
    );
627
}
627
}
628
628
629
my @branches = Koha::Libraries->search();
630
my %hold_pickup_delay_by_branch = ();
631
632
foreach my $branch ( @branches ) {
633
    my $rule = Koha::CirculationRules->get_effective_rule({
634
        categorycode => $patron->categorycode,
635
        branchcode => $branch->branchcode,
636
        itemtype => undef,
637
        rule_name => 'holds_pickup_period',
638
    });
639
    $hold_pickup_delay_by_branch{$branch->branchcode} = $rule->rule_value if ( $rule and $rule->rule_value );
640
}
641
642
$template->param( pickup_delays => \%hold_pickup_delay_by_branch );
643
629
output_html_with_http_headers $query, $cookie, $template->output, undef, { force_no_caching => 1 };
644
output_html_with_http_headers $query, $cookie, $template->output, undef, { force_no_caching => 1 };
(-)a/t/db_dependent/Holds/WaitingReserves.t (-2 / +67 lines)
Lines 8-14 use Koha::DateUtils qw( dt_from_string ); Link Here
8
use t::lib::Mocks;
8
use t::lib::Mocks;
9
use t::lib::TestBuilder;
9
use t::lib::TestBuilder;
10
10
11
use Test::More tests => 11;
11
use Test::More tests => 13;
12
12
13
use_ok('C4::Reserves', qw( ModReserve ModReserveAffect ));
13
use_ok('C4::Reserves', qw( ModReserve ModReserveAffect ));
14
14
Lines 63-73 my $biblio = $builder->build_sample_biblio; Link Here
63
my $biblio2 = $builder->build_sample_biblio;
63
my $biblio2 = $builder->build_sample_biblio;
64
my $biblio3 = $builder->build_sample_biblio;
64
my $biblio3 = $builder->build_sample_biblio;
65
my $biblio4 = $builder->build_sample_biblio;
65
my $biblio4 = $builder->build_sample_biblio;
66
my $biblio5 = $builder->build_sample_biblio;
67
my $biblio6 = $builder->build_sample_biblio;
66
68
67
my $item1 = $builder->build_sample_item({biblionumber => $biblio->biblionumber});
69
my $item1 = $builder->build_sample_item({biblionumber => $biblio->biblionumber});
68
my $item2 = $builder->build_sample_item({biblionumber => $biblio2->biblionumber});
70
my $item2 = $builder->build_sample_item({biblionumber => $biblio2->biblionumber});
69
my $item3 = $builder->build_sample_item({biblionumber => $biblio3->biblionumber});
71
my $item3 = $builder->build_sample_item({biblionumber => $biblio3->biblionumber});
70
my $item4 = $builder->build_sample_item({biblionumber => $biblio4->biblionumber});
72
my $item4 = $builder->build_sample_item({biblionumber => $biblio4->biblionumber});
73
my $item5 = $builder->build_sample_item({biblionumber => $biblio5->biblionumber});
74
my $item6 = $builder->build_sample_item({biblionumber => $biblio6->biblionumber});
75
76
Koha::CirculationRules->set_rules({
77
    categorycode => undef,
78
    itemtype => undef,
79
    branchcode => undef,
80
    rules => {
81
        holds_pickup_period => undef,
82
    }
83
});
71
84
72
my $today = dt_from_string();
85
my $today = dt_from_string();
73
86
Lines 199-202 ModReserveAffect( $item4->itemnumber, $patron2->{borrowernumber}, 0, $reserve4-> Link Here
199
my $r4 = Koha::Holds->find($reserve4->{reserve_id});
212
my $r4 = Koha::Holds->find($reserve4->{reserve_id});
200
is($r4->expirationdate, $requested_expiredate->ymd, 'Requested expiration date should be kept' );
213
is($r4->expirationdate, $requested_expiredate->ymd, 'Requested expiration date should be kept' );
201
214
215
Koha::CirculationRules->set_rules({
216
    categorycode => $patron1->{categorycode},
217
    itemtype => undef,
218
    branchcode => undef,
219
    rules => {
220
        holds_pickup_period => '3',
221
    }
222
});
223
t::lib::Mocks::mock_preference('ReservesMaxPickUpDelay', 7);
224
225
my $reserve5_reservedate = $today->clone;
226
my $reserve5_expirationdate = $reserve5_reservedate->add(days => 3);
227
228
my $reserve5 = $builder->build({
229
    source => 'Reserve',
230
    value => {
231
        borrowernumber => $patron1->{borrowernumber},
232
        reservedate => $reserve5_reservedate->ymd,
233
        expirationdate => undef,
234
        biblionumber => $biblio5->biblionumber,
235
        branchcode => 'LIB2',
236
        priority => 1,
237
        found => '',
238
    },
239
});
240
241
ModReserveAffect( $item5->itemnumber, $patron1->{borrowernumber});
242
my $r5 = Koha::Holds->find($reserve5->{reserve_id});
243
244
is($r5->expirationdate, $reserve5_expirationdate->ymd, 'Expiration date should be set to today + 3 based on circulation rules' );
245
246
my $reserve6_reservedate = $today->clone;
247
# add 3 days of pickup + 1 day of holiday
248
my $reserve6_expirationdate = $reserve6_reservedate->add(days => 5);
249
250
my $reserve6 = $builder->build({
251
    source => 'Reserve',
252
    value => {
253
        borrowernumber => $patron1->{borrowernumber},
254
        reservedate => $reserve6_reservedate->ymd,
255
        expirationdate => undef,
256
        biblionumber => $biblio6->biblionumber,
257
        branchcode => 'LIB1',
258
        priority => 1,
259
        found => '',
260
    },
261
});
262
263
ModReserveAffect( $item6->itemnumber, $patron1->{borrowernumber});
264
my $r6 = Koha::Holds->find($reserve6->{reserve_id});
265
266
is($r6->expirationdate, $reserve6_expirationdate->ymd, 'Expiration date should be set to today + 4 based on circulation rules and including a holiday' );
267
202
$schema->storage->txn_rollback;
268
$schema->storage->txn_rollback;
203
- 

Return to bug 8367