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

(-)a/Koha/Hold.pm (+16 lines)
Lines 293-298 sub biblio { Link Here
293
    return $self->{_biblio};
293
    return $self->{_biblio};
294
}
294
}
295
295
296
=head3 volume
297
298
Returns the related Koha::Biblio::Volume object for this hold
299
300
=cut
301
302
sub volume {
303
    my ($self) = @_;
304
305
    my $volume_rs = $self->_result->volume;
306
307
    return unless $volume_rs;
308
309
    return Koha::Biblio::Volume->_new_from_dbic($volume_rs);
310
}
311
296
=head3 item
312
=head3 item
297
313
298
Returns the related Koha::Item object for this Hold
314
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 165-170 Link Here
165
                    [% ELSE %]
165
                    [% ELSE %]
166
                        [% IF hold.itemtype %]
166
                        [% IF hold.itemtype %]
167
                            <i>Next available [% ItemTypes.GetDescription( hold.itemtype ) | html %] item</i>
167
                            <i>Next available [% ItemTypes.GetDescription( hold.itemtype ) | html %] item</i>
168
                        [% ELSIF hold.object.volume_id %]
169
                            <i>Next available item from volume <strong>[% hold.object.volume.description | html %]</strong></i>
168
                        [% ELSE %]
170
                        [% ELSE %]
169
                            <i>Next available</i>
171
                            <i>Next available</i>
170
                        [% END %]
172
                        [% 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
                        </ol>
514
                        </ol>
480
515
Lines 523-528 Link Here
523
                                                <th>Item type</th>
558
                                                <th>Item type</th>
524
                                            [% END %]
559
                                            [% END %]
525
                                            <th>Barcode</th>
560
                                            <th>Barcode</th>
561
                                            [% IF Koha.Preference('EnableVolumeHolds') && bibitemloo.volumes.count %]
562
                                                <th>Volume</th>
563
                                            [% END %]
526
                                            <th>Home library</th>
564
                                            <th>Home library</th>
527
                                            <th>Last location</th>
565
                                            <th>Last location</th>
528
                                            [% IF itemdata_ccode %]
566
                                            [% IF itemdata_ccode %]
Lines 548-553 Link Here
548
                                                                <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i>
586
                                                                <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i>
549
                                                                Hold must be record level
587
                                                                Hold must be record level
550
                                                            </span>
588
                                                            </span>
589
                                                        [% ELSIF itemloo.force_hold_level == 'volume' # Patron has placed a volume level hold previously for this record %]
590
                                                            <span class="error">
591
                                                                <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i>
592
                                                                Hold must be volume level
593
                                                            </span>
551
                                                        [% ELSIF ( itemloo.available ) %]
594
                                                        [% ELSIF ( itemloo.available ) %]
552
                                                            <input type="radio" name="checkitem" value="[% itemloo.itemnumber | html %]" />
595
                                                            <input type="radio" name="checkitem" value="[% itemloo.itemnumber | html %]" />
553
                                                        [% ELSIF ( itemloo.override ) %]
596
                                                        [% ELSIF ( itemloo.override ) %]
Lines 595-600 Link Here
595
                                                    <td>
638
                                                    <td>
596
                                                        [% itemloo.barcode | html %]
639
                                                        [% itemloo.barcode | html %]
597
                                                    </td>
640
                                                    </td>
641
                                                    [% IF Koha.Preference('EnableVolumeHolds') && bibitemloo.volumes.count %]
642
                                                        <td>
643
                                                            [% itemloo.object.volume.description | html %]
644
                                                        </td>
645
                                                    [% END %]
598
                                                    <td>
646
                                                    <td>
599
                                                        [% Branches.GetName( itemloo.homebranch ) | html %]
647
                                                        [% Branches.GetName( itemloo.homebranch ) | html %]
600
                                                    </td>
648
                                                    </td>
Lines 1082-1087 Link Here
1082
                };
1130
                };
1083
                if($('input[name="checkitem"]:checked').length)
1131
                if($('input[name="checkitem"]:checked').length)
1084
                    data.item_id = $('input[name="checkitem"]:checked').val();
1132
                    data.item_id = $('input[name="checkitem"]:checked').val();
1133
                if($('input[name="volume_id"]:checked').length)
1134
                    data.volume_id = $('input[name="volume_id"]:checked').val();
1085
                if($('input[name="borrowernumber"]').length)
1135
                if($('input[name="borrowernumber"]').length)
1086
                    data.patron_id = $('input[name="borrowernumber"]').val();
1136
                    data.patron_id = $('input[name="borrowernumber"]').val();
1087
                if($('textarea[name="notes"]').length)
1137
                if($('textarea[name="notes"]').length)
Lines 1104-1115 Link Here
1104
                const count = $('input[name="holds_to_place_count"]').length?$('input[name="holds_to_place_count"]').val():1;
1154
                const count = $('input[name="holds_to_place_count"]').length?$('input[name="holds_to_place_count"]').val():1;
1105
                biblionumbers.forEach(function(biblionumber) {
1155
                biblionumbers.forEach(function(biblionumber) {
1106
                    data.biblio_id = biblionumber;
1156
                    data.biblio_id = biblionumber;
1157
                    console.log(data);
1107
                    let options = {
1158
                    let options = {
1108
                        url: $t.attr('action'),
1159
                        url: $t.attr('action'),
1109
                        method: $t.attr('method').toUpperCase(),
1160
                        method: $t.attr('method').toUpperCase(),
1110
                        contentType: 'application/json',
1161
                        contentType: 'application/json',
1111
                        data: JSON.stringify(data)
1162
                        data: JSON.stringify(data)
1112
                    };
1163
                    };
1164
                    console.log(options);
1113
                    for(let i = 0; i < count; i++) {
1165
                    for(let i = 0; i < count; i++) {
1114
                        $.ajax(options)
1166
                        $.ajax(options)
1115
                        .then(function(result) {
1167
                        .then(function(result) {
Lines 1134-1141 Link Here
1134
            });
1186
            });
1135
1187
1136
            [% UNLESS ( multi_hold ) %]
1188
            [% UNLESS ( multi_hold ) %]
1137
                $("#hold-request-form").on("submit", function(){
1189
                $("#hold-request-form [type='submit']").on("click", function(e){
1138
                    return check();
1190
                    return check(e);
1139
                });
1191
                });
1140
            [% ELSE %]
1192
            [% ELSE %]
1141
                $("#hold-request-form").on("submit", function(){
1193
                $("#hold-request-form").on("submit", function(){
Lines 1145-1151 Link Here
1145
1197
1146
        });
1198
        });
1147
1199
1148
        function check() {
1200
        function check(e) {
1149
            var msg = "";
1201
            var msg = "";
1150
            var count_reserv = 0;
1202
            var count_reserv = 0;
1151
1203
Lines 1164-1169 Link Here
1164
                }
1216
                }
1165
            }
1217
            }
1166
1218
1219
            count_reserv += $("input[name='volume_id']:checked").length;
1220
1167
            if (document.form.requestany.checked == true){
1221
            if (document.form.requestany.checked == true){
1168
                count_reserv++ ;
1222
                count_reserv++ ;
1169
            }
1223
            }
Lines 1176-1181 Link Here
1176
                $('#hold-request-form').preventDoubleFormSubmit();
1230
                $('#hold-request-form').preventDoubleFormSubmit();
1177
                return(true);
1231
                return(true);
1178
            } else {
1232
            } else {
1233
                e.preventDefault();
1179
                alert(msg);
1234
                alert(msg);
1180
                return(false);
1235
                return(false);
1181
            }
1236
            }
Lines 1228-1241 Link Here
1228
            });
1283
            });
1229
            $("#requestany").click(function() {
1284
            $("#requestany").click(function() {
1230
                if(this.checked){
1285
                if(this.checked){
1231
                    $("input[name=checkitem]").each(function() {
1286
                    $("input[name=checkitem], input[name='volume_id']").each(function() {
1232
                        $(this).prop("checked", false);
1287
                        $(this).prop("checked", false);
1233
                    });
1288
                    });
1234
                }
1289
                }
1235
            });
1290
            });
1236
            $("input[name=checkitem]").click(function() {
1291
            $("input[name=checkitem], input[name='volume_id']").click(function() {
1237
                onechecked = 0;
1292
                onechecked = 0;
1238
                $("input[name=checkitem]").each(function() {
1293
                $("input[name=checkitem], input[name='volume_id']").each(function() {
1239
                    if(this.checked){
1294
                    if(this.checked){
1240
                        onechecked = 1;
1295
                        onechecked = 1;
1241
                    }
1296
                    }
Lines 1322-1332 Link Here
1322
                };
1377
                };
1323
                [% END %]
1378
                [% END %]
1324
            [% END %]
1379
            [% END %]
1380
1325
            Sticky = $("#toolbar");
1381
            Sticky = $("#toolbar");
1326
            Sticky.hcSticky({
1382
            Sticky.hcSticky({
1327
                stickTo: "#existing_holds",
1383
                stickTo: "#existing_holds",
1328
                stickyClass: "floating"
1384
                stickyClass: "floating"
1329
            });
1385
            });
1386
1387
            [% IF Koha.Preference('EnableVolumeHolds') %]
1388
                $(':radio[name="volume_id"]').change(function(){
1389
                    $(':radio[name="checkitem"]').attr('checked', false);
1390
                });
1391
                $(':radio[name="checkitem"]').change(function(){
1392
                    $(':radio[name="volume_id"]').attr('checked', false);
1393
                });
1394
            [% END %]
1395
1330
        });
1396
        });
1331
    </script>
1397
    </script>
1332
[% END %]
1398
[% 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
56
Lines 155-160 if ( $type eq 'str8' && $borrower ) { Link Here
155
                            itemnumber       => $checkitem,
156
                            itemnumber       => $checkitem,
156
                            found            => $found,
157
                            found            => $found,
157
                            itemtype         => $itemtype,
158
                            itemtype         => $itemtype,
159
                            volume_id        => $volume_id,
158
                        }
160
                        }
159
                    );
161
                    );
160
                }
162
                }
(-)a/reserve/request.pl (+7 lines)
Lines 499-504 foreach my $biblionumber (@biblionumbers) { Link Here
499
499
500
            # checking reserve
500
            # checking reserve
501
            my $item_object = Koha::Items->find( $itemnumber );
501
            my $item_object = Koha::Items->find( $itemnumber );
502
            $item->{object} = $item_object;
502
            my $holds = $item_object->current_holds;
503
            my $holds = $item_object->current_holds;
503
            if ( my $first_hold = $holds->next ) {
504
            if ( my $first_hold = $holds->next ) {
504
                my $p = Koha::Patrons->find( $first_hold->borrowernumber );
505
                my $p = Koha::Patrons->find( $first_hold->borrowernumber );
Lines 627-632 foreach my $biblionumber (@biblionumbers) { Link Here
627
        }
628
        }
628
        $template->param( hiddencount => $hiddencount);
629
        $template->param( hiddencount => $hiddencount);
629
630
631
        if ( C4::Context->preference('EnableVolumeHolds') ) {
632
            my $volumes = Koha::Biblio::Volumes->search(
633
                { biblionumber => $biblionumber } );
634
            $biblioitem->{volumes} = $volumes;
635
        }
636
630
        push @bibitemloop, $biblioitem;
637
        push @bibitemloop, $biblioitem;
631
    }
638
    }
632
639
(-)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