/* * Imixs-Workflow * * Copyright (C) 2001-2020 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: * https://www.imixs.org * https://github.com/imixs/imixs-workflow * * Contributors: * Imixs Software Solutions GmbH - Project Management * Ralph Soika - Software Developer */ package com.alexanderlogistics.xml; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.logging.Logger; import org.imixs.archive.core.SnapshotService; import org.imixs.workflow.ItemCollection; import org.imixs.workflow.WorkflowKernel; import org.imixs.workflow.engine.DocumentEvent; import org.imixs.workflow.engine.DocumentService; import org.imixs.workflow.engine.ModelService; 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; import org.imixs.workflow.exceptions.QueryException; import com.alexanderlogistics.BusinessPartnerService; import com.alexanderlogistics.InvoiceUtil; import com.alexanderlogistics.KreditorDebitorService; import jakarta.annotation.security.DeclareRoles; import jakarta.annotation.security.RolesAllowed; import jakarta.annotation.security.RunAs; import jakarta.ejb.EJB; import jakarta.ejb.Stateless; import jakarta.enterprise.event.Observes; /** * Der BusinessPartnerImportService hängt sich an den standard CSVImport Service * der die Cargosoft Stammdaten aktualisiert. * Es ist ein simples Observer Pattern das auf das Document Event * "ON_DOCUMENT_SAVE" reagiert. Hier hängt sich der BusinessPartnerImportService * ein und prüft ob der Workflow schon existiert oder ggf. aktualisiert werden * muss. *

* Der Service migriert auch die alten zusätzlichen IBAN/BIC felder wenn der * Business partner erstmals neu angelegt wird. *

* Falls bei der ersten Migration erkannt wird, dass die IBAN Nummern nicht * eindeutig sind wir der BusinessParter mit dem Event 300 angelegt. *

* Im Cargosoft Entity wird zusätzlich das flag NOSNAPSHOT=true gesetzt. Dies * ist nur eine Performance Optimierung. * * @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" }) @RunAs("org.imixs.ACCESSLEVEL.MANAGERACCESS") @Stateless public class BusinessPartnerImportService { private static Logger logger = Logger.getLogger(BusinessPartnerImportService.class.getName()); public static final String OPTION_MANDANT_ID = "mandant.id"; public static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss"; public static final String REGEX_IMPORTTEXTPATTERN = "^R[1-8] .*$"; @EJB WorkflowService workflowService; @EJB DocumentService documentService; @EJB ModelService modelService; /** * Die Methode reagiert auf das CDI DocumentEvent beim Import von cargosoft * cargosoftkreditor documenten. * * */ public void onEvent(@Observes DocumentEvent event) { if (event == null || event.getDocument() == null) { return; } // check source if (event.getEventType() == DocumentEvent.ON_DOCUMENT_SAVE && "cargosoftkreditor".equals(event.getDocument().getType())) { // set NOSNAPSHOT=true fro cargosoft item (migration) event.getDocument().setItemValue(SnapshotService.NOSNAPSHOT, true); // run only if we have the model 'businesspartner-*'; if (modelService.findVersionsByRegEx("(businesspartner*)").size() == 0) { // no business partner workflow found return; } logger.fine("Verify business partner object...."); ItemCollection importDoc = event.getDocument(); String name = event.getDocument().getItemValueString("name"); boolean isCreditor = name.toUpperCase().startsWith("K"); String partnerID = InvoiceUtil.buildBPID(name); // Prüfen ob es diesen partner schon gibt? ItemCollection businesspartner = lookupBusinessPartner(partnerID); if (businesspartner == null) { businesspartner = createBusinessPartner(partnerID); } ItemCollection oldBussinessPartnerItemColl = (ItemCollection) businesspartner.clone(); // Update Fields... businesspartner.setItemValue("name", partnerID); businesspartner.setItemValue("partner.id", partnerID); if (isCreditor) { businesspartner.setItemValue("cdtr.number", name); if (businesspartner.isItemEmpty("cdtr.mail")) { businesspartner.setItemValue("cdtr.mail", importDoc.getItemValueString("_vendor_email")); } } else { businesspartner.setItemValue("dbtr.number", name); if (businesspartner.isItemEmpty("dbtr.mail")) { businesspartner.setItemValue("dbtr.mail", importDoc.getItemValueString("_vendor_email")); } } businesspartner.setItemValue("partner.country", importDoc.getItemValueString("_vendor_country")); businesspartner.setItemValue("partner.name", importDoc.getItemValueString("_vendor_name")); businesspartner.setItemValue("partner.phone", importDoc.getItemValueString("_vendor_phone")); businesspartner.setItemValue("partner.address", importDoc.getItemValueString("_vendor_str")); businesspartner.setItemValue("partner.zip", importDoc.getItemValueString("_vendor_zip_code")); businesspartner.setItemValue("partner.city", importDoc.getItemValueString("_vendor_city")); // hat sich das Objekt verändert? if (!businesspartner.equals(oldBussinessPartnerItemColl)) { // Prüfe IBAN auf plausibilität List bankList = BusinessPartnerService.getBanks(businesspartner); boolean ibanDublette = false; List dublettenIban = new ArrayList<>(); for (ItemCollection bank : bankList) { String iban = bank.getItemValueString("iban"); // erkenne fehlerhaften kontonummern if (dublettenIban.contains(iban)) { // ACHTUNG - uneindeutige Bankverbindung ibanDublette = true; } else { dublettenIban.add(iban); } } int eventID = 200; // default // event errechnen if (!businesspartner.hasItem(WorkflowKernel.LASTEVENT)) { // create new! if (ibanDublette) { eventID = 300; // Exception } else { eventID = 100; // update/create } } businesspartner.setEventID(eventID); try { workflowService.processWorkItemByNewTransaction(businesspartner); } catch (AccessDeniedException | ProcessingErrorException | PluginException | ModelException e) { logger.warning("Failed to update Business Partner Object " + name + " - " + e.getMessage()); } } } } /** * Erstellt ein neues leeres Business Partner Object * * @return */ private ItemCollection createBusinessPartner(String partnerID) { ItemCollection businessPartner = new ItemCollection(); businessPartner.setType("workitem"); businessPartner.setWorkflowGroup("Business Partner"); businessPartner.task(1000); // Hier migrieren wir jetzt auch die alten IBAN/BIC Daten try { String cargoShortID = partnerID.substring(2); String query = "(type:" + KreditorDebitorService.TYPE_CARGOSOFTKREDITOR + ")"; query = query + " AND ( name:K7" + cargoShortID + " OR name:D1" + cargoShortID + " )"; List oldList = documentService.find(query, 2, 0); // es können 2 Datensätze ankommen // Items: // cdtr.mail (Liste) // cdtr.creditperiod // cdtr.iban , cdtr.iban2 - 4 // cdtr.bic , cdtr.bic2 - 4 List ibanList = new ArrayList<>(); List bicList = new ArrayList<>(); for (ItemCollection oldData : oldList) { if (!oldData.getItemValueString("cdtr.mail").isEmpty()) { businessPartner.setItemValue("cdtr.mail", oldData.getItemValue("cdtr.mail")); businessPartner.setItemValue("dbtr.mail", oldData.getItemValue("cdtr.mail")); } if (!oldData.getItemValueString("cdtr.creditperiod").isEmpty()) { businessPartner.setItemValue("cdtr.creditperiod", oldData.getItemValue("cdtr.creditperiod")); } if (!oldData.getItemValueString("cdtr.iban").isEmpty()) { ibanList.add(oldData.getItemValueString("cdtr.iban")); } if (!oldData.getItemValueString("cdtr.bic").isEmpty()) { bicList.add(oldData.getItemValueString("cdtr.bic")); } if (!oldData.getItemValueString("cdtr.iban2").isEmpty()) { ibanList.add(oldData.getItemValueString("cdtr.iban2")); } if (!oldData.getItemValueString("cdtr.bic2").isEmpty()) { bicList.add(oldData.getItemValueString("cdtr.bic2")); } if (!oldData.getItemValueString("cdtr.iban3").isEmpty()) { ibanList.add(oldData.getItemValueString("cdtr.iban3")); } if (!oldData.getItemValueString("cdtr.bic3").isEmpty()) { bicList.add(oldData.getItemValueString("cdtr.bic3")); } if (!oldData.getItemValueString("cdtr.iban4").isEmpty()) { ibanList.add(oldData.getItemValueString("cdtr.iban4")); } if (!oldData.getItemValueString("cdtr.bic4").isEmpty()) { bicList.add(oldData.getItemValueString("cdtr.bic4")); } } // build partner.iban.list - dublettenprüfung und Trim List dubletten = new ArrayList<>(); List dublettenIban = new ArrayList<>(); if (ibanList.size() > 0) { List bankList = new ArrayList<>(); for (int i = 0; i < ibanList.size(); i++) { String iban = ibanList.get(i); String bic = ""; if (bicList.size() > i) { bic = bicList.get(i); } iban = superTrim(iban); bic = superTrim(bic); if (dubletten.contains(iban + "/" + bic)) { // voll dublette continue; } else { dubletten.add(iban + "/" + bic); } ItemCollection bank = new ItemCollection(); // {cdtr.iban=[A], name=[cdtr1], cdtr.name=[a], cdtr.bic=[a]} bank.setItemValue("id", "bank" + (i + 1)); bank.setItemValue("name", "Bank " + (i + 1)); bank.setItemValue("iban", iban); bank.setItemValue("bic", bic); bankList.add(bank); } Iterator var3 = bankList.iterator(); List mapOrderItems = new ArrayList(); while (var3.hasNext()) { ItemCollection orderItem = (ItemCollection) var3.next(); mapOrderItems.add(orderItem.getAllItems()); } businessPartner.setItemValue(BusinessPartnerService.ITEM_IBAN_LIST, mapOrderItems); } } catch (QueryException e) { // TODO Auto-generated catch block e.printStackTrace(); } return businessPartner; } /** * entfernt alle leerzeichen */ public String superTrim(String data) { String result = data.trim(); result = result.replace(" ", ""); return result; } /** * Sucht nach einem Business partner * * @param id * @return */ private ItemCollection lookupBusinessPartner(String id) { String query = "(type:workitem OR type:workitemarchive) AND ($modelversion:businesspartner*) AND (name:" + id + ")"; try { List result = documentService.find(query, 1, 0, null, false); if (result.size() > 0) { return result.get(0); } } catch (QueryException e) { logger.warning("Failed to query businesspartner: " + query + " - Error: " + e.getMessage()); } return null; } }