allow to match category names on import/sync
This commit is contained in:
parent
16b78ba2a0
commit
d9c61b2db3
8 changed files with 30 additions and 6 deletions
|
@ -148,7 +148,7 @@ class ArticlesController < ApplicationController
|
||||||
no_category = ArticleCategory.new
|
no_category = ArticleCategory.new
|
||||||
articles.each do |row|
|
articles.each do |row|
|
||||||
# fallback to Others category
|
# fallback to Others category
|
||||||
category = (ArticleCategory.find_by_name(row[:category]) or no_category)
|
category = (ArticleCategory.find_match(row[:category]) or no_category)
|
||||||
# creates a new article and price
|
# creates a new article and price
|
||||||
article = Article.new( :name => row[:name],
|
article = Article.new( :name => row[:name],
|
||||||
:note => row[:note],
|
:note => row[:note],
|
||||||
|
|
|
@ -12,10 +12,26 @@ class ArticleCategory < ActiveRecord::Base
|
||||||
|
|
||||||
normalize_attributes :name, :description
|
normalize_attributes :name, :description
|
||||||
|
|
||||||
validates :name, :presence => true, :uniqueness => true, :length => { :in => 2..20 }
|
validates :name, :presence => true, :uniqueness => true, :length => { :minimum => 2 }
|
||||||
|
|
||||||
before_destroy :check_for_associated_articles
|
before_destroy :check_for_associated_articles
|
||||||
|
|
||||||
|
# Find a category that matches a category name; may return nil.
|
||||||
|
# TODO more intelligence like remembering earlier associations (global and/or per-supplier)
|
||||||
|
def self.find_match(category)
|
||||||
|
return if category.blank? or category.length < 3
|
||||||
|
c = nil
|
||||||
|
## exact match - not needed, will be returned by next query as well
|
||||||
|
#c ||= ArticleCategory.where(name: category).first
|
||||||
|
# case-insensitive substring match (take the closest match = shortest)
|
||||||
|
c = ArticleCategory.where('name LIKE ?', "%#{category}%") unless c and c.any?
|
||||||
|
# case-insensitive phrase present in category description
|
||||||
|
c = ArticleCategory.where('description LIKE ?', "%#{category}%").select {|s| s.description.match /(^|,)\s*#{category}\s*(,|$)/i} unless c and c.any?
|
||||||
|
# return closest match if there are multiple
|
||||||
|
c = c.sort_by {|s| s.name.length}.first if c.respond_to? :sort_by
|
||||||
|
c
|
||||||
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
# Deny deleting the category when there are associated articles.
|
# Deny deleting the category when there are associated articles.
|
||||||
|
|
|
@ -19,6 +19,7 @@ class SharedArticle < ActiveRecord::Base
|
||||||
:deposit => deposit,
|
:deposit => deposit,
|
||||||
:unit_quantity => unit_quantity,
|
:unit_quantity => unit_quantity,
|
||||||
:order_number => number,
|
:order_number => number,
|
||||||
|
:article_category => ArticleCategory.find_match(category),
|
||||||
# convert to db-compatible-string
|
# convert to db-compatible-string
|
||||||
:shared_updated_on => updated_on.to_formatted_s(:db)
|
:shared_updated_on => updated_on.to_formatted_s(:db)
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
= simple_form_for @article_category do |f|
|
= simple_form_for @article_category do |f|
|
||||||
= f.input :name
|
= f.input :name
|
||||||
= f.input :description
|
= f.input :description, as: :text, input_html: {class: 'input-xxlarge'}
|
||||||
.form-actions
|
.form-actions
|
||||||
= f.submit class: 'btn'
|
= f.submit class: 'btn'
|
||||||
= link_to t('ui.or_cancel'), article_categories_path
|
= link_to t('ui.or_cancel'), article_categories_path
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
- @article_categories.each do |article_category|
|
- @article_categories.each do |article_category|
|
||||||
%tr
|
%tr
|
||||||
%td= article_category.name
|
%td= article_category.name
|
||||||
%td= article_category.description
|
%td= truncate article_category.description, length: 50
|
||||||
%td
|
%td
|
||||||
= link_to t('ui.edit'), edit_article_category_path(article_category), class: 'btn btn-mini'
|
= link_to t('ui.edit'), edit_article_category_path(article_category), class: 'btn btn-mini'
|
||||||
= link_to t('ui.delete'), article_category, :method => :delete, :data => {:confirm => t('.confirm_delete')},
|
= link_to t('ui.delete'), article_category, :method => :delete, :data => {:confirm => t('.confirm_delete')},
|
||||||
|
|
|
@ -26,7 +26,7 @@ en:
|
||||||
unit_quantity_short: U.Q.
|
unit_quantity_short: U.Q.
|
||||||
units: Units
|
units: Units
|
||||||
article_category:
|
article_category:
|
||||||
description: Description
|
description: Import names
|
||||||
name: Name
|
name: Name
|
||||||
article_price:
|
article_price:
|
||||||
deposit: Deposit
|
deposit: Deposit
|
||||||
|
@ -1299,6 +1299,8 @@ en:
|
||||||
hints:
|
hints:
|
||||||
article:
|
article:
|
||||||
unit: e.g. KG or 1L or 500g
|
unit: e.g. KG or 1L or 500g
|
||||||
|
article_category:
|
||||||
|
description: comma-separated list of category names recognised at import/synchronisation
|
||||||
message:
|
message:
|
||||||
private: Message doesn’t show in Foodsoft mail inbox
|
private: Message doesn’t show in Foodsoft mail inbox
|
||||||
order_article:
|
order_article:
|
||||||
|
|
|
@ -26,7 +26,7 @@ nl:
|
||||||
unit_quantity_short: Colli
|
unit_quantity_short: Colli
|
||||||
units: Eenheden
|
units: Eenheden
|
||||||
article_category:
|
article_category:
|
||||||
description: Omschrijving
|
description: Import namen
|
||||||
name: Naam
|
name: Naam
|
||||||
article_price:
|
article_price:
|
||||||
deposit: Statiegeld
|
deposit: Statiegeld
|
||||||
|
@ -1294,6 +1294,8 @@ nl:
|
||||||
hints:
|
hints:
|
||||||
article:
|
article:
|
||||||
unit: 'Bijvoorbeeld: KG of 1L of 500g'
|
unit: 'Bijvoorbeeld: KG of 1L of 500g'
|
||||||
|
article_category:
|
||||||
|
description: komma-gescheiden lijst van namen die herkend worden bij uploaden/synchroniseren
|
||||||
message:
|
message:
|
||||||
private: Bericht wordt niet getoond in de Foodsoft inbox.
|
private: Bericht wordt niet getoond in de Foodsoft inbox.
|
||||||
order_article:
|
order_article:
|
||||||
|
|
|
@ -22,6 +22,9 @@ ActiveSupport.on_load(:after_initialize) do
|
||||||
SharedArticle.class_eval do
|
SharedArticle.class_eval do
|
||||||
alias_attribute :number, :order_number
|
alias_attribute :number, :order_number
|
||||||
alias_attribute :updated_on, :updated_at
|
alias_attribute :updated_on, :updated_at
|
||||||
|
def category
|
||||||
|
ArticleCategory.find(article_category_id).name
|
||||||
|
end
|
||||||
def self.find_by_number(n)
|
def self.find_by_number(n)
|
||||||
find_by_order_number(n)
|
find_by_order_number(n)
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue