498 lines
20 KiB
Java
498 lines
20 KiB
Java
/*******************************************************************************
|
|
* 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<ItemCollection> ibanList = null;
|
|
protected List<ItemCollection> invoicesOut = null;
|
|
protected List<ItemCollection> invoicesIn = null;
|
|
protected List<ItemCollection> dunnings = null;
|
|
|
|
@Inject
|
|
DocumentService documentService;
|
|
|
|
@Inject
|
|
BusinessPartnerService businessPartnerService;
|
|
|
|
@Inject
|
|
ValidationController validationController;
|
|
|
|
private List<BusinessPartnerSearchEntry> searchResult = null;
|
|
|
|
private static Logger logger = Logger.getLogger(BusinessPartnerController.class.getName());
|
|
|
|
public List<ItemCollection> getInvoicesOut() {
|
|
if (invoicesOut == null) {
|
|
invoicesOut = new ArrayList<>();
|
|
}
|
|
return invoicesOut;
|
|
}
|
|
|
|
public List<ItemCollection> getInvoicesIn() {
|
|
if (invoicesIn == null) {
|
|
invoicesIn = new ArrayList<>();
|
|
}
|
|
return invoicesIn;
|
|
}
|
|
|
|
public List<ItemCollection> getDunnings() {
|
|
if (dunnings == null) {
|
|
dunnings = new ArrayList<>();
|
|
}
|
|
return dunnings;
|
|
}
|
|
|
|
/**
|
|
* This method searches a text phrase within the list of DATEV kreditoren
|
|
* <p>
|
|
* JSF Integration:
|
|
*
|
|
* {@code
|
|
<h:commandScript name="datevSearch" action=
|
|
* "#{datevSearchController.searchCdtr()}" render=
|
|
* "autocomplete-resultlist-datev" onevent="autocompleteShowResult" /> }
|
|
*/
|
|
public void search(String options) {
|
|
List<ItemCollection> resultList = null;
|
|
searchResult = new ArrayList<BusinessPartnerSearchEntry>();
|
|
// 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<BusinessPartnerSearchEntry> 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<String> getAccounts(String bpid) {
|
|
List<String> 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<ItemCollection> getIbanList() {
|
|
return ibanList;
|
|
}
|
|
|
|
public void addIBAN() {
|
|
if (ibanList == null) {
|
|
ibanList = new ArrayList<ItemCollection>();
|
|
}
|
|
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.
|
|
* <p>
|
|
* 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<ItemCollection> 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;
|
|
}
|
|
|
|
}
|