ref: master
plugins/suppliers/lib/suppliers_plugin/import.rb
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 139 |
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 product.distribute_to_consumer consumer, distributed_attrs end end end end |