diff --git a/app/assets/javascripts/controllers/admin/invoices.js.erb b/app/assets/javascripts/controllers/admin/invoices.js.erb index 995d9f844..56520dc38 100644 --- a/app/assets/javascripts/controllers/admin/invoices.js.erb +++ b/app/assets/javascripts/controllers/admin/invoices.js.erb @@ -1003,6 +1003,8 @@ Application.Controllers.controller('AccountingExportModalController', ['$scope', // if the invoice was payed with stripe, allow to refund through stripe Invoice.first(function (data) { $scope.firstInvoice = data.date; + $scope.exportTarget.startDate = data.date; + $scope.exportTarget.endDate = moment().toISOString(); }); }; @@ -1019,7 +1021,9 @@ Application.Controllers.controller('AccountingExportModalController', ['$scope', query: JSON.stringify({ columns: $scope.exportTarget.settings.columns, encoding: $scope.exportTarget.settings.encoding, - date_format: $scope.exportTarget.settings.dateFormat + date_format: $scope.exportTarget.settings.dateFormat, + start_date: $scope.exportTarget.startDate, + end_date: $scope.exportTarget.endDate }) }; } diff --git a/app/controllers/api/accounting_exports_controller.rb b/app/controllers/api/accounting_exports_controller.rb index ab6184dee..cd91f835f 100644 --- a/app/controllers/api/accounting_exports_controller.rb +++ b/app/controllers/api/accounting_exports_controller.rb @@ -8,7 +8,8 @@ class API::AccountingExportsController < API::ApiController def export authorize :accounting_export - export = Export.where(category: 'accounting', export_type: 'accounting-software') + export = Export.where(category: 'accounting', export_type: 'accounting-software', key: params[:key]) + .where(extension: params[:extension], query: params[:query]) .where('created_at > ?', Invoice.maximum('updated_at')) .last if export.nil? || !FileTest.exist?(export.file) diff --git a/app/services/accounting_export_service.rb b/app/services/accounting_export_service.rb index 75a1c8815..8089920bd 100644 --- a/app/services/accounting_export_service.rb +++ b/app/services/accounting_export_service.rb @@ -1,16 +1,17 @@ -# frozen_string_literal: true +# frozen_string_literal: false # Provides the routine to export the accounting data to an external accounting software class AccountingExportService - attr_reader :encoding, :format, :separator, :journal_code, :date_format + attr_reader :encoding, :format, :separator, :journal_code, :date_format, :columns, :vat_rate def initialize(columns, encoding = 'UTF-8', format = 'CSV', separator = ';', date_format = '%d/%m/%Y') @encoding = encoding @format = format @separator = separator - @journal_code = Setting.find_by(name: 'accounting-export_journal-code').value + @journal_code = Setting.find_by(name: 'accounting-export_journal-code')&.value @date_format = date_format @columns = columns + @vat_rate = Setting.find_by(name: 'invoice_VAT-rate')&.value&.to_f end def export(start_date, end_date, file) @@ -18,7 +19,7 @@ class AccountingExportService content = '' invoices = Invoice.where('created_at >= ? AND created_at <= ?', start_date, end_date).order('created_at ASC') invoices.each do |i| - content << generate_rows(i) + content += generate_rows(i) end # write content to file @@ -28,16 +29,16 @@ class AccountingExportService private def generate_rows(invoice) - client_row(invoice) << "\n" << - items_rows(invoice) << "\n" << - vat_row(invoice) << "\n" + client_row(invoice) + "\n" + + items_rows(invoice) + "\n" + + vat_row(invoice) + "\n" end # Generate the "subscription" and "reservation" rows associated with the provided invoice def items_rows(invoice) - rows = invoice.subscription_invoice? ? subscription_row(invoice) << "\n" : '' + rows = invoice.subscription_invoice? ? subscription_row(invoice) + "\n" : '' invoice.invoice_items.each do |item| - rows << reservation_row(invoice, item) << "\n" + rows += reservation_row(invoice, item) + "\n" end end @@ -46,135 +47,130 @@ class AccountingExportService row = '' columns.each do |column| case column - when :journal_code - row << journal_code - when :date - row << invoice.created_at.strftime(date_format) - when :account_code - row << account(invoice, :client) - when :account_label - row << account(invoice, :client, :label) - when :piece - row << invoice.reference - when :line_label - row << invoice.invoicing_profile.full_name - when :debit_origin - row << debit_client(invoice, invoice.total / 100.0) - when :credit_origin - row << credit_client(invoice, invoice.total / 100.0) - when :debit_euro - row << debit_client(invoice, invoice.total / 100.0) - when :credit_euro - row << credit_client(invoice, invoice.total / 100.0) + when 'journal_code' + row += journal_code + when 'date' + row += invoice.created_at&.strftime(date_format) + when 'account_code' + row += account(invoice, :client) + when 'account_label' + row += account(invoice, :client, :label) + when 'piece' + row += invoice.reference + when 'line_label' + row += invoice.invoicing_profile.full_name + when 'debit_origin' + row += debit_client(invoice, invoice.total / 100.0) + when 'credit_origin' + row += credit_client(invoice, invoice.total / 100.0) + when 'debit_euro' + row += debit_client(invoice, invoice.total / 100.0) + when 'credit_euro' + row += credit_client(invoice, invoice.total / 100.0) else puts "Unsupported column: #{column}" end - row << separator + row += separator end end # Generate the "reservation" row, which contains the credit to the reservation account, all taxes excluded def reservation_row(invoice, item) - vat_rate = Setting.find_by(name: 'invoice_VAT-rate').value.to_f wo_taxes = item.amount / (vat_rate / 100 + 1) row = '' columns.each do |column| case column - when :journal_code - row << journal_code - when :date - row << invoice.created_at.strftime(date_format) - when :account_code - row << account(invoice, :reservation) - when :account_label - row << account(invoice, :reservation, :label) - when :piece - row << invoice.reference - when :line_label - row << item.description - when :debit_origin - row << debit(invoice, wo_taxes) - when :credit_origin - row << credit(invoice, wo_taxes) - when :debit_euro - row << debit(invoice, wo_taxes) - when :credit_euro - row << credit(invoice, wo_taxes) + when 'journal_code' + row += journal_code + when 'date' + row += invoice.created_at&.strftime(date_format) + when 'account_code' + row += account(invoice, :reservation) + when 'account_label' + row += account(invoice, :reservation, :label) + when 'piece' + row += invoice.reference + when 'line_label' + row += item.description + when 'debit_origin' + row += debit(invoice, wo_taxes) + when 'credit_origin' + row += credit(invoice, wo_taxes) + when 'debit_euro' + row += debit(invoice, wo_taxes) + when 'credit_euro' + row += credit(invoice, wo_taxes) else puts "Unsupported column: #{column}" end - row << separator + row += separator end end # Generate the "subscription" row, which contains the credit to the subscription account, all taxes excluded def subscription_row(invoice) subscription_item = invoice.invoice_items.select(&:subscription).first - vat_rate = Setting.find_by(name: 'invoice_VAT-rate').value.to_f wo_taxes = subscription_item.amount / (vat_rate / 100 + 1) row = '' columns.each do |column| case column - when :journal_code - row << journal_code - when :date - row << invoice.created_at.strftime(date_format) - when :account_code - row << account(invoice, :subscription) - when :account_label - row << account(invoice, :subscription, :label) - when :piece - row << invoice.reference - when :line_label - row << subscription_item.description - when :debit_origin - row << debit(invoice, wo_taxes) - when :credit_origin - row << credit(invoice, wo_taxes) - when :debit_euro - row << debit(invoice, wo_taxes) - when :credit_euro - row << credit(invoice, wo_taxes) + when 'journal_code' + row += journal_code + when 'date' + row += invoice.created_at&.strftime(date_format) + when 'account_code' + row += account(invoice, :subscription) + when 'account_label' + row += account(invoice, :subscription, :label) + when 'piece' + row += invoice.reference + when 'line_label' + row += subscription_item.description + when 'debit_origin' + row += debit(invoice, wo_taxes) + when 'credit_origin' + row += credit(invoice, wo_taxes) + when 'debit_euro' + row += debit(invoice, wo_taxes) + when 'credit_euro' + row += credit(invoice, wo_taxes) else puts "Unsupported column: #{column}" end - row << separator + row += separator end end # Generate the "VAT" row, which contains the credit to the VAT account, with VAT amount only def vat_row(invoice) - # first compute the VAT amount - vat_rate = Setting.find_by(name: 'invoice_VAT-rate').value.to_f vat = invoice.total - (invoice.total / (vat_rate / 100 + 1)) - # now feed the row row = '' columns.each do |column| case column - when :journal_code - row << journal_code - when :date - row << invoice.created_at.strftime(date_format) - when :account_code - row << account(invoice, :vat) - when :account_label - row << account(invoice, :vat, :label) - when :piece - row << invoice.reference - when :line_label - row << I18n.t('accounting_export.VAT') - when :debit_origin - row << debit(invoice, vat) - when :credit_origin - row << credit(invoice, vat) - when :debit_euro - row << debit(invoice, vat) - when :credit_euro - row << credit(invoice, vat) + when 'journal_code' + row += journal_code + when 'date' + row += invoice.created_at&.strftime(date_format) + when 'account_code' + row += account(invoice, :vat) + when 'account_label' + row += account(invoice, :vat, :label) + when 'piece' + row += invoice.reference + when 'line_label' + row += I18n.t('accounting_export.VAT') + when 'debit_origin' + row += debit(invoice, vat) + when 'credit_origin' + row += credit(invoice, vat) + when 'debit_euro' + row += debit(invoice, vat) + when 'credit_euro' + row += credit(invoice, vat) else puts "Unsupported column: #{column}" end - row << separator + row += separator end end @@ -182,17 +178,17 @@ class AccountingExportService def account(invoice, account, type = :code) case account when :client - Setting.find_by(name: "accounting_client_#{type}").value + Setting.find_by(name: "accounting_client_#{type}")&.value || '' when :vat - Setting.find_by(name: "accounting_VAT_#{type}").value + Setting.find_by(name: "accounting_VAT_#{type}")&.value || '' when :subscription return if invoice.invoiced_type != 'Subscription' - Setting.find_by(name: "accounting_subscription_#{type}").value + Setting.find_by(name: "accounting_subscription_#{type}")&.value || '' when :reservation return if invoice.invoiced_type != 'Reservation' - Setting.find_by(name: "accounting_#{invoice.invoiced.reservable_type}_#{type}").value + Setting.find_by(name: "accounting_#{invoice.invoiced.reservable_type}_#{type}")&.value || '' else puts "Unsupported account #{account}" end @@ -201,13 +197,13 @@ class AccountingExportService # Fill the value of the "debit" column: if the invoice is a refund, returns the given amount, returns 0 otherwise def debit(invoice, amount) avoir = invoice.is_a? Avoir - avoir ? amount : 0 + avoir ? amount.to_s : '0' end # Fill the value of the "credit" column: if the invoice is a refund, returns 0, otherwise, returns the given amount def credit(invoice, amount) avoir = invoice.is_a? Avoir - avoir ? 0 : amount + avoir ? '0' : amount.to_s end # Fill the value of the "debit" column for the client row: if the invoice is a refund, returns 0, otherwise, returns the given amount