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.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/stylesheets/renalware/modules/_clinical.scss +73 -0
  3. data/app/models/concerns/renalware/clinics/most_recent_measurement_scopes.rb.dead +43 -0
  4. data/app/models/renalware/clinics/clinic_visit.rb +2 -2
  5. data/app/models/renalware/clinics/current_observations.rb +57 -0
  6. data/app/models/renalware/letters/letter.rb +5 -1
  7. data/app/models/renalware/pathology/current_observation_set.rb +6 -0
  8. data/app/models/renalware/pathology/observation.rb +1 -0
  9. data/app/models/renalware/pathology/observation_request.rb +3 -0
  10. data/app/models/renalware/pathology/observations_jsonb_serializer.rb +7 -6
  11. data/app/models/renalware/pathology/{view_current_observation_results.rb → view_current_observation_results.rb.dead} +0 -0
  12. data/app/presenters/renalware/clinical/header_presenter.rb +33 -0
  13. data/app/presenters/renalware/letters/letter_presenter.rb +5 -1
  14. data/app/presenters/renalware/letters/part_class_filter.rb +36 -0
  15. data/app/presenters/renalware/renal/clinical_summary_presenter.rb +0 -1
  16. data/app/presenters/renalware/ukrdc/patient_presenter.rb +8 -2
  17. data/app/values/renalware/bmi.rb +20 -0
  18. data/app/views/renalware/admissions/consults/_table.html.slim +1 -1
  19. data/app/views/renalware/api/ukrdc/patients/_clinic_visit_observation.xml.builder +1 -1
  20. data/app/views/renalware/api/ukrdc/patients/_lab_orders.xml.builder +3 -3
  21. data/app/views/renalware/api/ukrdc/patients/_observations.xml.builder +3 -1
  22. data/app/views/renalware/api/ukrdc/patients/lab_orders/_lab_order.xml.builder +2 -2
  23. data/app/views/renalware/api/ukrdc/patients/lab_orders/_result_item.xml.builder +7 -2
  24. data/app/views/renalware/clinical/_header.html.slim +47 -0
  25. data/app/views/renalware/clinics/clinic_visits/_table.html.slim +0 -1
  26. data/app/views/renalware/clinics/visits/_table.html.slim +4 -1
  27. data/app/views/renalware/events/events/_event.html.slim +1 -1
  28. data/app/views/renalware/events/events/_table.html.slim +3 -0
  29. data/app/views/renalware/layouts/_patient.html.slim +1 -0
  30. data/app/views/renalware/letters/letters/_form.html.slim +1 -1
  31. data/app/views/renalware/letters/letters/_pathology.html.slim +0 -1
  32. data/app/views/renalware/mdm_patients/_table.html.slim +1 -1
  33. data/app/views/renalware/pathology/_navigation.html.slim +1 -1
  34. data/app/views/renalware/patients/patients/_table.html.slim +2 -2
  35. data/config/initializers/core_extensions.rb +1 -0
  36. data/config/initializers/inflections.rb +1 -0
  37. data/config/locales/renalware/clinical/allergies.en.yml +0 -2
  38. data/config/locales/renalware/clinical/{dry_weight.yml → dry_weight.en.yml} +0 -0
  39. data/config/locales/renalware/clinical/header.en.yml +14 -0
  40. data/db/functions/audit_view_as_json_v01.sql +25 -0
  41. data/db/functions/count_estimate_v01.sql +20 -0
  42. data/db/functions/generate_patient_secure_id_v01.sql +21 -0
  43. data/db/functions/generate_secure_id_v01.sql +18 -0
  44. data/db/functions/import_gps_csv_v01.sql +129 -0
  45. data/db/functions/import_practice_memberships_csv_v01.sql +48 -0
  46. data/db/functions/import_practices_csv_v01.sql +109 -0
  47. data/db/functions/preprocess_hl7_message_v01.sql +29 -0
  48. data/db/functions/preprocess_hl7_message_v02.sql +31 -0
  49. data/db/functions/refresh_all_matierialized_views_v01.sql +32 -0
  50. data/db/functions/refresh_current_observation_set_v01.sql +39 -0
  51. data/db/functions/update_current_observation_set_from_trigger_v01.sql +88 -0
  52. data/db/functions/update_current_observation_set_from_trigger_v02.sql +90 -0
  53. data/db/migrate/20161124152732_add_deleted_at_to_patient_bookmarks.rb +1 -1
  54. data/db/migrate/20170608135553_create_functions_to_generate_secure_patient_id.rb +4 -48
  55. data/db/migrate/20170705090219_create_refresh_all_materialized_views_fn.rb +2 -37
  56. data/db/migrate/20170707110155_rename_access_plans_to_access_plan_types.rb +1 -1
  57. data/db/migrate/20170831142819_enable_crosstab_extension.rb +2 -2
  58. data/db/migrate/20170911133224_add_type_to_messaging_messages.rb +1 -1
  59. data/db/migrate/20170915115228_add_schedule_diurnal_period_id_to_hd_profiles.rb +1 -1
  60. data/db/migrate/20171013145849_set_patients_secure_id.rb +1 -1
  61. data/db/migrate/20171101121130_create_function_to_render_audit_view_as_json.rb +2 -29
  62. data/db/migrate/20171127092158_create_function_to_import_practices.rb +4 -118
  63. data/db/migrate/20171127092359_create_fn_to_insert_gps.rb +3 -139
  64. data/db/migrate/20171206140738_create_fn_to_load_practice_memberships_csv.rb +2 -53
  65. data/db/migrate/20171213111513_create_fn_to_refresh_current_obs.rb +2 -43
  66. data/db/migrate/20171214141335_create_trigger_to_update_current_observation_sets.rb +3 -101
  67. data/db/migrate/20180119121243_create_trigger_to_preprocess_hl7_msg.rb +2 -41
  68. data/db/migrate/20180121115246_add_include_pathology_in_letter_to_letters_letterheads.rb +5 -0
  69. data/db/migrate/20180125201356_make_obs_set_trigger_change_updated_at.rb +2 -184
  70. data/db/migrate/20180130165803_add_deleted_at_indexes.rb +16 -0
  71. data/db/migrate/20180201090444_add_created_at_to_delayed_jobs_in_hl7_trig_fn.rb +9 -0
  72. data/db/migrate/20180207082540_create_count_estimate_function.rb +9 -0
  73. data/db/triggers/feed_messages_preprocessing_trigger_v01.sql +5 -0
  74. data/db/triggers/update_current_observation_set_trigger_v01.sql +7 -0
  75. data/lib/core_extensions/active_record/migration_helpers.rb +43 -0
  76. data/lib/renalware/engine.rb +6 -4
  77. data/lib/renalware/version.rb +1 -1
  78. data/spec/factories/pathology/observation_descriptions.rb +7 -1
  79. data/spec/support/shared_examples/accountable_examples.rb +6 -0
  80. data/spec/support/shared_examples/supersedable_examples.rb +12 -0
  81. metadata +33 -10
  82. data/app/models/renalware/letters/delivery/deliver_letter.rb.dead +0 -41
  83. data/app/models/renalware/pathology/current_key_observation_set.rb.dead +0 -10
  84. data/app/models/renalware/pathology/update_current_observations.rb.dead +0 -25
  85. data/app/presenters/renalware/pathology/current_observation_results.dead/presenter.rb.dead +0 -54
  86. data/app/views/renalware/letters/formatted_letters/show.rtf.slim.ol +0 -1
  87. data/app/views/renalware/patients/_prescriptions.html.slim.dead +0 -23
@@ -6,7 +6,7 @@ xml.Observation do
6
6
 
7
7
  xml.ObservationCode do
8
8
  # xml.CodingStandard "2.16.840.1.113883.4.642.2.115"
9
- xml.CodingStandard "LOCAL"
9
+ xml.CodingStandard "PV"
10
10
  xml.Code I18n.t("loinc.#{i18n_key}.code")
11
11
  xml.Description I18n.t("loinc.#{i18n_key}.description")
12
12
  end
@@ -1,8 +1,8 @@
1
1
  xml = builder
2
2
 
3
- xml.LabOrders(start: Time.zone.today.iso8601, stop: Time.zone.today.iso8601) do
4
- # xml.comment! "TODO: start and stop date"
5
-
3
+ # TODO: Implement start stop dates
4
+ # xml.LabOrders (start: Time.zone.today.iso8601, stop: Time.zone.today.iso8601) do
5
+ xml.LabOrders do
6
6
  render partial: "renalware/api/ukrdc/patients/lab_orders/lab_order",
7
7
  collection: patient.observation_requests.includes(
8
8
  :description,
@@ -4,7 +4,9 @@
4
4
  # - bp
5
5
  xml = builder
6
6
 
7
- xml.Observations(start: Time.zone.today.iso8601, stop: Time.zone.today.iso8601) do
7
+ # TODO: Implement start stop dates
8
+ # xml.Observations do(start: Time.zone.today.iso8601, stop: Time.zone.today.iso8601) do
9
+ xml.Observations do
8
10
  patient.clinic_visits.includes(:updated_by).each do |visit|
9
11
  render "clinic_visit_observation",
10
12
  visit: visit,
@@ -20,7 +20,7 @@ xml.LabOrder do
20
20
  xml.OrderCategory do
21
21
  xml.Code request.description.code
22
22
  end
23
- xml.SpecimenCollectedTime request.requested_at.iso8601
23
+ # xml.SpecimenCollectedTime request.requested_at.iso8601
24
24
  # xml.SpecimenReceivedTime "TODO"
25
25
  # xml.Priority do
26
26
  # xml.Code "TODO: Probably n/a"
@@ -30,7 +30,7 @@ xml.LabOrder do
30
30
 
31
31
  xml.ResultItems do
32
32
  render partial: "renalware/api/ukrdc/patients/lab_orders/result_item",
33
- collection: request.observations,
33
+ collection: request.observations.having_a_loinc_code,
34
34
  as: :observation,
35
35
  locals: { builder: builder, patient: patient }
36
36
  end
@@ -7,8 +7,13 @@ xml.ResultItem do
7
7
  xml.EnteredOn observation.updated_at&.iso8601
8
8
  xml.PrePost observation.pre_post(patient_is_on_hd: patient.current_modality_hd?)
9
9
  xml.ServiceId do
10
- xml.CodingStandard "LOCAL"
11
- xml.Code(observation.description_loinc_code || observation.description_code)
10
+ if observation.description_loinc_code.present?
11
+ xml.CodingStandard "PV"
12
+ xml.Code observation.description_loinc_code
13
+ else
14
+ xml.CodingStandard "LOCAL"
15
+ xml.Code observation.description_code
16
+ end
12
17
  xml.Description observation.description_name
13
18
  end
14
19
  # xml.SubId
@@ -0,0 +1,47 @@
1
+ ruby:
2
+ header = local_assigns[:header] || Renalware::Clinical::HeaderPresenter.new(patient)
3
+ current_pathology = header.current_pathology
4
+
5
+ .clinical-header.lozenge
6
+ ul
7
+ li
8
+ dl
9
+ dt= t(".blood_pressure")
10
+ - result = header.blood_pressure_measurement.compact.join("/")
11
+ - if result.present?
12
+ dd= result
13
+ dd.date= l(header.blood_pressure_date)
14
+ - else
15
+ dd.empty
16
+ li
17
+ dl
18
+ dt= t(".weight")
19
+ - result = header.weight_measurement
20
+ - if result.present?
21
+ dd= "#{result} kg"
22
+ dd.date= l(header.weight_date)
23
+ - else
24
+ dd.empty
25
+ li
26
+ dl
27
+ dt= t(".height")
28
+ - result = header.height_measurement
29
+ - if result.present?
30
+ dd= "#{result} m"
31
+ - else
32
+ dd.empty
33
+ li
34
+ dl
35
+ dt= t(".bmi")
36
+ dd= header.bmi_measurement
37
+
38
+ - %i(hgb cre pot egfr ure).each do |code|
39
+ li
40
+ dl
41
+ dt= t(".#{code}")
42
+ - result = current_pathology.send(:"#{code}_result")
43
+ - if result.present?
44
+ dd= result
45
+ dd.date= l(current_pathology.send(:"#{code}_observed_at"))
46
+ - else
47
+ dd.empty
@@ -15,7 +15,6 @@ table.clinics.auto-layout
15
15
  th.col-width-tiny Urine blood
16
16
  th.col-width-tiny Urine protein
17
17
  th.col-width-medium Created by
18
-
19
18
  tbody
20
19
  = render partial: "renalware/clinics/clinic_visits/table_row",
21
20
  collection: clinic_visits,
@@ -8,13 +8,16 @@ table.global-clinic-visits
8
8
  th.col-width-nhs-no NHS Number
9
9
  th.col-width-tiny Sex
10
10
  th.col-width-tiny Age
11
- th.col-width-small Modality
11
+ th.col-width-medium Modality
12
12
  th.col-width-medium Clinic Type
13
13
  th.col-width-tiny BMI
14
14
  th.col-width-tiny BP
15
15
  th.no-print
16
16
  th.col-width-medium Created by
17
17
  tbody
18
+ / Note we can't use cached: true yet when rendering the events collection, as each row is
19
+ / used in a different context and displays there slightly differently, for example showing
20
+ / an Edit link or Type column in certain circumstances.
18
21
  = render partial: "table_row",
19
22
  collection: clinic_visits,
20
23
  as: :clinic_visit
@@ -9,7 +9,7 @@ tr
9
9
  = link_to("Edit", edit_proc.call(event))
10
10
 
11
11
  td.nowrap= l event.created_at.to_date
12
- - unless local_assigns.fetch(:exclude_type_column, false)
12
+ - unless local_assigns[:exclude_type_column] == true
13
13
  td= event.event_type
14
14
  td.col-width-medium-with-ellipsis
15
15
  = render partial: "renalware/events/events/cell/#{event.to_partial_path}",
@@ -11,6 +11,9 @@ table.has-togglable-rows.events-table
11
11
  th.created_at.col-width-date-time= t(".date_time")
12
12
  th.created_by.col-width-medium= t(".created_by")
13
13
  tbody
14
+ / Note we can't use cached: true yet when rendering the events collection, as each row is
15
+ / used in a different context and displays there slightly differently, for example showing
16
+ / an Edit link or Type column in certain circumstances.
14
17
  = render partial: "renalware/events/events/event",
15
18
  collection: events,
16
19
  locals: { exclude_type_column: local_assigns[:exclude_type_column],
@@ -8,6 +8,7 @@
8
8
  .patient-content.full-screenable
9
9
  .layout-wrapper
10
10
  = render "renalware/patients/mini_profile", patient: current_patient
11
+ = render "renalware/clinical/header", patient: current_patient
11
12
  = render "renalware/patients/alerts/list", patient: current_patient
12
13
  .row.collapse
13
14
  - if local_assigns[:title].present?
@@ -29,7 +29,7 @@ ruby:
29
29
  }
30
30
  = hidden_field_tag "description_id"
31
31
  = f.input :clinical, as: :hidden
32
- = f.input :issued_on, as: :date_picker
32
+ = f.input :issued_on, as: :date_picker, wrapper: :horizontal_datepicker
33
33
  = f.association :author,
34
34
  as: :user_picker,
35
35
  collection: Renalware::System::UsersPresenter.new.list_for_dropdown( \
@@ -5,7 +5,6 @@ ruby:
5
5
  observation_set_b: letter.patient.current_observation_set&.values,
6
6
  descriptions: Renalware::Letters::RelevantObservationDescription.all
7
7
  )
8
-
9
8
  - if letter.clinical?
10
9
  article.letter-pathology
11
10
  header
@@ -7,7 +7,7 @@ table#patients.mdm-patients.columns
7
7
  th.col-width-reference-no= t(".hosp_no")
8
8
  th.col-width-tiny= t(".sex")
9
9
  th.col-width-tiny= t(".age")
10
- th.col-width-small= t(".modality")
10
+ th.col-width-medium= t(".modality")
11
11
  - %i(hgb ure cre).each do |code|
12
12
  th.col-width-tiny= sort_link(path, code, t(".#{code}"))
13
13
  th.col-width-date= sort_link(path, :"#{code}_date", t(".#{code}_date"))
@@ -1,7 +1,7 @@
1
1
  dl.sub-nav
2
2
  dd= link_to "Historical", patient_pathology_historical_observations_path(@patient)
3
3
  dd= link_to "Current", patient_pathology_current_observations_path(@patient)
4
- dd= link_to "Recent", patient_pathology_recent_observations_path(@patient)
4
+ / dd= link_to "Recent", patient_pathology_recent_observations_path(@patient)
5
5
  dd= link_to "Investigations", patient_pathology_observation_requests_path(@patient)
6
6
  dd= link_to "Required Observations", patient_pathology_required_observations_path(@patient)
7
7
  dd= link_to "New Patient Rule", new_patient_pathology_patient_rule_path(@patient)
@@ -1,7 +1,7 @@
1
1
  table#patients
2
2
  thead
3
3
  tr
4
- th.col-width-medium= attr_name(Renalware::Patient, :name)
4
+ th.col-width-large= attr_name(Renalware::Patient, :name)
5
5
  th.col-width-nhs-no NHS Number
6
6
  - Renalware.config.patient_hospital_identifiers.each_key do |key|
7
7
  th.col-width-reference-without-prefix="#{key} No"
@@ -10,7 +10,7 @@ table#patients
10
10
  th.col-width-tiny= attr_name(Renalware::Patient, :age)
11
11
  th.col-width-tiny= sort_link(search, :send_to_rpv, "RPV")
12
12
  th.col-width-tiny= sort_link(search, :send_to_renalreg, "RReg")
13
- th.col-width-small Modality
13
+ th.col-width-medium Modality
14
14
 
15
15
  tbody
16
16
  = render partial: "patient", collection: patients
@@ -1,6 +1,7 @@
1
1
  require "core_extensions/i18n/handle_blank_value"
2
2
  require "core_extensions/i18n/always_cascade"
3
3
  require "core_extensions/dumb_delegator"
4
+ require "core_extensions/active_record/migration_helpers"
4
5
  require "core_extensions/active_record/sort"
5
6
  require "core_extensions/date"
6
7
  require "core_extensions/active_support/duration"
@@ -15,6 +15,7 @@ ActiveSupport::Inflector.inflections(:en) do |inflect|
15
15
  inflect.acronym "AKI"
16
16
  inflect.acronym "APD"
17
17
  inflect.acronym "API"
18
+ inflect.acronym "BMI"
18
19
  inflect.acronym "CAPD"
19
20
  inflect.acronym "CC"
20
21
  inflect.acronym "CCs"
@@ -10,8 +10,6 @@ en:
10
10
  delete: Delete
11
11
  edit: Edit
12
12
 
13
-
14
-
15
13
  new:
16
14
  title: Add allergy
17
15
  description: Description
@@ -0,0 +1,14 @@
1
+ en:
2
+ renalware:
3
+ clinical:
4
+ header:
5
+ blood_pressure: "BP:"
6
+ weight: "Wt:"
7
+ height: "Ht:"
8
+ bmi: "BMI:"
9
+ hgb: "HGB:"
10
+ cre: "Creat:"
11
+ pot: "Potass:"
12
+ egfr: "eGFR:"
13
+ ure: "Urea:"
14
+ cockroft_gault: "Cockr-Glt"
@@ -0,0 +1,25 @@
1
+ CREATE OR REPLACE FUNCTION audit_view_as_json(view_name text)
2
+ /*
3
+ Converts the specified view into its json representation suitable for feeding for example
4
+ into jQuery datatables plugin, or creating a historical snapshot.
5
+ Example usage:
6
+ select audit_view_as_json('reporting_bone_audit')
7
+ TC 1.11.2017
8
+ */
9
+ RETURNS json
10
+ LANGUAGE 'plpgsql'
11
+ as $$
12
+ DECLARE result json;
13
+ BEGIN
14
+ EXECUTE format('
15
+ select row_to_json(t)
16
+ from (
17
+ select
18
+ current_timestamp as runat,
19
+ (select array_to_json(array_agg(row_to_json(d))
20
+ )
21
+ from (select * from %s) d) as data) t;
22
+ ', quote_ident(view_name)) into result;
23
+ return result;
24
+ END
25
+ $$;
@@ -0,0 +1,20 @@
1
+ /*
2
+ A plpgsql function by Michael Fuhr for faster counting.
3
+ See https://wiki.postgresql.org/wiki/Count_estimate
4
+ Normal count(*) can be slow where that are millions of rows.
5
+ This is a faster way to count filtered rows by parsing the output of an explain query.
6
+ */
7
+ CREATE FUNCTION count_estimate(query text) RETURNS INTEGER AS
8
+ $func$
9
+ DECLARE
10
+ rec record;
11
+ ROWS INTEGER;
12
+ BEGIN
13
+ FOR rec IN EXECUTE 'EXPLAIN ' || query LOOP
14
+ ROWS := SUBSTRING(rec."QUERY PLAN" FROM ' rows=([[:digit:]]+)');
15
+ EXIT WHEN ROWS IS NOT NULL;
16
+ END LOOP;
17
+
18
+ RETURN ROWS;
19
+ END
20
+ $func$ LANGUAGE plpgsql;
@@ -0,0 +1,21 @@
1
+ CREATE OR REPLACE FUNCTION generate_patient_secure_id()
2
+ /*
3
+ Generates and returns a unique base 58 token 24 characters long for use as a secure_id on
4
+ the Renalware patients table. If the generated token is in use already (very unlikely) it
5
+ retries until a unique one is generated.
6
+ Example usage:
7
+ select generate_patient_secure_id #=> 0KPNXf4X5x1o6O4mXWE5MC9H
8
+ TC 8.6.2017
9
+ */
10
+ RETURNS varchar AS $$
11
+ DECLARE
12
+ new_secure_id varchar;
13
+ BEGIN
14
+ LOOP
15
+ new_secure_id := generate_secure_id(24);
16
+ EXIT WHEN NOT EXISTS(select 1 from patients where 'secure_id' = new_secure_id);
17
+ RAISE NOTICE 'The generated secure_id % was already in use - now generating another', new_secure_id;
18
+ END LOOP;
19
+ RETURN new_secure_id;
20
+ END
21
+ $$ LANGUAGE plpgsql;
@@ -0,0 +1,18 @@
1
+ CREATE OR REPLACE FUNCTION generate_secure_id(length integer default 24)
2
+ /*
3
+ Generates and returns a unique base 58 token of <length> length for use in for example
4
+ the obfuscation of database ids in URLs.
5
+ Note base58 tokens are case sensitive.
6
+ Example usage:
7
+ select generate_secure_id(24) #=> 0KPNXf4X5x1o6O4mXWE5MC9H
8
+ TC 8.6.2017
9
+ */
10
+ RETURNS text AS
11
+ $body$
12
+ SELECT string_agg (substr('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',
13
+ ceil (random() * 62)::integer,
14
+ 1), '')
15
+ FROM generate_series(1, length)
16
+ ;
17
+ $body$
18
+ LANGUAGE sql;
@@ -0,0 +1,129 @@
1
+ CREATE OR REPLACE FUNCTION renalware.import_gps_csv(file text) RETURNS void
2
+ AS $$
3
+ BEGIN
4
+ -- Imports a egpcur.csv.csv file created from ODS.
5
+ -- Returns counts of changed (insert/updated) and (soft) deleted rows.
6
+
7
+ DROP TABLE IF EXISTS tmp_gps_copy;
8
+
9
+ -- Create a tmp table to hold the ODS-defined standard 27 field format into which we will insert out CSV data
10
+ CREATE TEMP TABLE tmp_gps_copy (
11
+ code text NOT NULL,
12
+ name text NOT NULL,
13
+ unused3 text,
14
+ unused4 text,
15
+ street_1 text,
16
+ street_2 text,
17
+ street_3 text,
18
+ town text,
19
+ county text,
20
+ postcode text,
21
+ unused11 text,
22
+ unused12 text,
23
+ status text, -- A = Active B = Retired C = Closed P = Proposed
24
+ unused14 text,
25
+ unused15 text,
26
+ unused16 text,
27
+ unused17 text,
28
+ telephone text,
29
+ unused19 text,
30
+ unused20 text,
31
+ unused21 text,
32
+ amended_record_indicator text,
33
+ unused23 text,
34
+ unused24 text,
35
+ unused25 text,
36
+ unused26 text,
37
+ unused27 text,
38
+ CONSTRAINT tmp_gps_pkey PRIMARY KEY (code)
39
+ );
40
+
41
+ -- Import the CSV file into tmp_practices - note there is no CSV header in this file
42
+ EXECUTE format ('COPY tmp_gps_copy FROM %L DELIMITER %L CSV ', file, ',');
43
+
44
+ DROP TABLE IF EXISTS tmp_gps;
45
+ CREATE TEMP TABLE tmp_gps AS SELECT
46
+ code,
47
+ name,
48
+ telephone,
49
+ street_1,
50
+ street_2,
51
+ street_3,
52
+ town,
53
+ county,
54
+ postcode,
55
+ left(status,1) as status from tmp_gps_copy ;
56
+ ALTER TABLE tmp_gps ADD PRIMARY KEY (code);
57
+
58
+ RAISE NOTICE 'Calling cs_create_job(%)', (select status from tmp_gps limit 1);
59
+
60
+ -- Upsert GPs
61
+ WITH
62
+ data AS (select * from tmp_gps),
63
+ gp_changes AS (
64
+ INSERT INTO renalware.patient_primary_care_physicians (code, name, telephone, practitioner_type, created_at, updated_at)
65
+ SELECT code, name, telephone, 'GP', clock_timestamp(), clock_timestamp()
66
+ FROM data
67
+ ON CONFLICT (code) DO UPDATE
68
+ SET
69
+ telephone = excluded.telephone,
70
+ name = excluded.name,
71
+ updated_at = excluded.updated_at
72
+ where (patient_primary_care_physicians.telephone) is distinct from (excluded.telephone)
73
+ RETURNING code, id
74
+ )
75
+
76
+ -- Upsert GP addresses
77
+ INSERT INTO renalware.addresses (
78
+ addressable_type,
79
+ addressable_id,
80
+ street_1,
81
+ street_2,
82
+ street_3,
83
+ town,
84
+ county,
85
+ postcode,
86
+ created_at,
87
+ updated_at)
88
+ SELECT
89
+ 'Renalware::Patients::PrimaryCarePhysician' as addressable_type,
90
+ gps.id as addressable_id,
91
+ street_1,
92
+ street_2,
93
+ street_3,
94
+ town,
95
+ county,
96
+ postcode,
97
+ CURRENT_TIMESTAMP as created_at,
98
+ CURRENT_TIMESTAMP as updated_at
99
+ FROM data join patient_primary_care_physicians gps using(code)
100
+ ON CONFLICT (addressable_type, addressable_id) DO UPDATE
101
+ SET
102
+ street_1 = excluded.street_1,
103
+ street_2 = excluded.street_2,
104
+ street_3 = excluded.street_3,
105
+ town = excluded.town,
106
+ county = excluded.county,
107
+ postcode = excluded.postcode,
108
+ updated_at = clock_timestamp()
109
+ where (addresses.street_1, addresses.street_2, addresses.street_3)
110
+ is distinct from (excluded.street_1, excluded.street_2, excluded.street_3);
111
+
112
+ --GET DIAGNOSTICS changed_count = ROW_COUNT;
113
+
114
+ -- Update the deleted_at column of any gps which do not have an Active status_code
115
+ UPDATE renalware.patient_primary_care_physicians AS p
116
+ SET deleted_at = CURRENT_TIMESTAMP
117
+ FROM tmp_gps AS tp
118
+ WHERE p.code = tp.code AND tp.status IN ('C', 'P', 'B');
119
+
120
+ -- Un-delete any previously deleted GPs
121
+ UPDATE renalware.patient_primary_care_physicians AS gp
122
+ SET deleted_at = NULL
123
+ FROM tmp_gps
124
+ WHERE gp.code = tmp_gps.code AND tmp_gps.status IN ('A') AND gp.code NOT IN ('A');
125
+
126
+ --GET DIAGNOSTICS deleted_count = ROW_COUNT;
127
+ --select changed_count, deleted_count;
128
+ END;
129
+ $$ LANGUAGE plpgsql;