/******************************************************************************* * 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.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.logging.Logger; import org.eclipse.microprofile.config.inject.ConfigProperty; import org.imixs.workflow.ItemCollection; import org.imixs.workflow.ItemCollectionComparator; import org.imixs.workflow.engine.DocumentService; import org.imixs.workflow.engine.WorkflowService; import org.imixs.workflow.engine.index.SchemaService; 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 jakarta.annotation.PostConstruct; import jakarta.annotation.security.DeclareRoles; import jakarta.annotation.security.RolesAllowed; import jakarta.annotation.security.RunAs; import jakarta.ejb.Singleton; import jakarta.inject.Inject; /** * Der BusinessPartnerService stellt Methoden für den Zugriff auf Business * Partner bereit. * * @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 BusinessPartnerService { public static final int MAX_SEARCH_RESULT = 100; public static final String ITEM_IBAN_LIST = "partner.bank.list"; public static final String WORKFLOW_SERVICE_ENDPOINT = "workflow.service.endpoint"; public static final String WORKFLOW_SERVICE_USER = "workflow.service.user"; public static final String WORKFLOW_SERVICE_PASSWORD = "workflow.service.password"; public static final String ERROR_BUSINESSPARTNER_MISSING = "ERROR_BUSINESSPARTNER_MISSING"; public static final String ERROR_BUSINESSPARTNER_LOCKED = "ERROR_BUSINESSPARTNER_LOCKED"; public static final String ERROR_BUSINESSPARTNER_VERIFICATION = "ERROR_BUSINESSPARTNER_VERIFICATION"; public static final int TASK_ACTIVE = 1100; public static final int TASK_VERIFICATION = 1300; public static final int TASK_INACTIVE = 1700; public static final int TASK_LOCKED = 1800; public static final int EVENT_ACTIVATE = 210; private static Logger logger = Logger.getLogger(BusinessPartnerService.class.getName()); @Inject @ConfigProperty(name = WORKFLOW_SERVICE_ENDPOINT) Optional workflowServiceEndpoint; @Inject @ConfigProperty(name = WORKFLOW_SERVICE_USER) Optional workflowServiceUser; @Inject @ConfigProperty(name = WORKFLOW_SERVICE_PASSWORD) Optional workflowServicePassword; @Inject DocumentService documentService; @Inject WorkflowService workflowService; @Inject SchemaService schemaService; /** * Initialize the rest clients */ @PostConstruct public void init() { } /** * Diese Methode aktualisiert das business Partner object. Sie wird von den * Invoice Plugins genutzt. * Die Methode wirft eine PluginException falls das BusinessPartner Objekt * gesperrt oder in verification ist! * * Gleichzeitig wird bei Rechnungen in Abhängigkeit der Rechnungsart die * dbtr./cdtr. items sowie mail und country aktualisiert. * * @param partnerID * @param workitem * @throws PluginException */ public void updateBusinessPartnerData(ItemCollection workitem) throws PluginException { String partnerID = workitem.getItemValueString("partner.id"); // Migration wenn keine partner.id existier! if (partnerID.isEmpty()) { if (InvoiceUtil.isCreditorInvoice(workitem)) { partnerID = InvoiceUtil.buildBPID(workitem.getItemValueString("cdtr.number")); } if (InvoiceUtil.isDebitorInvoice(workitem)) { partnerID = InvoiceUtil.buildBPID(workitem.getItemValueString("dbtr.number")); } workitem.setItemValue("partner.id", partnerID); } // load Business Partner ItemCollection businessPartner = getBusinessPartnerByID(partnerID); if (businessPartner != null) { workitem.setItemValue("partner.name", businessPartner.getItemValueString("partner.name")); // Update Invoice Partner Meta Data if (InvoiceUtil.isDebitorInvoice(workitem)) { workitem.setItemValue("dbtr.number", businessPartner.getItemValueString("dbtr.number")); workitem.setItemValue("dbtr.name", businessPartner.getItemValueString("partner.name")); workitem.setItemValue("dbtr.mail", businessPartner.getItemValueString("dbtr.mail")); workitem.setItemValue("invoice.country", businessPartner.getItemValueString("_vendor_country")); } if (InvoiceUtil.isCreditorInvoice(workitem)) { workitem.setItemValue("cdtr.number", businessPartner.getItemValueString("cdtr.number")); workitem.setItemValue("cdtr.name", businessPartner.getItemValueString("partner.name")); workitem.setItemValue("cdtr.mail", businessPartner.getItemValueString("cdtr.mail")); workitem.setItemValue("invoice.country", businessPartner.getItemValueString("_vendor_country")); } // Validate Business Partner Status! if (businessPartner.getTaskID() == TASK_VERIFICATION) { throw new PluginException(InvoicePlugin.class.getName(), ERROR_BUSINESSPARTNER_VERIFICATION, "Businesspartner is in verification. Invoice can't be processed!"); } if (businessPartner.getTaskID() == TASK_LOCKED) { throw new PluginException(InvoicePlugin.class.getName(), ERROR_BUSINESSPARTNER_LOCKED, "Businesspartner is locked. Invoice can't be processed!"); } // update business partner status... try { if (businessPartner.getTaskID() == TASK_INACTIVE) { // Workitem erneut aktivieren businessPartner.event(EVENT_ACTIVATE); workflowService.processWorkItem(businessPartner); } else { // workItem einfach nur speichern! documentService.save(businessPartner); } } catch (PluginException | ProcessingErrorException | AccessDeniedException | ModelException e) { logger.warning("Failed to update BusinessPartner object '" + partnerID + "'!"); } } else { logger.warning("BusinessPartner '" + partnerID + "' not found!"); } } /** * Returns the stubs of all outgoing invoices * * @param _dbtrNumber * @return */ public List findOutgoingInvoices(String _dbtrNumber) { // Aus der dbtrNummer muss das führendde D entfernt werden String query = "(type:workitem) AND ($modelversion:rechnungsausgang-*)"; // Aus der dbtrNummer muss das führendde D entfernt werden // wir speichern dieses zwar im Zahlungseingangs Workflow, aber eine // Ausganksrechnung kennt das nicht // Das ganze ist ein übles Relikt aus Cargosoft und kann nicht vermieden werden String _dbtrNumberOld = _dbtrNumber; if (_dbtrNumberOld.startsWith("D")) { _dbtrNumberOld = _dbtrNumber.substring(1); } query = query + " AND (dbtr.number:" + _dbtrNumber + " OR dbtr.number:" + _dbtrNumberOld + ")"; try { return documentService.find(query, 999, 0, "invoice.number", false); } catch (QueryException e) { logger.severe("Failed to compute outgoing invoices: " + e.getMessage()); } return new ArrayList<>(); } /** * Diese Methode sucht einen Business Partner anhand seiner BPID * * @param bpid * - business partner id phrase * @return - matching business partner */ public ItemCollection getBusinessPartnerByID(String bpid) { if (bpid == null || bpid.isEmpty()) { return null; } List result; try { String sQuery = "(type:\"workitem\" OR type:\"workitemarchive\" ) AND ($modelversion:businesspartner-*)"; sQuery += " AND (name:" + bpid.trim() + ")"; logger.finest("SearchQuery= " + sQuery); result = documentService.find(sQuery, 1, 0); if (result.size() > 0) { return result.get(0); } } catch (Exception e) { logger.warning(" lucene error - " + e.getMessage()); } return null; } /** * Diese Methode sucht Business Partner anhand einer Suchphrase * * @param phrase * - search phrase * @return - list of matching business partners */ public List search(String phrase) { List searchResult = new ArrayList(); if (phrase == null || phrase.isEmpty()) { return searchResult; } try { phrase = phrase.trim(); // phrase = LuceneSearchService.escapeSearchTerm(phrase); phrase = schemaService.normalizeSearchTerm(phrase); String sQuery = "(type:\"workitem\" OR type:\"workitemarchive\") AND ($modelversion:businesspartner-*)"; sQuery += " AND (" + phrase + "*)"; logger.finest("SearchQuery= " + sQuery); searchResult = documentService.find(sQuery, MAX_SEARCH_RESULT, 0); } catch (Exception e) { logger.warning(" lucene error - " + e.getMessage()); } // sort by txtname.. Collections.sort(searchResult, new ItemCollectionComparator("$workflowsummary", true)); return searchResult; } /** * Packt die Liste der Bank Details (ItemCollections) in ein Workitem * * @param workitem */ public static void implodeBanks(ItemCollection workitem, List ibanList) { List mapOrderItems = new ArrayList(); if (ibanList != null) { logger.fine("Convert child items into Map..."); Iterator var3 = ibanList.iterator(); while (var3.hasNext()) { ItemCollection orderItem = (ItemCollection) var3.next(); mapOrderItems.add(orderItem.getAllItems()); } workitem.replaceItemValue(BusinessPartnerService.ITEM_IBAN_LIST, mapOrderItems); } } /** * Enpackt die iban Map Liste von eiem Worktiem in eine Liste von ItemCollection * * @param workitem */ public static List explodeBanks(ItemCollection workitem) { List ibanList = new ArrayList(); List mapOrderItems = workitem.getItemValue(BusinessPartnerService.ITEM_IBAN_LIST); Iterator var4 = mapOrderItems.iterator(); while (var4.hasNext()) { Object mapOderItem = var4.next(); if (mapOderItem instanceof Map) { ItemCollection itemCol = new ItemCollection((Map) mapOderItem); ibanList.add(itemCol); } } return ibanList; } /** * Liefert die ChildItems mit den IBAN daten * * @param workitem * @return */ public static List getBanks(ItemCollection workitem) { List result = new ArrayList<>(); List mapOrderItems = workitem.getItemValue(BusinessPartnerService.ITEM_IBAN_LIST); Iterator var4 = mapOrderItems.iterator(); while (var4.hasNext()) { Object mapOderItem = var4.next(); if (mapOderItem instanceof Map) { ItemCollection itemCol = new ItemCollection((Map) mapOderItem); result.add(itemCol); } } return result; } /** * Diese Methode übertragt neue IBAN/BIC Pare in den Kreditor Banken Bereich * * @param cdtrNumber * @param iban * @param bic * @throws PluginException */ public void addNewIBANBIC(ItemCollection businessPartner, String iban, String bic) throws PluginException { if (businessPartner != null) { List bankenListe = explodeBanks(businessPartner); ItemCollection newbank = new ItemCollection(); // {iban=[IBAN], name=[Test Bank], id=[test ], bic=[BIC]} newbank.setItemValue("iban", iban); newbank.setItemValue("bic", bic); newbank.setItemValue("id", bankenListe.size() + 1); newbank.setItemValue("name", "Bank-" + bankenListe.size() + 1); bankenListe.add(newbank); implodeBanks(businessPartner, bankenListe); documentService.save(businessPartner); } } /** * Diese Methode gibt true zurück wenn die angegebene IBAN/BIC Kombination als * bank bereits bekannt ist * * @param cdtrNumber * @param iban * @param bic * @throws PluginException */ public boolean isIBANBICKnown(ItemCollection businessPartner, String iban, String bic) throws PluginException { if (businessPartner != null) { List bankenListe = explodeBanks(businessPartner); for (ItemCollection bank : bankenListe) { if (iban.equals(bank.getItemValueString("iban")) && bic.equals(bank.getItemValueString("bic"))) { // known! return true; } } } return false; } }