import.rb
4.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
require 'csv'
require 'charlock_holmes'
class SuppliersPlugin::Import
def self.product_columns header
keys = I18n.t'suppliers_plugin.lib.import.keys'
columns = []
header.each do |name|
c = nil; keys.each do |key, regex|
if /#{regex}/i =~ name
c = key
break
end
end
raise "duplicate column match '#{name}' already added as :#{c}" if c and c.in? columns
columns << c
end
# check required fields
return if ([:supplier_name, :product_name, :price] - columns).present?
columns
end
def self.products consumer, csv
default_product_category = consumer.environment.product_categories.find_by name: 'Produtos'
detection = CharlockHolmes::EncodingDetector.detect csv
csv = CharlockHolmes::Converter.convert csv, detection[:encoding], 'UTF-8'
data = {}
rows = []
columns = []
quote_chars = %w[" | ~ ^ & *]
[",", ";", "\t"].each do |sep|
begin
rows = CSV.parse csv, quote_char: quote_chars.shift, col_sep: sep
columns = self.product_columns rows.first
rescue
if quote_chars.empty? then raise else retry end
ensure
break if columns.present?
end
end
rows.shift
raise "can't find required columns" if columns.blank?
# extract and treat attributes
rows.each do |row|
attrs = {}; row.each.with_index do |value, i|
next unless c = columns[i]
value = value.to_s.squish
attrs[c] = if value.present? then value else nil end
end
distributed = attrs[:distributed] = {}
distributed[:external_id] = attrs.delete :external_id
if supplier_price = attrs.delete(:supplier_price)
distributed[:price] = attrs[:price]
attrs[:price] = supplier_price
end
attrs[:name] = attrs.delete :product_name
if product_category = attrs[:product_category]
attrs[:product_category] = ProductCategory.find_by_solr(product_category, query_fields: ['name']).first
end
attrs[:product_category] ||= default_product_category
if qualifiers = attrs[:qualifiers]
qualifiers = JSON.parse qualifiers
qualifiers.map! do |q|
next if q.blank?
Qualifier.find_by_solr(q, query_fields: ['name']).first
end.compact!
attrs[:qualifiers] = qualifiers
end
attrs[:unit] = consumer.environment.units.where(singular: attrs[:unit]).first || SuppliersPlugin::BaseProduct.default_unit
# FIXME
attrs.delete :stock
if composition = attrs.delete(:composition)
composition = JSON.parse composition rescue nil
distributed[:price_details] = composition.map do |name, price|
production_cost = consumer.environment.production_costs.where(name: name).first
production_cost ||= consumer.production_costs.where(name: name).first
production_cost ||= consumer.production_costs.create! name: name, owner: profile
PriceDetail.new production_cost: production_cost, price: price
end
end
# treat URLs
profile = nil
if product_url = attrs.delete(:product_url) and /manage_products\/show\/(\d+)/ =~ product_url
product = Product.where(id: $1).first
next if product.blank?
attrs[:record] = product
profile = product.profile
end
if supplier_url = attrs.delete(:supplier_url)
uri = URI.parse supplier_url
profile = Domain.where(name: uri.host).first.profile rescue nil
profile ||= Profile.where(identifier: Rails.application.routes.recognize_path(uri.path)[:profile]).first
next if profile.blank?
end
supplier_name = attrs.delete :supplier_name
supplier = profile || supplier_name
data[supplier] ||= []
data[supplier] << attrs
end
data.each do |supplier, products|
if supplier.is_a? Profile
supplier = consumer.add_supplier supplier, distribute_products_on_create: false
else
supplier_name = supplier
supplier = consumer.suppliers.where(name: supplier_name).first
supplier ||= SuppliersPlugin::Supplier.create_dummy consumer: consumer, name: supplier_name
end
products.each do |attrs|
distributed_attrs = attrs.delete :distributed
product = attrs.delete :record
product ||= supplier.profile.products.where(name: attrs[:name]).first
product ||= supplier.profile.products.build attrs
# let update happen only on dummy suppliers
if product.persisted? and supplier.dummy?
product.update! attrs
elsif product.new_record?
# create products as not available
attrs[:available] = false if not supplier.dummy?
product.update! attrs
end
distributed_product = product.distribute_to_consumer consumer, distributed_attrs
end
end
end
end