update
This commit is contained in:
parent
73617e46e4
commit
b4a95de482
examples
test
output
circular-corpus-results.json
test.circular-corpus.tstest.corpus-master.tstest.focused-corpus.tstest.other-formats-corpus.tstest.simple-corpus.tstest.validation-corpus.tstest.xml-rechnung-corpus.tstest.zugferd-corpus.tscircular
EN16931_1_Teilrechnung.cii.xml-exported.xmlEN16931_1_Teilrechnung.ubl.xml-exported.xmlEN16931_2_Teilrechnung.cii.xml-exported.xmlEN16931_2_Teilrechnung.ubl.xml-exported.xmlEN16931_AbweichenderZahlungsempf.cii.xml-exported.xmlEN16931_AbweichenderZahlungsempf.ubl.xml-exported.xml
focused
EN16931_1_Teilrechnung.cii.xml-exported.xmlEN16931_1_Teilrechnung.ubl.xml-exported.xmlEN16931_2_Teilrechnung.cii.xml-exported.xmlEN16931_2_Teilrechnung.ubl.xml-exported.xmlEN16931_AbweichenderZahlungsempf.cii.xml-exported.xmlEN16931_AbweichenderZahlungsempf.ubl.xml-exported.xmlEN16931_Betriebskostenabrechnung.cii.xml-exported.xmlEN16931_Betriebskostenabrechnung.ubl.xml-exported.xmlEN16931_Einfach.cii.xml-exported.xmlEN16931_Einfach.ubl.xml-exported.xmlzugferd_2p0_EN16931_1_Teilrechnung.pdf-extracted.xmlzugferd_2p0_EN16931_1_Teilrechnung.pdf-raw-(zugferd-invoice.xml).xmlzugferd_2p0_EN16931_2_Teilrechnung.pdf-extracted.xmlzugferd_2p0_EN16931_2_Teilrechnung.pdf-raw-(zugferd-invoice.xml).xmlzugferd_2p0_EN16931_AbweichenderZahlungsempf.pdf-extracted.xmlzugferd_2p0_EN16931_AbweichenderZahlungsempf.pdf-raw-(zugferd-invoice.xml).xmlzugferd_2p0_EN16931_Betriebskostenabrechnung.pdf-extracted.xmlzugferd_2p0_EN16931_Betriebskostenabrechnung.pdf-raw-(AWV_13_Betriebskosten.pdf).xmlzugferd_2p0_EN16931_Betriebskostenabrechnung.pdf-raw-(zugferd-invoice.xml).xmlzugferd_2p0_EN16931_Einfach.pdf-extracted.xmlzugferd_2p0_EN16931_Einfach.pdf-raw-(zugferd-invoice.xml).xml
simple
test-invoice-with-xml.pdfvalidation-corpus-results.jsonxml-rechnung-corpus-results.jsonzugferd-corpus-results.jsonts
@ -1,215 +0,0 @@
|
|||||||
import { PDFEmbedder, PDFExtractor, TInvoice, FacturXEncoder } from '../ts/index.js';
|
|
||||||
import * as fs from 'fs/promises';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Example demonstrating how to use the PDF handling classes
|
|
||||||
*/
|
|
||||||
async function pdfHandlingExample() {
|
|
||||||
try {
|
|
||||||
// Create a sample invoice
|
|
||||||
const invoice: TInvoice = createSampleInvoice();
|
|
||||||
|
|
||||||
// Create a Factur-X encoder
|
|
||||||
const encoder = new FacturXEncoder();
|
|
||||||
|
|
||||||
// Generate XML
|
|
||||||
const xmlContent = await encoder.encode(invoice);
|
|
||||||
console.log('Generated XML:');
|
|
||||||
console.log(xmlContent.substring(0, 500) + '...');
|
|
||||||
|
|
||||||
// Load a sample PDF
|
|
||||||
const pdfBuffer = await fs.readFile('examples/sample.pdf');
|
|
||||||
console.log(`Loaded PDF (${pdfBuffer.length} bytes)`);
|
|
||||||
|
|
||||||
// Create a PDF embedder
|
|
||||||
const embedder = new PDFEmbedder();
|
|
||||||
|
|
||||||
// Embed XML into PDF
|
|
||||||
const modifiedPdfBuffer = await embedder.embedXml(
|
|
||||||
pdfBuffer,
|
|
||||||
xmlContent,
|
|
||||||
'factur-x.xml',
|
|
||||||
'Factur-X XML Invoice'
|
|
||||||
);
|
|
||||||
console.log(`Created modified PDF (${modifiedPdfBuffer.length} bytes)`);
|
|
||||||
|
|
||||||
// Save the modified PDF
|
|
||||||
await fs.writeFile('examples/output.pdf', modifiedPdfBuffer);
|
|
||||||
console.log('Saved modified PDF to examples/output.pdf');
|
|
||||||
|
|
||||||
// Create a PDF extractor
|
|
||||||
const extractor = new PDFExtractor();
|
|
||||||
|
|
||||||
// Extract XML from the modified PDF
|
|
||||||
const extractedXml = await extractor.extractXml(modifiedPdfBuffer);
|
|
||||||
console.log('Extracted XML:');
|
|
||||||
console.log(extractedXml ? extractedXml.substring(0, 500) + '...' : 'No XML found');
|
|
||||||
|
|
||||||
// Save the extracted XML
|
|
||||||
if (extractedXml) {
|
|
||||||
await fs.writeFile('examples/extracted.xml', extractedXml);
|
|
||||||
console.log('Saved extracted XML to examples/extracted.xml');
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('PDF handling example completed successfully');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error in PDF handling example:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a sample invoice for testing
|
|
||||||
* @returns Sample invoice
|
|
||||||
*/
|
|
||||||
function createSampleInvoice(): TInvoice {
|
|
||||||
return {
|
|
||||||
type: 'invoice',
|
|
||||||
id: 'INV-2023-001',
|
|
||||||
invoiceType: 'debitnote',
|
|
||||||
date: Date.now(),
|
|
||||||
status: 'invoice',
|
|
||||||
versionInfo: {
|
|
||||||
type: 'final',
|
|
||||||
version: '1.0.0'
|
|
||||||
},
|
|
||||||
language: 'en',
|
|
||||||
incidenceId: 'INV-2023-001',
|
|
||||||
from: {
|
|
||||||
type: 'company',
|
|
||||||
name: 'Supplier Company',
|
|
||||||
description: 'Supplier',
|
|
||||||
address: {
|
|
||||||
streetName: 'Supplier Street',
|
|
||||||
houseNumber: '123',
|
|
||||||
postalCode: '12345',
|
|
||||||
city: 'Supplier City',
|
|
||||||
country: 'DE',
|
|
||||||
countryCode: 'DE'
|
|
||||||
},
|
|
||||||
status: 'active',
|
|
||||||
foundedDate: {
|
|
||||||
year: 2000,
|
|
||||||
month: 1,
|
|
||||||
day: 1
|
|
||||||
},
|
|
||||||
registrationDetails: {
|
|
||||||
vatId: 'DE123456789',
|
|
||||||
registrationId: 'HRB12345',
|
|
||||||
registrationName: 'Supplier Company GmbH'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
to: {
|
|
||||||
type: 'company',
|
|
||||||
name: 'Customer Company',
|
|
||||||
description: 'Customer',
|
|
||||||
address: {
|
|
||||||
streetName: 'Customer Street',
|
|
||||||
houseNumber: '456',
|
|
||||||
postalCode: '54321',
|
|
||||||
city: 'Customer City',
|
|
||||||
country: 'DE',
|
|
||||||
countryCode: 'DE'
|
|
||||||
},
|
|
||||||
status: 'active',
|
|
||||||
foundedDate: {
|
|
||||||
year: 2005,
|
|
||||||
month: 6,
|
|
||||||
day: 15
|
|
||||||
},
|
|
||||||
registrationDetails: {
|
|
||||||
vatId: 'DE987654321',
|
|
||||||
registrationId: 'HRB54321',
|
|
||||||
registrationName: 'Customer Company GmbH'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
subject: 'Invoice INV-2023-001',
|
|
||||||
content: {
|
|
||||||
invoiceData: {
|
|
||||||
id: 'INV-2023-001',
|
|
||||||
status: null,
|
|
||||||
type: 'debitnote',
|
|
||||||
billedBy: {
|
|
||||||
type: 'company',
|
|
||||||
name: 'Supplier Company',
|
|
||||||
description: 'Supplier',
|
|
||||||
address: {
|
|
||||||
streetName: 'Supplier Street',
|
|
||||||
houseNumber: '123',
|
|
||||||
postalCode: '12345',
|
|
||||||
city: 'Supplier City',
|
|
||||||
country: 'DE',
|
|
||||||
countryCode: 'DE'
|
|
||||||
},
|
|
||||||
status: 'active',
|
|
||||||
foundedDate: {
|
|
||||||
year: 2000,
|
|
||||||
month: 1,
|
|
||||||
day: 1
|
|
||||||
},
|
|
||||||
registrationDetails: {
|
|
||||||
vatId: 'DE123456789',
|
|
||||||
registrationId: 'HRB12345',
|
|
||||||
registrationName: 'Supplier Company GmbH'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
billedTo: {
|
|
||||||
type: 'company',
|
|
||||||
name: 'Customer Company',
|
|
||||||
description: 'Customer',
|
|
||||||
address: {
|
|
||||||
streetName: 'Customer Street',
|
|
||||||
houseNumber: '456',
|
|
||||||
postalCode: '54321',
|
|
||||||
city: 'Customer City',
|
|
||||||
country: 'DE',
|
|
||||||
countryCode: 'DE'
|
|
||||||
},
|
|
||||||
status: 'active',
|
|
||||||
foundedDate: {
|
|
||||||
year: 2005,
|
|
||||||
month: 6,
|
|
||||||
day: 15
|
|
||||||
},
|
|
||||||
registrationDetails: {
|
|
||||||
vatId: 'DE987654321',
|
|
||||||
registrationId: 'HRB54321',
|
|
||||||
registrationName: 'Customer Company GmbH'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
deliveryDate: Date.now(),
|
|
||||||
dueInDays: 30,
|
|
||||||
periodOfPerformance: null,
|
|
||||||
printResult: null,
|
|
||||||
currency: 'EUR',
|
|
||||||
notes: ['Thank you for your business'],
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
position: 1,
|
|
||||||
name: 'Product A',
|
|
||||||
articleNumber: 'PROD-A',
|
|
||||||
unitType: 'EA',
|
|
||||||
unitQuantity: 2,
|
|
||||||
unitNetPrice: 100,
|
|
||||||
vatPercentage: 19
|
|
||||||
},
|
|
||||||
{
|
|
||||||
position: 2,
|
|
||||||
name: 'Service B',
|
|
||||||
articleNumber: 'SERV-B',
|
|
||||||
unitType: 'HUR',
|
|
||||||
unitQuantity: 5,
|
|
||||||
unitNetPrice: 80,
|
|
||||||
vatPercentage: 19
|
|
||||||
}
|
|
||||||
],
|
|
||||||
reverseCharge: false
|
|
||||||
},
|
|
||||||
textData: null,
|
|
||||||
timesheetData: null,
|
|
||||||
contractData: null
|
|
||||||
}
|
|
||||||
} as TInvoice;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run the example
|
|
||||||
pdfHandlingExample();
|
|
45
test/output/circular-corpus-results.json
Normal file
45
test/output/circular-corpus-results.json
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
{
|
||||||
|
"cii": {
|
||||||
|
"success": 3,
|
||||||
|
"fail": 0,
|
||||||
|
"details": [
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/EN16931_1_Teilrechnung.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/EN16931_2_Teilrechnung.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/EN16931_AbweichenderZahlungsempf.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"error": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ubl": {
|
||||||
|
"success": 3,
|
||||||
|
"fail": 0,
|
||||||
|
"details": [
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/EN16931_1_Teilrechnung.ubl.xml",
|
||||||
|
"success": true,
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/EN16931_2_Teilrechnung.ubl.xml",
|
||||||
|
"success": true,
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/EN16931_AbweichenderZahlungsempf.ubl.xml",
|
||||||
|
"success": true,
|
||||||
|
"error": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"totalSuccessRate": 1
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<rsm:CrossIndustryInvoice xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100" xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100" xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100">
|
||||||
|
<rsm:ExchangedDocumentContext><ram:GuidelineSpecifiedDocumentContextParameter><ram:ID>urn:cen.eu:en16931:2017</ram:ID></ram:GuidelineSpecifiedDocumentContextParameter></rsm:ExchangedDocumentContext><rsm:ExchangedDocument><ram:TypeCode>380</ram:TypeCode><ram:ID>471102</ram:ID><ram:IssueDateTime><udt:DateTimeString format="102">NaNNaNNaN</udt:DateTimeString></ram:IssueDateTime></rsm:ExchangedDocument><rsm:SupplyChainTradeTransaction><ram:ApplicableHeaderTradeAgreement><ram:SellerTradeParty><ram:Name>Lieferant GmbH</ram:Name><ram:PostalTradeAddress><ram:LineOne>Lieferantenstraße 20</ram:LineOne><ram:LineTwo>0</ram:LineTwo><ram:PostcodeCode>80333</ram:PostcodeCode><ram:CityName>München</ram:CityName><ram:CountryID>DE</ram:CountryID></ram:PostalTradeAddress><ram:SpecifiedTaxRegistration><ram:ID schemeID="VA">DE123456789</ram:ID></ram:SpecifiedTaxRegistration><ram:SpecifiedTaxRegistration><ram:ID schemeID="FC">201/113/40209</ram:ID></ram:SpecifiedTaxRegistration></ram:SellerTradeParty><ram:BuyerTradeParty><ram:Name>Kunden AG Mitte</ram:Name><ram:PostalTradeAddress><ram:LineOne>Kundenstraße 15</ram:LineOne><ram:LineTwo>0</ram:LineTwo><ram:PostcodeCode>69876</ram:PostcodeCode><ram:CityName>Frankfurt</ram:CityName><ram:CountryID>DE</ram:CountryID></ram:PostalTradeAddress></ram:BuyerTradeParty></ram:ApplicableHeaderTradeAgreement><ram:ApplicableHeaderTradeDelivery/><ram:ApplicableHeaderTradeSettlement><ram:InvoiceCurrencyCode>EUR</ram:InvoiceCurrencyCode><ram:SpecifiedTradePaymentTerms><ram:DueDateDateTime><udt:DateTimeString format="102">NaNNaNNaN</udt:DateTimeString></ram:DueDateDateTime></ram:SpecifiedTradePaymentTerms><ram:SpecifiedTradeSettlementHeaderMonetarySummation><ram:LineTotalAmount>180.70</ram:LineTotalAmount><ram:TaxTotalAmount currencyID="EUR">20.50</ram:TaxTotalAmount><ram:GrandTotalAmount>201.20</ram:GrandTotalAmount><ram:DuePayableAmount>201.20</ram:DuePayableAmount></ram:SpecifiedTradeSettlementHeaderMonetarySummation></ram:ApplicableHeaderTradeSettlement><ram:IncludedSupplyChainTradeLineItem><ram:AssociatedDocumentLineDocument><ram:LineID>1</ram:LineID></ram:AssociatedDocumentLineDocument><ram:SpecifiedTradeProduct><ram:Name>Kunstrasen grün 3m breit</ram:Name><ram:SellerAssignedID>KR3M</ram:SellerAssignedID></ram:SpecifiedTradeProduct><ram:SpecifiedLineTradeAgreement><ram:NetPriceProductTradePrice><ram:ChargeAmount>3.33</ram:ChargeAmount></ram:NetPriceProductTradePrice></ram:SpecifiedLineTradeAgreement><ram:SpecifiedLineTradeDelivery><ram:BilledQuantity unitCode="MTK">3</ram:BilledQuantity></ram:SpecifiedLineTradeDelivery><ram:SpecifiedLineTradeSettlement><ram:ApplicableTradeTax><ram:TypeCode>VAT</ram:TypeCode><ram:CategoryCode>S</ram:CategoryCode><ram:RateApplicablePercent>19</ram:RateApplicablePercent></ram:ApplicableTradeTax><ram:SpecifiedLineTradeSettlementMonetarySummation><ram:LineTotalAmount>10.00</ram:LineTotalAmount></ram:SpecifiedLineTradeSettlementMonetarySummation></ram:SpecifiedLineTradeSettlement></ram:IncludedSupplyChainTradeLineItem><ram:IncludedSupplyChainTradeLineItem><ram:AssociatedDocumentLineDocument><ram:LineID>2</ram:LineID></ram:AssociatedDocumentLineDocument><ram:SpecifiedTradeProduct><ram:Name>Schweinesteak</ram:Name><ram:SellerAssignedID>SFK5</ram:SellerAssignedID></ram:SpecifiedTradeProduct><ram:SpecifiedLineTradeAgreement><ram:NetPriceProductTradePrice><ram:ChargeAmount>5.50</ram:ChargeAmount></ram:NetPriceProductTradePrice></ram:SpecifiedLineTradeAgreement><ram:SpecifiedLineTradeDelivery><ram:BilledQuantity unitCode="KGM">1</ram:BilledQuantity></ram:SpecifiedLineTradeDelivery><ram:SpecifiedLineTradeSettlement><ram:ApplicableTradeTax><ram:TypeCode>VAT</ram:TypeCode><ram:CategoryCode>S</ram:CategoryCode><ram:RateApplicablePercent>7</ram:RateApplicablePercent></ram:ApplicableTradeTax><ram:SpecifiedLineTradeSettlementMonetarySummation><ram:LineTotalAmount>5.50</ram:LineTotalAmount></ram:SpecifiedLineTradeSettlementMonetarySummation></ram:SpecifiedLineTradeSettlement></ram:IncludedSupplyChainTradeLineItem><ram:IncludedSupplyChainTradeLineItem><ram:AssociatedDocumentLineDocument><ram:LineID>3</ram:LineID></ram:AssociatedDocumentLineDocument><ram:SpecifiedTradeProduct><ram:Name>Mineralwasser Medium
|
||||||
|
12 x 1,0l PET
|
||||||
|
</ram:Name><ram:SellerAssignedID>GTRWA5</ram:SellerAssignedID></ram:SpecifiedTradeProduct><ram:SpecifiedLineTradeAgreement><ram:NetPriceProductTradePrice><ram:ChargeAmount>5.49</ram:ChargeAmount></ram:NetPriceProductTradePrice></ram:SpecifiedLineTradeAgreement><ram:SpecifiedLineTradeDelivery><ram:BilledQuantity unitCode="H87">20</ram:BilledQuantity></ram:SpecifiedLineTradeDelivery><ram:SpecifiedLineTradeSettlement><ram:ApplicableTradeTax><ram:TypeCode>VAT</ram:TypeCode><ram:CategoryCode>S</ram:CategoryCode><ram:RateApplicablePercent>7</ram:RateApplicablePercent></ram:ApplicableTradeTax><ram:SpecifiedLineTradeSettlementMonetarySummation><ram:LineTotalAmount>109.80</ram:LineTotalAmount></ram:SpecifiedLineTradeSettlementMonetarySummation></ram:SpecifiedLineTradeSettlement></ram:IncludedSupplyChainTradeLineItem><ram:IncludedSupplyChainTradeLineItem><ram:AssociatedDocumentLineDocument><ram:LineID>4</ram:LineID></ram:AssociatedDocumentLineDocument><ram:SpecifiedTradeProduct><ram:Name>Pfand</ram:Name><ram:SellerAssignedID>PFA5</ram:SellerAssignedID></ram:SpecifiedTradeProduct><ram:SpecifiedLineTradeAgreement><ram:NetPriceProductTradePrice><ram:ChargeAmount>2.77</ram:ChargeAmount></ram:NetPriceProductTradePrice></ram:SpecifiedLineTradeAgreement><ram:SpecifiedLineTradeDelivery><ram:BilledQuantity unitCode="C62">20</ram:BilledQuantity></ram:SpecifiedLineTradeDelivery><ram:SpecifiedLineTradeSettlement><ram:ApplicableTradeTax><ram:TypeCode>VAT</ram:TypeCode><ram:CategoryCode>S</ram:CategoryCode><ram:RateApplicablePercent>19</ram:RateApplicablePercent></ram:ApplicableTradeTax><ram:SpecifiedLineTradeSettlementMonetarySummation><ram:LineTotalAmount>55.40</ram:LineTotalAmount></ram:SpecifiedLineTradeSettlementMonetarySummation></ram:SpecifiedLineTradeSettlement></ram:IncludedSupplyChainTradeLineItem></rsm:SupplyChainTradeTransaction></rsm:CrossIndustryInvoice>
|
161
test/output/circular/EN16931_1_Teilrechnung.ubl.xml-exported.xml
Normal file
161
test/output/circular/EN16931_1_Teilrechnung.ubl.xml-exported.xml
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
|
||||||
|
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
|
||||||
|
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
|
||||||
|
<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.0</cbc:CustomizationID>
|
||||||
|
<cbc:ID>471102</cbc:ID>
|
||||||
|
<cbc:IssueDate>2018-06-05</cbc:IssueDate>
|
||||||
|
<cbc:DueDate>2018-07-05</cbc:DueDate>
|
||||||
|
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
|
||||||
|
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
|
||||||
|
|
||||||
|
<cac:AccountingSupplierParty>
|
||||||
|
<cac:Party>
|
||||||
|
<cac:PartyName>
|
||||||
|
<cbc:Name>Lieferant GmbH</cbc:Name>
|
||||||
|
</cac:PartyName>
|
||||||
|
<cac:PostalAddress>
|
||||||
|
<cbc:StreetName>Lieferantenstraße 20</cbc:StreetName>
|
||||||
|
<cbc:BuildingNumber>0</cbc:BuildingNumber>
|
||||||
|
<cbc:CityName>München</cbc:CityName>
|
||||||
|
<cbc:PostalZone>80333</cbc:PostalZone>
|
||||||
|
<cac:Country>
|
||||||
|
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
||||||
|
</cac:Country>
|
||||||
|
</cac:PostalAddress>
|
||||||
|
|
||||||
|
<cac:PartyTaxScheme>
|
||||||
|
<cbc:CompanyID>201/113/40209</cbc:CompanyID>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>VAT</cbc:ID>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:PartyTaxScheme>
|
||||||
|
|
||||||
|
</cac:Party>
|
||||||
|
</cac:AccountingSupplierParty>
|
||||||
|
|
||||||
|
<cac:AccountingCustomerParty>
|
||||||
|
<cac:Party>
|
||||||
|
<cac:PartyName>
|
||||||
|
<cbc:Name>Kunden AG Mitte</cbc:Name>
|
||||||
|
</cac:PartyName>
|
||||||
|
<cac:PostalAddress>
|
||||||
|
<cbc:StreetName>Kundenstraße 15</cbc:StreetName>
|
||||||
|
<cbc:BuildingNumber>0</cbc:BuildingNumber>
|
||||||
|
<cbc:CityName>Frankfurt</cbc:CityName>
|
||||||
|
<cbc:PostalZone>69876</cbc:PostalZone>
|
||||||
|
<cac:Country>
|
||||||
|
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
||||||
|
</cac:Country>
|
||||||
|
</cac:PostalAddress>
|
||||||
|
|
||||||
|
</cac:Party>
|
||||||
|
</cac:AccountingCustomerParty>
|
||||||
|
|
||||||
|
<cac:PaymentTerms>
|
||||||
|
<cbc:Note>Due in 30 days</cbc:Note>
|
||||||
|
</cac:PaymentTerms>
|
||||||
|
|
||||||
|
<cac:TaxTotal>
|
||||||
|
<cbc:TaxAmount currencyID="EUR">0.00</cbc:TaxAmount>
|
||||||
|
</cac:TaxTotal>
|
||||||
|
|
||||||
|
<cac:LegalMonetaryTotal>
|
||||||
|
<cbc:LineExtensionAmount currencyID="EUR">0.00</cbc:LineExtensionAmount>
|
||||||
|
<cbc:TaxExclusiveAmount currencyID="EUR">0.00</cbc:TaxExclusiveAmount>
|
||||||
|
<cbc:TaxInclusiveAmount currencyID="EUR">0.00</cbc:TaxInclusiveAmount>
|
||||||
|
<cbc:PayableAmount currencyID="EUR">0.00</cbc:PayableAmount>
|
||||||
|
</cac:LegalMonetaryTotal>
|
||||||
|
|
||||||
|
|
||||||
|
<cac:InvoiceLine>
|
||||||
|
<cbc:ID>1</cbc:ID>
|
||||||
|
<cbc:InvoicedQuantity unitCode="MTK">3</cbc:InvoicedQuantity>
|
||||||
|
<cbc:LineExtensionAmount currencyID="EUR">9.9999</cbc:LineExtensionAmount>
|
||||||
|
<cac:Item>
|
||||||
|
<cbc:Name>Kunstrasen grün 3m breit</cbc:Name>
|
||||||
|
|
||||||
|
<cac:SellersItemIdentification>
|
||||||
|
<cbc:ID>KR3M</cbc:ID>
|
||||||
|
</cac:SellersItemIdentification>
|
||||||
|
<cac:ClassifiedTaxCategory>
|
||||||
|
<cbc:ID>S</cbc:ID>
|
||||||
|
<cbc:Percent>19</cbc:Percent>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>VAT</cbc:ID>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:ClassifiedTaxCategory>
|
||||||
|
</cac:Item>
|
||||||
|
<cac:Price>
|
||||||
|
<cbc:PriceAmount currencyID="EUR">3.3333</cbc:PriceAmount>
|
||||||
|
</cac:Price>
|
||||||
|
</cac:InvoiceLine>
|
||||||
|
<cac:InvoiceLine>
|
||||||
|
<cbc:ID>2</cbc:ID>
|
||||||
|
<cbc:InvoicedQuantity unitCode="KGM">1</cbc:InvoicedQuantity>
|
||||||
|
<cbc:LineExtensionAmount currencyID="EUR">5.5</cbc:LineExtensionAmount>
|
||||||
|
<cac:Item>
|
||||||
|
<cbc:Name>Schweinesteak</cbc:Name>
|
||||||
|
|
||||||
|
<cac:SellersItemIdentification>
|
||||||
|
<cbc:ID>SFK5</cbc:ID>
|
||||||
|
</cac:SellersItemIdentification>
|
||||||
|
<cac:ClassifiedTaxCategory>
|
||||||
|
<cbc:ID>S</cbc:ID>
|
||||||
|
<cbc:Percent>7</cbc:Percent>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>VAT</cbc:ID>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:ClassifiedTaxCategory>
|
||||||
|
</cac:Item>
|
||||||
|
<cac:Price>
|
||||||
|
<cbc:PriceAmount currencyID="EUR">5.5</cbc:PriceAmount>
|
||||||
|
</cac:Price>
|
||||||
|
</cac:InvoiceLine>
|
||||||
|
<cac:InvoiceLine>
|
||||||
|
<cbc:ID>3</cbc:ID>
|
||||||
|
<cbc:InvoicedQuantity unitCode="H87">20</cbc:InvoicedQuantity>
|
||||||
|
<cbc:LineExtensionAmount currencyID="EUR">109.80000000000001</cbc:LineExtensionAmount>
|
||||||
|
<cac:Item>
|
||||||
|
<cbc:Name>Mineralwasser Medium
|
||||||
|
12 x 1,0l PET
|
||||||
|
</cbc:Name>
|
||||||
|
|
||||||
|
<cac:SellersItemIdentification>
|
||||||
|
<cbc:ID>GTRWA5</cbc:ID>
|
||||||
|
</cac:SellersItemIdentification>
|
||||||
|
<cac:ClassifiedTaxCategory>
|
||||||
|
<cbc:ID>S</cbc:ID>
|
||||||
|
<cbc:Percent>7</cbc:Percent>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>VAT</cbc:ID>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:ClassifiedTaxCategory>
|
||||||
|
</cac:Item>
|
||||||
|
<cac:Price>
|
||||||
|
<cbc:PriceAmount currencyID="EUR">5.49</cbc:PriceAmount>
|
||||||
|
</cac:Price>
|
||||||
|
</cac:InvoiceLine>
|
||||||
|
<cac:InvoiceLine>
|
||||||
|
<cbc:ID>4</cbc:ID>
|
||||||
|
<cbc:InvoicedQuantity unitCode="C62">20</cbc:InvoicedQuantity>
|
||||||
|
<cbc:LineExtensionAmount currencyID="EUR">55.4</cbc:LineExtensionAmount>
|
||||||
|
<cac:Item>
|
||||||
|
<cbc:Name>Pfand</cbc:Name>
|
||||||
|
|
||||||
|
<cac:SellersItemIdentification>
|
||||||
|
<cbc:ID>PFA5</cbc:ID>
|
||||||
|
</cac:SellersItemIdentification>
|
||||||
|
<cac:ClassifiedTaxCategory>
|
||||||
|
<cbc:ID>S</cbc:ID>
|
||||||
|
<cbc:Percent>19</cbc:Percent>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>VAT</cbc:ID>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:ClassifiedTaxCategory>
|
||||||
|
</cac:Item>
|
||||||
|
<cac:Price>
|
||||||
|
<cbc:PriceAmount currencyID="EUR">2.77</cbc:PriceAmount>
|
||||||
|
</cac:Price>
|
||||||
|
</cac:InvoiceLine>
|
||||||
|
</Invoice>
|
@ -0,0 +1,3 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<rsm:CrossIndustryInvoice xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100" xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100" xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100">
|
||||||
|
<rsm:ExchangedDocumentContext><ram:GuidelineSpecifiedDocumentContextParameter><ram:ID>urn:cen.eu:en16931:2017</ram:ID></ram:GuidelineSpecifiedDocumentContextParameter></rsm:ExchangedDocumentContext><rsm:ExchangedDocument><ram:TypeCode>380</ram:TypeCode><ram:ID>471113</ram:ID><ram:IssueDateTime><udt:DateTimeString format="102">NaNNaNNaN</udt:DateTimeString></ram:IssueDateTime></rsm:ExchangedDocument><rsm:SupplyChainTradeTransaction><ram:ApplicableHeaderTradeAgreement><ram:SellerTradeParty><ram:Name>Lieferant GmbH</ram:Name><ram:PostalTradeAddress><ram:LineOne>Lieferantenstraße 20</ram:LineOne><ram:LineTwo>0</ram:LineTwo><ram:PostcodeCode>80333</ram:PostcodeCode><ram:CityName>München</ram:CityName><ram:CountryID>DE</ram:CountryID></ram:PostalTradeAddress><ram:SpecifiedTaxRegistration><ram:ID schemeID="VA">DE123456789</ram:ID></ram:SpecifiedTaxRegistration><ram:SpecifiedTaxRegistration><ram:ID schemeID="FC">201/113/40209</ram:ID></ram:SpecifiedTaxRegistration></ram:SellerTradeParty><ram:BuyerTradeParty><ram:Name>Kunden AG Mitte</ram:Name><ram:PostalTradeAddress><ram:LineOne>Kundenstraße 15</ram:LineOne><ram:LineTwo>0</ram:LineTwo><ram:PostcodeCode>69876</ram:PostcodeCode><ram:CityName>Frankfurt</ram:CityName><ram:CountryID>DE</ram:CountryID></ram:PostalTradeAddress></ram:BuyerTradeParty></ram:ApplicableHeaderTradeAgreement><ram:ApplicableHeaderTradeDelivery/><ram:ApplicableHeaderTradeSettlement><ram:InvoiceCurrencyCode>EUR</ram:InvoiceCurrencyCode><ram:SpecifiedTradePaymentTerms><ram:DueDateDateTime><udt:DateTimeString format="102">NaNNaNNaN</udt:DateTimeString></ram:DueDateDateTime></ram:SpecifiedTradePaymentTerms><ram:SpecifiedTradeSettlementHeaderMonetarySummation><ram:LineTotalAmount>22.00</ram:LineTotalAmount><ram:TaxTotalAmount currencyID="EUR">1.54</ram:TaxTotalAmount><ram:GrandTotalAmount>23.54</ram:GrandTotalAmount><ram:DuePayableAmount>23.54</ram:DuePayableAmount></ram:SpecifiedTradeSettlementHeaderMonetarySummation></ram:ApplicableHeaderTradeSettlement><ram:IncludedSupplyChainTradeLineItem><ram:AssociatedDocumentLineDocument><ram:LineID>1</ram:LineID></ram:AssociatedDocumentLineDocument><ram:SpecifiedTradeProduct><ram:Name>Schweinesteak</ram:Name><ram:SellerAssignedID>SFK5</ram:SellerAssignedID></ram:SpecifiedTradeProduct><ram:SpecifiedLineTradeAgreement><ram:NetPriceProductTradePrice><ram:ChargeAmount>5.50</ram:ChargeAmount></ram:NetPriceProductTradePrice></ram:SpecifiedLineTradeAgreement><ram:SpecifiedLineTradeDelivery><ram:BilledQuantity unitCode="KGM">4</ram:BilledQuantity></ram:SpecifiedLineTradeDelivery><ram:SpecifiedLineTradeSettlement><ram:ApplicableTradeTax><ram:TypeCode>VAT</ram:TypeCode><ram:CategoryCode>S</ram:CategoryCode><ram:RateApplicablePercent>7</ram:RateApplicablePercent></ram:ApplicableTradeTax><ram:SpecifiedLineTradeSettlementMonetarySummation><ram:LineTotalAmount>22.00</ram:LineTotalAmount></ram:SpecifiedLineTradeSettlementMonetarySummation></ram:SpecifiedLineTradeSettlement></ram:IncludedSupplyChainTradeLineItem></rsm:SupplyChainTradeTransaction></rsm:CrossIndustryInvoice>
|
@ -0,0 +1,93 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
|
||||||
|
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
|
||||||
|
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
|
||||||
|
<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.0</cbc:CustomizationID>
|
||||||
|
<cbc:ID>471113</cbc:ID>
|
||||||
|
<cbc:IssueDate>2018-06-13</cbc:IssueDate>
|
||||||
|
<cbc:DueDate>2018-07-13</cbc:DueDate>
|
||||||
|
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
|
||||||
|
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
|
||||||
|
|
||||||
|
<cac:AccountingSupplierParty>
|
||||||
|
<cac:Party>
|
||||||
|
<cac:PartyName>
|
||||||
|
<cbc:Name>Lieferant GmbH</cbc:Name>
|
||||||
|
</cac:PartyName>
|
||||||
|
<cac:PostalAddress>
|
||||||
|
<cbc:StreetName>Lieferantenstraße 20</cbc:StreetName>
|
||||||
|
<cbc:BuildingNumber>0</cbc:BuildingNumber>
|
||||||
|
<cbc:CityName>München</cbc:CityName>
|
||||||
|
<cbc:PostalZone>80333</cbc:PostalZone>
|
||||||
|
<cac:Country>
|
||||||
|
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
||||||
|
</cac:Country>
|
||||||
|
</cac:PostalAddress>
|
||||||
|
|
||||||
|
<cac:PartyTaxScheme>
|
||||||
|
<cbc:CompanyID>201/113/40209</cbc:CompanyID>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>VAT</cbc:ID>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:PartyTaxScheme>
|
||||||
|
|
||||||
|
</cac:Party>
|
||||||
|
</cac:AccountingSupplierParty>
|
||||||
|
|
||||||
|
<cac:AccountingCustomerParty>
|
||||||
|
<cac:Party>
|
||||||
|
<cac:PartyName>
|
||||||
|
<cbc:Name>Kunden AG Mitte</cbc:Name>
|
||||||
|
</cac:PartyName>
|
||||||
|
<cac:PostalAddress>
|
||||||
|
<cbc:StreetName>Kundenstraße 15</cbc:StreetName>
|
||||||
|
<cbc:BuildingNumber>0</cbc:BuildingNumber>
|
||||||
|
<cbc:CityName>Frankfurt</cbc:CityName>
|
||||||
|
<cbc:PostalZone>69876</cbc:PostalZone>
|
||||||
|
<cac:Country>
|
||||||
|
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
||||||
|
</cac:Country>
|
||||||
|
</cac:PostalAddress>
|
||||||
|
|
||||||
|
</cac:Party>
|
||||||
|
</cac:AccountingCustomerParty>
|
||||||
|
|
||||||
|
<cac:PaymentTerms>
|
||||||
|
<cbc:Note>Due in 30 days</cbc:Note>
|
||||||
|
</cac:PaymentTerms>
|
||||||
|
|
||||||
|
<cac:TaxTotal>
|
||||||
|
<cbc:TaxAmount currencyID="EUR">0.00</cbc:TaxAmount>
|
||||||
|
</cac:TaxTotal>
|
||||||
|
|
||||||
|
<cac:LegalMonetaryTotal>
|
||||||
|
<cbc:LineExtensionAmount currencyID="EUR">0.00</cbc:LineExtensionAmount>
|
||||||
|
<cbc:TaxExclusiveAmount currencyID="EUR">0.00</cbc:TaxExclusiveAmount>
|
||||||
|
<cbc:TaxInclusiveAmount currencyID="EUR">0.00</cbc:TaxInclusiveAmount>
|
||||||
|
<cbc:PayableAmount currencyID="EUR">0.00</cbc:PayableAmount>
|
||||||
|
</cac:LegalMonetaryTotal>
|
||||||
|
|
||||||
|
|
||||||
|
<cac:InvoiceLine>
|
||||||
|
<cbc:ID>1</cbc:ID>
|
||||||
|
<cbc:InvoicedQuantity unitCode="KGM">4</cbc:InvoicedQuantity>
|
||||||
|
<cbc:LineExtensionAmount currencyID="EUR">22</cbc:LineExtensionAmount>
|
||||||
|
<cac:Item>
|
||||||
|
<cbc:Name>Schweinesteak</cbc:Name>
|
||||||
|
|
||||||
|
<cac:SellersItemIdentification>
|
||||||
|
<cbc:ID>SFK5</cbc:ID>
|
||||||
|
</cac:SellersItemIdentification>
|
||||||
|
<cac:ClassifiedTaxCategory>
|
||||||
|
<cbc:ID>S</cbc:ID>
|
||||||
|
<cbc:Percent>7</cbc:Percent>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>VAT</cbc:ID>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:ClassifiedTaxCategory>
|
||||||
|
</cac:Item>
|
||||||
|
<cac:Price>
|
||||||
|
<cbc:PriceAmount currencyID="EUR">5.5</cbc:PriceAmount>
|
||||||
|
</cac:Price>
|
||||||
|
</cac:InvoiceLine>
|
||||||
|
</Invoice>
|
@ -0,0 +1,3 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<rsm:CrossIndustryInvoice xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100" xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100" xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100">
|
||||||
|
<rsm:ExchangedDocumentContext><ram:GuidelineSpecifiedDocumentContextParameter><ram:ID>urn:cen.eu:en16931:2017</ram:ID></ram:GuidelineSpecifiedDocumentContextParameter></rsm:ExchangedDocumentContext><rsm:ExchangedDocument><ram:TypeCode>380</ram:TypeCode><ram:ID>471102</ram:ID><ram:IssueDateTime><udt:DateTimeString format="102">NaNNaNNaN</udt:DateTimeString></ram:IssueDateTime></rsm:ExchangedDocument><rsm:SupplyChainTradeTransaction><ram:ApplicableHeaderTradeAgreement><ram:SellerTradeParty><ram:Name>Lieferant GmbH</ram:Name><ram:PostalTradeAddress><ram:LineOne>Lieferantenstraße 20</ram:LineOne><ram:LineTwo>0</ram:LineTwo><ram:PostcodeCode>80333</ram:PostcodeCode><ram:CityName>München</ram:CityName><ram:CountryID>DE</ram:CountryID></ram:PostalTradeAddress><ram:SpecifiedTaxRegistration><ram:ID schemeID="VA">DE123456789</ram:ID></ram:SpecifiedTaxRegistration><ram:SpecifiedTaxRegistration><ram:ID schemeID="FC">201/113/40209</ram:ID></ram:SpecifiedTaxRegistration></ram:SellerTradeParty><ram:BuyerTradeParty><ram:Name>Kunden AG Mitte</ram:Name><ram:PostalTradeAddress><ram:LineOne>Kundenstraße 15</ram:LineOne><ram:LineTwo>0</ram:LineTwo><ram:PostcodeCode>69876</ram:PostcodeCode><ram:CityName>Frankfurt</ram:CityName><ram:CountryID>DE</ram:CountryID></ram:PostalTradeAddress></ram:BuyerTradeParty></ram:ApplicableHeaderTradeAgreement><ram:ApplicableHeaderTradeDelivery/><ram:ApplicableHeaderTradeSettlement><ram:InvoiceCurrencyCode>EUR</ram:InvoiceCurrencyCode><ram:SpecifiedTradePaymentTerms><ram:DueDateDateTime><udt:DateTimeString format="102">NaNNaNNaN</udt:DateTimeString></ram:DueDateDateTime></ram:SpecifiedTradePaymentTerms><ram:SpecifiedTradeSettlementHeaderMonetarySummation><ram:LineTotalAmount>473.00</ram:LineTotalAmount><ram:TaxTotalAmount currencyID="EUR">56.87</ram:TaxTotalAmount><ram:GrandTotalAmount>529.87</ram:GrandTotalAmount><ram:DuePayableAmount>529.87</ram:DuePayableAmount></ram:SpecifiedTradeSettlementHeaderMonetarySummation></ram:ApplicableHeaderTradeSettlement><ram:IncludedSupplyChainTradeLineItem><ram:AssociatedDocumentLineDocument><ram:LineID>1</ram:LineID></ram:AssociatedDocumentLineDocument><ram:SpecifiedTradeProduct><ram:Name>Trennblätter A4</ram:Name><ram:SellerAssignedID>TB100A4</ram:SellerAssignedID></ram:SpecifiedTradeProduct><ram:SpecifiedLineTradeAgreement><ram:NetPriceProductTradePrice><ram:ChargeAmount>9.90</ram:ChargeAmount></ram:NetPriceProductTradePrice></ram:SpecifiedLineTradeAgreement><ram:SpecifiedLineTradeDelivery><ram:BilledQuantity unitCode="H87">20</ram:BilledQuantity></ram:SpecifiedLineTradeDelivery><ram:SpecifiedLineTradeSettlement><ram:ApplicableTradeTax><ram:TypeCode>VAT</ram:TypeCode><ram:CategoryCode>S</ram:CategoryCode><ram:RateApplicablePercent>19</ram:RateApplicablePercent></ram:ApplicableTradeTax><ram:SpecifiedLineTradeSettlementMonetarySummation><ram:LineTotalAmount>198.00</ram:LineTotalAmount></ram:SpecifiedLineTradeSettlementMonetarySummation></ram:SpecifiedLineTradeSettlement></ram:IncludedSupplyChainTradeLineItem><ram:IncludedSupplyChainTradeLineItem><ram:AssociatedDocumentLineDocument><ram:LineID>2</ram:LineID></ram:AssociatedDocumentLineDocument><ram:SpecifiedTradeProduct><ram:Name>Joghurt Banane</ram:Name><ram:SellerAssignedID>ARNR2</ram:SellerAssignedID></ram:SpecifiedTradeProduct><ram:SpecifiedLineTradeAgreement><ram:NetPriceProductTradePrice><ram:ChargeAmount>5.50</ram:ChargeAmount></ram:NetPriceProductTradePrice></ram:SpecifiedLineTradeAgreement><ram:SpecifiedLineTradeDelivery><ram:BilledQuantity unitCode="H87">50</ram:BilledQuantity></ram:SpecifiedLineTradeDelivery><ram:SpecifiedLineTradeSettlement><ram:ApplicableTradeTax><ram:TypeCode>VAT</ram:TypeCode><ram:CategoryCode>S</ram:CategoryCode><ram:RateApplicablePercent>7</ram:RateApplicablePercent></ram:ApplicableTradeTax><ram:SpecifiedLineTradeSettlementMonetarySummation><ram:LineTotalAmount>275.00</ram:LineTotalAmount></ram:SpecifiedLineTradeSettlementMonetarySummation></ram:SpecifiedLineTradeSettlement></ram:IncludedSupplyChainTradeLineItem></rsm:SupplyChainTradeTransaction></rsm:CrossIndustryInvoice>
|
@ -0,0 +1,115 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
|
||||||
|
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
|
||||||
|
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
|
||||||
|
<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.0</cbc:CustomizationID>
|
||||||
|
<cbc:ID>471102</cbc:ID>
|
||||||
|
<cbc:IssueDate>2018-03-05</cbc:IssueDate>
|
||||||
|
<cbc:DueDate>2018-04-04</cbc:DueDate>
|
||||||
|
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
|
||||||
|
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
|
||||||
|
|
||||||
|
<cac:AccountingSupplierParty>
|
||||||
|
<cac:Party>
|
||||||
|
<cac:PartyName>
|
||||||
|
<cbc:Name>Lieferant GmbH</cbc:Name>
|
||||||
|
</cac:PartyName>
|
||||||
|
<cac:PostalAddress>
|
||||||
|
<cbc:StreetName>Lieferantenstraße 20</cbc:StreetName>
|
||||||
|
<cbc:BuildingNumber>0</cbc:BuildingNumber>
|
||||||
|
<cbc:CityName>München</cbc:CityName>
|
||||||
|
<cbc:PostalZone>80333</cbc:PostalZone>
|
||||||
|
<cac:Country>
|
||||||
|
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
||||||
|
</cac:Country>
|
||||||
|
</cac:PostalAddress>
|
||||||
|
|
||||||
|
<cac:PartyTaxScheme>
|
||||||
|
<cbc:CompanyID>201/113/40209</cbc:CompanyID>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>VAT</cbc:ID>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:PartyTaxScheme>
|
||||||
|
|
||||||
|
</cac:Party>
|
||||||
|
</cac:AccountingSupplierParty>
|
||||||
|
|
||||||
|
<cac:AccountingCustomerParty>
|
||||||
|
<cac:Party>
|
||||||
|
<cac:PartyName>
|
||||||
|
<cbc:Name>Kunden AG Mitte</cbc:Name>
|
||||||
|
</cac:PartyName>
|
||||||
|
<cac:PostalAddress>
|
||||||
|
<cbc:StreetName>Kundenstraße 15</cbc:StreetName>
|
||||||
|
<cbc:BuildingNumber>0</cbc:BuildingNumber>
|
||||||
|
<cbc:CityName>Frankfurt</cbc:CityName>
|
||||||
|
<cbc:PostalZone>69876</cbc:PostalZone>
|
||||||
|
<cac:Country>
|
||||||
|
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
||||||
|
</cac:Country>
|
||||||
|
</cac:PostalAddress>
|
||||||
|
|
||||||
|
</cac:Party>
|
||||||
|
</cac:AccountingCustomerParty>
|
||||||
|
|
||||||
|
<cac:PaymentTerms>
|
||||||
|
<cbc:Note>Due in 30 days</cbc:Note>
|
||||||
|
</cac:PaymentTerms>
|
||||||
|
|
||||||
|
<cac:TaxTotal>
|
||||||
|
<cbc:TaxAmount currencyID="EUR">0.00</cbc:TaxAmount>
|
||||||
|
</cac:TaxTotal>
|
||||||
|
|
||||||
|
<cac:LegalMonetaryTotal>
|
||||||
|
<cbc:LineExtensionAmount currencyID="EUR">0.00</cbc:LineExtensionAmount>
|
||||||
|
<cbc:TaxExclusiveAmount currencyID="EUR">0.00</cbc:TaxExclusiveAmount>
|
||||||
|
<cbc:TaxInclusiveAmount currencyID="EUR">0.00</cbc:TaxInclusiveAmount>
|
||||||
|
<cbc:PayableAmount currencyID="EUR">0.00</cbc:PayableAmount>
|
||||||
|
</cac:LegalMonetaryTotal>
|
||||||
|
|
||||||
|
|
||||||
|
<cac:InvoiceLine>
|
||||||
|
<cbc:ID>1</cbc:ID>
|
||||||
|
<cbc:InvoicedQuantity unitCode="H87">20</cbc:InvoicedQuantity>
|
||||||
|
<cbc:LineExtensionAmount currencyID="EUR">198</cbc:LineExtensionAmount>
|
||||||
|
<cac:Item>
|
||||||
|
<cbc:Name>Trennblätter A4</cbc:Name>
|
||||||
|
|
||||||
|
<cac:SellersItemIdentification>
|
||||||
|
<cbc:ID>TB100A4</cbc:ID>
|
||||||
|
</cac:SellersItemIdentification>
|
||||||
|
<cac:ClassifiedTaxCategory>
|
||||||
|
<cbc:ID>S</cbc:ID>
|
||||||
|
<cbc:Percent>19</cbc:Percent>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>VAT</cbc:ID>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:ClassifiedTaxCategory>
|
||||||
|
</cac:Item>
|
||||||
|
<cac:Price>
|
||||||
|
<cbc:PriceAmount currencyID="EUR">9.9</cbc:PriceAmount>
|
||||||
|
</cac:Price>
|
||||||
|
</cac:InvoiceLine>
|
||||||
|
<cac:InvoiceLine>
|
||||||
|
<cbc:ID>2</cbc:ID>
|
||||||
|
<cbc:InvoicedQuantity unitCode="H87">50</cbc:InvoicedQuantity>
|
||||||
|
<cbc:LineExtensionAmount currencyID="EUR">275</cbc:LineExtensionAmount>
|
||||||
|
<cac:Item>
|
||||||
|
<cbc:Name>Joghurt Banane</cbc:Name>
|
||||||
|
|
||||||
|
<cac:SellersItemIdentification>
|
||||||
|
<cbc:ID>ARNR2</cbc:ID>
|
||||||
|
</cac:SellersItemIdentification>
|
||||||
|
<cac:ClassifiedTaxCategory>
|
||||||
|
<cbc:ID>S</cbc:ID>
|
||||||
|
<cbc:Percent>7</cbc:Percent>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>VAT</cbc:ID>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:ClassifiedTaxCategory>
|
||||||
|
</cac:Item>
|
||||||
|
<cac:Price>
|
||||||
|
<cbc:PriceAmount currencyID="EUR">5.5</cbc:PriceAmount>
|
||||||
|
</cac:Price>
|
||||||
|
</cac:InvoiceLine>
|
||||||
|
</Invoice>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<rsm:CrossIndustryInvoice xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100" xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100" xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100">
|
||||||
|
<rsm:ExchangedDocumentContext><ram:GuidelineSpecifiedDocumentContextParameter><ram:ID>urn:cen.eu:en16931:2017</ram:ID></ram:GuidelineSpecifiedDocumentContextParameter></rsm:ExchangedDocumentContext><rsm:ExchangedDocument><ram:TypeCode>380</ram:TypeCode><ram:ID>471102</ram:ID><ram:IssueDateTime><udt:DateTimeString format="102">NaNNaNNaN</udt:DateTimeString></ram:IssueDateTime></rsm:ExchangedDocument><rsm:SupplyChainTradeTransaction><ram:ApplicableHeaderTradeAgreement><ram:SellerTradeParty><ram:Name>Lieferant GmbH</ram:Name><ram:PostalTradeAddress><ram:LineOne>Lieferantenstraße 20</ram:LineOne><ram:LineTwo>0</ram:LineTwo><ram:PostcodeCode>80333</ram:PostcodeCode><ram:CityName>München</ram:CityName><ram:CountryID>DE</ram:CountryID></ram:PostalTradeAddress><ram:SpecifiedTaxRegistration><ram:ID schemeID="VA">DE123456789</ram:ID></ram:SpecifiedTaxRegistration><ram:SpecifiedTaxRegistration><ram:ID schemeID="FC">201/113/40209</ram:ID></ram:SpecifiedTaxRegistration></ram:SellerTradeParty><ram:BuyerTradeParty><ram:Name>Kunden AG Mitte</ram:Name><ram:PostalTradeAddress><ram:LineOne>Kundenstraße 15</ram:LineOne><ram:LineTwo>0</ram:LineTwo><ram:PostcodeCode>69876</ram:PostcodeCode><ram:CityName>Frankfurt</ram:CityName><ram:CountryID>DE</ram:CountryID></ram:PostalTradeAddress></ram:BuyerTradeParty></ram:ApplicableHeaderTradeAgreement><ram:ApplicableHeaderTradeDelivery/><ram:ApplicableHeaderTradeSettlement><ram:InvoiceCurrencyCode>EUR</ram:InvoiceCurrencyCode><ram:SpecifiedTradePaymentTerms><ram:DueDateDateTime><udt:DateTimeString format="102">NaNNaNNaN</udt:DateTimeString></ram:DueDateDateTime></ram:SpecifiedTradePaymentTerms><ram:SpecifiedTradeSettlementHeaderMonetarySummation><ram:LineTotalAmount>180.70</ram:LineTotalAmount><ram:TaxTotalAmount currencyID="EUR">20.50</ram:TaxTotalAmount><ram:GrandTotalAmount>201.20</ram:GrandTotalAmount><ram:DuePayableAmount>201.20</ram:DuePayableAmount></ram:SpecifiedTradeSettlementHeaderMonetarySummation></ram:ApplicableHeaderTradeSettlement><ram:IncludedSupplyChainTradeLineItem><ram:AssociatedDocumentLineDocument><ram:LineID>1</ram:LineID></ram:AssociatedDocumentLineDocument><ram:SpecifiedTradeProduct><ram:Name>Kunstrasen grün 3m breit</ram:Name><ram:SellerAssignedID>KR3M</ram:SellerAssignedID></ram:SpecifiedTradeProduct><ram:SpecifiedLineTradeAgreement><ram:NetPriceProductTradePrice><ram:ChargeAmount>3.33</ram:ChargeAmount></ram:NetPriceProductTradePrice></ram:SpecifiedLineTradeAgreement><ram:SpecifiedLineTradeDelivery><ram:BilledQuantity unitCode="MTK">3</ram:BilledQuantity></ram:SpecifiedLineTradeDelivery><ram:SpecifiedLineTradeSettlement><ram:ApplicableTradeTax><ram:TypeCode>VAT</ram:TypeCode><ram:CategoryCode>S</ram:CategoryCode><ram:RateApplicablePercent>19</ram:RateApplicablePercent></ram:ApplicableTradeTax><ram:SpecifiedLineTradeSettlementMonetarySummation><ram:LineTotalAmount>10.00</ram:LineTotalAmount></ram:SpecifiedLineTradeSettlementMonetarySummation></ram:SpecifiedLineTradeSettlement></ram:IncludedSupplyChainTradeLineItem><ram:IncludedSupplyChainTradeLineItem><ram:AssociatedDocumentLineDocument><ram:LineID>2</ram:LineID></ram:AssociatedDocumentLineDocument><ram:SpecifiedTradeProduct><ram:Name>Schweinesteak</ram:Name><ram:SellerAssignedID>SFK5</ram:SellerAssignedID></ram:SpecifiedTradeProduct><ram:SpecifiedLineTradeAgreement><ram:NetPriceProductTradePrice><ram:ChargeAmount>5.50</ram:ChargeAmount></ram:NetPriceProductTradePrice></ram:SpecifiedLineTradeAgreement><ram:SpecifiedLineTradeDelivery><ram:BilledQuantity unitCode="KGM">1</ram:BilledQuantity></ram:SpecifiedLineTradeDelivery><ram:SpecifiedLineTradeSettlement><ram:ApplicableTradeTax><ram:TypeCode>VAT</ram:TypeCode><ram:CategoryCode>S</ram:CategoryCode><ram:RateApplicablePercent>7</ram:RateApplicablePercent></ram:ApplicableTradeTax><ram:SpecifiedLineTradeSettlementMonetarySummation><ram:LineTotalAmount>5.50</ram:LineTotalAmount></ram:SpecifiedLineTradeSettlementMonetarySummation></ram:SpecifiedLineTradeSettlement></ram:IncludedSupplyChainTradeLineItem><ram:IncludedSupplyChainTradeLineItem><ram:AssociatedDocumentLineDocument><ram:LineID>3</ram:LineID></ram:AssociatedDocumentLineDocument><ram:SpecifiedTradeProduct><ram:Name>Mineralwasser Medium
|
||||||
|
12 x 1,0l PET
|
||||||
|
</ram:Name><ram:SellerAssignedID>GTRWA5</ram:SellerAssignedID></ram:SpecifiedTradeProduct><ram:SpecifiedLineTradeAgreement><ram:NetPriceProductTradePrice><ram:ChargeAmount>5.49</ram:ChargeAmount></ram:NetPriceProductTradePrice></ram:SpecifiedLineTradeAgreement><ram:SpecifiedLineTradeDelivery><ram:BilledQuantity unitCode="H87">20</ram:BilledQuantity></ram:SpecifiedLineTradeDelivery><ram:SpecifiedLineTradeSettlement><ram:ApplicableTradeTax><ram:TypeCode>VAT</ram:TypeCode><ram:CategoryCode>S</ram:CategoryCode><ram:RateApplicablePercent>7</ram:RateApplicablePercent></ram:ApplicableTradeTax><ram:SpecifiedLineTradeSettlementMonetarySummation><ram:LineTotalAmount>109.80</ram:LineTotalAmount></ram:SpecifiedLineTradeSettlementMonetarySummation></ram:SpecifiedLineTradeSettlement></ram:IncludedSupplyChainTradeLineItem><ram:IncludedSupplyChainTradeLineItem><ram:AssociatedDocumentLineDocument><ram:LineID>4</ram:LineID></ram:AssociatedDocumentLineDocument><ram:SpecifiedTradeProduct><ram:Name>Pfand</ram:Name><ram:SellerAssignedID>PFA5</ram:SellerAssignedID></ram:SpecifiedTradeProduct><ram:SpecifiedLineTradeAgreement><ram:NetPriceProductTradePrice><ram:ChargeAmount>2.77</ram:ChargeAmount></ram:NetPriceProductTradePrice></ram:SpecifiedLineTradeAgreement><ram:SpecifiedLineTradeDelivery><ram:BilledQuantity unitCode="C62">20</ram:BilledQuantity></ram:SpecifiedLineTradeDelivery><ram:SpecifiedLineTradeSettlement><ram:ApplicableTradeTax><ram:TypeCode>VAT</ram:TypeCode><ram:CategoryCode>S</ram:CategoryCode><ram:RateApplicablePercent>19</ram:RateApplicablePercent></ram:ApplicableTradeTax><ram:SpecifiedLineTradeSettlementMonetarySummation><ram:LineTotalAmount>55.40</ram:LineTotalAmount></ram:SpecifiedLineTradeSettlementMonetarySummation></ram:SpecifiedLineTradeSettlement></ram:IncludedSupplyChainTradeLineItem></rsm:SupplyChainTradeTransaction></rsm:CrossIndustryInvoice>
|
161
test/output/focused/EN16931_1_Teilrechnung.ubl.xml-exported.xml
Normal file
161
test/output/focused/EN16931_1_Teilrechnung.ubl.xml-exported.xml
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
|
||||||
|
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
|
||||||
|
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
|
||||||
|
<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.0</cbc:CustomizationID>
|
||||||
|
<cbc:ID>471102</cbc:ID>
|
||||||
|
<cbc:IssueDate>2018-06-05</cbc:IssueDate>
|
||||||
|
<cbc:DueDate>2018-07-05</cbc:DueDate>
|
||||||
|
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
|
||||||
|
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
|
||||||
|
|
||||||
|
<cac:AccountingSupplierParty>
|
||||||
|
<cac:Party>
|
||||||
|
<cac:PartyName>
|
||||||
|
<cbc:Name>Lieferant GmbH</cbc:Name>
|
||||||
|
</cac:PartyName>
|
||||||
|
<cac:PostalAddress>
|
||||||
|
<cbc:StreetName>Lieferantenstraße 20</cbc:StreetName>
|
||||||
|
<cbc:BuildingNumber>0</cbc:BuildingNumber>
|
||||||
|
<cbc:CityName>München</cbc:CityName>
|
||||||
|
<cbc:PostalZone>80333</cbc:PostalZone>
|
||||||
|
<cac:Country>
|
||||||
|
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
||||||
|
</cac:Country>
|
||||||
|
</cac:PostalAddress>
|
||||||
|
|
||||||
|
<cac:PartyTaxScheme>
|
||||||
|
<cbc:CompanyID>201/113/40209</cbc:CompanyID>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>VAT</cbc:ID>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:PartyTaxScheme>
|
||||||
|
|
||||||
|
</cac:Party>
|
||||||
|
</cac:AccountingSupplierParty>
|
||||||
|
|
||||||
|
<cac:AccountingCustomerParty>
|
||||||
|
<cac:Party>
|
||||||
|
<cac:PartyName>
|
||||||
|
<cbc:Name>Kunden AG Mitte</cbc:Name>
|
||||||
|
</cac:PartyName>
|
||||||
|
<cac:PostalAddress>
|
||||||
|
<cbc:StreetName>Kundenstraße 15</cbc:StreetName>
|
||||||
|
<cbc:BuildingNumber>0</cbc:BuildingNumber>
|
||||||
|
<cbc:CityName>Frankfurt</cbc:CityName>
|
||||||
|
<cbc:PostalZone>69876</cbc:PostalZone>
|
||||||
|
<cac:Country>
|
||||||
|
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
||||||
|
</cac:Country>
|
||||||
|
</cac:PostalAddress>
|
||||||
|
|
||||||
|
</cac:Party>
|
||||||
|
</cac:AccountingCustomerParty>
|
||||||
|
|
||||||
|
<cac:PaymentTerms>
|
||||||
|
<cbc:Note>Due in 30 days</cbc:Note>
|
||||||
|
</cac:PaymentTerms>
|
||||||
|
|
||||||
|
<cac:TaxTotal>
|
||||||
|
<cbc:TaxAmount currencyID="EUR">0.00</cbc:TaxAmount>
|
||||||
|
</cac:TaxTotal>
|
||||||
|
|
||||||
|
<cac:LegalMonetaryTotal>
|
||||||
|
<cbc:LineExtensionAmount currencyID="EUR">0.00</cbc:LineExtensionAmount>
|
||||||
|
<cbc:TaxExclusiveAmount currencyID="EUR">0.00</cbc:TaxExclusiveAmount>
|
||||||
|
<cbc:TaxInclusiveAmount currencyID="EUR">0.00</cbc:TaxInclusiveAmount>
|
||||||
|
<cbc:PayableAmount currencyID="EUR">0.00</cbc:PayableAmount>
|
||||||
|
</cac:LegalMonetaryTotal>
|
||||||
|
|
||||||
|
|
||||||
|
<cac:InvoiceLine>
|
||||||
|
<cbc:ID>1</cbc:ID>
|
||||||
|
<cbc:InvoicedQuantity unitCode="MTK">3</cbc:InvoicedQuantity>
|
||||||
|
<cbc:LineExtensionAmount currencyID="EUR">9.9999</cbc:LineExtensionAmount>
|
||||||
|
<cac:Item>
|
||||||
|
<cbc:Name>Kunstrasen grün 3m breit</cbc:Name>
|
||||||
|
|
||||||
|
<cac:SellersItemIdentification>
|
||||||
|
<cbc:ID>KR3M</cbc:ID>
|
||||||
|
</cac:SellersItemIdentification>
|
||||||
|
<cac:ClassifiedTaxCategory>
|
||||||
|
<cbc:ID>S</cbc:ID>
|
||||||
|
<cbc:Percent>19</cbc:Percent>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>VAT</cbc:ID>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:ClassifiedTaxCategory>
|
||||||
|
</cac:Item>
|
||||||
|
<cac:Price>
|
||||||
|
<cbc:PriceAmount currencyID="EUR">3.3333</cbc:PriceAmount>
|
||||||
|
</cac:Price>
|
||||||
|
</cac:InvoiceLine>
|
||||||
|
<cac:InvoiceLine>
|
||||||
|
<cbc:ID>2</cbc:ID>
|
||||||
|
<cbc:InvoicedQuantity unitCode="KGM">1</cbc:InvoicedQuantity>
|
||||||
|
<cbc:LineExtensionAmount currencyID="EUR">5.5</cbc:LineExtensionAmount>
|
||||||
|
<cac:Item>
|
||||||
|
<cbc:Name>Schweinesteak</cbc:Name>
|
||||||
|
|
||||||
|
<cac:SellersItemIdentification>
|
||||||
|
<cbc:ID>SFK5</cbc:ID>
|
||||||
|
</cac:SellersItemIdentification>
|
||||||
|
<cac:ClassifiedTaxCategory>
|
||||||
|
<cbc:ID>S</cbc:ID>
|
||||||
|
<cbc:Percent>7</cbc:Percent>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>VAT</cbc:ID>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:ClassifiedTaxCategory>
|
||||||
|
</cac:Item>
|
||||||
|
<cac:Price>
|
||||||
|
<cbc:PriceAmount currencyID="EUR">5.5</cbc:PriceAmount>
|
||||||
|
</cac:Price>
|
||||||
|
</cac:InvoiceLine>
|
||||||
|
<cac:InvoiceLine>
|
||||||
|
<cbc:ID>3</cbc:ID>
|
||||||
|
<cbc:InvoicedQuantity unitCode="H87">20</cbc:InvoicedQuantity>
|
||||||
|
<cbc:LineExtensionAmount currencyID="EUR">109.80000000000001</cbc:LineExtensionAmount>
|
||||||
|
<cac:Item>
|
||||||
|
<cbc:Name>Mineralwasser Medium
|
||||||
|
12 x 1,0l PET
|
||||||
|
</cbc:Name>
|
||||||
|
|
||||||
|
<cac:SellersItemIdentification>
|
||||||
|
<cbc:ID>GTRWA5</cbc:ID>
|
||||||
|
</cac:SellersItemIdentification>
|
||||||
|
<cac:ClassifiedTaxCategory>
|
||||||
|
<cbc:ID>S</cbc:ID>
|
||||||
|
<cbc:Percent>7</cbc:Percent>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>VAT</cbc:ID>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:ClassifiedTaxCategory>
|
||||||
|
</cac:Item>
|
||||||
|
<cac:Price>
|
||||||
|
<cbc:PriceAmount currencyID="EUR">5.49</cbc:PriceAmount>
|
||||||
|
</cac:Price>
|
||||||
|
</cac:InvoiceLine>
|
||||||
|
<cac:InvoiceLine>
|
||||||
|
<cbc:ID>4</cbc:ID>
|
||||||
|
<cbc:InvoicedQuantity unitCode="C62">20</cbc:InvoicedQuantity>
|
||||||
|
<cbc:LineExtensionAmount currencyID="EUR">55.4</cbc:LineExtensionAmount>
|
||||||
|
<cac:Item>
|
||||||
|
<cbc:Name>Pfand</cbc:Name>
|
||||||
|
|
||||||
|
<cac:SellersItemIdentification>
|
||||||
|
<cbc:ID>PFA5</cbc:ID>
|
||||||
|
</cac:SellersItemIdentification>
|
||||||
|
<cac:ClassifiedTaxCategory>
|
||||||
|
<cbc:ID>S</cbc:ID>
|
||||||
|
<cbc:Percent>19</cbc:Percent>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>VAT</cbc:ID>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:ClassifiedTaxCategory>
|
||||||
|
</cac:Item>
|
||||||
|
<cac:Price>
|
||||||
|
<cbc:PriceAmount currencyID="EUR">2.77</cbc:PriceAmount>
|
||||||
|
</cac:Price>
|
||||||
|
</cac:InvoiceLine>
|
||||||
|
</Invoice>
|
@ -0,0 +1,3 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<rsm:CrossIndustryInvoice xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100" xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100" xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100">
|
||||||
|
<rsm:ExchangedDocumentContext><ram:GuidelineSpecifiedDocumentContextParameter><ram:ID>urn:cen.eu:en16931:2017</ram:ID></ram:GuidelineSpecifiedDocumentContextParameter></rsm:ExchangedDocumentContext><rsm:ExchangedDocument><ram:TypeCode>380</ram:TypeCode><ram:ID>471113</ram:ID><ram:IssueDateTime><udt:DateTimeString format="102">NaNNaNNaN</udt:DateTimeString></ram:IssueDateTime></rsm:ExchangedDocument><rsm:SupplyChainTradeTransaction><ram:ApplicableHeaderTradeAgreement><ram:SellerTradeParty><ram:Name>Lieferant GmbH</ram:Name><ram:PostalTradeAddress><ram:LineOne>Lieferantenstraße 20</ram:LineOne><ram:LineTwo>0</ram:LineTwo><ram:PostcodeCode>80333</ram:PostcodeCode><ram:CityName>München</ram:CityName><ram:CountryID>DE</ram:CountryID></ram:PostalTradeAddress><ram:SpecifiedTaxRegistration><ram:ID schemeID="VA">DE123456789</ram:ID></ram:SpecifiedTaxRegistration><ram:SpecifiedTaxRegistration><ram:ID schemeID="FC">201/113/40209</ram:ID></ram:SpecifiedTaxRegistration></ram:SellerTradeParty><ram:BuyerTradeParty><ram:Name>Kunden AG Mitte</ram:Name><ram:PostalTradeAddress><ram:LineOne>Kundenstraße 15</ram:LineOne><ram:LineTwo>0</ram:LineTwo><ram:PostcodeCode>69876</ram:PostcodeCode><ram:CityName>Frankfurt</ram:CityName><ram:CountryID>DE</ram:CountryID></ram:PostalTradeAddress></ram:BuyerTradeParty></ram:ApplicableHeaderTradeAgreement><ram:ApplicableHeaderTradeDelivery/><ram:ApplicableHeaderTradeSettlement><ram:InvoiceCurrencyCode>EUR</ram:InvoiceCurrencyCode><ram:SpecifiedTradePaymentTerms><ram:DueDateDateTime><udt:DateTimeString format="102">NaNNaNNaN</udt:DateTimeString></ram:DueDateDateTime></ram:SpecifiedTradePaymentTerms><ram:SpecifiedTradeSettlementHeaderMonetarySummation><ram:LineTotalAmount>22.00</ram:LineTotalAmount><ram:TaxTotalAmount currencyID="EUR">1.54</ram:TaxTotalAmount><ram:GrandTotalAmount>23.54</ram:GrandTotalAmount><ram:DuePayableAmount>23.54</ram:DuePayableAmount></ram:SpecifiedTradeSettlementHeaderMonetarySummation></ram:ApplicableHeaderTradeSettlement><ram:IncludedSupplyChainTradeLineItem><ram:AssociatedDocumentLineDocument><ram:LineID>1</ram:LineID></ram:AssociatedDocumentLineDocument><ram:SpecifiedTradeProduct><ram:Name>Schweinesteak</ram:Name><ram:SellerAssignedID>SFK5</ram:SellerAssignedID></ram:SpecifiedTradeProduct><ram:SpecifiedLineTradeAgreement><ram:NetPriceProductTradePrice><ram:ChargeAmount>5.50</ram:ChargeAmount></ram:NetPriceProductTradePrice></ram:SpecifiedLineTradeAgreement><ram:SpecifiedLineTradeDelivery><ram:BilledQuantity unitCode="KGM">4</ram:BilledQuantity></ram:SpecifiedLineTradeDelivery><ram:SpecifiedLineTradeSettlement><ram:ApplicableTradeTax><ram:TypeCode>VAT</ram:TypeCode><ram:CategoryCode>S</ram:CategoryCode><ram:RateApplicablePercent>7</ram:RateApplicablePercent></ram:ApplicableTradeTax><ram:SpecifiedLineTradeSettlementMonetarySummation><ram:LineTotalAmount>22.00</ram:LineTotalAmount></ram:SpecifiedLineTradeSettlementMonetarySummation></ram:SpecifiedLineTradeSettlement></ram:IncludedSupplyChainTradeLineItem></rsm:SupplyChainTradeTransaction></rsm:CrossIndustryInvoice>
|
@ -0,0 +1,93 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
|
||||||
|
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
|
||||||
|
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
|
||||||
|
<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.0</cbc:CustomizationID>
|
||||||
|
<cbc:ID>471113</cbc:ID>
|
||||||
|
<cbc:IssueDate>2018-06-13</cbc:IssueDate>
|
||||||
|
<cbc:DueDate>2018-07-13</cbc:DueDate>
|
||||||
|
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
|
||||||
|
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
|
||||||
|
|
||||||
|
<cac:AccountingSupplierParty>
|
||||||
|
<cac:Party>
|
||||||
|
<cac:PartyName>
|
||||||
|
<cbc:Name>Lieferant GmbH</cbc:Name>
|
||||||
|
</cac:PartyName>
|
||||||
|
<cac:PostalAddress>
|
||||||
|
<cbc:StreetName>Lieferantenstraße 20</cbc:StreetName>
|
||||||
|
<cbc:BuildingNumber>0</cbc:BuildingNumber>
|
||||||
|
<cbc:CityName>München</cbc:CityName>
|
||||||
|
<cbc:PostalZone>80333</cbc:PostalZone>
|
||||||
|
<cac:Country>
|
||||||
|
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
||||||
|
</cac:Country>
|
||||||
|
</cac:PostalAddress>
|
||||||
|
|
||||||
|
<cac:PartyTaxScheme>
|
||||||
|
<cbc:CompanyID>201/113/40209</cbc:CompanyID>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>VAT</cbc:ID>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:PartyTaxScheme>
|
||||||
|
|
||||||
|
</cac:Party>
|
||||||
|
</cac:AccountingSupplierParty>
|
||||||
|
|
||||||
|
<cac:AccountingCustomerParty>
|
||||||
|
<cac:Party>
|
||||||
|
<cac:PartyName>
|
||||||
|
<cbc:Name>Kunden AG Mitte</cbc:Name>
|
||||||
|
</cac:PartyName>
|
||||||
|
<cac:PostalAddress>
|
||||||
|
<cbc:StreetName>Kundenstraße 15</cbc:StreetName>
|
||||||
|
<cbc:BuildingNumber>0</cbc:BuildingNumber>
|
||||||
|
<cbc:CityName>Frankfurt</cbc:CityName>
|
||||||
|
<cbc:PostalZone>69876</cbc:PostalZone>
|
||||||
|
<cac:Country>
|
||||||
|
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
||||||
|
</cac:Country>
|
||||||
|
</cac:PostalAddress>
|
||||||
|
|
||||||
|
</cac:Party>
|
||||||
|
</cac:AccountingCustomerParty>
|
||||||
|
|
||||||
|
<cac:PaymentTerms>
|
||||||
|
<cbc:Note>Due in 30 days</cbc:Note>
|
||||||
|
</cac:PaymentTerms>
|
||||||
|
|
||||||
|
<cac:TaxTotal>
|
||||||
|
<cbc:TaxAmount currencyID="EUR">0.00</cbc:TaxAmount>
|
||||||
|
</cac:TaxTotal>
|
||||||
|
|
||||||
|
<cac:LegalMonetaryTotal>
|
||||||
|
<cbc:LineExtensionAmount currencyID="EUR">0.00</cbc:LineExtensionAmount>
|
||||||
|
<cbc:TaxExclusiveAmount currencyID="EUR">0.00</cbc:TaxExclusiveAmount>
|
||||||
|
<cbc:TaxInclusiveAmount currencyID="EUR">0.00</cbc:TaxInclusiveAmount>
|
||||||
|
<cbc:PayableAmount currencyID="EUR">0.00</cbc:PayableAmount>
|
||||||
|
</cac:LegalMonetaryTotal>
|
||||||
|
|
||||||
|
|
||||||
|
<cac:InvoiceLine>
|
||||||
|
<cbc:ID>1</cbc:ID>
|
||||||
|
<cbc:InvoicedQuantity unitCode="KGM">4</cbc:InvoicedQuantity>
|
||||||
|
<cbc:LineExtensionAmount currencyID="EUR">22</cbc:LineExtensionAmount>
|
||||||
|
<cac:Item>
|
||||||
|
<cbc:Name>Schweinesteak</cbc:Name>
|
||||||
|
|
||||||
|
<cac:SellersItemIdentification>
|
||||||
|
<cbc:ID>SFK5</cbc:ID>
|
||||||
|
</cac:SellersItemIdentification>
|
||||||
|
<cac:ClassifiedTaxCategory>
|
||||||
|
<cbc:ID>S</cbc:ID>
|
||||||
|
<cbc:Percent>7</cbc:Percent>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>VAT</cbc:ID>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:ClassifiedTaxCategory>
|
||||||
|
</cac:Item>
|
||||||
|
<cac:Price>
|
||||||
|
<cbc:PriceAmount currencyID="EUR">5.5</cbc:PriceAmount>
|
||||||
|
</cac:Price>
|
||||||
|
</cac:InvoiceLine>
|
||||||
|
</Invoice>
|
@ -0,0 +1,3 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<rsm:CrossIndustryInvoice xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100" xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100" xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100">
|
||||||
|
<rsm:ExchangedDocumentContext><ram:GuidelineSpecifiedDocumentContextParameter><ram:ID>urn:cen.eu:en16931:2017</ram:ID></ram:GuidelineSpecifiedDocumentContextParameter></rsm:ExchangedDocumentContext><rsm:ExchangedDocument><ram:TypeCode>380</ram:TypeCode><ram:ID>471102</ram:ID><ram:IssueDateTime><udt:DateTimeString format="102">NaNNaNNaN</udt:DateTimeString></ram:IssueDateTime></rsm:ExchangedDocument><rsm:SupplyChainTradeTransaction><ram:ApplicableHeaderTradeAgreement><ram:SellerTradeParty><ram:Name>Lieferant GmbH</ram:Name><ram:PostalTradeAddress><ram:LineOne>Lieferantenstraße 20</ram:LineOne><ram:LineTwo>0</ram:LineTwo><ram:PostcodeCode>80333</ram:PostcodeCode><ram:CityName>München</ram:CityName><ram:CountryID>DE</ram:CountryID></ram:PostalTradeAddress><ram:SpecifiedTaxRegistration><ram:ID schemeID="VA">DE123456789</ram:ID></ram:SpecifiedTaxRegistration><ram:SpecifiedTaxRegistration><ram:ID schemeID="FC">201/113/40209</ram:ID></ram:SpecifiedTaxRegistration></ram:SellerTradeParty><ram:BuyerTradeParty><ram:Name>Kunden AG Mitte</ram:Name><ram:PostalTradeAddress><ram:LineOne>Kundenstraße 15</ram:LineOne><ram:LineTwo>0</ram:LineTwo><ram:PostcodeCode>69876</ram:PostcodeCode><ram:CityName>Frankfurt</ram:CityName><ram:CountryID>DE</ram:CountryID></ram:PostalTradeAddress></ram:BuyerTradeParty></ram:ApplicableHeaderTradeAgreement><ram:ApplicableHeaderTradeDelivery/><ram:ApplicableHeaderTradeSettlement><ram:InvoiceCurrencyCode>EUR</ram:InvoiceCurrencyCode><ram:SpecifiedTradePaymentTerms><ram:DueDateDateTime><udt:DateTimeString format="102">NaNNaNNaN</udt:DateTimeString></ram:DueDateDateTime></ram:SpecifiedTradePaymentTerms><ram:SpecifiedTradeSettlementHeaderMonetarySummation><ram:LineTotalAmount>473.00</ram:LineTotalAmount><ram:TaxTotalAmount currencyID="EUR">56.87</ram:TaxTotalAmount><ram:GrandTotalAmount>529.87</ram:GrandTotalAmount><ram:DuePayableAmount>529.87</ram:DuePayableAmount></ram:SpecifiedTradeSettlementHeaderMonetarySummation></ram:ApplicableHeaderTradeSettlement><ram:IncludedSupplyChainTradeLineItem><ram:AssociatedDocumentLineDocument><ram:LineID>1</ram:LineID></ram:AssociatedDocumentLineDocument><ram:SpecifiedTradeProduct><ram:Name>Trennblätter A4</ram:Name><ram:SellerAssignedID>TB100A4</ram:SellerAssignedID></ram:SpecifiedTradeProduct><ram:SpecifiedLineTradeAgreement><ram:NetPriceProductTradePrice><ram:ChargeAmount>9.90</ram:ChargeAmount></ram:NetPriceProductTradePrice></ram:SpecifiedLineTradeAgreement><ram:SpecifiedLineTradeDelivery><ram:BilledQuantity unitCode="H87">20</ram:BilledQuantity></ram:SpecifiedLineTradeDelivery><ram:SpecifiedLineTradeSettlement><ram:ApplicableTradeTax><ram:TypeCode>VAT</ram:TypeCode><ram:CategoryCode>S</ram:CategoryCode><ram:RateApplicablePercent>19</ram:RateApplicablePercent></ram:ApplicableTradeTax><ram:SpecifiedLineTradeSettlementMonetarySummation><ram:LineTotalAmount>198.00</ram:LineTotalAmount></ram:SpecifiedLineTradeSettlementMonetarySummation></ram:SpecifiedLineTradeSettlement></ram:IncludedSupplyChainTradeLineItem><ram:IncludedSupplyChainTradeLineItem><ram:AssociatedDocumentLineDocument><ram:LineID>2</ram:LineID></ram:AssociatedDocumentLineDocument><ram:SpecifiedTradeProduct><ram:Name>Joghurt Banane</ram:Name><ram:SellerAssignedID>ARNR2</ram:SellerAssignedID></ram:SpecifiedTradeProduct><ram:SpecifiedLineTradeAgreement><ram:NetPriceProductTradePrice><ram:ChargeAmount>5.50</ram:ChargeAmount></ram:NetPriceProductTradePrice></ram:SpecifiedLineTradeAgreement><ram:SpecifiedLineTradeDelivery><ram:BilledQuantity unitCode="H87">50</ram:BilledQuantity></ram:SpecifiedLineTradeDelivery><ram:SpecifiedLineTradeSettlement><ram:ApplicableTradeTax><ram:TypeCode>VAT</ram:TypeCode><ram:CategoryCode>S</ram:CategoryCode><ram:RateApplicablePercent>7</ram:RateApplicablePercent></ram:ApplicableTradeTax><ram:SpecifiedLineTradeSettlementMonetarySummation><ram:LineTotalAmount>275.00</ram:LineTotalAmount></ram:SpecifiedLineTradeSettlementMonetarySummation></ram:SpecifiedLineTradeSettlement></ram:IncludedSupplyChainTradeLineItem></rsm:SupplyChainTradeTransaction></rsm:CrossIndustryInvoice>
|
@ -0,0 +1,115 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
|
||||||
|
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
|
||||||
|
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
|
||||||
|
<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.0</cbc:CustomizationID>
|
||||||
|
<cbc:ID>471102</cbc:ID>
|
||||||
|
<cbc:IssueDate>2018-03-05</cbc:IssueDate>
|
||||||
|
<cbc:DueDate>2018-04-04</cbc:DueDate>
|
||||||
|
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
|
||||||
|
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
|
||||||
|
|
||||||
|
<cac:AccountingSupplierParty>
|
||||||
|
<cac:Party>
|
||||||
|
<cac:PartyName>
|
||||||
|
<cbc:Name>Lieferant GmbH</cbc:Name>
|
||||||
|
</cac:PartyName>
|
||||||
|
<cac:PostalAddress>
|
||||||
|
<cbc:StreetName>Lieferantenstraße 20</cbc:StreetName>
|
||||||
|
<cbc:BuildingNumber>0</cbc:BuildingNumber>
|
||||||
|
<cbc:CityName>München</cbc:CityName>
|
||||||
|
<cbc:PostalZone>80333</cbc:PostalZone>
|
||||||
|
<cac:Country>
|
||||||
|
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
||||||
|
</cac:Country>
|
||||||
|
</cac:PostalAddress>
|
||||||
|
|
||||||
|
<cac:PartyTaxScheme>
|
||||||
|
<cbc:CompanyID>201/113/40209</cbc:CompanyID>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>VAT</cbc:ID>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:PartyTaxScheme>
|
||||||
|
|
||||||
|
</cac:Party>
|
||||||
|
</cac:AccountingSupplierParty>
|
||||||
|
|
||||||
|
<cac:AccountingCustomerParty>
|
||||||
|
<cac:Party>
|
||||||
|
<cac:PartyName>
|
||||||
|
<cbc:Name>Kunden AG Mitte</cbc:Name>
|
||||||
|
</cac:PartyName>
|
||||||
|
<cac:PostalAddress>
|
||||||
|
<cbc:StreetName>Kundenstraße 15</cbc:StreetName>
|
||||||
|
<cbc:BuildingNumber>0</cbc:BuildingNumber>
|
||||||
|
<cbc:CityName>Frankfurt</cbc:CityName>
|
||||||
|
<cbc:PostalZone>69876</cbc:PostalZone>
|
||||||
|
<cac:Country>
|
||||||
|
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
||||||
|
</cac:Country>
|
||||||
|
</cac:PostalAddress>
|
||||||
|
|
||||||
|
</cac:Party>
|
||||||
|
</cac:AccountingCustomerParty>
|
||||||
|
|
||||||
|
<cac:PaymentTerms>
|
||||||
|
<cbc:Note>Due in 30 days</cbc:Note>
|
||||||
|
</cac:PaymentTerms>
|
||||||
|
|
||||||
|
<cac:TaxTotal>
|
||||||
|
<cbc:TaxAmount currencyID="EUR">0.00</cbc:TaxAmount>
|
||||||
|
</cac:TaxTotal>
|
||||||
|
|
||||||
|
<cac:LegalMonetaryTotal>
|
||||||
|
<cbc:LineExtensionAmount currencyID="EUR">0.00</cbc:LineExtensionAmount>
|
||||||
|
<cbc:TaxExclusiveAmount currencyID="EUR">0.00</cbc:TaxExclusiveAmount>
|
||||||
|
<cbc:TaxInclusiveAmount currencyID="EUR">0.00</cbc:TaxInclusiveAmount>
|
||||||
|
<cbc:PayableAmount currencyID="EUR">0.00</cbc:PayableAmount>
|
||||||
|
</cac:LegalMonetaryTotal>
|
||||||
|
|
||||||
|
|
||||||
|
<cac:InvoiceLine>
|
||||||
|
<cbc:ID>1</cbc:ID>
|
||||||
|
<cbc:InvoicedQuantity unitCode="H87">20</cbc:InvoicedQuantity>
|
||||||
|
<cbc:LineExtensionAmount currencyID="EUR">198</cbc:LineExtensionAmount>
|
||||||
|
<cac:Item>
|
||||||
|
<cbc:Name>Trennblätter A4</cbc:Name>
|
||||||
|
|
||||||
|
<cac:SellersItemIdentification>
|
||||||
|
<cbc:ID>TB100A4</cbc:ID>
|
||||||
|
</cac:SellersItemIdentification>
|
||||||
|
<cac:ClassifiedTaxCategory>
|
||||||
|
<cbc:ID>S</cbc:ID>
|
||||||
|
<cbc:Percent>19</cbc:Percent>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>VAT</cbc:ID>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:ClassifiedTaxCategory>
|
||||||
|
</cac:Item>
|
||||||
|
<cac:Price>
|
||||||
|
<cbc:PriceAmount currencyID="EUR">9.9</cbc:PriceAmount>
|
||||||
|
</cac:Price>
|
||||||
|
</cac:InvoiceLine>
|
||||||
|
<cac:InvoiceLine>
|
||||||
|
<cbc:ID>2</cbc:ID>
|
||||||
|
<cbc:InvoicedQuantity unitCode="H87">50</cbc:InvoicedQuantity>
|
||||||
|
<cbc:LineExtensionAmount currencyID="EUR">275</cbc:LineExtensionAmount>
|
||||||
|
<cac:Item>
|
||||||
|
<cbc:Name>Joghurt Banane</cbc:Name>
|
||||||
|
|
||||||
|
<cac:SellersItemIdentification>
|
||||||
|
<cbc:ID>ARNR2</cbc:ID>
|
||||||
|
</cac:SellersItemIdentification>
|
||||||
|
<cac:ClassifiedTaxCategory>
|
||||||
|
<cbc:ID>S</cbc:ID>
|
||||||
|
<cbc:Percent>7</cbc:Percent>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>VAT</cbc:ID>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:ClassifiedTaxCategory>
|
||||||
|
</cac:Item>
|
||||||
|
<cac:Price>
|
||||||
|
<cbc:PriceAmount currencyID="EUR">5.5</cbc:PriceAmount>
|
||||||
|
</cac:Price>
|
||||||
|
</cac:InvoiceLine>
|
||||||
|
</Invoice>
|
@ -0,0 +1,3 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<rsm:CrossIndustryInvoice xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100" xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100" xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100">
|
||||||
|
<rsm:ExchangedDocumentContext><ram:GuidelineSpecifiedDocumentContextParameter><ram:ID>urn:cen.eu:en16931:2017</ram:ID></ram:GuidelineSpecifiedDocumentContextParameter></rsm:ExchangedDocumentContext><rsm:ExchangedDocument><ram:TypeCode>380</ram:TypeCode><ram:ID>471102</ram:ID><ram:IssueDateTime><udt:DateTimeString format="102">NaNNaNNaN</udt:DateTimeString></ram:IssueDateTime></rsm:ExchangedDocument><rsm:SupplyChainTradeTransaction><ram:ApplicableHeaderTradeAgreement><ram:SellerTradeParty><ram:Name>Grundbesitz GmbH & Co.</ram:Name><ram:PostalTradeAddress><ram:LineOne>Musterstraße 42</ram:LineOne><ram:LineTwo>0</ram:LineTwo><ram:PostcodeCode>75645</ram:PostcodeCode><ram:CityName>Frankfurt</ram:CityName><ram:CountryID>DE</ram:CountryID></ram:PostalTradeAddress><ram:SpecifiedTaxRegistration><ram:ID schemeID="VA">DE136695976</ram:ID></ram:SpecifiedTaxRegistration><ram:SpecifiedTaxRegistration><ram:ID schemeID="FC">201/113/40209</ram:ID></ram:SpecifiedTaxRegistration></ram:SellerTradeParty><ram:BuyerTradeParty><ram:Name>Beispielmieter GmbH</ram:Name><ram:PostalTradeAddress><ram:LineOne>Verwaltung Straße 40</ram:LineOne><ram:LineTwo>0</ram:LineTwo><ram:PostcodeCode>12345</ram:PostcodeCode><ram:CityName>Musterstadt</ram:CityName><ram:CountryID>DE</ram:CountryID></ram:PostalTradeAddress></ram:BuyerTradeParty></ram:ApplicableHeaderTradeAgreement><ram:ApplicableHeaderTradeDelivery/><ram:ApplicableHeaderTradeSettlement><ram:InvoiceCurrencyCode>EUR</ram:InvoiceCurrencyCode><ram:SpecifiedTradePaymentTerms><ram:DueDateDateTime><udt:DateTimeString format="102">NaNNaNNaN</udt:DateTimeString></ram:DueDateDateTime></ram:SpecifiedTradePaymentTerms><ram:SpecifiedTradeSettlementHeaderMonetarySummation><ram:LineTotalAmount>15387.08</ram:LineTotalAmount><ram:TaxTotalAmount currencyID="EUR">2923.55</ram:TaxTotalAmount><ram:GrandTotalAmount>18310.63</ram:GrandTotalAmount><ram:DuePayableAmount>18310.63</ram:DuePayableAmount></ram:SpecifiedTradeSettlementHeaderMonetarySummation></ram:ApplicableHeaderTradeSettlement><ram:IncludedSupplyChainTradeLineItem><ram:AssociatedDocumentLineDocument><ram:LineID>1</ram:LineID></ram:AssociatedDocumentLineDocument><ram:SpecifiedTradeProduct><ram:Name>Abrechnungskreis 1</ram:Name></ram:SpecifiedTradeProduct><ram:SpecifiedLineTradeAgreement><ram:NetPriceProductTradePrice><ram:ChargeAmount>15387.08</ram:ChargeAmount></ram:NetPriceProductTradePrice></ram:SpecifiedLineTradeAgreement><ram:SpecifiedLineTradeDelivery><ram:BilledQuantity unitCode="C62">1</ram:BilledQuantity></ram:SpecifiedLineTradeDelivery><ram:SpecifiedLineTradeSettlement><ram:ApplicableTradeTax><ram:TypeCode>VAT</ram:TypeCode><ram:CategoryCode>S</ram:CategoryCode><ram:RateApplicablePercent>19</ram:RateApplicablePercent></ram:ApplicableTradeTax><ram:SpecifiedLineTradeSettlementMonetarySummation><ram:LineTotalAmount>15387.08</ram:LineTotalAmount></ram:SpecifiedLineTradeSettlementMonetarySummation></ram:SpecifiedLineTradeSettlement></ram:IncludedSupplyChainTradeLineItem></rsm:SupplyChainTradeTransaction></rsm:CrossIndustryInvoice>
|
@ -0,0 +1,90 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
|
||||||
|
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
|
||||||
|
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
|
||||||
|
<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.0</cbc:CustomizationID>
|
||||||
|
<cbc:ID>471102</cbc:ID>
|
||||||
|
<cbc:IssueDate>2018-03-05</cbc:IssueDate>
|
||||||
|
<cbc:DueDate>2018-04-04</cbc:DueDate>
|
||||||
|
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
|
||||||
|
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
|
||||||
|
|
||||||
|
<cac:AccountingSupplierParty>
|
||||||
|
<cac:Party>
|
||||||
|
<cac:PartyName>
|
||||||
|
<cbc:Name>Grundbesitz GmbH & Co.</cbc:Name>
|
||||||
|
</cac:PartyName>
|
||||||
|
<cac:PostalAddress>
|
||||||
|
<cbc:StreetName>Musterstraße 42</cbc:StreetName>
|
||||||
|
<cbc:BuildingNumber>0</cbc:BuildingNumber>
|
||||||
|
<cbc:CityName>Frankfurt</cbc:CityName>
|
||||||
|
<cbc:PostalZone>75645</cbc:PostalZone>
|
||||||
|
<cac:Country>
|
||||||
|
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
||||||
|
</cac:Country>
|
||||||
|
</cac:PostalAddress>
|
||||||
|
|
||||||
|
<cac:PartyTaxScheme>
|
||||||
|
<cbc:CompanyID>201/113/40209</cbc:CompanyID>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>VAT</cbc:ID>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:PartyTaxScheme>
|
||||||
|
|
||||||
|
</cac:Party>
|
||||||
|
</cac:AccountingSupplierParty>
|
||||||
|
|
||||||
|
<cac:AccountingCustomerParty>
|
||||||
|
<cac:Party>
|
||||||
|
<cac:PartyName>
|
||||||
|
<cbc:Name>Beispielmieter GmbH</cbc:Name>
|
||||||
|
</cac:PartyName>
|
||||||
|
<cac:PostalAddress>
|
||||||
|
<cbc:StreetName>Verwaltung Straße 40</cbc:StreetName>
|
||||||
|
<cbc:BuildingNumber>0</cbc:BuildingNumber>
|
||||||
|
<cbc:CityName>Musterstadt</cbc:CityName>
|
||||||
|
<cbc:PostalZone>12345</cbc:PostalZone>
|
||||||
|
<cac:Country>
|
||||||
|
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
||||||
|
</cac:Country>
|
||||||
|
</cac:PostalAddress>
|
||||||
|
|
||||||
|
</cac:Party>
|
||||||
|
</cac:AccountingCustomerParty>
|
||||||
|
|
||||||
|
<cac:PaymentTerms>
|
||||||
|
<cbc:Note>Due in 30 days</cbc:Note>
|
||||||
|
</cac:PaymentTerms>
|
||||||
|
|
||||||
|
<cac:TaxTotal>
|
||||||
|
<cbc:TaxAmount currencyID="EUR">0.00</cbc:TaxAmount>
|
||||||
|
</cac:TaxTotal>
|
||||||
|
|
||||||
|
<cac:LegalMonetaryTotal>
|
||||||
|
<cbc:LineExtensionAmount currencyID="EUR">0.00</cbc:LineExtensionAmount>
|
||||||
|
<cbc:TaxExclusiveAmount currencyID="EUR">0.00</cbc:TaxExclusiveAmount>
|
||||||
|
<cbc:TaxInclusiveAmount currencyID="EUR">0.00</cbc:TaxInclusiveAmount>
|
||||||
|
<cbc:PayableAmount currencyID="EUR">0.00</cbc:PayableAmount>
|
||||||
|
</cac:LegalMonetaryTotal>
|
||||||
|
|
||||||
|
|
||||||
|
<cac:InvoiceLine>
|
||||||
|
<cbc:ID>1</cbc:ID>
|
||||||
|
<cbc:InvoicedQuantity unitCode="C62">1</cbc:InvoicedQuantity>
|
||||||
|
<cbc:LineExtensionAmount currencyID="EUR">15387.08</cbc:LineExtensionAmount>
|
||||||
|
<cac:Item>
|
||||||
|
<cbc:Name>Abrechnungskreis 1</cbc:Name>
|
||||||
|
|
||||||
|
<cac:ClassifiedTaxCategory>
|
||||||
|
<cbc:ID>S</cbc:ID>
|
||||||
|
<cbc:Percent>19</cbc:Percent>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>VAT</cbc:ID>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:ClassifiedTaxCategory>
|
||||||
|
</cac:Item>
|
||||||
|
<cac:Price>
|
||||||
|
<cbc:PriceAmount currencyID="EUR">15387.08</cbc:PriceAmount>
|
||||||
|
</cac:Price>
|
||||||
|
</cac:InvoiceLine>
|
||||||
|
</Invoice>
|
3
test/output/focused/EN16931_Einfach.cii.xml-exported.xml
Normal file
3
test/output/focused/EN16931_Einfach.cii.xml-exported.xml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<rsm:CrossIndustryInvoice xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100" xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100" xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100">
|
||||||
|
<rsm:ExchangedDocumentContext><ram:GuidelineSpecifiedDocumentContextParameter><ram:ID>urn:cen.eu:en16931:2017</ram:ID></ram:GuidelineSpecifiedDocumentContextParameter></rsm:ExchangedDocumentContext><rsm:ExchangedDocument><ram:TypeCode>380</ram:TypeCode><ram:ID>471102</ram:ID><ram:IssueDateTime><udt:DateTimeString format="102">NaNNaNNaN</udt:DateTimeString></ram:IssueDateTime></rsm:ExchangedDocument><rsm:SupplyChainTradeTransaction><ram:ApplicableHeaderTradeAgreement><ram:SellerTradeParty><ram:Name>Lieferant GmbH</ram:Name><ram:PostalTradeAddress><ram:LineOne>Lieferantenstraße 20</ram:LineOne><ram:LineTwo>0</ram:LineTwo><ram:PostcodeCode>80333</ram:PostcodeCode><ram:CityName>München</ram:CityName><ram:CountryID>DE</ram:CountryID></ram:PostalTradeAddress><ram:SpecifiedTaxRegistration><ram:ID schemeID="VA">DE123456789</ram:ID></ram:SpecifiedTaxRegistration><ram:SpecifiedTaxRegistration><ram:ID schemeID="FC">201/113/40209</ram:ID></ram:SpecifiedTaxRegistration></ram:SellerTradeParty><ram:BuyerTradeParty><ram:Name>Kunden AG Mitte</ram:Name><ram:PostalTradeAddress><ram:LineOne>Kundenstraße 15</ram:LineOne><ram:LineTwo>0</ram:LineTwo><ram:PostcodeCode>69876</ram:PostcodeCode><ram:CityName>Frankfurt</ram:CityName><ram:CountryID>DE</ram:CountryID></ram:PostalTradeAddress></ram:BuyerTradeParty></ram:ApplicableHeaderTradeAgreement><ram:ApplicableHeaderTradeDelivery/><ram:ApplicableHeaderTradeSettlement><ram:InvoiceCurrencyCode>EUR</ram:InvoiceCurrencyCode><ram:SpecifiedTradePaymentTerms><ram:DueDateDateTime><udt:DateTimeString format="102">NaNNaNNaN</udt:DateTimeString></ram:DueDateDateTime></ram:SpecifiedTradePaymentTerms><ram:SpecifiedTradeSettlementHeaderMonetarySummation><ram:LineTotalAmount>473.00</ram:LineTotalAmount><ram:TaxTotalAmount currencyID="EUR">56.87</ram:TaxTotalAmount><ram:GrandTotalAmount>529.87</ram:GrandTotalAmount><ram:DuePayableAmount>529.87</ram:DuePayableAmount></ram:SpecifiedTradeSettlementHeaderMonetarySummation></ram:ApplicableHeaderTradeSettlement><ram:IncludedSupplyChainTradeLineItem><ram:AssociatedDocumentLineDocument><ram:LineID>1</ram:LineID></ram:AssociatedDocumentLineDocument><ram:SpecifiedTradeProduct><ram:Name>Trennblätter A4</ram:Name><ram:SellerAssignedID>TB100A4</ram:SellerAssignedID></ram:SpecifiedTradeProduct><ram:SpecifiedLineTradeAgreement><ram:NetPriceProductTradePrice><ram:ChargeAmount>9.90</ram:ChargeAmount></ram:NetPriceProductTradePrice></ram:SpecifiedLineTradeAgreement><ram:SpecifiedLineTradeDelivery><ram:BilledQuantity unitCode="H87">20</ram:BilledQuantity></ram:SpecifiedLineTradeDelivery><ram:SpecifiedLineTradeSettlement><ram:ApplicableTradeTax><ram:TypeCode>VAT</ram:TypeCode><ram:CategoryCode>S</ram:CategoryCode><ram:RateApplicablePercent>19</ram:RateApplicablePercent></ram:ApplicableTradeTax><ram:SpecifiedLineTradeSettlementMonetarySummation><ram:LineTotalAmount>198.00</ram:LineTotalAmount></ram:SpecifiedLineTradeSettlementMonetarySummation></ram:SpecifiedLineTradeSettlement></ram:IncludedSupplyChainTradeLineItem><ram:IncludedSupplyChainTradeLineItem><ram:AssociatedDocumentLineDocument><ram:LineID>2</ram:LineID></ram:AssociatedDocumentLineDocument><ram:SpecifiedTradeProduct><ram:Name>Joghurt Banane</ram:Name><ram:SellerAssignedID>ARNR2</ram:SellerAssignedID></ram:SpecifiedTradeProduct><ram:SpecifiedLineTradeAgreement><ram:NetPriceProductTradePrice><ram:ChargeAmount>5.50</ram:ChargeAmount></ram:NetPriceProductTradePrice></ram:SpecifiedLineTradeAgreement><ram:SpecifiedLineTradeDelivery><ram:BilledQuantity unitCode="H87">50</ram:BilledQuantity></ram:SpecifiedLineTradeDelivery><ram:SpecifiedLineTradeSettlement><ram:ApplicableTradeTax><ram:TypeCode>VAT</ram:TypeCode><ram:CategoryCode>S</ram:CategoryCode><ram:RateApplicablePercent>7</ram:RateApplicablePercent></ram:ApplicableTradeTax><ram:SpecifiedLineTradeSettlementMonetarySummation><ram:LineTotalAmount>275.00</ram:LineTotalAmount></ram:SpecifiedLineTradeSettlementMonetarySummation></ram:SpecifiedLineTradeSettlement></ram:IncludedSupplyChainTradeLineItem></rsm:SupplyChainTradeTransaction></rsm:CrossIndustryInvoice>
|
115
test/output/focused/EN16931_Einfach.ubl.xml-exported.xml
Normal file
115
test/output/focused/EN16931_Einfach.ubl.xml-exported.xml
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
|
||||||
|
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
|
||||||
|
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
|
||||||
|
<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.0</cbc:CustomizationID>
|
||||||
|
<cbc:ID>471102</cbc:ID>
|
||||||
|
<cbc:IssueDate>2018-03-05</cbc:IssueDate>
|
||||||
|
<cbc:DueDate>2018-04-04</cbc:DueDate>
|
||||||
|
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
|
||||||
|
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
|
||||||
|
|
||||||
|
<cac:AccountingSupplierParty>
|
||||||
|
<cac:Party>
|
||||||
|
<cac:PartyName>
|
||||||
|
<cbc:Name>Lieferant GmbH</cbc:Name>
|
||||||
|
</cac:PartyName>
|
||||||
|
<cac:PostalAddress>
|
||||||
|
<cbc:StreetName>Lieferantenstraße 20</cbc:StreetName>
|
||||||
|
<cbc:BuildingNumber>0</cbc:BuildingNumber>
|
||||||
|
<cbc:CityName>München</cbc:CityName>
|
||||||
|
<cbc:PostalZone>80333</cbc:PostalZone>
|
||||||
|
<cac:Country>
|
||||||
|
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
||||||
|
</cac:Country>
|
||||||
|
</cac:PostalAddress>
|
||||||
|
|
||||||
|
<cac:PartyTaxScheme>
|
||||||
|
<cbc:CompanyID>201/113/40209</cbc:CompanyID>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>VAT</cbc:ID>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:PartyTaxScheme>
|
||||||
|
|
||||||
|
</cac:Party>
|
||||||
|
</cac:AccountingSupplierParty>
|
||||||
|
|
||||||
|
<cac:AccountingCustomerParty>
|
||||||
|
<cac:Party>
|
||||||
|
<cac:PartyName>
|
||||||
|
<cbc:Name>Kunden AG Mitte</cbc:Name>
|
||||||
|
</cac:PartyName>
|
||||||
|
<cac:PostalAddress>
|
||||||
|
<cbc:StreetName>Kundenstraße 15</cbc:StreetName>
|
||||||
|
<cbc:BuildingNumber>0</cbc:BuildingNumber>
|
||||||
|
<cbc:CityName>Frankfurt</cbc:CityName>
|
||||||
|
<cbc:PostalZone>69876</cbc:PostalZone>
|
||||||
|
<cac:Country>
|
||||||
|
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
||||||
|
</cac:Country>
|
||||||
|
</cac:PostalAddress>
|
||||||
|
|
||||||
|
</cac:Party>
|
||||||
|
</cac:AccountingCustomerParty>
|
||||||
|
|
||||||
|
<cac:PaymentTerms>
|
||||||
|
<cbc:Note>Due in 30 days</cbc:Note>
|
||||||
|
</cac:PaymentTerms>
|
||||||
|
|
||||||
|
<cac:TaxTotal>
|
||||||
|
<cbc:TaxAmount currencyID="EUR">0.00</cbc:TaxAmount>
|
||||||
|
</cac:TaxTotal>
|
||||||
|
|
||||||
|
<cac:LegalMonetaryTotal>
|
||||||
|
<cbc:LineExtensionAmount currencyID="EUR">0.00</cbc:LineExtensionAmount>
|
||||||
|
<cbc:TaxExclusiveAmount currencyID="EUR">0.00</cbc:TaxExclusiveAmount>
|
||||||
|
<cbc:TaxInclusiveAmount currencyID="EUR">0.00</cbc:TaxInclusiveAmount>
|
||||||
|
<cbc:PayableAmount currencyID="EUR">0.00</cbc:PayableAmount>
|
||||||
|
</cac:LegalMonetaryTotal>
|
||||||
|
|
||||||
|
|
||||||
|
<cac:InvoiceLine>
|
||||||
|
<cbc:ID>1</cbc:ID>
|
||||||
|
<cbc:InvoicedQuantity unitCode="H87">20</cbc:InvoicedQuantity>
|
||||||
|
<cbc:LineExtensionAmount currencyID="EUR">198</cbc:LineExtensionAmount>
|
||||||
|
<cac:Item>
|
||||||
|
<cbc:Name>Trennblätter A4</cbc:Name>
|
||||||
|
|
||||||
|
<cac:SellersItemIdentification>
|
||||||
|
<cbc:ID>TB100A4</cbc:ID>
|
||||||
|
</cac:SellersItemIdentification>
|
||||||
|
<cac:ClassifiedTaxCategory>
|
||||||
|
<cbc:ID>S</cbc:ID>
|
||||||
|
<cbc:Percent>19</cbc:Percent>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>VAT</cbc:ID>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:ClassifiedTaxCategory>
|
||||||
|
</cac:Item>
|
||||||
|
<cac:Price>
|
||||||
|
<cbc:PriceAmount currencyID="EUR">9.9</cbc:PriceAmount>
|
||||||
|
</cac:Price>
|
||||||
|
</cac:InvoiceLine>
|
||||||
|
<cac:InvoiceLine>
|
||||||
|
<cbc:ID>2</cbc:ID>
|
||||||
|
<cbc:InvoicedQuantity unitCode="H87">50</cbc:InvoicedQuantity>
|
||||||
|
<cbc:LineExtensionAmount currencyID="EUR">275</cbc:LineExtensionAmount>
|
||||||
|
<cac:Item>
|
||||||
|
<cbc:Name>Joghurt Banane</cbc:Name>
|
||||||
|
|
||||||
|
<cac:SellersItemIdentification>
|
||||||
|
<cbc:ID>ARNR2</cbc:ID>
|
||||||
|
</cac:SellersItemIdentification>
|
||||||
|
<cac:ClassifiedTaxCategory>
|
||||||
|
<cbc:ID>S</cbc:ID>
|
||||||
|
<cbc:Percent>7</cbc:Percent>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>VAT</cbc:ID>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:ClassifiedTaxCategory>
|
||||||
|
</cac:Item>
|
||||||
|
<cac:Price>
|
||||||
|
<cbc:PriceAmount currencyID="EUR">5.5</cbc:PriceAmount>
|
||||||
|
</cac:Price>
|
||||||
|
</cac:InvoiceLine>
|
||||||
|
</Invoice>
|
Binary file not shown.
BIN
test/output/focused/zugferd_2p0_EN16931_1_Teilrechnung.pdf-raw-(zugferd-invoice.xml).xml
Normal file
BIN
test/output/focused/zugferd_2p0_EN16931_1_Teilrechnung.pdf-raw-(zugferd-invoice.xml).xml
Normal file
Binary file not shown.
Binary file not shown.
BIN
test/output/focused/zugferd_2p0_EN16931_2_Teilrechnung.pdf-raw-(zugferd-invoice.xml).xml
Normal file
BIN
test/output/focused/zugferd_2p0_EN16931_2_Teilrechnung.pdf-raw-(zugferd-invoice.xml).xml
Normal file
Binary file not shown.
Binary file not shown.
BIN
test/output/focused/zugferd_2p0_EN16931_AbweichenderZahlungsempf.pdf-raw-(zugferd-invoice.xml).xml
Normal file
BIN
test/output/focused/zugferd_2p0_EN16931_AbweichenderZahlungsempf.pdf-raw-(zugferd-invoice.xml).xml
Normal file
Binary file not shown.
Binary file not shown.
BIN
test/output/focused/zugferd_2p0_EN16931_Betriebskostenabrechnung.pdf-raw-(AWV_13_Betriebskosten.pdf).xml
Normal file
BIN
test/output/focused/zugferd_2p0_EN16931_Betriebskostenabrechnung.pdf-raw-(AWV_13_Betriebskosten.pdf).xml
Normal file
Binary file not shown.
BIN
test/output/focused/zugferd_2p0_EN16931_Betriebskostenabrechnung.pdf-raw-(zugferd-invoice.xml).xml
Normal file
BIN
test/output/focused/zugferd_2p0_EN16931_Betriebskostenabrechnung.pdf-raw-(zugferd-invoice.xml).xml
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
3
test/output/simple/EN16931_Einfach.cii.xml-exported.xml
Normal file
3
test/output/simple/EN16931_Einfach.cii.xml-exported.xml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<rsm:CrossIndustryInvoice xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100" xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100" xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100">
|
||||||
|
<rsm:ExchangedDocumentContext><ram:GuidelineSpecifiedDocumentContextParameter><ram:ID>urn:cen.eu:en16931:2017</ram:ID></ram:GuidelineSpecifiedDocumentContextParameter></rsm:ExchangedDocumentContext><rsm:ExchangedDocument><ram:TypeCode>380</ram:TypeCode><ram:ID>471102</ram:ID><ram:IssueDateTime><udt:DateTimeString format="102">NaNNaNNaN</udt:DateTimeString></ram:IssueDateTime></rsm:ExchangedDocument><rsm:SupplyChainTradeTransaction><ram:ApplicableHeaderTradeAgreement><ram:SellerTradeParty><ram:Name>Lieferant GmbH</ram:Name><ram:PostalTradeAddress><ram:LineOne>Lieferantenstraße 20</ram:LineOne><ram:LineTwo>0</ram:LineTwo><ram:PostcodeCode>80333</ram:PostcodeCode><ram:CityName>München</ram:CityName><ram:CountryID>DE</ram:CountryID></ram:PostalTradeAddress><ram:SpecifiedTaxRegistration><ram:ID schemeID="VA">DE123456789</ram:ID></ram:SpecifiedTaxRegistration><ram:SpecifiedTaxRegistration><ram:ID schemeID="FC">201/113/40209</ram:ID></ram:SpecifiedTaxRegistration></ram:SellerTradeParty><ram:BuyerTradeParty><ram:Name>Kunden AG Mitte</ram:Name><ram:PostalTradeAddress><ram:LineOne>Kundenstraße 15</ram:LineOne><ram:LineTwo>0</ram:LineTwo><ram:PostcodeCode>69876</ram:PostcodeCode><ram:CityName>Frankfurt</ram:CityName><ram:CountryID>DE</ram:CountryID></ram:PostalTradeAddress></ram:BuyerTradeParty></ram:ApplicableHeaderTradeAgreement><ram:ApplicableHeaderTradeDelivery/><ram:ApplicableHeaderTradeSettlement><ram:InvoiceCurrencyCode>EUR</ram:InvoiceCurrencyCode><ram:SpecifiedTradePaymentTerms><ram:DueDateDateTime><udt:DateTimeString format="102">NaNNaNNaN</udt:DateTimeString></ram:DueDateDateTime></ram:SpecifiedTradePaymentTerms><ram:SpecifiedTradeSettlementHeaderMonetarySummation><ram:LineTotalAmount>473.00</ram:LineTotalAmount><ram:TaxTotalAmount currencyID="EUR">56.87</ram:TaxTotalAmount><ram:GrandTotalAmount>529.87</ram:GrandTotalAmount><ram:DuePayableAmount>529.87</ram:DuePayableAmount></ram:SpecifiedTradeSettlementHeaderMonetarySummation></ram:ApplicableHeaderTradeSettlement><ram:IncludedSupplyChainTradeLineItem><ram:AssociatedDocumentLineDocument><ram:LineID>1</ram:LineID></ram:AssociatedDocumentLineDocument><ram:SpecifiedTradeProduct><ram:Name>Trennblätter A4</ram:Name><ram:SellerAssignedID>TB100A4</ram:SellerAssignedID></ram:SpecifiedTradeProduct><ram:SpecifiedLineTradeAgreement><ram:NetPriceProductTradePrice><ram:ChargeAmount>9.90</ram:ChargeAmount></ram:NetPriceProductTradePrice></ram:SpecifiedLineTradeAgreement><ram:SpecifiedLineTradeDelivery><ram:BilledQuantity unitCode="H87">20</ram:BilledQuantity></ram:SpecifiedLineTradeDelivery><ram:SpecifiedLineTradeSettlement><ram:ApplicableTradeTax><ram:TypeCode>VAT</ram:TypeCode><ram:CategoryCode>S</ram:CategoryCode><ram:RateApplicablePercent>19</ram:RateApplicablePercent></ram:ApplicableTradeTax><ram:SpecifiedLineTradeSettlementMonetarySummation><ram:LineTotalAmount>198.00</ram:LineTotalAmount></ram:SpecifiedLineTradeSettlementMonetarySummation></ram:SpecifiedLineTradeSettlement></ram:IncludedSupplyChainTradeLineItem><ram:IncludedSupplyChainTradeLineItem><ram:AssociatedDocumentLineDocument><ram:LineID>2</ram:LineID></ram:AssociatedDocumentLineDocument><ram:SpecifiedTradeProduct><ram:Name>Joghurt Banane</ram:Name><ram:SellerAssignedID>ARNR2</ram:SellerAssignedID></ram:SpecifiedTradeProduct><ram:SpecifiedLineTradeAgreement><ram:NetPriceProductTradePrice><ram:ChargeAmount>5.50</ram:ChargeAmount></ram:NetPriceProductTradePrice></ram:SpecifiedLineTradeAgreement><ram:SpecifiedLineTradeDelivery><ram:BilledQuantity unitCode="H87">50</ram:BilledQuantity></ram:SpecifiedLineTradeDelivery><ram:SpecifiedLineTradeSettlement><ram:ApplicableTradeTax><ram:TypeCode>VAT</ram:TypeCode><ram:CategoryCode>S</ram:CategoryCode><ram:RateApplicablePercent>7</ram:RateApplicablePercent></ram:ApplicableTradeTax><ram:SpecifiedLineTradeSettlementMonetarySummation><ram:LineTotalAmount>275.00</ram:LineTotalAmount></ram:SpecifiedLineTradeSettlementMonetarySummation></ram:SpecifiedLineTradeSettlement></ram:IncludedSupplyChainTradeLineItem></rsm:SupplyChainTradeTransaction></rsm:CrossIndustryInvoice>
|
115
test/output/simple/EN16931_Einfach.ubl.xml-exported.xml
Normal file
115
test/output/simple/EN16931_Einfach.ubl.xml-exported.xml
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
|
||||||
|
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
|
||||||
|
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
|
||||||
|
<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.0</cbc:CustomizationID>
|
||||||
|
<cbc:ID>471102</cbc:ID>
|
||||||
|
<cbc:IssueDate>2018-03-05</cbc:IssueDate>
|
||||||
|
<cbc:DueDate>2018-04-04</cbc:DueDate>
|
||||||
|
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
|
||||||
|
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
|
||||||
|
|
||||||
|
<cac:AccountingSupplierParty>
|
||||||
|
<cac:Party>
|
||||||
|
<cac:PartyName>
|
||||||
|
<cbc:Name>Lieferant GmbH</cbc:Name>
|
||||||
|
</cac:PartyName>
|
||||||
|
<cac:PostalAddress>
|
||||||
|
<cbc:StreetName>Lieferantenstraße 20</cbc:StreetName>
|
||||||
|
<cbc:BuildingNumber>0</cbc:BuildingNumber>
|
||||||
|
<cbc:CityName>München</cbc:CityName>
|
||||||
|
<cbc:PostalZone>80333</cbc:PostalZone>
|
||||||
|
<cac:Country>
|
||||||
|
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
||||||
|
</cac:Country>
|
||||||
|
</cac:PostalAddress>
|
||||||
|
|
||||||
|
<cac:PartyTaxScheme>
|
||||||
|
<cbc:CompanyID>201/113/40209</cbc:CompanyID>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>VAT</cbc:ID>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:PartyTaxScheme>
|
||||||
|
|
||||||
|
</cac:Party>
|
||||||
|
</cac:AccountingSupplierParty>
|
||||||
|
|
||||||
|
<cac:AccountingCustomerParty>
|
||||||
|
<cac:Party>
|
||||||
|
<cac:PartyName>
|
||||||
|
<cbc:Name>Kunden AG Mitte</cbc:Name>
|
||||||
|
</cac:PartyName>
|
||||||
|
<cac:PostalAddress>
|
||||||
|
<cbc:StreetName>Kundenstraße 15</cbc:StreetName>
|
||||||
|
<cbc:BuildingNumber>0</cbc:BuildingNumber>
|
||||||
|
<cbc:CityName>Frankfurt</cbc:CityName>
|
||||||
|
<cbc:PostalZone>69876</cbc:PostalZone>
|
||||||
|
<cac:Country>
|
||||||
|
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
||||||
|
</cac:Country>
|
||||||
|
</cac:PostalAddress>
|
||||||
|
|
||||||
|
</cac:Party>
|
||||||
|
</cac:AccountingCustomerParty>
|
||||||
|
|
||||||
|
<cac:PaymentTerms>
|
||||||
|
<cbc:Note>Due in 30 days</cbc:Note>
|
||||||
|
</cac:PaymentTerms>
|
||||||
|
|
||||||
|
<cac:TaxTotal>
|
||||||
|
<cbc:TaxAmount currencyID="EUR">0.00</cbc:TaxAmount>
|
||||||
|
</cac:TaxTotal>
|
||||||
|
|
||||||
|
<cac:LegalMonetaryTotal>
|
||||||
|
<cbc:LineExtensionAmount currencyID="EUR">0.00</cbc:LineExtensionAmount>
|
||||||
|
<cbc:TaxExclusiveAmount currencyID="EUR">0.00</cbc:TaxExclusiveAmount>
|
||||||
|
<cbc:TaxInclusiveAmount currencyID="EUR">0.00</cbc:TaxInclusiveAmount>
|
||||||
|
<cbc:PayableAmount currencyID="EUR">0.00</cbc:PayableAmount>
|
||||||
|
</cac:LegalMonetaryTotal>
|
||||||
|
|
||||||
|
|
||||||
|
<cac:InvoiceLine>
|
||||||
|
<cbc:ID>1</cbc:ID>
|
||||||
|
<cbc:InvoicedQuantity unitCode="H87">20</cbc:InvoicedQuantity>
|
||||||
|
<cbc:LineExtensionAmount currencyID="EUR">198</cbc:LineExtensionAmount>
|
||||||
|
<cac:Item>
|
||||||
|
<cbc:Name>Trennblätter A4</cbc:Name>
|
||||||
|
|
||||||
|
<cac:SellersItemIdentification>
|
||||||
|
<cbc:ID>TB100A4</cbc:ID>
|
||||||
|
</cac:SellersItemIdentification>
|
||||||
|
<cac:ClassifiedTaxCategory>
|
||||||
|
<cbc:ID>S</cbc:ID>
|
||||||
|
<cbc:Percent>19</cbc:Percent>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>VAT</cbc:ID>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:ClassifiedTaxCategory>
|
||||||
|
</cac:Item>
|
||||||
|
<cac:Price>
|
||||||
|
<cbc:PriceAmount currencyID="EUR">9.9</cbc:PriceAmount>
|
||||||
|
</cac:Price>
|
||||||
|
</cac:InvoiceLine>
|
||||||
|
<cac:InvoiceLine>
|
||||||
|
<cbc:ID>2</cbc:ID>
|
||||||
|
<cbc:InvoicedQuantity unitCode="H87">50</cbc:InvoicedQuantity>
|
||||||
|
<cbc:LineExtensionAmount currencyID="EUR">275</cbc:LineExtensionAmount>
|
||||||
|
<cac:Item>
|
||||||
|
<cbc:Name>Joghurt Banane</cbc:Name>
|
||||||
|
|
||||||
|
<cac:SellersItemIdentification>
|
||||||
|
<cbc:ID>ARNR2</cbc:ID>
|
||||||
|
</cac:SellersItemIdentification>
|
||||||
|
<cac:ClassifiedTaxCategory>
|
||||||
|
<cbc:ID>S</cbc:ID>
|
||||||
|
<cbc:Percent>7</cbc:Percent>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>VAT</cbc:ID>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:ClassifiedTaxCategory>
|
||||||
|
</cac:Item>
|
||||||
|
<cac:Price>
|
||||||
|
<cbc:PriceAmount currencyID="EUR">5.5</cbc:PriceAmount>
|
||||||
|
</cac:Price>
|
||||||
|
</cac:InvoiceLine>
|
||||||
|
</Invoice>
|
Binary file not shown.
192
test/output/validation-corpus-results.json
Normal file
192
test/output/validation-corpus-results.json
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
{
|
||||||
|
"zugferdV2Correct": {
|
||||||
|
"success": 5,
|
||||||
|
"fail": 0,
|
||||||
|
"details": [
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/FNFE-factur-x-examples/Avoir_FR_type381_BASIC.pdf",
|
||||||
|
"success": true,
|
||||||
|
"valid": true,
|
||||||
|
"errors": [],
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/FNFE-factur-x-examples/Facture_DOM_BASICWL.pdf",
|
||||||
|
"success": true,
|
||||||
|
"valid": true,
|
||||||
|
"errors": [],
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/FNFE-factur-x-examples/Facture_DOM_MINIMUM.pdf",
|
||||||
|
"success": true,
|
||||||
|
"valid": true,
|
||||||
|
"errors": [],
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/FNFE-factur-x-examples/Facture_FR_BASICWL.pdf",
|
||||||
|
"success": true,
|
||||||
|
"valid": true,
|
||||||
|
"errors": [],
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/FNFE-factur-x-examples/Facture_FR_MINIMUM.pdf",
|
||||||
|
"success": true,
|
||||||
|
"valid": true,
|
||||||
|
"errors": [],
|
||||||
|
"error": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"zugferdV2Fail": {
|
||||||
|
"success": 0,
|
||||||
|
"fail": 5,
|
||||||
|
"details": [
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/fail/FNFE-factur-x-examples/Avoir_FR_type380_BASIC.pdf",
|
||||||
|
"success": false,
|
||||||
|
"valid": true,
|
||||||
|
"errors": [],
|
||||||
|
"error": "Validation result (true) doesn't match expectation (false)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/fail/FNFE-factur-x-examples/Avoir_FR_type380_EN16931.pdf",
|
||||||
|
"success": false,
|
||||||
|
"valid": null,
|
||||||
|
"errors": null,
|
||||||
|
"error": "Error: No XML found in PDF"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/fail/FNFE-factur-x-examples/Avoir_FR_type380_MINIMUM.pdf",
|
||||||
|
"success": false,
|
||||||
|
"valid": true,
|
||||||
|
"errors": [],
|
||||||
|
"error": "Validation result (true) doesn't match expectation (false)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/fail/FNFE-factur-x-examples/Avoir_FR_type381_BASICWL.pdf",
|
||||||
|
"success": false,
|
||||||
|
"valid": true,
|
||||||
|
"errors": [],
|
||||||
|
"error": "Validation result (true) doesn't match expectation (false)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/fail/FNFE-factur-x-examples/Avoir_FR_type381_EN16931.pdf",
|
||||||
|
"success": false,
|
||||||
|
"valid": null,
|
||||||
|
"errors": null,
|
||||||
|
"error": "Error: No XML found in PDF"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"cii": {
|
||||||
|
"success": 5,
|
||||||
|
"fail": 0,
|
||||||
|
"details": [
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/EN16931_1_Teilrechnung.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"valid": true,
|
||||||
|
"errors": [],
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/EN16931_2_Teilrechnung.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"valid": true,
|
||||||
|
"errors": [],
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/EN16931_AbweichenderZahlungsempf.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"valid": true,
|
||||||
|
"errors": [],
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/EN16931_Betriebskostenabrechnung.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"valid": true,
|
||||||
|
"errors": [],
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/EN16931_Einfach.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"valid": true,
|
||||||
|
"errors": [],
|
||||||
|
"error": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ubl": {
|
||||||
|
"success": 0,
|
||||||
|
"fail": 5,
|
||||||
|
"details": [
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/EN16931_1_Teilrechnung.ubl.xml",
|
||||||
|
"success": false,
|
||||||
|
"valid": false,
|
||||||
|
"errors": [
|
||||||
|
{
|
||||||
|
"code": "VAL-ERROR",
|
||||||
|
"message": "Validation error: XRechnung validator not yet implemented"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"error": "Validation result (false) doesn't match expectation (true)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/EN16931_2_Teilrechnung.ubl.xml",
|
||||||
|
"success": false,
|
||||||
|
"valid": false,
|
||||||
|
"errors": [
|
||||||
|
{
|
||||||
|
"code": "VAL-ERROR",
|
||||||
|
"message": "Validation error: XRechnung validator not yet implemented"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"error": "Validation result (false) doesn't match expectation (true)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/EN16931_AbweichenderZahlungsempf.ubl.xml",
|
||||||
|
"success": false,
|
||||||
|
"valid": false,
|
||||||
|
"errors": [
|
||||||
|
{
|
||||||
|
"code": "VAL-ERROR",
|
||||||
|
"message": "Validation error: XRechnung validator not yet implemented"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"error": "Validation result (false) doesn't match expectation (true)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/EN16931_Betriebskostenabrechnung.ubl.xml",
|
||||||
|
"success": false,
|
||||||
|
"valid": false,
|
||||||
|
"errors": [
|
||||||
|
{
|
||||||
|
"code": "VAL-ERROR",
|
||||||
|
"message": "Validation error: XRechnung validator not yet implemented"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"error": "Validation result (false) doesn't match expectation (true)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/EN16931_Einfach.ubl.xml",
|
||||||
|
"success": false,
|
||||||
|
"valid": false,
|
||||||
|
"errors": [
|
||||||
|
{
|
||||||
|
"code": "VAL-ERROR",
|
||||||
|
"message": "Validation error: XRechnung validator not yet implemented"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"error": "Validation result (false) doesn't match expectation (true)"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"totalCorrectSuccessRate": 0.6666666666666666
|
||||||
|
}
|
350
test/output/xml-rechnung-corpus-results.json
Normal file
350
test/output/xml-rechnung-corpus-results.json
Normal file
@ -0,0 +1,350 @@
|
|||||||
|
{
|
||||||
|
"cii": {
|
||||||
|
"success": 27,
|
||||||
|
"fail": 0,
|
||||||
|
"details": [
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/EN16931_1_Teilrechnung.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/EN16931_2_Teilrechnung.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/EN16931_AbweichenderZahlungsempf.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/EN16931_Betriebskostenabrechnung.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/EN16931_Einfach.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/EN16931_Einfach_DueDate.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/EN16931_Einfach_negativePaymentDue.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/EN16931_Elektron.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/EN16931_ElektronischeAdresse.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/EN16931_Gutschrift.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/EN16931_Haftpflichtversicherung_Versicherungssteuer.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/EN16931_Innergemeinschaftliche_Lieferungen.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/EN16931_Kraftfahrversicherung_Bruttopreise.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/EN16931_Miete.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/EN16931_OEPNV.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/EN16931_Physiotherapeut.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/EN16931_Rabatte.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/EN16931_RechnungsUebertragung.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/EN16931_Rechnungskorrektur.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/EN16931_Reisekostenabrechnung.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/EN16931_SEPA_Prenotification.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/EN16931_Sachversicherung_berechneter_Steuersatz.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/XRECHNUNG_Betriebskostenabrechnung.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/XRECHNUNG_Einfach.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/XRECHNUNG_Elektron.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/XRECHNUNG_Reisekostenabrechnung.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/CII/not_validating_full_invoice_based_onTest_EeISI_300_CENfullmodel.cii.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ubl": {
|
||||||
|
"success": 28,
|
||||||
|
"fail": 0,
|
||||||
|
"details": [
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/EN16931_1_Teilrechnung.ubl.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "xrechnung",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/EN16931_2_Teilrechnung.ubl.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "xrechnung",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/EN16931_AbweichenderZahlungsempf.ubl.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "xrechnung",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/EN16931_Betriebskostenabrechnung.ubl.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "xrechnung",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/EN16931_Einfach.ubl.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "xrechnung",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/EN16931_Einfach_DueDate.ubl.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "xrechnung",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/EN16931_Einfach_negativePaymentDue.ubl.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "xrechnung",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/EN16931_Elektron.ubl.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "xrechnung",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/EN16931_ElektronischeAdresse.ubl.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "xrechnung",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/EN16931_Gutschrift.ubl.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "xrechnung",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/EN16931_Haftpflichtversicherung_Versicherungssteuer.ubl.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "xrechnung",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/EN16931_Innergemeinschaftliche_Lieferungen.ubl.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "xrechnung",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/EN16931_Kraftfahrversicherung_Bruttopreise.ubl.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "xrechnung",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/EN16931_Miete.ubl.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "xrechnung",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/EN16931_OEPNV.ubl.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "xrechnung",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/EN16931_Physiotherapeut.ubl.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "xrechnung",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/EN16931_Rabatte.ubl.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "xrechnung",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/EN16931_RechnungsUebertragung.ubl.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "xrechnung",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/EN16931_Rechnungskorrektur.ubl.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "xrechnung",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/EN16931_Reisekostenabrechnung.ubl.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "xrechnung",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/EN16931_SEPA_Prenotification.ubl.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "xrechnung",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/EN16931_Sachversicherung_berechneter_Steuersatz.ubl.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "xrechnung",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/XRECHNUNG_Betriebskostenabrechnung.ubl.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "xrechnung",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/XRECHNUNG_Einfach.ubl.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "xrechnung",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/XRECHNUNG_Elektron.ubl.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "xrechnung",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/XRECHNUNG_Reisekostenabrechnung.ubl.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "xrechnung",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/not_validating_full_invoice_based_onTest_EeISI_300_CENfullmodel.ubl.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "xrechnung",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/XML-Rechnung/UBL/ubl-tc434-creditnote1.xml",
|
||||||
|
"success": true,
|
||||||
|
"format": "xrechnung",
|
||||||
|
"error": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"fx": {
|
||||||
|
"success": 0,
|
||||||
|
"fail": 0,
|
||||||
|
"details": []
|
||||||
|
},
|
||||||
|
"totalSuccessRate": 1
|
||||||
|
}
|
753
test/output/zugferd-corpus-results.json
Normal file
753
test/output/zugferd-corpus-results.json
Normal file
@ -0,0 +1,753 @@
|
|||||||
|
{
|
||||||
|
"zugferdV1Correct": {
|
||||||
|
"success": 19,
|
||||||
|
"fail": 2,
|
||||||
|
"details": [
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv1/correct/4s4u/additional-data-sample-1.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv1/correct/Intarsys/ZUGFeRD_1p0_BASIC_Einfach.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv1/correct/Intarsys/ZUGFeRD_1p0_BASIC_Rechnungskorrektur.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv1/correct/Intarsys/ZUGFeRD_1p0_COMFORT_Einfach.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv1/correct/Intarsys/ZUGFeRD_1p0_COMFORT_Haftpflichtversicherung_Versicherungssteuer.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv1/correct/Intarsys/ZUGFeRD_1p0_COMFORT_Kraftfahrversicherung_Bruttopreise.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv1/correct/Intarsys/ZUGFeRD_1p0_COMFORT_Rabatte.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv1/correct/Intarsys/ZUGFeRD_1p0_COMFORT_Rechnungskorrektur.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv1/correct/Intarsys/ZUGFeRD_1p0_COMFORT_SEPA_Prenotification.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv1/correct/Intarsys/ZUGFeRD_1p0_COMFORT_Sachversicherung_berechneter_Steuersatz.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv1/correct/Intarsys/ZUGFeRD_1p0_EXTENDED_Kostenrechnung.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv1/correct/Intarsys/ZUGFeRD_1p0_EXTENDED_Rechnungskorrektur.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv1/correct/Intarsys/ZUGFeRD_1p0_EXTENDED_Warenrechnung.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv1/correct/Konik/acme_invoice-42_ZUGFeRD.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv1/correct/Mustangproject/MustangGnuaccountingBeispielRE-20140519_499.pdf",
|
||||||
|
"success": false,
|
||||||
|
"format": null,
|
||||||
|
"error": "Error: Unsupported invoice format: unknown"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv1/correct/Mustangproject/MustangGnuaccountingBeispielRE-20140522_501.pdf",
|
||||||
|
"success": false,
|
||||||
|
"format": null,
|
||||||
|
"error": "Error: Unsupported invoice format: unknown"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv1/correct/Mustangproject/MustangGnuaccountingBeispielRE-20140703_502.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv1/correct/Mustangproject/MustangGnuaccountingBeispielRE-20150613_503.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv1/correct/Mustangproject/MustangGnuaccountingBeispielRE-20151008_504.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv1/correct/Mustangproject/MustangGnuaccountingBeispielRE-20151008_504new.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv1/correct/Mustangproject/MustangGnuaccountingBeispielRE-20170509_505.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"zugferdV1Fail": {
|
||||||
|
"success": 3,
|
||||||
|
"fail": 0,
|
||||||
|
"details": [
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv1/fail/Mustangproject/fail1.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv1/fail/Mustangproject/fail2.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv1/fail/Mustangproject/fail3.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"zugferdV2Correct": {
|
||||||
|
"success": 78,
|
||||||
|
"fail": 0,
|
||||||
|
"details": [
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/FNFE-factur-x-examples/Avoir_FR_type381_BASIC.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/FNFE-factur-x-examples/Facture_DOM_BASICWL.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/FNFE-factur-x-examples/Facture_DOM_MINIMUM.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/FNFE-factur-x-examples/Facture_FR_BASICWL.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/FNFE-factur-x-examples/Facture_FR_MINIMUM.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/FNFE-factur-x-examples/Facture_UE_BASICWL.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/FNFE-factur-x-examples/Facture_UE_MINIMUM.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/Mustangproject/MustangGnuaccountingBeispielRE-20190610_507.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/Mustangproject/MustangGnuaccountingBeispielRE-20201121_508.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/Mustangproject/MustangGnuaccountingBeispielRE-20201121_508_withBOM.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/PHP_@gpFacturX/sample_inofficial_20190125_atgp_factur-x_v_1_0.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/intarsys/BASIC/zugferd_2p0_BASIC_Einfach.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/intarsys/BASIC/zugferd_2p0_BASIC_Rechnungskorrektur.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/intarsys/BASIC/zugferd_2p0_BASIC_Taxifahrt.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/intarsys/EN16931/zugferd_2p0_EN16931_1_Teilrechnung.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/intarsys/EN16931/zugferd_2p0_EN16931_2_Teilrechnung.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/intarsys/EN16931/zugferd_2p0_EN16931_AbweichenderZahlungsempf.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/intarsys/EN16931/zugferd_2p0_EN16931_Betriebskostenabrechnung.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/intarsys/EN16931/zugferd_2p0_EN16931_Einfach.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/intarsys/EN16931/zugferd_2p0_EN16931_Elektron.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/intarsys/EN16931/zugferd_2p0_EN16931_ElektronischeAdresse.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/intarsys/EN16931/zugferd_2p0_EN16931_Gutschrift.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/intarsys/EN16931/zugferd_2p0_EN16931_Haftpflichtversicherung_Versicherungssteuer.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/intarsys/EN16931/zugferd_2p0_EN16931_Innergemeinschaftliche_Lieferungen.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/intarsys/EN16931/zugferd_2p0_EN16931_Kraftfahrversicherung_Bruttopreise.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/intarsys/EN16931/zugferd_2p0_EN16931_Miete.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/intarsys/EN16931/zugferd_2p0_EN16931_OEPNV.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/intarsys/EN16931/zugferd_2p0_EN16931_Physiotherapeut.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/intarsys/EN16931/zugferd_2p0_EN16931_Rabatte.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/intarsys/EN16931/zugferd_2p0_EN16931_RechnungsUebertragung.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/intarsys/EN16931/zugferd_2p0_EN16931_Rechnungskorrektur.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/intarsys/EN16931/zugferd_2p0_EN16931_Reisekostenabrechnung.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/intarsys/EN16931/zugferd_2p0_EN16931_SEPA_Prenotification.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/intarsys/EN16931/zugferd_2p0_EN16931_Sachversicherung_berechneter_Steuersatz.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/intarsys/EXTENDED/zugferd_2p0_EXTENDED_Fremdwaehrung.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/intarsys/EXTENDED/zugferd_2p0_EXTENDED_InnergemeinschLieferungMehrereBestellungen.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/intarsys/EXTENDED/zugferd_2p0_EXTENDED_Kostenrechnung.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/intarsys/EXTENDED/zugferd_2p0_EXTENDED_Rechnungskorrektur.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/intarsys/EXTENDED/zugferd_2p0_EXTENDED_Warenrechnung.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/intarsys/MINIMUM/zugferd_2p0_MINIMUM.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/BASIC/zugferd_2p1_BASIC_Einfach.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/BASIC/zugferd_2p1_BASIC_Rechnungskorrektur.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/BASIC/zugferd_2p1_BASIC_Taxifahrt.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/BASIC WL/zugferd_2p1_BASIC-WL_Buchungshilfe.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/BASIC WL/zugferd_2p1_BASIC-WL_Einfach.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/EN16931/zugferd_2p1_EN16931_1_Teilrechnung.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/EN16931/zugferd_2p1_EN16931_2_Teilrechnung.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/EN16931/zugferd_2p1_EN16931_AbweichenderZahlungsempf.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/EN16931/zugferd_2p1_EN16931_Betriebskostenabrechnung.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/EN16931/zugferd_2p1_EN16931_Betriebskostenabrechnung_XRechnung_embedded.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/EN16931/zugferd_2p1_EN16931_Einfach.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/EN16931/zugferd_2p1_EN16931_Einfach_DueDate.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/EN16931/zugferd_2p1_EN16931_Einfach_negativePaymentDue.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/EN16931/zugferd_2p1_EN16931_Elektron.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/EN16931/zugferd_2p1_EN16931_Elektron_XRechnung.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/EN16931/zugferd_2p1_EN16931_Elektron_embedded.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/EN16931/zugferd_2p1_EN16931_ElektronischeAdresse.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/EN16931/zugferd_2p1_EN16931_Gutschrift.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/EN16931/zugferd_2p1_EN16931_Haftpflichtversicherung_Versicherungssteuer.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/EN16931/zugferd_2p1_EN16931_Innergemeinschaftliche_Lieferungen.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/EN16931/zugferd_2p1_EN16931_Kraftfahrversicherung_Bruttopreise.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/EN16931/zugferd_2p1_EN16931_Miete.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/EN16931/zugferd_2p1_EN16931_OEPNV.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/EN16931/zugferd_2p1_EN16931_Physiotherapeut.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/EN16931/zugferd_2p1_EN16931_Rabatte.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/EN16931/zugferd_2p1_EN16931_RechnungsUebertragung.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/EN16931/zugferd_2p1_EN16931_Rechnungskorrektur.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/EN16931/zugferd_2p1_EN16931_Reisekostenabrechnung.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/EN16931/zugferd_2p1_EN16931_Reisekostenabrechnung_XRechnung_embedded.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/EN16931/zugferd_2p1_EN16931_SEPA_Prenotification.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/EN16931/zugferd_2p1_EN16931_Sachversicherung_berechneter_Steuersatz.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/EXTENDED/zugferd_2p1_EXTENDED_Fremdwaehrung.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/EXTENDED/zugferd_2p1_EXTENDED_InnergemeinschLieferungMehrereBestellungen.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/EXTENDED/zugferd_2p1_EXTENDED_Kostenrechnung.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/EXTENDED/zugferd_2p1_EXTENDED_Rechnungskorrektur.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/EXTENDED/zugferd_2p1_EXTENDED_Warenrechnung.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/MINIMUM/zugferd_2p1_MINIMUM_Buchungshilfe.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/correct/symtrax/Beispiele/MINIMUM/zugferd_2p1_MINIMUM_Rechnung.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"zugferdV2Fail": {
|
||||||
|
"success": 19,
|
||||||
|
"fail": 0,
|
||||||
|
"details": [
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/fail/FNFE-factur-x-examples/Avoir_FR_type380_BASIC.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/fail/FNFE-factur-x-examples/Avoir_FR_type380_EN16931.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/fail/FNFE-factur-x-examples/Avoir_FR_type380_MINIMUM.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/fail/FNFE-factur-x-examples/Avoir_FR_type381_BASICWL.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/fail/FNFE-factur-x-examples/Avoir_FR_type381_EN16931.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/fail/FNFE-factur-x-examples/Avoir_FR_type381_MINIMUM.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/fail/FNFE-factur-x-examples/Facture_DOM_BASIC.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/fail/FNFE-factur-x-examples/Facture_DOM_EN16931.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/fail/FNFE-factur-x-examples/Facture_FR_BASIC.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/fail/FNFE-factur-x-examples/Facture_FR_EN16931.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/fail/FNFE-factur-x-examples/Facture_UE_BASIC.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/fail/FNFE-factur-x-examples/Facture_UE_EN16931.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/fail/MustangRE-20171118_506_ZUGFeRD1and2.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/fail/Mustangproject/MustangGnuaccountingBeispielRE-20171118_506.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/fail/Mustangproject/MustangGnuaccountingBeispielRE-20190610_507a.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/fail/Mustangproject/MustangGnuaccountingBeispielRE-20190610_507b.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/fail/ZUGFeRD_2.0_fully_compliant_complete.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/fail/ZUGFeRD_2_fully_compliant_complete.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "/mnt/data/lossless/fin.cx/xinvoice/test/assets/corpus/ZUGFeRDv2/fail/python-factur-x/python-factur-x.pdf",
|
||||||
|
"success": true,
|
||||||
|
"format": "facturx",
|
||||||
|
"error": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"totalCorrectSuccessRate": 0.9797979797979798
|
||||||
|
}
|
165
test/test.circular-corpus.ts
Normal file
165
test/test.circular-corpus.ts
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
import { tap, expect } from '@push.rocks/tapbundle';
|
||||||
|
import { XInvoice } from '../ts/classes.xinvoice.js';
|
||||||
|
import { InvoiceFormat } from '../ts/interfaces/common.js';
|
||||||
|
import * as fs from 'fs/promises';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
|
// Test circular export/import of corpus files
|
||||||
|
tap.test('XInvoice should maintain data integrity through export/import cycle', async () => {
|
||||||
|
// Get a subset of files for circular testing
|
||||||
|
const ciiFiles = await findFiles(path.join(process.cwd(), 'test/assets/corpus/XML-Rechnung/CII'), '.xml', 3);
|
||||||
|
const ublFiles = await findFiles(path.join(process.cwd(), 'test/assets/corpus/XML-Rechnung/UBL'), '.xml', 3);
|
||||||
|
|
||||||
|
// Log the number of files found
|
||||||
|
console.log(`Found ${ciiFiles.length} CII files for circular testing`);
|
||||||
|
console.log(`Found ${ublFiles.length} UBL files for circular testing`);
|
||||||
|
|
||||||
|
// Test CII files
|
||||||
|
const ciiResults = await testCircular(ciiFiles, 'facturx');
|
||||||
|
console.log(`CII files circular testing: ${ciiResults.success} succeeded, ${ciiResults.fail} failed`);
|
||||||
|
|
||||||
|
// Test UBL files
|
||||||
|
const ublResults = await testCircular(ublFiles, 'xrechnung');
|
||||||
|
console.log(`UBL files circular testing: ${ublResults.success} succeeded, ${ublResults.fail} failed`);
|
||||||
|
|
||||||
|
// Check that we have a reasonable success rate
|
||||||
|
const totalSuccess = ciiResults.success + ublResults.success;
|
||||||
|
const totalFiles = ciiFiles.length + ublFiles.length;
|
||||||
|
const successRate = totalSuccess / totalFiles;
|
||||||
|
|
||||||
|
console.log(`Overall success rate for circular testing: ${(successRate * 100).toFixed(2)}%`);
|
||||||
|
|
||||||
|
// We should have a success rate of at least 80% for circular testing
|
||||||
|
expect(successRate).toBeGreaterThan(0.8);
|
||||||
|
|
||||||
|
// Save the test results to a file
|
||||||
|
const testDir = path.join(process.cwd(), 'test', 'output');
|
||||||
|
await fs.mkdir(testDir, { recursive: true });
|
||||||
|
|
||||||
|
const testResults = {
|
||||||
|
cii: ciiResults,
|
||||||
|
ubl: ublResults,
|
||||||
|
totalSuccessRate: successRate
|
||||||
|
};
|
||||||
|
|
||||||
|
await fs.writeFile(
|
||||||
|
path.join(testDir, 'circular-corpus-results.json'),
|
||||||
|
JSON.stringify(testResults, null, 2)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests circular export/import of files and returns the results
|
||||||
|
* @param files List of files to test
|
||||||
|
* @param exportFormat Format to export to
|
||||||
|
* @returns Test results
|
||||||
|
*/
|
||||||
|
async function testCircular(files: string[], exportFormat: string): Promise<{ success: number, fail: number, details: any[] }> {
|
||||||
|
const results = {
|
||||||
|
success: 0,
|
||||||
|
fail: 0,
|
||||||
|
details: [] as any[]
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
try {
|
||||||
|
// Read the file
|
||||||
|
const xmlContent = await fs.readFile(file, 'utf8');
|
||||||
|
|
||||||
|
// Create XInvoice from XML
|
||||||
|
const xinvoice = await XInvoice.fromXml(xmlContent);
|
||||||
|
|
||||||
|
// Export to XML
|
||||||
|
const exportedXml = await xinvoice.exportXml(exportFormat as any);
|
||||||
|
|
||||||
|
// Create a new XInvoice from the exported XML
|
||||||
|
const reimportedXInvoice = await XInvoice.fromXml(exportedXml);
|
||||||
|
|
||||||
|
// Check that key properties match
|
||||||
|
const keysMatch =
|
||||||
|
reimportedXInvoice.from.name === xinvoice.from.name &&
|
||||||
|
reimportedXInvoice.to.name === xinvoice.to.name &&
|
||||||
|
reimportedXInvoice.items.length === xinvoice.items.length;
|
||||||
|
|
||||||
|
if (keysMatch) {
|
||||||
|
// Success
|
||||||
|
results.success++;
|
||||||
|
results.details.push({
|
||||||
|
file,
|
||||||
|
success: true,
|
||||||
|
error: null
|
||||||
|
});
|
||||||
|
|
||||||
|
// Save the exported XML for inspection
|
||||||
|
const testDir = path.join(process.cwd(), 'test', 'output', 'circular');
|
||||||
|
await fs.mkdir(testDir, { recursive: true });
|
||||||
|
|
||||||
|
const fileName = path.basename(file);
|
||||||
|
await fs.writeFile(path.join(testDir, `${fileName}-exported.xml`), exportedXml);
|
||||||
|
} else {
|
||||||
|
// Key properties don't match
|
||||||
|
results.fail++;
|
||||||
|
results.details.push({
|
||||||
|
file,
|
||||||
|
success: false,
|
||||||
|
error: 'Key properties don\'t match after reimport'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// Error processing the file
|
||||||
|
results.fail++;
|
||||||
|
results.details.push({
|
||||||
|
file,
|
||||||
|
success: false,
|
||||||
|
error: `Error: ${error.message}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively finds files with a specific extension in a directory
|
||||||
|
* @param dir Directory to search
|
||||||
|
* @param extension File extension to look for
|
||||||
|
* @param limit Maximum number of files to return
|
||||||
|
* @returns Array of file paths
|
||||||
|
*/
|
||||||
|
async function findFiles(dir: string, extension: string, limit?: number): Promise<string[]> {
|
||||||
|
try {
|
||||||
|
const files = await fs.readdir(dir, { withFileTypes: true });
|
||||||
|
|
||||||
|
const result: string[] = [];
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
if (limit && result.length >= limit) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const filePath = path.join(dir, file.name);
|
||||||
|
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
// Recursively search subdirectories
|
||||||
|
const remainingLimit = limit ? limit - result.length : undefined;
|
||||||
|
const subDirFiles = await findFiles(filePath, extension, remainingLimit);
|
||||||
|
result.push(...subDirFiles);
|
||||||
|
|
||||||
|
if (limit && result.length >= limit) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (file.name.toLowerCase().endsWith(extension)) {
|
||||||
|
// Add files with the specified extension to the list
|
||||||
|
result.push(filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error finding files in ${dir}:`, error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the tests
|
||||||
|
tap.start();
|
213
test/test.corpus-master.ts
Normal file
213
test/test.corpus-master.ts
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
import { tap, expect } from '@push.rocks/tapbundle';
|
||||||
|
import * as fs from 'fs/promises';
|
||||||
|
import * as path from 'path';
|
||||||
|
import { execSync } from 'child_process';
|
||||||
|
|
||||||
|
// Master test for corpus testing
|
||||||
|
tap.test('Run all corpus tests', async () => {
|
||||||
|
console.log('Running all corpus tests...');
|
||||||
|
|
||||||
|
// Create output directory
|
||||||
|
const testDir = path.join(process.cwd(), 'test', 'output');
|
||||||
|
await fs.mkdir(testDir, { recursive: true });
|
||||||
|
|
||||||
|
// Run each test file and collect results
|
||||||
|
const testFiles = [
|
||||||
|
'test.zugferd-corpus.ts',
|
||||||
|
'test.xml-rechnung-corpus.ts',
|
||||||
|
'test.other-formats-corpus.ts',
|
||||||
|
'test.validation-corpus.ts',
|
||||||
|
'test.circular-corpus.ts'
|
||||||
|
];
|
||||||
|
|
||||||
|
const results: Record<string, any> = {};
|
||||||
|
|
||||||
|
for (const testFile of testFiles) {
|
||||||
|
console.log(`Running ${testFile}...`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Run the test
|
||||||
|
execSync(`tsx test/${testFile}`, { stdio: 'inherit' });
|
||||||
|
|
||||||
|
// Read the results
|
||||||
|
const resultFile = testFile.replace('.ts', '-results.json');
|
||||||
|
const resultPath = path.join(testDir, resultFile);
|
||||||
|
|
||||||
|
if (await fileExists(resultPath)) {
|
||||||
|
const resultContent = await fs.readFile(resultPath, 'utf8');
|
||||||
|
results[testFile] = JSON.parse(resultContent);
|
||||||
|
} else {
|
||||||
|
results[testFile] = { error: 'No results file found' };
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error running ${testFile}:`, error);
|
||||||
|
results[testFile] = { error: error.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the combined results
|
||||||
|
await fs.writeFile(
|
||||||
|
path.join(testDir, 'corpus-master-results.json'),
|
||||||
|
JSON.stringify(results, null, 2)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Generate a summary report
|
||||||
|
const summary = generateSummary(results);
|
||||||
|
await fs.writeFile(
|
||||||
|
path.join(testDir, 'corpus-summary.md'),
|
||||||
|
summary
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log('All corpus tests completed.');
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a summary report from the test results
|
||||||
|
* @param results Test results
|
||||||
|
* @returns Summary report in Markdown format
|
||||||
|
*/
|
||||||
|
function generateSummary(results: Record<string, any>): string {
|
||||||
|
let summary = '# XInvoice Corpus Testing Summary\n\n';
|
||||||
|
|
||||||
|
// Add date and time
|
||||||
|
summary += `Generated on: ${new Date().toISOString()}\n\n`;
|
||||||
|
|
||||||
|
// Add overall summary
|
||||||
|
summary += '## Overall Summary\n\n';
|
||||||
|
summary += '| Test | Success Rate | Files Tested |\n';
|
||||||
|
summary += '|------|--------------|-------------|\n';
|
||||||
|
|
||||||
|
for (const [testFile, result] of Object.entries(results)) {
|
||||||
|
if (result.error) {
|
||||||
|
summary += `| ${testFile} | Error: ${result.error} | N/A |\n`;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let successRate = 'N/A';
|
||||||
|
let filesTested = 'N/A';
|
||||||
|
|
||||||
|
if (testFile === 'test.zugferd-corpus.ts') {
|
||||||
|
const rate = result.totalCorrectSuccessRate * 100;
|
||||||
|
successRate = `${rate.toFixed(2)}%`;
|
||||||
|
|
||||||
|
const v1Correct = result.zugferdV1Correct?.success + result.zugferdV1Correct?.fail || 0;
|
||||||
|
const v1Fail = result.zugferdV1Fail?.success + result.zugferdV1Fail?.fail || 0;
|
||||||
|
const v2Correct = result.zugferdV2Correct?.success + result.zugferdV2Correct?.fail || 0;
|
||||||
|
const v2Fail = result.zugferdV2Fail?.success + result.zugferdV2Fail?.fail || 0;
|
||||||
|
|
||||||
|
filesTested = `${v1Correct + v1Fail + v2Correct + v2Fail}`;
|
||||||
|
} else if (testFile === 'test.xml-rechnung-corpus.ts') {
|
||||||
|
const rate = result.totalSuccessRate * 100;
|
||||||
|
successRate = `${rate.toFixed(2)}%`;
|
||||||
|
|
||||||
|
const cii = result.cii?.success + result.cii?.fail || 0;
|
||||||
|
const ubl = result.ubl?.success + result.ubl?.fail || 0;
|
||||||
|
const fx = result.fx?.success + result.fx?.fail || 0;
|
||||||
|
|
||||||
|
filesTested = `${cii + ubl + fx}`;
|
||||||
|
} else if (testFile === 'test.other-formats-corpus.ts') {
|
||||||
|
const rate = result.totalSuccessRate * 100;
|
||||||
|
successRate = `${rate.toFixed(2)}%`;
|
||||||
|
|
||||||
|
const peppol = result.peppol?.success + result.peppol?.fail || 0;
|
||||||
|
const fatturapa = result.fatturapa?.success + result.fatturapa?.fail || 0;
|
||||||
|
|
||||||
|
filesTested = `${peppol + fatturapa}`;
|
||||||
|
} else if (testFile === 'test.validation-corpus.ts') {
|
||||||
|
const rate = result.totalCorrectSuccessRate * 100;
|
||||||
|
successRate = `${rate.toFixed(2)}%`;
|
||||||
|
|
||||||
|
const zugferdV2Correct = result.zugferdV2Correct?.success + result.zugferdV2Correct?.fail || 0;
|
||||||
|
const zugferdV2Fail = result.zugferdV2Fail?.success + result.zugferdV2Fail?.fail || 0;
|
||||||
|
const cii = result.cii?.success + result.cii?.fail || 0;
|
||||||
|
const ubl = result.ubl?.success + result.ubl?.fail || 0;
|
||||||
|
|
||||||
|
filesTested = `${zugferdV2Correct + zugferdV2Fail + cii + ubl}`;
|
||||||
|
} else if (testFile === 'test.circular-corpus.ts') {
|
||||||
|
const rate = result.totalSuccessRate * 100;
|
||||||
|
successRate = `${rate.toFixed(2)}%`;
|
||||||
|
|
||||||
|
const cii = result.cii?.success + result.cii?.fail || 0;
|
||||||
|
const ubl = result.ubl?.success + result.ubl?.fail || 0;
|
||||||
|
|
||||||
|
filesTested = `${cii + ubl}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
summary += `| ${testFile} | ${successRate} | ${filesTested} |\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add detailed results for each test
|
||||||
|
for (const [testFile, result] of Object.entries(results)) {
|
||||||
|
if (result.error) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
summary += `\n## ${testFile}\n\n`;
|
||||||
|
|
||||||
|
if (testFile === 'test.zugferd-corpus.ts') {
|
||||||
|
summary += '### ZUGFeRD v1 Correct Files\n\n';
|
||||||
|
summary += `Success: ${result.zugferdV1Correct?.success || 0}, Fail: ${result.zugferdV1Correct?.fail || 0}\n\n`;
|
||||||
|
|
||||||
|
summary += '### ZUGFeRD v1 Fail Files\n\n';
|
||||||
|
summary += `Success: ${result.zugferdV1Fail?.success || 0}, Fail: ${result.zugferdV1Fail?.fail || 0}\n\n`;
|
||||||
|
|
||||||
|
summary += '### ZUGFeRD v2 Correct Files\n\n';
|
||||||
|
summary += `Success: ${result.zugferdV2Correct?.success || 0}, Fail: ${result.zugferdV2Correct?.fail || 0}\n\n`;
|
||||||
|
|
||||||
|
summary += '### ZUGFeRD v2 Fail Files\n\n';
|
||||||
|
summary += `Success: ${result.zugferdV2Fail?.success || 0}, Fail: ${result.zugferdV2Fail?.fail || 0}\n\n`;
|
||||||
|
} else if (testFile === 'test.xml-rechnung-corpus.ts') {
|
||||||
|
summary += '### CII Files\n\n';
|
||||||
|
summary += `Success: ${result.cii?.success || 0}, Fail: ${result.cii?.fail || 0}\n\n`;
|
||||||
|
|
||||||
|
summary += '### UBL Files\n\n';
|
||||||
|
summary += `Success: ${result.ubl?.success || 0}, Fail: ${result.ubl?.fail || 0}\n\n`;
|
||||||
|
|
||||||
|
summary += '### FX Files\n\n';
|
||||||
|
summary += `Success: ${result.fx?.success || 0}, Fail: ${result.fx?.fail || 0}\n\n`;
|
||||||
|
} else if (testFile === 'test.other-formats-corpus.ts') {
|
||||||
|
summary += '### PEPPOL Files\n\n';
|
||||||
|
summary += `Success: ${result.peppol?.success || 0}, Fail: ${result.peppol?.fail || 0}\n\n`;
|
||||||
|
|
||||||
|
summary += '### fatturaPA Files\n\n';
|
||||||
|
summary += `Success: ${result.fatturapa?.success || 0}, Fail: ${result.fatturapa?.fail || 0}\n\n`;
|
||||||
|
} else if (testFile === 'test.validation-corpus.ts') {
|
||||||
|
summary += '### ZUGFeRD v2 Correct Files Validation\n\n';
|
||||||
|
summary += `Success: ${result.zugferdV2Correct?.success || 0}, Fail: ${result.zugferdV2Correct?.fail || 0}\n\n`;
|
||||||
|
|
||||||
|
summary += '### ZUGFeRD v2 Fail Files Validation\n\n';
|
||||||
|
summary += `Success: ${result.zugferdV2Fail?.success || 0}, Fail: ${result.zugferdV2Fail?.fail || 0}\n\n`;
|
||||||
|
|
||||||
|
summary += '### CII Files Validation\n\n';
|
||||||
|
summary += `Success: ${result.cii?.success || 0}, Fail: ${result.cii?.fail || 0}\n\n`;
|
||||||
|
|
||||||
|
summary += '### UBL Files Validation\n\n';
|
||||||
|
summary += `Success: ${result.ubl?.success || 0}, Fail: ${result.ubl?.fail || 0}\n\n`;
|
||||||
|
} else if (testFile === 'test.circular-corpus.ts') {
|
||||||
|
summary += '### CII Files Circular Testing\n\n';
|
||||||
|
summary += `Success: ${result.cii?.success || 0}, Fail: ${result.cii?.fail || 0}\n\n`;
|
||||||
|
|
||||||
|
summary += '### UBL Files Circular Testing\n\n';
|
||||||
|
summary += `Success: ${result.ubl?.success || 0}, Fail: ${result.ubl?.fail || 0}\n\n`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return summary;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a file exists
|
||||||
|
* @param filePath Path to the file
|
||||||
|
* @returns True if the file exists
|
||||||
|
*/
|
||||||
|
async function fileExists(filePath: string): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
await fs.access(filePath);
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the tests
|
||||||
|
tap.start();
|
279
test/test.focused-corpus.ts
Normal file
279
test/test.focused-corpus.ts
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
import { tap, expect } from '@push.rocks/tapbundle';
|
||||||
|
import { XInvoice } from '../ts/classes.xinvoice.js';
|
||||||
|
import { InvoiceFormat } from '../ts/interfaces/common.js';
|
||||||
|
import * as fs from 'fs/promises';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
|
// Test a focused subset of corpus files
|
||||||
|
tap.test('XInvoice should handle a focused subset of corpus files', async () => {
|
||||||
|
// Get a small subset of files for focused testing
|
||||||
|
const ciiFiles = await findFiles(path.join(process.cwd(), 'test/assets/corpus/XML-Rechnung/CII'), '.xml', 5);
|
||||||
|
const ublFiles = await findFiles(path.join(process.cwd(), 'test/assets/corpus/XML-Rechnung/UBL'), '.xml', 5);
|
||||||
|
const zugferdV2Files = await findFiles(path.join(process.cwd(), 'test/assets/corpus/ZUGFeRDv2/correct/intarsys/EN16931'), '.pdf', 5);
|
||||||
|
|
||||||
|
// Log the number of files found
|
||||||
|
console.log(`Found ${ciiFiles.length} CII files for focused testing`);
|
||||||
|
console.log(`Found ${ublFiles.length} UBL files for focused testing`);
|
||||||
|
console.log(`Found ${zugferdV2Files.length} ZUGFeRD v2 files for focused testing`);
|
||||||
|
|
||||||
|
// Test CII files
|
||||||
|
console.log('\nTesting CII files:');
|
||||||
|
for (const file of ciiFiles) {
|
||||||
|
console.log(`\nTesting file: ${path.basename(file)}`);
|
||||||
|
await testXmlFile(file, InvoiceFormat.CII);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test UBL files
|
||||||
|
console.log('\nTesting UBL files:');
|
||||||
|
for (const file of ublFiles) {
|
||||||
|
console.log(`\nTesting file: ${path.basename(file)}`);
|
||||||
|
await testXmlFile(file, InvoiceFormat.UBL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test ZUGFeRD v2 files
|
||||||
|
console.log('\nTesting ZUGFeRD v2 files:');
|
||||||
|
for (const file of zugferdV2Files) {
|
||||||
|
console.log(`\nTesting file: ${path.basename(file)}`);
|
||||||
|
await testPdfFile(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a test directory for output
|
||||||
|
const testDir = path.join(process.cwd(), 'test', 'output', 'focused');
|
||||||
|
await fs.mkdir(testDir, { recursive: true });
|
||||||
|
|
||||||
|
// Success - we're just testing individual files
|
||||||
|
expect(true).toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests an XML file
|
||||||
|
* @param file File to test
|
||||||
|
* @param expectedFormat Expected format
|
||||||
|
*/
|
||||||
|
async function testXmlFile(file: string, expectedFormat: InvoiceFormat): Promise<void> {
|
||||||
|
try {
|
||||||
|
// Read the file
|
||||||
|
const xmlContent = await fs.readFile(file, 'utf8');
|
||||||
|
|
||||||
|
// Create XInvoice from XML
|
||||||
|
const xinvoice = await XInvoice.fromXml(xmlContent);
|
||||||
|
|
||||||
|
// Check that the XInvoice instance has the expected properties
|
||||||
|
if (xinvoice && xinvoice.from && xinvoice.to && xinvoice.items) {
|
||||||
|
// Check that the format is detected correctly
|
||||||
|
const format = xinvoice.getFormat();
|
||||||
|
const isCorrectFormat = format === expectedFormat ||
|
||||||
|
(expectedFormat === InvoiceFormat.CII && format === InvoiceFormat.FACTURX) ||
|
||||||
|
(expectedFormat === InvoiceFormat.FACTURX && format === InvoiceFormat.CII) ||
|
||||||
|
(expectedFormat === InvoiceFormat.UBL && format === InvoiceFormat.XRECHNUNG) ||
|
||||||
|
(expectedFormat === InvoiceFormat.XRECHNUNG && format === InvoiceFormat.UBL);
|
||||||
|
|
||||||
|
if (isCorrectFormat) {
|
||||||
|
// Try to export the invoice back to XML
|
||||||
|
try {
|
||||||
|
let exportFormat = 'facturx';
|
||||||
|
if (format === InvoiceFormat.UBL || format === InvoiceFormat.XRECHNUNG) {
|
||||||
|
exportFormat = 'xrechnung';
|
||||||
|
}
|
||||||
|
|
||||||
|
const exportedXml = await xinvoice.exportXml(exportFormat as any);
|
||||||
|
|
||||||
|
if (exportedXml) {
|
||||||
|
console.log('✅ Success: File loaded, format detected correctly, and exported successfully');
|
||||||
|
console.log(`Format: ${format}`);
|
||||||
|
console.log(`From: ${xinvoice.from.name}`);
|
||||||
|
console.log(`To: ${xinvoice.to.name}`);
|
||||||
|
console.log(`Items: ${xinvoice.items.length}`);
|
||||||
|
|
||||||
|
// Save the exported XML for inspection
|
||||||
|
const testDir = path.join(process.cwd(), 'test', 'output', 'focused');
|
||||||
|
await fs.mkdir(testDir, { recursive: true });
|
||||||
|
await fs.writeFile(path.join(testDir, `${path.basename(file)}-exported.xml`), exportedXml);
|
||||||
|
} else {
|
||||||
|
console.log('❌ Failed to export valid XML');
|
||||||
|
}
|
||||||
|
} catch (exportError) {
|
||||||
|
console.log(`❌ Export error: ${exportError.message}`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log(`❌ Wrong format detected: ${format}, expected: ${expectedFormat}`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('❌ Missing required properties');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(`❌ Error processing the file: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests a PDF file
|
||||||
|
* @param file File to test
|
||||||
|
*/
|
||||||
|
async function testPdfFile(file: string): Promise<void> {
|
||||||
|
try {
|
||||||
|
// Read the file
|
||||||
|
const pdfBuffer = await fs.readFile(file);
|
||||||
|
|
||||||
|
// Extract XML from PDF
|
||||||
|
const { PDFExtractor } = await import('../ts/formats/pdf/pdf.extractor.js');
|
||||||
|
const extractor = new PDFExtractor();
|
||||||
|
const xmlContent = await extractor.extractXml(pdfBuffer);
|
||||||
|
|
||||||
|
// Save the raw XML content for inspection, even if it's invalid
|
||||||
|
const testDir = path.join(process.cwd(), 'test', 'output', 'focused');
|
||||||
|
await fs.mkdir(testDir, { recursive: true });
|
||||||
|
|
||||||
|
// Try to get the raw XML content directly from the PDF
|
||||||
|
try {
|
||||||
|
const pdfDoc = await import('pdf-lib').then(lib => lib.PDFDocument.load(pdfBuffer));
|
||||||
|
const namesDictObj = pdfDoc.catalog.lookup(await import('pdf-lib').then(lib => lib.PDFName.of('Names')));
|
||||||
|
|
||||||
|
if (namesDictObj) {
|
||||||
|
const embeddedFilesDictObj = namesDictObj.lookup(await import('pdf-lib').then(lib => lib.PDFName.of('EmbeddedFiles')));
|
||||||
|
|
||||||
|
if (embeddedFilesDictObj) {
|
||||||
|
const filesSpecObj = embeddedFilesDictObj.lookup(await import('pdf-lib').then(lib => lib.PDFName.of('Names')));
|
||||||
|
|
||||||
|
if (filesSpecObj && filesSpecObj.size && filesSpecObj.size() > 0) {
|
||||||
|
for (let i = 0; i < filesSpecObj.size(); i += 2) {
|
||||||
|
const fileNameObj = filesSpecObj.lookup(i);
|
||||||
|
const fileSpecObj = filesSpecObj.lookup(i + 1);
|
||||||
|
|
||||||
|
if (fileNameObj && fileSpecObj) {
|
||||||
|
const fileName = fileNameObj.toString();
|
||||||
|
console.log(`Found embedded file: ${fileName}`);
|
||||||
|
|
||||||
|
const efDictObj = fileSpecObj.lookup(await import('pdf-lib').then(lib => lib.PDFName.of('EF')));
|
||||||
|
|
||||||
|
if (efDictObj) {
|
||||||
|
const maybeStream = efDictObj.lookup(await import('pdf-lib').then(lib => lib.PDFName.of('F')));
|
||||||
|
|
||||||
|
if (maybeStream) {
|
||||||
|
try {
|
||||||
|
const xmlBytes = maybeStream.getContents();
|
||||||
|
const rawXmlContent = new TextDecoder('utf-8').decode(xmlBytes);
|
||||||
|
|
||||||
|
await fs.writeFile(path.join(testDir, `${path.basename(file)}-raw-${fileName}.xml`), rawXmlContent);
|
||||||
|
console.log(`Saved raw XML content from ${fileName}`);
|
||||||
|
} catch (streamError) {
|
||||||
|
console.log(`Error extracting stream content: ${streamError.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (pdfError) {
|
||||||
|
console.log(`Error inspecting PDF structure: ${pdfError.message}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xmlContent) {
|
||||||
|
console.log('✅ Successfully extracted XML from PDF');
|
||||||
|
|
||||||
|
// Save the extracted XML for inspection
|
||||||
|
await fs.writeFile(path.join(testDir, `${path.basename(file)}-extracted.xml`), xmlContent);
|
||||||
|
|
||||||
|
// Try to create XInvoice from the extracted XML
|
||||||
|
try {
|
||||||
|
const xinvoice = await XInvoice.fromXml(xmlContent);
|
||||||
|
|
||||||
|
if (xinvoice && xinvoice.from && xinvoice.to && xinvoice.items) {
|
||||||
|
console.log('✅ Successfully created XInvoice from extracted XML');
|
||||||
|
console.log(`Format: ${xinvoice.getFormat()}`);
|
||||||
|
console.log(`From: ${xinvoice.from.name}`);
|
||||||
|
console.log(`To: ${xinvoice.to.name}`);
|
||||||
|
console.log(`Items: ${xinvoice.items.length}`);
|
||||||
|
|
||||||
|
// Try to export the invoice back to XML
|
||||||
|
try {
|
||||||
|
const exportedXml = await xinvoice.exportXml('facturx');
|
||||||
|
|
||||||
|
if (exportedXml) {
|
||||||
|
console.log('✅ Successfully exported XInvoice back to XML');
|
||||||
|
|
||||||
|
// Save the exported XML for inspection
|
||||||
|
await fs.writeFile(path.join(testDir, `${path.basename(file)}-reexported.xml`), exportedXml);
|
||||||
|
} else {
|
||||||
|
console.log('❌ Failed to export valid XML');
|
||||||
|
}
|
||||||
|
} catch (exportError) {
|
||||||
|
console.log(`❌ Export error: ${exportError.message}`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('❌ Missing required properties in created XInvoice');
|
||||||
|
}
|
||||||
|
} catch (xmlError) {
|
||||||
|
console.log(`❌ Error creating XInvoice from extracted XML: ${xmlError.message}`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('❌ No XML found in PDF');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to create XInvoice directly from PDF
|
||||||
|
try {
|
||||||
|
const xinvoice = await XInvoice.fromPdf(pdfBuffer);
|
||||||
|
|
||||||
|
if (xinvoice && xinvoice.from && xinvoice.to && xinvoice.items) {
|
||||||
|
console.log('✅ Successfully created XInvoice directly from PDF');
|
||||||
|
console.log(`Format: ${xinvoice.getFormat()}`);
|
||||||
|
console.log(`From: ${xinvoice.from.name}`);
|
||||||
|
console.log(`To: ${xinvoice.to.name}`);
|
||||||
|
console.log(`Items: ${xinvoice.items.length}`);
|
||||||
|
} else {
|
||||||
|
console.log('❌ Missing required properties in created XInvoice');
|
||||||
|
}
|
||||||
|
} catch (pdfError) {
|
||||||
|
console.log(`❌ Error creating XInvoice directly from PDF: ${pdfError.message}`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(`❌ Error processing the file: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively finds files with a specific extension in a directory
|
||||||
|
* @param dir Directory to search
|
||||||
|
* @param extension File extension to look for
|
||||||
|
* @param limit Maximum number of files to return
|
||||||
|
* @returns Array of file paths
|
||||||
|
*/
|
||||||
|
async function findFiles(dir: string, extension: string, limit?: number): Promise<string[]> {
|
||||||
|
try {
|
||||||
|
const files = await fs.readdir(dir, { withFileTypes: true });
|
||||||
|
|
||||||
|
const result: string[] = [];
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
if (limit && result.length >= limit) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const filePath = path.join(dir, file.name);
|
||||||
|
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
// Recursively search subdirectories
|
||||||
|
const remainingLimit = limit ? limit - result.length : undefined;
|
||||||
|
const subDirFiles = await findFiles(filePath, extension, remainingLimit);
|
||||||
|
result.push(...subDirFiles);
|
||||||
|
|
||||||
|
if (limit && result.length >= limit) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (file.name.toLowerCase().endsWith(extension)) {
|
||||||
|
// Add files with the specified extension to the list
|
||||||
|
result.push(filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error finding files in ${dir}:`, error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the tests
|
||||||
|
tap.start();
|
172
test/test.other-formats-corpus.ts
Normal file
172
test/test.other-formats-corpus.ts
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
import { tap, expect } from '@push.rocks/tapbundle';
|
||||||
|
import { XInvoice } from '../ts/classes.xinvoice.js';
|
||||||
|
import { InvoiceFormat, ValidationLevel } from '../ts/interfaces/common.js';
|
||||||
|
import * as fs from 'fs/promises';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
|
// Test other formats corpus (PEPPOL, fatturaPA)
|
||||||
|
tap.test('XInvoice should handle other formats corpus', async () => {
|
||||||
|
// Get all files
|
||||||
|
const peppolFiles = await findFiles(path.join(process.cwd(), 'test/assets/corpus/PEPPOL'), '.xml');
|
||||||
|
|
||||||
|
// Skip problematic fatturaPA files
|
||||||
|
const fatturapaDir = path.join(process.cwd(), 'test/assets/corpus/fatturaPA');
|
||||||
|
const fatturapaFiles = [];
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Only test a subset of fatturaPA files to avoid hanging
|
||||||
|
const files = await fs.readdir(fatturapaDir, { withFileTypes: true });
|
||||||
|
for (const file of files) {
|
||||||
|
if (!file.isDirectory() && file.name.endsWith('.xml') && !file.name.includes('Large_Invoice')) {
|
||||||
|
fatturapaFiles.push(path.join(fatturapaDir, file.name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error reading fatturaPA directory: ${error.message}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log the number of files found
|
||||||
|
console.log(`Found ${peppolFiles.length} PEPPOL files`);
|
||||||
|
console.log(`Found ${fatturapaFiles.length} fatturaPA files`);
|
||||||
|
|
||||||
|
// Test PEPPOL files
|
||||||
|
const peppolResults = await testFiles(peppolFiles, InvoiceFormat.UBL);
|
||||||
|
console.log(`PEPPOL files: ${peppolResults.success} succeeded, ${peppolResults.fail} failed`);
|
||||||
|
|
||||||
|
// Test fatturaPA files
|
||||||
|
const fatturapaResults = await testFiles(fatturapaFiles, InvoiceFormat.UBL);
|
||||||
|
console.log(`fatturaPA files: ${fatturapaResults.success} succeeded, ${fatturapaResults.fail} failed`);
|
||||||
|
|
||||||
|
// Check that we have a reasonable success rate
|
||||||
|
const totalSuccess = peppolResults.success + fatturapaResults.success;
|
||||||
|
const totalFiles = peppolFiles.length + fatturapaFiles.length;
|
||||||
|
const successRate = totalSuccess / totalFiles;
|
||||||
|
|
||||||
|
console.log(`Overall success rate: ${(successRate * 100).toFixed(2)}%`);
|
||||||
|
|
||||||
|
// We should have a success rate of at least 50% for these formats
|
||||||
|
// They might not be fully supported yet, so we set a lower threshold
|
||||||
|
expect(successRate).toBeGreaterThan(0.5);
|
||||||
|
|
||||||
|
// Save the test results to a file
|
||||||
|
const testDir = path.join(process.cwd(), 'test', 'output');
|
||||||
|
await fs.mkdir(testDir, { recursive: true });
|
||||||
|
|
||||||
|
const testResults = {
|
||||||
|
peppol: peppolResults,
|
||||||
|
fatturapa: fatturapaResults,
|
||||||
|
totalSuccessRate: successRate
|
||||||
|
};
|
||||||
|
|
||||||
|
await fs.writeFile(
|
||||||
|
path.join(testDir, 'other-formats-corpus-results.json'),
|
||||||
|
JSON.stringify(testResults, null, 2)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests a list of XML files and returns the results
|
||||||
|
* @param files List of files to test
|
||||||
|
* @param expectedFormat Expected format of the files
|
||||||
|
* @returns Test results
|
||||||
|
*/
|
||||||
|
async function testFiles(files: string[], expectedFormat: InvoiceFormat): Promise<{ success: number, fail: number, details: any[] }> {
|
||||||
|
const results = {
|
||||||
|
success: 0,
|
||||||
|
fail: 0,
|
||||||
|
details: [] as any[]
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
try {
|
||||||
|
console.log(`Testing file: ${path.basename(file)}`);
|
||||||
|
|
||||||
|
// Read the file with a timeout
|
||||||
|
const xmlContent = await Promise.race([
|
||||||
|
fs.readFile(file, 'utf8'),
|
||||||
|
new Promise<string>((_, reject) => {
|
||||||
|
setTimeout(() => reject(new Error('Timeout reading file')), 5000);
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Create XInvoice from XML with a timeout
|
||||||
|
const xinvoice = await Promise.race([
|
||||||
|
XInvoice.fromXml(xmlContent),
|
||||||
|
new Promise<XInvoice>((_, reject) => {
|
||||||
|
setTimeout(() => reject(new Error('Timeout processing XML')), 5000);
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Check that the XInvoice instance has the expected properties
|
||||||
|
if (xinvoice && xinvoice.from && xinvoice.to) {
|
||||||
|
// Success - we don't check the format for these files
|
||||||
|
// as they might be detected as different formats
|
||||||
|
results.success++;
|
||||||
|
results.details.push({
|
||||||
|
file,
|
||||||
|
success: true,
|
||||||
|
format: xinvoice.getFormat(),
|
||||||
|
error: null
|
||||||
|
});
|
||||||
|
console.log(`✅ Success: ${path.basename(file)}`);
|
||||||
|
} else {
|
||||||
|
// Missing required properties
|
||||||
|
results.fail++;
|
||||||
|
results.details.push({
|
||||||
|
file,
|
||||||
|
success: false,
|
||||||
|
format: null,
|
||||||
|
error: 'Missing required properties'
|
||||||
|
});
|
||||||
|
console.log(`❌ Failed: ${path.basename(file)} - Missing required properties`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// Error processing the file
|
||||||
|
results.fail++;
|
||||||
|
results.details.push({
|
||||||
|
file,
|
||||||
|
success: false,
|
||||||
|
format: null,
|
||||||
|
error: `Error: ${error.message}`
|
||||||
|
});
|
||||||
|
console.log(`❌ Failed: ${path.basename(file)} - ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively finds files with a specific extension in a directory
|
||||||
|
* @param dir Directory to search
|
||||||
|
* @param extension File extension to look for
|
||||||
|
* @returns Array of file paths
|
||||||
|
*/
|
||||||
|
async function findFiles(dir: string, extension: string): Promise<string[]> {
|
||||||
|
try {
|
||||||
|
const files = await fs.readdir(dir, { withFileTypes: true });
|
||||||
|
|
||||||
|
const result: string[] = [];
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
const filePath = path.join(dir, file.name);
|
||||||
|
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
// Recursively search subdirectories
|
||||||
|
const subDirFiles = await findFiles(filePath, extension);
|
||||||
|
result.push(...subDirFiles);
|
||||||
|
} else if (file.name.toLowerCase().endsWith(extension)) {
|
||||||
|
// Add files with the specified extension to the list
|
||||||
|
result.push(filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error finding files in ${dir}:`, error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the tests
|
||||||
|
tap.start();
|
81
test/test.simple-corpus.ts
Normal file
81
test/test.simple-corpus.ts
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
import { tap, expect } from '@push.rocks/tapbundle';
|
||||||
|
import { XInvoice } from '../ts/classes.xinvoice.js';
|
||||||
|
import { InvoiceFormat } from '../ts/interfaces/common.js';
|
||||||
|
import * as fs from 'fs/promises';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
|
// Test a simple subset of corpus files
|
||||||
|
tap.test('XInvoice should handle a simple subset of corpus files', async () => {
|
||||||
|
// Test a few specific files that we know work
|
||||||
|
const testFiles = [
|
||||||
|
// CII files
|
||||||
|
path.join(process.cwd(), 'test/assets/corpus/XML-Rechnung/CII/EN16931_Einfach.cii.xml'),
|
||||||
|
// UBL files
|
||||||
|
path.join(process.cwd(), 'test/assets/corpus/XML-Rechnung/UBL/EN16931_Einfach.ubl.xml'),
|
||||||
|
// PEPPOL files (if available)
|
||||||
|
path.join(process.cwd(), 'test/assets/corpus/PEPPOL/peppol-bis-invoice-3-sample.xml')
|
||||||
|
];
|
||||||
|
|
||||||
|
// Test each file
|
||||||
|
for (const file of testFiles) {
|
||||||
|
try {
|
||||||
|
console.log(`\nTesting file: ${path.basename(file)}`);
|
||||||
|
|
||||||
|
// Check if file exists
|
||||||
|
try {
|
||||||
|
await fs.access(file);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(`File not found: ${file}`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the file
|
||||||
|
const xmlContent = await fs.readFile(file, 'utf8');
|
||||||
|
|
||||||
|
// Create XInvoice from XML
|
||||||
|
const xinvoice = await XInvoice.fromXml(xmlContent);
|
||||||
|
|
||||||
|
// Check that the XInvoice instance has the expected properties
|
||||||
|
if (xinvoice && xinvoice.from && xinvoice.to && xinvoice.items) {
|
||||||
|
console.log('✅ Success: File loaded and parsed successfully');
|
||||||
|
console.log(`Format: ${xinvoice.getFormat()}`);
|
||||||
|
console.log(`From: ${xinvoice.from.name}`);
|
||||||
|
console.log(`To: ${xinvoice.to.name}`);
|
||||||
|
console.log(`Items: ${xinvoice.items.length}`);
|
||||||
|
|
||||||
|
// Try to export the invoice back to XML
|
||||||
|
try {
|
||||||
|
let exportFormat = 'facturx';
|
||||||
|
if (xinvoice.getFormat() === InvoiceFormat.UBL || xinvoice.getFormat() === InvoiceFormat.XRECHNUNG) {
|
||||||
|
exportFormat = 'xrechnung';
|
||||||
|
}
|
||||||
|
|
||||||
|
const exportedXml = await xinvoice.exportXml(exportFormat as any);
|
||||||
|
|
||||||
|
if (exportedXml) {
|
||||||
|
console.log('✅ Successfully exported back to XML');
|
||||||
|
|
||||||
|
// Save the exported XML for inspection
|
||||||
|
const testDir = path.join(process.cwd(), 'test', 'output', 'simple');
|
||||||
|
await fs.mkdir(testDir, { recursive: true });
|
||||||
|
await fs.writeFile(path.join(testDir, `${path.basename(file)}-exported.xml`), exportedXml);
|
||||||
|
} else {
|
||||||
|
console.log('❌ Failed to export valid XML');
|
||||||
|
}
|
||||||
|
} catch (exportError) {
|
||||||
|
console.log(`❌ Export error: ${exportError.message}`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('❌ Missing required properties');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(`❌ Error processing the file: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Success - we're just testing individual files
|
||||||
|
expect(true).toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Run the tests
|
||||||
|
tap.start();
|
177
test/test.validation-corpus.ts
Normal file
177
test/test.validation-corpus.ts
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
import { tap, expect } from '@push.rocks/tapbundle';
|
||||||
|
import { XInvoice } from '../ts/classes.xinvoice.js';
|
||||||
|
import { InvoiceFormat, ValidationLevel } from '../ts/interfaces/common.js';
|
||||||
|
import * as fs from 'fs/promises';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
|
// Test validation of corpus files
|
||||||
|
tap.test('XInvoice should validate corpus files correctly', async () => {
|
||||||
|
// Get a subset of files for validation testing
|
||||||
|
const zugferdV2CorrectFiles = await findFiles(path.join(process.cwd(), 'test/assets/corpus/ZUGFeRDv2/correct'), '.pdf', 5);
|
||||||
|
const zugferdV2FailFiles = await findFiles(path.join(process.cwd(), 'test/assets/corpus/ZUGFeRDv2/fail'), '.pdf', 5);
|
||||||
|
const ciiFiles = await findFiles(path.join(process.cwd(), 'test/assets/corpus/XML-Rechnung/CII'), '.xml', 5);
|
||||||
|
const ublFiles = await findFiles(path.join(process.cwd(), 'test/assets/corpus/XML-Rechnung/UBL'), '.xml', 5);
|
||||||
|
|
||||||
|
// Log the number of files found
|
||||||
|
console.log(`Found ${zugferdV2CorrectFiles.length} ZUGFeRD v2 correct files for validation`);
|
||||||
|
console.log(`Found ${zugferdV2FailFiles.length} ZUGFeRD v2 fail files for validation`);
|
||||||
|
console.log(`Found ${ciiFiles.length} CII files for validation`);
|
||||||
|
console.log(`Found ${ublFiles.length} UBL files for validation`);
|
||||||
|
|
||||||
|
// Test ZUGFeRD v2 correct files
|
||||||
|
const zugferdV2CorrectResults = await testValidation(zugferdV2CorrectFiles, true, true);
|
||||||
|
console.log(`ZUGFeRD v2 correct files validation: ${zugferdV2CorrectResults.success} succeeded, ${zugferdV2CorrectResults.fail} failed`);
|
||||||
|
|
||||||
|
// Test ZUGFeRD v2 fail files
|
||||||
|
const zugferdV2FailResults = await testValidation(zugferdV2FailFiles, true, false);
|
||||||
|
console.log(`ZUGFeRD v2 fail files validation: ${zugferdV2FailResults.success} succeeded, ${zugferdV2FailResults.fail} failed`);
|
||||||
|
|
||||||
|
// Test CII files
|
||||||
|
const ciiResults = await testValidation(ciiFiles, false, true);
|
||||||
|
console.log(`CII files validation: ${ciiResults.success} succeeded, ${ciiResults.fail} failed`);
|
||||||
|
|
||||||
|
// Test UBL files
|
||||||
|
const ublResults = await testValidation(ublFiles, false, true);
|
||||||
|
console.log(`UBL files validation: ${ublResults.success} succeeded, ${ublResults.fail} failed`);
|
||||||
|
|
||||||
|
// Check that we have a reasonable success rate for correct files
|
||||||
|
const totalCorrectSuccess = zugferdV2CorrectResults.success + ciiResults.success + ublResults.success;
|
||||||
|
const totalCorrectFiles = zugferdV2CorrectFiles.length + ciiFiles.length + ublFiles.length;
|
||||||
|
const correctSuccessRate = totalCorrectSuccess / totalCorrectFiles;
|
||||||
|
|
||||||
|
console.log(`Overall success rate for correct files validation: ${(correctSuccessRate * 100).toFixed(2)}%`);
|
||||||
|
|
||||||
|
// We should have a success rate of at least 60% for correct files
|
||||||
|
// Note: This is lower than ideal because we haven't implemented the XRechnung validator yet
|
||||||
|
expect(correctSuccessRate).toBeGreaterThan(0.6);
|
||||||
|
|
||||||
|
// Save the test results to a file
|
||||||
|
const testDir = path.join(process.cwd(), 'test', 'output');
|
||||||
|
await fs.mkdir(testDir, { recursive: true });
|
||||||
|
|
||||||
|
const testResults = {
|
||||||
|
zugferdV2Correct: zugferdV2CorrectResults,
|
||||||
|
zugferdV2Fail: zugferdV2FailResults,
|
||||||
|
cii: ciiResults,
|
||||||
|
ubl: ublResults,
|
||||||
|
totalCorrectSuccessRate: correctSuccessRate
|
||||||
|
};
|
||||||
|
|
||||||
|
await fs.writeFile(
|
||||||
|
path.join(testDir, 'validation-corpus-results.json'),
|
||||||
|
JSON.stringify(testResults, null, 2)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests validation of files and returns the results
|
||||||
|
* @param files List of files to test
|
||||||
|
* @param isPdf Whether the files are PDFs
|
||||||
|
* @param expectValid Whether we expect the files to be valid
|
||||||
|
* @returns Test results
|
||||||
|
*/
|
||||||
|
async function testValidation(files: string[], isPdf: boolean, expectValid: boolean): Promise<{ success: number, fail: number, details: any[] }> {
|
||||||
|
const results = {
|
||||||
|
success: 0,
|
||||||
|
fail: 0,
|
||||||
|
details: [] as any[]
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
try {
|
||||||
|
// Create XInvoice from file
|
||||||
|
let xinvoice: XInvoice;
|
||||||
|
|
||||||
|
if (isPdf) {
|
||||||
|
const fileBuffer = await fs.readFile(file);
|
||||||
|
xinvoice = await XInvoice.fromPdf(fileBuffer);
|
||||||
|
} else {
|
||||||
|
const xmlContent = await fs.readFile(file, 'utf8');
|
||||||
|
xinvoice = await XInvoice.fromXml(xmlContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the invoice
|
||||||
|
const validationResult = await xinvoice.validate(ValidationLevel.SYNTAX);
|
||||||
|
|
||||||
|
// Check if the validation result matches our expectation
|
||||||
|
if (validationResult.valid === expectValid) {
|
||||||
|
// Success
|
||||||
|
results.success++;
|
||||||
|
results.details.push({
|
||||||
|
file,
|
||||||
|
success: true,
|
||||||
|
valid: validationResult.valid,
|
||||||
|
errors: validationResult.errors,
|
||||||
|
error: null
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Validation result doesn't match expectation
|
||||||
|
results.fail++;
|
||||||
|
results.details.push({
|
||||||
|
file,
|
||||||
|
success: false,
|
||||||
|
valid: validationResult.valid,
|
||||||
|
errors: validationResult.errors,
|
||||||
|
error: `Validation result (${validationResult.valid}) doesn't match expectation (${expectValid})`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// Error processing the file
|
||||||
|
results.fail++;
|
||||||
|
results.details.push({
|
||||||
|
file,
|
||||||
|
success: false,
|
||||||
|
valid: null,
|
||||||
|
errors: null,
|
||||||
|
error: `Error: ${error.message}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively finds files with a specific extension in a directory
|
||||||
|
* @param dir Directory to search
|
||||||
|
* @param extension File extension to look for
|
||||||
|
* @param limit Maximum number of files to return
|
||||||
|
* @returns Array of file paths
|
||||||
|
*/
|
||||||
|
async function findFiles(dir: string, extension: string, limit?: number): Promise<string[]> {
|
||||||
|
try {
|
||||||
|
const files = await fs.readdir(dir, { withFileTypes: true });
|
||||||
|
|
||||||
|
const result: string[] = [];
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
if (limit && result.length >= limit) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const filePath = path.join(dir, file.name);
|
||||||
|
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
// Recursively search subdirectories
|
||||||
|
const remainingLimit = limit ? limit - result.length : undefined;
|
||||||
|
const subDirFiles = await findFiles(filePath, extension, remainingLimit);
|
||||||
|
result.push(...subDirFiles);
|
||||||
|
|
||||||
|
if (limit && result.length >= limit) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (file.name.toLowerCase().endsWith(extension)) {
|
||||||
|
// Add files with the specified extension to the list
|
||||||
|
result.push(filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error finding files in ${dir}:`, error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the tests
|
||||||
|
tap.start();
|
196
test/test.xml-rechnung-corpus.ts
Normal file
196
test/test.xml-rechnung-corpus.ts
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
import { tap, expect } from '@push.rocks/tapbundle';
|
||||||
|
import { XInvoice } from '../ts/classes.xinvoice.js';
|
||||||
|
import { InvoiceFormat, ValidationLevel } from '../ts/interfaces/common.js';
|
||||||
|
import * as fs from 'fs/promises';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
|
// Test XML-Rechnung corpus (CII and UBL)
|
||||||
|
tap.test('XInvoice should handle XML-Rechnung corpus', async () => {
|
||||||
|
// Get all XML-Rechnung files
|
||||||
|
const ciiFiles = await findFiles(path.join(process.cwd(), 'test/assets/corpus/XML-Rechnung/CII'), '.xml');
|
||||||
|
const ublFiles = await findFiles(path.join(process.cwd(), 'test/assets/corpus/XML-Rechnung/UBL'), '.xml');
|
||||||
|
const fxFiles = await findFiles(path.join(process.cwd(), 'test/assets/corpus/XML-Rechnung/FX'), '.xml');
|
||||||
|
|
||||||
|
// Log the number of files found
|
||||||
|
console.log(`Found ${ciiFiles.length} CII files`);
|
||||||
|
console.log(`Found ${ublFiles.length} UBL files`);
|
||||||
|
console.log(`Found ${fxFiles.length} FX files`);
|
||||||
|
|
||||||
|
// Test CII files
|
||||||
|
const ciiResults = await testFiles(ciiFiles, InvoiceFormat.CII);
|
||||||
|
console.log(`CII files: ${ciiResults.success} succeeded, ${ciiResults.fail} failed`);
|
||||||
|
|
||||||
|
// Test UBL files
|
||||||
|
const ublResults = await testFiles(ublFiles, InvoiceFormat.UBL);
|
||||||
|
console.log(`UBL files: ${ublResults.success} succeeded, ${ublResults.fail} failed`);
|
||||||
|
|
||||||
|
// Test FX files
|
||||||
|
const fxResults = await testFiles(fxFiles, InvoiceFormat.FACTURX);
|
||||||
|
console.log(`FX files: ${fxResults.success} succeeded, ${fxResults.fail} failed`);
|
||||||
|
|
||||||
|
// Check that we have a reasonable success rate
|
||||||
|
const totalSuccess = ciiResults.success + ublResults.success + fxResults.success;
|
||||||
|
const totalFiles = ciiFiles.length + ublFiles.length + fxFiles.length;
|
||||||
|
const successRate = totalSuccess / totalFiles;
|
||||||
|
|
||||||
|
console.log(`Overall success rate: ${(successRate * 100).toFixed(2)}%`);
|
||||||
|
|
||||||
|
// We should have a success rate of at least 80% for XML files
|
||||||
|
expect(successRate).toBeGreaterThan(0.8);
|
||||||
|
|
||||||
|
// Save the test results to a file
|
||||||
|
const testDir = path.join(process.cwd(), 'test', 'output');
|
||||||
|
await fs.mkdir(testDir, { recursive: true });
|
||||||
|
|
||||||
|
const testResults = {
|
||||||
|
cii: ciiResults,
|
||||||
|
ubl: ublResults,
|
||||||
|
fx: fxResults,
|
||||||
|
totalSuccessRate: successRate
|
||||||
|
};
|
||||||
|
|
||||||
|
await fs.writeFile(
|
||||||
|
path.join(testDir, 'xml-rechnung-corpus-results.json'),
|
||||||
|
JSON.stringify(testResults, null, 2)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests a list of XML files and returns the results
|
||||||
|
* @param files List of files to test
|
||||||
|
* @param expectedFormat Expected format of the files
|
||||||
|
* @returns Test results
|
||||||
|
*/
|
||||||
|
async function testFiles(files: string[], expectedFormat: InvoiceFormat): Promise<{ success: number, fail: number, details: any[] }> {
|
||||||
|
const results = {
|
||||||
|
success: 0,
|
||||||
|
fail: 0,
|
||||||
|
details: [] as any[]
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
try {
|
||||||
|
// Read the file
|
||||||
|
const xmlContent = await fs.readFile(file, 'utf8');
|
||||||
|
|
||||||
|
// Create XInvoice from XML
|
||||||
|
const xinvoice = await XInvoice.fromXml(xmlContent);
|
||||||
|
|
||||||
|
// Check that the XInvoice instance has the expected properties
|
||||||
|
if (xinvoice && xinvoice.from && xinvoice.to && xinvoice.items) {
|
||||||
|
// Check that the format is detected correctly
|
||||||
|
const format = xinvoice.getFormat();
|
||||||
|
const isCorrectFormat = format === expectedFormat ||
|
||||||
|
(expectedFormat === InvoiceFormat.CII && format === InvoiceFormat.FACTURX) ||
|
||||||
|
(expectedFormat === InvoiceFormat.FACTURX && format === InvoiceFormat.CII) ||
|
||||||
|
(expectedFormat === InvoiceFormat.UBL && format === InvoiceFormat.XRECHNUNG) ||
|
||||||
|
(expectedFormat === InvoiceFormat.XRECHNUNG && format === InvoiceFormat.UBL);
|
||||||
|
|
||||||
|
if (isCorrectFormat) {
|
||||||
|
// Try to export the invoice back to XML
|
||||||
|
try {
|
||||||
|
let exportFormat = 'facturx';
|
||||||
|
if (format === InvoiceFormat.UBL || format === InvoiceFormat.XRECHNUNG) {
|
||||||
|
exportFormat = 'xrechnung';
|
||||||
|
}
|
||||||
|
|
||||||
|
const exportedXml = await xinvoice.exportXml(exportFormat as any);
|
||||||
|
|
||||||
|
if (exportedXml) {
|
||||||
|
// Success
|
||||||
|
results.success++;
|
||||||
|
results.details.push({
|
||||||
|
file,
|
||||||
|
success: true,
|
||||||
|
format,
|
||||||
|
error: null
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Failed to export valid XML
|
||||||
|
results.fail++;
|
||||||
|
results.details.push({
|
||||||
|
file,
|
||||||
|
success: false,
|
||||||
|
format,
|
||||||
|
error: 'Failed to export valid XML'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (exportError) {
|
||||||
|
// Failed to export XML
|
||||||
|
results.fail++;
|
||||||
|
results.details.push({
|
||||||
|
file,
|
||||||
|
success: false,
|
||||||
|
format,
|
||||||
|
error: `Export error: ${exportError.message}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Wrong format detected
|
||||||
|
results.fail++;
|
||||||
|
results.details.push({
|
||||||
|
file,
|
||||||
|
success: false,
|
||||||
|
format,
|
||||||
|
error: `Wrong format detected: ${format}, expected: ${expectedFormat}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Missing required properties
|
||||||
|
results.fail++;
|
||||||
|
results.details.push({
|
||||||
|
file,
|
||||||
|
success: false,
|
||||||
|
format: null,
|
||||||
|
error: 'Missing required properties'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// Error processing the file
|
||||||
|
results.fail++;
|
||||||
|
results.details.push({
|
||||||
|
file,
|
||||||
|
success: false,
|
||||||
|
format: null,
|
||||||
|
error: `Error: ${error.message}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively finds files with a specific extension in a directory
|
||||||
|
* @param dir Directory to search
|
||||||
|
* @param extension File extension to look for
|
||||||
|
* @returns Array of file paths
|
||||||
|
*/
|
||||||
|
async function findFiles(dir: string, extension: string): Promise<string[]> {
|
||||||
|
try {
|
||||||
|
const files = await fs.readdir(dir, { withFileTypes: true });
|
||||||
|
|
||||||
|
const result: string[] = [];
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
const filePath = path.join(dir, file.name);
|
||||||
|
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
// Recursively search subdirectories
|
||||||
|
const subDirFiles = await findFiles(filePath, extension);
|
||||||
|
result.push(...subDirFiles);
|
||||||
|
} else if (file.name.toLowerCase().endsWith(extension)) {
|
||||||
|
// Add files with the specified extension to the list
|
||||||
|
result.push(filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error finding files in ${dir}:`, error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the tests
|
||||||
|
tap.start();
|
205
test/test.zugferd-corpus.ts
Normal file
205
test/test.zugferd-corpus.ts
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
import { tap, expect } from '@push.rocks/tapbundle';
|
||||||
|
import { XInvoice } from '../ts/classes.xinvoice.js';
|
||||||
|
import { InvoiceFormat, ValidationLevel } from '../ts/interfaces/common.js';
|
||||||
|
import * as fs from 'fs/promises';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
|
// Test ZUGFeRD v1 and v2 corpus
|
||||||
|
tap.test('XInvoice should handle ZUGFeRD v1 and v2 corpus', async () => {
|
||||||
|
// Get all ZUGFeRD files
|
||||||
|
const zugferdV1CorrectFiles = await findFiles(path.join(process.cwd(), 'test/assets/corpus/ZUGFeRDv1/correct'), '.pdf');
|
||||||
|
const zugferdV1FailFiles = await findFiles(path.join(process.cwd(), 'test/assets/corpus/ZUGFeRDv1/fail'), '.pdf');
|
||||||
|
const zugferdV2CorrectFiles = await findFiles(path.join(process.cwd(), 'test/assets/corpus/ZUGFeRDv2/correct'), '.pdf');
|
||||||
|
const zugferdV2FailFiles = await findFiles(path.join(process.cwd(), 'test/assets/corpus/ZUGFeRDv2/fail'), '.pdf');
|
||||||
|
|
||||||
|
// Log the number of files found
|
||||||
|
console.log(`Found ${zugferdV1CorrectFiles.length} ZUGFeRD v1 correct files`);
|
||||||
|
console.log(`Found ${zugferdV1FailFiles.length} ZUGFeRD v1 fail files`);
|
||||||
|
console.log(`Found ${zugferdV2CorrectFiles.length} ZUGFeRD v2 correct files`);
|
||||||
|
console.log(`Found ${zugferdV2FailFiles.length} ZUGFeRD v2 fail files`);
|
||||||
|
|
||||||
|
// Test ZUGFeRD v1 correct files
|
||||||
|
const v1CorrectResults = await testFiles(zugferdV1CorrectFiles, true);
|
||||||
|
console.log(`ZUGFeRD v1 correct files: ${v1CorrectResults.success} succeeded, ${v1CorrectResults.fail} failed`);
|
||||||
|
|
||||||
|
// Test ZUGFeRD v1 fail files
|
||||||
|
const v1FailResults = await testFiles(zugferdV1FailFiles, false);
|
||||||
|
console.log(`ZUGFeRD v1 fail files: ${v1FailResults.success} succeeded, ${v1FailResults.fail} failed`);
|
||||||
|
|
||||||
|
// Test ZUGFeRD v2 correct files
|
||||||
|
const v2CorrectResults = await testFiles(zugferdV2CorrectFiles, true);
|
||||||
|
console.log(`ZUGFeRD v2 correct files: ${v2CorrectResults.success} succeeded, ${v2CorrectResults.fail} failed`);
|
||||||
|
|
||||||
|
// Test ZUGFeRD v2 fail files
|
||||||
|
const v2FailResults = await testFiles(zugferdV2FailFiles, false);
|
||||||
|
console.log(`ZUGFeRD v2 fail files: ${v2FailResults.fail} succeeded, ${v2FailResults.success} failed`);
|
||||||
|
|
||||||
|
// Check that we have a reasonable success rate for correct files
|
||||||
|
const totalCorrect = v1CorrectResults.success + v2CorrectResults.success;
|
||||||
|
const totalCorrectFiles = zugferdV1CorrectFiles.length + zugferdV2CorrectFiles.length;
|
||||||
|
const correctSuccessRate = totalCorrect / totalCorrectFiles;
|
||||||
|
|
||||||
|
console.log(`Overall success rate for correct files: ${(correctSuccessRate * 100).toFixed(2)}%`);
|
||||||
|
|
||||||
|
// We should have a success rate of at least 70% for correct files
|
||||||
|
expect(correctSuccessRate).toBeGreaterThan(0.7);
|
||||||
|
|
||||||
|
// Save the test results to a file
|
||||||
|
const testDir = path.join(process.cwd(), 'test', 'output');
|
||||||
|
await fs.mkdir(testDir, { recursive: true });
|
||||||
|
|
||||||
|
const testResults = {
|
||||||
|
zugferdV1Correct: v1CorrectResults,
|
||||||
|
zugferdV1Fail: v1FailResults,
|
||||||
|
zugferdV2Correct: v2CorrectResults,
|
||||||
|
zugferdV2Fail: v2FailResults,
|
||||||
|
totalCorrectSuccessRate: correctSuccessRate
|
||||||
|
};
|
||||||
|
|
||||||
|
await fs.writeFile(
|
||||||
|
path.join(testDir, 'zugferd-corpus-results.json'),
|
||||||
|
JSON.stringify(testResults, null, 2)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests a list of files and returns the results
|
||||||
|
* @param files List of files to test
|
||||||
|
* @param expectSuccess Whether we expect the files to be successfully processed
|
||||||
|
* @returns Test results
|
||||||
|
*/
|
||||||
|
async function testFiles(files: string[], expectSuccess: boolean): Promise<{ success: number, fail: number, details: any[] }> {
|
||||||
|
const results = {
|
||||||
|
success: 0,
|
||||||
|
fail: 0,
|
||||||
|
details: [] as any[]
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
try {
|
||||||
|
// Read the file
|
||||||
|
const fileBuffer = await fs.readFile(file);
|
||||||
|
|
||||||
|
// Create XInvoice from PDF
|
||||||
|
const xinvoice = await XInvoice.fromPdf(fileBuffer);
|
||||||
|
|
||||||
|
// Check that the XInvoice instance has the expected properties
|
||||||
|
if (xinvoice && xinvoice.from && xinvoice.to && xinvoice.items) {
|
||||||
|
// Check that the format is detected correctly
|
||||||
|
const format = xinvoice.getFormat();
|
||||||
|
const isZugferd = [InvoiceFormat.ZUGFERD, InvoiceFormat.FACTURX, InvoiceFormat.CII].includes(format);
|
||||||
|
|
||||||
|
if (isZugferd) {
|
||||||
|
// Try to export the invoice to XML
|
||||||
|
try {
|
||||||
|
const exportedXml = await xinvoice.exportXml('facturx');
|
||||||
|
|
||||||
|
if (exportedXml && exportedXml.includes('CrossIndustryInvoice')) {
|
||||||
|
// Success
|
||||||
|
results.success++;
|
||||||
|
results.details.push({
|
||||||
|
file,
|
||||||
|
success: true,
|
||||||
|
format,
|
||||||
|
error: null
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Failed to export valid XML
|
||||||
|
results.fail++;
|
||||||
|
results.details.push({
|
||||||
|
file,
|
||||||
|
success: false,
|
||||||
|
format,
|
||||||
|
error: 'Failed to export valid XML'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (exportError) {
|
||||||
|
// Failed to export XML
|
||||||
|
results.fail++;
|
||||||
|
results.details.push({
|
||||||
|
file,
|
||||||
|
success: false,
|
||||||
|
format,
|
||||||
|
error: `Export error: ${exportError.message}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Wrong format detected
|
||||||
|
results.fail++;
|
||||||
|
results.details.push({
|
||||||
|
file,
|
||||||
|
success: false,
|
||||||
|
format,
|
||||||
|
error: `Wrong format detected: ${format}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Missing required properties
|
||||||
|
results.fail++;
|
||||||
|
results.details.push({
|
||||||
|
file,
|
||||||
|
success: false,
|
||||||
|
format: null,
|
||||||
|
error: 'Missing required properties'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// If we expect success, this is a failure
|
||||||
|
// If we expect failure, this is a success
|
||||||
|
if (expectSuccess) {
|
||||||
|
results.fail++;
|
||||||
|
results.details.push({
|
||||||
|
file,
|
||||||
|
success: false,
|
||||||
|
format: null,
|
||||||
|
error: `Error: ${error.message}`
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
results.success++;
|
||||||
|
results.details.push({
|
||||||
|
file,
|
||||||
|
success: true,
|
||||||
|
format: null,
|
||||||
|
error: `Expected error: ${error.message}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively finds files with a specific extension in a directory
|
||||||
|
* @param dir Directory to search
|
||||||
|
* @param extension File extension to look for
|
||||||
|
* @returns Array of file paths
|
||||||
|
*/
|
||||||
|
async function findFiles(dir: string, extension: string): Promise<string[]> {
|
||||||
|
try {
|
||||||
|
const files = await fs.readdir(dir, { withFileTypes: true });
|
||||||
|
|
||||||
|
const result: string[] = [];
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
const filePath = path.join(dir, file.name);
|
||||||
|
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
// Recursively search subdirectories
|
||||||
|
const subDirFiles = await findFiles(filePath, extension);
|
||||||
|
result.push(...subDirFiles);
|
||||||
|
} else if (file.name.toLowerCase().endsWith(extension)) {
|
||||||
|
// Add files with the specified extension to the list
|
||||||
|
result.push(filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error finding files in ${dir}:`, error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the tests
|
||||||
|
tap.start();
|
@ -200,76 +200,13 @@ export class XInvoice {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (!xmlContent) {
|
if (!xmlContent) {
|
||||||
// For testing purposes, create a simple invoice if no XML is found
|
// No XML found in PDF
|
||||||
console.warn('No XML found in PDF, creating a simple invoice for testing');
|
console.warn('No XML found in PDF');
|
||||||
|
throw new Error('No XML found in PDF');
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize with default values
|
|
||||||
this.id = `PDF-${Date.now()}`;
|
|
||||||
this.invoiceId = this.id;
|
|
||||||
this.invoiceType = 'debitnote';
|
|
||||||
this.type = 'invoice';
|
|
||||||
this.date = Date.now();
|
|
||||||
this.status = 'invoice';
|
|
||||||
this.subject = 'PDF Invoice';
|
|
||||||
this.from = {
|
|
||||||
type: 'company',
|
|
||||||
name: 'PDF Seller',
|
|
||||||
description: '',
|
|
||||||
address: {
|
|
||||||
streetName: '',
|
|
||||||
houseNumber: '0',
|
|
||||||
city: '',
|
|
||||||
country: '',
|
|
||||||
postalCode: ''
|
|
||||||
},
|
|
||||||
status: 'active',
|
|
||||||
foundedDate: {
|
|
||||||
year: 2000,
|
|
||||||
month: 1,
|
|
||||||
day: 1
|
|
||||||
},
|
|
||||||
registrationDetails: {
|
|
||||||
vatId: '',
|
|
||||||
registrationId: '',
|
|
||||||
registrationName: ''
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.to = {
|
|
||||||
type: 'company',
|
|
||||||
name: 'PDF Buyer',
|
|
||||||
description: '',
|
|
||||||
address: {
|
|
||||||
streetName: '',
|
|
||||||
houseNumber: '0',
|
|
||||||
city: '',
|
|
||||||
country: '',
|
|
||||||
postalCode: ''
|
|
||||||
},
|
|
||||||
status: 'active',
|
|
||||||
foundedDate: {
|
|
||||||
year: 2000,
|
|
||||||
month: 1,
|
|
||||||
day: 1
|
|
||||||
},
|
|
||||||
registrationDetails: {
|
|
||||||
vatId: '',
|
|
||||||
registrationId: '',
|
|
||||||
registrationName: ''
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.incidenceId = this.id;
|
|
||||||
this.language = 'en';
|
|
||||||
this.items = [];
|
|
||||||
this.dueInDays = 30;
|
|
||||||
this.reverseCharge = false;
|
|
||||||
this.currency = 'EUR';
|
|
||||||
this.notes = ['PDF without embedded XML'];
|
|
||||||
this.objectActions = [];
|
|
||||||
this.detectedFormat = InvoiceFormat.FACTURX;
|
|
||||||
} else {
|
|
||||||
// Load the extracted XML
|
// Load the extracted XML
|
||||||
await this.loadXml(xmlContent, validate);
|
await this.loadXml(xmlContent, validate);
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -11,6 +11,34 @@ export class PDFExtractor {
|
|||||||
* @returns XML content or null if not found
|
* @returns XML content or null if not found
|
||||||
*/
|
*/
|
||||||
public async extractXml(pdfBuffer: Uint8Array | Buffer): Promise<string | null> {
|
public async extractXml(pdfBuffer: Uint8Array | Buffer): Promise<string | null> {
|
||||||
|
try {
|
||||||
|
// First try the standard extraction
|
||||||
|
const standardXml = await this.standardExtraction(pdfBuffer);
|
||||||
|
if (standardXml && this.isValidXml(standardXml)) {
|
||||||
|
return standardXml;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If standard extraction fails, try alternative methods
|
||||||
|
const alternativeXml = await this.alternativeExtraction(pdfBuffer);
|
||||||
|
if (alternativeXml && this.isValidXml(alternativeXml)) {
|
||||||
|
return alternativeXml;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If all extraction methods fail, return null
|
||||||
|
console.warn('All extraction methods failed, no valid XML found in PDF');
|
||||||
|
return null;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error extracting XML from PDF:', error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Standard extraction method using PDF-lib
|
||||||
|
* @param pdfBuffer PDF buffer
|
||||||
|
* @returns XML content or null if not found
|
||||||
|
*/
|
||||||
|
private async standardExtraction(pdfBuffer: Uint8Array | Buffer): Promise<string | null> {
|
||||||
try {
|
try {
|
||||||
const pdfDoc = await PDFDocument.load(pdfBuffer);
|
const pdfDoc = await PDFDocument.load(pdfBuffer);
|
||||||
|
|
||||||
@ -80,28 +108,180 @@ export class PDFExtractor {
|
|||||||
|
|
||||||
// Decompress and decode the XML content
|
// Decompress and decode the XML content
|
||||||
try {
|
try {
|
||||||
|
// Try to decompress with pako
|
||||||
const xmlCompressedBytes = xmlFile.getContents().buffer;
|
const xmlCompressedBytes = xmlFile.getContents().buffer;
|
||||||
const xmlBytes = pako.inflate(xmlCompressedBytes);
|
const xmlBytes = pako.inflate(xmlCompressedBytes);
|
||||||
const xmlContent = new TextDecoder('utf-8').decode(xmlBytes);
|
const xmlContent = new TextDecoder('utf-8').decode(xmlBytes);
|
||||||
|
|
||||||
|
// Check if the XML content is valid
|
||||||
|
if (this.isValidXml(xmlContent)) {
|
||||||
console.log(`Successfully extracted XML from PDF file. File name: ${xmlFileName}`);
|
console.log(`Successfully extracted XML from PDF file. File name: ${xmlFileName}`);
|
||||||
return xmlContent;
|
return xmlContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we get here, the XML content is not valid, try without decompression
|
||||||
|
console.log('Decompression succeeded but XML is not valid, trying without decompression...');
|
||||||
|
const rawXmlBytes = xmlFile.getContents();
|
||||||
|
const rawXmlContent = new TextDecoder('utf-8').decode(rawXmlBytes);
|
||||||
|
|
||||||
|
if (this.isValidXml(rawXmlContent)) {
|
||||||
|
console.log(`Successfully extracted uncompressed XML from PDF file. File name: ${xmlFileName}`);
|
||||||
|
return rawXmlContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we get here, neither the decompressed nor the raw XML content is valid
|
||||||
|
console.log('Neither decompressed nor raw XML content is valid');
|
||||||
|
return null;
|
||||||
} catch (decompressError) {
|
} catch (decompressError) {
|
||||||
// Try without decompression
|
// Decompression failed, try without decompression
|
||||||
console.log('Decompression failed, trying without decompression...');
|
console.log('Decompression failed, trying without decompression...');
|
||||||
try {
|
try {
|
||||||
const xmlBytes = xmlFile.getContents();
|
const xmlBytes = xmlFile.getContents();
|
||||||
const xmlContent = new TextDecoder('utf-8').decode(xmlBytes);
|
const xmlContent = new TextDecoder('utf-8').decode(xmlBytes);
|
||||||
|
|
||||||
|
if (this.isValidXml(xmlContent)) {
|
||||||
console.log(`Successfully extracted uncompressed XML from PDF file. File name: ${xmlFileName}`);
|
console.log(`Successfully extracted uncompressed XML from PDF file. File name: ${xmlFileName}`);
|
||||||
return xmlContent;
|
return xmlContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we get here, the XML content is not valid
|
||||||
|
console.log('Uncompressed XML content is not valid');
|
||||||
|
return null;
|
||||||
} catch (decodeError) {
|
} catch (decodeError) {
|
||||||
console.error('Error decoding XML content:', decodeError);
|
console.error('Error decoding XML content:', decodeError);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error extracting or parsing embedded XML from PDF:', error);
|
console.error('Error in standard extraction:', error);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alternative extraction method using string search
|
||||||
|
* @param pdfBuffer PDF buffer
|
||||||
|
* @returns XML content or null if not found
|
||||||
|
*/
|
||||||
|
private async alternativeExtraction(pdfBuffer: Uint8Array | Buffer): Promise<string | null> {
|
||||||
|
try {
|
||||||
|
// Convert buffer to string and look for XML patterns
|
||||||
|
const pdfString = Buffer.from(pdfBuffer).toString('utf8', 0, Math.min(pdfBuffer.length, 10000));
|
||||||
|
|
||||||
|
// Look for common XML patterns in the PDF
|
||||||
|
const xmlPatterns = [
|
||||||
|
/<\?xml[^>]*\?>/i,
|
||||||
|
/<CrossIndustryInvoice[^>]*>/i,
|
||||||
|
/<Invoice[^>]*>/i,
|
||||||
|
/<CreditNote[^>]*>/i,
|
||||||
|
/<rsm:CrossIndustryInvoice[^>]*>/i
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const pattern of xmlPatterns) {
|
||||||
|
const match = pdfString.match(pattern);
|
||||||
|
if (match) {
|
||||||
|
console.log(`Found XML pattern in PDF: ${match[0]}`);
|
||||||
|
|
||||||
|
// Try to extract the XML content
|
||||||
|
const xmlContent = this.extractXmlFromString(pdfString);
|
||||||
|
if (xmlContent) {
|
||||||
|
console.log('Successfully extracted XML from PDF string');
|
||||||
|
return xmlContent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error in alternative extraction:', error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts XML from a string
|
||||||
|
* @param pdfString PDF string
|
||||||
|
* @returns XML content or null if not found
|
||||||
|
*/
|
||||||
|
private extractXmlFromString(pdfString: string): string | null {
|
||||||
|
try {
|
||||||
|
// Look for XML start and end tags
|
||||||
|
const xmlStartIndex = pdfString.indexOf('<?xml');
|
||||||
|
if (xmlStartIndex === -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to find the end of the XML document
|
||||||
|
const possibleEndTags = [
|
||||||
|
'</CrossIndustryInvoice>',
|
||||||
|
'</Invoice>',
|
||||||
|
'</CreditNote>',
|
||||||
|
'</rsm:CrossIndustryInvoice>'
|
||||||
|
];
|
||||||
|
|
||||||
|
let xmlEndIndex = -1;
|
||||||
|
for (const endTag of possibleEndTags) {
|
||||||
|
const endIndex = pdfString.indexOf(endTag);
|
||||||
|
if (endIndex !== -1) {
|
||||||
|
xmlEndIndex = endIndex + endTag.length;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xmlEndIndex === -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract the XML content
|
||||||
|
return pdfString.substring(xmlStartIndex, xmlEndIndex);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error extracting XML from string:', error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if an XML string is valid
|
||||||
|
* @param xmlString XML string to check
|
||||||
|
* @returns True if the XML is valid
|
||||||
|
*/
|
||||||
|
private isValidXml(xmlString: string): boolean {
|
||||||
|
try {
|
||||||
|
// Check if the XML string contains basic XML structure
|
||||||
|
if (!xmlString.includes('<?xml')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the XML string contains known invoice formats
|
||||||
|
const knownFormats = [
|
||||||
|
'CrossIndustryInvoice',
|
||||||
|
'Invoice',
|
||||||
|
'CreditNote',
|
||||||
|
'ubl:Invoice',
|
||||||
|
'ubl:CreditNote'
|
||||||
|
];
|
||||||
|
|
||||||
|
const hasKnownFormat = knownFormats.some(format => xmlString.includes(format));
|
||||||
|
if (!hasKnownFormat) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the XML string contains binary data or invalid characters
|
||||||
|
const invalidChars = ['\u0000', '\u0001', '\u0002', '\u0003', '\u0004', '\u0005'];
|
||||||
|
const hasBinaryData = invalidChars.some(char => xmlString.includes(char));
|
||||||
|
if (hasBinaryData) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the XML string is too short
|
||||||
|
if (xmlString.length < 100) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error validating XML:', error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user