|
1 | 1 | # frozen_string_literal: true |
2 | 2 |
|
3 | 3 | module NHS::ImmunisationsAPI |
4 | | - class PatientNotFound < StandardError |
5 | | - end |
6 | | - |
7 | 4 | class << self |
8 | 5 | def record_immunisation(vaccination_record) |
9 | | - NHS::API.connection.post( |
10 | | - "/immunisation-fhir-api/FHIR/R4/Immunization", |
11 | | - vaccination_record.fhir_record.to_json, |
12 | | - "Content-Type" => "application/fhir+json" |
13 | | - ) |
14 | | - rescue Faraday::Error => e |
15 | | - info = extract_error_info(e.response[:body]) |
16 | | - Rails.logger.error( |
17 | | - "Error recording vaccination record (#{vaccination_record.id}):" \ |
18 | | - " [#{info[:code]}] #{info[:diagnostics]}" |
19 | | - ) |
20 | | - raise e |
| 6 | + unless Flipper.enabled?(:immunisations_fhir_api_integration) |
| 7 | + Rails.logger.info( |
| 8 | + "Not syncing vaccination record to immunisations API as the feature" \ |
| 9 | + " flag is disabled: #{vaccination_record.id}" |
| 10 | + ) |
| 11 | + return |
| 12 | + end |
| 13 | + |
| 14 | + response = |
| 15 | + NHS::API.connection.post( |
| 16 | + "/immunisation-fhir-api/FHIR/R4/Immunization", |
| 17 | + vaccination_record.fhir_record.to_json, |
| 18 | + "Content-Type" => "application/fhir+json" |
| 19 | + ) |
| 20 | + |
| 21 | + if response.status == 201 |
| 22 | + vaccination_record.update!( |
| 23 | + nhs_immunisations_api_id: |
| 24 | + extract_nhs_id(response.headers.fetch("location")), |
| 25 | + nhs_immunisations_api_synced_at: Time.current, |
| 26 | + # We would normally retrieve this from the API response, but the NHS |
| 27 | + # Immunisations API does not return this to us, yet. |
| 28 | + nhs_immunisations_api_etag: 1 |
| 29 | + ) |
| 30 | + else |
| 31 | + raise "Error syncing vaccination record #{vaccination_record.id} to" \ |
| 32 | + " Immunisations API: unexpected response status" \ |
| 33 | + " #{response.status}" |
| 34 | + end |
| 35 | + rescue Faraday::ClientError => e |
| 36 | + if (diagnostics = extract_error_diagnostics(e&.response)).present? |
| 37 | + raise "Error syncing vaccination record #{vaccination_record.id} to" \ |
| 38 | + " Immunisations API: #{diagnostics}" |
| 39 | + else |
| 40 | + raise |
| 41 | + end |
21 | 42 | end |
22 | 43 |
|
23 | | - def extract_error_info(response_body) |
24 | | - return { code: nil, diagnostics: "No response body" } unless response_body |
| 44 | + private |
25 | 45 |
|
26 | | - response = JSON.parse(response_body, symbolize_names: true) |
| 46 | + def extract_error_diagnostics(response) |
| 47 | + return nil if response.nil? || response[:body].blank? |
27 | 48 |
|
28 | | - if response.empty? |
29 | | - { code: nil, diagnostics: "No response body" } |
30 | | - elsif response[:issue].blank? |
31 | | - { code: nil, diagnostics: "No issues in response" } |
32 | | - elsif response[:issue].first[:severity] != "error" |
33 | | - { code: nil, diagnostics: "Issue is not an error" } |
34 | | - else |
35 | | - diagnostics = response[:issue].first[:diagnostics] |
36 | | - if diagnostics.match?(/NHS Number: \d{10} is invalid.*/) |
37 | | - diagnostics.replace("NHS Number is invalid or it doesn't exist") |
38 | | - end |
| 49 | + begin |
| 50 | + JSON.parse(response[:body], symbolize_names: true).dig( |
| 51 | + :issue, |
| 52 | + 0, |
| 53 | + :diagnostics |
| 54 | + ) |
| 55 | + rescue JSON::ParserError |
| 56 | + nil |
| 57 | + end |
| 58 | + end |
39 | 59 |
|
40 | | - { code: response[:issue].first[:code], diagnostics: diagnostics } |
| 60 | + def extract_nhs_id(location) |
| 61 | + if (match = location.match(%r{Immunization/([a-f0-9-]+)})) |
| 62 | + match[1] |
| 63 | + else |
| 64 | + raise UnrecognisedLocation, location |
41 | 65 | end |
42 | 66 | end |
43 | 67 | end |
|
0 commit comments