Steuerbescheide
This commit is contained in:
parent
0d31aec3be
commit
9654b42d48
4 changed files with 785 additions and 34 deletions
|
|
@ -0,0 +1,728 @@
|
||||||
|
/*
|
||||||
|
* Imixs-Workflow
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001-2020 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:
|
||||||
|
* https://www.imixs.org
|
||||||
|
* https://github.com/imixs/imixs-workflow
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Imixs Software Solutions GmbH - Project Management
|
||||||
|
* Ralph Soika - Software Developer
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.alexanderlogistics.xml;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
import javax.xml.transform.Transformer;
|
||||||
|
import javax.xml.transform.TransformerException;
|
||||||
|
import javax.xml.transform.TransformerFactory;
|
||||||
|
import javax.xml.transform.dom.DOMSource;
|
||||||
|
import javax.xml.transform.stream.StreamResult;
|
||||||
|
import javax.xml.xpath.XPath;
|
||||||
|
import javax.xml.xpath.XPathConstants;
|
||||||
|
import javax.xml.xpath.XPathExpression;
|
||||||
|
import javax.xml.xpath.XPathExpressionException;
|
||||||
|
import javax.xml.xpath.XPathFactory;
|
||||||
|
|
||||||
|
import org.apache.commons.net.ftp.FTP;
|
||||||
|
import org.apache.commons.net.ftp.FTPClient;
|
||||||
|
import org.apache.commons.net.ftp.FTPFile;
|
||||||
|
import org.apache.commons.net.ftp.FTPSClient;
|
||||||
|
import org.imixs.archive.importer.DocumentImportEvent;
|
||||||
|
import org.imixs.archive.importer.DocumentImportService;
|
||||||
|
import org.imixs.workflow.FileData;
|
||||||
|
import org.imixs.workflow.ItemCollection;
|
||||||
|
import org.imixs.workflow.engine.DocumentService;
|
||||||
|
import org.imixs.workflow.engine.ModelService;
|
||||||
|
import org.imixs.workflow.engine.WorkflowService;
|
||||||
|
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 org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
import org.xml.sax.InputSource;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
import com.alexanderlogistics.InvoiceUtil;
|
||||||
|
import com.alexanderlogistics.KreditorDebitorService;
|
||||||
|
import com.alexanderlogistics.mahnlauf.MahnlaufService;
|
||||||
|
|
||||||
|
import jakarta.ejb.EJB;
|
||||||
|
import jakarta.ejb.Stateless;
|
||||||
|
import jakarta.enterprise.event.Observes;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Der CargosoftXMLEAkteImportService erweitert den FTPImportService und
|
||||||
|
* kann XML EAkten (Steuerbescheide) von Cargosoft importieren.
|
||||||
|
* Der Service reagiert auf DocumentImportEvents und kann über das Options Feld
|
||||||
|
* konfiguriert werden.
|
||||||
|
* <p>
|
||||||
|
* Im Gegensatz zum FTPImportService werden die XML Dateien nach einem
|
||||||
|
* speziellen Verfahren geparsed und dann als Steuerbescheid importiert.
|
||||||
|
* <p>
|
||||||
|
* In den Optionen muss die option "mandant.id" hinterlegt sein. Stimmt
|
||||||
|
* diese beim Import nicht mit der Mandanten Nummer in der XML Datei überein,
|
||||||
|
* wird das XML Dokument gelöscht und nicht importiert.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @author rsoika
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Stateless
|
||||||
|
public class CargosoftXMLEAkteImportService {
|
||||||
|
|
||||||
|
private static Logger logger = Logger.getLogger(CargosoftXMLEAkteImportService.class.getName());
|
||||||
|
public static final String OPTION_MANDANT_ID = "mandant.id";
|
||||||
|
public static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss";
|
||||||
|
public static final String REGEX_IMPORTTEXTPATTERN = "^R[1-8] .*$";
|
||||||
|
|
||||||
|
@EJB
|
||||||
|
WorkflowService workflowService;
|
||||||
|
|
||||||
|
@EJB
|
||||||
|
DocumentService documentService;
|
||||||
|
|
||||||
|
@EJB
|
||||||
|
ModelService modelService;
|
||||||
|
|
||||||
|
@EJB
|
||||||
|
KreditorDebitorService kreditorDebitorService;
|
||||||
|
|
||||||
|
@EJB
|
||||||
|
DocumentImportService documentImportService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
MahnlaufService mahnlaufService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method reacts on a CDI ImportEvent and reads documents form a ftp
|
||||||
|
* server.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void onEvent(@Observes DocumentImportEvent event) {
|
||||||
|
|
||||||
|
// check if source is already completed
|
||||||
|
if (event.getResult() == DocumentImportEvent.PROCESSING_COMPLETED) {
|
||||||
|
logger.finest("...... import source already completed - no processing will be performed.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!"CARGOSOFT_EAKTE_XML".equalsIgnoreCase(event.getSource().getItemValueString("type"))) {
|
||||||
|
// ignore data source
|
||||||
|
logger.finest("...... type '" + event.getSource().getItemValueString("type") + "' skipped.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Properties sourceOptions = documentImportService.getOptionsProperties(event.getSource());
|
||||||
|
// Read Mandand ID form Option list
|
||||||
|
String mandantID = sourceOptions.getProperty(OPTION_MANDANT_ID, "");
|
||||||
|
if (mandantID == null || mandantID.isEmpty()) {
|
||||||
|
documentImportService.logMessage("...CARGOSOFT_EAKTE_XML Import failed - missing mandant.id in options!",
|
||||||
|
event);
|
||||||
|
event.setResult(DocumentImportEvent.PROCESSING_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
documentImportService.logMessage("...CARGOSOFT_EAKTE_XML Import started: mandant.id=" + mandantID,
|
||||||
|
event);
|
||||||
|
String ftpServer = event.getSource().getItemValueString(DocumentImportService.SOURCE_ITEM_SERVER);
|
||||||
|
String ftpPort = event.getSource().getItemValueString(DocumentImportService.SOURCE_ITEM_PORT);
|
||||||
|
String ftpUser = event.getSource().getItemValueString(DocumentImportService.SOURCE_ITEM_USER);
|
||||||
|
String ftpPassword = event.getSource().getItemValueString(DocumentImportService.SOURCE_ITEM_PASSWORD);
|
||||||
|
String ftpPath = event.getSource().getItemValueString(DocumentImportService.SOURCE_ITEM_SELECTOR);
|
||||||
|
|
||||||
|
if (!ftpPath.startsWith("/") && !ftpPath.startsWith("./")) {
|
||||||
|
ftpPath = "/" + ftpPath;
|
||||||
|
}
|
||||||
|
if (!ftpPath.endsWith("/")) {
|
||||||
|
ftpPath = ftpPath + "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
// if no server is given we exit
|
||||||
|
if (ftpServer.isEmpty()) {
|
||||||
|
logger.warning("...... no server specified!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ftpPort.isEmpty()) {
|
||||||
|
// set default port
|
||||||
|
ftpPort = "21";
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
documentImportService.logMessage("...connecting to FTP server: " + ftpServer, event);
|
||||||
|
documentImportService.logMessage("...working directory: " + ftpPath, event);
|
||||||
|
FTPClient ftpClient = connectServer(ftpServer, Integer.parseInt(ftpPort), ftpUser, ftpPassword);
|
||||||
|
scannFTPDirectory(ftpClient, ftpPath, mandantID, event);
|
||||||
|
} catch (PluginException pe) {
|
||||||
|
documentImportService.logMessage(pe.getMessage(), event);
|
||||||
|
event.setResult(DocumentImportEvent.PROCESSING_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// completed
|
||||||
|
event.setResult(DocumentImportEvent.PROCESSING_COMPLETED);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connects to the FTP Server and returns a ftpClient instance.
|
||||||
|
*/
|
||||||
|
private FTPClient connectServer(String ftpServer, int ftpPort, String ftpUser, String ftpPassword)
|
||||||
|
throws PluginException {
|
||||||
|
FTPClient ftpClient = null;
|
||||||
|
// TLS
|
||||||
|
ftpClient = new FTPSClient("TLS", false);
|
||||||
|
ftpClient.setControlEncoding("UTF-8");
|
||||||
|
try {
|
||||||
|
ftpClient.connect(ftpServer, ftpPort);
|
||||||
|
|
||||||
|
if (ftpClient.login(ftpUser, ftpPassword) == false) {
|
||||||
|
throw new PluginException(CargosoftXMLEAkteImportService.class.getName(),
|
||||||
|
"FTP_ERROR", "FTP file transfer failed: login failed!");
|
||||||
|
}
|
||||||
|
ftpClient.enterLocalPassiveMode();
|
||||||
|
logger.finest("...... FileType=" + FTP.BINARY_FILE_TYPE);
|
||||||
|
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
|
||||||
|
ftpClient.setControlEncoding("UTF-8");
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new PluginException(CargosoftXMLEAkteImportService.class.getName(),
|
||||||
|
"FTP_ERROR", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return ftpClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method reads the working FTP directory and starts importing the files.
|
||||||
|
*
|
||||||
|
* @param ftpClient
|
||||||
|
* @param ftpPath
|
||||||
|
* @throws PluginException
|
||||||
|
*/
|
||||||
|
private void scannFTPDirectory(FTPClient ftpClient, String ftpPath, String mandantID, DocumentImportEvent event)
|
||||||
|
throws PluginException {
|
||||||
|
try {
|
||||||
|
|
||||||
|
// load spaces Pos Expressions
|
||||||
|
Map<String, List<String>> spacePosMappings = mahnlaufService.loadSpacePosMappings();
|
||||||
|
|
||||||
|
logger.finest("......read directory " + ftpPath);
|
||||||
|
// try to enter the working directory and read all files...
|
||||||
|
boolean bWorkingDir = ftpClient.changeWorkingDirectory(ftpPath);
|
||||||
|
if (bWorkingDir == false) {
|
||||||
|
throw new PluginException(CargosoftXMLEAkteImportService.class.getName(),
|
||||||
|
"FTP_ERROR", "...failed to change into working directory: ");
|
||||||
|
}
|
||||||
|
|
||||||
|
FTPFile[] allFiles = ftpClient.listFiles(ftpPath);
|
||||||
|
|
||||||
|
// FTPFile[] allFiles = ftpClient.listFiles();
|
||||||
|
int count = 0;
|
||||||
|
if (allFiles.length > 0) {
|
||||||
|
documentImportService.logMessage("..." + allFiles.length + " files found ", event);
|
||||||
|
for (FTPFile file : allFiles) {
|
||||||
|
// if this is a directory or symlink then we do ignore this entry
|
||||||
|
if (!file.isFile()) {
|
||||||
|
logger.warning("...'" + file.getName() + "' is not a valid file, object will be ignored!");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ItemCollection invoice = null;
|
||||||
|
logger.info("import file " + file.getName() + "...");
|
||||||
|
// String fullFileName = ftpPath + "/" + file.getName();
|
||||||
|
try (ByteArrayOutputStream is = new ByteArrayOutputStream();) {
|
||||||
|
ftpClient.retrieveFile(file.getName(), is);
|
||||||
|
byte[] rawData = is.toByteArray();
|
||||||
|
if (rawData != null && rawData.length > 0) {
|
||||||
|
logger.finest("......file '" + file.getName() + "' successful read - bytes size = "
|
||||||
|
+ rawData.length);
|
||||||
|
// create new workitem
|
||||||
|
invoice = createWorkitem(event.getSource(), file.getName(), rawData, spacePosMappings);
|
||||||
|
if (invoice != null) {
|
||||||
|
// persist workitem only if not exists and with a matching mandant.id
|
||||||
|
if (!invoice.getItemValueString("mandant.id").equals(mandantID)) {
|
||||||
|
throw new PluginException(CargosoftXMLEAkteImportService.class.getName(),
|
||||||
|
"FTP_ERROR", "Invoice does not match mandantID " + mandantID);
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
workflowService.processWorkItemByNewTransaction(invoice);
|
||||||
|
// .processWorkItem(invoice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// finally delete teh file from the transfer folder
|
||||||
|
ftpClient.deleteFile(ftpPath + file.getName());
|
||||||
|
// String sourceFilePath = ftpPath + file.getName();
|
||||||
|
// String destinationFilePath = ftpPath + "processed/" + file.getName();
|
||||||
|
// boolean success = ftpClient.rename(sourceFilePath, destinationFilePath);
|
||||||
|
// if (!success) {
|
||||||
|
// logger.warning("Failed to move file " + file.getName() + " to " + ftpPath +
|
||||||
|
// "processed/");
|
||||||
|
// }
|
||||||
|
|
||||||
|
} catch (AccessDeniedException | ProcessingErrorException | PluginException
|
||||||
|
| ModelException | XPathExpressionException | TransformerException e) {
|
||||||
|
throw new PluginException(CargosoftXMLEAkteImportService.class.getName(),
|
||||||
|
"FTP_ERROR", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
documentImportService.logMessage("..." + count + " new files imported.", event);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.severe("FTP I/O Error: " + e.getMessage());
|
||||||
|
int r = ftpClient.getReplyCode();
|
||||||
|
logger.severe("FTP ReplyCode=" + r);
|
||||||
|
|
||||||
|
throw new PluginException(CargosoftXMLEAkteImportService.class.getName(),
|
||||||
|
"FTP_ERROR", e.getMessage());
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
// do logout....
|
||||||
|
try {
|
||||||
|
|
||||||
|
ftpClient.logout();
|
||||||
|
ftpClient.disconnect();
|
||||||
|
} catch (IOException e) {
|
||||||
|
documentImportService.logMessage("...FTP file transfer failed: " + e.getMessage(), event);
|
||||||
|
throw new PluginException(CargosoftXMLEAkteImportService.class.getName(),
|
||||||
|
"FTP_ERROR", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and processes a new workitem with a given xml information from the
|
||||||
|
* filedata
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* @throws ModelException
|
||||||
|
* @throws PluginException
|
||||||
|
* @throws ProcessingErrorException
|
||||||
|
* @throws AccessDeniedException
|
||||||
|
* @throws TransformerException
|
||||||
|
* @throws XPathExpressionException
|
||||||
|
*/
|
||||||
|
public ItemCollection createWorkitem(ItemCollection source, String fileName, byte[] rawData,
|
||||||
|
Map<String, List<String>> spacePosMappings)
|
||||||
|
throws AccessDeniedException, ProcessingErrorException, PluginException, ModelException,
|
||||||
|
XPathExpressionException, TransformerException {
|
||||||
|
ItemCollection workitem = new ItemCollection();
|
||||||
|
workitem.model(source.getItemValueString(DocumentImportService.SOURCE_ITEM_MODELVERSION));
|
||||||
|
workitem.task(source.getItemValueInteger(DocumentImportService.SOURCE_ITEM_TASK));
|
||||||
|
workitem.event(source.getItemValueInteger(DocumentImportService.SOURCE_ITEM_EVENT));
|
||||||
|
workitem.setWorkflowGroup(source.getItemValueString("workflowgroup"));
|
||||||
|
workitem.setItemValue("cargosoft.import.filename", fileName);
|
||||||
|
|
||||||
|
// Now we parse the rawData....
|
||||||
|
InputStream inputStream = new ByteArrayInputStream(rawData);
|
||||||
|
InputSource inputSource = new InputSource(inputStream);
|
||||||
|
|
||||||
|
DocumentBuilder documentBuilder;
|
||||||
|
try {
|
||||||
|
documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||||
|
Document doc = documentBuilder.parse(inputSource);
|
||||||
|
|
||||||
|
// Now we parse the following item values
|
||||||
|
// invoice.number
|
||||||
|
// invoice.currency
|
||||||
|
// invoice.text
|
||||||
|
// invoice.date
|
||||||
|
// dbtr.number
|
||||||
|
// invoice.duedate
|
||||||
|
// invoice.reminder
|
||||||
|
// payment.term
|
||||||
|
// invoice.rate
|
||||||
|
// invoice.base.amount
|
||||||
|
|
||||||
|
readXMLValue(doc, "/CargoSoftEFile/EFile/References/Reference[@type='client']", workitem,
|
||||||
|
"mandant.id", String.class);
|
||||||
|
|
||||||
|
readXMLValue(doc, "/CargoSoftEFile/EFile/References/Reference[@type='cs_voucher_number']",
|
||||||
|
workitem, "invoice.number", String.class);
|
||||||
|
readXMLValue(doc, "/CargoSoftEFile/EFile/References/Reference[@type='currency']",
|
||||||
|
workitem, "invoice.currency", String.class);
|
||||||
|
readXMLValue(doc, "/CargoSoftEFile/EFile/References/Reference[@type='total_net_amount']",
|
||||||
|
workitem, "invoice.total.net", String.class);
|
||||||
|
readXMLValue(doc, "/CargoSoftEFile/EFile/References/Reference[@type='total_tax_amount']",
|
||||||
|
workitem, "invoice.total.tax", String.class);
|
||||||
|
readXMLValue(doc, "/CargoSoftEFile/EFile/References/Reference[@type='reference']",
|
||||||
|
workitem, "invoice.atc.number", String.class);
|
||||||
|
readXMLValue(doc, "/CargoSoftEFile/EFile/References/Reference[@type='booking_period']",
|
||||||
|
workitem, "invoice.booking_period", String.class);
|
||||||
|
|
||||||
|
readXMLValue(doc, "/CargoSoftEFile/EFile/References/Reference[@type='booking_date']",
|
||||||
|
workitem, "invoice.booking_date", String.class);
|
||||||
|
readXMLValue(doc, "/CargoSoftEFile/EFile/References/Reference[@type='booking_text']",
|
||||||
|
workitem, "invoice.booking_text", String.class);
|
||||||
|
|
||||||
|
// Read rows
|
||||||
|
readXMLValue(doc, "/CargoSoftEFile/EFile/References/Reference[@type='row_1_cs_filenumber']",
|
||||||
|
workitem, "invoice.text", String.class);
|
||||||
|
|
||||||
|
// verify if invoice is already imported.
|
||||||
|
if (alreadyImported(workitem.getItemValueString("invoice.number"))) {
|
||||||
|
logger.warning("Invoice " + workitem.getItemValueString("invoice.number") + " already imported");
|
||||||
|
// return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rechnungssumme errechnen.....
|
||||||
|
// readXMLValue(doc,
|
||||||
|
// "/Invoices/Invoice/InvoiceHeader/InvoiceAmount/NetAmount/Amount/Value",
|
||||||
|
// workitem, "invoice.total.net", Double.class);
|
||||||
|
// readXMLValue(doc,
|
||||||
|
// "/Invoices/Invoice/InvoiceHeader/InvoiceAmount/VATInformation/VATAmount/Amount/Value",
|
||||||
|
// workitem, "invoice.total.tax", Double.class);
|
||||||
|
// if (!workitem.hasItem("invoice.total.tax")) {
|
||||||
|
// workitem.setItemValue("invoice.total.tax", 0.0);
|
||||||
|
// }
|
||||||
|
// // Total = net + tax
|
||||||
|
// double _total = workitem.getItemValueDouble("invoice.total.net");
|
||||||
|
// _total = _total + workitem.getItemValueDouble("invoice.total.tax");
|
||||||
|
// _total = Math.round(_total * 100) / 100.0;
|
||||||
|
// workitem.setItemValue("invoice.total", _total);
|
||||||
|
// workitem.setItemValue("invoice.saldo", _total);
|
||||||
|
|
||||||
|
// Bei Gutschrift und Stornorechnung Wert negieren...
|
||||||
|
// if (isGutschrift(workitem)) {
|
||||||
|
// workitem.setItemValue("invoice.saldo",
|
||||||
|
// -workitem.getItemValueDouble("invoice.total"));
|
||||||
|
// workitem.setItemValue("invoice.total",
|
||||||
|
// -workitem.getItemValueDouble("invoice.total"));
|
||||||
|
// }
|
||||||
|
|
||||||
|
String cdtrNumber = workitem.getItemValueString("cdtr.number");
|
||||||
|
if (cdtrNumber.startsWith("K") || cdtrNumber.startsWith("D")) {
|
||||||
|
workitem.setItemValue("cdtr.number", cdtrNumber.substring(1));
|
||||||
|
}
|
||||||
|
// lookup debitor and set name
|
||||||
|
if (cdtrNumber != null && !cdtrNumber.isEmpty())
|
||||||
|
try {
|
||||||
|
ItemCollection cdtr = kreditorDebitorService.findCreditor(cdtrNumber);
|
||||||
|
if (cdtr != null) {
|
||||||
|
workitem.setItemValue("cdtr.name", cdtr.getItemValueString("_vendor_name"));
|
||||||
|
// Anhand der Creditoren Stammdaten errrechnen wir die Sprache für diese
|
||||||
|
// Rechnung
|
||||||
|
String country = cdtr.getItemValueString("_VENDOR_COUNTRY");
|
||||||
|
workitem.setItemValue("cdtr.country", country);
|
||||||
|
if (country.equalsIgnoreCase("de") || country.equalsIgnoreCase("ch")
|
||||||
|
|| country.equalsIgnoreCase("at")) {
|
||||||
|
workitem.setItemValue("invoice.language", "DE");
|
||||||
|
} else {
|
||||||
|
workitem.setItemValue("invoice.language", "EN");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (PluginException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Row Positions lesen
|
||||||
|
// readXMLRows(doc, workitem);
|
||||||
|
|
||||||
|
// Jetzt noch das Space mapping
|
||||||
|
mahnlaufService.mapInvoiceTextToSpace(workitem, spacePosMappings);
|
||||||
|
|
||||||
|
// Rückstellungen ignorieren
|
||||||
|
// if (isRueckStellung(workitem)) {
|
||||||
|
// // Ignore invoice!
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Finally we attache the pdf file and the XML content to the workitem.
|
||||||
|
attacheFiles(doc, workitem);
|
||||||
|
|
||||||
|
} catch (ParserConfigurationException | SAXException | IOException e) {
|
||||||
|
throw new PluginException(CargosoftXMLEAkteImportService.class.getName(),
|
||||||
|
"XML_ERROR", e.getMessage());
|
||||||
|
}
|
||||||
|
return workitem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prüft ob die Rechnung eine Rückstellung ist also mit R1 bis R8 beginnt
|
||||||
|
*
|
||||||
|
* ^R[1-8] .
|
||||||
|
*
|
||||||
|
* @param workitem
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean isRueckStellung(ItemCollection workitem) {
|
||||||
|
String text = workitem.getItemValueString("invoice.text");
|
||||||
|
return text.matches(REGEX_IMPORTTEXTPATTERN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a tag value from the xml tree and set the value into the given
|
||||||
|
* workitem.
|
||||||
|
*
|
||||||
|
* /Invoices/Invoice/InvoiceHeader/Client/Code
|
||||||
|
*
|
||||||
|
* Beispiel Datum:
|
||||||
|
* <InvoiceDate>2024-05-13T00:00:00+02:00</InvoiceDate>
|
||||||
|
*
|
||||||
|
* @param doc - xml doc
|
||||||
|
* @param expression - xpath expression
|
||||||
|
* @param workitem
|
||||||
|
* @param itemName
|
||||||
|
* @param itemType
|
||||||
|
*/
|
||||||
|
private <T> void readXMLValue(Document doc, String expression, ItemCollection workitem, String itemName,
|
||||||
|
Class<T> itemType) {
|
||||||
|
// create XPath...
|
||||||
|
XPathFactory xpathFactory = XPathFactory.newInstance();
|
||||||
|
XPath xpath = xpathFactory.newXPath();
|
||||||
|
XPathExpression xPathExpression;
|
||||||
|
try {
|
||||||
|
xPathExpression = xpath.compile(expression);
|
||||||
|
|
||||||
|
// extract node value
|
||||||
|
Node valueNode = (Node) xPathExpression.evaluate(doc, XPathConstants.NODE);
|
||||||
|
if (valueNode != null) {
|
||||||
|
String value = valueNode.getTextContent();
|
||||||
|
|
||||||
|
if (itemType == Date.class) {
|
||||||
|
// 2024-05-13T00:00:00+02:00
|
||||||
|
SimpleDateFormat formatter = new SimpleDateFormat(DATE_FORMAT);
|
||||||
|
formatter.setTimeZone(TimeZone.getTimeZone("CET"));
|
||||||
|
try {
|
||||||
|
workitem.setItemValue(itemName, formatter.parse(value));
|
||||||
|
} catch (ParseException e) {
|
||||||
|
logger.warning("Invalid Date Format");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (itemType == Double.class && value != null && !value.isEmpty()) {
|
||||||
|
workitem.setItemValue(itemName, Double.parseDouble(value));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (itemType == Integer.class && value != null && !value.isEmpty()) {
|
||||||
|
workitem.setItemValue(itemName, Integer.parseInt(value));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Default String format
|
||||||
|
workitem.setItemValue(itemName, value);
|
||||||
|
|
||||||
|
}
|
||||||
|
} catch (XPathExpressionException e) {
|
||||||
|
logger.warning("Unable to read data field '" + expression + "' : " + e.getMessage());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the positions rows
|
||||||
|
*
|
||||||
|
* InvoiceRows/InvoiceRow
|
||||||
|
*
|
||||||
|
* Each row has the following items:
|
||||||
|
* _childitems {
|
||||||
|
* datev.shzeichen=[H],
|
||||||
|
* datev.kurs=[0.0],
|
||||||
|
* datev.basisumsatz=[0.0],
|
||||||
|
* datev.text=[R LA-PAP-2405-051],
|
||||||
|
* datev.konto=[3851],
|
||||||
|
* datev.umsatz=[3307.81],
|
||||||
|
* datev.wkz=[EUR]}}
|
||||||
|
*
|
||||||
|
* @param doc - xml doc
|
||||||
|
* @param workitem
|
||||||
|
*/
|
||||||
|
private void readXMLRows(Document doc, ItemCollection workitem) {
|
||||||
|
// create XPath...
|
||||||
|
List<ItemCollection> childItems = new ArrayList<>();
|
||||||
|
|
||||||
|
XPathFactory xpathFactory = XPathFactory.newInstance();
|
||||||
|
XPath xPath = xpathFactory.newXPath();
|
||||||
|
try {
|
||||||
|
// Compile the XPath expressions
|
||||||
|
XPathExpression fileNumberExpr = xPath.compile("FileNumber/text()");
|
||||||
|
XPathExpression netAmountCurrencyExpr = xPath
|
||||||
|
.compile("InvoiceAmount/NetAmount/Amount/Currency/Codes/Code[@Type='cs']/text()");
|
||||||
|
XPathExpression netAmountValueExpr = xPath.compile("InvoiceAmount/NetAmount/Amount/Value/text()");
|
||||||
|
XPathExpression netAmountExchangeRateExpr = xPath
|
||||||
|
.compile("InvoiceAmount/NetAmount/Amount/ExchangeRate/text()");
|
||||||
|
|
||||||
|
XPathExpression netActivityTypeExpr = xPath
|
||||||
|
.compile("InvoiceAmount/ActivityType/Codes/Code[@Type='cs']/text()");
|
||||||
|
|
||||||
|
NodeList rowList = doc.getElementsByTagName("InvoiceRow");
|
||||||
|
double _kurs = 0.0;
|
||||||
|
double _baseAmount = 0.0;
|
||||||
|
for (int i = 0; i < rowList.getLength(); i++) {
|
||||||
|
ItemCollection childItemCol = new ItemCollection();
|
||||||
|
Node rowNode = rowList.item(i);
|
||||||
|
if (rowNode.getNodeType() == Node.ELEMENT_NODE) {
|
||||||
|
|
||||||
|
// Get the FileNumber value
|
||||||
|
String fileNumber = (String) fileNumberExpr.evaluate(rowNode, XPathConstants.STRING);
|
||||||
|
childItemCol.setItemValue("datev.text", fileNumber);
|
||||||
|
|
||||||
|
// speichere die Position in invoice.positions zur suche nach dem
|
||||||
|
// Positionskennzeichen
|
||||||
|
workitem.appendItemValue("invoice.positions", fileNumber);
|
||||||
|
|
||||||
|
String currency = (String) netAmountCurrencyExpr.evaluate(rowNode, XPathConstants.STRING);
|
||||||
|
childItemCol.setItemValue("datev.wkz", currency);
|
||||||
|
// Umsatz
|
||||||
|
String umsatz = (String) netAmountValueExpr.evaluate(rowNode, XPathConstants.STRING);
|
||||||
|
double dUmsatz = Double.parseDouble(umsatz);
|
||||||
|
childItemCol.setItemValue("datev.umsatz", dUmsatz);
|
||||||
|
// Kurs
|
||||||
|
String _kursByRow = (String) netAmountExchangeRateExpr.evaluate(rowNode, XPathConstants.STRING);
|
||||||
|
if (_kursByRow != null && !_kursByRow.isEmpty()) {
|
||||||
|
Double dKurs = Double.parseDouble(_kursByRow);
|
||||||
|
_kurs = dKurs;
|
||||||
|
childItemCol.setItemValue("datev.kurs", dKurs);
|
||||||
|
// Basisumsatz
|
||||||
|
if (dKurs != 0) {
|
||||||
|
double basisUmsatz = dUmsatz / dKurs;
|
||||||
|
double gerundeterBasisUmsatz = Math.round(basisUmsatz * 100) / 100.0;
|
||||||
|
|
||||||
|
_baseAmount = _baseAmount + gerundeterBasisUmsatz;
|
||||||
|
|
||||||
|
childItemCol.setItemValue("datev.basisumsatz", gerundeterBasisUmsatz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String activityType = (String) netActivityTypeExpr.evaluate(rowNode, XPathConstants.STRING);
|
||||||
|
childItemCol.setItemValue("category", activityType);
|
||||||
|
|
||||||
|
childItemCol.setItemValue("datev.shzeichen", "H");
|
||||||
|
|
||||||
|
childItems.add(childItemCol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Update invoice.rate und invoice.base.amount
|
||||||
|
workitem.setItemValue("invoice.rate", _kurs);
|
||||||
|
_baseAmount = Math.round(_baseAmount * 100) / 100.0;
|
||||||
|
workitem.setItemValue("invoice.base.amount", _baseAmount);
|
||||||
|
|
||||||
|
} catch (XPathExpressionException e) {
|
||||||
|
logger.warning("Unable to read row : " + e.getMessage());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set child items
|
||||||
|
InvoiceUtil.implodeChildList(workitem, childItems);
|
||||||
|
// invoice.text ist erste position
|
||||||
|
workitem.setItemValue("invoice.text", workitem.getItemValueString("invoice.positions"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method attache the pdf file and the XML file to the workitem.
|
||||||
|
* The method removes the file content first form the xml tree and attache the
|
||||||
|
* XML without the pdf data.
|
||||||
|
*
|
||||||
|
* @throws XPathExpressionException
|
||||||
|
* @throws TransformerException
|
||||||
|
*/
|
||||||
|
private void attacheFiles(Document doc, ItemCollection workitem)
|
||||||
|
throws XPathExpressionException, TransformerException {
|
||||||
|
// create XPath...
|
||||||
|
XPathFactory xpathFactory = XPathFactory.newInstance();
|
||||||
|
XPath xpath = xpathFactory.newXPath();
|
||||||
|
// read filename and content....
|
||||||
|
readXMLValue(doc, "/CargoSoftEFile/EFile/Attachments/Attachment/Filename",
|
||||||
|
workitem, "import.filename", String.class);
|
||||||
|
readXMLValue(doc, "/CargoSoftEFile/EFile/Attachments/Attachment/Content",
|
||||||
|
workitem, "import.filedata", String.class);
|
||||||
|
|
||||||
|
// attache the PDF file content
|
||||||
|
String fileDataString = workitem.getItemValueString("import.filedata");
|
||||||
|
byte[] decodedPDFData = java.util.Base64.getDecoder().decode(fileDataString);
|
||||||
|
FileData fileData = new FileData(workitem.getItemValueString("import.filename"),
|
||||||
|
decodedPDFData, "application/pdf", null);
|
||||||
|
workitem.addFileData(fileData);
|
||||||
|
// remove the temp items..
|
||||||
|
workitem.removeItem("import.filename");
|
||||||
|
workitem.removeItem("import.filedata");
|
||||||
|
|
||||||
|
// next remove the Attachments/AttachmentContent from the dom tree
|
||||||
|
XPathExpression attachmentsExpr = xpath
|
||||||
|
.compile("/CargoSoftEFile/EFile/Attachments/Attachment/Content");
|
||||||
|
NodeList contentNodes = (NodeList) attachmentsExpr.evaluate(doc, XPathConstants.NODESET);
|
||||||
|
// Remove the matching nodes
|
||||||
|
for (int i = 0; i < contentNodes.getLength(); i++) {
|
||||||
|
Node contentNode = contentNodes.item(i);
|
||||||
|
Node parentNode = contentNode.getParentNode();
|
||||||
|
parentNode.removeChild(contentNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now attache the XML tree without the file...
|
||||||
|
StringWriter stringWriter = new StringWriter();
|
||||||
|
TransformerFactory transformerFactory = TransformerFactory.newInstance();
|
||||||
|
Transformer transformer = transformerFactory.newTransformer();
|
||||||
|
DOMSource source = new DOMSource(doc);
|
||||||
|
StreamResult result = new StreamResult(stringWriter);
|
||||||
|
transformer.transform(source, result);
|
||||||
|
// byte[] decodedXMLData =
|
||||||
|
// java.util.Base64.getDecoder().decode(stringWriter.toString().);
|
||||||
|
FileData fileDataXML = new FileData(workitem.getItemValueString("cargosoft.import.filename"),
|
||||||
|
stringWriter.toString().getBytes(), "application/xml", null);
|
||||||
|
workitem.addFileData(fileDataXML);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prüft ob die Belegnummer schon existiert (importiert wurde)
|
||||||
|
*
|
||||||
|
* @param belegNummer
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean alreadyImported(String belegNummer) {
|
||||||
|
|
||||||
|
String sQuery = "((type:workitem OR type:workitemarchive) AND $modelversion:steuerbescheid* AND invoice.number:\""
|
||||||
|
+ belegNummer + "\")";
|
||||||
|
try {
|
||||||
|
// find the textblock...
|
||||||
|
List<ItemCollection> result = documentService.find(sQuery, 1, 0);
|
||||||
|
if (result.size() > 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (QueryException e) {
|
||||||
|
logger.warning("failed to search invoices by query: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -472,6 +472,9 @@ public class CargosoftXMLInvoiceImportService {
|
||||||
// Row Positions lesen
|
// Row Positions lesen
|
||||||
readXMLRows(doc, workitem);
|
readXMLRows(doc, workitem);
|
||||||
|
|
||||||
|
// Suche die ATC Nummer....
|
||||||
|
resolveATCNumber(doc, workitem);
|
||||||
|
|
||||||
// Jetzt noch das Space mapping
|
// Jetzt noch das Space mapping
|
||||||
mahnlaufService.mapInvoiceTextToSpace(workitem, spacePosMappings);
|
mahnlaufService.mapInvoiceTextToSpace(workitem, spacePosMappings);
|
||||||
|
|
||||||
|
|
@ -562,6 +565,36 @@ public class CargosoftXMLInvoiceImportService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hilfsmethode die die ATC Nummer sucht.
|
||||||
|
* Wir gehen davon aus, das diese pro Rechnung nur einmal existieren kann.
|
||||||
|
*
|
||||||
|
* @param doc
|
||||||
|
* @param workitem
|
||||||
|
*/
|
||||||
|
private void resolveATCNumber(Document doc, ItemCollection workitem) {
|
||||||
|
String atcNumber = null;
|
||||||
|
// Liste der BillingText-Elemente erhalten
|
||||||
|
NodeList billingTextList = doc.getElementsByTagName("BillingText");
|
||||||
|
if (billingTextList == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Über die Liste iterieren und nach einem BillingText suchen, der mit "ATC"
|
||||||
|
// beginnt
|
||||||
|
for (int i = 0; i < billingTextList.getLength(); i++) {
|
||||||
|
Node billingTextNode = billingTextList.item(i);
|
||||||
|
if (billingTextNode.getNodeType() == Node.ELEMENT_NODE) {
|
||||||
|
String billingText = billingTextNode.getTextContent().trim();
|
||||||
|
if (billingText.startsWith("ATC")) {
|
||||||
|
atcNumber = billingText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (atcNumber != null && !atcNumber.isEmpty()) {
|
||||||
|
workitem.setItemValue("invoice.atc.number", atcNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the positions rows
|
* Reads the positions rows
|
||||||
*
|
*
|
||||||
|
|
@ -596,7 +629,7 @@ public class CargosoftXMLInvoiceImportService {
|
||||||
.compile("InvoiceAmount/NetAmount/Amount/ExchangeRate/text()");
|
.compile("InvoiceAmount/NetAmount/Amount/ExchangeRate/text()");
|
||||||
|
|
||||||
XPathExpression netActivityTypeExpr = xPath
|
XPathExpression netActivityTypeExpr = xPath
|
||||||
.compile("InvoiceAmount/ActivityType/Codes/Code[@Type='cs']/text()");
|
.compile("ActivityType/Codes/Code[@Type='cs']/text()");
|
||||||
|
|
||||||
NodeList rowList = doc.getElementsByTagName("InvoiceRow");
|
NodeList rowList = doc.getElementsByTagName("InvoiceRow");
|
||||||
double _kurs = 0.0;
|
double _kurs = 0.0;
|
||||||
|
|
|
||||||
|
|
@ -184,13 +184,15 @@
|
||||||
<dl>
|
<dl>
|
||||||
<dt>Type</dt>
|
<dt>Type</dt>
|
||||||
<dd>
|
<dd>
|
||||||
<h:selectOneRadio
|
<h:selectOneRadio layout="pageDirection"
|
||||||
value="#{documentImportController.source.item['type']}">
|
value="#{documentImportController.source.item['type']}">
|
||||||
<f:selectItem itemLabel="IMAP" itemValue="IMAP" />
|
<f:selectItem itemLabel="IMAP" itemValue="IMAP" />
|
||||||
<f:selectItem itemLabel="FTP" itemValue="FTP" />
|
<f:selectItem itemLabel="FTP" itemValue="FTP" />
|
||||||
<f:selectItem itemLabel="CSV" itemValue="CSV" />
|
<f:selectItem itemLabel="CSV" itemValue="CSV" />
|
||||||
<f:selectItem itemLabel="Cargosoft Invoice Import"
|
<f:selectItem itemLabel="Cargosoft Invoice Import"
|
||||||
itemValue="CARGOSOFT_INVOICE_XML" />
|
itemValue="CARGOSOFT_INVOICE_XML" />
|
||||||
|
<f:selectItem itemLabel="Cargosoft eAkte Import"
|
||||||
|
itemValue="CARGOSOFT_EAKTE_XML" />
|
||||||
</h:selectOneRadio>
|
</h:selectOneRadio>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<!-- origin at X=0.0 Y=0.0 --><bpmn2:definitions xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:imixs="http://www.imixs.org/bpmn2" xmlns:open-bpmn="http://open-bpmn.org/XMLSchema" xmlns:tl="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" exporter="org.eclipse.bpmn2.modeler.core" exporterVersion="1.5.4.RC1-v20220528-0836-B1" id="Definitions_1" name="Definitions 1" targetNamespace="http://www.imixs.org/bpmn2">
|
<!-- origin at X=0.0 Y=0.0 --><bpmn2:definitions xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:imixs="http://www.imixs.org/bpmn2" xmlns:open-bpmn="http://open-bpmn.org/XMLSchema" xmlns:tl="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" exporter="org.eclipse.bpmn2.modeler.core" exporterVersion="1.5.4.RC1-v20220528-0836-B1" id="Definitions_1" name="Definitions 1" targetNamespace="http://www.imixs.org/bpmn2">
|
||||||
<bpmn2:extensionElements>
|
<bpmn2:extensionElements>
|
||||||
<imixs:item name="txtworkflowmodelversion" type="xs:string">
|
<imixs:item name="txtworkflowmodelversion" type="xs:string">
|
||||||
<imixs:value><![CDATA[zollanmeldung-de-1.0]]></imixs:value>
|
<imixs:value><![CDATA[steuerbescheid-de-1.0]]></imixs:value>
|
||||||
</imixs:item>
|
</imixs:item>
|
||||||
<imixs:item name="txtfieldmapping" type="xs:string">
|
<imixs:item name="txtfieldmapping" type="xs:string">
|
||||||
<imixs:value><![CDATA[Prozess-Verantwortliche|process.manager]]></imixs:value>
|
<imixs:value><![CDATA[Prozess-Verantwortliche|process.manager]]></imixs:value>
|
||||||
|
|
@ -72,15 +72,15 @@ th { font-weight: bold;}
|
||||||
</html>]]></bpmn2:documentation>
|
</html>]]></bpmn2:documentation>
|
||||||
</bpmn2:message>
|
</bpmn2:message>
|
||||||
<bpmn2:collaboration id="Collaboration_1" name="Zahlungseingang">
|
<bpmn2:collaboration id="Collaboration_1" name="Zahlungseingang">
|
||||||
<bpmn2:participant id="Participant_1" name="Zollanmeldung" processRef="Process_1">
|
<bpmn2:participant id="Participant_1" name="Steuerbescheid" processRef="Process_1">
|
||||||
<bpmn2:documentation id="documentation_9Tp5PA"/>
|
<bpmn2:documentation id="documentation_9Tp5PA"/>
|
||||||
</bpmn2:participant>
|
</bpmn2:participant>
|
||||||
<bpmn2:participant id="Participant_2" name="SEPA-Export Pool" processRef="eingangsrechnung-de"/>
|
<bpmn2:participant id="Participant_2" name="SEPA-Export Pool" processRef="eingangsrechnung-de"/>
|
||||||
</bpmn2:collaboration>
|
</bpmn2:collaboration>
|
||||||
<bpmn2:process id="eingangsrechnung-de" isExecutable="false" name="Zollanmeldung">
|
<bpmn2:process id="eingangsrechnung-de" isExecutable="false" name="Steuerbescheid">
|
||||||
<bpmn2:documentation id="documentation_GmzFcw"/>
|
<bpmn2:documentation id="documentation_GmzFcw"/>
|
||||||
</bpmn2:process>
|
</bpmn2:process>
|
||||||
<bpmn2:process definitionalCollaborationRef="Collaboration_1" id="Process_1" isExecutable="false" name="Zollanmeldung">
|
<bpmn2:process definitionalCollaborationRef="Collaboration_1" id="Process_1" isExecutable="false" name="Steuerbescheid">
|
||||||
<bpmn2:laneSet id="LaneSet_1" name="Lane Set 1">
|
<bpmn2:laneSet id="LaneSet_1" name="Lane Set 1">
|
||||||
<bpmn2:lane id="Lane_1" name="Fachbereich">
|
<bpmn2:lane id="Lane_1" name="Fachbereich">
|
||||||
<bpmn2:flowNodeRef>StartEvent_1</bpmn2:flowNodeRef>
|
<bpmn2:flowNodeRef>StartEvent_1</bpmn2:flowNodeRef>
|
||||||
|
|
@ -176,8 +176,7 @@ th { font-weight: bold;}
|
||||||
<bpmn2:documentation id="Documentation_3"><![CDATA[<textblock><itemvalue>$workflowgroup</itemvalue> - <itemvalue>$workflowstatus</itemvalue></textblock>]]></bpmn2:documentation>
|
<bpmn2:documentation id="Documentation_3"><![CDATA[<textblock><itemvalue>$workflowgroup</itemvalue> - <itemvalue>$workflowstatus</itemvalue></textblock>]]></bpmn2:documentation>
|
||||||
<bpmn2:outgoing>sequenceFlow_EzmiPA</bpmn2:outgoing>
|
<bpmn2:outgoing>sequenceFlow_EzmiPA</bpmn2:outgoing>
|
||||||
<bpmn2:incoming>sequenceFlow_rbVgQA</bpmn2:incoming>
|
<bpmn2:incoming>sequenceFlow_rbVgQA</bpmn2:incoming>
|
||||||
<bpmn2:outgoing>sequenceFlow_aXX5dg</bpmn2:outgoing>
|
<bpmn2:incoming>sequenceFlow_GN53Kg</bpmn2:incoming>
|
||||||
<bpmn2:incoming>sequenceFlow_M5IK7w</bpmn2:incoming>
|
|
||||||
</bpmn2:task>
|
</bpmn2:task>
|
||||||
<bpmn2:task id="Task_4" imixs:processid="1900" name="Abgeschlossen">
|
<bpmn2:task id="Task_4" imixs:processid="1900" name="Abgeschlossen">
|
||||||
<bpmn2:extensionElements>
|
<bpmn2:extensionElements>
|
||||||
|
|
@ -206,7 +205,6 @@ th { font-weight: bold;}
|
||||||
<bpmn2:documentation id="Documentation_16"><![CDATA[<textblock><itemvalue>$workflowgroup</itemvalue> - <itemvalue>$workflowstatus</itemvalue></textblock>]]></bpmn2:documentation>
|
<bpmn2:documentation id="Documentation_16"><![CDATA[<textblock><itemvalue>$workflowgroup</itemvalue> - <itemvalue>$workflowstatus</itemvalue></textblock>]]></bpmn2:documentation>
|
||||||
<bpmn2:incoming>SequenceFlow_18</bpmn2:incoming>
|
<bpmn2:incoming>SequenceFlow_18</bpmn2:incoming>
|
||||||
<bpmn2:outgoing>SequenceFlow_19</bpmn2:outgoing>
|
<bpmn2:outgoing>SequenceFlow_19</bpmn2:outgoing>
|
||||||
<bpmn2:incoming>sequenceFlow_MTbeHA</bpmn2:incoming>
|
|
||||||
</bpmn2:task>
|
</bpmn2:task>
|
||||||
<bpmn2:intermediateCatchEvent id="IntermediateCatchEvent_8" imixs:activityid="50" name="Abschließen">
|
<bpmn2:intermediateCatchEvent id="IntermediateCatchEvent_8" imixs:activityid="50" name="Abschließen">
|
||||||
<bpmn2:extensionElements>
|
<bpmn2:extensionElements>
|
||||||
|
|
@ -242,7 +240,7 @@ th { font-weight: bold;}
|
||||||
<bpmn2:sequenceFlow id="SequenceFlow_1" sourceRef="IntermediateCatchEvent_2" targetRef="Task_2">
|
<bpmn2:sequenceFlow id="SequenceFlow_1" sourceRef="IntermediateCatchEvent_2" targetRef="Task_2">
|
||||||
<bpmn2:documentation id="documentation_ZiY0pQ"/>
|
<bpmn2:documentation id="documentation_ZiY0pQ"/>
|
||||||
</bpmn2:sequenceFlow>
|
</bpmn2:sequenceFlow>
|
||||||
<bpmn2:intermediateCatchEvent id="IntermediateCatchEvent_3" imixs:activityid="980" name="[create]">
|
<bpmn2:intermediateCatchEvent id="IntermediateCatchEvent_3" imixs:activityid="900" name="[create]">
|
||||||
<bpmn2:extensionElements>
|
<bpmn2:extensionElements>
|
||||||
<imixs:item name="txtmailsubject" type="xs:string">
|
<imixs:item name="txtmailsubject" type="xs:string">
|
||||||
<imixs:value/>
|
<imixs:value/>
|
||||||
|
|
@ -263,8 +261,8 @@ th { font-weight: bold;}
|
||||||
</bpmn2:extensionElements>
|
</bpmn2:extensionElements>
|
||||||
<bpmn2:messageEventDefinition id="MessageEventDefinition_1"/>
|
<bpmn2:messageEventDefinition id="MessageEventDefinition_1"/>
|
||||||
<bpmn2:documentation id="documentation_pNB3fg"/>
|
<bpmn2:documentation id="documentation_pNB3fg"/>
|
||||||
<bpmn2:incoming>sequenceFlow_aXX5dg</bpmn2:incoming>
|
<bpmn2:incoming>sequenceFlow_M5IK7w</bpmn2:incoming>
|
||||||
<bpmn2:outgoing>sequenceFlow_MTbeHA</bpmn2:outgoing>
|
<bpmn2:outgoing>sequenceFlow_GN53Kg</bpmn2:outgoing>
|
||||||
</bpmn2:intermediateCatchEvent>
|
</bpmn2:intermediateCatchEvent>
|
||||||
<bpmn2:dataObject id="DataObject_2" name="Form">
|
<bpmn2:dataObject id="DataObject_2" name="Form">
|
||||||
<bpmn2:documentation id="Documentation_5"><![CDATA[<?xml version="1.0"?>
|
<bpmn2:documentation id="Documentation_5"><![CDATA[<?xml version="1.0"?>
|
||||||
|
|
@ -328,18 +326,15 @@ Wird täglich über die DATEV OP-Liste importiert]]></bpmn2:text>
|
||||||
<bpmn2:sequenceFlow id="sequenceFlow_rbVgQA" sourceRef="event_9fS4uw" targetRef="Task_1">
|
<bpmn2:sequenceFlow id="sequenceFlow_rbVgQA" sourceRef="event_9fS4uw" targetRef="Task_1">
|
||||||
<bpmn2:documentation id="documentation_AcFalQ"/>
|
<bpmn2:documentation id="documentation_AcFalQ"/>
|
||||||
</bpmn2:sequenceFlow>
|
</bpmn2:sequenceFlow>
|
||||||
<bpmn2:sequenceFlow id="sequenceFlow_aXX5dg" sourceRef="Task_1" targetRef="IntermediateCatchEvent_3">
|
<bpmn2:sequenceFlow id="sequenceFlow_M5IK7w" sourceRef="StartEvent_1" targetRef="IntermediateCatchEvent_3">
|
||||||
<bpmn2:documentation id="documentation_OFz0ng"/>
|
|
||||||
</bpmn2:sequenceFlow>
|
|
||||||
<bpmn2:sequenceFlow id="sequenceFlow_MTbeHA" sourceRef="IntermediateCatchEvent_3" targetRef="Task_4">
|
|
||||||
<bpmn2:documentation id="documentation_AWXRsQ"/>
|
|
||||||
</bpmn2:sequenceFlow>
|
|
||||||
<bpmn2:sequenceFlow id="sequenceFlow_M5IK7w" sourceRef="StartEvent_1" targetRef="Task_1">
|
|
||||||
<bpmn2:documentation id="documentation_nuyBIg"/>
|
<bpmn2:documentation id="documentation_nuyBIg"/>
|
||||||
</bpmn2:sequenceFlow>
|
</bpmn2:sequenceFlow>
|
||||||
<bpmn2:association id="association_2r0omw" sourceRef="DataObject_2" targetRef="Task_4">
|
<bpmn2:association id="association_2r0omw" sourceRef="DataObject_2" targetRef="Task_4">
|
||||||
<bpmn2:documentation id="documentation_6aRYjQ"/>
|
<bpmn2:documentation id="documentation_6aRYjQ"/>
|
||||||
</bpmn2:association>
|
</bpmn2:association>
|
||||||
|
<bpmn2:sequenceFlow id="sequenceFlow_GN53Kg" sourceRef="IntermediateCatchEvent_3" targetRef="Task_1">
|
||||||
|
<bpmn2:documentation id="documentation_G2kAIg"/>
|
||||||
|
</bpmn2:sequenceFlow>
|
||||||
</bpmn2:process>
|
</bpmn2:process>
|
||||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1" name="Default Process Diagram">
|
<bpmndi:BPMNDiagram id="BPMNDiagram_1" name="Default Process Diagram">
|
||||||
<bpmndi:BPMNPlane bpmnElement="Collaboration_1" id="BPMNPlane_1">
|
<bpmndi:BPMNPlane bpmnElement="Collaboration_1" id="BPMNPlane_1">
|
||||||
|
|
@ -395,9 +390,9 @@ Wird täglich über die DATEV OP-Liste importiert]]></bpmn2:text>
|
||||||
</bpmndi:BPMNLabel>
|
</bpmndi:BPMNLabel>
|
||||||
</bpmndi:BPMNShape>
|
</bpmndi:BPMNShape>
|
||||||
<bpmndi:BPMNShape bpmnElement="IntermediateCatchEvent_3" id="BPMNShape_IntermediateCatchEvent_3">
|
<bpmndi:BPMNShape bpmnElement="IntermediateCatchEvent_3" id="BPMNShape_IntermediateCatchEvent_3">
|
||||||
<dc:Bounds height="36.0" width="36.0" x="447.0" y="217.0"/>
|
<dc:Bounds height="36.0" width="36.0" x="297.0" y="297.0"/>
|
||||||
<bpmndi:BPMNLabel id="BPMNLabel_8" labelStyle="BPMNLabelStyle_1">
|
<bpmndi:BPMNLabel id="BPMNLabel_8" labelStyle="BPMNLabelStyle_1">
|
||||||
<dc:Bounds height="20.0" width="100.0" x="421.5" y="260.0"/>
|
<dc:Bounds height="20.0" width="100.0" x="271.5" y="340.0"/>
|
||||||
</bpmndi:BPMNLabel>
|
</bpmndi:BPMNLabel>
|
||||||
</bpmndi:BPMNShape>
|
</bpmndi:BPMNShape>
|
||||||
<bpmndi:BPMNShape bpmnElement="DataObject_2" id="BPMNShape_DataObject_2">
|
<bpmndi:BPMNShape bpmnElement="DataObject_2" id="BPMNShape_DataObject_2">
|
||||||
|
|
@ -461,26 +456,19 @@ Wird täglich über die DATEV OP-Liste importiert]]></bpmn2:text>
|
||||||
<di:waypoint x="465.0" y="357.0"/>
|
<di:waypoint x="465.0" y="357.0"/>
|
||||||
<di:waypoint x="465.0" y="340.0"/>
|
<di:waypoint x="465.0" y="340.0"/>
|
||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_aXX5dg" id="BPMNEdge_Wkee0Q" sourceElement="BPMNShape_Task_1" targetElement="BPMNShape_IntermediateCatchEvent_3">
|
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_M5IK7w" id="BPMNEdge_gTIgKQ" sourceElement="BPMNShape_1" targetElement="BPMNShape_IntermediateCatchEvent_3">
|
||||||
<di:waypoint x="465.0" y="290.0"/>
|
|
||||||
<di:waypoint x="465.0" y="271.5"/>
|
|
||||||
<di:waypoint x="470.0" y="271.5"/>
|
|
||||||
<di:waypoint x="470.0" y="252.29161646579058"/>
|
|
||||||
</bpmndi:BPMNEdge>
|
|
||||||
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_MTbeHA" id="BPMNEdge_RhmZbw" sourceElement="BPMNShape_IntermediateCatchEvent_3" targetElement="BPMNShape_Task_4">
|
|
||||||
<di:waypoint x="482.54992877478423" y="231.0"/>
|
|
||||||
<di:waypoint x="1175.0" y="231.0"/>
|
|
||||||
<di:waypoint x="1175.0" y="290.0"/>
|
|
||||||
</bpmndi:BPMNEdge>
|
|
||||||
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_M5IK7w" id="BPMNEdge_gTIgKQ" sourceElement="BPMNShape_1" targetElement="BPMNShape_Task_1">
|
|
||||||
<di:waypoint x="263.0" y="315.0"/>
|
<di:waypoint x="263.0" y="315.0"/>
|
||||||
<di:waypoint x="410.0" y="315.0"/>
|
<di:waypoint x="297.0" y="315.0"/>
|
||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
<bpmndi:BPMNEdge bpmnElement="association_2r0omw" id="BPMNEdge_pgk0IA" sourceElement="BPMNShape_DataObject_2" targetElement="BPMNShape_Task_4">
|
<bpmndi:BPMNEdge bpmnElement="association_2r0omw" id="BPMNEdge_pgk0IA" sourceElement="BPMNShape_DataObject_2" targetElement="BPMNShape_Task_4">
|
||||||
<di:waypoint x="775.0" y="525.0"/>
|
<di:waypoint x="775.0" y="525.0"/>
|
||||||
<di:waypoint x="1162.0" y="525.0"/>
|
<di:waypoint x="1162.0" y="525.0"/>
|
||||||
<di:waypoint x="1162.0" y="340.0"/>
|
<di:waypoint x="1162.0" y="340.0"/>
|
||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
|
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_GN53Kg" id="BPMNEdge_RtC0kg" sourceElement="BPMNShape_IntermediateCatchEvent_3" targetElement="BPMNShape_Task_1">
|
||||||
|
<di:waypoint x="333.0" y="315.0"/>
|
||||||
|
<di:waypoint x="410.0" y="315.0"/>
|
||||||
|
</bpmndi:BPMNEdge>
|
||||||
</bpmndi:BPMNPlane>
|
</bpmndi:BPMNPlane>
|
||||||
<bpmndi:BPMNLabelStyle id="BPMNLabelStyle_1">
|
<bpmndi:BPMNLabelStyle id="BPMNLabelStyle_1">
|
||||||
<dc:Font name="arial" size="9.0"/>
|
<dc:Font name="arial" size="9.0"/>
|
||||||
Loading…
Reference in a new issue