update ksef workflow
This commit is contained in:
parent
9884a3cd00
commit
ae11393c8c
5 changed files with 228 additions and 11 deletions
|
|
@ -2,6 +2,10 @@ package com.alexanderlogistics.einvoice;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
import java.text.NumberFormat;
|
import java.text.NumberFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
@ -10,6 +14,9 @@ import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
import javax.xml.transform.TransformerException;
|
import javax.xml.transform.TransformerException;
|
||||||
|
|
||||||
import org.imixs.archive.core.SnapshotService;
|
import org.imixs.archive.core.SnapshotService;
|
||||||
|
|
@ -29,11 +36,15 @@ import org.imixs.workflow.exceptions.AdapterException;
|
||||||
import org.imixs.workflow.exceptions.PluginException;
|
import org.imixs.workflow.exceptions.PluginException;
|
||||||
import org.imixs.workflow.exceptions.QueryException;
|
import org.imixs.workflow.exceptions.QueryException;
|
||||||
import org.imixs.workflow.util.XMLParser;
|
import org.imixs.workflow.util.XMLParser;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
|
import org.xml.sax.InputSource;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
import com.alexanderlogistics.BusinessPartnerService;
|
import com.alexanderlogistics.BusinessPartnerService;
|
||||||
import com.alexanderlogistics.InvoiceService;
|
import com.alexanderlogistics.InvoiceService;
|
||||||
import com.alexanderlogistics.InvoiceUtil;
|
import com.alexanderlogistics.InvoiceUtil;
|
||||||
|
import com.alexanderlogistics.xml.CargosoftXMLInvoiceImportService;
|
||||||
|
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
|
|
||||||
|
|
@ -155,13 +166,20 @@ public class KSeFAdapter implements SignalAdapter {
|
||||||
|
|
||||||
// date
|
// date
|
||||||
model.setIssueDateTime(workitem.getItemValueLocalDate("invoice.date"));
|
model.setIssueDateTime(workitem.getItemValueLocalDate("invoice.date"));
|
||||||
model.setDueDateTime(workitem.getItemValueLocalDate("invoice.duedate"));
|
|
||||||
|
// Set Performance Date
|
||||||
|
if (workitem.getItemValueDate("invoice.performancedate") == null) {
|
||||||
|
// hilfs code um das invoice.performancedate nachträglich zu parsen
|
||||||
|
syncPerformanceDate(workitem);
|
||||||
|
}
|
||||||
|
((EInvoiceModelKSeF) model)
|
||||||
|
.setPerformanceDateTime(workitem.getItemValueLocalDate("invoice.performancedate"));
|
||||||
|
|
||||||
// Update Addresses
|
// Update Addresses
|
||||||
TradeParty billingAddress = buildAddress(workitem, "buyer", model);
|
TradeParty billingAddress = buildAddress(workitem, "buyer", model);
|
||||||
model.setTradeParty(billingAddress);
|
model.setTradeParty(billingAddress);
|
||||||
|
|
||||||
// set Tax Type based on vatID
|
// set Tax Type based on vatID - as a result taxType is 1=Poland 2=EU 3=Other
|
||||||
((EInvoiceModelKSeF) model).setTaxType(workitem.getItemValueString("partner.vat"));
|
((EInvoiceModelKSeF) model).setTaxType(workitem.getItemValueString("partner.vat"));
|
||||||
workitem.setItemValue("invoice.tax.type", ((EInvoiceModelKSeF) model).getTaxType());
|
workitem.setItemValue("invoice.tax.type", ((EInvoiceModelKSeF) model).getTaxType());
|
||||||
|
|
||||||
|
|
@ -227,16 +245,56 @@ public class KSeFAdapter implements SignalAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Summenbildung
|
// Summenbildung
|
||||||
|
/*
|
||||||
// Netto
|
* Field mapping:
|
||||||
|
* <ul>
|
||||||
|
* <li>taxType "1" (Poland): P_13_1 (domestic VAT)</li>
|
||||||
|
* <li>taxType "2" (EU): P_13_6_2 (intra-community delivery, 0%)</li>
|
||||||
|
* <li>taxType "3" (Non-EU): P_13_6_3 (export, 0%)</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
model.setNetTotalAmount(workitem.getItemValueDouble("invoice.total.net"));
|
model.setNetTotalAmount(workitem.getItemValueDouble("invoice.total.net"));
|
||||||
|
|
||||||
|
// ?? has no function
|
||||||
|
model.setTaxRate(workitem.getItemValueDouble("invoice.total.tax"));
|
||||||
|
|
||||||
// Tax
|
// Tax
|
||||||
|
/*
|
||||||
|
* P_14_1
|
||||||
|
*
|
||||||
|
* This call also generate P_14_1W bei fremdwährung
|
||||||
|
*/
|
||||||
model.setTaxTotalAmount(InvoiceUtil.round(workitem.getItemValueDouble("invoice.total")
|
model.setTaxTotalAmount(InvoiceUtil.round(workitem.getItemValueDouble("invoice.total")
|
||||||
- workitem.getItemValueDouble("invoice.total.net")));
|
- workitem.getItemValueDouble("invoice.total.net")));
|
||||||
model.setTaxRate(workitem.getItemValueDouble("invoice.total.tax"));
|
/*
|
||||||
|
* If we have Foreign Currency we need to set P_14_1W in case we are tax type 1
|
||||||
|
*/
|
||||||
|
if (!"PLN".equals(workitem.getItemValueString("invoice.currency"))) {
|
||||||
|
if ("1".equals(((EInvoiceModelKSeF) model).getTaxType())) {
|
||||||
|
// compute rate
|
||||||
|
double rate = workitem.getItemValueDouble("invoice.rate");
|
||||||
|
logger.info("│ ├── rate=" + rate);
|
||||||
|
double totalTax = InvoiceUtil.round(workitem.getItemValueDouble("invoice.total.tax"));
|
||||||
|
logger.info("│ ├── total.tax=" + totalTax);
|
||||||
|
BigDecimal value = BigDecimal.valueOf(totalTax)
|
||||||
|
.divide(BigDecimal.valueOf(rate), 10, RoundingMode.HALF_UP);
|
||||||
|
// P_14_1W must come directly after P_14_1
|
||||||
|
logger.info("│ ├── P_14_1W=" + value);
|
||||||
|
Element element = model.findOrCreateChildNodeAfter(elementFa, EInvoiceNS.KSEF, "P_14_1W", "P_14_1");
|
||||||
|
element.setTextContent(value.setScale(2, RoundingMode.HALF_UP).toPlainString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Brutto
|
// Brutto
|
||||||
|
/*
|
||||||
|
* P_15
|
||||||
|
*/
|
||||||
model.setGrandTotalAmount(workitem.getItemValueDouble("invoice.total"));
|
model.setGrandTotalAmount(workitem.getItemValueDouble("invoice.total"));
|
||||||
|
|
||||||
|
// finally set the due date at the end of the XML tree
|
||||||
|
model.setDueDateTime(workitem.getItemValueLocalDate("invoice.duedate"));
|
||||||
|
|
||||||
// finally update the template file
|
// finally update the template file
|
||||||
fileDataXMLTemplate.setContent(model.getContent());
|
fileDataXMLTemplate.setContent(model.getContent());
|
||||||
|
|
||||||
|
|
@ -246,6 +304,42 @@ public class KSeFAdapter implements SignalAdapter {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dies ist eine Hilfsmethode die nachträglich das invoice.performancedate aus
|
||||||
|
* dem Cargosoft XML ausliest
|
||||||
|
*
|
||||||
|
* @param workitem
|
||||||
|
* @throws PluginException
|
||||||
|
*/
|
||||||
|
private void syncPerformanceDate(ItemCollection workitem) throws PluginException {
|
||||||
|
try {
|
||||||
|
logger.info("----Resync cargosoft performancedate....");
|
||||||
|
DocumentBuilder documentBuilder;
|
||||||
|
// hole die XML Datei
|
||||||
|
FileData cargoXML = snapshotService.getWorkItemFile(workitem.getUniqueID(),
|
||||||
|
workitem.getItemValueString("cargosoft.import.filename"));
|
||||||
|
if (cargoXML != null) {
|
||||||
|
InputStream inputStream = new ByteArrayInputStream(cargoXML.getContent());
|
||||||
|
InputSource inputSource = new InputSource(inputStream);
|
||||||
|
|
||||||
|
documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||||
|
Document doc = documentBuilder.parse(inputSource);
|
||||||
|
|
||||||
|
// Performance Date
|
||||||
|
CargosoftXMLInvoiceImportService.readXMLValue(doc, "/Invoices/Invoice/InvoiceHeader/PerformanceDate",
|
||||||
|
workitem, "invoice.performancedate",
|
||||||
|
Date.class);
|
||||||
|
|
||||||
|
// falls keines gefunden wurde nehmen wir das invoice date
|
||||||
|
if (workitem.getItemValueDate("invoice.performancedate") == null) {
|
||||||
|
workitem.setItemValue("invoice.performancedate", workitem.getItemValueDate("invoice.date"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (ParserConfigurationException | SAXException | IOException e) {
|
||||||
|
throw new PluginException(CargosoftXMLInvoiceImportService.class.getName(), "XML_ERROR", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gibt True zurück wenn es eine korrektur rechnung ist
|
* Gibt True zurück wenn es eine korrektur rechnung ist
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -445,6 +445,10 @@ public class CargosoftXMLInvoiceImportService {
|
||||||
readXMLValue(doc, "/Invoices/Invoice/InvoiceHeader/PaymentConditions/DueDate", workitem, "invoice.reminder",
|
readXMLValue(doc, "/Invoices/Invoice/InvoiceHeader/PaymentConditions/DueDate", workitem, "invoice.reminder",
|
||||||
Date.class);
|
Date.class);
|
||||||
|
|
||||||
|
// Performance Date
|
||||||
|
readXMLValue(doc, "/Invoices/Invoice/InvoiceHeader/PerformanceDate", workitem, "invoice.performancedate",
|
||||||
|
Date.class);
|
||||||
|
|
||||||
readXMLValue(doc, "/Invoices/Invoice/InvoiceHeader/InvoiceAddress/Codes/Code", workitem, "dbtr.number",
|
readXMLValue(doc, "/Invoices/Invoice/InvoiceHeader/InvoiceAddress/Codes/Code", workitem, "dbtr.number",
|
||||||
String.class);
|
String.class);
|
||||||
String dbtrNumber = workitem.getItemValueString("dbtr.number");
|
String dbtrNumber = workitem.getItemValueString("dbtr.number");
|
||||||
|
|
@ -522,7 +526,7 @@ public class CargosoftXMLInvoiceImportService {
|
||||||
* @param itemName
|
* @param itemName
|
||||||
* @param itemType
|
* @param itemType
|
||||||
*/
|
*/
|
||||||
private <T> void readXMLValue(Document doc, String expression, ItemCollection workitem, String itemName,
|
public static <T> void readXMLValue(Document doc, String expression, ItemCollection workitem, String itemName,
|
||||||
Class<T> itemType) {
|
Class<T> itemType) {
|
||||||
// create XPath...
|
// create XPath...
|
||||||
XPathFactory xpathFactory = XPathFactory.newInstance();
|
XPathFactory xpathFactory = XPathFactory.newInstance();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Faktura xmlns="http://crd.gov.pl/wzor/2025/06/25/13775/"
|
||||||
|
xmlns:etd="http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2022/01/05/eD/DefinicjeTypy/"
|
||||||
|
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<Naglowek>
|
||||||
|
<KodFormularza kodSystemowy="FA (3)" wersjaSchemy="1-0E">FA</KodFormularza>
|
||||||
|
<WariantFormularza>3</WariantFormularza>
|
||||||
|
<DataWytworzeniaFa>2026-04-16T06:22:32.455873037Z</DataWytworzeniaFa>
|
||||||
|
<SystemInfo>Imixs eInvoice</SystemInfo>
|
||||||
|
</Naglowek>
|
||||||
|
<!-- Seller (Your Polish Company - Pre-filled) -->
|
||||||
|
<Podmiot1>
|
||||||
|
<DaneIdentyfikacyjne>
|
||||||
|
<NIP>9552521552</NIP>
|
||||||
|
<Nazwa>Alexander Global Logistics</Nazwa>
|
||||||
|
</DaneIdentyfikacyjne>
|
||||||
|
<Adres>
|
||||||
|
<KodKraju>PL</KodKraju>
|
||||||
|
<AdresL1>Gdanska 36</AdresL1>
|
||||||
|
<AdresL2>70-660 Szczecin</AdresL2>
|
||||||
|
</Adres>
|
||||||
|
<DaneKontaktowe>
|
||||||
|
<Email>MBudas@alexander-logistics.com</Email>
|
||||||
|
</DaneKontaktowe>
|
||||||
|
</Podmiot1>
|
||||||
|
<!-- Buyer (Customer - Empty, to be filled) -->
|
||||||
|
<Podmiot2>
|
||||||
|
<DaneIdentyfikacyjne>
|
||||||
|
<!-- NIP falls eine PL Ust Vorliegt
|
||||||
|
ansonsten NrID - geht immer -->
|
||||||
|
<!-- <Nazwa>#Customer Name#</Nazwa> -->
|
||||||
|
<NIP>1234567890</NIP>
|
||||||
|
<Nazwa>Test Sp. z o.o.</Nazwa>
|
||||||
|
</DaneIdentyfikacyjne>
|
||||||
|
<Adres>
|
||||||
|
<KodKraju>PL</KodKraju>
|
||||||
|
<AdresL1>ul. Testowa 1</AdresL1>
|
||||||
|
<AdresL2>00-001 Warszawa</AdresL2>
|
||||||
|
</Adres>
|
||||||
|
<!---
|
||||||
|
Contact information from buyer can be left
|
||||||
|
<DaneKontaktowe>
|
||||||
|
<Email></Email>
|
||||||
|
<Telefon></Telefon>
|
||||||
|
</DaneKontaktowe>
|
||||||
|
-->
|
||||||
|
<NrKlienta>D-12345</NrKlienta>
|
||||||
|
<JST>2</JST>
|
||||||
|
<!-- fixed -->
|
||||||
|
<GV>2</GV>
|
||||||
|
<!-- fixed -->
|
||||||
|
</Podmiot2>
|
||||||
|
<!-- Invoice Data -->
|
||||||
|
<Fa>
|
||||||
|
<KodWaluty>PLN</KodWaluty>
|
||||||
|
<P_1>2025-02-10</P_1>
|
||||||
|
<!-- Invoice Date -->
|
||||||
|
<P_2>FV/2025/001</P_2>
|
||||||
|
<!-- Invoice Number -->
|
||||||
|
<P_6>2025-03-10</P_6>
|
||||||
|
<!-- Due Date -->
|
||||||
|
<!-- Totals will only be computed by the EInvoiceModelKSeF Class-->
|
||||||
|
<!--
|
||||||
|
<P_13_1>0.00</P_13_1>
|
||||||
|
<P_14_1>0.00</P_14_1>
|
||||||
|
<P_15>0.00</P_15>
|
||||||
|
-->
|
||||||
|
<P_13_1>10000.00</P_13_1>
|
||||||
|
<P_14_1>2300.00</P_14_1>
|
||||||
|
<P_15>12300.00</P_15>
|
||||||
|
<Adnotacje>
|
||||||
|
<!-- 1 yes - 2 no -->
|
||||||
|
<P_16>2</P_16>
|
||||||
|
<!-- Keine Selbstfakturierung -->
|
||||||
|
<P_17>2</P_17>
|
||||||
|
<!-- Kein Reverse Charge -->
|
||||||
|
<P_18>2</P_18>
|
||||||
|
<!-- Kein Split Payment (Rechnung unter 15.000 PLN/EUR) -->
|
||||||
|
<P_18A>2</P_18A>
|
||||||
|
<!-- Keine Steuerbefreiung -->
|
||||||
|
<Zwolnienie>
|
||||||
|
<P_19N>1</P_19N>
|
||||||
|
</Zwolnienie>
|
||||||
|
<!-- Keine neuen Verkehrsmittel -->
|
||||||
|
<NoweSrodkiTransportu>
|
||||||
|
<P_22N>1</P_22N>
|
||||||
|
</NoweSrodkiTransportu>
|
||||||
|
<!-- Kein vereinfachtes Verfahren nach Art. 135 -->
|
||||||
|
<P_23>2</P_23>
|
||||||
|
<!-- Keine Margenregelung -->
|
||||||
|
<PMarzy>
|
||||||
|
<P_PMarzyN>1</P_PMarzyN>
|
||||||
|
</PMarzy>
|
||||||
|
</Adnotacje>
|
||||||
|
<!-- Invoice Type (VAT) -->
|
||||||
|
<RodzajFaktury>VAT</RodzajFaktury>
|
||||||
|
<!-- Invoice Positions: FaWiersz -->
|
||||||
|
<FaWiersz>
|
||||||
|
<NrWierszaFa>1</NrWierszaFa>
|
||||||
|
<UU_ID>a743f373-b75c-44c5-a077-ee628295b5d3</UU_ID>
|
||||||
|
<P_8A>szt.</P_8A>
|
||||||
|
<P_8B>1</P_8B>
|
||||||
|
<P_9A>6000.00</P_9A>
|
||||||
|
<P_11>6000.00</P_11>
|
||||||
|
<P_12>0</P_12>
|
||||||
|
</FaWiersz>
|
||||||
|
<FaWiersz>
|
||||||
|
<NrWierszaFa>2</NrWierszaFa>
|
||||||
|
<UU_ID>9eb2d946-a3cb-4adb-8ed1-069e2f48d67d</UU_ID>
|
||||||
|
<P_8A>szt.</P_8A>
|
||||||
|
<P_8B>1</P_8B>
|
||||||
|
<P_9A>4000.00</P_9A>
|
||||||
|
<P_11>4000.00</P_11>
|
||||||
|
<P_12>0</P_12>
|
||||||
|
</FaWiersz>
|
||||||
|
</Fa>
|
||||||
|
</Faktura>
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
<Naglowek>
|
<Naglowek>
|
||||||
<KodFormularza kodSystemowy="FA (3)" wersjaSchemy="1-0E">FA</KodFormularza>
|
<KodFormularza kodSystemowy="FA (3)" wersjaSchemy="1-0E">FA</KodFormularza>
|
||||||
<WariantFormularza>3</WariantFormularza>
|
<WariantFormularza>3</WariantFormularza>
|
||||||
<DataWytworzeniaFa>2026-02-24T16:11:02.707702Z</DataWytworzeniaFa>
|
<DataWytworzeniaFa>2026-04-16T06:22:32.198172335Z</DataWytworzeniaFa>
|
||||||
<SystemInfo>Imixs eInvoice</SystemInfo>
|
<SystemInfo>Imixs eInvoice</SystemInfo>
|
||||||
</Naglowek>
|
</Naglowek>
|
||||||
<!-- Seller (Your Polish Company - Pre-filled) -->
|
<!-- Seller (Your Polish Company - Pre-filled) -->
|
||||||
|
|
@ -103,12 +103,13 @@
|
||||||
</DaneFaKorygowanej>
|
</DaneFaKorygowanej>
|
||||||
<FaWiersz>
|
<FaWiersz>
|
||||||
<NrWierszaFa>1</NrWierszaFa>
|
<NrWierszaFa>1</NrWierszaFa>
|
||||||
<UU_ID>781e1f16-a86e-452d-b959-01c76743a792</UU_ID>
|
<UU_ID>d437ac36-9439-4bd6-96fb-0fe0b91fd32d</UU_ID>
|
||||||
<P_7>Transport Berlin - Warsaw</P_7>
|
<P_7>usługa spedycyjna / transport w relacji, PL63 - CZ43</P_7>
|
||||||
<P_8A>szt.</P_8A>
|
<P_8A>szt.</P_8A>
|
||||||
<P_8B>1</P_8B>
|
<P_8B>1</P_8B>
|
||||||
<P_9A>-900.00</P_9A>
|
<P_9A>-900.00</P_9A>
|
||||||
<P_11>-900.00</P_11>
|
<P_11>-900.00</P_11>
|
||||||
|
<P_12>0</P_12>
|
||||||
</FaWiersz>
|
</FaWiersz>
|
||||||
</Fa>
|
</Fa>
|
||||||
</Faktura>
|
</Faktura>
|
||||||
|
|
|
||||||
|
|
@ -1569,7 +1569,7 @@ Wiedervorlage wird um 7 bzw. 5 Tage erhöht</bpmn2:text>
|
||||||
<imixs:value><![CDATA[0]]></imixs:value>
|
<imixs:value><![CDATA[0]]></imixs:value>
|
||||||
</imixs:item>
|
</imixs:item>
|
||||||
<imixs:item name="rtfresultlog" type="xs:string">
|
<imixs:item name="rtfresultlog" type="xs:string">
|
||||||
<imixs:value/>
|
<imixs:value><![CDATA[-> ksef.xml created]]></imixs:value>
|
||||||
</imixs:item>
|
</imixs:item>
|
||||||
<imixs:item name="keyupdateacl" type="xs:boolean">
|
<imixs:item name="keyupdateacl" type="xs:boolean">
|
||||||
<imixs:value>false</imixs:value>
|
<imixs:value>false</imixs:value>
|
||||||
|
|
@ -2301,7 +2301,7 @@ AGL Poland Team
|
||||||
<imixs:value><![CDATA[0]]></imixs:value>
|
<imixs:value><![CDATA[0]]></imixs:value>
|
||||||
</imixs:item>
|
</imixs:item>
|
||||||
<imixs:item name="rtfresultlog" type="xs:string">
|
<imixs:item name="rtfresultlog" type="xs:string">
|
||||||
<imixs:value/>
|
<imixs:value><![CDATA[-> ksef.xml tranfered successful. ]]></imixs:value>
|
||||||
</imixs:item>
|
</imixs:item>
|
||||||
<imixs:item name="keyupdateacl" type="xs:boolean">
|
<imixs:item name="keyupdateacl" type="xs:boolean">
|
||||||
<imixs:value>false</imixs:value>
|
<imixs:value>false</imixs:value>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue