2019-07-31 16:52:11 +02:00
|
|
|
# frozen_string_literal: false
|
2019-07-29 17:51:53 +02:00
|
|
|
|
2022-11-15 13:52:39 +01:00
|
|
|
# module definition
|
|
|
|
module Accounting; end
|
|
|
|
|
2019-07-29 17:51:53 +02:00
|
|
|
# Provides the routine to export the accounting data to an external accounting software
|
2022-11-15 13:52:39 +01:00
|
|
|
class Accounting::AccountingExportService
|
2019-09-17 12:35:34 +02:00
|
|
|
include ActionView::Helpers::NumberHelper
|
2019-07-29 17:51:53 +02:00
|
|
|
|
2022-11-18 16:42:11 +01:00
|
|
|
attr_reader :encoding, :format, :separator, :date_format, :columns, :decimal_separator, :label_max_length, :export_zeros
|
2019-09-17 12:35:34 +02:00
|
|
|
|
|
|
|
def initialize(columns, encoding: 'UTF-8', format: 'CSV', separator: ';')
|
2019-07-29 17:51:53 +02:00
|
|
|
@encoding = encoding
|
|
|
|
@format = format
|
|
|
|
@separator = separator
|
2019-09-17 12:35:34 +02:00
|
|
|
@decimal_separator = ','
|
|
|
|
@date_format = '%d/%m/%Y'
|
|
|
|
@label_max_length = 50
|
|
|
|
@export_zeros = false
|
2019-07-29 17:51:53 +02:00
|
|
|
@columns = columns
|
|
|
|
end
|
|
|
|
|
2019-09-17 12:35:34 +02:00
|
|
|
def set_options(decimal_separator: ',', date_format: '%d/%m/%Y', label_max_length: 50, export_zeros: false)
|
|
|
|
@decimal_separator = decimal_separator
|
|
|
|
@date_format = date_format
|
|
|
|
@label_max_length = label_max_length
|
|
|
|
@export_zeros = export_zeros
|
|
|
|
end
|
|
|
|
|
2019-07-30 16:06:35 +02:00
|
|
|
def export(start_date, end_date, file)
|
2019-10-07 17:12:49 +02:00
|
|
|
# build CSV content
|
2019-08-01 09:49:09 +02:00
|
|
|
content = header_row
|
2022-11-18 16:42:11 +01:00
|
|
|
lines = AccountingLine.where('date >= ? AND date <= ?', start_date, end_date)
|
|
|
|
.order('date ASC')
|
|
|
|
lines = lines.joins(:invoice).where('invoices.total > 0') unless export_zeros
|
|
|
|
lines.each do |l|
|
|
|
|
Rails.logger.debug { "processing invoice #{l.invoice_id}..." } unless Rails.env.test?
|
|
|
|
content << "#{row(l)}\n"
|
2019-07-29 17:51:53 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
# write content to file
|
2019-08-01 09:49:09 +02:00
|
|
|
File.open(file, "w:#{encoding}") { |f| f.puts content.encode(encoding, invalid: :replace, undef: :replace) }
|
2019-07-29 17:51:53 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
2019-08-01 09:49:09 +02:00
|
|
|
def header_row
|
|
|
|
row = ''
|
|
|
|
columns.each do |column|
|
|
|
|
row << I18n.t("accounting_export.#{column}") << separator
|
|
|
|
end
|
2019-08-01 10:24:34 +02:00
|
|
|
"#{row}\n"
|
2019-08-01 09:49:09 +02:00
|
|
|
end
|
|
|
|
|
2019-09-19 13:57:33 +02:00
|
|
|
# Generate a row of the export, filling the configured columns with the provided values
|
2022-11-18 16:42:11 +01:00
|
|
|
def row(line)
|
2019-07-29 17:51:53 +02:00
|
|
|
row = ''
|
|
|
|
columns.each do |column|
|
|
|
|
case column
|
2019-07-31 16:52:11 +02:00
|
|
|
when 'journal_code'
|
2022-11-18 16:42:11 +01:00
|
|
|
row << line.journal_code.to_s
|
2019-07-31 16:52:11 +02:00
|
|
|
when 'date'
|
2022-11-18 16:42:11 +01:00
|
|
|
row << line.date&.strftime(date_format)
|
2019-07-31 16:52:11 +02:00
|
|
|
when 'account_code'
|
2023-01-19 15:25:20 +01:00
|
|
|
row << line.account_code.to_s
|
2019-07-31 16:52:11 +02:00
|
|
|
when 'account_label'
|
2023-01-19 15:25:20 +01:00
|
|
|
row << line.account_label.to_s
|
2019-07-31 16:52:11 +02:00
|
|
|
when 'piece'
|
2022-11-18 16:42:11 +01:00
|
|
|
row << line.invoice.reference
|
2019-07-31 16:52:11 +02:00
|
|
|
when 'line_label'
|
2022-11-18 16:42:11 +01:00
|
|
|
row << label(line)
|
2022-07-19 17:32:55 +02:00
|
|
|
when 'debit_origin', 'debit_euro'
|
2022-11-18 16:42:11 +01:00
|
|
|
row << format_number(line.debit / 100.00)
|
2022-07-19 17:32:55 +02:00
|
|
|
when 'credit_origin', 'credit_euro'
|
2022-11-18 16:42:11 +01:00
|
|
|
row << format_number(line.credit / 100.00)
|
2019-08-01 09:49:09 +02:00
|
|
|
when 'lettering'
|
|
|
|
row << ''
|
2019-07-29 17:51:53 +02:00
|
|
|
else
|
2022-11-18 16:42:11 +01:00
|
|
|
Rails.logger.warn { "Unsupported column: #{column}" }
|
2019-07-29 17:51:53 +02:00
|
|
|
end
|
2019-08-01 09:49:09 +02:00
|
|
|
row << separator
|
2019-07-29 17:51:53 +02:00
|
|
|
end
|
2019-08-01 09:49:09 +02:00
|
|
|
row
|
2019-07-29 17:51:53 +02:00
|
|
|
end
|
|
|
|
|
2019-09-17 12:35:34 +02:00
|
|
|
# Format the given number as a string, using the configured separator
|
|
|
|
def format_number(num)
|
|
|
|
number_to_currency(num, unit: '', separator: decimal_separator, delimiter: '', precision: 2)
|
|
|
|
end
|
|
|
|
|
|
|
|
# Create a text from the given invoice, matching the accounting software rules for the labels
|
2022-11-18 16:42:11 +01:00
|
|
|
def label(line)
|
|
|
|
name = "#{line.invoicing_profile.last_name} #{line.invoicing_profile.first_name}".tr separator, ''
|
|
|
|
summary = line.summary
|
|
|
|
"#{name.truncate(label_max_length - summary.length)}, #{summary}"
|
2019-08-01 14:58:10 +02:00
|
|
|
end
|
2019-07-29 17:51:53 +02:00
|
|
|
end
|