oddb2xml 2.5.0 → 2.5.1

Sign up to get free protection for your applications and to get access to all the features.
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