Skip to content

Commit

Permalink
On #42: Fax pdf/csv: Decimals dependant on supplier_order_unit's si c…
Browse files Browse the repository at this point in the history
…onvertability (#70)

* On #42: Fax pdf/csv: Decimals dependant on supplier_order_unit's si convertability

* Solve #42: Improve fax PDF, CSV, text

- outsource format_units_to_order to OrderHelper
- fax text: include unit, adjust column width
- fax PDF & text: only include order number if any present

* On #42:

- Adapted order_txt to generalized creating the text table and added
  spec
- Code style fixes for order_fax

* On #42 Fixes error dad0bb9#r143648091

---------

Co-authored-by: twothreenine <[email protected]>
  • Loading branch information
lentschi and twothreenine authored Jun 28, 2024
1 parent b38dfb0 commit c73596b
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 17 deletions.
40 changes: 29 additions & 11 deletions app/documents/order_fax.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
class OrderFax < OrderPdf
include ArticlesHelper
include OrdersHelper

BATCH_SIZE = 250

Expand Down Expand Up @@ -74,28 +75,39 @@ def recipient_paragraph

def articles_paragraph
total = 0
data = [I18n.t('documents.order_fax.rows')]
any_order_number_present = order_articles.where.not(article_version: { order_number: nil }).any?
data = [get_header_labels(!any_order_number_present)]
each_order_article do |oa|
price = oa.article_version.price
subtotal = oa.units_to_order * price
total += subtotal
data << [oa.article_version.order_number,
number_with_precision(oa.units_to_order, precision: 3),
format_supplier_order_unit_with_ratios(oa.price),
oa.article_version.name,
number_to_currency(price),
number_to_currency(subtotal)]
oa_data = []
oa_data += [oa.article_version.order_number] if any_order_number_present
oa_data += [
format_units_to_order(oa),
format_supplier_order_unit_with_ratios(oa.price),
oa.article_version.name,
number_to_currency(price),
number_to_currency(subtotal)
]
data << oa_data
end
data << [I18n.t('documents.order_fax.total'), nil, nil, nil, nil, number_to_currency(total)]

total_row_spacing_columns = [nil] * (any_order_number_present ? 4 : 3)
total_row = [I18n.t('documents.order_fax.total')] + total_row_spacing_columns + [number_to_currency(total)]

data << total_row

table data, cell_style: { size: fontsize(8), overflow: :shrink_to_fit } do |table|
table.header = true
table.cells.border_width = 1
table.cells.border_color = '666666'

table.row(0).border_bottom_width = 2
table.columns(1).align = :right
table.columns(4..5).align = :right
table.row(data.length - 1).columns(0..4).borders = %i[top bottom]
table.columns(-5).align = :right
table.columns(-2..-1).align = :right
table.row(data.length - 1).columns(0).align = :left
table.row(data.length - 1).columns(0..-2).borders = %i[top bottom]
table.row(data.length - 1).columns(0).borders = %i[top bottom left]
table.row(data.length - 1).border_top_width = 2
end
Expand All @@ -116,4 +128,10 @@ def order_articles
def each_order_article(&block)
order_articles.find_each_with_order(batch_size: BATCH_SIZE, &block)
end

def get_header_labels(exclude_order_number)
labels = I18n.t('documents.order_fax.rows').clone
labels.delete_at(0) if exclude_order_number
labels
end
end
11 changes: 11 additions & 0 deletions app/helpers/orders_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ def options_for_suppliers_to_select
options_for_select(options)
end

def format_units_to_order(order_article, strip_insignificant_zeros: false)
format_amount(order_article.units_to_order, order_article, strip_insignificant_zeros: strip_insignificant_zeros)
end

# "1×2 ordered, 2×2 billed, 2×2 received"
def units_history_line(order_article, options = {})
if order_article.order.open?
Expand Down Expand Up @@ -206,4 +210,11 @@ def receive_button(order, options = {})
class: "btn#{' btn-success' unless order.received?} #{options[:class]}"
end
end

private

def format_amount(amount, order_article, strip_insignificant_zeros: false)
strip_insignificant_zeros = true unless order_article.article_version.supplier_order_unit_is_si_convertible
number_with_precision(amount, precision: 3, strip_insignificant_zeros: strip_insignificant_zeros)
end
end
3 changes: 2 additions & 1 deletion app/lib/order_csv.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
class OrderCsv < RenderCsv
include ApplicationHelper
include ArticlesHelper
include OrdersHelper

def header
[
Expand All @@ -19,7 +20,7 @@ def data
@object.order_articles.ordered.includes(:article_version).all.map do |oa|
yield [
oa.article_version.order_number,
number_with_precision(oa.units_to_order, precision: 3),
format_units_to_order(oa, strip_insignificant_zeros: true),
format_supplier_order_unit_with_ratios(oa.article_version),
oa.article_version.name,
number_to_currency(oa.article_version.price),
Expand Down
61 changes: 56 additions & 5 deletions app/lib/order_txt.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
class OrderTxt
include ActionView::Helpers::NumberHelper
include ArticlesHelper
include OrdersHelper

def initialize(order, _options = {})
@order = order
Expand All @@ -17,12 +19,61 @@ def to_txt
text += '****** ' + I18n.t('orders.fax.to_address') + "\n\n"
text += "#{FoodsoftConfig[:name]}\n#{contact[:street]}\n#{contact[:zip_code]} #{contact[:city]}\n\n"
text += '****** ' + I18n.t('orders.fax.articles') + "\n\n"
text += format("%8s %8s %s\n", I18n.t('orders.fax.number'), I18n.t('orders.fax.amount'),
I18n.t('orders.fax.name'))
# now display all ordered articles
@order.order_articles.ordered.includes(:article_version).each do |oa|
text += format("%8s %8.3f %s\n", oa.article_version.order_number, oa.units_to_order, oa.article_version.name)

# prepare order_articles data
order_articles = @order.order_articles.ordered.includes(:article_version).order('article_versions.order_number ASC, article_versions.name ASC')
any_number_present = order_articles.where.not(article_version: { order_number: nil }).any?

order_headers = {
number: any_number_present ? { label: I18n.t('orders.fax.number') } : nil,
amount: { label: I18n.t('orders.fax.amount'), align: :right },
unit: { label: I18n.t('orders.fax.unit') },
name: { label: I18n.t('orders.fax.name') }
}.compact

order_positions = order_articles.map do |oa|
number = oa.article_version.order_number || ''
amount = format_units_to_order(oa).to_s
unit = format_supplier_order_unit_with_ratios(oa.price)
{
number: number,
amount: amount,
unit: unit,
name: oa.article_version.name
}
end

text += text_table(order_headers, order_positions)
text
end

private

def text_table(headers, rows)
table_keys = headers.keys
columns = table_keys.each_with_index.map do |key, index|
header = headers[key]
label = header[:label]
{
key: key,
label: label,
align: header[:align],
characters: index + 1 < table_keys.length ? (rows.pluck(key) + [label]).map(&:length).max : nil
}
end

header_txt = columns.map { |column| align_text_column(column[:label], column[:characters], column[:align]) }.join(' ')

rows_texts = rows.map do |row|
columns.map { |column| align_text_column(row[column[:key]], column[:characters], column[:align]) }.join(' ')
end

([header_txt] + rows_texts).join("\n")
end

def align_text_column(text, characters, align)
return text if characters.nil?

align == :right ? text.rjust(characters) : text.ljust(characters)
end
end
1 change: 1 addition & 0 deletions config/locales/de.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1537,6 +1537,7 @@ de:
heading: Bestellung für %{name}
name: Name
number: Nummer
unit: Einheit
to_address: Versandaddresse
finish:
notice: Die Bestellung wurde beendet.
Expand Down
1 change: 1 addition & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1541,6 +1541,7 @@ en:
heading: Order for %{name}
name: Name
number: Number
unit: Unit
to_address: Shipping address
finish:
notice: The order has been closed.
Expand Down
49 changes: 49 additions & 0 deletions spec/lib/order_txt_csv_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
require_relative '../spec_helper'

describe OrderTxt do
let(:user) { create(:user, groups: [create(:ordergroup)]) }
let(:order) { create(:order, created_by: user, starts: Date.yesterday, ends: 1.hour.ago, end_action: :auto_close, article_count: 3) }
let(:supplier) { order.supplier }
let(:go) { create(:group_order, order: order, ordergroup: user.ordergroup) }
let(:articles) { order.articles }
let(:order_articles) { order.order_articles }
let(:first_article_version) { articles.first.latest_article_version }
let(:second_article_version) { articles.second.latest_article_version }
let(:third_article_version) { articles.third.latest_article_version }

it 'creates a proper csv table sorted by order_number from an order' do
first_article_version.update(name: 'Short name', supplier_order_unit: 'XPK')
second_article_version.update(name: 'Much longer complicated name', supplier_order_unit: 'KGM')
third_article_version.update(name: 'Quite short name', supplier_order_unit: 'GRM')
order_articles.where(article_version: first_article_version).update(units_to_order: 1)
order_articles.where(article_version: second_article_version).update(units_to_order: 1.421)
order_articles.where(article_version: third_article_version).update(units_to_order: 4.432643311)

result = described_class.new(order).to_txt
expected_table = %(
Number Amount Unit Name
0 1 Package Short name
1 1.421 kg Much longer complicated name
2 4.433 g Quite short name
)
expect(result.strip).to end_with(expected_table.strip)
end

it 'omits the order_number column and sort alphabetically if none of the ordered articles have an order_number' do
first_article_version.update(name: 'Short name', supplier_order_unit: 'XPK', order_number: nil)
second_article_version.update(name: 'Much longer complicated name', supplier_order_unit: 'KGM', order_number: nil)
third_article_version.update(name: 'Quite short name', supplier_order_unit: 'GRM', order_number: nil)
order_articles.where(article_version: first_article_version).update(units_to_order: 1)
order_articles.where(article_version: second_article_version).update(units_to_order: 1.421)
order_articles.where(article_version: third_article_version).update(units_to_order: 4.432643311)

result = described_class.new(order).to_txt
expected_table = %(
Amount Unit Name
1.421 kg Much longer complicated name
4.433 g Quite short name
1 Package Short name
)
expect(result.strip).to end_with(expected_table.strip)
end
end

0 comments on commit c73596b

Please sign in to comment.