296 lines
11 KiB
Java
296 lines
11 KiB
Java
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.Date;
|
|
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";
|
|
|
|
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 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 Simple Invoice")
|
|
public void testSimpleInvoice() throws Exception {
|
|
logger.info("==> Test: Upload Invoice XML");
|
|
|
|
// Prepare a workitem with typical invoice data
|
|
ItemCollection 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");
|
|
workitem.setItemValue("invoice.performancedate", new Date());
|
|
|
|
// 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);
|
|
|
|
// 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, "invoice-simple.xml");
|
|
|
|
}
|
|
|
|
/**
|
|
* Erzeugt ein lokales XML File zum testen
|
|
*/
|
|
@Test
|
|
@DisplayName("Test Invoice Korrektur")
|
|
public void testInvoiceKorektur() throws Exception {
|
|
logger.info("==> Test: Upload Invoice XML");
|
|
|
|
// Prepare a workitem with typical invoice data
|
|
ItemCollection 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", "EUR");
|
|
workitem.setItemValue("invoice.total.net", 0.00);
|
|
workitem.setItemValue("invoice.total.tax", 0.0);
|
|
workitem.setItemValue("invoice.total", 0.00);
|
|
|
|
workitem.setItemValue("partner.id", "BP-001");
|
|
workitem.setItemValue("partner.vat", "PL1234567890");
|
|
|
|
// simulation Korrekturrechnung
|
|
workitem.setItemValue("invoice.correction", true);
|
|
workitem.setItemValue("invoice.CorrectionInvoiceNumber", "6551");
|
|
workitem.setItemValue("invoice.performancedate", new Date());
|
|
// Prepare child items (invoice line items)
|
|
List<Object> childItems = new ArrayList<>();
|
|
|
|
ItemCollection lineItem1 = new ItemCollection()
|
|
.setItemValue("numpos", "1")
|
|
.setItemValue("datev.shzeichen", "H")
|
|
.setItemValue("datev.kurs", 0.236485)
|
|
.setItemValue("datev.basisumsatz", -3805.74)
|
|
.setItemValue("datev.text", "Transport Berlin - Warsaw")
|
|
.setItemValue("billingtext", "usługa spedycyjna / transport w relacji, PL63 - CZ43")
|
|
.setItemValue("datev.umsatz", -900.00)
|
|
.setItemValue("datev.wkz", "EUR")
|
|
.setItemValue("billingcode", "TRANSLKW");
|
|
|
|
childItems.add(lineItem1.getAllItems());
|
|
|
|
/**
|
|
* <NrWierszaFa>1</NrWierszaFa>
|
|
* <UU_ID>7f846436-7c29-48b3-8f5a-fed996ea30a3</UU_ID>
|
|
* <P_7>IM-POL-2512-008</P_7>
|
|
* <P_8A>szt.</P_8A>
|
|
* <P_8B>1</P_8B>
|
|
* <P_9A>0.00</P_9A>
|
|
* <P_11>0.00</P_11>
|
|
* </FaWiersz>
|
|
* <FaWiersz>
|
|
* <NrWierszaFa>2</NrWierszaFa>
|
|
* <UU_ID>f3077e37-9198-4431-a82b-68d9439b587e</UU_ID>
|
|
* <P_7>IM-POL-2512-008</P_7>
|
|
* <P_8A>szt.</P_8A>
|
|
* <P_8B>1</P_8B>
|
|
* <P_9A>-900.00</P_9A>
|
|
* <P_11>-900.00</P_11>
|
|
* </FaWiersz>
|
|
* <FaWiersz>
|
|
* <NrWierszaFa>3</NrWierszaFa>
|
|
* <UU_ID>31fdfe9e-671e-42f6-9f7e-ceb227a3a42c</UU_ID>
|
|
* <P_7>IM-POL-2512-008</P_7>
|
|
* <P_8A>szt.</P_8A>
|
|
* <P_8B>1</P_8B>
|
|
* <P_9A>0.00</P_9A>
|
|
* <P_11>0.00</P_11>
|
|
* </FaWiersz>
|
|
* <FaWiersz>
|
|
* <NrWierszaFa>4</NrWierszaFa>
|
|
* <UU_ID>79ffd1e8-be87-478b-97b5-d37aa302d090</UU_ID>
|
|
* <P_7>IM-POL-2512-008</P_7>
|
|
* <P_8A>szt.</P_8A>
|
|
* <P_8B>1</P_8B>
|
|
* <P_9A>0.00</P_9A>
|
|
* <P_11>0.00</P_11>
|
|
* </FaWiersz>
|
|
* <FaWiersz>
|
|
* <NrWierszaFa>5</NrWierszaFa>
|
|
* <UU_ID>38e8cbd3-e558-4b0e-875c-c4f2d96d1659</UU_ID>
|
|
* <P_7>IM-POL-2512-008</P_7>
|
|
* <P_8A>szt.</P_8A>
|
|
* <P_8B>1</P_8B>
|
|
* <P_9A>900.00</P_9A>
|
|
* <P_11>900.00</P_11>
|
|
* </FaWiersz>
|
|
* <FaWiersz>
|
|
* <NrWierszaFa>6</NrWierszaFa>
|
|
* <UU_ID>3774dab3-b6c4-433e-8298-60ecf6cbab74</UU_ID>
|
|
* <P_7>IM-POL-2512-008</P_7>
|
|
* <P_8A>szt.</P_8A>
|
|
* <P_8B>1</P_8B>
|
|
* <P_9A>0.00</P_9A>
|
|
* <P_11>0.00</P_11>
|
|
* </FaWiersz>
|
|
* <FaWiersz>
|
|
* <NrWierszaFa>7</NrWierszaFa>
|
|
* <UU_ID>f19846ab-3567-4e5d-823b-807d474af062</UU_ID>
|
|
* <P_7>IM-POL-2512-008</P_7>
|
|
* <P_8A>szt.</P_8A>
|
|
* <P_8B>1</P_8B>
|
|
* <P_9A>0.00</P_9A>
|
|
* <P_11>0.00</P_11>
|
|
*/
|
|
|
|
workitem.setItemValue("_childitems", childItems);
|
|
|
|
// 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, "test-korrekturrechnung.xml");
|
|
|
|
}
|
|
|
|
// ── 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", "ksef/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("──────────────────────────────────────────────");
|
|
}
|
|
}
|