From 27f7b2b4f6f63aa7959c431402e61eb0c06b0534 Mon Sep 17 00:00:00 2001 From: Ralph Soika Date: Fri, 25 Apr 2025 13:59:24 +0200 Subject: [PATCH] zoho invoice export - draft --- .../zoho/ZohoAPIService.java | 143 +- .../zoho/ZohoExportAdapter.java | 130 ++ ...ice.java => ZohoOAuthCallbackService.java} | 16 +- .../zoho/ZohoOAuthManager.java | 63 +- .../zoho/dto/ZohoInvoiceDTO.java | 70 + .../zoho/dto/ZohoInvoiceItemDTO.java | 42 + .../dwc/rechnungsausgang-dwc-1.0.3-draft.bpmn | 2011 +++++++++++++++++ 7 files changed, 2430 insertions(+), 45 deletions(-) create mode 100644 office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/ZohoExportAdapter.java rename office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/{ZohoOAuthGrantService.java => ZohoOAuthCallbackService.java} (88%) create mode 100644 office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoInvoiceDTO.java create mode 100644 office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoInvoiceItemDTO.java create mode 100644 workflow/dwc/rechnungsausgang-dwc-1.0.3-draft.bpmn diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/ZohoAPIService.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/ZohoAPIService.java index 1be7114..7c28bdd 100644 --- a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/ZohoAPIService.java +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/ZohoAPIService.java @@ -1,17 +1,34 @@ package com.alexanderlogistics.zoho; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; +import java.util.List; +import java.util.Locale; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +import org.imixs.workflow.ItemCollection; +import org.imixs.workflow.exceptions.PluginException; + +import com.alexanderlogistics.InvoiceUtil; +import com.alexanderlogistics.zoho.dto.ZohoInvoiceDTO; +import com.alexanderlogistics.zoho.dto.ZohoInvoiceItemDTO; + +import jakarta.annotation.PostConstruct; import jakarta.annotation.security.DeclareRoles; import jakarta.annotation.security.RolesAllowed; import jakarta.annotation.security.RunAs; -import jakarta.ejb.Lock; -import jakarta.ejb.LockType; import jakarta.ejb.Singleton; +import jakarta.inject.Inject; +import jakarta.json.bind.Jsonb; +import jakarta.json.bind.JsonbBuilder; +import jakarta.json.bind.JsonbConfig; /** * Der ZohoAPIService stellt methoden für den Zugriff auf die Zoho API bereit. - * Er handelt auch die Authentifizeirung über einen Access Token. Der - * ZohoOAuhtGrantService der dazu dient einen AccessCode von Zoho zu ermitteln - * übergibt den code an diesesn Servcie. Er dietn also als Singelton */ @DeclareRoles({ "org.imixs.ACCESSLEVEL.NOACCESS", "org.imixs.ACCESSLEVEL.READERACCESS", "org.imixs.ACCESSLEVEL.AUTHORACCESS", "org.imixs.ACCESSLEVEL.EDITORACCESS", @@ -23,18 +40,116 @@ import jakarta.ejb.Singleton; @RunAs("org.imixs.ACCESSLEVEL.MANAGERACCESS") public class ZohoAPIService { - private String accessToken; - private String clientID; - private String clientSecret; + private static Logger logger = Logger.getLogger(ZohoAPIService.class.getName()); + private static final String ZOHO_API_BASE_URL = "https://www.zohoapis.eu/books/v3/"; + + @Inject + ZohoOAuthManager zohoOAuthManager; + + private HttpClient httpClient; + private Jsonb jsonb; + + @PostConstruct + void init() { + this.httpClient = HttpClient.newBuilder() + .connectTimeout(Duration.ofSeconds(10)) + .build(); + // this.jsonb = JsonbBuilder.create(); + this.jsonb = JsonbBuilder.create(new JsonbConfig() + .withDateFormat("yyyy-MM-dd", Locale.getDefault())); - @Lock(LockType.WRITE) // Standardmäßig ist @Lock(LockType.READ) - public void setAccessToken(String token) { - this.accessToken = token; } - @Lock(LockType.READ) // Erlaubt parallele Lesezugriffe - public String getAccessToken() { - return accessToken; + /** + * Exports an invocie document + * + * @see https://www.zoho.com/books/api/v3/invoices/#create-an-invoice + * + * @param invoice + * @throws PluginException + */ + public void exportInvoice(ItemCollection invoice) throws PluginException { + String accessToken = zohoOAuthManager.getValidAccessToken(); + + // Konvertiere ItemCollection zu ZohoInvoiceDTO + ZohoInvoiceDTO zohoInvoice = convertToZohoInvoice(invoice); + + try { + String requestBody = jsonb.toJson(zohoInvoice); + + // Print JSON to console for verification + logger.info("├── Zoho Invoice JSON Request..."); + logger.info("│ ├── " + requestBody); + + // https://www.zohoapis.com/books/v3/invoices?organization_id=10234695' + String uri = ZOHO_API_BASE_URL + "invoices?organization_id=" + zohoOAuthManager.getOrganization(); + logger.info("│ ├── uri= " + uri); + logger.info("│ ├── accessToken=" + accessToken); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(uri)) + .header("Authorization", "Zoho-oauthtoken " + accessToken) + .header("Content-Type", "application/json") + .POST(HttpRequest.BodyPublishers.ofString(requestBody)) + .build(); + + HttpResponse response = httpClient.send( + request, HttpResponse.BodyHandlers.ofString()); + + // Print response details to console + logger.info("├── Zoho Response:"); + logger.info("│ ├── Status Code: " + response.statusCode()); + logger.info("│ ├── Response Body: " + response.body()); + + if (response.statusCode() >= 300) { + throw new PluginException(this.getClass().getName(), "Zoho API error", + "Failed to create invoice. Status code: " + response.statusCode() + + ", Response: " + response.body()); + } + + // Erfolgreiche Verarbeitung hier + // Optional: Response auswerten + + } catch (Exception e) { + throw new PluginException(this.getClass().getName(), "Zoho API error", + "Failed to export invoice to Zoho", e); + } } + private ZohoInvoiceDTO convertToZohoInvoice(ItemCollection invoice) { + ZohoInvoiceDTO zohoInvoice = new ZohoInvoiceDTO(); + + // Basisinformationen + // zohoInvoice.setInvoiceNumber(invoice.getItemValueString("invoice.number")); + + logger.info("invoice.date=" + invoice.getItemValueDate("invoice.date")); + logger.info("invoice.duedate=" + invoice.getItemValueDate("invoice.duedate")); + + zohoInvoice.setDate(invoice.getItemValueDate("invoice.date")); + zohoInvoice.setDueDate(invoice.getItemValueDate("invoice.duedate")); + zohoInvoice.setTotal(invoice.getItemValueDouble("invoice.total")); + + // Kunden-ID (muss angepasst werden je nachdem wie du sie speicherst) + // zohoInvoice.setCustomerId(invoice.getItemValueString("dbtr.number")); + zohoInvoice.setCustomerId("777249000000055569"); + + // Positionen (muss angepasst werden je nach Datenstruktur) + // List lineItems = new ArrayList<>(); + List positionen = InvoiceUtil.explodeChildList(invoice); + + List lineItems = positionen.stream() + .map(item -> { + ItemCollection itemCol = (ItemCollection) item; + ZohoInvoiceItemDTO lineItem = new ZohoInvoiceItemDTO(); + lineItem.setName(itemCol.getItemValueString("datev.text")); + lineItem.setDescription(itemCol.getItemValueString("billingtext")); + lineItem.setRate(itemCol.getItemValueDouble("datev.umsatz")); + lineItem.setQuantity(1); + return lineItem; + }) + .collect(Collectors.toList()); + + zohoInvoice.setLineItems(lineItems); + + return zohoInvoice; + } } diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/ZohoExportAdapter.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/ZohoExportAdapter.java new file mode 100644 index 0000000..4749977 --- /dev/null +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/ZohoExportAdapter.java @@ -0,0 +1,130 @@ +package com.alexanderlogistics.zoho; + +import java.util.List; +import java.util.logging.Logger; + +import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.imixs.archive.core.SnapshotService; +import org.imixs.workflow.FileData; +import org.imixs.workflow.ItemCollection; +import org.imixs.workflow.SignalAdapter; +import org.imixs.workflow.engine.WorkflowService; +import org.imixs.workflow.exceptions.AdapterException; +import org.imixs.workflow.exceptions.PluginException; + +import com.alexanderlogistics.InvoicePlugin; + +import jakarta.inject.Inject; + +/** + * This adapter exports the invoice data to zoho + * + * @version 1.0 + * @author rsoika + */ +public class ZohoExportAdapter implements SignalAdapter { + + public static final String CONFIG_ERROR = "CONFIG_ERROR"; + public static final String ENV_ZOHO_EXPORT_MAX_ATTACHMENT_SIZE = "zoho.export.maxattachmentsize"; + + private static Logger logger = Logger.getLogger(ZohoExportAdapter.class.getName()); + + @Inject + ZohoAPIService zohoAPIService; + + @Inject + WorkflowService workflowService; + + @Inject + SnapshotService snapshotService; + + @Inject + @ConfigProperty(name = ENV_ZOHO_EXPORT_MAX_ATTACHMENT_SIZE, defaultValue = "10485760") + long maxAttachmentSize; + + /** + * This method calls the zoho api + * + * @throws PluginException + */ + @Override + public ItemCollection execute(ItemCollection document, ItemCollection event) + throws AdapterException, PluginException { + + logger.info("......starting export..."); + + // read the cargosoft export options + ItemCollection evalItemCollection = workflowService.evalWorkflowResult(event, "zoho", document, false); + + zohoAPIService.exportInvoice(document); + return document; + } + + /** + * This method lookups the origin snapshot data and add the content of the $file + * to the export document + *

+ * Change 14.10.2021 - Wir senden maximal 5MB and Daten, da die Cargosoft + * Schnittstelle größere Datensätze mit großen Dateianhängen einfach verschluckt + * ohne eine Fehlermeldugn zu liefern. + * + * + * @param document + * @return + */ + @SuppressWarnings("unchecked") + private ItemCollection loadFileDataFromSnapshot(ItemCollection document) { + ItemCollection origin = null; + ItemCollection result = (ItemCollection) document.clone(); + + // find the origin document + List refs = document.getItemValue(WorkflowService.UNIQUEIDREF); + for (String ref : refs) { + origin = workflowService.getWorkItem(ref); + // "Rechnungseingang".equals(origin.getWorkflowGroup()) + if (InvoicePlugin.isCargoRechnung(origin)) { + break; + } + origin = null; + } + + // we should have found the origin... + if (origin != null) { + ItemCollection snapshot = snapshotService.findSnapshot(origin); + // we should have found a snapshot... + if (snapshot != null) { + List fileDataList = snapshot.getFileData(); + // transfer origin file content + result.removeItem("$file"); + long currentAttachmentSize = 0; + // we do only accept .pdf files and a maximum size of 10MB + for (FileData filedata : fileDataList) { + if (filedata.getName().toLowerCase().endsWith(".pdf")) { + // test if the size of the file is below the + // "cargosoft.export.ftp.maxattachmentsize" + if ((currentAttachmentSize + filedata.getContent().length) > maxAttachmentSize) { + long maxSizeInMB = maxAttachmentSize / 1024 / 1024; + String message = "Attachment '" + filedata.getName() + + "' can not be exported to cargosoft - max file size exeeded (" + maxSizeInMB + + "MB)!"; + logger.warning(message); + // add comment + document.setItemValue("txtComment", message); + } else { + result.addFileData(filedata); + currentAttachmentSize = currentAttachmentSize + filedata.getContent().length; + } + } + } + } else { + logger.warning("...did not found snapshot for origin workitem " + origin.getUniqueID()); + } + } else { + logger.warning("...did not found origin workitem " + document.getUniqueID()); + } + + return result; + + } + +} \ No newline at end of file diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/ZohoOAuthGrantService.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/ZohoOAuthCallbackService.java similarity index 88% rename from office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/ZohoOAuthGrantService.java rename to office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/ZohoOAuthCallbackService.java index 3d195e9..6c2ffaa 100644 --- a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/ZohoOAuthGrantService.java +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/ZohoOAuthCallbackService.java @@ -48,9 +48,12 @@ import jakarta.ws.rs.core.MediaType; * * https://www.zoho.com/books/api/v3/oauth/ * - * Er dient als redirect URL wenn jemand einen solchen Token über den Browser - * anfordert. - * Der URL muss hier als CallBack URL angegeben sein! + * Der Service wird aktuell nicht benötigt, das wir sogenannte Zoho Self-Clients + * verwenden! + * + * Der Service stellt im Grunde nur eine Callback URL für einen normalen Zoho + * Client ein. Also wenn jemand einen solchen Token über den Browser + * anfordert. Der URL muss dann odrt als CallBack URL angegeben sein! * * Beispiel: * @@ -60,9 +63,10 @@ import jakarta.ws.rs.core.MediaType; * @author rsoika * */ +@Deprecated @Path("/zoho") @Stateless -public class ZohoOAuthGrantService { +public class ZohoOAuthCallbackService { @Context private HttpServletRequest servletRequest; @@ -70,7 +74,7 @@ public class ZohoOAuthGrantService { @EJB ZohoOAuthManager zohoOAuthManager; - private static Logger logger = Logger.getLogger(ZohoOAuthGrantService.class.getName()); + private static Logger logger = Logger.getLogger(ZohoOAuthCallbackService.class.getName()); @GET @Path("/ping") @@ -117,8 +121,6 @@ public class ZohoOAuthGrantService { logger.info("│ ├── location=" + location); logger.info("│ ├── accounts-server=" + accountsServer); - // zohoOAuthManager.updateTokens(code); - return "Zoho Callback received!"; } diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/ZohoOAuthManager.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/ZohoOAuthManager.java index 36d3d79..b794262 100644 --- a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/ZohoOAuthManager.java +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/ZohoOAuthManager.java @@ -35,12 +35,8 @@ import jakarta.json.bind.JsonbBuilder; public class ZohoOAuthManager { private static Logger logger = Logger.getLogger(ZohoOAuthManager.class.getName()); - - private String refreshToken; - private String accessToken; - private long accessTokenExpiry; // Timestamp (System.currentTimeMillis() + expires_in*1000) - private String redirectURI = "https://alexander-logistics-dwc.office-workflow.de/api/zoho/grant"; + public static final String ERROR_CONFIG = "CONFIG_ERROR"; @EJB @@ -57,11 +53,40 @@ public class ZohoOAuthManager { this.jsonb = JsonbBuilder.create(); } + /** + * Gibt den aktuellen Access Token zurück. Falls dieser expired ist wird + * automatisch ein refresh durchgeführt. Somit liefert die Methode immer einen + * gültigen token. + * + * @return + * @throws PluginException + */ @Lock(LockType.READ) - public String getValidAccessToken() { + public String getValidAccessToken() throws PluginException { + logger.info("├── get Zoho AccessTokens"); + ItemCollection zohoConfig = configService.loadConfiguration(ZohoController.ZOHO_CONFIGURATION, false); + String accessToken = zohoConfig.getItemValueString("zoho.accessToken"); + logger.fine("│ ├── accessToken=" + accessToken); + logger.fine("│ ├── refresh=" + zohoConfig.getItemValueString("zoho.refreshToken")); + logger.fine("│ ├── expires_in=" + zohoConfig.getItemValueDate("zoho.expires")); + + Date expireDate = zohoConfig.getItemValueDate("zoho.expires"); + if (expireDate.getTime() < System.currentTimeMillis()) { + logger.info("│ ├── Access Token expired (" + expireDate + ")"); + accessToken = refreshAccessToken(); + } + return accessToken; } + public String getOrganization() throws PluginException { + ItemCollection zohoConfig = configService.loadConfiguration(ZohoController.ZOHO_CONFIGURATION, false); + if (zohoConfig != null) { + return zohoConfig.getItemValueString("zoho.organization"); + } + return null; + } + /** * Step 3: Generate Access and Refresh Token * @@ -75,14 +100,10 @@ public class ZohoOAuthManager { */ @Lock(LockType.WRITE) public void updateTokens(String code) throws PluginException { - logger.info("├── update Zoho tokens"); - refreshToken = null; - accessToken = null; - try { - ItemCollection zohoConfig = configService.loadConfiguration(ZohoController.ZOHO_CONFIGURATION); + ItemCollection zohoConfig = configService.loadConfiguration(ZohoController.ZOHO_CONFIGURATION, false); String clientID = zohoConfig.getItemValueString("zoho.clientid"); String clientSecret = zohoConfig.getItemValueString("zoho.clientsecret"); @@ -138,18 +159,15 @@ public class ZohoOAuthManager { * @throws PluginException */ @Lock(LockType.WRITE) - public void refreshAccessToken() throws PluginException { + public String refreshAccessToken() throws PluginException { logger.info("├── refresh Zoho access token"); - - ItemCollection zohoConfig = configService.loadConfiguration(ZohoController.ZOHO_CONFIGURATION); - + ItemCollection zohoConfig = configService.loadConfiguration(ZohoController.ZOHO_CONFIGURATION, false); String clientID = zohoConfig.getItemValueString("zoho.clientid"); String clientSecret = zohoConfig.getItemValueString("zoho.clientsecret"); - refreshToken = zohoConfig.getItemValueString("zoho.refreshToken"); + String refreshToken = zohoConfig.getItemValueString("zoho.refreshToken"); try { - String requestUrl = "https://accounts.zoho.eu/oauth/v2/token" + "?refresh_token=" + URLEncoder.encode(refreshToken, StandardCharsets.UTF_8) + "&client_id=" + URLEncoder.encode(clientID, StandardCharsets.UTF_8) + @@ -179,12 +197,9 @@ public class ZohoOAuthManager { TokenResponse tokenResponse = jsonb.fromJson(response.body(), TokenResponse.class); - saveTokenData(zohoConfig, tokenResponse); + return zohoConfig.getItemValueString("zoho.accessToken"); - // String accessToken = tokenResponse.getAccess_token(); - // logger.info("│ ├── accessToken=" + accessToken); - // logger.info("│ ├── expires_in=" + tokenResponse.getExpires_in()); } else { throw new RuntimeException("Failed to get tokens: " + response.statusCode() + " - " + response.body()); @@ -194,7 +209,6 @@ public class ZohoOAuthManager { throw new PluginException(ZohoOAuthManager.class.getSimpleName(), ZohoOAuthManager.ERROR_CONFIG, "Unable to refresh access tokens: " + e.getMessage()); } - } /** @@ -216,12 +230,12 @@ public class ZohoOAuthManager { zohoConfig.setItemValue("zoho.scope", scope); } - accessToken = tokenResponse.getAccess_token(); + String accessToken = tokenResponse.getAccess_token(); if (accessToken != null && !accessToken.isEmpty()) { logger.info("│ ├── accessToken=" + accessToken); zohoConfig.setItemValue("zoho.accessToken", accessToken); } - refreshToken = tokenResponse.getRefresh_token(); + String refreshToken = tokenResponse.getRefresh_token(); if (refreshToken != null && !refreshToken.isEmpty()) { logger.info("│ ├── refreshToken=" + refreshToken); zohoConfig.setItemValue("zoho.refreshToken", refreshToken); @@ -233,6 +247,7 @@ public class ZohoOAuthManager { long expiresTimeMillis = currentTimeMillis + (expiresInSeconds * 1000); // Expires-Zeit in ein Date-Objekt konvertieren Date expiresDate = new Date(expiresTimeMillis); + logger.info("│ ├── expire date=" + expiresDate); zohoConfig.setItemValue("zoho.expires", expiresDate); zohoConfig.setItemValue("message", "Access Token OK"); configService.save(zohoConfig); diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoInvoiceDTO.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoInvoiceDTO.java new file mode 100644 index 0000000..025faa7 --- /dev/null +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoInvoiceDTO.java @@ -0,0 +1,70 @@ +package com.alexanderlogistics.zoho.dto; + +import java.util.Date; +import java.util.List; + +import jakarta.json.bind.annotation.JsonbProperty; + +public class ZohoInvoiceDTO { + + private String customerId; + private Date date; + private Date dueDate; + private String invoiceNumber; + private List lineItems; + private double total; + + // Getter und Setter + + @JsonbProperty("customer_id") + public String getCustomerId() { + return customerId; + } + + public void setCustomerId(String customerId) { + this.customerId = customerId; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + @JsonbProperty("due_date") + public Date getDueDate() { + return dueDate; + } + + public void setDueDate(Date duedate) { + this.dueDate = duedate; + } + + @JsonbProperty("invoice_number") + public String getInvoiceNumber() { + return invoiceNumber; + } + + public void setInvoiceNumber(String invoiceNumber) { + this.invoiceNumber = invoiceNumber; + } + + @JsonbProperty("line_items") + public List getLineItems() { + return lineItems; + } + + public void setLineItems(List lineItems) { + this.lineItems = lineItems; + } + + public double getTotal() { + return total; + } + + public void setTotal(double total) { + this.total = total; + } +} diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoInvoiceItemDTO.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoInvoiceItemDTO.java new file mode 100644 index 0000000..e5ebb6f --- /dev/null +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoInvoiceItemDTO.java @@ -0,0 +1,42 @@ +package com.alexanderlogistics.zoho.dto; + +public class ZohoInvoiceItemDTO { + private String name; + private String description; + private double rate; + private int quantity; + + // Getter und Setter + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public double getRate() { + return rate; + } + + public void setRate(double rate) { + this.rate = rate; + } + + public int getQuantity() { + return quantity; + } + + public void setQuantity(int quantity) { + this.quantity = quantity; + } +} diff --git a/workflow/dwc/rechnungsausgang-dwc-1.0.3-draft.bpmn b/workflow/dwc/rechnungsausgang-dwc-1.0.3-draft.bpmn new file mode 100644 index 0000000..6aab7ce --- /dev/null +++ b/workflow/dwc/rechnungsausgang-dwc-1.0.3-draft.bpmn @@ -0,0 +1,2011 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + + + + + + + + +<itemvalue>$workflowstatus</itemvalue> + +]]> + + + In case you have already made the payment, please disregard this notice. If you require any information regarding your account, please do not hesitate to contact us.

+

Thank you for your cooperation.

+

 

+

Kind regards
Alexander Global Logistics GmbH

+ +]]> + + + + + + + + + + + + + + Task_2 + ExclusiveGateway_1 + StartEvent_1 + IntermediateCatchEvent_6 + EventBasedGateway_1 + IntermediateThrowEvent_11 + IntermediateThrowEvent_8 + IntermediateCatchEvent_5000-20 + Task_8 + Task_6 + Task_5 + IntermediateCatchEvent_23 + IntermediateCatchEvent_27 + EndEvent_1 + EndEvent_3 + EndEvent_2 + IntermediateCatchEvent_3 + ExclusiveGateway_5 + IntermediateCatchEvent_18 + IntermediateCatchEvent_17 + IntermediateCatchEvent_2 + IntermediateCatchEvent_5 + + TextAnnotation_1 + DataObject_2 + task_LqbtSQ + gateway_k30TvQ + event_Rou0Sw + event_0zodvw + textAnnotation_QBZ00w + event_EO54Yg + + + Task_1 + IntermediateCatchEvent_9 + ExclusiveGateway_3 + IntermediateCatchEvent_8 + IntermediateThrowEvent_10 + IntermediateThrowEvent_9 + + TextAnnotation_2 + IntermediateCatchEvent_1 + event_D2TmxA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + home]]> + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + SequenceFlow_22 + SequenceFlow_27 + + + + SequenceFlow_33 + + SequenceFlow_15 + sequenceFlow_0g2PeQ + + + + + + SequenceFlow_0 + + + + + + + + + + + + txtlastcomment]]> + + + + + + + + + _imginvoice.number dbtr.number dbtr.name (invoice.currency invoice.total) ]]> + + + true + + + + + + + + + + + + + + + $workflowgroup - $workflowstatus]]> + SequenceFlow_33 + SequenceFlow_14 + SequenceFlow_39 + SequenceFlow_22 + sequenceFlow_tjoqtg + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +]]> + + + + + + + + + txtlastcomment]]> + + + + + + + + + _imginvoice.number dbtr.number dbtr.name (invoice.currency invoice.total) ]]> + + + true + + + + + + + + + + + + + + + $workflowgroup - $workflowstatus]]> + SequenceFlow_52 + SequenceFlow_11 + SequenceFlow_47 + + + SequenceFlow_47 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Dunning]]> + + + + + + + + + + + + false + + + + SequenceFlow_21 + + + + + + + + + + + + + txtlastcomment]]> + + + + + + + + + _imginvoice.number dbtr.number dbtr.name (invoice.currency invoice.total) ]]> + + + true + + + + + + + + + + + + + + $workflowgroup - $workflowstatus]]> + SequenceFlow_27 + SequenceFlow_4 + SequenceFlow_18 + SequenceFlow_34 + sequenceFlow_zhcE7Q + sequenceFlow_6zqWyg + + + SequenceFlow_61 + + + + SequenceFlow_39 + SequenceFlow_17 + SequenceFlow_65 + SequenceFlow_13 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ]]> + + + + + + + + + + + + false + + + + SequenceFlow_52 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mahnlauf-de-1.0 +1000 +100 +/pages/workitems/workitem.jsf?id=dunning.ref +]]> + + + + + + + + + + + + false + + + + + + + + + + + + SequenceFlow_4 + + + DataOutput_1 + + + DataOutput_1 + + + + + SequenceFlow_18 + SequenceFlow_25 + SequenceFlow_64 + SequenceFlow_9 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ]]> + + + + + + + + + + + + false + + + + + + + SequenceFlow_42 + SequenceFlow_8 + + + + + + + + + + SequenceFlow_42 + + + + + SequenceFlow_8 + SequenceFlow_10 + SequenceFlow_12 + + + + + + + + + invoice.saldo]]> + + + + + + SequenceFlow_10 + SequenceFlow_11 + + + + + + + + + + + + + invoice.saldo]]> + + + + + + SequenceFlow_12 + SequenceFlow_14 + + + + + + + + + + SequenceFlow_17 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + home]]> + + + + + + + + + + + + false + + + + + SequenceFlow_34 + SequenceFlow_15 + + + + + + SequenceFlow_25 + + + + + + + + + + + + + + + + + + + cdtr.name invoice.number]]> + + + + + + + + + cdtr.name +Rechnungsnummer: invoice.number +Betrag: invoice.total invoice.currency + + +]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + 7 +1. Dunning + +]]> + + + + + + + + + + + + false + + + + + + + + + + sequenceFlow_zhcE7Q + association_P36Fzw + + + + + + + + txtlastcomment]]> + + + + + + + + + _imginvoice.number dbtr.number dbtr.name (invoice.currency invoice.total) ]]> + + + true + + + + + + + + + + + + + + + $workflowgroup - $workflowstatus]]> + SequenceFlow_60 + SequenceFlow_61 + + + + + invoice.saldo]]> + + + + + + SequenceFlow_60 + + + + + + + + + + SequenceFlow_64 + + + + + + + + SequenceFlow_65 + + + + + + + + + + + + + + + + _subject]]> + + + + + + + + + _amount (Brutto € _amount_brutto) +_description]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + home]]> + + + + + + + + + + + + false + + + + + + + SequenceFlow_9 + SequenceFlow_13 + SequenceFlow_5 + + + + + + + + + + + + + + + + + txtlastcomment]]> + + + + + + + + + _imginvoice.number dbtr.number dbtr.name (invoice.currency invoice.total) ]]> + + + true + + + + + + + + + + + + + + + $workflowgroup - $workflowstatus]]> + SequenceFlow_5 + SequenceFlow_19 + + + SequenceFlow_19 + + + + + + + + + + + + + Trigger über ZahlungseingangsSaldoAdapter + + + + + + + Triggered by MahnlaufExecuteAdapter + +Wiedervorlage wird um 7 bzw. 5 Tage erhöht + + + + + + + + + + + + + + + txtlastcomment]]> + + + + + + + + + _imginvoice.number dbtr.number dbtr.name (invoice.currency invoice.total) ]]> + + + true + + + + + + + + + + + + + + + $workflowgroup - $workflowstatus]]> + SequenceFlow_14 + SequenceFlow_22 + sequenceFlow_m0aH7g + sequenceFlow_di0Bhg + sequenceFlow_6HEChQ + + + SequenceFlow_21 + + sequenceFlow_m0aH7g + SequenceFlow_21 + SequenceFlow_0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + $uniqueid + 60000 + + ftp.target.path + \.pdf$ + + ]]> + + + + + + DataOutput_1 + + + DataOutput_1 + + + sequenceFlow_di0Bhg + sequenceFlow_0g2PeQ + sequenceFlow_38nBkg + + + + + + + + + + + sequenceFlow_38nBkg + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ]]> + + + + + + + + + + + + false + + + + sequenceFlow_tjoqtg + sequenceFlow_6HEChQ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + DataOutput_1 + + + DataOutput_1 + + + sequenceFlow_6zqWyg + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +