added qr-code to invoice

This commit is contained in:
Ralph Soika 2025-12-04 16:48:33 +01:00
parent e09e25766a
commit 5f20bc458b
4 changed files with 413 additions and 127 deletions

View file

@ -7,7 +7,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
@ -21,7 +20,6 @@ import org.apache.pdfbox.pdmodel.PDDocumentNameDictionary;
import org.apache.pdfbox.pdmodel.PDEmbeddedFilesNameTreeNode;
import org.apache.pdfbox.pdmodel.common.filespecification.PDComplexFileSpecification;
import org.apache.pdfbox.pdmodel.common.filespecification.PDEmbeddedFile;
import org.imixs.archive.core.SnapshotService;
import org.imixs.einvoice.EInvoiceFormatException;
import org.imixs.einvoice.EInvoiceModel;
import org.imixs.einvoice.EInvoiceModelFactory;
@ -34,11 +32,11 @@ import org.imixs.workflow.engine.DocumentService;
import org.imixs.workflow.engine.WorkflowService;
import org.imixs.workflow.exceptions.AdapterException;
import org.imixs.workflow.exceptions.PluginException;
import org.imixs.workflow.exceptions.QueryException;
import org.imixs.workflow.util.XMLParser;
import com.alexanderlogistics.BusinessPartnerService;
import com.alexanderlogistics.InvoiceUtil;
import com.alexanderlogistics.ksef.api.KSeFAPIService;
import jakarta.inject.Inject;
@ -80,9 +78,6 @@ import jakarta.inject.Inject;
*/
public class EInvoiceAdapter implements SignalAdapter {
final String TYPE_TEXTBLOCK = "textblock";
public static final String DOCUMENT_ERROR = "DOCUMENT_ERROR";
public static final String CONFIG_ERROR = "CONFIG_ERROR";
public static final String LINE_ITEMS_PROPERTY = "invoice.items";
private static Logger logger = Logger.getLogger(EInvoiceAdapter.class.getName());
@ -97,10 +92,10 @@ public class EInvoiceAdapter implements SignalAdapter {
DocumentService documentService;
@Inject
SnapshotService snapshotService;
BusinessPartnerService businessPartnerService;
@Inject
BusinessPartnerService businessPartnerService;
KSeFAPIService kSeFAPIService;
/**
* This method
@ -117,14 +112,14 @@ public class EInvoiceAdapter implements SignalAdapter {
workitem,
false);
if (eInvoiceConfig == null || !eInvoiceConfig.hasItem("create")) {
throw new PluginException(EInvoiceAdapter.class.getSimpleName(), CONFIG_ERROR,
throw new PluginException(EInvoiceAdapter.class.getSimpleName(), KSeFAPIService.CONFIG_ERROR,
"missing e-invoice configuration in model event - please check model configuration");
}
ItemCollection createDefinition = XMLParser.parseItemStructure(eInvoiceConfig.getItemValueString("CREATE"));
try {
// Load the e-invoice template....
FileData xmlFileData = loadXMLTemplate(workitem, createDefinition);
FileData pdfFileData = loadPDF(workitem);
FileData xmlFileData = kSeFAPIService.loadXMLTemplate(workitem, createDefinition);
FileData pdfFileData = kSeFAPIService.loadPDF(workitem);
logger.info("│ ├── Source File: " + pdfFileData.getName());
@ -148,47 +143,50 @@ public class EInvoiceAdapter implements SignalAdapter {
return workitem;
}
/**
* This helper method tries to find the pdf file matching the item
* 'cargosoft.import.filename'. If not found the method returns the first .pdf
* file form the list of attachments. The method returns null if no pdf file
* exits
*
* @param workitem
* @return the pdf FileData object
* @throws PluginException if not pdf file was found
*/
private FileData loadPDF(ItemCollection workitem) throws PluginException {
FileData pdfFileData = null;
String cargosoftFileName = workitem.getItemValueString("cargosoft.import.filename");
if (!cargosoftFileName.isEmpty()) {
cargosoftFileName = cargosoftFileName.replace(".xml", ".pdf");
// /**
// * This helper method tries to find the pdf file matching the item
// * 'cargosoft.import.filename'. If not found the method returns the first .pdf
// * file form the list of attachments. The method returns null if no pdf file
// * exits
// *
// * @param workitem
// * @return the pdf FileData object
// * @throws PluginException if not pdf file was found
// */
// private FileData loadPDF(ItemCollection workitem) throws PluginException {
// FileData pdfFileData = null;
// String cargosoftFileName =
// workitem.getItemValueString("cargosoft.import.filename");
// if (!cargosoftFileName.isEmpty()) {
// cargosoftFileName = cargosoftFileName.replace(".xml", ".pdf");
// try to load filedata....
pdfFileData = snapshotService.getWorkItemFile(workitem.getUniqueID(), cargosoftFileName);
// // try to load filedata....
// pdfFileData = snapshotService.getWorkItemFile(workitem.getUniqueID(),
// cargosoftFileName);
}
// }
if (pdfFileData == null) {
// take first pdf file available
List<String> fileNames = workitem.getFileNames();
for (String filename : fileNames) {
// if (pdfFileData == null) {
// // take first pdf file available
// List<String> fileNames = workitem.getFileNames();
// for (String filename : fileNames) {
if (filename.toLowerCase().endsWith(".pdf")) {
pdfFileData = snapshotService.getWorkItemFile(workitem.getUniqueID(), filename);
break;
}
}
}
// if (filename.toLowerCase().endsWith(".pdf")) {
// pdfFileData = snapshotService.getWorkItemFile(workitem.getUniqueID(),
// filename);
// break;
// }
// }
// }
if (pdfFileData == null) {
throw new PluginException(EInvoiceAdapter.class.getSimpleName(),
DOCUMENT_ERROR,
"DOCUMENT_ERROR: no pdf file found!");
}
return pdfFileData;
// if (pdfFileData == null) {
// throw new PluginException(EInvoiceAdapter.class.getSimpleName(),
// DOCUMENT_ERROR,
// "DOCUMENT_ERROR: no pdf file found!");
// }
// return pdfFileData;
}
// }
private FileData embeddXML(FileData pdfFileData, FileData xmlFileData) throws PluginException {
try {
@ -236,7 +234,7 @@ public class EInvoiceAdapter implements SignalAdapter {
} catch (IOException e) {
// TODO Auto-generated catch block
throw new PluginException(EInvoiceAdapter.class.getSimpleName(), CONFIG_ERROR,
throw new PluginException(EInvoiceAdapter.class.getSimpleName(), KSeFAPIService.CONFIG_ERROR,
"Failed to generate e-invoice: " + e.getMessage());
}
}
@ -298,7 +296,7 @@ public class EInvoiceAdapter implements SignalAdapter {
fileDataXMLTemplate.setContent(model.getContent());
} catch (FileNotFoundException | EInvoiceFormatException | TransformerException e) {
throw new PluginException(this.getClass().getName(), DOCUMENT_ERROR, e.getMessage(), e);
throw new PluginException(this.getClass().getName(), KSeFAPIService.DOCUMENT_ERROR, e.getMessage(), e);
}
}
@ -312,12 +310,12 @@ public class EInvoiceAdapter implements SignalAdapter {
*/
public TradeParty buildAddress(String partnerID, String type) throws PluginException {
if (partnerID == null || partnerID.isEmpty()) {
throw new PluginException(this.getClass().getName(), DOCUMENT_ERROR, "Missing partnerID");
throw new PluginException(this.getClass().getName(), KSeFAPIService.DOCUMENT_ERROR, "Missing partnerID");
}
ItemCollection businessPartner = businessPartnerService.getBusinessPartnerByID(partnerID);
if (businessPartner == null) {
throw new PluginException(this.getClass().getName(), DOCUMENT_ERROR,
throw new PluginException(this.getClass().getName(), KSeFAPIService.DOCUMENT_ERROR,
"Business Partner ID '" + partnerID + "' does not exist");
}
TradeParty tradeParty = new TradeParty(type);
@ -352,80 +350,4 @@ public class EInvoiceAdapter implements SignalAdapter {
return tradeLineItem;
}
/**
* This method loads a text-block for a specified ref and appends the named
* fileData object of this document.
*
* @param document
* @throws PluginException
*/
private FileData loadXMLTemplate(ItemCollection workitem, ItemCollection config)
throws PluginException {
String textblock = config.getItemValueString("textblock");
String template = config.getItemValueString("template");
String sourceName = config.getItemValueString("source");
try {
debug = Boolean.parseBoolean(config.getItemValueString("debug"));
} catch (Exception e) {
}
String targetName = "factur-x.xml";
// adapt text....
sourceName = workflowService.adaptText(sourceName, workitem);
if ((template == null || template.isEmpty()) || (textblock == null || textblock.isEmpty())) {
throw new PluginException(EInvoiceAdapter.class.getSimpleName(),
CONFIG_ERROR,
"invalid e-invoice configuration in model event - textblock/template reference not defined!");
}
// load the text block
FileData fileData = loadTextBlockFileData(textblock, template);
// do we found the document?
if (fileData == null) {
throw new PluginException(EInvoiceAdapter.class.getSimpleName(),
CONFIG_ERROR,
"invalid e-invoice configuration in model event - textblock/template: " + textblock + "/" + template
+ " not found!");
}
fileData.setName(targetName);
return fileData;
}
/**
* This method returns a text-block ItemCollection for a specified name.
*
* @param name in attribute txtname
*
*
*/
public FileData loadTextBlockFileData(String name, String fileName) {
ItemCollection textBlockItemCollection = null;
// load text-block by name....
String sQuery = "(type:\"" + TYPE_TEXTBLOCK + "\" AND txtname:\"" + name + "\")";
Collection<ItemCollection> col;
try {
// find the textblock...
col = documentService.find(sQuery, 1, 0);
if (col.size() > 0) {
textBlockItemCollection = col.iterator().next();
// fetch the fileData...
return snapshotService.getWorkItemFile(textBlockItemCollection.getUniqueID(), fileName);
} else {
logger.warning("Missing text-block : '" + name + "'");
}
} catch (QueryException e) {
logger.warning("getTextBlock - invalid query: " + e.getMessage());
}
return null;
}
}

View file

@ -0,0 +1,51 @@
package com.alexanderlogistics.einvoice;
import org.imixs.archive.core.SnapshotService;
import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.SignalAdapter;
import org.imixs.workflow.engine.DocumentService;
import org.imixs.workflow.engine.WorkflowService;
import org.imixs.workflow.exceptions.AdapterException;
import org.imixs.workflow.exceptions.PluginException;
import com.alexanderlogistics.BusinessPartnerService;
import com.alexanderlogistics.ksef.api.KSeFAPIService;
import jakarta.inject.Inject;
/**
*
* @version 1.0
* @author rsoika
*/
public class QRTest implements SignalAdapter {
@Inject
WorkflowService workflowService;
@Inject
DocumentService documentService;
@Inject
SnapshotService snapshotService;
@Inject
BusinessPartnerService businessPartnerService;
@Inject
KSeFAPIService kSeFAPIService;
/**
* This method
*
* @throws PluginException
*/
@Override
public ItemCollection execute(ItemCollection workitem, ItemCollection event)
throws AdapterException, PluginException {
kSeFAPIService.embedQRCode(workitem);
return workitem;
}
}

View file

@ -12,6 +12,7 @@ import java.security.NoSuchAlgorithmException;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Collection;
import java.util.List;
import java.util.logging.Logger;
import java.util.stream.Collectors;
@ -23,11 +24,18 @@ import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.imixs.archive.core.SnapshotService;
import org.imixs.workflow.FileData;
import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.engine.DocumentService;
import org.imixs.workflow.engine.WorkflowService;
import org.imixs.workflow.exceptions.PluginException;
import org.imixs.workflow.exceptions.QueryException;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.WriterException;
@ -64,6 +72,9 @@ public class KSeFAPIService {
private static Logger logger = Logger.getLogger(KSeFAPIService.class.getName());
public static final String ERROR_API = "API_ERROR";
public static final String DOCUMENT_ERROR = "DOCUMENT_ERROR";
public static final String CONFIG_ERROR = "CONFIG_ERROR";
final String TYPE_TEXTBLOCK = "textblock";
@Inject
KSeFAuthManager kseFAuthManager;
@ -71,6 +82,9 @@ public class KSeFAPIService {
@Inject
DocumentService documentService;
@Inject
WorkflowService workflowService;
@Inject
SnapshotService snapshotService;
@ -249,6 +263,9 @@ public class KSeFAPIService {
// store QR Code
generateQRCode(workitem);
// print QR Code to pdf
embedQRCode(workitem);
}
} catch (IOException | NoSuchAlgorithmException | InterruptedException e) {
@ -453,6 +470,88 @@ public class KSeFAPIService {
}
}
/**
* This helper method prints the QR Code on the AGL Invoice document
*
* @param workitem
* @throws PluginException
*/
public void embedQRCode(ItemCollection workitem) {
try {
FileData pdfFileData = this.loadPDF(workitem);
String ksefRefNumber = workitem.getItemValueString("ksef.referenceNumber");
FileData qrCodeFileData = workitem.getFileData(ksefRefNumber + ".png");
if (qrCodeFileData.getContent().length == 0) {
qrCodeFileData = snapshotService.getWorkItemFile(workitem.getUniqueID(), ksefRefNumber + ".png");
}
// now we have the QR Code (qrCodeFileData) and the PDF (pdfFileData)
PDDocument document = PDDocument.load(pdfFileData.getContent());
logger.info("pdf file loaded, embed qrcode...");
// place thee PNG on the first page 10x10 cm from left upper corner
// ....
PDPage page = document.getPage(0);
PDImageXObject pdImage = PDImageXObject.createFromByteArray(document, qrCodeFileData.getContent(),
pdfFileData.getName());
// PDPageContentStream contentStream = new PDPageContentStream(document, page);
PDPageContentStream contentStream = new PDPageContentStream(
document,
page,
PDPageContentStream.AppendMode.APPEND, // Append statt Overwrite
true, // compress
true // resetContext - wichtig für konsistente Grafik-Zustände
);
// Mit Größenangabe (Breite und Höhe in Points):
// QR-Code zeichnen
// Seitenhöhe auslesen
float pageHeight = page.getMediaBox().getHeight();
// Position von OBEN berechnen (z.B. 50 Points vom oberen Rand)
float marginFromTop = 230;
float imageWidth = 50;
float imageHeight = 50;
float imageX = 350;
float imageY = pageHeight - marginFromTop - imageHeight; // Von oben berechnet!
contentStream.drawImage(pdImage, imageX, imageY, imageWidth, imageHeight);
// Text darunter schreiben
String text = "KSeF-No.: " + workitem.getItemValueString("ksef.number");
float fontSize = 7;
PDType1Font font = PDType1Font.COURIER;
float textX = imageX + 5;
float textY = imageY - 5; // 10 Points unter dem Bild
contentStream.beginText();
contentStream.setFont(font, fontSize);
contentStream.newLineAtOffset(textX, textY);
contentStream.showText(text);
contentStream.endText();
contentStream.close();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
document.save(baos);
byte[] eInvoiceData = baos.toByteArray();
document.close();
baos.close();
pdfFileData.setContent(eInvoiceData);
// finally update the pdf file
workitem.removeFile(pdfFileData.getName());
// set new pdf file...
workitem.addFileData(pdfFileData);
} catch (IOException | PluginException e) {
logger.warning("Failed to embed QR Code on PDF file: " + e.getMessage());
}
}
/**
* Encrypt invoice XML with the session encryption keys
*
@ -505,4 +604,117 @@ public class KSeFAPIService {
return Base64.getEncoder().encodeToString(hashBytes);
}
/**
* This helper method tries to find the pdf file matching the item
* 'cargosoft.import.filename'. If not found the method returns the first .pdf
* file form the list of attachments. The method returns null if no pdf file
* exits
*
* @param workitem
* @return the pdf FileData object
* @throws PluginException if not pdf file was found
*/
public FileData loadPDF(ItemCollection workitem) throws PluginException {
FileData pdfFileData = null;
String cargosoftFileName = workitem.getItemValueString("cargosoft.import.filename");
if (!cargosoftFileName.isEmpty()) {
cargosoftFileName = cargosoftFileName.replace(".xml", ".pdf");
// try to load filedata....
pdfFileData = snapshotService.getWorkItemFile(workitem.getUniqueID(), cargosoftFileName);
}
if (pdfFileData == null) {
// take first pdf file available
List<String> fileNames = workitem.getFileNames();
for (String filename : fileNames) {
if (filename.toLowerCase().endsWith(".pdf")) {
pdfFileData = snapshotService.getWorkItemFile(workitem.getUniqueID(), filename);
break;
}
}
}
if (pdfFileData == null) {
throw new PluginException(KSeFAPIService.class.getSimpleName(),
DOCUMENT_ERROR,
"DOCUMENT_ERROR: no pdf file found!");
}
return pdfFileData;
}
/**
* This method returns a text-block ItemCollection for a specified name.
*
* @param name in attribute txtname
*
*
*/
public FileData loadTextBlockFileData(String name, String fileName) {
ItemCollection textBlockItemCollection = null;
// load text-block by name....
String sQuery = "(type:\"" + TYPE_TEXTBLOCK + "\" AND txtname:\"" + name + "\")";
Collection<ItemCollection> col;
try {
// find the textblock...
col = documentService.find(sQuery, 1, 0);
if (col.size() > 0) {
textBlockItemCollection = col.iterator().next();
// fetch the fileData...
return snapshotService.getWorkItemFile(textBlockItemCollection.getUniqueID(), fileName);
} else {
logger.warning("Missing text-block : '" + name + "'");
}
} catch (QueryException e) {
logger.warning("getTextBlock - invalid query: " + e.getMessage());
}
return null;
}
/**
* This method loads a text-block for a specified ref and appends the named
* fileData object of this document.
*
* @param document
* @throws PluginException
*/
public FileData loadXMLTemplate(ItemCollection workitem, ItemCollection config)
throws PluginException {
String textblock = config.getItemValueString("textblock");
String template = config.getItemValueString("template");
String sourceName = config.getItemValueString("source");
String targetName = "factur-x.xml";
// adapt text....
sourceName = workflowService.adaptText(sourceName, workitem);
if ((template == null || template.isEmpty()) || (textblock == null || textblock.isEmpty())) {
throw new PluginException(KSeFAPIService.class.getSimpleName(),
KSeFAPIService.CONFIG_ERROR,
"invalid e-invoice configuration in model event - textblock/template reference not defined!");
}
// load the text block
FileData fileData = this.loadTextBlockFileData(textblock, template);
// do we found the document?
if (fileData == null) {
throw new PluginException(KSeFAPIService.class.getSimpleName(),
KSeFAPIService.CONFIG_ERROR,
"invalid e-invoice configuration in model event - textblock/template: " + textblock + "/" + template
+ " not found!");
}
fileData.setName(targetName);
return fileData;
}
}

View file

@ -173,6 +173,7 @@ th { font-weight: bold;}
<bpmn2:flowNodeRef>ExclusiveGateway_3</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>dataObject_V0KVQg</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>event_w96sOg</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>event_xxUDcA</bpmn2:flowNodeRef>
</bpmn2:lane>
</bpmn2:laneSet>
<bpmn2:intermediateCatchEvent id="IntermediateCatchEvent_5000-20" imixs:activityid="50" name="[Due date]">
@ -340,6 +341,19 @@ Bei Fragen wenden Sie sich bitte an info@imixs.com
<imixs-form-section label="Invoice positions" path="alexander/section_datevbuchung" />
<imixs-form-section label="Payment" path="alexander/section_payments" />
<imixs-form-section label="Dunning" path="alexander/section_dunnings" />
<imixs-form-section columns="1" label="KSeF">
<item name="ksef.encryptedinvoicehash" type="text" label="Encrypted Invoice Hash:" readonly="true" />
<item name="ksef.invoicehash" type="text" label="Invoice Hash:" readonly="true" />
<item name="ksef.number" type="text" label="KSeF Number:" readonly="true" />
<item name="ksef.referencenumber" type="text" label="Ref.No.:" readonly="true" />
<item name="ksef.status.description" type="text" label="Status:" readonly="true" />
<item name="ksef.upo.downloadurl" type="text" label="Download URL:" readonly="true" />
<item name="ksef.upo.referencenumber" type="text" label="UPO Ref.No.:" readonly="true" />
<item name="ksef.verificationurl" type="text" label="Verification URL:" readonly="true" />
</imixs-form-section>
</imixs-form>]]></bpmn2:documentation>
<bpmn2:dataState id="DataState_1"/>
</bpmn2:dataObject>
@ -496,6 +510,7 @@ Bei Fragen wenden Sie sich bitte an info@imixs.com
<bpmn2:documentation id="Documentation_9"><![CDATA[<textblock><itemvalue>$workflowgroup</itemvalue> - <itemvalue>$workflowstatus</itemvalue></textblock>]]></bpmn2:documentation>
<bpmn2:incoming>SequenceFlow_27</bpmn2:incoming>
<bpmn2:incoming>sequenceFlow_EZX5kQ</bpmn2:incoming>
<bpmn2:incoming>sequenceFlow_seshBg</bpmn2:incoming>
<bpmn2:outgoing>SequenceFlow_18</bpmn2:outgoing>
<bpmn2:outgoing>SequenceFlow_34</bpmn2:outgoing>
<bpmn2:incoming>sequenceFlow_zhcE7Q</bpmn2:incoming>
@ -2428,7 +2443,7 @@ Wiedervorlage wird um 7 bzw. 5 Tage erhöht</bpmn2:text>
<bpmn2:association id="association_PwhTLg" sourceRef="textAnnotation_zVr90Q" targetRef="event_NIn1DQ">
<bpmn2:documentation id="documentation_3RHL2w"/>
</bpmn2:association>
<bpmn2:intermediateThrowEvent id="event_rTm4Aw" name="KSEF">
<bpmn2:intermediateThrowEvent id="event_rTm4Aw" name="EINVOICE">
<bpmn2:incoming>sequenceFlow_bRxzKQ</bpmn2:incoming>
<bpmn2:linkEventDefinition id="linkEventDefinition_XpOKjQ" name="Link Event Definition 5"/>
<bpmn2:documentation id="documentation_jDLGbA"/>
@ -2571,6 +2586,79 @@ Wiedervorlage wird um 7 bzw. 5 Tage erhöht</bpmn2:text>
<bpmn2:association id="association_XEg2bw" sourceRef="task_aZVPjw" targetRef="textAnnotation_CARutw">
<bpmn2:documentation id="documentation_LZEbVQ"/>
</bpmn2:association>
<bpmn2:intermediateCatchEvent id="event_xxUDcA" imixs:activityid="10" name="Save">
<bpmn2:extensionElements>
<imixs:item name="keylogtimeformat" type="xs:string">
<imixs:value><![CDATA[2]]></imixs:value>
</imixs:item>
<imixs:item name="keyarchive" type="xs:string">
<imixs:value><![CDATA[0]]></imixs:value>
</imixs:item>
<imixs:item name="txtmailsubject" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="keyaccessmode" type="xs:string">
<imixs:value><![CDATA[0]]></imixs:value>
</imixs:item>
<imixs:item name="keyscheduledactivity" type="xs:string">
<imixs:value><![CDATA[0]]></imixs:value>
</imixs:item>
<imixs:item name="rtfmailbody" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="keyversion" type="xs:string">
<imixs:value><![CDATA[0]]></imixs:value>
</imixs:item>
<imixs:item name="keyaddwritefields" type="xs:string">
<imixs:value><![CDATA[$creator]]></imixs:value>
<imixs:value><![CDATA[$editor]]></imixs:value>
<imixs:value><![CDATA[process.manager]]></imixs:value>
<imixs:value><![CDATA[process.team]]></imixs:value>
</imixs:item>
<imixs:item name="numnextactivityid" type="xs:int">
<imixs:value><![CDATA[0]]></imixs:value>
</imixs:item>
<imixs:item name="keyfollowup" type="xs:string">
<imixs:value><![CDATA[2]]></imixs:value>
</imixs:item>
<imixs:item name="keypublicresult" type="xs:string">
<imixs:value><![CDATA[1]]></imixs:value>
</imixs:item>
<imixs:item name="keylogdateformat" type="xs:string">
<imixs:value><![CDATA[2]]></imixs:value>
</imixs:item>
<imixs:item name="keyownershipfields" type="xs:string">
<imixs:value><![CDATA[$editor]]></imixs:value>
<imixs:value><![CDATA[$creator]]></imixs:value>
</imixs:item>
<imixs:item name="numnextid" type="xs:int">
<imixs:value><![CDATA[5000]]></imixs:value>
</imixs:item>
<imixs:item name="txtnextprocesstree" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="txtactivityresult" type="xs:string">
<imixs:value><![CDATA[<item name="comment" ignore="true"/>]]></imixs:value>
</imixs:item>
<imixs:item name="txtname" type="xs:string">
<imixs:value><![CDATA[Speichern]]></imixs:value>
</imixs:item>
<imixs:item name="keyownershipmode" type="xs:string">
<imixs:value><![CDATA[0]]></imixs:value>
</imixs:item>
<imixs:item name="rtfresultlog" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="keyupdateacl" type="xs:boolean">
<imixs:value>false</imixs:value>
</imixs:item>
</bpmn2:extensionElements>
<bpmn2:documentation id="documentation_CVDzIA"><![CDATA[Zwischenspeichern]]></bpmn2:documentation>
<bpmn2:outgoing>sequenceFlow_seshBg</bpmn2:outgoing>
</bpmn2:intermediateCatchEvent>
<bpmn2:sequenceFlow id="sequenceFlow_seshBg" sourceRef="event_xxUDcA" targetRef="Task_1">
<bpmn2:documentation id="documentation_wxQsPA"/>
</bpmn2:sequenceFlow>
</bpmn2:process>
<bpmn2:process id="process_2" name="Default Process" processType="Public">
<bpmn2:documentation id="documentation_J67Rkw"/>
@ -2583,6 +2671,7 @@ Wiedervorlage wird um 7 bzw. 5 Tage erhöht</bpmn2:text>
<bpmn2:signal id="signal_9" name="com.alexanderlogistics.einvoice.EInvoiceAdapter"/>
<bpmn2:signal id="signal_10" name="com.alexanderlogistics.einvoice.KSeFAdapter"/>
<bpmn2:signal id="signal_11" name="com.alexanderlogistics.einvoice.KSeFAPIAdapter"/>
<bpmn2:signal id="signal_12" name="com.alexanderlogistics.einvoice.QRTest"/>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane bpmnElement="Collaboration_1" id="BPMNPlane_Process_1">
<bpmndi:BPMNShape bpmnElement="Participant_1" id="BPMNShape_Participant_1" isHorizontal="true">
@ -2966,6 +3055,12 @@ Wiedervorlage wird um 7 bzw. 5 Tage erhöht</bpmn2:text>
<bpmndi:BPMNShape bpmnElement="textAnnotation_CARutw" id="BPMNShape_x4G0Eg">
<dc:Bounds height="109.0" width="294.0" x="310.0" y="890.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_xxUDcA" id="BPMNShape_B0zMZw">
<dc:Bounds height="36.0" width="36.0" x="1421.0" y="1533.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_yQj5fA">
<dc:Bounds height="20.0" width="100.0" x="1389.0" y="1572.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="SequenceFlow_33" id="BPMNEdge_SequenceFlow_34" sourceElement="BPMNShape_ExclusiveGateway_1">
<di:waypoint x="910.0" y="835.0"/>
<di:waypoint x="1130.0" y="835.0"/>
@ -3338,6 +3433,12 @@ Wiedervorlage wird um 7 bzw. 5 Tage erhöht</bpmn2:text>
<di:waypoint x="457.0" y="875.0"/>
<di:waypoint x="457.0" y="890.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_seshBg" id="BPMNEdge_yhILiw" sourceElement="BPMNShape_B0zMZw" targetElement="BPMNShape_Task_3">
<di:waypoint x="1421.0" y="1551.0"/>
<di:waypoint x="1331.0" y="1551.0"/>
<di:waypoint x="1331.0" y="1375.0"/>
<di:waypoint x="1240.0" y="1375.0"/>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
<bpmndi:BPMNLabelStyle id="BPMNLabelStyle_1">
<dc:Font name="arial" size="9.0"/>