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 463-469 Link Here
463
                            [% UNLESS ( multi_hold ) %]
463
                            [% UNLESS ( multi_hold ) %]
464
                                <li>
464
                                <li>
465
                                    <label for="requestany">Hold next available item </label>
465
                                    <label for="requestany">Hold next available item </label>
466
                                    [% IF force_hold_level == 'item' %]
466
                                    [% IF force_hold_level == 'item' || force_hold_level == 'volume' %]
467
                                        <input type="checkbox" id="requestany" name="request" disabled="true" />
467
                                        <input type="checkbox" id="requestany" name="request" disabled="true" />
468
                                    [% ELSIF force_hold_level == 'record' %]
468
                                    [% ELSIF force_hold_level == 'record' %]
469
                                        <input type="checkbox" id="requestany" checked="checked" value="Any" disabled="true"/>
469
                                        <input type="checkbox" id="requestany" checked="checked" value="Any" disabled="true"/>
Lines 483-488 Link Here
483
                                [% ELSE %]
483
                                [% ELSE %]
484
                                    <input type="hidden" name="holds_to_place_count" value="1" />
484
                                    <input type="hidden" name="holds_to_place_count" value="1" />
485
                                [% END %]
485
                                [% END %]
486
487
                                <!-- Volume level holds -->
488
                                [% FOREACH bibitemloo IN bibitemloop %]
489
                                    [% IF Koha.Preference('EnableVolumeHolds') && bibitemloo.volumes.count %]
490
                                        <label>
491
                                            Hold next available item from a volume
492
                                            [% IF bibitemloo.force_hold_level == 'volume' %]
493
                                                <span class="error"><i>(Required)</i></span>
494
                                            [% END %]
495
                                        </label>
496
497
                                        [% IF bibitemloo.force_hold_level == 'record' # Patron has placed a record level hold previously for this record %]
498
                                            <span class="error">
499
                                                <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i>
500
                                                Hold must be record level
501
                                            </span>
502
                                        [% ELSIF bibitemloo.force_hold_level == 'item' # Patron has placed an item level hold previously for this record %]
503
                                            <span class="error">
504
                                                <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i>
505
                                                Hold must be item level
506
                                            </span>
507
                                        [% ELSE %]
508
                                            [% FOREACH v IN bibitemloo.volumes %]
509
                                                [% IF v.items %]
510
                                                    <li>
511
                                                        <label for="volume_id">[% v.description | html %]</label>
512
                                                        <input type="radio" name="volume_id" value="[% v.id | html %]" />
513
                                                    </li>
514
                                                [% END %]
515
                                            [% END %]
516
                                        [% END %]
517
                                    [% END %]
518
                                [% END %]
519
                                <!-- /Volume level holds -->
520
486
                            [% END # /UNLESS multi_hold %]
521
                            [% END # /UNLESS multi_hold %]
487
                        </ol>
522
                        </ol>
488
523
Lines 531-536 Link Here
531
                                                <th>Item type</th>
566
                                                <th>Item type</th>
532
                                            [% END %]
567
                                            [% END %]
533
                                            <th>Barcode</th>
568
                                            <th>Barcode</th>
569
                                            [% IF Koha.Preference('EnableVolumeHolds') && bibitemloo.volumes.count %]
570
                                                <th>Volume</th>
571
                                            [% END %]
534
                                            <th>Home library</th>
572
                                            <th>Home library</th>
535
                                            <th>Last location</th>
573
                                            <th>Last location</th>
536
                                            [% IF itemdata_ccode %]
574
                                            [% IF itemdata_ccode %]
Lines 556-561 Link Here
556
                                                                <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i>
594
                                                                <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i>
557
                                                                Hold must be record level
595
                                                                Hold must be record level
558
                                                            </span>
596
                                                            </span>
597
                                                        [% ELSIF itemloo.force_hold_level == 'volume' # Patron has placed a volume level hold previously for this record %]
598
                                                            <span class="error">
599
                                                                <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i>
600
                                                                Hold must be volume level
601
                                                            </span>
559
                                                        [% ELSIF ( itemloo.available ) %]
602
                                                        [% ELSIF ( itemloo.available ) %]
560
                                                            <input type="radio" name="checkitem" value="[% itemloo.itemnumber | html %]" />
603
                                                            <input type="radio" name="checkitem" value="[% itemloo.itemnumber | html %]" />
561
                                                        [% ELSIF ( itemloo.override ) %]
604
                                                        [% ELSIF ( itemloo.override ) %]
Lines 603-608 Link Here
603
                                                    <td>
646
                                                    <td>
604
                                                        [% itemloo.barcode | html %]
647
                                                        [% itemloo.barcode | html %]
605
                                                    </td>
648
                                                    </td>
649
                                                    [% IF Koha.Preference('EnableVolumeHolds') && bibitemloo.volumes.count %]
650
                                                        <td>
651
                                                            [% itemloo.object.volume.description | html %]
652
                                                        </td>
653
                                                    [% END %]
606
                                                    <td>
654
                                                    <td>
607
                                                        [% Branches.GetName( itemloo.homebranch ) | html %]
655
                                                        [% Branches.GetName( itemloo.homebranch ) | html %]
608
                                                    </td>
656
                                                    </td>
Lines 1041-1046 Link Here
1041
                };
1089
                };
1042
                if($('input[name="checkitem"]:checked').length)
1090
                if($('input[name="checkitem"]:checked').length)
1043
                    data.item_id = $('input[name="checkitem"]:checked').val();
1091
                    data.item_id = $('input[name="checkitem"]:checked').val();
1092
                if($('input[name="volume_id"]:checked').length)
1093
                    data.volume_id = $('input[name="volume_id"]:checked').val();
1044
                if($('input[name="borrowernumber"]').length)
1094
                if($('input[name="borrowernumber"]').length)
1045
                    data.patron_id = $('input[name="borrowernumber"]').val();
1095
                    data.patron_id = $('input[name="borrowernumber"]').val();
1046
                if($('textarea[name="notes"]').length)
1096
                if($('textarea[name="notes"]').length)
Lines 1060-1071 Link Here
1060
                const count = $('input[name="holds_to_place_count"]').length?$('input[name="holds_to_place_count"]').val():1;
1110
                const count = $('input[name="holds_to_place_count"]').length?$('input[name="holds_to_place_count"]').val():1;
1061
                biblionumbers.forEach(function(biblionumber) {
1111
                biblionumbers.forEach(function(biblionumber) {
1062
                    data.biblio_id = biblionumber;
1112
                    data.biblio_id = biblionumber;
1113
                    console.log(data);
1063
                    let options = {
1114
                    let options = {
1064
                        url: $t.attr('action'),
1115
                        url: $t.attr('action'),
1065
                        method: $t.attr('method').toUpperCase(),
1116
                        method: $t.attr('method').toUpperCase(),
1066
                        contentType: 'application/json',
1117
                        contentType: 'application/json',
1067
                        data: JSON.stringify(data)
1118
                        data: JSON.stringify(data)
1068
                    };
1119
                    };
1120
                    console.log(options);
1069
                    for(let i = 0; i < count; i++) {
1121
                    for(let i = 0; i < count; i++) {
1070
                        $.ajax(options)
1122
                        $.ajax(options)
1071
                        .then(function(result) {
1123
                        .then(function(result) {
Lines 1090-1097 Link Here
1090
            });
1142
            });
1091
1143
1092
            [% UNLESS ( multi_hold ) %]
1144
            [% UNLESS ( multi_hold ) %]
1093
                $("#hold-request-form").on("submit", function(){
1145
                $("#hold-request-form [type='submit']").on("click", function(e){
1094
                    return check();
1146
                    return check(e);
1095
                });
1147
                });
1096
            [% ELSE %]
1148
            [% ELSE %]
1097
                $("#hold-request-form").on("submit", function(){
1149
                $("#hold-request-form").on("submit", function(){
Lines 1101-1107 Link Here
1101
1153
1102
        });
1154
        });
1103
1155
1104
        function check() {
1156
        function check(e) {
1105
            var msg = "";
1157
            var msg = "";
1106
            var count_reserv = 0;
1158
            var count_reserv = 0;
1107
1159
Lines 1120-1125 Link Here
1120
                }
1172
                }
1121
            }
1173
            }
1122
1174
1175
            count_reserv += $("input[name='volume_id']:checked").length;
1176
1123
            if (document.form.requestany.checked == true){
1177
            if (document.form.requestany.checked == true){
1124
                count_reserv++ ;
1178
                count_reserv++ ;
1125
            }
1179
            }
Lines 1132-1137 Link Here
1132
                $('#hold-request-form').preventDoubleFormSubmit();
1186
                $('#hold-request-form').preventDoubleFormSubmit();
1133
                return(true);
1187
                return(true);
1134
            } else {
1188
            } else {
1189
                e.preventDefault();
1135
                alert(msg);
1190
                alert(msg);
1136
                return(false);
1191
                return(false);
1137
            }
1192
            }
Lines 1184-1197 Link Here
1184
            });
1239
            });
1185
            $("#requestany").click(function() {
1240
            $("#requestany").click(function() {
1186
                if(this.checked){
1241
                if(this.checked){
1187
                    $("input[name=checkitem]").each(function() {
1242
                    $("input[name=checkitem], input[name='volume_id']").each(function() {
1188
                        $(this).prop("checked", false);
1243
                        $(this).prop("checked", false);
1189
                    });
1244
                    });
1190
                }
1245
                }
1191
            });
1246
            });
1192
            $("input[name=checkitem]").click(function() {
1247
            $("input[name=checkitem], input[name='volume_id']").click(function() {
1193
                onechecked = 0;
1248
                onechecked = 0;
1194
                $("input[name=checkitem]").each(function() {
1249
                $("input[name=checkitem], input[name='volume_id']").each(function() {
1195
                    if(this.checked){
1250
                    if(this.checked){
1196
                        onechecked = 1;
1251
                        onechecked = 1;
1197
                    }
1252
                    }
Lines 1263-1268 Link Here
1263
                [% END %]
1318
                [% END %]
1264
            [% END %]
1319
            [% END %]
1265
1320
1321
            [% IF Koha.Preference('EnableVolumeHolds') %]
1322
                $(':radio[name="volume_id"]').change(function(){
1323
                    $(':radio[name="checkitem"]').attr('checked', false);
1324
                });
1325
                $(':radio[name="checkitem"]').change(function(){
1326
                    $(':radio[name="volume_id"]').attr('checked', false);
1327
                });
1328
            [% END %]
1329
1266
        });
1330
        });
1267
    </script>
1331
    </script>
1268
[% END %]
1332
[% 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 154-159 if ( $type eq 'str8' && $borrower ) { Link Here
154
                            itemnumber       => $checkitem,
155
                            itemnumber       => $checkitem,
155
                            found            => $found,
156
                            found            => $found,
156
                            itemtype         => $itemtype,
157
                            itemtype         => $itemtype,
158
                            volume_id        => $volume_id,
157
                        }
159
                        }
158
                    );
160
                    );
159
                }
161
                }
(-)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 628-633 foreach my $biblionumber (@biblionumbers) { Link Here
628
        }
629
        }
629
        $template->param( hiddencount => $hiddencount);
630
        $template->param( hiddencount => $hiddencount);
630
631
632
        if ( C4::Context->preference('EnableVolumeHolds') ) {
633
            my $volumes = Koha::Biblio::Volumes->search(
634
                { biblionumber => $biblionumber } );
635
            $biblioitem->{volumes} = $volumes;
636
        }
637
631
        push @bibitemloop, $biblioitem;
638
        push @bibitemloop, $biblioitem;
632
    }
639
    }
633
640
(-)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 59-65 subtest 'DB constraints' => sub { Link Here
59
};
60
};
60
61
61
subtest 'cancel' => sub {
62
subtest 'cancel' => sub {
62
    plan tests => 12;
63
    plan tests => 13;
63
    my $biblioitem = $builder->build_object( { class => 'Koha::Biblioitems' } );
64
    my $biblioitem = $builder->build_object( { class => 'Koha::Biblioitems' } );
64
    my $library    = $builder->build_object( { class => 'Koha::Libraries' } );
65
    my $library    = $builder->build_object( { class => 'Koha::Libraries' } );
65
    my $itemtype   = $builder->build_object( { class => 'Koha::ItemTypes', value => { rentalcharge => 0 } } );
66
    my $itemtype   = $builder->build_object( { class => 'Koha::ItemTypes', value => { rentalcharge => 0 } } );
Lines 182-187 subtest 'cancel' => sub { Link Here
182
        is( $hold_old->found, 'W', 'The found column should have been kept and a hold is cancelled' );
183
        is( $hold_old->found, 'W', 'The found column should have been kept and a hold is cancelled' );
183
    };
184
    };
184
185
186
    subtest 'Test Koha::Hold::volume' => sub {
187
        plan tests => 1;
188
        my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
189
        my $volume = $builder->build_object(
190
            {
191
                class => 'Koha::Biblio::Volumes',
192
                value => { biblionumber => $item->biblionumber }
193
            }
194
        );
195
        my $reserve_id = C4::Reserves::AddReserve(
196
            $library->branchcode, $patron->borrowernumber,
197
            $item->biblionumber,  '',
198
            1,                    undef,
199
            undef,                '',
200
            "title for fee",      $item->itemnumber,
201
            'W',                  undef,
202
            $volume->id
203
        );
204
205
        my $hold = Koha::Holds->find($reserve_id);
206
        is( $hold->volume_id, $volume->id,
207
            'Koha::Hold::volume returns the correct volume' );
208
    };
209
210
185
    subtest 'HoldsLog' => sub {
211
    subtest 'HoldsLog' => sub {
186
        plan tests => 2;
212
        plan tests => 2;
187
        my $patron = $builder->build_object({ class => 'Koha::Patrons' });
213
        my $patron = $builder->build_object({ class => 'Koha::Patrons' });
188
- 

Return to bug 24860