diff --git a/office-alexander-logistics-app/pom.xml b/office-alexander-logistics-app/pom.xml index 6d7ac71..7691d1d 100644 --- a/office-alexander-logistics-app/pom.xml +++ b/office-alexander-logistics-app/pom.xml @@ -350,7 +350,7 @@ - + org.glassfish.jersey.core diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/xml/CargosoftXMLInvoiceImportService.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/xml/CargosoftXMLInvoiceImportService.java index 16d3c16..d5cc583 100644 --- a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/xml/CargosoftXMLInvoiceImportService.java +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/xml/CargosoftXMLInvoiceImportService.java @@ -335,7 +335,7 @@ public class CargosoftXMLInvoiceImportService { /** * Creates and processes a new workitem with a given xml information from the - * filedata + * fileData * * * @return @@ -567,27 +567,20 @@ public class CargosoftXMLInvoiceImportService { /** * Hilfsmethode die die ATC Nummer sucht. - * Wir gehen davon aus, das diese pro Rechnung nur einmal existieren kann. + * Wir gehen davon aus, das wir über die ChildItems diese aus dem billingtexts + * schon ermittel haben. * * @param doc * @param workitem */ private void resolveATCNumber(Document doc, ItemCollection workitem) { + String atcNumber = null; - // Liste der BillingText-Elemente erhalten - NodeList billingTextList = doc.getElementsByTagName("BillingText"); - if (billingTextList == null) { - return; - } - // Über die Liste iterieren und nach einem BillingText suchen, der mit "ATC" - // beginnt - for (int i = 0; i < billingTextList.getLength(); i++) { - Node billingTextNode = billingTextList.item(i); - if (billingTextNode.getNodeType() == Node.ELEMENT_NODE) { - String billingText = billingTextNode.getTextContent().trim(); - if (billingText.startsWith("ATC")) { - atcNumber = billingText; - } + List childs = InvoiceUtil.explodeChildList(workitem); + for (ItemCollection child : childs) { + if (child.hasItem("atc.number")) { + atcNumber = child.getItemValueString("atc.number"); + break; } } if (atcNumber != null && !atcNumber.isEmpty()) { @@ -616,7 +609,6 @@ public class CargosoftXMLInvoiceImportService { private void readXMLRows(Document doc, ItemCollection workitem) { // create XPath... List childItems = new ArrayList<>(); - XPathFactory xpathFactory = XPathFactory.newInstance(); XPath xPath = xpathFactory.newXPath(); try { @@ -676,8 +668,12 @@ public class CargosoftXMLInvoiceImportService { String activityType = (String) netActivityTypeExpr.evaluate(rowNode, XPathConstants.STRING); childItemCol.setItemValue("category", activityType); - // Bei G = Gutschrift oder SR = Stornorechnung müssen wir das vorzeichen ändern - // Invoice Type S/H + /** + * S/H Kennzeichen auflösen + * + * Bei G = Gutschrift oder SR = Stornorechnung müssen wir das vorzeichen ändern + * Invoice Type S/H + */ if (isGutschrift(workitem)) { // Gutschrift childItemCol.setItemValue("datev.shzeichen", "S"); @@ -686,6 +682,27 @@ public class CargosoftXMLInvoiceImportService { childItemCol.setItemValue("datev.shzeichen", "H"); } + /** + * Liste der BillingText-Elemente lesen.... + * + * und ggf. die ATC Nummer finden.... + **/ + // XPath-Ausdruck für den BillingCode + XPathExpression billingCodeExpr = xPath.compile("BillingCode/Codes/Code"); + String billingCode = (String) billingCodeExpr.evaluate(rowNode, XPathConstants.STRING); + childItemCol.setItemValue("BillingCode", billingCode); + // XPath-Ausdruck für die BillingTexts + XPathExpression billingTextsExpr = xPath.compile("BillingTexts/BillingText"); + NodeList billingTextNodes = (NodeList) billingTextsExpr.evaluate(rowNode, XPathConstants.NODESET); + for (int bi = 0; bi < billingTextNodes.getLength(); bi++) { + String val = billingTextNodes.item(bi).getTextContent(); + childItemCol.appendItemValue("BillingText", val); + // handelt es sich um eine ATC Nummer? + if (val.startsWith("ATC")) { + childItemCol.setItemValue("atc.number", val); + } + } + childItems.add(childItemCol); } } @@ -783,7 +800,7 @@ public class CargosoftXMLInvoiceImportService { * @param belegNummer * @return */ - private boolean alreadyImported(String belegNummer) { + protected boolean alreadyImported(String belegNummer) { String sQuery = "((type:workitem OR type:workitemarchive) AND $modelversion:rechnungsausgang* AND invoice.number:\"" + belegNummer + "\")"; diff --git a/office-alexander-logistics-app/src/test/java/com/alexanderlogistics/TestIMAPAuhtenticators.java b/office-alexander-logistics-app/src/test/java/com/alexanderlogistics/TestIMAPAuhtenticators.java index 5370f9c..0bcc39f 100644 --- a/office-alexander-logistics-app/src/test/java/com/alexanderlogistics/TestIMAPAuhtenticators.java +++ b/office-alexander-logistics-app/src/test/java/com/alexanderlogistics/TestIMAPAuhtenticators.java @@ -111,6 +111,48 @@ public class TestIMAPAuhtenticators { } + /** + * Test IMAP connect via OAuth for email address imixs@alexander-logistics.com + * + * https://techcommunity.microsoft.com/t5/exchange/javamail-connecting-to-office-365-xoauth2-for-imap/m-p/1505026 + */ + @Test + public void testOutlookAuthenticator_Imixs_plAGL() { + + IMAPOutlookAuthenticator auth = new IMAPOutlookAuthenticator(); + + ItemCollection source = new ItemCollection(); + source.setItemValue(DocumentImportService.SOURCE_ITEM_SERVER, "outlook.office365.com"); + source.setItemValue(DocumentImportService.SOURCE_ITEM_PORT, "993"); + + source.setItemValue(DocumentImportService.SOURCE_ITEM_USER, "imixspl@alexander-logistics.com"); + source.setItemValue(DocumentImportService.SOURCE_ITEM_PASSWORD, "A6x8Q~EWVUyt~gfyTHtIJf4ig.F9tajUpEEXMaCL"); + + Properties sourceOptions = new Properties(); + sourceOptions.put("microsoft.tenantid", "51e2f038-0a96-41be-801d-bb4118aa018e"); + sourceOptions.put("microsoft.clientid", "39e9eec5-6939-47dc-9729-3438a9898e63"); + logger.info("Connect started...."); + + try { + Store store = auth.openMessageStore(source, sourceOptions); + Assert.assertNotNull(store); + Assert.assertTrue(store.isConnected()); + logger.info("Connect OK"); + + // test open INBOX + IMAPFolder inbox = (IMAPFolder) store.getFolder("INBOX"); + inbox.open(Folder.READ_WRITE); + // test messages + Message[] messages = inbox.getMessages(); + logger.log(Level.INFO, "... {0} new messages found", messages.length); + } catch (MessagingException e) { + e.printStackTrace(); + Assert.fail(); + + } + + } + /** * Test IMAP connect via Basic Authentication *

diff --git a/office-alexander-logistics-app/src/test/java/com/alexanderlogistics/xml/InvoiceImportTester.java b/office-alexander-logistics-app/src/test/java/com/alexanderlogistics/xml/InvoiceImportTester.java new file mode 100644 index 0000000..0fc11c7 --- /dev/null +++ b/office-alexander-logistics-app/src/test/java/com/alexanderlogistics/xml/InvoiceImportTester.java @@ -0,0 +1,164 @@ +package com.alexanderlogistics.xml; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.List; + +import javax.xml.transform.TransformerException; +import javax.xml.xpath.XPathExpressionException; + +import org.imixs.workflow.ItemCollection; +import org.imixs.workflow.engine.DocumentService; +import org.imixs.workflow.exceptions.AccessDeniedException; +import org.imixs.workflow.exceptions.ModelException; +import org.imixs.workflow.exceptions.PluginException; +import org.imixs.workflow.exceptions.ProcessingErrorException; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnitRunner; + +import com.alexanderlogistics.InvoiceUtil; +import com.alexanderlogistics.KreditorDebitorService; +import com.alexanderlogistics.mahnlauf.MahnlaufService; + +/** + * Testet den Import Vorgang anhand einer Cargosoft XML Datei + * + * + * + * @author rsoika + */ +@RunWith(MockitoJUnitRunner.class) +public class InvoiceImportTester { + + @Spy + @InjectMocks + private CargosoftXMLInvoiceImportService service; + + @Mock + private DocumentService documentService; + + @Mock + private KreditorDebitorService kreditorDebitorService; + + @Mock + private MahnlaufService mahnlaufService; + + @Before + public void setUp() { + // Mock protected Methode 'alreadyImported' -> always false + Mockito.when(service.alreadyImported(Mockito.anyString())).thenReturn(false); + } + + /** + * Ein Einfacher test + * + * @throws TransformerException + * @throws XPathExpressionException + * @throws ModelException + * @throws PluginException + * @throws ProcessingErrorException + * @throws AccessDeniedException + * + * @throws Exception + */ + @Test + public void testInvoiceBasic() throws Exception { + + ItemCollection source = new ItemCollection(); + String fileName = "001_R_224380_110136787.xml"; + byte[] xmlContent = readTestFile("cargosoft/" + fileName); + assertNotNull(xmlContent); + + // Act + ItemCollection result = service.createWorkitem(source, fileName, xmlContent, new HashMap<>()); + + // Assert + assertNotNull(result); + assertEquals("001", result.getItemValueString("mandant.id")); + + // test Rows + List rows = InvoiceUtil.explodeChildList(result); + assertNotNull(rows); + assertEquals(2, rows.size()); + ItemCollection row1 = rows.get(0); + ItemCollection row2 = rows.get(1); + assertEquals("EX-GCA-2408-042", row1.getItemValueString("datev.text")); + assertEquals("EX-GCA-2408-042", row2.getItemValueString("datev.text")); + + } + + /** + * Ein ATC test + * + * @throws IOException + * + * @throws Exception + */ + @Test + public void testInvoiceATC() throws Exception { + + ItemCollection source = new ItemCollection(); + String fileName = "001_R_224225_115103063.xml"; + byte[] xmlContent = readTestFile("cargosoft/" + fileName); + assertNotNull(xmlContent); + + // Act + ItemCollection result = service.createWorkitem(source, fileName, xmlContent, new HashMap<>()); + + // Assert + assertNotNull(result); + assertEquals("001", result.getItemValueString("mandant.id")); + assertEquals("ATC400012650820242452", result.getItemValueString("invoice.atc.number")); + + // test Rows + List rows = InvoiceUtil.explodeChildList(result); + assertNotNull(rows); + assertEquals(2, rows.size()); + ItemCollection row1 = rows.get(0); + assertEquals("IM-GCA-2408-116", row1.getItemValueString("datev.text")); + assertEquals("EUST", row1.getItemValueString("category")); + assertEquals("EUST", row1.getItemValueString("BillingCode")); + // test BillingText + + List billingTextList = row1.getItemValue("BillingText"); + assertEquals(2, billingTextList.size()); + // test ATC Number + assertEquals("ATC400012650820242452", row1.getItemValueString("atc.number")); + + ItemCollection row2 = rows.get(1); + assertEquals("IM-GCA-2408-116", row2.getItemValueString("datev.text")); + assertEquals("SONST", row2.getItemValueString("category")); + + } + + /** + * Hilfsmethode zum einlesen einer xml test datei + * + * @return + * @throws IOException + */ + private byte[] readTestFile(String filename) throws IOException { + // Load the file from the resources folder + ClassLoader classLoader = getClass().getClassLoader(); + InputStream inputStream = classLoader.getResourceAsStream(filename); + + // Convert the InputStream to a String + // String xmlContent = new String(inputStream.readAllBytes(), + // StandardCharsets.UTF_8); + + byte[] data = inputStream.readAllBytes(); + // Optional: Close the InputStream + inputStream.close(); + return data; + } +} diff --git a/office-alexander-logistics-app/src/test/resources/cargosoft/001_R_224225_115103063.xml b/office-alexander-logistics-app/src/test/resources/cargosoft/001_R_224225_115103063.xml new file mode 100644 index 0000000..0a21013 --- /dev/null +++ b/office-alexander-logistics-app/src/test/resources/cargosoft/001_R_224225_115103063.xml @@ -0,0 +1,257 @@ + + + + CARGOSOFT + CUSTOMER + UTC + 1 + + 2024-08-14T11:51:03 + + + + + + Alexander Global Logistics GmbH + + 001 + + + + Alexander Global Logistics GmbH + + BRE + + + 224225 + + Ausgangsrechnung + + R + + + + EURO + + EUR + + + + + + + EURO + +EUR + + + 3752.95 + + + + + steuerfrei Ausfuhr + + 0 + + 0.0 + + + + +EURO + + EUR + + + 0.0 + + + + + false + + 202408 + false + false + + IM-ZEL + + 40 + + + + 2024-08-14T00:00:00 + + + D15445 + + + Wancaster + + + Hochbuchstr. 17 + 78253 + Eigeltingen + + + + DE319845483 + + + + + + A1972 + + + Alexander Global Logistics GmbH + Museumstr. 2-6 + Museumstr. 2-6 + 28195 + Bremen + + DE + DEUTSCHLAND + + + + 460/104/05589 + DE250152875 + + Sparkasse Bremen + Sparkasse Bremen + USD - Account 555102599 + IBAN: DE98 2905 0101 0555 1025 99 + SWIFT: SBREDE22XXX + IBAN : DE97 2905 0101 0081 2163 92 + + + + + Sofort zahlbar + + 01 + + + 2024-08-14T00:00:00 + + + 2024-08-14T00:00:00 + 00:00:00 + + Mohamed Kanaan + mkanaan@alexander-logistics.com + +49 421 56 646-191 + +49 421 56 646-200 + + + + IM-GCA-2408-116 + IMPORT + 1 + 2023.2.6300 Terminals + 3265.865 + 0.0 + 0 + + + 1004 + + + + 001_224225_240814_R.pdf + + + + + + + 5 + IM-GCA-2408-116 + + + EUST + + + + Einfuhrumsatzsteuer laut Auslagen + ATC400012650820242452 + + + + + +EURO + + EUR + + + 3591.34 + + + + + steuerfrei Ausfuhr + +0 + + 0.0 + + + + + EUSt + + EUST + + + 3591.340 + + + 10 + IM-GCA-2408-116 + + + VP + + + + Vorlageprovision 4,5 % + bei einer Einhaltung einer Zahlung + binnen 8 Banktagen kann der Betrag + in Abzug gebracht werden + + + + + +EURO + + EUR + + + 161.61 + + + + + steuerfrei Ausfuhr + +0 + + 0.0 + + + + + other charges + + SONST + + + 4.500 + + + + \ No newline at end of file diff --git a/office-alexander-logistics-app/src/test/resources/cargosoft/001_R_224380_110136787.xml b/office-alexander-logistics-app/src/test/resources/cargosoft/001_R_224380_110136787.xml new file mode 100644 index 0000000..dbd8d3d --- /dev/null +++ b/office-alexander-logistics-app/src/test/resources/cargosoft/001_R_224380_110136787.xml @@ -0,0 +1,253 @@ + + + + CARGOSOFT + CUSTOMER + UTC + 1 + + 2024-08-16T11:01:36 + + + + + + Alexander Global Logistics GmbH + + 001 + + + + Alexander Global Logistics GmbH + + BRE + + + 224380 + + Ausgangsrechnung + + R + + + + EURO + + EUR + + + + + + + EURO + +EUR + + + 1150.0 + + + + + steuerfrei Ausfuhr + + 0 + + 0.0 + + + + +EURO + + EUR + + + 0.0 + + + + + false + + 202408 + false + false + + EX-GCA + + 90 + + + + 2024-08-16T00:00:00 + + + D13680 + + + HQ Recyclers Network e.K. + + + Liebigstr. 2-20 + 22113 + Hamburg + + + + DE309035001 + + + + + + A1972 + + + Alexander Global Logistics GmbH + Museumstr. 2-6 + Museumstr. 2-6 + 28195 + Bremen + + DE + DEUTSCHLAND + + + + 460/104/05589 + DE250152875 + + Sparkasse Bremen + Sparkasse Bremen + USD - Account 555102599 + IBAN: DE98 2905 0101 0555 1025 99 + SWIFT: SBREDE22XXX + IBAN : DE97 2905 0101 0081 2163 92 + + + + + Sofort zahlbar + + 01 + + + 2024-08-16T00:00:00 + + + 2024-08-16T00:00:00 + 00:00:00 + + Mathis Hoffmann + mhoffmann@alexander-logistics.com + +49 421 56 646-116 + +49 421 56 646-201 + + + + EX-GCA-2408-042 + EXPORT + 1 + 2023.2.6300 Terminals + 24000.0 + 0.0 + 0 + + + 1004 + + + + 001_224380_240816_R.pdf + + + + + + + 5 + EX-GCA-2408-042 + + + TRANS + + + + Rate Schwarzenbek bis Port Kelang + + + + + +EURO + + EUR + + + 1100.0 + + + + + steuerfrei Ausfuhr + +0 + + 0.0 + + + + + Seefracht + + SEE + + + 1100.000 + + + 10 + EX-GCA-2408-042 + + + TRANS + + + + Telex + + + + + +EURO + + EUR + + + 50.0 + + + + + steuerfrei Ausfuhr + +0 + + 0.0 + + + + + Seefracht + + SEE + + + 50.000 + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index ce84a11..f0aea13 100644 --- a/pom.xml +++ b/pom.xml @@ -267,14 +267,33 @@ junit junit - 4.8.1 + 4.13.1 test org.mockito - mockito-all - 1.9.5 + mockito-core + 5.8.0 test + + org.eclipse.parsson + jakarta.json + 1.1.1 + test + + + org.glassfish.jaxb + jaxb-runtime + 3.0.0 + test + + + jakarta.xml.bind + jakarta.xml.bind-api + 3.0.0 + test + + \ No newline at end of file