diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 926c39a..4d1537f 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,7 +1,13 @@ # Versionen +### 1.2.7 (Development) -### 1.2.6 (Development) + Erweiterte Kreditoren Verwaltung. Es können bis zu 4 IBAN/BIC Kombinationen pro Kreditor erfasst werden. + + Wenn vom Benutezr bei der Rechnungserfassugn eine Kombination eingegeben wird die noch nicht gespeichert war, + wird diese aufgenomen und die anderen rutschen nach unten. + +### 1.2.6 Übernahme von IBAN BIC aus kreditoren verwaltung diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/CargosoftController.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/CargosoftController.java index e79f5ea..75773d8 100644 --- a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/CargosoftController.java +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/CargosoftController.java @@ -121,7 +121,7 @@ public class CargosoftController implements Serializable { searchResult.add(new KreditorSearchEntry(cdtrNo, display, buildJsonData(cdtr, cdtr.getItemValueString("cdtr.iban"), cdtr.getItemValueString("cdtr.bic")))); // haben wir noch weitere IBAN/BIC kombis? - for (int j = 1; j < 4; j++) { + for (int j = 1; j <=4 ; j++) { if (!cdtr.getItemValueString("cdtr.iban" + j).isEmpty()) { // Dublette mit alternativer IBAN erzeugen display = cdtrNo + " - " + cdtr.getItemValueString("_VENDOR_Name"); @@ -187,6 +187,7 @@ public class CargosoftController implements Serializable { add("iban", cdtr.getItemValueString("cdtr.iban")). // add("bic", cdtr.getItemValueString("cdtr.bic")). // // add ibans für kreditoren verwaltung + add("iban2", cdtr.getItemValueString("cdtr.iban2")). // add("iban3", cdtr.getItemValueString("cdtr.iban3")). // add("iban4", cdtr.getItemValueString("cdtr.iban4")). // add("bic2", cdtr.getItemValueString("cdtr.bic2")). // diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/InvoicePlugin.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/InvoicePlugin.java index 921c280..1ff6449 100644 --- a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/InvoicePlugin.java +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/InvoicePlugin.java @@ -6,6 +6,8 @@ import java.util.List; import java.util.Map; import java.util.logging.Logger; +import javax.inject.Inject; + import org.imixs.workflow.ItemCollection; import org.imixs.workflow.engine.plugins.AbstractPlugin; import org.imixs.workflow.exceptions.PluginException; @@ -35,342 +37,397 @@ import org.imixs.workflow.exceptions.QueryException; */ public class InvoicePlugin extends AbstractPlugin { - public static final int TASK_ERFASSUNG = 5001; - public static final int TASK_SACHPRUEFUNG = 5200; - public static final int TASK_SACHPRUEFUNG_DELEGATION = 5210; - public static final int EVENT_FREIGEBEN = 20; - public static final String ITEM_INVOICE_PERIOD = "invoice.period"; + public static final int TASK_ERFASSUNG = 5001; + public static final int TASK_SACHPRUEFUNG = 5200; + public static final int TASK_SACHPRUEFUNG_DELEGATION = 5210; + public static final int EVENT_FREIGEBEN = 20; + public static final String ITEM_INVOICE_PERIOD = "invoice.period"; - public static final String CHILD_ITEM_PROPERTY = "_ChildItems"; - public static final String ERROR_MISSING_DATA = "MISSING_DATA"; - public static final String ERROR_DUPPLICATE_INVOICE_NUMBER = "DUPPLICATE_INVOICE_NUMBER"; + public static final String CHILD_ITEM_PROPERTY = "_ChildItems"; + public static final String ERROR_MISSING_DATA = "MISSING_DATA"; + public static final String ERROR_DUPPLICATE_INVOICE_NUMBER = "DUPPLICATE_INVOICE_NUMBER"; + public static final String ERROR_NEW_IBANBIC = "NEW_IBANBIC"; - // XX-YYY-####-### - public static final String REGEX_POSNUMER = "([A-Z]{2}-[A-Z]{3}-[0-9]{4}-[0-9]{3})"; + // XX-YYY-####-### + public static final String REGEX_POSNUMER = "([A-Z]{2}-[A-Z]{3}-[0-9]{4}-[0-9]{3})"; - private static Logger logger = Logger.getLogger(InvoicePlugin.class.getName()); + private static Logger logger = Logger.getLogger(InvoicePlugin.class.getName()); - /** - * Test childworkitems for empty lines - * - * @throws PluginException - if data is missing - * - **/ - @Override - public ItemCollection run(ItemCollection workitem, ItemCollection event) throws PluginException { + @Inject + KreditorService kreditorService; - updateImg(workitem); - - // skip if validaten tag is required=false - ItemCollection evalItemCollection = this.getWorkflowService().evalWorkflowResult(event, "validation", workitem); - if (evalItemCollection != null) { - // evaluate the validation rules... - if ("false".equalsIgnoreCase(evalItemCollection.getItemValueString("required"))) { - return workitem; - } - } + /** + * Test childworkitems for empty lines + * + * @throws PluginException - if data is missing + * + **/ + @Override + public ItemCollection run(ItemCollection workitem, ItemCollection event) throws PluginException { - boolean isPublicEvent = !("0".equals(event.getItemValueString("keypublicresult"))); - boolean isCargoRechnung = ("Rechnungseingang".equals(workitem.getWorkflowGroup())); + updateImg(workitem); - // Payment.type muss immer eingetragne werden! - if (isPublicEvent && workitem.getTaskID() >= TASK_ERFASSUNG && workitem.getEventID() < 900) { - if (workitem.getItemValueString("payment.type").trim().isEmpty()) { - // throw a plugin exception! - throw new PluginException(InvoicePlugin.class.getName(), ERROR_MISSING_DATA, - "Eingabefehler - Bitte wählen Sie eine Zahlungsart aus!"); - } - // doppelte Rechnungsnummer prüfen - if (workitem.getTaskID() == TASK_ERFASSUNG) { - validateInvoiceNumber(workitem); - } + // skip if validaten tag is required=false + ItemCollection evalItemCollection = this.getWorkflowService().evalWorkflowResult(event, "validation", workitem); + if (evalItemCollection != null) { + // evaluate the validation rules... + if ("false".equalsIgnoreCase(evalItemCollection.getItemValueString("required"))) { + return workitem; + } + } - if (workitem.getTaskID() == TASK_ERFASSUNG || ((workitem.getTaskID() == TASK_SACHPRUEFUNG - || workitem.getTaskID() == TASK_SACHPRUEFUNG_DELEGATION) - && workitem.getEventID() == EVENT_FREIGEBEN)) { - // Buchungsperiode auf plausi prüfen - if (isCargoRechnung && "workitem".equals(workitem.getType())) { - validateBuchungsperiode(workitem.getItemValueString(ITEM_INVOICE_PERIOD)); - } - // Cargosoft Kreditorennnummer prüfen - if (isCargoRechnung) { - validateCargosoftCdtrNumber(workitem); - } - } - } + boolean isPublicEvent = !("0".equals(event.getItemValueString("keypublicresult"))); + boolean isCargoRechnung = ("Rechnungseingang".equals(workitem.getWorkflowGroup())); - // die prüfung der positionsnummern und Category erfolgt nur im Status - // Sachprüfung (5200) und nur beim Freigeben (20)! - if (isCargoRechnung - && ((workitem.getTaskID() == TASK_SACHPRUEFUNG || workitem.getTaskID() == TASK_SACHPRUEFUNG_DELEGATION) - && workitem.getEventID() == EVENT_FREIGEBEN)) { - List childs = explodeChildList(workitem); - for (ItemCollection posItem : childs) { - if (posItem.getItemValueString("name").trim().isEmpty()) { - // throw a plugin exception - because name is missing! - throw new PluginException(InvoicePlugin.class.getName(), ERROR_MISSING_DATA, - "Eingabefehler - Die Positionsnummer in Zeile " + posItem.getItemValueString("numpos") - + " muss ausgefüllt sein!"); - } + // Payment.type muss immer eingetragne werden! + if (isPublicEvent && workitem.getTaskID() >= TASK_ERFASSUNG && workitem.getEventID() < 900) { + if (workitem.getItemValueString("payment.type").trim().isEmpty()) { + // throw a plugin exception! + throw new PluginException(InvoicePlugin.class.getName(), ERROR_MISSING_DATA, + "Eingabefehler - Bitte wählen Sie eine Zahlungsart aus!"); + } + // doppelte Rechnungsnummer prüfen + if (workitem.getTaskID() == TASK_ERFASSUNG) { + validateInvoiceNumber(workitem); - // validate pos for regex pattern 'XX-YYY-####-###' - if (!posItem.getItemValueString("name").matches(REGEX_POSNUMER)) { - // throw a plugin exception - because name is missing! - throw new PluginException(InvoicePlugin.class.getName(), ERROR_MISSING_DATA, - "Eingabefehler - Die Positionsnummer in Zeile " + posItem.getItemValueString("numpos") - + " muss im Format 'XX-YYY-####-###' eingegeben werden!"); - } + checkIBANNumber(workitem); - if (posItem.getItemValueString("category").trim().isEmpty()) { - // throw a plugin exception - because name is missing! - throw new PluginException(InvoicePlugin.class.getName(), ERROR_MISSING_DATA, - "Eingabefehler - Die Leistungsart in Zeile " + posItem.getItemValueString("numpos") - + " muss ausgefüllt sein!"); - } + } - if (posItem.getItemValueString("tax").trim().isEmpty()) { - // throw a plugin exception - because name is missing! - throw new PluginException(InvoicePlugin.class.getName(), ERROR_MISSING_DATA, - "Eingabefehler - Die Steuer in Zeile " + posItem.getItemValueString("numpos") - + " muss ausgefüllt sein!"); - } + if (workitem.getTaskID() == TASK_ERFASSUNG || ((workitem.getTaskID() == TASK_SACHPRUEFUNG + || workitem.getTaskID() == TASK_SACHPRUEFUNG_DELEGATION) + && workitem.getEventID() == EVENT_FREIGEBEN)) { + // Buchungsperiode auf plausi prüfen + if (isCargoRechnung && "workitem".equals(workitem.getType())) { + validateBuchungsperiode(workitem.getItemValueString(ITEM_INVOICE_PERIOD)); + } + // Cargosoft Kreditorennnummer prüfen + if (isCargoRechnung) { + validateCargosoftCdtrNumber(workitem); + } + } + } - if (posItem.getItemValueFloat("amount") == 0) { - // throw a plugin exception - because name is missing! - throw new PluginException(InvoicePlugin.class.getName(), ERROR_MISSING_DATA, - "Eingabefehler - Der Nettobetrag in Zeile " + posItem.getItemValueString("numpos") - + " darf nicht 0 sein!"); - } + // die prüfung der positionsnummern und Category erfolgt nur im Status + // Sachprüfung (5200) und nur beim Freigeben (20)! + if (isCargoRechnung + && ((workitem.getTaskID() == TASK_SACHPRUEFUNG || workitem.getTaskID() == TASK_SACHPRUEFUNG_DELEGATION) + && workitem.getEventID() == EVENT_FREIGEBEN)) { + List childs = explodeChildList(workitem); + for (ItemCollection posItem : childs) { + if (posItem.getItemValueString("name").trim().isEmpty()) { + // throw a plugin exception - because name is missing! + throw new PluginException(InvoicePlugin.class.getName(), ERROR_MISSING_DATA, + "Eingabefehler - Die Positionsnummer in Zeile " + posItem.getItemValueString("numpos") + + " muss ausgefüllt sein!"); + } - // Buchunsperiode - if (!posItem.getItemValueString(ITEM_INVOICE_PERIOD).trim().isEmpty()) { - validateBuchungsperiode(posItem.getItemValueString(ITEM_INVOICE_PERIOD)); + // validate pos for regex pattern 'XX-YYY-####-###' + if (!posItem.getItemValueString("name").matches(REGEX_POSNUMER)) { + // throw a plugin exception - because name is missing! + throw new PluginException(InvoicePlugin.class.getName(), ERROR_MISSING_DATA, + "Eingabefehler - Die Positionsnummer in Zeile " + posItem.getItemValueString("numpos") + + " muss im Format 'XX-YYY-####-###' eingegeben werden!"); + } - } - } + if (posItem.getItemValueString("category").trim().isEmpty()) { + // throw a plugin exception - because name is missing! + throw new PluginException(InvoicePlugin.class.getName(), ERROR_MISSING_DATA, + "Eingabefehler - Die Leistungsart in Zeile " + posItem.getItemValueString("numpos") + + " muss ausgefüllt sein!"); + } - // Ergaenzung 18.05.2021: - // es kann vorkommen, das die Anwender abweichende Buchungsperioden eingeben so - // das die Hauptbuchungsperiode gar ncht merh vorkommt. Das darf aber nicht der - // fall sein. - // Im folgenden überprüfen wir ob eine Buchungszeile vorkommt in der keine oder - // die Hauptbuchunsperiode ausgewählt wurde. Ist das nicht der Fal gibt es eine - // Fehlermeldung für den Anwendere - if (isCargoRechnung && childs.size() > 0) { - String hauptBuchungsperiode = workitem.getItemValueString("invoice.period"); - boolean buchungsperiodenValid = false; - for (ItemCollection posItem : childs) { - String posBuchungsperiode = posItem.getItemValueString("invoice.period"); - if (posBuchungsperiode.isEmpty() || posBuchungsperiode.equals(hauptBuchungsperiode)) { - // alles fein! - buchungsperiodenValid = true; - } - } - if (buchungsperiodenValid == false) { - // fehlerhafte Buchungsperioden. - throw new PluginException(InvoicePlugin.class.getName(), ERROR_MISSING_DATA, - "Eingabefehler - Bitte überprüfen Sie die Hauptbuchungsperiode mit den Buchungsperioden der einzelnen Positionen!"); - } - } + if (posItem.getItemValueString("tax").trim().isEmpty()) { + // throw a plugin exception - because name is missing! + throw new PluginException(InvoicePlugin.class.getName(), ERROR_MISSING_DATA, + "Eingabefehler - Die Steuer in Zeile " + posItem.getItemValueString("numpos") + + " muss ausgefüllt sein!"); + } - } - - - + if (posItem.getItemValueFloat("amount") == 0) { + // throw a plugin exception - because name is missing! + throw new PluginException(InvoicePlugin.class.getName(), ERROR_MISSING_DATA, + "Eingabefehler - Der Nettobetrag in Zeile " + posItem.getItemValueString("numpos") + + " darf nicht 0 sein!"); + } - return workitem; - } + // Buchunsperiode + if (!posItem.getItemValueString(ITEM_INVOICE_PERIOD).trim().isEmpty()) { + validateBuchungsperiode(posItem.getItemValueString(ITEM_INVOICE_PERIOD)); - /** - * Hilfsroutine die das _img item aktualisiert. - */ - private void updateImg(ItemCollection workitem) { - - // Update _img icon list - String img=workitem.getItemValueString("_img"); - // 031=ablehnen - // 100=sofortüberweichung - // 074=mahnen - // sofortüberweisung - if (workitem.getEventID()==96 && !img.contains("100.png")) { - img=img+""; - } - // mahnen - if (workitem.getEventID()==95 && !img.contains("103.png")) { - img=img+""; - - } - // ablehnen - if (workitem.getTaskID()==5100 && workitem.getEventID()==90 && !img.contains("028.png")) { - img=img+""; - } - if (workitem.getTaskID()==5200 && workitem.getEventID()==90 && !img.contains("028.png")) { - img=img+""; - } - workitem.setItemValue("_img", img); - - - - - - /* - for (String entry: eventLog) { - // sofortüberweisung - if (entry.contains(".96") && !img.contains("100.png")) { - img=img+""; - } - // mahnen - if (entry.contains(".95") && !img.contains("074.png")) { - img=img+""; - } - // ablehnen - if (entry.contains("5100.90") && !img.contains("031.png")) { - img=img+""; - } - } - workitem.setItemValue("_img", img); - */ - } - - /** - * Diese Method prüft die Buchungsperiode auf Plausibilität - * - * YYYY(+1)01-12 - * - * z.b. 202110 oder 202107 oder 202201 - * - * @param workitem - * @throws PluginException - */ - private void validateBuchungsperiode(String period) throws PluginException { + } + } - // buchungsperionde nur prüfen wenn noch nicht archiviert - if (!period.isEmpty()) { - LocalDate localDate = LocalDate.now(); - int year = localDate.getYear(); - // build regex.... - String regex = "(" + year + "|" + (year + 1) + "|" + (year - 1) + ")(1[0-2]|0[1-9])"; + // Ergaenzung 18.05.2021: + // es kann vorkommen, das die Anwender abweichende Buchungsperioden eingeben so + // das die Hauptbuchungsperiode gar ncht merh vorkommt. Das darf aber nicht der + // fall sein. + // Im folgenden überprüfen wir ob eine Buchungszeile vorkommt in der keine oder + // die Hauptbuchunsperiode ausgewählt wurde. Ist das nicht der Fal gibt es eine + // Fehlermeldung für den Anwendere + if (isCargoRechnung && childs.size() > 0) { + String hauptBuchungsperiode = workitem.getItemValueString("invoice.period"); + boolean buchungsperiodenValid = false; + for (ItemCollection posItem : childs) { + String posBuchungsperiode = posItem.getItemValueString("invoice.period"); + if (posBuchungsperiode.isEmpty() || posBuchungsperiode.equals(hauptBuchungsperiode)) { + // alles fein! + buchungsperiodenValid = true; + } + } + if (buchungsperiodenValid == false) { + // fehlerhafte Buchungsperioden. + throw new PluginException(InvoicePlugin.class.getName(), ERROR_MISSING_DATA, + "Eingabefehler - Bitte überprüfen Sie die Hauptbuchungsperiode mit den Buchungsperioden der einzelnen Positionen!"); + } + } - if (!period.matches(regex)) { - // throw a plugin exception - because name is missing! - throw new PluginException(InvoicePlugin.class.getName(), ERROR_MISSING_DATA, - "Eingabefehler - Bitte geben Sie eine gültige Buchungsperiode ein! Prüfen Sie auch die Spalte BP in der Positionstabelle."); - } - } - } + } - /** - * Diese Method prüft ob die "invoice.number" bereits einmal im - * Rechnugnsworkflow vergeben wurde. Falls ja wird eine PluginExcpetion - * ausgelöst. - *

- * Query Example: - *

- * NOT $uniqueid:"9f72fa50-4845-41ea-b6b9-ccd518c353be" AND - txtcooperatespace:"9dba107e-f8ef-4150-a832-040d75a6eda7" AND invoice.number:"45" - * - *

- * in case a duplicate invoice was detected the item invoice.number.duplicate is - * filled. This item is used for a conditional event. The case is displayed as a - * warning in the form. - * - * @throws PluginException - * @throws QueryException - * - */ - private void validateInvoiceNumber(ItemCollection workitem) throws PluginException { + return workitem; + } - String invoiceNumber = workitem.getItemValueString("invoice.number"); - // strip - String invoiceNumberStripped=invoiceNumber.replace(" ",""); - workitem.setItemValue("invoice.number.stripped", invoiceNumberStripped); - String invoiceNumberDuplicate = workitem.getItemValueString("invoice.number.duplicate"); + /** + * Hilfsroutine die das _img item aktualisiert. + */ + private void updateImg(ItemCollection workitem) { - // wenn keine Rechnungsnummer eingegeben wurde gehts weiter! - if (invoiceNumber.isEmpty()) { - return; - } + // Update _img icon list + String img = workitem.getItemValueString("_img"); + // 031=ablehnen + // 100=sofortüberweichung + // 074=mahnen + // sofortüberweisung + if (workitem.getEventID() == 96 && !img.contains("100.png")) { + img = img + ""; + } + // mahnen + if (workitem.getEventID() == 95 && !img.contains("103.png")) { + img = img + ""; - // rechnungseingang only workitems... - // Change 11.4.22 - we have now an additional field: invoice.number.stripped - String query = "(type:workitem OR type:workitemarchive) AND ($modelversion:rechnungseingang*) AND NOT ($uniqueid:\"" - + workitem.getUniqueID() + "\") AND ((invoice.number:\"" + invoiceNumberStripped + "\") OR (invoice.number.stripped:\"" + invoiceNumberStripped + "\"))"; - try { - int result = this.getWorkflowService().getDocumentService().count(query, 1); - if (result > 0) { - // wenn _invoicenumber_duplicate bereits gesetzt ist - dann geht es ohne prüfung - // weiter - if (!invoiceNumberDuplicate.isEmpty()) { - logger.warning("...validateion skipped by user with duplicate invoice number: " + invoiceNumber); - } else { + } + // ablehnen + if (workitem.getTaskID() == 5100 && workitem.getEventID() == 90 && !img.contains("028.png")) { + img = img + ""; + } + if (workitem.getTaskID() == 5200 && workitem.getEventID() == 90 && !img.contains("028.png")) { + img = img + ""; + } + workitem.setItemValue("_img", img); - // set _invoicenumber_duplicate - dadurch wird die warnmeldung ausgegeben und - // der Vorgang nicht weitergeleitet - workitem.replaceItemValue("invoice.number.duplicate", invoiceNumber); - throw new PluginException(InvoicePlugin.class.getName(), ERROR_DUPPLICATE_INVOICE_NUMBER, - "ACHTUNG: Die Rechnungsnummer wurde bereits gebucht. Bitte prüfen Sie den Beleg. Sollte die Belegnummer korrekt sein, wiederholen Sie die Aktion."); - } - } else { - // clear ! - workitem.appendItemValue("invoice.number.duplicate.history", - workitem.getItemValueString("invoice.number.duplicate")); - workitem.replaceItemValue("invoice.number.duplicate", ""); - } - } catch (QueryException e) { - throw new PluginException(PluginException.class.getName(), "QUERY ERROR", e.getMessage(), e); - } - } + /* + * for (String entry: eventLog) { // sofortüberweisung if (entry.contains(".96") + * && !img.contains("100.png")) { + * img=img+""; } // mahnen if + * (entry.contains(".95") && !img.contains("074.png")) { + * img=img+""; } // ablehnen if + * (entry.contains("5100.90") && !img.contains("031.png")) { + * img=img+""; } } + * workitem.setItemValue("_img", img); + */ + } - /** - * Hilfsmethod prüft ob die cdtr.nummer mit einer nummer aus der Cargosoft - * Import Datei übereinstimmt. - * - * @param workitem - * @throws PluginException - */ - private void validateCargosoftCdtrNumber(ItemCollection workitem) throws PluginException { - String crdtrNumber = workitem.getItemValueString("cdtr.number"); + /** + * Diese Method prüft die Buchungsperiode auf Plausibilität + * + * YYYY(+1)01-12 + * + * z.b. 202110 oder 202107 oder 202201 + * + * @param workitem + * @throws PluginException + */ + private void validateBuchungsperiode(String period) throws PluginException { - // wenn keine Nummer eingegeben wurde gehts weiter! - if (crdtrNumber.isEmpty()) { - return; - } + // buchungsperionde nur prüfen wenn noch nicht archiviert + if (!period.isEmpty()) { + LocalDate localDate = LocalDate.now(); + int year = localDate.getYear(); + // build regex.... + String regex = "(" + year + "|" + (year + 1) + "|" + (year - 1) + ")(1[0-2]|0[1-9])"; - // search creditor number in cargosoft... - // die cargosoft Kreditornummer beginnt seltsamerweise mit einem K..... - try { - String query = "(type:cargosoftkreditor) AND (name:K" + crdtrNumber + " OR name:" + crdtrNumber + ")"; - List result = this.getWorkflowService().getDocumentService().find(query, 1, 0); - if (result == null || result.size() == 0) { - throw new PluginException(InvoicePlugin.class.getName(), ERROR_MISSING_DATA, - "Die Kreditorennummer ist nicht gültig."); + if (!period.matches(regex)) { + // throw a plugin exception - because name is missing! + throw new PluginException(InvoicePlugin.class.getName(), ERROR_MISSING_DATA, + "Eingabefehler - Bitte geben Sie eine gültige Buchungsperiode ein! Prüfen Sie auch die Spalte BP in der Positionstabelle."); + } + } + } - } else { - // update cargosoft crediotr name - ItemCollection cargo = result.get(0); - workitem.setItemValue("cdtr.name.cargosoft", cargo.getItemValueString("_VENDOR_Name")); - } - } catch (QueryException e) { - e.printStackTrace(); - } + /** + * Diese Method prüft ob die "invoice.number" bereits einmal im + * Rechnugnsworkflow vergeben wurde. Falls ja wird eine PluginExcpetion + * ausgelöst. + *

+ * Query Example: + *

+ * NOT $uniqueid:"9f72fa50-4845-41ea-b6b9-ccd518c353be" AND + txtcooperatespace:"9dba107e-f8ef-4150-a832-040d75a6eda7" AND invoice.number:"45" + * + *

+ * in case a duplicate invoice was detected the item invoice.number.duplicate is + * filled. This item is used for a conditional event. The case is displayed as a + * warning in the form. + * + * @throws PluginException + * @throws QueryException + * + */ + private void validateInvoiceNumber(ItemCollection workitem) throws PluginException { - } + String invoiceNumber = workitem.getItemValueString("invoice.number"); + // strip + String invoiceNumberStripped = invoiceNumber.replace(" ", ""); + workitem.setItemValue("invoice.number.stripped", invoiceNumberStripped); + String invoiceNumberDuplicate = workitem.getItemValueString("invoice.number.duplicate"); - /** - * converts the Map List of a workitem into a List of ItemCollectons - */ - @SuppressWarnings({ "rawtypes", "unchecked" }) - protected static List explodeChildList(ItemCollection workitem) { - // convert current list of childItems into ItemCollection elements - ArrayList childItems = new ArrayList(); + // wenn keine Rechnungsnummer eingegeben wurde gehts weiter! + if (invoiceNumber.isEmpty()) { + return; + } - List mapOrderItems = workitem.getItemValue(CHILD_ITEM_PROPERTY); - for (Object mapOderItem : mapOrderItems) { - if (mapOderItem instanceof Map) { - ItemCollection itemCol = new ItemCollection((Map) mapOderItem); - childItems.add(itemCol); - } - } - return childItems; - } + // rechnungseingang only workitems... + // Change 11.4.22 - we have now an additional field: invoice.number.stripped + String query = "(type:workitem OR type:workitemarchive) AND ($modelversion:rechnungseingang*) AND NOT ($uniqueid:\"" + + workitem.getUniqueID() + "\") AND ((invoice.number:\"" + invoiceNumberStripped + + "\") OR (invoice.number.stripped:\"" + invoiceNumberStripped + "\"))"; + try { + int result = this.getWorkflowService().getDocumentService().count(query, 1); + if (result > 0) { + // wenn _invoicenumber_duplicate bereits gesetzt ist - dann geht es ohne prüfung + // weiter + if (!invoiceNumberDuplicate.isEmpty()) { + logger.warning("...validateion skipped by user with duplicate invoice number: " + invoiceNumber); + } else { + + // set _invoicenumber_duplicate - dadurch wird die warnmeldung ausgegeben und + // der Vorgang nicht weitergeleitet + workitem.replaceItemValue("invoice.number.duplicate", invoiceNumber); + throw new PluginException(InvoicePlugin.class.getName(), ERROR_DUPPLICATE_INVOICE_NUMBER, + "ACHTUNG: Die Rechnungsnummer wurde bereits gebucht. Bitte prüfen Sie den Beleg. Sollte die Belegnummer korrekt sein, wiederholen Sie die Aktion."); + } + } else { + // clear ! + workitem.appendItemValue("invoice.number.duplicate.history", + workitem.getItemValueString("invoice.number.duplicate")); + workitem.replaceItemValue("invoice.number.duplicate", ""); + } + } catch (QueryException e) { + throw new PluginException(PluginException.class.getName(), "QUERY ERROR", e.getMessage(), e); + } + } + + /** + * Diese Method prüft ob die eingegebene IBAN nummer bereits in dem ausgewälten + * Kreditor bekannt ist. Fallst nicht wird diese schnell mal in den Kreditoren + * Datensatz übertragen. Dadurch muss man nicht extra die Kreditoren Verwaltung + * aufrufen. Es ist ein art selbst-lernendes System. + *

+ * Die Mehtode ruft eine Plugin Exception aus um den User zu fragen ob er das + * möchte. + * + * @throws PluginException + * @throws QueryException + * + */ + private void checkIBANNumber(ItemCollection workitem) throws PluginException { + + String cdtrNumber = workitem.getItemValueString("cdtr.number"); + String iban = workitem.getItemValueString("cdtr.iban"); + String bic = workitem.getItemValueString("cdtr.bic"); + String overtakeIBAN = workitem.getItemValueString("ibanbic.overtake"); + + if (cdtrNumber.isEmpty() || iban.isEmpty() || bic.isEmpty()) { + // no op + return; + } + + // wenn bereits eine Überneahme angedroht wurde dann übernehemen! + if (!overtakeIBAN.isEmpty()) { + kreditorService.addNewIBANBIC(cdtrNumber, iban, bic); + workitem.setItemValue("ibanbic.overtake",""); + return; + } + + // search the kreditor + ItemCollection cdtr = kreditorService.findCreditor(cdtrNumber); + if (cdtr != null) { + // Prüfen ob wir die IBAN schon kennen + if (iban.equals(cdtr.getItemValueString("cdtr.iban")) && bic.equals(cdtr.getItemValueString("cdtr.bic"))) { + return; + } + if (iban.equals(cdtr.getItemValueString("cdtr.iban2")) + && bic.equals(cdtr.getItemValueString("cdtr.bic2"))) { + return; + } + if (iban.equals(cdtr.getItemValueString("cdtr.iban3")) + && bic.equals(cdtr.getItemValueString("cdtr.bic3"))) { + return; + } + if (iban.equals(cdtr.getItemValueString("cdtr.iban4")) + && bic.equals(cdtr.getItemValueString("cdtr.bic4"))) { + return; + } + // OK - scheinbar ist diese IBAN/BIC nicht bekannt. Also fragen wir mal nach.... + workitem.setItemValue("ibanbic.overtake", iban + bic); + throw new PluginException(InvoicePlugin.class.getName(), ERROR_NEW_IBANBIC, + "Die von Ihnen erfasste IBAN/BIC ist noch nicht bekannt. Sollte die Eingabe korrekt sein, wiederholen Sie die Aktion."); + } + + } + + + + /** + * Hilfsmethod prüft ob die cdtr.nummer mit einer nummer aus der Cargosoft + * Import Datei übereinstimmt. + * + * @param workitem + * @throws PluginException + */ + private void validateCargosoftCdtrNumber(ItemCollection workitem) throws PluginException { + String crdtrNumber = workitem.getItemValueString("cdtr.number"); + + // wenn keine Nummer eingegeben wurde gehts weiter! + if (crdtrNumber.isEmpty()) { + return; + } + + // search creditor number in cargosoft... + // die cargosoft Kreditornummer beginnt seltsamerweise mit einem K..... + try { + String query = "(type:cargosoftkreditor) AND (name:K" + crdtrNumber + " OR name:" + crdtrNumber + ")"; + List result = this.getWorkflowService().getDocumentService().find(query, 1, 0); + if (result == null || result.size() == 0) { + throw new PluginException(InvoicePlugin.class.getName(), ERROR_MISSING_DATA, + "Die Kreditorennummer ist nicht gültig."); + + } else { + // update cargosoft crediotr name + ItemCollection cargo = result.get(0); + workitem.setItemValue("cdtr.name.cargosoft", cargo.getItemValueString("_VENDOR_Name")); + } + } catch (QueryException e) { + e.printStackTrace(); + } + + } + + /** + * converts the Map List of a workitem into a List of ItemCollectons + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + protected static List explodeChildList(ItemCollection workitem) { + // convert current list of childItems into ItemCollection elements + ArrayList childItems = new ArrayList(); + + List mapOrderItems = workitem.getItemValue(CHILD_ITEM_PROPERTY); + for (Object mapOderItem : mapOrderItems) { + if (mapOderItem instanceof Map) { + ItemCollection itemCol = new ItemCollection((Map) mapOderItem); + childItems.add(itemCol); + } + } + return childItems; + } } diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/KreditorService.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/KreditorService.java new file mode 100644 index 0000000..1bc98a6 --- /dev/null +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/KreditorService.java @@ -0,0 +1,144 @@ +/******************************************************************************* + * 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.List; +import java.util.logging.Logger; + +import javax.annotation.security.DeclareRoles; +import javax.annotation.security.RolesAllowed; +import javax.annotation.security.RunAs; +import javax.ejb.EJB; +import javax.ejb.Singleton; + +import org.imixs.workflow.ItemCollection; +import org.imixs.workflow.engine.DocumentService; +import org.imixs.workflow.exceptions.PluginException; +import org.imixs.workflow.exceptions.QueryException; + +/** + * Der KreditorService wird verwendet um einen Kreditor zu finden oder neue + * IBAN/BIC kombinationen aufzunehmen. + * + * @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 KreditorService { + + @SuppressWarnings("unused") + private static Logger logger = Logger.getLogger(KreditorService.class.getName()); + + @EJB + DocumentService documentService; + + /** + * sucht einen Kreditor + * + * + * @throws PluginException + */ + public ItemCollection findCreditor(String cdtrNumber) throws PluginException { + + try { + String query = "(type:" + CargosoftController.TYPE_CARGOSOFTKREDITOR + ") AND (name:" + cdtrNumber + ")"; + List result = documentService.find(query, 1, 0, "$modified", true); + if (result.size() > 0) { + return result.get(0); + + } + } catch (QueryException e) { + throw new PluginException(PluginException.class.getName(), "QUERY ERROR", e.getMessage(), e); + } + + return null; + } + + /** + * Diese Methode übertragt neue IBAN/BIC kombis in den kreditor + * + * @param cdtrNumber + * @param iban + * @param bic + * @throws PluginException + */ + public void addNewIBANBIC(String cdtrNumber, String iban, String bic) throws PluginException { + ItemCollection cdtr = findCreditor(cdtrNumber); + + if (cdtr != null) { + + // Wir rotieren die nummern nach unten + cdtr.setItemValue("cdtr.iban4", cdtr.getItemValue("cdtr.iban3")); + cdtr.setItemValue("cdtr.bic4", cdtr.getItemValue("cdtr.bic3")); + cdtr.setItemValue("cdtr.iban3", cdtr.getItemValue("cdtr.iban2")); + cdtr.setItemValue("cdtr.bic3", cdtr.getItemValue("cdtr.bic2")); + cdtr.setItemValue("cdtr.iban2", cdtr.getItemValue("cdtr.iban")); + cdtr.setItemValue("cdtr.bic2", cdtr.getItemValue("cdtr.bic")); + // clear slot 0 + cdtr.setItemValue("cdtr.iban", ""); + cdtr.setItemValue("cdtr.bic", ""); + + // nun können wir die neue IBAN/BIC in die erste frei park position legen + if (cdtr.getItemValueString("cdtr.iban").isEmpty()) { + cdtr.setItemValue("cdtr.iban", iban); + cdtr.setItemValue("cdtr.bic", bic); + documentService.save(cdtr); + return; + } + if (cdtr.getItemValueString("cdtr.iban2").isEmpty()) { + cdtr.setItemValue("cdtr.iban2", iban); + cdtr.setItemValue("cdtr.bic2", bic); + documentService.save(cdtr); + return; + } + if (cdtr.getItemValueString("cdtr.iban3").isEmpty()) { + cdtr.setItemValue("cdtr.iban3", iban); + cdtr.setItemValue("cdtr.bic3", bic); + documentService.save(cdtr); + return; + } + if (cdtr.getItemValueString("cdtr.iban4").isEmpty()) { + cdtr.setItemValue("cdtr.iban4", iban); + cdtr.setItemValue("cdtr.bic4", bic); + documentService.save(cdtr); + return; + } + + } + + } + +}