oddb2xml 2.7.1 → 2.7.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +1 -2
  3. data/.standard.yml +2 -0
  4. data/Gemfile +3 -3
  5. data/History.txt +24 -0
  6. data/README.md +3 -3
  7. data/Rakefile +24 -23
  8. data/bin/check_artikelstamm +11 -11
  9. data/bin/compare_v5 +23 -23
  10. data/bin/oddb2xml +14 -13
  11. data/lib/oddb2xml/builder.rb +1070 -1038
  12. data/lib/oddb2xml/calc.rb +232 -233
  13. data/lib/oddb2xml/chapter_70_hack.rb +38 -32
  14. data/lib/oddb2xml/cli.rb +252 -236
  15. data/lib/oddb2xml/compare.rb +70 -59
  16. data/lib/oddb2xml/compositions_syntax.rb +451 -430
  17. data/lib/oddb2xml/compressor.rb +20 -20
  18. data/lib/oddb2xml/downloader.rb +157 -129
  19. data/lib/oddb2xml/extractor.rb +295 -295
  20. data/lib/oddb2xml/options.rb +34 -35
  21. data/lib/oddb2xml/parslet_compositions.rb +265 -269
  22. data/lib/oddb2xml/semantic_check.rb +39 -33
  23. data/lib/oddb2xml/util.rb +163 -163
  24. data/lib/oddb2xml/version.rb +1 -1
  25. data/lib/oddb2xml/xml_definitions.rb +32 -33
  26. data/lib/oddb2xml.rb +1 -1
  27. data/oddb2xml.gemspec +34 -34
  28. data/shell.nix +17 -0
  29. data/spec/artikelstamm_spec.rb +111 -110
  30. data/spec/builder_spec.rb +490 -505
  31. data/spec/calc_spec.rb +552 -593
  32. data/spec/check_artikelstamm_spec.rb +26 -26
  33. data/spec/cli_spec.rb +173 -174
  34. data/spec/compare_spec.rb +9 -11
  35. data/spec/composition_syntax_spec.rb +390 -409
  36. data/spec/compressor_spec.rb +48 -48
  37. data/spec/data/transfer.dat +1 -0
  38. data/spec/data_helper.rb +47 -49
  39. data/spec/downloader_spec.rb +251 -260
  40. data/spec/extractor_spec.rb +171 -159
  41. data/spec/fixtures/vcr_cassettes/oddb2xml.json +1 -1
  42. data/spec/galenic_spec.rb +233 -256
  43. data/spec/options_spec.rb +116 -119
  44. data/spec/parslet_spec.rb +896 -863
  45. data/spec/spec_helper.rb +153 -153
  46. data/test_options.rb +39 -42
  47. data/tools/win_fetch_cacerts.rb +2 -3
  48. metadata +42 -12
@@ -1,22 +1,22 @@
1
- # encoding: utf-8
2
- require 'xmlsimple'
1
+ require "xmlsimple"
3
2
 
4
3
  module Oddb2xml
5
4
  def self.log_timestamp(msg)
6
5
  full_msg = "#{Time.now.strftime("%H:%M:%S")}: #{msg}"
7
6
  puts full_msg
8
- STDOUT.flush
7
+ $stdout.flush
9
8
  full_msg
10
9
  end
10
+
11
11
  class StammXML
12
12
  V3_NAME_REG = /_([N,P])_/
13
13
  attr_accessor :components
14
14
  attr_reader :keys, :sub_key_names, :filename, :basename, :version, :hash
15
- def initialize(filename, components = ['ITEMS'])
15
+ def initialize(filename, components = ["ITEMS"])
16
16
  raise "File #{filename} must exist" unless File.exist?(filename)
17
17
  @filename = filename
18
18
  @basename = File.basename(filename)
19
- @version = V3_NAME_REG.match(filename) ? 3 : 5
19
+ @version = V3_NAME_REG.match(filename) ? 3 : 5
20
20
  @components = components
21
21
  if @version == 5
22
22
  @hash = load_file(@filename)
@@ -24,41 +24,47 @@ module Oddb2xml
24
24
  raise "Unsupported version #{@version}"
25
25
  end
26
26
  end
27
+
27
28
  def self.get_component_key_name(component_name)
28
- return 'LIMNAMEBAG' if /LIMITATION/i.match(component_name)
29
- return 'PRODNO' if /PRODUCT/i.match(component_name)
30
- return 'GTIN' if /ITEM/i.match(component_name)
31
- raise "Cannot determine keyname for component #{component_name}"
29
+ return "LIMNAMEBAG" if /LIMITATION/i.match?(component_name)
30
+ return "PRODNO" if /PRODUCT/i.match?(component_name)
31
+ return "GTIN" if /ITEM/i.match?(component_name)
32
+ raise "Cannot determine keyname for component #{component_name}"
32
33
  end
34
+
33
35
  def get_limitation_from_v5(item)
34
- get_item('PRODUCTS', item['PRODNO'].first.to_i)['LIMNAMEBAG'] ? ['true'] : nil
36
+ get_item("PRODUCTS", item["PRODNO"].first.to_i)["LIMNAMEBAG"] ? ["true"] : nil
35
37
  end
38
+
36
39
  def get_field_from_v5_product(item, field_name)
37
- get_item('PRODUCTS', item['PRODNO'].first.to_i)[field_name]
40
+ get_item("PRODUCTS", item["PRODNO"].first.to_i)[field_name]
38
41
  end
42
+
39
43
  def get_items(component_name)
40
44
  if @version == 3
41
- items = @hash[component_name]
45
+ @hash[component_name]
42
46
  else
43
- items = @hash[component_name].first.values.first
47
+ @hash[component_name].first.values.first
44
48
  end
45
- items
46
49
  end
50
+
47
51
  def get_item(component_name, id)
48
52
  keyname = StammXML.get_component_key_name(component_name)
49
- get_items(component_name).find{|item| item[keyname].first.to_i == id}
53
+ get_items(component_name).find { |item| item[keyname].first.to_i == id }
50
54
  end
55
+
51
56
  def load_file(name)
52
- Oddb2xml.log_timestamp "Reading #{name} #{(File.size(name)/1024/1024).to_i} MB. This may take some time"
57
+ Oddb2xml.log_timestamp "Reading #{name} #{(File.size(name) / 1024 / 1024).to_i} MB. This may take some time"
53
58
  XmlSimple.xml_in(IO.read(name))
54
59
  end
55
60
  end
61
+
56
62
  class CompareV5
57
63
  DEFAULTS = {
58
- :components => ["PRODUCTS", "LIMITATIONS", "ITEMS",],
59
- :fields_to_ignore => ['COMP', 'DOSAGE_FORMF', 'MEASUREF'],
60
- :fields_as_floats => [ 'PEXT', 'PEXF', 'PPUB' ],
61
- :min_diff_for_floats => 0.01,
64
+ components: ["PRODUCTS", "LIMITATIONS", "ITEMS"],
65
+ fields_to_ignore: ["COMP", "DOSAGE_FORMF", "MEASUREF"],
66
+ fields_as_floats: ["PEXT", "PEXF", "PPUB"],
67
+ min_diff_for_floats: 0.01
62
68
  }
63
69
  def initialize(left, right, options = DEFAULTS.clone)
64
70
  @options = options
@@ -68,37 +74,38 @@ module Oddb2xml
68
74
  @occurrences = {}
69
75
  @report = []
70
76
  end
71
- def get_keys(items, key='GTIN')
72
- items.collect{|item| item[key].first.to_i }
77
+
78
+ def get_keys(items, key = "GTIN")
79
+ items.collect { |item| item[key].first.to_i }
73
80
  end
81
+
74
82
  def get_names(items)
75
- items.collect{|item| item.keys}.flatten.uniq.sort
83
+ items.collect { |item| item.keys }.flatten.uniq.sort
76
84
  end
85
+
77
86
  def compare
78
87
  show_header("Start comparing #{@left.filename} with #{@right.filename}")
79
88
  (@left.components & @right.components).each do |name|
80
- begin
81
- puts "\n#{Time.now.strftime("%H:%M:%S")}: Comparing #{name} in #{@left.basename} with #{@right.basename}"
82
- key = StammXML.get_component_key_name(name)
83
- left_items = @left.get_items(name)
84
- next unless left_items
85
- right_items = @right.get_items(name)
86
- next unless right_items
87
- @diff_stat[name] = {}
88
- @occurrences[name] = {}
89
- @diff_stat[name][NR_COMPARED] = 0
90
- l_names = get_names(left_items)
91
- r_names = get_names(right_items)
92
- compare_names = l_names & r_names
93
- l_keys = get_keys(left_items, key)
94
- r_keys = get_keys(right_items, key)
95
- (l_keys & r_keys).each do |id|
96
- compare_details(name, compare_names, id)
97
- end
98
- key_results_details(name, compare_names, l_keys, r_keys)
99
- rescue => error
100
- puts "Execution failed with #{error}"
89
+ puts "\n#{Time.now.strftime("%H:%M:%S")}: Comparing #{name} in #{@left.basename} with #{@right.basename}"
90
+ key = StammXML.get_component_key_name(name)
91
+ left_items = @left.get_items(name)
92
+ next unless left_items
93
+ right_items = @right.get_items(name)
94
+ next unless right_items
95
+ @diff_stat[name] = {}
96
+ @occurrences[name] = {}
97
+ @diff_stat[name][NR_COMPARED] = 0
98
+ l_names = get_names(left_items)
99
+ r_names = get_names(right_items)
100
+ compare_names = l_names & r_names
101
+ l_keys = get_keys(left_items, key)
102
+ r_keys = get_keys(right_items, key)
103
+ (l_keys & r_keys).each do |id|
104
+ compare_details(name, compare_names, id)
101
105
  end
106
+ key_results_details(name, compare_names, l_keys, r_keys)
107
+ rescue => error
108
+ puts "Execution failed with #{error}"
102
109
  end
103
110
  show_header("Summary comparing #{@left.filename} with #{@right.filename}")
104
111
  puts "Ignored differences in #{@options[:fields_to_ignore]}. Signaled when differences in #{@options[:fields_as_floats]} were bigger than #{@options[:min_diff_for_floats]}"
@@ -116,28 +123,31 @@ module Oddb2xml
116
123
  puts "Execution failed with #{error}"
117
124
  raise error
118
125
  end
126
+
119
127
  private
120
- NR_COMPARED = 'NR_COMPARED'
121
- COUNT = '_count'
128
+
129
+ NR_COMPARED = "NR_COMPARED"
130
+ COUNT = "_count"
122
131
  def show_header(header)
123
132
  text = Oddb2xml.log_timestamp(header)
124
133
  pad = 5
125
134
  puts
126
- puts '-'*(text.length+2*pad)
127
- puts ''.ljust(pad) + text
128
- puts '-'*(text.length+2*pad)
135
+ puts "-" * (text.length + 2 * pad)
136
+ puts "".ljust(pad) + text
137
+ puts "-" * (text.length + 2 * pad)
129
138
  puts
130
139
  end
140
+
131
141
  def compare_details(component_name, compare_names, id)
132
142
  l_item = @left.get_item(component_name, id)
133
143
  r_item = @right.get_item(component_name, id)
134
144
  found_one = false
135
145
  length = 32
136
146
  found = false
137
- detail_name = l_item['DSCR'] ? l_item['DSCR'].first[0..length-1].rjust(length) : ''.rjust(length)
147
+ detail_name = l_item["DSCR"] ? l_item["DSCR"].first[0..length - 1].rjust(length) : "".rjust(length)
138
148
  details = "Diff in #{id.to_s.ljust(15)} #{detail_name}"
139
149
  diff_name = component_name
140
- diff_name += 'S' unless /S$/.match(diff_name)
150
+ diff_name += "S" unless /S$/.match?(diff_name)
141
151
  @diff_stat[diff_name] ||= {}
142
152
  @occurrences[diff_name] ||= {}
143
153
  @diff_stat[diff_name][NR_COMPARED] ||= 0
@@ -154,33 +164,34 @@ module Oddb2xml
154
164
  r_float = r_value ? r_value.first.to_f : 0.0
155
165
  next if (l_float - r_float).abs < @options[:min_diff_for_floats]
156
166
  end
157
- next if (r_value.is_a?(Array) && '--missing--'.eql?(r_value.first)) || (l_value.is_a?(Array) && '--missing--'.eql?(l_value.first))
158
- # TODO: get_field_from_v5_product
167
+ next if (r_value.is_a?(Array) && "--missing--".eql?(r_value.first)) || (l_value.is_a?(Array) && "--missing--".eql?(l_value.first))
168
+ # TODO: get_field_from_v5_product
159
169
  next if r_value.to_s.eql?(l_value.to_s)
160
170
  next if r_value.to_s.upcase.eql?(l_value.to_s.upcase) && @options[:case_insensitive]
161
171
  details += " #{sub_key}: '#{l_value}' != '#{r_value}'"
162
172
  found = found_one = true
163
173
  @diff_stat[diff_name][sub_key] += 1
164
174
  end
165
- puts details.gsub(/[\[\]]/,'') if found
175
+ puts details.gsub(/[\[\]]/, "") if found
166
176
  end
167
177
 
168
178
  def show_keys(keys, batch_size = 20)
169
179
  0.upto(keys.size) do |idx|
170
180
  next unless idx % batch_size == 0
171
- puts ' ' + keys[idx..(idx + batch_size-1)].join(' ')
181
+ puts " " + keys[idx..(idx + batch_size - 1)].join(" ")
172
182
  end
173
183
  end
184
+
174
185
  def key_results_details(component_name, compare_names, l_keys, r_keys)
175
- component_name += 'S' unless /S$/.match(component_name)
176
- @report << "#{component_name}: Found #{l_keys.size} items only in #{@left.basename} #{r_keys.size} items only in #{@right.basename}, compared #{@diff_stat[component_name][NR_COMPARED]} items"
186
+ component_name += "S" unless /S$/.match?(component_name)
187
+ @report << "#{component_name}: Found #{l_keys.size} items only in #{@left.basename} #{r_keys.size} items only in #{@right.basename}, compared #{@diff_stat[component_name][NR_COMPARED]} items"
177
188
  keys = r_keys - l_keys
178
- head = "#{component_name}: #{(keys).size} keys only in #{@right.basename}"
189
+ head = "#{component_name}: #{keys.size} keys only in #{@right.basename}"
179
190
  puts "#{head}: Keys were #{keys.size}"
180
191
  show_keys(keys)
181
192
  @report << head
182
193
  keys = l_keys - r_keys
183
- head = "#{component_name}: #{(keys).size} keys only in #{@left.basename}"
194
+ head = "#{component_name}: #{keys.size} keys only in #{@left.basename}"
184
195
  puts "#{head}: Keys were #{keys.size}"
185
196
  show_keys(keys)
186
197
  @report << head