renalware-core 2.0.78 → 2.0.79

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/app/assets/javascripts/renalware/application.js.erb +1 -0
  4. data/app/assets/javascripts/renalware/layout.js +3 -0
  5. data/app/assets/stylesheets/renalware/modules/_patients.scss +2 -1
  6. data/app/controllers/renalware/admin/feeds/files_controller.rb +7 -1
  7. data/app/controllers/renalware/patients/practices_controller.rb +1 -1
  8. data/app/controllers/renalware/patients/primary_care_physician_controller.rb +32 -13
  9. data/app/controllers/renalware/virology/dashboards_controller.rb +1 -4
  10. data/app/controllers/renalware/virology/profiles_controller.rb +10 -5
  11. data/app/documents/renalware/hd/session_document.rb +4 -0
  12. data/app/documents/renalware/patient_document.rb +15 -1
  13. data/app/documents/renalware/renal/profile_document.rb +22 -0
  14. data/app/documents/renalware/virology/profile_document.rb +1 -0
  15. data/app/models/renalware/clinics/remembered_clinic_visit_preferences.rb +1 -1
  16. data/app/models/renalware/feeds/files/practice_memberships/import_job.rb +2 -8
  17. data/app/models/renalware/feeds/files/primary_care_physicians/import_csv.rb +2 -2
  18. data/app/models/renalware/hd/session/closed.rb +2 -0
  19. data/app/models/renalware/patients/last_successful_practice_sync_date_query.rb +28 -0
  20. data/app/models/renalware/patients/practice.rb +0 -2
  21. data/app/models/renalware/patients/practice_search_query.rb +4 -2
  22. data/app/models/renalware/patients/sync_gps_via_file_download_job.rb +52 -0
  23. data/app/models/renalware/patients/sync_ods_job.rb +53 -0
  24. data/app/models/renalware/patients/sync_practices_via_api.rb +157 -0
  25. data/app/models/renalware/system/api_log.rb +29 -0
  26. data/app/presenters/renalware/admissions/consult_summary_part.rb +36 -0
  27. data/app/presenters/renalware/ukrdc/patient_presenter.rb +66 -6
  28. data/app/presenters/renalware/virology/dashboard_presenter.rb +32 -0
  29. data/app/validators/renalware/patients/respiratory_rate_validator.rb +17 -0
  30. data/app/views/renalware/admissions/consults/_summary_part.html.slim +17 -0
  31. data/app/views/renalware/admissions/consults/_table.html.slim +58 -19
  32. data/app/views/renalware/api/ukrdc/patients/_diagnoses.xml.builder +43 -3
  33. data/app/views/renalware/api/ukrdc/patients/_medications.xml.builder +23 -3
  34. data/app/views/renalware/api/ukrdc/patients/_social_histories.xml.builder +2 -2
  35. data/app/views/renalware/hd/protocols/_virology.html.slim +2 -0
  36. data/app/views/renalware/hd/sessions/_form.html.slim +4 -0
  37. data/app/views/renalware/pathology/historical_observation_results/index.html.slim +2 -2
  38. data/app/views/renalware/virology/dashboards/_latest_hep_b_antibody_statuses.html.slim +5 -0
  39. data/app/views/renalware/virology/dashboards/show.html.slim +6 -3
  40. data/app/views/renalware/virology/profiles/_summary.html.slim +2 -2
  41. data/app/views/renalware/virology/profiles/edit.html.slim +1 -0
  42. data/config/locales/renalware/hd/session.en.yml +4 -0
  43. data/config/locales/renalware/virology/virology.en.yml +1 -0
  44. data/db/functions/import_practice_memberships_csv_v03.sql +65 -0
  45. data/db/migrate/20190531172829_add_last_change_date_to_patient_practices.rb +26 -0
  46. data/db/migrate/20190602114659_create_system_api_logs.rb +15 -0
  47. data/db/migrate/20190603084428_add_pages_to_system_api_logs.rb +5 -0
  48. data/db/migrate/20190603135247_add_columns_to_patient_primary_care_physicians.rb +8 -0
  49. data/db/migrate/20190603143834_update_import_practice_memberships_csv.rb +13 -0
  50. data/db/migrate/20190603165812_drop_import_practices_csv_function.rb +13 -0
  51. data/db/seeds/default/feeds/import_file_types.rb +0 -8
  52. data/db/seeds/default/renal/prd_descriptions.csv +266 -266
  53. data/lib/document/enum.rb +4 -0
  54. data/lib/renalware/configuration.rb +1 -0
  55. data/lib/renalware/version.rb +1 -1
  56. data/lib/tasks/feeds/files.rake +0 -16
  57. data/lib/tasks/hd.rake +2 -0
  58. data/lib/tasks/ods.rake +10 -0
  59. data/spec/factories/feeds/file.rb +0 -4
  60. data/spec/factories/feeds/file_types.rb +2 -7
  61. data/spec/factories/hd/hd_session_document.rb +2 -0
  62. data/spec/factories/system/api_logs.rb +19 -0
  63. data/spec/support/pathology_spec_helper.rb +12 -8
  64. data/vendor/assets/javascripts/renalware/double_scroll.js +128 -0
  65. metadata +23 -9
  66. data/app/models/renalware/feeds/files/practices/convert_xml_to_csv.rb +0 -153
  67. data/app/models/renalware/feeds/files/practices/country_map.rb +0 -36
  68. data/app/models/renalware/feeds/files/practices/csv_file.rb +0 -25
  69. data/app/models/renalware/feeds/files/practices/csv_organisation.rb +0 -37
  70. data/app/models/renalware/feeds/files/practices/import_csv.rb +0 -32
  71. data/app/models/renalware/feeds/files/practices/import_job.rb +0 -61
  72. data/app/models/renalware/feeds/files/practices/xml_parser.rb +0 -102
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_dependency "renalware/feeds"
4
-
5
- module Renalware
6
- module Feeds
7
- module Files
8
- module Practices
9
- class CountryMap
10
- UK_COUNTRIES = [
11
- "ENGLAND",
12
- "WALES",
13
- "SCOTLAND",
14
- "NORTHERN IRELAND"
15
- ].freeze
16
-
17
- class Country
18
- include Virtus.model
19
- attribute :region
20
- attribute :country
21
- end
22
-
23
- def map(country)
24
- return if country.blank?
25
-
26
- if UK_COUNTRIES.include?(country.upcase.strip)
27
- Country.new(country: "United Kingdom", region: country.strip.titleize)
28
- else
29
- Country.new(country: country)
30
- end
31
- end
32
- end
33
- end
34
- end
35
- end
36
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_dependency "renalware/feeds"
4
-
5
- module Renalware
6
- module Feeds
7
- module Files
8
- module Practices
9
- class CSVFile
10
- include Virtus.model
11
- attribute :dir, Pathname
12
-
13
- def create
14
- path = ::File.join(dir, "practices.csv")
15
- CSV.open(path, "wb", quote_char: '"', force_quotes: false) do |csv|
16
- csv << CSVOrganisation.headers
17
- yield(csv)
18
- end
19
- path
20
- end
21
- end
22
- end
23
- end
24
- end
25
- end
@@ -1,37 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_dependency "renalware/feeds"
4
-
5
- module Renalware
6
- module Feeds
7
- module Files
8
- module Practices
9
- class CSVOrganisation
10
- include Virtus.model
11
- attribute :code, String
12
- attribute :name, String
13
- attribute :telephone, String
14
- attribute :street_1, String
15
- attribute :street_2, String
16
- attribute :street_3, String
17
- attribute :city, String
18
- attribute :county, String
19
- attribute :postcode, String
20
- attribute :region, String # used to capture England, Wales etc
21
- attribute :country_id, Integer # will normally be id for United Kingdom country
22
- attribute :roles
23
- attribute :active
24
- attribute :skip, Boolean
25
-
26
- def self.headers
27
- attribute_set.map(&:name) - [:roles, :skip]
28
- end
29
-
30
- def to_a
31
- self.class.headers.map { |key| public_send(key) }
32
- end
33
- end
34
- end
35
- end
36
- end
37
- end
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_dependency "renalware/feeds"
4
- require "attr_extras"
5
-
6
- module Renalware
7
- module Feeds
8
- module Files
9
- module Practices
10
- class ImportCSV
11
- pattr_initialize :csv_path
12
-
13
- def call
14
- Rails.logger.info("Importing CSV file #{csv_path}...")
15
- import_practices_csv_using_sql_function
16
- Rails.logger.info("... done")
17
- end
18
-
19
- private
20
-
21
- # See migration for SQL function definition
22
- def import_practices_csv_using_sql_function
23
- conn = ActiveRecord::Base.connection
24
- conn.execute(
25
- "SELECT import_practices_csv(#{conn.quote(csv_path.realpath.to_s)})"
26
- )
27
- end
28
- end
29
- end
30
- end
31
- end
32
- end
@@ -1,61 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_dependency "renalware/feeds"
4
-
5
- module Renalware
6
- module Feeds
7
- module Files
8
- module Practices
9
- class ImportJob < ApplicationJob
10
- include StringLogging
11
- include Feeds::Job
12
- FILE_TO_EXTRACT_FROM_ARCHIVE = /HSCOrgRefData_Full_/
13
-
14
- # Initialize with the absolute path to an fullfile.zip file
15
- # e.g. /Users/tim/Downloads/hscorgrefdataxml_data_1.0.1_20170526000001.zip
16
- # downloaded from
17
- # https://isd.digital.nhs.uk/trud3/user/authenticated/group/0/pack/5/subpack/341/releases
18
- #
19
- # Example usage:
20
- # # Download and unzip hscorgrefdataxml_data_1.0.1_000001.zip and grab the fullfile.zip
21
- # Practices::Import.new("/Users/tim/Downloads/fullfile.zip")
22
-
23
- # Arguments:
24
- # file - a Feeds::File object previously persisted.
25
- def perform(file)
26
- logging_to_stringio(strio = StringIO.new) # so we can write the error to the File model
27
- file.update!(status: :processing, attempts: file.attempts + 1)
28
- status = :success
29
- elapsed_ms = Benchmark.ms do
30
- process_archive(file.location)
31
- end
32
- rescue StandardError => e
33
- Rails.logger.error(formatted_exception(e))
34
- status = :failure
35
- raise e
36
- ensure
37
- file.update!(status: status, result: strio.string, time_taken: elapsed_ms)
38
- end
39
-
40
- private
41
-
42
- def process_archive(zipfile)
43
- log "Practice count before update: #{practice_count}"
44
- log "Opening #{zipfile}"
45
- ZipArchive.new(zipfile).unzip do |files|
46
- xml_pathname = find_file_in(files, FILE_TO_EXTRACT_FROM_ARCHIVE)
47
- csv_path = Practices::ConvertXmlToCsv.call(xml_pathname)
48
- FileUtils.copy(csv_path, Rails.root.join("generated_organisations.csv"))
49
- Practices::ImportCSV.new(csv_path).call
50
- end
51
- log "Practice count after update: #{practice_count}"
52
- end
53
-
54
- def practice_count
55
- Renalware::Patients::Practice.count
56
- end
57
- end
58
- end
59
- end
60
- end
61
- end
@@ -1,102 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # rubocop:disable Metrics/PerceivedComplexity
4
- # rubocop:disable Metrics/AbcSize
5
- # -----
6
- # From https://gist.github.com/kmile/827475
7
- # A small DSL for helping parsing documents using Nokogiri::XML::Reader. The
8
- # XML Reader is a good way to move a cursor through a (large) XML document fast,
9
- # but is not as cumbersome as writing a full SAX document handler. Read about
10
- # it here: http://nokogiri.org/Nokogiri/XML/Reader.html
11
- #
12
- # Just pass the reader in this parser and specify the nodes that you are interested
13
- # in in a block. You can just parse every node or only look inside certain nodes.
14
- #
15
- # A small example:
16
- #
17
- # Xml::Parser.new(Nokogiri::XML::Reader(open(file))) do
18
- # inside_element 'User' do
19
- # for_element 'Name' do puts "Username: #{inner_xml}" end
20
- # for_element 'Email' do puts "Email: #{inner_xml}" end
21
- #
22
- # for_element 'Address' do
23
- # puts 'Start of address:'
24
- # inside_element do
25
- # for_element 'Street' do puts "Street: #{inner_xml}" end
26
- # for_element 'Zipcode' do puts "Zipcode: #{inner_xml}" end
27
- # for_element 'City' do puts "City: #{inner_xml}" end
28
- # end
29
- # puts 'End of address'
30
- # end
31
- # end
32
- # end
33
- #
34
- # It does NOT fail on missing tags, and does not guarantee order of execution. It parses
35
- # every tag regardless of nesting. The only way to guarantee scope is by using
36
- # the `inside_element` method. This limits the parsing to the current or the named tag.
37
- # If tags are encountered multiple times, their blocks will be called multiple times.
38
-
39
- require "nokogiri"
40
- require_dependency "renalware/feeds"
41
-
42
- # Note I moved XmlParse into this namespace as I was getting strange
43
- # 'uninitialised constant XmlParser' errors in production when it was in /lib
44
-
45
- module Renalware
46
- module Feeds
47
- module Files
48
- module Practices
49
- class XmlParser
50
- def initialize(node, &block)
51
- @node = node
52
- @node.each do
53
- self.instance_eval(&block)
54
- end
55
- end
56
-
57
- def name
58
- @node.name
59
- end
60
-
61
- def inner_xml
62
- @node.inner_xml.strip
63
- end
64
-
65
- def is_start?
66
- @node.node_type == Nokogiri::XML::Reader::TYPE_ELEMENT
67
- end
68
-
69
- def is_end?
70
- @node.node_type == Nokogiri::XML::Reader::TYPE_END_ELEMENT
71
- end
72
-
73
- def attribute(attribute)
74
- @node.attribute(attribute)
75
- end
76
-
77
- def for_element(name, &block)
78
- return unless self.name == name and is_start?
79
-
80
- self.instance_eval(&block)
81
- end
82
-
83
- def inside_element(name = nil, &block)
84
- return if @node.self_closing?
85
- return unless name.nil? or (self.name == name and is_start?)
86
-
87
- name = @node.name
88
- depth = @node.depth
89
-
90
- @node.each do
91
- return if self.name == name and is_end? and @node.depth == depth
92
-
93
- self.instance_eval(&block)
94
- end
95
- end
96
- end
97
- end
98
- end
99
- end
100
- end
101
- # rubocop:enable Metrics/PerceivedComplexity
102
- # rubocop:enable Metrics/AbcSize