allow to match category names on import/sync

This commit is contained in:
wvengen 2014-05-21 14:12:38 +02:00
parent 16b78ba2a0
commit d9c61b2db3
8 changed files with 30 additions and 6 deletions

View file

@ -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],

View file

@ -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.

View file

@ -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)
) )

View file

@ -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

View file

@ -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')},

View file

@ -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 doesnt show in Foodsoft mail inbox private: Message doesnt show in Foodsoft mail inbox
order_article: order_article:

View file

@ -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:

View file

@ -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