hln_ice 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5cc821a0690dfaa750fb0dd36f1409a8a20054486318166f708bd8a266ff5c7a
4
- data.tar.gz: 424486397d7ae838ee6af769155deef6a8b5bff76309291470a295c10eb58389
3
+ metadata.gz: ad2a04435e36bc2e843e01c674c067f8d552f7b528e95e5540b19cbb11a06ff4
4
+ data.tar.gz: c5a5769cbf8c2d41e7074812a1ff83e0caf489a9a31d3bf4f2486a2160674118
5
5
  SHA512:
6
- metadata.gz: 172c72400334ad1e9ca73b37fd7c77c7227386336e44e5d751c69d1bf40e021664ac0ceeeb835361924d6ddaff6cc0898420e07f5088fe72925821fdfa35bf11
7
- data.tar.gz: 1ee834f1abd93c7cb9dc19453a7afd111a39f5745ad12d3d6345bae406805c9fb837fa3aacb80ecc03e9fe81c1cfe6d36d36b6790be2ed657aa0596e147f624d
6
+ metadata.gz: 0ea75c7a3a922fb8fb76388f3d5d3ae568f324afe744861cc79b74c2eb0d83fbcdbed60ff2839391dd0823ba36cb197101494c147cd690036013ad46ea9ffc54
7
+ data.tar.gz: e66a9cd04e3b62d2e47731311dbc1ddc1f57f5a52259f81cc5d3a334fd8f82826ac53ba6e75c3f76630b92b8d54761ae5236127162b2893ec177c7c1469c9f00
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.3.0] - 2026-09-24
4
+
5
+ - Expose schedule authorities (e.g. `ACIP_CDC`, `AAP`, `AAFP`) on each recommendation under `schedule_authorities` when the ICE server has `outputScheduleAuthorities` enabled. The key is omitted when the server does not return them.
6
+ - Fix recommendations being silently dropped when a proposal's schedule authorities observation precedes its status observation.
7
+
8
+ ## [0.2.0] - 2026-07-02
9
+
10
+ - Stop logging PHI by default. The ICE input data, generated request XML, and raw service response are no longer logged unless the new `log_payloads:` option is set to `true`. Warnings and errors are still logged.
11
+ - The service response is now logged at `debug` (was `info`), matching the input data and generated XML, so all payload logging behaves uniformly and stays out of `info`-level logs.
12
+
3
13
  ## [0.1.0] - 2026-06-22
4
14
 
5
15
  - Initial release
data/README.md CHANGED
@@ -49,6 +49,7 @@ All options:
49
49
  | `max_retries:`| `3` | Number of retries on a failed evaluation request. |
50
50
  | `retry_delay:`| `1` | Seconds to wait between retries. |
51
51
  | `logger:` | `Logger.new($stdout)` | Any `Logger`-compatible object. In Rails, pass `Rails.logger`. |
52
+ | `log_payloads:`| `false` | When `true`, logs the ICE input data, generated request XML, and raw service response. These contain patient PHI, so keep this off outside local debugging. |
52
53
 
53
54
  ```ruby
54
55
  # In a Rails app, reuse the application logger:
@@ -107,7 +108,12 @@ On success:
107
108
  vaccine: { code: "10", code_system: "...", name: "Polio Vaccine Group" },
108
109
  status: { code: "RECOMMENDED", name: "Recommended" },
109
110
  reasons: [{ code: "DUE_NOW", name: "Due Now" }],
110
- intervals: { proposed: { low: "2020-03-01", high: "2020-04-01" } }
111
+ intervals: { proposed: { low: "2020-03-01", high: "2020-04-01" } },
112
+ # Only present when the ICE server has outputScheduleAuthorities enabled
113
+ schedule_authorities: [
114
+ { code: "ACIP_CDC", name: "Advisory Committee on Immunization Practices / Centers for Disease Control and Prevention" },
115
+ { code: "AAP", name: "American Academy of Pediatrics" }
116
+ ]
111
117
  }
112
118
  ],
113
119
  simplified_status: { ipv_opv: "overdue" }
@@ -37,14 +37,18 @@ module HlnIce
37
37
  "Varicella Vaccine Group" => :var,
38
38
  }.freeze
39
39
 
40
- attr_reader :base_url, :timeout, :max_retries, :retry_delay, :logger
40
+ attr_reader :base_url, :timeout, :max_retries, :retry_delay, :logger, :log_payloads
41
41
 
42
- def initialize(base_url:, timeout: 30, max_retries: 3, retry_delay: 1, logger: nil)
42
+ # log_payloads: when false (default), the ICE input data, generated request
43
+ # XML, and raw service response are NOT logged. These contain patient PHI, so
44
+ # logging stays off unless a caller explicitly opts in (e.g. local debugging).
45
+ def initialize(base_url:, timeout: 30, max_retries: 3, retry_delay: 1, logger: nil, log_payloads: false)
43
46
  @base_url = base_url
44
47
  @timeout = timeout
45
48
  @max_retries = max_retries
46
49
  @retry_delay = retry_delay
47
50
  @logger = logger || Logger.new($stdout)
51
+ @log_payloads = log_payloads
48
52
  end
49
53
 
50
54
  # Check if the ICE service is available
@@ -127,7 +131,7 @@ module HlnIce
127
131
  gender = "U" if blank?(gender) # Set default to 'U' if blank
128
132
 
129
133
  # Log input data for debugging
130
- logger.debug("ICE Input Data: #{JSON.pretty_generate(patient_data)}")
134
+ logger.debug("ICE Input Data: #{JSON.pretty_generate(patient_data)}") if log_payloads
131
135
 
132
136
  # Build the VMR XML
133
137
  xml_payload = <<~XML
@@ -196,7 +200,7 @@ module HlnIce
196
200
  XML
197
201
 
198
202
  # Log the generated XML for debugging
199
- logger.debug("Generated ICE XML: #{xml_payload}")
203
+ logger.debug("Generated ICE XML: #{xml_payload}") if log_payloads
200
204
 
201
205
  # Base64 encode the XML
202
206
  base64_encoded_payload = Base64.strict_encode64(xml_payload)
@@ -245,7 +249,7 @@ module HlnIce
245
249
  end
246
250
 
247
251
  def parse_ice_response(response_body)
248
- logger.info("ICE service response: #{response_body}")
252
+ logger.debug("ICE service response: #{response_body}") if log_payloads
249
253
 
250
254
  result = JSON.parse(response_body)
251
255
 
@@ -302,13 +306,14 @@ module HlnIce
302
306
  vaccine_name = substance_element["displayName"]
303
307
  vaccine_code_system = substance_element["codeSystem"]
304
308
 
305
- # Get the clinical observation result
306
- observation = proposal.xpath(".//observationResult").first
309
+ # Get the clinical observation result carrying the recommendation status.
310
+ # A proposal may contain other observation results (e.g. schedule
311
+ # authorities), in any order, so select the one with a status concept.
312
+ observation = proposal.xpath(".//observationResult[observationValue/concept]").first
307
313
  next unless observation
308
314
 
309
315
  # Get recommendation status
310
316
  status_element = observation.xpath(".//observationValue/concept").first
311
- next unless status_element
312
317
 
313
318
  status_code = status_element["code"]
314
319
  status_name = status_element["displayName"]
@@ -365,6 +370,11 @@ module HlnIce
365
370
  # Only add intervals if they exist
366
371
  recommendation[:intervals] = intervals if present?(intervals)
367
372
 
373
+ # Only add schedule authorities if the service returned them
374
+ # (requires the ICE outputScheduleAuthorities property)
375
+ schedule_authorities = parse_schedule_authorities(proposal)
376
+ recommendation[:schedule_authorities] = schedule_authorities if present?(schedule_authorities)
377
+
368
378
  all_recommendations << recommendation
369
379
  end
370
380
 
@@ -409,6 +419,21 @@ module HlnIce
409
419
  }
410
420
  end
411
421
 
422
+ # Extract the schedule authorities (e.g. ACIP_CDC, AAP) for a proposal.
423
+ # Returns an empty array when the service did not include them.
424
+ def parse_schedule_authorities(proposal)
425
+ authorities = proposal.xpath(
426
+ ".//observationResult[observationFocus/@code='ICE_VACCINE_GROUP_SCHEDULE_AUTHORITIES']/interpretation"
427
+ )
428
+
429
+ authorities.map do |interpretation|
430
+ {
431
+ code: interpretation["code"],
432
+ name: interpretation["displayName"]
433
+ }
434
+ end
435
+ end
436
+
412
437
  def handle_error_response(response)
413
438
  error_message = "ICE service error: #{response.code}"
414
439
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HlnIce
4
- VERSION = "0.1.0"
4
+ VERSION = "0.3.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hln_ice
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Sohn
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2026-06-22 00:00:00.000000000 Z
10
+ date: 2026-09-24 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: base64
@@ -78,7 +77,6 @@ metadata:
78
77
  homepage_uri: https://github.com/PrimaryDotHealth/hln_ice
79
78
  source_code_uri: https://github.com/PrimaryDotHealth/hln_ice
80
79
  changelog_uri: https://github.com/PrimaryDotHealth/hln_ice/blob/main/CHANGELOG.md
81
- post_install_message:
82
80
  rdoc_options: []
83
81
  require_paths:
84
82
  - lib
@@ -93,8 +91,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
93
91
  - !ruby/object:Gem::Version
94
92
  version: '0'
95
93
  requirements: []
96
- rubygems_version: 3.5.3
97
- signing_key:
94
+ rubygems_version: 3.6.5
98
95
  specification_version: 4
99
96
  summary: Ruby client for the HLN ICE (Immunization Calculation Engine) OpenCDS service.
100
97
  test_files: []