oddb2xml 2.5.0 → 2.5.1

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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -1
  3. data/Elexis_Artikelstamm_v003.xsd +387 -0
  4. data/Elexis_Artikelstamm_v5.xsd +513 -0
  5. data/Gemfile +2 -6
  6. data/History.txt +11 -0
  7. data/README.md +35 -27
  8. data/artikelstamm.md +68 -0
  9. data/bin/compare_v5 +41 -0
  10. data/bin/oddb2xml +3 -15
  11. data/data/article_overrides.yaml +51859 -0
  12. data/data/gtin2ignore.yaml +30510 -0
  13. data/data/product_overrides.yaml +4 -0
  14. data/lib/oddb2xml/builder.rb +543 -192
  15. data/lib/oddb2xml/cli.rb +82 -62
  16. data/lib/oddb2xml/compare.rb +189 -0
  17. data/lib/oddb2xml/compressor.rb +6 -3
  18. data/lib/oddb2xml/downloader.rb +79 -64
  19. data/lib/oddb2xml/extractor.rb +67 -40
  20. data/lib/oddb2xml/options.rb +76 -77
  21. data/lib/oddb2xml/parslet_compositions.rb +18 -1
  22. data/lib/oddb2xml/util.rb +25 -3
  23. data/lib/oddb2xml/version.rb +1 -1
  24. data/oddb2xml.gemspec +8 -5
  25. data/oddb2xml.xsd +1 -0
  26. data/spec/artikelstamm_spec.rb +383 -0
  27. data/spec/builder_spec.rb +147 -118
  28. data/spec/calc_spec.rb +3 -15
  29. data/spec/cli_spec.rb +24 -35
  30. data/spec/compare_spec.rb +24 -0
  31. data/spec/compressor_spec.rb +1 -3
  32. data/spec/data/Elexis_Artikelstamm_v5.xsd +513 -0
  33. data/spec/data/Preparations.xml +2200 -0
  34. data/spec/data/Publications.xls +0 -0
  35. data/spec/data/artikelstamm_N_010917.xml +39 -0
  36. data/spec/data/artikelstamm_N_011217.xml +17 -0
  37. data/spec/data/artikelstamm_P_010917.xml +86 -0
  38. data/spec/data/artikelstamm_P_011217.xml +63 -0
  39. data/spec/data/oddb2xml_files_lppv.txt +2 -0
  40. data/spec/data/refdata_NonPharma.xml +38 -0
  41. data/spec/data/refdata_Pharma.xml +220 -0
  42. data/spec/data/swissmedic_orphan.xlsx +0 -0
  43. data/spec/data/swissmedic_package.xlsx +0 -0
  44. data/spec/data/transfer.dat +59 -19
  45. data/spec/data/v5_first.xml +102 -0
  46. data/spec/data/v5_second.xml +184 -0
  47. data/spec/data_helper.rb +72 -0
  48. data/spec/downloader_spec.rb +19 -27
  49. data/spec/extractor_spec.rb +27 -33
  50. data/spec/fixtures/vcr_cassettes/artikelstamm.json +1 -0
  51. data/spec/options_spec.rb +73 -66
  52. data/spec/spec_helper.rb +73 -24
  53. data/test_options.rb +4 -2
  54. metadata +100 -21
  55. data/spec/data/XMLPublications.zip +0 -0
  56. data/spec/data/compressor/oddb_article.xml +0 -0
  57. data/spec/data/compressor/oddb_fi.xml +0 -0
  58. data/spec/data/compressor/oddb_fi_product.xml +0 -0
  59. data/spec/data/compressor/oddb_limitation.xml +0 -0
  60. data/spec/data/compressor/oddb_product.xml +0 -0
  61. data/spec/data/compressor/oddb_substance.xml +0 -0
@@ -16,6 +16,9 @@ module ParseUtil
16
16
  # this class is responsible to patch errors in swissmedic entries after
17
17
  # oddb.org detected them, as it takes sometimes a few days (or more) till they get corrected
18
18
  # Reports the number of occurrences of each entry
19
+ @@saved_parsed ||= {}
20
+ @@nr_saved_parsed_used ||= 0
21
+
19
22
  class HandleSwissmedicErrors
20
23
 
21
24
  attr_accessor :nrParsingErrors
@@ -51,7 +54,7 @@ module ParseUtil
51
54
  result = result.gsub(entry.pattern, entry.replacement)
52
55
  unless result.eql?(intermediate)
53
56
  entry.nr_occurrences += 1
54
- puts "#{File.basename(__FILE__)}:#{__LINE__}: fixed \nbefore: #{intermediate}\nafter: #{result}" unless defined?(RSpec)
57
+ puts "#{File.basename(__FILE__)}:#{__LINE__}: fixed \nbefore: #{intermediate}\nafter: #{result}" if $VERBOSE
55
58
  end
56
59
  }
57
60
  @nrLines += 1
@@ -64,8 +67,18 @@ module ParseUtil
64
67
  string.split(/\s+/u).collect { |word| word.capitalize }.join(' ').strip
65
68
  end
66
69
 
70
+ def ParseUtil.nr_saved_parsed_used
71
+ @@nr_saved_parsed_used
72
+ end
73
+
67
74
  def ParseUtil.parse_compositions(composition_text, active_agents_string = '')
68
75
  active_agents = active_agents_string ? active_agents_string.downcase.split(/,\s+/) : []
76
+ key = [ composition_text, active_agents ]
77
+ saved_value = @@saved_parsed[key]
78
+ if saved_value
79
+ @@nr_saved_parsed_used += 1
80
+ return saved_value
81
+ end
69
82
  comps = []
70
83
  lines = composition_text.gsub(/\r\n?/u, "\n").split(/\n/u)
71
84
  lines.select do
@@ -82,7 +95,11 @@ module ParseUtil
82
95
  end
83
96
  end
84
97
  comps << ParseComposition.new(composition_text.split(/,|:|\(/)[0]) if comps.size == 0
98
+ @@saved_parsed[key] = comps
85
99
  comps
100
+ rescue => error
101
+ puts "error #{error}"
102
+ # binding.pry
86
103
  end
87
104
 
88
105
  end
@@ -21,6 +21,10 @@ module Oddb2xml
21
21
  @atc_csv_content = {}
22
22
 
23
23
  def Oddb2xml.patch_some_utf8(line)
24
+ begin
25
+ line = line.encode('utf-8')
26
+ rescue => error
27
+ end
24
28
  begin
25
29
  line.gsub("\u0089", "‰").gsub("\u0092", '’').gsub("\u0096", '-').gsub("\u2013",'-').gsub("\u201D", '"').chomp
26
30
  rescue => error
@@ -36,11 +40,11 @@ module Oddb2xml
36
40
  ausgabe.encode('ISO-8859-1')
37
41
  rescue => error
38
42
  puts "#{error}: in #{line}"
39
- require 'pry'; binding.pry
40
43
  end
41
44
  end
42
45
 
43
- def Oddb2xml.add_epha_changes_for_ATC(iksnr, atc_code)
46
+ def Oddb2xml.add_epha_changes_for_ATC(iksnr, atc_code, force_run: false)
47
+ @atc_csv_content = {} if force_run
44
48
  if @atc_csv_content.size == 0
45
49
  open(@atc_csv_origin).readlines.each{
46
50
  |line|
@@ -55,7 +59,8 @@ module Oddb2xml
55
59
 
56
60
  def Oddb2xml.log(msg)
57
61
  return unless @options[:log]
58
- $stdout.puts "#{Time.now.strftime("%Y-%m-%d %H:%M:%S")}: #{msg}"
62
+ # TODO:: require 'pry'; binding.pry if msg.size > 1000
63
+ $stdout.puts "#{Time.now.strftime("%Y-%m-%d %H:%M:%S")}: #{msg[0..250]}"
59
64
  $stdout.flush
60
65
  end
61
66
 
@@ -159,4 +164,21 @@ module Oddb2xml
159
164
  end
160
165
  return true
161
166
  end
167
+
168
+ def Oddb2xml.validate_via_xsd(xsd_file, xml_file)
169
+ xsd =open(xsd_file).read
170
+ xsd_rtikelstamm_xml = Nokogiri::XML::Schema(xsd)
171
+ doc = Nokogiri::XML(File.read(xml_file))
172
+ xsd_rtikelstamm_xml.validate(doc).each do
173
+ |error|
174
+ if error.message
175
+ puts "Failed validating #{xml_file} with #{File.size(xml_file)} bytes using XSD from #{xsd_file}"
176
+ puts "CMD: xmllint --noout --schema #{xsd_file} #{xml_file}"
177
+ end
178
+ msg = "expected #{error.message} to be nil\nfor #{xml_file}"
179
+ puts msg
180
+ expect(error.message).to be_nil, msg
181
+ end
182
+ end
183
+
162
184
  end
@@ -1,3 +1,3 @@
1
1
  module Oddb2xml
2
- VERSION = "2.5.0"
2
+ VERSION = "2.5.1"
3
3
  end
@@ -19,11 +19,11 @@ Gem::Specification.new do |spec|
19
19
 
20
20
  # We fix the version of the spec to newer versions only in the third position
21
21
  # hoping that these version fix only security/severe bugs
22
- # Consulted the Gemfile.lock to get
22
+ # Consulted the Gemfile.lock to get
23
23
  spec.add_dependency 'rubyzip'#, '~> 1.1.3'
24
- spec.add_dependency 'archive-tar-minitar'#, '~> 0.5.2'
24
+ spec.add_dependency 'minitar'#, '~> 0.5.2'
25
25
  spec.add_dependency 'mechanize'#, '~> 2.5.1'
26
- spec.add_dependency 'nokogiri'#, '~> 1.6.0'
26
+ spec.add_dependency 'nokogiri', '>= 1.8.2'
27
27
  spec.add_dependency 'savon'#, '~> 2.11.0'
28
28
  spec.add_dependency 'spreadsheet'#, '~> 1.0.0'
29
29
  spec.add_dependency 'rubyXL'#, '~> 3.3.1'
@@ -31,7 +31,10 @@ Gem::Specification.new do |spec|
31
31
  spec.add_dependency 'parslet'#, '~> 1.7.0'
32
32
  spec.add_dependency 'rubyntlm', '0.5.1'
33
33
  spec.add_dependency 'multi_json'#, '>= 0.3.2'
34
- spec.add_dependency 'httpi', '>= 2.4.1'
34
+ spec.add_dependency 'rack', '< 2.0'
35
+ spec.add_dependency 'httpi' #, '>= 2.4.1'
36
+ spec.add_dependency 'trollop' #, '>= 2.4.1'
37
+ spec.add_dependency 'xml-simple'
35
38
 
36
39
  spec.add_development_dependency "bundler"
37
40
  spec.add_development_dependency "rake"
@@ -40,6 +43,6 @@ Gem::Specification.new do |spec|
40
43
  spec.add_development_dependency "rdoc"
41
44
  spec.add_development_dependency "vcr"
42
45
  spec.add_development_dependency "timecop"
43
- # spec.add_development_dependency "ruby-prof"
46
+ spec.add_development_dependency "flexmock"
44
47
  end
45
48
 
@@ -218,6 +218,7 @@
218
218
  <xs:enumeration value="60" />
219
219
  <xs:enumeration value="80" />
220
220
  <xs:enumeration value="100" />
221
+ <xs:enumeration value="120" />
221
222
  </xs:restriction>
222
223
  </xs:simpleType>
223
224
  </xs:element>
@@ -0,0 +1,383 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+ require "rexml/document"
5
+ require 'webmock/rspec'
6
+ include REXML
7
+ RUN_ALL = true
8
+
9
+ describe Oddb2xml::Builder do
10
+ raise "Cannot rspec in directroy containing a spac" if / /.match(Oddb2xml::SpecData)
11
+ NrExtendedArticles = 34
12
+ NrSubstances = 14
13
+ NrLimitations = 5
14
+ NrInteractions = 5
15
+ NrCodes = 5
16
+ NrProdno = 23
17
+ NrPackages = 24
18
+ NrProducts = 19
19
+ RegExpDesitin = /1125819012LEVETIRACETAM DESITIN Mini Filmtab 250 mg 30 Stk/
20
+ include ServerMockHelper
21
+ def check_artikelstamm_xml(key, expected_value)
22
+ expect(@artikelstamm_name).not_to be nil
23
+ expect(@inhalt).not_to be nil
24
+ unless @inhalt.index(expected_value)
25
+ puts expected_value
26
+ end
27
+ # binding.pry unless @inhalt.index(expected_value)
28
+ expect(@inhalt.index(expected_value)).not_to be nil
29
+ end
30
+ def common_run_init(options = {})
31
+ @savedDir = Dir.pwd
32
+ @oddb2xml_xsd = File.expand_path(File.join(File.dirname(__FILE__), '..', 'oddb2xml.xsd'))
33
+ @oddb_calc_xsd = File.expand_path(File.join(File.dirname(__FILE__), '..', 'oddb_calc.xsd'))
34
+ @elexis_v5_xsd = File.expand_path(File.join(__FILE__, '..', '..', 'Elexis_Artikelstamm_v5.xsd'))
35
+ @elexis_v5_csv = File.join(Oddb2xml::WorkDir, 'Elexis_Artikelstamm_v5.csv')
36
+ expect(File.exist?(@oddb2xml_xsd)).to eq true
37
+ expect(File.exist?(@oddb_calc_xsd)).to eq true
38
+ expect(File.exist?(@elexis_v5_xsd)).to eq true
39
+ cleanup_directories_before_run
40
+ FileUtils.makedirs(Oddb2xml::WorkDir)
41
+ Dir.chdir(Oddb2xml::WorkDir)
42
+ mock_downloads
43
+ end
44
+
45
+ after(:all) do
46
+ Dir.chdir @savedDir if @savedDir and File.directory?(@savedDir)
47
+ end
48
+ context 'when artikelstamm option is given' do
49
+ before(:all) do
50
+ common_run_init
51
+ options = Oddb2xml::Options.parse(['--artikelstamm']) # , '--log'])
52
+ # @res = buildr_capture(:stdout){ Oddb2xml::Cli.new(options).run }
53
+ Oddb2xml::Cli.new(options).run # to debug
54
+ @artikelstamm_name = File.join(Oddb2xml::WorkDir, "artikelstamm_#{Date.today.strftime('%d%m%Y')}_v5.xml")
55
+ @doc = Nokogiri::XML(File.open(@artikelstamm_name))
56
+ # @rexml = REXML::Document.new File.read(@artikelstamm_name)
57
+ @inhalt = IO.read(@artikelstamm_name)
58
+ end
59
+
60
+ it 'should exist' do
61
+ expect(File.exists?(@artikelstamm_name)).to eq true
62
+ end
63
+
64
+ it 'should create transfer.ut8' do
65
+ expect(File.exists?(File.join(Oddb2xml::Downloads, 'transfer.utf8'))).to eq true
66
+ end
67
+
68
+ it 'should have a comment' do
69
+ expect(@inhalt).to match /<!--Produced by/
70
+ end
71
+
72
+ it 'should produce a Elexis_Artikelstamm_v5.csv' do
73
+ expect(File.exists?(@elexis_v5_csv)).to eq true
74
+ inhalt = File.open(@elexis_v5_csv, 'r+').read
75
+ expect(inhalt.size).to be > 0
76
+ expect(inhalt).to match /7680284860144/
77
+ end
78
+
79
+ it 'should NOT generate a v3 nonpharma xml' do
80
+ v3_name = @artikelstamm_name.sub('_v5.xml', '_v3.xml').sub('artikelstamm_', 'artikelstamm_N_')
81
+ expect(File.exist?(v3_name)).to eq false
82
+ end
83
+
84
+ it 'should NOT generate a vx pharma xml' do
85
+ v3_name = @artikelstamm_name.sub('_v5.xml', '_v3.xml').sub('artikelstamm_', 'artikelstamm_P_')
86
+ expect(File.exist?(v3_name)).to eq false
87
+ end
88
+
89
+ it 'should contain a LIMITATION_PTS' do
90
+ expect(@inhalt.index('<LIMITATION_PTS>40</LIMITATION_PTS>')).not_to be nil
91
+ end
92
+
93
+ it 'should find price from Preparations.xml by setting' do
94
+ expect(File.exists?(@elexis_v5_csv)).to eq true
95
+ inhalt = File.open(@elexis_v5_csv, 'r+').read
96
+ expected = %(7680658560014,"DIBASE 10'000, orale Tropflösung",Flasche(n),Flasche(n),5,9.25,6585601,A11CC05,cholecalciferolum,,07.02.3.,SL)
97
+ expect(inhalt.index(expected)).to be > 0
98
+ end
99
+
100
+ it 'should contain a PRODUCT which was not in refdata' do
101
+ expected = %(<PRODUCT>
102
+ <PRODNO>6118601</PRODNO>
103
+ <SALECD>A</SALECD>
104
+ <DSCR>Nutriflex Omega special, Infusionsemulsion 625 ml</DSCR>
105
+ <DSCRF/>
106
+ <ATC>B05BA10</ATC>
107
+ </PRODUCT>)
108
+ expect(@inhalt.index(expected)).not_to be nil
109
+ end
110
+
111
+ it 'should have a price for Lynparza' do
112
+ expect(File.exists?(@elexis_v5_csv)).to eq true
113
+ inhalt = File.open(@elexis_v5_csv, 'r+').read
114
+ expect(inhalt.index('7680651600014,LYNPARZA Kaps 50 mg 448 Stk,,Kapsel(n),5562.48,5947.55')).not_to be nil
115
+ end
116
+ it 'should trim the ean13 to 13 length' do
117
+ gtin14 = "00040565124346"
118
+ expect(gtin14.length).to eq 14
119
+ expected14 = %(<GTIN>#{gtin14}</GTIN>)
120
+ expect(@inhalt.index(expected14)).to be nil
121
+ gtin13 = gtin14[1..-1]
122
+ expect(gtin13.length).to eq 13
123
+ expected13 = %(<GTIN>#{gtin13}</GTIN>)
124
+ expect(@inhalt.index(expected13)).not_to be nil
125
+ end
126
+
127
+ it 'should not contain a GTIN=0' do
128
+ expect(@inhalt.index('GTIN>0</GTIN')).to be nil
129
+ end
130
+
131
+ it 'should contain a GTIN starting 0' do
132
+ expect(@inhalt.index('GTIN>0')).to be > 0
133
+ end
134
+
135
+ it 'should contain a PHAR 4236857 from refdata_NonPharma.xml' do
136
+ expect(@inhalt.index('<PHAR>4236863</PHAR>')).to be > 0
137
+ # Marco leaves the 14 GTIN digit in previous importes. As of January 2018 force it to the 13 digits
138
+ expect(@inhalt.index('<GTIN>0040565124346</GTIN>')).to be > 0
139
+ end
140
+
141
+ it 'should a DSCRF for 4042809018288 TENSOPLAST Kompressionsbinde 5cmx4.5m' do
142
+ skip("Where does the DSCR for 4042809018288 come from. It should be TENSOPLAST bande compression 5cmx4.5m")
143
+ end
144
+
145
+ it 'should NOT add GTIN 7680172330414 SELSUN and ean13 start with 7680 (Swissmedic) which is marked as inactive in transfer.dat' do
146
+ @inhalt = IO.read(@artikelstamm_name)
147
+ expect(@inhalt.index('7680172330414')).to be nil
148
+ end
149
+
150
+ it 'should add GTIN 3605520301605 Armani Attitude which is marked as inactive in transfer.dat' do
151
+ @inhalt = IO.read(@artikelstamm_name)
152
+ expect(@inhalt.index('3605520301605')).not_to be nil
153
+ end
154
+
155
+ it 'should add BIOMARIS Voll Meersalz which is marked as inactive in transfer.dat but has PPUB and PEXF' do
156
+ @inhalt = IO.read(@artikelstamm_name)
157
+ expect(@inhalt.index('BIOMARIS Voll Meersalz 500 g')).not_to be nil
158
+ end
159
+
160
+ it 'Should not contain PHAR 8809544 Sildenavil wiht pexf and ppub 0.0' do
161
+ #1128809544Sildenafil Suspension 7mg/ml 100ml 0030850045801000000000000000000000002
162
+ @inhalt = IO.read(@artikelstamm_name)
163
+ expect(@inhalt.index('ildenafil Suspension')).to be nil
164
+ end
165
+
166
+ it 'should a company EAN for 4042809018288 TENSOPLAST Kompressionsbinde 5cmx4.5m' do
167
+ skip("Where does the COMP GLN for 4042809018288 come from. It should be 7601003468441")
168
+ end
169
+
170
+ it 'shoud contain Lamivudinum as 3TC substance' do
171
+ expect(@inhalt.index('<SUBSTANCE>Lamivudinum</SUBSTANCE>')).not_to be nil
172
+ end
173
+
174
+ it 'shoud contain GENERIC_TYPE' do
175
+ expect(@inhalt.index('<GENERIC_TYPE')).not_to be nil
176
+ end
177
+
178
+ it 'should contain DIBASE with phar' do
179
+ info = %(DIBASE 10'000 - 7199565
180
+ DIBASE 25'000 - 7210539
181
+ )
182
+ expected = %(
183
+ <GTIN>7680658560014</GTIN>
184
+ <SALECD>A</SALECD>
185
+ <DSCR>DIBASE 10'000, orale Tropflösung</DSCR>
186
+ )
187
+ expect(@inhalt.index('<GTIN>7680658560014</GTIN>')).not_to be nil
188
+ end
189
+
190
+ it 'should contain a public price if the item was only in the SL liste (Preparations.xml)' do
191
+ # same as 7680403330459 CARBADERM
192
+ expect(@inhalt.index('<PPUB>27.70</PPUB>')).not_to be nil
193
+ end
194
+ it 'should contain PEVISONE Creme 30 g' do
195
+ expect(@inhalt.index('PEVISONE Creme 15 g')).not_to be nil # 7680406620144
196
+ expect(@inhalt.index('PEVISONE Creme 30 g')).not_to be nil # 7680406620229
197
+ # Should also check for price!
198
+ end
199
+ it 'should validate against artikelstamm.xsd' do
200
+ validate_via_xsd(@elexis_v5_xsd, @artikelstamm_name)
201
+ end
202
+ tests = { 'item 7680403330459 CARBADERM only in Preparations(SL)' =>
203
+ %(<ITEM PHARMATYPE="P">
204
+ <GTIN>7680403330459</GTIN>
205
+ <PHAR>3603779</PHAR>
206
+ <SALECD>A</SALECD>
207
+ <DSCR>CARBADERM Creme Tb 300 ml</DSCR>
208
+ <DSCRF>--missing--</DSCRF>
209
+ <PEXF>16.22</PEXF>
210
+ <PPUB>27.70</PPUB>
211
+ </ITEM>),
212
+ 'item 4042809018288 TENSOPLAST' =>
213
+ %(<ITEM PHARMATYPE="N">
214
+ <GTIN>4042809018288</GTIN>
215
+ <PHAR>0055805</PHAR>
216
+ <SALECD>A</SALECD>
217
+ <DSCR>TENSOPLAST Kompressionsbinde 5cmx4.5m</DSCR>
218
+ <DSCRF>--missing--</DSCRF>
219
+ <PEXF>0.00</PEXF>
220
+ <PPUB>22.95</PPUB>
221
+ </ITEM>),
222
+ 'product 3247501 LANSOYL' => '<ITEM PHARMATYPE="P">
223
+ <GTIN>7680324750190</GTIN>
224
+ <PHAR>0023722</PHAR>
225
+ <SALECD>A</SALECD>
226
+ <DSCR>LANSOYL Gel 225 g</DSCR>
227
+ <DSCRF>LANSOYL gel 225 g</DSCRF>
228
+ <COMP>
229
+ <NAME>Actipharm SA</NAME>
230
+ <GLN>7601001002012</GLN>
231
+ </COMP>
232
+ <PKG_SIZE>225</PKG_SIZE>
233
+ <MEASURE>g</MEASURE>
234
+ <MEASUREF>g</MEASUREF>
235
+ <DOSAGE_FORM>Gelée</DOSAGE_FORM>
236
+ <IKSCAT>D</IKSCAT>
237
+ <LPPV>true</LPPV>
238
+ <PRODNO>3247501</PRODNO>
239
+ </ITEM>',
240
+ 'product 5366201 3TC' =>
241
+ %(<ITEM PHARMATYPE="P">
242
+ <GTIN>7680536620137</GTIN>
243
+ <PHAR>1699947</PHAR>
244
+ <SALECD>A</SALECD>
245
+ <DSCR>3TC Filmtabl 150 mg 60 Stk</DSCR>
246
+ <DSCRF>3TC cpr pell 150 mg 60 pce</DSCRF>
247
+ <COMP>
248
+ <NAME>ViiV Healthcare GmbH</NAME>
249
+ <GLN>7601001392175</GLN>
250
+ </COMP>
251
+ <PEXF>164.55</PEXF>
252
+ <PPUB>205.3</PPUB>
253
+ <PKG_SIZE>60</PKG_SIZE>
254
+ <MEASURE>Tablette(n)</MEASURE>
255
+ <MEASUREF>Tablette(n)</MEASUREF>
256
+ <DOSAGE_FORM>Filmtabletten</DOSAGE_FORM>
257
+ <DOSAGE_FORMF>Comprimés filmés</DOSAGE_FORMF>
258
+ <SL_ENTRY>true</SL_ENTRY>
259
+ <IKSCAT>A</IKSCAT>
260
+ <GENERIC_TYPE>O</GENERIC_TYPE>
261
+ <DEDUCTIBLE>10</DEDUCTIBLE>
262
+ <PRODNO>5366201</PRODNO>
263
+ </ITEM>),
264
+ 'item 7680161050583 HIRUDOID' =>
265
+ %(<ITEM PHARMATYPE="P">
266
+ <GTIN>7680161050583</GTIN>
267
+ <PHAR>2731179</PHAR>
268
+ <SALECD>A</SALECD>
269
+ <DSCR>HIRUDOID Creme 3 mg/g 40 g</DSCR>
270
+ <DSCRF>HIRUDOID crème 3 mg/g 40 g</DSCRF>
271
+ <COMP>
272
+ <NAME>Medinova AG</NAME>
273
+ <GLN>7601001002258</GLN>
274
+ </COMP>
275
+ <PEXF>4.768575</PEXF>
276
+ <PPUB>8.8</PPUB>
277
+ <PKG_SIZE>40</PKG_SIZE>
278
+ <MEASURE>g</MEASURE>
279
+ <MEASUREF>g</MEASUREF>
280
+ <DOSAGE_FORM>Creme</DOSAGE_FORM>
281
+ <SL_ENTRY>true</SL_ENTRY>
282
+ <IKSCAT>D</IKSCAT>
283
+ <DEDUCTIBLE>10</DEDUCTIBLE>
284
+ <PRODNO>1610501</PRODNO>
285
+ </ITEM>),
286
+ 'item 7680284860144 ANCOPIR' =>'<ITEM PHARMATYPE="P">
287
+ <GTIN>7680284860144</GTIN>
288
+ <PHAR>0177804</PHAR>
289
+ <SALECD>A</SALECD>
290
+ <DSCR>Ancopir, Injektionslösung</DSCR>
291
+ <DSCRF>--missing--</DSCRF>
292
+ <COMP>
293
+ <NAME>Dr. Grossmann AG, Pharmaca</NAME>
294
+ <GLN/>
295
+ </COMP>
296
+ <PEXF>3.89</PEXF>
297
+ <PPUB>8.55</PPUB>
298
+ <PKG_SIZE>5</PKG_SIZE>
299
+ <MEASURE>Ampulle(n)</MEASURE>
300
+ <MEASUREF>Ampulle(n)</MEASUREF>
301
+ <DOSAGE_FORM>Injektionslösung</DOSAGE_FORM>
302
+ <DOSAGE_FORMF>Solution injectable</DOSAGE_FORMF>
303
+ <SL_ENTRY>true</SL_ENTRY>
304
+ <IKSCAT>B</IKSCAT>
305
+ <DEDUCTIBLE>10</DEDUCTIBLE>
306
+ <PRODNO>2848601</PRODNO>
307
+ </ITEM>',
308
+ 'FERROUMET pice from ZurRose ' => %(<ITEM PHARMATYPE="P">
309
+ <GTIN>7680316440115</GTIN>
310
+ <PHAR>0020244</PHAR>
311
+ <SALECD>A</SALECD>
312
+ <DSCR>FERRO-GRADUMET Depottabl 30 Stk</DSCR>
313
+ <DSCRF>FERRO-GRADUMET cpr dépôt 30 pce</DSCRF>
314
+ <COMP>
315
+ <NAME>Farmaceutica Teofarma Suisse SA</NAME>
316
+ <GLN>7601001374539</GLN>
317
+ </COMP>
318
+ <PEXF>8.96</PEXF>
319
+ <PPUB>13.80</PPUB>
320
+ <PKG_SIZE>30</PKG_SIZE>
321
+ <MEASURE>Tablette(n)</MEASURE>
322
+ <MEASUREF>Tablette(n)</MEASUREF>
323
+ <DOSAGE_FORM>Tupfer</DOSAGE_FORM>
324
+ <DOSAGE_FORMF>Compresse</DOSAGE_FORMF>
325
+ <IKSCAT>C</IKSCAT>
326
+ <PRODNO>3164402</PRODNO>
327
+ </ITEM>),
328
+ 'product 3TC Filmtabl' => %(<PRODUCT>
329
+ <PRODNO>5366201</PRODNO>
330
+ <SALECD>A</SALECD>
331
+ <DSCR>3TC Filmtabl 150 mg</DSCR>
332
+ <DSCRF>3TC cpr pell 150 mg</DSCRF>
333
+ <ATC>J05AF05</ATC>
334
+ <SUBSTANCE>Lamivudinum</SUBSTANCE>
335
+ </PRODUCT>),
336
+ 'nur aus Packungen Coeur-Vaisseaux Sérocytol,' => %(<ITEM PHARMATYPE="P">
337
+ <GTIN>7680002770014</GTIN>
338
+ <PHAR>0361815</PHAR>
339
+ <SALECD>A</SALECD>
340
+ <DSCR>SEROCYTOL Herz-Gefässe Supp 3 Stk</DSCR>
341
+ <DSCRF>SEROCYTOL Coeur-Vaisseaux supp 3 pce</DSCRF>
342
+ <COMP>
343
+ <NAME>Serolab SA (succursale de Remaufens)</NAME>
344
+ <GLN>7640128710004</GLN>
345
+ </COMP>
346
+ <PKG_SIZE>3</PKG_SIZE>
347
+ <MEASURE>Suppositorien</MEASURE>
348
+ <MEASUREF>Suppositorien</MEASUREF>
349
+ <DOSAGE_FORM>suppositoire</DOSAGE_FORM>
350
+ <IKSCAT>B</IKSCAT>
351
+ <PRODNO>0027701</PRODNO>
352
+ </ITEM>),
353
+ 'HUMALOG (Richter)' => %(<ITEM PHARMATYPE="P">
354
+ <GTIN>7680532900196</GTIN>
355
+ <PHAR>1699999</PHAR>
356
+ <SALECD>A</SALECD>
357
+ <DSCR>HUMALOG Inj Lös 100 IE/ml Durchstf 10 ml</DSCR>
358
+ <DSCRF>HUMALOG sol inj 100 UI/ml flac 10 ml</DSCRF>
359
+ <COMP>
360
+ <NAME>Eli Lilly (Suisse) SA</NAME>
361
+ <GLN>7601001261853</GLN>
362
+ </COMP>
363
+ <PEXF>30.4</PEXF>
364
+ <PPUB>51.3</PPUB>
365
+ <PKG_SIZE>1</PKG_SIZE>
366
+ <MEASURE>Flasche(n)</MEASURE>
367
+ <MEASUREF>Flasche(n)</MEASUREF>
368
+ <DOSAGE_FORM>Injektionslösung</DOSAGE_FORM>
369
+ <DOSAGE_FORMF>Solution injectable</DOSAGE_FORMF>
370
+ <SL_ENTRY>true</SL_ENTRY>
371
+ <IKSCAT>B</IKSCAT>
372
+ <DEDUCTIBLE>20</DEDUCTIBLE>
373
+ <PRODNO>5329001</PRODNO>
374
+ </ITEM>)
375
+ }
376
+
377
+ tests.each do |key, expected|
378
+ it "should a valid entry for #{key}" do
379
+ check_artikelstamm_xml(key, expected)
380
+ end
381
+ end
382
+ end
383
+ end