saft 0.1.1

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