This commit is contained in:
jstaerk
2025-02-11 13:36:24 +01:00
parent 6f19c3996a
commit e76c522639
6 changed files with 257 additions and 4 deletions

View File

@@ -1,4 +1,6 @@
#558
#686
#739
2.16.2
=======

View File

@@ -129,7 +129,13 @@ public class XMLTools extends XMLWriter {
* @return a util.Date, or null, if not parseable
*/
public static Date tryDate(String toParse) {
final SimpleDateFormat formatter = ZUGFeRDDateFormat.DATE.getFormatter();
SimpleDateFormat formatter = null;
if (toParse.contains("-")) {
// from ubl
formatter = new SimpleDateFormat("yyyy-MM-dd");
} else {
formatter = ZUGFeRDDateFormat.DATE.getFormatter();
}
try {
return formatter.parse(toParse);
} catch (final Exception e) {

View File

@@ -775,6 +775,21 @@ public class ZUGFeRDInvoiceImporter {
}
}
xpr = xpath.compile("/*[local-name()=\"Invoice\"]/*[local-name()=\"InvoicePeriod\"]/*"); //UBL only
NodeList periodNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
for (int periodChildIndex = 0; periodChildIndex < periodNodes.getLength(); periodChildIndex++) {
String localName=periodNodes.item(periodChildIndex).getLocalName();
if ((localName != null) && (periodNodes.item(periodChildIndex).getLocalName().equals("StartDate"))) {
deliveryPeriodStart = XMLTools.trimOrNull(periodNodes.item(periodChildIndex));
}
if ((localName != null) && (periodNodes.item(periodChildIndex).getLocalName().equals("EndDate"))) {
deliveryPeriodEnd = XMLTools.trimOrNull(periodNodes.item(periodChildIndex));
}
}
if ((deliveryPeriodStart != null) && (deliveryPeriodEnd != null)) {
zpp.setDetailedDeliveryPeriod(XMLTools.tryDate(deliveryPeriodStart), XMLTools.tryDate(deliveryPeriodEnd));
} else if (deliveryPeriodStart != null) {

View File

@@ -32,6 +32,7 @@ import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.mustangproject.*;
import org.junit.FixMethodOrder;
import org.junit.runners.MethodSorters;
@@ -254,7 +255,7 @@ public class ZF2PushTest extends TestCase {
// ze.setTransaction(new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()).setSender(new TradeParty(orgname,"teststr", "55232","teststadt","DE")).setOwnTaxID("4711").setOwnVATID("DE0815").setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE")).setNumber(number)
// .addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addAllowance(new Allowance().setPercent(new BigDecimal(50)))));
ze.setTransaction(new Invoice().setDueDate(new Date()).setIssueDate(new Date())
Invoice i=new Invoice().setDueDate(new Date()).setIssueDate(new Date())
.setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID("4711").addVATID("DE0815"))
.setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE")
.setContact(new Contact("contact testname", "123456", "contact.testemail@example.org").setFax("0911623562")))
@@ -263,8 +264,9 @@ public class ZF2PushTest extends TestCase {
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addAllowance(new Allowance(new BigDecimal("0.1"))))
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addAllowance(new Allowance().setPercent(new BigDecimal(50))))
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(2.0)).addCharge(new Charge(new BigDecimal(1)).setReasonCode("ABK").setReason("AnotherReason")))
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addCharge(new Charge(new BigDecimal(1))).addAllowance(new Allowance(new BigDecimal("1"))))
);
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addCharge(new Charge(new BigDecimal(1))).addAllowance(new Allowance(new BigDecimal("1"))));
ze.setTransaction(i);
String theXML = new String(ze.getProvider().getXML());
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
@@ -593,6 +595,9 @@ public class ZF2PushTest extends TestCase {
assertEquals(1, i.getInvoiceReferencedDocuments().size());
assertEquals("abcd1234", i.getInvoiceReferencedDocuments().get(0).getIssuerAssignedID());
assertEquals("4304171000002", i.getRecipient().getGlobalID());
SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMdd");
assertEquals(occurrenceFrom, sdf.format(i.getDetailedDeliveryPeriodFrom()));
assertEquals(occurrenceTo, sdf.format(i.getDetailedDeliveryPeriodTo()));
assertEquals("2001015001325", i.getZFItems()[0].getProduct().getGlobalID());
assertEquals(orgID, i.getSender().getID());
assertEquals("Verwendungszweck", i.getPaymentReference());

View File

@@ -441,6 +441,34 @@ public class ZF2ZInvoiceImporterTest extends ResourceCase {
}
}
public void testImportUBLPeriods() { // Confirm some basics also work with UBL credit notes
File ublinputFile = getResourceAsFile("ubl/periods.ubl.xml");
try {
ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter();
zii.doIgnoreCalculationErrors();
zii.setInputStream(new FileInputStream(ublinputFile));
CalculatedInvoice i = new CalculatedInvoice();
zii.extractInto(i);
assertEquals("123", i.getNumber());
assertEquals("1.48", i.getGrandTotal().toString());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
assertEquals("2020-10-01", sdf.format(i.getDetailedDeliveryPeriodFrom()));
assertEquals("2020-10-05", sdf.format(i.getDetailedDeliveryPeriodTo()));
} catch (IOException e) {
fail("IOException not expected");
} catch (XPathExpressionException e) {
throw new RuntimeException(e);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}

View File

@@ -0,0 +1,197 @@
<?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" xmlns:ccts="urn:un:unece:uncefact:documentation:2" xmlns:qdt="urn:oasis:names:specification:ubl:schema:xsd:QualifiedDataTypes-2" xmlns:udt="urn:oasis:names:specification:ubl:schema:xsd:UnqualifiedDataTypes-2">
<cbc:CustomizationID>urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended</cbc:CustomizationID>
<cbc:ID>123</cbc:ID>
<cbc:IssueDate>2025-02-10</cbc:IssueDate>
<cbc:DueDate>2025-02-10</cbc:DueDate>
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
<cbc:Note>document level 1/2</cbc:Note>
<cbc:Note>document level 2/2</cbc:Note>
<cbc:DocumentCurrencyCode>CHF</cbc:DocumentCurrencyCode>
<cac:InvoicePeriod>
<cbc:StartDate>2020-10-01</cbc:StartDate>
<cbc:EndDate>2020-10-05</cbc:EndDate>
<cbc:DescriptionCode>432</cbc:DescriptionCode>
</cac:InvoicePeriod>
<cac:OrderReference>
<cbc:ID>28934</cbc:ID>
<cbc:SalesOrderID>9384</cbc:SalesOrderID>
</cac:OrderReference>
<cac:BillingReference>
<cac:InvoiceDocumentReference>
<cbc:ID>abc123</cbc:ID>
</cac:InvoiceDocumentReference>
</cac:BillingReference>
<cac:ContractDocumentReference>
<cbc:ID>376zreurzu0983</cbc:ID>
</cac:ContractDocumentReference>
<cac:AccountingSupplierParty>
<cac:Party>
<cbc:EndpointID schemeID="EM">sender@test.org</cbc:EndpointID>
<cac:PartyIdentification>
<cbc:ID>0009845</cbc:ID>
</cac:PartyIdentification>
<cac:PostalAddress>
<cbc:StreetName>teststr</cbc:StreetName>
<cbc:CityName>teststadt</cbc:CityName>
<cbc:PostalZone>55232</cbc:PostalZone>
<cac:Country>
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyTaxScheme>
<cbc:CompanyID>DE0815</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyTaxScheme>
<cbc:CompanyID>9990815</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>NOVAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyLegalEntity>
<cbc:RegistrationName>Test company</cbc:RegistrationName>
</cac:PartyLegalEntity>
</cac:Party>
</cac:AccountingSupplierParty>
<cac:AccountingCustomerParty>
<cac:Party>
<cbc:EndpointID schemeID="EM">recipient@test.org</cbc:EndpointID>
<cac:PartyIdentification>
<cbc:ID>0088:4304171000002</cbc:ID>
</cac:PartyIdentification>
<cac:PostalAddress>
<cbc:StreetName>teststr.12</cbc:StreetName>
<cbc:AdditionalStreetName>Hinterhaus 3</cbc:AdditionalStreetName>
<cbc:CityName>Entenhausen</cbc:CityName>
<cbc:PostalZone>55232</cbc:PostalZone>
<cac:Country>
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyTaxScheme>
<cbc:CompanyID>DE4711</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyLegalEntity>
<cbc:RegistrationName>Franz Müller</cbc:RegistrationName>
</cac:PartyLegalEntity>
<cac:Contact>
<cbc:Telephone>01779999999</cbc:Telephone>
<cbc:ElectronicMail>franz@mueller.de</cbc:ElectronicMail>
</cac:Contact>
</cac:Party>
</cac:AccountingCustomerParty>
<cac:Delivery>
<cbc:ActualDeliveryDate>2020-11-02</cbc:ActualDeliveryDate>
<cac:DeliveryLocation>
<cac:Address>
<cbc:StreetName>teststr.12a</cbc:StreetName>
<cbc:CityName>Entenhausen</cbc:CityName>
<cbc:PostalZone>55232</cbc:PostalZone>
<cac:Country>
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
</cac:Country>
</cac:Address>
</cac:DeliveryLocation>
<cac:DeliveryParty>
<cac:PartyName>
<cbc:Name>just the other side of the street</cbc:Name>
</cac:PartyName>
</cac:DeliveryParty>
</cac:Delivery>
<cac:PaymentMeans>
<cbc:PaymentID>Verwendungszweck</cbc:PaymentID>
</cac:PaymentMeans>
<cac:PaymentTerms>
<cbc:Note>Please remit until 10.02.2025</cbc:Note>
</cac:PaymentTerms>
<cac:AllowanceCharge>
<cbc:ChargeIndicator>false</cbc:ChargeIndicator>
<cbc:AllowanceChargeReason>discount</cbc:AllowanceChargeReason>
<cbc:Amount currencyID="CHF">0.20</cbc:Amount>
<cac:TaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>16.00</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:AllowanceCharge>
<cac:AllowanceCharge>
<cbc:ChargeIndicator>true</cbc:ChargeIndicator>
<cbc:AllowanceChargeReason>quick delivery charge</cbc:AllowanceChargeReason>
<cbc:Amount currencyID="CHF">0.50</cbc:Amount>
<cac:TaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>16.00</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:AllowanceCharge>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="CHF">0.20</cbc:TaxAmount>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="CHF">1.28</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="CHF">0.20</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>16.00</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
</cac:TaxTotal>
<cac:LegalMonetaryTotal>
<cbc:LineExtensionAmount currencyID="CHF">0.98</cbc:LineExtensionAmount>
<cbc:TaxExclusiveAmount currencyID="CHF">1.28</cbc:TaxExclusiveAmount>
<cbc:TaxInclusiveAmount currencyID="CHF">1.48</cbc:TaxInclusiveAmount>
<cbc:AllowanceTotalAmount currencyID="CHF">0.20</cbc:AllowanceTotalAmount>
<cbc:ChargeTotalAmount currencyID="CHF">0.50</cbc:ChargeTotalAmount>
<cbc:PayableAmount currencyID="CHF">1.48</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
<cac:InvoiceLine>
<cbc:ID>a123</cbc:ID>
<cbc:Note>item level 1/1</cbc:Note>
<cbc:InvoicedQuantity unitCode="H87">1.00000000</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="CHF">0.98</cbc:LineExtensionAmount>
<cac:InvoicePeriod>
<cbc:StartDate>2020-01-13</cbc:StartDate>
<cbc:EndDate>2020-01-15</cbc:EndDate>
</cac:InvoicePeriod>
<cac:OrderLineReference>
<cbc:LineID>xxx</cbc:LineID>
</cac:OrderLineReference>
<cac:Item>
<cbc:Name>Testprodukt</cbc:Name>
<cac:SellersItemIdentification>
<cbc:ID>4711</cbc:ID>
</cac:SellersItemIdentification>
<cac:StandardItemIdentification>
<cbc:ID schemeID="0160">2001015001325</cbc:ID>
</cac:StandardItemIdentification>
<cac:ClassifiedTaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>16.00</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="CHF">0.98</cbc:PriceAmount>
<cbc:BaseQuantity unitCode="H87">1.00</cbc:BaseQuantity>
<cac:AllowanceCharge>
<cbc:ChargeIndicator>false</cbc:ChargeIndicator>
<cbc:Amount currencyID="CHF">0.0200</cbc:Amount>
<cbc:BaseAmount currencyID="CHF">1.0000</cbc:BaseAmount>
</cac:AllowanceCharge>
</cac:Price>
</cac:InvoiceLine>
</Invoice>