mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-02-19 13:54:25 +01:00
service to export invoices into a given period to CSV lines for an accounting sofware
This commit is contained in:
parent
3d3be70e29
commit
ab295f064d
@ -3,7 +3,7 @@ Metrics/LineLength:
|
||||
Metrics/MethodLength:
|
||||
Max: 30
|
||||
Metrics/CyclomaticComplexity:
|
||||
Max: 9
|
||||
Max: 12
|
||||
Metrics/PerceivedComplexity:
|
||||
Max: 9
|
||||
Metrics/AbcSize:
|
||||
|
@ -188,7 +188,7 @@ class Invoice < ActiveRecord::Base
|
||||
|
||||
def subscription_invoice?
|
||||
invoice_items.each do |ii|
|
||||
return true if ii.subscription && !ii.subscription.expired?
|
||||
return true if ii.subscription
|
||||
end
|
||||
false
|
||||
end
|
||||
|
200
app/services/accounting_export_service.rb
Normal file
200
app/services/accounting_export_service.rb
Normal file
@ -0,0 +1,200 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Provides the routine to export the accounting data to an external accounting software
|
||||
class AccountingExportService
|
||||
attr_reader :file, :encoding, :format, :separator, :log_code, :date_format
|
||||
|
||||
def initialize(file, columns, encoding = 'UTF-8', format = 'CSV', separator = ';')
|
||||
@file = file
|
||||
@encoding = encoding
|
||||
@format = format
|
||||
@separator = separator
|
||||
@log_code = Setting.find_by(name: 'accounting-export_log-code').value
|
||||
@date_format = Setting.find_by(name: 'accounting-export_date-format').value
|
||||
@columns = columns
|
||||
end
|
||||
|
||||
def export(start_date, end_date)
|
||||
# build CVS content
|
||||
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)
|
||||
end
|
||||
|
||||
# write content to file
|
||||
File.open(file, "w:#{encoding}+b") { |f| f.puts content }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def generate_rows(invoice)
|
||||
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" : ''
|
||||
invoice.invoice_items.each do |item|
|
||||
rows << reservation_row(invoice, item) << "\n"
|
||||
end
|
||||
end
|
||||
|
||||
# Generate the "client" row, which contains the debit to the client account, all taxes included
|
||||
def client_row(invoice)
|
||||
row = ''
|
||||
columns.each do |column|
|
||||
case column
|
||||
when :log_code
|
||||
row << log_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 << invoice.total / 100.0
|
||||
when :credit_origin
|
||||
row << 0
|
||||
when :debit_euro
|
||||
row << invoice.total / 100.0
|
||||
when :credit_euro
|
||||
row << 0
|
||||
else
|
||||
puts "Unsupported column: #{column}"
|
||||
end
|
||||
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 :log_code
|
||||
row << log_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 << 0
|
||||
when :credit_origin
|
||||
row << wo_taxes
|
||||
when :debit_euro
|
||||
row << 0
|
||||
when :credit_euro
|
||||
row << wo_taxes
|
||||
else
|
||||
puts "Unsupported column: #{column}"
|
||||
end
|
||||
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 :log_code
|
||||
row << log_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 << 0
|
||||
when :credit_origin
|
||||
row << wo_taxes
|
||||
when :debit_euro
|
||||
row << 0
|
||||
when :credit_euro
|
||||
row << wo_taxes
|
||||
else
|
||||
puts "Unsupported column: #{column}"
|
||||
end
|
||||
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 :log_code
|
||||
row << log_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 << vat
|
||||
when :credit_origin
|
||||
row << 0
|
||||
when :debit_euro
|
||||
row << vat
|
||||
when :credit_euro
|
||||
row << 0
|
||||
else
|
||||
puts "Unsupported column: #{column}"
|
||||
end
|
||||
row << separator
|
||||
end
|
||||
end
|
||||
|
||||
# Get the account code (or label) for the given invoice and the specified line type (client, vat, subscription or reservation)
|
||||
def account(invoice, account, type = :code)
|
||||
case account
|
||||
when :client
|
||||
Setting.find_by(name: "accounting-export_client-account-#{type.to_s}").value
|
||||
when :vat
|
||||
Setting.find_by(name: "accounting-export_VAT-account-#{type.to_s}").value
|
||||
when :subscription
|
||||
return if invoice.invoiced_type != 'Subscription'
|
||||
|
||||
Setting.find_by(name: "accounting-export_subscription-account-#{type.to_s}").value
|
||||
when :reservation
|
||||
return if invoice.invoiced_type != 'Reservation'
|
||||
|
||||
Setting.find_by(name: "accounting-export_#{invoice.invoiced.reservable_type}-account-#{type.to_s}").value
|
||||
else
|
||||
puts "Unsupported account #{account}"
|
||||
end
|
||||
end
|
||||
end
|
@ -1,3 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'abstract_controller'
|
||||
require 'action_controller'
|
||||
require 'action_view'
|
||||
@ -13,7 +15,7 @@ class StatisticsExportService
|
||||
# query all stats with range arguments
|
||||
query = MultiJson.load(export.query)
|
||||
|
||||
@results = Elasticsearch::Model.client.search({index: 'stats', scroll: '30s', body: query})
|
||||
@results = Elasticsearch::Model.client.search(index: 'stats', scroll: '30s', body: query)
|
||||
scroll_id = @results['_scroll_id']
|
||||
while @results['hits']['hits'].size != @results['hits']['total']
|
||||
scroll_res = Elasticsearch::Model.client.scroll(scroll: '30s', scroll_id: scroll_id)
|
||||
@ -22,9 +24,9 @@ class StatisticsExportService
|
||||
end
|
||||
|
||||
ids = @results['hits']['hits'].map { |u| u['_source']['userId'] }
|
||||
@users = User.includes(:profile).where(:id => ids)
|
||||
@users = User.includes(:profile).where(id: ids)
|
||||
|
||||
@indices = StatisticIndex.all.includes(:statistic_fields, :statistic_types => [:statistic_sub_types])
|
||||
@indices = StatisticIndex.all.includes(:statistic_fields, statistic_types: [:statistic_sub_types])
|
||||
|
||||
ActionController::Base.prepend_view_path './app/views/'
|
||||
# place data in view_assigns
|
||||
@ -37,10 +39,10 @@ class StatisticsExportService
|
||||
|
||||
content = av.render template: 'exports/statistics_global.xlsx.axlsx'
|
||||
# write content to file
|
||||
File.open(export.file,"w+b") {|f| f.puts content }
|
||||
File.open(export.file, 'w+b') { |f| f.puts content }
|
||||
end
|
||||
|
||||
%w(account event machine project subscription training space).each do |path|
|
||||
%w[account event machine project subscription training space].each do |path|
|
||||
class_eval %{
|
||||
def export_#{path}(export)
|
||||
|
||||
@ -76,7 +78,7 @@ class StatisticsExportService
|
||||
# write content to file
|
||||
File.open(export.file,"w+b") {|f| f.puts content }
|
||||
end
|
||||
}
|
||||
}, __FILE__, __LINE__ - 35
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
@ -126,6 +126,9 @@ fr:
|
||||
subscription_of_NAME_extended_starting_from_STARTDATE_until_ENDDATE: "Prolongement Abonnement (Jours gratuits) de %{NAME} à compter du %{STARTDATE} jusqu'au %{ENDDATE}"
|
||||
and: 'et'
|
||||
|
||||
accounting_export:
|
||||
VAT: 'TVA'
|
||||
|
||||
trainings:
|
||||
# disponibilités formations
|
||||
i_ve_reserved: "J'ai réservé"
|
||||
|
Loading…
x
Reference in New Issue
Block a user