oddb2xml 2.7.8 → 2.8.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 +4 -4
- data/.envrc +1 -0
- data/.github/workflows/codeql.yml +41 -0
- data/.github/workflows/ruby.yml +1 -1
- data/.gitignore +0 -0
- data/.rspec +0 -0
- data/.ruby-version +1 -0
- data/.standard.yml +0 -0
- data/Elexis_Artikelstamm_v003.xsd +0 -0
- data/Elexis_Artikelstamm_v5.xsd +4 -4
- data/Gemfile +2 -0
- data/Gemfile.lock +198 -0
- data/History.txt +4 -0
- data/LICENSE +0 -0
- data/Manifest.txt +0 -0
- data/QA.md +0 -0
- data/README.md +0 -0
- data/Rakefile +0 -0
- data/artikelstamm.md +0 -0
- data/data/article_overrides.yaml +0 -0
- data/data/gal_forms.yaml +0 -0
- data/data/gal_groups.yaml +0 -0
- data/data/gtin2ignore.yaml +0 -0
- data/data/product_overrides.yaml +0 -0
- data/dokumentation_calc.textile +0 -0
- data/flake.lock +80 -0
- data/flake.nix +36 -0
- data/gemset.nix +814 -0
- data/lib/oddb2xml/builder.rb +34 -17
- data/lib/oddb2xml/calc.rb +2 -2
- data/lib/oddb2xml/chapter_70_hack.rb +0 -0
- data/lib/oddb2xml/cli.rb +15 -1
- data/lib/oddb2xml/compare.rb +0 -0
- data/lib/oddb2xml/compositions_syntax.rb +0 -0
- data/lib/oddb2xml/compressor.rb +0 -0
- data/lib/oddb2xml/downloader.rb +22 -0
- data/lib/oddb2xml/extractor.rb +30 -0
- data/lib/oddb2xml/options.rb +4 -0
- data/lib/oddb2xml/parslet_compositions.rb +2 -0
- data/lib/oddb2xml/util.rb +0 -0
- data/lib/oddb2xml/version.rb +1 -1
- data/lib/oddb2xml/xml_definitions.rb +0 -0
- data/lib/oddb2xml.rb +0 -0
- data/oddb2xml.xsd +3 -27
- data/oddb_calc.xsd +0 -0
- data/spec/artikelstamm_spec.rb +8 -2
- data/spec/builder_spec.rb +7 -8
- data/spec/calc_spec.rb +0 -0
- data/spec/check_artikelstamm_spec.rb +0 -0
- data/spec/cli_spec.rb +0 -0
- data/spec/compare_spec.rb +0 -0
- data/spec/composition_syntax_spec.rb +0 -0
- data/spec/compressor_spec.rb +0 -0
- data/spec/data/AipsDownload.zip +0 -0
- data/spec/data/Elexis_Artikelstamm_v5.xsd +0 -0
- data/spec/data/GL_Diff_SB.xml +0 -0
- data/spec/data/ItCodes.xml +0 -0
- data/spec/data/PR121001.txt +0 -0
- data/spec/data/PR121002.txt +0 -0
- data/spec/data/Preparations.xml +0 -0
- data/spec/data/Publications.xls +0 -0
- data/spec/data/artikelstamm_N_010917.xml +0 -0
- data/spec/data/artikelstamm_N_011217.xml +0 -0
- data/spec/data/artikelstamm_P_010917.xml +0 -0
- data/spec/data/artikelstamm_P_011217.xml +0 -0
- data/spec/data/atc.csv +0 -0
- data/spec/data/check_artikelstamm/artikelstamm_v5_gtin_non_numeric.xml +0 -0
- data/spec/data/check_artikelstamm/artikelstamm_v5_gtin_not_uniq.xml +0 -0
- data/spec/data/check_artikelstamm/artikelstamm_v5_limitation_exists.xml +0 -0
- data/spec/data/check_artikelstamm/artikelstamm_v5_okay.xml +0 -0
- data/spec/data/check_artikelstamm/artikelstamm_v5_pharma_has_product.xml +0 -0
- data/spec/data/check_artikelstamm/artikelstamm_v5_prodno_not_uniq.xml +0 -0
- data/spec/data/check_artikelstamm/artikelstamm_v5_product_needs_article.xml +0 -0
- data/spec/data/column_c.txt +0 -0
- data/spec/data/compositions.txt +0 -0
- data/spec/data/compressor/oddb2xml_files_bm_update.txt +0 -0
- data/spec/data/compressor/oddb2xml_files_lppv.txt +0 -0
- data/spec/data/compressor/oddb2xml_files_nonpharma.xls +0 -0
- data/spec/data/epha_interactions.csv +0 -0
- data/spec/data/listen_neu.html +0 -0
- data/spec/data/medregbm_betrieb.txt +0 -0
- data/spec/data/medregbm_person.txt +0 -0
- data/spec/data/oddb2xml_files_bm_update.txt +0 -0
- data/spec/data/oddb2xml_files_lppv.txt +0 -0
- data/spec/data/oddb2xml_files_nonpharma.xls +0 -0
- data/spec/data/problems.txt +0 -0
- data/spec/data/refdata_NonPharma.xml +0 -0
- data/spec/data/refdata_Pharma.xml +0 -0
- data/spec/data/swissmedic_fridges.html +0 -0
- data/spec/data/swissmedic_info.html +0 -0
- data/spec/data/swissmedic_info_2.html +0 -0
- data/spec/data/swissmedic_orphan.xlsx +0 -0
- data/spec/data/swissmedic_orphans.html +0 -0
- data/spec/data/swissmedic_package.xlsx +0 -0
- data/spec/data/swissmedic_packages.html +0 -0
- data/spec/data/transfer.dat +0 -0
- data/spec/data/v5_first.xml +0 -0
- data/spec/data/v5_second.xml +0 -0
- data/spec/data/varia_De.htm +0 -0
- data/spec/data/vcr/transfer.dat +0 -0
- data/spec/data/vcr/transfer.zip +0 -0
- data/spec/data/wsdl_nonpharma.xml +0 -0
- data/spec/data/wsdl_pharma.xml +0 -0
- data/spec/fixtures/vcr_cassettes/artikelstamm.json +0 -0
- data/spec/galenic_spec.rb +0 -0
- data/spec/parslet_spec.rb +1 -1
- data/tools/cacert.pem +0 -0
- data/tools/set.bat +0 -0
- data/tools/win_fetch_cacerts.rb +0 -0
- metadata +13 -7
- data/shell.nix +0 -19
data/lib/oddb2xml/builder.rb
CHANGED
|
@@ -42,7 +42,7 @@ module Oddb2xml
|
|
|
42
42
|
@@gtin2ignore ||= []
|
|
43
43
|
attr_accessor :subject, :refdata, :items, :flags, :lppvs,
|
|
44
44
|
:actions, :migel, :orphan,
|
|
45
|
-
:infos, :packs, :infos_zur_rose,
|
|
45
|
+
:infos, :packs, :infos_zur_rose, :firstbase,
|
|
46
46
|
:ean14, :tag_suffix,
|
|
47
47
|
:companies, :people,
|
|
48
48
|
:xsd
|
|
@@ -57,6 +57,7 @@ module Oddb2xml
|
|
|
57
57
|
@packs = {}
|
|
58
58
|
@migel = {}
|
|
59
59
|
@infos_zur_rose ||= {}
|
|
60
|
+
@firstbase ||= {}
|
|
60
61
|
@actions = []
|
|
61
62
|
@orphan = []
|
|
62
63
|
@ean14 = false
|
|
@@ -170,6 +171,19 @@ module Oddb2xml
|
|
|
170
171
|
end
|
|
171
172
|
end
|
|
172
173
|
end
|
|
174
|
+
@firstbase.each do |ean13, obj|
|
|
175
|
+
entry = {
|
|
176
|
+
ean13: obj[:gtin],
|
|
177
|
+
desc_de: obj[:trade_item_description_de],
|
|
178
|
+
desc_fr: obj[:trade_item_description_fr],
|
|
179
|
+
atc_code: "",
|
|
180
|
+
company_ean: obj[:gln],
|
|
181
|
+
firstbase: true
|
|
182
|
+
}
|
|
183
|
+
if @refdata[obj[:gtin]].nil?
|
|
184
|
+
@articles << entry
|
|
185
|
+
end
|
|
186
|
+
end
|
|
173
187
|
end
|
|
174
188
|
Oddb2xml.log("prepare_articles done. Added #{nr_added} prices. Total #{@articles.size}")
|
|
175
189
|
end
|
|
@@ -378,7 +392,6 @@ module Oddb2xml
|
|
|
378
392
|
xml.LIMNIV lim[:niv]
|
|
379
393
|
xml.DSCRD lim[:desc_de]
|
|
380
394
|
xml.DSCRF lim[:desc_fr]
|
|
381
|
-
xml.DSCRI lim[:desc_it]
|
|
382
395
|
xml.VDAT lim[:vdate]
|
|
383
396
|
nbr_records += 1
|
|
384
397
|
end
|
|
@@ -536,7 +549,7 @@ module Oddb2xml
|
|
|
536
549
|
if lang == :de
|
|
537
550
|
name = refdata && refdata[:desc_de] ? refdata[:desc_de] : obj[:sequence_name]
|
|
538
551
|
elsif lang == :fr
|
|
539
|
-
name =
|
|
552
|
+
name = refdata && refdata[:desc_fr] ? refdata[:desc_fr] : obj[:sequence_name]
|
|
540
553
|
elsif lang == :it
|
|
541
554
|
name = refdata[:desc_it] if refdata && refdata[:desc_it]
|
|
542
555
|
else
|
|
@@ -560,7 +573,7 @@ module Oddb2xml
|
|
|
560
573
|
@missing.each do |obj|
|
|
561
574
|
ean = obj[:ean13]
|
|
562
575
|
next unless check_name(obj, :de)
|
|
563
|
-
|
|
576
|
+
next unless check_name(obj, :fr)
|
|
564
577
|
next if /^Q/i.match?(obj[:atc])
|
|
565
578
|
if obj[:prodno]
|
|
566
579
|
next if emitted.index(obj[:prodno])
|
|
@@ -572,9 +585,6 @@ module Oddb2xml
|
|
|
572
585
|
xml.PRODNO obj[:prodno] if obj[:prodno]
|
|
573
586
|
xml.DSCRD check_name(obj, :de)
|
|
574
587
|
xml.DSCRF check_name(obj, :fr) if check_name(obj, :fr)
|
|
575
|
-
binding.pry if check_name(obj, :de) && check_name(obj, :de).eql?('Varilrix Trockensub c solv')
|
|
576
|
-
|
|
577
|
-
xml.DSCRI check_name(obj, :it) if check_name(obj, :it)
|
|
578
588
|
xml.ATC obj[:atc_code] unless obj[:atc_code].empty?
|
|
579
589
|
xml.IT obj[:ith_swissmedic] if obj[:ith_swissmedic]
|
|
580
590
|
xml.CPT
|
|
@@ -584,6 +594,14 @@ module Oddb2xml
|
|
|
584
594
|
xml.CompositionSwissmedic obj[:composition_swissmedic] if obj[:composition_swissmedic]
|
|
585
595
|
}
|
|
586
596
|
end
|
|
597
|
+
@firstbase.each do |ean13, obj|
|
|
598
|
+
xml.PRD("DT" => "") {
|
|
599
|
+
xml.GTIN obj[:gtin]
|
|
600
|
+
xml.CPT
|
|
601
|
+
xml.DSCRD obj[:trade_item_description_de]
|
|
602
|
+
xml.DSCRF obj[:trade_item_description_fr]
|
|
603
|
+
}
|
|
604
|
+
end
|
|
587
605
|
@products.sort.to_h.each do |ean13, obj|
|
|
588
606
|
next if /^Q/i.match?(obj[:atc])
|
|
589
607
|
seq = obj[:seq]
|
|
@@ -598,7 +616,6 @@ module Oddb2xml
|
|
|
598
616
|
xml.PRODNO ppac[:prodno] if ppac[:prodno] && !ppac[:prodno].empty?
|
|
599
617
|
xml.DSCRD check_name(obj, :de)
|
|
600
618
|
xml.DSCRF check_name(obj, :fr)
|
|
601
|
-
xml.DSCRI check_name(obj, :it)
|
|
602
619
|
# xml.BNAMD
|
|
603
620
|
# xml.BNAMF
|
|
604
621
|
# xml.ADNAMD
|
|
@@ -952,10 +969,10 @@ module Oddb2xml
|
|
|
952
969
|
end
|
|
953
970
|
xml.DSCRD obj[:desc_de] if obj[:desc_de] && !obj[:desc_de].empty?
|
|
954
971
|
xml.DSCRF obj[:desc_fr] if obj[:desc_fr] && !obj[:desc_fr].empty?
|
|
955
|
-
xml.
|
|
972
|
+
xml.DSCRF obj[:desc_de] if !obj[:desc_fr] || obj[:desc_fr].empty?
|
|
956
973
|
xml.SORTD obj[:desc_de].upcase if obj[:desc_de] && !obj[:desc_de].empty?
|
|
957
974
|
xml.SORTF obj[:desc_fr].upcase if obj[:desc_fr] && !obj[:desc_fr].empty?
|
|
958
|
-
xml.
|
|
975
|
+
xml.SORTF obj[:desc_de].upcase if !obj[:desc_fr] || obj[:desc_fr].empty?
|
|
959
976
|
# xml.QTYUD
|
|
960
977
|
# xml.QTYUF
|
|
961
978
|
# xml.IMG
|
|
@@ -966,7 +983,6 @@ module Oddb2xml
|
|
|
966
983
|
if obj[:seq]
|
|
967
984
|
xml.SYN1D obj[:seq][:name_de] unless obj[:seq][:name_de].empty?
|
|
968
985
|
xml.SYN1F obj[:seq][:name_fr] unless obj[:seq][:name_fr].empty?
|
|
969
|
-
xml.SYN1I obj[:seq][:name_it] unless obj[:seq][:name_it].empty?
|
|
970
986
|
end
|
|
971
987
|
if obj[:seq]
|
|
972
988
|
case obj[:seq][:deductible]
|
|
@@ -1520,21 +1536,21 @@ module Oddb2xml
|
|
|
1520
1536
|
xml.GTIN pkg_gtin.to_s.rjust(13, "0")
|
|
1521
1537
|
xml.SALECD("A")
|
|
1522
1538
|
# maxLength for DSCR is 50 for Artikelstamm v3
|
|
1523
|
-
xml.DSCR(name) # for
|
|
1539
|
+
xml.DSCR(name) # for description for zur_rose
|
|
1524
1540
|
name_fr = item[:name_fr] + " " + item[:desc_fr].strip + " " + package[:desc_fr] if package && package[:desc_fr]
|
|
1525
1541
|
name_fr ||= @refdata[pkg_gtin] ? @refdata[pkg_gtin][:desc_fr] : nil
|
|
1526
1542
|
# Zugelassenen Packungen has only german names
|
|
1527
1543
|
name_fr ||= (obj[:name_fr] + ", " + obj[:desc_fr]).strip if obj[:name_fr]
|
|
1528
1544
|
# ZuRorse has only german names
|
|
1529
1545
|
name_fr ||= (item[:name_fr] + ", " + item[:desc_fr]) if item
|
|
1530
|
-
xml.DSCRF(name_fr)
|
|
1546
|
+
xml.DSCRF(name_fr)
|
|
1531
1547
|
name_it = item[:name_it] + " " + item[:desc_it].strip + " " + package[:desc_it] if package && package[:desc_it]
|
|
1532
1548
|
name_it ||= @refdata[pkg_gtin] ? @refdata[pkg_gtin][:desc_it] : nil
|
|
1533
1549
|
# Zugelassenen Packungen has only german names
|
|
1534
1550
|
name_it ||= (obj[:name_it] + ", " + obj[:desc_it]).strip if obj[:name_it]
|
|
1535
1551
|
# ZuRorse has only german names
|
|
1536
1552
|
name_it ||= (item[:name_it] + ", " + item[:desc_it]) if item
|
|
1537
|
-
xml.DSCRI(name_it)
|
|
1553
|
+
xml.DSCRI(name_it)
|
|
1538
1554
|
if obj[:company_name] || obj[:company_ean]
|
|
1539
1555
|
xml.COMP do # Manufacturer
|
|
1540
1556
|
xml.NAME obj[:company_name][0..99] # limit to 100 chars as in XSD
|
|
@@ -1647,7 +1663,7 @@ module Oddb2xml
|
|
|
1647
1663
|
emit_salecd(xml, ean13, obj)
|
|
1648
1664
|
description = obj[:desc_de] || obj[:description] # for description for zur_rose
|
|
1649
1665
|
xml.DSCR(description)
|
|
1650
|
-
xml.DSCRF(obj[:desc_fr])
|
|
1666
|
+
xml.DSCRF(obj[:desc_fr])
|
|
1651
1667
|
xml.DSCRI(obj[:desc_it]) if obj[:desc_it] && !obj[:desc_it].empty?
|
|
1652
1668
|
if obj[:company_ean] && !obj[:company_ean].empty?
|
|
1653
1669
|
xml.COMP do
|
|
@@ -1752,7 +1768,6 @@ module Oddb2xml
|
|
|
1752
1768
|
nr_products += 1
|
|
1753
1769
|
xml.PRODUCT do
|
|
1754
1770
|
xml.PRODNO prodno
|
|
1755
|
-
|
|
1756
1771
|
if sequence
|
|
1757
1772
|
xml.SALECD("A") # these products are always active!
|
|
1758
1773
|
name_de = "#{sequence[:name_de]} #{sequence[:desc_de]}".strip if sequence[:name_de]
|
|
@@ -1761,10 +1776,11 @@ module Oddb2xml
|
|
|
1761
1776
|
else
|
|
1762
1777
|
sequence[:desc_de]
|
|
1763
1778
|
end
|
|
1779
|
+
name_fr ||= (ppac && ppac[:sequence_name])
|
|
1764
1780
|
name_fr = "#{sequence[:name_fr]} #{sequence[:desc_fr]}".strip if sequence[:name_fr]
|
|
1765
1781
|
name_it = "#{sequence[:name_it]} #{sequence[:desc_it]}".strip if sequence[:name_it]
|
|
1766
1782
|
override(xml, prodno, :DSCR, name_de.strip)
|
|
1767
|
-
override(xml, prodno, :DSCRF, name_fr.strip)
|
|
1783
|
+
override(xml, prodno, :DSCRF, name_fr.strip)
|
|
1768
1784
|
override(xml, prodno, :DSCRI, name_it.strip) if name_it && !name_it.empty?
|
|
1769
1785
|
# use overriden ATC if possibel
|
|
1770
1786
|
atc = sequence[:atc] || sequence[:atc_code]
|
|
@@ -1779,6 +1795,7 @@ module Oddb2xml
|
|
|
1779
1795
|
xml.comment "Chapter70 hack prodno #{prodno} #{obj[:description].encode(xml: :text).gsub("--", "-")}"
|
|
1780
1796
|
xml.SALECD("A") # these products are always active!
|
|
1781
1797
|
xml.DSCR obj[:description]
|
|
1798
|
+
xml.DSCRF ""
|
|
1782
1799
|
if @limitations.index(obj[:code])
|
|
1783
1800
|
xml.LIMNAMEBAG obj[:code]
|
|
1784
1801
|
used_limitations << obj[:code]
|
data/lib/oddb2xml/calc.rb
CHANGED
|
@@ -95,8 +95,8 @@ module Oddb2xml
|
|
|
95
95
|
UNKNOWN_GALENIC_FORM = 140
|
|
96
96
|
UNKNOWN_GALENIC_GROUP = 1
|
|
97
97
|
DATA_DIR = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "data"))
|
|
98
|
-
@@galenic_groups = YAML.load_file(File.join(DATA_DIR, "gal_groups.yaml"))
|
|
99
|
-
@@galenic_forms = YAML.load_file(File.join(DATA_DIR, "gal_forms.yaml"))
|
|
98
|
+
@@galenic_groups = YAML.load_file(File.join(DATA_DIR, "gal_groups.yaml"), permitted_classes: [ Oddb2xml::GalenicForm, Oddb2xml::GalenicGroup, Symbol])
|
|
99
|
+
@@galenic_forms = YAML.load_file(File.join(DATA_DIR, "gal_forms.yaml"), permitted_classes: [ Oddb2xml::GalenicForm, Oddb2xml::GalenicGroup, Symbol])
|
|
100
100
|
@@new_galenic_forms = []
|
|
101
101
|
@@names_without_galenic_forms = []
|
|
102
102
|
@@rules_counter = {}
|
|
File without changes
|
data/lib/oddb2xml/cli.rb
CHANGED
|
@@ -26,6 +26,7 @@ module Oddb2xml
|
|
|
26
26
|
@packs = {} # [option] Packungen from Swissmedic for dat
|
|
27
27
|
@infos_zur_rose = {} # [addition] infos_zur_rose and other infos from zurrose transfer.txt
|
|
28
28
|
@migel = {} # [addition] additional Non Pharma products from files repo
|
|
29
|
+
@firstbase = {}
|
|
29
30
|
@actions = [] # [addition] interactions from epha
|
|
30
31
|
@orphan = [] # [addition] Orphaned drugs from Swissmedic xls
|
|
31
32
|
# addresses
|
|
@@ -60,6 +61,9 @@ module Oddb2xml
|
|
|
60
61
|
threads << download(:package) # swissmedic
|
|
61
62
|
threads << download(:lppv) # oddb2xml_files
|
|
62
63
|
threads << download(:bag) # bag.e-mediat
|
|
64
|
+
if @options[:firstbase]
|
|
65
|
+
threads << download(:firstbase) # https://github.com/zdavatz/oddb2xml/issues/63
|
|
66
|
+
end
|
|
63
67
|
types.each do |type|
|
|
64
68
|
threads << download(:refdata, type) # refdata
|
|
65
69
|
end
|
|
@@ -85,6 +89,7 @@ module Oddb2xml
|
|
|
85
89
|
puts "Validatied #{@the_files[:artikelstamm]}"
|
|
86
90
|
else
|
|
87
91
|
puts "Validating failed using #{cmd}"
|
|
92
|
+
require'pry'; binding.pry
|
|
88
93
|
raise "Validating failed using #{cmd}"
|
|
89
94
|
end
|
|
90
95
|
end
|
|
@@ -124,7 +129,7 @@ module Oddb2xml
|
|
|
124
129
|
builder.infos = @infos
|
|
125
130
|
builder.packs = @packs
|
|
126
131
|
# additional sources
|
|
127
|
-
%w[actions orphan migel infos_zur_rose].each do |addition|
|
|
132
|
+
%w[actions orphan migel infos_zur_rose firstbase].each do |addition|
|
|
128
133
|
builder.send("#{addition}=".intern, instance_variable_get("@#{addition}"))
|
|
129
134
|
end
|
|
130
135
|
end
|
|
@@ -312,6 +317,15 @@ module Oddb2xml
|
|
|
312
317
|
@refdata_types[type]
|
|
313
318
|
end
|
|
314
319
|
|
|
320
|
+
when :firstbase
|
|
321
|
+
downloader = FirstbaseDownloader.new(@options)
|
|
322
|
+
bin = downloader.download
|
|
323
|
+
Oddb2xml.log("FirstbaseDownloader bin #{File.size(bin)} bytes")
|
|
324
|
+
@mutex.synchronize do
|
|
325
|
+
@firstbase = FirstbaseExtractor.new(bin).to_hash
|
|
326
|
+
Oddb2xml.log("FirstbaseExtractor added #{@firstbase.size} firstbase items")
|
|
327
|
+
@firstbase
|
|
328
|
+
end
|
|
315
329
|
end
|
|
316
330
|
end
|
|
317
331
|
|
data/lib/oddb2xml/compare.rb
CHANGED
|
File without changes
|
|
File without changes
|
data/lib/oddb2xml/compressor.rb
CHANGED
|
File without changes
|
data/lib/oddb2xml/downloader.rb
CHANGED
|
@@ -381,4 +381,26 @@ module Oddb2xml
|
|
|
381
381
|
read_xml_from_zip(/^AipsDownload_/iu, file)
|
|
382
382
|
end
|
|
383
383
|
end
|
|
384
|
+
|
|
385
|
+
class FirstbaseDownloader < Downloader
|
|
386
|
+
BASE_URL = "https://www.firstbase.ch"
|
|
387
|
+
include DownloadMethod
|
|
388
|
+
def initialize(type = :orphan, options = {})
|
|
389
|
+
@url = BASE_URL + "/sites/default/files/2023-09/firstbase_healthcare_public_data-dump%2C%2020230920.xlsx"
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
def download
|
|
393
|
+
@file2save = File.join(DOWNLOADS, "firstbase.xlsx")
|
|
394
|
+
report_download(@url, @file2save)
|
|
395
|
+
begin
|
|
396
|
+
download_as(@file2save, "w+")
|
|
397
|
+
return File.expand_path(@file2save)
|
|
398
|
+
rescue Timeout::Error, Errno::ETIMEDOUT
|
|
399
|
+
retrievable? ? retry : raise
|
|
400
|
+
ensure
|
|
401
|
+
Oddb2xml.download_finished(@file2save, false)
|
|
402
|
+
end
|
|
403
|
+
File.expand_path(@file2save)
|
|
404
|
+
end
|
|
405
|
+
end
|
|
384
406
|
end
|
data/lib/oddb2xml/extractor.rb
CHANGED
|
@@ -591,4 +591,34 @@ module Oddb2xml
|
|
|
591
591
|
nil
|
|
592
592
|
end
|
|
593
593
|
end
|
|
594
|
+
|
|
595
|
+
class FirstbaseExtractor < Extractor
|
|
596
|
+
def initialize(file)
|
|
597
|
+
@sheet = RubyXL::Parser.parse(file).worksheets[0]
|
|
598
|
+
end
|
|
599
|
+
|
|
600
|
+
def to_hash
|
|
601
|
+
data = {}
|
|
602
|
+
return data unless @sheet
|
|
603
|
+
@sheet.each_with_index do |row, i|
|
|
604
|
+
next if i <= 1
|
|
605
|
+
gtin = row[0].value.to_s.gsub(/^0+/, '')
|
|
606
|
+
data[gtin] = {
|
|
607
|
+
gtin: gtin,
|
|
608
|
+
gln: row[1].value.to_s,
|
|
609
|
+
target_market: row[2] ? row[2].value.to_s: "",
|
|
610
|
+
gpc: row[3] ? row[3].value.to_s: "",
|
|
611
|
+
trade_item_description_de: row[4] ? row[4].value.to_s: "",
|
|
612
|
+
trade_item_description_en: row[5] ? row[5].value.to_s: "",
|
|
613
|
+
trade_item_description_fr: row[6] ? row[6].value.to_s: "",
|
|
614
|
+
trade_item_description_it: row[7] ? row[7].value.to_s: "",
|
|
615
|
+
manufacturer_name: row[8] ? row[8].value.to_s: "",
|
|
616
|
+
start_availability_date: row[9] ? row[9].value.to_s: "",
|
|
617
|
+
gross_weight: row[10] ? row[10].value.to_s: "",
|
|
618
|
+
net_weight: row[11] ? row[11].value.to_s: "",
|
|
619
|
+
}
|
|
620
|
+
end
|
|
621
|
+
data
|
|
622
|
+
end
|
|
623
|
+
end
|
|
594
624
|
end
|
data/lib/oddb2xml/options.rb
CHANGED
|
@@ -43,6 +43,7 @@ module Oddb2xml
|
|
|
43
43
|
opt :log, "log important actions", short: :none
|
|
44
44
|
opt :use_ra11zip, "Use the ra11.zip (a zipped transfer.dat from Galexis)",
|
|
45
45
|
default: File.exist?("ra11.zip") ? "ra11.zip" : nil, type: :string
|
|
46
|
+
opt :firstbase, "Build all NONPHARMA articles on firstbase", short: "b", default: false
|
|
46
47
|
end
|
|
47
48
|
|
|
48
49
|
@opts[:percent] = @opts[:increment]
|
|
@@ -63,6 +64,9 @@ module Oddb2xml
|
|
|
63
64
|
@opts[:extended] = true
|
|
64
65
|
@opts[:price] = :zurrose
|
|
65
66
|
end
|
|
67
|
+
if @opts[:firstbase]
|
|
68
|
+
@opts[:nonpharma] = true
|
|
69
|
+
end
|
|
66
70
|
@opts[:price] = :zurrose if @opts[:price].is_a?(TrueClass)
|
|
67
71
|
@opts[:price] = @opts[:price].to_sym if @opts[:price]
|
|
68
72
|
@opts[:ean14] = @opts[:include]
|
|
@@ -430,6 +430,7 @@ class ParseComposition
|
|
|
430
430
|
ast = transf.apply(parser.parse(cleaned))
|
|
431
431
|
end
|
|
432
432
|
rescue Parslet::ParseFailed => error
|
|
433
|
+
@@error_handler.nrParsingErrors ||= 0
|
|
433
434
|
@@error_handler.nrParsingErrors += 1
|
|
434
435
|
puts "#{File.basename(__FILE__)}:#{__LINE__}: failed parsing ==> #{cleaned} #{error}"
|
|
435
436
|
return nil
|
|
@@ -495,6 +496,7 @@ class ParseGalenicForm
|
|
|
495
496
|
ast = transf.apply(parser.parse(string))
|
|
496
497
|
end
|
|
497
498
|
rescue Parslet::ParseFailed => error
|
|
499
|
+
@@error_handler.nrParsingErrors ||= 0
|
|
498
500
|
@@error_handler.nrParsingErrors += 1
|
|
499
501
|
puts "#{File.basename(__FILE__)}:#{__LINE__}: failed parsing ==> #{string} #{error}"
|
|
500
502
|
return nil
|
data/lib/oddb2xml/util.rb
CHANGED
|
File without changes
|
data/lib/oddb2xml/version.rb
CHANGED
|
File without changes
|
data/lib/oddb2xml.rb
CHANGED
|
File without changes
|
data/oddb2xml.xsd
CHANGED
|
@@ -48,7 +48,6 @@
|
|
|
48
48
|
FIRST import all data from swissINDEX
|
|
49
49
|
* DSCRD German name
|
|
50
50
|
* DSCRF French name (Products/article only from ZurRose do not have a french name)
|
|
51
|
-
* DSCRI Italian name (Products/article only from ZurRose do not have a french name)
|
|
52
51
|
* GTIN
|
|
53
52
|
GTIN may be 8, 12, 13 or 14 chars long (https://en.wikipedia.org/wiki/Global_Trade_Item_Number)
|
|
54
53
|
The EAN-8 code is an eight-digit barcode used usually for very small articles, such as a battery for hearing aid, where fitting a larger code onto the item would be difficult
|
|
@@ -129,15 +128,6 @@
|
|
|
129
128
|
</xs:simpleType>
|
|
130
129
|
</xs:element>
|
|
131
130
|
|
|
132
|
-
<xs:element name="DSCRI">
|
|
133
|
-
<xs:simpleType>
|
|
134
|
-
<xs:restriction base="xs:string">
|
|
135
|
-
<xs:minLength value="3" />
|
|
136
|
-
<xs:maxLength value="120" />
|
|
137
|
-
</xs:restriction>
|
|
138
|
-
</xs:simpleType>
|
|
139
|
-
</xs:element>
|
|
140
|
-
|
|
141
131
|
<xs:element name="ART">
|
|
142
132
|
<xs:complexType>
|
|
143
133
|
<xs:sequence>
|
|
@@ -167,15 +157,12 @@
|
|
|
167
157
|
<xs:element ref="ns1:BG"/>
|
|
168
158
|
</xs:sequence>
|
|
169
159
|
<xs:element ref="ns1:DSCRD"/>
|
|
170
|
-
<xs:element ref="ns1:DSCRF"
|
|
171
|
-
<xs:element ref="ns1:DSCRI" minOccurs="0"/>
|
|
160
|
+
<xs:element ref="ns1:DSCRF"/>
|
|
172
161
|
<xs:element ref="ns1:SORTD"/>
|
|
173
|
-
<xs:element ref="ns1:SORTF"
|
|
174
|
-
<xs:element ref="ns1:SORTI" minOccurs="0"/>
|
|
162
|
+
<xs:element ref="ns1:SORTF"/>
|
|
175
163
|
<xs:sequence minOccurs="0">
|
|
176
164
|
<xs:element ref="ns1:SYN1D"/>
|
|
177
165
|
<xs:element ref="ns1:SYN1F"/>
|
|
178
|
-
<xs:element ref="ns1:SYN1I"/>
|
|
179
166
|
<xs:element ref="ns1:SLOPLUS"/>
|
|
180
167
|
</xs:sequence>
|
|
181
168
|
<xs:element ref="ns1:ARTCOMP"/>
|
|
@@ -258,10 +245,8 @@
|
|
|
258
245
|
</xs:element>
|
|
259
246
|
<xs:element name="SORTD" type="xs:string"/>
|
|
260
247
|
<xs:element name="SORTF" type="xs:string"/>
|
|
261
|
-
<xs:element name="SORTI" type="xs:string"/>
|
|
262
248
|
<xs:element name="SYN1D" type="xs:string"/>
|
|
263
249
|
<xs:element name="SYN1F" type="xs:string"/>
|
|
264
|
-
<xs:element name="SYN1I" type="xs:string"/>
|
|
265
250
|
<xs:element name="SLOPLUS">
|
|
266
251
|
<xs:simpleType>
|
|
267
252
|
<xs:restriction base="xs:byte">
|
|
@@ -361,10 +346,8 @@
|
|
|
361
346
|
<xs:element ref="ns1:QTYMD"/>
|
|
362
347
|
<xs:element ref="ns1:DSCRDMD"/>
|
|
363
348
|
<xs:element ref="ns1:DSCRFMD"/>
|
|
364
|
-
<xs:element ref="ns1:DSCRIMD"/>
|
|
365
349
|
<xs:element ref="ns1:SORTDMD"/>
|
|
366
350
|
<xs:element ref="ns1:SORTFMD"/>
|
|
367
|
-
<xs:element ref="ns1:SORTIMD"/>
|
|
368
351
|
<xs:sequence minOccurs="0">
|
|
369
352
|
<xs:element ref="ns1:SYN1DMD"/>
|
|
370
353
|
<xs:element ref="ns1:SYN1FMD"/>
|
|
@@ -416,10 +399,8 @@
|
|
|
416
399
|
</xs:element>
|
|
417
400
|
<xs:element name="SORTDMD" type="xs:string"/>
|
|
418
401
|
<xs:element name="SORTFMD" type="xs:string"/>
|
|
419
|
-
<xs:element name="SORTIMD" type="xs:string"/>
|
|
420
402
|
<xs:element name="SYN1DMD" type="xs:string"/>
|
|
421
403
|
<xs:element name="SYN1FMD" type="xs:string"/>
|
|
422
|
-
<xs:element name="SYN1IMD" type="xs:string"/>
|
|
423
404
|
<xs:element name="SLOPLUSMD">
|
|
424
405
|
<xs:simpleType>
|
|
425
406
|
<xs:restriction base="xs:byte">
|
|
@@ -741,7 +722,6 @@
|
|
|
741
722
|
<xs:element ref="ns1:LIMNIV"/>
|
|
742
723
|
<xs:element name="DSCRD" type="xs:string"/>
|
|
743
724
|
<xs:element name="DSCRF" type="xs:string"/>
|
|
744
|
-
<xs:element name="DSCRI" type="xs:string"/>
|
|
745
725
|
<xs:element ref="ns1:VDAT"/>
|
|
746
726
|
</xs:sequence>
|
|
747
727
|
<xs:attribute name="DT" use="required"/>
|
|
@@ -800,7 +780,6 @@
|
|
|
800
780
|
<xs:element ref="ns1:LIMNIVMD"/>
|
|
801
781
|
<xs:element name="DSCRDMD" type="xs:string"/>
|
|
802
782
|
<xs:element name="DSCRFMD" type="xs:string"/>
|
|
803
|
-
<xs:element name="DSCRIMD" type="xs:string"/>
|
|
804
783
|
<xs:element ref="ns1:VDATMD"/>
|
|
805
784
|
</xs:sequence>
|
|
806
785
|
<xs:attribute name="DT" use="required"/>
|
|
@@ -865,8 +844,7 @@
|
|
|
865
844
|
<xs:element minOccurs="0" ref="ns1:PRODNO"/>
|
|
866
845
|
<xs:sequence minOccurs="0">
|
|
867
846
|
<xs:element ref="ns1:DSCRD"/>
|
|
868
|
-
<xs:element ref="ns1:DSCRF"
|
|
869
|
-
<xs:element ref="ns1:DSCRI" minOccurs="0"/>
|
|
847
|
+
<xs:element ref="ns1:DSCRF"/>
|
|
870
848
|
</xs:sequence>
|
|
871
849
|
<xs:element minOccurs="0" ref="ns1:ADINFD"/>
|
|
872
850
|
<xs:element minOccurs="0" ref="ns1:ADINFF"/>
|
|
@@ -942,7 +920,6 @@
|
|
|
942
920
|
<xs:sequence minOccurs="0">
|
|
943
921
|
<xs:element ref="ns1:DSCRDMD"/>
|
|
944
922
|
<xs:element ref="ns1:DSCRFMD"/>
|
|
945
|
-
<xs:element ref="ns1:DSCRIMD"/>
|
|
946
923
|
</xs:sequence>
|
|
947
924
|
<xs:element minOccurs="0" ref="ns1:ADINFDMD"/>
|
|
948
925
|
<xs:element minOccurs="0" ref="ns1:ADINFFMD"/>
|
|
@@ -1111,7 +1088,6 @@
|
|
|
1111
1088
|
<xs:element name="ITMD" type="xs:string"/>
|
|
1112
1089
|
<xs:element name="DSCRDMD" type="xs:string"/>
|
|
1113
1090
|
<xs:element name="DSCRFMD" type="xs:string"/>
|
|
1114
|
-
<xs:element name="DSCRIMD" type="xs:string"/>
|
|
1115
1091
|
<xs:element name="VDATMD" type="xs:NMTOKEN"/>
|
|
1116
1092
|
<xs:element name="RESULTMD">
|
|
1117
1093
|
<xs:complexType>
|
data/oddb_calc.xsd
CHANGED
|
File without changes
|
data/spec/artikelstamm_spec.rb
CHANGED
|
@@ -11,7 +11,7 @@ describe Oddb2xml::Builder do
|
|
|
11
11
|
expect(@inhalt).not_to be nil
|
|
12
12
|
unless @inhalt.index(expected_value)
|
|
13
13
|
puts expected_value
|
|
14
|
-
binding.pry # TODO: Must not be active in production!!
|
|
14
|
+
# binding.pry # TODO: Must not be active in production!!
|
|
15
15
|
end
|
|
16
16
|
expect(@inhalt.index(expected_value)).not_to be nil
|
|
17
17
|
end
|
|
@@ -75,11 +75,12 @@ describe Oddb2xml::Builder do
|
|
|
75
75
|
expect(@inhalt.index(expected)).not_to be nil
|
|
76
76
|
end
|
|
77
77
|
|
|
78
|
-
it "should have a ATC for product PRIORIX TETRA" do
|
|
78
|
+
it "should have a DSCRF and ATC for product PRIORIX TETRA" do
|
|
79
79
|
expected = %(<PRODUCT>
|
|
80
80
|
<PRODNO>5815801</PRODNO>
|
|
81
81
|
<SALECD>A</SALECD>
|
|
82
82
|
<DSCR>PRIORIX TETRA Trockensub c Solv Fertspr</DSCR>
|
|
83
|
+
<DSCRF>Priorix-Tetra, Pulver und Lösungsmittel zur Herstellung einer Injektionslösung</DSCRF>
|
|
83
84
|
<ATC>J07BD54</ATC>
|
|
84
85
|
</PRODUCT>)
|
|
85
86
|
expect(@inhalt.index(expected)).not_to be nil
|
|
@@ -118,6 +119,7 @@ describe Oddb2xml::Builder do
|
|
|
118
119
|
<PRODNO>5559401</PRODNO>
|
|
119
120
|
<SALECD>A</SALECD>
|
|
120
121
|
<DSCR>Nutriflex Lipid plus, Infusionsemulsion, 1250ml</DSCR>
|
|
122
|
+
<DSCRF/>
|
|
121
123
|
<ATC>B05BA10</ATC>
|
|
122
124
|
</PRODUCT>)
|
|
123
125
|
expect(@inhalt.index(expected)).not_to be nil
|
|
@@ -244,6 +246,7 @@ describe Oddb2xml::Builder do
|
|
|
244
246
|
<PHAR>0055805</PHAR>
|
|
245
247
|
<SALECD>A</SALECD>
|
|
246
248
|
<DSCR>TENSOPLAST Kompressionsbinde 5cmx4.5m</DSCR>
|
|
249
|
+
<DSCRF/>
|
|
247
250
|
<PEXF>0.00</PEXF>
|
|
248
251
|
<PPUB>22.95</PPUB>
|
|
249
252
|
</ITEM>),
|
|
@@ -458,12 +461,14 @@ describe Oddb2xml::Builder do
|
|
|
458
461
|
<!--Chapter70 hack prodno 2069639 Ceres Urtinkturen gemäss L2 mit - im Kommentar-->
|
|
459
462
|
<SALECD>A</SALECD>
|
|
460
463
|
<DSCR>Ceres Urtinkturen gemäss L2 mit -- im Kommentar</DSCR>
|
|
464
|
+
<DSCRF/>
|
|
461
465
|
</PRODUCT>),
|
|
462
466
|
"Chapter 70 item" => %(<ITEM PHARMATYPE="P">
|
|
463
467
|
<GTIN>2500000588532</GTIN>
|
|
464
468
|
<PHAR>2069639</PHAR>
|
|
465
469
|
<SALECD>A</SALECD>
|
|
466
470
|
<DSCR>EINF ARZNEI Ceres Urtinktur spez 20ml</DSCR>
|
|
471
|
+
<DSCRF/>
|
|
467
472
|
<PEXF>23.44</PEXF>
|
|
468
473
|
<PPUB>31.30</PPUB>
|
|
469
474
|
<!--Chapter70 hack 2500000588532 EINF ARZNEI Ceres Urtinktur spez 20ml-->
|
|
@@ -482,6 +487,7 @@ Der behandelnde Arzt ist verpflichtet, die erforderlichen Daten laufend im vorge
|
|
|
482
487
|
<PRODNO>1336901</PRODNO>
|
|
483
488
|
<SALECD>A</SALECD>
|
|
484
489
|
<DSCR>Pethidin HCl Amino 100 mg/2 ml, Injektionslösung</DSCR>
|
|
490
|
+
<DSCRF/>
|
|
485
491
|
<ATC>N02AB02</ATC>
|
|
486
492
|
</PRODUCT>)}
|
|
487
493
|
|
data/spec/builder_spec.rb
CHANGED
|
@@ -35,7 +35,7 @@ ARTICLE_ZURROSE_ELEMENTS = [
|
|
|
35
35
|
["ARTICLE/ART/ARTINS/NINCD", "20"]
|
|
36
36
|
]
|
|
37
37
|
|
|
38
|
-
ARTICLE_NAROPIN = %(
|
|
38
|
+
ARTICLE_NAROPIN = %(<REF_DATA>1</REF_DATA>
|
|
39
39
|
<SMCAT>B</SMCAT>
|
|
40
40
|
<SMNO>54015011</SMNO>
|
|
41
41
|
<PRODNO>5401501</PRODNO>
|
|
@@ -44,10 +44,8 @@ ARTICLE_NAROPIN = %( <REF_DATA>1</REF_DATA>
|
|
|
44
44
|
<BG>N</BG>
|
|
45
45
|
<DSCRD>NAROPIN Inj Lös 0.2 % 10ml Duofit Amp 5 Stk</DSCRD>
|
|
46
46
|
<DSCRF>NAROPIN sol inj 0.2 % 10ml amp duofit 5 pce</DSCRF>
|
|
47
|
-
<DSCRI>NAROPIN Inj Lös 0.2 % 10ml Duofit Amp 5 Stk</DSCRI>
|
|
48
47
|
<SORTD>NAROPIN INJ LÖS 0.2 % 10ML DUOFIT AMP 5 STK</SORTD>
|
|
49
48
|
<SORTF>NAROPIN SOL INJ 0.2 % 10ML AMP DUOFIT 5 PCE</SORTF>
|
|
50
|
-
<SORTI>NAROPIN INJ LÖS 0.2 % 10ML DUOFIT AMP 5 STK</SORTI>
|
|
51
49
|
<ARTCOMP>
|
|
52
50
|
<COMPNO>7601001402539</COMPNO>
|
|
53
51
|
</ARTCOMP>
|
|
@@ -56,8 +54,7 @@ ARTICLE_NAROPIN = %( <REF_DATA>1</REF_DATA>
|
|
|
56
54
|
<BC>7680540150118</BC>
|
|
57
55
|
<BCSTAT>A</BCSTAT>
|
|
58
56
|
</ARTBAR>
|
|
59
|
-
</ART>
|
|
60
|
-
)
|
|
57
|
+
</ART>)
|
|
61
58
|
|
|
62
59
|
ARTICLE_COMMON_ELEMENTS = [
|
|
63
60
|
["ARTICLE/ART/REF_DATA", "1"],
|
|
@@ -571,10 +568,11 @@ describe Oddb2xml::Builder do
|
|
|
571
568
|
|
|
572
569
|
it "should generate ATC for 7680002770014" do
|
|
573
570
|
oddb_product_xml = IO.read(File.join(Oddb2xml::WORK_DIR, "oddb_product.xml"))
|
|
574
|
-
text = %(<GTIN>
|
|
571
|
+
text = %(<GTIN>7680002770014</GTIN>
|
|
575
572
|
<PRODNO>0027701</PRODNO>
|
|
576
|
-
<DSCRD>
|
|
577
|
-
<
|
|
573
|
+
<DSCRD>SEROCYTOL Herz-Gefässe Supp 3 Stk</DSCRD>
|
|
574
|
+
<DSCRF>SEROCYTOL Coeur-Vaisseaux supp 3 pce</DSCRF>
|
|
575
|
+
<ATC>J06AA99</ATC>
|
|
578
576
|
<IT>08.07.</IT>
|
|
579
577
|
<CPT/>)
|
|
580
578
|
expect(oddb_product_xml.index(text)).to be >= 1
|
|
@@ -585,6 +583,7 @@ describe Oddb2xml::Builder do
|
|
|
585
583
|
text2 = %( <GTIN>7680002770021</GTIN>
|
|
586
584
|
<PRODNO>0027701</PRODNO>
|
|
587
585
|
<DSCRD>Coeur-Vaisseaux Sérocytol, suppositoire</DSCRD>
|
|
586
|
+
<DSCRF>Coeur-Vaisseaux Sérocytol, suppositoire</DSCRF>
|
|
588
587
|
<ATC>J06AA</ATC>
|
|
589
588
|
<IT>08.07.</IT>
|
|
590
589
|
<CPT/>)
|
data/spec/calc_spec.rb
CHANGED
|
File without changes
|
|
File without changes
|
data/spec/cli_spec.rb
CHANGED
|
File without changes
|
data/spec/compare_spec.rb
CHANGED
|
File without changes
|
|
File without changes
|
data/spec/compressor_spec.rb
CHANGED
|
File without changes
|
data/spec/data/AipsDownload.zip
CHANGED
|
File without changes
|
|
File without changes
|
data/spec/data/GL_Diff_SB.xml
CHANGED
|
File without changes
|
data/spec/data/ItCodes.xml
CHANGED
|
File without changes
|
data/spec/data/PR121001.txt
CHANGED
|
File without changes
|
data/spec/data/PR121002.txt
CHANGED
|
File without changes
|
data/spec/data/Preparations.xml
CHANGED
|
File without changes
|
data/spec/data/Publications.xls
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
data/spec/data/atc.csv
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|