renalware-core 2.0.0.pre.rc8 → 2.0.0.pre.rc9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/stylesheets/renalware/modules/_clinical.scss +73 -0
- data/app/models/concerns/renalware/clinics/most_recent_measurement_scopes.rb.dead +43 -0
- data/app/models/renalware/clinics/clinic_visit.rb +2 -2
- data/app/models/renalware/clinics/current_observations.rb +57 -0
- data/app/models/renalware/letters/letter.rb +5 -1
- data/app/models/renalware/pathology/current_observation_set.rb +6 -0
- data/app/models/renalware/pathology/observation.rb +1 -0
- data/app/models/renalware/pathology/observation_request.rb +3 -0
- data/app/models/renalware/pathology/observations_jsonb_serializer.rb +7 -6
- data/app/models/renalware/pathology/{view_current_observation_results.rb → view_current_observation_results.rb.dead} +0 -0
- data/app/presenters/renalware/clinical/header_presenter.rb +33 -0
- data/app/presenters/renalware/letters/letter_presenter.rb +5 -1
- data/app/presenters/renalware/letters/part_class_filter.rb +36 -0
- data/app/presenters/renalware/renal/clinical_summary_presenter.rb +0 -1
- data/app/presenters/renalware/ukrdc/patient_presenter.rb +8 -2
- data/app/values/renalware/bmi.rb +20 -0
- data/app/views/renalware/admissions/consults/_table.html.slim +1 -1
- data/app/views/renalware/api/ukrdc/patients/_clinic_visit_observation.xml.builder +1 -1
- data/app/views/renalware/api/ukrdc/patients/_lab_orders.xml.builder +3 -3
- data/app/views/renalware/api/ukrdc/patients/_observations.xml.builder +3 -1
- data/app/views/renalware/api/ukrdc/patients/lab_orders/_lab_order.xml.builder +2 -2
- data/app/views/renalware/api/ukrdc/patients/lab_orders/_result_item.xml.builder +7 -2
- data/app/views/renalware/clinical/_header.html.slim +47 -0
- data/app/views/renalware/clinics/clinic_visits/_table.html.slim +0 -1
- data/app/views/renalware/clinics/visits/_table.html.slim +4 -1
- data/app/views/renalware/events/events/_event.html.slim +1 -1
- data/app/views/renalware/events/events/_table.html.slim +3 -0
- data/app/views/renalware/layouts/_patient.html.slim +1 -0
- data/app/views/renalware/letters/letters/_form.html.slim +1 -1
- data/app/views/renalware/letters/letters/_pathology.html.slim +0 -1
- data/app/views/renalware/mdm_patients/_table.html.slim +1 -1
- data/app/views/renalware/pathology/_navigation.html.slim +1 -1
- data/app/views/renalware/patients/patients/_table.html.slim +2 -2
- data/config/initializers/core_extensions.rb +1 -0
- data/config/initializers/inflections.rb +1 -0
- data/config/locales/renalware/clinical/allergies.en.yml +0 -2
- data/config/locales/renalware/clinical/{dry_weight.yml → dry_weight.en.yml} +0 -0
- data/config/locales/renalware/clinical/header.en.yml +14 -0
- data/db/functions/audit_view_as_json_v01.sql +25 -0
- data/db/functions/count_estimate_v01.sql +20 -0
- data/db/functions/generate_patient_secure_id_v01.sql +21 -0
- data/db/functions/generate_secure_id_v01.sql +18 -0
- data/db/functions/import_gps_csv_v01.sql +129 -0
- data/db/functions/import_practice_memberships_csv_v01.sql +48 -0
- data/db/functions/import_practices_csv_v01.sql +109 -0
- data/db/functions/preprocess_hl7_message_v01.sql +29 -0
- data/db/functions/preprocess_hl7_message_v02.sql +31 -0
- data/db/functions/refresh_all_matierialized_views_v01.sql +32 -0
- data/db/functions/refresh_current_observation_set_v01.sql +39 -0
- data/db/functions/update_current_observation_set_from_trigger_v01.sql +88 -0
- data/db/functions/update_current_observation_set_from_trigger_v02.sql +90 -0
- data/db/migrate/20161124152732_add_deleted_at_to_patient_bookmarks.rb +1 -1
- data/db/migrate/20170608135553_create_functions_to_generate_secure_patient_id.rb +4 -48
- data/db/migrate/20170705090219_create_refresh_all_materialized_views_fn.rb +2 -37
- data/db/migrate/20170707110155_rename_access_plans_to_access_plan_types.rb +1 -1
- data/db/migrate/20170831142819_enable_crosstab_extension.rb +2 -2
- data/db/migrate/20170911133224_add_type_to_messaging_messages.rb +1 -1
- data/db/migrate/20170915115228_add_schedule_diurnal_period_id_to_hd_profiles.rb +1 -1
- data/db/migrate/20171013145849_set_patients_secure_id.rb +1 -1
- data/db/migrate/20171101121130_create_function_to_render_audit_view_as_json.rb +2 -29
- data/db/migrate/20171127092158_create_function_to_import_practices.rb +4 -118
- data/db/migrate/20171127092359_create_fn_to_insert_gps.rb +3 -139
- data/db/migrate/20171206140738_create_fn_to_load_practice_memberships_csv.rb +2 -53
- data/db/migrate/20171213111513_create_fn_to_refresh_current_obs.rb +2 -43
- data/db/migrate/20171214141335_create_trigger_to_update_current_observation_sets.rb +3 -101
- data/db/migrate/20180119121243_create_trigger_to_preprocess_hl7_msg.rb +2 -41
- data/db/migrate/20180121115246_add_include_pathology_in_letter_to_letters_letterheads.rb +5 -0
- data/db/migrate/20180125201356_make_obs_set_trigger_change_updated_at.rb +2 -184
- data/db/migrate/20180130165803_add_deleted_at_indexes.rb +16 -0
- data/db/migrate/20180201090444_add_created_at_to_delayed_jobs_in_hl7_trig_fn.rb +9 -0
- data/db/migrate/20180207082540_create_count_estimate_function.rb +9 -0
- data/db/triggers/feed_messages_preprocessing_trigger_v01.sql +5 -0
- data/db/triggers/update_current_observation_set_trigger_v01.sql +7 -0
- data/lib/core_extensions/active_record/migration_helpers.rb +43 -0
- data/lib/renalware/engine.rb +6 -4
- data/lib/renalware/version.rb +1 -1
- data/spec/factories/pathology/observation_descriptions.rb +7 -1
- data/spec/support/shared_examples/accountable_examples.rb +6 -0
- data/spec/support/shared_examples/supersedable_examples.rb +12 -0
- metadata +33 -10
- data/app/models/renalware/letters/delivery/deliver_letter.rb.dead +0 -41
- data/app/models/renalware/pathology/current_key_observation_set.rb.dead +0 -10
- data/app/models/renalware/pathology/update_current_observations.rb.dead +0 -25
- data/app/presenters/renalware/pathology/current_observation_results.dead/presenter.rb.dead +0 -54
- data/app/views/renalware/letters/formatted_letters/show.rtf.slim.ol +0 -1
- data/app/views/renalware/patients/_prescriptions.html.slim.dead +0 -23
@@ -12,7 +12,7 @@ class AddDeletedAtToPatientBookmarks < ActiveRecord::Migration[4.2]
|
|
12
12
|
# deleted_at datetime. Because NULLs don't help in the index for our un-deleted
|
13
13
|
# scenario (deleted_at == NULL) we have to coalesce those NULLs into the same
|
14
14
|
# valid date. This lets us have a unique index when deleted_at is NULL.
|
15
|
-
|
15
|
+
connection.execute(
|
16
16
|
"CREATE UNIQUE INDEX patient_bookmarks_uniqueness
|
17
17
|
ON patient_bookmarks
|
18
18
|
(patient_id, user_id, COALESCE(deleted_at, '1970-01-01'));"
|
@@ -1,55 +1,11 @@
|
|
1
1
|
class CreateFunctionsToGenerateSecurePatientId < ActiveRecord::Migration[5.0]
|
2
|
-
|
3
|
-
sql
|
4
|
-
|
5
|
-
/*
|
6
|
-
Generates and returns a unique base 58 token of <length> length for use in for example
|
7
|
-
the obfuscation of database ids in URLs.
|
8
|
-
Note base58 tokens are case sensitive.
|
9
|
-
Example usage:
|
10
|
-
select generate_secure_id(24) #=> 0KPNXf4X5x1o6O4mXWE5MC9H
|
11
|
-
TC 8.6.2017
|
12
|
-
*/
|
13
|
-
RETURNS text AS
|
14
|
-
$body$
|
15
|
-
SELECT string_agg (substr('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',
|
16
|
-
ceil (random() * 62)::integer,
|
17
|
-
1), '')
|
18
|
-
FROM generate_series(1, length)
|
19
|
-
;
|
20
|
-
$body$
|
21
|
-
LANGUAGE sql;
|
22
|
-
SQL
|
23
|
-
ActiveRecord::Base.connection.execute(sql)
|
24
|
-
|
25
|
-
sql = <<-SQL.squish
|
26
|
-
CREATE OR REPLACE FUNCTION generate_patient_secure_id()
|
27
|
-
/*
|
28
|
-
Generates and returns a unique base 58 token 24 characters long for use as a secure_id on
|
29
|
-
the Renalware patients table. If the generated token is in use already (very unlikely) it
|
30
|
-
retries until a unique one is generated.
|
31
|
-
Example usage:
|
32
|
-
select generate_patient_secure_id #=> 0KPNXf4X5x1o6O4mXWE5MC9H
|
33
|
-
TC 8.6.2017
|
34
|
-
*/
|
35
|
-
RETURNS varchar AS $$
|
36
|
-
DECLARE
|
37
|
-
new_secure_id varchar;
|
38
|
-
BEGIN
|
39
|
-
LOOP
|
40
|
-
new_secure_id := generate_secure_id(24);
|
41
|
-
EXIT WHEN NOT EXISTS(select 1 from patients where 'secure_id' = new_secure_id);
|
42
|
-
RAISE NOTICE 'The generated secure_id % was already in use - now generating another', new_secure_id;
|
43
|
-
END LOOP;
|
44
|
-
RETURN new_secure_id;
|
45
|
-
END
|
46
|
-
$$ LANGUAGE plpgsql;
|
47
|
-
SQL
|
48
|
-
ActiveRecord::Base.connection.execute(sql)
|
2
|
+
def up
|
3
|
+
load_function("generate_secure_id_v01.sql")
|
4
|
+
load_function("generate_patient_secure_id_v01.sql")
|
49
5
|
end
|
50
6
|
|
51
7
|
def down
|
52
|
-
|
8
|
+
connection.execute(
|
53
9
|
"DROP FUNCTION IF EXISTS generate_secure_id(integer); \
|
54
10
|
DROP FUNCTION IF EXISTS generate_patient_secure_id();"
|
55
11
|
)
|
@@ -1,44 +1,9 @@
|
|
1
1
|
class CreateRefreshAllMaterializedViewsFn < ActiveRecord::Migration[5.0]
|
2
2
|
def up
|
3
|
-
|
4
|
-
# optionally concurrently
|
5
|
-
# From https://github.com/frankhommers/RefreshAllMaterializedViews
|
6
|
-
sql = <<-SQL.squish
|
7
|
-
CREATE OR REPLACE FUNCTION
|
8
|
-
refresh_all_matierialized_views(_schema TEXT DEFAULT '*', _concurrently BOOLEAN DEFAULT false)
|
9
|
-
RETURNS INT AS $$
|
10
|
-
DECLARE
|
11
|
-
r RECORD;
|
12
|
-
BEGIN
|
13
|
-
RAISE NOTICE 'Refreshing materialized view(s) in % %',
|
14
|
-
CASE WHEN _schema = '*' THEN 'all schemas'
|
15
|
-
ELSE 'schema "'|| _schema || '"'
|
16
|
-
END,
|
17
|
-
CASE WHEN _concurrently
|
18
|
-
THEN 'concurrently'
|
19
|
-
ELSE '' END;
|
20
|
-
IF pg_is_in_recovery() THEN
|
21
|
-
RETURN 0;
|
22
|
-
ELSE
|
23
|
-
FOR r IN SELECT schemaname,
|
24
|
-
matviewname FROM pg_matviews WHERE schemaname = _schema OR _schema = '*'
|
25
|
-
LOOP
|
26
|
-
RAISE NOTICE 'Refreshing materialized view "%"."%"', r.schemaname, r.matviewname;
|
27
|
-
EXECUTE 'REFRESH MATERIALIZED VIEW ' || CASE WHEN _concurrently THEN 'CONCURRENTLY '
|
28
|
-
ELSE '' END || '"' || r.schemaname || '"."' || r.matviewname || '"';
|
29
|
-
END LOOP;
|
30
|
-
END IF;
|
31
|
-
RETURN 1;
|
32
|
-
END
|
33
|
-
$$ LANGUAGE plpgsql;
|
34
|
-
SQL
|
35
|
-
|
36
|
-
ActiveRecord::Base.connection.execute(sql)
|
3
|
+
load_function("refresh_all_matierialized_views_v01.sql")
|
37
4
|
end
|
38
5
|
|
39
6
|
def down
|
40
|
-
|
41
|
-
"DROP FUNCTION refresh_all_matierialized_views(TEXT,BOOLEAN);"
|
42
|
-
)
|
7
|
+
connection.execute("DROP FUNCTION refresh_all_matierialized_views(TEXT,BOOLEAN);")
|
43
8
|
end
|
44
9
|
end
|
@@ -23,7 +23,7 @@ class RenameAccessPlansToAccessPlanTypes < ActiveRecord::Migration[5.0]
|
|
23
23
|
add_foreign_key :access_plans, :users, column: :updated_by_id
|
24
24
|
|
25
25
|
# There can only ever be one un-terminated plan per user - is the current one
|
26
|
-
|
26
|
+
connection.execute(
|
27
27
|
"CREATE UNIQUE INDEX access_plan_uniqueness ON access_plans
|
28
28
|
(patient_id, COALESCE(terminated_at, '1970-01-01'));"
|
29
29
|
)
|
@@ -1,9 +1,9 @@
|
|
1
1
|
class EnableCrosstabExtension < ActiveRecord::Migration[5.1]
|
2
2
|
def up
|
3
|
-
|
3
|
+
connection.execute("CREATE extension IF NOT EXISTS tablefunc;")
|
4
4
|
end
|
5
5
|
|
6
6
|
def down
|
7
|
-
|
7
|
+
connection.execute("DROP extension IF EXISTS tablefunc;")
|
8
8
|
end
|
9
9
|
end
|
@@ -3,7 +3,7 @@ class AddTypeToMessagingMessages < ActiveRecord::Migration[5.1]
|
|
3
3
|
def up
|
4
4
|
add_column :messaging_messages, :type, :string, null: true
|
5
5
|
add_index :messaging_messages, :type
|
6
|
-
|
6
|
+
connection.execute(
|
7
7
|
"update messaging_messages set type = 'Renalware::Messaging::Internal::Message' where type is null;"
|
8
8
|
)
|
9
9
|
change_column_null(:messaging_messages, :type, false)
|
@@ -2,7 +2,7 @@ class AddScheduleDiurnalPeriodIdToHDProfiles < ActiveRecord::Migration[5.1]
|
|
2
2
|
def change
|
3
3
|
|
4
4
|
#ActiveRecord::Base.clear_all_connections!
|
5
|
-
conn =
|
5
|
+
conn = connection
|
6
6
|
|
7
7
|
# Enable the intarray extension which is required if we want to index the days[] array
|
8
8
|
# - see below
|
@@ -6,7 +6,7 @@ class SetPatientsSecureId < ActiveRecord::Migration[5.1]
|
|
6
6
|
|
7
7
|
reversible do |direction|
|
8
8
|
direction.up do
|
9
|
-
|
9
|
+
connection.execute(
|
10
10
|
"DROP FUNCTION IF EXISTS generate_secure_id(integer); \
|
11
11
|
DROP FUNCTION IF EXISTS generate_patient_secure_id();"
|
12
12
|
)
|
@@ -1,37 +1,10 @@
|
|
1
1
|
class CreateFunctionToRenderAuditViewAsJson < ActiveRecord::Migration[5.1]
|
2
2
|
def up
|
3
|
-
sql
|
4
|
-
CREATE OR REPLACE FUNCTION audit_view_as_json(view_name text)
|
5
|
-
/*
|
6
|
-
Converts the specified view into its json representation suitable for feeding for example
|
7
|
-
into jQuery datatables plugin, or creating a historical snapshot.
|
8
|
-
Example usage:
|
9
|
-
select audit_view_as_json('reporting_bone_audit')
|
10
|
-
TC 1.11.2017
|
11
|
-
*/
|
12
|
-
RETURNS json
|
13
|
-
LANGUAGE 'plpgsql'
|
14
|
-
as $$
|
15
|
-
DECLARE result json;
|
16
|
-
BEGIN
|
17
|
-
EXECUTE format('
|
18
|
-
select row_to_json(t)
|
19
|
-
from (
|
20
|
-
select
|
21
|
-
current_timestamp as runat,
|
22
|
-
(select array_to_json(array_agg(row_to_json(d))
|
23
|
-
)
|
24
|
-
from (select * from %s) d) as data) t;
|
25
|
-
', quote_ident(view_name)) into result;
|
26
|
-
return result;
|
27
|
-
END
|
28
|
-
$$;
|
29
|
-
SQL
|
30
|
-
ActiveRecord::Base.connection.execute(sql)
|
3
|
+
load_function("audit_view_as_json_v01.sql")
|
31
4
|
end
|
32
5
|
|
33
6
|
def down
|
34
|
-
|
7
|
+
connection.execute(
|
35
8
|
"DROP FUNCTION IF EXISTS audit_view_as_json(text);"
|
36
9
|
)
|
37
10
|
end
|
@@ -1,123 +1,9 @@
|
|
1
1
|
class CreateFunctionToImportPractices < ActiveRecord::Migration[5.0]
|
2
|
-
|
3
|
-
def down
|
4
|
-
ActiveRecord::Base.connection.execute(
|
5
|
-
"DROP FUNCTION IF EXISTS import_practices_csv(file text);"
|
6
|
-
)
|
7
|
-
end
|
8
|
-
|
9
2
|
def up
|
10
|
-
sql
|
11
|
-
|
12
|
-
BEGIN
|
13
|
-
/*
|
14
|
-
Imports a practices.csv file created by parsing out an HSCOrgRefData_Full_xxxxx.xml file.
|
15
|
-
*/
|
16
|
-
DROP TABLE IF EXISTS tmp_practices;
|
17
|
-
|
18
|
-
CREATE TEMP TABLE tmp_practices (
|
19
|
-
code text NOT NULL,
|
20
|
-
name text NOT NULL,
|
21
|
-
tel text,
|
22
|
-
street_1 text,
|
23
|
-
street_2 text,
|
24
|
-
street_3 text,
|
25
|
-
town text,
|
26
|
-
county text,
|
27
|
-
postcode text NOT NULL,
|
28
|
-
region text,
|
29
|
-
country_id integer,
|
30
|
-
active text NOT NULL,
|
31
|
-
CONSTRAINT tmp_practices_pkey PRIMARY KEY (code)
|
32
|
-
);
|
33
|
-
|
34
|
-
/* Import the CSV file into tmp_practices, ignoring the first row which is a header */
|
35
|
-
EXECUTE format ('COPY tmp_practices FROM %L DELIMITER %L CSV HEADER', file, ',');
|
36
|
-
|
37
|
-
/* Upsert practices */
|
38
|
-
WITH data(
|
39
|
-
code,
|
40
|
-
name,
|
41
|
-
telephone,
|
42
|
-
street_1,
|
43
|
-
street_2,
|
44
|
-
street_3,
|
45
|
-
town,
|
46
|
-
county,
|
47
|
-
postcode,
|
48
|
-
region,
|
49
|
-
country_id,
|
50
|
-
active)
|
51
|
-
AS (select * from tmp_practices)
|
52
|
-
, practice_changes AS (
|
53
|
-
INSERT INTO patient_practices (code, name, telephone, created_at, updated_at)
|
54
|
-
SELECT code, name, telephone, clock_timestamp(), clock_timestamp()
|
55
|
-
FROM data
|
56
|
-
ON CONFLICT (code) DO UPDATE
|
57
|
-
SET
|
58
|
-
name = excluded.name,
|
59
|
-
telephone = excluded.telephone,
|
60
|
-
updated_at = excluded.updated_at
|
61
|
-
RETURNING code, id
|
62
|
-
)
|
63
|
-
|
64
|
-
/* Upsert practice addresses */
|
65
|
-
INSERT INTO addresses (
|
66
|
-
addressable_type,
|
67
|
-
addressable_id,
|
68
|
-
street_1,
|
69
|
-
street_2,
|
70
|
-
street_3,
|
71
|
-
town,
|
72
|
-
county,
|
73
|
-
postcode,
|
74
|
-
region,
|
75
|
-
country_id,
|
76
|
-
created_at,
|
77
|
-
updated_at)
|
78
|
-
SELECT
|
79
|
-
'Renalware::Patients::Practice',
|
80
|
-
practice_changes.id,
|
81
|
-
street_1,
|
82
|
-
street_2,
|
83
|
-
street_3,
|
84
|
-
town,
|
85
|
-
county,
|
86
|
-
postcode,
|
87
|
-
region,
|
88
|
-
country_id,
|
89
|
-
CURRENT_TIMESTAMP,
|
90
|
-
CURRENT_TIMESTAMP
|
91
|
-
FROM data join practice_changes using(code)
|
92
|
-
ON CONFLICT (addressable_type, addressable_id) DO UPDATE
|
93
|
-
SET
|
94
|
-
street_1 = excluded.street_1,
|
95
|
-
street_2 = excluded.street_2,
|
96
|
-
street_3 = excluded.street_3,
|
97
|
-
town = excluded.town,
|
98
|
-
county = excluded.county,
|
99
|
-
postcode = excluded.postcode,
|
100
|
-
region = excluded.region,
|
101
|
-
country_id = excluded.country_id,
|
102
|
-
updated_at = clock_timestamp();
|
103
|
-
|
104
|
-
/* Update the deleted_at column of any practices which do not have an Active status_code */
|
105
|
-
UPDATE patient_practices AS p
|
106
|
-
SET deleted_at = CURRENT_TIMESTAMP
|
107
|
-
FROM tmp_practices AS tp
|
108
|
-
WHERE p.code = tp.code AND tp.active = 'false';
|
109
|
-
|
110
|
-
/* Set deleted_at tp NULL for active practices */
|
111
|
-
UPDATE patient_practices AS p
|
112
|
-
SET deleted_at = NULL
|
113
|
-
FROM tmp_practices AS tp
|
114
|
-
WHERE p.code = tp.code AND tp.active != 'false';
|
115
|
-
|
116
|
-
DROP TABLE tmp_practices;
|
3
|
+
load_function("import_practices_csv_v01.sql")
|
4
|
+
end
|
117
5
|
|
118
|
-
|
119
|
-
|
120
|
-
SQL
|
121
|
-
ActiveRecord::Base.connection.execute(sql)
|
6
|
+
def down
|
7
|
+
connection.execute("DROP FUNCTION IF EXISTS import_practices_csv(file text);")
|
122
8
|
end
|
123
9
|
end
|
@@ -1,145 +1,9 @@
|
|
1
1
|
class CreateFnToInsertGps < ActiveRecord::Migration[5.0]
|
2
|
-
|
3
2
|
def up
|
4
|
-
sql
|
5
|
-
CREATE OR REPLACE FUNCTION import_gps_csv(file text) RETURNS void
|
6
|
-
|
7
|
-
AS $$
|
8
|
-
BEGIN
|
9
|
-
-- Imports a egpcur.csv.csv file created from ODS.
|
10
|
-
-- Returns counts of changed (insert/updated) and (soft) deleted rows.
|
11
|
-
|
12
|
-
DROP TABLE IF EXISTS tmp_gps_copy;
|
13
|
-
|
14
|
-
-- Create a tmp table to hold the ODS-defined standard 27 field format into which we will insert out CSV data
|
15
|
-
CREATE TEMP TABLE tmp_gps_copy (
|
16
|
-
code text NOT NULL,
|
17
|
-
name text NOT NULL,
|
18
|
-
unused3 text,
|
19
|
-
unused4 text,
|
20
|
-
street_1 text,
|
21
|
-
street_2 text,
|
22
|
-
street_3 text,
|
23
|
-
town text,
|
24
|
-
county text,
|
25
|
-
postcode text,
|
26
|
-
unused11 text,
|
27
|
-
unused12 text,
|
28
|
-
status text, -- A = Active B = Retired C = Closed P = Proposed
|
29
|
-
unused14 text,
|
30
|
-
unused15 text,
|
31
|
-
unused16 text,
|
32
|
-
unused17 text,
|
33
|
-
telephone text,
|
34
|
-
unused19 text,
|
35
|
-
unused20 text,
|
36
|
-
unused21 text,
|
37
|
-
amended_record_indicator text,
|
38
|
-
unused23 text,
|
39
|
-
unused24 text,
|
40
|
-
unused25 text,
|
41
|
-
unused26 text,
|
42
|
-
unused27 text,
|
43
|
-
CONSTRAINT tmp_gps_pkey PRIMARY KEY (code)
|
44
|
-
);
|
45
|
-
|
46
|
-
-- Import the CSV file into tmp_practices - note there is no CSV header in this file
|
47
|
-
EXECUTE format ('COPY tmp_gps_copy FROM %L DELIMITER %L CSV ', file, ',');
|
48
|
-
|
49
|
-
DROP TABLE IF EXISTS tmp_gps;
|
50
|
-
CREATE TEMP TABLE tmp_gps AS SELECT
|
51
|
-
code,
|
52
|
-
name,
|
53
|
-
telephone,
|
54
|
-
street_1,
|
55
|
-
street_2,
|
56
|
-
street_3,
|
57
|
-
town,
|
58
|
-
county,
|
59
|
-
postcode,
|
60
|
-
left(status,1) as status from tmp_gps_copy ;
|
61
|
-
ALTER TABLE tmp_gps ADD PRIMARY KEY (code);
|
62
|
-
|
63
|
-
RAISE NOTICE 'Calling cs_create_job(%)', (select status from tmp_gps limit 1);
|
64
|
-
|
65
|
-
-- Upsert GPs
|
66
|
-
WITH
|
67
|
-
data AS (select * from tmp_gps),
|
68
|
-
gp_changes AS (
|
69
|
-
INSERT INTO renalware.patient_primary_care_physicians (code, name, telephone, practitioner_type, created_at, updated_at)
|
70
|
-
SELECT code, name, telephone, 'GP', clock_timestamp(), clock_timestamp()
|
71
|
-
FROM data
|
72
|
-
ON CONFLICT (code) DO UPDATE
|
73
|
-
SET
|
74
|
-
telephone = excluded.telephone,
|
75
|
-
name = excluded.name,
|
76
|
-
updated_at = excluded.updated_at
|
77
|
-
where (patient_primary_care_physicians.telephone) is distinct from (excluded.telephone)
|
78
|
-
RETURNING code, id
|
79
|
-
)
|
80
|
-
|
81
|
-
-- Upsert GP addresses
|
82
|
-
INSERT INTO renalware.addresses (
|
83
|
-
addressable_type,
|
84
|
-
addressable_id,
|
85
|
-
street_1,
|
86
|
-
street_2,
|
87
|
-
street_3,
|
88
|
-
town,
|
89
|
-
county,
|
90
|
-
postcode,
|
91
|
-
created_at,
|
92
|
-
updated_at)
|
93
|
-
SELECT
|
94
|
-
'Renalware::Patients::PrimaryCarePhysician' as addressable_type,
|
95
|
-
gps.id as addressable_id,
|
96
|
-
street_1,
|
97
|
-
street_2,
|
98
|
-
street_3,
|
99
|
-
town,
|
100
|
-
county,
|
101
|
-
postcode,
|
102
|
-
CURRENT_TIMESTAMP as created_at,
|
103
|
-
CURRENT_TIMESTAMP as updated_at
|
104
|
-
FROM data join patient_primary_care_physicians gps using(code)
|
105
|
-
ON CONFLICT (addressable_type, addressable_id) DO UPDATE
|
106
|
-
SET
|
107
|
-
street_1 = excluded.street_1,
|
108
|
-
street_2 = excluded.street_2,
|
109
|
-
street_3 = excluded.street_3,
|
110
|
-
town = excluded.town,
|
111
|
-
county = excluded.county,
|
112
|
-
postcode = excluded.postcode,
|
113
|
-
updated_at = clock_timestamp()
|
114
|
-
where (addresses.street_1, addresses.street_2, addresses.street_3)
|
115
|
-
is distinct from (excluded.street_1, excluded.street_2, excluded.street_3);
|
116
|
-
|
117
|
-
--GET DIAGNOSTICS changed_count = ROW_COUNT;
|
118
|
-
|
119
|
-
-- Update the deleted_at column of any gps which do not have an Active status_code
|
120
|
-
UPDATE renalware.patient_primary_care_physicians AS p
|
121
|
-
SET deleted_at = CURRENT_TIMESTAMP
|
122
|
-
FROM tmp_gps AS tp
|
123
|
-
WHERE p.code = tp.code AND tp.status IN ('C', 'P', 'B');
|
124
|
-
|
125
|
-
-- Un-delete any previously deleted GPs
|
126
|
-
UPDATE renalware.patient_primary_care_physicians AS gp
|
127
|
-
SET deleted_at = NULL
|
128
|
-
FROM tmp_gps
|
129
|
-
WHERE gp.code = tmp_gps.code AND tmp_gps.status IN ('A') AND gp.code NOT IN ('A');
|
130
|
-
|
131
|
-
--GET DIAGNOSTICS deleted_count = ROW_COUNT;
|
132
|
-
--select changed_count, deleted_count;
|
133
|
-
END;
|
134
|
-
$$ LANGUAGE plpgsql;
|
135
|
-
SQL
|
136
|
-
|
137
|
-
ActiveRecord::Base.connection.execute(sql)
|
3
|
+
load_function("import_gps_csv_v01.sql")
|
138
4
|
end
|
139
5
|
|
140
|
-
|
141
|
-
|
142
|
-
"DROP FUNCTION IF EXISTS import_gps_csv(file text);"
|
143
|
-
)
|
6
|
+
def down
|
7
|
+
connection.execute("DROP FUNCTION IF EXISTS import_gps_csv(file text);")
|
144
8
|
end
|
145
9
|
end
|