BusinessPartner Suche

This commit is contained in:
Ralph Soika 2025-02-12 21:04:02 +01:00
parent 90166229bd
commit dfa089ba31
7 changed files with 8936 additions and 23 deletions

View file

@ -23,45 +23,121 @@
*******************************************************************************/ *******************************************************************************/
package com.alexanderlogistics; package com.alexanderlogistics;
import java.io.IOException;
import java.io.Serializable; import java.io.Serializable;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.imixs.workflow.ItemCollection; import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.engine.DocumentService; import org.imixs.workflow.engine.DocumentService;
import org.imixs.workflow.exceptions.AccessDeniedException; import org.imixs.workflow.exceptions.AccessDeniedException;
import org.imixs.workflow.faces.data.WorkflowEvent; import org.imixs.workflow.faces.data.WorkflowEvent;
import jakarta.ejb.EJB; import jakarta.enterprise.context.ConversationScoped;
import jakarta.enterprise.event.Observes; import jakarta.enterprise.event.Observes;
import jakarta.faces.view.ViewScoped; import jakarta.faces.context.FacesContext;
import jakarta.inject.Inject;
import jakarta.inject.Named; 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 * Der BusinessPartnerController stellt Methoden für die BusinessPartner Forms
* bereit. * sowie für die das Suche-Widget 'businesspartner_search' bereit.
* *
* *
* @author rsoika * @author rsoika
* @version 1.0 * @version 1.0
*/ */
@Named @Named
@ViewScoped @ConversationScoped
public class BusinessPartnerController implements Serializable { public class BusinessPartnerController implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
protected List<ItemCollection> ibanList = null; protected List<ItemCollection> ibanList = null;
@EJB @Inject
DocumentService documentService; DocumentService documentService;
@Inject
BusinessPartnerService businessPartnerService;
private List<ItemCollection> searchResult = null;
private static Logger logger = Logger.getLogger(BusinessPartnerController.class.getName()); private static Logger logger = Logger.getLogger(BusinessPartnerController.class.getName());
/**
* 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 regexPattern) {
List<ItemCollection> resultList = null;
searchResult = new ArrayList<ItemCollection>();
// 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);
resultList = businessPartnerService.search(phrase);
logger.info("found " + resultList.size() + " businesspartners");
// Compile the regex pattern
logger.fine("regex=" + regexPattern);
Pattern pattern = null;
if (regexPattern != null && !regexPattern.isEmpty()) {
pattern = Pattern.compile(regexPattern);
}
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;
}
}
String display = businessPartner.getItemValueString("$workflowsummary");
;
display = display.replace("\"", "");
display = display.replace("'", "");
searchResult.add(businessPartner);
}
}
/**
* Die Resultliste wird als eine Liste einen Arrays zurückgegeben. Der Erste
* Eintrag
*
* @return
*/
public List<ItemCollection> getSearchResult() {
return searchResult;
}
/** /**
* WorkflowEvent listener to convert the IBAN child list embeded HashMaps into * WorkflowEvent listener to convert the IBAN child list embeded HashMaps into
* ItemCollections and reconvert them before processing * ItemCollections and reconvert them before processing
@ -112,10 +188,10 @@ public class BusinessPartnerController implements Serializable {
* *
* @param name - name of dbtr * @param name - name of dbtr
*/ */
public void removeIBAN(String name) { public void removeIBAN(String id) {
if (name != null && ibanList != null) { if (id != null && ibanList != null) {
for (ItemCollection cdtr : ibanList) { for (ItemCollection cdtr : ibanList) {
if (name.equals(cdtr.getItemValueString("name"))) { if (id.equals(cdtr.getItemValueString("id"))) {
ibanList.remove(cdtr); ibanList.remove(cdtr);
break; break;
} }
@ -155,4 +231,69 @@ public class BusinessPartnerController implements Serializable {
} }
/**
* Liefert die ChildItems mit den IBAN daten
*
* @param workitem
* @return
*/
public List<ItemCollection> getIBANList(ItemCollection workitem) {
List<ItemCollection> result = new ArrayList<>();
List<Object> mapOrderItems = workitem.getItemValue("partner.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;
}
/**
* 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("name", jsonVal(businessPartner.getItemValueString("partner.name")));
// get iban list
// {iban=[Dxxxxxx1], name=[Bank 1], id=[bank1], bic=[CITIDEFF]}
ibanList = getIBANList(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;
}
} }

View file

@ -0,0 +1,106 @@
/*******************************************************************************
* 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.List;
import java.util.logging.Logger;
import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.ItemCollectionComparator;
import org.imixs.workflow.engine.DocumentService;
import org.imixs.workflow.engine.index.SchemaService;
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;
private static Logger logger = Logger.getLogger(BusinessPartnerService.class.getName());
@Inject
DocumentService documentService;
@Inject
SchemaService schemaService;
/**
* Diese Methode sucht Business Partner anhand einer Suchphrase
*
* @param phrase
* - search phrase
* @return - list of matching business partners
*/
public List<ItemCollection> search(String phrase) {
List<ItemCollection> searchResult = new ArrayList<ItemCollection>();
if (phrase == null || phrase.isEmpty()) {
return searchResult;
}
try {
phrase = phrase.trim();
// phrase = LuceneSearchService.escapeSearchTerm(phrase);
phrase = schemaService.normalizeSearchTerm(phrase);
String sQuery = "(type:\"workitem\") 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;
}
}

View file

@ -28,7 +28,10 @@
package com.alexanderlogistics.xml; package com.alexanderlogistics.xml;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.logging.Logger; import java.util.logging.Logger;
import org.imixs.archive.core.SnapshotService; import org.imixs.archive.core.SnapshotService;
@ -44,6 +47,7 @@ import org.imixs.workflow.exceptions.ProcessingErrorException;
import org.imixs.workflow.exceptions.QueryException; import org.imixs.workflow.exceptions.QueryException;
import com.alexanderlogistics.InvoiceUtil; import com.alexanderlogistics.InvoiceUtil;
import com.alexanderlogistics.KreditorDebitorService;
import jakarta.annotation.security.DeclareRoles; import jakarta.annotation.security.DeclareRoles;
import jakarta.annotation.security.RolesAllowed; import jakarta.annotation.security.RolesAllowed;
@ -60,6 +64,9 @@ import jakarta.enterprise.event.Observes;
* ein und prüft ob der Workflow schon existiert oder ggf. aktualisiert werden * ein und prüft ob der Workflow schon existiert oder ggf. aktualisiert werden
* muss. * muss.
* *
* Der Service migriert auch die alten zusätzlichen IBAN/BIC felder wenn der
* Business partner erstmals neu angelegt wird.
*
* The service set also the flag NOSNAPSHOT=true for the crgosoftcreditor * The service set also the flag NOSNAPSHOT=true for the crgosoftcreditor
* document type. * document type.
* *
@ -124,7 +131,7 @@ public class BusinessPartnerImportService {
// Prüfen ob es diesen partner schon gibt? // Prüfen ob es diesen partner schon gibt?
ItemCollection businesspartner = lookupBusinessPartner(partnerID); ItemCollection businesspartner = lookupBusinessPartner(partnerID);
if (businesspartner == null) { if (businesspartner == null) {
businesspartner = createBusinessPartner(); businesspartner = createBusinessPartner(partnerID);
} }
ItemCollection oldBussinessPartnerItemColl = (ItemCollection) businesspartner.clone(); ItemCollection oldBussinessPartnerItemColl = (ItemCollection) businesspartner.clone();
@ -168,12 +175,97 @@ public class BusinessPartnerImportService {
* *
* @return * @return
*/ */
private ItemCollection createBusinessPartner() { private ItemCollection createBusinessPartner(String partnerID) {
ItemCollection businessPartner = new ItemCollection(); ItemCollection businessPartner = new ItemCollection();
businessPartner.setType("workitem"); businessPartner.setType("workitem");
businessPartner.setWorkflowGroup("Business Partner"); businessPartner.setWorkflowGroup("Business Partner");
businessPartner.task(1000); 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<ItemCollection> 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<String> ibanList = new ArrayList<>();
List<String> bicList = new ArrayList<>();
for (ItemCollection oldData : oldList) {
if (!oldData.getItemValueString("cdtr.mail").isEmpty()) {
businessPartner.setItemValue("cdtr.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
if (ibanList.size() > 0) {
List<ItemCollection> 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);
}
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<Map> mapOrderItems = new ArrayList();
while (var3.hasNext()) {
ItemCollection orderItem = (ItemCollection) var3.next();
mapOrderItems.add(orderItem.getAllItems());
}
businessPartner.setItemValue("partner.iban.list", mapOrderItems);
}
} catch (QueryException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return businessPartner; return businessPartner;
} }

View file

@ -10,35 +10,35 @@
<f:ajax render="#{ibanListContainer.clientId}" onevent="updateSepaList"> <f:ajax render="#{ibanListContainer.clientId}" onevent="updateSepaList">
<table class="imixsdatatable imixs-orderitems"> <table class="imixsdatatable imixs-orderitems">
<tr> <tr>
<th style="width: 140px">Name</th> <th style="width: 140px">ID<span class="imixs-required">
<th style="">Bank<span class="imixs-required"> *</span></th>
*</span></th> <th style="">Bank</th>
<th style="width: 250px;">IBAN</th> <th style="width: 250px;">IBAN</th>
<th style="width: 150px;">BIC</th> <th style="width: 150px;">BIC</th>
<th style="width: 50px"> <th style="width: 50px">
</th> </th>
</tr> </tr>
<ui:repeat var="cdtr" value="#{businessPartnerController.ibanList}"> <ui:repeat var="bank" value="#{businessPartnerController.ibanList}">
<tr> <tr>
<td> <td>
<h:inputText value="#{cdtr.item['name']}" style="width:100%;" /> <h:inputText value="#{bank.item['id']}" required="true" style="width:100%;" />
</td> </td>
<td> <td>
<h:inputText value="#{cdtr.item['cdtr.name']}" <h:inputText value="#{bank.item['name']}"
style="width:100%;" /> style="width:100%;" />
</td> </td>
<td> <td>
<h:inputText value="#{cdtr.item['cdtr.iban']}" <h:inputText value="#{bank.item['iban']}"
onkeyup="imixsOfficeWorkitem.formatIBAN(this);" onkeyup="imixsOfficeWorkitem.formatIBAN(this);"
style="width:100%;" /> style="width:100%;" />
</td> </td>
<td> <td>
<h:inputText value="#{cdtr.item['cdtr.bic']}" style="width:100%;text-transform:uppercase;" /> <h:inputText value="#{bank.item['bic']}" style="width:100%;text-transform:uppercase;" />
</td> </td>
<td> <td>
<h:commandLink <h:commandLink
actionListener="#{businessPartnerController.removeIBAN(cdtr.item['name'])}"> actionListener="#{businessPartnerController.removeIBAN(bank.item['id'])}">
<span class="typcn typcn-trash imixs-state-info"></span> <span class="typcn typcn-trash imixs-state-info"></span>
<f:ajax render="#{ibanListContainer.clientId}" <f:ajax render="#{ibanListContainer.clientId}"
onevent="updateSepaList" /> onevent="updateSepaList" />

View file

@ -0,0 +1,79 @@
<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets" xmlns:pt="http://xmlns.jcp.org/jsf/passthrough"
xmlns:marty="http://xmlns.jcp.org/jsf/composite/marty" xmlns:i="http://xmlns.jcp.org/jsf/composite/imixs">
<!-- DATEV Kreditor/Debitor Search integration
This subform is a custom form part.
The subform provides a jsf commandScript which calls the datevSearchController.search method in the backend.
The script below inits a autocompletion feature for the input field.
See imixs-office.autocompletion.js
See also:
https://stackoverflow.com/questions/16588327/how-to-invoke-a-jsf-managed-bean-on-a-html-dom-event-using-native-javascript
https://dzone.com/articles/execute-a-jsf-ajax-request-by-just-a-function-call
https://www.w3schools.com/howto/howto_js_autocomplete.asp
-->
<ui:param name="item_konto_name" value="#{item.name}.name"></ui:param>
<ui:fragment rendered="#{!readonly}">
<h:inputText value="#{workitem.item[item.name]}" pt:data-item="#{item.name}" />
<h:inputHidden value="#{workitem.item[item_konto_name]}" pt:data-item="#{item_konto_name}" />
<br />
<span id='datev-konto-id' class='small'>#{workitem.item[item_konto_name]}</span>
<h:commandScript name="datevSearch" action="#{businessPartnerController.search(options)}"
render="autocomplete-resultlist-datev-debkredkonto" onevent="autocompleteShowResult" />
<script type="text/javascript">
/*<![CDATA[*/
// init input fields...
$(document).ready(function () {
// add autocomplete feature ..
var creditorField = $("input[data-item='#{item.name}']");
$(creditorField).each(function () {
$(this).addClass("imixs-ml");
autocompleteInitInput(this, datevSearch, 'autocomplete-resultlist-datev-debkredkonto', selectDebitorCreditorCallback);
});
});
// Hier bekommen wir die JSON Struktur mit allen daten.
// diese Daten werden auf die einzelnen Felder verteilt.
function selectDebitorCreditorCallback(selection) {
const kontoData = JSON.parse(selection);
// fill data into the fields....
var inputElementKonto = $("input[data-item='#{item.name}']");
var inputElementKreditor = $("input[data-item='#{item_konto_name}']");
inputElementKonto.val(kontoData.konto);
inputElementKreditor.val(kontoData.name);
// remove old konto name
$('#datev-konto-id').remove();
// append span with konto name....
inputElementKonto.after("<span id='datev-konto-id' class='small'>" + kontoData.name + "</span>");
}
/*]]>*/
</script>
<!-- datev debkredkonto suggest list -->
<h:panelGroup id="autocomplete-resultlist-datev-debkredkonto" layout="block" class="autocomplete-resultlist">
<ui:repeat var="suggest" value="#{datevSearchController.searchResult}">
<div class="autocomplete-resultlist-element" onclick="autocompleteSelectElement('#{suggest.data}')">
<a href="#">
<h:outputText value="#{suggest.display}" escape="false" />
</a>
</div>
</ui:repeat>
</h:panelGroup>
</ui:fragment>
<!-- Read only -->
<ui:fragment rendered="#{readonly}">
<h:outputText value="#{workitem.item[item.name]} #{workitem.item[item_konto_name]}"/>
</ui:fragment>
</ui:composition>

View file

@ -164,13 +164,13 @@
<imixs-form-section columns="1" label="Rechnungseingang "> <imixs-form-section columns="1" label="Rechnungseingang ">
<item name="cdtr.number" type="text" span="2" readonly="true" label="Kreditoren Nr.:" /> <item name="cdtr.number" type="text" span="2" readonly="true" label="Kreditoren Nr.:" />
<item name="cdtr.email" type="text" span="4" readonly="false" label="E-Mail:" /> <item name="cdtr.email" type="textlist" span="4" readonly="false" label="E-Mail:" />
<item name="cdtr.creditperiod" type="text" span="2" readonly="false" label="Zahlungsziel (Tage):" /> <item name="cdtr.creditperiod" type="text" span="2" readonly="false" label="Zahlungsziel (Tage):" />
</imixs-form-section> </imixs-form-section>
<imixs-form-section columns="1" label="Rechnungsausgang "> <imixs-form-section columns="1" label="Rechnungsausgang ">
<item name="dbtr.number" type="text" span="2" readonly="true" label="Debitoren Nr.:" /> <item name="dbtr.number" type="text" span="2" readonly="true" label="Debitoren Nr.:" />
<item name="dbtr.email" type="text" span="4" readonly="false" label="E-Mail SOA/Mahnungen:" /> <item name="dbtr.email" type="textlist" span="4" readonly="false" label="E-Mail SOA/Mahnungen:" />
<item name="dbtr.creditperiod" type="text" span="2" readonly="false" label="Zahlungsziel (Tage):" /> <item name="dbtr.creditperiod" type="text" span="2" readonly="false" label="Zahlungsziel (Tage):" />
</imixs-form-section> </imixs-form-section>

File diff suppressed because it is too large Load diff