finish plugin for bnn, foodsoft, odin uploads

This commit is contained in:
viehlieb 2023-03-30 14:55:24 +02:00
parent 9d0e2fdafc
commit e42baa1d3b
9 changed files with 167 additions and 210 deletions

View file

@ -1,18 +1,20 @@
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')
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')
@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')
@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
@ignored_article_count = 0
rescue => error
redirect_to upload_supplier_articles_path(@supplier), :alert => I18n.t('errors.general_msg', :msg => error.message)
end
end
end

View file

@ -1,37 +1,39 @@
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
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
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.compare_attributes(attribute_hash)
end
end
end
end

View file

@ -1,51 +1,53 @@
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 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
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
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
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
new_attrs[:article_category] = nil
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)
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
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
all_order_numbers << article.order_number if article
end
all_order_numbers << article.order_number if article
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
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