update - added test

This commit is contained in:
Ralph Soika 2026-02-10 12:47:20 +01:00
parent fc69af8bd5
commit 1a614564a8
6 changed files with 512 additions and 113 deletions

View file

@ -146,7 +146,7 @@ public class KSeFAdapter implements SignalAdapter {
* @param workitem
* @throws PluginException
*/
private void updateEInvoice(FileData fileDataXMLTemplate, ItemCollection workitem) throws PluginException {
public void updateEInvoice(FileData fileDataXMLTemplate, ItemCollection workitem) throws PluginException {
try {
EInvoiceModel model = EInvoiceModelFactory.read(new ByteArrayInputStream(fileDataXMLTemplate.getContent()));

View file

@ -426,8 +426,11 @@ public class KSeFAPIService {
// Base64URL ohne Padding
String base64Url = Base64.getUrlEncoder().withoutPadding().encodeToString(decoded);
// https://ksef-test.mf.gov.pl/api/v2 -> https://ksef-test.mf.gov.pl/client-app/
baseURL = baseURL.replace("/api/v2", "/client-app/invoice");
// Die Client App URL muss angepasst werden. Das /v2/ element aus der Basis URL
// muss mit 'client-app/invoice' ausgetauscht werden.
// Es entsteht dann https://api-test.ksef.mf.gov.pl/client-app/invoice/
baseURL = baseURL.replace("/v2", "/client-app/invoice");
// Build verification URL
workitem.setItemValue("ksef.VerificationUrl",
baseURL + "/" + kseFAuthManager.getKsefNip() + "/" + invoiceDate + "/"

View file

@ -0,0 +1,170 @@
package com.alexanderlogistics.ksef.api;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static org.mockito.Mockito.when;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import org.imixs.workflow.FileData;
import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.engine.DocumentService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import com.alexanderlogistics.BusinessPartnerService;
import com.alexanderlogistics.InvoiceService;
import com.alexanderlogistics.TestLoggerConfig;
import com.alexanderlogistics.einvoice.KSeFAdapter;
/**
* Der KSeFAdapterTest prüft die Umwandlung einer Rechnung in die KSeF XML
* Struktur.
*
* Der Test simuliert eine Invoice und ruft dann den KSeFAdapter an um ein
* Output File zu erzeugen.
* <p>
* Zum validieren kann man dann den validate_xml.sh Script hernehmen
*
*/
@ExtendWith(MockitoExtension.class)
public class KSeFAdapterTest {
private static Logger logger = Logger.getLogger(KSeFAdapterTest.class.getName());
private static final String TEMPLATE_FILE = "ksef/ksef.xml";
private static final String OUTPUT_FILE = "ksef-output.xml";
ItemCollection workitem;
ItemCollection businessPartner;
@Mock
private BusinessPartnerService businessPartnerService;
@Mock
private DocumentService documentService;
@Mock
private InvoiceService invoiceService;
@InjectMocks
private KSeFAdapter adapter;
@BeforeEach
void setup() throws Exception {
TestLoggerConfig.setupTestLogger();
// Prepare a workitem with typical invoice data
workitem = new ItemCollection();
workitem.setItemValue("invoice.number", "FV/2025/001");
workitem.setItemValue("invoice.date", LocalDate.of(2025, 2, 10));
workitem.setItemValue("invoice.duedate", LocalDate.of(2025, 3, 10));
workitem.setItemValue("invoice.currency", "PLN");
workitem.setItemValue("invoice.total.net", 10000.00);
workitem.setItemValue("invoice.total.tax", 23.0);
workitem.setItemValue("invoice.total", 12300.00);
workitem.setItemValue("invoice.correction", "false");
workitem.setItemValue("invoice.CorrectionInvoiceNumber", "");
workitem.setItemValue("partner.id", "BP-001");
workitem.setItemValue("partner.vat", "PL1234567890");
// Prepare child items (invoice line items)
List<Object> childItems = new ArrayList<>();
ItemCollection lineItem1 = new ItemCollection();
lineItem1.setItemValue("numpos", "1");
lineItem1.setItemValue("datev.text", "Transport Berlin - Warsaw");
lineItem1.setItemValue("datev.umsatz", 6000.00);
childItems.add(lineItem1.getAllItems());
ItemCollection lineItem2 = new ItemCollection();
lineItem2.setItemValue("numpos", "2");
lineItem2.setItemValue("datev.text", "Customs handling");
lineItem2.setItemValue("datev.umsatz", 4000.00);
childItems.add(lineItem2.getAllItems());
workitem.setItemValue("_childitems", childItems);
// Prepare mock business partner
businessPartner = new ItemCollection();
businessPartner.setItemValue("partner.name", "Test Sp. z o.o.");
businessPartner.setItemValue("partner.country", "PL");
businessPartner.setItemValue("partner.city", "Warszawa");
businessPartner.setItemValue("partner.zip", "00-001");
businessPartner.setItemValue("partner.address", "ul. Testowa 1");
businessPartner.setItemValue("partner.vat", "PL1234567890");
businessPartner.setItemValue("dbtr.number", "D-12345");
}
/**
* Erzeugt ein lokales XML File zum testen
*/
@Test
@DisplayName("Test Transform")
public void testTransform() throws Exception {
logger.info("==> Test: Upload Invoice XML");
// Arrange
when(businessPartnerService.getBusinessPartnerByID("BP-001"))
.thenReturn(businessPartner);
FileData xmlTemplate = loadTemplateFromResources(TEMPLATE_FILE);
// Act
adapter.updateEInvoice(xmlTemplate, workitem);
// Assert - basic checks
assertNotNull(xmlTemplate.getContent(), "XML content should not be null after update");
assertTrue(xmlTemplate.getContent().length > 0, "XML content should not be empty");
// Write output for manual inspection
writeOutputToResources(xmlTemplate, OUTPUT_FILE);
}
// Helper methods
/**
* Load the KSeF XML template from src/test/resources.
*/
private FileData loadTemplateFromResources(String filename) {
try (InputStream is = getClass().getClassLoader().getResourceAsStream(filename)) {
if (is == null) {
fail("Template file not found in test resources: " + filename
+ "\nPlease place your KSeF XML template at: src/test/resources/" + filename);
}
byte[] content = is.readAllBytes();
return new FileData(filename, content, "application/xml", null);
} catch (IOException e) {
fail("Failed to read template: " + e.getMessage());
return null;
}
}
/**
* Write the resulting XML to src/test/resources/output/ for manual inspection.
*/
private void writeOutputToResources(FileData fileData, String filename) throws IOException {
Path outputDir = Paths.get("src", "test", "resources", "output");
Files.createDirectories(outputDir);
Path outputPath = outputDir.resolve(filename);
Files.write(outputPath, fileData.getContent());
System.out.println("──────────────────────────────────────────────");
System.out.println("Output written to: " + outputPath.toAbsolutePath());
System.out.println("──────────────────────────────────────────────");
}
}

View file

@ -0,0 +1,119 @@
<?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>2025-11-19T16:43:15.545220735Z</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 -->
<!-- <NIP></NIP> -->
<Nazwa>REGESTA Spolka Akcyjna</Nazwa>
</DaneIdentyfikacyjne>
<Adres>
<KodKraju>PL</KodKraju>
<AdresL1>ul. Nowowiejska 52a</AdresL1>
<AdresL2>28-400 Pinczow</AdresL2>
</Adres>
<!---
Contact information from buyer can be left
<DaneKontaktowe>
<Email></Email>
<Telefon></Telefon>
</DaneKontaktowe>
-->
<NrKlienta>D15231</NrKlienta>
<JST>2</JST>
<!-- fixed -->
<GV>2</GV>
<!-- fixed -->
</Podmiot2>
<!-- Invoice Data -->
<Fa>
<KodWaluty>EUR</KodWaluty>
<P_1>2024-04-03</P_1>
<!-- Invoice Date -->
<P_2>216525</P_2>
<!-- Invoice Number -->
<P_6>2024-06-02</P_6>
<!-- Due Date -->
<!-- Line Items will be added here -->
<!-- Totals -->
<P_13_1>4128.00</P_13_1>
<!-- Total Net -->
<P_14_1>0.00</P_14_1>
<!-- Total VAT -->
<P_15>4128.00</P_15>
<!-- Total Gross -->
<FaWiersz>
<NrWierszaFa>1</NrWierszaFa>
<UU_ID>2b141c75-7867-4975-846a-a2c2683e1fc5</UU_ID>
<P_7>R IM-ZEL-2403-259</P_7>
<P_8A>szt.</P_8A>
<P_8B>1</P_8B>
<P_9A>4128.00</P_9A>
<P_11>4128.00</P_11>
<P_12>0</P_12>
</FaWiersz>
<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>
<!-- Normale Rechnung (VAT) -->
<RodzajFaktury>VAT | ??? </RodzajFaktury>
<!-- Invoice Poitions
<FaWiersz>
<NrWierszaFa>1</NrWierszaFa>
<UU_ID>f980444d-2cca-4fde-bf67-a08551f0dbd8</UU_ID>
<P_7>R IM-ZEL-2403-259</P_7>
<P_8A>szt.</P_8A>
<P_8B>1</P_8B>
<P_9A>4128.00</P_9A>
<P_11>4128.00</P_11>
<P_12>23</P_12>
</FaWiersz>
-->
</Fa>
</Faktura>

View file

@ -1,14 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<?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>2025-11-19T16:43:15.545220735Z</DataWytworzeniaFa>
<DataWytworzeniaFa>2026-06-05T02:45:33.422866Z</DataWytworzeniaFa>
<SystemInfo>Imixs eInvoice</SystemInfo>
</Naglowek>
<!-- Seller (Your Polish Company - Pre-filled) -->
<Podmiot1>
<DaneIdentyfikacyjne>
@ -24,19 +26,20 @@
<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 -->
<!-- <NIP></NIP> -->
<Nazwa>REGESTA Spolka Akcyjna</Nazwa>
<!-- <Nazwa>#Customer Name#</Nazwa> -->
</DaneIdentyfikacyjne>
<Adres>
<KodKraju>PL</KodKraju>
<AdresL1>ul. Nowowiejska 52a</AdresL1>
<AdresL2>28-400 Pinczow</AdresL2>
<KodKraju></KodKraju>
<AdresL1></AdresL1>
<AdresL2></AdresL2>
</Adres>
<!---
Contact information from buyer can be left
<DaneKontaktowe>
@ -44,76 +47,62 @@
<Telefon></Telefon>
</DaneKontaktowe>
-->
<NrKlienta>D15231</NrKlienta>
<JST>2</JST>
<!-- fixed -->
<GV>2</GV>
<!-- fixed -->
<NrKlienta>#CDTR-NUMBER#</NrKlienta>
<JST>2</JST> <!-- fixed -->
<GV>2</GV> <!-- fixed -->
</Podmiot2>
<!-- Invoice Data -->
<Fa>
<KodWaluty>EUR</KodWaluty>
<P_1>2024-04-03</P_1>
<!-- Invoice Date -->
<P_2>216525</P_2>
<!-- Invoice Number -->
<P_6>2024-06-02</P_6>
<!-- Due Date -->
<!-- Line Items will be added here -->
<!-- Totals -->
<P_13_1>4128.00</P_13_1>
<!-- Total Net -->
<KodWaluty>#CURRENCY#</KodWaluty>
<P_1></P_1> <!-- Invoice Date -->
<P_2></P_2> <!-- Invoice Number -->
<P_6></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>
<!-- Total VAT -->
<P_15>4128.00</P_15>
<!-- Total Gross -->
<FaWiersz>
<NrWierszaFa>1</NrWierszaFa>
<UU_ID>2b141c75-7867-4975-846a-a2c2683e1fc5</UU_ID>
<P_7>R IM-ZEL-2403-259</P_7>
<P_8A>szt.</P_8A>
<P_8B>1</P_8B>
<P_9A>4128.00</P_9A>
<P_11>4128.00</P_11>
<P_12>0</P_12>
</FaWiersz>
<P_15>0.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>
<!-- Normale Rechnung (VAT) -->
<RodzajFaktury>VAT | ??? </RodzajFaktury>
<!-- Invoice Poitions
<FaWiersz>
<NrWierszaFa>1</NrWierszaFa>
<UU_ID>f980444d-2cca-4fde-bf67-a08551f0dbd8</UU_ID>
<P_7>R IM-ZEL-2403-259</P_7>
<P_8A>szt.</P_8A>
<P_8B>1</P_8B>
<P_9A>4128.00</P_9A>
<P_11>4128.00</P_11>
<P_12>23</P_12>
</FaWiersz>
-->
<!-- Invoice Type (VAT) -->
<RodzajFaktury>VAT</RodzajFaktury>
<!-- Invoice Positions: FaWiersz -->
</Fa>
</Faktura>

View file

@ -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-02-10T12:46:08.366684Z</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>5a2dd34c-6592-40aa-aafc-80bac9c9b9c4</UU_ID>
<P_7>Transport Berlin - Warsaw</P_7>
<P_8A>szt.</P_8A>
<P_8B>1</P_8B>
<P_9A>6000.00</P_9A>
<P_11>6000.00</P_11>
</FaWiersz>
<FaWiersz>
<NrWierszaFa>2</NrWierszaFa>
<UU_ID>d44bf6a0-758b-415b-b45a-d83052a2f2aa</UU_ID>
<P_7>Customs handling</P_7>
<P_8A>szt.</P_8A>
<P_8B>1</P_8B>
<P_9A>4000.00</P_9A>
<P_11>4000.00</P_11>
</FaWiersz>
</Fa>
</Faktura>