2 CREATE OR REPLACE FUNCTION migration_tools.create_staff_user(
7 first_name TEXT DEFAULT '',
8 last_name TEXT DEFAULT ''
9 ) RETURNS VOID AS $func$
11 RAISE NOTICE '%', org ;
12 INSERT INTO actor.usr (usrname, passwd, ident_type, first_given_name, family_name, home_ou, profile)
13 SELECT username, password, 1, first_name, last_name, aou.id, pgt.id
14 FROM actor.org_unit aou, permission.grp_tree pgt
15 WHERE aou.shortname = org
16 AND pgt.name = perm_group;
21 -- FIXME: testing for STAFF_LOGIN perm is probably better
22 CREATE OR REPLACE FUNCTION migration_tools.is_staff_profile (INT) RETURNS BOOLEAN AS $$
26 RETURN CASE WHEN 'Staff' IN (select (permission.grp_ancestors(profile)).name) THEN TRUE ELSE FALSE END;
28 $$ LANGUAGE PLPGSQL STRICT STABLE;
30 -- TODO: make another version of the procedure below that can work with specified copy staging tables
31 -- The following should track the logic of OpenILS::Application::AppUtils::get_copy_price
32 CREATE OR REPLACE FUNCTION migration_tools.get_copy_price( item BIGINT ) RETURNS NUMERIC AS $$
35 charge_lost_on_zero BOOLEAN;
38 default_price NUMERIC;
39 working_price NUMERIC;
43 SELECT INTO context_lib CASE WHEN call_number = -1 THEN circ_lib ELSE owning_lib END
44 FROM asset.copy ac, asset.call_number acn WHERE ac.call_number = acn.id AND ac.id = item;
46 SELECT INTO charge_lost_on_zero value
47 FROM actor.org_unit_ancestor_setting('circ.charge_lost_on_zero',context_lib);
49 SELECT INTO min_price value
50 FROM actor.org_unit_ancestor_setting('circ.min_item_price',context_lib);
52 SELECT INTO max_price value
53 FROM actor.org_unit_ancestor_setting('circ.max_item_price',context_lib);
55 SELECT INTO default_price value
56 FROM actor.org_unit_ancestor_setting('cat.default_item_price',context_lib);
58 SELECT INTO working_price price FROM asset.copy WHERE id = item;
60 IF (working_price IS NULL OR (working_price = 0 AND charge_lost_on_zero)) THEN
61 working_price := default_price;
64 IF (max_price IS NOT NULL AND working_price > max_price) THEN
65 working_price := max_price;
68 IF (min_price IS NOT NULL AND working_price < min_price) THEN
69 IF (working_price <> 0 OR charge_lost_on_zero IS NULL OR charge_lost_on_zero) THEN
70 working_price := min_price;
80 CREATE OR REPLACE FUNCTION migration_tools.apply_circ_matrix( tablename TEXT ) RETURNS VOID AS $$
84 -- First make sure the circ matrix is loaded and the circulations
85 -- have been staged to the extent possible (but at the very least
86 -- circ_lib, target_copy, usr, and *_renewal). User profiles and
87 -- circ modifiers must also be in place.
89 -- SELECT migration_tools.apply_circ_matrix('m_pioneer.action_circulation');
97 this_duration_rule INT;
99 this_max_fine_rule INT;
100 rcd config.rule_circ_duration%ROWTYPE;
101 rrf config.rule_recurring_fine%ROWTYPE;
102 rmf config.rule_max_fine%ROWTYPE;
109 EXECUTE 'SELECT COUNT(*) FROM ' || tablename || ';' INTO n_circs;
111 FOR circ IN EXECUTE ('SELECT id FROM ' || tablename) LOOP
113 -- Fetch the correct rules for this circulation
120 WHEN phone_renewal OR desk_renewal OR opac_renewal THEN TRUE
123 FROM ' || tablename || ' WHERE id = ' || circ || ';')
124 INTO circ_lib, target_copy, usr, is_renewal ;
126 INTO this_duration_rule,
132 FROM action.item_user_circ_test(
138 SELECT INTO rcd * FROM config.rule_circ_duration
139 WHERE id = this_duration_rule;
140 SELECT INTO rrf * FROM config.rule_recurring_fine
141 WHERE id = this_fine_rule;
142 SELECT INTO rmf * FROM config.rule_max_fine
143 WHERE id = this_max_fine_rule;
145 -- Apply the rules to this circulation
146 EXECUTE ('UPDATE ' || tablename || ' c
148 duration_rule = rcd.name,
149 recurring_fine_rule = rrf.name,
150 max_fine_rule = rmf.name,
151 duration = rcd.normal,
152 recurring_fine = rrf.normal,
155 WHEN TRUE THEN (rmf.amount / 100.0) * ac.price
158 renewal_remaining = rcd.max_renewals
160 config.rule_circ_duration rcd,
161 config.rule_recurring_fine rrf,
162 config.rule_max_fine rmf,
165 rcd.id = ' || this_duration_rule || ' AND
166 rrf.id = ' || this_fine_rule || ' AND
167 rmf.id = ' || this_max_fine_rule || ' AND
168 ac.id = c.target_copy AND
169 c.id = ' || circ || ';');
171 -- Keep track of where we are in the process
173 IF (n % 100 = 0) THEN
174 RAISE INFO '%', n || ' of ' || n_circs
175 || ' (' || (100*n/n_circs) || '%) circs updated.';
185 CREATE OR REPLACE FUNCTION migration_tools.apply_circ_matrix_to_specific_circ( tablename TEXT, circ BIGINT ) RETURNS VOID AS $$
189 -- First make sure the circ matrix is loaded and the circulations
190 -- have been staged to the extent possible (but at the very least
191 -- circ_lib, target_copy, usr, and *_renewal). User profiles and
192 -- circ modifiers must also be in place.
194 -- SELECT migration_tools.apply_circ_matrix_to_specific_circ('m_nwrl.action_circulation', 18391960);
202 this_duration_rule INT;
204 this_max_fine_rule INT;
205 rcd config.rule_circ_duration%ROWTYPE;
206 rrf config.rule_recurring_fine%ROWTYPE;
207 rmf config.rule_max_fine%ROWTYPE;
213 --EXECUTE 'SELECT COUNT(*) FROM ' || tablename || ';' INTO n_circs;
215 --FOR circ IN EXECUTE ('SELECT id FROM ' || tablename) LOOP
217 -- Fetch the correct rules for this circulation
224 WHEN phone_renewal OR desk_renewal OR opac_renewal THEN TRUE
227 FROM ' || tablename || ' WHERE id = ' || circ || ';')
228 INTO circ_lib, target_copy, usr, is_renewal ;
230 INTO this_duration_rule,
233 (matchpoint).duration_rule,
234 (matchpoint).recurring_fine_rule,
235 (matchpoint).max_fine_rule
236 FROM action.find_circ_matrix_matchpoint(
242 SELECT INTO rcd * FROM config.rule_circ_duration
243 WHERE id = this_duration_rule;
244 SELECT INTO rrf * FROM config.rule_recurring_fine
245 WHERE id = this_fine_rule;
246 SELECT INTO rmf * FROM config.rule_max_fine
247 WHERE id = this_max_fine_rule;
249 -- Apply the rules to this circulation
250 EXECUTE ('UPDATE ' || tablename || ' c
252 duration_rule = rcd.name,
253 recurring_fine_rule = rrf.name,
254 max_fine_rule = rmf.name,
255 duration = rcd.normal,
256 recurring_fine = rrf.normal,
259 WHEN TRUE THEN (rmf.amount / 100.0) * migration_tools.get_copy_price(ac.id)
262 renewal_remaining = rcd.max_renewals,
263 grace_period = rrf.grace_period
265 config.rule_circ_duration rcd,
266 config.rule_recurring_fine rrf,
267 config.rule_max_fine rmf,
270 rcd.id = ' || this_duration_rule || ' AND
271 rrf.id = ' || this_fine_rule || ' AND
272 rmf.id = ' || this_max_fine_rule || ' AND
273 ac.id = c.target_copy AND
274 c.id = ' || circ || ';');
276 -- Keep track of where we are in the process
278 IF (n % 100 = 0) THEN
279 RAISE INFO '%', n || ' of ' || n_circs
280 || ' (' || (100*n/n_circs) || '%) circs updated.';
290 CREATE OR REPLACE FUNCTION migration_tools.assign_standing_penalties ( ) RETURNS VOID AS $$
292 -- USAGE: Once circulation data has been loaded, and group penalty thresholds have been set up, run this.
293 -- This will assign standing penalties as needed.
301 FOR org_unit IN EXECUTE ('SELECT DISTINCT org_unit FROM permission.grp_penalty_threshold;') LOOP
303 FOR usr IN EXECUTE ('SELECT id FROM actor.usr WHERE NOT deleted;') LOOP
305 EXECUTE('SELECT actor.calculate_system_penalties(' || usr || ', ' || org_unit || ');');
317 CREATE OR REPLACE FUNCTION migration_tools.insert_metarecords_for_pristine_database () RETURNS VOID AS $$
320 INSERT INTO metabib.metarecord (fingerprint, master_record)
321 SELECT DISTINCT ON (b.fingerprint) b.fingerprint, b.id
322 FROM biblio.record_entry b
324 AND b.id IN (SELECT r.id FROM biblio.record_entry r LEFT JOIN metabib.metarecord_source_map k ON (k.source = r.id) WHERE k.id IS NULL AND r.fingerprint IS NOT NULL)
325 AND NOT EXISTS ( SELECT 1 FROM metabib.metarecord WHERE fingerprint = b.fingerprint )
326 ORDER BY b.fingerprint, b.quality DESC;
327 INSERT INTO metabib.metarecord_source_map (metarecord, source)
329 FROM biblio.record_entry r
330 JOIN metabib.metarecord m USING (fingerprint)
337 CREATE OR REPLACE FUNCTION migration_tools.insert_metarecords_for_incumbent_database () RETURNS VOID AS $$
340 INSERT INTO metabib.metarecord (fingerprint, master_record)
341 SELECT DISTINCT ON (b.fingerprint) b.fingerprint, b.id
342 FROM biblio.record_entry b
344 AND b.id IN (SELECT r.id FROM biblio.record_entry r LEFT JOIN metabib.metarecord_source_map k ON (k.source = r.id) WHERE k.id IS NULL AND r.fingerprint IS NOT NULL)
345 AND NOT EXISTS ( SELECT 1 FROM metabib.metarecord WHERE fingerprint = b.fingerprint )
346 ORDER BY b.fingerprint, b.quality DESC;
347 INSERT INTO metabib.metarecord_source_map (metarecord, source)
349 FROM biblio.record_entry r
350 JOIN metabib.metarecord m USING (fingerprint)
352 AND r.id IN (SELECT b.id FROM biblio.record_entry b LEFT JOIN metabib.metarecord_source_map k ON (k.source = b.id) WHERE k.id IS NULL);
357 CREATE OR REPLACE FUNCTION migration_tools.create_cards( schemaname TEXT ) RETURNS VOID AS $$
359 -- USAGE: Make sure the patrons are staged in schemaname.actor_usr_legacy and have 'usrname' assigned.
360 -- Then SELECT migration_tools.create_cards('m_foo');
363 u TEXT := schemaname || '.actor_usr_legacy';
364 c TEXT := schemaname || '.actor_card';
368 EXECUTE ('DELETE FROM ' || c || ';');
369 EXECUTE ('INSERT INTO ' || c || ' (usr, barcode) SELECT id, usrname FROM ' || u || ';');
370 EXECUTE ('UPDATE ' || u || ' u SET card = c.id FROM ' || c || ' c WHERE c.usr = u.id;');
378 CREATE OR REPLACE FUNCTION migration_tools.check_ou_depth ( ) RETURNS VOID AS $$
385 errors_found BOOLEAN;
387 parent_shortname TEXT;
393 type_parent_depth INT;
398 errors_found := FALSE;
400 -- Checking actor.org_unit_type
402 FOR type_id IN EXECUTE ('SELECT id FROM actor.org_unit_type ORDER BY id;') LOOP
404 SELECT depth FROM actor.org_unit_type WHERE id = type_id INTO type_depth;
405 SELECT parent FROM actor.org_unit_type WHERE id = type_id INTO type_parent;
407 IF type_parent IS NOT NULL THEN
409 SELECT depth FROM actor.org_unit_type WHERE id = type_parent INTO type_parent_depth;
411 IF type_depth - type_parent_depth <> 1 THEN
412 SELECT name FROM actor.org_unit_type WHERE id = type_id INTO ou_type_name;
413 SELECT name FROM actor.org_unit_type WHERE id = type_parent INTO parent_type;
414 RAISE INFO 'The % org unit type has a depth of %, but its parent org unit type, %, has a depth of %.',
415 ou_type_name, type_depth, parent_type, type_parent_depth;
416 errors_found := TRUE;
424 -- Checking actor.org_unit
426 FOR ou IN EXECUTE ('SELECT id FROM actor.org_unit ORDER BY shortname;') LOOP
428 SELECT parent_ou FROM actor.org_unit WHERE id = ou INTO ou_parent;
429 SELECT t.depth FROM actor.org_unit_type t, actor.org_unit o WHERE o.ou_type = t.id and o.id = ou INTO org_unit_depth;
430 SELECT t.depth FROM actor.org_unit_type t, actor.org_unit o WHERE o.ou_type = t.id and o.id = ou_parent INTO parent_depth;
431 SELECT shortname FROM actor.org_unit WHERE id = ou INTO ou_shortname;
432 SELECT shortname FROM actor.org_unit WHERE id = ou_parent INTO parent_shortname;
433 SELECT t.name FROM actor.org_unit_type t, actor.org_unit o WHERE o.ou_type = t.id and o.id = ou INTO ou_type_name;
434 SELECT t.name FROM actor.org_unit_type t, actor.org_unit o WHERE o.ou_type = t.id and o.id = ou_parent INTO parent_type;
436 IF ou_parent IS NOT NULL THEN
438 IF (org_unit_depth - parent_depth <> 1) OR (
439 (SELECT parent FROM actor.org_unit_type WHERE name = ou_type_name) <> (SELECT id FROM actor.org_unit_type WHERE name = parent_type)
441 RAISE INFO '% (org unit %) is a % (depth %) but its parent, % (org unit %), is a % (depth %).',
442 ou_shortname, ou, ou_type_name, org_unit_depth, parent_shortname, ou_parent, parent_type, parent_depth;
443 errors_found := TRUE;
450 IF NOT errors_found THEN
451 RAISE INFO 'No errors found.';
460 CREATE OR REPLACE FUNCTION migration_tools.simple_export_library_config(dir TEXT, orgs INT[]) RETURNS VOID AS $FUNC$
462 EXECUTE $$COPY (SELECT * FROM actor.hours_of_operation WHERE id IN ($$ ||
463 ARRAY_TO_STRING(orgs, ',') || $$)$$ ||
464 $$) TO '$$ || dir || $$/actor_hours_of_operation'$$;
465 EXECUTE $$COPY (SELECT org_unit, close_start, close_end, reason FROM actor.org_unit_closed WHERE org_unit IN ($$ ||
466 ARRAY_TO_STRING(orgs, ',') || $$)$$ ||
467 $$) TO '$$ || dir || $$/actor_org_unit_closed'$$;
468 EXECUTE $$COPY (SELECT org_unit, name, value FROM actor.org_unit_setting WHERE org_unit IN ($$ ||
469 ARRAY_TO_STRING(orgs, ',') || $$)$$ ||
470 $$) TO '$$ || dir || $$/actor_org_unit_setting'$$;
471 EXECUTE $$COPY (SELECT name, owning_lib, holdable, hold_verify, opac_visible, circulate FROM asset.copy_location WHERE owning_lib IN ($$ ||
472 ARRAY_TO_STRING(orgs, ',') || $$)$$ ||
473 $$) TO '$$ || dir || $$/asset_copy_location'$$;
474 EXECUTE $$COPY (SELECT grp, org_unit, penalty, threshold FROM permission.grp_penalty_threshold WHERE org_unit IN ($$ ||
475 ARRAY_TO_STRING(orgs, ',') || $$)$$ ||
476 $$) TO '$$ || dir || $$/permission_grp_penalty_threshold'$$;
477 EXECUTE $$COPY (SELECT owning_lib, label, label_sortkey FROM asset.call_number_prefix WHERE owning_lib IN ($$ ||
478 ARRAY_TO_STRING(orgs, ',') || $$)$$ ||
479 $$) TO '$$ || dir || $$/asset_call_number_prefix'$$;
480 EXECUTE $$COPY (SELECT owning_lib, label, label_sortkey FROM asset.call_number_suffix WHERE owning_lib IN ($$ ||
481 ARRAY_TO_STRING(orgs, ',') || $$)$$ ||
482 $$) TO '$$ || dir || $$/asset_call_number_suffix'$$;
483 EXECUTE $$COPY config.rule_circ_duration TO '$$ || dir || $$/config_rule_circ_duration'$$;
484 EXECUTE $$COPY config.rule_age_hold_protect TO '$$ || dir || $$/config_rule_age_hold_protect'$$;
485 EXECUTE $$COPY config.rule_max_fine TO '$$ || dir || $$/config_rule_max_fine'$$;
486 EXECUTE $$COPY config.rule_recurring_fine TO '$$ || dir || $$/config_rule_recurring_fine'$$;
487 EXECUTE $$COPY permission.grp_tree TO '$$ || dir || $$/permission_grp_tree'$$;
489 $FUNC$ LANGUAGE PLPGSQL;
491 CREATE OR REPLACE FUNCTION migration_tools.simple_import_library_config(dir TEXT) RETURNS VOID AS $FUNC$
493 EXECUTE $$COPY actor.hours_of_operation FROM '$$ || dir || $$/actor_hours_of_operation'$$;
494 EXECUTE $$COPY actor.org_unit_closed (org_unit, close_start, close_end, reason) FROM '$$ || dir || $$/actor_org_unit_closed'$$;
495 EXECUTE $$COPY actor.org_unit_setting (org_unit, name, value) FROM '$$ || dir || $$/actor_org_unit_setting'$$;
496 EXECUTE $$COPY asset.copy_location (name, owning_lib, holdable, hold_verify, opac_visible, circulate) FROM '$$ || dir || $$/asset_copy_location'$$;
497 EXECUTE $$COPY permission.grp_penalty_threshold (grp, org_unit, penalty, threshold) FROM '$$ || dir || $$/permission_grp_penalty_threshold'$$;
498 EXECUTE $$COPY asset.call_number_prefix (owning_lib, label, label_sortkey) FROM '$$ || dir || $$/asset_call_number_prefix'$$;
499 EXECUTE $$COPY asset.call_number_suffix (owning_lib, label, label_sortkey) FROM '$$ || dir || $$/asset_call_number_suffix'$$;
501 -- import any new circ rules
502 PERFORM migration_tools.simple_import_new_rows_by_value(dir, 'config', 'rule_circ_duration', 'id', 'name');
503 PERFORM migration_tools.simple_import_new_rows_by_value(dir, 'config', 'rule_age_hold_protect', 'id', 'name');
504 PERFORM migration_tools.simple_import_new_rows_by_value(dir, 'config', 'rule_max_fine', 'id', 'name');
505 PERFORM migration_tools.simple_import_new_rows_by_value(dir, 'config', 'rule_recurring_fine', 'id', 'name');
507 -- and permission groups
508 PERFORM migration_tools.simple_import_new_rows_by_value(dir, 'permission', 'grp_tree', 'id', 'name');
511 $FUNC$ LANGUAGE PLPGSQL;
513 -- example: SELECT * FROM migration_tools.duplicate_template(5,'{3,4}');
514 CREATE OR REPLACE FUNCTION migration_tools.duplicate_template (INTEGER, INTEGER[]) RETURNS VOID AS $$
516 target_event_def ALIAS FOR $1;
519 DROP TABLE IF EXISTS new_atevdefs;
520 CREATE TEMP TABLE new_atevdefs (atevdef INTEGER);
521 FOR i IN array_lower(orgs,1) .. array_upper(orgs,1) LOOP
522 INSERT INTO action_trigger.event_definition (
543 ,name || ' (clone of '||target_event_def||')'
559 action_trigger.event_definition
561 id = target_event_def
563 RAISE INFO 'created atevdef with id = %', currval('action_trigger.event_definition_id_seq');
564 INSERT INTO new_atevdefs SELECT currval('action_trigger.event_definition_id_seq');
565 INSERT INTO action_trigger.environment (
571 currval('action_trigger.event_definition_id_seq')
576 action_trigger.environment
578 event_def = target_event_def
580 INSERT INTO action_trigger.event_params (
585 currval('action_trigger.event_definition_id_seq')
589 action_trigger.event_params
591 event_def = target_event_def
594 RAISE INFO '-- UPDATE action_trigger.event_definition SET active = CASE WHEN id = % THEN FALSE ELSE TRUE END WHERE id in (%,%);', target_event_def, target_event_def, (SELECT array_to_string(array_agg(atevdef),',') from new_atevdefs);
596 $$ LANGUAGE PLPGSQL STRICT VOLATILE;
598 -- example: SELECT * FROM migration_tools.duplicate_template_but_change_delay(5,'{3,4}','00:30:00'::INTERVAL);
599 CREATE OR REPLACE FUNCTION migration_tools.duplicate_template_but_change_delay (INTEGER, INTEGER[], INTERVAL) RETURNS VOID AS $$
601 target_event_def ALIAS FOR $1;
603 new_interval ALIAS FOR $3;
605 DROP TABLE IF EXISTS new_atevdefs;
606 CREATE TEMP TABLE new_atevdefs (atevdef INTEGER);
607 FOR i IN array_lower(orgs,1) .. array_upper(orgs,1) LOOP
608 INSERT INTO action_trigger.event_definition (
629 ,name || ' (clone of '||target_event_def||')'
645 action_trigger.event_definition
647 id = target_event_def
649 RAISE INFO 'created atevdef with id = %', currval('action_trigger.event_definition_id_seq');
650 INSERT INTO new_atevdefs SELECT currval('action_trigger.event_definition_id_seq');
651 INSERT INTO action_trigger.environment (
657 currval('action_trigger.event_definition_id_seq')
662 action_trigger.environment
664 event_def = target_event_def
666 INSERT INTO action_trigger.event_params (
671 currval('action_trigger.event_definition_id_seq')
675 action_trigger.event_params
677 event_def = target_event_def
680 RAISE INFO '-- UPDATE action_trigger.event_definition SET active = CASE WHEN id = % THEN FALSE ELSE TRUE END WHERE id in (%,%);', target_event_def, target_event_def, (SELECT array_to_string(array_agg(atevdef),',') from new_atevdefs);
682 $$ LANGUAGE PLPGSQL STRICT VOLATILE;
684 -- example: SELECT * FROM migration_tools.duplicate_templates(3,'{5,6}');
685 CREATE OR REPLACE FUNCTION migration_tools.duplicate_templates (INTEGER, INTEGER[]) RETURNS VOID AS $$
688 target_event_defs ALIAS FOR $2;
690 DROP TABLE IF EXISTS new_atevdefs;
691 CREATE TEMP TABLE new_atevdefs (atevdef INTEGER);
692 FOR i IN array_lower(target_event_defs,1) .. array_upper(target_event_defs,1) LOOP
693 INSERT INTO action_trigger.event_definition (
714 ,name || ' (clone of '||target_event_defs[i]||')'
730 action_trigger.event_definition
732 id = target_event_defs[i]
734 RAISE INFO 'created atevdef with id = %', currval('action_trigger.event_definition_id_seq');
735 INSERT INTO new_atevdefs SELECT currval('action_trigger.event_definition_id_seq');
736 INSERT INTO action_trigger.environment (
742 currval('action_trigger.event_definition_id_seq')
747 action_trigger.environment
749 event_def = target_event_defs[i]
751 INSERT INTO action_trigger.event_params (
756 currval('action_trigger.event_definition_id_seq')
760 action_trigger.event_params
762 event_def = target_event_defs[i]
765 RAISE INFO '-- UPDATE action_trigger.event_definition SET active = TRUE WHERE id in (%);', (SELECT array_to_string(array_agg(atevdef),',') from new_atevdefs);
767 $$ LANGUAGE PLPGSQL STRICT VOLATILE;
769 CREATE OR REPLACE FUNCTION migration_tools.reset_event (BIGINT) RETURNS VOID AS $$
775 ,complete_time = NULL
776 ,update_process = NULL
778 ,template_output = NULL
785 CREATE OR REPLACE FUNCTION migration_tools.find_hold_matrix_matchpoint (INTEGER) RETURNS INTEGER AS $$
786 SELECT action.find_hold_matrix_matchpoint(
787 (SELECT pickup_lib FROM action.hold_request WHERE id = $1),
788 (SELECT request_lib FROM action.hold_request WHERE id = $1),
789 (SELECT current_copy FROM action.hold_request WHERE id = $1),
790 (SELECT usr FROM action.hold_request WHERE id = $1),
791 (SELECT requestor FROM action.hold_request WHERE id = $1)
795 CREATE OR REPLACE FUNCTION migration_tools.find_hold_matrix_matchpoint2 (INTEGER) RETURNS SETOF action.matrix_test_result AS $$
796 SELECT action.hold_request_permit_test(
797 (SELECT pickup_lib FROM action.hold_request WHERE id = $1),
798 (SELECT request_lib FROM action.hold_request WHERE id = $1),
799 (SELECT current_copy FROM action.hold_request WHERE id = $1),
800 (SELECT usr FROM action.hold_request WHERE id = $1),
801 (SELECT requestor FROM action.hold_request WHERE id = $1)
805 CREATE OR REPLACE FUNCTION migration_tools.find_circ_matrix_matchpoint (INTEGER) RETURNS SETOF action.found_circ_matrix_matchpoint AS $$
806 SELECT action.find_circ_matrix_matchpoint(
807 (SELECT circ_lib FROM action.circulation WHERE id = $1),
808 (SELECT target_copy FROM action.circulation WHERE id = $1),
809 (SELECT usr FROM action.circulation WHERE id = $1),
811 NULLIF(phone_renewal,false),
812 NULLIF(desk_renewal,false),
813 NULLIF(opac_renewal,false),
815 ) FROM action.circulation WHERE id = $1