oddb2xml 3.0.9 → 3.0.10
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 +4 -4
- data/CLAUDE.md +1 -1
- data/Gemfile.lock +1 -1
- data/History.txt +3 -0
- data/README.md +13 -8
- data/lib/oddb2xml/fhir_support.rb +29 -1
- data/lib/oddb2xml/version.rb +1 -1
- data/spec/fhir_spec.rb +36 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 371c2ba25fb99bf0255bc0d336b0ae8a8a0cee64e9cd869e249e7fe7cd1d9da0
|
|
4
|
+
data.tar.gz: b85bd319a9179098af8c97bd6c1d8671a1e1cf656c0e83fdc7a0ede20ccf60fc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bab282fd20949a78607099dba3d64288cc63809b9e25f3e95015cd7f826a274a4010f9654117710976391561524c8f57b2c0727ed8b9ef7e8511f5fe9cd31c72
|
|
7
|
+
data.tar.gz: b4eef9e9aa441a567ac050c0ff27170ef8f9d64f8f9993b7c014ee9b7e79241ba6d5f917b956649cb194fcb59e8b06694db4d8e4500f113adb3f1212236d8430
|
data/CLAUDE.md
CHANGED
|
@@ -47,7 +47,7 @@ The system follows a **download → extract → build → compress** pipeline:
|
|
|
47
47
|
|
|
48
48
|
6. **Compressor** (`lib/oddb2xml/compressor.rb`) — Optional ZIP/TAR.GZ output compression.
|
|
49
49
|
|
|
50
|
-
7. **FHIR support** (`lib/oddb2xml/fhir_support.rb`) — Self-contained module providing `FhirDownloader` and FHIR NDJSON parsing. Activated via `--fhir` (or `--fhir-url=<URL>`). Downloads per-language NDJSON files (`foph-sl-export-latest-{de,fr,it}.ndjson`) from `epl.bag.admin.ch` to populate French and Italian product names/descriptions. Maps legal status codes `756005022007` and `756005022008` to Swissmedic category D.
|
|
50
|
+
7. **FHIR support** (`lib/oddb2xml/fhir_support.rb`) — Self-contained module providing `FhirDownloader` and FHIR NDJSON parsing. Activated via `--fhir` (or `--fhir-url=<URL>`). Downloads per-language NDJSON files (`foph-sl-export-latest-{de,fr,it}.ndjson`) from `epl.bag.admin.ch` to populate French and Italian product names/descriptions. Maps legal status codes `756005022007` and `756005022008` to Swissmedic category D. Reads the BAG **Indikationscode** (`XXXXX.NN`) from the explicit `indicationCode` extension on each `RegulatedAuthorization.indication[].extension[regulatedAuthorization-limitation]` (BAG SL FHIR export >= v2.0.5; handled from 3.0.10). The BAG changelog states the limitation code (`ClinicalUseDefinition.id`) and the indication code are **independent** fields, so the older derivation — combining each indication CUD's `.NN` id-suffix with the reimbursement RA's `FOPHDossierNumber` — is kept only as a fallback for feeds lacking the extension. Exposed as `item[:indication_codes]` and per-package `:indication_codes` (each entry a `{code:, cud_id:, text:}` hash, where `cud_id` is the `limitationIndication` CUD reference used to resolve the text). From 3.0.7 onwards, `Builder#build_product` emits one `<INDICATION_CODE code="XXXXX.NN" cud_id="DRUG.NN">limitation text</INDICATION_CODE>` child per indication on every `<PRD>` in `oddb_product.xml`; live feed numbers: 539 products / 1,293 codes / 100 % with non-empty indication text. Mandatory on prescriptions/invoices for SL price-model drugs from 2026-07-01 — see issue [#113](https://github.com/zdavatz/oddb2xml/issues/113). **Limitation texts** (3.0.8 onwards): the `regulatedAuthorization-limitation` extension has no inline `limitationText` in the live BAG feed — it carries a `limitationIndication` reference to a `ClinicalUseDefinition` whose `indication.diseaseSymptomProcedure.concept.text` is the actual text. The parser stores the ref as `cud_ref` on each Limitation, `Bundle#cud_text_by_id` resolves DE, and `merge_language` propagates FR/IT from the per-language NDJSON files via the same CUD id. Coverage on the live feed jumped from 0 / 9'108 to 9'108 / 9'108 (issue [#116](https://github.com/zdavatz/oddb2xml/issues/116)).
|
|
51
51
|
|
|
52
52
|
8. **Refdata cleanup** (`lib/oddb2xml/refdata_cleanup.rb`) — Compensates for known data-quality issues in upstream Refdata.Articles.xml before they reach the output. Each fix is guarded by a Swissmedic-side heuristic (e.g. comma in `substance_swissmedic` to distinguish mono products from real combinations). Currently fixes the doubled-dose template bug (`X mg / X mg / Stk`). Called from `Builder#apply_refdata_description_cleanups!` at the start of `prepare_articles`. See GitHub issue #112 for the catalogue.
|
|
53
53
|
|
data/Gemfile.lock
CHANGED
data/History.txt
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
=== 3.0.10 / 01.06.2026
|
|
2
|
+
* FHIR: read the BAG Indikationscode (XXXXX.NN) from the explicit `indicationCode` extension now carried on each limitation (BAG SL FHIR export >= v2.0.5) instead of reconstructing it from FOPHDossierNumber + the ClinicalUseDefinition id suffix. The changelog states the limitation code (CUD id) and the indication code are independent fields, so the old derivation was no longer guaranteed correct. Falls back to the previous derivation for older feeds that lack the extension. Output is identical on the current live feed. Other changelog items (limitation text moved to ClinicalUseDefinition, sanitized CUD ids, un-truncated `<` in texts, deduplicated/ordered Ingredients) were already handled or are transparent upstream fixes.
|
|
3
|
+
|
|
1
4
|
=== 3.0.9 / 01.06.2026
|
|
2
5
|
* FHIR is now the default source for -e/--extended and -b/--firstbase. As of June 2026, running oddb2xml -e or oddb2xml -b downloads the FOPH/BAG FHIR NDJSON feed instead of the BAG-XML Spezialitätenliste. Plain runs are unchanged. Opt out with --no-fhir; explicit --fhir/--fhir-url still work.
|
|
3
6
|
|
data/README.md
CHANGED
|
@@ -51,7 +51,7 @@ HIN (http://hin.ch) creates daily the actual file. They can be downloaded from `
|
|
|
51
51
|
see `--help`.
|
|
52
52
|
|
|
53
53
|
```
|
|
54
|
-
/opt/src/oddb2xml/bin/oddb2xml version 3.0.
|
|
54
|
+
/opt/src/oddb2xml/bin/oddb2xml version 3.0.10
|
|
55
55
|
Usage:
|
|
56
56
|
oddb2xml [option]
|
|
57
57
|
produced files are found under data
|
|
@@ -311,13 +311,18 @@ indication on each `<PRD>` in `oddb_product.xml`:
|
|
|
311
311
|
</PRD>
|
|
312
312
|
```
|
|
313
313
|
|
|
314
|
-
|
|
315
|
-
`
|
|
316
|
-
(`
|
|
317
|
-
|
|
318
|
-
`
|
|
319
|
-
|
|
320
|
-
`
|
|
314
|
+
Since 3.0.10 the code is read directly from the explicit
|
|
315
|
+
`indicationCode` extension carried on each limitation
|
|
316
|
+
(`RegulatedAuthorization.indication[].extension[regulatedAuthorization-limitation]`),
|
|
317
|
+
introduced in the BAG SL FHIR export ≥ v2.0.5 (e.g. `20403.01` /
|
|
318
|
+
`20403.02`). The BAG changelog states that the limitation code
|
|
319
|
+
(`ClinicalUseDefinition.id`) and the indication code are **independent**
|
|
320
|
+
fields, so the previous reconstruction from `FOPHDossierNumber` + the
|
|
321
|
+
`.NN` CUD-id suffix is no longer used (it is kept only as a fallback for
|
|
322
|
+
older feeds without the extension). `cud_id` still carries the
|
|
323
|
+
`limitationIndication` reference, and the element body carries the
|
|
324
|
+
human-readable indication text from the referenced
|
|
325
|
+
`ClinicalUseDefinition`'s `indication.diseaseSymptomProcedure.concept.text`.
|
|
321
326
|
|
|
322
327
|
The same data is also exposed in-memory on each item and package as
|
|
323
328
|
`item[:indication_codes]` (an array of `{code:, cud_id:, text:}`
|
|
@@ -395,6 +395,11 @@ module Oddb2xml
|
|
|
395
395
|
when "limitationText"
|
|
396
396
|
# Not present in the live FHIR feed — kept for forward-compat.
|
|
397
397
|
limitation[:text] = sub_ext["valueString"]
|
|
398
|
+
when "indicationCode"
|
|
399
|
+
# Authoritative BAG Indikationscode XXXXX.NN (feed >= v2.0.5).
|
|
400
|
+
# Independent of the CUD id, so it must be read here rather than
|
|
401
|
+
# reconstructed from FOPHDossierNumber + CUD suffix.
|
|
402
|
+
limitation[:indication_code] = sub_ext["valueString"]
|
|
398
403
|
when "limitationIndication"
|
|
399
404
|
ref = sub_ext.dig("valueReference", "reference")
|
|
400
405
|
limitation[:cud_ref] = ref&.sub(%r{\A.*ClinicalUseDefinition/}, "")
|
|
@@ -591,7 +596,30 @@ module Oddb2xml
|
|
|
591
596
|
|
|
592
597
|
def build_indication_codes(bundle)
|
|
593
598
|
reimbursement = bundle.authorizations.find(&:reimbursement_sl?)
|
|
594
|
-
|
|
599
|
+
return [] unless reimbursement
|
|
600
|
+
|
|
601
|
+
cud_texts = bundle.cud_text_by_id
|
|
602
|
+
|
|
603
|
+
# Preferred (BAG feed >= v2.0.5): read the explicit `indicationCode`
|
|
604
|
+
# carried on each limitation. The changelog warns that the limitation
|
|
605
|
+
# code (CUD id) and the indication code are independent, so we must NOT
|
|
606
|
+
# reconstruct XXXXX.NN from the CUD id suffix. Text is resolved via the
|
|
607
|
+
# limitationIndication reference (cud_ref) into the CUD's text.
|
|
608
|
+
from_ext = reimbursement.limitations.each_with_object([]) do |lim, acc|
|
|
609
|
+
code = lim[:indication_code]
|
|
610
|
+
next unless code && !code.empty?
|
|
611
|
+
cud_ref = lim[:cud_ref]
|
|
612
|
+
acc << OpenStruct.new(
|
|
613
|
+
code: code,
|
|
614
|
+
cud_id: cud_ref,
|
|
615
|
+
text: (cud_ref && cud_texts[cud_ref]) || lim[:text]
|
|
616
|
+
)
|
|
617
|
+
end
|
|
618
|
+
return from_ext unless from_ext.empty?
|
|
619
|
+
|
|
620
|
+
# Fallback for older feeds without the indicationCode extension:
|
|
621
|
+
# derive XXXXX.NN from FOPHDossierNumber + each indication CUD's suffix.
|
|
622
|
+
dossier = reimbursement.foph_dossier_no
|
|
595
623
|
return [] unless dossier && !bundle.clinical_use_definitions.empty?
|
|
596
624
|
|
|
597
625
|
bundle.clinical_use_definitions.each_with_object([]) do |cud, acc|
|
data/lib/oddb2xml/version.rb
CHANGED
data/spec/fhir_spec.rb
CHANGED
|
@@ -32,11 +32,46 @@ describe "FHIR Indikationscode support" do
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
describe Oddb2xml::FHIR::PreparationsParser do
|
|
35
|
-
it "
|
|
35
|
+
it "reads the explicit indicationCode (XXXXX.NN) from each limitation" do
|
|
36
36
|
parser = described_class.new(cyramza_fixture)
|
|
37
37
|
prep = parser.preparations.first
|
|
38
38
|
codes = prep.IndicationCodes.map(&:code)
|
|
39
39
|
expect(codes).to include("20403.01", "20403.02")
|
|
40
|
+
# cud_id still carries the CUD reference so the text can be resolved.
|
|
41
|
+
expect(prep.IndicationCodes.map(&:cud_id)).to include("CYRAMZA.01", "CYRAMZA.02")
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "uses the explicit indicationCode field, not a dossier+CUD-suffix derivation" do
|
|
45
|
+
# The BAG changelog (>= v2.0.5) states the limitation code (CUD id) and
|
|
46
|
+
# the indication code are independent. Rewrite the explicit indicationCode
|
|
47
|
+
# values so they no longer correspond to FOPHDossierNumber + CUD suffix,
|
|
48
|
+
# and confirm the parser surfaces the explicit values verbatim.
|
|
49
|
+
bundle = JSON.parse(File.read(cyramza_fixture))
|
|
50
|
+
bundle["entry"].each do |entry|
|
|
51
|
+
res = entry["resource"]
|
|
52
|
+
next unless res["resourceType"] == "RegulatedAuthorization"
|
|
53
|
+
Array(res["indication"]).each do |ind|
|
|
54
|
+
Array(ind["extension"]).each do |ext|
|
|
55
|
+
next unless ext["url"].to_s.include?("regulatedAuthorization-limitation")
|
|
56
|
+
Array(ext["extension"]).each do |sub|
|
|
57
|
+
sub["valueString"] = "99999.77" if sub["url"] == "indicationCode"
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
file = Tempfile.new(["cyramza-indc", ".ndjson"])
|
|
64
|
+
begin
|
|
65
|
+
file.write(JSON.generate(bundle))
|
|
66
|
+
file.flush
|
|
67
|
+
parser = described_class.new(file.path)
|
|
68
|
+
codes = parser.preparations.first.IndicationCodes.map(&:code)
|
|
69
|
+
expect(codes).to all(eq("99999.77"))
|
|
70
|
+
expect(codes).not_to include("20403.01", "20403.02")
|
|
71
|
+
ensure
|
|
72
|
+
file.close
|
|
73
|
+
file.unlink
|
|
74
|
+
end
|
|
40
75
|
end
|
|
41
76
|
end
|
|
42
77
|
|