diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 894d0e0b5..468e7de2f 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -208,7 +208,7 @@ Metrics/BlockNesting: # Offense count: 18 # Configuration parameters: CountComments, CountAsOne. Metrics/ClassLength: - Max: 304 + Max: 350 # Offense count: 51 # Configuration parameters: AllowedMethods, AllowedPatterns. @@ -223,7 +223,7 @@ Metrics/MethodLength: # Offense count: 4 # Configuration parameters: CountComments, CountAsOne. Metrics/ModuleLength: - Max: 192 + Max: 200 # Offense count: 1 # Configuration parameters: CountKeywordArgs, MaxOptionalParameters. diff --git a/app/assets/stylesheets/bootstrap_and_overrides.css.less b/app/assets/stylesheets/bootstrap_and_overrides.css.less index 364dd8e25..0f7e5d989 100644 --- a/app/assets/stylesheets/bootstrap_and_overrides.css.less +++ b/app/assets/stylesheets/bootstrap_and_overrides.css.less @@ -537,7 +537,11 @@ span.positive_amount { color: black; } -span.negative_amout { +span.positive_green { + color: green; +} + +span.negative_amount { color: red; } @@ -547,4 +551,4 @@ span.negative_amout { details { cursor: pointer; -} \ No newline at end of file +} diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 4cd91e200..6f21fbbdb 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -22,10 +22,15 @@ def format_datetime_timespec(time, format) def format_currency(amount) return nil if amount.nil? - class_name = amount < 0 ? 'negative_amout' : 'positive_amount' + class_name = amount < 0 ? 'negative_amount' : 'positive_amount' content_tag :span, number_to_currency(amount), class: class_name end + def format_currency_difference(amount) + class_name = amount < 0 ? 'negative_amount' : 'positive_green' + content_tag :span, (amount > 0 ? '+' : '') + number_to_currency(amount), class: class_name + end + # Splits an IBAN into groups of 4 digits displayed with margins in between def format_iban(iban) iban && iban.scan(/..?.?.?/).map { |item| content_tag(:span, item, style: 'margin-right: 0.5em;') }.join.html_safe diff --git a/app/models/invoice.rb b/app/models/invoice.rb index 781b1f1f4..e1c929b0d 100644 --- a/app/models/invoice.rb +++ b/app/models/invoice.rb @@ -30,22 +30,32 @@ def net_amount amount - deposit + deposit_credit end - def orders_sum - orders - .joins(order_articles: [:article_price]) - .sum('COALESCE(order_articles.units_received, order_articles.units_billed, order_articles.units_to_order)' \ - + '* article_prices.unit_quantity' \ - + '* ROUND((article_prices.price + article_prices.deposit) * (100 + article_prices.tax) / 100, 2)') + def orders_sum(type = :without_markup) + if type == :without_markup + orders.sum { |order| order.sum(:groups_without_markup) } + elsif type == :with_markup + orders.sum { |order| order.sum(:groups) } + end end def orders_transport_sum - orders.sum(:transport) + orders.sum { |order| order.sum(:transport) } end - def expected_amount - return net_amount unless orders.any? + def deliveries_sum(type = :without_markup) + if type == :without_markup + deliveries.sum(&:sum) + elsif type == :with_markup + deliveries.sum { |delivery| delivery.sum(:fc) } + end + end + + def expected_amount(type = :without_markup) + orders_sum(type) + orders_transport_sum + deliveries_sum(type) + end - orders_sum + orders_transport_sum + def profit(type = :without_markup) + expected_amount(type) - net_amount end protected diff --git a/app/models/order.rb b/app/models/order.rb index 23c19baab..3b09e5a9a 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -189,15 +189,15 @@ def articles_sort_by_category end end - # Returns the defecit/benefit for the foodcoop + # Returns the defecit/benefit for the foodcoop per order # Requires a valid invoice, belonging to this order # FIXME: Consider order.foodcoop_result - def profit(options = {}) - markup = options[:without_markup] || false - return unless invoice - - groups_sum = markup ? sum(:groups_without_markup) : sum(:groups) - groups_sum - invoice.net_amount + def profit(type = :with_markup) + if invoice + invoice.profit(type) / invoice.orders.count + else + type == :without_markup ? sum(:groups_without_markup) : sum(:groups) + end end # Returns the all round price of a finished order @@ -220,7 +220,7 @@ def sum(type = :gross) end end elsif %i[groups groups_without_markup].include?(type) - for go in group_orders.includes(group_order_articles: { order_article: %i[article article_price] }) + for go in group_orders.includes(group_order_articles: { order_article: %i[article article_price] }).where.not(ordergroup: nil) for goa in go.group_order_articles case type when :groups @@ -230,6 +230,14 @@ def sum(type = :gross) end end end + elsif type == :stock_order + for go in group_orders.includes(group_order_articles: { order_article: %i[article article_price] }).where(ordergroup: nil) + for goa in go.group_order_articles + total += goa.result * goa.order_article.price.gross_price + end + end + elsif type == :transport + total = group_orders.where.not(ordergroup: nil).sum(:transport) end total end @@ -397,6 +405,8 @@ def distribute_transport group_orders.each do |go| go.transport = (amount * go.group_order_articles.sum(:result)).ceil(2) end + when Order.transport_distributions[:skip] + group_orders.each { |go| go.transport = 0 } end end diff --git a/app/views/finance/balancing/_invoice.html.haml b/app/views/finance/balancing/_invoice.html.haml index bae9a3478..c0e990505 100644 --- a/app/views/finance/balancing/_invoice.html.haml +++ b/app/views/finance/balancing/_invoice.html.haml @@ -18,8 +18,38 @@ %tr %td= t('.refund_adjusted_amount') %td.curreny= number_to_currency invoice.net_amount + + - n_orders = invoice.orders.count + - n_deliveries = invoice.deliveries.count + - if n_orders > 1 + %tr + %td= t('.orders') + %td.numeric= n_orders.to_s + - if n_deliveries > 0 + %tr + %td= t('.deliveries') + %td.numeric= n_deliveries.to_s + + - profit_without_markup = invoice.profit(:without_markup) + - profit_with_markup = invoice.profit(:with_markup) + %tr + %td + = t('.fc_profit') + - if profit_with_markup > profit_without_markup + %small= t('.without_extra_charge') + - else + = ':' + %td.numeric= format_currency_difference(profit_without_markup) + - if profit_with_markup > profit_without_markup + %tr + %td + = t('.fc_profit') + %small= t('.with_extra_charge') + %td#order_profit.numeric= format_currency_difference(profit_with_markup) + %br/ - = link_to t('.edit'), edit_finance_invoice_path(invoice) + = link_to t('.view'), finance_invoice_path(invoice), class: 'btn' + = link_to t('.edit'), edit_finance_invoice_path(invoice), class: 'btn' - else = t '.new_body' diff --git a/app/views/finance/balancing/_summary.haml b/app/views/finance/balancing/_summary.haml index e466727fb..c2dd104d6 100644 --- a/app/views/finance/balancing/_summary.haml +++ b/app/views/finance/balancing/_summary.haml @@ -3,28 +3,46 @@ = t('.duration', {starts: format_date(order.starts), ends: format_date(order.ends)}) %p %table + - gross_sum = order.sum(:gross) + - fc_sum = order.sum(:fc) + - stock_order_amount = order.sum(:stock_order) %tr %td= t('.net_amount') %td.numeric= number_to_currency(order.sum(:net)) %tr %td= t('.gross_amount') - %td.numeric= number_to_currency(order.sum(:gross)) - %tr - %td= t('.fc_amount') - %td.numeric= number_to_currency(order.sum(:fc)) + %td.numeric= number_to_currency(gross_sum) + - if fc_sum > gross_sum + %tr + %td= t('.fc_amount') + %td.numeric= number_to_currency(fc_sum) %tr %td= t('.groups_amount') %td.numeric= number_to_currency(order.sum(:groups)) + + - if stock_order_amount > 0 + %tr + %td= t('.stock_order_amount') + %td.numeric= number_to_currency(stock_order_amount) + + - total_transport_costs = order.transport || 0 + - if total_transport_costs > 0 + %tr + %td= t('.total_transport_costs') + %td.numeric= number_to_currency(total_transport_costs) + - group_transport_costs = order.sum(:transport) + - fc_transport_costs = total_transport_costs - group_transport_costs + %tr + %td= t('.group_transport_costs') + %td.numeric= number_to_currency(group_transport_costs) + %tr + %td= t('.fc_transport_costs') + %td.numeric= number_to_currency(fc_transport_costs) + %tr - %td - = t('.fc_profit') - %small= t('.without_extra_charge') - %td.numeric= number_to_currency(order.profit(:without_markup => true)) - %tr - %td - = t('.fc_profit') - %small= t('.with_extra_charge') - %td#order_profit.numeric= number_to_currency(order.profit) + %td= t('.order_surplus') + %td.numeric= format_currency_difference(order.profit(:without_markup)) + #summaryChangedWarning.alert(style="display:none;") %strong= t '.changed' %br/ diff --git a/app/views/finance/invoices/show.html.haml b/app/views/finance/invoices/show.html.haml index 3cd96b5f2..06352a1aa 100644 --- a/app/views/finance/invoices/show.html.haml +++ b/app/views/finance/invoices/show.html.haml @@ -1,6 +1,7 @@ - title t('.title', number: @invoice.number) - total = 0 +- total_fc = 0 .row-fluid .span6 @@ -20,6 +21,7 @@ - @invoice.deliveries.order(:date).each_with_index do |delivery, index| - sum = delivery.sum - total += sum + - total_fc += delivery.sum(:fc) = ', ' if index > 0 = link_to format_date(delivery.date), [delivery.supplier, delivery] = ' (' + number_to_currency(sum) + ')' @@ -28,14 +30,21 @@ %dt= heading_helper(Invoice, :orders) + ':' %dd>< - @invoice.orders.order(:ends).each_with_index do |order, index| - - sum = order.sum + - sum_og = order.sum(:groups_without_markup) # without markup + - sum = order.sum # without markup + - transport_og = order.sum(:transport) - transport = order.transport || 0 - - total += sum + transport + - total += sum_og + transport_og # without markup + - total_fc += order.sum(:groups) + transport_og # with_markup = ', ' if index > 0 = link_to format_date(order.ends), new_finance_order_path(order_id: order) - = ' (' + number_to_currency(sum) + = ' (' + number_to_currency(sum_og) + - if sum_og < sum + = ' / ' + number_to_currency(sum) - if transport != 0 - = ' + ' + number_to_currency(transport) + = ' + ' + number_to_currency(transport_og) + - if transport_og < transport + = ' / ' + number_to_currency(transport) = ')' %dt= heading_helper(Invoice, :number) + ':' @@ -60,8 +69,19 @@ %dd= number_to_currency @invoice.net_amount - if @invoice.deliveries.any? || @invoice.orders.any? - %dt= heading_helper(Invoice, :total) + ':' - %dd= number_to_currency total + %dt= heading_helper(Invoice, :total) + (total_fc > total ? t('.without_extra_charge') : '') + ':' # + %dd= number_to_currency(total) + - if total_fc > total + %dt= heading_helper(Invoice, :total) + t('.with_extra_charge') + ':' + %dd= number_to_currency(total_fc) + + %dt= t('.fc_profit') + (total_fc > total ? t('.without_extra_charge') : '') + ':' + %dd + = format_currency_difference(total - @invoice.net_amount) + - if total_fc > total + %dt= t('.fc_profit') + ' ' + t('.with_extra_charge') + ':' + %dd + = format_currency_difference(total_fc - @invoice.net_amount) - if @invoice.attachments.attached? %dt= heading_helper(Invoice, :attachment) + ':' diff --git a/app/views/finance/invoices/unpaid.html.haml b/app/views/finance/invoices/unpaid.html.haml index f93932c6c..502b868fd 100644 --- a/app/views/finance/invoices/unpaid.html.haml +++ b/app/views/finance/invoices/unpaid.html.haml @@ -9,16 +9,17 @@ %p - for invoice in invoices - invoice_amount_diff = invoice.expected_amount - invoice.net_amount + - invoice_profit = invoice.expected_amount(:with_markup) - invoice.net_amount - invoices_sum += invoice.amount - invoices_text << invoice.number = link_to finance_invoice_path(invoice) do = format_date invoice.date = ' ' + invoice.number = ' ' + number_to_currency(invoice.amount) - - if invoice_amount_diff != 0 - %span{style: "color:#{invoice_amount_diff < 0 ? 'red' : 'green'}"} - = invoice_amount_diff > 0 ? '+' : '-' - = number_to_currency(invoice_amount_diff.abs) + = format_currency_difference(invoice_amount_diff) + - if invoice_profit > invoice_amount_diff + = ' / ' + = format_currency_difference(invoice_profit) - if invoice.attachments.attached? - for attachment in invoice.attachments = link_to attachment.filename, url_for(attachment) diff --git a/config/locales/de.yml b/config/locales/de.yml index 68e01b143..ecc07d048 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -820,6 +820,7 @@ de: title: Beendete Bestellungen invoice: edit: Rechnung bearbeiten + view: Rechnung ansehen invoice_amount: 'Rechnungsbetrag:' invoice_date: 'Rechnungsdatum:' invoice_number: 'Rechnungsnummer:' @@ -828,6 +829,11 @@ de: new_body: 'Eine Rechnung für diese Bestellung anlegen:' plus_refund_credited: "+ Pfand gutgeschrieben:" refund_adjusted_amount: 'pfandbereinigter Betrag:' + fc_profit: 'FC Überschuss' + with_extra_charge: 'mit Aufschlag:' + without_extra_charge: 'ohne Aufschlag:' + orders: 'Anzahl Bestellungen:' + deliveries: 'Anzahl Lager-Lieferungen:' new: alert: Achtung, Bestellung wurde schon abgerechnet articles_overview: Artikelübersicht @@ -859,13 +865,17 @@ de: changed: Daten wurden verändert! duration: von %{starts} bis %{ends} fc_amount: 'FC-Betrag:' - fc_profit: FC Gewinn gross_amount: 'Bruttobetrag:' groups_amount: 'Gruppenbeträge:' + stock_order_amount: 'Lager-Bestellung:' net_amount: 'Nettobetrag:' reload: Zusammenfassung neu laden with_extra_charge: 'mit Aufschlag:' without_extra_charge: 'ohne Aufschlag:' + total_transport_costs: 'Transportkosten gesamt:' + group_transport_costs: 'Transportkosten Gruppen:' + fc_transport_costs: 'Transportkosten FC:' + order_surplus: 'FC Überschuss Bestellung:' bank_accounts: assign_unlinked_transactions: notice: 'Es wurden %{count} Transaktionen zugeordnet.' @@ -990,6 +1000,9 @@ de: title: Neue Rechnung anlegen show: title: Rechnung %{number} + fc_profit: FC Überschuss + with_extra_charge: ' mit Aufschlag' + without_extra_charge: ' ohne Aufschlag' unpaid: invoices_sum: Gesamtsumme invoices_text: Verwendungszweck diff --git a/config/locales/en.yml b/config/locales/en.yml index a863a670b..ea29bf40a 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -820,6 +820,7 @@ en: title: Closed orders invoice: edit: Edit invoice + view: View invoice invoice_amount: 'Invoice amount:' invoice_date: 'Invoice date:' invoice_number: 'Invoice number:' @@ -828,6 +829,11 @@ en: new_body: 'Create an invoice for this order:' plus_refund_credited: "+ deposit returned:" refund_adjusted_amount: 'amount adjusted for refund:' + fc_profit: 'FC surplus' + with_extra_charge: 'with extra charge:' + without_extra_charge: 'without extra charge:' + orders: 'Number of orders:' + deliveries: 'Number of stock delivieries:' new: alert: Attention, order was already accounted articles_overview: Overview of articles @@ -859,13 +865,17 @@ en: changed: Data was changed! duration: From %{starts} till %{ends} fc_amount: 'Sales value:' - fc_profit: FC surplus gross_amount: 'Gross value:' groups_amount: 'Ordergroups sum:' + stock_order_amount: 'Stock order:' net_amount: 'Net value:' reload: Reload summary with_extra_charge: 'with extra charge:' without_extra_charge: 'without extra charge:' + total_transport_costs: 'Transport costs total:' + group_transport_costs: 'Transport costs groups:' + fc_transport_costs: 'Transport costs FC:' + order_surplus: 'FC order surplus:' bank_accounts: assign_unlinked_transactions: notice: '%{count} transactions have been assigned' @@ -990,6 +1000,9 @@ en: title: Create new invoice show: title: Invoice %{number} + fc_profit: FC surplus + with_extra_charge: ' with margin' + without_extra_charge: ' without margin' unpaid: invoices_sum: Total sum invoices_text: Reference