Skip to content

Commit

Permalink
feat: improve taf export
Browse files Browse the repository at this point in the history
  • Loading branch information
diegosteiner committed Dec 5, 2024
1 parent 800c2d9 commit ca0c60a
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 76 deletions.
1 change: 1 addition & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ Naming/MethodParameterName:
AllowedNames:
- "to"
- "at"
- "as"

Rails/EnvironmentVariableAccess:
AllowReads: true
Expand Down
21 changes: 0 additions & 21 deletions app/models/accounting.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,25 +46,4 @@ def to_s
].compact.join(' ')
end
end

JournalEntryGroup = Data.define(:id, :date, :items) do
extend ActiveModel::Translation
extend ActiveModel::Naming

def initialize(**args)
args.symbolize_keys!
date = args.delete(:date)&.then { _1.try(:to_date) || Date.parse(_1).to_date }
items = Array.wrap(args.delete(:items)).map do |item|
case item
when Hash, JournalEntry
JournalEntry.new(**item.to_h)
end
end.compact
super(id: nil, **args, items:, date:)
end

def to_h
super.merge(items: items.map(&:to_h))
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ def crunch(records)
formatter(:taf) do |_options = {}|
records.keys.map do |source|
TafBlock::Collection.new do
derive(source.booking.tenant)
derive(source)
end
end.join("\n\n")
Expand Down
6 changes: 3 additions & 3 deletions app/models/invoice.rb
Original file line number Diff line number Diff line change
Expand Up @@ -192,15 +192,15 @@ def journal_entries
end

def human_ref
ref
format('HV%05d', id)
end

def debitor_journal_entry
Accounting::JournalEntry.new(
account: booking.tenant.accounting_debitor_account_nr,
date: issued_at, amount:, amount_type: :brutto, side: :soll,
reference: ref, source: self, currency:, booking:,
text: [self.class.model_name.human, ref].join(' ')
reference: human_ref, source: self, currency:, booking:,
text: [self.class.model_name.human, human_ref].join(' ')
)
end
end
4 changes: 2 additions & 2 deletions app/models/invoice_parts/add.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ def journal_entries # rubocop:disable Metrics/AbcSize
[
Accounting::JournalEntry.new(
account: tarif&.accounting_account_nr, date: invoice.issued_at, amount: amount.abs, amount_type: :brutto,
side: :haben, tax_code: vat_category&.accounting_vat_code, reference: invoice.ref, source: self,
side: :haben, tax_code: vat_category&.accounting_vat_code, reference: invoice.human_ref, source: self,
currency: organisation.currency, booking:, cost_center: tarif&.accounting_profit_center_nr,
text: [invoice.class.model_name.human, invoice.ref, self.class.model_name.human, label].join(' ')
text: [invoice.class.model_name.human, invoice.human_ref, label].join(' ')
)
]
end
Expand Down
3 changes: 1 addition & 2 deletions app/models/tenant.rb
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,6 @@ def merge_with_new(tenant)
end

def accounting_debitor_account_nr
@accounting_debitor_account_nr ||= organisation.accounting_settings&.debitor_account_nr.presence ||
(id + (organisation.accounting_settings&.tenant_debitor_account_nr_base || 0))
@accounting_debitor_account_nr ||= (organisation.accounting_settings&.tenant_debitor_account_nr_base || 0) + id
end
end
109 changes: 63 additions & 46 deletions app/services/taf_block.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,40 +7,46 @@ class TafBlock

def initialize(type, **properties, &)
@type = type
@properties = properties.to_h
@properties = properties.transform_values { Value.cast(_1) }
@children = Collection.new(&)
end

def self.block(...)
new(...)
end

Value = Data.define(:value) do
delegate :to_s, to: :value

def self.derive(value)
new derive_value(value)
Value = Data.define(:value, :as) do
CAST_BLOCKS = { # rubocop:disable Lint/ConstantDefinitionInBlock
boolean: ->(value) { value ? '1' : '0' },
decimal: ->(value) { format('%.2f', value) },
number: ->(value) { value.to_i.to_s },
date: ->(value) { value.strftime('%d.%m.%Y') },
string: ->(value) { "\"#{value.gsub(/["']/, '""')}\"" },
symbol: ->(value) { value.to_s },
vector: ->(value) { "[#{value.to_a.map(&:to_s).join(',')}]" },
value: ->(value) { value }
}.freeze

CAST_CLASSES = { # rubocop:disable Lint/ConstantDefinitionInBlock
boolean: [::FalseClass, ::TrueClass],
decimal: [::BigDecimal, ::Float],
number: [::Numeric],
date: [::Date, ::DateTime, ::ActiveSupport::TimeWithZone],
string: [::String]
}.freeze

def self.cast(value, as: nil)
return value if value.is_a?(Value)
return nil if value.blank?

as = CAST_CLASSES.find { |_key, klasses| klasses.any? { |klass| value.is_a?(klass) } }&.first if as.nil?
value = CAST_BLOCKS.fetch(as).call(value)

new(value, as)
end

def self.derive_value(value) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/MethodLength
case value
when ::FalseClass, ::TrueClass
value ? '1' : '0'
when ::BigDecimal, ::Float
format('%.2f', value)
when ::Numeric
value.to_s
when ::Date, ::DateTime, ::ActiveSupport::TimeWithZone
value.strftime('%d.%m.%Y')
when ::String
"\"#{value.gsub(/["']/, '""')}\""
when ::Enumerable
"[#{value.to_a.each { derive_value(_1) }.join(',')}]"
when Value
value
else
derive_value value.to_s
end
def serialize
value.to_s
end
end

Expand Down Expand Up @@ -75,14 +81,14 @@ def serialize(indent_level: 0, indent_with: ' ', separate_with: "\n")
indent = [indent_with * indent_level].join
separate_and_indent = [separate_with, indent, indent_with].join
serialized_children = children.serialize(indent_level:, indent_with:, separate_with:)
serialized_properties = properties.compact.map { |key, value| "#{key}=#{Value.derive(value)}" }
serialized_properties = properties.compact.map { |key, value| "#{key}=#{value.serialize}" }

[ # tag_start
indent, "{#{type}",
# properties
separate_and_indent, serialized_properties.join(separate_and_indent),
separate_and_indent, serialized_properties.join(separate_and_indent), separate_with,
# children
(serialized_children.present? && separate_with) || nil, serialized_children,
(separate_with if children.present?), serialized_children,
# tag end
separate_with, indent, '}'
].compact.join
Expand All @@ -100,18 +106,9 @@ def self.derive_from(klass, &derive_block)
factories[klass] = derive_block
end

def self.derive(value, **override, &block)
def self.derive(value, **override)
derive_block = factories[factories.keys.find { |klass| value.is_a?(klass) }]
instance_exec(value, override, block, &derive_block) if derive_block.present?
end

derive_from Accounting::JournalEntryGroup do |value, **override|
new(:Blg, **{
# Date; The date of the booking.
Date: override.fetch(:Date, value.date),

Orig: true
})
instance_exec(value, **override, &derive_block) if derive_block.present?
end

derive_from Accounting::JournalEntry do |journal_entry, **override|
Expand Down Expand Up @@ -187,20 +184,40 @@ def self.derive(value, **override, &block)
}, **override)
end

derive_from Invoice do |invoice, **override|
derive_from Invoice do |invoice, **_override|
next unless invoice.is_a?(Invoices::Invoice) || invoice.is_a?(Invoices::Deposit)

op_id = invoice.human_ref
pk_key = [Value.new(invoice.booking.tenant.accounting_debitor_account_nr),
Value.new(invoice.organisation.accounting_settings.currency_account_nr)]
journal_entries = invoice.journal_entries.to_a
op_id = Value.cast(invoice.human_ref, as: :symbol)
pk_key = [invoice.booking.tenant.accounting_debitor_account_nr,
invoice.organisation.accounting_settings.currency_account_nr].then { "[#{_1.join(',')}]" }

journal_entries = invoice.journal_entries.flatten.compact

[
new(:OPd, **{ PkKey: pk_key, OpId: op_id, ZabId: '15T' }, **override),
new(:Blg, **{ OpId: op_id, Date: invoice.issued_at, Orig: true }, **override) do
new(:OPd, **{ PkKey: pk_key, OpId: op_id, ZabId: '15T' }),
new(:Blg, **{ OpId: op_id, Date: invoice.issued_at, Orig: true }) do
derive(journal_entries.shift, Flags: 1, OpId: op_id)
journal_entries.each { derive(_1, OpId: op_id) }
end
]
end

derive_from Tenant do |tenant, **_override|
[
new(:Adr, **{
AdrId: tenant.accounting_debitor_account_nr,
Line1: tenant.full_name,
Road: tenant.street_address,
CCode: tenant.country_code,
ACode: tenant.zipcode,
City: tenant.city
}),
new(:PKd, **{
PkKey: Value.cast(tenant.accounting_debitor_account_nr, as: :symbol),
AdrId: Value.cast(tenant.accounting_debitor_account_nr, as: :symbol),
AccId: Value.cast(tenant.organisation.accounting_settings.currency_account_nr, as: :symbol)
})

]
end
end
8 changes: 6 additions & 2 deletions spec/services/taf_block_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
describe '#initialize' do
it 'works as DSL' do
expect(taf_block.type).to eq(:Blg)
expect(taf_block.properties).to eq({ test: 1, text: 'TAF is "great"' })
expect(taf_block.properties.transform_values(&:value)).to eq({ test: '1', text: '"TAF is ""great"""' })
expect(taf_block.children.count).to eq(1)
expect(taf_block.children.first.type).to eq(:Bk)
expect(taf_block.children.first.properties).to eq({ test: 2 })
expect(taf_block.children.first.properties.transform_values(&:value)).to eq({ test: '2' })
expect(taf_block.children.first.children.count).to eq(0)
end
end
Expand All @@ -28,8 +28,10 @@
{Blg
text="TAF is ""great"""
test=1
{Bk
test=2
}
}
TAF
Expand Down Expand Up @@ -60,6 +62,7 @@
Type=0
ValNt=2091.75
OpId="1234"
}
TAF
end
Expand All @@ -86,6 +89,7 @@
Type=0
ValNt=2091.75
OpId="1234"
}
TAF
end
Expand Down

0 comments on commit ca0c60a

Please sign in to comment.