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

(-)a/Koha/Hold.pm (+16 lines)
Lines 351-356 sub patron { Link Here
351
    return Koha::Patron->_new_from_dbic($patron_rs);
351
    return Koha::Patron->_new_from_dbic($patron_rs);
352
}
352
}
353
353
354
=head3 volume
355
356
Returns the related Koha::Biblio::Volume object for this hold
357
358
=cut
359
360
sub volume {
361
    my ($self) = @_;
362
363
    my $volume_rs = $self->_result->volume;
364
365
    return unless $volume_rs;
366
367
    return Koha::Biblio::Volume->_new_from_dbic($volume_rs);
368
}
369
354
=head3 item
370
=head3 item
355
371
356
Returns the related Koha::Item object for this Hold
372
Returns the related Koha::Item object for this Hold
(-)a/Koha/Holds.pm (+3 lines)
Lines 86-91 sub forced_hold_level { Link Here
86
    my $item_level_count = $self->search( { itemnumber => { '!=' => undef } } )->count();
86
    my $item_level_count = $self->search( { itemnumber => { '!=' => undef } } )->count();
87
    return 'item' if $item_level_count > 0;
87
    return 'item' if $item_level_count > 0;
88
88
89
    my $volume_level_count = $self->search( { volume_id => { '!=' => undef } } )->count();
90
    return 'volume' if $volume_level_count > 0;
91
89
    my $record_level_count = $self->search( { itemnumber => undef } )->count();
92
    my $record_level_count = $self->search( { itemnumber => undef } )->count();
90
    return 'record' if $record_level_count > 0;
93
    return 'record' if $record_level_count > 0;
91
94
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/holds_table.inc (+2 lines)
Lines 167-172 Link Here
167
                    [% ELSE %]
167
                    [% ELSE %]
168
                        [% IF hold.itemtype %]
168
                        [% IF hold.itemtype %]
169
                            <em>Next available [% ItemTypes.GetDescription( hold.itemtype ) | html %] item</em>
169
                            <em>Next available [% ItemTypes.GetDescription( hold.itemtype ) | html %] item</em>
170
                        [% ELSIF hold.object.volume_id %]
171
                            <em>Next available item from volume <strong>[% hold.object.volume.description | html %]</strong></em>
170
                        [% ELSE %]
172
                        [% ELSE %]
171
                            <em>Next available</em>
173
                            <em>Next available</em>
172
                        [% END %]
174
                        [% END %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt (-7 / +73 lines)
Lines 455-461 Link Here
455
                            [% UNLESS ( multi_hold ) %]
455
                            [% UNLESS ( multi_hold ) %]
456
                                <li>
456
                                <li>
457
                                    <label for="requestany">Hold next available item </label>
457
                                    <label for="requestany">Hold next available item </label>
458
                                    [% IF force_hold_level == 'item' %]
458
                                    [% IF force_hold_level == 'item' || force_hold_level == 'volume' %]
459
                                        <input type="checkbox" id="requestany" name="request" disabled="true" />
459
                                        <input type="checkbox" id="requestany" name="request" disabled="true" />
460
                                    [% ELSIF force_hold_level == 'record' %]
460
                                    [% ELSIF force_hold_level == 'record' %]
461
                                        <input type="checkbox" id="requestany" checked="checked" value="Any" disabled="true"/>
461
                                        <input type="checkbox" id="requestany" checked="checked" value="Any" disabled="true"/>
Lines 475-480 Link Here
475
                                [% ELSE %]
475
                                [% ELSE %]
476
                                    <input type="hidden" name="holds_to_place_count" value="1" />
476
                                    <input type="hidden" name="holds_to_place_count" value="1" />
477
                                [% END %]
477
                                [% END %]
478
479
                                <!-- Volume level holds -->
480
                                [% FOREACH bibitemloo IN bibitemloop %]
481
                                    [% IF Koha.Preference('EnableVolumeHolds') && bibitemloo.volumes.count %]
482
                                        <label>
483
                                            Hold next available item from a volume
484
                                            [% IF bibitemloo.force_hold_level == 'volume' %]
485
                                                <span class="error"><i>(Required)</i></span>
486
                                            [% END %]
487
                                        </label>
488
489
                                        [% IF bibitemloo.force_hold_level == 'record' # Patron has placed a record level hold previously for this record %]
490
                                            <span class="error">
491
                                                <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i>
492
                                                Hold must be record level
493
                                            </span>
494
                                        [% ELSIF bibitemloo.force_hold_level == 'item' # Patron has placed an item level hold previously for this record %]
495
                                            <span class="error">
496
                                                <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i>
497
                                                Hold must be item level
498
                                            </span>
499
                                        [% ELSE %]
500
                                            [% FOREACH v IN bibitemloo.volumes %]
501
                                                [% IF v.items %]
502
                                                    <li>
503
                                                        <label for="volume_id">[% v.description | html %]</label>
504
                                                        <input type="radio" name="volume_id" value="[% v.id | html %]" />
505
                                                    </li>
506
                                                [% END %]
507
                                            [% END %]
508
                                        [% END %]
509
                                    [% END %]
510
                                [% END %]
511
                                <!-- /Volume level holds -->
512
478
                            [% END # /UNLESS multi_hold %]
513
                            [% END # /UNLESS multi_hold %]
479
514
480
                            <li id="non_priority_list_item">
515
                            <li id="non_priority_list_item">
Lines 529-534 Link Here
529
                                                <th>Item type</th>
564
                                                <th>Item type</th>
530
                                            [% END %]
565
                                            [% END %]
531
                                            <th>Barcode</th>
566
                                            <th>Barcode</th>
567
                                            [% IF Koha.Preference('EnableVolumeHolds') && bibitemloo.volumes.count %]
568
                                                <th>Volume</th>
569
                                            [% END %]
532
                                            <th>Home library</th>
570
                                            <th>Home library</th>
533
                                            <th>Last location</th>
571
                                            <th>Last location</th>
534
                                            [% IF itemdata_ccode %]
572
                                            [% IF itemdata_ccode %]
Lines 554-559 Link Here
554
                                                                <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i>
592
                                                                <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i>
555
                                                                Hold must be record level
593
                                                                Hold must be record level
556
                                                            </span>
594
                                                            </span>
595
                                                        [% ELSIF itemloo.force_hold_level == 'volume' # Patron has placed a volume level hold previously for this record %]
596
                                                            <span class="error">
597
                                                                <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i>
598
                                                                Hold must be volume level
599
                                                            </span>
557
                                                        [% ELSIF ( itemloo.available ) %]
600
                                                        [% ELSIF ( itemloo.available ) %]
558
                                                            <input type="radio" name="checkitem" value="[% itemloo.itemnumber | html %]" />
601
                                                            <input type="radio" name="checkitem" value="[% itemloo.itemnumber | html %]" />
559
                                                        [% ELSIF ( itemloo.override ) %]
602
                                                        [% ELSIF ( itemloo.override ) %]
Lines 601-606 Link Here
601
                                                    <td>
644
                                                    <td>
602
                                                        [% itemloo.barcode | html %]
645
                                                        [% itemloo.barcode | html %]
603
                                                    </td>
646
                                                    </td>
647
                                                    [% IF Koha.Preference('EnableVolumeHolds') && bibitemloo.volumes.count %]
648
                                                        <td>
649
                                                            [% itemloo.object.volume.description | html %]
650
                                                        </td>
651
                                                    [% END %]
604
                                                    <td>
652
                                                    <td>
605
                                                        [% Branches.GetName( itemloo.homebranch ) | html %]
653
                                                        [% Branches.GetName( itemloo.homebranch ) | html %]
606
                                                    </td>
654
                                                    </td>
Lines 1089-1094 Link Here
1089
                };
1137
                };
1090
                if($('input[name="checkitem"]:checked').length)
1138
                if($('input[name="checkitem"]:checked').length)
1091
                    data.item_id = $('input[name="checkitem"]:checked').val();
1139
                    data.item_id = $('input[name="checkitem"]:checked').val();
1140
                if($('input[name="volume_id"]:checked').length)
1141
                    data.volume_id = $('input[name="volume_id"]:checked').val();
1092
                if($('input[name="borrowernumber"]').length)
1142
                if($('input[name="borrowernumber"]').length)
1093
                    data.patron_id = $('input[name="borrowernumber"]').val();
1143
                    data.patron_id = $('input[name="borrowernumber"]').val();
1094
                if($('textarea[name="notes"]').length)
1144
                if($('textarea[name="notes"]').length)
Lines 1111-1122 Link Here
1111
                const count = $('input[name="holds_to_place_count"]').length?$('input[name="holds_to_place_count"]').val():1;
1161
                const count = $('input[name="holds_to_place_count"]').length?$('input[name="holds_to_place_count"]').val():1;
1112
                biblionumbers.forEach(function(biblionumber) {
1162
                biblionumbers.forEach(function(biblionumber) {
1113
                    data.biblio_id = biblionumber;
1163
                    data.biblio_id = biblionumber;
1164
                    console.log(data);
1114
                    let options = {
1165
                    let options = {
1115
                        url: $t.attr('action'),
1166
                        url: $t.attr('action'),
1116
                        method: $t.attr('method').toUpperCase(),
1167
                        method: $t.attr('method').toUpperCase(),
1117
                        contentType: 'application/json',
1168
                        contentType: 'application/json',
1118
                        data: JSON.stringify(data)
1169
                        data: JSON.stringify(data)
1119
                    };
1170
                    };
1171
                    console.log(options);
1120
                    for(let i = 0; i < count; i++) {
1172
                    for(let i = 0; i < count; i++) {
1121
                        $.ajax(options)
1173
                        $.ajax(options)
1122
                        .then(function(result) {
1174
                        .then(function(result) {
Lines 1141-1148 Link Here
1141
            });
1193
            });
1142
1194
1143
            [% UNLESS ( multi_hold ) %]
1195
            [% UNLESS ( multi_hold ) %]
1144
                $("#hold-request-form").on("submit", function(){
1196
                $("#hold-request-form [type='submit']").on("click", function(e){
1145
                    return check();
1197
                    return check(e);
1146
                });
1198
                });
1147
            [% ELSE %]
1199
            [% ELSE %]
1148
                $("#hold-request-form").on("submit", function(){
1200
                $("#hold-request-form").on("submit", function(){
Lines 1152-1158 Link Here
1152
1204
1153
        });
1205
        });
1154
1206
1155
        function check() {
1207
        function check(e) {
1156
            var msg = "";
1208
            var msg = "";
1157
            var count_reserv = 0;
1209
            var count_reserv = 0;
1158
1210
Lines 1171-1176 Link Here
1171
                }
1223
                }
1172
            }
1224
            }
1173
1225
1226
            count_reserv += $("input[name='volume_id']:checked").length;
1227
1174
            if (document.form.requestany.checked == true){
1228
            if (document.form.requestany.checked == true){
1175
                count_reserv++ ;
1229
                count_reserv++ ;
1176
            }
1230
            }
Lines 1183-1188 Link Here
1183
                $('#hold-request-form').preventDoubleFormSubmit();
1237
                $('#hold-request-form').preventDoubleFormSubmit();
1184
                return(true);
1238
                return(true);
1185
            } else {
1239
            } else {
1240
                e.preventDefault();
1186
                alert(msg);
1241
                alert(msg);
1187
                return(false);
1242
                return(false);
1188
            }
1243
            }
Lines 1235-1248 Link Here
1235
            });
1290
            });
1236
            $("#requestany").click(function() {
1291
            $("#requestany").click(function() {
1237
                if(this.checked){
1292
                if(this.checked){
1238
                    $("input[name=checkitem]").each(function() {
1293
                    $("input[name=checkitem], input[name='volume_id']").each(function() {
1239
                        $(this).prop("checked", false);
1294
                        $(this).prop("checked", false);
1240
                    });
1295
                    });
1241
                }
1296
                }
1242
            });
1297
            });
1243
            $("input[name=checkitem]").click(function() {
1298
            $("input[name=checkitem], input[name='volume_id']").click(function() {
1244
                onechecked = 0;
1299
                onechecked = 0;
1245
                $("input[name=checkitem]").each(function() {
1300
                $("input[name=checkitem], input[name='volume_id']").each(function() {
1246
                    if(this.checked){
1301
                    if(this.checked){
1247
                        onechecked = 1;
1302
                        onechecked = 1;
1248
                    }
1303
                    }
Lines 1342-1352 Link Here
1342
                };
1397
                };
1343
                [% END %]
1398
                [% END %]
1344
            [% END %]
1399
            [% END %]
1400
1345
            Sticky = $("#toolbar");
1401
            Sticky = $("#toolbar");
1346
            Sticky.hcSticky({
1402
            Sticky.hcSticky({
1347
                stickTo: "#existing_holds",
1403
                stickTo: "#existing_holds",
1348
                stickyClass: "floating"
1404
                stickyClass: "floating"
1349
            });
1405
            });
1406
1407
            [% IF Koha.Preference('EnableVolumeHolds') %]
1408
                $(':radio[name="volume_id"]').change(function(){
1409
                    $(':radio[name="checkitem"]').attr('checked', false);
1410
                });
1411
                $(':radio[name="checkitem"]').change(function(){
1412
                    $(':radio[name="volume_id"]').attr('checked', false);
1413
                });
1414
            [% END %]
1415
1350
        });
1416
        });
1351
    </script>
1417
    </script>
1352
[% END %]
1418
[% END %]
(-)a/reserve/placerequest.pl (+2 lines)
Lines 50-55 my @rank = $input->multi_param('rank-request'); Link Here
50
my $type           = $input->param('type');
50
my $type           = $input->param('type');
51
my $title          = $input->param('title');
51
my $title          = $input->param('title');
52
my $checkitem      = $input->param('checkitem');
52
my $checkitem      = $input->param('checkitem');
53
my $volume_id      = $input->param('volume_id');
53
my $expirationdate = $input->param('expiration_date');
54
my $expirationdate = $input->param('expiration_date');
54
my $itemtype       = $input->param('itemtype') || undef;
55
my $itemtype       = $input->param('itemtype') || undef;
55
my $non_priority   = $input->param('non_priority');
56
my $non_priority   = $input->param('non_priority');
Lines 159-164 if ( $type eq 'str8' && $borrower ) { Link Here
159
                            found            => $found,
160
                            found            => $found,
160
                            itemtype         => $itemtype,
161
                            itemtype         => $itemtype,
161
                            non_priority     => $non_priority,
162
                            non_priority     => $non_priority,
163
                            volume_id        => $volume_id,
162
                        }
164
                        }
163
                    );
165
                    );
164
                }
166
                }
(-)a/reserve/request.pl (+7 lines)
Lines 492-497 foreach my $biblionumber (@biblionumbers) { Link Here
492
492
493
            # checking reserve
493
            # checking reserve
494
            my $item_object = Koha::Items->find( $itemnumber );
494
            my $item_object = Koha::Items->find( $itemnumber );
495
            $item->{object} = $item_object;
495
            my $holds = $item_object->current_holds;
496
            my $holds = $item_object->current_holds;
496
            if ( my $first_hold = $holds->next ) {
497
            if ( my $first_hold = $holds->next ) {
497
                my $p = Koha::Patrons->find( $first_hold->borrowernumber );
498
                my $p = Koha::Patrons->find( $first_hold->borrowernumber );
Lines 620-625 foreach my $biblionumber (@biblionumbers) { Link Here
620
        }
621
        }
621
        $template->param( hiddencount => $hiddencount);
622
        $template->param( hiddencount => $hiddencount);
622
623
624
        if ( C4::Context->preference('EnableVolumeHolds') ) {
625
            my $volumes = Koha::Biblio::Volumes->search(
626
                { biblionumber => $biblionumber } );
627
            $biblioitem->{volumes} = $volumes;
628
        }
629
623
        push @bibitemloop, $biblioitem;
630
        push @bibitemloop, $biblioitem;
624
    }
631
    }
625
632
(-)a/t/db_dependent/Koha/Holds.t (-2 / +27 lines)
Lines 26-31 use C4::Reserves; Link Here
26
use Koha::AuthorisedValueCategory;
26
use Koha::AuthorisedValueCategory;
27
use Koha::Database;
27
use Koha::Database;
28
use Koha::Holds;
28
use Koha::Holds;
29
use Koha::Biblio::Volumes;
29
30
30
use t::lib::Mocks;
31
use t::lib::Mocks;
31
use t::lib::TestBuilder;
32
use t::lib::TestBuilder;
Lines 60-66 subtest 'DB constraints' => sub { Link Here
60
};
61
};
61
62
62
subtest 'cancel' => sub {
63
subtest 'cancel' => sub {
63
    plan tests => 12;
64
    plan tests => 13;
64
    my $biblioitem = $builder->build_object( { class => 'Koha::Biblioitems' } );
65
    my $biblioitem = $builder->build_object( { class => 'Koha::Biblioitems' } );
65
    my $library    = $builder->build_object( { class => 'Koha::Libraries' } );
66
    my $library    = $builder->build_object( { class => 'Koha::Libraries' } );
66
    my $itemtype   = $builder->build_object( { class => 'Koha::ItemTypes', value => { rentalcharge => 0 } } );
67
    my $itemtype   = $builder->build_object( { class => 'Koha::ItemTypes', value => { rentalcharge => 0 } } );
Lines 183-188 subtest 'cancel' => sub { Link Here
183
        is( $hold_old->found, 'W', 'The found column should have been kept and a hold is cancelled' );
184
        is( $hold_old->found, 'W', 'The found column should have been kept and a hold is cancelled' );
184
    };
185
    };
185
186
187
    subtest 'Test Koha::Hold::volume' => sub {
188
        plan tests => 1;
189
        my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
190
        my $volume = $builder->build_object(
191
            {
192
                class => 'Koha::Biblio::Volumes',
193
                value => { biblionumber => $item->biblionumber }
194
            }
195
        );
196
        my $reserve_id = C4::Reserves::AddReserve(
197
            $library->branchcode, $patron->borrowernumber,
198
            $item->biblionumber,  '',
199
            1,                    undef,
200
            undef,                '',
201
            "title for fee",      $item->itemnumber,
202
            'W',                  undef,
203
            $volume->id
204
        );
205
206
        my $hold = Koha::Holds->find($reserve_id);
207
        is( $hold->volume_id, $volume->id,
208
            'Koha::Hold::volume returns the correct volume' );
209
    };
210
211
186
    subtest 'HoldsLog' => sub {
212
    subtest 'HoldsLog' => sub {
187
        plan tests => 2;
213
        plan tests => 2;
188
        my $patron = $builder->build_object({ class => 'Koha::Patrons' });
214
        my $patron = $builder->build_object({ class => 'Koha::Patrons' });
189
- 

Return to bug 24860