Bug 29602: (follow-up) fix duplicate, missing or mismatching <span>
[koha.git] / koha-tmpl / intranet-tmpl / prog / en / modules / tools / inventory.tt
1 [% USE raw %]
2 [% USE Asset %]
3 [% USE AuthorisedValues %]
4 [% USE KohaDates %]
5 [% USE Branches %]
6 [% SET footerjs = 1 %]
7 [% INCLUDE 'doc-head-open.inc' %]
8 <title>Inventory &rsaquo; Tools &rsaquo; Koha</title>
9 [% INCLUDE 'doc-head-close.inc' %]
10 </head>
11
12 <body id="tools_inventory" class="tools">
13 [% INCLUDE 'header.inc' %]
14 [% INCLUDE 'cat-search.inc' %]
15
16 <nav id="breadcrumbs" aria-label="Breadcrumb" class="breadcrumb">
17     <ol>
18         <li>
19             <a href="/cgi-bin/koha/mainpage.pl">Home</a>
20         </li>
21         <li>
22             <a href="/cgi-bin/koha/tools/tools-home.pl">Tools</a>
23         </li>
24
25         [% IF (loop) %]
26             <li>
27                 <a href="/cgi-bin/koha/tools/inventory.pl">Inventory</a>
28             </li>
29             <li>
30                 <a href="#" aria-current="page">
31                     Results
32                 </a>
33             </li>
34         [% ELSE %]
35             <li>
36                 <a href="#" aria-current="page">
37                     Inventory
38                 </a>
39             </li>
40         [% END %]
41     </ol>
42 </nav>
43
44 <div class="main container-fluid">
45     <div class="row">
46         <div class="col-sm-10 col-sm-push-2">
47             <main>
48
49     <h1>Inventory</h1>
50     [% IF (moddatecount) %]<div class="dialog message">[% moddatecount | html %] items modified : datelastseen set to [% date | $KohaDates %]</div>
51     <div class="dialog alert">Number of potential barcodes read: [% LinesRead | html %]</div>[% END %]
52     [% IF (errorfile) %]<div class="dialog alert">[% errorfile | html %] can't be opened</div>[% END %]
53     [% IF (err_length && err_length==1) %]<div class="dialog alert">There was 1 barcode that was too long.</div>[% END %]
54     [% IF (err_length && err_length>1) %]<div class="dialog alert">There were [% err_length | html %] barcodes that were too long.</div>[% END %]
55     [% IF (err_data && err_data==1) %]<div class="dialog alert">There was 1 barcode that contained at least one unprintable character.</div>[% END %]
56     [% IF (err_data && err_data>1) %]<div class="dialog alert">There were [% err_data | html %] barcodes that contained at least one unprintable character.</div>[% END %]
57     [% FOREACH error IN errorloop %]
58         <div class="dialog alert">
59             [% error.barcode | html %]
60             [% IF (error.ERR_BARCODE) %]: barcode not found[% END %]
61             [% IF (error.ERR_WTHDRAWN) %]: item withdrawn[% END %]
62             [% IF (error.ERR_ONLOAN_RET) %]: item was on loan. It was returned before marked as seen[% END %]
63             [% IF (error.ERR_ONLOAN_NOT_RET) %]: item was on loan. couldn't be returned.[% END %]
64         </div>
65     [% END %]
66        [% UNLESS op %]
67
68     <form method="post" id="inventory_form" action="/cgi-bin/koha/tools/inventory.pl" enctype="multipart/form-data">
69         <fieldset class="rows">
70           <legend>Use a barcode file</legend>
71           <ol>
72             <li><label for="uploadbarcodes">Barcode file: </label> <input type="file" id="uploadbarcodes" name="uploadbarcodes" />
73             <input type="button" id="resetuploadbarcodes" name="resetuploadbarcodes" value="Reset" /></li>
74           </ol>
75         </fieldset>
76         <fieldset class="rows">
77             <legend>Or scan items one by one</legend>
78             <ol>
79                 <li>
80                   <label for="barcodelist">Barcode list (one barcode per line): </label>
81                   <textarea rows="10" cols="30" id="barcodelist" name="barcodelist"></textarea>
82                 </li>
83             </ol>
84         </fieldset>
85         <fieldset class="rows">
86             <legend>Parameters</legend>
87             <ol>
88                 <li><label for="setdate">Set inventory date to:</label> <input type="text" id="setdate" name="setdate" value="[% today | $KohaDates %]" class="flatpickr" /></li>
89                 <li><label for="compareinv2barcd">Compare barcodes list to results: </label><input type="checkbox" name="compareinv2barcd" id="compareinv2barcd" disabled /></li>
90                 <li><label for="dont_checkin">Do not check in items scanned during inventory: </label><input type="checkbox" name="dont_checkin" id="dont_checkin" disabled /></li>
91                 <li><label for="out_of_order">Check barcodes list for items shelved out of order: </label><input type="checkbox" name="out_of_order" id="out_of_order" disabled /></li>
92             </ol>
93         </fieldset>
94         <fieldset class="rows">
95         <legend>Item location filters</legend>
96         <ol><li>
97         <label for="branch">Location: </label>
98             <input type="radio" name="branch" value="homebranch"> Home library</input>
99             <input type="radio" name="branch" value="holdingbranch"> Current library</input>
100         </li><li>
101         <label for="branchloop">Library: </label><select id="branchloop" name="branchcode" style="width:12em;">
102             <option value="">All libraries</option>
103             [% PROCESS options_for_libraries libraries => Branches.all( selected => branchcode, unfiltered => 1, ) %]
104         </select>
105         </li>
106         [% IF (authorised_values) %]
107         <li>
108             <label for="locationloop">Shelving location (items.location) is: </label>
109         <select id="locationloop" name="location">
110                 <option value="">Filter location</option>
111         [% FOREACH value IN authorised_values %]
112             [% IF (value.selected) %]
113                 <option value="[% value.authorised_value | html %]" selected="selected">[% value.lib | html %]</option>
114             [% ELSE %]
115                 <option value="[% value.authorised_value | html %]">[% value.lib | html %]</option>
116             [% END %]
117         [% END %]
118         </select>        </li>
119         [% END %]
120         [% SET ccodes = AuthorisedValues.GetAuthValueDropbox('CCODE') %]
121         [% IF ( ccodes.count > 0 ) %]
122         <li>
123             <label for="ccode">Collection code: </label>
124             <select id="ccodeloop" name="ccode">
125                         <option value="">Filter collection</option>
126                 [% FOREACH cc IN ccodes %]
127                     [% IF (ccode == cc.authorised_value) %]
128                         <option value="[% cc.authorised_value | html %]" selected="selected">[% cc.lib | html %]</option>
129                     [% ELSE %]
130                         <option value="[% cc.authorised_value | html %]">[% cc.lib | html %]</option>
131                     [% END %]
132                 [% END %]
133             </select>
134         </li>
135         [% END %]
136         <li>
137             <label for="minlocation">Item call number between: </label>
138                 <input type="text" name="minlocation" id="minlocation" value="[% minlocation | html %]" /> (items.itemcallnumber)  </li>
139            <li><label for="maxlocation">...and: </label>
140                 <input type="text" name="maxlocation" id="maxlocation" value="[% maxlocation | html %]" />
141            <li>
142             <label for="class_source">Call number classification scheme</label>
143             <select name="class_source">
144             [% FOREACH class_source IN class_sources %]
145                 [% IF class_source.cn_source == pref_class %]
146                 <option value="[% class_source.cn_source | html %]" selected="selected">[% class_source.description | html %] (default)</option>
147                 [% ELSE %]
148                 <option value="[% class_source.cn_source | html %]">[% class_source.description | html %]</option>
149                 [% END %]
150             [% END %]
151             </select>
152           </li>
153     </ol>
154     </fieldset>
155
156     <fieldset class="rows" id="optionalfilters">
157             <legend>Optional filters for inventory list or comparing barcodes</legend>
158             <br/>
159             <div id="statuses" style="display: block;">
160                   [% FOREACH status IN statuses %]
161                       [% IF (status.values) %]
162                           <fieldset style="float: left; padding: 5px; margin: 5px;text-align:right">
163                               <legend>[% status.fieldname | html %]</legend>
164                               <ul id="statuses-[% fieldname | html %]" style="display: inline;">
165                               [% FOREACH value IN status.values %]
166                                   [% IF (value.lib) %]
167                                     <li>
168                                     <label for="[% value.id | html %]">
169                                         [% IF ( status.fieldname == 'items.notforloan' && value.authorised_value == 0 && value.lib == '__IGNORE__' ) %]
170                                             For loan
171                                         [% ELSE %]
172                                             [% value.lib | html %]
173                                         [% END %]
174                                     </label>
175                                     <input type="checkbox" name="status-[% status.fieldname | html %]-[% value.authorised_value | html %]" id="[% value.authorised_value | html %]" />
176                                     </li>
177                                   [% END %]
178                               [% END %]
179                               </ul>
180                           </fieldset>
181                       [% END %]
182                   [% END %]
183                 </div>
184         <ol>
185         <li>
186             <br/>
187             <label for="datelastseen">Last inventory date:</label>
188             <input type="text" id="datelastseen" name="datelastseen" value="[% datelastseen | $KohaDates %]" class="flatpickr" />
189             (Skip records marked as seen on or after this date.)
190         </li>
191         <li>
192             <label for="ignoreissued">Skip items on loan: </label>
193             [% IF (ignoreissued) %]
194                 <input type="checkbox" id="ignoreissued" name="ignoreissued" checked="checked" />
195             [% ELSE %]
196                 <input type="checkbox" id="ignoreissued" name="ignoreissued" />
197             [% END %]
198         </li>
199         <li>
200             <label for="ignore_waiting_holds">Skip items on hold awaiting pickup: </label>
201             <input type="checkbox" id="ignore_waiting_holds" name="ignore_waiting_holds" />
202         </li>
203         <li>
204             <label>Item types: </label>
205             <div class="branchselector">
206                 <p><a href="#" id="checkallitemtypes"> <i class="fa fa-check"></i> Select all</a> | <a href="#" id="checknoneitemtypes"> <i class="fa fa-remove"></i> Clear all</a></p>
207                 <div class="branchgridrow">
208                     [% FOREACH itemtype IN itemtypes %]
209                         <div class="branchgriditem">
210                             <input id="itemtype-[% itemtype.itemtype | html %]" class="branch_select" type="checkbox" name="itemtype-[% itemtype.itemtype | html %]" value="[% itemtype.itemtype | html %]" />
211                             <label for="itemtype-[% itemtype.itemtype | html %]">[% itemtype.description | html %]</label>
212                         </div>
213                         [% IF loop.count() % 4 == 0 && !loop.last() %]
214                             </div>
215                             <div class="branchgridrow">
216                         [% END %]
217                     [% END %]
218                 </div>
219             </div>
220         </li>
221
222         </ol>
223
224     </fieldset>
225
226         <fieldset class="rows">
227           <legend>Additional options</legend>
228           <ol>
229
230         <li>
231            <label for="CSVexport">Export to CSV file: </label>
232            <input type="checkbox" name="CSVexport" id="CSVexport" />
233         </li>
234         </ol>
235   </fieldset>
236             <input type="hidden" name="op" value="do_it" />
237
238             <fieldset class="action"><input type="submit" value="Submit" class="button" /></fieldset>
239     </form>
240
241     [% END %]
242     [% IF (op) %]
243     <form method="post" action="/cgi-bin/koha/tools/inventory.pl">
244     <input type="hidden" name="minlocation" value="[% minlocation | html %]" />
245     <input type="hidden" name="maxlocation" value="[% maxlocation | html %]" />
246     <input type="hidden" name="location" value="[% location | html %]" />
247     <input type="hidden" name="branchcode" value="[% branchcode | html %]" />
248     <input type="hidden" name="datelastseen" value="[% datelastseen | html %]" />
249     <input type="hidden" name="ccode" value="[% ccode | html %]" />
250
251     [% UNLESS uploadedbarcodesflag %]
252       <div><a href="#" class="checkall"><i class="fa fa-check"></i> Select all</a> <a href="#" class="clearall"><i class="fa fa-remove"></i> Clear all</a></div>
253     [% END %]
254
255     <table id="inventoryt">
256     <thead>
257         <tr>
258             [% UNLESS uploadedbarcodesflag %]<th>Seen</th>[% END %]
259             <th>Barcode</th>
260             <th>Call number</th>
261             <th>Library</th>
262             <th>Collection code</th>
263             <th class="anti-the">Title</th>
264             <th>Not for loan</th>
265             <th>Lost</th>
266             <th>Damaged</th>
267             <th>Withdrawn</th>
268             <th>Last seen</th>
269             <th>Problems</th>
270         </tr>
271     </thead>
272     <tbody>
273     [% FOREACH result IN loop %]
274         <tr>
275             [% UNLESS uploadedbarcodesflag %]
276               <td>
277                 <input type="checkbox" name="SEEN-[% result.itemnumber | html %]" value="1" />
278               </td>
279             [% END %]
280             <td>
281             [% result.barcode | html %]
282             </td>
283             <td data-order="[% result.cn_sort | html %]">
284                 [% result.itemcallnumber | html %]
285             </td>
286             <td>
287                 [% Branches.GetName( result.homebranch ) | html %]
288                 <span class="shelvingloc">[% result.location | html %]</span>
289             </td>
290             <td>
291                 <span class="ccode">[% result.ccode | html %]</span>
292             </td>
293             <td>
294                 <a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% result.biblionumber | uri %]" class="openWin">[% result.title | html %]</a>
295                 [% IF ( result.author ) %]
296                     by <span class="author">[% result.author | html %]</span>
297                 [% END %]
298             </td>
299             <td>
300             [% result.notforloan | html %]
301             </td>
302             <td>
303             [% result.itemlost | html %]
304             </td>
305             <td>
306             [% result.damaged | html %]
307             </td>
308             <td>
309             [% result.withdrawn | html %]
310             </td>
311             <td data-order="[% result.datelastseen | html %]">
312                 [% result.datelastseen | $KohaDates%]
313             </td>
314             <td>
315             [% FOREACH problem IN result.problems %]
316                 [% IF problem.key == 'wrongplace' %]
317                     <span>Found in wrong place</span><br/>
318                 [% ELSIF problem.key == 'changestatus' %]
319                     <span>Unknown not-for-loan status</span><br/>
320                 [% ELSIF problem.key == 'not_scanned' %]
321                     <span>Missing (not scanned)</span><br/>
322                 [% ELSIF problem.key == 'checkedout' %]
323                     <span>Still checked out</span><br/>
324                 [% ELSIF problem.key == 'no_barcode' %]
325                     <span>No barcode</span><br/>
326                 [% ELSIF problem.key == 'out_of_order' %]
327                     <span>Item may be shelved out of order</span><br/>
328                 [% END %]
329             [% END %]
330             </td>
331         </tr>
332     [% END %]
333     </tbody>
334     </table>
335     <div class="spacer"></div>
336     [% UNLESS uploadedbarcodesflag %]
337       <div style="padding : .3em 0"><a href="#" class="checkall"><i class="fa fa-check"></i> Select all</a> <a href="#" class="clearall"><i class="fa fa-remove"></i> Clear all</a></div>
338       <input type="submit" id="markseenandquit" value="Mark seen and quit" />
339       <input type="submit" value="Mark seen and continue &gt;&gt;" id="markseenandcontinuebutton" />
340       <input type="submit" value="Continue without marking &gt;&gt;" id="continuewithoutmarkingbutton" class="submit" />
341     [% END %]
342     </form>
343
344
345     [% END %]
346
347             </main>
348         </div> <!-- /.col-sm-10.col-sm-push-2 -->
349
350         <div class="col-sm-2 col-sm-pull-10">
351             <aside>
352                 [% INCLUDE 'tools-menu.inc' %]
353             </aside>
354         </div> <!-- .col-sm-2.col-sm-pull-10 -->
355      </div> <!-- /.row -->
356
357 [% MACRO jsinclude BLOCK %]
358     [% Asset.js("js/tools-menu.js") | $raw %]
359     [% INCLUDE 'datatables.inc' %]
360     [% INCLUDE 'calendar.inc' %]
361     <script>
362         function checkForm() {
363             if ( $('#uploadbarcodes').val() && $('#barcodelist').val() ) {
364                 alert(_("You have uploaded a barcode file and scanned barcodes at the same time. Please choose one of the two options."));
365                 return false;
366             }
367             if ( $('#uploadbarcodes').val() || $('#barcodelist').val() ) {
368                 if ( !(
369                     $('#branchloop').val()   ||
370                     $('#locationloop').val() ||
371                     $('#minlocation').val()  ||
372                     $('#maxlocation').val()  ||
373                     $('#statuses input:checked').length
374                 ) ) {
375                     return confirm(
376                         _("You have not selected any catalog filters and are about to compare a file of barcodes to your entire catalog.") + "\n\n" +
377                         _("For large catalogs this can result in unexpected behavior") + "\n\n" +
378                         _("Are you sure you want to do this?")
379                     );
380                 }
381             }
382
383             return true;
384         }
385
386         function barcodesProvided() {
387             if( $("#uploadbarcodes").val() || $("#barcodelist").val() ) {
388                 $("#setdate").prop('disabled',false);
389                 $("#compareinv2barcd").prop('disabled',false);
390                 $("#compareinv2barcd").attr('checked',true); // default
391                 $("#dont_checkin").prop('disabled',false);
392                 $("#out_of_order").prop('disabled',false);
393                 if( $("#compareinv2barcd").attr('checked') ) {
394                     $("fieldset#optionalfilters").show();
395                     $("#ignoreissued").attr('checked',true); // default
396                 } else {
397                     $("fieldset#optionalfilters").hide();
398                     $("#ignoreissued").attr('checked',false);
399                 }
400             } else {
401                 $("#setdate").prop('disabled',true);
402                 $("#compareinv2barcd").prop('disabled',true);
403                 $("#compareinv2barcd").attr('checked',false);
404                 $("#dont_checkin").prop('disabled',true);
405                 $("#dont_checkin").attr('checked',false);
406                 $("#out_of_order").prop('disabled',true);
407                 $("#out_of_order").attr('checked',false);
408                 $("fieldset#optionalfilters").show();
409             }
410         }
411
412         $(document).ready(function(){
413             inventorydt = $('#inventoryt').dataTable($.extend(true, {}, dataTablesDefaults, {
414                 'sPaginationType': 'full_numbers',
415                 [% IF compareinv2barcd %]
416                     // sort on callnumber
417                     "aaSorting": [[ 1, "asc" ]],
418                 [% ELSE %]
419                     // first column contains checkboxes
420                     "aoColumnDefs": [
421                         { "sType": "anti-the", "aTargets" : [ "anti-the" ] },
422                         { "bSortable": false, "bSearchable": false, "aTargets": [ 0 ] }
423                     ],
424                     // 3rd column is callnumber
425                     "aaSorting": [[ 2, "asc" ]],
426                 [% END %]
427                 'fnDrawCallback': function() {
428                     //bind the click handler script to the newly created elements held in the table
429                     $('.openWin').bind('click',function(e){
430                         e.preventDefault();
431                         openWindow(this.href,'marcview',800,600);
432                     });
433                 }
434             } ));
435
436
437             $("#continuewithoutmarkingbutton").click(function(){
438                 inventorydt.fnPageChange( 'next' );
439                 return false;
440             });
441
442             $("#markseenandcontinuebutton").click(function(){
443                 var param = '';
444                 $("input:checked").each(function() {
445                     param += "|" + $(this).attr('name');
446                 });
447                 $.post('/cgi-bin/koha/tools/ajax-inventory.pl', { seen: param });
448                 inventorydt.fnPageChange( 'next' );
449                 return false;
450             });
451
452             $("#markseenandquit").click(function(){
453                 var param = '';
454                 $("input:checked").each(function() {
455                     param += "|" + $(this).attr('name');
456                 });
457                 $.ajax({
458                   type: 'POST',
459                   url: '/cgi-bin/koha/tools/ajax-inventory.pl',
460                   data: { seen: param},
461                   async: false
462                 });
463                 document.location.href = '/cgi-bin/koha/tools/inventory.pl';
464                 return false;
465             });
466
467             $(".checkall").click(function(e){
468                 e.preventDefault();
469                 $("#inventoryt input:checkbox").each(function(){
470                     $(this).prop("checked", true);
471                 });
472             });
473             $(".clearall").click(function(e){
474                 e.preventDefault();
475                 $("#inventoryt input:checkbox").each(function(){
476                     $(this).prop("checked", false);
477                 });
478             });
479             $("#inventory_form").on("submit",function(){
480                 return checkForm();
481             });
482
483             $("#resetuploadbarcodes").click(function() {
484                 $("#uploadbarcodes").val("");
485                 barcodesProvided();
486             });
487
488             // #uploadbarcodes and #compareinv2barcd determine the behavior of
489             // the controls within the barcode fieldset and the optional filters
490             $("#uploadbarcodes").change(barcodesProvided);
491             $("#barcodelist").on("change keyup paste", barcodesProvided);
492
493             $("#compareinv2barcd").click(function() {
494                 if( $("#compareinv2barcd").attr('checked') ) {
495                     $("fieldset#optionalfilters").show();
496                     $("#ignoreissued").attr('checked',true); // default
497                 } else {
498                     $("#ignoreissued").attr('checked',false);
499                     $("fieldset#optionalfilters").hide();
500                 }
501             });
502
503             $("#checkallitemtypes").on("click",function(e){
504                 e.preventDefault();
505                 $(".branch_select").prop("checked",1);
506             });
507             $("#checknoneitemtypes").on("click",function(e){
508                 e.preventDefault();
509                 $(".branch_select").prop("checked",0);
510             });
511         });
512     </script>
513 [% END %]
514
515 [% INCLUDE 'intranet-bottom.inc' %]