diff --git a/plugins/article_import/app/overrides/controllers/articles_controller_override.rb b/plugins/article_import/app/overrides/controllers/articles_controller_override.rb
index 7777064e..43e9773b 100644
--- a/plugins/article_import/app/overrides/controllers/articles_controller_override.rb
+++ b/plugins/article_import/app/overrides/controllers/articles_controller_override.rb
@@ -1,20 +1,18 @@
-if FoodsoftArticleImport.enabled?
- ArticlesController.class_eval do
- def parse_upload
- uploaded_file = params[:articles]['file'] or raise I18n.t('articles.controller.parse_upload.no_file')
- type = params[:articles]['type']
- options = { filename: uploaded_file.original_filename }
- options[:outlist_absent] = (params[:articles]['outlist_absent'] == '1')
- options[:convert_units] = (params[:articles]['convert_units'] == '1')
- options[:update_category] = (params[:articles]['update_category'] == '1')
+ArticlesController.class_eval do
+ def parse_upload
+ uploaded_file = params[:articles]['file'] or raise I18n.t('articles.controller.parse_upload.no_file')
+ type = params[:articles]['type']
+ options = { filename: uploaded_file.original_filename }
+ options[:outlist_absent] = (params[:articles]['outlist_absent'] == '1')
+ options[:convert_units] = (params[:articles]['convert_units'] == '1')
+ options[:update_category] = (params[:articles]['update_category'] == '1')
- @updated_article_pairs, @outlisted_articles, @new_articles = @supplier.sync_from_file uploaded_file.tempfile, type, options
- if @updated_article_pairs.empty? && @outlisted_articles.empty? && @new_articles.empty?
- redirect_to supplier_articles_path(@supplier), :notice => I18n.t('articles.controller.parse_upload.notice')
- end
- @ignored_article_count = 0
- rescue => error
- redirect_to upload_supplier_articles_path(@supplier), :alert => I18n.t('errors.general_msg', :msg => error.message)
+ @updated_article_pairs, @outlisted_articles, @new_articles = @supplier.sync_from_file uploaded_file.tempfile, type, options
+ if @updated_article_pairs.empty? && @outlisted_articles.empty? && @new_articles.empty?
+ redirect_to supplier_articles_path(@supplier), :notice => I18n.t('articles.controller.parse_upload.notice')
end
+ @ignored_article_count = 0
+ rescue => error
+ redirect_to upload_supplier_articles_path(@supplier), :alert => I18n.t('errors.general_msg', :msg => error.message)
end
-end
\ No newline at end of file
+end
diff --git a/plugins/article_import/app/overrides/models/article_override.rb b/plugins/article_import/app/overrides/models/article_override.rb
index 5ca177ad..2018a4e7 100644
--- a/plugins/article_import/app/overrides/models/article_override.rb
+++ b/plugins/article_import/app/overrides/models/article_override.rb
@@ -1,39 +1,37 @@
-if FoodsoftArticleImport.enabled?
- Article.class_eval do
- def unequal_attributes(new_article, options = {})
- # try to convert different units when desired
- if options[:convert_units] == false
- new_price = nil
- new_unit_quantity = nil
- else
- new_price, new_unit_quantity = convert_units(new_article)
- end
- if new_price && new_unit_quantity
- new_unit = self.unit
- else
- new_price = new_article.price
- new_unit_quantity = new_article.unit_quantity
- new_unit = new_article.unit
- end
-
- attribute_hash = {
- :name => [self.name, new_article.name],
- :manufacturer => [self.manufacturer, new_article.manufacturer.to_s],
- :origin => [self.origin, new_article.origin],
- :unit => [self.unit, new_unit],
- :price => [self.price.to_f.round(2), new_price.to_f.round(2)],
- :tax => [self.tax, new_article.tax],
- :deposit => [self.deposit.to_f.round(2), new_article.deposit.to_f.round(2)],
- # take care of different num-objects.
- :unit_quantity => [self.unit_quantity.to_s.to_f, new_unit_quantity.to_s.to_f],
- :note => [self.note.to_s, new_article.note.to_s]
- }
- if options[:update_category] == true
- new_article_category = new_article.article_category
- attribute_hash[:article_category] = [self.article_category, new_article_category] unless new_article_category.blank?
- end
-
- Article.compare_attributes(attribute_hash)
+Article.class_eval do
+ def unequal_attributes(new_article, options = {})
+ # try to convert different units when desired
+ if options[:convert_units] == false
+ new_price = nil
+ new_unit_quantity = nil
+ else
+ new_price, new_unit_quantity = convert_units(new_article)
end
+ if new_price && new_unit_quantity
+ new_unit = self.unit
+ else
+ new_price = new_article.price
+ new_unit_quantity = new_article.unit_quantity
+ new_unit = new_article.unit
+ end
+
+ attribute_hash = {
+ :name => [self.name, new_article.name],
+ :manufacturer => [self.manufacturer, new_article.manufacturer.to_s],
+ :origin => [self.origin, new_article.origin],
+ :unit => [self.unit, new_unit],
+ :price => [self.price.to_f.round(2), new_price.to_f.round(2)],
+ :tax => [self.tax, new_article.tax],
+ :deposit => [self.deposit.to_f.round(2), new_article.deposit.to_f.round(2)],
+ # take care of different num-objects.
+ :unit_quantity => [self.unit_quantity.to_s.to_f, new_unit_quantity.to_s.to_f],
+ :note => [self.note.to_s, new_article.note.to_s]
+ }
+ if options[:update_category] == true
+ new_article_category = new_article.article_category
+ attribute_hash[:article_category] = [self.article_category, new_article_category] unless new_article_category.blank?
+ end
+
+ Article.compare_attributes(attribute_hash)
end
-end
\ No newline at end of file
+end
diff --git a/plugins/article_import/app/overrides/models/supplier_override.rb b/plugins/article_import/app/overrides/models/supplier_override.rb
index 62885aac..504bc26d 100644
--- a/plugins/article_import/app/overrides/models/supplier_override.rb
+++ b/plugins/article_import/app/overrides/models/supplier_override.rb
@@ -1,53 +1,51 @@
-if FoodsoftArticleImport.enabled?
- Supplier.class_eval do
- # Synchronise articles with spreadsheet.
- #
- # @param file [File] Spreadsheet file to parse
- # @param options [Hash] Options passed to {FoodsoftArticleImport#parse} except when listed here.
- # @option options [Boolean] :outlist_absent Set to +true+ to remove articles not in spreadsheet.
- # @option options [Boolean] :convert_units Omit or set to +true+ to keep current units, recomputing unit quantity and price.
- def sync_from_file(file, type, options = {})
- all_order_numbers = []
- updated_article_pairs, outlisted_articles, new_articles = [], [], []
- custom_codes_path = File.join(Rails.root, "config", "custom_codes.yml")
- opts = options.except(:convert_units, :outlist_absent)
- custom_codes_file_path = custom_codes_path if File.exist?(custom_codes_path)
- FoodsoftArticleImport.parse(file, custom_file_path: custom_codes_file_path, type: type, **opts) do |new_attrs, status, line|
- article = articles.undeleted.where(order_number: new_attrs[:order_number]).first
+Supplier.class_eval do
+ # Synchronise articles with spreadsheet.
+ #
+ # @param file [File] Spreadsheet file to parse
+ # @param options [Hash] Options passed to {FoodsoftArticleImport#parse} except when listed here.
+ # @option options [Boolean] :outlist_absent Set to +true+ to remove articles not in spreadsheet.
+ # @option options [Boolean] :convert_units Omit or set to +true+ to keep current units, recomputing unit quantity and price.
+ def sync_from_file(file, type, options = {})
+ all_order_numbers = []
+ updated_article_pairs, outlisted_articles, new_articles = [], [], []
+ custom_codes_path = File.join(Rails.root, "config", "custom_codes.yml")
+ opts = options.except(:convert_units, :outlist_absent)
+ custom_codes_file_path = custom_codes_path if File.exist?(custom_codes_path)
+ FoodsoftArticleImport.parse(file, custom_file_path: custom_codes_file_path, type: type, **opts) do |new_attrs, status, line|
+ article = articles.undeleted.where(order_number: new_attrs[:order_number]).first
- if new_attrs[:article_category].present? && options[:update_category]
- new_attrs[:article_category] = ArticleCategory.find_match(new_attrs[:article_category]) || ArticleCategory.create_or_find_by!(name: new_attrs[:article_category])
+ if new_attrs[:article_category].present? && options[:update_category]
+ new_attrs[:article_category] = ArticleCategory.find_match(new_attrs[:article_category]) || ArticleCategory.create_or_find_by!(name: new_attrs[:article_category])
+ else
+ new_attrs[:article_category] = nil
+ end
+
+ new_attrs[:tax] ||= FoodsoftConfig[:tax_default]
+ new_article = articles.build(new_attrs)
+ if status.nil?
+ if article.nil?
+ new_articles << new_article
else
- new_attrs[:article_category] = nil
- end
-
- new_attrs[:tax] ||= FoodsoftConfig[:tax_default]
- new_article = articles.build(new_attrs)
- if status.nil?
- if article.nil?
- new_articles << new_article
- else
- unequal_attributes = article.unequal_attributes(new_article, options.slice(:convert_units, :update_category))
- unless unequal_attributes.empty?
- article.attributes = unequal_attributes
- updated_article_pairs << [article, unequal_attributes]
- end
+ unequal_attributes = article.unequal_attributes(new_article, options.slice(:convert_units, :update_category))
+ unless unequal_attributes.empty?
+ article.attributes = unequal_attributes
+ updated_article_pairs << [article, unequal_attributes]
end
- elsif status == :outlisted && article.present?
- outlisted_articles << article
-
- # stop when there is a parsing error
- elsif status.is_a? String
- # @todo move I18n key to model
- raise I18n.t('articles.model.error_parse', :msg => status, :line => line.to_s)
end
+ elsif status == :outlisted && article.present?
+ outlisted_articles << article
- all_order_numbers << article.order_number if article
+ # stop when there is a parsing error
+ elsif status.is_a? String
+ # @todo move I18n key to model
+ raise I18n.t('articles.model.error_parse', :msg => status, :line => line.to_s)
end
- if options[:outlist_absent]
- outlisted_articles += articles.undeleted.where.not(order_number: all_order_numbers + [nil])
- end
- [updated_article_pairs, outlisted_articles, new_articles]
+
+ all_order_numbers << article.order_number if article
end
+ if options[:outlist_absent]
+ outlisted_articles += articles.undeleted.where.not(order_number: all_order_numbers + [nil])
+ end
+ [updated_article_pairs, outlisted_articles, new_articles]
end
end
diff --git a/plugins/article_import/lib/foodsoft_article_import/engine.rb b/plugins/article_import/lib/foodsoft_article_import/engine.rb
index a2eee118..49c54bab 100644
--- a/plugins/article_import/lib/foodsoft_article_import/engine.rb
+++ b/plugins/article_import/lib/foodsoft_article_import/engine.rb
@@ -6,7 +6,7 @@ module FoodsoftArticleImport
end
end
def default_foodsoft_config(cfg)
- cfg[:use_article_import] = false
+ cfg[:use_article_import] = true
end
end
end
diff --git a/plugins/article_import/spec/app_config.yml b/plugins/article_import/spec/app_config.yml
deleted file mode 100644
index e31af571..00000000
--- a/plugins/article_import/spec/app_config.yml
+++ /dev/null
@@ -1,34 +0,0 @@
-# Minimal Foodsoft configuration
-#
-# Without those settings, Foodsoft may not even work.
-# This file is used when running tests. When plugins would modify foodsoft behaviour
-# and they are enabled in the sample configuration, there is stable base to test with.
-
-default: &defaults
- multi_coop_install: false
- use_self_service: true
- default_scope: 'f'
-
- name: FC Minimal
-
- # true by default to keep compat with older installations, but test with false here
- use_nick: false
- use_article_import: true
-
- price_markup: 5
-
- # do we really need the following ones?
- tax_default: 6.0
- email_sender: noreply@minimal.test
-
- host: localhost
-
-
-development:
- <<: *defaults
-
-test:
- <<: *defaults
-
-production:
- <<: *defaults
diff --git a/plugins/article_import/spec/fixtures/bnn_file01.bnn b/plugins/article_import/spec/fixtures/bnn_file01.bnn
deleted file mode 100644
index b75b63cf..00000000
--- a/plugins/article_import/spec/fixtures/bnn_file01.bnn
+++ /dev/null
@@ -1,5 +0,0 @@
-BNN;3;0;Naturkost Nord, Hamburg;T;Angebot Nr. 0922;EUR;20220905;20221001;20220825;837;1
-29932;;;;4280001958081;4280001958203;Walnoten (ongeroosterd);bio;;;med;;GR;C%;DE-?KO-001;120;1302;10;55;;1;;1;1 kg;1;N;930190;99260;;1,41;;;;1;;;4,49;2,34;J;;2;3;;;;;;;;;;;;;;;;;;;A;;;;;Kg;28,571;;
-28391;;;;4280001958081;4280001958203;Pijnboompitten;dem;;;med;;GR;C%;DE-?KO-001;120;1302;10;55;;1;;1;100 g;10;N;930190;99260;;1,41;;;;1;;;5,56;2.89;J;;2;3;;;;;;;;;;;;;;;;;;;A;;;;;Kg;28,571;;
-1829;;;;4280001958081;4280001958203;Appelsap (verpakt);;;;med;;GR;C%;DE-?KO-001;120;1302;10;55;;1;4x250 ml;10;4x250 ml;10;N;930190;99260;;3,21;;;;1;;;4,49;2.89;J;;2;3;;;;;;;;;;;;;;;;;;;A;;;;;ml;28,571;;
-177813;;;;4280001958081;4280001958203;Tomaten;bio;;;med;;GR;C%;DE-?KO-001;120;1302;10;55;;1;;1;500 g;20;N;930190;99260;;1,20;;;;1;;;4,49;2.89;J;;2;3;;;;;;;;;;;;;;;;;;;A;;;;;g;28,571;;
\ No newline at end of file
diff --git a/plugins/article_import/spec/fixtures/bnn_file_02.bnn b/plugins/article_import/spec/fixtures/bnn_file_02.bnn
deleted file mode 100644
index e3dba5bb..00000000
--- a/plugins/article_import/spec/fixtures/bnn_file_02.bnn
+++ /dev/null
@@ -1,2 +0,0 @@
-BNN;3;0;Naturkost Nord, Hamburg;T;Angebot Nr. 0922;EUR;20220905;20221001;20220825;837;1
-1;;;;4280001958081;4280001958203;Tomatoes;organic;;;med;;GR;C%;DE-?KO-001;120;1302;10;55;;1;;20;500 g;1;N;930190;99260;;1,41;;;;1;;;4,49;1,20;J;;2;3;;;;;;;;;;;;;;;;;;;A;;;;;g;28,571;;
\ No newline at end of file
diff --git a/plugins/article_import/spec/fixtures/odin_file_01.xml b/plugins/article_import/spec/fixtures/odin_file_01.xml
deleted file mode 100644
index 3b60e83e..00000000
--- a/plugins/article_import/spec/fixtures/odin_file_01.xml
+++ /dev/null
@@ -1,273 +0,0 @@
-
-
-
-1039
-1.08
-Estafette Associatie C.V.
-Geldermalsen
-
-
-8719325207668
-Walnoten (ongeroosterd)
-Nucli rose
-
-0
-0
-0
-1
-kg
-Stuk
-0
-Het warme woud
-bio
-
-
-NL
-
-6
-1017515
-29932
-10
-Actief
-druiven*
-0
-0
-2
-2
-0
-0
-0
-2
-2
-0
-2
-0
-2
-0
-2
-2
-2
-2
-1
-0
-2
-0
-2
-2
-
-
-
-0
-0
-0
-0
-1
-
-2
-0
-
-adviesprijs
-2022-08-18
-2.34
-7.95
-
-
-
-8719325207668
-Pijnboompitten
-Nucli rose
-
-0
-0
-0
-100
-g
-Stuk
-0
-NELEMAN
-dem
-
-
-TR
-
-6
-1017515
-28391
-10
-Actief
-druiven*
-0
-0
-2
-2
-0
-0
-0
-2
-2
-0
-2
-0
-2
-0
-2
-2
-2
-2
-1
-0
-2
-0
-2
-2
-
-
-
-0
-0
-0
-0
-1
-
-2
-0
-
-adviesprijs
-2022-08-18
-5.56
-7.95
-
-
-
-8719325207668
-Appelsap (verpakt)
-Nucli rose
-
-0
-0
-0
-4x250
-ml
-Stuk
-0.4
-Appelgaarde
-
-
-
-DE
-
-6
-1017515
-1829
-10
-Actief
-druiven*
-0
-0
-2
-2
-0
-0
-0
-2
-2
-0
-2
-0
-2
-0
-2
-2
-2
-2
-1
-0
-2
-0
-2
-2
-
-
-
-0
-0
-0
-0
-1
-
-2
-0
-
-adviesprijs
-2022-08-18
-3.21
-7.95
-
-
-
-8719325207668
-Tomaten
-Nucli rose
-
-0
-0
-0
-500
-g
-Stuk
-0
-De röde hof
-bio
-
-
-DE
-
-6
-1017515
-177813
-20
-Actief
-druiven*
-0
-0
-2
-2
-0
-0
-0
-2
-2
-0
-2
-0
-2
-0
-2
-2
-2
-2
-1
-0
-2
-0
-2
-2
-
-
-
-0
-0
-0
-0
-1
-
-2
-0
-
-adviesprijs
-2022-08-18
-1.2
-7.95
-
-
-
\ No newline at end of file
diff --git a/plugins/article_import/spec/fixtures/odin_file_02.xml b/plugins/article_import/spec/fixtures/odin_file_02.xml
deleted file mode 100644
index c732b4d5..00000000
--- a/plugins/article_import/spec/fixtures/odin_file_02.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-
-
-
-1039
-1.08
-Estafette Associatie C.V.
-Geldermalsen
-
-
-8719325207668
-Tomatoes
-Nucli rose
-
-0
-0
-0
-500
-g
-Stuk
-0
-De röde hof
-organic
-
-
-Somewhere, UK
-
-6
-1017515
-1
-20
-Actief
-druiven*
-0
-0
-2
-2
-0
-0
-0
-2
-2
-0
-2
-0
-2
-0
-2
-2
-2
-2
-1
-0
-2
-0
-2
-2
-
-
-
-0
-0
-0
-0
-1
-
-2
-0
-
-adviesprijs
-2022-08-18
-1.2
-7.95
-
-
-
\ No newline at end of file
diff --git a/plugins/article_import/spec/integration/articles_spec.rb b/plugins/article_import/spec/integration/articles_spec.rb
deleted file mode 100644
index 0a547515..00000000
--- a/plugins/article_import/spec/integration/articles_spec.rb
+++ /dev/null
@@ -1,169 +0,0 @@
-require_relative '../test_helper'
-require_relative '../../../../spec/spec_helper'
-
-feature ArticlesController do
-
- let(:user) { create(:user, groups: [create(:workgroup, role_article_meta: true)]) }
- let(:supplier) { create(:supplier) }
- let!(:article_category) { create(:article_category) }
-
- before { login user }
-
- describe ':index', js: true do
- before do
- login user
- visit supplier_articles_path(supplier_id: supplier.id)
- end
-
- it 'can visit supplier articles path' do
- expect(page).to have_content(supplier.name)
- expect(page).to have_content(I18n.t('articles.index.edit_all'))
- end
-
- it 'can create a new article' do
- click_on I18n.t('articles.index.new')
- expect(page).to have_selector('form#new_article')
- article = build(:article, supplier: supplier, article_category: article_category)
- within('#new_article') do
- fill_in 'article_name', :with => article.name
- fill_in 'article_unit', :with => article.unit
- select article.article_category.name, :from => 'article_article_category_id'
- fill_in 'article_price', :with => article.price
- fill_in 'article_unit_quantity', :with => article.unit_quantity
- fill_in 'article_tax', :with => article.tax
- fill_in 'article_deposit', :with => article.deposit
- # "Element cannot be scrolled into view" error, js as workaround
- # find('input[type="submit"]').click
- page.execute_script('$("form#new_article").submit();')
- end
- expect(page).to have_content(article.name)
- end
- end
-
- describe ':upload' do
- let(:filename) { 'foodsoft_file_02.csv' }
- let(:file) { Rails.root.join("spec/fixtures/#{filename}") }
-
- before do
- visit upload_supplier_articles_path(supplier_id: supplier.id)
- attach_file 'articles_file', file
- end
-
- Dir.glob('spec/fixtures/foodsoft_file_01.*') do |test_file|
- describe "can import articles from #{test_file}" do
- let(:file) { Rails.root.join(test_file) }
-
- it do
- find("#articles_type option[value='foodsoft']").select_option
- find('input[type="submit"]').click
- expect(find("tr:nth-child(1) #new_articles__note").value).to eq "bio ◎"
- expect(find("tr:nth-child(2) #new_articles__name").value).to eq "Pijnboompitten"
-
- 4.times do |i|
- all("tr:nth-child(#{i + 1}) select > option")[1].select_option
- end
- find('input[type="submit"]').click
- expect(page).to have_content("Pijnboompitten")
-
- expect(supplier.articles.count).to eq 4
- end
- end
- end
-
- Dir.glob('spec/fixtures/bnn_file_01.*') do |test_file|
- describe "can import articles from #{test_file}" do
- let(:file) { Rails.root.join(test_file) }
-
- it do
- find("#articles_type option[value='bnn']").select_option
- find('input[type="submit"]').click
- expect(find("tr:nth-child(1) #new_articles__note").value).to eq "bio"
- expect(find("tr:nth-child(1) #new_articles__name").value).to eq "Walnoten (ongeroosterd)"
- # set article category
- 4.times do |i|
- all("tr:nth-child(#{i + 1}) select > option")[1].select_option
- end
- find('input[type="submit"]').click
-
- expect(page).to have_content("Pijnboompitten")
-
- expect(supplier.articles.count).to eq 4
- end
- end
- end
- end
-
- describe "updates" do
- file_paths = ['spec/fixtures/foodsoft_file_02.csv', 'plugins/article_import/spec/fixtures/bnn_file_02.bnn', 'plugins/article_import/spec/fixtures/odin_file_02.xml']
- let(:filename) { 'foodsoft_file_02.csv' }
- let(:file) { Rails.root.join("spec/fixtures/#{filename}") }
- let(:val) { 'foodsoft' }
- let(:type) { %w[foodsoft bnn odin] }
-
- before do
- visit upload_supplier_articles_path(supplier_id: supplier.id)
- attach_file 'articles_file', file
- find("#articles_type option[value='#{val}']").select_option
- end
-
- file_paths.each_with_index do |test_file, index|
- describe "updates article for #{test_file}" do
- let(:article) { create(:article, supplier: supplier, name: 'Foobar', order_number: 1, unit: '250 g') }
- let(:file) { Rails.root.join(test_file) }
- let(:val) { type[index] }
-
- it do
- article.reload
- find('input[type="submit"]').click
- expect(find("#articles_#{article.id}_name").value).to eq 'Tomatoes'
- find('input[type="submit"]').click
- article.reload
- expect(article.name).to eq 'Tomatoes'
- if type[index] == "odin"
- expect([article.unit, article.unit_quantity, article.price]).to eq ['500gr', 20, 1.20]
- else
- expect([article.unit, article.unit_quantity, article.price]).to eq ['500 g', 20, 1.20]
- end
- end
-
- it "handles missing data" do
- find('input[type="submit"]').click # to overview
- find('input[type="submit"]').click # missing category, re-show form
- expect(find('tr.alert')).to be_present
- expect(supplier.articles.count).to eq 0
-
- all("tr select > option")[1].select_option
- find('input[type="submit"]').click # now it should succeed
- expect(supplier.articles.count).to eq 1
- end
- end
-
- describe "can remove an existing article" do
- let!(:article) { create(:article, supplier: supplier, name: 'Foobar', order_number: 99999) }
-
- it do
- check('articles_outlist_absent')
- find('input[type="submit"]').click
- expect(find("#outlisted_articles_#{article.id}", visible: :all)).to be_present
-
- all("tr select > option")[1].select_option
- find('input[type="submit"]').click
- expect(article.reload.deleted?).to be true
- end
- end
-
- describe "can convert units when updating" do
- let!(:article) { create(:article, supplier: supplier, order_number: 1, unit: '250 g') }
-
- it do
- check('articles_convert_units')
- find('input[type="submit"]').click
- expect(find("#articles_#{article.id}_name").value).to eq 'Tomatoes'
- find('input[type="submit"]').click
- article.reload
- expect([article.unit, article.unit_quantity, article.price]).to eq ['250 g', 40, 0.6]
- end
- end
- end
- end
-end
diff --git a/plugins/article_import/spec/integration/supplier_spec.rb b/plugins/article_import/spec/integration/supplier_spec.rb
deleted file mode 100644
index d80c0d52..00000000
--- a/plugins/article_import/spec/integration/supplier_spec.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-require_relative '../test_helper'
-require_relative '../../../../spec/spec_helper'
-
-describe Supplier do
- let(:supplier) { create :supplier }
-
- context 'syncs from file' do
- it 'imports and updates articles' do
- article1 = create(:article, supplier: supplier, order_number: 177813, unit: '250 g', price: 0.1)
- article2 = create(:article, supplier: supplier, order_number: 12345)
- supplier.articles = [article1, article2]
- options = { filename: 'foodsoft_file_01.csv' }
- options[:outlist_absent] = true
- options[:convert_units] = true
- updated_article_pairs, outlisted_articles, new_articles = supplier.sync_from_file(Rails.root.join('spec/fixtures/foodsoft_file_01.csv'), 'foodsoft', options)
- expect(new_articles.length).to be > 0
- expect(updated_article_pairs.first[1][:name]).to eq 'Tomaten'
- expect(outlisted_articles.first).to eq article2
- end
- end
-end
\ No newline at end of file
diff --git a/plugins/article_import/spec/spec_helper.rb b/plugins/article_import/spec/spec_helper.rb
new file mode 100644
index 00000000..d3e43d53
--- /dev/null
+++ b/plugins/article_import/spec/spec_helper.rb
@@ -0,0 +1,100 @@
+# frozen_string_literal: true
+
+require 'simplecov'
+SimpleCov.start
+# This file was generated by the `rspec --init` command. Conventionally, all
+# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
+# The generated `.rspec` file contains `--require spec_helper` which will cause
+# this file to always be loaded, without a need to explicitly require it in any
+# files.
+#
+# Given that it is always loaded, you are encouraged to keep this file as
+# light-weight as possible. Requiring heavyweight dependencies from this file
+# will add to the boot time of your test suite on EVERY test run, even for an
+# individual file that may not need all of that loaded. Instead, consider making
+# a separate helper file that requires the additional dependencies and performs
+# the additional setup, and require it from the spec files that actually need
+# it.
+#
+# See https://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
+RSpec.configure do |config|
+ # rspec-expectations config goes here. You can use an alternate
+ # assertion/expectation library such as wrong or the stdlib/minitest
+ # assertions if you prefer.
+ config.expect_with :rspec do |expectations|
+ # This option will default to `true` in RSpec 4. It makes the `description`
+ # and `failure_message` of custom matchers include text for helper methods
+ # defined using `chain`, e.g.:
+ # be_bigger_than(2).and_smaller_than(4).description
+ # # => "be bigger than 2 and smaller than 4"
+ # ...rather than:
+ # # => "be bigger than 2"
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
+ end
+
+ # rspec-mocks config goes here. You can use an alternate test double
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
+ config.mock_with :rspec do |mocks|
+ # Prevents you from mocking or stubbing a method that does not exist on
+ # a real object. This is generally recommended, and will default to
+ # `true` in RSpec 4.
+ mocks.verify_partial_doubles = true
+ end
+
+ # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
+ # have no way to turn it off -- the option exists only for backwards
+ # compatibility in RSpec 3). It causes shared context metadata to be
+ # inherited by the metadata hash of host groups and examples, rather than
+ # 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.
+ # # 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
diff --git a/plugins/article_import/spec/test_helper.rb b/plugins/article_import/spec/test_helper.rb
deleted file mode 100644
index 527a16d8..00000000
--- a/plugins/article_import/spec/test_helper.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-module TestHelper
- ENV["FOODSOFT_APP_CONFIG"] = "plugins/article_import/spec/app_config.yml"
-end
-
-RSpec.configure do |config|
- config.include TestHelper, :type => :feature
-end