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 4931ff2..5f5f558 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
@@ -49,6 +49,7 @@ public class DatevCargosoftImportAdapter implements SignalAdapter {
public static final String ENCODING = "ISO-8859-1";
public static final String CHILD_ITEM_PROPERTY = "_ChildItems";
+ public static final String REGEX_IMPORTTEXTPATTERN = "^R[1-8] .*$";
@Inject
WorkflowService workflowService;
@@ -102,6 +103,8 @@ public class DatevCargosoftImportAdapter implements SignalAdapter {
int positions = 0;
int invoices = 0;
int dupplicates = 0;
+ int rueckstellungen=0;
+ int eingangsrechnungen=0;
String dataLine;
// Start Datum Wirtschaftsjahr berechnen (JJJJMMTT)
@@ -168,10 +171,22 @@ public class DatevCargosoftImportAdapter implements SignalAdapter {
// Skip Eingangsrechnungen
if (!gegenKonto.startsWith("1")) {
+ eingangsrechnungen++;
// skip
continue;
}
+ // Skip Rückstellung
+ // text darf nicht mit R1 bis R8 beginnen
+ // ^R[1-8] .
+ if (text.matches(REGEX_IMPORTTEXTPATTERN)) {
+ rueckstellungen++;
+ // skip
+ continue;
+ }
+
+
+
positions++;
logger.info("...read dbtr: " + gegenKonto + " beleg-nr: " + belegNummer);
@@ -236,6 +251,14 @@ public class DatevCargosoftImportAdapter implements SignalAdapter {
log(logBuffer, line + " Zeilen eingelesen ");
log(logBuffer, positions + " Rechnungspositionen eingelesen ");
log(logBuffer, invoices + " Rechnungen importiert ");
+
+ if (rueckstellungen>0) {
+ log(logBuffer, rueckstellungen + " Rückstellungen wurden übersprungen.");
+ }
+ if (eingangsrechnungen>0) {
+ log(logBuffer, eingangsrechnungen + " Eingangsrechnungen wurden übersprungen.");
+ }
+
if (dupplicates > 0) {
log(logBuffer, dupplicates + " Rechnungen wurden übersprungen da diese bereits importiert wurden!");
}
diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/mahnlauf/MahnlaufExecuteAdapter.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/mahnlauf/MahnlaufExecuteAdapter.java
new file mode 100644
index 0000000..2374a75
--- /dev/null
+++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/mahnlauf/MahnlaufExecuteAdapter.java
@@ -0,0 +1,61 @@
+package com.alexanderlogistics.mahnlauf;
+
+import java.util.List;
+import java.util.logging.Logger;
+
+import javax.ejb.EJB;
+import javax.inject.Inject;
+
+import org.imixs.workflow.ItemCollection;
+import org.imixs.workflow.SignalAdapter;
+import org.imixs.workflow.engine.ModelService;
+import org.imixs.workflow.engine.WorkflowService;
+import org.imixs.workflow.exceptions.AdapterException;
+import org.imixs.workflow.exceptions.PluginException;
+
+/**
+ * The MahnlaufExecuteAdapter triggers the event 300 for all linked invoices
+ *
+ *
+ * @version 1.0
+ * @author rsoika
+ */
+public class MahnlaufExecuteAdapter implements SignalAdapter {
+
+ @SuppressWarnings("unused")
+ private static Logger logger = Logger.getLogger(MahnlaufExecuteAdapter.class.getName());
+
+ @EJB
+ ModelService modelService;
+
+ @EJB
+ WorkflowService workflowService = null;
+
+ @Inject
+ MahnlaufService mahnlaufService;
+
+ /**
+ * This method finds all invices ($workitemref) and tirgges event 300
+ *
+ * @throws PluginException
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public ItemCollection execute(ItemCollection mahnLaufWorkitem, ItemCollection event)
+ throws AdapterException, PluginException {
+
+ // get all Invoices of this Mahnlauf
+ List refList = mahnLaufWorkitem.getItemValue("$workitemref");
+
+ for (String uniqueId : refList) {
+ ItemCollection invoice = workflowService.getWorkItem(uniqueId);
+ if (invoice != null && (invoice.getTaskID()>=MahnlaufService.TASK_MAHNLAUF_START && invoice.getTaskID()<=MahnlaufService.TASK_MAHNLAUF_END)) {
+ mahnlaufService.processInvoice(invoice.event(MahnlaufService.EVENT_MAHNLAUF_EXECUTE));
+ }
+
+ }
+
+ return mahnLaufWorkitem;
+ }
+
+}
\ No newline at end of file
diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/mahnlauf/MahnlaufRefAddAdapter.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/mahnlauf/MahnlaufRefAddAdapter.java
new file mode 100644
index 0000000..eba02f7
--- /dev/null
+++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/mahnlauf/MahnlaufRefAddAdapter.java
@@ -0,0 +1,160 @@
+package com.alexanderlogistics.mahnlauf;
+
+import java.util.Date;
+import java.util.List;
+import java.util.logging.Logger;
+
+import javax.ejb.EJB;
+import javax.inject.Inject;
+
+import org.imixs.workflow.ItemCollection;
+import org.imixs.workflow.Model;
+import org.imixs.workflow.SignalAdapter;
+import org.imixs.workflow.WorkflowKernel;
+import org.imixs.workflow.engine.ModelService;
+import org.imixs.workflow.engine.WorkflowService;
+import org.imixs.workflow.exceptions.AdapterException;
+import org.imixs.workflow.exceptions.ModelException;
+import org.imixs.workflow.exceptions.PluginException;
+import org.imixs.workflow.exceptions.QueryException;
+import org.imixs.workflow.sepa.services.SepaWorkflowService;
+
+/**
+ * The MahnlaufRefAddAdapter links an invoice with a Mahnlauf for the
+ * dbtr.number item . If there is currently no open Mahnlauf for this key, the
+ * adapter automatically creates a new process instance. If a manhlauf for this
+ * dbt.number is found, the invoice is just added.
+ *
+ * If the invoice has already been linked to a Mahnlauf nothing happens.
+ *
+ *
+ * @version 1.0
+ * @author rsoika
+ */
+public class MahnlaufRefAddAdapter implements SignalAdapter {
+
+ private static Logger logger = Logger.getLogger(MahnlaufRefAddAdapter.class.getName());
+
+ @EJB
+ ModelService modelService;
+
+ @EJB
+ WorkflowService workflowService = null;
+
+ @Inject
+ SepaWorkflowService sepaWorkflowService;
+
+ /**
+ * This method finds or create the Mahnlauf and adds a reference ($workitemref)
+ * to the current invoice.
+ *
+ * @throws PluginException
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public ItemCollection execute(ItemCollection invoice, ItemCollection event)
+ throws AdapterException, PluginException {
+
+ String dbtrNumber = invoice.getItemValueString(MahnlaufService.ITEM_DBTR_NUMBER);
+ ItemCollection mahnLaufWorkitem;
+ try {
+ mahnLaufWorkitem = findMahnlauf(dbtrNumber);
+
+ if (mahnLaufWorkitem == null) {
+ // create one...
+ mahnLaufWorkitem = createNewMahnlauf(dbtrNumber, invoice, event);
+ }
+
+ // add Invoice to Mahnlauf
+ List refList = mahnLaufWorkitem.getItemValue("$workitemref");
+ if (!refList.contains(invoice.getUniqueID())) {
+ mahnLaufWorkitem.appendItemValueUnique("$workitemref", invoice.getUniqueID());
+ }
+
+ // set event 100 and process
+ ItemCollection mahnlaufConfig = workflowService.evalWorkflowResult(event, "mahnlauf", invoice, true);
+ int eventID = mahnlaufConfig.getItemValueInteger("event");
+
+ mahnLaufWorkitem.event(eventID);
+ workflowService.processWorkItem(mahnLaufWorkitem);
+
+ } catch (QueryException | ModelException e) {
+ throw new PluginException(MahnlaufRefAddAdapter.class.getName(),
+ MahnlaufService.ERROR_CONFIG, "Unable to create Mahnlauf", e);
+ }
+
+ // set mahnlauf ref
+ invoice.setItemValue("dunning.ref", mahnLaufWorkitem.getUniqueID());
+ return invoice;
+ }
+
+ /**
+ * Helper method finds an open mahnlauf for a debtr.numbre (name)
+ *
+ * @param key
+ * @return
+ * @throws QueryException
+ */
+ public ItemCollection findMahnlauf(String key) throws QueryException {
+ String query = "(type:workitem) AND ($modelversion:mahnlauf*) AND (name:\"" + key + "\")";
+ List resultList = workflowService.getDocumentService().find(query, 1, 0, "$modified", true);
+
+ if (resultList.size() > 0) {
+ return resultList.get(0);
+ }
+ // no mahnaluffound
+ return null;
+ }
+
+ /**
+ * Helper method to create a new Mahnlauf workitem
+ *
+ * @param key
+ * @param invoice
+ * @return
+ * @throws ModelException
+ * @throws PluginException
+ */
+ public ItemCollection createNewMahnlauf(String key, ItemCollection invoice, ItemCollection event)
+ throws ModelException, PluginException {
+ String modelVersion = null;
+ int taskID = -1;
+ int eventID=-1;
+ // test if the event provides a sepa export configuration
+ ItemCollection mahnlaufConfig = workflowService.evalWorkflowResult(event, "mahnlauf", invoice, true);
+ if (mahnlaufConfig != null && mahnlaufConfig.hasItem("modelversion") && mahnlaufConfig.hasItem("task")) {
+ logger.fine("read model information from event");
+ modelVersion = mahnlaufConfig.getItemValueString("modelVersion");
+ taskID = mahnlaufConfig.getItemValueInteger("task");
+ eventID = mahnlaufConfig.getItemValueInteger("event");
+ }
+
+ // build the sepa export workitem....
+ ItemCollection mahnlaufWorkitem = new ItemCollection().model(modelVersion).task(taskID);
+ mahnlaufWorkitem.replaceItemValue("name", key);
+ mahnlaufWorkitem.replaceItemValue(WorkflowKernel.CREATED, new Date());
+ mahnlaufWorkitem.replaceItemValue(WorkflowKernel.MODIFIED, new Date());
+ // set unqiueid
+ mahnlaufWorkitem.setItemValue(WorkflowKernel.UNIQUEID, WorkflowKernel.generateUniqueID());
+
+ // copy dbtr_iban
+ mahnlaufWorkitem.setItemValue(MahnlaufService.ITEM_DBTR_NAME, invoice.getItemValue(MahnlaufService.ITEM_DBTR_NAME));
+ mahnlaufWorkitem.setItemValue(MahnlaufService.ITEM_DBTR_EMAIL, invoice.getItemValue(MahnlaufService.ITEM_DBTR_EMAIL));
+ mahnlaufWorkitem.setItemValue(MahnlaufService.ITEM_DBTR_NUMBER, invoice.getItemValue(MahnlaufService.ITEM_DBTR_NUMBER));
+
+ mahnlaufWorkitem.setItemValue("invoice.language", invoice.getItemValue("invoice.language"));
+
+
+
+ // set workflow group name from the Task Element to identify document in xslt
+ Model model = modelService.getModel(modelVersion);
+ ItemCollection task = model.getTask(taskID);
+ String modelTaskGroupName = task.getItemValueString("txtworkflowgroup"); // DO NOT CHANGE!
+ mahnlaufWorkitem.setItemValue(WorkflowKernel.WORKFLOWGROUP, modelTaskGroupName);
+
+ logger.info("...created new mahnlauf " + key + "...");
+
+ return mahnlaufWorkitem;
+ }
+
+}
\ No newline at end of file
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
new file mode 100644
index 0000000..b5406ff
--- /dev/null
+++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/mahnlauf/MahnlaufService.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Imixs Workflow
+ * Copyright (C) 2001, 2011 Imixs Software Solutions GmbH,
+ * http://www.imixs.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You can receive a copy of the GNU General Public
+ * License at http://www.gnu.org/licenses/gpl.html
+ *
+ * Project:
+ * http://www.imixs.org
+ * http://java.net/projects/imixs-workflow
+ *
+ * Contributors:
+ * Imixs Software Solutions GmbH - initial API and implementation
+ * Ralph Soika - Software Developer
+ *******************************************************************************/
+
+package com.alexanderlogistics.mahnlauf;
+
+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.workflow.ItemCollection;
+import org.imixs.workflow.engine.WorkflowService;
+import org.imixs.workflow.exceptions.AccessDeniedException;
+import org.imixs.workflow.exceptions.ModelException;
+import org.imixs.workflow.exceptions.PluginException;
+import org.imixs.workflow.exceptions.ProcessingErrorException;
+
+/**
+ * Der MahnlaufService wird vom MahnlaufExecuteAdapter um
+ * Ausgangsrechnungen zu akutalisieren.
+ *
+ * @author rsoika
+ *
+ */
+
+@DeclareRoles({ "org.imixs.ACCESSLEVEL.NOACCESS", "org.imixs.ACCESSLEVEL.READERACCESS",
+ "org.imixs.ACCESSLEVEL.AUTHORACCESS", "org.imixs.ACCESSLEVEL.EDITORACCESS",
+ "org.imixs.ACCESSLEVEL.MANAGERACCESS" })
+@RolesAllowed({ "org.imixs.ACCESSLEVEL.NOACCESS", "org.imixs.ACCESSLEVEL.READERACCESS",
+ "org.imixs.ACCESSLEVEL.AUTHORACCESS", "org.imixs.ACCESSLEVEL.EDITORACCESS",
+ "org.imixs.ACCESSLEVEL.MANAGERACCESS" })
+@Singleton
+@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";
+
+
+ @Inject
+ WorkflowService workflowService;
+
+
+
+ /**
+ * * Diese Method processed eine Invoice mit Manager Rechnten
+ *
+ * @throws PluginException
+ * @throws ModelException
+ * @throws ProcessingErrorException
+ * @throws AccessDeniedException
+ */
+ public ItemCollection processInvoice(ItemCollection invoice) throws PluginException {
+ try {
+ return workflowService.processWorkItem(invoice);
+ } catch (AccessDeniedException | ProcessingErrorException | PluginException | ModelException e) {
+ throw new PluginException(PluginException.class.getName(), ERROR_WORKFLOW,
+ "Die Rechnung konnte nicht verarbeitet werden - " + e.getMessage(), e);
+ }
+ }
+
+}
diff --git a/office-alexander-logistics-app/src/test/java/com/alexanderlogistics/TestPostionsnummernRegex.java b/office-alexander-logistics-app/src/test/java/com/alexanderlogistics/TestPostionsnummernRegex.java
index 32c2b47..2e4cda0 100644
--- a/office-alexander-logistics-app/src/test/java/com/alexanderlogistics/TestPostionsnummernRegex.java
+++ b/office-alexander-logistics-app/src/test/java/com/alexanderlogistics/TestPostionsnummernRegex.java
@@ -2,6 +2,8 @@ package com.alexanderlogistics;
import org.junit.Test;
+import com.alexanderlogistics.datev.DatevCargosoftImportAdapter;
+
import junit.framework.Assert;
/**
@@ -12,18 +14,27 @@ import junit.framework.Assert;
*/
public class TestPostionsnummernRegex {
- /**
- * Test positionnummern 'XX-YYY-####-###'
- */
- @Test
- public void testPutFileToFTP() {
+ /**
+ * Test positionnummern 'XX-YYY-####-###'
+ */
+ @Test
+ public void testPutFileToFTP() {
- Assert.assertTrue("AA-BBC-1234-991".matches(InvoicePlugin.REGEX_POSNUMER));
- Assert.assertFalse("aa-BBC-1234-991".matches(InvoicePlugin.REGEX_POSNUMER));
- Assert.assertFalse("CC-BBC-1234-991 ".matches(InvoicePlugin.REGEX_POSNUMER));
-
- Assert.assertTrue("IM-ZEL-2101-005".matches(InvoicePlugin.REGEX_POSNUMER));
-
- }
+ Assert.assertTrue("AA-BBC-1234-991".matches(InvoicePlugin.REGEX_POSNUMER));
+ Assert.assertFalse("aa-BBC-1234-991".matches(InvoicePlugin.REGEX_POSNUMER));
+ Assert.assertFalse("CC-BBC-1234-991 ".matches(InvoicePlugin.REGEX_POSNUMER));
+ Assert.assertTrue("IM-ZEL-2101-005".matches(InvoicePlugin.REGEX_POSNUMER));
+
+ }
+
+
+ @Test
+ public void testCargoImportText() {
+
+ Assert.assertTrue("R3 EX-PRO-2208-054".matches(DatevCargosoftImportAdapter.REGEX_IMPORTTEXTPATTERN));
+ Assert.assertTrue("R3 VP".matches(DatevCargosoftImportAdapter.REGEX_IMPORTTEXTPATTERN));
+ Assert.assertFalse("R LA-HOL-2208-013".matches(DatevCargosoftImportAdapter.REGEX_IMPORTTEXTPATTERN));
+
+ }
}
diff --git a/workflow/mahnlauf-de-1.0.0.bpmn b/workflow/mahnlauf-de-1.0.0.bpmn
index 77ff780..b3a55c4 100644
--- a/workflow/mahnlauf-de-1.0.0.bpmn
+++ b/workflow/mahnlauf-de-1.0.0.bpmn
@@ -32,7 +32,8 @@
-
+
+