added qr-code to invoice
This commit is contained in:
parent
e09e25766a
commit
5f20bc458b
4 changed files with 413 additions and 127 deletions
|
|
@ -7,7 +7,6 @@ import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.text.NumberFormat;
|
import java.text.NumberFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
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.PDEmbeddedFilesNameTreeNode;
|
||||||
import org.apache.pdfbox.pdmodel.common.filespecification.PDComplexFileSpecification;
|
import org.apache.pdfbox.pdmodel.common.filespecification.PDComplexFileSpecification;
|
||||||
import org.apache.pdfbox.pdmodel.common.filespecification.PDEmbeddedFile;
|
import org.apache.pdfbox.pdmodel.common.filespecification.PDEmbeddedFile;
|
||||||
import org.imixs.archive.core.SnapshotService;
|
|
||||||
import org.imixs.einvoice.EInvoiceFormatException;
|
import org.imixs.einvoice.EInvoiceFormatException;
|
||||||
import org.imixs.einvoice.EInvoiceModel;
|
import org.imixs.einvoice.EInvoiceModel;
|
||||||
import org.imixs.einvoice.EInvoiceModelFactory;
|
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.engine.WorkflowService;
|
||||||
import org.imixs.workflow.exceptions.AdapterException;
|
import org.imixs.workflow.exceptions.AdapterException;
|
||||||
import org.imixs.workflow.exceptions.PluginException;
|
import org.imixs.workflow.exceptions.PluginException;
|
||||||
import org.imixs.workflow.exceptions.QueryException;
|
|
||||||
import org.imixs.workflow.util.XMLParser;
|
import org.imixs.workflow.util.XMLParser;
|
||||||
|
|
||||||
import com.alexanderlogistics.BusinessPartnerService;
|
import com.alexanderlogistics.BusinessPartnerService;
|
||||||
import com.alexanderlogistics.InvoiceUtil;
|
import com.alexanderlogistics.InvoiceUtil;
|
||||||
|
import com.alexanderlogistics.ksef.api.KSeFAPIService;
|
||||||
|
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
|
|
||||||
|
|
@ -80,9 +78,6 @@ import jakarta.inject.Inject;
|
||||||
*/
|
*/
|
||||||
public class EInvoiceAdapter implements SignalAdapter {
|
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";
|
public static final String LINE_ITEMS_PROPERTY = "invoice.items";
|
||||||
private static Logger logger = Logger.getLogger(EInvoiceAdapter.class.getName());
|
private static Logger logger = Logger.getLogger(EInvoiceAdapter.class.getName());
|
||||||
|
|
||||||
|
|
@ -97,10 +92,10 @@ public class EInvoiceAdapter implements SignalAdapter {
|
||||||
DocumentService documentService;
|
DocumentService documentService;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
SnapshotService snapshotService;
|
BusinessPartnerService businessPartnerService;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
BusinessPartnerService businessPartnerService;
|
KSeFAPIService kSeFAPIService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method
|
* This method
|
||||||
|
|
@ -117,14 +112,14 @@ public class EInvoiceAdapter implements SignalAdapter {
|
||||||
workitem,
|
workitem,
|
||||||
false);
|
false);
|
||||||
if (eInvoiceConfig == null || !eInvoiceConfig.hasItem("create")) {
|
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");
|
"missing e-invoice configuration in model event - please check model configuration");
|
||||||
}
|
}
|
||||||
ItemCollection createDefinition = XMLParser.parseItemStructure(eInvoiceConfig.getItemValueString("CREATE"));
|
ItemCollection createDefinition = XMLParser.parseItemStructure(eInvoiceConfig.getItemValueString("CREATE"));
|
||||||
try {
|
try {
|
||||||
// Load the e-invoice template....
|
// Load the e-invoice template....
|
||||||
FileData xmlFileData = loadXMLTemplate(workitem, createDefinition);
|
FileData xmlFileData = kSeFAPIService.loadXMLTemplate(workitem, createDefinition);
|
||||||
FileData pdfFileData = loadPDF(workitem);
|
FileData pdfFileData = kSeFAPIService.loadPDF(workitem);
|
||||||
|
|
||||||
logger.info("│ ├── Source File: " + pdfFileData.getName());
|
logger.info("│ ├── Source File: " + pdfFileData.getName());
|
||||||
|
|
||||||
|
|
@ -148,47 +143,50 @@ public class EInvoiceAdapter implements SignalAdapter {
|
||||||
return workitem;
|
return workitem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* This helper method tries to find the pdf file matching the item
|
// * This helper method tries to find the pdf file matching the item
|
||||||
* 'cargosoft.import.filename'. If not found the method returns the first .pdf
|
// * '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
|
// * file form the list of attachments. The method returns null if no pdf file
|
||||||
* exits
|
// * exits
|
||||||
*
|
// *
|
||||||
* @param workitem
|
// * @param workitem
|
||||||
* @return the pdf FileData object
|
// * @return the pdf FileData object
|
||||||
* @throws PluginException if not pdf file was found
|
// * @throws PluginException if not pdf file was found
|
||||||
*/
|
// */
|
||||||
private FileData loadPDF(ItemCollection workitem) throws PluginException {
|
// private FileData loadPDF(ItemCollection workitem) throws PluginException {
|
||||||
FileData pdfFileData = null;
|
// FileData pdfFileData = null;
|
||||||
String cargosoftFileName = workitem.getItemValueString("cargosoft.import.filename");
|
// String cargosoftFileName =
|
||||||
if (!cargosoftFileName.isEmpty()) {
|
// workitem.getItemValueString("cargosoft.import.filename");
|
||||||
cargosoftFileName = cargosoftFileName.replace(".xml", ".pdf");
|
// if (!cargosoftFileName.isEmpty()) {
|
||||||
|
// cargosoftFileName = cargosoftFileName.replace(".xml", ".pdf");
|
||||||
|
|
||||||
// try to load filedata....
|
// // try to load filedata....
|
||||||
pdfFileData = snapshotService.getWorkItemFile(workitem.getUniqueID(), cargosoftFileName);
|
// pdfFileData = snapshotService.getWorkItemFile(workitem.getUniqueID(),
|
||||||
|
// cargosoftFileName);
|
||||||
|
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (pdfFileData == null) {
|
// if (pdfFileData == null) {
|
||||||
// take first pdf file available
|
// // take first pdf file available
|
||||||
List<String> fileNames = workitem.getFileNames();
|
// List<String> fileNames = workitem.getFileNames();
|
||||||
for (String filename : fileNames) {
|
// for (String filename : fileNames) {
|
||||||
|
|
||||||
if (filename.toLowerCase().endsWith(".pdf")) {
|
// if (filename.toLowerCase().endsWith(".pdf")) {
|
||||||
pdfFileData = snapshotService.getWorkItemFile(workitem.getUniqueID(), filename);
|
// pdfFileData = snapshotService.getWorkItemFile(workitem.getUniqueID(),
|
||||||
break;
|
// filename);
|
||||||
}
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
if (pdfFileData == null) {
|
// if (pdfFileData == null) {
|
||||||
throw new PluginException(EInvoiceAdapter.class.getSimpleName(),
|
// throw new PluginException(EInvoiceAdapter.class.getSimpleName(),
|
||||||
DOCUMENT_ERROR,
|
// DOCUMENT_ERROR,
|
||||||
"DOCUMENT_ERROR: no pdf file found!");
|
// "DOCUMENT_ERROR: no pdf file found!");
|
||||||
}
|
// }
|
||||||
return pdfFileData;
|
// return pdfFileData;
|
||||||
|
|
||||||
}
|
// }
|
||||||
|
|
||||||
private FileData embeddXML(FileData pdfFileData, FileData xmlFileData) throws PluginException {
|
private FileData embeddXML(FileData pdfFileData, FileData xmlFileData) throws PluginException {
|
||||||
try {
|
try {
|
||||||
|
|
@ -236,7 +234,7 @@ public class EInvoiceAdapter implements SignalAdapter {
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// TODO Auto-generated catch block
|
// 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());
|
"Failed to generate e-invoice: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -298,7 +296,7 @@ public class EInvoiceAdapter implements SignalAdapter {
|
||||||
fileDataXMLTemplate.setContent(model.getContent());
|
fileDataXMLTemplate.setContent(model.getContent());
|
||||||
|
|
||||||
} catch (FileNotFoundException | EInvoiceFormatException | TransformerException e) {
|
} 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 {
|
public TradeParty buildAddress(String partnerID, String type) throws PluginException {
|
||||||
if (partnerID == null || partnerID.isEmpty()) {
|
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);
|
ItemCollection businessPartner = businessPartnerService.getBusinessPartnerByID(partnerID);
|
||||||
if (businessPartner == null) {
|
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");
|
"Business Partner ID '" + partnerID + "' does not exist");
|
||||||
}
|
}
|
||||||
TradeParty tradeParty = new TradeParty(type);
|
TradeParty tradeParty = new TradeParty(type);
|
||||||
|
|
@ -352,80 +350,4 @@ public class EInvoiceAdapter implements SignalAdapter {
|
||||||
return tradeLineItem;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -12,6 +12,7 @@ import java.security.NoSuchAlgorithmException;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
@ -23,11 +24,18 @@ import javax.crypto.NoSuchPaddingException;
|
||||||
import javax.crypto.spec.IvParameterSpec;
|
import javax.crypto.spec.IvParameterSpec;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
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.archive.core.SnapshotService;
|
||||||
import org.imixs.workflow.FileData;
|
import org.imixs.workflow.FileData;
|
||||||
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.engine.WorkflowService;
|
||||||
import org.imixs.workflow.exceptions.PluginException;
|
import org.imixs.workflow.exceptions.PluginException;
|
||||||
|
import org.imixs.workflow.exceptions.QueryException;
|
||||||
|
|
||||||
import com.google.zxing.BarcodeFormat;
|
import com.google.zxing.BarcodeFormat;
|
||||||
import com.google.zxing.WriterException;
|
import com.google.zxing.WriterException;
|
||||||
|
|
@ -64,6 +72,9 @@ public class KSeFAPIService {
|
||||||
private static Logger logger = Logger.getLogger(KSeFAPIService.class.getName());
|
private static Logger logger = Logger.getLogger(KSeFAPIService.class.getName());
|
||||||
|
|
||||||
public static final String ERROR_API = "API_ERROR";
|
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
|
@Inject
|
||||||
KSeFAuthManager kseFAuthManager;
|
KSeFAuthManager kseFAuthManager;
|
||||||
|
|
@ -71,6 +82,9 @@ public class KSeFAPIService {
|
||||||
@Inject
|
@Inject
|
||||||
DocumentService documentService;
|
DocumentService documentService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
WorkflowService workflowService;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
SnapshotService snapshotService;
|
SnapshotService snapshotService;
|
||||||
|
|
||||||
|
|
@ -249,6 +263,9 @@ public class KSeFAPIService {
|
||||||
|
|
||||||
// store QR Code
|
// store QR Code
|
||||||
generateQRCode(workitem);
|
generateQRCode(workitem);
|
||||||
|
|
||||||
|
// print QR Code to pdf
|
||||||
|
embedQRCode(workitem);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (IOException | NoSuchAlgorithmException | InterruptedException e) {
|
} 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
|
* Encrypt invoice XML with the session encryption keys
|
||||||
*
|
*
|
||||||
|
|
@ -505,4 +604,117 @@ public class KSeFAPIService {
|
||||||
return Base64.getEncoder().encodeToString(hashBytes);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -173,6 +173,7 @@ th { font-weight: bold;}
|
||||||
<bpmn2:flowNodeRef>ExclusiveGateway_3</bpmn2:flowNodeRef>
|
<bpmn2:flowNodeRef>ExclusiveGateway_3</bpmn2:flowNodeRef>
|
||||||
<bpmn2:flowNodeRef>dataObject_V0KVQg</bpmn2:flowNodeRef>
|
<bpmn2:flowNodeRef>dataObject_V0KVQg</bpmn2:flowNodeRef>
|
||||||
<bpmn2:flowNodeRef>event_w96sOg</bpmn2:flowNodeRef>
|
<bpmn2:flowNodeRef>event_w96sOg</bpmn2:flowNodeRef>
|
||||||
|
<bpmn2:flowNodeRef>event_xxUDcA</bpmn2:flowNodeRef>
|
||||||
</bpmn2:lane>
|
</bpmn2:lane>
|
||||||
</bpmn2:laneSet>
|
</bpmn2:laneSet>
|
||||||
<bpmn2:intermediateCatchEvent id="IntermediateCatchEvent_5000-20" imixs:activityid="50" name="[Due date]">
|
<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="Invoice positions" path="alexander/section_datevbuchung" />
|
||||||
<imixs-form-section label="Payment" path="alexander/section_payments" />
|
<imixs-form-section label="Payment" path="alexander/section_payments" />
|
||||||
<imixs-form-section label="Dunning" path="alexander/section_dunnings" />
|
<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>
|
</imixs-form>]]></bpmn2:documentation>
|
||||||
<bpmn2:dataState id="DataState_1"/>
|
<bpmn2:dataState id="DataState_1"/>
|
||||||
</bpmn2:dataObject>
|
</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:documentation id="Documentation_9"><![CDATA[<textblock><itemvalue>$workflowgroup</itemvalue> - <itemvalue>$workflowstatus</itemvalue></textblock>]]></bpmn2:documentation>
|
||||||
<bpmn2:incoming>SequenceFlow_27</bpmn2:incoming>
|
<bpmn2:incoming>SequenceFlow_27</bpmn2:incoming>
|
||||||
<bpmn2:incoming>sequenceFlow_EZX5kQ</bpmn2:incoming>
|
<bpmn2:incoming>sequenceFlow_EZX5kQ</bpmn2:incoming>
|
||||||
|
<bpmn2:incoming>sequenceFlow_seshBg</bpmn2:incoming>
|
||||||
<bpmn2:outgoing>SequenceFlow_18</bpmn2:outgoing>
|
<bpmn2:outgoing>SequenceFlow_18</bpmn2:outgoing>
|
||||||
<bpmn2:outgoing>SequenceFlow_34</bpmn2:outgoing>
|
<bpmn2:outgoing>SequenceFlow_34</bpmn2:outgoing>
|
||||||
<bpmn2:incoming>sequenceFlow_zhcE7Q</bpmn2:incoming>
|
<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:association id="association_PwhTLg" sourceRef="textAnnotation_zVr90Q" targetRef="event_NIn1DQ">
|
||||||
<bpmn2:documentation id="documentation_3RHL2w"/>
|
<bpmn2:documentation id="documentation_3RHL2w"/>
|
||||||
</bpmn2:association>
|
</bpmn2:association>
|
||||||
<bpmn2:intermediateThrowEvent id="event_rTm4Aw" name="KSEF">
|
<bpmn2:intermediateThrowEvent id="event_rTm4Aw" name="EINVOICE">
|
||||||
<bpmn2:incoming>sequenceFlow_bRxzKQ</bpmn2:incoming>
|
<bpmn2:incoming>sequenceFlow_bRxzKQ</bpmn2:incoming>
|
||||||
<bpmn2:linkEventDefinition id="linkEventDefinition_XpOKjQ" name="Link Event Definition 5"/>
|
<bpmn2:linkEventDefinition id="linkEventDefinition_XpOKjQ" name="Link Event Definition 5"/>
|
||||||
<bpmn2:documentation id="documentation_jDLGbA"/>
|
<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:association id="association_XEg2bw" sourceRef="task_aZVPjw" targetRef="textAnnotation_CARutw">
|
||||||
<bpmn2:documentation id="documentation_LZEbVQ"/>
|
<bpmn2:documentation id="documentation_LZEbVQ"/>
|
||||||
</bpmn2:association>
|
</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>
|
||||||
<bpmn2:process id="process_2" name="Default Process" processType="Public">
|
<bpmn2:process id="process_2" name="Default Process" processType="Public">
|
||||||
<bpmn2:documentation id="documentation_J67Rkw"/>
|
<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_9" name="com.alexanderlogistics.einvoice.EInvoiceAdapter"/>
|
||||||
<bpmn2:signal id="signal_10" name="com.alexanderlogistics.einvoice.KSeFAdapter"/>
|
<bpmn2:signal id="signal_10" name="com.alexanderlogistics.einvoice.KSeFAdapter"/>
|
||||||
<bpmn2:signal id="signal_11" name="com.alexanderlogistics.einvoice.KSeFAPIAdapter"/>
|
<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:BPMNDiagram id="BPMNDiagram_1">
|
||||||
<bpmndi:BPMNPlane bpmnElement="Collaboration_1" id="BPMNPlane_Process_1">
|
<bpmndi:BPMNPlane bpmnElement="Collaboration_1" id="BPMNPlane_Process_1">
|
||||||
<bpmndi:BPMNShape bpmnElement="Participant_1" id="BPMNShape_Participant_1" isHorizontal="true">
|
<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">
|
<bpmndi:BPMNShape bpmnElement="textAnnotation_CARutw" id="BPMNShape_x4G0Eg">
|
||||||
<dc:Bounds height="109.0" width="294.0" x="310.0" y="890.0"/>
|
<dc:Bounds height="109.0" width="294.0" x="310.0" y="890.0"/>
|
||||||
</bpmndi:BPMNShape>
|
</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">
|
<bpmndi:BPMNEdge bpmnElement="SequenceFlow_33" id="BPMNEdge_SequenceFlow_34" sourceElement="BPMNShape_ExclusiveGateway_1">
|
||||||
<di:waypoint x="910.0" y="835.0"/>
|
<di:waypoint x="910.0" y="835.0"/>
|
||||||
<di:waypoint x="1130.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="875.0"/>
|
||||||
<di:waypoint x="457.0" y="890.0"/>
|
<di:waypoint x="457.0" y="890.0"/>
|
||||||
</bpmndi:BPMNEdge>
|
</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: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