saft 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,364 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SAFT::V2
4
+ class Scribe
5
+ def self.write_xml(audit_file)
6
+ new.write_xml(audit_file)
7
+ end
8
+
9
+ def write_xml(audit_file)
10
+ builder = Nokogiri::XML::Builder.new(encoding: "UTF-8") do |xml|
11
+ build_the_xml(xml, audit_file)
12
+ end
13
+
14
+ builder.to_xml(save_with: SAFT.nokogiri_save_setting)
15
+ end
16
+
17
+ private
18
+
19
+ attr_reader(:xml)
20
+
21
+ def build_the_xml(xml, audit_file)
22
+ # avoid passing the xml builder instance
23
+ @xml = xml
24
+ namespaces = {"xmlns" => "urn:StandardAuditFile-Taxation-Financial:NO"}
25
+ xml.AuditFile(namespaces) do
26
+ build(audit_file)
27
+ end
28
+
29
+ @xml = nil
30
+ end
31
+
32
+ def build_company_structure(struct)
33
+ xml.RegistrationNumber(struct.registration_number) if struct.registration_number
34
+ xml.Name(struct.name) if struct.name
35
+ struct.addresses&.each { |address| xml.Address { build(address) } }
36
+ struct.contacts&.each { |contact| xml.Contact { build(contact) } }
37
+ struct.tax_registrations&.each { |tax_registration| xml.TaxRegistration { build(tax_registration) } }
38
+ struct.bank_accounts&.each { |bank_account| xml.BankAccount { build(bank_account) } }
39
+ end
40
+
41
+ def build(struct)
42
+ return unless struct
43
+
44
+ klass = struct.class.ancestors.detect { _1.name&.start_with?("SAFT::V2") }
45
+ # We do .name.split("::").last because this has to support all three types
46
+ case klass.name.split("::").last
47
+ when Types::AuditFile.name.split("::").last
48
+ xml.Header { build(struct.header) }
49
+ if struct.master_files
50
+ xml.MasterFiles { build(struct.master_files) }
51
+ end
52
+ if struct.general_ledger_entries
53
+ xml.GeneralLedgerEntries { build(struct.general_ledger_entries) }
54
+ end
55
+
56
+ when Types::Header.name.split("::").last
57
+ xml.AuditFileVersion(struct.audit_file_version)
58
+ xml.AuditFileCountry(struct.audit_file_country)
59
+ xml.AuditFileDateCreated(struct.audit_file_date_created)
60
+ xml.SoftwareCompanyName(struct.software_company_name)
61
+ xml.SoftwareID(struct.software_id)
62
+ xml.SoftwareVersion(struct.software_version)
63
+ xml.Company { build(struct.company) }
64
+ xml.DefaultCurrencyCode(struct.default_currency_code)
65
+ xml.SelectionCriteria { build(struct.selection_criteria) } if struct.selection_criteria
66
+ xml.HeaderComment(struct.header_comment) if struct.header_comment
67
+ xml.TaxAccountingBasis(struct.tax_accounting_basis)
68
+ xml.TaxEntity(struct.tax_entity) if struct.tax_entity
69
+ xml.UserID(struct.user_id) if struct.user_id
70
+ xml.AuditFileSender { build(struct.audit_file_sender) } if struct.audit_file_sender
71
+
72
+ when Types::Customer.name.split("::").last
73
+ build_company_structure(struct)
74
+ xml.CustomerID(struct.customer_id)
75
+ xml.SelfBillingIndicator(struct.self_billing_indicator) if struct.self_billing_indicator
76
+ xml.AccountID(struct.account_id) if struct.account_id
77
+ xml.OpeningDebitBalance(struct.opening_debit_balance.to_s("F")) if struct.opening_debit_balance
78
+ xml.OpeningCreditBalance(struct.opening_credit_balance.to_s("F")) if struct.opening_credit_balance
79
+ xml.ClosingDebitBalance(struct.closing_debit_balance.to_s("F")) if struct.closing_debit_balance
80
+ xml.ClosingCreditBalance(struct.closing_credit_balance.to_s("F")) if struct.closing_credit_balance
81
+ xml.PartyInfo { build(struct.party_info) } if struct.party_info
82
+
83
+ when Types::Supplier.name.split("::").last
84
+ build_company_structure(struct)
85
+ xml.SupplierID(struct.supplier_id)
86
+ xml.SelfBillingIndicator(struct.self_billing_indicator) if struct.self_billing_indicator
87
+ xml.AccountID(struct.account_id) if struct.account_id
88
+ xml.OpeningDebitBalance(struct.opening_debit_balance.to_s("F")) if struct.opening_debit_balance
89
+ xml.OpeningCreditBalance(struct.opening_credit_balance.to_s("F")) if struct.opening_credit_balance
90
+ xml.ClosingDebitBalance(struct.closing_debit_balance.to_s("F")) if struct.closing_debit_balance
91
+ xml.ClosingCreditBalance(struct.closing_credit_balance.to_s("F")) if struct.closing_credit_balance
92
+ xml.PartyInfo { build(struct.party_info) } if struct.party_info
93
+
94
+ when Types::Owner.name.split("::").last
95
+ build_company_structure(struct)
96
+ xml.OwnerID(struct.owner_id) if struct.owner_id
97
+ xml.AccountID(struct.account_id) if struct.account_id
98
+
99
+ when Types::CompanyHeaderStructure.name.split("::").last
100
+ build_company_structure(struct)
101
+
102
+ when Types::CompanyStructure.name.split("::").last
103
+ build_company_structure(struct)
104
+
105
+ when Types::AddressStructure.name.split("::").last
106
+ xml.StreetName(struct.street_name) if struct.street_name
107
+ xml.Number(struct.number) if struct.number
108
+ xml.AdditionalAddressDetail(struct.additional_address_detail) if struct.additional_address_detail
109
+ xml.Building(struct.building) if struct.building
110
+ xml.City(struct.city) if struct.city
111
+ xml.PostalCode(struct.postal_code) if struct.postal_code
112
+ xml.Region(struct.region) if struct.region
113
+ xml.Country(struct.country) if struct.country
114
+ xml.AddressType(struct.address_type) if struct.address_type
115
+
116
+ when Types::ContactInformationStructure.name.split("::").last
117
+ xml.ContactPerson { build(struct.contact_person) }
118
+ xml.Telephone(struct.telephone) if struct.telephone
119
+ xml.Fax(struct.fax) if struct.fax
120
+ xml.Email(struct.email) if struct.email
121
+ xml.Website(struct.website) if struct.website
122
+ xml.MobilePhone(struct.mobile_phone) if struct.mobile_phone
123
+
124
+ when Types::TaxIDStructure.name.split("::").last
125
+ xml.TaxRegistrationNumber(struct.tax_registration_number)
126
+ xml.TaxAuthority(struct.tax_authority) if struct.tax_authority
127
+ xml.TaxVerificationDate(struct.tax_verification_date) if struct.tax_verification_date
128
+
129
+ when Types::BankAccountStructure.name.split("::").last
130
+ xml.IBANNumber(struct.iban_number) if struct.iban_number
131
+ xml.BankAccountNumber(struct.bank_account_number) if struct.bank_account_number
132
+ xml.BankAccountName(struct.bank_account_name) if struct.bank_account_name
133
+ xml.SortCode(struct.sort_code) if struct.sort_code
134
+ xml.BIC(struct.bic) if struct.bic
135
+ xml.CurrencyCode(struct.currency_code) if struct.currency_code
136
+ xml.GeneralLedgerAccountID(struct.general_ledger_account_id) if struct.general_ledger_account_id
137
+
138
+ when Types::PersonNameStructure.name.split("::").last
139
+ xml.Title(struct.title) if struct.title
140
+ xml.FirstName(struct.first_name)
141
+ xml.Initials(struct.initials) if struct.initials
142
+ xml.LastNamePrefix(struct.last_name_prefix) if struct.last_name_prefix
143
+ xml.LastName(struct.last_name)
144
+ xml.BirthName(struct.birth_name) if struct.birth_name
145
+ xml.Salutation(struct.salutation) if struct.salutation
146
+ struct.other_titles&.each { xml.OtherTitles(_1) }
147
+
148
+ when Types::SelectionCriteriaStructure.name.split("::").last
149
+ xml.TaxReportingJurisdiction(struct.tax_reporting_jurisdiction) if struct.tax_reporting_jurisdiction
150
+ xml.CompanyEntity(struct.company_entity) if struct.company_entity
151
+ xml.SelectionStartDate(struct.selection_start_date) if struct.selection_start_date
152
+ xml.SelectionEndDate(struct.selection_end_date) if struct.selection_end_date
153
+ xml.PeriodStart(struct.period_start) if struct.period_start
154
+ xml.PeriodStartYear(struct.period_start_year) if struct.period_start_year
155
+ xml.PeriodEnd(struct.period_end) if struct.period_end
156
+ xml.PeriodEndYear(struct.period_end_year) if struct.period_end_year
157
+ xml.DocumentType(struct.document_type) if struct.document_type
158
+ struct.other_criterias&.each { |criteria| xml.OtherCriteria(criteria) }
159
+
160
+ when Types::AmountStructure.name.split("::").last
161
+ xml.Amount(struct.amount.to_s("F"))
162
+ xml.CurrencyCode(struct.currency_code) if struct.currency_code
163
+ xml.CurrencyAmount(struct.currency_amount.to_s("F")) if struct.currency_amount
164
+ xml.ExchangeRate(struct.exchange_rate.to_s("F")) if struct.exchange_rate
165
+
166
+ when Types::AnalysisStructure.name.split("::").last
167
+ xml.AnalysisType(struct.analysis_type) if struct.analysis_type
168
+ xml.AnalysisID(struct.analysis_id) if struct.analysis_id
169
+ xml.AnalysisAmount { build(struct.analysis_amount) } if struct.analysis_amount
170
+
171
+ when Types::AnalysisPartyInfoStructure.name.split("::").last
172
+ xml.AnalysisType(struct.analysis_type)
173
+ xml.AnalysisID(struct.analysis_id)
174
+
175
+ when Types::TaxInformationStructure.name.split("::").last
176
+ xml.TaxType(struct.tax_type) if struct.tax_type
177
+ xml.TaxCode(struct.tax_code) if struct.tax_code
178
+ xml.TaxPercentage(struct.tax_percentage.to_s("F")) if struct.tax_percentage
179
+ xml.Country(struct.country) if struct.country
180
+ xml.TaxBase(struct.tax_base.to_s("F")) if struct.tax_base
181
+ xml.TaxBaseDescription(struct.tax_base_description) if struct.tax_base_description
182
+ xml.TaxAmount { build(struct.tax_amount) }
183
+ xml.TaxExemptionReason(struct.tax_exemption_reason) if struct.tax_exemption_reason
184
+ xml.TaxDeclarationPeriod(struct.tax_declaration_period) if struct.tax_declaration_period
185
+
186
+ when Types::PaymentTerms.name.split("::").last
187
+ xml.Days(struct.days) if struct.days
188
+ xml.Months(struct.months) if struct.months
189
+ xml.CashDiscountDays(struct.cash_discount_days) if struct.cash_discount_days
190
+ xml.CashDiscountRate(struct.cash_discount_rate.to_s("F")) if struct.cash_discount_rate
191
+ xml.FreeBillingMonth(struct.free_billing_month) if struct.free_billing_month
192
+
193
+ when Types::PartyInfoStructure.name.split("::").last
194
+ xml.PaymentTerms { build(struct.payment_terms) } if struct.payment_terms
195
+ xml.NaceCode(struct.nace_code) if struct.nace_code
196
+ xml.CurrencyCode(struct.currency_code) if struct.currency_code
197
+ xml.Type(struct.type) if struct.type
198
+ xml.Status(struct.status) if struct.status
199
+ struct.analyses&.each { |analysis| xml.Analysis { build(analysis) } }
200
+ xml.Notes(struct.notes) if struct.notes
201
+
202
+ when Types::ShippingPointStructure.name.split("::").last
203
+ xml.DeliveryID(struct.delivery_id) if struct.delivery_id
204
+ xml.DeliveryDate(struct.delivery_date) if struct.delivery_date
205
+ xml.WarehouseID(struct.warehouse_id) if struct.warehouse_id
206
+ xml.LocationID(struct.location_id) if struct.location_id
207
+ xml.UCR(struct.ucr) if struct.ucr
208
+ xml.Address(struct.address) if struct.address
209
+
210
+ when Types::HeaderStructure.name.split("::").last
211
+ xml.AuditFileVersion(struct.audit_file_version)
212
+ xml.AuditFileCountry(struct.audit_file_country)
213
+ xml.AuditFileDateCreated(struct.audit_file_date_created)
214
+ xml.SoftwareCompanyName(struct.software_company_name)
215
+ xml.SoftwareID(struct.software_id)
216
+ xml.SoftwareVersion(struct.software_version)
217
+ xml.Company { build(struct.company) }
218
+ xml.DefaultCurrencyCode(struct.default_currency_code)
219
+ xml.SelectionCriteria { build(struct.selection_criteria) } if struct.selection_criteria
220
+ xml.HeaderComment(struct.header_comment) if struct.header_comment
221
+
222
+ when Types::Account.name.split("::").last
223
+ xml.AccountID(struct.account_id)
224
+ xml.AccountDescription(struct.account_description)
225
+ xml.StandardAccountID(struct.standard_account_id) if struct.standard_account_id
226
+ xml.GroupingCategory(struct.grouping_category) if struct.grouping_category
227
+ xml.GroupingCode(struct.grouping_code) if struct.grouping_code
228
+ xml.AccountType(struct.account_type)
229
+ xml.AccountCreationDate(struct.account_creation_date) if struct.account_creation_date
230
+ xml.OpeningDebitBalance(struct.opening_debit_balance.to_s("F")) if struct.opening_debit_balance
231
+ xml.OpeningCreditBalance(struct.opening_credit_balance.to_s("F")) if struct.opening_credit_balance
232
+ xml.ClosingDebitBalance(struct.closing_debit_balance.to_s("F")) if struct.closing_debit_balance
233
+ xml.ClosingCreditBalance(struct.closing_credit_balance.to_s("F")) if struct.closing_credit_balance
234
+
235
+ when Types::TaxCodeDetails.name.split("::").last
236
+ xml.TaxCode(struct.tax_code)
237
+ xml.EffectiveDate(struct.effective_date) if struct.effective_date
238
+ xml.ExpirationDate(struct.expiration_date) if struct.expiration_date
239
+ xml.Description(struct.description) if struct.description
240
+ xml.TaxPercentage(struct.tax_percentage.to_s("F")) if struct.tax_percentage
241
+ xml.Country(struct.country)
242
+ xml.StandardTaxCode(struct.standard_tax_code)
243
+ xml.Compensation(struct.compensation) if struct.compensation
244
+ struct.base_rates&.each { xml.BaseRate(_1.to_s("F")) }
245
+
246
+ when Types::TaxTableEntry.name.split("::").last
247
+ xml.TaxType(struct.tax_type) if struct.tax_type
248
+ xml.Description(struct.description) if struct.description
249
+ struct.tax_code_details&.each { |tax_code_detail| xml.TaxCodeDetails { build(tax_code_detail) } }
250
+
251
+ when Types::AnalysisTypeTableEntry.name.split("::").last
252
+ xml.AnalysisType(struct.analysis_type)
253
+ xml.AnalysisTypeDescription(struct.analysis_type_description)
254
+ xml.AnalysisID(struct.analysis_id)
255
+ xml.AnalysisIDDescription(struct.analysis_id_description)
256
+ xml.StartDate(struct.start_date) if struct.start_date
257
+ xml.EndDate(struct.end_date) if struct.end_date
258
+ xml.Status(struct.status) if struct.status
259
+ struct.analyses&.each { |analysis| xml.Analysis { build(analysis) } }
260
+
261
+ when Types::MasterFiles.name.split("::").last
262
+ if struct.general_ledger_accounts
263
+ xml.GeneralLedgerAccounts {
264
+ struct.general_ledger_accounts.each do |account|
265
+ xml.Account { build(account) }
266
+ end
267
+ }
268
+ end
269
+
270
+ if struct.customers
271
+ xml.Customers {
272
+ struct.customers.each do |customer|
273
+ xml.Customer { build(customer) }
274
+ end
275
+ }
276
+ end
277
+
278
+ if struct.suppliers
279
+ xml.Suppliers {
280
+ struct.suppliers.each do |supplier|
281
+ xml.Supplier { build(supplier) }
282
+ end
283
+ }
284
+ end
285
+
286
+ if struct.tax_table
287
+ xml.TaxTable {
288
+ struct.tax_table.each do |tax_table_entry|
289
+ xml.TaxTableEntry { build(tax_table_entry) }
290
+ end
291
+ }
292
+ end
293
+
294
+ if struct.analysis_type_table
295
+ xml.AnalysisTypeTable {
296
+ struct.analysis_type_table.each do |analysis_type_table_entry|
297
+ xml.AnalysisTypeTableEntry { build(analysis_type_table_entry) }
298
+ end
299
+ }
300
+ end
301
+
302
+ if struct.owners
303
+ xml.Owners {
304
+ struct.owners.each do |owner|
305
+ xml.Owner { build(owner) }
306
+ end
307
+ }
308
+ end
309
+
310
+ when Types::Line.name.split("::").last
311
+ xml.RecordID(struct.record_id)
312
+ xml.AccountID(struct.account_id)
313
+ struct.analyses&.each { |analysis| xml.Analysis { build(analysis) } }
314
+ xml.ValueDate(struct.value_date) if struct.value_date
315
+ xml.SourceDocumentID(struct.source_document_id) if struct.source_document_id
316
+ xml.CustomerID(struct.customer_id) if struct.customer_id
317
+ xml.SupplierID(struct.supplier_id) if struct.supplier_id
318
+ xml.Description(struct.description)
319
+ xml.DebitAmount { build(struct.debit_amount) } if struct.debit_amount
320
+ xml.CreditAmount { build(struct.credit_amount) } if struct.credit_amount
321
+ struct.tax_information&.each { |tax_information| xml.TaxInformation { build(tax_information) } }
322
+ xml.ReferenceNumber(struct.reference_number) if struct.reference_number
323
+ xml.CID(struct.cid) if struct.cid
324
+ xml.DueDate(struct.due_date) if struct.due_date
325
+ xml.Quantity(struct.quantity.to_s("F")) if struct.quantity
326
+ xml.CrossReference(struct.cross_reference) if struct.cross_reference
327
+ xml.SystemEntryTime(struct.system_entry_time.strftime("%FT%T")) if struct.system_entry_time
328
+ xml.OwnerID(struct.owner_id) if struct.owner_id
329
+
330
+ when Types::Transaction.name.split("::").last
331
+ xml.TransactionID(struct.transaction_id) if struct.transaction_id
332
+ xml.Period(struct.period) if struct.period
333
+ xml.PeriodYear(struct.period_year) if struct.period_year
334
+ xml.TransactionDate(struct.transaction_date) if struct.transaction_date
335
+ xml.SourceID(struct.source_id) if struct.source_id
336
+ xml.TransactionType(struct.transaction_type) if struct.transaction_type
337
+ xml.Description(struct.description) if struct.description
338
+ xml.BatchID(struct.batch_id) if struct.batch_id
339
+ xml.SystemEntryDate(struct.system_entry_date) if struct.system_entry_date
340
+ xml.GLPostingDate(struct.gl_posting_date) if struct.gl_posting_date
341
+ xml.SystemID(struct.system_id) if struct.system_id
342
+ struct.lines&.each do |line|
343
+ xml.Line { build(line) }
344
+ end
345
+
346
+ when Types::Journal.name.split("::").last
347
+ xml.JournalID(struct.journal_id) if struct.journal_id
348
+ xml.Description(struct.description) if struct.description
349
+ xml.Type(struct.type) if struct.type
350
+ struct.transactions&.each do |transaction|
351
+ xml.Transaction { build(transaction) }
352
+ end
353
+
354
+ when Types::GeneralLedgerEntries.name.split("::").last
355
+ xml.NumberOfEntries(struct.number_of_entries) if struct.number_of_entries
356
+ xml.TotalDebit(struct.total_debit.to_s("F")) if struct.total_debit
357
+ xml.TotalCredit(struct.total_credit.to_s("F")) if struct.total_credit
358
+ struct.journals&.each do |journal|
359
+ xml.Journal { build(journal) }
360
+ end
361
+ end
362
+ end
363
+ end
364
+ end