LP#1643709 User merge + purge pgtap test
[working/Evergreen.git] / Open-ILS / src / sql / Pg / upgrade / xxxx.function.global.purge-usr-on-merge.sql
1 BEGIN;
2
3 -- SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version);
4
5 CREATE OR REPLACE FUNCTION actor.usr_merge( src_usr INT, dest_usr INT, del_addrs BOOLEAN, del_cards BOOLEAN, deactivate_cards BOOLEAN ) RETURNS VOID AS $$
6 DECLARE
7         suffix TEXT;
8         bucket_row RECORD;
9         picklist_row RECORD;
10         queue_row RECORD;
11         folder_row RECORD;
12 BEGIN
13
14     -- Bail if src_usr equals dest_usr because the result of merging a
15     -- user with itself is not what you want.
16     IF src_usr = dest_usr THEN
17         RETURN;
18     END IF;
19
20     -- do some initial cleanup 
21     UPDATE actor.usr SET card = NULL WHERE id = src_usr;
22     UPDATE actor.usr SET mailing_address = NULL WHERE id = src_usr;
23     UPDATE actor.usr SET billing_address = NULL WHERE id = src_usr;
24
25     -- actor.*
26     IF del_cards THEN
27         DELETE FROM actor.card where usr = src_usr;
28     ELSE
29         IF deactivate_cards THEN
30             UPDATE actor.card SET active = 'f' WHERE usr = src_usr;
31         END IF;
32         UPDATE actor.card SET usr = dest_usr WHERE usr = src_usr;
33     END IF;
34
35
36     IF del_addrs THEN
37         DELETE FROM actor.usr_address WHERE usr = src_usr;
38     ELSE
39         UPDATE actor.usr_address SET usr = dest_usr WHERE usr = src_usr;
40     END IF;
41
42     UPDATE actor.usr_note SET usr = dest_usr WHERE usr = src_usr;
43     -- dupes are technically OK in actor.usr_standing_penalty, should manually delete them...
44     UPDATE actor.usr_standing_penalty SET usr = dest_usr WHERE usr = src_usr;
45     PERFORM actor.usr_merge_rows('actor.usr_org_unit_opt_in', 'usr', src_usr, dest_usr);
46     PERFORM actor.usr_merge_rows('actor.usr_setting', 'usr', src_usr, dest_usr);
47
48     -- permission.*
49     PERFORM actor.usr_merge_rows('permission.usr_perm_map', 'usr', src_usr, dest_usr);
50     PERFORM actor.usr_merge_rows('permission.usr_object_perm_map', 'usr', src_usr, dest_usr);
51     PERFORM actor.usr_merge_rows('permission.usr_grp_map', 'usr', src_usr, dest_usr);
52     PERFORM actor.usr_merge_rows('permission.usr_work_ou_map', 'usr', src_usr, dest_usr);
53
54
55     -- container.*
56         
57         -- For each *_bucket table: transfer every bucket belonging to src_usr
58         -- into the custody of dest_usr.
59         --
60         -- In order to avoid colliding with an existing bucket owned by
61         -- the destination user, append the source user's id (in parenthesese)
62         -- to the name.  If you still get a collision, add successive
63         -- spaces to the name and keep trying until you succeed.
64         --
65         FOR bucket_row in
66                 SELECT id, name
67                 FROM   container.biblio_record_entry_bucket
68                 WHERE  owner = src_usr
69         LOOP
70                 suffix := ' (' || src_usr || ')';
71                 LOOP
72                         BEGIN
73                                 UPDATE  container.biblio_record_entry_bucket
74                                 SET     owner = dest_usr, name = name || suffix
75                                 WHERE   id = bucket_row.id;
76                         EXCEPTION WHEN unique_violation THEN
77                                 suffix := suffix || ' ';
78                                 CONTINUE;
79                         END;
80                         EXIT;
81                 END LOOP;
82         END LOOP;
83
84         FOR bucket_row in
85                 SELECT id, name
86                 FROM   container.call_number_bucket
87                 WHERE  owner = src_usr
88         LOOP
89                 suffix := ' (' || src_usr || ')';
90                 LOOP
91                         BEGIN
92                                 UPDATE  container.call_number_bucket
93                                 SET     owner = dest_usr, name = name || suffix
94                                 WHERE   id = bucket_row.id;
95                         EXCEPTION WHEN unique_violation THEN
96                                 suffix := suffix || ' ';
97                                 CONTINUE;
98                         END;
99                         EXIT;
100                 END LOOP;
101         END LOOP;
102
103         FOR bucket_row in
104                 SELECT id, name
105                 FROM   container.copy_bucket
106                 WHERE  owner = src_usr
107         LOOP
108                 suffix := ' (' || src_usr || ')';
109                 LOOP
110                         BEGIN
111                                 UPDATE  container.copy_bucket
112                                 SET     owner = dest_usr, name = name || suffix
113                                 WHERE   id = bucket_row.id;
114                         EXCEPTION WHEN unique_violation THEN
115                                 suffix := suffix || ' ';
116                                 CONTINUE;
117                         END;
118                         EXIT;
119                 END LOOP;
120         END LOOP;
121
122         FOR bucket_row in
123                 SELECT id, name
124                 FROM   container.user_bucket
125                 WHERE  owner = src_usr
126         LOOP
127                 suffix := ' (' || src_usr || ')';
128                 LOOP
129                         BEGIN
130                                 UPDATE  container.user_bucket
131                                 SET     owner = dest_usr, name = name || suffix
132                                 WHERE   id = bucket_row.id;
133                         EXCEPTION WHEN unique_violation THEN
134                                 suffix := suffix || ' ';
135                                 CONTINUE;
136                         END;
137                         EXIT;
138                 END LOOP;
139         END LOOP;
140
141         UPDATE container.user_bucket_item SET target_user = dest_usr WHERE target_user = src_usr;
142
143     -- vandelay.*
144         -- transfer queues the same way we transfer buckets (see above)
145         FOR queue_row in
146                 SELECT id, name
147                 FROM   vandelay.queue
148                 WHERE  owner = src_usr
149         LOOP
150                 suffix := ' (' || src_usr || ')';
151                 LOOP
152                         BEGIN
153                                 UPDATE  vandelay.queue
154                                 SET     owner = dest_usr, name = name || suffix
155                                 WHERE   id = queue_row.id;
156                         EXCEPTION WHEN unique_violation THEN
157                                 suffix := suffix || ' ';
158                                 CONTINUE;
159                         END;
160                         EXIT;
161                 END LOOP;
162         END LOOP;
163
164     UPDATE vandelay.session_tracker SET usr = dest_usr WHERE usr = src_usr;
165
166     -- money.*
167     PERFORM actor.usr_merge_rows('money.collections_tracker', 'usr', src_usr, dest_usr);
168     PERFORM actor.usr_merge_rows('money.collections_tracker', 'collector', src_usr, dest_usr);
169     UPDATE money.billable_xact SET usr = dest_usr WHERE usr = src_usr;
170     UPDATE money.billing SET voider = dest_usr WHERE voider = src_usr;
171     UPDATE money.bnm_payment SET accepting_usr = dest_usr WHERE accepting_usr = src_usr;
172
173     -- action.*
174     UPDATE action.circulation SET usr = dest_usr WHERE usr = src_usr;
175     UPDATE action.circulation SET circ_staff = dest_usr WHERE circ_staff = src_usr;
176     UPDATE action.circulation SET checkin_staff = dest_usr WHERE checkin_staff = src_usr;
177     UPDATE action.usr_circ_history SET usr = dest_usr WHERE usr = src_usr;
178
179     UPDATE action.hold_request SET usr = dest_usr WHERE usr = src_usr;
180     UPDATE action.hold_request SET fulfillment_staff = dest_usr WHERE fulfillment_staff = src_usr;
181     UPDATE action.hold_request SET requestor = dest_usr WHERE requestor = src_usr;
182     UPDATE action.hold_notification SET notify_staff = dest_usr WHERE notify_staff = src_usr;
183
184     UPDATE action.in_house_use SET staff = dest_usr WHERE staff = src_usr;
185     UPDATE action.non_cataloged_circulation SET staff = dest_usr WHERE staff = src_usr;
186     UPDATE action.non_cataloged_circulation SET patron = dest_usr WHERE patron = src_usr;
187     UPDATE action.non_cat_in_house_use SET staff = dest_usr WHERE staff = src_usr;
188     UPDATE action.survey_response SET usr = dest_usr WHERE usr = src_usr;
189
190     -- acq.*
191     UPDATE acq.fund_allocation SET allocator = dest_usr WHERE allocator = src_usr;
192         UPDATE acq.fund_transfer SET transfer_user = dest_usr WHERE transfer_user = src_usr;
193     UPDATE acq.invoice SET closed_by = dest_usr WHERE closed_by = src_usr;
194
195         -- transfer picklists the same way we transfer buckets (see above)
196         FOR picklist_row in
197                 SELECT id, name
198                 FROM   acq.picklist
199                 WHERE  owner = src_usr
200         LOOP
201                 suffix := ' (' || src_usr || ')';
202                 LOOP
203                         BEGIN
204                                 UPDATE  acq.picklist
205                                 SET     owner = dest_usr, name = name || suffix
206                                 WHERE   id = picklist_row.id;
207                         EXCEPTION WHEN unique_violation THEN
208                                 suffix := suffix || ' ';
209                                 CONTINUE;
210                         END;
211                         EXIT;
212                 END LOOP;
213         END LOOP;
214
215     UPDATE acq.purchase_order SET owner = dest_usr WHERE owner = src_usr;
216     UPDATE acq.po_note SET creator = dest_usr WHERE creator = src_usr;
217     UPDATE acq.po_note SET editor = dest_usr WHERE editor = src_usr;
218     UPDATE acq.provider_note SET creator = dest_usr WHERE creator = src_usr;
219     UPDATE acq.provider_note SET editor = dest_usr WHERE editor = src_usr;
220     UPDATE acq.lineitem_note SET creator = dest_usr WHERE creator = src_usr;
221     UPDATE acq.lineitem_note SET editor = dest_usr WHERE editor = src_usr;
222     UPDATE acq.lineitem_usr_attr_definition SET usr = dest_usr WHERE usr = src_usr;
223
224     -- asset.*
225     UPDATE asset.copy SET creator = dest_usr WHERE creator = src_usr;
226     UPDATE asset.copy SET editor = dest_usr WHERE editor = src_usr;
227     UPDATE asset.copy_note SET creator = dest_usr WHERE creator = src_usr;
228     UPDATE asset.call_number SET creator = dest_usr WHERE creator = src_usr;
229     UPDATE asset.call_number SET editor = dest_usr WHERE editor = src_usr;
230     UPDATE asset.call_number_note SET creator = dest_usr WHERE creator = src_usr;
231
232     -- serial.*
233     UPDATE serial.record_entry SET creator = dest_usr WHERE creator = src_usr;
234     UPDATE serial.record_entry SET editor = dest_usr WHERE editor = src_usr;
235
236     -- reporter.*
237     -- It's not uncommon to define the reporter schema in a replica 
238     -- DB only, so don't assume these tables exist in the write DB.
239     BEGIN
240         UPDATE reporter.template SET owner = dest_usr WHERE owner = src_usr;
241     EXCEPTION WHEN undefined_table THEN
242         -- do nothing
243     END;
244     BEGIN
245         UPDATE reporter.report SET owner = dest_usr WHERE owner = src_usr;
246     EXCEPTION WHEN undefined_table THEN
247         -- do nothing
248     END;
249     BEGIN
250         UPDATE reporter.schedule SET runner = dest_usr WHERE runner = src_usr;
251     EXCEPTION WHEN undefined_table THEN
252         -- do nothing
253     END;
254     BEGIN
255                 -- transfer folders the same way we transfer buckets (see above)
256                 FOR folder_row in
257                         SELECT id, name
258                         FROM   reporter.template_folder
259                         WHERE  owner = src_usr
260                 LOOP
261                         suffix := ' (' || src_usr || ')';
262                         LOOP
263                                 BEGIN
264                                         UPDATE  reporter.template_folder
265                                         SET     owner = dest_usr, name = name || suffix
266                                         WHERE   id = folder_row.id;
267                                 EXCEPTION WHEN unique_violation THEN
268                                         suffix := suffix || ' ';
269                                         CONTINUE;
270                                 END;
271                                 EXIT;
272                         END LOOP;
273                 END LOOP;
274     EXCEPTION WHEN undefined_table THEN
275         -- do nothing
276     END;
277     BEGIN
278                 -- transfer folders the same way we transfer buckets (see above)
279                 FOR folder_row in
280                         SELECT id, name
281                         FROM   reporter.report_folder
282                         WHERE  owner = src_usr
283                 LOOP
284                         suffix := ' (' || src_usr || ')';
285                         LOOP
286                                 BEGIN
287                                         UPDATE  reporter.report_folder
288                                         SET     owner = dest_usr, name = name || suffix
289                                         WHERE   id = folder_row.id;
290                                 EXCEPTION WHEN unique_violation THEN
291                                         suffix := suffix || ' ';
292                                         CONTINUE;
293                                 END;
294                                 EXIT;
295                         END LOOP;
296                 END LOOP;
297     EXCEPTION WHEN undefined_table THEN
298         -- do nothing
299     END;
300     BEGIN
301                 -- transfer folders the same way we transfer buckets (see above)
302                 FOR folder_row in
303                         SELECT id, name
304                         FROM   reporter.output_folder
305                         WHERE  owner = src_usr
306                 LOOP
307                         suffix := ' (' || src_usr || ')';
308                         LOOP
309                                 BEGIN
310                                         UPDATE  reporter.output_folder
311                                         SET     owner = dest_usr, name = name || suffix
312                                         WHERE   id = folder_row.id;
313                                 EXCEPTION WHEN unique_violation THEN
314                                         suffix := suffix || ' ';
315                                         CONTINUE;
316                                 END;
317                                 EXIT;
318                         END LOOP;
319                 END LOOP;
320     EXCEPTION WHEN undefined_table THEN
321         -- do nothing
322     END;
323
324     -- propagate preferred name values from the source user to the
325     -- destination user, but only when values are not being replaced.
326     WITH susr AS (SELECT * FROM actor.usr WHERE id = src_usr)
327     UPDATE actor.usr SET 
328         pref_prefix = 
329             COALESCE(pref_prefix, (SELECT pref_prefix FROM susr)),
330         pref_first_given_name = 
331             COALESCE(pref_first_given_name, (SELECT pref_first_given_name FROM susr)),
332         pref_second_given_name = 
333             COALESCE(pref_second_given_name, (SELECT pref_second_given_name FROM susr)),
334         pref_family_name = 
335             COALESCE(pref_family_name, (SELECT pref_family_name FROM susr)),
336         pref_suffix = 
337             COALESCE(pref_suffix, (SELECT pref_suffix FROM susr))
338     WHERE id = dest_usr;
339
340     -- Copy and deduplicate name keywords
341     -- String -> array -> rows -> DISTINCT -> array -> string
342     WITH susr AS (SELECT * FROM actor.usr WHERE id = src_usr),
343          dusr AS (SELECT * FROM actor.usr WHERE id = dest_usr)
344     UPDATE actor.usr SET name_keywords = (
345         WITH keywords AS (
346             SELECT DISTINCT UNNEST(
347                 REGEXP_SPLIT_TO_ARRAY(
348                     COALESCE((SELECT name_keywords FROM susr), '') || ' ' ||
349                     COALESCE((SELECT name_keywords FROM dusr), ''),  E'\\s+'
350                 )
351             ) AS parts
352         ) SELECT ARRAY_TO_STRING(ARRAY_AGG(kw.parts), ' ') FROM keywords kw
353     ) WHERE id = dest_usr;
354
355     -- Finally, delete the source user
356     PERFORM actor.usr_delete(src_usr,dest_usr);
357
358 END;
359 $$ LANGUAGE plpgsql;
360
361 COMMIT;