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

(-)a/Koha/Hold.pm (+16 lines)
Lines 282-287 sub biblio { Link Here
282
    return $self->{_biblio};
282
    return $self->{_biblio};
283
}
283
}
284
284
285
=head3 volume
286
287
Returns the related Koha::Biblio::Volume object for this hold
288
289
=cut
290
291
sub volume {
292
    my ($self) = @_;
293
294
    my $volume_rs = $self->_result->volume;
295
296
    return unless $volume_rs;
297
298
    return Koha::Biblio::Volume->_new_from_dbic($volume_rs);
299
}
300
285
=head3 item
301
=head3 item
286
302
287
Returns the related Koha::Item object for this Hold
303
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 163-168 Link Here
163
                    [% ELSE %]
163
                    [% ELSE %]
164
                        [% IF hold.itemtype %]
164
                        [% IF hold.itemtype %]
165
                            <i>Next available [% ItemTypes.GetDescription( hold.itemtype ) | html %] item</i>
165
                            <i>Next available [% ItemTypes.GetDescription( hold.itemtype ) | html %] item</i>
166
                        [% ELSIF hold.object.volume_id %]
167
                            <i>Next available item from volume <strong>[% hold.object.volume.description | html %]</strong></i>
166
                        [% ELSE %]
168
                        [% ELSE %]
167
                            <i>Next available</i>
169
                            <i>Next available</i>
168
                        [% END %]
170
                        [% END %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt (-7 / +71 lines)
Lines 465-471 Link Here
465
                            [% UNLESS ( multi_hold ) %]
465
                            [% UNLESS ( multi_hold ) %]
466
                                <li>
466
                                <li>
467
                                    <label for="requestany">Hold next available item </label>
467
                                    <label for="requestany">Hold next available item </label>
468
                                    [% IF force_hold_level == 'item' %]
468
                                    [% IF force_hold_level == 'item' || force_hold_level == 'volume' %]
469
                                        <input type="checkbox" id="requestany" name="request" disabled="true" />
469
                                        <input type="checkbox" id="requestany" name="request" disabled="true" />
470
                                    [% ELSIF force_hold_level == 'record' %]
470
                                    [% ELSIF force_hold_level == 'record' %]
471
                                        <input type="checkbox" id="requestany" checked="checked" value="Any" disabled="true"/>
471
                                        <input type="checkbox" id="requestany" checked="checked" value="Any" disabled="true"/>
Lines 485-490 Link Here
485
                                [% ELSE %]
485
                                [% ELSE %]
486
                                    <input type="hidden" name="holds_to_place_count" value="1" />
486
                                    <input type="hidden" name="holds_to_place_count" value="1" />
487
                                [% END %]
487
                                [% END %]
488
489
                                <!-- Volume level holds -->
490
                                [% FOREACH bibitemloo IN bibitemloop %]
491
                                    [% IF Koha.Preference('EnableVolumeHolds') && bibitemloo.volumes.count %]
492
                                        <label>
493
                                            Hold next available item from a volume
494
                                            [% IF bibitemloo.force_hold_level == 'volume' %]
495
                                                <span class="error"><i>(Required)</i></span>
496
                                            [% END %]
497
                                        </label>
498
499
                                        [% IF bibitemloo.force_hold_level == 'record' # Patron has placed a record level hold previously for this record %]
500
                                            <span class="error">
501
                                                <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i>
502
                                                Hold must be record level
503
                                            </span>
504
                                        [% ELSIF bibitemloo.force_hold_level == 'item' # Patron has placed an item level hold previously for this record %]
505
                                            <span class="error">
506
                                                <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i>
507
                                                Hold must be item level
508
                                            </span>
509
                                        [% ELSE %]
510
                                            [% FOREACH v IN bibitemloo.volumes %]
511
                                                [% IF v.items %]
512
                                                    <li>
513
                                                        <label for="volume_id">[% v.description | html %]</label>
514
                                                        <input type="radio" name="volume_id" value="[% v.id | html %]" />
515
                                                    </li>
516
                                                [% END %]
517
                                            [% END %]
518
                                        [% END %]
519
                                    [% END %]
520
                                [% END %]
521
                                <!-- /Volume level holds -->
522
488
                            [% END # /UNLESS multi_hold %]
523
                            [% END # /UNLESS multi_hold %]
489
                        </ol>
524
                        </ol>
490
525
Lines 533-538 Link Here
533
                                                <th>Item type</th>
568
                                                <th>Item type</th>
534
                                            [% END %]
569
                                            [% END %]
535
                                            <th>Barcode</th>
570
                                            <th>Barcode</th>
571
                                            [% IF Koha.Preference('EnableVolumeHolds') && bibitemloo.volumes.count %]
572
                                                <th>Volume</th>
573
                                            [% END %]
536
                                            <th>Home library</th>
574
                                            <th>Home library</th>
537
                                            <th>Last location</th>
575
                                            <th>Last location</th>
538
                                            [% IF itemdata_ccode %]
576
                                            [% IF itemdata_ccode %]
Lines 558-563 Link Here
558
                                                                <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i>
596
                                                                <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i>
559
                                                                Hold must be record level
597
                                                                Hold must be record level
560
                                                            </span>
598
                                                            </span>
599
                                                        [% ELSIF itemloo.force_hold_level == 'volume' # Patron has placed a volume level hold previously for this record %]
600
                                                            <span class="error">
601
                                                                <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i>
602
                                                                Hold must be volume level
603
                                                            </span>
561
                                                        [% ELSIF ( itemloo.available ) %]
604
                                                        [% ELSIF ( itemloo.available ) %]
562
                                                            <input type="radio" name="checkitem" value="[% itemloo.itemnumber | html %]" />
605
                                                            <input type="radio" name="checkitem" value="[% itemloo.itemnumber | html %]" />
563
                                                        [% ELSIF ( itemloo.override ) %]
606
                                                        [% ELSIF ( itemloo.override ) %]
Lines 605-610 Link Here
605
                                                    <td>
648
                                                    <td>
606
                                                        [% itemloo.barcode | html %]
649
                                                        [% itemloo.barcode | html %]
607
                                                    </td>
650
                                                    </td>
651
                                                    [% IF Koha.Preference('EnableVolumeHolds') && bibitemloo.volumes.count %]
652
                                                        <td>
653
                                                            [% itemloo.object.volume.description | html %]
654
                                                        </td>
655
                                                    [% END %]
608
                                                    <td>
656
                                                    <td>
609
                                                        [% Branches.GetName( itemloo.homebranch ) | html %]
657
                                                        [% Branches.GetName( itemloo.homebranch ) | html %]
610
                                                    </td>
658
                                                    </td>
Lines 1038-1043 Link Here
1038
                };
1086
                };
1039
                if($('input[name="checkitem"]:checked').length)
1087
                if($('input[name="checkitem"]:checked').length)
1040
                    data.item_id = $('input[name="checkitem"]:checked').val();
1088
                    data.item_id = $('input[name="checkitem"]:checked').val();
1089
                if($('input[name="volume_id"]:checked').length)
1090
                    data.volume_id = $('input[name="volume_id"]:checked').val();
1041
                if($('input[name="borrowernumber"]').length)
1091
                if($('input[name="borrowernumber"]').length)
1042
                    data.patron_id = $('input[name="borrowernumber"]').val();
1092
                    data.patron_id = $('input[name="borrowernumber"]').val();
1043
                if($('textarea[name="notes"]').length)
1093
                if($('textarea[name="notes"]').length)
Lines 1057-1068 Link Here
1057
                const count = $('input[name="holds_to_place_count"]').length?$('input[name="holds_to_place_count"]').val():1;
1107
                const count = $('input[name="holds_to_place_count"]').length?$('input[name="holds_to_place_count"]').val():1;
1058
                biblionumbers.forEach(function(biblionumber) {
1108
                biblionumbers.forEach(function(biblionumber) {
1059
                    data.biblio_id = biblionumber;
1109
                    data.biblio_id = biblionumber;
1110
                    console.log(data);
1060
                    let options = {
1111
                    let options = {
1061
                        url: $t.attr('action'),
1112
                        url: $t.attr('action'),
1062
                        method: $t.attr('method').toUpperCase(),
1113
                        method: $t.attr('method').toUpperCase(),
1063
                        contentType: 'application/json',
1114
                        contentType: 'application/json',
1064
                        data: JSON.stringify(data)
1115
                        data: JSON.stringify(data)
1065
                    };
1116
                    };
1117
                    console.log(options);
1066
                    for(let i = 0; i < count; i++) {
1118
                    for(let i = 0; i < count; i++) {
1067
                        $.ajax(options)
1119
                        $.ajax(options)
1068
                        .then(function(result) {
1120
                        .then(function(result) {
Lines 1087-1094 Link Here
1087
            });
1139
            });
1088
1140
1089
            [% UNLESS ( multi_hold ) %]
1141
            [% UNLESS ( multi_hold ) %]
1090
                $("#hold-request-form").on("submit", function(){
1142
                $("#hold-request-form [type='submit']").on("click", function(e){
1091
                    return check();
1143
                    return check(e);
1092
                });
1144
                });
1093
            [% ELSE %]
1145
            [% ELSE %]
1094
                $("#hold-request-form").on("submit", function(){
1146
                $("#hold-request-form").on("submit", function(){
Lines 1098-1104 Link Here
1098
1150
1099
        });
1151
        });
1100
1152
1101
        function check() {
1153
        function check(e) {
1102
            var msg = "";
1154
            var msg = "";
1103
            var count_reserv = 0;
1155
            var count_reserv = 0;
1104
1156
Lines 1117-1122 Link Here
1117
                }
1169
                }
1118
            }
1170
            }
1119
1171
1172
            count_reserv += $("input[name='volume_id']:checked").length;
1173
1120
            if (document.form.requestany.checked == true){
1174
            if (document.form.requestany.checked == true){
1121
                count_reserv++ ;
1175
                count_reserv++ ;
1122
            }
1176
            }
Lines 1129-1134 Link Here
1129
                $('#hold-request-form').preventDoubleFormSubmit();
1183
                $('#hold-request-form').preventDoubleFormSubmit();
1130
                return(true);
1184
                return(true);
1131
            } else {
1185
            } else {
1186
                e.preventDefault();
1132
                alert(msg);
1187
                alert(msg);
1133
                return(false);
1188
                return(false);
1134
            }
1189
            }
Lines 1181-1194 Link Here
1181
            });
1236
            });
1182
            $("#requestany").click(function() {
1237
            $("#requestany").click(function() {
1183
                if(this.checked){
1238
                if(this.checked){
1184
                    $("input[name=checkitem]").each(function() {
1239
                    $("input[name=checkitem], input[name='volume_id']").each(function() {
1185
                        $(this).prop("checked", false);
1240
                        $(this).prop("checked", false);
1186
                    });
1241
                    });
1187
                }
1242
                }
1188
            });
1243
            });
1189
            $("input[name=checkitem]").click(function() {
1244
            $("input[name=checkitem], input[name='volume_id']").click(function() {
1190
                onechecked = 0;
1245
                onechecked = 0;
1191
                $("input[name=checkitem]").each(function() {
1246
                $("input[name=checkitem], input[name='volume_id']").each(function() {
1192
                    if(this.checked){
1247
                    if(this.checked){
1193
                        onechecked = 1;
1248
                        onechecked = 1;
1194
                    }
1249
                    }
Lines 1260-1265 Link Here
1260
                [% END %]
1315
                [% END %]
1261
            [% END %]
1316
            [% END %]
1262
1317
1318
            [% IF Koha.Preference('EnableVolumeHolds') %]
1319
                $(':radio[name="volume_id"]').change(function(){
1320
                    $(':radio[name="checkitem"]').attr('checked', false);                    
1321
                });
1322
                $(':radio[name="checkitem"]').change(function(){
1323
                    $(':radio[name="volume_id"]').attr('checked', false);                    
1324
                });
1325
            [% END %]
1326
1263
        });
1327
        });
1264
    </script>
1328
    </script>
1265
[% END %]
1329
[% END %]
(-)a/reserve/request.pl (+7 lines)
Lines 490-495 foreach my $biblionumber (@biblionumbers) { Link Here
490
490
491
            # checking reserve
491
            # checking reserve
492
            my $item_object = Koha::Items->find( $itemnumber );
492
            my $item_object = Koha::Items->find( $itemnumber );
493
            $item->{object} = $item_object;
493
            my $holds = $item_object->current_holds;
494
            my $holds = $item_object->current_holds;
494
            if ( my $first_hold = $holds->next ) {
495
            if ( my $first_hold = $holds->next ) {
495
                my $p = Koha::Patrons->find( $first_hold->borrowernumber );
496
                my $p = Koha::Patrons->find( $first_hold->borrowernumber );
Lines 617-622 foreach my $biblionumber (@biblionumbers) { Link Here
617
        }
618
        }
618
        $template->param( hiddencount => $hiddencount);
619
        $template->param( hiddencount => $hiddencount);
619
620
621
        if ( C4::Context->preference('EnableVolumeHolds') ) {
622
            my $volumes = Koha::Biblio::Volumes->search(
623
                { biblionumber => $biblionumber } );
624
            $biblioitem->{volumes} = $volumes;
625
        }
626
620
        push @bibitemloop, $biblioitem;
627
        push @bibitemloop, $biblioitem;
621
    }
628
    }
622
629
(-)a/t/db_dependent/Koha/Holds.t (-2 / +27 lines)
Lines 25-30 use Test::Warn; Link Here
25
use C4::Reserves;
25
use C4::Reserves;
26
use Koha::Holds;
26
use Koha::Holds;
27
use Koha::Database;
27
use Koha::Database;
28
use Koha::Biblio::Volumes;
28
29
29
use t::lib::Mocks;
30
use t::lib::Mocks;
30
use t::lib::TestBuilder;
31
use t::lib::TestBuilder;
Lines 35-41 $schema->storage->txn_begin; Link Here
35
my $builder = t::lib::TestBuilder->new;
36
my $builder = t::lib::TestBuilder->new;
36
37
37
subtest 'cancel' => sub {
38
subtest 'cancel' => sub {
38
    plan tests => 12;
39
    plan tests => 13;
39
    my $biblioitem = $builder->build_object( { class => 'Koha::Biblioitems' } );
40
    my $biblioitem = $builder->build_object( { class => 'Koha::Biblioitems' } );
40
    my $library    = $builder->build_object( { class => 'Koha::Libraries' } );
41
    my $library    = $builder->build_object( { class => 'Koha::Libraries' } );
41
    my $itemtype   = $builder->build_object( { class => 'Koha::ItemTypes', value => { rentalcharge => 0 } } );
42
    my $itemtype   = $builder->build_object( { class => 'Koha::ItemTypes', value => { rentalcharge => 0 } } );
Lines 151-156 subtest 'cancel' => sub { Link Here
151
        is( $hold_old->found, 'W', 'The found column should have been kept and a hold is cancelled' );
152
        is( $hold_old->found, 'W', 'The found column should have been kept and a hold is cancelled' );
152
    };
153
    };
153
154
155
    subtest 'Test Koha::Hold::volume' => sub {
156
        plan tests => 1;
157
        my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
158
        my $volume = $builder->build_object(
159
            {
160
                class => 'Koha::Biblio::Volumes',
161
                value => { biblionumber => $item->biblionumber }
162
            }
163
        );
164
        my $reserve_id = C4::Reserves::AddReserve(
165
            $library->branchcode, $patron->borrowernumber,
166
            $item->biblionumber,  '',
167
            1,                    undef,
168
            undef,                '',
169
            "title for fee",      $item->itemnumber,
170
            'W',                  undef,
171
            $volume->id
172
        );
173
174
        my $hold = Koha::Holds->find($reserve_id);
175
        is( $hold->volume_id, $volume->id,
176
            'Koha::Hold::volume returns the correct volume' );
177
    };
178
179
154
    subtest 'HoldsLog' => sub {
180
    subtest 'HoldsLog' => sub {
155
        plan tests => 2;
181
        plan tests => 2;
156
        my $patron = $builder->build_object({ class => 'Koha::Patrons' });
182
        my $patron = $builder->build_object({ class => 'Koha::Patrons' });
157
- 

Return to bug 24860