oddb2xml 3.0.20 → 3.0.21

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.
data/spec/spec_helper.rb CHANGED
@@ -257,6 +257,8 @@ def mock_downloads
257
257
  "http://pillbox.oddb.org/TRANSFER.ZIP" => "transfer.zip",
258
258
  "https://raw.githubusercontent.com/zdavatz/cpp2sqlite/master/input/atc_codes_multi_lingual.txt" => "atc.csv",
259
259
  "https://raw.githubusercontent.com/zdavatz/oddb2xml_files/master/LPPV.txt" => "oddb2xml_files_lppv.txt",
260
+ "https://raw.githubusercontent.com/zdavatz/oddb2xml_files/master/weleda_arzneimittel.csv" => "weleda_arzneimittel.csv",
261
+ "https://raw.githubusercontent.com/zdavatz/oddb2xml_files/master/bag_sl_group_prices.csv" => "bag_sl_group_prices.csv",
260
262
  "http://www.xn--spezialittenliste-yqb.ch/File.axd?file=XMLPublications.zip" => "XMLPublications.zip",
261
263
  "https://www.spezialitaetenliste.ch/File.axd?file=XMLPublications.zip" => "XMLPublications.zip",
262
264
  "https://files.refdata.ch/simis-public-prod/Articles/1.0/Refdata.Articles.zip" => "Refdata.Articles.zip",
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require "oddb2xml/weleda_sl"
5
+
6
+ RSpec.describe Oddb2xml::WeledaSL do
7
+ let(:prices_csv) {
8
+ <<~CSV
9
+ pharma_group_code,price_chf_incl_vat,description,limitation
10
+ 2069591,26.95,Urtinktur 41−60 g/ml,
11
+ 2070631,2.50,D/C 1−9 Ampulle,
12
+ 2070275,28.45,D/C 10−29,
13
+ CSV
14
+ }
15
+
16
+ let(:weleda_csv) {
17
+ <<~CSV
18
+ id,name,darreichung,status,verweis,artikelnummer,pharmacode,ean,abgabekategorie,zulassungsnummer,csl
19
+ 1,"Absinthium, ethanol. Infusum D1",Tropfen 50 ml,Lieferbar,,124755,1019849,7611916162404,FM / SL,,2069591
20
+ 2,Acidum Formicae D6,Ampullen 8x1ml,Lieferbar,,1,2,7611916151071,B / SL,1,8x2070631
21
+ 3,Anaemodoron,Tropfen 50 ml,Lieferbar,,5055,7767096,7680215220016,D / -,21522,
22
+ 4,No Price Product,Tropfen,Lieferbar,,9,9,7611916999999,B / SL,9,
23
+ 5,Spaced Multiplier,Ampullen,Lieferbar,,9,9,7611916152665,B / SL,9,2 x 2070275
24
+ CSV
25
+ }
26
+
27
+ describe ".parse_prices" do
28
+ it "maps group code to price" do
29
+ prices = described_class.parse_prices(prices_csv)
30
+ expect(prices["2069591"]).to eq "26.95"
31
+ expect(prices.size).to eq 3
32
+ end
33
+
34
+ it "returns {} for blank input" do
35
+ expect(described_class.parse_prices("")).to eq({})
36
+ expect(described_class.parse_prices(nil)).to eq({})
37
+ end
38
+ end
39
+
40
+ describe ".resolve_price" do
41
+ let(:prices) { described_class.parse_prices(prices_csv) }
42
+
43
+ it "resolves a plain code" do
44
+ expect(described_class.resolve_price("2069591", prices)).to eq "26.95"
45
+ end
46
+
47
+ it "applies the Nx package multiplier" do
48
+ expect(described_class.resolve_price("8x2070631", prices)).to eq "20.00"
49
+ end
50
+
51
+ it "tolerates spaces around the multiplier" do
52
+ expect(described_class.resolve_price("2 x 2070275", prices)).to eq "56.90"
53
+ end
54
+
55
+ it "returns nil for an unknown or empty code" do
56
+ expect(described_class.resolve_price("9999999", prices)).to be_nil
57
+ expect(described_class.resolve_price("", prices)).to be_nil
58
+ expect(described_class.resolve_price(nil, prices)).to be_nil
59
+ end
60
+ end
61
+
62
+ describe ".build_map" do
63
+ let(:prices) { described_class.parse_prices(prices_csv) }
64
+ subject(:map) { described_class.build_map(weleda_csv, prices) }
65
+
66
+ it "includes only SL rows, keyed by 13-digit GTIN" do
67
+ expect(map.keys).to contain_exactly(
68
+ "7611916162404", "7611916151071", "7611916999999", "7611916152665"
69
+ )
70
+ expect(map).not_to have_key("7680215220016") # D / - is not SL
71
+ end
72
+
73
+ it "joins the public price via csl, including the multiplier" do
74
+ expect(map["7611916162404"][:price]).to eq "26.95"
75
+ expect(map["7611916151071"][:price]).to eq "20.00"
76
+ expect(map["7611916152665"][:price]).to eq "56.90"
77
+ end
78
+
79
+ it "keeps SL rows whose price cannot be resolved (price nil)" do
80
+ expect(map["7611916999999"][:sl]).to be true
81
+ expect(map["7611916999999"][:price]).to be_nil
82
+ end
83
+ end
84
+
85
+ describe ".load with bundled fallback" do
86
+ it "loads the bundled data files when the download yields nothing" do
87
+ flexmock(Oddb2xml::WeledaDownloader).new_instances.should_receive(:download).and_return(nil)
88
+ flexmock(Oddb2xml::BagSlGroupPricesDownloader).new_instances.should_receive(:download).and_return(nil)
89
+ map = described_class.load({})
90
+ expect(map.size).to be > 400
91
+ expect(map["7611916162404"]).to include(sl: true, price: "26.95")
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Regenerate data/bag_sl_group_prices.csv (and the copy in
5
+ # github.com/zdavatz/oddb2xml_files) from the BAG SL definition PDF
6
+ # "Homoeopathica, Anthroposophica, Allergene".
7
+ #
8
+ # This maps each Pharma-Gruppen-Code (the `csl` column of
9
+ # weleda_arzneimittel.csv) to its public price (CHF incl. MWST). oddb2xml joins
10
+ # GTIN -> csl -> price to recover the SL flag and public price of Kapitel-70
11
+ # complementary medicines that are missing from the FHIR feed (issue #121).
12
+ #
13
+ # Requirements: poppler's `pdftotext` (dev-time only -- NOT a gem/runtime
14
+ # dependency, so the gem keeps its Ruby >= 2.5 floor; pdf-reader was rejected
15
+ # because its `afm` dependency now requires Ruby >= 3.2).
16
+ #
17
+ # Usage:
18
+ # ruby tools/generate_bag_sl_group_prices.rb [path/to/HAA.pdf] [out.csv]
19
+ # With no PDF path it downloads the current PDF from epl.bag.admin.ch.
20
+
21
+ require "csv"
22
+ require "open-uri"
23
+ require "tempfile"
24
+
25
+ PDF_URL = "https://epl.bag.admin.ch/static/sl/definitions/" \
26
+ "Homoeopathica,%20Anthroposophica,%20Allergene.pdf"
27
+
28
+ pdf_path = ARGV[0]
29
+ out_path = ARGV[1] || File.expand_path("../data/bag_sl_group_prices.csv", __dir__)
30
+
31
+ unless pdf_path
32
+ tmp = Tempfile.new(["haa", ".pdf"])
33
+ tmp.binmode
34
+ tmp.write(URI.parse(PDF_URL).open.read) # standard:disable Security/Open
35
+ tmp.close
36
+ pdf_path = tmp.path
37
+ end
38
+
39
+ txt = `pdftotext -layout #{pdf_path.inspect} -`
40
+ raise "pdftotext failed (is poppler installed?)" unless $?.success?
41
+
42
+ seen = {}
43
+ rows = []
44
+ txt.each_line do |line|
45
+ rest = line.rstrip
46
+ next unless rest =~ /^\s*(\d{7})\s+(.*)$/
47
+ code = $1
48
+ body = $2
49
+ nums = body.scan(/\d+\.\d{2}/)
50
+ next if nums.empty?
51
+ price = nums.last # price is the last NN.NN on the row
52
+ next if seen[code]
53
+ seen[code] = true
54
+ tail = body.split(price, 2)[1].to_s
55
+ limitation = tail.gsub(/[^L0-9, ]/, "").strip # optional Lx limitation markers
56
+ desc = body.sub(/\s+#{Regexp.escape(price)}.*$/, "").gsub(/\s{2,}/, " ").strip
57
+ rows << [code, price, desc, limitation]
58
+ end
59
+
60
+ CSV.open(out_path, "w") do |csv|
61
+ csv << %w[pharma_group_code price_chf_incl_vat description limitation]
62
+ rows.each { |r| csv << r }
63
+ end
64
+
65
+ puts "Wrote #{rows.size} price rows to #{out_path}"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oddb2xml
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.20
4
+ version: 3.0.21
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yasuhiro Asaka, Zeno R.R. Davatz, Niklaus Giger
@@ -462,10 +462,12 @@ files:
462
462
  - bin/compare_v5
463
463
  - bin/oddb2xml
464
464
  - data/article_overrides.yaml
465
+ - data/bag_sl_group_prices.csv
465
466
  - data/gal_forms.yaml
466
467
  - data/gal_groups.yaml
467
468
  - data/gtin2ignore.yaml
468
469
  - data/product_overrides.yaml
470
+ - data/weleda_arzneimittel.csv
469
471
  - dokumentation_calc.textile
470
472
  - flake.lock
471
473
  - flake.nix
@@ -488,6 +490,7 @@ files:
488
490
  - lib/oddb2xml/semantic_check.rb
489
491
  - lib/oddb2xml/util.rb
490
492
  - lib/oddb2xml/version.rb
493
+ - lib/oddb2xml/weleda_sl.rb
491
494
  - lib/oddb2xml/xml_definitions.rb
492
495
  - oddb2xml.gemspec
493
496
  - oddb2xml.xsd
@@ -514,6 +517,7 @@ files:
514
517
  - spec/data/artikelstamm_P_010917.xml
515
518
  - spec/data/artikelstamm_P_011217.xml
516
519
  - spec/data/atc.csv
520
+ - spec/data/bag_sl_group_prices.csv
517
521
  - spec/data/check_artikelstamm/artikelstamm_v5_gtin_non_numeric.xml
518
522
  - spec/data/check_artikelstamm/artikelstamm_v5_gtin_not_uniq.xml
519
523
  - spec/data/check_artikelstamm/artikelstamm_v5_limitation_exists.xml
@@ -552,6 +556,7 @@ files:
552
556
  - spec/data/varia_De_spa.htm
553
557
  - spec/data/vcr/transfer.dat
554
558
  - spec/data/vcr/transfer.zip
559
+ - spec/data/weleda_arzneimittel.csv
555
560
  - spec/data/wsdl_nonpharma.xml
556
561
  - spec/data/wsdl_pharma.xml
557
562
  - spec/data_helper.rb
@@ -565,8 +570,10 @@ files:
565
570
  - spec/parslet_spec.rb
566
571
  - spec/refdata_cleanup_spec.rb
567
572
  - spec/spec_helper.rb
573
+ - spec/weleda_sl_spec.rb
568
574
  - test_options.rb
569
575
  - tools/cacert.pem
576
+ - tools/generate_bag_sl_group_prices.rb
570
577
  - tools/set.bat
571
578
  - tools/win_fetch_cacerts.rb
572
579
  homepage: https://github.com/zdavatz/oddb2xml
@@ -613,6 +620,7 @@ test_files:
613
620
  - spec/data/artikelstamm_P_010917.xml
614
621
  - spec/data/artikelstamm_P_011217.xml
615
622
  - spec/data/atc.csv
623
+ - spec/data/bag_sl_group_prices.csv
616
624
  - spec/data/check_artikelstamm/artikelstamm_v5_gtin_non_numeric.xml
617
625
  - spec/data/check_artikelstamm/artikelstamm_v5_gtin_not_uniq.xml
618
626
  - spec/data/check_artikelstamm/artikelstamm_v5_limitation_exists.xml
@@ -651,6 +659,7 @@ test_files:
651
659
  - spec/data/varia_De_spa.htm
652
660
  - spec/data/vcr/transfer.dat
653
661
  - spec/data/vcr/transfer.zip
662
+ - spec/data/weleda_arzneimittel.csv
654
663
  - spec/data/wsdl_nonpharma.xml
655
664
  - spec/data/wsdl_pharma.xml
656
665
  - spec/data_helper.rb
@@ -664,3 +673,4 @@ test_files:
664
673
  - spec/parslet_spec.rb
665
674
  - spec/refdata_cleanup_spec.rb
666
675
  - spec/spec_helper.rb
676
+ - spec/weleda_sl_spec.rb