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

(-)a/Koha/Hold.pm (-4 / +29 lines)
Lines 250-255 sub move_hold { Link Here
250
    return { success => 1, hold => $self };
250
    return { success => 1, hold => $self };
251
}
251
}
252
252
253
=head3 cleanup_hold_group
254
255
$self->cleanup_hold_group;
256
257
Check if a hold group is left with a single or zero holds. Delete hold_group if so.
258
Accepts an optional $hold_group_id that, if defined, uses that instead of self->hold_group_id
259
260
=cut
261
262
sub cleanup_hold_group {
263
    my ( $self, $hold_group_id ) = @_;
264
265
    my $hold_group_id_to_check = $hold_group_id // $self->hold_group_id;
266
    my $hold_group             = Koha::HoldGroups->find($hold_group_id_to_check);
267
    return unless $hold_group;
268
269
    if ( $hold_group->holds->count <= 1 ) {
270
        $hold_group->delete();
271
    }
272
}
273
253
=head3 set_transfer
274
=head3 set_transfer
254
275
255
=cut
276
=cut
Lines 744-752 sub cancellation_requested { Link Here
744
765
745
my $cancel_hold = $hold->cancel(
766
my $cancel_hold = $hold->cancel(
746
    {
767
    {
747
        [ charge_cancel_fee   => 1||0, ]
768
        [ charge_cancel_fee       => 1||0, ]
748
        [ cancellation_reason => $cancellation_reason, ]
769
        [ cancellation_reason     => $cancellation_reason, ]
749
        [ skip_holds_queue    => 1||0 ]
770
        [ skip_holds_queue        => 1||0 ]
771
        [ skip_hold_group_cleanup => 1||0 ]
750
    }
772
    }
751
);
773
);
752
774
Lines 870-875 sub cancel { Link Here
870
        }
892
        }
871
    );
893
    );
872
894
895
    $self->cleanup_hold_group() unless $params->{skip_hold_group_cleanup};
896
873
    if ($autofill_next) {
897
    if ($autofill_next) {
874
        my ( undef, $next_hold ) = C4::Reserves::CheckReserves( $self->item );
898
        my ( undef, $next_hold ) = C4::Reserves::CheckReserves( $self->item );
875
        if ($next_hold) {
899
        if ($next_hold) {
Lines 957-965 sub fill { Link Here
957
            if ( $self->hold_group_id ) {
981
            if ( $self->hold_group_id ) {
958
                my @holds = $self->hold_group->holds->as_list;
982
                my @holds = $self->hold_group->holds->as_list;
959
                foreach my $h (@holds) {
983
                foreach my $h (@holds) {
960
                    $h->cancel unless $h->reserve_id == $self->id;
984
                    $h->cancel( { skip_hold_group_cleanup => 1 } ) unless $h->reserve_id == $self->id;
961
                }
985
                }
962
            }
986
            }
987
            $self->cleanup_hold_group();
963
988
964
            Koha::BackgroundJob::BatchUpdateBiblioHoldsQueue->new->enqueue(
989
            Koha::BackgroundJob::BatchUpdateBiblioHoldsQueue->new->enqueue(
965
                { biblio_ids => [ $old_me->biblionumber ] } )
990
                { biblio_ids => [ $old_me->biblionumber ] } )
(-)a/Koha/Patron.pm (-1 / +7 lines)
Lines 1912-1917 Creates and returns a hold group given a list of hold ids Link Here
1912
1912
1913
If force_grouped is supplied, the hold group will be created even if the holds are already grouped
1913
If force_grouped is supplied, the hold group will be created even if the holds are already grouped
1914
1914
1915
Checks if the hold is moving from another group, and if so, removes the old group if empty
1916
1915
=cut
1917
=cut
1916
1918
1917
sub create_hold_group {
1919
sub create_hold_group {
Lines 1968-1976 sub create_hold_group { Link Here
1968
        { visual_hold_group_id => $next_available_visual_hold_group_id }
1970
        { visual_hold_group_id => $next_available_visual_hold_group_id }
1969
    );
1971
    );
1970
    foreach my $hold_id (@$hold_ids) {
1972
    foreach my $hold_id (@$hold_ids) {
1971
        my $hold = Koha::Holds->find($hold_id);
1973
        my $hold                   = Koha::Holds->find($hold_id);
1974
        my $previous_hold_group_id = $hold->hold_group_id;
1972
1975
1973
        $hold->hold_group_id( $hold_group_rs->hold_group_id )->store;
1976
        $hold->hold_group_id( $hold_group_rs->hold_group_id )->store;
1977
        if ( $previous_hold_group_id && $previous_hold_group_id != $hold_group_rs->hold_group_id ) {
1978
            $hold->cleanup_hold_group($previous_hold_group_id);
1979
        }
1974
    }
1980
    }
1975
1981
1976
    return Koha::HoldGroup->_new_from_dbic($hold_group_rs);
1982
    return Koha::HoldGroup->_new_from_dbic($hold_group_rs);
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/modals/holds_table_modals.inc (+21 lines)
Lines 74-76 Link Here
74
        </div>
74
        </div>
75
    </div>
75
    </div>
76
[% END %]
76
[% END %]
77
78
[% BLOCK 'group-hold-modal' %]
79
    <div id="group-modal" class="modal" role="dialog" aria-hidden="true">
80
        <div class="modal-dialog">
81
            <div class="modal-content">
82
                <div class="modal-header">
83
                    <h1 class="modal-title" id="suspend-modal-label"> Group selected holds </h1>
84
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
85
                </div>
86
                <div class="modal-body">
87
                    <p>Are you sure you want to group the selected holds?</p>
88
                </div>
89
                <div class="modal-footer">
90
                    <button id="group-modal-submit" class="btn btn-primary" type="submit" name="submit">Group</button>
91
                    <button type="button" class="btn btn-default" data-bs-dismiss="modal">Cancel </button>
92
                </div>
93
                <div id="inputs"></div>
94
            </div>
95
        </div>
96
    </div>
97
[% END %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/patron-detail-tabs.inc (+9 lines)
Lines 150-155 Link Here
150
                            <tr>
150
                            <tr>
151
                                <th id="checkbox" data-colname="checkbox"><input type="checkbox" class="select_hold_all" /></th>
151
                                <th id="checkbox" data-colname="checkbox"><input type="checkbox" class="select_hold_all" /></th>
152
                                <th>Hold date</th>
152
                                <th>Hold date</th>
153
                                [% IF Koha.Preference('DisplayAddHoldGroups') %]
154
                                    <th>Hold group</th>
155
                                [% END %]
153
                                <th class="anti-the">Title</th>
156
                                <th class="anti-the">Title</th>
154
                                <th>Call number</th>
157
                                <th>Call number</th>
155
                                <th>Item type</th>
158
                                <th>Item type</th>
Lines 171-176 Link Here
171
174
172
                    [% PROCESS 'cancel-hold-modal' form_action = '/cgi-bin/koha/reserve/modrequest.pl' from_param = patronpage %]
175
                    [% PROCESS 'cancel-hold-modal' form_action = '/cgi-bin/koha/reserve/modrequest.pl' from_param = patronpage %]
173
                    [% PROCESS 'suspend-hold-modal' %]
176
                    [% PROCESS 'suspend-hold-modal' %]
177
                    [% PROCESS 'group-hold-modal' %]
178
                    [% IF Koha.Preference('DisplayAddHoldGroups') %]
179
                        <fieldset class="action">
180
                            <button class="btn btn-primary group_selected_holds" data-bulk="true"></button>
181
                        </fieldset>
182
                    [% END # IF DisplayAddHoldGroups %]
174
183
175
                    [% IF Koha.Preference('SuspendHoldsIntranet') %]
184
                    [% IF Koha.Preference('SuspendHoldsIntranet') %]
176
                        <fieldset class="action">
185
                        <fieldset class="action">
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt (+1 lines)
Lines 1103-1108 Link Here
1103
            relatives_borrowernumbers.push("[% b | html %]");
1103
            relatives_borrowernumbers.push("[% b | html %]");
1104
        [% END %]
1104
        [% END %]
1105
        var SuspendHoldsIntranet = [% ( Koha.Preference('SuspendHoldsIntranet') ) ? 1 : 0 | html %];
1105
        var SuspendHoldsIntranet = [% ( Koha.Preference('SuspendHoldsIntranet') ) ? 1 : 0 | html %];
1106
        var DisplayAddHoldGroups = [% ( Koha.Preference('DisplayAddHoldGroups') ) ? 1 : 0 | html %];
1106
    </script>
1107
    </script>
1107
    [% Asset.js("js/pages/circulation.js") | $raw %]
1108
    [% Asset.js("js/pages/circulation.js") | $raw %]
1108
    [% IF Koha.Preference('ClaimReturnedLostValue') || Koha.Preference('BundleLostValue') %]
1109
    [% IF Koha.Preference('ClaimReturnedLostValue') || Koha.Preference('BundleLostValue') %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt (+1 lines)
Lines 785-790 Link Here
785
            relatives_borrowernumbers.push("[% b | html %]");
785
            relatives_borrowernumbers.push("[% b | html %]");
786
        [% END %]
786
        [% END %]
787
        var SuspendHoldsIntranet = [% ( Koha.Preference('SuspendHoldsIntranet') ) ? 1 : 0 | html %];
787
        var SuspendHoldsIntranet = [% ( Koha.Preference('SuspendHoldsIntranet') ) ? 1 : 0 | html %];
788
        var DisplayAddHoldGroups = [% ( Koha.Preference('DisplayAddHoldGroups') ) ? 1 : 0 | html %];
788
    </script>
789
    </script>
789
    [% Asset.js("js/pages/circulation.js") | $raw %]
790
    [% Asset.js("js/pages/circulation.js") | $raw %]
790
    [% IF Koha.Preference('ClaimReturnedLostValue') || Koha.Preference('BundleLostValue') %]
791
    [% IF Koha.Preference('ClaimReturnedLostValue') || Koha.Preference('BundleLostValue') %]
(-)a/koha-tmpl/intranet-tmpl/prog/js/holds.js (-25 / +131 lines)
Lines 164-169 $(document).ready(function () { Link Here
164
                                return (
164
                                return (
165
                                    '<input type="checkbox" class="select_hold" data-id="' +
165
                                    '<input type="checkbox" class="select_hold" data-id="' +
166
                                    oObj.reserve_id +
166
                                    oObj.reserve_id +
167
                                    (oObj.hold_group_id
168
                                        ? '" data-hold-group-id="' +
169
                                          oObj.hold_group_id +
170
                                          '"'
171
                                        : '"') +
167
                                    '" data-borrowernumber="' +
172
                                    '" data-borrowernumber="' +
168
                                    borrowernumber +
173
                                    borrowernumber +
169
                                    '" data-biblionumber="' +
174
                                    '" data-biblionumber="' +
Lines 178-183 $(document).ready(function () { Link Here
178
                                sort: "reservedate",
183
                                sort: "reservedate",
179
                            },
184
                            },
180
                        },
185
                        },
186
                        ...(DisplayAddHoldGroups
187
                            ? [
188
                                  {
189
                                      data: function (oObj) {
190
                                          title = "";
191
                                          if (oObj.visual_hold_group_id) {
192
                                              var link =
193
                                                  '<a class="hold-group" href="/cgi-bin/koha/reserve/hold-group.pl?hold_group_id=' +
194
                                                  oObj.hold_group_id +
195
                                                  '">' +
196
                                                  oObj.visual_hold_group_id +
197
                                                  "</a>";
198
199
                                              title =
200
                                                  "<span>" + link + "</span>";
201
                                          }
202
203
                                          return title;
204
                                      },
205
                                  },
206
                              ]
207
                            : []),
181
                        {
208
                        {
182
                            data: function (oObj) {
209
                            data: function (oObj) {
183
                                title =
210
                                title =
Lines 232-248 $(document).ready(function () { Link Here
232
                                        "</span>";
259
                                        "</span>";
233
                                }
260
                                }
234
261
235
                                if (oObj.hold_group_id) {
236
                                    title += "<br>";
237
                                    var link =
238
                                        '<a class="hold-group" href="/cgi-bin/koha/reserve/hold-group.pl?hold_group_id=' +
239
                                        oObj.hold_group_id +
240
                                        '">' +
241
                                        __("part of a hold group") +
242
                                        "</a>";
243
                                    title += "<span>(" + link + ")</span>";
244
                                }
245
246
                                return title;
262
                                return title;
247
                            },
263
                            },
248
                        },
264
                        },
Lines 617-635 $(document).ready(function () { Link Here
617
        e.preventDefault();
633
        e.preventDefault();
618
        let selected_holds;
634
        let selected_holds;
619
        if (!$(this).data("hold-id")) {
635
        if (!$(this).data("hold-id")) {
620
            selected_holds =
636
            selected_holds = get_selected_holds_data();
621
                "[" +
622
                $(".holds_table .select_hold:checked")
623
                    .toArray()
624
                    .map(el =>
625
                        JSON.stringify({
626
                            hold: $(el).data("id"),
627
                            borrowernumber: $(el).data("borrowernumber"),
628
                            biblionumber: $(el).data("biblionumber"),
629
                        })
630
                    )
631
                    .join(",") +
632
                "]";
633
        } else {
637
        } else {
634
            selected_holds =
638
            selected_holds =
635
                "[" + JSON.stringify({ hold: $(this).data("hold-id") }) + "]";
639
                "[" + JSON.stringify({ hold: $(this).data("hold-id") }) + "]";
Lines 800-805 $(document).ready(function () { Link Here
800
        });
804
        });
801
    }
805
    }
802
806
807
    var MSG_GROUP_SELECTED = _("Group selected (%s)");
808
803
    function updateSelectedHoldsButtonCounters() {
809
    function updateSelectedHoldsButtonCounters() {
804
        $(".cancel_selected_holds").html(
810
        $(".cancel_selected_holds").html(
805
            MSG_CANCEL_SELECTED.format(
811
            MSG_CANCEL_SELECTED.format(
Lines 816-821 $(document).ready(function () { Link Here
816
                $(".holds_table .select_hold:checked").length
822
                $(".holds_table .select_hold:checked").length
817
            )
823
            )
818
        );
824
        );
825
        $(".group_selected_holds").html(
826
            MSG_GROUP_SELECTED.format(
827
                $(".holds_table .select_hold:checked").length
828
            )
829
        );
819
    }
830
    }
820
831
821
    function updateMoveButtons(table) {
832
    function updateMoveButtons(table) {
Lines 1148-1151 $(document).ready(function () { Link Here
1148
            '<input type="hidden" name="reserve_id" value="' + hold.hold + '">'
1159
            '<input type="hidden" name="reserve_id" value="' + hold.hold + '">'
1149
        );
1160
        );
1150
    }
1161
    }
1162
1163
    $(".group_selected_holds").html(
1164
        MSG_GROUP_SELECTED.format($(".holds_table .select_hold:checked").length)
1165
    );
1166
1167
    $(".group_selected_holds").click(function (e) {
1168
        if ($(".holds_table .select_hold:checked").length > 1) {
1169
            let selected_holds = get_selected_holds_data();
1170
            const group_ids = JSON.parse(selected_holds)
1171
                .filter(hold => hold.hold_group_id)
1172
                .map(hold => hold.hold_group_id);
1173
1174
            if (group_ids.length > 0) {
1175
                $("#group-modal .modal-body").prepend(
1176
                    '<div class="alert alert-warning">' +
1177
                        __(
1178
                            "Already grouped holds will be moved to the new group"
1179
                        ) +
1180
                        "</div>"
1181
                );
1182
            }
1183
1184
            $("#group-modal").modal("show");
1185
        }
1186
        return false;
1187
    });
1188
1189
    $("#group-modal-submit").click(function (e) {
1190
        e.preventDefault();
1191
        let selected_holds = get_selected_holds_data();
1192
1193
        const hold_ids = JSON.parse(selected_holds).map(hold => hold.hold);
1194
1195
        try {
1196
            group_holds(hold_ids)
1197
                .success(function () {
1198
                    holdsTable.api().ajax.reload();
1199
                })
1200
                .fail(function (jqXHR) {
1201
                    $("#group-modal .modal-body").prepend(
1202
                        '<div class="alert alert-danger">' +
1203
                            jqXHR.responseJSON.error +
1204
                            "</div>"
1205
                    );
1206
                    $("#group-modal-submit").prop("disabled", true);
1207
                })
1208
                .done(function () {
1209
                    $("#group-modal").modal("hide");
1210
                    $(".select_hold_all").click();
1211
                });
1212
        } catch (error) {
1213
            if (error.status === 404) {
1214
                alert(__("Unable to group, hold not found."));
1215
            } else {
1216
                alert(
1217
                    __(
1218
                        "Your request could not be processed. Check the logs for details."
1219
                    )
1220
                );
1221
            }
1222
        }
1223
        return false;
1224
    });
1225
1226
    function group_holds(hold_ids) {
1227
        return $.ajax({
1228
            method: "POST",
1229
            url: "/api/v1/patrons/" + borrowernumber + "/hold_groups",
1230
            contentType: "application/json",
1231
            data: JSON.stringify({ hold_ids: hold_ids, force_grouped: true }),
1232
        });
1233
    }
1234
1235
    $("#group-modal").on("hidden.bs.modal", function () {
1236
        $("#group-modal .modal-body .alert-warning").remove();
1237
        $("#group-modal .modal-body .alert-danger").remove();
1238
        $("#group-modal-submit").prop("disabled", false);
1239
    });
1240
1241
    function get_selected_holds_data() {
1242
        return (
1243
            "[" +
1244
            $(".holds_table .select_hold:checked")
1245
                .toArray()
1246
                .map(el =>
1247
                    JSON.stringify({
1248
                        hold: $(el).data("id"),
1249
                        borrowernumber: $(el).data("borrowernumber"),
1250
                        biblionumber: $(el).data("biblionumber"),
1251
                        hold_group_id: $(el).data("hold-group-id"),
1252
                    })
1253
                )
1254
                .join(",") +
1255
            "]"
1256
        );
1257
    }
1151
});
1258
});
1152
- 

Return to bug 40517