From 3a25a5f61ea442b23f0186037590540a32e562d5 Mon Sep 17 00:00:00 2001 From: viehlieb Date: Mon, 20 Feb 2023 18:22:32 +0100 Subject: [PATCH] fix rubocop --- Gemfile | 4 +- foodsoft_article_import.gemspec | 2 + lib/foodsoft_article_import.rb | 24 +-- lib/foodsoft_article_import/bioromeo.rb | 142 +++++++++--------- lib/foodsoft_article_import/bnn.rb | 81 +++++----- lib/foodsoft_article_import/foodsoft.rb | 93 ++++++------ lib/foodsoft_article_import/odin.rb | 86 +++++------ lib/foodsoft_article_import/utf8_encoder.rb | 2 + lib/foodsoft_article_import/version.rb | 4 +- .../foodsoft_article_import_bioromeo_spec.rb | 17 ++- .../bnn/foodsoft_article_import_bnn_spec.rb | 51 ++++--- .../foodsoft_article_import_foodsoft_spec.rb | 55 ++++--- .../odin/foodsoft_article_import_odin_spec.rb | 61 +++++--- spec/spec_helper.rb | 102 ++++++------- 14 files changed, 381 insertions(+), 343 deletions(-) diff --git a/Gemfile b/Gemfile index ab62740..38c6645 100644 --- a/Gemfile +++ b/Gemfile @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # foodsoft_article_import/Gemfile source 'http://rubygems.org' -gemspec \ No newline at end of file +gemspec diff --git a/foodsoft_article_import.gemspec b/foodsoft_article_import.gemspec index b3a02f9..853892d 100644 --- a/foodsoft_article_import.gemspec +++ b/foodsoft_article_import.gemspec @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require File.expand_path('lib/foodsoft_article_import/version', __dir__) Gem::Specification.new do |spec| spec.name = 'foodsoft_article_import' diff --git a/lib/foodsoft_article_import.rb b/lib/foodsoft_article_import.rb index a2fa255..289ecb7 100644 --- a/lib/foodsoft_article_import.rb +++ b/lib/foodsoft_article_import.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'digest/sha1' require 'tempfile' require 'csv' @@ -9,9 +11,8 @@ require_relative 'foodsoft_article_import/utf8_encoder' require_relative 'foodsoft_article_import/odin' require_relative 'foodsoft_article_import/foodsoft' module FoodsoftArticleImport + class ConversionFailedException < StandardError; end - class ConversionFailedException < Exception; end - # return list of known file formats # each file_format module has # #name return a human-readable file format name @@ -25,10 +26,10 @@ module FoodsoftArticleImport 'foodsoft' => FoodsoftArticleImport::Foodsoft, 'dnb_xml' => FoodsoftArticleImport::Odin, 'odin' => FoodsoftArticleImport::Odin, - 'bioromeo' => FoodsoftArticleImport::Bioromeo, + 'bioromeo' => FoodsoftArticleImport::Bioromeo }.freeze end - + # Parse file by type (one of {.file_formats}) # # @param file [File, Tempfile] @@ -47,18 +48,17 @@ module FoodsoftArticleImport data end end - - + # Helper method to generate an article number for suppliers that do not have one def self.generate_number(article) # something unique, but not too unique s = "#{article[:name]}-#{article[:unit_quantity]}x#{article[:unit]}" - s = s.downcase.gsub(/[^a-z0-9.]/,'') + s = s.downcase.gsub(/[^a-z0-9.]/, '') # prefix abbreviated sha1-hash with colon to indicate that it's a generated number - article[:order_number] = ':' + Digest::SHA1.hexdigest(s)[-7..-1] + article[:order_number] = ":#{Digest::SHA1.hexdigest(s)[-7..]}" article end - + # Helper method for opening a spreadsheet file # # @param file [File] file to open @@ -67,15 +67,15 @@ module FoodsoftArticleImport # @param col_sep [String, NilClass] optional column separator # @return [Roo::Spreadsheet] def self.open_spreadsheet(file, filename: nil, encoding: nil, col_sep: nil, liberal_parsing: nil) - opts = {csv_options: {}} + opts = { csv_options: {} } opts[:csv_options][:encoding] = encoding if encoding opts[:csv_options][:col_sep] = col_sep if col_sep opts[:csv_options][:liberal_parsing] = true if liberal_parsing opts[:extension] = File.extname(filename) if filename begin Roo::Spreadsheet.open(file, **opts) - rescue => e + rescue StandardError => e raise "Failed to parse foodsoft file. make sure file format is correct: #{e.message}" end end -end \ No newline at end of file +end diff --git a/lib/foodsoft_article_import/bioromeo.rb b/lib/foodsoft_article_import/bioromeo.rb index be076b4..135cf1b 100644 --- a/lib/foodsoft_article_import/bioromeo.rb +++ b/lib/foodsoft_article_import/bioromeo.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Module for import of BioRomeo products from their Excel sheet, from Aug 2014 onwards require 'roo' @@ -5,44 +7,42 @@ require 'roo-xls' module FoodsoftArticleImport class Bioromeo - - NAME = "BioRomeo (XLSX, XLS, CSV)" + NAME = 'BioRomeo (XLSX, XLS, CSV)' OUTLIST = true OPTIONS = { - encoding: "UTF-8", - col_sep: ";" + encoding: 'UTF-8', + col_sep: ';' }.freeze - RE_UNITS = /(kg|gr|gram|pond|st|stuks?|set|bos|bossen|bosjes?|bak|bakjes?|liter|ltr|[lL]\.|ml|bol|krop)(\s*\.)?/i + RE_UNITS = /(kg|gr|gram|pond|st|stuks?|set|bos|bossen|bosjes?|bak|bakjes?|liter|ltr|[lL]\.|ml|bol|krop)(\s*\.)?/i.freeze RES_PARSE_UNIT_LIST = [ /\b((per|a)\s*)?([0-9,.]+\s*x\s*[0-9,.]+\s*#{RE_UNITS})/i, # 1x5 kg /\b((per|a)\s*)?([0-9,.]+\s*#{RE_UNITS}\s+x\s*[0-9,.]+)/i, # 1kg x 5 /\b((per|a)\s*)?(([0-9,.]+\s*,\s+)*[0-9,.]+\s+of\s+[0-9,.]+\s*#{RE_UNITS})/i, # 1, 2 of 5 kg /\b((per|a)\s*)?([0-9,.]+\s*#{RE_UNITS})/i, # 1kg /\b((per|a)\s*)?(#{RE_UNITS})/i # kg - ] + ].freeze # first parse with dash separator at the end, fallback to less specific - RES_PARSE_UNIT = RES_PARSE_UNIT_LIST.map {|r| /-\s*#{r}\s*$/} + - RES_PARSE_UNIT_LIST.map {|r| /-\s+#{r}/} + - RES_PARSE_UNIT_LIST.map {|r| /#{r}\s*$/} + - RES_PARSE_UNIT_LIST.map {|r| /-#{r}/} + RES_PARSE_UNIT = RES_PARSE_UNIT_LIST.map { |r| /-\s*#{r}\s*$/ } + + RES_PARSE_UNIT_LIST.map { |r| /-\s+#{r}/ } + + RES_PARSE_UNIT_LIST.map { |r| /#{r}\s*$/ } + + RES_PARSE_UNIT_LIST.map { |r| /-#{r}/ } def self.parse(file, custom_file_path: nil, **opts) custom_file_path ||= nil opts = OPTIONS.merge(opts) - opts[:liberal_parsing]=true - opts[:col_sep]="," + opts[:liberal_parsing] = true + opts[:col_sep] = ',' ss = FoodsoftArticleImport.open_spreadsheet(file, **opts) header_row = true sheet = ss.sheet(0).parse(clean: true, - order_number: /Artnr./, - name: /Product/, - skal: /Skal$/, - demeter: /Demeter$/, - unit_price: /prijs\b.*\beenh/i, - pack_price: /prijs\b.*\bcolli/i, - comment: /opm(erking)?/i, - ) + order_number: /Artnr./, + name: /Product/, + skal: /Skal$/, + demeter: /Demeter$/, + unit_price: /prijs\b.*\beenh/i, + pack_price: /prijs\b.*\bcolli/i, + comment: /opm(erking)?/i) linenum = 0 category = nil @@ -64,21 +64,21 @@ module FoodsoftArticleImport # extract name and unit errors = [] notes = [] - unit_price = row[:unit_price].gsub("€","").to_s.strip.to_f - pack_price = row[:pack_price].gsub("€","").to_s.strip.to_f + unit_price = row[:unit_price].gsub('€', '').to_s.strip.to_f + pack_price = row[:pack_price].gsub('€', '').to_s.strip.to_f number = row[:order_number] name = row[:name] unit = nil manufacturer = nil prod_category = nil RES_PARSE_UNIT.each do |re| - m=name.match(re) + m = name.match(re) unless m yield nil, nil, linenum next end - unit = self.normalize_unit(m[3]) - name = name.sub(re, '').sub(/\(\s*\)\s*$/,'').sub(/\s+/, ' ').sub(/\.\s*$/, '').strip + unit = normalize_unit(m[3]) + name = name.sub(re, '').sub(/\(\s*\)\s*$/, '').sub(/\s+/, ' ').sub(/\.\s*$/, '').strip break end unit ||= '1 st' if name.match(/\bsla\b/i) @@ -90,10 +90,10 @@ module FoodsoftArticleImport end # handle multiple units in one line if unit.match(/\b(,\s+|of)\b/) - # TODO create multiple articles instead of taking first one + # TODO: create multiple articles instead of taking first one end # sometimes category is also used to indicate manufacturer - m=category.match(/((eko\s*)?boerderij.*?)\s*$/i) and manufacturer = m[1] + m = category.match(/((eko\s*)?boerderij.*?)\s*$/i) and manufacturer = m[1] # Ad-hoc fix for package of eggs: always take pack price if name.match(/^eieren/i) unit_price = pack_price @@ -103,48 +103,47 @@ module FoodsoftArticleImport # figure out unit_quantity if unit.match(/x/) unit_quantity, unit = unit.split(/\s*x\s*/i, 2) - unit,unit_quantity = unit_quantity,unit if unit_quantity.match(/[a-z]/i) - elsif (unit_price-pack_price).abs < 1e-3 + unit, unit_quantity = unit_quantity, unit if unit_quantity.match(/[a-z]/i) + elsif (unit_price - pack_price).abs < 1e-3 unit_quantity = 1 - elsif m=unit.match(/^(.*)\b\s*(st|bos|bossen|bosjes?)\.?\s*$/i) + elsif (m = unit.match(/^(.*)\b\s*(st|bos|bossen|bosjes?)\.?\s*$/i)) unit_quantity, unit = m[1..2] unit_quantity.blank? and unit_quantity = 1 else unit_quantity = 1 end # there may be a more informative unit in the line - if unit=='st' && !name.match(/kool/i) + if unit == 'st' && !name.match(/kool/i) RES_PARSE_UNIT.each do |re| - m=name.match(re) or next - unit = self.normalize_unit(m[3]) + m = name.match(re) or next + unit = normalize_unit(m[3]) name = name.sub(re, '').strip end end - # note from various fields + # NOTE: from various fields notes.append("Skal #{row[:skal]}") unless row[:skal].to_s.strip.empty? notes.append(row[:demeter]) unless row[:skal].to_s.strip.empty? - notes.append("Demeter #{row[:demeter]}") unless row[:skal].to_s.strip.empty? && row[:demeter].is_a?(Fixnum) + notes.append("Demeter #{row[:demeter]}") unless row[:skal].to_s.strip.empty? && row[:demeter].is_a?(Integer) notes.append "(#{row[:comment]})" unless row[:comment].to_s.strip.empty? - name.sub!(/(,\.?\s*)?\bDemeter\b/i, '') and notes.prepend("Demeter") - name.sub!(/(,\.?\s*)?\bBIO\b/i, '') and notes.prepend "BIO" + name.sub!(/(,\.?\s*)?\bDemeter\b/i, '') and notes.prepend('Demeter') + name.sub!(/(,\.?\s*)?\bBIO\b/i, '') and notes.prepend 'BIO' # unit check errors << check_price(unit, unit_quantity, unit_price, pack_price) # create new article name.gsub!(/\s+/, ' ') - article = {:order_number => number, - :name => name.strip, - :note => notes.count > 0 && notes.map(&:strip).join("; "), - :manufacturer => manufacturer, - :origin => 'Noordoostpolder, NL', - :unit => unit, - :price => pack_price.to_f/unit_quantity.to_f, - :unit_quantity => unit_quantity, - :tax => 6, - :deposit => 0, - :article_category => prod_category || category - } + article = { order_number: number, + name: name.strip, + note: notes.count.positive? && notes.map(&:strip).join('; '), + manufacturer: manufacturer, + origin: 'Noordoostpolder, NL', + unit: unit, + price: pack_price.to_f / unit_quantity, + unit_quantity: unit_quantity, + tax: 6, + deposit: 0, + article_category: prod_category || category } errors.compact! - if errors.count > 0 + if errors.count.positive? yield article, errors.join("\n"), linenum else # outlisting not used by supplier @@ -153,44 +152,39 @@ module FoodsoftArticleImport end end - protected - def self.check_price(unit, unit_quantity, unit_price, pack_price) - if (unit_price-pack_price).abs < 1e-3 + if (unit_price - pack_price).abs < 1e-3 return if unit_quantity == 1 + return "price per unit #{unit_price} is pack price, but unit quantity #{unit_quantity} is not one" end - if m = unit.match(/^(.*)(#{RE_UNITS})\s*$/) - amount, what = m[1..2] - else - return "could not parse unit: #{unit}" - end + return "could not parse unit: #{unit}" unless (m = unit.match(/^(.*)(#{RE_UNITS})\s*$/)) + + amount, what = m[1..2] # perhaps unit price is kg-price - kgprice = if what =~ /^kg/i + kgprice = case what + when /^kg/i pack_price.to_f / amount.to_f - elsif what =~ /^gr/ + when /^gr/ pack_price.to_f / amount.to_f * 1000 end - unless kgprice.to_s.strip.empty? && (kgprice - unit_price.to_f).abs < 1e-2 - return - end + return unless kgprice.to_s.strip.empty? && (kgprice - unit_price.to_f).abs < 1e-2 - unit_price_computed = pack_price.to_f/unit_quantity.to_i - if (unit_price_computed - unit_price.to_f).abs > 1e-2 - "price per unit given #{unit_price.round(3)} does not match computed " + - "#{pack_price.round(3)}/#{unit_quantity}=#{unit_price_computed.round(3)}" + - (kgprice ? " (nor is it a kg-price #{kgprice.round(3)})" : '') - end + unit_price_computed = pack_price.to_f / unit_quantity.to_i + return unless (unit_price_computed - unit_price.to_f).abs > 1e-2 + + "price per unit given #{unit_price.round(3)} does not match computed " \ + "#{pack_price.round(3)}/#{unit_quantity}=#{unit_price_computed.round(3)}" + + (kgprice ? " (nor is it a kg-price #{kgprice.round(3)})" : '') end def self.normalize_unit(unit) unit = unit.sub(/1\s*x\s*/, '') - unit = unit.sub(/,([0-9])/, '.\1').gsub(/^per\s*/,'').sub(/^1\s*([^0-9.])/,'\1').sub(/^a\b\s*/,'') - unit = unit.sub(/(bossen|bosjes?)/, 'bos').sub(/(liter|l\.|L\.)/,'ltr').sub(/stuks?/, 'st').sub('gram','gr') - unit = unit.sub(/\s*\.\s*$/,'').sub(/\s+/, ' ').strip + unit = unit.sub(/,([0-9])/, '.\1').gsub(/^per\s*/, '').sub(/^1\s*([^0-9.])/, '\1').sub(/^a\b\s*/, '') + unit = unit.sub(/(bossen|bosjes?)/, 'bos').sub(/(liter|l\.|L\.)/, 'ltr').sub(/stuks?/, 'st').sub('gram', 'gr') + unit = unit.sub(/\s*\.\s*$/, '').sub(/\s+/, ' ').strip end - end -end \ No newline at end of file +end diff --git a/lib/foodsoft_article_import/bnn.rb b/lib/foodsoft_article_import/bnn.rb index c38e1cd..83809be 100644 --- a/lib/foodsoft_article_import/bnn.rb +++ b/lib/foodsoft_article_import/bnn.rb @@ -1,54 +1,49 @@ -# -*- coding: utf-8 -*- +# frozen_string_literal: true # Module for translation and parsing of BNN-files (www.n-bnn.de) # module FoodsoftArticleImport module Bnn - - private - @@codes = Hash.new - @@midgard = Hash.new + @@codes = {} + @@midgard = {} # Loads the codes_file config/bnn_codes.yml into the class variable @@codes - def self.load_codes(custom_file_path=nil) - @gem_lib = File.expand_path "../../", __FILE__ + def self.load_codes(custom_file_path = nil) + @gem_lib = File.expand_path '..', __dir__ dir = File.join @gem_lib, 'foodsoft_article_import' begin - @@codes = YAML::load(File.open(File.join(dir,"bnn_codes.yml"))).symbolize_keys - if(custom_file_path) - custom_codes = YAML::load(File.open(custom_file_path)).symbolize_keys - custom_codes.keys.each do |key| - if @@codes.keys.include?(key) - custom_codes[key] =custom_codes[key].merge @@codes[key] - end - @@codes = @@codes.merge custom_codes + @@codes = YAML.safe_load(File.open(File.join(dir, 'bnn_codes.yml'))).symbolize_keys + if custom_file_path + custom_codes = YAML.safe_load(File.open(custom_file_path)).symbolize_keys + custom_codes.each_key do |key| + custom_codes[key] = custom_codes[key].merge @@codes[key] if @@codes.keys.include?(key) + @@codes = @@codes.merge custom_codes end end - @@midgard = YAML::load(File.open(File.join(dir,"midgard_codes.yml"))).symbolize_keys - rescue => e + @@midgard = YAML.safe_load(File.open(File.join(dir, 'midgard_codes.yml'))).symbolize_keys + rescue StandardError => e raise "Failed to load bnn_codes: #{dir}/{bnn,midgard}_codes.yml: #{e.message}" end end - public - $missing_bnn_codes = Array.new + $missing_bnn_codes = [] # translates codes from BNN to foodsoft-code def self.translate(key, value) if @@codes[key][value] - return @@codes[key][value] + @@codes[key][value] elsif @@midgard[key] - return @@midgard[key][value] - elsif value != nil + @@midgard[key][value] + elsif !value.nil? $missing_bnn_codes << value - return nil + nil end end - - NAME = "BNN (CSV)" + + NAME = 'BNN (CSV)' OUTLIST = false OPTIONS = { - encoding: "IBM850", - col_sep: ";" + encoding: 'IBM850', + col_sep: ';' }.freeze # parses a bnn-file @@ -56,29 +51,29 @@ module FoodsoftArticleImport custom_file_path ||= nil encoding = opts[:encoding] || OPTIONS[:encoding] col_sep = opts[:col_sep] || OPTIONS[:col_sep] - self.load_codes(custom_file_path) - CSV.foreach(file, {col_sep: col_sep, encoding: encoding, headers: true}).with_index(1) do |row, i| + load_codes(custom_file_path) + CSV.foreach(file, { col_sep: col_sep, encoding: encoding, headers: true }).with_index(1) do |row, i| # check if the line is empty - unless row[0] == "" || row[0].nil? + unless row[0] == '' || row[0].nil? article = { - :name => UTF8Encoder.clean(row[6]), - :order_number => row[0], - :note => UTF8Encoder.clean(row[7]), - :manufacturer => self.translate(:manufacturer, row[10]), - :origin => row[12], - :article_category => self.translate(:category, row[16]), - :unit => row[23], - :price => row[37], - :tax => self.translate(:tax, row[33]), - :unit_quantity => row[22] + name: UTF8Encoder.clean(row[6]), + order_number: row[0], + note: UTF8Encoder.clean(row[7]), + manufacturer: translate(:manufacturer, row[10]), + origin: row[12], + article_category: translate(:category, row[16]), + unit: row[23], + price: row[37], + tax: translate(:tax, row[33]), + unit_quantity: row[22] } # TODO: Complete deposit list.... - article.merge!(:deposit => self.translate(:deposit, row[26])) if self.translate(:deposit, row[26]) + article.merge!(deposit: translate(:deposit, row[26])) if translate(:deposit, row[26]) # get scale prices if exists # article.merge!(:scale_quantity => row[40], :scale_price => row[41]) unless row[40].nil? or row[41].nil? - if row[62] != nil + if !row[62].nil? # consider special prices article[:note] = "Sonderpreis: #{article[:price]} von #{row[62]} bis #{row[63]}" yield article, :special, i @@ -86,7 +81,7 @@ module FoodsoftArticleImport # Check now for article status, we only consider outlisted articles right now # N=neu, A=Änderung, X=ausgelistet, R=Restbestand, # V=vorübergehend ausgelistet, W=wiedergelistet - elsif row[1] == "X" || row[1] == "V" + elsif row[1] == 'X' || row[1] == 'V' yield article, :outlisted, i else yield article, nil, i diff --git a/lib/foodsoft_article_import/foodsoft.rb b/lib/foodsoft_article_import/foodsoft.rb index 76fe45d..5fd09b4 100644 --- a/lib/foodsoft_article_import/foodsoft.rb +++ b/lib/foodsoft_article_import/foodsoft.rb @@ -1,59 +1,60 @@ -# -*- coding: utf-8 -*- +# frozen_string_literal: true + # Module for Foodsoft-file import # The Foodsoft-file is a CSV-file, with semicolon-separated columns, or ODS/XLS/XLSX require 'roo' require 'roo-xls' -module FoodsoftArticleImport::Foodsoft +module FoodsoftArticleImport + module Foodsoft + NAME = 'Foodsoft (CSV, ODS, XLS, XLSX)' + OUTLIST = false + OPTIONS = { + encoding: 'UTF-8', + col_sep: ';' + }.freeze - NAME = "Foodsoft (CSV, ODS, XLS, XLSX)" - OUTLIST = false - OPTIONS = { - encoding: "UTF-8", - col_sep: ";" - }.freeze + # Parses Foodsoft file + # the yielded article is a simple hash + def self.parse(file, custom_file_path: nil, **opts) + custom_file_path ||= nil + opts = OPTIONS.merge(opts) - # Parses Foodsoft file - # the yielded article is a simple hash - def self.parse(file, custom_file_path: nil, **opts) - custom_file_path ||= nil - opts = OPTIONS.merge(opts) + ss = FoodsoftArticleImport.open_spreadsheet(file, **opts) - ss = FoodsoftArticleImport.open_spreadsheet(file, **opts) + header_row = true + ss.sheet(0).each.with_index(1) do |row, i| + # skip first header row + if header_row + header_row = false + next + end + # skip empty lines + if row[2].to_s.strip.empty? + # raise no order number given + yield nil, nil, i + next + end - header_row = true - ss.sheet(0).each.with_index(1) do |row, i| - # skip first header row - if header_row - header_row = false - next - end - # skip empty lines - if row[2].to_s.strip.empty? - # raise no order number given - yield nil, nil, i - next - end - - article = {:order_number => row[1], - :name => row[2], - :note => row[3], - :manufacturer => row[4], - :origin => row[5], - :unit => row[6], - :price => row[7], - :tax => row[8], - :unit_quantity => row[10], - :article_category => row[13]} - article.merge!(:deposit => row[9]) unless row[9].nil? - FoodsoftArticleImport.generate_number(article) if article[:order_number].to_s.strip.empty? - if row[6].nil? || row[7].nil? or row[8].nil? - yield article, "Error: unit, price and tax must be entered", i - else - yield article, (row[0]=='x' ? :outlisted : nil), i + article = { order_number: row[1], + name: row[2], + note: row[3], + manufacturer: row[4], + origin: row[5], + unit: row[6], + price: row[7], + tax: row[8], + unit_quantity: row[10], + article_category: row[13] } + article.merge!(deposit: row[9]) unless row[9].nil? + FoodsoftArticleImport.generate_number(article) if article[:order_number].to_s.strip.empty? + if row[6].nil? || row[7].nil? || row[8].nil? + yield article, 'Error: unit, price and tax must be entered', i + else + yield article, (row[0] == 'x' ? :outlisted : nil), i + end end end end - -end \ No newline at end of file +end diff --git a/lib/foodsoft_article_import/odin.rb b/lib/foodsoft_article_import/odin.rb index bb9992d..bdfa605 100644 --- a/lib/foodsoft_article_import/odin.rb +++ b/lib/foodsoft_article_import/odin.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Article import for De Nieuw Band XML file # # Always contains full assortment, including recently outlisted articles. @@ -8,33 +10,31 @@ require 'nokogiri' module FoodsoftArticleImport class Odin - - NAME = "De Nieuwe Band (XML)" + NAME = 'De Nieuwe Band (XML)' OUTLIST = true OPTIONS = {}.freeze # parses a string or file - def self.parse(file, custom_file_path: nil, **opts) + def self.parse(file, custom_file_path: nil, **_opts) custom_file_path ||= nil xml = File.open(file) doc = Nokogiri.XML(xml, nil, nil, - Nokogiri::XML::ParseOptions::RECOVER + - Nokogiri::XML::ParseOptions::NONET + - Nokogiri::XML::ParseOptions::COMPACT # do not modify doc! - ) - self.load_codes(custom_file_path) + Nokogiri::XML::ParseOptions::RECOVER + + Nokogiri::XML::ParseOptions::NONET + + Nokogiri::XML::ParseOptions::COMPACT) # do not modify doc! + load_codes(custom_file_path) doc.search('product').each.with_index(1) do |row, i| # create a new article unit = row.search('eenheid').text - unit = case(unit.strip) - when '' then 'st' - when 'stuk' then 'st' - when 'g' then 'gr' # need at least 2 chars - when 'l' then 'ltr' - else unit - end + unit = case unit.strip + when '' then 'st' + when 'stuk' then 'st' + when 'g' then 'gr' # need at least 2 chars + when 'l' then 'ltr' + else unit + end inhoud = row.search('inhoud').text - inhoud.to_s.strip.empty? or (inhoud.to_f-1).abs > 1e-3 and unit = inhoud.gsub(/\.0+\s*$/,'') + unit + inhoud.to_s.strip.empty? or (inhoud.to_f - 1).abs > 1e-3 and unit = inhoud.gsub(/\.0+\s*$/, '') + unit deposit = row.search('statiegeld').text deposit.to_s.strip.empty? and deposit = 0 category = [ @@ -42,48 +42,44 @@ module FoodsoftArticleImport @@codes[:indeling][row.search('subindeling').text.to_i] ].compact.join(' - ') - status = row.search('status').text == "Actief" ? nil : :outlisted + status = row.search('status').text == 'Actief' ? nil : :outlisted article = {} - unless row.search('bestelnummer').text == "" - article = {:order_number => row.search('bestelnummer').text, - #:ean => row.search('eancode').text, - :name => row.search('omschrijving').text, - :note => row.search('kwaliteit').text, - :manufacturer => row.search('merk').text, - :origin => row.search('herkomst').text, - :unit => unit, - :price => row.search('prijs inkoopprijs').text, - :unit_quantity => row.search('sve').text, - :tax => row.search('btw').text, - :deposit => deposit, - :article_category => category} + unless row.search('bestelnummer').text == '' + article = { order_number: row.search('bestelnummer').text, + # :ean => row.search('eancode').text, + name: row.search('omschrijving').text, + note: row.search('kwaliteit').text, + manufacturer: row.search('merk').text, + origin: row.search('herkomst').text, + unit: unit, + price: row.search('prijs inkoopprijs').text, + unit_quantity: row.search('sve').text, + tax: row.search('btw').text, + deposit: deposit, + article_category: category } end yield article, status, i end end - private + @@codes = {} - @@codes = Hash.new - - def self.load_codes(custom_file_path=nil) - @gem_lib = File.expand_path "../../", __FILE__ + def self.load_codes(custom_file_path = nil) + @gem_lib = File.expand_path '..', __dir__ dir = File.join @gem_lib, 'foodsoft_article_import' begin - @@codes = YAML::load(File.open(File.join(dir, "dnb_codes.yml"))).symbolize_keys - if(custom_file_path) - custom_codes = YAML::load(File.open(custom_file_path)).symbolize_keys - custom_codes.keys.each do |key| - if @@codes.keys.include?(key) - custom_codes[key] =custom_codes[key].merge @@codes[key] - end - @@codes = @@codes.merge custom_codes + @@codes = YAML.safe_load(File.open(File.join(dir, 'dnb_codes.yml'))).symbolize_keys + if custom_file_path + custom_codes = YAML.safe_load(File.open(custom_file_path)).symbolize_keys + custom_codes.each_key do |key| + custom_codes[key] = custom_codes[key].merge @@codes[key] if @@codes.keys.include?(key) + @@codes = @@codes.merge custom_codes end end @@codes - rescue => e + rescue StandardError => e raise "Failed to load dnb_codes: #{dir}/dnb_codes.yml: #{e.message}" end end end -end \ No newline at end of file +end diff --git a/lib/foodsoft_article_import/utf8_encoder.rb b/lib/foodsoft_article_import/utf8_encoder.rb index 0715a7e..1edb672 100644 --- a/lib/foodsoft_article_import/utf8_encoder.rb +++ b/lib/foodsoft_article_import/utf8_encoder.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module UTF8Encoder def self.clean(string) if string.nil? diff --git a/lib/foodsoft_article_import/version.rb b/lib/foodsoft_article_import/version.rb index e4b8866..6d110f0 100644 --- a/lib/foodsoft_article_import/version.rb +++ b/lib/foodsoft_article_import/version.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module FoodsoftArticleImport VERSION = '1.0.0' -end \ No newline at end of file +end diff --git a/spec/lib/bioromeo/foodsoft_article_import_bioromeo_spec.rb b/spec/lib/bioromeo/foodsoft_article_import_bioromeo_spec.rb index 63bd522..3c4848b 100644 --- a/spec/lib/bioromeo/foodsoft_article_import_bioromeo_spec.rb +++ b/spec/lib/bioromeo/foodsoft_article_import_bioromeo_spec.rb @@ -1,22 +1,23 @@ +# frozen_string_literal: true + require 'spec_helper' require_relative '../../../lib/foodsoft_article_import' describe FoodsoftArticleImport do - files_path = File.expand_path '../../files', __dir__ bioromeo_files_path = File.join(files_path, 'bioromeo') - dummy_article = {:order_number=>"1", :name => "Wilde aardappels",:article_category => "Aardappels \"nieuwe oogst\"", :deposit => 0, :manufacturer => nil, :origin => "Noordoostpolder, NL", :price => 5.0, :tax => 6, :unit => "5kg", :unit_quantity => 1, :note => "Skal 1234; 123456; Demeter 123456; (Kopervrij)"} - + dummy_article = { order_number: '1', name: 'Wilde aardappels', article_category: 'Aardappels "nieuwe oogst"', + deposit: 0, manufacturer: nil, origin: 'Noordoostpolder, NL', price: 5.0, tax: 6, unit: '5kg', unit_quantity: 1, note: 'Skal 1234; 123456; Demeter 123456; (Kopervrij)' } empty = {} - context "bioromeo" do + context 'bioromeo' do it 'parses file correctly with type parameter bioromeo' do - FoodsoftArticleImport.parse(File.open(File.join(bioromeo_files_path, 'bioromeo_flawless.csv')), type: 'bioromeo') do |new_attrs, status, line| - if new_attrs==nil - next - end + FoodsoftArticleImport.parse(File.open(File.join(bioromeo_files_path, 'bioromeo_flawless.csv')), + type: 'bioromeo') do |new_attrs, _status, _line| + next if new_attrs.nil? + expect(new_attrs).to eq dummy_article end end diff --git a/spec/lib/bnn/foodsoft_article_import_bnn_spec.rb b/spec/lib/bnn/foodsoft_article_import_bnn_spec.rb index 42c60ef..87f66c8 100644 --- a/spec/lib/bnn/foodsoft_article_import_bnn_spec.rb +++ b/spec/lib/bnn/foodsoft_article_import_bnn_spec.rb @@ -1,70 +1,85 @@ +# frozen_string_literal: true + require 'spec_helper' require_relative '../../../lib/foodsoft_article_import' describe FoodsoftArticleImport do - files_path = File.expand_path '../../files', __dir__ bnn_files_path = File.join(files_path, 'bnn') dummy_article = { name: 'Greek Dressing - Kräuter Mix', order_number: '64721', note: 'Oregano, Basilikum und Minze', - manufacturer: 'Medousa, Griechenland Importe', origin: 'GR', article_category: 'Kräutermischungen', unit: '35g', price: '2,89', tax: 7.0, unit_quantity: '6'} + manufacturer: 'Medousa, Griechenland Importe', origin: 'GR', article_category: 'Kräutermischungen', unit: '35g', price: '2,89', tax: 7.0, unit_quantity: '6' } - article = dummy_article.merge({ deposit: 0.08}) + article = dummy_article.merge({ deposit: 0.08 }) article_special = article.merge(note: 'Sonderpreis: 2,89 von 20230101 bis 20230201') - article_2 = dummy_article.merge({manufacturer: nil, article_category: nil}) + article_2 = dummy_article.merge({ manufacturer: nil, article_category: nil }) - article_custom_code = article.merge(article_category: "Schuhe") + article_custom_code = article.merge(article_category: 'Schuhe') empty = {} context 'bnn' do it 'parses bnn file correctly without type parameter' do - FoodsoftArticleImport.parse(File.open(File.join(bnn_files_path, 'bnn_flawless.BNN'))) do |new_attrs, status, line| + FoodsoftArticleImport.parse(File.open(File.join(bnn_files_path, + 'bnn_flawless.BNN'))) do |new_attrs, status, _line| expect(new_attrs).to eq article expect(status).to eq :outlisted end end it 'parses file correctly with type parameter' do - FoodsoftArticleImport.parse(File.open(File.join(bnn_files_path, 'bnn_flawless.BNN')), type: 'bnn') do |new_attrs, status, line| + FoodsoftArticleImport.parse(File.open(File.join(bnn_files_path, 'bnn_flawless.BNN')), + type: 'bnn') do |new_attrs, status, _line| expect(new_attrs).to eq article expect(status).to eq :outlisted end end it 'raises error wenn wrong type (except dnb_xml) specified' do - expect{FoodsoftArticleImport.parse(File.open(File.join(bnn_files_path, 'bnn_flawless.BNN')),type: 'foodsoft')}.to raise_error(RuntimeError) - expect{FoodsoftArticleImport.parse(File.open(File.join(bnn_files_path, 'bnn_flawless.BNN')),type: 'bioromeo')}.to raise_error(RuntimeError) + expect do + FoodsoftArticleImport.parse(File.open(File.join(bnn_files_path, 'bnn_flawless.BNN')), + type: 'foodsoft') + end.to raise_error(RuntimeError) + expect do + FoodsoftArticleImport.parse(File.open(File.join(bnn_files_path, 'bnn_flawless.BNN')), + type: 'bioromeo') + end.to raise_error(RuntimeError) - expect(FoodsoftArticleImport.parse(File.open(File.join(bnn_files_path, 'bnn_flawless.BNN')),type: 'dnb_xml')).to eq [] + expect(FoodsoftArticleImport.parse(File.open(File.join(bnn_files_path, 'bnn_flawless.BNN')), + type: 'dnb_xml')).to eq [] end it 'parses article with special correctly' do - FoodsoftArticleImport.parse(File.open(File.join(bnn_files_path, 'bnn_flawless_special.BNN')), type: 'bnn') do |new_attrs, status, line| + FoodsoftArticleImport.parse(File.open(File.join(bnn_files_path, 'bnn_flawless_special.BNN')), + type: 'bnn') do |new_attrs, status, _line| expect(new_attrs).to eq article_special expect(status).to eq :special end end it 'parses missing entries correctly' do - FoodsoftArticleImport.parse(File.open(File.join(bnn_files_path, 'bnn_missing_entries.BNN')), type: 'bnn') do |new_attrs, status, line| + FoodsoftArticleImport.parse(File.open(File.join(bnn_files_path, 'bnn_missing_entries.BNN')), + type: 'bnn') do |new_attrs, status, _line| expect(new_attrs).to eq article_2 expect(status).to eq nil end end it 'skips rows without order_number' do - FoodsoftArticleImport.parse(File.open(File.join(bnn_files_path, 'bnn_missing_order_number.BNN')), type: 'bnn') do |new_attrs, status, line| + FoodsoftArticleImport.parse(File.open(File.join(bnn_files_path, 'bnn_missing_order_number.BNN')), + type: 'bnn') do |new_attrs, _status, _line| expect(new_attrs).to eq empty end end it 'joins custom_codes file' do custom_file_path = File.join(files_path, 'custom_codes.yml').to_s - FoodsoftArticleImport.parse(File.open(File.join(bnn_files_path, 'bnn_flawless_category.BNN')), custom_file_path: custom_file_path, type: 'bnn') do |new_attrs, status, line| + FoodsoftArticleImport.parse(File.open(File.join(bnn_files_path, 'bnn_flawless_category.BNN')), + custom_file_path: custom_file_path, type: 'bnn') do |new_attrs, _status, _line| expect(new_attrs).to eq article_custom_code end end it 'parses file with different encoding' do - #the bnn file is loaded with encoding ibm850. If file is not ibm850 encoded, some characters might look weird - FoodsoftArticleImport.parse(File.open(File.join(bnn_files_path, 'bnn_bad_encoding.BNN')), type: 'bnn') do |new_attrs, status, line| - expect(new_attrs[:order_number]).to eq("64721") - expect(new_attrs[:name]).to eq("Greek Dressing - Kr├ñuter Mix") + # the bnn file is loaded with encoding ibm850. If file is not ibm850 encoded, some characters might look weird + FoodsoftArticleImport.parse(File.open(File.join(bnn_files_path, 'bnn_bad_encoding.BNN')), + type: 'bnn') do |new_attrs, _status, _line| + expect(new_attrs[:order_number]).to eq('64721') + expect(new_attrs[:name]).to eq('Greek Dressing - Kr├ñuter Mix') end end end diff --git a/spec/lib/foodsoft/foodsoft_article_import_foodsoft_spec.rb b/spec/lib/foodsoft/foodsoft_article_import_foodsoft_spec.rb index 59b4404..c794e45 100644 --- a/spec/lib/foodsoft/foodsoft_article_import_foodsoft_spec.rb +++ b/spec/lib/foodsoft/foodsoft_article_import_foodsoft_spec.rb @@ -1,56 +1,67 @@ +# frozen_string_literal: true + require 'spec_helper' require_relative '../../../lib/foodsoft_article_import' describe FoodsoftArticleImport do - files_path = File.expand_path '../../files', __dir__ foodsoft_files_path = File.join(files_path, 'foodsoft') - dummy_article = {:order_number=>"1", :name=>"product", :note=>"bio", :manufacturer=>"someone", :origin=>"eu", :unit=>"1 kg", :price=>"1.23", :tax=>"6", :unit_quantity=>"10", :article_category=>"coolstuff", :deposit=>"0"} + dummy_article = { order_number: '1', name: 'product', note: 'bio', manufacturer: 'someone', origin: 'eu', + unit: '1 kg', price: '1.23', tax: '6', unit_quantity: '10', article_category: 'coolstuff', deposit: '0' } + dummy_article_2 = { order_number: '12', name: 'other product', note: 'bio', manufacturer: 'someone', + origin: 'eu', unit: '2 kg', price: '3.45', tax: '6', unit_quantity: '10', article_category: 'coolstuff', deposit: '0' } - dummy_article_2 = {:order_number=>"12", :name=>"other product", :note=>"bio", :manufacturer=>"someone", :origin=>"eu", :unit=>"2 kg", :price=>"3.45", :tax=>"6", :unit_quantity=>"10", :article_category=>"coolstuff", :deposit=>"0"} + articles = [dummy_article, dummy_article_2] - articles=[dummy_article, dummy_article_2] - - dummy_article_3 = dummy_article.merge({ order_number: ":d8df298"}) - dummy_article_4 = dummy_article_2.merge({ order_number: ":1f37e39"}) - articles_number_generated= [dummy_article_3, dummy_article_4] + dummy_article_3 = dummy_article.merge({ order_number: ':d8df298' }) + dummy_article_4 = dummy_article_2.merge({ order_number: ':1f37e39' }) + articles_number_generated = [dummy_article_3, dummy_article_4] empty = {} - context "foodsoft" do + context 'foodsoft' do it 'parses file correctly with type parameter foodsoft' do - count =0 - FoodsoftArticleImport.parse(File.open(File.join(foodsoft_files_path, 'foodsoft_flawless.csv')), type: 'foodsoft') do |new_attrs, status, line| + count = 0 + FoodsoftArticleImport.parse(File.open(File.join(foodsoft_files_path, 'foodsoft_flawless.csv')), + type: 'foodsoft') do |new_attrs, status, _line| expect(new_attrs).to eq articles[count] expect(status).to eq nil - count+=1 + count += 1 end end it 'raises error wenn wrong type specified' do - expect{FoodsoftArticleImport.parse(File.open(File.join(foodsoft_files_path, 'foodsoft_flawless.csv')),type: 'bioromeo')}.to raise_error(Roo::HeaderRowNotFoundError) - expect(FoodsoftArticleImport.parse(File.open(File.join(foodsoft_files_path, 'foodsoft_flawless.csv')),type: 'odin')).to eq [] + expect do + FoodsoftArticleImport.parse(File.open(File.join(foodsoft_files_path, 'foodsoft_flawless.csv')), + type: 'bioromeo') + end.to raise_error(Roo::HeaderRowNotFoundError) + expect(FoodsoftArticleImport.parse(File.open(File.join(foodsoft_files_path, 'foodsoft_flawless.csv')), + type: 'odin')).to eq [] - expect(FoodsoftArticleImport.parse(File.open(File.join(foodsoft_files_path, 'foodsoft_flawless.csv')),type: 'bnn')).to eq [] + expect(FoodsoftArticleImport.parse(File.open(File.join(foodsoft_files_path, 'foodsoft_flawless.csv')), + type: 'bnn')).to eq [] end it 'parses missing entries correctly' do - FoodsoftArticleImport.parse(File.open(File.join(foodsoft_files_path, 'foodsoft_missing_entries.csv')), type: 'foodsoft') do |new_attrs, status, line| + FoodsoftArticleImport.parse(File.open(File.join(foodsoft_files_path, 'foodsoft_missing_entries.csv')), + type: 'foodsoft') do |new_attrs, status, _line| expect(status).to eq 'Error: unit, price and tax must be entered' - expect(new_attrs[:unit]).to eq "1 kg" + expect(new_attrs[:unit]).to eq '1 kg' expect(new_attrs[:manufacturer]).to eq nil end end it 'generates order numbers for articles without order number' do - count=0 - FoodsoftArticleImport.parse(File.open(File.join(foodsoft_files_path, 'foodsoft_generate_order_number.csv')), type: 'foodsoft') do |new_attrs, status, line| + count = 0 + FoodsoftArticleImport.parse(File.open(File.join(foodsoft_files_path, 'foodsoft_generate_order_number.csv')), + type: 'foodsoft') do |new_attrs, _status, _line| expect(new_attrs).to eq articles_number_generated[count] - count+=1 + count += 1 end end xit 'joins custom_codes file' do custom_file_path = File.join(files_path, 'custom_codes.yml').to_s - FoodsoftArticleImport.parse(File.open(File.join(foodsoft_files_path, 'foodsoft_flawless_custom_category.csv')), custom_file_path: custom_file_path, type: 'foodsoft') do |new_attrs, status, line| - expect(new_attrs[:article_category]).to eq "Test Indeling - Test Subindeling" + FoodsoftArticleImport.parse(File.open(File.join(foodsoft_files_path, 'foodsoft_flawless_custom_category.csv')), + custom_file_path: custom_file_path, type: 'foodsoft') do |new_attrs, _status, _line| + expect(new_attrs[:article_category]).to eq 'Test Indeling - Test Subindeling' end end end diff --git a/spec/lib/odin/foodsoft_article_import_odin_spec.rb b/spec/lib/odin/foodsoft_article_import_odin_spec.rb index bdac2ae..8e5906c 100644 --- a/spec/lib/odin/foodsoft_article_import_odin_spec.rb +++ b/spec/lib/odin/foodsoft_article_import_odin_spec.rb @@ -1,66 +1,83 @@ +# frozen_string_literal: true + require 'spec_helper' require_relative '../../../lib/foodsoft_article_import' describe FoodsoftArticleImport do - files_path = File.expand_path '../../files', __dir__ odin_files_path = File.join(files_path, 'odin') - dummy_article = {:order_number=>"0109", :name=>"nucli rose", :note=>"Biologisch", :manufacturer=>"NELEMAN", :origin=>"ES", :unit=>"750gr", :price=>"4.52", :unit_quantity=>"6", :tax=>"21", :deposit=>"0", :article_category=>""} - + dummy_article = { order_number: '0109', name: 'nucli rose', note: 'Biologisch', manufacturer: 'NELEMAN', + origin: 'ES', unit: '750gr', price: '4.52', unit_quantity: '6', tax: '21', deposit: '0', article_category: '' } empty = {} - context "odin/dnb_xml" do + context 'odin/dnb_xml' do it 'parses file correctly with type parameter dnb_xml' do - FoodsoftArticleImport.parse(File.open(File.join(odin_files_path, 'odin_flawless.xml')), type: 'dnb_xml') do |new_attrs, status, line| + FoodsoftArticleImport.parse(File.open(File.join(odin_files_path, 'odin_flawless.xml')), + type: 'dnb_xml') do |new_attrs, status, _line| expect(new_attrs).to eq dummy_article expect(status).to eq nil end end it 'parses file correctly with type parameter odin' do - FoodsoftArticleImport.parse(File.open(File.join(odin_files_path, 'odin_flawless.xml')), type: 'odin') do |new_attrs, status, line| + FoodsoftArticleImport.parse(File.open(File.join(odin_files_path, 'odin_flawless.xml')), + type: 'odin') do |new_attrs, status, _line| expect(new_attrs).to eq dummy_article expect(status).to eq nil end end it 'raises error wenn wrong type specified' do - expect{FoodsoftArticleImport.parse(File.open(File.join(odin_files_path, 'odin_flawless.xml')),type: 'foodsoft')}.to raise_error(RuntimeError) - expect{FoodsoftArticleImport.parse(File.open(File.join(odin_files_path, 'odin_flawless.xml')),type: 'bioromeo')}.to raise_error(RuntimeError) + expect do + FoodsoftArticleImport.parse(File.open(File.join(odin_files_path, 'odin_flawless.xml')), + type: 'foodsoft') + end.to raise_error(RuntimeError) + expect do + FoodsoftArticleImport.parse(File.open(File.join(odin_files_path, 'odin_flawless.xml')), + type: 'bioromeo') + end.to raise_error(RuntimeError) - expect{FoodsoftArticleImport.parse(File.open(File.join(odin_files_path, 'odin_flawless.xml')),type: 'bnn')}.to raise_error(CSV::MalformedCSVError) + expect do + FoodsoftArticleImport.parse(File.open(File.join(odin_files_path, 'odin_flawless.xml')), + type: 'bnn') + end.to raise_error(CSV::MalformedCSVError) end it 'parses missing entries correctly' do - FoodsoftArticleImport.parse(File.open(File.join(odin_files_path, 'odin_missing_entries.xml')), type: 'odin') do |new_attrs, status, line| + FoodsoftArticleImport.parse(File.open(File.join(odin_files_path, 'odin_missing_entries.xml')), + type: 'odin') do |new_attrs, status, _line| expect(status).to eq :outlisted - expect(new_attrs[:unit]).to eq "750st" - expect(new_attrs[:manufacturer]).to eq "" + expect(new_attrs[:unit]).to eq '750st' + expect(new_attrs[:manufacturer]).to eq '' end end it 'skips rows without order_number' do - FoodsoftArticleImport.parse(File.open(File.join(odin_files_path, 'odin_missing_order_number.xml')), type: 'odin') do |new_attrs, status, line| + FoodsoftArticleImport.parse(File.open(File.join(odin_files_path, 'odin_missing_order_number.xml')), + type: 'odin') do |new_attrs, _status, _line| expect(new_attrs).to eq empty end end it 'joins custom_codes file' do custom_file_path = File.join(files_path, 'custom_codes.yml').to_s - FoodsoftArticleImport.parse(File.open(File.join(odin_files_path, 'odin_flawless_custom_category.xml')), custom_file_path: custom_file_path, type: 'odin') do |new_attrs, status, line| - expect(new_attrs[:article_category]).to eq "Test Indeling - Test Subindeling" + FoodsoftArticleImport.parse(File.open(File.join(odin_files_path, 'odin_flawless_custom_category.xml')), + custom_file_path: custom_file_path, type: 'odin') do |new_attrs, _status, _line| + expect(new_attrs[:article_category]).to eq 'Test Indeling - Test Subindeling' end end xit 'parses dummy_article with special correctly' do - #TODO: find out whether there are special prices for odin files - FoodsoftArticleImport.parse(File.open(File.join(odin_files_path, 'bnn_flawless_special.BNN')), type: 'bnn') do |new_attrs, status, line| + # TODO: find out whether there are special prices for odin files + FoodsoftArticleImport.parse(File.open(File.join(odin_files_path, 'bnn_flawless_special.BNN')), + type: 'bnn') do |new_attrs, _status, _line| expect(new_attrs.manufacturer).to eq nil - expect(new_attrs.unit).to eq "750st" + expect(new_attrs.unit).to eq '750st' end end xit 'parses file with different encoding' do - #the bnn file is loaded with encoding ibm850. If file is not ibm850 encoded, some characters might look weird - FoodsoftArticleImport.parse(File.open(File.join(odin_files_path, 'bnn_bad_encoding.BNN')), type: 'bnn') do |new_attrs, status, line| - expect(new_attrs[:order_number]).to eq("64721") - expect(new_attrs[:name]).to eq("Greek Dressing - Kr├ñuter Mix") + # the bnn file is loaded with encoding ibm850. If file is not ibm850 encoded, some characters might look weird + FoodsoftArticleImport.parse(File.open(File.join(odin_files_path, 'bnn_bad_encoding.BNN')), + type: 'bnn') do |new_attrs, _status, _line| + expect(new_attrs[:order_number]).to eq('64721') + expect(new_attrs[:name]).to eq('Greek Dressing - Kr├ñuter Mix') end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 03990c4..d3e43d5 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'simplecov' SimpleCov.start # This file was generated by the `rspec --init` command. Conventionally, all @@ -46,55 +48,53 @@ RSpec.configure do |config| # triggering implicit auto-inclusion in groups with matching metadata. config.shared_context_metadata_behavior = :apply_to_host_groups -# The settings below are suggested to provide a good initial experience -# with RSpec, but feel free to customize to your heart's content. -=begin - # This allows you to limit a spec run to individual examples or groups - # you care about by tagging them with `:focus` metadata. When nothing - # is tagged with `:focus`, all examples get run. RSpec also provides - # aliases for `it`, `describe`, and `context` that include `:focus` - # metadata: `fit`, `fdescribe` and `fcontext`, respectively. - config.filter_run_when_matching :focus - - # Allows RSpec to persist some state between runs in order to support - # the `--only-failures` and `--next-failure` CLI options. We recommend - # you configure your source control system to ignore this file. - config.example_status_persistence_file_path = "spec/examples.txt" - - # Limits the available syntax to the non-monkey patched syntax that is - # recommended. For more details, see: - # https://relishapp.com/rspec/rspec-core/docs/configuration/zero-monkey-patching-mode - config.disable_monkey_patching! - - # This setting enables warnings. It's recommended, but in some cases may - # be too noisy due to issues in dependencies. - config.warnings = true - - # Many RSpec users commonly either run the entire suite or an individual - # file, and it's useful to allow more verbose output when running an - # individual spec file. - if config.files_to_run.one? - # Use the documentation formatter for detailed output, - # unless a formatter has already been configured - # (e.g. via a command-line flag). - config.default_formatter = "doc" - end - - # Print the 10 slowest examples and example groups at the - # end of the spec run, to help surface which specs are running - # particularly slow. - config.profile_examples = 10 - - # Run specs in random order to surface order dependencies. If you find an - # order dependency and want to debug it, you can fix the order by providing - # the seed, which is printed after each run. - # --seed 1234 - config.order = :random - - # Seed global randomization in this process using the `--seed` CLI option. - # Setting this allows you to use `--seed` to deterministically reproduce - # test failures related to randomization by passing the same `--seed` value - # as the one that triggered the failure. - Kernel.srand config.seed -=end + # The settings below are suggested to provide a good initial experience + # with RSpec, but feel free to customize to your heart's content. + # # This allows you to limit a spec run to individual examples or groups + # # you care about by tagging them with `:focus` metadata. When nothing + # # is tagged with `:focus`, all examples get run. RSpec also provides + # # aliases for `it`, `describe`, and `context` that include `:focus` + # # metadata: `fit`, `fdescribe` and `fcontext`, respectively. + # config.filter_run_when_matching :focus + # + # # Allows RSpec to persist some state between runs in order to support + # # the `--only-failures` and `--next-failure` CLI options. We recommend + # # you configure your source control system to ignore this file. + # config.example_status_persistence_file_path = "spec/examples.txt" + # + # # Limits the available syntax to the non-monkey patched syntax that is + # # recommended. For more details, see: + # # https://relishapp.com/rspec/rspec-core/docs/configuration/zero-monkey-patching-mode + # config.disable_monkey_patching! + # + # # This setting enables warnings. It's recommended, but in some cases may + # # be too noisy due to issues in dependencies. + # config.warnings = true + # + # # Many RSpec users commonly either run the entire suite or an individual + # # file, and it's useful to allow more verbose output when running an + # # individual spec file. + # if config.files_to_run.one? + # # Use the documentation formatter for detailed output, + # # unless a formatter has already been configured + # # (e.g. via a command-line flag). + # config.default_formatter = "doc" + # end + # + # # Print the 10 slowest examples and example groups at the + # # end of the spec run, to help surface which specs are running + # # particularly slow. + # config.profile_examples = 10 + # + # # Run specs in random order to surface order dependencies. If you find an + # # order dependency and want to debug it, you can fix the order by providing + # # the seed, which is printed after each run. + # # --seed 1234 + # config.order = :random + # + # # Seed global randomization in this process using the `--seed` CLI option. + # # Setting this allows you to use `--seed` to deterministically reproduce + # # test failures related to randomization by passing the same `--seed` value + # # as the one that triggered the failure. + # Kernel.srand config.seed end