circuitdata 0.3.5 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +11 -0
- data/Rakefile +8 -0
- data/lib/circuitdata.rb +76 -388
- data/lib/circuitdata/bk_comparer.rb +106 -0
- data/lib/circuitdata/compatibility_checker.rb +119 -0
- data/lib/circuitdata/file_comparer.rb +243 -0
- data/lib/circuitdata/schema_files/v1/ottp_circuitdata_schema.json +5587 -0
- data/lib/circuitdata/schema_files/v1/ottp_circuitdata_schema_definitions.json +1139 -0
- data/lib/circuitdata/schema_files/v1/ottp_circuitdata_skeleton_schema.json +55 -0
- data/lib/circuitdata/schema_files/v1/ottp_schema_definitions.json +102 -0
- data/lib/circuitdata/version.rb +1 -1
- metadata +10 -3
- data/lib/tasks/circuitdata_tasks.rake +0 -4
@@ -0,0 +1,106 @@
|
|
1
|
+
def self.compare_files(filehash, validate_origins=false)
|
2
|
+
# Prepare the return
|
3
|
+
ra = {
|
4
|
+
error: false,
|
5
|
+
errormessage: "",
|
6
|
+
summary: {},
|
7
|
+
conflicts: {},
|
8
|
+
product: nil,
|
9
|
+
columns: [],
|
10
|
+
mastercolumn: nil,
|
11
|
+
rows: []
|
12
|
+
}
|
13
|
+
|
14
|
+
#parsedfiles
|
15
|
+
unless filehash.is_a? Hash
|
16
|
+
ra[:error] = true
|
17
|
+
ra[:errormessage] = "You have to feed this function with a hash of names and hashes"
|
18
|
+
return ra
|
19
|
+
end
|
20
|
+
|
21
|
+
# extend the hash that is received
|
22
|
+
nh = {}
|
23
|
+
filehash.each do |fhk, fhv|
|
24
|
+
nh[fhk] = {
|
25
|
+
orig: fhv,
|
26
|
+
parsed: nil,
|
27
|
+
content: nil,
|
28
|
+
has: {}
|
29
|
+
}
|
30
|
+
# READ THE CONTENT
|
31
|
+
ra[:error], ra[:errormessage], nh[fhk][:content] = self.read_json(fhv)
|
32
|
+
ra[:summary] = {} if ra[:error]
|
33
|
+
ra[:conflicts] = {} if ra[:error]
|
34
|
+
return ra if ra[:error]
|
35
|
+
# VALIDATE THE FILES
|
36
|
+
if validate_origins
|
37
|
+
ra[:error], ra[:errormessage], validationserrors = self.validate(nh[fhk][:content])
|
38
|
+
ra[:summary] = {} if ra[:error]
|
39
|
+
ra[:conflicts] = {} if ra[:error]
|
40
|
+
return ra if ra[:error]
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
# SET THE PRODUCT NAME
|
45
|
+
nh[fhk][:has][:products], nh[fhk][:has][:stackup], nh[fhk][:has][:profile_default], nh[fhk][:has][:profile_restricted], nh[fhk][:has][:profile_enforced], nh[fhk][:has][:capabilities], nh[fhk][:has][:product] = self.content(nh[fhk][:content])
|
46
|
+
unless nh[fhk][:has][:product].nil?
|
47
|
+
#self.iterate(nh[fhk][:content])
|
48
|
+
|
49
|
+
#root_node = Tree::TreeNode.new("ROOT", "Root Content")
|
50
|
+
#root_node.print_tree
|
51
|
+
|
52
|
+
ra[:product] = nh[fhk][:has][:product] if ra[:product].nil?
|
53
|
+
if nh[fhk][:has][:product] != ra[:product]
|
54
|
+
ra[:error] = true
|
55
|
+
ra[:errormessage] = "Your files contains several different product names"
|
56
|
+
ra[:summary] = {}
|
57
|
+
ra[:conflicts] = {}
|
58
|
+
return ra
|
59
|
+
end
|
60
|
+
ra[:mastercolumn] = fhk if ra[:mastercolumn].nil?
|
61
|
+
end
|
62
|
+
|
63
|
+
# THIS IS WHERE I NEED THINGS TO HAPPEN
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
# RETURN IF THERE IS NO PRODUCT
|
68
|
+
if ra[:mastercolumn].nil?
|
69
|
+
ra[:error] = true
|
70
|
+
ra[:errormessage] = "none of the files contains a product"
|
71
|
+
ra[:summary] = {}
|
72
|
+
ra[:conflicts] = {}
|
73
|
+
return ra
|
74
|
+
end
|
75
|
+
|
76
|
+
{
|
77
|
+
current_level: 0,
|
78
|
+
current_key: nil,
|
79
|
+
|
80
|
+
}
|
81
|
+
# Populate the master column
|
82
|
+
#self.iterate(filehash[ra[:mastercolumn].to_sym])
|
83
|
+
#ra[:summary] = productjson[:open_trade_transfer_package][:products][ra[:product]][:printed_circuits_fabrication_data]
|
84
|
+
|
85
|
+
#test = {}
|
86
|
+
#self.save_pair(productjson[:open_trade_transfer_package][:products][ra[:product]][:printed_circuits_fabrication_data], test)
|
87
|
+
#puts test
|
88
|
+
# Populate the product rows
|
89
|
+
#productjson[:open_trade_transfer_package]["products"][ra[:product]]["printed_circuits_fabrication_data"].each do |key, value|
|
90
|
+
# if value.is_a? Hash
|
91
|
+
# value.each do |subkey, subvalue|
|
92
|
+
# ra[:rows][]
|
93
|
+
#end
|
94
|
+
|
95
|
+
# Do comparisons
|
96
|
+
#number = 1
|
97
|
+
#filehash.each do |key, value|
|
98
|
+
# unless key.to_s == productfile
|
99
|
+
# #puts self.compatibility_checker( productjson, value, false )
|
100
|
+
# number += 1
|
101
|
+
# end
|
102
|
+
# end
|
103
|
+
#puts JSON.pretty_generate(ra)
|
104
|
+
#puts JSON.pretty_generate(nh)
|
105
|
+
return ra
|
106
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
class Circuitdata::CompatibilityChecker
|
2
|
+
def initialize(product_file, check_file, validate_origins)
|
3
|
+
require 'json'
|
4
|
+
require 'json-schema'
|
5
|
+
|
6
|
+
@product_file = product_file
|
7
|
+
@check_file = check_file
|
8
|
+
@validate_origins = validate_origins
|
9
|
+
# Final hash
|
10
|
+
@fh = {error: false, message: nil, errors: {validation: {}, restricted: {}, enforced: {}, capabilities: {}}}
|
11
|
+
end
|
12
|
+
|
13
|
+
def start_check
|
14
|
+
# Initialize & validate
|
15
|
+
@fh[:error], @fh[:message], product_data = Circuitdata.read_json(@product_file)
|
16
|
+
return @fh if @fh[:error]
|
17
|
+
@fh[:error], @fh[:message], @fh[:errors][:validation] = Circuitdata.validate(product_data)
|
18
|
+
return @fh if @fh[:error]
|
19
|
+
if @check_file.present?
|
20
|
+
@fh[:error], @fh[:message], check_data = Circuitdata.read_json(@check_file)
|
21
|
+
return @fh if @fh[:error]
|
22
|
+
@fh[:error], @fh[:message], @fh[:errors][:validation] = Circuitdata.validate(check_data)
|
23
|
+
return @fh if @fh[:error]
|
24
|
+
f2_types = Circuitdata.get_data_summary(check_data)[1]
|
25
|
+
# read the schema
|
26
|
+
schema_path = File.join(File.dirname(__FILE__), 'schema_files/v1/ottp_circuitdata_skeleton_schema.json')
|
27
|
+
restricted_schema = enforced_schema = capability_schema = Circuitdata.read_json(schema_path)[2]
|
28
|
+
# Compare the content
|
29
|
+
perform_comparison(product_data, check_data, restricted_schema, 'restricted') if f2_types.include? 'profile_restricted'
|
30
|
+
perform_comparison(product_data, check_data, enforced_schema, 'enforced') if f2_types.include? 'profile_enforced'
|
31
|
+
perform_comparison(product_data, check_data, capability_schema, 'capabilities') if f2_types.include? 'capabilities'
|
32
|
+
end
|
33
|
+
|
34
|
+
@fh
|
35
|
+
end
|
36
|
+
|
37
|
+
def perform_comparison(product_data, check_data, schema, type)
|
38
|
+
case type
|
39
|
+
when 'restricted'
|
40
|
+
check_hash = check_data.dig(:open_trade_transfer_package, :profiles, :restricted, :printed_circuits_fabrication_data)
|
41
|
+
when 'enforced'
|
42
|
+
check_hash = check_data.dig(:open_trade_transfer_package, :profiles, :enforced, :printed_circuits_fabrication_data)
|
43
|
+
when 'capabilities'
|
44
|
+
check_hash = check_data.dig(:open_trade_transfer_package, :capabilities, :printed_circuits_fabrication_data)
|
45
|
+
else
|
46
|
+
check_hash = {}
|
47
|
+
end
|
48
|
+
# binding.pry
|
49
|
+
|
50
|
+
check_hash.each do |k, v|
|
51
|
+
v.each do |kl1, vl1| # level 1
|
52
|
+
common_hash = schema.dig(:properties, :open_trade_transfer_package, :properties, :products, :patternProperties, :'^(?!generic$).*', :properties, :printed_circuits_fabrication_data, :properties)
|
53
|
+
# binding.pry
|
54
|
+
common_hash[k.to_sym]||= {:type => 'object', :properties => {}}
|
55
|
+
common_hash[:stackup][:properties][:specified][:properties][k.to_sym] ||= {:type => 'object', :properties => {}}
|
56
|
+
|
57
|
+
case vl1.class.name
|
58
|
+
when 'String'
|
59
|
+
if vl1.match("^(\\d*|\\d*.\\d*)\\.\\.\\.(\\d*|\\d*.\\d*)$") #This is a value range
|
60
|
+
from, too = vl1.match("^(\\d*|\\d*.\\d*)\\.\\.\\.(\\d*|\\d*.\\d*)$").captures
|
61
|
+
case type
|
62
|
+
when 'restricted'
|
63
|
+
new_hash = {:not => {:allOf => [{:minimum => from.to_f},{:maximum => too.to_f}]}}
|
64
|
+
else
|
65
|
+
new_hash = eval("{:minimum => #{from}, :maximum => #{too}}")
|
66
|
+
end
|
67
|
+
else # This is a normal string - check for commas
|
68
|
+
enum = []
|
69
|
+
vl1.split(',').each {|enumvalue| enum << enumvalue.strip}
|
70
|
+
case type
|
71
|
+
when 'restricted'
|
72
|
+
new_hash = {:not => {:anyOf => [{ :enum => ''}]}}
|
73
|
+
new_hash[:not][:anyOf][0][:enum] = enum
|
74
|
+
else
|
75
|
+
new_hash = eval("{:enum => #{enum}}")
|
76
|
+
end
|
77
|
+
end
|
78
|
+
when 'Numeric' # This is a normal string
|
79
|
+
case type
|
80
|
+
when 'restricted'
|
81
|
+
new_hash = {:not => {:allOf => [{:minimum => vl1.to_f},{:maximum => vl1.to_f}]}}
|
82
|
+
else
|
83
|
+
new_hash = eval("{:enum => [#{vl1.to_s}]}")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
common_hash[k.to_sym][:properties][kl1.to_sym] = new_hash
|
87
|
+
common_hash[:stackup][:properties][:specified][:properties][k.to_sym][:properties][kl1.to_sym] = new_hash
|
88
|
+
end if v.is_a? Hash
|
89
|
+
end
|
90
|
+
|
91
|
+
# perform validations
|
92
|
+
begin
|
93
|
+
validation_errors = JSON::Validator.fully_validate(schema.to_json, product_data, :errors_as_objects => true)
|
94
|
+
|
95
|
+
if validation_errors.any?
|
96
|
+
@fh[:error] = true
|
97
|
+
@fh[:message] = 'The product to check did not meet the requirements'
|
98
|
+
|
99
|
+
# format the errors well here
|
100
|
+
|
101
|
+
validation_errors.each do |error|
|
102
|
+
error_array = []
|
103
|
+
begin
|
104
|
+
error_array << error[:message].match("^(The\\sproperty\\s\\'[\\s\\S]*\\'\\s)([\\s\\S]*)(\\sin\\sschema[\\s\\S]*)$").captures[1]
|
105
|
+
rescue
|
106
|
+
error_array << error[:message]
|
107
|
+
end
|
108
|
+
@fh[:errors][type.to_sym][error[:fragment]] = error_array
|
109
|
+
end
|
110
|
+
end
|
111
|
+
rescue JSON::Schema::ReadFailed
|
112
|
+
@fh[:error] = true
|
113
|
+
@fh[:message] = "Could not read the submitted `#{type}` schema" # enforced_schema
|
114
|
+
rescue JSON::Schema::SchemaError
|
115
|
+
@fh[:error] = true
|
116
|
+
@fh[:message] = "Something was wrong with the submitted `#{type}` schema" # enforced_schema
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,243 @@
|
|
1
|
+
class Circuitdata::FileComparer
|
2
|
+
def initialize(file_hash, validate_origins)
|
3
|
+
@file_hash = file_hash
|
4
|
+
@validate_origins = validate_origins
|
5
|
+
@rows = {}
|
6
|
+
@nh = {} # a new_hash to combine all the data
|
7
|
+
@columns = []
|
8
|
+
@default_column = nil
|
9
|
+
@master_column = nil
|
10
|
+
# Final hash
|
11
|
+
@fh = {error: false, message: nil, conflict: false, product_name: nil, columns: nil, master_column: nil, rows: nil}
|
12
|
+
end
|
13
|
+
|
14
|
+
def compare
|
15
|
+
# Initial check
|
16
|
+
unless @file_hash.is_a? Hash
|
17
|
+
@fh[:error] = true
|
18
|
+
@fh[:message] = 'You have to feed this function with a hash of names and hashes'
|
19
|
+
return @fh
|
20
|
+
end
|
21
|
+
|
22
|
+
# Process the hashes
|
23
|
+
products_array = []
|
24
|
+
@file_hash.each do |k, v|
|
25
|
+
# read content
|
26
|
+
@fh[:error], @fh[:message], file_content = Circuitdata.read_json(v)
|
27
|
+
return @fh if @fh[:error]
|
28
|
+
products, types = Circuitdata.get_data_summary(file_content)
|
29
|
+
products_array.push(*products) # add products to tracking array
|
30
|
+
# populate the new_hash to be used later
|
31
|
+
@nh[k] = {types: types, products: products, data: file_content}
|
32
|
+
end
|
33
|
+
|
34
|
+
# check if the files content meet the requirements
|
35
|
+
if valid_product?(products_array)
|
36
|
+
@fh[:product_name] = products_array.first.to_s
|
37
|
+
@columns = @nh.keys
|
38
|
+
# get all data with products in it
|
39
|
+
product_hashes = @nh.select{|k, v| v[:products].any?}
|
40
|
+
product_columns = product_hashes.keys
|
41
|
+
|
42
|
+
# Add conflicts into the new_hash
|
43
|
+
product_hashes.each do |column_k, column_v|
|
44
|
+
master_json = column_v.dig(:data)
|
45
|
+
@nh.each do |file_k, file_v|
|
46
|
+
products, data = file_v[:products], file_v[:data]
|
47
|
+
check_results = Circuitdata.compatibility_checker(master_json, data, false)
|
48
|
+
# format the conflicts correctly here
|
49
|
+
file_v[:conflicts] ||= {}
|
50
|
+
file_v[:conflicts][column_k] = get_validation_summary(check_results, file_k)
|
51
|
+
# initialize the rows format - for all the product items
|
52
|
+
product_hash = data.dig(:open_trade_transfer_package, :products, @fh[:product_name].to_sym, :printed_circuits_fabrication_data)
|
53
|
+
if products.any?
|
54
|
+
init_row_format(product_hash)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
# Initialize the rows format - for all default profile items
|
58
|
+
@default_column, file_v = @nh.select{|k, v| v[:types].include?("profile_defaults")}.first # this should only be a single file
|
59
|
+
data = file_v[:data]
|
60
|
+
product_hash = data.dig(:open_trade_transfer_package, :profiles, :defaults, :printed_circuits_fabrication_data)
|
61
|
+
init_row_format(product_hash)
|
62
|
+
end
|
63
|
+
|
64
|
+
# populate the @rows
|
65
|
+
product_columns.each do |column|
|
66
|
+
@master_column = column
|
67
|
+
process_row_hash('populate')
|
68
|
+
end
|
69
|
+
# populate the @rows summary
|
70
|
+
product_columns.each do |column|
|
71
|
+
@master_column = column
|
72
|
+
process_row_hash('get_summary')
|
73
|
+
end
|
74
|
+
process_row_hash('populate_defaults')
|
75
|
+
end
|
76
|
+
|
77
|
+
@fh[:columns] = @columns.unshift(:summary)
|
78
|
+
@fh[:rows] = @rows
|
79
|
+
@fh
|
80
|
+
end
|
81
|
+
|
82
|
+
def init_row_format(product_hash)
|
83
|
+
product_hash.each do |k, v|
|
84
|
+
if v.is_a?(Hash)
|
85
|
+
@rows[k] ||= {}
|
86
|
+
v.each do |kl1, vl1|
|
87
|
+
@rows[k][kl1] ||= get_l1_hash(@columns)
|
88
|
+
end
|
89
|
+
else
|
90
|
+
@rows[k] ||= []
|
91
|
+
# if array functionality eg Holes
|
92
|
+
end if ['Hash', 'Array'].include?(v.class.name)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def process_row_hash(action)
|
97
|
+
@rows.each do |k, v| # product elements level
|
98
|
+
if v.is_a?(Hash)
|
99
|
+
v.each do |kl1, vl1| # specification level
|
100
|
+
value, conflict, conflicts_with, conflict_message = [], false, [], []
|
101
|
+
vl1.each do |kl2, vl2| # the specification column level - call the function from here
|
102
|
+
conflicts = @nh.dig(kl2, :conflicts, @master_column)
|
103
|
+
case action
|
104
|
+
when 'populate'
|
105
|
+
check = conflicts.any? && conflicts.dig(:rows, k, kl1).present?
|
106
|
+
vl2[:value] = @nh.dig(kl2, :data, :open_trade_transfer_package, :products, @fh[:product_name].to_sym, :printed_circuits_fabrication_data, k, kl1)
|
107
|
+
vl2[:conflict] = check unless vl2[:conflict] # update only when the status is false
|
108
|
+
vl2[:conflicts_with] = check ? vl2[:conflicts_with] << @master_column : []
|
109
|
+
vl2[:conflict_message] = check ? vl2[:conflict_message] + conflicts&.dig(:rows, k, kl1) : []
|
110
|
+
|
111
|
+
# update master_column conflicts with
|
112
|
+
if check
|
113
|
+
master_row = @rows.dig(k, kl1, @master_column)
|
114
|
+
master_row[:conflicts_with] = master_row[:conflicts_with] + conflicts.dig(:master_conflicts)
|
115
|
+
master_row[:conflict] = true
|
116
|
+
master_row[:conflict_message] = (master_row[:conflict_message] + vl2[:conflict_message]).uniq
|
117
|
+
end
|
118
|
+
when 'get_summary'
|
119
|
+
# get the summary items
|
120
|
+
if kl2 != :summary
|
121
|
+
items_v = vl2[:value]
|
122
|
+
master_value = vl1.dig(@master_column, :value)
|
123
|
+
# dont test if the @master_column value is also nil
|
124
|
+
if value.empty? || !value.include?(items_v)
|
125
|
+
value << items_v
|
126
|
+
conflicts_with << kl2
|
127
|
+
# jump the default column
|
128
|
+
if kl2 != @master_column # Add errors to the specific rows items
|
129
|
+
# get the item type
|
130
|
+
col_type = get_column_type(@nh.dig(kl2, :types))
|
131
|
+
vl2[:conflict] = true
|
132
|
+
vl2[:conflicts_with] = (vl2[:conflicts_with] << @master_column).uniq
|
133
|
+
vl2[:conflict_message] = (vl2[:conflict_message] << customize_conflict_message(col_type, kl2, @master_column)).uniq
|
134
|
+
# update the master row
|
135
|
+
master_row = @rows.dig(k, kl1, @master_column)
|
136
|
+
master_row[:conflicts_with] = master_row[:conflicts_with] << kl2
|
137
|
+
master_row[:conflict] = true
|
138
|
+
# get a customized error message here
|
139
|
+
master_row[:conflict_message] = (master_row[:conflict_message] << customize_conflict_message(col_type, @master_column, kl2)).uniq
|
140
|
+
end
|
141
|
+
end unless items_v.nil? || master_value.nil?
|
142
|
+
conflict = true if vl2[:conflict]
|
143
|
+
conflicts_with = conflicts_with + vl2[:conflicts_with]
|
144
|
+
conflict_message = conflict_message + vl2[:conflict_message]
|
145
|
+
end
|
146
|
+
when 'populate_defaults'
|
147
|
+
if kl2 == @default_column
|
148
|
+
vl2[:value] = @nh.dig(kl2, :data, :open_trade_transfer_package, :profiles, :defaults, :printed_circuits_fabrication_data, k, kl1)
|
149
|
+
vl2[:conflict] = false
|
150
|
+
vl2[:conflicts_with] = []
|
151
|
+
vl2[:conflict_message] = []
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
case action
|
156
|
+
when 'get_summary'
|
157
|
+
if value.count > 1
|
158
|
+
conflict = true
|
159
|
+
else
|
160
|
+
value = value.first
|
161
|
+
end
|
162
|
+
vl1[:summary] = {value: value, conflict: conflict, conflicts_with: conflicts_with.uniq, conflict_message: conflict_message.uniq}
|
163
|
+
when 'populate_defaults'
|
164
|
+
# if all the values are blank, use the default value
|
165
|
+
vl1[:summary][:value] ||= vl1.dig(@default_column, :value)
|
166
|
+
end
|
167
|
+
if action == 'get_summary'
|
168
|
+
end
|
169
|
+
@fh[:conflict] = true if conflict
|
170
|
+
end
|
171
|
+
else
|
172
|
+
# if array functionality eg Holes
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def customize_conflict_message(type, col, conflicting_col)
|
178
|
+
case type
|
179
|
+
when :product
|
180
|
+
"#{col.to_s} value conflicts with value from #{conflicting_col.to_s}"
|
181
|
+
when :restricted
|
182
|
+
"#{col.to_s} value is restricted in #{conflicting_col.to_s}"
|
183
|
+
when :enforced
|
184
|
+
"#{col.to_s} value conflicts with the enforced value from #{conflicting_col.to_s}"
|
185
|
+
when :capability
|
186
|
+
"#{col.to_s} value is outside the capabilities of #{conflicting_col.to_s}"
|
187
|
+
else
|
188
|
+
"There were some value conflicts"
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def get_column_type(types)
|
193
|
+
types ||= []
|
194
|
+
if types.include? "product"
|
195
|
+
:product
|
196
|
+
elsif types.include? "profile_restricted"
|
197
|
+
:restricted
|
198
|
+
elsif types.include? "profile_enforced"
|
199
|
+
:enforced
|
200
|
+
elsif types.include? "capabilities"
|
201
|
+
:capability
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def get_validation_summary(validation, column)
|
206
|
+
summary = {}
|
207
|
+
if validation[:error]
|
208
|
+
summary[:master_conflicts] ||= []
|
209
|
+
summary[:master_conflicts] << column
|
210
|
+
summary[:conflicts], summary[:rows] = true, {}
|
211
|
+
validation[:errors].each do |type, errors| # validation, restricted, enforced, capabilities
|
212
|
+
errors.each do |k, v|
|
213
|
+
folders_stack = k.split('/')
|
214
|
+
folder, spec = folders_stack[5], folders_stack[6]
|
215
|
+
summary[:rows][folder.to_sym] ||= {}
|
216
|
+
spec_message = summary[:rows][folder.to_sym][spec.to_sym] || []
|
217
|
+
summary[:rows][folder.to_sym][spec.to_sym] = spec_message+v
|
218
|
+
end if errors.any?
|
219
|
+
end
|
220
|
+
end
|
221
|
+
summary
|
222
|
+
end
|
223
|
+
|
224
|
+
def get_l1_hash(columns)
|
225
|
+
l1_hash = {}
|
226
|
+
columns.each{|c| l1_hash[c]={} }
|
227
|
+
l1_hash
|
228
|
+
end
|
229
|
+
|
230
|
+
def valid_product?(products_array)
|
231
|
+
if products_array.uniq.count > 1
|
232
|
+
@fh[:error] = true
|
233
|
+
@fh[:message] = 'Your files contains several different product names'
|
234
|
+
return false # validation fails because of different product names
|
235
|
+
end
|
236
|
+
if products_array.empty?
|
237
|
+
@fh[:error] = true
|
238
|
+
@fh[:message] = 'None of the files contains a product'
|
239
|
+
return false # c=validation fails because there are no products
|
240
|
+
end
|
241
|
+
true
|
242
|
+
end
|
243
|
+
end
|