Bug 27883: (follow-up) Make label match input id
[koha.git] / koha-tmpl / intranet-tmpl / prog / en / modules / tools / import_borrowers.tt
1 [% USE raw %]
2 [% USE Asset %]
3 [% USE Koha %]
4 [% USE Branches %]
5 [% SET footerjs = 1 %]
6 [% INCLUDE 'doc-head-open.inc' %]
7 <title>
8     [% IF ( uploadborrowers ) %]
9         Results &rsaquo; [% END %]
10     Import patrons &rsaquo; Tools &rsaquo; Koha
11 </title>
12 [% INCLUDE 'doc-head-close.inc' %]
13 <style>
14     .yui-u fieldset.rows .widelabel { width: 12em; }
15     label.description { width: 20em; }
16     .line_error { width: 100%; }
17     code { background-color: yellow; }
18 </style>
19 </head>
20
21 <body id="tools_import_borrowers" class="tools">
22 [% INCLUDE 'header.inc' %]
23 [% INCLUDE 'patron-search.inc' %]
24
25 <nav id="breadcrumbs" aria-label="Breadcrumb" class="breadcrumb">
26     <ol>
27         <li>
28             <a href="/cgi-bin/koha/mainpage.pl">Home</a>
29         </li>
30         <li>
31             <a href="/cgi-bin/koha/tools/tools-home.pl">Tools</a>
32         </li>
33         [% IF ( uploadborrowers ) %]
34             <li>
35                 <a href="/cgi-bin/koha/tools/import_borrowers.pl">Import patrons</a>
36             </li>
37             <li>
38                 <a href="#" aria-current="page">
39                     Results
40                 </a>
41             </li>
42         [% ELSE %]
43             <li>
44                 <a href="#" aria-current="page">
45                     Import patrons
46                 </a>
47             </li>
48         [% END %]
49     </ol>
50 </nav>
51
52 [% INCLUDE 'blocking_errors.inc' %]
53 <div class="main container-fluid">
54     <div class="row">
55         <div class="col-sm-10 col-sm-push-2">
56             <main>
57
58     <div class="row">
59      <div class="col-sm-6">
60 <h1>Import patrons</h1>
61 [% IF ( uploadborrowers ) %]
62     <h5>Import results :</h5>
63     <ul>
64         <li>[% imported | html %] imported records [% IF ( lastimported ) %](last was [% lastimported | html %])[% END %]</li>
65         [% IF imported and patronlistname %]
66             <li>Patronlist with imported patrons: [% patronlistname | html %]</li>
67         [% END %]
68         <li>[% overwritten | html %] overwritten [% IF ( lastoverwritten ) %](last was [% lastoverwritten | html %])[% END %]</li>
69         <li>[% alreadyindb | html %] not imported because already in borrowers table and overwrite disabled [% IF ( lastalreadyindb ) %](last was [% lastalreadyindb | html %])[% END %]</li>
70         <li>[% invalid | html %] not imported because they are not in the expected format [% IF ( lastinvalid ) %](last was [% lastinvalid | html %])[% END %]</li>
71         <li>[% total | html %] records parsed</li>
72         <li><a href="/cgi-bin/koha/tools/tools-home.pl">Back to Tools</a></li>
73     </ul>
74
75     [% IF ( feedback ) %]
76         <br /><br />
77
78         <div>
79             <h5>Feedback:</h5>
80                 <ul class="feedback">
81                     [% FOREACH f IN feedback %]
82                         <li>
83                             [% IF ( f.filename ) %]
84                                 Parsing upload file <span class="filename">[% f.filename | html %]</span>
85                             [% ELSIF ( f.backend ) %]
86                                 Upload parsed using [% f.backend | html %]
87                             [% ELSIF ( f.headerrow ) %]
88                                 These fields found: [% f.value | html %]
89                             [% ELSIF ( f.already_in_db ) %]
90                                 Patron already in database: [% f.value | html %]
91                             [% ELSE %]
92                                 [% f.name | html %] : [% f.value | html %]
93                             [% END %]
94                         </li>
95                     [% END %]
96                 </ul>
97         </div>
98     [% END %]
99
100     [% IF ( errors ) %]
101         <br /><br />
102
103         <div>
104             <h5>Error analysis:</h5>
105             <ul>
106                 [% FOREACH e IN errors %]
107                     [% IF ( e.badheader ) %]<li>Header row could not be parsed</li>[% END %]
108
109                     [% FOREACH missing_critical IN e.missing_criticals %]
110                         <li class="line_error">
111                             Line <span class="linenumber">[% missing_critical.line | html %]</span>
112
113                             [% IF ( missing_critical.badparse ) %]
114                                 could not be parsed!
115                             [% ELSIF ( missing_critical.bad_date ) %]
116                                 has &quot;[% missing_critical.key | html %]&quot; in unrecognized format: &quot;[% missing_critical.value | html %]&quot;
117                             [% ELSE %]
118                                 Critical field &quot;[% missing_critical.key | html %]&quot;
119
120                                 [% IF ( missing_critical.branch_map ) %]
121                                     has unrecognized value &quot;[% missing_critical.value | html %]&quot;
122                                 [% ELSIF ( missing_critical.category_map ) %]
123                                     has unrecognized value &quot;[% missing_critical.value | html %]&quot;
124                                 [% ELSE %]
125                                     missing
126                                 [% END %]
127
128                                 (borrowernumber: [% missing_critical.borrowernumber | html %]; surname: [% missing_critical.surname | html %]).
129                             [% END %]
130
131                             <br/>
132                             <code>[% missing_critical.lineraw | html %]</code>
133                         </li>
134                     [% END %]
135
136                     [% IF e.invalid_cardnumber %]
137                         <li class="line_error">
138                             Cardnumber [% e.cardnumber | html %] is not a valid cardnumber
139                             [% IF e.borrowernumber %] (for patron with borrowernumber [% e.borrowernumber | html %])[% END %]
140                         </li>
141                     [% END %]
142                     [% IF e.duplicate_userid %]
143                         <li class="line_error">
144                             Userid [% e.userid | html %] is already used by another patron.
145                         </li>
146                     [% END %]
147                     [% IF e.passwd_too_short %]
148                         <li class="line_error">
149                             Password is too short for patron with borrowernumber [% e.borrowernumber | html %]. Minimum length is [% e.min_length | html %], length is [% e.length | html %]
150                         </li>
151                     [% END %]
152                     [% IF e.passwd_whitespace %]
153                         <li class="line_error">
154                             Password contains whitespace for patron with borrowernumber [% e.borrowernumber | html %].
155                         </li>
156                     [% END %]
157                     [% IF e.passwd_too_weak %]
158                         <li class="line_error">
159                             Password is too weak for patron with borrowernumber [% e.borrowernumber | html %].
160                         </li>
161                     [% END %]
162                     [% IF e.passwd_plugin_err %]
163                         <li class="line_error">
164                             Password plugin error for patron with borrowernumber [% e.borrowernumber | html %].
165                         </li>
166                     [% END %]
167                     [% IF e.passwd_unknown_err %]
168                         <li class="line_error">
169                             Password error for patron with borrowernumber [% e.borrowernumber | html %].
170                         </li>
171                     [% END %]
172                     [% IF e.patron_attribute_unique_id_constraint %]
173                         <li class="line_error">
174                             [% IF e.borrowernumber %]
175                                 Patron attribute [% e.attribute.code | html %] must be unique for patron with borrowernumber [% e.borrowernumber | html %].
176                             [% ELSE %]
177                                 Patron attribute [% e.attribute.code | html %] must be unique for patron [% e.patron_id | html %].
178                             [% END %]
179                         </li>
180                     [% END %]
181                     [% IF e.patron_attribute_invalid_type %]
182                         <li class="line_error">
183                             [% IF e.borrowernumber %]
184                                 Patron attribute [% e.attribute_type_code | html %] is invalid for patron with borrowernumber [% e.borrowernumber | html %].
185                             [% ELSE %]
186                                 Patron attribute [% e.attribute_type_code | html %] is invalid for patron [% e.patron_id | html %].
187                             [% END %]
188                         </li>
189                     [% END %]
190                     [% IF e.patron_attribute_non_repeatable %]
191                         <li class="line_error">
192                             [% IF e.borrowernumber %]
193                                 Patron attribute [% e.attribute.code | html %] is non-repeatable for patron with borrowernumber [% e.borrowernumber | html %].
194                             [% ELSE %]
195                                 Patron attribute [% e.attribute.code | html %] is non-repeatable for patron [% e.patron_id | html %].
196                             [% END %]
197                         </li>
198                     [% END %]
199                 [% END %]
200             </ul>
201         </div>
202     [% END %]
203 [% ELSE %]
204     <ul>
205         <li>Select a file to import into the borrowers table</li>
206         <li>If a cardnumber exists in the table, you can choose whether to ignore the new one or overwrite the old one.</li>
207     </ul>
208
209     <form method="post" action="[% SCRIPT_NAME | html %]" enctype="multipart/form-data">
210         <fieldset class="rows">
211             <legend>Import into the borrowers table</legend>
212
213             <ol>
214                 <li>
215                     <label for="uploadborrowers">Select the file to import: </label>
216                     <input type="file" id="uploadborrowers" name="uploadborrowers" />
217                 </li>
218
219                 <li>
220                     <label for "createpatronlist">Create patron list: </label>
221                     <input name="createpatronlist" id="createpatronlist" value="1" type="checkbox">
222                     <span class="hint">List name will be file name with timestamp</span>
223                 </li>
224             </ol>
225         </fieldset>
226
227         <fieldset class="rows">
228             <legend>Field to use for record matching</legend>
229             <ol>
230                 <li class="radio">
231                     <select name="matchpoint" id="matchpoint">
232                         <option value="cardnumber">Cardnumber</option>
233                         <option value="userid">Username</option>
234                         [% FOREACH matchpoint IN matchpoints %]
235                             <option value="[% matchpoint.code | html %]">[% matchpoint.description | html %]</option>
236                         [% END %]
237                     </select>
238                 </li>
239             </ol>
240         </fieldset>
241
242         <fieldset class="rows">
243             <legend>
244                 <a href="#" class="expand_defaults"><i class="fa fa-plus-square"></i> Enter default values</a>
245                 <a href="#" class="expand_defaults" style="display:none;"><i class="fa fa-minus-square"></i> Hide default value fields</a>
246             </legend>
247
248             <ol class="default_values" style="display:none;">
249                 [% FOREACH borrower_field IN borrower_fields %]
250
251                     [% SWITCH borrower_field.field %]
252                     [% CASE 'branchcode' %]
253                         <li>
254                             <label class="description" for="branchcode">[% borrower_field.description | html %]: </label>
255                             <select id="branchcode" name="branchcode">
256                                 <option value="" selected="selected"></option>
257                                 [% FOREACH library IN Branches.all() %]
258                                     <option value="[% library.branchcode | html %]">[% library.branchname | html %]</option>
259                                 [% END %]
260                             </select>
261                             <span class="field_hint">[% borrower_field.field | html %]</span>
262                         </li>
263                     [% CASE 'categorycode' %]
264                         <li>
265                             <label class="description" for="categorycode">[% borrower_field.description | html %]: </label>
266                             <select id="categorycode" name="categorycode">
267                                 <option value="" selected="selected"></option>
268                                 [% FOREACH category IN categories %]
269                                     <option value="[% category.categorycode | html %]">[% category.description | html %]</option>
270                                 [% END %]
271                             </select>
272                             <span class="field_hint">[% borrower_field.field | html %]</span>
273                         </li>
274                     [% CASE %]
275                         <li>
276                             <label class="description" for="[% borrower_field.field | html %]">[% borrower_field.description | html %]: </label>
277                             <input id="[% borrower_field.field | html %]" name="[% borrower_field.field | html %]" type="text" />
278                             <span class="field_hint">[% borrower_field.field | html %]</span>
279                         </li>
280                     [% END %]
281                 [% END %]
282
283                 [% IF ( Koha.Preference('ExtendedPatronAttributes') == 1 ) %]
284                     <li>
285                         <label class="description" for="patron_attributes">Patron attributes: </label>
286                         <input id="patron_attributes" name="patron_attributes" type="text" />
287                         <span class="field_hint">patron_attributes</span>
288                     </li>
289                 [% END %]
290
291             </ol>
292         </fieldset>
293         <fieldset class="rows">
294             <legend>
295                 <a href="#" class="expand_preserves"><i class="fa fa-plus-square"></i> Preserve existing values</a>
296                 <a href="#" class="expand_preserves" style="display:none;"><i class="fa fa-minus-square"></i> Hide preserve value fields</a>
297             </legend>
298
299             <ol class="preserve_values" style="display:none;">
300                 <div class="hint">Selected fields will be preserved from original patron record when overwriting existing patron.</div>
301                 [% FOREACH borrower_field IN borrower_fields %]
302                         <li>
303                             <label class="description" for="preserve_existing_[% borrower_field.field | html %]">[% borrower_field.description | html %]: </label>
304                             <input name="preserve_existing" id="preserve_existing_[%  borrower_field.field | html %]" value="[%  borrower_field.field | html %]" type="checkbox">
305                             <span class="field_hint">[% borrower_field.field | html %]</span>
306                         </li>
307                 [% END %]
308             </ol>
309         </fieldset>
310
311         <fieldset class="rows">
312             <legend>If matching record is already in the borrowers table:</legend>
313
314             <ol>
315                 <li class="radio">
316                     <input type="radio" id="overwrite_cardnumberno" name="overwrite_cardnumber" value="0" checked="checked" /><label for="overwrite_cardnumberno">Ignore this one, keep the existing one</label>
317                 </li>
318
319                 <li class="radio">
320                     <input type="radio" id="overwrite_cardnumberyes" name="overwrite_cardnumber" value="1" /><label for="overwrite_cardnumberyes">Overwrite the existing one with this</label>
321                     <ul>
322                         <li>
323                             <input class="overwrite_passwords" type="checkbox" id="overwrite_passwords" name="overwrite_passwords" disabled/>
324                             <label class="overwrite_passwords" for="overwrite_passwords">Replace patron passwords with those in the file (blank passwords will be ignored)</label>
325                         </li
326                     </ul>
327                 </li>
328             </ol>
329         </fieldset>
330
331         [% IF ( Koha.Preference('ExtendedPatronAttributes') == 1 ) %]
332             <fieldset class="rows">
333                 <legend>Patron attributes</legend>
334
335                 <ol>
336                     <li class="radio">
337                         <input type="radio" id="ext_preserve_0" name="ext_preserve" value="0" /><label for="ext_preserve_0">Replace all patron attributes</label>
338                     </li>
339
340                     <li class="radio">
341                         <input type="radio" id="ext_preserve_1" name="ext_preserve" value="1" checked="checked" /><label for="ext_preserve_1">Replace only included patron attributes</label>
342                     </li>
343                 </ol>
344             </fieldset>
345         [% END %]
346
347         <fieldset class="action">
348             <input type="hidden" name="csrf_token" value="[% csrf_token | html %]" />
349             <input type="submit" value="Import" />
350         </fieldset>
351     </form>
352 [% END %]
353
354 </div>
355
356 <div class="col-sm-6">
357     <h2>Notes:</h2>
358     <ul>
359         <li>The first line in the file must be a header row defining which columns you are supplying in the import file.</li>
360
361         <li><strong>Download a <a href="?sample=1">Starter CSV file</a> with all the columns.</strong>  Values are comma-separated.</li>
362
363         <li>
364             OR choose which fields you want to supply from the following list:
365             <ul>
366                 <li>
367                     [% FOREACH columnkey IN borrower_fields %]'[% columnkey.field | html %]', [% END %]
368                 </li>
369             </ul>
370         </li>
371
372         [% IF ( Koha.Preference('ExtendedPatronAttributes') ) %]
373             <li>
374                 If loading patron attributes, the 'patron_attributes' field should contain a comma-separated list of attribute types and values. The attribute type code and a colon should precede each value. For example: <strong>INSTID:12345,LANG:fr</strong> or <strong>STARTDATE:January 1 2010,TRACK:Day</strong>. If an input record has more than one attribute, the fields should either be entered as an unquoted string (previous examples), or with each field wrapped in separate double quotes and delimited by a comma: <strong>&quot;STARTDATE:January 1, 2010&quot;,&quot;TRACK:Day&quot;</strong>.  The second syntax would be required if the data might have a comma in it, like a date string.
375             </li>
376         [% END %]
377
378         <li>
379             <strong>Required fields:</strong> The fields 'surname', 'branchcode', and 'categorycode' are <em>required</em> and 'branchcode' and 'categorycode' <strong>must match</strong> valid entries in your database.
380         </li>
381
382         <li>
383             'password' should be stored in plaintext, and will be converted to a Bcrypt hash (if your passwords are already encrypted, talk to your system administrator about options). Passwords will not be updated on overwrite unless replace passwords option is checked.
384         </li>
385
386         <li>
387             Date formats should match your system preference, and <strong>must</strong> be zero-padded, e.g. '01/02/2008'.  Alternatively,
388 you can supply dates in ISO format (e.g., '2010-10-28').
389         </li>
390     </ul>
391 </div>
392 </div>
393
394             </main>
395         </div> <!-- /.col-sm-10.col-sm-push-2 -->
396
397         <div class="col-sm-2 col-sm-pull-10">
398             <aside>
399                 [% INCLUDE 'tools-menu.inc' %]
400             </aside>
401         </div> <!-- .col-sm-2.col-sm-pull-10 -->
402      </div> <!-- /.row -->
403
404 [% MACRO jsinclude BLOCK %]
405     [% INCLUDE 'calendar.inc' %]
406     [% Asset.js("js/tools-menu.js") | $raw %]
407     [% INCLUDE 'str/members-menu.inc' %]
408     [% Asset.js("js/members-menu.js") | $raw %]
409     <script>
410         $(document).ready(function() {
411             [%# Make date fields have the datepicker %]
412             $("#dateenrolled, #dateexpiry, #dateofbirth").datepicker();
413
414             $(".expand_defaults").click(function(e){
415                 e.preventDefault();
416                 $(".default_values").toggle();
417                 $(".expand_defaults").toggle();
418             });
419
420             $(".expand_preserves").click(function(e){
421                 e.preventDefault();
422                 $(".preserve_values").toggle();
423                 $(".expand_preserves").toggle();
424             });
425         });
426
427         $("#overwrite_cardnumberno").click(function(){
428             $("#overwrite_passwords").prop('checked',false).prop('disabled',true);
429         });
430         $("#overwrite_cardnumberyes").click(function(){
431             $("#overwrite_passwords").prop('disabled',false);
432         });
433     </script>
434 [% END %]
435 [% INCLUDE 'intranet-bottom.inc' %]