6 [% INCLUDE 'doc-head-open.inc' %]
8 [% IF ( uploadborrowers ) %]
9 Results › [% END %]
10 Import patrons › Tools › Koha
12 [% INCLUDE 'doc-head-close.inc' %]
14 label.description { width: 20em; }
15 .line_error { width: 100%; }
16 code { background-color: yellow; }
20 <body id="tools_import_borrowers" class="tools">
21 [% WRAPPER 'header.inc' %]
22 [% INCLUDE 'patron-search-header.inc' %]
25 [% WRAPPER 'sub-header.inc' %]
26 <nav id="breadcrumbs" aria-label="Breadcrumb" class="breadcrumb">
29 <a href="/cgi-bin/koha/mainpage.pl">Home</a>
32 <a href="/cgi-bin/koha/tools/tools-home.pl">Tools</a>
34 [% IF ( uploadborrowers ) %]
36 <a href="/cgi-bin/koha/tools/import_borrowers.pl">Import patrons</a>
39 <a href="#" aria-current="page">
45 <a href="#" aria-current="page">
54 [% INCLUDE 'blocking_errors.inc' %]
55 <div class="main container-fluid">
57 <div class="col-sm-10 col-sm-push-2">
61 <div class="col-sm-6">
62 <h1>Import patrons</h1>
63 [% IF ( uploadborrowers ) %]
64 <h5>Import results :</h5>
66 <li>[% imported | html %] imported records [% IF ( lastimported ) %](last was [% lastimported | html %])[% END %]</li>
67 [% IF imported and patronlistname %]
68 <li>Patronlist with imported patrons: [% patronlistname | html %]</li>
70 <li>[% overwritten | html %] overwritten [% IF ( lastoverwritten ) %](last was [% lastoverwritten | html %])[% END %]</li>
71 <li>[% alreadyindb | html %] not imported because already in borrowers table and overwrite disabled [% IF ( lastalreadyindb ) %](last was [% lastalreadyindb | html %])[% END %]</li>
72 <li>[% invalid | html %] not imported because they are not in the expected format [% IF ( lastinvalid ) %](last was [% lastinvalid | html %])[% END %]</li>
73 <li>[% total | html %] records parsed</li>
74 <li><a href="/cgi-bin/koha/tools/tools-home.pl">Back to Tools</a></li>
83 [% FOREACH f IN feedback %]
85 [% IF ( f.filename ) %]
86 <span>Parsing upload file</span> <span class="filename">[% f.filename | html %]</span>
87 [% ELSIF ( f.backend ) %]
88 <span>Upload parsed using [% f.backend | html %]</span>
89 [% ELSIF ( f.headerrow ) %]
90 <span>These fields found: [% f.value | html %]</span>
91 [% ELSIF ( f.already_in_db ) %]
92 <span>Patron already in database: [% f.value | html %]</span>
94 [% f.name | html %] : [% f.value | html %]
106 <h5>Error analysis:</h5>
108 [% FOREACH e IN errors %]
109 [% IF ( e.badheader ) %]<li>Header row could not be parsed</li>[% END %]
111 [% FOREACH missing_critical IN e.missing_criticals %]
112 <li class="line_error">
113 Line <span class="linenumber">[% missing_critical.line | html %]</span>
115 [% IF ( missing_critical.badparse ) %]
116 <span>could not be parsed!</span>
117 [% ELSIF ( missing_critical.bad_date ) %]
118 <span>has "[% missing_critical.key | html %]" in unrecognized format:</span> "[% missing_critical.value | html %]"
120 <span>Critical field "[% missing_critical.key | html %]"</span>
122 [% IF ( missing_critical.branch_map ) %]
123 <span>has unrecognized value "[% missing_critical.value | html %]"</span>
124 [% ELSIF ( missing_critical.category_map ) %]
125 <span>has unrecognized value "[% missing_critical.value | html %]"</span>
130 (<span>borrowernumber: [% missing_critical.borrowernumber | html %]</span>; <span>surname: [% missing_critical.surname | html %]</span>).
134 <code>[% missing_critical.lineraw | html %]</code>
138 [% IF e.invalid_cardnumber %]
139 <li class="line_error">
140 Card number [% e.cardnumber | html %] is not a valid card number
141 [% IF e.borrowernumber %] (for patron with borrowernumber [% e.borrowernumber | html %])[% END %]
144 [% IF e.duplicate_userid %]
145 <li class="line_error">
146 Userid [% e.userid | html %] is already used by another patron.
149 [% IF e.passwd_too_short %]
150 <li class="line_error">
151 Password is too short for patron with borrowernumber [% e.borrowernumber | html %]. Minimum length is [% e.min_length | html %], length is [% e.length | html %]
154 [% IF e.passwd_whitespace %]
155 <li class="line_error">
156 Password contains whitespace for patron with borrowernumber [% e.borrowernumber | html %].
159 [% IF e.passwd_too_weak %]
160 <li class="line_error">
161 Password is too weak for patron with borrowernumber [% e.borrowernumber | html %].
164 [% IF e.passwd_plugin_err %]
165 <li class="line_error">
166 Password plugin error for patron with borrowernumber [% e.borrowernumber | html %].
169 [% IF e.passwd_unknown_err %]
170 <li class="line_error">
171 Password error for patron with borrowernumber [% e.borrowernumber | html %].
174 [% IF e.patron_attribute_unique_id_constraint %]
175 <li class="line_error">
176 [% IF e.borrowernumber %]
177 <span>Patron attribute [% e.attribute.code | html %] must be unique for patron with borrowernumber [% e.borrowernumber | html %].</span>
179 <span>Patron attribute [% e.attribute.code | html %] must be unique for patron [% e.patron_id | html %].</span>
183 [% IF e.patron_attribute_invalid_type %]
184 <li class="line_error">
185 [% IF e.borrowernumber %]
186 <span>Patron attribute [% e.attribute_type_code | html %] is invalid for patron with borrowernumber [% e.borrowernumber | html %].</span>
188 <span>Patron attribute [% e.attribute_type_code | html %] is invalid for patron [% e.patron_id | html %].</span>
192 [% IF e.patron_attribute_non_repeatable %]
193 <li class="line_error">
194 [% IF e.borrowernumber %]
195 <span>Patron attribute [% e.attribute.code | html %] is non-repeatable for patron with borrowernumber [% e.borrowernumber | html %].</span>
197 <span>Patron attribute [% e.attribute.code | html %] is non-repeatable for patron [% e.patron_id | html %].</span>
207 <li>Select a file to import into the borrowers table</li>
208 <li>If a card number exists in the table, you can choose whether to ignore the new one or overwrite the old one.</li>
211 <form method="post" action="[% SCRIPT_NAME | html %]" enctype="multipart/form-data">
212 <fieldset class="rows">
213 <legend>Import into the borrowers table</legend>
217 <label for="uploadborrowers">Select the file to import: </label>
218 <input type="file" id="uploadborrowers" name="uploadborrowers" />
222 <label for "createpatronlist">Create patron list: </label>
223 <input name="createpatronlist" id="createpatronlist" value="1" type="checkbox">
224 <span class="hint">List name will be file name with timestamp</span>
229 <fieldset class="rows">
230 <legend>Field to use for record matching</legend>
233 <select name="matchpoint" id="matchpoint">
234 <option value="cardnumber">Card number</option>
235 <option value="userid">Username</option>
236 [% FOREACH matchpoint IN matchpoints %]
237 <option value="[% matchpoint.code | html %]">[% matchpoint.description | html %]</option>
244 <fieldset class="rows">
246 <a href="#" class="expand_defaults"><i class="fa fa-plus-square"></i> Enter default values</a>
247 <a href="#" class="expand_defaults" style="display:none;"><i class="fa fa-minus-square"></i> Hide default value fields</a>
250 <ol class="default_values" style="display:none;">
251 [% FOREACH borrower_db_column IN borrower_fields.keys.sort %]
252 [% SWITCH borrower_db_column %]
253 [% CASE 'branchcode' %]
255 <label class="description" for="branchcode">[% borrower_fields.$borrower_db_column | html %]: </label>
256 <select id="branchcode" name="branchcode">
257 <option value="" selected="selected"></option>
258 [% FOREACH library IN Branches.all() %]
259 <option value="[% library.branchcode | html %]">[% library.branchname | html %]</option>
262 <span class="field_hint">[% borrower_db_column | html %]</span>
264 [% CASE 'categorycode' %]
266 <label class="description" for="categorycode">[% borrower_fields.$borrower_db_column | html %]: </label>
267 <select id="categorycode" name="categorycode">
268 <option value="" selected="selected"></option>
269 [% FOREACH category IN categories %]
270 <option value="[% category.categorycode | html %]">[% category.description | html %]</option>
273 <span class="field_hint">[% borrower_db_column | html %]</span>
277 <label class="description" for="[% borrower_db_column| html %]">[% borrower_fields.$borrower_db_column | html %]: </label>
278 <input id="[% borrower_db_column | html %]" name="[% borrower_db_column | html %]" type="text" />
279 <span class="field_hint">[% borrower_db_column | html %]</span>
284 [% IF ( Koha.Preference('ExtendedPatronAttributes') == 1 ) %]
286 <label class="description" for="patron_attributes">Patron attributes: </label>
287 <input id="patron_attributes" name="patron_attributes" type="text" />
288 <span class="field_hint">patron_attributes</span>
294 <fieldset class="rows">
296 <a href="#" class="expand_preserves"><i class="fa fa-plus-square"></i> Preserve existing values</a>
297 <a href="#" class="expand_preserves" style="display:none;"><i class="fa fa-minus-square"></i> Hide preserve value fields</a>
300 <ol class="preserve_values" style="display:none;">
301 <div class="hint">Selected fields will be preserved from original patron record when overwriting existing patron.</div>
302 [% FOREACH borrower_db_column IN borrower_fields.keys.sort %]
304 <label class="description" for="preserve_existing_[% borrower_db_column | html %]">[% borrower_fields.$borrower_db_column | html %]: </label>
305 <input name="preserve_existing" id="preserve_existing_[% borrower_db_column | html %]" value="[% borrower_db_column | html %]" type="checkbox">
306 <span class="field_hint">[% borrower_db_column | html %]</span>
312 <fieldset class="brief">
313 <legend>If matching record is already in the borrowers table:</legend>
317 <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>
321 <input type="radio" id="overwrite_cardnumberyes" name="overwrite_cardnumber" value="1" /><label for="overwrite_cardnumberyes">Overwrite the existing one with this</label>
324 <label class="update_dateexpiry" for="update_dateexpiry">Renew existing patrons</label>
325 <select class="update_dateexpiry" type="select" id="update_dateexpiry" name="update_dateexpiry" disabled/>
326 <option value="">using the datexpiry value in the file, if present</option>
327 <option value="dateexpiry">from the current membership expiry date</option>
328 <option value="now">from the current date</option>
332 <input class="overwrite_passwords" type="checkbox" id="overwrite_passwords" name="overwrite_passwords" disabled/>
333 <label class="overwrite_passwords" for="overwrite_passwords">Replace patron passwords with those in the file (blank passwords will be ignored)</label>
340 [% IF ( Koha.Preference('ExtendedPatronAttributes') == 1 ) %]
341 <fieldset class="brief">
342 <legend>Patron attributes</legend>
346 <input type="radio" id="ext_preserve_0" name="ext_preserve" value="0" /><label for="ext_preserve_0">Replace all patron attributes</label>
350 <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>
356 <fieldset class="rows">
357 <legend>Welcome email</legend>
360 <input class="welcome_new" type="checkbox" id="welcome_new" name="welcome_new"/>
361 <label class="welcome_new" for="welcome_new">Send email to new patrons</label>
362 <span class="hint"> WELCOME notice is used</span>
367 <fieldset class="action">
368 <input type="hidden" name="csrf_token" value="[% csrf_token | html %]" />
369 <input type="submit" class="btn btn-primary" value="Import" />
376 <div class="col-sm-6 page-section bg-info">
379 <li>The first line in the file must be a header row defining which columns you are supplying in the import file.</li>
381 <li><strong>Download a <a href="?sample=1">Starter CSV file</a> with all the columns.</strong> Values are comma-separated.</li>
384 OR choose which fields you want to supply from the following list:
387 [% FOREACH columnkey IN borrower_fields.keys.sort %]'[% columnkey | html %]', [% END %]
392 [% IF ( Koha.Preference('ExtendedPatronAttributes') ) %]
394 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>"STARTDATE:January 1, 2010","TRACK:Day"</strong>. The second syntax would be required if the data might have a comma in it, like a date string.
399 <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.
403 '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.
407 Date formats should match your system preference, and <strong>must</strong> be zero-padded, e.g. '01/02/2008'. Alternatively,
408 you can supply dates in ISO format (e.g., '2010-10-28').
415 </div> <!-- /.col-sm-10.col-sm-push-2 -->
417 <div class="col-sm-2 col-sm-pull-10">
419 [% INCLUDE 'tools-menu.inc' %]
421 </div> <!-- .col-sm-2.col-sm-pull-10 -->
422 </div> <!-- /.row -->
424 [% MACRO jsinclude BLOCK %]
425 [% INCLUDE 'calendar.inc' %]
426 [% Asset.js("js/tools-menu.js") | $raw %]
427 [% INCLUDE 'str/members-menu.inc' %]
428 [% Asset.js("js/members-menu.js") | $raw %]
430 $(document).ready(function() {
431 [%# Make date fields have the datepicker %]
432 $("#dateenrolled, #dateexpiry, #dateofbirth").flatpickr({
434 altFormat: flatpickr_dateformat_string,
435 altInputClass: 'flatpickr-input',
439 $(".expand_defaults").click(function(e){
441 $(".default_values").toggle();
442 $(".expand_defaults").toggle();
445 $(".expand_preserves").click(function(e){
447 $(".preserve_values").toggle();
448 $(".expand_preserves").toggle();
452 $("#overwrite_cardnumberno").click(function(){
453 $("#overwrite_passwords").prop('checked',false).prop('disabled',true);
454 $("#update_dateexpiry").prop('checked',false).prop('disabled',true);
456 $("#overwrite_cardnumberyes").click(function(){
457 $("#overwrite_passwords").prop('disabled',false);
458 $("#update_dateexpiry").prop('disabled',false);
462 [% INCLUDE 'intranet-bottom.inc' %]