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

(-)a/Koha/Hold.pm (+16 lines)
Lines 291-296 sub biblio { Link Here
291
    return $self->{_biblio};
291
    return $self->{_biblio};
292
}
292
}
293
293
294
=head3 volume
295
296
Returns the related Koha::Biblio::Volume object for this hold
297
298
=cut
299
300
sub volume {
301
    my ($self) = @_;
302
303
    my $volume_rs = $self->_result->volume;
304
305
    return unless $volume_rs;
306
307
    return Koha::Biblio::Volume->_new_from_dbic($volume_rs);
308
}
309
294
=head3 item
310
=head3 item
295
311
296
Returns the related Koha::Item object for this Hold
312
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 451-457 Link Here
451
                            [% UNLESS ( multi_hold ) %]
451
                            [% UNLESS ( multi_hold ) %]
452
                                <li>
452
                                <li>
453
                                    <label for="requestany">Hold next available item </label>
453
                                    <label for="requestany">Hold next available item </label>
454
                                    [% IF force_hold_level == 'item' %]
454
                                    [% IF force_hold_level == 'item' || force_hold_level == 'volume' %]
455
                                        <input type="checkbox" id="requestany" name="request" disabled="true" />
455
                                        <input type="checkbox" id="requestany" name="request" disabled="true" />
456
                                    [% ELSIF force_hold_level == 'record' %]
456
                                    [% ELSIF force_hold_level == 'record' %]
457
                                        <input type="checkbox" id="requestany" checked="checked" value="Any" disabled="true"/>
457
                                        <input type="checkbox" id="requestany" checked="checked" value="Any" disabled="true"/>
Lines 471-476 Link Here
471
                                [% ELSE %]
471
                                [% ELSE %]
472
                                    <input type="hidden" name="holds_to_place_count" value="1" />
472
                                    <input type="hidden" name="holds_to_place_count" value="1" />
473
                                [% END %]
473
                                [% END %]
474
475
                                <!-- Volume level holds -->
476
                                [% FOREACH bibitemloo IN bibitemloop %]
477
                                    [% IF Koha.Preference('EnableVolumeHolds') && bibitemloo.volumes.count %]
478
                                        <label>
479
                                            Hold next available item from a volume
480
                                            [% IF bibitemloo.force_hold_level == 'volume' %]
481
                                                <span class="error"><i>(Required)</i></span>
482
                                            [% END %]
483
                                        </label>
484
485
                                        [% IF bibitemloo.force_hold_level == 'record' # Patron has placed a record level hold previously for this record %]
486
                                            <span class="error">
487
                                                <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i>
488
                                                Hold must be record level
489
                                            </span>
490
                                        [% ELSIF bibitemloo.force_hold_level == 'item' # Patron has placed an item level hold previously for this record %]
491
                                            <span class="error">
492
                                                <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i>
493
                                                Hold must be item level
494
                                            </span>
495
                                        [% ELSE %]
496
                                            [% FOREACH v IN bibitemloo.volumes %]
497
                                                [% IF v.items %]
498
                                                    <li>
499
                                                        <label for="volume_id">[% v.description | html %]</label>
500
                                                        <input type="radio" name="volume_id" value="[% v.id | html %]" />
501
                                                    </li>
502
                                                [% END %]
503
                                            [% END %]
504
                                        [% END %]
505
                                    [% END %]
506
                                [% END %]
507
                                <!-- /Volume level holds -->
508
474
                            [% END # /UNLESS multi_hold %]
509
                            [% END # /UNLESS multi_hold %]
475
                        </ol>
510
                        </ol>
476
511
Lines 519-524 Link Here
519
                                                <th>Item type</th>
554
                                                <th>Item type</th>
520
                                            [% END %]
555
                                            [% END %]
521
                                            <th>Barcode</th>
556
                                            <th>Barcode</th>
557
                                            [% IF Koha.Preference('EnableVolumeHolds') && bibitemloo.volumes.count %]
558
                                                <th>Volume</th>
559
                                            [% END %]
522
                                            <th>Home library</th>
560
                                            <th>Home library</th>
523
                                            <th>Last location</th>
561
                                            <th>Last location</th>
524
                                            [% IF itemdata_ccode %]
562
                                            [% IF itemdata_ccode %]
Lines 544-549 Link Here
544
                                                                <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i>
582
                                                                <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i>
545
                                                                Hold must be record level
583
                                                                Hold must be record level
546
                                                            </span>
584
                                                            </span>
585
                                                        [% ELSIF itemloo.force_hold_level == 'volume' # Patron has placed a volume level hold previously for this record %]
586
                                                            <span class="error">
587
                                                                <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i>
588
                                                                Hold must be volume level
589
                                                            </span>
547
                                                        [% ELSIF ( itemloo.available ) %]
590
                                                        [% ELSIF ( itemloo.available ) %]
548
                                                            <input type="radio" name="checkitem" value="[% itemloo.itemnumber | html %]" />
591
                                                            <input type="radio" name="checkitem" value="[% itemloo.itemnumber | html %]" />
549
                                                        [% ELSIF ( itemloo.override ) %]
592
                                                        [% ELSIF ( itemloo.override ) %]
Lines 591-596 Link Here
591
                                                    <td>
634
                                                    <td>
592
                                                        [% itemloo.barcode | html %]
635
                                                        [% itemloo.barcode | html %]
593
                                                    </td>
636
                                                    </td>
637
                                                    [% IF Koha.Preference('EnableVolumeHolds') && bibitemloo.volumes.count %]
638
                                                        <td>
639
                                                            [% itemloo.object.volume.description | html %]
640
                                                        </td>
641
                                                    [% END %]
594
                                                    <td>
642
                                                    <td>
595
                                                        [% Branches.GetName( itemloo.homebranch ) | html %]
643
                                                        [% Branches.GetName( itemloo.homebranch ) | html %]
596
                                                    </td>
644
                                                    </td>
Lines 1028-1033 Link Here
1028
                };
1076
                };
1029
                if($('input[name="checkitem"]:checked').length)
1077
                if($('input[name="checkitem"]:checked').length)
1030
                    data.item_id = $('input[name="checkitem"]:checked').val();
1078
                    data.item_id = $('input[name="checkitem"]:checked').val();
1079
                if($('input[name="volume_id"]:checked').length)
1080
                    data.volume_id = $('input[name="volume_id"]:checked').val();
1031
                if($('input[name="borrowernumber"]').length)
1081
                if($('input[name="borrowernumber"]').length)
1032
                    data.patron_id = $('input[name="borrowernumber"]').val();
1082
                    data.patron_id = $('input[name="borrowernumber"]').val();
1033
                if($('textarea[name="notes"]').length)
1083
                if($('textarea[name="notes"]').length)
Lines 1047-1058 Link Here
1047
                const count = $('input[name="holds_to_place_count"]').length?$('input[name="holds_to_place_count"]').val():1;
1097
                const count = $('input[name="holds_to_place_count"]').length?$('input[name="holds_to_place_count"]').val():1;
1048
                biblionumbers.forEach(function(biblionumber) {
1098
                biblionumbers.forEach(function(biblionumber) {
1049
                    data.biblio_id = biblionumber;
1099
                    data.biblio_id = biblionumber;
1100
                    console.log(data);
1050
                    let options = {
1101
                    let options = {
1051
                        url: $t.attr('action'),
1102
                        url: $t.attr('action'),
1052
                        method: $t.attr('method').toUpperCase(),
1103
                        method: $t.attr('method').toUpperCase(),
1053
                        contentType: 'application/json',
1104
                        contentType: 'application/json',
1054
                        data: JSON.stringify(data)
1105
                        data: JSON.stringify(data)
1055
                    };
1106
                    };
1107
                    console.log(options);
1056
                    for(let i = 0; i < count; i++) {
1108
                    for(let i = 0; i < count; i++) {
1057
                        $.ajax(options)
1109
                        $.ajax(options)
1058
                        .then(function(result) {
1110
                        .then(function(result) {
Lines 1077-1084 Link Here
1077
            });
1129
            });
1078
1130
1079
            [% UNLESS ( multi_hold ) %]
1131
            [% UNLESS ( multi_hold ) %]
1080
                $("#hold-request-form").on("submit", function(){
1132
                $("#hold-request-form [type='submit']").on("click", function(e){
1081
                    return check();
1133
                    return check(e);
1082
                });
1134
                });
1083
            [% ELSE %]
1135
            [% ELSE %]
1084
                $("#hold-request-form").on("submit", function(){
1136
                $("#hold-request-form").on("submit", function(){
Lines 1088-1094 Link Here
1088
1140
1089
        });
1141
        });
1090
1142
1091
        function check() {
1143
        function check(e) {
1092
            var msg = "";
1144
            var msg = "";
1093
            var count_reserv = 0;
1145
            var count_reserv = 0;
1094
1146
Lines 1107-1112 Link Here
1107
                }
1159
                }
1108
            }
1160
            }
1109
1161
1162
            count_reserv += $("input[name='volume_id']:checked").length;
1163
1110
            if (document.form.requestany.checked == true){
1164
            if (document.form.requestany.checked == true){
1111
                count_reserv++ ;
1165
                count_reserv++ ;
1112
            }
1166
            }
Lines 1119-1124 Link Here
1119
                $('#hold-request-form').preventDoubleFormSubmit();
1173
                $('#hold-request-form').preventDoubleFormSubmit();
1120
                return(true);
1174
                return(true);
1121
            } else {
1175
            } else {
1176
                e.preventDefault();
1122
                alert(msg);
1177
                alert(msg);
1123
                return(false);
1178
                return(false);
1124
            }
1179
            }
Lines 1171-1184 Link Here
1171
            });
1226
            });
1172
            $("#requestany").click(function() {
1227
            $("#requestany").click(function() {
1173
                if(this.checked){
1228
                if(this.checked){
1174
                    $("input[name=checkitem]").each(function() {
1229
                    $("input[name=checkitem], input[name='volume_id']").each(function() {
1175
                        $(this).prop("checked", false);
1230
                        $(this).prop("checked", false);
1176
                    });
1231
                    });
1177
                }
1232
                }
1178
            });
1233
            });
1179
            $("input[name=checkitem]").click(function() {
1234
            $("input[name=checkitem], input[name='volume_id']").click(function() {
1180
                onechecked = 0;
1235
                onechecked = 0;
1181
                $("input[name=checkitem]").each(function() {
1236
                $("input[name=checkitem], input[name='volume_id']").each(function() {
1182
                    if(this.checked){
1237
                    if(this.checked){
1183
                        onechecked = 1;
1238
                        onechecked = 1;
1184
                    }
1239
                    }
Lines 1250-1255 Link Here
1250
                [% END %]
1305
                [% END %]
1251
            [% END %]
1306
            [% END %]
1252
1307
1308
            [% IF Koha.Preference('EnableVolumeHolds') %]
1309
                $(':radio[name="volume_id"]').change(function(){
1310
                    $(':radio[name="checkitem"]').attr('checked', false);
1311
                });
1312
                $(':radio[name="checkitem"]').change(function(){
1313
                    $(':radio[name="volume_id"]').attr('checked', false);
1314
                });
1315
            [% END %]
1316
1253
        });
1317
        });
1254
    </script>
1318
    </script>
1255
[% END %]
1319
[% 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 498-503 foreach my $biblionumber (@biblionumbers) { Link Here
498
498
499
            # checking reserve
499
            # checking reserve
500
            my $item_object = Koha::Items->find( $itemnumber );
500
            my $item_object = Koha::Items->find( $itemnumber );
501
            $item->{object} = $item_object;
501
            my $holds = $item_object->current_holds;
502
            my $holds = $item_object->current_holds;
502
            if ( my $first_hold = $holds->next ) {
503
            if ( my $first_hold = $holds->next ) {
503
                my $p = Koha::Patrons->find( $first_hold->borrowernumber );
504
                my $p = Koha::Patrons->find( $first_hold->borrowernumber );
Lines 626-631 foreach my $biblionumber (@biblionumbers) { Link Here
626
        }
627
        }
627
        $template->param( hiddencount => $hiddencount);
628
        $template->param( hiddencount => $hiddencount);
628
629
630
        if ( C4::Context->preference('EnableVolumeHolds') ) {
631
            my $volumes = Koha::Biblio::Volumes->search(
632
                { biblionumber => $biblionumber } );
633
            $biblioitem->{volumes} = $volumes;
634
        }
635
629
        push @bibitemloop, $biblioitem;
636
        push @bibitemloop, $biblioitem;
630
    }
637
    }
631
638
(-)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