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

(-)a/api/v1/swagger/definitions/hold.yaml (+5 lines)
Lines 123-128 properties: Link Here
123
      - object
123
      - object
124
      - "null"
124
      - "null"
125
    description: The item
125
    description: The item
126
  patron:
127
    type:
128
      - object
129
      - "null"
130
    description: The patron
126
  pickup_library:
131
  pickup_library:
127
    type:
132
    type:
128
      - object
133
      - object
(-)a/api/v1/swagger/paths/holds.yaml (+2 lines)
Lines 104-109 Link Here
104
            - cancellation_requested
104
            - cancellation_requested
105
            - biblio
105
            - biblio
106
            - pickup_library
106
            - pickup_library
107
            - patron
108
            - item
107
        collectionFormat: csv
109
        collectionFormat: csv
108
    produces:
110
    produces:
109
      - application/json
111
      - application/json
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/holds_table.inc (-254 / +4 lines)
Lines 5-277 Link Here
5
[% #This include depends on the asset js/form-submit.js. Any template making use of this include must import form-submit.js as well. %]
5
[% #This include depends on the asset js/form-submit.js. Any template making use of this include must import form-submit.js as well. %]
6
[% #FIXME can form-submit.js be imported into this file directly? %]
6
[% #FIXME can form-submit.js be imported into this file directly? %]
7
7
8
<table id="patron_holds_table" class="holds_table">
8
<table id="patron_holds_table_[% biblio_id | html %]_[% split_data | html %]" class="holds_table" data-total-holds="[% total_holds | html %]">
9
    <thead>
9
    <thead>
10
        <tr>
10
        <tr>
11
            <th id="checkbox" data-colname="checkbox"><input type="checkbox" class="select_hold_all"/></th>
11
            <th id="checkbox" data-colname="checkbox"><input type="checkbox" class="select_hold_all"/></th>
12
            <th id="priority" data-colname="priority">Priority</th>
12
            <th id="priority" data-colname="priority">Priority</th>
13
            [% IF ( CAN_user_reserveforothers_modify_holds_priority ) %]
13
            <th id="change_priority" data-colname="change_priority">Change priority</th>
14
                <th id="change_priority" data-colname="change_priority">Change priority</th>
15
            [% END %]
16
            <th id="patron" data-colname="patron">Patron</th>
14
            <th id="patron" data-colname="patron">Patron</th>
17
            <th id="notes" data-colname="notes">Notes</th>
15
            <th id="notes" data-colname="notes">Notes</th>
18
            <th id="date" data-colname="date">Date</th>
16
            <th id="date" data-colname="date">Date</th>
19
            <th id="expiration" data-colname="expiration">Expiration</th>
17
            <th id="expiration" data-colname="expiration">Expiration</th>
20
            <th id="pickup_library" data-colname="pickup_library">Pickup library</th>
18
            <th id="pickup_library" data-colname="pickup_library">Pickup library</th>
21
            <th id="details" data-colname="details">Details</th>
19
            <th id="details" data-colname="details">Details</th>
22
            [% IF ( CAN_user_reserveforothers_modify_holds_priority ) %]
20
            <th id="set_lowest_priority" data-colname="set_lowest_priority"><span style="display:none;">Set lowest priority</span><i class="fa fa-lg fa-rotate-90 fa-fast-forward" title="Toggle set to lowest priority"></i></th>
23
                <th id="set_lowest_priority" data-colname="set_lowest_priority"><span style="display:none;">Set lowest priority</span><i class="fa fa-lg fa-rotate-90 fa-fast-forward" title="Toggle set to lowest priority"></i></th>
24
            [% END %]
25
            <th id="delete" data-colname="delete">Delete</th>
21
            <th id="delete" data-colname="delete">Delete</th>
26
            <th id="suspend" data-colname="suspend">Suspend</th>
22
            <th id="suspend" data-colname="suspend">Suspend</th>
27
            <th id="print_slip" data-colname="print_slip">Print hold/transfer slip</th>
23
            <th id="print_slip" data-colname="print_slip">Print hold/transfer slip</th>
28
        </tr>
24
        </tr>
29
    </thead>
25
    </thead>
30
    [%- SET first_priority = 0 -%]
31
    [%- SET found_holds = 0 -%]
32
    [%- SET last_priority  = holds.last.priority -%]
33
34
    [% SET all_priorities = [] %]
35
    [% FOREACH hold IN holds %]
36
        [% all_priorities.push( hold.priority ) %]
37
    [% END %]
38
39
    <tbody>
40
        [% FOREACH hold IN holds %]
41
        [%- IF !hold.found && first_priority == 0 -%]
42
            [%- first_priority = hold.priority -%]
43
            [%- found_holds = loop.index() -%]
44
        [%- END -%]
45
        [%- IF Koha.Preference('HoldsSplitQueueNumbering') == 'actual' -%]
46
            [%- this_priority = hold.priority -%]
47
        [%- ELSE -%]
48
            [%- this_priority = loop.count() - found_holds -%]
49
        [%- END -%]
50
            [% IF hold.suspend %]
51
                <tr class="suspend">
52
            [% ELSE %]
53
                <tr>
54
            [% END %]
55
                <td><input type="checkbox" class="select_hold" data-id="[% hold.reserve_id | html %]"/></td>
56
                <td>
57
                    <input type="hidden" name="reserve_id" value="[% hold.reserve_id | html %]" />
58
                    <input type="hidden" name="borrowernumber" value="[% hold.borrowernumber | html %]" />
59
                    <input type="hidden" name="biblionumber" value="[% hold.biblionumber | html %]" />
60
                    [% IF ( CAN_user_reserveforothers_modify_holds_priority ) %]
61
                        [% IF Koha.Preference('HoldsSplitQueue') == "nothing" && !hold.found %]
62
                            <select name="rank-request" class="rank-request" data-hold-id="[% hold.reserve_id | html %]">
63
                            [% IF ( CAN_user_reserveforothers_modify_holds_priority ) %]
64
                                [% FOREACH priority IN all_priorities %]
65
                                    [% IF priority == this_priority %]
66
                                        <option value="[% priority | html %]" selected="selected">[% priority | html %]</option>
67
                                    [% ELSE %]
68
                                        <option value="[% priority | html %]">[% priority | html %]</option>
69
                                    [% END %]
70
                                [% END %]
71
                            [% ELSE %]
72
                                <option value="[% hold.priority | html %]" selected="selected">[% this_priority | html %]</option>
73
                            [% END %]
74
                                <option value="del">del</option>
75
                            </select>
76
                        [% ELSE %]
77
                            <input type="hidden" name="rank-request" class="rank-request" value="[% hold.priority | html %]" data-hold-id="[% hold.reserve_id | html %]">
78
                            <select name="rank-request" class="rank-request" disabled="disabled" data-hold-id="[% hold.reserve_id | html %]">
79
                            [% IF ( hold.found ) %]
80
                                [% IF ( hold.intransit ) %]
81
                                    <option value="T" selected="selected">In transit</option>
82
                                [% ELSIF (hold.inprocessing) %]
83
                                    <option value="P" selected="selected">In processing</option>
84
                                [% ELSE %]
85
                                    <option value="W" selected="selected">Waiting</option>
86
                                [% END %]
87
                            [% ELSE %]
88
                                <option value="[% hold.priority | html %]" selected="selected">[% this_priority | html %]</option>
89
                            [% END %]
90
                            </select>
91
                        [% END %]
92
                    [% ELSE %]
93
                        <input type="hidden" name="rank-request" class="rank-request" value="[% hold.priority | html %]" data-hold-id="[% hold.reserve_id | html %]">
94
                        [% hold.priority | html %]
95
                    [% END %]
96
                </td>
97
                [%- IF ( CAN_user_reserveforothers_modify_holds_priority ) -%]
98
                [%- UNLESS hold.found -%]
99
                        [%- SET prev_priority  = loop.prev.priority -%]
100
                        [%- SET next_priority  = loop.next.priority -%]
101
                        <td style="white-space:nowrap;">
102
                            <a class="hold-arrow" title="Move hold up" data-op="cud-move" data-where="up" data-first_priority="[% first_priority | html %]" data-last_priority="[% last_priority | html %]" data-prev_priority="[% prev_priority | html %]" data-next_priority="[% next_priority | html %]" data-borrowernumber="[% hold.borrowernumber | html %]" data-biblionumber="[% hold.biblionumber | html %]" data-reserve_id="[% hold.reserve_id | html %]" data-date="[% hold.date | html %]">
103
                                <i class="fa fa-lg icon-move-hold-up" aria-hidden="true"></i>
104
                            </a>
105
106
                            <a class="hold-arrow" title="Move hold to top" data-op="cud-move" data-where="top" data-first_priority="[% first_priority | html %]" data-last_priority="[% last_priority | html %]" data-prev_priority="[% prev_priority | html %]" data-next_priority="[% next_priority | html %]" data-borrowernumber="[% hold.borrowernumber | html %]" data-biblionumber="[% hold.biblionumber | html %]" data-reserve_id="[% hold.reserve_id | html %]" data-date="[% hold.date | html %]">
107
                                <i class="fa fa-lg icon-move-hold-top" aria-hidden="true"></i>
108
                            </a>
109
110
                            <a class="hold-arrow" title="Move hold to bottom" data-op="cud-move" data-where="bottom" data-first_priority="[% first_priority | html %]" data-last_priority="[% last_priority | html %]" data-prev_priority="[% prev_priority | html %]" data-next_priority="[% next_priority | html %]" data-borrowernumber="[% hold.borrowernumber | html %]" data-biblionumber="[% hold.biblionumber | html %]" data-reserve_id="[% hold.reserve_id | html %]" data-date="[% hold.date | html %]">
111
                                <i class="fa fa-lg icon-move-hold-bottom" aria-hidden="true"></i>
112
                            </a>
113
114
                            <a class="hold-arrow" title="Move hold down" data-op="cud-move" data-where="down" data-first_priority="[% first_priority | html %]" data-last_priority="[% last_priority | html %]" data-prev_priority="[% prev_priority | html %]" data-next_priority="[% next_priority | html %]" data-borrowernumber="[% hold.borrowernumber | html %]" data-biblionumber="[% hold.biblionumber | html %]" data-reserve_id="[% hold.reserve_id | html %]" data-date="[% hold.date | html %]">
115
                                <i class="fa fa-lg icon-move-hold-down" aria-hidden="true"></i>
116
                            </a>
117
                        </td>
118
            [%- ELSE -%]
119
                <td></td>
120
            [%- END -%]
121
                [%- END -%]
122
                <td>
123
                    [% INCLUDE 'patron-title.inc' patron=hold.patron hide_patron_infos_if_needed=1 %]
124
                </td>
125
                <td>[% hold.notes | html | html_line_break %]</td>
126
                <td data-order="[% hold.date| html %]">
127
                    [% IF Koha.Preference('AllowHoldDateInFuture') %]
128
                        <input type="text" class="flatpickr" value="[% hold.date | html %]" required="required" size="10" name="reservedate" />
129
                    [% ELSE %]
130
                        [% hold.date | $KohaDates %]
131
                    [% END %]
132
                </td>
133
                <td>
134
                    <input type="text" class="flatpickr" data-flatpickr-futuredate="true" value="[% hold.expirationdate | html %]" size="10" name="expirationdate" />
135
                </td>
136
                <td>
137
                    [%- IF ( hold.found ) -%]
138
                        <input type="hidden" name="pickup" value="[% hold.wbrcode | html %]" />
139
                        [%- IF ( hold.atdestination ) -%]
140
                                Item waiting at <strong> [% hold.wbrname | html %]</strong>[% IF hold.desk_name %], [% hold.desk_name | html %],[% END %] since [% hold.waiting_date | $KohaDates %]
141
                        [%- ELSIF (hold.intransit) -%]
142
                            Item being transferred to <strong> [% hold.wbrname | html %]</strong>
143
                        [%- ELSIF (hold.inprocessing) -%]
144
                            Item being processed at <strong> [% hold.wbrname | html %]</strong>
145
                        [%- ELSE -%]
146
                            Hold expected at <strong>[% hold.wbrname | html %]</strong>, please checkin to verify status
147
                        [%- END -%]
148
                    [%- ELSE -%]
149
                        [%- IF Koha.Preference('IndependentBranches') && Branches.all().size == 1 -%]
150
                            [% Branches.GetName(hold.branchcode) | html %] <input type="hidden" name="pickup" value="[% hold.branchcode | html %]" />
151
                        [%- ELSE -%]
152
                            <select class="pickup_location_dropdown"
153
                                    data-selected="[% hold.branchcode | html %]"
154
                                    data-hold-id="[% hold.reserve_id | html %]"
155
                                    data-pickup-location-source="hold"
156
                                    name="pickup">
157
                                <option selected="selected" value="[% hold.branchcode | html %]">[% Branches.GetName(hold.branchcode) | html %]</option>
158
                                <option value="" disabled="disabled" class="loading">Loading...</option>
159
                            </select>
160
                            <img class="loading_[% hold.reserve_id | html %]" src="[% interface | html %]/[% theme | html %]/img/spinner-small.gif" alt="" style="display:none;"/>
161
                        [%- END -%]
162
                    [%- END -%]
163
                </td>
164
                <td>
165
                    [%- IF ( hold.found ) -%]
166
                        <a href="/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=[% hold.biblionumber | uri %]&amp;itemnumber=[% hold.itemnumber | uri %]#item[% hold.itemnumber | uri %]">
167
                            [%- IF ( hold.barcodenumber ) -%]
168
                                [%- hold.barcodenumber | html -%]
169
                            [%- ELSE -%]
170
                                <span>No barcode</span>
171
                            [%- END -%]
172
                            <input type="hidden" name="itemnumber" value="[% hold.itemnumber | html %]" />
173
                        </a>
174
                    [%- ELSE -%]
175
                        [%- IF ( hold.item_level_hold ) -%]
176
                            <em>
177
                                [%- IF ! hold.change_hold_type_allowed -%]
178
                                    <span>Only item</span>
179
                                    <a href="/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=[% hold.biblionumber | uri %]&amp;itemnumber=[% hold.itemnumber | uri %]#item[% hold.itemnumber | uri %]">
180
                                        [%- IF ( hold.barcodenumber ) -%]
181
                                            [%- hold.barcodenumber | html -%]
182
                                        [%- ELSE -%]
183
                                            <span>No barcode</span>
184
                                        [%- END -%]
185
                                        <input type="hidden" name="itemnumber" value="[% hold.itemnumber | html %]" />
186
                                    </a>
187
                                [%- ELSE -%]
188
                                        <select name="change_hold_type_[% hold.reserve_id | html %]">
189
                                        <option selected="selected" value="">Only item [%- IF ( hold.barcodenumber ) -%]
190
                                            [%- hold.barcodenumber | html -%]
191
                                        [%- ELSE -%]
192
                                            No barcode
193
                                        [%- END -%]
194
                                        </option>
195
                                        <option value="1">Next available</option>
196
                                    </select>
197
                                    [%- IF ( hold.itemnumber ) -%]
198
                                        <input type="hidden" name="itemnumber" value="[% hold.itemnumber | html %]" />
199
                                    [%- END -%]
200
                                    [%- IF hold.itemtype -%]
201
                                        <span style="display:none">Next available [% ItemTypes.GetDescription( hold.itemtype ) | html %] item</span>
202
                                    [%- ELSE -%]
203
                                        <span style="display:none">Next available</span>
204
                                    [%- END -%]
205
                                [%- END -%]
206
                            </em>
207
                        [%- ELSE -%]
208
                            [%- IF hold.itemtype -%]
209
                                <em>Next available [% ItemTypes.GetDescription( hold.itemtype ) | html %] item</em>
210
                            [%- ELSIF hold.object.item_group -%]
211
                                <em>Next available item from group <strong>[% hold.object.item_group.description | html %]</strong></em>
212
                            [%- ELSE -%]
213
                                <em>Next available</em>
214
                            [%- END -%]
215
216
                            <input type="hidden" name="itemnumber" value="" />
217
                        [%- END -%]
218
                    [%- END -%]
219
                    [%- IF hold.non_priority -%]
220
                        <br><i>Non priority hold</i>
221
                    [%- END -%]
222
                </td>
223
                [%- IF ( CAN_user_reserveforothers_modify_holds_priority ) -%]
224
                [%- UNLESS hold.found -%]
225
                        <td>
226
                                [% IF ( hold.lowestPriority ) %]
227
                                    <a class="hold-arrow" title="Remove lowest priority" data-op="cud-setLowestPriority" data-borrowernumber="[% hold.borrowernumber | html %]" data-biblionumber="[% hold.biblionumber | html %]" data-reserve_id="[% hold.reserve_id | html %]" data-date="[% hold.date | html %]">
228
                                        <i class="fa fa-lg fa-rotate-90 icon-unset-lowest" aria-hidden="true"></i>
229
                                [% ELSE %]
230
                                    <a class="hold-arrow" title="Set lowest priority" data-op="cud-setLowestPriority" data-borrowernumber="[% hold.borrowernumber | html %]" data-biblionumber="[% hold.biblionumber | html %]" data-reserve_id="[% hold.reserve_id | html %]" data-date="[% hold.date | html %]">
231
                                        <i class="fa fa-lg fa-rotate-90 icon-set-lowest" aria-hidden="true"></i>
232
                                [% END %]
233
                            </a>
234
                        </td>
235
            [%- ELSE -%]
236
                <td></td>
237
            [%- END -%]
238
                [%- END -%]
239
                <td>
240
                    <a class="cancel-hold" title="Cancel hold" data-borrowernumber="[% hold.borrowernumber | html %]" data-biblionumber="[% hold.biblionumber | html %]" data-id="[% hold.reserve_id | html %]" href="request.pl?op=cancel&amp;borrowernumber=[% hold.borrowernumber | html %]&amp;biblionumber=[% hold.biblionumber | html %]&amp;reserve_id=[% hold.reserve_id | html %]&amp;date=[% hold.date | html %]">
241
                        <i class="fa fa-trash" aria-label="Cancel hold"></i>
242
                    </a>
243
                </td>
244
                <td>
245
                    [% IF Koha.Preference('SuspendHoldsIntranet') %]
246
                        [% UNLESS ( hold.found ) %]
247
                            [% IF ( hold.suspend ) %]
248
                                <button class="btn btn-default btn-xs unsuspend-hold" data-reserve-id="[% hold.reserve_id | html %]" data-biblionumber="[% hold.biblionumber | html %]">
249
                                    <i class="fa fa-play" aria-hidden="true"></i> Unsuspend
250
                                </button>
251
                            [% ELSE %]
252
                                <button class="btn btn-default btn-xs suspend-hold" data-reserve-id="[% hold.reserve_id | html %]" data-biblionumber="[% hold.biblionumber | html %]">
253
                                    <i class="fa fa-pause" aria-hidden="true"></i> Suspend
254
                                </button>
255
                            [% END %]
256
257
                            [% IF Koha.Preference('AutoResumeSuspendedHolds') %]
258
                                <label for="suspend_until_[% hold.reserve_id | html %]">[% IF ( hold.suspend ) %] on [% ELSE %] until [% END %]</label>
259
                                <input type="text" name="suspend_until_[% hold.reserve_id | html %]" id="suspend_until_[% hold.reserve_id | html %]" size="10" value="[% hold.suspend_until | html %]" class="flatpickr" data-flatpickr-futuredate="true" />
260
                            [%- ELSE -%]
261
                                <input type="hidden" name="suspend_until_[% hold.reserve_id | html %]" id="suspend_until_[% hold.reserve_id | html %]" value=""/>
262
                            [%- END -%]
263
                        [%- END -%]
264
                    [%- END # IF SuspendHoldsIntranet -%]
265
                    [%- IF ( hold.found ) -%]
266
                        <a class="btn btn-default  submit-form-link" href="#" id="revert_hold_[% hold.reserve_id | html %]" data-op="cud-move" data-where="down" data-first_priority="[% first_priority | html %]" data-last_priority="[% last_priority | html %]" data-prev_priority="0" data-next_priority="1" data-borrowernumber="[% hold.borrowernumber | html %]" data-biblionumber="[% hold.biblionumber | html %]" data-itemnumber="[% hold.itemnumber | html %]" data-reserve_id="[% hold.reserve_id | html %]" data-date="[% hold.date | html %]" data-action="request.pl" data-method="post">[% IF hold.intransit %]Revert transit status[% ELSE %]Revert waiting status[% END %]</a>
267
                    [%- END -%]
268
                </td>
269
                [% IF ( hold.intransit || hold.atdestination ) %]
270
                    <td><input class="printholdslip" type="button" name="printholdslip" value="Print slip" data-reserve_id="[% hold.reserve_id | html %]"></td>
271
                [% ELSE %]
272
                    <td></td>
273
                [% END %]
274
            </tr>
275
        [% END %]
276
    </tbody>
277
</table>
26
</table>
27
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt (-227 / +79 lines)
Lines 1229-1235 Link Here
1229
                        [% END %]
1229
                        [% END %]
1230
                    [% END %]
1230
                    [% END %]
1231
                [% END %]
1231
                [% END %]
1232
                [% IF ( reserveloop ) %]
1232
                [% IF ( total_holds ) %]
1233
                    <form id="existing_holds" name="T[% time | html %]" action="modrequest.pl" method="post" style="display:block">
1233
                    <form id="existing_holds" name="T[% time | html %]" action="modrequest.pl" method="post" style="display:block">
1234
                        [% INCLUDE 'csrf-token.inc' %]
1234
                        [% INCLUDE 'csrf-token.inc' %]
1235
                        [% IF ( multi_hold ) %]
1235
                        [% IF ( multi_hold ) %]
Lines 1249-1255 Link Here
1249
                        <div id="toolbar" class="btn-toolbar sticky">
1249
                        <div id="toolbar" class="btn-toolbar sticky">
1250
                            <div class="btn-group">
1250
                            <div class="btn-group">
1251
                                <input type="hidden" name="op" value="cud-modifyall">
1251
                                <input type="hidden" name="op" value="cud-modifyall">
1252
                                <input type="submit" class="btn btn-primary" name="submit" value="Update hold(s)" />
1252
                                <input type="submit" class="btn btn-primary update_selected_holds" name="submit" value="Update hold(s)" />
1253
                            </div>
1253
                            </div>
1254
                            <div class="btn-group">
1254
                            <div class="btn-group">
1255
                                <button class="btn cancel_selected_holds" data-bulk="true"></button>
1255
                                <button class="btn cancel_selected_holds" data-bulk="true"></button>
Lines 1270-1416 Link Here
1270
                        <div class="page-section">
1270
                        <div class="page-section">
1271
1271
1272
                        [% FOREACH biblioloo IN biblioloop %]
1272
                        [% FOREACH biblioloo IN biblioloop %]
1273
                            [% IF ( biblioloo.reserveloop ) %]
1273
                            [% IF ( biblioloo.total_holds ) %]
1274
                                <div class="hold_title" id="hold_title_[% biblioloo.biblionumber | html %]">
1274
                                <div class="hold_title" id="hold_title_[% biblioloo.biblionumber | html %]">
1275
                                    [% IF ( multi_hold ) %]
1275
                                    [% IF ( multi_hold ) %]
1276
                                        <h3>
1276
                                        <h3>
1277
                                            <a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% biblioloo.biblionumber | uri %]">
1277
                                            <a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% biblioloo.biblionumber | uri %]">
1278
                                                [% biblioloo.title | html %]
1278
                                                [% biblioloo.title | html %]
1279
                                            </a> <span class="badge text-bg-info"><span>[% biblioloo.reserveloop.size | html %] [% tn('Hold', 'Holds', biblioloo.reserveloop.size) | $raw %]</span></span>
1279
                                            </a> <span class="badge text-bg-info"><span>[% biblioloo.total_holds | html %] [% tn('Hold', 'Holds', biblioloo.total_holds) | $raw %]</span></span>
1280
                                        </h3>
1280
                                        </h3>
1281
                                    [% END %]
1281
                                    [% END %]
1282
1282
1283
                                    [% IF Koha.Preference('HoldsSplitQueue') == 'branch' %]
1283
                                    [% IF Koha.Preference('HoldsSplitQueue') == 'branch' %]
1284
1284
                                        
1285
                                        [% SET branchcodes = [] %]
1285
                                        [% IF biblioloo.hold_branches.empty %]
1286
1286
                                            <div class="holds_by_library">
1287
                                        [% FOREACH h IN biblioloo.reserveloop %]
1287
                                                <h4>Any library</h4>
1288
                                            [% branchcodes.push( h.branchcode ) %]
1288
                                                [% INCLUDE holds_table.inc biblio_id=biblioloo.biblionumber total_holds=biblioloo.total_holds split_data="any" %]
1289
                                        [% END %]
1290
                                        [% branchcodes = branchcodes.unique %]
1291
                                        [% IF ( branchcodes.empty ) %]
1292
                                            <div class="note">
1293
                                                There are no holds on this title.
1294
                                            </div>
1289
                                            </div>
1295
                                        [% ELSE %]
1290
                                        [% ELSE %]
1296
1291
                                            [% FOREACH b IN biblioloo.hold_branches %]
1297
                                            [% FOREACH b IN branchcodes.sort %]
1298
                                                [% SET holds_by_branch = [] %]
1299
                                                [% FOREACH h IN biblioloo.reserveloop %]
1300
                                                    [% IF h.branchcode == b %]
1301
                                                        [% holds_by_branch.push( h ) %]
1302
                                                    [% END %]
1303
                                                [% END %]
1304
                                                <div class="holds_by_library">
1292
                                                <div class="holds_by_library">
1305
                                                    <h4>[% Branches.GetName( b ) | html %]</h4>
1293
                                                    <h4>[% Branches.GetName( b ) | html %]</h4>
1306
1294
1307
                                                    [% INCLUDE holds_table.inc holds=holds_by_branch %]
1295
                                                    [% INCLUDE holds_table.inc biblio_id=biblioloo.biblionumber total_holds=biblioloo.total_holds split_data=b %]
1308
                                                </div>
1296
                                                </div>
1309
                                            [% END # /FOREACh b %]
1297
                                            [% END %]
1310
                                        [% END # /IF ( branchcodes.empty ) %]
1298
                                        [% END # /IF hold_branches.empty %]
1311
1299
1312
                                    [% ELSIF Koha.Preference('HoldsSplitQueue') == 'itemtype' %]
1300
                                    [% ELSIF Koha.Preference('HoldsSplitQueue') == 'itemtype' %]
1313
1301
1314
                                        [% SET itemtypes = [] %]
1302
                                        [% IF biblioloo.hold_itemtypes.empty %]
1315
1303
                                            <div class="holds_by_itemtype">
1316
                                        [% FOREACH h IN biblioloo.reserveloop %]
1304
                                                <h4>Any item type</h4>
1317
                                            [% SET hold_itemtype = h.object.item.effective_itemtype || h.itemtype %]
1305
                                                [% INCLUDE holds_table.inc biblio_id=biblioloo.biblionumber total_holds=biblioloo.total_holds split_data="any" %]
1318
                                            [% itemtypes.push( hold_itemtype ) %]
1319
                                        [% END %]
1320
                                        [% itemtypes = itemtypes.unique %]
1321
                                        [% IF ( itemtypes.empty ) %]
1322
                                            <div class="note">
1323
                                                There are no holds on this title.
1324
                                            </div>
1306
                                            </div>
1325
                                        [% ELSE %]
1307
                                        [% ELSE %]
1326
1308
                                            [% FOREACH i IN biblioloo.hold_itemtypes %]
1327
                                            [% FOREACH i IN itemtypes.sort %]
1328
                                                [% SET holds_by_itemtype = [] %]
1329
                                                [% FOREACH h IN biblioloo.reserveloop %]
1330
                                                    [% SET hold_itemtype = h.object.item.effective_itemtype || h.itemtype %]
1331
                                                    [% IF hold_itemtype == i %]
1332
                                                        [% holds_by_itemtype.push( h ) %]
1333
                                                    [% END %]
1334
                                                [% END %]
1335
1336
                                                <div class="holds_by_itemtype">
1309
                                                <div class="holds_by_itemtype">
1337
                                                    [% IF i %]
1310
                                                    [% IF i && i != 'any' %]
1338
                                                        <h4>[% ItemTypes.GetDescription( i ) | html %]</h4>
1311
                                                        <h4>[% ItemTypes.GetDescription( i ) | html %]</h4>
1339
                                                    [% ELSE %]
1312
                                                    [% ELSE %]
1340
                                                        <h4>Any item type</h4>
1313
                                                        <h4>Any item type</h4>
1341
                                                    [% END %]
1314
                                                    [% END %]
1342
                                                    [% INCLUDE holds_table.inc holds=holds_by_itemtype %]
1315
                                                    [% INCLUDE holds_table.inc biblio_id=biblioloo.biblionumber total_holds=biblioloo.total_holds split_data=i %]
1343
                                                </div>
1316
                                                </div>
1344
                                            [% END # /FOREACH i %]
1317
                                            [% END %]
1345
                                        [% END # /IF ( itemtypes.empty ) %]
1318
                                        [% END # /IF hold_split.empty %]
1346
1319
1347
                                    [% ELSIF Koha.Preference('HoldsSplitQueue') == 'branch_itemtype' %]
1320
                                    [% ELSIF Koha.Preference('HoldsSplitQueue') == 'branch_itemtype' %]
1348
                                        [% SET branchcodes = [] %]
1349
1350
                                        [% FOREACH h IN biblioloo.reserveloop %]
1351
                                            [% branchcodes.push( h.branchcode ) %]
1352
                                        [% END %]
1353
                                        [% branchcodes = branchcodes.unique %]
1354
                                        [% IF ( branchcodes.empty ) %]
1355
                                            <div class="note">
1356
                                                There are no holds on this title.
1357
                                            </div>
1358
                                        [% ELSE %]
1359
1321
1360
                                            [% FOREACH b IN branchcodes.sort %]
1322
                                        [% FOREACH b IN biblioloo.hold_branches %]
1361
                                                <div class="holds_by_library">
1323
                                            <div class="holds_by_library">
1362
                                                    <h4 class="library_holds">[% Branches.GetName( b ) | html %]</h4>
1324
                                                <h4>[% Branches.GetName( b ) | html %]</h4>
1363
                                                    [% SET holds_by_branch = [] %]
1325
                                                [% FOREACH i IN biblioloo.hold_itemtypes %]
1364
                                                    [% FOREACH h IN biblioloo.reserveloop %]
1326
                                                    <div class="holds_by_itemtype">
1365
                                                        [% IF h.branchcode == b %]
1327
                                                        [% IF i && i != 'any' %]
1366
                                                            [% holds_by_branch.push( h ) %]
1328
                                                            <h4>[% ItemTypes.GetDescription( i ) | html %]</h4>
1329
                                                        [% ELSE %]
1330
                                                            <h4>Any item type</h4>
1367
                                                        [% END %]
1331
                                                        [% END %]
1368
                                                    [% END %]
1332
                                                        [% SET split_data = b _ "_" _ i %]
1369
1333
                                                        [% INCLUDE holds_table.inc biblio_id=biblioloo.biblionumber total_holds=biblioloo.total_holds split_data=split_data %]
1370
                                                    [% SET itemtypes = [] %]
1334
                                                    </div>
1371
                                                    [% FOREACH h IN holds_by_branch %]
1335
                                                [% END %]
1372
                                                        [% SET hold_itemtype = h.object.item.effective_itemtype || h.itemtype %]
1373
                                                        [% itemtypes.push( hold_itemtype ) %]
1374
                                                    [% END %]
1375
                                                    [% itemtypes = itemtypes.unique %]
1376
1377
                                                    [% FOREACH i IN itemtypes.sort %]
1378
                                                        <div class="holds_by_itemtype">
1379
                                                            <h5 class="itemtype_holds">
1380
                                                                [% IF i %]
1381
                                                                    [% ItemTypes.GetDescription( i ) | html %]
1382
                                                                [% ELSE %]
1383
                                                                    <span>Any item type</span>
1384
                                                                [% END %]
1385
                                                            </h5>
1386
1387
                                                            [% SET holds_by_itemtype = [] %]
1388
                                                            [% FOREACH h IN holds_by_branch %]
1389
                                                                [% SET hold_itemtype = h.object.item.effective_itemtype || h.itemtype %]
1390
                                                                [% IF hold_itemtype == i %]
1391
                                                                    [% holds_by_itemtype.push( h ) %]
1392
                                                                [% END %]
1393
                                                            [% END %]
1394
                                                            [% INCLUDE holds_table.inc holds=holds_by_itemtype %]
1395
                                                        </div> <!-- /.holds_by_itemtype -->
1396
                                                    [% END %]
1397
                                                </div> <!-- /.holds_by_library -->
1398
                                            [% END # /FOREACH b %]
1399
                                        [% END # /IF ( branchcodes.empty ) %]
1400
1401
                                    [% ELSE %]
1402
1403
                                        [% IF ( biblioloo.reserveloop.size ) %]
1404
                                            [% INCLUDE holds_table.inc holds=biblioloo.reserveloop %]
1405
                                        [% ELSE %]
1406
                                            <div class="note">
1407
                                                There are no holds on this title.
1408
                                            </div>
1336
                                            </div>
1409
                                        [% END %]
1337
                                        [% END %]
1410
1338
1339
                                    [% ELSE %]
1340
                                        [% INCLUDE holds_table.inc biblio_id=biblioloo.biblionumber total_holds=biblioloo.total_holds split_data="any"%]
1411
                                    [% END # /IF HoldsSplitQueue %]
1341
                                    [% END # /IF HoldsSplitQueue %]
1412
                                </div> <!-- /hold_title -->
1342
                                </div> <!-- /hold_title -->
1413
                            [% END # /IF biblioloo.reserveloop %]
1343
                            [% ELSE %]
1344
                                <div class="note">
1345
                                    There are no holds on this title.
1346
                                </div>
1347
                            [% END # /IF ( biblioloo.total_holds ) %]
1414
                        [% END # FOREACH biblioloo %]
1348
                        [% END # FOREACH biblioloo %]
1415
                        </div>
1349
                        </div>
1416
                    </form> <!-- /#existing_holds -->
1350
                    </form> <!-- /#existing_holds -->
Lines 1483-1488 Link Here
1483
    [% INCLUDE 'calendar.inc' %]
1417
    [% INCLUDE 'calendar.inc' %]
1484
    [% INCLUDE 'columns_settings.inc' %]
1418
    [% INCLUDE 'columns_settings.inc' %]
1485
    [% INCLUDE 'select2.inc' %]
1419
    [% INCLUDE 'select2.inc' %]
1420
    <script>
1421
        hold_table_settings = [% TablesSettings.GetTableSettings( 'circ', 'holds', 'patron_holds_table', 'json' ) | $raw %];
1422
    </script>
1486
    [% Asset.js("js/holds.js") | $raw%]
1423
    [% Asset.js("js/holds.js") | $raw%]
1487
    [% Asset.js("js/form-submit.js") | $raw%]
1424
    [% Asset.js("js/form-submit.js") | $raw%]
1488
1425
Lines 1492-1505 Link Here
1492
    [% END %]
1429
    [% END %]
1493
1430
1494
    <script>
1431
    <script>
1495
        $(document).ready(function () {
1496
            hold_table_settings = [% TablesSettings.GetTableSettings( 'circ', 'holds', 'patron_holds_table', 'json' ) | $raw %];
1497
            KohaTable("patron_holds_table", {
1498
                "bPaginate":false,
1499
                "bKohaColumnsUseNames": true,
1500
           }, hold_table_settings);
1501
        });
1502
        var biblionumbers = [[% biblionumbers.join(', ') | $raw %]];
1432
        var biblionumbers = [[% biblionumbers.join(', ') | $raw %]];
1433
        var hold_branches = {[% FOREACH biblio_info IN biblioloop %] [% biblio_info.biblionumber | html %]: ["[% biblio_info.hold_branches.join('", "') | $raw %]"], [% END %]};
1434
        var hold_itemtypes = {[% FOREACH biblio_info IN biblioloop %] [% biblio_info.biblionumber | html %]: ["[% biblio_info.hold_itemtypes.join('", "') | $raw %]"], [% END %]};
1435
        var HoldsSplitQueue = "[% Koha.Preference('HoldsSplitQueue') | html %]";
1436
        var HoldsSplitQueueNumbering = "[% Koha.Preference('HoldsSplitQueueNumbering') | html %]";
1437
        var SuspendHoldsIntranet = [% ( Koha.Preference('SuspendHoldsIntranet') ) ? 1 : 0 | html %];
1438
        var AutoResumeSuspendedHolds = [% ( Koha.Preference('AutoResumeSuspendedHolds') ) ? 1 : 0 | html %];
1439
        var AllowHoldDateInFuture = [% ( Koha.Preference('AllowHoldDateInFuture') ) ? 1 : 0 | html %];
1440
        var HidePatronName = [% ( Koha.Preference('HidePatronName') ) ? 1 : 0 | html %];
1441
        var CAN_user_reserveforothers_modify_holds_priority = [%CAN_user_reserveforothers_modify_holds_priority ? 1 : 0 | html %];
1503
        var borrowernumber = "[% patron.borrowernumber | $raw %]";
1442
        var borrowernumber = "[% patron.borrowernumber | $raw %]";
1504
        var patron_homebranch = "[% To.json( Branches.GetName( patron.branchcode ) ) | $raw %]";
1443
        var patron_homebranch = "[% To.json( Branches.GetName( patron.branchcode ) ) | $raw %]";
1505
        var override_items = {[% FOREACH biblio_info IN biblioloop %][% FOREACH itemloo IN biblio_info.itemloop %][% IF ( itemloo.override ) %]
1444
        var override_items = {[% FOREACH biblio_info IN biblioloop %][% FOREACH itemloo IN biblio_info.itemloop %][% IF ( itemloo.override ) %]
Lines 1529-1534 Link Here
1529
        $.fn.select2.defaults.set("dropdownAutoWidth", true );
1468
        $.fn.select2.defaults.set("dropdownAutoWidth", true );
1530
1469
1531
        $(document).ready(function() {
1470
        $(document).ready(function() {
1471
            biblionumbers.forEach(function(biblionumber) {
1472
                let branches = hold_branches[biblionumber];
1473
                let itemtypes = hold_itemtypes[biblionumber];
1474
                switch (HoldsSplitQueue) {
1475
                    case 'branch':
1476
                        branches.forEach(function(branch) {
1477
                            load_patron_holds_table(biblionumber, {name: HoldsSplitQueue, value: branch});
1478
                        });
1479
                        break;
1480
                    case 'itemtype':
1481
                        itemtypes.forEach(function(itemtype) {
1482
                            load_patron_holds_table(biblionumber, {name: HoldsSplitQueue, value: itemtype});
1483
                        });
1484
                        break;
1485
                    case 'branch_itemtype':
1486
                        branches.forEach(function(branch) {
1487
                            itemtypes.forEach(function(itemtype) {
1488
                                load_patron_holds_table(biblionumber, {name: HoldsSplitQueue, value: branch + '_' + itemtype});
1489
                            });
1490
                        });
1491
                        break;
1492
                    default:
1493
                        load_patron_holds_table(biblionumber, {name: 'any', value: 'any'});
1494
                }
1495
            });
1532
            $('#cancellation-reason-fieldset').hide();
1496
            $('#cancellation-reason-fieldset').hide();
1533
            $('.rank-request').on('change', function() {
1497
            $('.rank-request').on('change', function() {
1534
                if ( $(".rank-request option:selected[value='del']").length ) {
1498
                if ( $(".rank-request option:selected[value='del']").length ) {
Lines 1879-1996 Link Here
1879
                localStorage.selectedHolds = [];
1843
                localStorage.selectedHolds = [];
1880
            }
1844
            }
1881
1845
1882
            $('.holds_table .select_hold').each(function() {
1883
                if(localStorage.selectedHolds.includes($(this).data('id'))) {
1884
                    $(this).prop('checked', true);
1885
                }
1886
            });
1887
1888
            $('.holds_table .select_hold_all').each(function() {
1889
                var table = $(this).parents('.holds_table');
1890
                var count = $('.select_hold:not(:checked)', table).length;
1891
                $('.select_hold_all', table).prop('checked', !count);
1892
            });
1893
1894
            $('.cancel_selected_holds').html(MSG_CANCEL_SELECTED.format($('.holds_table .select_hold:checked').length));
1895
1896
            $('.holds_table .select_hold_all').click(function() {
1897
                var table = $(this).parents('.holds_table');
1898
                var count = $('.select_hold:checked', table).length;
1899
                $('.select_hold', table).prop('checked', !count);
1900
                $(this).prop('checked', !count);
1901
                $('.cancel_selected_holds').html(MSG_CANCEL_SELECTED.format($('.holds_table .select_hold:checked').length));
1902
                $('#cancel_hold_alert').html( MSG_CANCEL_ALERT.format($('.holds_table .select_hold:checked').length));
1903
                $('#cancel_hold_alert').show();
1904
                localStorage.selectedHolds = $('.holds_table .select_hold:checked').toArray().map(el => $(el).data('id'));
1905
            });
1906
1907
            $('.holds_table .select_hold').click(function() {
1908
                var table = $(this).parents('.holds_table');
1909
                var count = $('.select_hold:not(:checked)', table).length;
1910
                $('.select_hold_all', table).prop('checked', !count);
1911
                $('.cancel_selected_holds').html(MSG_CANCEL_SELECTED.format($('.holds_table .select_hold:checked').length));
1912
                $('#cancel_hold_alert').html( MSG_CANCEL_ALERT.format($('.holds_table .select_hold:checked').length));
1913
                $('#cancel_hold_alert').show();
1914
                localStorage.selectedHolds = $('.holds_table .select_hold:checked').toArray().map(el => $(el).data('id'));
1915
            });
1916
1917
            $('.cancel_selected_holds').click(function(e) {
1918
                e.preventDefault();
1919
                if($('.holds_table .select_hold:checked').length) {
1920
                    cancel_link = $(this);
1921
                    $("#cancel_modal_form #inputs").empty;
1922
                    biblionumbers.forEach( function(biblionumber){
1923
                        $("#cancel_modal_form #inputs").append('<input type="hidden" name="biblionumber" value="'+biblionumber+'">');
1924
                    });
1925
                    $("#cancel_modal_form #inputs").append('<input type="hidden" name="op" value="cud-cancel_bulk">');
1926
                    let hold_ids= $('.holds_table .select_hold:checked').toArray().map(el => $(el).data('id')).join(',');
1927
                    $("#cancel_modal_form #inputs").append('<input type="hidden" name="ids" value="' + hold_ids + '">');
1928
                    delete localStorage.selectedHolds;
1929
                    $('#cancelModal').modal('show');
1930
                }
1931
                return false;
1932
            });
1933
1934
            $(".hold-arrow").click(function(e) {
1935
                e.preventDefault();
1936
                let arrowForm = $("#hold-actions-form").attr({
1937
                    action: 'request.pl',
1938
                    method: 'post'
1939
                });
1940
                let arrow_op = $("<input />").attr({
1941
                    name: 'op',
1942
                    type: 'hidden',
1943
                    value: $(this).data('op')
1944
                });
1945
                let arrow_where = $("<input />").attr({
1946
                    name: 'where',
1947
                    type: 'hidden',
1948
                    value: $(this).data('where')
1949
                });
1950
                let arrow_fp = $("<input />").attr({
1951
                    name: 'first_priority',
1952
                    type: 'hidden',
1953
                    value: $(this).data('first_priority')
1954
                });
1955
                let arrow_lp = $("<input />").attr({
1956
                    name: 'last_priority',
1957
                    type: 'hidden',
1958
                    value: $(this).data('last_priority')
1959
                });
1960
                let arrow_pp = $("<input />").attr({
1961
                    name: 'prev_priority',
1962
                    type: 'hidden',
1963
                    value: $(this).data('prev_priority')
1964
                });
1965
                let arrow_np = $("<input />").attr({
1966
                    name: 'next_priority',
1967
                    type: 'hidden',
1968
                    value: $(this).data('next_priority')
1969
                });
1970
                let arrow_bn = $("<input />").attr({
1971
                    name: 'borrowernumber',
1972
                    type: 'hidden',
1973
                    value: $(this).data('borrowernumber')
1974
                });
1975
                let arrow_bb = $("<input />").attr({
1976
                    name: 'biblionumber',
1977
                    type: 'hidden',
1978
                    value: $(this).data('biblionumber')
1979
                });
1980
                let arrow_ri = $("<input />").attr({
1981
                    name: 'reserve_id',
1982
                    type: 'hidden',
1983
                    value: $(this).data('reserve_id')
1984
                });
1985
                let arrow_date = $("<input />").attr({
1986
                    name: 'date',
1987
                    type: 'hidden',
1988
                    value: $(this).data('date')
1989
                });
1990
                arrowForm.append(arrow_op,arrow_where,arrow_fp,arrow_lp,arrow_pp,arrow_np,arrow_bn,arrow_bb,arrow_ri,arrow_date);
1991
                $("#hold-actions-form").submit();
1992
                return true;
1993
            })
1994
        });
1846
        });
1995
</script>
1847
</script>
1996
1848
(-)a/koha-tmpl/intranet-tmpl/prog/js/holds.js (+615 lines)
Lines 498-500 $(document).ready(function() { Link Here
498
    });
498
    });
499
499
500
});
500
});
501
502
function fetch_libraries() {
503
    return $.ajax({
504
        method: "GET",
505
        url: "/api/v1/libraries",
506
        data: {_per_page: -1},
507
        success: function(data, textStatus, request){
508
        },
509
        error: function( jqXHR, textStatus, errorThrown) {
510
            console.log(errorThrown);
511
        },
512
    });
513
}
514
515
async function load_patron_holds_table(biblio_id, split_data) {
516
    const { name: split_name, value: split_value } = split_data;
517
    const table_id = `#patron_holds_table_${biblio_id}_${split_value}`;
518
    hold_table_settings.table = `patron_holds_table_${biblio_id}_${split_data.value}`;
519
    let url = `/api/v1/holds/?q={"me.biblio_id":${biblio_id}`;
520
521
    if (split_name === 'branch' && split_value !== 'any') {
522
        url += `, "me.pickup_library_id":"${split_value}"`;
523
    } else if (split_name === 'itemtype' && split_value !== 'any') {
524
        url += `, "me.itemtype":"${split_value}"`;
525
    } else if (split_name === 'branch_itemtype') {
526
        const [branch, itemtype] = split_value.split('_');
527
        url += itemtype === 'any' 
528
            ? `, "me.pickup_library_id":"${branch}"`
529
            : `, "me.pickup_library_id":"${branch}", "me.itemtype":"${itemtype}"`;
530
    }
531
532
    url += '}';
533
    const totalHolds = $(table_id).data('total-holds');
534
    const totalHoldsSelect = parseInt(totalHolds)+1;
535
    const multiChange = {};
536
    let pageStart;
537
    const libraries = await fetch_libraries();
538
    var holdsQueueTable = $(table_id).kohaTable({
539
        ajax: {
540
            url: url,
541
            data: function (params) {
542
                pageStart = params.start;
543
                var query = {
544
                    "_per_page": params.length,
545
                    "_page": params.start / params.length + 1,
546
                    "_order_by": "priority",
547
                    "_match": "exact"
548
                };  
549
                return query;
550
            },
551
        },
552
        embed: ['patron'],
553
        columnDefs: [
554
            {
555
                targets: [2, 3],
556
                className: 'dt-body-nowrap'
557
            },
558
            {
559
                targets: [3, 9],
560
                visible: CAN_user_reserveforothers_modify_holds_priority ? true : false
561
            },
562
563
        ],
564
        columns: [
565
            {   
566
                data: "hold_id",
567
                orderable: false,
568
                searchable: false,
569
                render: function( data, type, row, meta ) {
570
                    return '<input type="checkbox" class="select_hold" data-id="'+data+'"/>';
571
                }
572
            },
573
            {
574
                data: "priority",
575
                orderable: false,
576
                searchable: false,
577
                render: function(data, type, row, meta) {
578
                    let select = '<select name="rank-request" class="rank-request" data-id="'+row.hold_id;
579
                    if(CAN_user_reserveforothers_modify_holds_priority && split_name == 'any') {
580
                        for ( var i=0; i < totalHoldsSelect; i++ ){
581
                            let selected;
582
                            let value;
583
                            let desc;
584
                            if (data == i && row.status == 'T') {
585
                                select += '" disabled="disabled">';
586
                                selected = " selected='selected' ";
587
                                value = 'T';
588
                                desc = 'In transit';
589
                            } else if (data == i && row.status == 'P') {
590
                                select += '" disabled="disabled">';
591
                                selected = " selected='selected' ";
592
                                value = 'P';
593
                                desc = 'In processing';
594
                            } else if (data == i && row.status == 'W'){
595
                                select += '" disabled="disabled">';
596
                                selected = " selected='selected' ";
597
                                value = 'W';
598
                                desc = 'Waiting';
599
                            } else if (data == i && !row.status) {
600
                                select += '">';
601
                                selected = " selected='selected' ";
602
                                value = data;
603
                                desc = data;
604
                            } else {
605
                                if (i != 0) {
606
                                    select += '">';
607
                                    value = i;
608
                                    desc = i;
609
                                } else {
610
                                    select += '">';
611
                                }
612
                            }
613
                            if (value) {
614
                                select += '<option value="'+ value +'"'+selected+'>'+desc+'</option>';
615
                            }
616
                        }
617
                    }else {
618
                        if (row.status == 'T') {
619
                            select += '" disabled="disabled"><option value="T" selected="selected">In transit</option></select>';
620
                        } else if (row.status == 'P') {
621
                            select += '" disabled="disabled"><option value="P" selected="selected">In processing</option></select>';
622
                        } else if (row.status == 'W') {
623
                            select += '" disabled="disabled"><option value="W" selected="selected">Waiting</option></select>';
624
                        } else {
625
                            if (HoldsSplitQueue !== "nothing" && HoldsSplitQueueNumbering === 'virtual') {
626
                                let virtualPriority = pageStart + meta.row + 1;
627
                                select += '" disabled="disabled"><option value="'+ data +'" selected="selected">'+ virtualPriority +'</option></select>';
628
                            } else {
629
                                select += '" disabled="disabled"><option value="'+ data +'" selected="selected">'+ data +'</option></select>';
630
                            }
631
                        }
632
                    }
633
                    select += '</select>';
634
                    return select;
635
                }
636
            },
637
            {
638
                data: "",
639
                orderable: false,
640
                searchable: false,
641
                render: function(data, type, row, meta) {
642
                    if (row.status) {
643
                        return null;
644
                    }
645
                    let buttons = '<a class="hold-arrow move-hold" title="Move hold up" href="#" data-move-hold="up" data-priority="'+row.priority+'" reserve_id="'+row.hold_id+'"><i class="fa fa-lg icon-move-hold-up" aria-hidden="true"></i></a>';
646
                    buttons += '<a class="hold-arrow move-hold" title="Move hold to top" href="#" data-move-hold="top" data-priority="'+row.priority+'" reserve_id="'+row.hold_id+'"><i class="fa fa-lg icon-move-hold-top" aria-hidden="true"></i></a>';
647
                    buttons += '<a class="hold-arrow move-hold" title="Move hold to bottom" href="#" data-move-hold="bottom" data-priority="'+row.priority+'" reserve_id="'+row.hold_id+'"><i class="fa fa-lg icon-move-hold-bottom" aria-hidden="true"></i></a>';
648
                    buttons += '<a class="hold-arrow move-hold" title="Move hold down" href="#" data-move-hold="down" data-priority="'+row.priority+'" reserve_id="'+row.hold_id+'"><i class="fa fa-lg icon-move-hold-down" aria-hidden="true"></i></a>';
649
                    return buttons;
650
                }
651
            },
652
            {
653
                data: "patron.cardnumber",
654
                orderable: false,
655
                searchable: true,
656
                render: function(data, type, row, meta) {
657
                    if(data == null) {
658
                        let library = libraries.find(library => library.library_id == row.pickup_library_id);
659
                        return __("A patron from library %s").format(library.name);
660
                    } else {
661
                        return '<a href="/cgi-bin/koha/members/moremember.pl?borrowernumber='+row.patron.patron_id+'">'+data+'</a>';
662
                    }
663
                }
664
            },
665
            {
666
                data: "notes", 
667
                orderable: false,
668
                searchable: false,
669
                render: function(data, type, row, meta) {
670
                    return data;
671
                }
672
            },
673
            {
674
                data: "hold_date",
675
                orderable: false,
676
                searchable: false,
677
                render: function(data, type, row, meta) {
678
                    if (AllowHoldDateInFuture) {
679
                        return '<input type="text" class="holddate" value="'+$date(data)+'" size="10" name="hold_date" data-id="'+row.hold_id+'" data-current-date="'+data+'"/>';
680
                    } else {
681
                        return $date(data);
682
                    }
683
                }
684
            },
685
            {
686
                data: "expiration_date",
687
                orderable: false,
688
                searchable: false,
689
                render: function(data, type, row, meta) {
690
                    return '<input type="text" class="expirationdate" value="'+$date(data)+'" size="10" name="expiration_date" data-id="'+row.hold_id+'" data-current-date="'+data+'"/>';
691
                }
692
            },
693
            {
694
                data: "pickup_library_id",
695
                orderable: false,
696
                searchable: false,
697
                render: function(data, type, row, meta) {
698
                    var branchSelect='<select priority='+row.priority+' class="hold_location_select" data-id="'+row.hold_id+'" reserve_id="'+row.hold_id+'" name="pick-location" data-pickup-location-source="hold">';
699
                    var libraryname;
700
                    for ( var i=0; i < libraries.length; i++ ){
701
                        var selectedbranch;
702
                        var setbranch;
703
                        if( libraries[i].library_id == data ){
704
                            selectedbranch = " selected='selected' ";
705
                            setbranch = __(" (current) ");
706
                            libraryname = libraries[i].name;
707
                        } else if ( libraries[i].pickup_location == false ) {
708
                            continue;
709
                        } else{
710
                            selectedbranch = '';
711
                            setbranch = '';
712
                        }
713
                        branchSelect += '<option value="'+ libraries[i].library_id.escapeHtml() +'"'+selectedbranch+'>'+libraries[i].name.escapeHtml()+setbranch+'</option>';
714
                    }
715
                    branchSelect +='</select>';
716
                    if ( row.status == 'T' ) {
717
                        return __("Item being transferred to <strong>%s</strong>").format(libraryname);
718
                    } else if (row.status == 'P') {
719
                        return __("Item being processed at <strong>%s</strong>").format(libraryname);
720
                    }
721
                    else if (row.status == 'W') {
722
                        return __("Item waiting at <strong>%s</strong> since %s").format(libraryname, $date(row.waiting_date));
723
                    } else {
724
                        return branchSelect;
725
                    }
726
                }
727
            },
728
            {
729
                data: "item_id",
730
                orderable: false,
731
                searchable: false,
732
                render: function(data, type, row, meta) {
733
                    let currentCell = $(table_id).DataTable().cells({"row":meta.row, "column":meta.col}).nodes(0);
734
                    if (data) {
735
                        $.ajax({
736
                            method: "GET",
737
                            url: "/api/v1/items/"+data,
738
                            success: function(res){
739
                                $(currentCell).html('<a href="/cgi-bin/koha/catalogue/moredetail.pl?biblionumber='+biblio_id+'&itemnumber='+data+'">'+res.external_id+'</a>');
740
                            }
741
                        });
742
                        return '<img src="/intranet-tmpl/prog/img/spinner-small.gif" alt="" /><span class="waiting_msg"></span></div>';
743
                    } else if (row.item_group_id) {
744
                        $.ajax({
745
                            method: "GET",
746
                            url: "/api/v1/biblios/"+biblio_id+"/item_groups/"+row.item_group_id,
747
                            success: function(res){
748
                                $(currentCell).html(__("Next available item group <strong>%s</strong> item").format( res.description ));
749
                            }
750
                        });
751
                        return '<img src="/intranet-tmpl/prog/img/spinner-small.gif" alt="" /><span class="waiting_msg"></span></div>';
752
                    } else {
753
                        if (row.non_priority) {
754
                            return '<em>'+__("Next available")+'</em><br/><i>'+__("Non priority hold")+'</i>';
755
                        } else {
756
                            return '<em>'+__("Next available")+'</em>';
757
                        }
758
                    }
759
                }
760
            },
761
            {
762
                data: "",
763
                orderable: false,
764
                searchable: false,
765
                render: function(data, type, row, meta) {
766
                    if (row.item_id) {
767
                        return null
768
                    } else {
769
                        if(row.lowest_priority){
770
                            return '<a class="hold-arrow toggle-lowest-priority" title="Remove lowest priority" data-op="cud-setLowestPriority" data-borrowernumber="'+ row.patron_id +'" data-biblionumber="'+ biblio_id +'" data-reserve_id="'+ row.hold_id +'" data-date="'+ row.hold_date +'"><i class="fa fa-lg fa-rotate-90 icon-unset-lowest" aria-hidden="true"></i></a>';
771
                        } else {
772
                            return '<a class="hold-arrow toggle-lowest-priority" title="Set lowest priority" data-op="cud-setLowestPriority" data-borrowernumber="'+ row.patron_id +'" data-biblionumber="'+ biblio_id +'" data-reserve_id="'+ row.hold_id +'" data-date="'+ row.hold_date +'"><i class="fa fa-lg fa-rotate-90 icon-set-lowest" aria-hidden="true"></i></a>';
773
                        }
774
                    }
775
                }
776
            },
777
            {
778
                data: "hold_id",
779
                orderable: false,
780
                searchable: false,
781
                render: function(data, type, row, meta) {
782
                    return '<a class="cancel-hold" title="Cancel hold" reserve_id="'+data+'"><i class="fa fa-trash text-danger" aria-label="Cancel hold"></i></a>';
783
                }
784
            },
785
            {
786
                data: "hold_id",
787
                orderable: false,
788
                searchable: false,
789
                render: function(data, type, row, meta) {
790
                    if (row.status) {
791
                        var link_value = row.status == 'T' ? __("Revert transit status") : __("Revert waiting status");
792
                        return '<a class="btn btn-default submit-form-link" href="#" id="revert_hold_'+data+'" data-op="cud-move" data-where="down" data-first_priority="1" data-last_priority="'+ totalHolds +'" data-prev_priority="0" data-next_priority="1" data-borrowernumber="'+ row.patron_id +'" data-biblionumber="'+ biblio_id +'" data-itemnumber="'+ row.item_id +'" data-reserve_id="'+ row.hold_id +'" data-date="'+ row.hold_date +'" data-action="request.pl" data-method="post">'+ link_value +'</a>';
793
                    } else {
794
                        let td = '';
795
                        if (SuspendHoldsIntranet) {
796
                            td += '<button class="btn btn-default btn-xs toggle-suspend" data-id="'+data+'" data-biblionumber="'+biblio_id+'" data-suspended="'+row.suspended+'">'
797
                            if ( row.suspended ) {
798
                                td += '<i class="fa fa-play" aria-hidden="true"></i> '+__("Resume")+'</button>';
799
                            } else {
800
                                td += '<i class="fa fa-pause" aria-hidden="true"></i> '+__("Suspend")+'</button>';
801
                            }
802
                            if (AutoResumeSuspendedHolds) {
803
                                if (row.suspended) {
804
                                    td += '<label for="suspend_until_'+data+'">'+__("Suspend on")+' </label>';
805
                                } else {
806
                                    td += '<label for="suspend_until_'+data+'">'+__("Suspend until")+' </label>';
807
                                }
808
                                td += '<input type="text" name="suspend_until_'+data+'" data-id="'+data+'" size="10" value="'+$date(row.suspended_until)+'" class="suspenddate" data-flatpickr-futuredate="true" data-current-date="'+row.suspended_until+'" />';
809
                            }
810
                            return td;
811
                        } else {
812
                            return null;
813
                        }
814
                    }
815
                }
816
            },
817
            {
818
                data: "hold_id",
819
                orderable: false,
820
                searchable: false,
821
                render: function(data, type, row, meta) {
822
                    return '<a class="btn btn-default btn-xs printholdslip" data-reserve_id="'+data+'">'+__("Print slip")+'</a>';
823
                }
824
            },
825
        ]
826
    },hold_table_settings);
827
    $(table_id).on( 'draw.dt', function () {
828
        // Remove the search box. Don't know why it isn't working in the table settings
829
        $(this).parent().find(".dataTables_filter, .dt_button_clear_filter").remove();
830
        let multiselect = false;
831
        var MSG_CANCEL_SELECTED = _("Cancel selected (%s)");
832
        $('.cancel_selected_holds').html(MSG_CANCEL_SELECTED.format($('.holds_table .select_hold:checked').length));
833
        $('.holds_table .select_hold').each(function() {
834
            if(localStorage.selectedHolds && localStorage.selectedHolds.includes($(this).data('id'))) {
835
                $(this).prop('checked', true);
836
            }
837
        });
838
        $('.holds_table .select_hold_all').on("click",function() {
839
            var table = $(this).parents('.holds_table');
840
            var count = $('.select_hold:checked', table).length;
841
            $('.select_hold', table).prop('checked', !count);
842
            $(this).prop('checked', !count);
843
            $(this).parent().parent().toggleClass('selected');
844
            $('.cancel_selected_holds').html(MSG_CANCEL_SELECTED.format($('.holds_table .select_hold:checked').length));
845
            localStorage.selectedHolds = $('.holds_table .select_hold:checked').toArray().map(el => $(el).data('id'));
846
            multiselect = true;
847
848
        });
849
        $('.holds_table .select_hold').on("click", function() {
850
            var table = $(this).parents('.holds_table');
851
            var count = $('.select_hold:not(:checked)', table).length;
852
            $('.select_hold_all', table).prop('checked', !count);
853
            $(this).parent().parent().toggleClass('selected');
854
            $('.cancel_selected_holds').html(MSG_CANCEL_SELECTED.format($('.holds_table .select_hold:checked').length));
855
            localStorage.selectedHolds = $('.holds_table .select_hold:checked').toArray().map(el => $(el).data('id'));
856
            multiselect = true;
857
        });
858
        $(".cancel-hold").on("click",function(e) {
859
            e.preventDefault;
860
            var res_id = $(this).attr('reserve_id');
861
            $('.select_hold').prop('checked', false);
862
            $('.select_hold_all').prop('checked', false);
863
            $('.cancel_selected_holds').html(MSG_CANCEL_SELECTED.format(0));
864
            $('#cancelModal').modal('show').find('#cancelModalConfirmBtn').attr("data-id", res_id);
865
            delete localStorage.selectedHolds;
866
        });
867
        $('.cancel_selected_holds').on("click", function(e) {
868
            e.preventDefault();
869
            if($('.holds_table .select_hold:checked').length) {
870
                delete localStorage.selectedHolds;
871
                $('#cancelModal').modal('show');
872
            }
873
            return false;
874
        });
875
        $("#cancelModalConfirmBtn").one("click",function(e) {
876
            e.preventDefault();
877
            let hold_ids;
878
            const hold_id = $('#cancelModal').modal('show').find('#cancelModalConfirmBtn').attr("data-id");
879
            let reason = $("#modal-cancellation-reason").val();
880
            if (hold_id) {
881
                hold_ids = [hold_id];
882
            } else {
883
                hold_ids = $('.holds_table .select_hold:checked').toArray().map(el => $(el).data('id'));
884
            }
885
            $('#cancelModal').find('.modal-footer #cancelModalConfirmBtn').before('<img src="/intranet-tmpl/prog/img/spinner-small.gif" alt="" style="padding-right: 10px;"/>');
886
            deleteHolds(hold_ids, reason);
887
            $('#cancelModal').modal('show').find('#cancelModalConfirmBtn').attr("data-id", "");
888
            
889
        });
890
        async function deleteHolds (hold_ids, reason) {
891
            for (const hold_id of hold_ids) {
892
                await deleteHold(hold_id, reason);
893
                $('#cancelModal').find('.modal-body').append('<p class="hold-cancelled">'+__("Hold")+' '+hold_id+' '+__("cancelled")+'</p>');
894
                await new Promise(resolve => setTimeout(resolve, 1000));
895
            }
896
            holdsQueueTable.api().ajax.reload(null, false);
897
            setTimeout(() => {
898
                $('#cancelModal').modal('hide');
899
                $('#cancelModal').find('.modal-footer #cancelModalConfirmBtn').prev('img').remove();
900
                $('#cancelModal').find('.modal-body').find('.hold-cancelled').remove();
901
            });
902
        }
903
        async function deleteHold(hold_id, reason) {
904
            try {
905
                await $.ajax({
906
                    method: "DELETE",
907
                    url: '/api/v1/holds/' + encodeURIComponent(hold_id),
908
                    data: JSON.stringify(reason),
909
                });
910
            } catch (error) {
911
                console.error("Error when deleting hold: " + hold_id);
912
            }
913
        }
914
        $(".holddate, .expirationdate").flatpickr({
915
            dateFormat: flatpickr_dateformat_string,
916
            onChange: function (selectedDates, dateStr, instance){
917
                let hold_id = $(instance.input).attr('data-id');
918
                let fieldname = $(instance.input).attr('name');
919
                let current_date = $(instance.input).attr('data-current-date');
920
                const date = new Date(selectedDates);
921
                const year = date.getFullYear();
922
                const month = String(date.getMonth() + 1).padStart(2, '0');
923
                const day = String(date.getDate()).padStart(2, '0');
924
                let newdate;
925
                if (year && month && day) {
926
                    newdate = [year, month, day].join('-');
927
                }
928
                multiChange[hold_id] = fieldname == "hold_date" ? {"hold_date": newdate} : { "expiration_date": dateStr };
929
                let req = fieldname == "hold_date" ? { "hold_date": newdate } : { "expiration_date": newdate };
930
                if (current_date != newdate && !multiselect) {
931
                    $.ajax({
932
                        method: "PATCH",
933
                        url: '/api/v1/holds/' + encodeURIComponent(hold_id),
934
                        contentType: 'application/json',
935
                        data: JSON.stringify(req),
936
                        success: function( data ){ holdsQueueTable.api().ajax.reload(null, false); },
937
                        error: function( jqXHR, textStatus, errorThrown) {
938
                            holdsQueueTable.api().ajax.reload(null, false);
939
                        },
940
                    });
941
                }
942
            }
943
        });
944
        $(".suspenddate").flatpickr({
945
            dateFormat: flatpickr_dateformat_string,
946
            onChange: function (selectedDates, dateStr, instance){
947
                let hold_id = $(instance.input).data('id');
948
                let current_date = $(instance.input).attr('data-current-date');
949
                const date = new Date(selectedDates);
950
                const year = date.getFullYear();
951
                const month = String(date.getMonth() + 1).padStart(2, '0');
952
                const day = String(date.getDate()).padStart(2, '0');
953
                const newdate = [year, month, day].join('-');
954
                const method = dateStr ? 'POST' : 'DELETE';
955
                multiChange[hold_id] = {suspended_until: dateStr};
956
                if (current_date != newdate && !multiselect) {
957
                    $.ajax({
958
                        method: method,
959
                        url: '/api/v1/holds/' + encodeURIComponent(hold_id) +'/suspension',
960
                        contentType: 'application/json',
961
                        data: JSON.stringify({ "end_date": newdate }),
962
                        success: function( data ){ holdsQueueTable.api().ajax.reload(null, false); },
963
                        error: function( jqXHR, textStatus, errorThrown) {
964
                            holdsQueueTable.api().ajax.reload(null, false);
965
                        },
966
                    });
967
                }
968
            }
969
        });
970
        $(".toggle-suspend").one("click",function(e) {
971
            e.preventDefault();
972
            const hold_id = $(this).data('id');
973
            const suspended = $(this).attr('data-suspended');
974
            const method = suspended == 'true' ? 'DELETE' : 'POST';
975
            if (!multiselect) {
976
                $.ajax({
977
                    method: method,
978
                    url: '/api/v1/holds/' + encodeURIComponent(hold_id) +'/suspension',
979
                    success: function( data ){ holdsQueueTable.api().ajax.reload(null, false); },
980
                    error: function( jqXHR, textStatus, errorThrown) {
981
                        holdsQueueTable.api().ajax.reload(null, false);
982
                        alert('There was an error:'+textStatus+" "+errorThrown);
983
                    },
984
                });
985
            }
986
        });
987
        $(".rank-request").on("change", function(e){
988
            e.preventDefault();
989
            const hold_id = $(this).data('id');
990
            let priority = e.target.value;
991
            multiChange[hold_id] = {priority: priority};
992
            if (!multiselect) {
993
                $.ajax({
994
                    method: "PUT",
995
                    url: '/api/v1/holds/' + encodeURIComponent(hold_id) +'/priority',
996
                    data: JSON.stringify(priority),
997
                    success: function( data ){ holdsQueueTable.api().ajax.reload(null, false); },
998
                    error: function( jqXHR, textStatus, errorThrown) {
999
                        alert('There was an error:'+textStatus+" "+errorThrown);
1000
                    },
1001
                });
1002
            }
1003
        });
1004
        $(".move-hold").one("click", function(e){
1005
            e.preventDefault();
1006
            let toPosition = $(this).attr('data-move-hold');
1007
            let priority = $(this).attr('data-priority');
1008
            var res_id = $(this).attr('reserve_id');
1009
            var moveTo;
1010
            if (toPosition == 'up'){
1011
                moveTo = parseInt(priority)-1;
1012
            }
1013
            if (toPosition == 'down'){
1014
                moveTo = parseInt(priority)+1;
1015
            }
1016
            if (toPosition == 'top'){
1017
                moveTo = 1;
1018
            }
1019
            if (toPosition == 'bottom'){
1020
                moveTo = totalHolds;
1021
            }
1022
            if (!multiselect) {
1023
                $.ajax({
1024
                    method: "PUT",
1025
                    url: '/api/v1/holds/' + encodeURIComponent(res_id) +'/priority',
1026
                    data: JSON.stringify(moveTo),
1027
                    success: function( data ){
1028
                        holdsQueueTable.api().ajax.reload(null, false);
1029
                    },
1030
                    error: function( jqXHR, textStatus, errorThrown) {
1031
                        alert('There was an error:'+textStatus+" "+errorThrown);
1032
                    },
1033
                });
1034
            }
1035
        });
1036
        $(".toggle-lowest-priority").one("click", function(e){
1037
            e.preventDefault();
1038
            var res_id = $(this).attr('data-reserve_id');
1039
            $.ajax({
1040
                method: "PUT",
1041
                url: '/api/v1/holds/' + encodeURIComponent(res_id) +'/lowest_priority',
1042
                success: function( data ){ holdsQueueTable.api().ajax.reload(null, false); },
1043
                error: function( jqXHR, textStatus, errorThrown) {
1044
                    alert('There was an error:'+textStatus+" "+errorThrown);
1045
                },
1046
            });
1047
        });
1048
        $(".hold_location_select").on("change", function(){
1049
            $(this).prop("disabled",true);
1050
            var cur_select = $(this);
1051
            var res_id = $(this).attr('reserve_id');
1052
            multiChange[res_id] = {pickup_library_id: $(this).val()};
1053
            if (!multiselect) {
1054
                $(this).after('<div id="updating_reserveno'+res_id+'" class="waiting"><img src="/intranet-tmpl/prog/img/spinner-small.gif" alt="" /><span class="waiting_msg"></span></div>');
1055
                let api_url = '/api/v1/holds/' + encodeURIComponent(res_id) + '/pickup_location';
1056
                $.ajax({
1057
                    method: "PUT",
1058
                    url: api_url,
1059
                    data: JSON.stringify({ "pickup_library_id": $(this).val() }),
1060
                    headers: { "x-koha-override": "any" },
1061
                    success: function( data ){ holdsQueueTable.api().ajax.reload(null, false); },
1062
                    error: function( jqXHR, textStatus, errorThrown) {
1063
                        alert('There was an error:'+textStatus+" "+errorThrown);
1064
                        cur_select.prop("disabled",false);
1065
                        $("#updating_reserveno"+res_id).remove();
1066
                        cur_select.val( cur_select.children('option[selected="selected"]').val() );
1067
                    },
1068
                });
1069
            }
1070
        });
1071
        $('.printholdslip').one('click', function(){
1072
            var reserve_id = $(this).attr('data-reserve_id');
1073
            window.open("/cgi-bin/koha/circ/hold-transfer-slip.pl?reserve_id=" + reserve_id);
1074
            return false;
1075
        });
1076
    });
1077
1078
    $('.update_selected_holds').on('click', function (e) {
1079
        const data = []
1080
        holdsQueueTable.api().rows('.selected').every(function (index, element) {
1081
            data.push(this.data());
1082
        });
1083
        fieldNames = {
1084
            hold_id: 'reserve_id',
1085
            hold_date: 'reservedate',
1086
            pickup_library_id: 'pickup',
1087
            item_id: 'itemnumber',
1088
            expiration_date: 'expirationdate',
1089
            suspended_until: 'suspend_until',
1090
            priority: 'rank-request',
1091
        };
1092
        let biblionumberInput = $("<input>").attr({
1093
            type: "hidden",
1094
            name: "biblionumber",
1095
            value: biblio_id
1096
        });
1097
        $("#existing_holds").append(biblionumberInput);
1098
        data.forEach((row) => {
1099
            Object.keys(row).forEach((key) => {
1100
                let update = multiChange[row.hold_id];
1101
                if (update && update[key]) {
1102
                    row[key] = update[key];
1103
                }
1104
                if (fieldNames[key] && row[key] != null) {
1105
                    let input = $("<input>").attr({
1106
                        type: "hidden",
1107
                        name: fieldNames[key],
1108
                        value: row[key]
1109
                    });
1110
                    $("#existing_holds").append(input);
1111
                }
1112
            });
1113
        });
1114
    });
1115
}
(-)a/reserve/request.pl (-54 / +29 lines)
Lines 595-600 if ( ( $findborrower && $borrowernumber_hold || $findclub && $club_hold ) Link Here
595
595
596
        # existingreserves building
596
        # existingreserves building
597
        my @reserveloop;
597
        my @reserveloop;
598
        my $total_holds = 0;
599
        my $hold_branches = [];
600
        my $hold_itemtypes = [];
598
        my $always_show_holds = $input->cookie('always_show_holds');
601
        my $always_show_holds = $input->cookie('always_show_holds');
599
        $template->param( always_show_holds => $always_show_holds );
602
        $template->param( always_show_holds => $always_show_holds );
600
        my $show_holds_now = $input->param('show_holds_now');
603
        my $show_holds_now = $input->param('show_holds_now');
Lines 610-670 if ( ( $findborrower && $borrowernumber_hold || $findclub && $club_hold ) Link Here
610
                    )->unblessed
613
                    )->unblessed
611
                }
614
                }
612
            };
615
            };
613
            my @reserves = Koha::Holds->search( { biblionumber => $biblionumber }, { order_by => 'priority' } )->as_list;
616
            $total_holds = Koha::Holds->search( { biblionumber => $biblionumber } )->count;
614
            foreach my $res (
617
            my $branches = Koha::Holds->search(
615
                sort {
618
                {
616
                    my $a_found = $a->found() || '';
619
                    biblionumber => $biblionumber,
617
                    my $b_found = $a->found() || '';
620
                },
618
                    $a_found cmp $b_found;
621
                {
619
                } @reserves
622
                    select   => [ { distinct => 'branchcode' } ],
620
              )
623
                    as       => [qw( branchcode )],
621
            {
622
                my %reserve;
623
                if ( $res->is_found() ) {
624
                    $reserve{'holdingbranch'} = $res->item()->holdingbranch();
625
                    $reserve{'biblionumber'}  = $res->item()->biblionumber();
626
                    $reserve{'barcodenumber'} = $res->item()->barcode();
627
                    $reserve{'wbrcode'}       = $res->branchcode();
628
                    $reserve{'itemnumber'}    = $res->itemnumber();
629
                    $reserve{'wbrname'}       = $res->branch()->branchname();
630
                    $reserve{'atdestination'} = $res->is_at_destination();
631
                    $reserve{'desk_name'}     = ( $res->desk() ) ? $res->desk()->desk_name() : '' ;
632
                    $reserve{'found'}     = $res->is_found();
633
                    $reserve{'inprocessing'} = $res->is_in_processing();
634
                    $reserve{'intransit'} = $res->is_in_transit();
635
                }
636
                elsif ( $res->priority() > 0 ) {
637
                    if ( my $item = $res->item() )  {
638
                        $reserve{'itemnumber'}      = $item->id();
639
                        $reserve{'barcodenumber'}   = $item->barcode();
640
                        $reserve{'item_level_hold'} = 1;
641
                    }
642
                }
624
                }
643
                $reserve{'expirationdate'} = $res->expirationdate;
625
            )->unblessed;
644
                $reserve{'date'}           = $res->reservedate;
626
            
645
                $reserve{'borrowernumber'} = $res->borrowernumber();
627
            $hold_branches = [ map { $_->{branchcode} } @$branches ];
646
                $reserve{'biblionumber'}   = $res->biblionumber();
628
            my $itemtypes = Koha::Holds->search(
647
                $reserve{'patron'}         = $res->borrower;
629
                {
648
                $reserve{'notes'}          = $res->reservenotes();
630
                    biblionumber => $biblionumber,
649
                $reserve{'waiting_date'}   = $res->waitingdate();
631
                },
650
                $reserve{'ccode'}          = $res->item() ? $res->item()->ccode() : undef;
632
                {
651
                $reserve{'barcode'}        = $res->item() ? $res->item()->barcode() : undef;
633
                    select   => [ { distinct => 'itemtype' } ],
652
                $reserve{'priority'}       = $res->priority();
634
                    as       => [qw( itemtype )],
653
                $reserve{'lowestPriority'} = $res->lowestPriority();
654
                $reserve{'suspend'}        = $res->suspend();
655
                $reserve{'suspend_until'}  = $res->suspend_until();
656
                $reserve{'reserve_id'}     = $res->reserve_id();
657
                $reserve{itemtype}         = $res->itemtype();
658
                $reserve{branchcode}       = $res->branchcode();
659
                $reserve{non_priority}     = $res->non_priority();
660
                $reserve{object}           = $res;
661
662
                if ( $holds_count_per_patron->{ $reserve{'borrowernumber'} } == 1 ) {
663
                    $reserve{'change_hold_type_allowed'} = 1;
664
                }
635
                }
665
636
            )->unblessed;
666
                push( @reserveloop, \%reserve );
637
            
667
            }
638
            $hold_itemtypes = [ map { $_->{itemtype} ? $_->{itemtype} : 'any' } @$itemtypes ];
668
        }
639
        }
669
640
670
        # get the time for the form name...
641
        # get the time for the form name...
Lines 692-702 if ( ( $findborrower && $borrowernumber_hold || $findclub && $club_hold ) Link Here
692
        $biblioloopiter{author} = $biblio->author;
663
        $biblioloopiter{author} = $biblio->author;
693
        $biblioloopiter{rank} = $fixedRank;
664
        $biblioloopiter{rank} = $fixedRank;
694
        $biblioloopiter{reserveloop} = \@reserveloop;
665
        $biblioloopiter{reserveloop} = \@reserveloop;
666
        $biblioloopiter{total_holds} = $total_holds;
667
        $biblioloopiter{hold_branches} = $hold_branches;
668
        $biblioloopiter{hold_itemtypes} = $hold_itemtypes;
695
669
696
        if (@reserveloop) {
670
        if (@reserveloop) {
697
            $template->param( reserveloop => \@reserveloop );
671
            $template->param( reserveloop => \@reserveloop );
698
        }
672
        }
699
673
674
        $template->param( total_holds => $total_holds );
675
700
        if ( $patron && $multi_hold ) {
676
        if ( $patron && $multi_hold ) {
701
            # Add the valid pickup locations
677
            # Add the valid pickup locations
702
            my @pickup_locations = $biblio->pickup_locations({ patron => $patron })->as_list;
678
            my @pickup_locations = $biblio->pickup_locations({ patron => $patron })->as_list;
703
- 

Return to bug 23269