Skip to content

Commit

Permalink
added new cdtr/dbtr search (Issue #172)
Browse files Browse the repository at this point in the history
  • Loading branch information
rsoika committed Feb 11, 2025
1 parent ff81058 commit e5b8f8b
Show file tree
Hide file tree
Showing 7 changed files with 209 additions and 85 deletions.
145 changes: 84 additions & 61 deletions imixs-adapters-datev/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,122 +4,145 @@ This adapter module provides services to import and export data from DATEV.
The import feature allows the import of DATEV master data like 'Kontenbeschriftungen'.
The export feature allows the export of workflow invoice data into a DATEV file (Buchungstapel).


## DATEV Import

The imixs-datev-adapter provides mechanisms to import DATEV data. The import is based on the standard DATEV-Format which provides different data in CSV files.
The imixs-datev-adapter provides mechanisms to import DATEV data. The import is based on the standard DATEV-Format which provides different data in CSV files.

### The DataImportService

The DatevImportService EJB provides methods to read a Datev-Format file and import the data.
The DatevImportService EJB provides methods to read a Datev-Format file and import the data.

// test if supported CSV file?
if (file.getName().endsWith(".csv")) {
ByteArrayInputStream input = new ByteArrayInputStream(file.getContent());
String result = datevImportService.importData(input, "ISO-8859-1");
getImportData().replaceItemValue("log", result);
} else {
throw new PluginException(this.getClass().getName(), DatevImportService.IMPORT_ERROR,
"File Format not supported: " + file.getName());
}

// test if supported CSV file?
if (file.getName().endsWith(".csv")) {
ByteArrayInputStream input = new ByteArrayInputStream(file.getContent());
String result = datevImportService.importData(input, "ISO-8859-1");
getImportData().replaceItemValue("log", result);
} else {
throw new PluginException(this.getClass().getName(), DatevImportService.IMPORT_ERROR,
"File Format not supported: " + file.getName());
}
The column 'Formatname' will be mapped to the item 'type'.

#### Client and Consultant ID

The column 'Formatname' will be mapped to the item 'type'.
A DATEV-Format file contains a header with different information. The Datev 'Berater' and 'Mandant' are mapped to each imported dataset

#### Client and Consultant ID

A DATEV-Format file contains a header with different information. The Datev 'Berater' and 'Mandant' are mapped to each imported dataset
- Berater = \_datev_consultant_id
- Mandant = \_datev_client_id

* Berater = _datev_consultant_id
* Mandant = _datev_client_id

This item fields which are part of each imported datev dataset can be used to import data from different sources. The data can be selected by the items. There for the items must be added into the imixs.properties entry: 'lucence.indexFieldListNoAnalyze'

lucence.indexFieldListNoAnalyze=....,_datev_client_id,_datev_consultant_id

lucence.indexFieldListNoAnalyze=....,_datev_client_id,_datev_consultant_id

#### Query DATEV data

Data can be selected by a query based on the type and the categories. See the following example:

(type:"Kontenbeschriftungen" AND _datev_client_id:"00001" AND _datev_consultant_id:"00001")

(type:"Kontenbeschriftungen" AND _datev_client_id:"00001" AND _datev_consultant_id:"00001")

## DATEV Export


The DATEV Export is generated by a SignalAdapter within a Invoice Workflow model.

org.imixs.workflow.datev.adapter.DATEVRefAddAdapter

org.imixs.workflow.datev.adapter.DATEVRefAddAdapter

The adapter automatically verifies if a DATEV Export for the current booking period and the `datev.client_id` already exists. If not, the adapter creates a new one.
The adapter automatically verifies if a DATEV Export for the current booking period and the `datev.client_id` already exists. If not, the adapter creates a new one.

The DATEV Export Workflow can be fully controlled by the user

<img src="datev-export-workflow.png" />


This model must at least define an initial Task with the following Events:

* add Invoice reference = 100
* remove invoice reference = 200
- add Invoice reference = 100
- remove invoice reference = 200

To remove a linked invoice the RemoveAdapter can be used.
To remove a linked invoice the RemoveAdapter can be used.

org.imixs.workflow.datev.adapter.DATEVRefRemoveAdapter


To execute a SEPA Export the ExecuteAdatper can be used

org.imixs.workflow.datev.adapter.DATEVExecuteAdapter




### XSL Transformation

The DATEV file is generated using the imixs-report functionality. The DATEV report is assigned with a XSLT file to generate the output.
The DATEV file format is standardized. The DATEV interface is not public and not open source!
The DATEV file format is standardized. The DATEV interface is not public and not open source!

For the DATEV Standard CSV export one report need to be defined. For the DATEV XML format two reports a necessary. The report for invoices defines the invoice selection and the XSL to transform one invoice into the corresponding XML file. Thre report for documents is needed to define the XSLT definition to generate the XML file Dokument.xml.
For the DATEV Standard CSV export one report need to be defined. For the DATEV XML format two reports a necessary. The report for invoices defines the invoice selection and the XSL to transform one invoice into the corresponding XML file. Thre report for documents is needed to define the XSLT definition to generate the XML file Dokument.xml.

**Note: ** The DATEV interface is not public and not open source! You need the official DATEV documentation to get information how the CSV and XML files have to be designed.
**Note: ** The DATEV interface is not public and not open source! You need the official DATEV documentation to get information how the CSV and XML files have to be designed.

#### XML Data Source

The xml data source is generated by the set of selected invoices defined by report definition and the DATEV export workitem itself. So the number of data entries is the count of invoices +1.
The xml data source is generated by the set of selected invoices defined by report definition and the DATEV export workitem itself. So the number of data entries is the count of invoices +1.
DATEVasdfDDD
To identify the type of document you can make use of the xsl select statement:

....
<xsl:template
match="/data/document[normalize-space(item[@name = '$workflowgroup']/value) = 'DATEV-Export']">
....
</xsl:template>

....
<xsl:template
match="/data/document[normalize-space(item[@name = '$workflowgroup']/value) = 'DATEV-Export']">
....
</xsl:template>

<xsl:template
match="/data/document[normalize-space(item[@name = '$workflowgroup']/value) = 'Rechnungseingang']">
....
</xsl:template>
.....
<xsl:template
match="/data/document[normalize-space(item[@name = '$workflowgroup']/value) = 'Rechnungseingang']">
....
</xsl:template>
.....

## Forms

## Maven
There are also custom form Elements that can be used for typical Datev processes

### Booking Table

The imxis-adapter-sepa module can be added into an applicaton module. The module provides CDI and EJB components. Optional the module contains also JSF pages to be used for frontends.
The custom form section `datev/booking_account` can be used to display a booking table

Add the following maven dependency into a parent project:
```
<imixs-form-section type="custom" path="datev/booking_account" label="Buchungen" />
```

<img src="image-01.png" />

### Search Konto

The custom form part `datev/account_search` can be used to display a input search field for debitor / creditor accounts

```xml
<item name="datev.cdtr" type="custom"
path="datev/account_search"
label="Kreditor Konto:"
required="true" />
```

<img src="image-02.png" />

You can restrict the search result optional by providing a regular expression.
For example, if you want to filter only account numbers that start with "7", you can add a regex as follows:

```xml
<item name="datev.cdtr" type="custom"
path="datev/account_search"
label="Kreditor Konto:"
options="^7.*"
required="false" />
```

This filters all account numbers that start with "7". The ^ anchor characters in the regex mean that the string must start with "7", and .\* means that after the "7" any character can follow.

## Maven

The imxis-adapter-sepa module can be added into an applicaton module. The module provides CDI and EJB components. Optional the module contains also JSF pages to be used for frontends.

Add the following maven dependency into a parent project:

<!-- DATEV Adapter -->
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-adapters-datev</artifactId>
<version>${org.imixs.adapters.version}</version>
<scope>provided</scope>
</dependency>
<!-- DATEV Adapter -->
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-adapters-datev</artifactId>
<version>${org.imixs.adapters.version}</version>
<scope>provided</scope>
</dependency>
Binary file added imixs-adapters-datev/image-01.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added imixs-adapters-datev/image-02.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
import java.util.Collections;
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.ItemCollectionComparator;
Expand Down Expand Up @@ -140,8 +142,8 @@ public void searchSachkonto() {
* render="autocomplete-resultlist-datev" onevent="autocompleteShowResult" />
* }
*/
public void searchCdtr() {
List<ItemCollection> dataList = null;
public void searchDebitorCreditor(String regexPattern) {
List<ItemCollection> kontenListe = null;
searchResult = new ArrayList<DatevSearchEntry>();
// get the param from faces context....
FacesContext fc = FacesContext.getCurrentInstance();
Expand All @@ -154,17 +156,32 @@ public void searchCdtr() {
if (phrase == null || phrase.length() < 2) {
return;
}
logger.finest(".......trigger datev search...");
logger.fine("search for=" + phrase);
dataList = searchEntity(phrase, "debitoren/kreditoren");
for (ItemCollection dbtr : dataList) {
String dbtrNo = dbtr.getItemValueString("_konto");
String name = dbtr.getItemValueString("_name");
dbtr.setItemValue("_name", name);
String display = dbtrNo + " - " + name;
kontenListe = searchEntity(phrase, "debitoren/kreditoren");
// Compile the regex pattern
logger.fine("regex=" + regexPattern);
Pattern pattern = null;
if (regexPattern != null && !regexPattern.isEmpty()) {
pattern = Pattern.compile(regexPattern);
}

for (ItemCollection konto : kontenListe) {
String kontoNummer = konto.getItemValueString("_konto");
// Prüfen, ob die Kontonummer der Regex entspricht
if (pattern != null) {
Matcher matcher = pattern.matcher(kontoNummer);
if (!matcher.matches()) {
// Kein passendes Konto
continue;

}
}
String kontoName = konto.getItemValueString("_name");
konto.setItemValue("_name", kontoName);
String display = kontoNummer + " - " + kontoName;
display = display.replace("\"", "");
display = display.replace("'", "");
searchResult.add(new DatevSearchEntry(dbtrNo, display, buildCdtrJsonData(dbtr)));
searchResult.add(new DatevSearchEntry(kontoNummer, display, buildCdtrJsonData(konto)));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,11 @@ public void saveEntry(ItemCollection aWorkitem, String type, String clientID, St
+ aWorkitem.getItemValueString("_kontobeschriftung");
aWorkitem.setItemValue("$workflowsummary", summary);
}
if ("debitoren/kreditoren".equals(type)) {
String summary = aWorkitem.getItemValueString("_konto") + " "
+ aWorkitem.getItemValueString("_name");
aWorkitem.setItemValue("$workflowsummary", summary);
}
documentService.save(aWorkitem);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
xmlns:fn="http://xmlns.jcp.org/jsp/jstl/functions">

<h:panelGroup layout="block" styleClass="imixs-form-section" style="position: relative;"
id="bookinglist" binding="#{orderlistContainer}">
id="bookinglist" binding="#{bookinglistContainer}">

<c:if test="#{!readonly}">
<h:commandScript name="sachkontoSearch" action="#{datevSearchController.searchSachkonto()}"
Expand All @@ -26,7 +26,7 @@
</th>
</tr>
<ui:repeat var="bookingItem"
value="#{childItemController.childItems}">
value="#{datevBookingController.bookingList}">
<tr>
<td class="konto-input">
<!-- Input Field -->
Expand Down Expand Up @@ -71,9 +71,9 @@
</h:inputText></td>

<td><h:commandLink
actionListener="#{childItemController.remove(bookingItem.item['numpos'])}">
actionListener="#{datevBookingController.remove(bookingItem.item['numpos'])}">
<span class="typcn typcn-trash imixs-state-info"></span>
<f:ajax render="#{orderlistContainer.clientId}" execute="#{orderlistContainer.clientId}"
<f:ajax render="#{bookinglistContainer.clientId}" execute="#{bookinglistContainer.clientId}"
onevent="initDatevTable" />
</h:commandLink></td>

Expand All @@ -85,9 +85,9 @@
<tr>
<td />

<td class="orderlist-sum"
<td class="bookinglist-sum"
style="text-align: right; font-weight: bold;">Summe:</td>
<td class="orderlist-sum orderlist_summary"
<td class="bookinglist-sum bookinglist_summary"
style="text-align: right; font-weight: bold;"></td>
<td />
</tr>
Expand All @@ -100,8 +100,8 @@
id="bookingitems_capacity_dsp" />

<h:commandButton value="#{message.add}" id="addposbutton_id"
actionListener="#{childItemController.add}">
<f:ajax render="#{orderlistContainer.clientId}" execute="#{orderlistContainer.clientId}"
actionListener="#{datevBookingController.add}">
<f:ajax render="#{bookinglistContainer.clientId}" execute="#{bookinglistContainer.clientId}"
onevent="initDatevTable" />
</h:commandButton>

Expand Down Expand Up @@ -171,11 +171,11 @@
});

// update total _capacity
// update orderlist_summary
// update bookinglist_summary
$("[id$=bookingitems_capacity]").val(total);
$("[id$=bookingitems_capacity_dsp]").val(convertToCurrency(total));
$(".orderlist_summary", ".imixs-bookingitems").empty();
$(".orderlist_summary", ".imixs-bookingitems").append(
$(".bookinglist_summary", ".imixs-bookingitems").empty();
$(".bookinglist_summary", ".imixs-bookingitems").append(
convertToCurrency(total));

}
Expand Down Expand Up @@ -216,7 +216,7 @@
</tr>

<ui:repeat var="bookingItem"
value="#{childItemController.childItems}">
value="#{datevBookingController.bookingList}">
<tr>
<td class="konto-input"><h:outputText
value="#{bookingItem.item['datev.sachkonto']}"></h:outputText>
Expand All @@ -240,9 +240,9 @@
<tr>

<td />
<td class="orderlist-sum"
<td class="bookinglist-sum"
style="text-align: right; font-weight: bold;">Summe:</td>
<td class="orderlist-sum orderlist_summary"
<td class="bookinglist-sum bookinglist_summary"
style="text-align: right; font-weight: bold;">#{workitem.item['_capacity_dsp']}</td>
</tr>
</table>
Expand Down
Loading

0 comments on commit e5b8f8b

Please sign in to comment.