Skip to content

Commit

Permalink
Started with #25
Browse files Browse the repository at this point in the history
  • Loading branch information
lentschi committed Nov 26, 2023
1 parent 56acdcb commit c56cf44
Show file tree
Hide file tree
Showing 10 changed files with 155 additions and 158 deletions.
1 change: 1 addition & 0 deletions app/controllers/article_units_controller.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
class ArticleUnitsController < ApplicationController
before_action :authenticate_article_meta
before_action :load_available_units, only: [:search, :create, :destroy]

def index; end
Expand Down
35 changes: 34 additions & 1 deletion app/controllers/articles_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ class ArticlesController < ApplicationController
before_action :authenticate_article_meta, :find_supplier

before_action :load_article, only: [:edit, :update]
before_action :load_article_units, only: [:edit, :update, :new, :create, :parse_upload, :sync, :update_synchronized, :edit_all]
before_action :load_article_units, only: [:edit, :update, :new, :create, :parse_upload, :sync, :update_synchronized, :edit_all, :migrate_units]
before_action :new_empty_article_ratio, only: [:edit, :update, :new, :create, :parse_upload, :sync, :update_synchronized]

def index
Expand Down Expand Up @@ -94,6 +94,39 @@ def edit_all
@articles = @supplier.articles.undeleted
end

def migrate_units
@articles = @supplier.articles.undeleted
@articles.each_with_index do |article, _index|
article_version = article.latest_article_version
quantity = 1
ratios = article_version.article_unit_ratios

next if ratios.length > 1

if ratios.length == 1 && ratios[0].quantity != 1 && ratios[0].unit == 'XPP'
quantity = ratios[0].quantity
end

conversion_result = ArticleUnitsLib.convert_old_unit(article_version.unit, quantity)

next if conversion_result.nil?

article_version.unit = nil
article_version.supplier_order_unit = conversion_result[:supplier_order_unit]
article_version.group_order_granularity = conversion_result[:group_order_granularity]
article_version.group_order_unit = conversion_result[:group_order_unit]

first_ratio = conversion_result[:first_ratio]
if first_ratio.nil?
article_version.article_unit_ratios = []
else
article_version.article_unit_ratios = [article_version.article_unit_ratios.build(first_ratio.merge(sort: 1))]
end
end

render :edit_all
end

# Updates all article of specific supplier
def update_all
invalid_articles = false
Expand Down
1 change: 1 addition & 0 deletions app/views/articles/_edit_all_table.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
%td= form.text_field 'name', class: 'input-medium'
%td
.d-flex.gap-1.align-items-center
= form.hidden_field :unit, id: 'article_unit_hidden', value: ''
= form.input :supplier_order_unit, as: :select, collection: @article_units, label: false, value: article.supplier_order_unit, include_blank: t('Custom (avoid if possible!)') + ':', input_html: {class: 'input-medium'}
= form.input :unit, input_html: {class: 'input-mini ml-1'}, label: false
%div.btn-link.toggle-extra-units.text-decoration-none.default-values
Expand Down
1 change: 1 addition & 0 deletions app/views/articles/index.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
.btn-group
= link_to t('.new'), new_supplier_article_path(@supplier), remote: true, class: "btn #{'btn-primary' if @supplier.supplier_remote_source.nil?}"
= link_to t('.edit_all'), edit_all_supplier_articles_path(@supplier), class: 'btn'
= link_to t('.migrate_units'), migrate_units_supplier_articles_path(@supplier), class: 'btn'
= link_to t('.upload'), upload_supplier_articles_path(@supplier), class: 'btn'
= link_to t('.download'), supplier_articles_path(@supplier, format: :csv), class: 'btn'
- if current_user.role_orders?
Expand Down
1 change: 1 addition & 0 deletions config/locales/de.yml
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,7 @@ de:
change_supplier: Lieferant wechseln ...
download: Artikel herunterladen
edit_all: Alle bearbeiten
migrate_units: Alte Artikeleinheiten migrieren
ext_db:
import: Suchen/Importieren
sync: Synchronisieren
Expand Down
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@
collection do
post :update_selected
get :edit_all
get :migrate_units
post :update_all
get :upload
post :parse_upload
Expand Down
1 change: 0 additions & 1 deletion config/units-of-measure/.~lock.translations_piece.csv#

This file was deleted.

1 change: 0 additions & 1 deletion config/units-of-measure/.~lock.translations_scalar-en.csv#

This file was deleted.

153 changes: 0 additions & 153 deletions db/migrate/20221026102301_alter_articles_add_more_unit_logic.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,60 +18,6 @@ def up
t.column :unit, :string, length: 3
end

latest_article_versions = select_all(%{
SELECT article_versions.*
FROM article_versions
JOIN (
SELECT article_id, MAX(created_at) AS max_created_at
FROM article_versions
GROUP BY article_id
) AS latest_article_versions
ON latest_article_versions.article_id = article_versions.article_id
AND latest_article_versions.max_created_at = article_versions.created_at
})
latest_article_versions.each do |latest_article_version|
unit_quantity = latest_article_version['unit_quantity'].nil? ? 1.0 : latest_article_version['unit_quantity'].to_f
new_unit_data = convert_old_unit(latest_article_version['unit'], unit_quantity)
next if new_unit_data.nil?

new_version_id = insert(%{
INSERT INTO article_versions (
article_id, price, tax, deposit, created_at, name, article_category_id, note, availability, manufacturer, origin, order_number, updated_at, supplier_order_unit, group_order_granularity, group_order_unit, billing_unit, price_unit)
VALUES(
#{quote latest_article_version['article_id']},
#{quote latest_article_version['price'].to_f * unit_quantity},
#{quote latest_article_version['tax']},
#{quote latest_article_version['deposit']},
NOW(),
#{quote latest_article_version['name']},
#{quote latest_article_version['article_category_id']},
#{quote latest_article_version['note']},
#{quote latest_article_version['availability']},
#{quote latest_article_version['manufacturer']},
#{quote latest_article_version['origin']},
#{quote latest_article_version['order_number']},
NOW(),
#{quote new_unit_data[:supplier_order_unit]},
#{quote new_unit_data[:group_order_granularity]},
#{quote new_unit_data[:group_order_unit]},
#{quote new_unit_data[:supplier_order_unit]},
#{quote new_unit_data[:supplier_order_unit]}
)
})

next if new_unit_data[:first_ratio].nil?

insert(%{
INSERT INTO article_unit_ratios (article_version_id, sort, quantity, unit)
VALUES (
#{quote new_version_id},
#{quote 1},
#{quote new_unit_data[:first_ratio][:quantity]},
#{quote new_unit_data[:first_ratio][:unit]}
)
})
end

article_versions = select_all('SELECT id, unit, unit_quantity, price FROM article_versions WHERE unit_quantity > 1 AND NOT unit IS NULL')
article_versions.each do |article_version|
insert(%{
Expand Down Expand Up @@ -154,103 +100,4 @@ def down
t.change :tolerance, :integer, null: false
end
end

private

def convert_old_unit(old_compound_unit_str, unit_quantity)
md = old_compound_unit_str.match(%r{^\s*([0-9][0-9,./]*)?\s*([A-Za-z\u00C0-\u017F.]+)\s*$})
return nil if md.nil?

unit = get_unit_from_old_str(md[2])
return nil if unit.nil?

quantity = get_quantity_from_old_str(md[1])

if quantity == 1 && unit_quantity == 1
{
supplier_order_unit: unit,
first_ratio: nil,
group_order_granularity: 1.0,
group_order_unit: unit
}
else
supplier_order_unit = unit.starts_with?('X') && unit != 'XPK' ? 'XPK' : 'XPP'
{
supplier_order_unit: supplier_order_unit,
first_ratio: {
quantity: quantity * unit_quantity,
unit: unit
},
group_order_granularity: unit_quantity > 1 ? quantity : 1.0,
group_order_unit: unit_quantity > 1 ? unit : supplier_order_unit
}
end
end

def get_quantity_from_old_str(quantity_str)
return 1 if quantity_str.nil?

quantity_str = quantity_str
.gsub(',', '.')
.gsub(' ', '')

division_parts = quantity_str.split('/').map(&:to_f)

if division_parts.length == 2
division_parts[0] / division_parts[1]
else
quantity_str.to_f
end
end

def get_unit_from_old_str(old_unit_str)
unit_str = old_unit_str.strip.downcase
matching_unit_arr = ArticleUnitsLib.untranslated_units
.select { |_key, unit| unit[:visible] && (unit[:symbol] == unit_str || matches_unit_name(unit, unit_str)) }
.to_a
return nil if matching_unit_arr.empty?

matching_unit_arr[0][0]
end

# Temporary workaround to
# a. map single names to unit specs' name fields (which include multiple names separated by commas)
# b. include some German unit names
# TODO: Do unit translations and matching properly somehow
# see https://github.com/foodcoopsat/foodsoft_hackathon/issues/10
def matches_unit_name(unit, unit_str)
unit_str = case unit_str
when "gr", "grm"
"gramm"
when "kilo"
"kilogramm"
when "dkg"
"decagramm"
when "bund", "bd", "bd."
"bunch"
when "stück", "stk", "st", "stk.", "stueck"
"piece"
when "glas", "gl"
"glass"
when "pkg", "packung", "pkt", "pkg."
"package"
when "schale"
"tray pack"
when "topf", "tiegel"
"pot"
when "flasche", "fl", "fl."
"bottle"
when "port", "port."
"portion"
when "stange"
"stick"
else
unit_str
end

name = unit[:name].downcase
return true if name == unit_str

name.split(',').map(&:strip).include?(unit_str)
end
end
Loading

0 comments on commit c56cf44

Please sign in to comment.