diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/datev/DatevCargosoftImportAdapter.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/datev/DatevCargosoftImportAdapter.java index 6b50023..552a37d 100644 --- a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/datev/DatevCargosoftImportAdapter.java +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/datev/DatevCargosoftImportAdapter.java @@ -8,12 +8,9 @@ import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Logger; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import javax.inject.Inject; @@ -33,6 +30,7 @@ import org.imixs.workflow.exceptions.QueryException; import com.alexanderlogistics.InvoiceUtil; import com.alexanderlogistics.KreditorDebitorService; +import com.alexanderlogistics.mahnlauf.MahnlaufService; /** * Der DatevCargosoftImportAdapter liest eine von Cargosoft bereitgestellte @@ -126,6 +124,9 @@ public class DatevCargosoftImportAdapter implements SignalAdapter { @Inject TeamService teamService; + @Inject + MahnlaufService mahnlaufService; + private String INITIAL_MODEL_VERSION_INVOICE; private int INITIAL_TASK_ID_INVOICE; private int INITIAL_EVENT_ID_INVOICE; @@ -206,7 +207,7 @@ public class DatevCargosoftImportAdapter implements SignalAdapter { SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyyMMdd"); // load spaces Pos Expressions - Map> spacePosMappings = loadSpacePosMappings(); + Map> spacePosMappings = mahnlaufService.loadSpacePosMappings(); ItemCollection invoiceWorkitem = null; List splitBuchungen = new ArrayList(); @@ -385,27 +386,6 @@ public class DatevCargosoftImportAdapter implements SignalAdapter { } - /** - * Helper method that loads all expressions from the spaces - * - * @return List of list of expressions - */ - private Map> loadSpacePosMappings() { - Map> result = new HashMap<>(); - // als erstes lesen wir die pos.mappings aus den Spaces ein, auf die dann eine - // Rechnung emapped werden kann. - List spaces_subs = teamService.getSpaces(); - for (ItemCollection stub : spaces_subs) { - // load full workitem - ItemCollection space = documentService.load(stub.getUniqueID()); - if (space != null) { - result.put(space.getUniqueID(), space.getItemValueList("pos.mapping", String.class)); - } - } - - return result; - } - /** * This method returns a new empty invoice ItemCollection. *

@@ -525,27 +505,29 @@ public class DatevCargosoftImportAdapter implements SignalAdapter { } // Jezt noch das Space mapping - // dazu kucken wir in alle spaces den config wert 'pos.mapping' - String text = datevWorkitem.getItemValueString("invoice.text"); - if (!text.isEmpty()) { - boolean found = false; - for (Map.Entry> entry : spacePosMappings.entrySet()) { - List expressionsList = entry.getValue(); - for (String expr : expressionsList) { - Pattern p = Pattern.compile(expr); - Matcher m = p.matcher(text); - if (m.find()) { - // we have a match - datevWorkitem.setItemValue("space.ref", entry.getKey()); - found = true; - break; - } - } - if (found) { - break; - } - } - } + mahnlaufService.mapInvoiceTextToSpace(datevWorkitem, spacePosMappings); + // // dazu kucken wir in alle spaces den config wert 'pos.mapping' + // String text = datevWorkitem.getItemValueString("invoice.text"); + // if (!text.isEmpty()) { + // boolean found = false; + // for (Map.Entry> entry : spacePosMappings.entrySet()) { + // List expressionsList = entry.getValue(); + // for (String expr : expressionsList) { + // Pattern p = Pattern.compile(expr); + // Matcher m = p.matcher(text); + // if (m.find()) { + // // we have a match + // datevWorkitem.setItemValue("space.ref", entry.getKey()); + // found = true; + // break; + // } + // } + // if (found) { + // break; + // } + // } + // } + // Processe die Invoice datevWorkitem.model(INITIAL_MODEL_VERSION_INVOICE).task(INITIAL_TASK_ID_INVOICE) .event(INITIAL_EVENT_ID_INVOICE); diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/mahnlauf/MahnlaufService.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/mahnlauf/MahnlaufService.java index d1dfb3b..a696de4 100644 --- a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/mahnlauf/MahnlaufService.java +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/mahnlauf/MahnlaufService.java @@ -27,13 +27,21 @@ package com.alexanderlogistics.mahnlauf; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + import javax.annotation.security.DeclareRoles; import javax.annotation.security.RolesAllowed; import javax.annotation.security.RunAs; import javax.ejb.Singleton; import javax.inject.Inject; +import org.imixs.marty.team.TeamService; import org.imixs.workflow.ItemCollection; +import org.imixs.workflow.engine.DocumentService; import org.imixs.workflow.engine.WorkflowService; import org.imixs.workflow.exceptions.AccessDeniedException; import org.imixs.workflow.exceptions.ModelException; @@ -58,22 +66,24 @@ import org.imixs.workflow.exceptions.ProcessingErrorException; @RunAs("org.imixs.ACCESSLEVEL.MANAGERACCESS") public class MahnlaufService { - - public static final int TASK_MAHNLAUF_START = 5100; - public static final int TASK_MAHNLAUF_END = 5299; - public static final int EVENT_MAHNLAUF_EXECUTE = 300; - - public static final String ITEM_DBTR_NUMBER = "dbtr.number"; - public static final String ITEM_DBTR_NAME = "dbtr.name"; - public static final String ITEM_DBTR_EMAIL = "dbtr.mail"; - public static final String ERROR_CONFIG = "CONFIG_ERROR"; - public static final String ERROR_WORKFLOW = "ERROR_WORKFLOW"; + public static final int TASK_MAHNLAUF_START = 5100; + public static final int TASK_MAHNLAUF_END = 5299; + public static final int EVENT_MAHNLAUF_EXECUTE = 300; + + public static final String ITEM_DBTR_NUMBER = "dbtr.number"; + public static final String ITEM_DBTR_NAME = "dbtr.name"; + public static final String ITEM_DBTR_EMAIL = "dbtr.mail"; + public static final String ERROR_CONFIG = "CONFIG_ERROR"; + public static final String ERROR_WORKFLOW = "ERROR_WORKFLOW"; - @Inject - WorkflowService workflowService; + WorkflowService workflowService; - + @Inject + TeamService teamService; + + @Inject + DocumentService documentService; /** * * Diese Method processed eine Invoice mit Manager Rechnten @@ -92,4 +102,55 @@ public class MahnlaufService { } } + /** + * Helper method that loads all expressions from the spaces + * + * @return List of list of expressions + */ + public Map> loadSpacePosMappings() { + Map> result = new HashMap<>(); + // als erstes lesen wir die pos.mappings aus den Spaces ein, auf die dann eine + // Rechnung emapped werden kann. + List spaces_subs = teamService.getSpaces(); + for (ItemCollection stub : spaces_subs) { + // load full workitem + ItemCollection space = documentService.load(stub.getUniqueID()); + if (space != null) { + result.put(space.getUniqueID(), space.getItemValueList("pos.mapping", String.class)); + } + } + + return result; + } + + /** + * Hilfsmethode zum errechnen des richtigen Spaces zu einer invoice.text Positon + * + * @param workitem + * @param spacePosMappings + */ + public void mapInvoiceTextToSpace(ItemCollection workitem, Map> spacePosMappings) { + // Jezt noch das Space mapping + // dazu kucken wir in alle spaces den config wert 'pos.mapping' + String text = workitem.getItemValueString("invoice.text"); + if (!text.isEmpty()) { + boolean found = false; + for (Map.Entry> entry : spacePosMappings.entrySet()) { + List expressionsList = entry.getValue(); + for (String expr : expressionsList) { + Pattern p = Pattern.compile(expr); + Matcher m = p.matcher(text); + if (m.find()) { + // we have a match + workitem.setItemValue("space.ref", entry.getKey()); + found = true; + break; + } + } + if (found) { + break; + } + } + } + } } diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/xml/CargosoftXMLInvoiceImportImportService.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/xml/CargosoftXMLInvoiceImportImportService.java index 0587c57..87df1d7 100644 --- a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/xml/CargosoftXMLInvoiceImportImportService.java +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/xml/CargosoftXMLInvoiceImportImportService.java @@ -37,6 +37,7 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Map; import java.util.Properties; import java.util.TimeZone; import java.util.logging.Logger; @@ -44,6 +45,7 @@ import java.util.logging.Logger; import javax.ejb.EJB; import javax.ejb.Stateless; import javax.enterprise.event.Observes; +import javax.inject.Inject; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; @@ -76,6 +78,8 @@ import org.xml.sax.InputSource; import org.xml.sax.SAXException; import com.alexanderlogistics.InvoiceUtil; +import com.alexanderlogistics.KreditorDebitorService; +import com.alexanderlogistics.mahnlauf.MahnlaufService; /** * Der CargosoftXMLInvoiceImportImportService erweitert den FTPImportService und @@ -110,12 +114,19 @@ public class CargosoftXMLInvoiceImportImportService { @EJB DocumentService documentService; + @EJB ModelService modelService; + @EJB + KreditorDebitorService kreditorDebitorService; + @EJB DocumentImportService documentImportService; + @Inject + MahnlaufService mahnlaufService; + /** * This method reacts on a CDI ImportEvent and reads documents form a ftp * server. @@ -226,6 +237,10 @@ public class CargosoftXMLInvoiceImportImportService { private void scannFTPDirectory(FTPClient ftpClient, String ftpPath, String mandantID, DocumentImportEvent event) throws PluginException { try { + + // load spaces Pos Expressions + Map> spacePosMappings = mahnlaufService.loadSpacePosMappings(); + logger.finest("......read directory " + ftpPath); // try to enter the working directory and read all files... boolean bWorkingDir = ftpClient.changeWorkingDirectory(ftpPath); @@ -256,7 +271,7 @@ public class CargosoftXMLInvoiceImportImportService { logger.finest("......file '" + file.getName() + "' successful read - bytes size = " + rawData.length); // create new workitem - invoice = createWorkitem(event.getSource(), file.getName(), rawData); + invoice = createWorkitem(event.getSource(), file.getName(), rawData, spacePosMappings); if (invoice == null) { // no new data found continue; @@ -319,7 +334,8 @@ public class CargosoftXMLInvoiceImportImportService { * @throws ProcessingErrorException * @throws AccessDeniedException */ - public ItemCollection createWorkitem(ItemCollection source, String fileName, byte[] rawData) + public ItemCollection createWorkitem(ItemCollection source, String fileName, byte[] rawData, + Map> spacePosMappings) throws AccessDeniedException, ProcessingErrorException, PluginException, ModelException { ItemCollection workitem = new ItemCollection(); workitem.model(source.getItemValueString(DocumentImportService.SOURCE_ITEM_MODELVERSION)); @@ -361,8 +377,20 @@ public class CargosoftXMLInvoiceImportImportService { return null; } - readXMLValue(doc, "/Invoices/Invoice/InvoiceHeader/InvoiceAmount/NetAmount/Amount/Value", - workitem, "invoice.total", String.class); + readXMLValue(doc, "/Invoices/Invoice/InvoiceHeader/InvoiceType/Codes/Code", + workitem, "invoice.type", String.class); + + // Gutschrift oder Rechnung? + if ("G".equals(workitem.getItemValueString("invoice.type"))) { + readXMLValue(doc, "/Invoices/Invoice/InvoiceHeader/InvoiceAmount/NetAmount/Amount/Value", + workitem, "invoice.total", Double.class); + workitem.setItemValue("invoice.saldo", -workitem.getItemValueDouble("invoice.total")); + workitem.setItemValue("invoice.total", -workitem.getItemValueDouble("invoice.total")); + } else { + readXMLValue(doc, "/Invoices/Invoice/InvoiceHeader/InvoiceAmount/NetAmount/Amount/Value", + workitem, "invoice.total", Double.class); + workitem.setItemValue("invoice.saldo", workitem.getItemValueDouble("invoice.total")); + } readXMLValue(doc, "/Invoices/Invoice/InvoiceHeader/InvoiceCurrency/Codes/Code", workitem, "invoice.currency", String.class); @@ -370,6 +398,10 @@ public class CargosoftXMLInvoiceImportImportService { readXMLValue(doc, "/Invoices/Invoice/InvoiceHeader/InvoiceDate", workitem, "invoice.date", Date.class); + readXMLValue(doc, + "/Invoices/Invoice/InvoiceHeader/PaymentConditions/PaymentCondition/Codes/Code[@Type='cs']", + workitem, "payment.term", String.class); + readXMLValue(doc, "/Invoices/Invoice/InvoiceHeader/PaymentConditions/DueDate", workitem, "invoice.duedate", Date.class); @@ -379,10 +411,21 @@ public class CargosoftXMLInvoiceImportImportService { if (dbtrNumber.startsWith("K") || dbtrNumber.startsWith("D")) { workitem.setItemValue("dbtr.number", dbtrNumber.substring(1)); } + // lookup debitor and set name + try { + ItemCollection dbtr = kreditorDebitorService.findDebitor(dbtrNumber); + if (dbtr != null) { + workitem.setItemValue("dbtr.name", dbtr.getItemValueString("_vendor_name")); + } + } catch (PluginException e) { + // e.printStackTrace(); + } // Row Positions lesen // InvoiceRows/InvoiceRow readXMLRows(doc, workitem); + // Jetzt noch das Space mapping + mahnlaufService.mapInvoiceTextToSpace(workitem, spacePosMappings); // read filename readXMLValue(doc, "/Invoices/Invoice/InvoiceHeader/Attachments/Attachment/Filename", @@ -404,9 +447,6 @@ public class CargosoftXMLInvoiceImportImportService { return workitem; } - public void getMist(String itemName, Class itemType) { - } - /** * Reads a tag value from the xml tree and set the value into the given * workitem. @@ -447,11 +487,11 @@ public class CargosoftXMLInvoiceImportImportService { } return; } - if (itemType == Double.class) { + if (itemType == Double.class && value != null && !value.isEmpty()) { workitem.setItemValue(itemName, Double.parseDouble(value)); return; } - if (itemType == Integer.class) { + if (itemType == Integer.class && value != null && !value.isEmpty()) { workitem.setItemValue(itemName, Integer.parseInt(value)); return; } @@ -495,6 +535,11 @@ public class CargosoftXMLInvoiceImportImportService { XPathExpression netAmountCurrencyExpr = xPath .compile("InvoiceAmount/NetAmount/Amount/Currency/Codes/Code[@Type='cs']/text()"); XPathExpression netAmountValueExpr = xPath.compile("InvoiceAmount/NetAmount/Amount/Value/text()"); + XPathExpression netAmountExchangeRateExpr = xPath + .compile("InvoiceAmount/NetAmount/Amount/ExchangeRate/text()"); + + XPathExpression netActivityTypeExpr = xPath + .compile("InvoiceAmount/ActivityType/Codes/Code[@Type='cs']/text()"); NodeList rowList = doc.getElementsByTagName("InvoiceRow"); for (int i = 0; i < rowList.getLength(); i++) { @@ -505,10 +550,41 @@ public class CargosoftXMLInvoiceImportImportService { // Get the FileNumber value String fileNumber = (String) fileNumberExpr.evaluate(rowNode, XPathConstants.STRING); childItemCol.setItemValue("datev.text", fileNumber); + + // speichere die Position in invoice.positions zur suche nach dem + // Positionskennzeichen + workitem.appendItemValue("invoice.positions", fileNumber); + String currency = (String) netAmountCurrencyExpr.evaluate(rowNode, XPathConstants.STRING); childItemCol.setItemValue("datev.wkz", currency); + // Umsatz String umsatz = (String) netAmountValueExpr.evaluate(rowNode, XPathConstants.STRING); - childItemCol.setItemValue("datev.umsatz", Double.parseDouble(umsatz)); + double dUmsatz = Double.parseDouble(umsatz); + childItemCol.setItemValue("datev.umsatz", dUmsatz); + // Kurs + String kurs = (String) netAmountExchangeRateExpr.evaluate(rowNode, XPathConstants.STRING); + if (kurs != null && !kurs.isEmpty()) { + Double dKurs = Double.parseDouble(kurs); + childItemCol.setItemValue("datev.kurs", dKurs); + // Basisumsatz + if (dKurs != 0) { + double basisUmsatz = dUmsatz / dKurs; + double gerundeterBasisUmsatz = Math.round(basisUmsatz * 100) / 100.0; + childItemCol.setItemValue("datev.basisumsatz", gerundeterBasisUmsatz); + } + } + + String activityType = (String) netActivityTypeExpr.evaluate(rowNode, XPathConstants.STRING); + childItemCol.setItemValue("category", activityType); + + // Invoice Type S/H + if ("G".equals(workitem.getItemValueString("invoice.type"))) { + // Gutschrift + childItemCol.setItemValue("datev.shzeichen", "S"); + } else { + // Rechnung + childItemCol.setItemValue("datev.shzeichen", "H"); + } childItems.add(childItemCol); } @@ -521,6 +597,8 @@ public class CargosoftXMLInvoiceImportImportService { // Set child items InvoiceUtil.implodeChildList(workitem, childItems); + // invoice.text ist erste position + workitem.setItemValue("invoice.text", workitem.getItemValueString("invoice.positions")); }