From 2461a55a8a5bf90943ee263c23b088244a389ae4 Mon Sep 17 00:00:00 2001 From: twothreenine Date: Tue, 23 Jul 2024 00:16:06 +0200 Subject: [PATCH] Article CSV: fix #47 and #46 - rearrange CSV columns as I suggested in #47 - add locales for column headings according to my suggestions in #50 (to do: adjust terms across menus -- post-merge?) - update documentation of CSV layout (#46) TO DO: #83, #81 (more important) #80, #82 (less important) any adaptations for rearranged tables necessary which I've overlooked? (for example sync feature) --- app/lib/articles_csv.rb | 42 +++++++-------- app/lib/foodsoft_file.rb | 28 +++++----- app/views/articles/upload.html.haml | 77 ++++++++++++++++++---------- config/locales/de.yml | 8 +++ config/locales/en.yml | 10 +++- spec/fixtures/foodsoft_file_01.csv | 10 ++-- spec/fixtures/foodsoft_file_01.ods | Bin 16501 -> 4388 bytes spec/fixtures/foodsoft_file_01.xls | Bin 7680 -> 27648 bytes spec/fixtures/foodsoft_file_01.xlsx | Bin 5913 -> 10154 bytes spec/fixtures/foodsoft_file_02.csv | 4 +- 10 files changed, 108 insertions(+), 71 deletions(-) diff --git a/app/lib/articles_csv.rb b/app/lib/articles_csv.rb index 2f14593b..8c6b3696 100644 --- a/app/lib/articles_csv.rb +++ b/app/lib/articles_csv.rb @@ -6,21 +6,21 @@ def header Article.human_attribute_name(:availability_short), Article.human_attribute_name(:order_number), Article.human_attribute_name(:name), - Article.human_attribute_name(:note), - Article.human_attribute_name(:manufacturer), - Article.human_attribute_name(:origin), - Article.human_attribute_name(:unit), - Article.human_attribute_name(:price), - Article.human_attribute_name(:tax), - Article.human_attribute_name(:deposit), Article.human_attribute_name(:supplier_order_unit), - Article.human_attribute_name(:price_unit), - Article.human_attribute_name(:group_order_unit), - Article.human_attribute_name(:group_order_granularity), + Article.human_attribute_name(:custom_unit), + Article.human_attribute_name(:ratios_to_supplier_order_unit), Article.human_attribute_name(:minimum_order_quantity), Article.human_attribute_name(:billing_unit), + Article.human_attribute_name(:group_order_granularity), + Article.human_attribute_name(:group_order_unit), + Article.human_attribute_name(:price), + Article.human_attribute_name(:price_unit), + Article.human_attribute_name(:tax), + Article.human_attribute_name(:deposit), + Article.human_attribute_name(:note), Article.human_attribute_name(:article_category), - Article.human_attribute_name(:ratios_to_supplier_order_unit) + Article.human_attribute_name(:origin), + Article.human_attribute_name(:manufacturer) ] end @@ -30,21 +30,21 @@ def data article.availability ? I18n.t('simple_form.yes') : I18n.t('simple_form.no'), article.order_number, article.name, - article.note, - article.manufacturer, - article.origin, + ArticleUnitsLib.get_translated_name_for_code(article.supplier_order_unit), article.unit, + get_csv_ratios(article), + article.minimum_order_quantity, + ArticleUnitsLib.get_translated_name_for_code(article.billing_unit), + article.group_order_granularity, + ArticleUnitsLib.get_translated_name_for_code(article.group_order_unit), article.price, + ArticleUnitsLib.get_translated_name_for_code(article.price_unit), article.tax, article.deposit, - ArticleUnitsLib.get_translated_name_for_code(article.supplier_order_unit), - ArticleUnitsLib.get_translated_name_for_code(article.price_unit), - ArticleUnitsLib.get_translated_name_for_code(article.group_order_unit), - article.group_order_granularity, - article.minimum_order_quantity, - ArticleUnitsLib.get_translated_name_for_code(article.billing_unit), + article.note, article.article_category.try(:name), - get_csv_ratios(article) + article.origin, + article.manufacturer ] end end diff --git a/app/lib/foodsoft_file.rb b/app/lib/foodsoft_file.rb index 17a26ba5..deca4d22 100644 --- a/app/lib/foodsoft_file.rb +++ b/app/lib/foodsoft_file.rb @@ -11,21 +11,21 @@ def self.parse(file, options = {}) article = { availability: row[0]&.strip == I18n.t('simple_form.yes'), order_number: row[1], name: row[2], - note: row[3], - manufacturer: row[4], - origin: row[5], - unit: row[6], - price: row[7], - tax: row[8], - deposit: (row[9].nil? ? '0' : row[9]), - supplier_order_unit: ArticleUnitsLib.get_code_for_unit_name(row[10]), + supplier_order_unit: ArticleUnitsLib.get_code_for_unit_name(row[3]), + unit: row[4], + article_unit_ratios: FoodsoftFile.parse_ratios_cell(row[5]), + minimum_order_quantity: row[6], + billing_unit: ArticleUnitsLib.get_code_for_unit_name(row[7]), + group_order_granularity: row[8], + group_order_unit: ArticleUnitsLib.get_code_for_unit_name(row[9]), + price: row[10], price_unit: ArticleUnitsLib.get_code_for_unit_name(row[11]), - group_order_unit: ArticleUnitsLib.get_code_for_unit_name(row[12]), - group_order_granularity: row[13], - minimum_order_quantity: row[14], - billing_unit: ArticleUnitsLib.get_code_for_unit_name(row[15]), - article_category: row[16], - article_unit_ratios: FoodsoftFile.parse_ratios_cell(row[17]) } + tax: row[12], + deposit: (row[13].nil? ? '0' : row[13]), + note: row[14], + article_category: row[15], + origin: row[16], + manufacturer: row[17] } articles << article end diff --git a/app/views/articles/upload.html.haml b/app/views/articles/upload.html.haml index 8f91d790..b01fe0d2 100644 --- a/app/views/articles/upload.html.haml +++ b/app/views/articles/upload.html.haml @@ -5,66 +5,87 @@ %table.table.table-bordered %thead %tr - %th= t '.field.status' + %th= Article.human_attribute_name(:availability_short) %th= Article.human_attribute_name(:order_number) %th= Article.human_attribute_name(:name) - %th= Article.human_attribute_name(:note) - %th= Article.human_attribute_name(:manufacturer) - %th= Article.human_attribute_name(:origin) - %th= Article.human_attribute_name(:unit) + %th= Article.human_attribute_name(:supplier_order_unit) + %th= Article.human_attribute_name(:custom_unit) + %th= Article.human_attribute_name(:ratios_to_supplier_order_unit) + %th= Article.human_attribute_name(:minimum_order_quantity) + %th= Article.human_attribute_name(:billing_unit) + %th= Article.human_attribute_name(:group_order_granularity) + %th= Article.human_attribute_name(:group_order_unit) %th= Article.human_attribute_name(:price) + %th= Article.human_attribute_name(:price_unit) %th= Article.human_attribute_name(:tax) %th= Article.human_attribute_name(:deposit) - %th= Article.human_attribute_name(:unit_quantity) - %th.muted= t '.fields.reserved' - %th.muted= t '.fields.reserved' + %th= Article.human_attribute_name(:note) %th= Article.human_attribute_name(:article_category) + %th= Article.human_attribute_name(:origin) + %th= Article.human_attribute_name(:manufacturer) %tbody + - kgm = ArticleUnitsLib.get_translated_name_for_code('KGM') + - xjy = ArticleUnitsLib.get_translated_name_for_code('XJY') + - ltr = ArticleUnitsLib.get_translated_name_for_code('LTR') + - xbd = ArticleUnitsLib.get_translated_name_for_code('XBD') + - xbo = ArticleUnitsLib.get_translated_name_for_code('XBO') %tr %td %td 1234A %td= t '.sample.walnuts' + %td= kgm %td - %td= t '.sample.supplier_1' - %td CA - %td 500 gr - %td 8.90 + %td + %td + %td= kgm + %td 0.5 + %td= kgm + %td 17.80 + %td= kgm %td= FoodsoftConfig[:tax_default] || 6 %td 0 - %td 6 - %td %td %td= t '.sample.nuts' + %td CA + %td= t '.sample.supplier_1' %tr %td x %td 4321Z %td= t '.sample.tomato_juice' - %td= t '.sample.organic' - %td= t '.sample.supplier_2' - %td IN - %td 1.5 l + %td= xjy + %td + %td= '1.5 ' + ltr + %td 4 + %td= ltr + %td 1 + %td= xjy %td 4.35 + %td= ltr %td= FoodsoftConfig[:tax_default] || 6 %td 0 - %td 1 - %td - %td + %td= t '.sample.organic' %td= t '.sample.juices' + %td IN + %td= t '.sample.supplier_2' %tr %td %td 4322Q %td= t '.sample.tomato_juice' - %td= t '.sample.organic' - %td= t '.sample.supplier_3' - %td TR - %td 1.2 l + %td= xbd + %td + %td= '6 ' + xbo + ', 1 ' + ltr + %td + %td= xbd + %td 1 + %td= xbo %td 4.02 + %td= xbo %td= FoodsoftConfig[:tax_default] || 6 %td 0 - %td 2 - %td - %td + %td= t '.sample.organic' %td= t '.sample.juices' + %td TR + %td= t '.sample.supplier_3' %p= t '.text_2' diff --git a/config/locales/de.yml b/config/locales/de.yml index 9b4c4ad1..58d4ce8a 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -22,9 +22,17 @@ de: supplier: Lieferantin tax: MwSt unit: Einheit + custom_unit: Benutzerdefinierte Einheit unit_quantity: Gebindegröße unit_quantity_short: GebGr units: Gebinde + supplier_order_unit: von Lieferantin bestellbar in (Einheit) + ratios_to_supplier_order_unit: Inhalt + minimum_order_quantity: Mindestbestellmenge + billing_unit: abgerechnet nach (Einheit) + group_order_granularity: für Mitglieder bestellbar in (Menge) + group_order_unit: für Mitglieder bestellbar in (Einheit) + price_unit: pro (Preiseinheit) article_unit: code: Einheitencode gemäß Empfehlung der United Nations Economic Commission (UNECE) code_short: Code diff --git a/config/locales/en.yml b/config/locales/en.yml index fe6a49c0..5bf6e818 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -22,10 +22,18 @@ en: supplier: Supplier tax: VAT unit: Unit + custom_unit: Custom unit unit_quantity: Unit quantity unit_quantity_short: U.Q. units: Units - supplier_order_unit: Supplier order unit + supplier_order_unit: orderable from supplier per (unit) + ratios_to_supplier_order_unit: Content + minimum_order_quantity: Minimum order quantity + billing_unit: billed per (unit) + group_order_granularity: members can order per (amount) + group_order_unit: members can order per (unit) + price_unit: per (price unit) + article_unit: code: Unit code according to the recommendation of the United Nations Economic Commission (UNECE) code_short: Code diff --git a/spec/fixtures/foodsoft_file_01.csv b/spec/fixtures/foodsoft_file_01.csv index 95af087c..99e6b4d8 100644 --- a/spec/fixtures/foodsoft_file_01.csv +++ b/spec/fixtures/foodsoft_file_01.csv @@ -1,5 +1,5 @@ -avail.;Order number;Name;Note;Manufacturer;Origin;Unit;Price (net);VAT;Deposit;Supplier order unit;Price unit;Group order unit;Group order granularity;Minimum order quantity;Billing unit;Category;Ratios to supplier order unit -Yes;29932;Walnoten (ongeroosterd);bio ◎;Het grote bomenbos;Veluwe, NL;kg;2.34;6;0;;;;1;;;Nuts; -Yes;28391;Pijnboompitten;dem;Het warme woud;TR;100g;5.56;6;0;;;;1;;;Nuts;10 Piece -Yes;1829;Appelsap (verpakt);;Appelgaarde;DE;4x250ml;3.21;6;0.4;;;;1;;;Drinks;10 Piece -Yes;177813;Tomaten;bio;De röde hof;Best, NL;500 g;1.2;6;0;;;;1;;;Vegetables;20 Piece +avail.;Order number;Name;Supplier order unit;Unit;Ratios to supplier order unit;Minimum order quantity;Billing unit;Group order granularity;Group order unit;Price (net);Price unit;VAT;Deposit;Note;Category;Origin;Manufacturer +Yes;29932;Walnoten (ongeroosterd);;kg;;;;1;;2.34;;6;0;bio ◎;Nuts;Veluwe, NL;Het grote bomenbos +Yes;28391;Pijnboompitten;;100g;10 Piece;;;1;;5.56;;6;0;dem;Nuts;TR;Het warme woud +Yes;1829;Appelsap (verpakt);;4x250ml;10 Piece;;;1;;3.21;;6;0.4;;Drinks;DE;Appelgaarde +Yes;177813;Tomaten;;500 g;20 Piece;;;1;;1.2;;6;0;bio;Vegetables;Best, NL;De röde hof diff --git a/spec/fixtures/foodsoft_file_01.ods b/spec/fixtures/foodsoft_file_01.ods index b18f662007c2f00263872bfd3f2deb11c37ba7d9..85a14245b9ca38966bab09ea2add8683d6bf5bef 100644 GIT binary patch literal 4388 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 V4?#x$dxh-c;=IWF4Z7c>{{l*T+s^<1 literal 16501 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 a#&9`F&<|n|006?r%jRSJIp_NI>Hh(Y!lC~F diff --git a/spec/fixtures/foodsoft_file_01.xls b/spec/fixtures/foodsoft_file_01.xls index 409ba1bdf61eb10a885b0d63ba6e11ee72074db4..b1d1059f1b727119df52bee7c605364da140b2a8 100644 GIT binary patch literal 27648 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 O+Nk~OzrX*t`~NrJ9mPZd diff --git a/spec/fixtures/foodsoft_file_01.xlsx b/spec/fixtures/foodsoft_file_01.xlsx index 07fee06d3db799c714cc3e3d2415b67d003a1521..cf094a793ecac8baa134e36f03024c47b46d5c1f 100644 GIT binary patch literal 10154 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 I`R&*L14gzF*#H0l literal 5913 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 diff --git a/spec/fixtures/foodsoft_file_02.csv b/spec/fixtures/foodsoft_file_02.csv index f0e92c3a..866fa0c4 100644 --- a/spec/fixtures/foodsoft_file_02.csv +++ b/spec/fixtures/foodsoft_file_02.csv @@ -1,2 +1,2 @@ -avail.;Order number;Name;Note;Manufacturer;Origin;Unit;Price (net);VAT;Deposit;Supplier order unit;Price unit;Group order unit;Group order granularity;Minimum order quantity;Billing unit;Category;Ratios to supplier order unit -Yes;1;Tomatoes;organic;Tommy farm;Somewhere, UK;500 g;1.2;6;0;;;;1;;;Vegetables;20 Piece +avail.;Order number;Name;Supplier order unit;Unit;Ratios to supplier order unit;Minimum order quantity;Billing unit;Group order granularity;Group order unit;Price (net);Price unit;VAT;Deposit;Note;Category;Origin;Manufacturer +Yes;1;Tomatoes;;500 g;20 Piece;;;1;;1.2;;6;0;organic;Vegetables;Somewhere, UK;Tommy farm