2019-09-20 17:40:27 +02:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2021-01-04 16:26:44 +01:00
|
|
|
require 'test_helper'
|
2019-09-20 17:40:27 +02:00
|
|
|
module Exports; end
|
|
|
|
|
|
|
|
class Exports::AccountingExportTest < ActionDispatch::IntegrationTest
|
|
|
|
setup do
|
|
|
|
admin = User.with_role(:admin).first
|
|
|
|
login_as(admin, scope: :user)
|
|
|
|
end
|
|
|
|
|
2020-07-22 11:16:43 +02:00
|
|
|
test 'export accounting period to ACD software' do
|
2019-09-20 17:40:27 +02:00
|
|
|
# First, we create a new export
|
|
|
|
post '/api/accounting/export',
|
2020-03-13 17:10:38 +01:00
|
|
|
params: {
|
2019-09-20 17:40:27 +02:00
|
|
|
query: {
|
2022-07-19 17:32:55 +02:00
|
|
|
columns: %w[journal_code date account_code account_label piece line_label
|
|
|
|
debit_origin credit_origin debit_euro credit_euro lettering],
|
2019-09-20 17:40:27 +02:00
|
|
|
encoding: 'ISO-8859-1',
|
|
|
|
date_format: '%d/%m/%Y',
|
|
|
|
start_date: '2012-03-12T00:00:00.000Z',
|
2023-02-14 13:10:58 +01:00
|
|
|
end_date: Time.current.utc.iso8601,
|
2019-09-20 17:40:27 +02:00
|
|
|
label_max_length: 50,
|
|
|
|
decimal_separator: ',',
|
|
|
|
export_invoices_at_zero: false
|
|
|
|
}.to_json.to_s,
|
|
|
|
extension: 'csv',
|
|
|
|
type: 'acd',
|
|
|
|
key: ';'
|
|
|
|
}.to_json,
|
2020-03-13 17:10:38 +01:00
|
|
|
headers: default_headers
|
2019-09-20 17:40:27 +02:00
|
|
|
|
|
|
|
# Check response format & status
|
|
|
|
assert_equal 200, response.status, response.body
|
2023-02-24 17:26:55 +01:00
|
|
|
assert_match Mime[:json].to_s, response.content_type
|
2019-09-20 17:40:27 +02:00
|
|
|
|
|
|
|
# Check the export was created correctly
|
|
|
|
res = json_response(response.body)
|
2022-10-26 14:32:19 +02:00
|
|
|
e = Export.find(res[:export_id])
|
2019-09-20 17:40:27 +02:00
|
|
|
assert_not_nil e, 'Export was not created in database'
|
|
|
|
|
|
|
|
# Run the worker
|
|
|
|
worker = AccountingExportWorker.new
|
|
|
|
worker.perform(e.id)
|
|
|
|
|
|
|
|
# notification
|
|
|
|
assert_not_empty Notification.where(attached_object: e)
|
|
|
|
|
|
|
|
# resulting CSV file
|
|
|
|
assert FileTest.exist?(e.file), 'CSV file was not generated'
|
|
|
|
require 'csv'
|
|
|
|
data = CSV.read(e.file, headers: true, col_sep: e.key)
|
|
|
|
|
|
|
|
# test values
|
2022-10-26 14:32:19 +02:00
|
|
|
first_invoice = Invoice.first
|
2022-12-12 11:10:06 +01:00
|
|
|
# first line = payment line
|
|
|
|
check_payment_line(first_invoice, data[0])
|
2022-10-26 14:32:19 +02:00
|
|
|
# second line = sold item line
|
|
|
|
check_item_line(first_invoice, first_invoice.invoice_items.first, data[1])
|
2019-09-20 17:40:27 +02:00
|
|
|
|
2022-10-26 14:32:19 +02:00
|
|
|
# ensure invoice 4 is not exported (0€ invoice)
|
|
|
|
zero_invoice = Invoice.find(4)
|
|
|
|
assert_nil(data.map { |line| line[I18n.t('accounting_export.piece')] }.find { |document| document == zero_invoice.reference },
|
|
|
|
'Invoice at 0 should not be exported')
|
2019-09-20 17:40:27 +02:00
|
|
|
|
2022-10-26 14:32:19 +02:00
|
|
|
# test with a reservation invoice
|
|
|
|
machine_invoice = Invoice.find(5)
|
2022-12-12 11:10:06 +01:00
|
|
|
check_payment_line(machine_invoice, data[6])
|
2022-10-26 14:32:19 +02:00
|
|
|
check_item_line(machine_invoice, machine_invoice.invoice_items.first, data[7])
|
2019-09-20 17:40:27 +02:00
|
|
|
|
2022-10-26 14:32:19 +02:00
|
|
|
# test with a shop order invoice (local payment)
|
|
|
|
shop_invoice = Invoice.find(5811)
|
2022-12-12 11:10:06 +01:00
|
|
|
check_payment_line(shop_invoice, data[10])
|
2022-10-26 14:32:19 +02:00
|
|
|
check_item_line(shop_invoice, shop_invoice.invoice_items.first, data[11])
|
|
|
|
check_item_line(shop_invoice, shop_invoice.invoice_items.last, data[12])
|
2019-09-20 17:40:27 +02:00
|
|
|
|
2022-10-26 14:32:19 +02:00
|
|
|
# Clean CSV file
|
|
|
|
require 'fileutils'
|
|
|
|
FileUtils.rm(e.file)
|
|
|
|
end
|
2019-09-20 17:40:27 +02:00
|
|
|
|
2022-12-12 11:10:06 +01:00
|
|
|
def check_payment_line(invoice, payment_line)
|
|
|
|
check_entry_date(invoice, payment_line)
|
|
|
|
check_client_accounts(invoice, payment_line)
|
|
|
|
check_entry_label(invoice, payment_line)
|
|
|
|
check_document(invoice, payment_line)
|
2019-09-20 17:40:27 +02:00
|
|
|
|
2022-10-26 14:32:19 +02:00
|
|
|
if invoice.wallet_transaction_id.nil?
|
2022-12-12 11:10:06 +01:00
|
|
|
assert_equal invoice.total / 100.00, payment_line[I18n.t('accounting_export.debit_origin')].to_f,
|
2022-10-25 19:10:14 +02:00
|
|
|
'Origin debit amount does not match'
|
2022-12-12 11:10:06 +01:00
|
|
|
assert_equal invoice.total / 100.00, payment_line[I18n.t('accounting_export.debit_euro')].to_f, 'Euro debit amount does not match'
|
2019-09-20 17:40:27 +02:00
|
|
|
else
|
2022-10-26 14:32:19 +02:00
|
|
|
warn "WARNING: unable to test accurately accounting export: invoice #{invoice.id} is using wallet"
|
2019-09-20 17:40:27 +02:00
|
|
|
end
|
|
|
|
|
2022-12-12 11:10:06 +01:00
|
|
|
assert_equal 0, payment_line[I18n.t('accounting_export.credit_origin')].to_f, 'Credit origin amount does not match'
|
|
|
|
assert_equal 0, payment_line[I18n.t('accounting_export.credit_euro')].to_f, 'Credit euro amount does not match'
|
2022-10-26 14:32:19 +02:00
|
|
|
end
|
2019-09-20 17:40:27 +02:00
|
|
|
|
2022-10-26 14:32:19 +02:00
|
|
|
def check_item_line(invoice, invoice_item, item_line)
|
2022-12-09 16:06:51 +01:00
|
|
|
check_sales_journal_code(item_line)
|
2022-10-26 14:32:19 +02:00
|
|
|
check_entry_date(invoice, item_line)
|
2019-09-20 17:40:27 +02:00
|
|
|
|
2022-10-26 14:32:19 +02:00
|
|
|
check_subscription_accounts(invoice, item_line)
|
|
|
|
check_reservation_accounts(invoice, item_line)
|
|
|
|
check_document(invoice, item_line)
|
|
|
|
check_entry_label(invoice, item_line)
|
2019-09-20 17:40:27 +02:00
|
|
|
|
2022-10-26 14:32:19 +02:00
|
|
|
assert_equal invoice_item.amount / 100.00, item_line[I18n.t('accounting_export.credit_origin')].to_f,
|
|
|
|
'Origin credit amount does not match'
|
|
|
|
assert_equal invoice_item.amount / 100.00, item_line[I18n.t('accounting_export.credit_euro')].to_f, 'Euro credit amount does not match'
|
2019-09-20 17:40:27 +02:00
|
|
|
|
2022-10-26 14:32:19 +02:00
|
|
|
assert_equal 0, item_line[I18n.t('accounting_export.debit_origin')].to_f, 'Debit origin amount does not match'
|
|
|
|
assert_equal 0, item_line[I18n.t('accounting_export.debit_euro')].to_f, 'Debit euro amount does not match'
|
|
|
|
end
|
2019-09-20 17:40:27 +02:00
|
|
|
|
2022-12-09 16:06:51 +01:00
|
|
|
def check_sales_journal_code(line)
|
|
|
|
journal_code = Setting.get('accounting_sales_journal_code')
|
2022-10-26 14:32:19 +02:00
|
|
|
assert_equal journal_code, line[I18n.t('accounting_export.journal_code')], 'Wrong journal code'
|
|
|
|
end
|
2019-09-20 17:40:27 +02:00
|
|
|
|
2022-10-26 14:32:19 +02:00
|
|
|
def check_entry_date(invoice, line)
|
|
|
|
entry_date = invoice.created_at.to_date
|
2023-02-14 13:10:58 +01:00
|
|
|
assert_equal entry_date, Time.zone.parse(line[I18n.t('accounting_export.date')]).to_date, 'Wrong date'
|
2022-10-26 14:32:19 +02:00
|
|
|
end
|
2019-09-20 17:40:27 +02:00
|
|
|
|
2022-10-26 14:32:19 +02:00
|
|
|
def check_client_accounts(invoice, client_line)
|
|
|
|
if invoice.wallet_transaction && invoice.wallet_amount.positive?
|
2022-12-12 11:10:06 +01:00
|
|
|
wallet_client_code = Setting.get('accounting_payment_wallet_code')
|
2022-10-26 14:32:19 +02:00
|
|
|
assert_equal wallet_client_code, client_line[I18n.t('accounting_export.account_code')], 'Account code for wallet client is wrong'
|
2019-09-20 17:40:27 +02:00
|
|
|
|
2022-12-12 11:10:06 +01:00
|
|
|
wallet_client_label = Setting.get('accounting_payment_wallet_label')
|
2022-10-26 14:32:19 +02:00
|
|
|
assert_equal wallet_client_label, client_line[I18n.t('accounting_export.account_label')], 'Account label for wallet client is wrong'
|
2022-12-09 16:06:51 +01:00
|
|
|
|
2022-12-12 11:10:06 +01:00
|
|
|
wallet_client_journal = Setting.get('accounting_payent_wallet_journal_code')
|
2022-12-09 16:06:51 +01:00
|
|
|
assert_equal wallet_client_journal, client_line[I18n.t('accounting_export.journal_code')], 'Journal code for wallet client is wrong'
|
2022-10-25 19:10:14 +02:00
|
|
|
end
|
2022-10-26 14:32:19 +02:00
|
|
|
mean = invoice.paid_by_card? ? 'card' : 'other'
|
2019-09-20 17:40:27 +02:00
|
|
|
|
2022-12-12 11:10:06 +01:00
|
|
|
client_code = Setting.get("accounting_payment_#{mean}_code")
|
2022-10-26 14:32:19 +02:00
|
|
|
assert_equal client_code, client_line[I18n.t('accounting_export.account_code')], 'Account code for client is wrong'
|
2023-03-23 17:39:06 +01:00
|
|
|
# the test above fails randomly... we don't know why!
|
2019-09-20 17:40:27 +02:00
|
|
|
|
2022-12-12 11:10:06 +01:00
|
|
|
client_label = Setting.get("accounting_payment_#{mean}_label")
|
2022-10-26 14:32:19 +02:00
|
|
|
assert_equal client_label, client_line[I18n.t('accounting_export.account_label')], 'Account label for client is wrong'
|
2022-12-09 16:06:51 +01:00
|
|
|
|
2022-12-12 11:10:06 +01:00
|
|
|
client_journal = Setting.get("accounting_payment_#{mean}_journal_code")
|
2022-12-09 16:06:51 +01:00
|
|
|
assert_equal client_journal, client_line[I18n.t('accounting_export.journal_code')], 'Journal code for client is wrong'
|
2022-10-26 14:32:19 +02:00
|
|
|
end
|
2019-09-20 17:40:27 +02:00
|
|
|
|
2022-10-26 14:32:19 +02:00
|
|
|
def check_subscription_accounts(invoice, item_line)
|
|
|
|
return unless invoice.subscription_invoice?
|
|
|
|
|
|
|
|
subscription_code = Setting.get('accounting_subscription_code')
|
|
|
|
assert_equal subscription_code, item_line[I18n.t('accounting_export.account_code')], 'Account code for subscription is wrong'
|
|
|
|
|
|
|
|
subscription_label = Setting.get('accounting_subscription_label')
|
|
|
|
assert_equal subscription_label, item_line[I18n.t('accounting_export.account_label')], 'Account label for subscription is wrong'
|
|
|
|
end
|
|
|
|
|
|
|
|
def check_reservation_accounts(invoice, item_line)
|
|
|
|
return unless invoice.main_item.object_type == 'Reservation'
|
|
|
|
|
|
|
|
code = Setting.get("accounting_#{invoice.main_item.object.reservable_type}_code")
|
|
|
|
assert_equal code, item_line[I18n.t('accounting_export.account_code')], 'Account code for reservation is wrong'
|
|
|
|
|
|
|
|
label = Setting.get("accounting_#{invoice.main_item.object.reservable_type}_label")
|
|
|
|
assert_equal label, item_line[I18n.t('accounting_export.account_label')], 'Account label for reservation is wrong'
|
|
|
|
end
|
|
|
|
|
|
|
|
def check_document(invoice, line)
|
|
|
|
assert_equal(invoice.reference, line[I18n.t('accounting_export.piece')], 'Document (invoice reference) is wrong')
|
|
|
|
end
|
|
|
|
|
|
|
|
def check_entry_label(invoice, line)
|
|
|
|
if invoice.subscription_invoice?
|
2022-11-18 16:42:11 +01:00
|
|
|
assert_match I18n.t('accounting_summary.subscription_abbreviation'),
|
2022-10-26 14:32:19 +02:00
|
|
|
line[I18n.t('accounting_export.line_label')],
|
|
|
|
'Entry label does not contains the reference to the subscription'
|
2019-09-20 17:40:27 +02:00
|
|
|
end
|
2022-10-26 14:32:19 +02:00
|
|
|
if invoice.main_item.object_type == 'Reservation'
|
2022-11-18 16:42:11 +01:00
|
|
|
assert_match I18n.t("accounting_summary.#{invoice.main_item.object.reservable_type}_reservation_abbreviation"),
|
2022-10-26 14:32:19 +02:00
|
|
|
line[I18n.t('accounting_export.line_label')],
|
|
|
|
'Entry label does not contains the reference to the reservation'
|
|
|
|
end
|
2022-11-18 16:42:11 +01:00
|
|
|
if invoice.main_item.object_type == 'WalletTransaction'
|
|
|
|
assert_match I18n.t('accounting_summary.wallet_abbreviation'),
|
|
|
|
line[I18n.t('accounting_export.line_label')],
|
|
|
|
'Entry label does not contains the reference to the wallet'
|
|
|
|
end
|
|
|
|
|
|
|
|
return unless invoice.main_item.object_type == 'OrderItem'
|
2019-09-20 17:40:27 +02:00
|
|
|
|
2022-11-18 16:42:11 +01:00
|
|
|
assert_match I18n.t('accounting_summary.shop_order_abbreviation'),
|
2022-10-26 14:32:19 +02:00
|
|
|
line[I18n.t('accounting_export.line_label')],
|
2022-11-18 16:42:11 +01:00
|
|
|
'Entry label does not contains the reference to the order'
|
2019-09-20 17:40:27 +02:00
|
|
|
end
|
|
|
|
end
|