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.
- checksums.yaml +4 -4
- data/CLAUDE.md +2 -0
- data/Gemfile.lock +1 -1
- data/History.txt +4 -0
- data/data/bag_sl_group_prices.csv +143 -0
- data/data/weleda_arzneimittel.csv +835 -0
- data/lib/oddb2xml/builder.rb +44 -3
- data/lib/oddb2xml/cli.rb +10 -0
- data/lib/oddb2xml/downloader.rb +20 -0
- data/lib/oddb2xml/version.rb +1 -1
- data/lib/oddb2xml/weleda_sl.rb +115 -0
- data/spec/artikelstamm_spec.rb +11 -0
- data/spec/builder_spec.rb +12 -0
- data/spec/data/bag_sl_group_prices.csv +143 -0
- data/spec/data/transfer.dat +1 -0
- data/spec/data/weleda_arzneimittel.csv +835 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/weleda_sl_spec.rb +94 -0
- data/tools/generate_bag_sl_group_prices.rb +65 -0
- metadata +11 -1
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.
|
|
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
|