/******************************************************************************* * Imixs Workflow Technology * Copyright (C) 2003, 2008 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 * * Contributors: * Imixs Software Solutions GmbH - initial API and implementation * Ralph Soika * *******************************************************************************/ package com.alexanderlogistics; import java.io.IOException; import java.io.Serializable; import java.io.StringWriter; import java.io.Writer; import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.imixs.workflow.ItemCollection; import org.imixs.workflow.engine.DocumentService; import org.imixs.workflow.exceptions.AccessDeniedException; import org.imixs.workflow.exceptions.QueryException; import org.imixs.workflow.faces.data.WorkflowEvent; import org.imixs.workflow.office.forms.ValidationController; import jakarta.enterprise.context.ConversationScoped; import jakarta.enterprise.event.Observes; import jakarta.faces.context.FacesContext; import jakarta.inject.Inject; import jakarta.inject.Named; import jakarta.json.Json; import jakarta.json.JsonObject; import jakarta.json.JsonObjectBuilder; /** * Der BusinessPartnerController stellt Methoden für die BusinessPartner Forms * sowie für die das Suche-Widget 'businesspartner_search' bereit. * * * @author rsoika * @version 1.0 */ @Named @ConversationScoped public class BusinessPartnerController implements Serializable { private static final long serialVersionUID = 1L; protected List ibanList = null; protected List invoicesOut = null; protected List invoicesIn = null; protected List dunnings = null; @Inject DocumentService documentService; @Inject BusinessPartnerService businessPartnerService; @Inject ValidationController validationController; private List searchResult = null; private static Logger logger = Logger.getLogger(BusinessPartnerController.class.getName()); public List getInvoicesOut() { if (invoicesOut == null) { invoicesOut = new ArrayList<>(); } return invoicesOut; } public List getInvoicesIn() { if (invoicesIn == null) { invoicesIn = new ArrayList<>(); } return invoicesIn; } public List getDunnings() { if (dunnings == null) { dunnings = new ArrayList<>(); } return dunnings; } /** * This method searches a text phrase within the list of DATEV kreditoren *

* JSF Integration: * * {@code } */ public void search(String options) { List resultList = null; searchResult = new ArrayList(); // get the param from faces context.... FacesContext fc = FacesContext.getCurrentInstance(); String phrase = fc.getExternalContext().getRequestParameterMap().get("phrase"); if (phrase == null) { return; } logger.fine("search prase '" + phrase + "'"); if (phrase == null || phrase.length() < 2) { return; } logger.fine("search for=" + phrase); Pattern pattern = null; resultList = businessPartnerService.search(phrase); // Compile the regex pattern if available if (options.contains("regexPattern=")) { String regexPattern = options.substring(options.indexOf("regexPattern=") + 13); logger.fine("regex=" + regexPattern); pattern = Pattern.compile(regexPattern); } // Filter by Regex and convert ItemCollection into a BusinessPartnerSearchEntry for (ItemCollection businessPartner : resultList) { String name = businessPartner.getItemValueString("name"); // Prüfen, ob der name der Regex entspricht if (pattern != null) { Matcher matcher = pattern.matcher(name); if (!matcher.matches()) { // Kein passendes Konto continue; } } // Anforderung Fau Kück vom 8.10.2025 // Es sollen all diese Nummern angezeigt werden. Sonst sind die User nicht in // der Lage die Adresse richtig auszuwählen // String display = businessPartner.getItemValueString("$workflowsummary"); String display = businessPartner.getItemValueString("partner.name"); display = display + " (" + businessPartner.getItemValueString("dbtr.number") + ", " + businessPartner.getItemValueString("cdtr.number"); String cargosoftCreditNoteNumber = businessPartner.getItemValueString("cargosot.credit.cdtr.number"); if (!cargosoftCreditNoteNumber.isBlank()) { display = display + ", Credit-Note " + cargosoftCreditNoteNumber; } display = display + ")"; // remove bad characters. display = display.replace("\"", ""); display = display.replace("'", ""); searchResult.add(new BusinessPartnerSearchEntry(name, display, buildJsonData(businessPartner))); } } /** * Diese Helper Method liefert true wenn in den Options von Form Part 'reRender' * angegeben wurde. Damit löst die Suchmaske businesspartner_search.xhtml eine * komplette rerender Phase der Form aus. Dies ist z.b. für den workflow * 'analyse-debitor.bpmn' nützlich * * @param options * @return */ public boolean isRerenderMode(String options) { return options.toLowerCase().contains("rerender"); } /** * Die Resultliste wird als eine Liste einen Arrays zurückgegeben. Der Erste * Eintrag * * @return */ public List getSearchResult() { return searchResult; } public ItemCollection getBusinessPartnerByID(String bpid) { ItemCollection partner = businessPartnerService.getBusinessPartnerByID(bpid); return partner; } /** * Helper method to disable the form validation during a metadata update */ public void disableValidation() { logger.info("Disable Validation"); validationController.setRequired(false); } /** * Diese Methode liefert eine Liste mit sämtlichen Buchungskonten die wir für * den aktuellen Businesspartner kennen * * @return */ public List getAccounts(String bpid) { List result = new ArrayList<>(); ItemCollection partner = businessPartnerService.getBusinessPartnerByID(bpid); if (partner != null) { result.add(partner.getItemValueString("cdtr.number")); result.add(partner.getItemValueString("cargosot.credit.cdtr.number")); result.add(partner.getItemValueString("dbtr.number")); } // Entfernt null oder leere Strings result.removeIf(s -> s == null || s.isBlank()); return result; } /** * WorkflowEvent listener resolved additional data. * * For businesspartner the method converts the IBAN child list embeded HashMaps * into ItemCollections and reconvert them before processing * * for invoices the method resolve the partner.id and partner.name * * @param workflowEvent * @throws AccessDeniedException */ public void onWorkflowEvent(@Observes WorkflowEvent workflowEvent) throws AccessDeniedException { int eventType = workflowEvent.getEventType(); ItemCollection workitem = workflowEvent.getWorkitem(); if (workitem == null) { return; } if (workitem.getModelVersion().startsWith("businesspartner-")) { // reset orderItems if workItem has changed if (WorkflowEvent.WORKITEM_CHANGED == eventType || WorkflowEvent.WORKITEM_CREATED == eventType) { // reset state ibanList = BusinessPartnerService.explodeBanks(workitem); loadStats(workitem); } // before the workitem is saved we update the field txtOrderItems if (WorkflowEvent.WORKITEM_BEFORE_PROCESS == eventType) { BusinessPartnerService.implodeBanks(workitem, ibanList); } if (WorkflowEvent.WORKITEM_AFTER_PROCESS == eventType) { // reset state ibanList = BusinessPartnerService.explodeBanks(workitem); } } if (workitem.getModelVersion().startsWith("rechnungsausgang-")) { // resolve partner.id and partner.name if (workitem.getItemValueString("partner.id").isEmpty()) { // try to resolve the data ItemCollection bpWorkitem = getBusinessPartnerByID(InvoiceUtil.getBPID(workitem)); if (bpWorkitem != null) { workitem.setItemValue("partner.id", bpWorkitem.getItemValueString("partner.id")); workitem.setItemValue("partner.name", bpWorkitem.getItemValueString("partner.name")); } } } if (workitem.getModelVersion().startsWith("rechnungseingang-")) { // resolve partner.id and partner.name if (workitem.getItemValueString("partner.id").isEmpty()) { // try to resolve the data ItemCollection bpWorkitem = getBusinessPartnerByID(InvoiceUtil.getBPID(workitem)); if (bpWorkitem != null) { workitem.setItemValue("partner.id", bpWorkitem.getItemValueString("partner.id")); workitem.setItemValue("partner.name", bpWorkitem.getItemValueString("partner.name")); } } } if (workitem.getModelVersion().startsWith("zahlungseingang-")) { // resolve partner.id and partner.name if (workitem.getItemValueString("partner.id").isEmpty()) { // try to resolve the data ItemCollection bpWorkitem = getBusinessPartnerByID( InvoiceUtil.buildBPID(workitem.getItemValueString("dbtr.number"))); if (bpWorkitem != null) { workitem.setItemValue("partner.id", bpWorkitem.getItemValueString("partner.id")); workitem.setItemValue("partner.name", bpWorkitem.getItemValueString("partner.name")); } } } } /** * Hilfsmethode die die offenen Rechnungen läd. Wird von WorktiemChanged Event * aufgerufen. * * @param workitem */ private void loadStats(ItemCollection workitem) { try { // Ausgangsrechnungen String dbtrNumber = workitem.getItemValueString("dbtr.number"); if (!dbtrNumber.isEmpty()) { invoicesOut = businessPartnerService.findOutgoingInvoices(dbtrNumber); // Mahnungen String query = "(type:workitem) AND ($modelversion:mahnlauf-*) " + " AND (dbtr.number:" + dbtrNumber + ")"; dunnings = documentService.findStubs(query, 999, 0, "invoice.number", false); } // Eingangsrechnungen String cdtrNumber = workitem.getItemValueString("cdtr.number"); if (!cdtrNumber.isEmpty()) { String query = "(type:workitem) AND ($modelversion:rechnungseingang-*) " + " AND (cdtr.number:" + cdtrNumber + ")"; invoicesIn = documentService.findStubs(query, 999, 0, "invoice.number", false); } } catch (QueryException e) { logger.severe("failed to load stats: " + e.getMessage()); } } public List getIbanList() { return ibanList; } public void addIBAN() { if (ibanList == null) { ibanList = new ArrayList(); } ItemCollection source = new ItemCollection(); ibanList.add(source); } /** * Removes an dbtr item from the list * * @param name - name of dbtr */ public void removeIBAN(String id) { if (id != null && ibanList != null) { for (ItemCollection cdtr : ibanList) { if (id.equals(cdtr.getItemValueString("id"))) { ibanList.remove(cdtr); break; } } } } /** * This JSF backing method is called by businesspartner_search.xhtml after the * user has selected a new businesspartner. *

* The method lookups the given BusinessPartner and updates the metadata for * dbtr/cdtr depending on the workflow type. A form will than rerender the * opList section. */ public void updateMetaData(ItemCollection workitem) { FacesContext fc = FacesContext.getCurrentInstance(); String bpid = fc.getExternalContext().getRequestParameterMap().get("partnerID"); logger.info("....update metadata.....bpid = " + bpid); ItemCollection businessPartner = businessPartnerService.getBusinessPartnerByID(bpid); searchResult = null; if (businessPartner != null) { workitem.setItemValue("partner.id", bpid); workitem.setItemValue("partner.ref", businessPartner.getUniqueID()); workitem.setItemValue("partner.name", businessPartner.getItemValueString("partner.name")); // Eingangsrechnung 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.getItemValue("cdtr.mail")); // Anforderung Frau Kück vom 20.8.2025 // bei Auswahl eines Kreditors sollen IBAN/BIC mit dem ersten vorhandenen // IBAN/BIC Kombination // im Business Partner überschreiben werden falls möglich! List bankList = BusinessPartnerService.getBanks(businessPartner); if (bankList != null && bankList.size() > 0) { ItemCollection bank = bankList.get(0); if (!bank.getItemValueString("iban").isEmpty()) { workitem.setItemValue("cdtr.iban", bank.getItemValueString("iban")); } if (!bank.getItemValueString("bic").isEmpty()) { workitem.setItemValue("cdtr.bic", bank.getItemValueString("bic")); } } } else if (InvoiceUtil.isDebitorInvoice(workitem)) { // Ausgangsrechnung workitem.setItemValue("dbtr.number", businessPartner.getItemValueString("dbtr.number")); workitem.setItemValue("dbtr.name", businessPartner.getItemValueString("partner.name")); workitem.setItemValue("dbtr.mail", businessPartner.getItemValue("dbtr.mail")); } else if (workitem.getModelVersion().startsWith("zahlungseingang")) { // Zahlungseingang workitem.setItemValue("dbtr.number", businessPartner.getItemValueString("dbtr.number")); workitem.setItemValue("dbtr.name", businessPartner.getItemValueString("partner.name")); workitem.setItemValue("dbtr.mail", businessPartner.getItemValue("dbtr.mail")); } else if (workitem.getModelVersion().startsWith("analyse-debitor")) { // Analyse Debitor workitem.setItemValue("dbtr.number", businessPartner.getItemValueString("dbtr.number")); workitem.setItemValue("dbtr.name", businessPartner.getItemValueString("partner.name")); workitem.setItemValue("dbtr.mail", businessPartner.getItemValue("dbtr.mail")); } else { if (workitem.getItemValueString("dbtr.number").isEmpty()) { // default behavior String number = businessPartner.getItemValueString("dbtr.number"); workitem.setItemValue("dbtr.number", number); if (number.length() > 1) { workitem.setItemValue("dbtr.number.short", number.substring(1)); } } if (workitem.getItemValueString("cdtr.number").isEmpty()) { String number = businessPartner.getItemValueString("cdtr.number"); workitem.setItemValue("cdtr.number", number); if (number.length() > 1) { workitem.setItemValue("cdtr.number.short", number.substring(1)); } } } } } /** * Hilfsmethode die eine JSON Struktur mit allen relevanten Daten für einen * BusinessPartner erzeugt. * * @return */ private String buildJsonData(ItemCollection businessPartner) { JsonObjectBuilder objectBuilder = Json.createObjectBuilder(). // add("name", jsonVal(businessPartner.getItemValueString("name"))). // add("cdtr.number", jsonVal(businessPartner.getItemValueString("cdtr.number"))). // add("dbtr.number", jsonVal(businessPartner.getItemValueString("dbtr.number"))). // add("partner.name", jsonVal(businessPartner.getItemValueString("partner.name"))); // get iban list // {iban=[Dxxxxxx1], name=[Bank 1], id=[bank1], bic=[CITIDEFF]} ibanList = BusinessPartnerService.getBanks(businessPartner); int i = 1; for (ItemCollection iban : ibanList) { objectBuilder.add("iban" + 1, jsonVal(iban.getItemValueString("iban"))). // add("bic" + 1, jsonVal(iban.getItemValueString("bic")));// } JsonObject jsonObject = objectBuilder.build(); String jsonString = "{}"; try (Writer writer = new StringWriter()) { Json.createWriter(writer).write(jsonObject); jsonString = writer.toString(); } catch (IOException e) { logger.warning("Unable to build json structure"); } return jsonString; } /** * Helper method to remove " and ' characters - causing problems * * @param val * @return */ public static String jsonVal(String val) { val = val.replace("\"", ""); val = val.replace("'", ""); return val; } }