diff --git a/office-alexander-logistics-app/pom.xml b/office-alexander-logistics-app/pom.xml index 289bd47..091b2b2 100644 --- a/office-alexander-logistics-app/pom.xml +++ b/office-alexander-logistics-app/pom.xml @@ -1,6 +1,5 @@ - + 4.0.0 office-alexander-logistics @@ -77,7 +76,7 @@ - + kubernetes @@ -94,21 +93,17 @@ - + - - + + - + @@ -122,7 +117,7 @@ - + @@ -137,9 +132,9 @@ ${custom.webResources} - **/WEB-INF/* - - + **/WEB-INF/* + + target/overlay-war-folder @@ -155,10 +150,45 @@ + + + org.imixs.maven + manik-hotdeploy-maven-plugin + 2.0.0 + + + install + + deploy + + + + + + + + + target/*.{war,ear,jar} + ../docker/deployments/ + true + + + + + src/main/webapp + ../docker/deployments/office-alexander-logistics.war + + + + + + + + - - + + @@ -198,66 +228,66 @@ jar compile - + org.imixs.workflow imixs-office-workflow-app war - + org.imixs.workflow imixs-office-workflow-util compile - + org.imixs.workflow imixs-archive-api compile - - - + + + org.imixs.workflow imixs-archive-documents compile - - - + + + org.imixs.workflow imixs-archive-importer compile - + - org.imixs.workflow - imixs-adapters-sepa - compile + org.imixs.workflow + imixs-adapters-sepa + compile - org.imixs.workflow - imixs-adapters-datev - compile + org.imixs.workflow + imixs-adapters-datev + compile - org.imixs.workflow - imixs-adapters-qrcode - compile + org.imixs.workflow + imixs-adapters-qrcode + compile - org.imixs.workflow - imixs-adapters-poi - compile + org.imixs.workflow + imixs-adapters-poi + compile - + org.imixs.workflow @@ -265,7 +295,7 @@ ${org.imixs.ml.version} compile - + org.apache.pdfbox @@ -273,7 +303,7 @@ 2.0.19 compile - + net.sf.saxon @@ -287,7 +317,7 @@ commons-net commons-net 3.6 - - + + \ No newline at end of file diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/OPListController.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/OPListController.java index 8ddc1aa..9f96edb 100644 --- a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/OPListController.java +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/OPListController.java @@ -19,9 +19,6 @@ import org.imixs.workflow.engine.WorkflowService; import org.imixs.workflow.exceptions.QueryException; import org.imixs.workflow.faces.data.WorkflowController; import org.imixs.workflow.faces.data.WorkflowEvent; -import org.imixs.workflow.office.forms.ChildItemController; -import org.imixs.workflow.office.forms.WorkitemLinkController; - /** * Der OPListeController dient dazu eine liste aller offenen Ausgangsrechnungen @@ -45,8 +42,6 @@ public class OPListController implements Serializable { private static final long serialVersionUID = 1L; public static final int TASK_ERSTELLUNG = 1000; - public static final String ITEM_PAYMENT_DETAILS="payment.details"; - private static Logger logger = Logger.getLogger(OPListController.class.getName()); private String lastDbtrNumber = null; @@ -55,12 +50,13 @@ public class OPListController implements Serializable { @Inject protected WorkflowController workflowController; - + @Inject protected WorkflowService workflowService; @Inject - protected WorkitemLinkController workitemLinkController; + ZahlungseingangService zahlungseingangService; + @Inject protected DocumentService documentService; @@ -79,7 +75,7 @@ public class OPListController implements Serializable { */ @SuppressWarnings("unchecked") public List getInvoices(String _dbtrNumber) { - + // Compute all open invoices if TASK_ERSTELLUNG.... if (workflowController.getWorkitem().getTaskID() == TASK_ERSTELLUNG) { @@ -126,17 +122,17 @@ public class OPListController implements Serializable { } } - // finally we set the 'selection' item depending on the $workitemList + // finally we set the 'selection' item depending on the $workitemList // and the payment amount form the 'payment.details' List selection = workflowController.getWorkitem().getItemValue("$workitemref"); - List paymentList=explodePaymentDetails(workflowController.getWorkitem()); + List paymentList = zahlungseingangService.loadPaymentDetails(workflowController.getWorkitem()); for (ItemCollection invoice : invoiceList) { if (selection.contains(invoice.getUniqueID())) { invoice.setItemValue("selected", true); // set amount - for (ItemCollection payment: paymentList) { + for (ItemCollection payment : paymentList) { if (invoice.getUniqueID().equals(payment.getUniqueID())) { - invoice.setItemValue("payment.amount",payment.getItemValue("payment.amount")); + invoice.setItemValue("payment.amount", payment.getItemValue("payment.amount")); break; } } @@ -146,7 +142,6 @@ public class OPListController implements Serializable { return invoiceList; } - // /** // * Liefert die Payments die mit diesem workitem verbunden sind... // * @return @@ -169,30 +164,6 @@ public class OPListController implements Serializable { // return result; // } - /** - * Convert the List of ItemCollections back into a List of Map elements - * - * @param workitem - */ - @SuppressWarnings({ "rawtypes" }) - protected List explodePaymentDetails(ItemCollection workitem) { - // convert current list of childItems into ItemCollection elements - ArrayList childItems = new ArrayList(); - - List mapOrderItems = workitem.getItemValue(ITEM_PAYMENT_DETAILS); - int pos = 1; - for (Object mapOderItem : mapOrderItems) { - - if (mapOderItem instanceof Map) { - ItemCollection itemCol = new ItemCollection((Map) mapOderItem); - itemCol.replaceItemValue("numPos", pos); - - childItems.add(itemCol); - pos++; - } - } - return childItems; - } /** * On Before Process we store the selected invoices in $worktiemRef * @@ -201,15 +172,14 @@ public class OPListController implements Serializable { public void onWorkflowEvent(@Observes WorkflowEvent workflowEvent) { if (workflowEvent == null || workflowEvent.getWorkitem() == null) { return; - } - // store a collection of child items - if (workflowEvent.getEventType() == WorkflowEvent.WORKITEM_BEFORE_PROCESS) { + // store a collection of child items if you are in a Zahlungseingang + if (workflowEvent.getWorkitem().getModelVersion().startsWith("zahlungseingang") + && workflowEvent.getEventType() == WorkflowEvent.WORKITEM_BEFORE_PROCESS) { updateChildList(workflowEvent.getWorkitem()); - } } - + public ItemCollection loadInvoice(String id) { return documentService.load(id); } @@ -240,9 +210,9 @@ public class OPListController implements Serializable { } // rond with 2 digits - workitem.replaceItemValue("payment.total", Math.round(paymentTotal * 100.0) / 100.0); + workitem.replaceItemValue("payment.total", Math.round(paymentTotal * 100.0) / 100.0); // update childitems - workitem.replaceItemValue(ITEM_PAYMENT_DETAILS, mapInvoiceItems); + workitem.replaceItemValue(ZahlungseingangService.ITEM_PAYMENT_DETAILS, mapInvoiceItems); // Update $workitemref workitem.setItemValue("$workitemref", selectionList); } @@ -263,6 +233,15 @@ public class OPListController implements Serializable { workflowController.getWorkitem().setItemValue("dbtr.number", dbtrNumber); } + + /** + * Hilfsmethode delegates to ZahlungseingangServcie + * @param payment + * @return + */ + public List loadPaymentDetails(ItemCollection payment) { + return zahlungseingangService.loadPaymentDetails(payment); + } /** * Berechnet den gesammten OP Saldo * @@ -278,5 +257,4 @@ public class OPListController implements Serializable { } - } diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/ZahlungseingangSaldoAdapter.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/ZahlungseingangSaldoAdapter.java new file mode 100644 index 0000000..b7a3912 --- /dev/null +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/ZahlungseingangSaldoAdapter.java @@ -0,0 +1,105 @@ +package com.alexanderlogistics; + +import java.util.List; +import java.util.logging.Logger; + +import javax.inject.Inject; + +import org.imixs.workflow.ItemCollection; +import org.imixs.workflow.SignalAdapter; +import org.imixs.workflow.exceptions.AdapterException; +import org.imixs.workflow.exceptions.PluginException; + +/** + * Der ZahlungseingangSaldoAdapter korrigiert den Saldo einer Ausgangsrechnung + * anhand der Zahlungsdaten in einem Zahlungseingangsworkflow. + *

+ * Die verknüpften Rechnungen in einem Zahlungseingang können am Item + * $workitemref ermittelt werden. + *

+ * Relevant für den Abgleich sin die felder: + *

    + *
  • invoice.currency + *
  • payment.amount + *

    + * com.alexanderlogistics.ZahlungseingangSaldoAdapter + * + * @version 1.0 + * @author rsoika + */ +public class ZahlungseingangSaldoAdapter implements SignalAdapter { + + private static Logger logger = Logger.getLogger(ZahlungseingangSaldoAdapter.class.getName()); + + + @Inject + ZahlungseingangService zahlungseingangService; + + /** + * This method finds the outgoing invoicdes and updates the saldo + * (payment.total). + * + * @throws PluginException + */ + @Override + public ItemCollection execute(ItemCollection document, ItemCollection event) + throws AdapterException, PluginException { + + updateSaldo(document); + + return document; + } + + /** + * Diese method hängt eine referenz der aktuellen Rechnung an den Zahlungsavis + * + * @param document + * @throws PluginException + */ + private void updateSaldo(ItemCollection document) throws PluginException { + + // payment currency + String paymentCurrency = document.getItemValueString("payment.currency"); + + List paymentDetails = zahlungseingangService.loadPaymentDetails(document); + + logger.info("......Updating " + paymentDetails.size() + " outgoing invoices...."); + for (ItemCollection payment : paymentDetails) { + + ItemCollection invoice = zahlungseingangService.findInvoice(payment.getUniqueID()); + + if (invoice != null) { + String invoiceNumber = invoice.getItemValueString("invoice.number"); + String invoiceCurrency = invoice.getItemValueString("invoice.currency"); + + if (!invoiceCurrency.equals(paymentCurrency)) { + throw new PluginException(PluginException.class.getName(),ZahlungseingangService.ERROR_PAYMENT_BOOKING_FAILED, + "Der Zahlungseingang kann nicht verbucht werden, da die Währung " + paymentCurrency + + " nicht mit der Währung der Rechnung " + invoiceNumber + " übereinstimmt!"); + } + + float invoiceSaldo = invoice.getItemValueFloat("invoice.saldo"); + float paymentAmount = payment.getItemValueFloat("payment.amount"); + + if (Math.abs(paymentAmount) > Math.abs(invoiceSaldo)) { + throw new PluginException(PluginException.class.getName(), ZahlungseingangService.ERROR_PAYMENT_BOOKING_FAILED, + "Der Zahlungseingang kann nicht verbucht werden, da der Restsaldo der Rechnung " + + invoiceNumber + " kleiner als der Zahlbetrag ist!"); + } + + + invoiceSaldo=invoiceSaldo-paymentAmount; + invoice.setItemValue("invoice.saldo", invoiceSaldo); + invoice.event(ZahlungseingangService.EVENT_UPDATE_INVOICE); + zahlungseingangService.processInvoice(invoice); + + + } else { + throw new PluginException(PluginException.class.getName(), ZahlungseingangService.ERROR_PAYMENT_BOOKING_FAILED, + "Rechnung konnte nicht gefunden werden!"); + } + } + + } + +} \ No newline at end of file diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/ZahlungseingangService.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/ZahlungseingangService.java new file mode 100644 index 0000000..558b8a4 --- /dev/null +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/ZahlungseingangService.java @@ -0,0 +1,134 @@ +/******************************************************************************* + * 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; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; + +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.DocumentService; +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 ZahlungseingangService wird vom ZahlungseingangSaldoAdapter verwendet 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 ZahlungseingangService { + + public static final int EVENT_UPDATE_INVOICE = 200; + public static final String ERROR_PAYMENT_BOOKING_FAILED = "PAYMENT_BOOKING_FAILED"; + public static final String ITEM_PAYMENT_DETAILS = "payment.details"; + + @SuppressWarnings("unused") + private static Logger logger = Logger.getLogger(ZahlungseingangService.class.getName()); + + @Inject + DocumentService documentService; + + @Inject + WorkflowService workflowService; + + /** + * Diese Method sucht eine Invoice mit Manager Rechnten + * + * @throws PluginException + */ + public ItemCollection findInvoice(String id) throws PluginException { + + return documentService.load(id); + } + + /** + * * 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_PAYMENT_BOOKING_FAILED, + "Der Rechnungs Saldo konnte nicht korrekt verbucht werden - " + e.getMessage(), e); + } + } + + /** + * The method returns a List of ItemCollection holding the payment details + * + * + * Convert the List of ItemCollections back into a List of Map elements + * + * @param invoice + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + public List loadPaymentDetails(ItemCollection payment) { + ArrayList childItems = new ArrayList(); + + List mapOrderItems = payment.getItemValue(ITEM_PAYMENT_DETAILS); + int pos = 1; + for (Object mapOderItem : mapOrderItems) { + + if (mapOderItem instanceof Map) { + ItemCollection itemCol = new ItemCollection((Map) mapOderItem); + itemCol.replaceItemValue("numPos", pos); + + childItems.add(itemCol); + pos++; + } + } + return childItems; + } + +} diff --git a/office-alexander-logistics-app/src/main/webapp/pages/workitems/forms/alexander/section_payments.xhtml b/office-alexander-logistics-app/src/main/webapp/pages/workitems/forms/alexander/section_payments.xhtml index c6d4327..43b5aba 100644 --- a/office-alexander-logistics-app/src/main/webapp/pages/workitems/forms/alexander/section_payments.xhtml +++ b/office-alexander-logistics-app/src/main/webapp/pages/workitems/forms/alexander/section_payments.xhtml @@ -15,14 +15,15 @@ - +
    - - - + + + + @@ -32,23 +33,52 @@ + + + + - + + + + + + + + + + + + + + + + + -
    #Datum *BetragZahlungseingangReferenzBetragZahlung Währung
    - #{payment.item['name']} + #{payment.item['$workflowsummary']} #{payment.item['payment.total']} - + + + +
    - Summe: + Saldo: + diff --git a/workflow/rechnungsausgang-de-1.0.0.bpmn b/workflow/rechnungsausgang-de-1.0.0.bpmn index 5c9982f..9a6ec18 100644 --- a/workflow/rechnungsausgang-de-1.0.0.bpmn +++ b/workflow/rechnungsausgang-de-1.0.0.bpmn @@ -62,6 +62,7 @@ ExclusiveGateway_4 IntermediateThrowEvent_3 IntermediateCatchEvent_18 + IntermediateCatchEvent_1 Task_3 @@ -314,6 +315,7 @@ Bei Fragen wenden Sie sich bitte an info@imixs.com SequenceFlow_33 SequenceFlow_20 SequenceFlow_44 + SequenceFlow_6 SequenceFlow_39 SequenceFlow_46 SequenceFlow_2 @@ -1513,6 +1515,78 @@ Betrag: invoice.total invoice.currency + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ]]> + + + + + + + + + + + + false + + + + + SequenceFlow_6 + + @@ -1753,6 +1827,12 @@ Betrag: invoice.total invoice.currency + + + + + + @@ -1986,6 +2066,12 @@ Betrag: invoice.total invoice.currency + + + + + + diff --git a/workflow/zahlungseingang-de-1.0.0.bpmn b/workflow/zahlungseingang-de-1.0.0.bpmn index 131f90b..052e709 100644 --- a/workflow/zahlungseingang-de-1.0.0.bpmn +++ b/workflow/zahlungseingang-de-1.0.0.bpmn @@ -31,6 +31,7 @@ + Task_1 IntermediateCatchEvent_3 EventBasedGateway_1 + IntermediateCatchEvent_1 @@ -217,6 +219,7 @@ result.isValid=true; $workflowgroup - $workflowstatus]]> SequenceFlow_14 SequenceFlow_4 + SequenceFlow_3 SequenceFlow_1 @@ -494,6 +497,77 @@ result.isValid=true; ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ]]> + + + + + + + + + + + + false + + + + SequenceFlow_3 + + + DataOutput_1 + + + DataOutput_1 + + + + @@ -586,6 +660,12 @@ result.isValid=true; + + + + + + @@ -652,6 +732,12 @@ result.isValid=true; + + + + + +