saft 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gemspec +34 -0
- data/.rspec +4 -0
- data/.rubocop.yml +72 -0
- data/.rubocop_strict.yml +7 -0
- data/.ruby-gemset +1 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +26 -0
- data/Rakefile +18 -0
- data/docs/Norwegian SAF-T Financial data.pdf +0 -0
- data/docs/Norwegian SAF-T Standard VAT:Tax codes.pdf +0 -0
- data/docs/saf-t v2 xsd by oecd.pdf +0 -0
- data/lib/saft/v2/html.css +3 -0
- data/lib/saft/v2/html.rb +685 -0
- data/lib/saft/v2/html_dist.css +594 -0
- data/lib/saft/v2/norway.rb +133 -0
- data/lib/saft/v2/parse.rb +351 -0
- data/lib/saft/v2/scribe.rb +364 -0
- data/lib/saft/v2/types.rb +493 -0
- data/lib/saft/v2/xsd_validate.rb +28 -0
- data/lib/saft/v2.rb +36 -0
- data/lib/saft/version.rb +3 -0
- data/lib/saft.rb +26 -0
- data/package.json +15 -0
- data/pnpm-lock.yaml +443 -0
- data/readme.md +92 -0
- data/tailwind.config.js +10 -0
- data/vendor/SAF-T_Financial_Schema_NO_1.10.xsd +3343 -0
- data/vendor/norway/general_ledger_standard_accounts.xsd +54 -0
- data/vendor/norway/general_ledger_standard_accounts_2_character.csv +75 -0
- data/vendor/norway/general_ledger_standard_accounts_2_character.xml +373 -0
- data/vendor/norway/general_ledger_standard_accounts_4_character.csv +747 -0
- data/vendor/norway/general_ledger_standard_accounts_4_character.xml +3733 -0
- data/vendor/norway/standard_tax_codes.csv +31 -0
- data/vendor/norway/standard_tax_codes.xml +199 -0
- data/vendor/norway/standard_tax_codes.xsd +67 -0
- metadata +121 -0
@@ -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
|