mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-01-29 18:52:22 +01:00
export collected VAT by rate
This commit is contained in:
parent
16242d2127
commit
00b9bce587
@ -70,6 +70,8 @@ class API::ExportsController < API::ApiController
|
|||||||
case type
|
case type
|
||||||
when 'acd'
|
when 'acd'
|
||||||
export = export.where('created_at > ?', Invoice.maximum('updated_at'))
|
export = export.where('created_at > ?', Invoice.maximum('updated_at'))
|
||||||
|
when 'vat'
|
||||||
|
export = export.where('created_at > ?', Invoice.maximum('updated_at'))
|
||||||
else
|
else
|
||||||
raise ArgumentError, "Unknown type accounting/#{type}"
|
raise ArgumentError, "Unknown type accounting/#{type}"
|
||||||
end
|
end
|
||||||
|
@ -1414,6 +1414,16 @@ Application.Controllers.controller('AccountingExportModalController', ['$scope',
|
|||||||
decimalSeparator: ',',
|
decimalSeparator: ',',
|
||||||
exportInvoicesAtZero: false,
|
exportInvoicesAtZero: false,
|
||||||
columns: ['journal_code', 'date', 'account_code', 'account_label', 'piece', 'line_label', 'debit_origin', 'credit_origin', 'debit_euro', 'credit_euro', 'lettering']
|
columns: ['journal_code', 'date', 'account_code', 'account_label', 'piece', 'line_label', 'debit_origin', 'credit_origin', 'debit_euro', 'credit_euro', 'lettering']
|
||||||
|
},
|
||||||
|
vat: {
|
||||||
|
format: 'csv',
|
||||||
|
encoding: 'UTF-8',
|
||||||
|
separator: ';',
|
||||||
|
dateFormat: '%Y-%m-%d',
|
||||||
|
labelMaxLength: 'N/A',
|
||||||
|
decimalSeparator: '.',
|
||||||
|
exportInvoicesAtZero: false,
|
||||||
|
columns: ['start_date', 'end_date', 'vat_rate', 'amount']
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1433,6 +1443,7 @@ Application.Controllers.controller('AccountingExportModalController', ['$scope',
|
|||||||
|
|
||||||
// binding to radio button "export to"
|
// binding to radio button "export to"
|
||||||
$scope.exportTarget = {
|
$scope.exportTarget = {
|
||||||
|
type: null,
|
||||||
software: null,
|
software: null,
|
||||||
startDate: null,
|
startDate: null,
|
||||||
endDate: null,
|
endDate: null,
|
||||||
|
@ -42,11 +42,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<h4 class="control-label m-l" translate>{{ 'app.admin.invoices.export_to' }}</h4>
|
<h4 class="control-label m-l" translate>{{ 'app.admin.invoices.export_what' }}</h4>
|
||||||
<div class="form-group m-l-lg">
|
<div class="form-group m-l-lg">
|
||||||
<label for="acd">
|
<label for="vat" class="block">
|
||||||
|
<input type="radio" name="vat" id="vat" ng-model="exportTarget.software" ng-value="'vat'" ng-click="fillSettings('vat')" required/>
|
||||||
|
{{ 'app.admin.invoices.export_VAT' | translate }}
|
||||||
|
</label>
|
||||||
|
<label for="acd" class="block">
|
||||||
<input type="radio" name="acd" id="acd" ng-model="exportTarget.software" ng-value="'acd'" ng-click="fillSettings('acd')" required/>
|
<input type="radio" name="acd" id="acd" ng-model="exportTarget.software" ng-value="'acd'" ng-click="fillSettings('acd')" required/>
|
||||||
{{ 'app.admin.invoices.acd' | translate }}
|
{{ 'app.admin.invoices.export_to_ACD' | translate }}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -40,8 +40,10 @@ class InvoiceItem < Footprintable
|
|||||||
def invoice_item_type
|
def invoice_item_type
|
||||||
if object_type == Reservation.name
|
if object_type == Reservation.name
|
||||||
object.try(:reservable_type) || ''
|
object.try(:reservable_type) || ''
|
||||||
elsif object_type == Subscription.name
|
elsif [Subscription.name, OfferDay.name].include? object_type
|
||||||
Subscription.name
|
Subscription.name
|
||||||
|
elsif object_type == StatisticProfilePrepaidPack.name
|
||||||
|
object.prepaid_pack.priceable_type
|
||||||
else
|
else
|
||||||
''
|
''
|
||||||
end
|
end
|
||||||
|
@ -16,7 +16,6 @@ class AccountingExportService
|
|||||||
@label_max_length = 50
|
@label_max_length = 50
|
||||||
@export_zeros = false
|
@export_zeros = false
|
||||||
@journal_code = Setting.get('accounting_journal_code') || ''
|
@journal_code = Setting.get('accounting_journal_code') || ''
|
||||||
@date_format = date_format
|
|
||||||
@columns = columns
|
@columns = columns
|
||||||
end
|
end
|
||||||
|
|
||||||
|
97
app/services/vat_export_service.rb
Normal file
97
app/services/vat_export_service.rb
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
# frozen_string_literal: false
|
||||||
|
|
||||||
|
# Provides the routine to export the collected VAT data to a CSV file.
|
||||||
|
class VatExportService
|
||||||
|
include ActionView::Helpers::NumberHelper
|
||||||
|
|
||||||
|
attr_reader :encoding, :format, :separator, :date_format, :columns, :decimal_separator
|
||||||
|
|
||||||
|
def initialize(columns, encoding: 'UTF-8', format: 'CSV', separator: ';')
|
||||||
|
@encoding = encoding
|
||||||
|
@format = format
|
||||||
|
@separator = separator
|
||||||
|
@decimal_separator = '.'
|
||||||
|
@date_format = '%Y-%m-%d'
|
||||||
|
@columns = columns
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_options(decimal_separator: ',', date_format: '%d/%m/%Y', label_max_length: nil, export_zeros: nil)
|
||||||
|
@decimal_separator = decimal_separator
|
||||||
|
@date_format = date_format
|
||||||
|
end
|
||||||
|
|
||||||
|
def export(start_date, end_date, file)
|
||||||
|
# build CSV content
|
||||||
|
content = header_row
|
||||||
|
invoices = Invoice.where('created_at >= ? AND created_at <= ?', start_date, end_date).order('created_at ASC')
|
||||||
|
vat_totals = compute_vat_totals(invoices)
|
||||||
|
content << generate_rows(vat_totals, start_date, end_date)
|
||||||
|
|
||||||
|
# write content to file
|
||||||
|
File.open(file, "w:#{encoding}") { |f| f.puts content.encode(encoding, invalid: :replace, undef: :replace) }
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def header_row
|
||||||
|
row = ''
|
||||||
|
columns.each do |column|
|
||||||
|
row << I18n.t("vat_export.#{column}") << separator
|
||||||
|
end
|
||||||
|
"#{row}\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
def generate_rows(vat_totals, start_date, end_date)
|
||||||
|
rows = ''
|
||||||
|
|
||||||
|
vat_totals.each do |rate, total|
|
||||||
|
next if rate.zero?
|
||||||
|
|
||||||
|
rows += "#{row(
|
||||||
|
start_date,
|
||||||
|
end_date,
|
||||||
|
rate,
|
||||||
|
total
|
||||||
|
)}\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
rows
|
||||||
|
end
|
||||||
|
|
||||||
|
def compute_vat_totals(invoices)
|
||||||
|
vat_total = []
|
||||||
|
service = VatHistoryService.new
|
||||||
|
invoices.each do |i|
|
||||||
|
puts "processing invoice #{i.id}..." unless Rails.env.test?
|
||||||
|
vat_total.push service.invoice_vat(i)
|
||||||
|
end
|
||||||
|
|
||||||
|
vat_total.map(&:values).flatten.group_by { |tot| tot[:vat_rate] }.map { |k, v| [k, v.map { |t| t[:total_vat] }.reduce(:+)] }.to_h
|
||||||
|
end
|
||||||
|
|
||||||
|
# Generate a row of the export, filling the configured columns with the provided values
|
||||||
|
def row(start_date, end_date, vat_rate, amount)
|
||||||
|
row = ''
|
||||||
|
columns.each do |column|
|
||||||
|
case column
|
||||||
|
when 'start_date'
|
||||||
|
row << DateTime.parse(start_date).strftime(date_format)
|
||||||
|
when 'end_date'
|
||||||
|
row << DateTime.parse(end_date).strftime(date_format)
|
||||||
|
when 'vat_rate'
|
||||||
|
row << vat_rate.to_s
|
||||||
|
when 'amount'
|
||||||
|
row << format_number(amount / 100.0)
|
||||||
|
else
|
||||||
|
puts "Unsupported column: #{column}"
|
||||||
|
end
|
||||||
|
row << separator
|
||||||
|
end
|
||||||
|
row
|
||||||
|
end
|
||||||
|
|
||||||
|
# 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
|
||||||
|
end
|
@ -10,7 +10,8 @@ class AccountingExportWorker
|
|||||||
raise SecurityError, 'Not allowed to export' unless export.user.admin?
|
raise SecurityError, 'Not allowed to export' unless export.user.admin?
|
||||||
|
|
||||||
data = JSON.parse(export.query)
|
data = JSON.parse(export.query)
|
||||||
service = AccountingExportService.new(
|
service = export.export_type == 'vat' ? VatExportService : AccountingExportService
|
||||||
|
service = service.new(
|
||||||
data['columns'],
|
data['columns'],
|
||||||
encoding: data['encoding'], format: export.extension, separator: export.key
|
encoding: data['encoding'], format: export.extension, separator: export.key
|
||||||
)
|
)
|
||||||
|
@ -679,9 +679,10 @@ en:
|
|||||||
codes_customization_success: "Customization of the accounting codes successfully saved."
|
codes_customization_success: "Customization of the accounting codes successfully saved."
|
||||||
unexpected_error_occurred: "An unexpected error occurred while saving the codes. Please try again later."
|
unexpected_error_occurred: "An unexpected error occurred while saving the codes. Please try again later."
|
||||||
export_accounting_data: "Export accounting data"
|
export_accounting_data: "Export accounting data"
|
||||||
export_to: "Export to the accounting software"
|
export_what: "What do you want to export?"
|
||||||
|
export_VAT: "Export the collected VAT"
|
||||||
|
export_to_ACD: "Export all data to the accounting software ACD"
|
||||||
export_is_running: "Export is running. You'll be notified when it's ready."
|
export_is_running: "Export is running. You'll be notified when it's ready."
|
||||||
acd: "ACD"
|
|
||||||
export_form_date: "Export from"
|
export_form_date: "Export from"
|
||||||
export_to_date: "Export until"
|
export_to_date: "Export until"
|
||||||
format: "File format"
|
format: "File format"
|
||||||
@ -704,6 +705,10 @@ en:
|
|||||||
debit_euro: "Euro debit"
|
debit_euro: "Euro debit"
|
||||||
credit_euro: "Euro credit"
|
credit_euro: "Euro credit"
|
||||||
lettering: "Lettering"
|
lettering: "Lettering"
|
||||||
|
start_date: "Start date"
|
||||||
|
end_date: "End date"
|
||||||
|
vat_rate: "VAT rate"
|
||||||
|
amount: "Total amount"
|
||||||
payment:
|
payment:
|
||||||
payment_settings: "Payment settings"
|
payment_settings: "Payment settings"
|
||||||
online_payment: "Online payment"
|
online_payment: "Online payment"
|
||||||
|
@ -147,6 +147,11 @@ en:
|
|||||||
Event_reservation: "event reserv."
|
Event_reservation: "event reserv."
|
||||||
Space_reservation: "space reserv."
|
Space_reservation: "space reserv."
|
||||||
wallet: "wallet"
|
wallet: "wallet"
|
||||||
|
vat_export:
|
||||||
|
start_date: "Start date"
|
||||||
|
end_date: "End date"
|
||||||
|
vat_rate: "VAT rate"
|
||||||
|
amount: "Total amount"
|
||||||
#training availabilities
|
#training availabilities
|
||||||
trainings:
|
trainings:
|
||||||
i_ve_reserved: "I've reserved"
|
i_ve_reserved: "I've reserved"
|
||||||
@ -331,6 +336,7 @@ en:
|
|||||||
users_reservations: "of the reservations' list"
|
users_reservations: "of the reservations' list"
|
||||||
availabilities_index: "of the reservations availabilities"
|
availabilities_index: "of the reservations availabilities"
|
||||||
accounting_acd: "of the accounting data to ACD"
|
accounting_acd: "of the accounting data to ACD"
|
||||||
|
accounting_vat: "of the collected VAT"
|
||||||
is_over: "is over."
|
is_over: "is over."
|
||||||
download_here: "Download here"
|
download_here: "Download here"
|
||||||
notify_admin_import_complete:
|
notify_admin_import_complete:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user