7 [% INCLUDE 'doc-head-open.inc' %]
8 <title>Merge patron records › Patrons › Koha</title>
9 [% INCLUDE 'doc-head-close.inc' %]
13 background-color: #e6ffe6;
16 background-color: #ffe6e6;
29 border-right: 1px solid #EEE;
34 font-family: monospace;
48 <body id="pat_merge" class="pat">
49 [% INCLUDE 'header.inc' %]
50 [% INCLUDE 'patron-search-header.inc' %]
52 [% BLOCK display_names %]
54 [% CASE 'Accountline' %]<span>account lines</span>
55 [% CASE 'ArticleRequest' %]<span>article requests</span>
56 [% CASE 'BorrowerAttribute' %]<span>extended patron attributes</span>
57 [% CASE 'BorrowerDebarment' %]<span>patron restrictions</span>
58 [% CASE 'BorrowerFile' %]<span>patrons files</span>
59 [% CASE 'BorrowerModification' %]<span>patron modification requests</span>
60 [% CASE 'ClubEnrollment' %]<span>club enrollments</span>
61 [% CASE 'Issue' %]<span>checkouts</span>
62 [% CASE 'ItemsLastBorrower' %]<span>marks as last borrower of item</span>
63 [% CASE 'Linktracker' %]<span>tracked link clicks</span>
64 [% CASE 'Message' %]<span>patron messages</span>
65 [% CASE 'MessageQueue' %]<span>patron notices</span>
66 [% CASE 'OldIssue' %]<span>previous checkouts</span>
67 [% CASE 'OldReserve' %]<span>filled holds</span>
68 [% CASE 'Rating' %]<span>ratings</span>
69 [% CASE 'Reserve' %]<span>current holds</span>
70 [% CASE 'Review' %]<span>reviews</span>
71 [% CASE 'Statistic' %]<span>statistics</span>
72 [% CASE 'SearchHistory' %]<span>historical searches</span>
73 [% CASE 'Suggestion' %]<span>purchase suggestions</span>
74 [% CASE 'TagAll' %]<span>tags</span>
75 [% CASE 'Virtualshelfcontent' %]<span>list items</span>
76 [% CASE 'Virtualshelfshare' %]<span>list shares</span>
77 [% CASE 'Virtualshelve' %]<span>lists</span>
78 [% CASE %][% rs | html %]
82 <nav id="breadcrumbs" aria-label="Breadcrumb" class="breadcrumb">
85 <a href="/cgi-bin/koha/mainpage.pl">Home</a>
88 <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a>
91 <a href="#" aria-current="page">Merge patron records</a>
96 <div class="main container-fluid">
98 <div class="col-md-10 col-md-offset-1 col-lg-8 col-lg-offset-2">
99 <h1>Merge patron records</h1>
101 [% IF action == 'show' %]
102 [% IF patrons.count > 1 %]
103 [% IF ( patrons.count == 2 ) %]
104 <div id="toolbar" class="btn-toolbar">
105 <div class="btn-group">
106 <button class="btn btn-default" id="compare_patrons">
107 <i class="fa fa-arrows-h"></i> Compare patrons
113 <p>Select patron to keep. Data from the other patrons will be transferred to this patron record and the remaining patron records will be deleted.</p>
115 <form type="post" action="merge-patrons.pl" id="patron-merge-form">
116 <table id="patron-merge-table" class="datatable">
122 <th>Date of birth</th>
130 [% FOREACH p IN patrons %]
132 <td><input class="keeper" type="radio" name="keeper" value="[% p.id | html %]" data-borrowernumber="[% p.id | html %]" id="keeper_[% p.id | html %]" /></td>
134 <label for="keeper_[% p.id | html %]">
135 <strong>[% p.cardnumber | html %]</strong>
139 <a target="_blank" href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% p.borrowernumber | uri %]">
140 [% INCLUDE 'patron-title.inc' patron = p %]
141 <i class="fa fa-window-restore"></i>
144 <td>[% p.dateofbirth | $KohaDates %]</td>
145 <td>[% Categories.GetName( p.categorycode ) | html %] ([% p.categorycode | html %])</td>
146 <td>[% Branches.GetName( p.branchcode ) | html %]</td>
147 <td>[% p.dateexpiry | $KohaDates %]</td>
152 <fieldset class="action">
153 [% FOREACH p IN patrons %]
154 <input type="hidden" name="id" value="[% p.id | html %]" />
156 <input type="hidden" name="action" value="merge" />
157 <input id="merge-patrons" type="submit" value="Merge patrons" />
161 <div class="dialog alert">Error: Two or more patrons need to be selected for merging</div>
164 [% ELSIF action == 'merge' %]
167 [% IF error == 'INVALID_KEEPER' %]
168 <div class="dialog alert">Merge failed! The patron to keep was invalid.</div>
170 <div class="dialog alert">Merge failed! The following error was reported: [% error | html %].</div>
172 [% ELSIF !results.merged.keys.size %]
173 <div class="dialog alert">No valid patrons to merge were found.</div>
176 Patron records merged into <a href="moremember.pl?borrowernumber=[% keeper.id | uri %]">[% INCLUDE 'patron-title.inc' patron = keeper %]</a>
179 [% FOREACH pair IN results.merged.pairs %]
180 [% SET patron = pair.value.patron %]
182 <h5>[% INCLUDE 'patron-title.inc' %]</h5>
184 [% FOREACH r IN pair.value.updated.pairs %]
185 [% SET name = r.key %]
186 [% SET count = r.value %]
189 <span>[% count | html %] [% PROCESS display_names rs = name %] transferred.</span>
190 [% IF name == 'Reserve' %]
191 <strong>It is advisable to check for and resolve duplicate holds due to merging.</strong>
200 <a class="btn btn-default" href="moremember.pl?borrowernumber=[% keeper.id | html %]">View patron record</a>
207 <div class="modal" id="compareModal" tabindex="-1" role="dialog" aria-labelledby="compareModalLabel">
208 <div class="modal-dialog modal-lg" role="document">
209 <div class="modal-content">
210 <div class="modal-header">
211 <button type="button" class="closebtn" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
212 <h4 class="modal-title" id="compareModalLabel">Compare patrons for merging</h4>
214 <div class="modal-body">
215 <div class="compare">
217 <div><strong>Name:</strong></div>
218 <div><strong>Initials:</strong></div>
219 <div><strong>Other name:</strong></div>
220 <div><strong>Library:</strong></div>
221 <div><strong>Card number:</strong></div>
222 <div><strong>Category:</strong></div>
224 <div><strong>Address line 1:</strong></div>
225 <div><strong>Address line 2:</strong></div>
226 <div><strong>City:</strong></div>
227 <div><strong>State:</strong></div>
228 <div><strong>ZIP/Postal code:</strong></div>
229 <div><strong>Country:</strong></div>
231 <div><strong>Registration date:</strong></div>
232 <div><strong>Renewal date:</strong></div>
233 <div><strong>Expiration date:</strong></div>
234 <div><strong>Date of birth:</strong></div>
235 <div><strong>Restricted:</strong></div>
236 <div><strong>Primary email:</strong></div>
237 <div><strong>Secondary email:</strong></div>
238 <div><strong>Primary phone:</strong></div>
239 <div><strong>Secondary phone:</strong></div>
240 <div><strong>Other phone:</strong></div>
241 <div><strong>Gender:</strong></div>
242 <div><strong>Updated on:</strong></div>
243 <div><strong>Username:</strong></div>
246 [% FOREACH p IN patrons %]
247 <div id="col-[% p.borrowernumber | html %]-orig"class="col[% loop.index | html %]">
248 <!-- <pre> block is unindented to avoid unwanted whitespace -->
250 [% IF ( p.surname ) %][% p.surname | html %], [% p.firstname | html %][% ELSE %]-[% END %]
251 [% IF ( p.initials ) %][% p.initials | html %][% ELSE %]-[% END %]
252 [% IF ( p.othernames ) %][% p.othernames | html %][% ELSE %]-[% END %]
253 [% IF ( p.branchcode ) %][% p.branchcode | html %][% ELSE %]-[% END %]
254 [% IF ( p.cardnumber ) %][% p.cardnumber | html %][% ELSE %]-[% END %]
255 [% IF ( p.categorycode ) %][% p.categorycode | html %][% ELSE %]-[% END %]
257 [% IF ( p.address ) %][% p.address | html %][% ELSE %]-[% END %]
258 [% IF ( p.address2 ) %][% p.address2 | html %][% ELSE %]-[% END %]
259 [% IF ( p.city ) %][% p.city | html %][% ELSE %]-[% END %]
260 [% IF ( p.state ) %][% p.state | html %][% ELSE %]-[% END %]
261 [% IF ( p.zipcode ) %][% p.zipcode | html %][% ELSE %]-[% END %]
262 [% IF ( p.country ) %][% p.country | html %][% ELSE %]-[% END %]
264 [% IF ( p.dateenrolled ) %][% p.dateenrolled | html %][% ELSE %]-[% END %]
265 [% IF ( p.date_renewed ) %][% p.date_renewed | html %][% ELSE %]-[% END %]
266 [% IF ( p.dateexpiry ) %][% p.dateexpiry | html %][% ELSE %]-[% END %]
267 [% IF ( p.dateofbirth ) %][% p.dateofbirth | html %][% ELSE %]-[% END %]
268 [% IF ( p.debarred ) %][% p.debarred | html %][% ELSE %]-[% END %]
269 [% IF ( p.email ) %][% p.email | html %][% ELSE %]-[% END %]
270 [% IF ( p.emailpro ) %][% p.emailpro | html %][% ELSE %]-[% END %]
271 [% IF ( p.phone ) %][% p.phone | html %][% ELSE %]-[% END %]
272 [% IF ( p.phonepro ) %][% p.phonepro | html %][% ELSE %]-[% END %]
273 [% IF ( p.mobile ) %][% p.mobile | html %][% ELSE %]-[% END %]
274 [% IF ( p.sex ) %][% p.sex | html %][% ELSE %]-[% END %]
275 [% IF ( p.updated_on ) %][% p.updated_on | html %][% ELSE %]-[% END %]
276 [% IF ( p.userid ) %][% p.userid | html %][% ELSE %]-[% END %]
280 [% FOREACH p IN patrons %]
281 <div id="col-[% p.borrowernumber | html %]-diff" class="col[% ( loop.index + 2 ) | html %]"><pre></pre></div>
285 <div class="modal-footer">
286 <button type="button" class="btn btn-default" id="submit-merge-form"><i class="fa fa-compress" aria-hidden="true"></i> Merge patrons</button>
287 <button type="button" class="btn btn-default" data-dismiss="modal"><i class="fa fa-remove" aria-hidden="true"></i> Close</button>
289 </div> <!-- /.modal-content -->
290 </div> <!-- /.modal-dialog -->
291 </div> <!-- /#compareModal -->
293 [% MACRO jsinclude BLOCK %]
294 [% INCLUDE 'str/members-menu.inc' %]
295 [% Asset.js("js/members-menu.js") | $raw %]
296 [% Asset.js("lib/jsdiff/jsdiff.min.js") | $raw %]
298 $(document).ready(function() {
299 var controls = $("#merge-patrons, #compare_patrons");
300 controls.prop('disabled', true);
301 $('#patron-merge-table').on('change', 'input', function() {
302 if ( $('.keeper:checked').length > 0 ) {
303 controls.prop('disabled', false);
305 controls.prop('disabled', true);
309 $("#compare_patrons").on("click", function(e){
311 $("#compareModal").modal("show");
314 $("#compareModal").on("shown.bs.modal", function(){
315 /* Find which column is the basis for merging */
316 var col0 = $(".keeper:checked").data("borrowernumber");
317 var col1 = $(".keeper:not(:checked)").data("borrowernumber");
318 /* Get the original patron data for comparison */
319 var diff1 = $("#col-" + col0 + "-orig pre").text();
320 var diff2 = $("#col-" + col1 + "-orig pre").text();
322 var diffs = diffString(diff2, diff1);
323 /* Load the diff HTML in the empty columns */
324 $(".col2 pre, .col3 pre").html(diffs);
327 $("#submit-merge-form").on("click", function(){
328 $("#patron-merge-form").submit();
335 [% INCLUDE 'intranet-bottom.inc' %]