oddb2xml 2.7.1 → 2.7.5
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/.github/workflows/ruby.yml +1 -2
- data/.standard.yml +2 -0
- data/Gemfile +3 -3
- data/History.txt +24 -0
- data/README.md +3 -3
- data/Rakefile +24 -23
- data/bin/check_artikelstamm +11 -11
- data/bin/compare_v5 +23 -23
- data/bin/oddb2xml +14 -13
- data/lib/oddb2xml/builder.rb +1070 -1038
- data/lib/oddb2xml/calc.rb +232 -233
- data/lib/oddb2xml/chapter_70_hack.rb +38 -32
- data/lib/oddb2xml/cli.rb +252 -236
- data/lib/oddb2xml/compare.rb +70 -59
- data/lib/oddb2xml/compositions_syntax.rb +451 -430
- data/lib/oddb2xml/compressor.rb +20 -20
- data/lib/oddb2xml/downloader.rb +157 -129
- data/lib/oddb2xml/extractor.rb +295 -295
- data/lib/oddb2xml/options.rb +34 -35
- data/lib/oddb2xml/parslet_compositions.rb +265 -269
- data/lib/oddb2xml/semantic_check.rb +39 -33
- data/lib/oddb2xml/util.rb +163 -163
- data/lib/oddb2xml/version.rb +1 -1
- data/lib/oddb2xml/xml_definitions.rb +32 -33
- data/lib/oddb2xml.rb +1 -1
- data/oddb2xml.gemspec +34 -34
- data/shell.nix +17 -0
- data/spec/artikelstamm_spec.rb +111 -110
- data/spec/builder_spec.rb +490 -505
- data/spec/calc_spec.rb +552 -593
- data/spec/check_artikelstamm_spec.rb +26 -26
- data/spec/cli_spec.rb +173 -174
- data/spec/compare_spec.rb +9 -11
- data/spec/composition_syntax_spec.rb +390 -409
- data/spec/compressor_spec.rb +48 -48
- data/spec/data/transfer.dat +1 -0
- data/spec/data_helper.rb +47 -49
- data/spec/downloader_spec.rb +251 -260
- data/spec/extractor_spec.rb +171 -159
- data/spec/fixtures/vcr_cassettes/oddb2xml.json +1 -1
- data/spec/galenic_spec.rb +233 -256
- data/spec/options_spec.rb +116 -119
- data/spec/parslet_spec.rb +896 -863
- data/spec/spec_helper.rb +153 -153
- data/test_options.rb +39 -42
- data/tools/win_fetch_cacerts.rb +2 -3
- metadata +42 -12
data/lib/oddb2xml/compare.rb
CHANGED
@@ -1,22 +1,22 @@
|
|
1
|
-
|
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
|
-
|
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 =
|
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 =
|
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
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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(
|
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(
|
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
|
-
|
45
|
+
@hash[component_name]
|
42
46
|
else
|
43
|
-
|
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
|
-
:
|
59
|
-
:
|
60
|
-
:
|
61
|
-
:
|
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
|
-
|
72
|
-
|
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
|
-
|
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
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
(
|
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
|
-
|
121
|
-
|
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
|
127
|
-
puts
|
128
|
-
puts
|
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[
|
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 +=
|
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) &&
|
158
|
-
|
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(/[\[\]]/,
|
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
|
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 +=
|
176
|
-
@report <<
|
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}: #{
|
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}: #{
|
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
|