diff --git a/CHANGELOG.md b/CHANGELOG.md index ad372e050..944e2ee4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog Fab Manager - Ability to configure and export the accounting data to the ACD accounting software +- Compute the VAT per item in each invoices, instead of globally - Fix a bug: invoices with total = 0, are marked as paid on site even if paid by card - [TODO DEPLOY] `rake db:migrate` diff --git a/app/models/invoice_item.rb b/app/models/invoice_item.rb index f6146824b..e6ff29e1d 100644 --- a/app/models/invoice_item.rb +++ b/app/models/invoice_item.rb @@ -21,6 +21,25 @@ class InvoiceItem < ActiveRecord::Base footprint == compute_footprint end + def amount_after_coupon + # deduct coupon discount + coupon_service = CouponService.new + coupon_service.ventilate(invoice.total, amount, invoice.coupon) + end + + # return the item amount, coupon discount deducted, if any, and VAT excluded, if applicable + def net_amount + # deduct VAT + vat_service = VatHistoryService.new + vat_rate = vat_service.invoice_vat(invoice) + Rational(amount_after_coupon / (vat_rate / 100.00 + 1)).round.to_f + end + + # return the VAT amount for this item + def vat + amount_after_coupon - net_amount + end + private def compute_footprint diff --git a/app/pdfs/pdf/invoice.rb b/app/pdfs/pdf/invoice.rb index d2decd133..5d0f8a5cc 100644 --- a/app/pdfs/pdf/invoice.rb +++ b/app/pdfs/pdf/invoice.rb @@ -121,6 +121,8 @@ class PDF::Invoice < Prawn::Document data = [[I18n.t('invoices.details'), I18n.t('invoices.amount')]] total_calc = 0 + total_ht = 0 + total_vat = 0 # going through invoice_items invoice.invoice_items.each do |item| @@ -184,6 +186,8 @@ class PDF::Invoice < Prawn::Document data += [[details, number_to_currency(price)]] total_calc += price + total_ht += item.net_amount + total_vat += item.vat end ## subtract the coupon, if any @@ -210,15 +214,13 @@ class PDF::Invoice < Prawn::Document # discount textual description literal_discount = cp.percent_off - if cp.type == 'amount_off' - literal_discount = number_to_currency(cp.amount_off / 100.00) - end + literal_discount = number_to_currency(cp.amount_off / 100.00) if cp.type == 'amount_off' # add a row for the coupon data += [[_t('invoices.coupon_CODE_discount_of_DISCOUNT', CODE: cp.code, DISCOUNT: literal_discount, - TYPE: cp.type), number_to_currency(-discount)] ] + TYPE: cp.type), number_to_currency(-discount)]] end # total verification @@ -226,20 +228,18 @@ class PDF::Invoice < Prawn::Document puts "ERROR: totals are NOT equals => expected: #{total}, computed: #{total_calc}" if total_calc != total # TVA - if Setting.find_by(name: 'invoice_VAT-active').value == 'true' + vat_service = VatHistoryService.new + vat_rate = vat_service.invoice_vat(invoice) + if vat_rate != 0 data += [[I18n.t('invoices.total_including_all_taxes'), number_to_currency(total)]] - - vat_service = VatHistoryService.new - vat_rate = vat_service.invoice_vat(invoice) - vat = total / (vat_rate / 100.00 + 1) - data += [[I18n.t('invoices.including_VAT_RATE', RATE: vat_rate), number_to_currency(total - vat)]] - data += [[I18n.t('invoices.including_total_excluding_taxes'), number_to_currency(vat)]] + data += [[I18n.t('invoices.including_VAT_RATE', RATE: vat_rate), number_to_currency(total_vat / 100.00)]] + data += [[I18n.t('invoices.including_total_excluding_taxes'), number_to_currency(total_ht / 100.00)]] data += [[I18n.t('invoices.including_amount_payed_on_ordering'), number_to_currency(total)]] # checking the round number - rounded = sprintf('%.2f', vat).to_f + sprintf('%.2f', total - vat).to_f + rounded = sprintf('%.2f', total_vat / 100.00).to_f + sprintf('%.2f', total_ht / 100.00).to_f if rounded != sprintf('%.2f', total_calc).to_f - puts 'ERROR: rounding the numbers cause an invoice inconsistency. ' + + puts 'ERROR: rounding the numbers cause an invoice inconsistency. ' \ "Total expected: #{sprintf('%.2f', total_calc)}, total computed: #{rounded}" end else diff --git a/app/services/footprint_service.rb b/app/services/footprint_service.rb index cf3b7708f..c5c584b1b 100644 --- a/app/services/footprint_service.rb +++ b/app/services/footprint_service.rb @@ -7,7 +7,7 @@ class FootprintService # @param item an instance of the provided class # @param sort the items in database by the provided criterion, to find the previous one def self.compute_footprint(klass, item, sort_on = 'id') - raise TypeError unless item.class.name == klass.name + raise TypeError unless item.is_a? klass previous = klass.where("#{sort_on} < ?", item[sort_on]) .order("#{sort_on} DESC")