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

(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/stockrotation-toolbar.inc (+9 lines)
Line 0 Link Here
1
[% USE Koha %]
2
<div id="toolbar" class="btn-toolbar">
3
    [% IF no_op_set %]
4
        <a id="addrota" class="btn btn-small" href="/cgi-bin/koha/tools/stockrotation.pl?op=create_edit_rota"><i class="fa fa-plus"></i> New rota</a>
5
    [% END %]
6
    [% IF op == 'manage_stages' %]
7
        <a id="addstage" class="btn btn-small" href="/cgi-bin/koha/tools/stockrotation.pl?op=create_edit_stage&amp;rota_id=[% rota_id %]"><i class="fa fa-plus"></i> New stage</a>
8
    [% END %]
9
</div>
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/stockrotation.tt (+435 lines)
Line 0 Link Here
1
[% USE Koha %]
2
[% USE Branches %]
3
[% INCLUDE 'doc-head-open.inc' %]
4
<title>Koha &rsaquo; Stock Rotation</title>
5
[% INCLUDE 'doc-head-close.inc' %]
6
<script type="text/javascript" src="[% interface %]/[% theme %]/js/pages/stockrotation.js"></script>
7
</head>
8
9
<body>
10
[% INCLUDE 'header.inc' %]
11
[% INCLUDE 'patron-search.inc' %]
12
13
<div id="breadcrumbs">
14
         <a href="/cgi-bin/koha/mainpage.pl">Home</a>
15
&rsaquo; <a href="/cgi-bin/koha/tools/tools-home.pl">Tools</a>
16
&rsaquo; Stock Rotation
17
</div>
18
19
<div id="doc3" class="yui-t2">
20
    <div id="bd">
21
        <div id="yui-main">
22
            <div id="stockrotation" class="yui-b">
23
24
                <h1>Stock Rotation</h1>
25
26
                [% IF no_op_set %]
27
28
                    [% INCLUDE 'stockrotation-toolbar.inc' %]
29
30
                    [% IF existing_rotas.size > 0 %]
31
                        <h3>Manage existing rotas</h3>
32
                        <table class="rotas_table" role="grid">
33
                            <thead>
34
                                <th>Name</th>
35
                                <th>Cyclical</th>
36
                                <th>Active</th>
37
                                <th>Description</th>
38
                                <th>Number of items</th>
39
                                <th>&nbsp;</th>
40
                            </thead>
41
                            <tbody>
42
                                [% FOREACH rota IN existing_rotas %]
43
                                    <tr>
44
                                        <td>[% rota.title %]</td>
45
                                        <td>[% rota.cyclical ? 'Yes' : 'No'%]</td>
46
                                        <td>[% rota.active ? 'Yes' : 'No'%]</td>
47
                                        <td>[% rota.description %]</td>
48
                                        <td>[% rota.stockrotationitems.count %]</td>
49
                                        <td class="actions">
50
                                            <a class="btn btn-mini" href="?op=create_edit_rota&amp;rota_id=[% rota.rota_id %]">
51
                                                <i class="fa fa-pencil"></i>
52
                                                Edit
53
                                            </a>
54
                                            <div class="btn-group" role="group">
55
                                                <button type="button" class="btn btn-mini dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
56
                                                    Manage
57
                                                    <i class="fa fa-caret-down"></i>
58
                                                </button>
59
                                                <ul class="dropdown-menu">
60
                                                    <li><a href="?op=manage_stages&amp;rota_id=[% rota.rota_id %]">Stages</a></li>
61
                                                    [% IF CAN_user_stockrotation_can_add_items_rotas && rota.stockrotationstages.count > 0 %]
62
                                                    <li><a href="?op=manage_items&amp;rota_id=[% rota.rota_id %]">Items</a></li>
63
                                                    [% END %]
64
                                                </ul>
65
                                            </div>
66
                                            <a class="btn btn-mini" href="?op=toggle_rota&amp;rota_id=[% rota.rota_id %]">
67
                                                <i class="fa fa-power-off"></i>
68
                                                [% IF !rota.active %]
69
                                                    Activate
70
                                                [% ELSE %]
71
                                                    Deactivate
72
                                                [% END %]
73
                                            </a>
74
                                        </td>
75
                                    </tr>
76
                                [% END %]
77
                            </tbody>
78
                        </table>
79
                    [% END %]
80
81
                [% ELSIF (op == 'create_edit_rota') %]
82
83
                    [% IF rota.rota_id %]
84
                        <h3>Edit "[% rota.title %]"</h3>
85
                    [% ELSE %]
86
                        <h3>Create new rota</h3>
87
                    [% END %]
88
89
                    [% IF error == 'invalid_form' %]
90
                    <div class="dialog alert">
91
                        <h3>There was a problem with your form submission</h3>
92
                    </div>
93
                    [% END %]
94
95
                    <form id="rota_form" method="post" enctype="multipart/form-data" class="validated">
96
                        <fieldset class="rows">
97
                            <ol>
98
                                <li>
99
                                    <label class="required" for="title">Name:</label>
100
                                    <input type="text" id="title" name="title" value="[% rota.title %]" required="required" placeholder="Rota name">
101
                                    <span class="required">Required</span>
102
                                </li>
103
                                <li>
104
                                    <label for="cyclical">Cyclical:</label>
105
                                    <select name="cyclical" id="cyclical">
106
                                        [% IF rota.cyclical %]
107
                                            <option value="1" selected>Yes</option>
108
                                            <option value="0">No</option>
109
                                        [% ELSE %]
110
                                            <option value="1">Yes</option>
111
                                            <option value="0" selected>No</option>
112
                                        [% END %]
113
                                    </select>
114
                                </li>
115
                                <li>
116
                                    <label for="active">Active:</label>
117
                                    <select name="active" id="active">
118
                                        [% IF rota.active %]
119
                                            <option value="1" selected>Yes</option>
120
                                            <option value="0">No</option>
121
                                        [% ELSE %]
122
                                            <option value="1">Yes</option>
123
                                            <option value="0" selected>No</option>
124
                                        [% END %]
125
                                    </select>
126
                                </li>
127
                                <li>
128
                                    <label for="description">Description:</label>
129
                                    <textarea id="description" name="description" placeholder="Rota description">[% rota.description %]</textarea>
130
                                </li>
131
                            </ol>
132
                        </fieldset>
133
                        <fieldset class="action">
134
                            <input type="submit" value="Submit">
135
                            <a href="/cgi-bin/koha/tools/stockrotation.pl" class="cancel">Cancel</a>
136
                        </fieldset>
137
                        [% IF rota.rota_id %]
138
                            <input type="hidden" name="id" value="[% rota.rota_id %]">
139
                        [% END %]
140
                        <input type="hidden" name="op" value="process_rota">
141
                    </form>
142
143
                [% ELSIF (op == 'manage_stages') %]
144
145
                    [% INCLUDE 'stockrotation-toolbar.inc' %]
146
147
                    [% IF existing_stages.size > 0 %]
148
                        <div id="manage_stages">
149
                            <h3>Manage stages</h3>
150
                            <div id="ajax_status"
151
                                data-saving-msg="Saving changes..."
152
                                data-success-msg=""
153
                                data-failed-msg="Error: ">
154
                                <span id="ajax_saving_msg"></span>
155
                                <i id="ajax_saving_icon" class="fa fa-spinner fa-spin"></i>
156
                                <i id="ajax_success_icon" class="fa fa-check"></i>
157
                                <i id="ajax_failed_icon" class="fa fa-times"></i>
158
                                <span id="ajax_success_msg"></span>
159
                                <span id="ajax_failed_msg"></span>
160
                            </div>
161
                            <div id="stage_list_headings">
162
                                <span class="stagename">Branch</span>
163
                                <span class="stageduration">Duration (days)</span>
164
                            </div>
165
                            <ul id="sortable_stages" data-rota-id="[% rota.rota_id %]">
166
                                [% FOREACH stage IN existing_stages %]
167
                                    <li id="stage_[% stage.stage_id %]">
168
                                        <span class="stagename">
169
                                            [% IF existing_stages.size > 1 %]
170
                                                <i class="drag_handle fa fa-lg fa-bars"></i>
171
                                            [% END %]
172
                                            [% Branches.GetName(stage.branchcode_id) %]
173
                                        </span>
174
                                        <span class="stageduration">[% stage.duration %]</span>
175
                                        <span class="stageactions">
176
                                            <a class="btn btn-mini" href="?op=create_edit_stage&amp;stage_id=[% stage.stage_id %]">
177
                                                <i class="fa fa-pencil"></i> Edit
178
                                            </a>
179
                                            <a class="btn btn-mini" href="?op=confirm_delete_stage&amp;stage_id=[% stage.stage_id %]">
180
                                                <i class="fa fa-trash"></i> Delete
181
                                            </a>
182
                                        </span>
183
                                    </li>
184
                                [% END %]
185
                            </ul>
186
                        </div>
187
                    [% END %]
188
189
                    <p><a href="stockrotation.pl">Return to rotas</a></p>
190
191
                [% ELSIF (op == 'create_edit_stage') %]
192
193
                    [% IF stage.id %]
194
                        <h3>Edit "[% Branches.GetName(stage.branchcode_id) %]"</h3>
195
                    [% ELSE %]
196
                        <h3>Create new stage</h3>
197
                    [% END %]
198
199
                    [% IF error == 'invalid_form' %]
200
                    <div class="dialog alert">
201
                        <h3>There was a problem with your form submission</h3>
202
                    </div>
203
                    [% END %]
204
205
                    <form id="stage_form" method="post" enctype="multipart/form-data" class="validated">
206
                        <fieldset class="rows">
207
                            <ol>
208
                                <li>
209
                                    <label class="required" for="branch">Branch:</label>
210
                                    <select name="branchcode" id="branch">
211
                                        [% FOREACH branch IN branches %]
212
                                            [% IF branch.branchcode == stage.branchcode_id %]
213
                                                <option value="[% branch.branchcode %]" selected>[% Branches.GetName(branch.branchcode) %]</option>
214
                                            [% ELSE %]
215
                                                <option value="[% branch.branchcode %]">[% Branches.GetName(branch.branchcode) %]</option>
216
                                            [% END %]
217
                                        [% END %]
218
                                    </select>
219
                                    <span class="required">Required</span>
220
                                </li>
221
                                <li>
222
                                    <label class="required" for="duration">Duration:</label>
223
                                    <input type="text" id="duration" name="duration" value="[% stage.duration %]" required="required" placeholder="Duration (days)">
224
                                    <span class="required">Required</span>
225
                                </li>
226
                            </ol>
227
                        </fieldset>
228
                        <fieldset class="action">
229
                            <input type="submit" value="Submit">
230
                            <a href="/cgi-bin/koha/tools/stockrotation.pl?op=manage_stages&amp;rota_id=[% rota_id %]" class="cancel">Cancel</a>
231
                        </fieldset>
232
                        <input type="hidden" name="stage_id" value="[% stage.id %]">
233
                        <input type="hidden" name="rota_id" value="[% rota_id %]">
234
                        <input type="hidden" name="op" value="process_stage">
235
                    </form>
236
                [% ELSIF (op == 'confirm_remove_from_rota') %]
237
238
                    <div class="dialog alert">
239
                        <h3>Are you sure you wish to remove this item from it's rota</h3>
240
                        <p>
241
                            <a class="btn approve" href="?op=remove_item_from_stage&amp;item_id=[% item_id %]&amp;stage_id=[% stage_id %]&amp;rota_id=[% rota_id %]"><i class="fa fa-fw fa-check"></i>Yes</a>
242
                            <a class="btn deny" href="?op=manage_items&amp;rota_id=[% rota_id %]"><i class="fa fa-fw fa-remove"></i>No</a>
243
                        </p>
244
                    </div>
245
                [% ELSIF (op == 'confirm_delete_stage') %]
246
247
                    <div class="dialog alert">
248
                        <h3>Are you sure you want to delete this stage?</h3>
249
                        [% IF stage.stockrotationitems.count > 0 %]
250
                            <p>This stage contains the following item(s):</p>
251
                            <ul>
252
                                [% FOREACH item IN stage.stockrotationitems %]
253
                                    <li>[% item.itemnumber.biblio.title %] (Barcode: [% item.itemnumber.barcode %])</li>
254
                                [% END %]
255
                            </ul>
256
                        [% END %]
257
                        <p>
258
                            <a class="btn approve" href="?op=delete_stage&amp;stage_id=[% stage.stage_id %]"><i class="fa fa-fw fa-check"></i>Yes</a>
259
                            <a class="btn deny" href="?op=manage_stages&amp;rota_id=[% stage.rota.rota_id %]"><i class="fa fa-fw fa-remove"></i>No</a>
260
                        </p>
261
                    </div>
262
                [% ELSIF (op == 'manage_items') %]
263
264
                    [% IF error %]
265
                        <div class="dialog alert">
266
                            [% IF error == "item_not_found" %]
267
                                <h3>The item was not found</h3>
268
                            [% ELSIF error == "already_on_rota" %]
269
                                <h3>This item is already on this rota</h3>
270
                            [% END %]
271
                        </div>
272
                    [% END %]
273
274
                    [% IF items.count > 0 %]
275
                        <h3>Manage items assigned to &quot;[% rota.title %]&quot;</h3>
276
                        <table class="items_table" role="grid">
277
                            <thead>
278
                                <th>Barcode</th>
279
                                <th>Title</th>
280
                                <th>Author</th>
281
                                <th>Shelfmark</th>
282
                                <th>In transit</th>
283
                                <th>Stages &amp; duration in days<br>(current stage highlighted)</th>
284
                                <th>&nbsp;</th>
285
                            </thead>
286
                            <tbody>
287
                                [% FOREACH item IN items %]
288
                                    <tr>
289
                                        <td>[% item.itemnumber.barcode %]</td>
290
                                        <td>[% item.itemnumber.biblio.title %]</td>
291
                                        <td>[% item.itemnumber.biblio.author %]</td>
292
                                        <td>[% item.itemnumber.itemcallnumber %]</td>
293
                                        <td>[% item.itemnumber.get_transfer ? 'Yes' : 'No' %]</td>
294
                                        <td>
295
                                            [% FOREACH this_stage IN stages %]
296
                                                [% IF this_stage.stage_id == item.stage.stage_id %]
297
                                                    <span class="stage highlight_stage">
298
                                                [% ELSE %]
299
                                                    <span class="stage">
300
                                                [% END %]
301
                                                [% Branches.GetName(this_stage.branchcode_id) %] ([% this_stage.duration %])
302
                                                </span>
303
                                                &raquo;
304
                                            [% END %]
305
                                            [% IF stages.size > 0 %]
306
                                                <span class="stage">[% rota.cyclical ? 'START' : 'END' %]</span>
307
                                            [% END %]
308
                                        </td>
309
                                        <td class="actions">
310
                                            [% in_transit = item.itemnumber.get_transfer %]
311
                                            [% IF !in_transit && stages.size > 1 %]
312
                                                <a class="btn btn-mini" href="?op=move_to_next_stage&amp;rota_id=[% rota.id %]&amp;item_id=[% item.id %]&amp;stage_id=[% item.stage.stage_id %]">
313
                                            [% ELSE %]
314
                                                <a class="btn btn-mini" disabled>
315
                                            [% END %]
316
                                                <i class="fa fa-arrow-right"></i>
317
                                                Move to next stage
318
                                            </a>
319
                                            [% IF !in_transit %]
320
                                                <a class="btn btn-mini" href="?op=toggle_in_demand&amp;stage_id=[% item.stage.stage_id %]&amp;item_id=[% item.id %]&amp;rota_id=[% rota.id %]">
321
                                            [% ELSE %]
322
                                                <a class="btn btn-mini" disabled>
323
                                            [% END %]
324
                                                <i class="fa fa-fire"></i>
325
                                                [% item.indemand ? 'Remove &quot;In demand&quot;' : 'Add &quot;In demand&quot;' %]
326
                                            </a>
327
                                            [% IF !in_transit %]
328
                                                <a class="btn btn-mini" href="?op=confirm_remove_from_rota&amp;stage_id=[% item.stage.stage_id %]&amp;item_id=[% item.id %]&amp;rota_id=[% rota.id %]">
329
                                            [% ELSE %]
330
                                                <a class="btn btn-mini" disabled>
331
                                            [% END %]
332
                                                <i class="fa fa-trash"></i>
333
                                                Remove from rota
334
                                            </a>
335
                                        </td>
336
                                    </tr>
337
                                [% END %]
338
                            </tbody>
339
                        </table>
340
                    [% END %]
341
342
                    <div>
343
                        <form id="add_rota_item_form" method="post" enctype="multipart/form-data" class="validated">
344
                            <fieldset class="rows">
345
                                <legend>Add item to &quot;[% rota.title %]&quot;</legend>
346
                                <ol>
347
                                    <li>
348
                                        <label for="barcode">Barcode:</label>
349
                                        <input type="text" id="barcode" name="barcode" placeholder="Item barcode" autofocus>
350
                                    </li>
351
                                </ol>
352
                            </fieldset>
353
                            <fieldset class="rows">
354
                                <legend>Use a barcode file</legend>
355
                                <ol>
356
                                    <li>
357
                                        <label for="barcodefile">Barcode file:</label>
358
                                        <input type="file" id="barcodefile" name="barcodefile">
359
                                    </li>
360
                                </ol>
361
                            </fieldset>
362
                            <fieldset class="action">
363
                                <input type="submit" value="Submit">
364
                            </fieldset>
365
                            <input type="hidden" name="rota_id" value="[% rota.id %]">
366
                            <input type="hidden" name="op" value="add_items_to_rota">
367
                        </form>
368
                    </div>
369
                    <p><a href="stockrotation.pl">Return to rotas</a></p>
370
371
                [% ELSIF op == 'add_items_to_rota' %]
372
373
374
                    <div class="dialog alert">
375
                        <h3>Add items to rota report</h3>
376
                        [% IF barcode_status.ok.size > 0 %]
377
                            <h4>Items added to rota:</h4>
378
                            <ul>
379
                                [% FOREACH item_ok IN barcode_status.ok %]
380
                                    <li>[% item_ok.biblio.title %]</li>
381
                                [% END %]
382
                            </ul>
383
                        [% END %]
384
                        [% IF barcode_status.on_this.size > 0 %]
385
                            <h4>Items already on this rota:</h4>
386
                            <ul>
387
                                [% FOREACH item_on_this IN barcode_status.on_this %]
388
                                    <li>[% item_on_this.biblio.title %]</li>
389
                                [% END %]
390
                            </ul>
391
                        [% END %]
392
                        [% IF barcode_status.not_found.size > 0 %]
393
                            <h4>Barcodes not found:</h4>
394
                            <ul>
395
                                [% FOREACH barcode_not_found IN barcode_status.not_found %]
396
                                    <li>[% barcode_not_found %]</li>
397
                                [% END %]
398
                            </ul>
399
                        [% END %]
400
                        [% IF barcode_status.on_other.size > 0 %]
401
                            <h4>Items found on other rotas:</h4>
402
                            <ul>
403
                                [% FOREACH item_on_other IN barcode_status.on_other %]
404
                                    <li>[% item_on_other.biblio.title %]</li>
405
                                [% END %]
406
                            </ul>
407
                        [% END %]
408
                    </div>
409
                    [% IF barcode_status.on_other.size > 0 %]
410
                        <form id="add_rota_item_form" method="post" enctype="multipart/form-data">
411
                            <fieldset>
412
                                <legend>Select items to move to this rota:</legend>
413
                                [% FOREACH item_on_other IN barcode_status.on_other %]
414
                                    <li><input type="checkbox" name="move_item" value="[% item_on_other.itemnumber %]"> [% item_on_other.biblio.title %] (Currently on &quot;[% item_on_other.stockrotationitem.stage.rota.title %]&quot;)</li>
415
                                [% END %]
416
417
                            </fieldset>
418
                            <fieldset class="action">
419
                                <input type="submit" value="Submit">
420
                            </fieldset>
421
                            <input type="hidden" name="rota_id" value="[% rota_id %]">
422
                            <input type="hidden" name="op" value="move_items_to_rota">
423
                        </form>
424
                    [% END %]
425
                    <p><a href="?op=manage_items&amp;rota_id=[% rota_id %]">Return to rota</a></p>
426
427
                [% END %]
428
            </div>
429
        </div>
430
        <div class="yui-b">
431
            [% INCLUDE 'tools-menu.inc' %]
432
        </div>
433
    </div>
434
</div>
435
[% INCLUDE 'intranet-bottom.inc' %]
(-)a/tools/stockrotation.pl (-1 / +519 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/perl
2
3
# Copyright 2016 PTFS-Europe Ltd
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 3 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
=head1 stockrotation.pl
21
22
 Script to handle stockrotation. Including rotas, their associated stages
23
 and items
24
25
=cut
26
27
use Modern::Perl;
28
use CGI;
29
30
use C4::Auth;
31
use C4::Output;
32
33
use Koha::Libraries;
34
use Koha::Stockrotationrotas;
35
use Koha::Stockrotationitems;
36
use Koha::Stockrotationstages;
37
use Koha::Item;
38
use Koha::Util::Stockrotation qw(:ALL);
39
40
my $input = new CGI;
41
42
my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
43
    {
44
        template_name   => 'tools/stockrotation.tt',
45
        query           => $input,
46
        type            => 'intranet',
47
        authnotrequired => 0
48
    }
49
);
50
51
# Grab all passed data
52
# 'our' since Plack changes the scoping
53
# of 'my'
54
our %params = $input->Vars();
55
56
my $op = $params{op};
57
58
if (!defined $op) {
59
60
    # No operation is supplied, we're just displaying the list of rotas
61
    my $rotas = Koha::Stockrotationrotas->search->as_list;
62
63
    $template->param(
64
        existing_rotas => $rotas,
65
        no_op_set      => 1
66
    );
67
68
} elsif ($op eq 'create_edit_rota') {
69
70
    # Edit an existing rota or define a new one
71
    my $rota_id = $params{rota_id};
72
73
    my $rota = {};
74
75
    if (!defined $rota_id) {
76
77
        # No ID supplied, we're creating a new rota
78
        # Create a shell rota hashref
79
        $rota = {
80
            cyclical => 1,
81
            active   => 0
82
        };
83
84
    } else {
85
86
        # ID supplied, we're editing an existing rota
87
        $rota = Koha::Stockrotationrotas->find($rota_id);
88
89
    }
90
91
    $template->param(
92
        rota => $rota,
93
        op   => $op
94
    );
95
96
} elsif ($op eq 'toggle_rota') {
97
98
    # Find and update the active status of the rota
99
    my $rota = Koha::Stockrotationrotas->find($params{rota_id});
100
101
    my $new_active = ($rota->active == 1) ? 0 : 1;
102
103
    $rota->active($new_active)->store;
104
105
    # Return to rotas page
106
    print $input->redirect('stockrotation.pl');
107
108
} elsif ($op eq 'process_rota') {
109
110
    # Get a hashref of the submitted rota data
111
    my $rota = get_rota_from_form();
112
113
    if (!process_rota($rota)) {
114
115
        # The submitted rota was invalid
116
        $template->param(
117
            error => 'invalid_form',
118
            rota => $rota,
119
            op   => 'create_edit_rota'
120
        );
121
122
    } else {
123
124
        # All was well, return to the rotas list
125
        print $input->redirect('stockrotation.pl');
126
127
    }
128
129
} elsif ($op eq 'manage_stages') {
130
131
    my $rota = Koha::Stockrotationrotas->find($params{rota_id});
132
133
    $template->param(
134
        rota            => $rota,
135
        branches        => get_branches(),
136
        existing_stages => get_stages($rota),
137
        rota_id         => $params{rota_id},
138
        op              => $op
139
    );
140
141
} elsif ($op eq 'create_edit_stage') {
142
143
    # Edit an existing stage or define a new one
144
    my $stage_id = $params{stage_id};
145
146
    my $rota_id = $params{rota_id};
147
148
    if (!defined $stage_id) {
149
150
        # No ID supplied, we're creating a new stage
151
        $template->param(
152
            branches => get_branches(),
153
            stage    => {},
154
            rota_id  => $rota_id,
155
            op       => $op
156
        );
157
158
    } else {
159
160
        # ID supplied, we're editing an existing stage
161
        my $stage = Koha::Stockrotationstages->find($stage_id);
162
163
        $template->param(
164
            branches => get_branches(),
165
            stage    => $stage,
166
            rota_id  => $stage->rota->rota_id,
167
            op       => $op
168
        );
169
170
    }
171
172
} elsif ($op eq 'confirm_remove_from_rota') {
173
174
    # Get the stage we're deleting
175
    $template->param(
176
        op       => $op,
177
        rota_id  => $params{rota_id},
178
        stage_id => $params{stage_id},
179
        item_id  => $params{item_id}
180
    );
181
182
} elsif ($op eq 'confirm_delete_stage') {
183
184
    # Get the stage we're deleting
185
    my $stage = Koha::Stockrotationstages->find($params{stage_id});
186
187
    $template->param(
188
        op    => $op,
189
        stage => $stage
190
    );
191
192
} elsif ($op eq 'delete_stage') {
193
194
    # Get the stage we're deleting
195
    my $stage = Koha::Stockrotationstages->find($params{stage_id});
196
197
    # Get the ID of the rota with which this stage is associated
198
    # (so we can return to the "Manage stages" page after deletion)
199
    my $rota_id = $stage->rota->rota_id;
200
201
    $stage->delete;
202
203
    # Return to the stages list
204
    print $input->redirect("?op=manage_stages&rota_id=$rota_id");
205
206
} elsif ($op eq 'process_stage') {
207
208
    # Get a hashref of the submitted stage data
209
    my $stage = get_stage_from_form();
210
211
    # The rota we're managing
212
    my $rota_id = $params{rota_id};
213
214
    if (!process_stage($stage, $rota_id)) {
215
216
        # The submitted stage was invalid
217
        # Get all branches
218
        my $branches = get_branches();
219
220
        $template->param(
221
            error        => 'invalid_form',
222
            all_branches => $branches,
223
            stage        => $stage,
224
            rota_id      => $rota_id,
225
            op           => 'create_edit_stage'
226
        );
227
228
    } else {
229
230
        # All was well, return to the stages list
231
        print $input->redirect("?op=manage_stages&rota_id=$rota_id");
232
233
    }
234
235
} elsif ($op eq 'manage_items') {
236
237
    my $rota = Koha::Stockrotationrotas->find($params{rota_id});
238
239
    # Get all items on this rota, for each prefetch their
240
    # stage and biblio objects
241
    my $items = Koha::Stockrotationitems->search(
242
        { 'stage.rota_id' => $params{rota_id} },
243
        {
244
            prefetch => {
245
                stage => {
246
                    'stockrotationitems' => {
247
                        'itemnumber' => 'biblionumber'
248
                    }
249
                }
250
            }
251
        }
252
    );
253
254
    $template->param(
255
        rota_id  => $params{rota_id},
256
        error    => $params{error},
257
        items    => $items,
258
        branches => get_branches(),
259
        stages   => get_stages($rota),
260
        rota     => $rota,
261
        op       => $op
262
    );
263
264
} elsif ($op eq 'move_to_next_stage') {
265
266
    move_to_next_stage($params{item_id}, $params{stage_id});
267
268
    # Return to the items list
269
    print $input->redirect("?op=manage_items&rota_id=" . $params{rota_id});
270
271
} elsif ($op eq 'toggle_in_demand') {
272
273
    # Toggle the item's in_demand
274
    toggle_indemand($params{item_id}, $params{stage_id});
275
276
    # Return to the items list
277
    print $input->redirect("?op=manage_items&rota_id=".$params{rota_id});
278
279
} elsif ($op eq 'remove_item_from_stage') {
280
281
    # Remove the item from the stage
282
    remove_from_stage($params{item_id}, $params{stage_id});
283
284
    # Return to the items list
285
    print $input->redirect("?op=manage_items&rota_id=".$params{rota_id});
286
287
} elsif ($op eq 'add_items_to_rota') {
288
289
    # The item's barcode,
290
    # which we may or may not have been passed
291
    my $barcode = $params{barcode};
292
293
    # The rota we're adding the item to
294
    my $rota_id = $params{rota_id};
295
296
    # The uploaded file filehandle,
297
    # which we may or may not have been passed
298
    my $barcode_file = $input->upload("barcodefile");
299
300
    # We need to create an array of one or more barcodes to
301
    # insert
302
    my @barcodes = ();
303
304
    # If the barcode input box was populated, use it
305
    push @barcodes, $barcode if $barcode;
306
307
    # Only parse the uploaded file if necessary
308
    if ($barcode_file) {
309
310
        # Call binmode on the filehandle as we want to set a
311
        # UTF-8 layer on it
312
        binmode($barcode_file, ":encoding(UTF-8)");
313
        # Parse the file into an array of barcodes
314
        while (my $barcode = <$barcode_file>) {
315
            $barcode =~ s/\r/\n/g;
316
            $barcode =~ s/\n+/\n/g;
317
            my @data = split(/\n/, $barcode);
318
            push @barcodes, @data;
319
        }
320
321
    }
322
323
    # A hashref to hold the status of each barcode
324
    my $barcode_status = {
325
        ok        => [],
326
        on_other  => [],
327
        on_this   => [],
328
        not_found => []
329
    };
330
331
    # If we have something to work with, do it
332
    get_barcodes_status($rota_id, \@barcodes, $barcode_status) if (@barcodes);
333
334
    # Now we know the status of each barcode, add those that
335
    # need it
336
    if (scalar @{$barcode_status->{ok}} > 0) {
337
338
        add_items_to_rota($rota_id, $barcode_status->{ok});
339
340
    }
341
    # If we were only passed one barcode and it was successfully
342
    # added, redirect back to ourselves, we don't want to display
343
    # a report, redirect also if we were passed no barcodes
344
    if (
345
        scalar @barcodes == 0 ||
346
        (scalar @barcodes == 1 && scalar @{$barcode_status->{ok}} == 1)
347
    ) {
348
349
        print $input->redirect("?op=manage_items&rota_id=$rota_id");
350
351
    } else {
352
353
        # Report on the outcome
354
        $template->param(
355
            barcode_status => $barcode_status,
356
            rota_id        => $rota_id,
357
            op             => $op
358
        );
359
360
    }
361
362
} elsif ($op eq 'move_items_to_rota') {
363
364
    # The barcodes of the items we're moving
365
    my @move = $input->param('move_item');
366
367
    foreach my $item(@move) {
368
369
        # The item we're moving
370
        my $item = Koha::Items->find($item);
371
372
        # Move it to the new rota
373
        $item->add_to_rota($params{rota_id});
374
375
    }
376
377
    # Return to the items list
378
    print $input->redirect("?op=manage_items&rota_id=".$params{rota_id});
379
380
}
381
382
output_html_with_http_headers $input, $cookie, $template->output;
383
384
sub get_rota_from_form {
385
386
    return {
387
        id          => $params{id},
388
        title       => $params{title},
389
        cyclical    => $params{cyclical},
390
        active      => $params{active},
391
        description => $params{description}
392
    };
393
}
394
395
sub get_stage_from_form {
396
397
    return {
398
        stage_id    => $params{stage_id},
399
        branchcode  => $params{branchcode},
400
        duration    => $params{duration}
401
    };
402
}
403
404
sub process_rota {
405
406
    my $sub_rota = shift;
407
408
    # Fields we require
409
    my @required = ('title','cyclical','active');
410
411
    # Count of the number of required fields we have
412
    my $valid = 0;
413
414
    # Ensure we have everything we require
415
    foreach my $req(@required) {
416
417
        if (exists $sub_rota->{$req}) {
418
419
            chomp(my $value = $sub_rota->{$req});
420
            if (length $value > 0) {
421
                $valid++;
422
            }
423
424
        }
425
426
    }
427
428
    # If we don't have everything we need
429
    return 0 if $valid != scalar @required;
430
431
    # Passed validation
432
    # Find the rota we're updating
433
    my $rota = Koha::Stockrotationrotas->find($sub_rota->{id});
434
435
    if ($rota) {
436
437
        $rota->title(
438
            $sub_rota->{title}
439
        )->cyclical(
440
            $sub_rota->{cyclical}
441
        )->active(
442
            $sub_rota->{active}
443
        )->description(
444
            $sub_rota->{description}
445
        )->store;
446
447
    } else {
448
449
        $rota = Koha::Stockrotationrota->new({
450
            title       => $sub_rota->{title},
451
            cyclical    => $sub_rota->{cyclical},
452
            active      => $sub_rota->{active},
453
            description => $sub_rota->{description}
454
        })->store;
455
456
    }
457
458
    return 1;
459
}
460
461
sub process_stage {
462
463
    my ($sub_stage, $rota_id) = @_;
464
465
    # Fields we require
466
    my @required = ('branchcode','duration');
467
468
    # Count of the number of required fields we have
469
    my $valid = 0;
470
471
    # Ensure we have everything we require
472
    foreach my $req(@required) {
473
474
        if (exists $sub_stage->{$req}) {
475
476
            chomp(my $value = $sub_stage->{$req});
477
            if (length $value > 0) {
478
                $valid++;
479
            }
480
481
        }
482
483
    }
484
485
    # If we don't have everything we need
486
    return 0 if $valid != scalar @required;
487
488
    # Passed validation
489
    # Find the stage we're updating
490
    my $stage = Koha::Stockrotationstages->find($sub_stage->{stage_id});
491
492
    if ($stage) {
493
494
        # Updating an existing stage
495
        $stage->branchcode_id(
496
            $sub_stage->{branchcode}
497
        )->duration(
498
            $sub_stage->{duration}
499
        )->store;
500
501
    } else {
502
503
        # Creating a new stage
504
        $stage = Koha::Stockrotationstage->new({
505
            branchcode_id  => $sub_stage->{branchcode},
506
            rota_id        => $rota_id,
507
            duration       => $sub_stage->{duration}
508
        })->store;
509
510
    }
511
512
    return 1;
513
}
514
515
=head1 AUTHOR
516
517
Andrew Isherwood <andrew.isherwood@ptfs-europe.com>
518
519
=cut

Return to bug 11897