From fe65ae16a417350fcd43c4ae86eef411bb3d532c Mon Sep 17 00:00:00 2001 From: Ralph Soika Date: Wed, 18 Jun 2025 08:52:14 +0200 Subject: [PATCH] zoho schnittstelle --- .../zoho/ZohoAPIService.java | 72 ++- .../zoho/ZohoExportAdapter.java | 36 +- .../zoho/dto/ZohoCreditnote.java | 25 +- .../alexanderlogistics/zoho/dto/ZohoTax.java | 12 +- workflow/dwc/rechnungsausgang-dwc-1.0.5.bpmn | 285 +++++++++++ workflow/dwc/rechnungseingang-dwc-1.0.6.bpmn | 468 ++++++++++++++++-- 6 files changed, 806 insertions(+), 92 deletions(-) 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 12e8b63..5445651 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,6 +1,7 @@ package com.alexanderlogistics.zoho; import java.io.IOException; +import java.io.StringReader; import java.net.URI; import java.net.URLEncoder; import java.net.http.HttpClient; @@ -14,8 +15,6 @@ import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.logging.Logger; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import java.util.stream.Collectors; import org.imixs.workflow.FileData; @@ -45,6 +44,11 @@ import jakarta.annotation.security.RolesAllowed; import jakarta.annotation.security.RunAs; import jakarta.ejb.Singleton; import jakarta.inject.Inject; +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import jakarta.json.JsonReader; +import jakarta.json.JsonValue; import jakarta.json.bind.Jsonb; import jakarta.json.bind.JsonbBuilder; import jakarta.json.bind.JsonbConfig; @@ -299,7 +303,7 @@ public class ZohoAPIService { String currencyID = lookupCurrency(invoice.getItemValueString("invoice.currency"), accessToken); // Konvertiere ItemCollection zu ZohoInvoiceDTO - ZohoBill zohoBill = convertToZohoBill(invoice, contactID, accountID, currencyID); + ZohoBill zohoBill = convertToZohoBill(invoice, contactID, accountID, currencyID, accessToken); try { String requestBody = jsonb.toJson(zohoBill); @@ -369,7 +373,8 @@ public class ZohoAPIService { String currencyID = lookupCurrency(invoice.getItemValueString("invoice.currency"), accessToken); // Konvertiere ItemCollection zu ZohoInvoiceDTO - ZohoVendorCredit zohoVendorCredit = convertToZohoVendorCredit(invoice, contactID, accountID, currencyID); + ZohoVendorCredit zohoVendorCredit = convertToZohoVendorCredit(invoice, contactID, accountID, currencyID, + accessToken); try { String requestBody = jsonb.toJson(zohoVendorCredit); @@ -520,7 +525,7 @@ public class ZohoAPIService { // set exchange Rate double exchangeRate = invoice.getItemValueDouble("invoice.rate"); if (exchangeRate != 0.0) { - zohoInvoice.setExchangeRate(exchangeRate); + zohoInvoice.setExchangeRate(1 / exchangeRate); } // add line items... @@ -555,10 +560,12 @@ public class ZohoAPIService { // Basisinformationen zohoCreditnote.setCreditNoteNumber(invoice.getItemValueString("invoice.number")); + zohoCreditnote.setReferenceNumber(invoice.getItemValueString("invoice.number")); zohoCreditnote.setDate( LocalDate.ofInstant(invoice.getItemValueDate("invoice.date").toInstant(), ZoneId.systemDefault())); - zohoCreditnote.setDueDate( - LocalDate.ofInstant(invoice.getItemValueDate("invoice.duedate").toInstant(), ZoneId.systemDefault())); + // zohoCreditnote.setDueDate( + // LocalDate.ofInstant(invoice.getItemValueDate("invoice.duedate").toInstant(), + // ZoneId.systemDefault())); zohoCreditnote.setCustomerId(contactID); @@ -572,7 +579,7 @@ public class ZohoAPIService { // set exchange Rate double exchangeRate = invoice.getItemValueDouble("invoice.rate"); if (exchangeRate != 0.0) { - zohoCreditnote.setExchangeRate(exchangeRate); + zohoCreditnote.setExchangeRate(1 / exchangeRate); } List positionen = InvoiceUtil.explodeChildList(invoice); @@ -636,7 +643,8 @@ public class ZohoAPIService { } } - private ZohoBill convertToZohoBill(ItemCollection invoice, String contactID, String accountID, String currencyID) + private ZohoBill convertToZohoBill(ItemCollection invoice, String contactID, String accountID, String currencyID, + String accessToken) throws PluginException { ZohoBill zohoBill = new ZohoBill(); @@ -658,7 +666,7 @@ public class ZohoAPIService { // set exchange Rate double exchangeRate = invoice.getItemValueDouble("invoice.exchangerate"); if (exchangeRate != 0.0) { - zohoBill.setExchangeRate(exchangeRate); + zohoBill.setExchangeRate(1 / exchangeRate); } // zohoBill.setPaid_through_account_id("1700"); @@ -676,7 +684,7 @@ public class ZohoAPIService { // tax - tax_id, tax_percentage try { float tax = itemCol.getItemValueFloat("tax"); - String taxID = lookupTaxID(tax, accountID); + String taxID = lookupTaxID(tax, accessToken); if (taxID != null && !taxID.isEmpty()) { lineItem.setTaxId(taxID); } @@ -692,7 +700,7 @@ public class ZohoAPIService { } private ZohoVendorCredit convertToZohoVendorCredit(ItemCollection invoice, String contactID, - String accountID, String currencyID) + String accountID, String currencyID, String accessToken) throws PluginException { ZohoVendorCredit zohoVendorCredit = new ZohoVendorCredit(); @@ -716,7 +724,7 @@ public class ZohoAPIService { // set exchange Rate double exchangeRate = invoice.getItemValueDouble("invoice.exchangerate"); if (exchangeRate != 0.0) { - zohoVendorCredit.setExchangeRate(exchangeRate); + zohoVendorCredit.setExchangeRate(1 / exchangeRate); } // zohoBill.setPaid_through_account_id("1700"); @@ -734,7 +742,7 @@ public class ZohoAPIService { // tax - tax_id, tax_percentage try { float tax = itemCol.getItemValueFloat("tax"); - String taxID = lookupTaxID(tax, accountID); + String taxID = lookupTaxID(tax, accessToken); if (taxID != null && !taxID.isEmpty()) { lineItem.setTaxId(taxID); } @@ -898,10 +906,12 @@ public class ZohoAPIService { } String json = response.body(); - String pattern = "\"currency_code\":\"" + Pattern.quote(currency) + "\".*?\"currency_id\":\"(\\d+)\""; - Matcher matcher = Pattern.compile(pattern).matcher(json); - - String result = matcher.find() ? matcher.group(1) : null; + // System.out.println(json); + String result = getCurrencyIdWithJakartaJson(json, currency); + // String pattern = "\"currency_code\":\"" + Pattern.quote(currency) + + // "\".*?\"currency_id\":\"(\\d+)\""; + // Matcher matcher = Pattern.compile(pattern).matcher(json); + // String result = matcher.find() ? matcher.group(1) : null; logger.info("│ ├── Currency ID=" + result); return result; @@ -912,6 +922,27 @@ public class ZohoAPIService { } + public static String getCurrencyIdWithJakartaJson(String jsonString, String currencyCode) { + try (JsonReader jsonReader = Json.createReader(new StringReader(jsonString))) { + JsonObject rootObject = jsonReader.readObject(); + + // Zugriff auf das currencies Array + JsonArray currenciesArray = rootObject.getJsonArray("currencies"); + + for (JsonValue currencyValue : currenciesArray) { + JsonObject currency = currencyValue.asJsonObject(); + String currencyCodeTmp = currency.getString("currency_code"); + + if (currencyCode.equals(currencyCodeTmp)) { + return currency.getString("currency_id"); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + /** * This method lookups a Contact by name. * If no contact with the given name exists, the method creats a new one. In @@ -974,7 +1005,7 @@ public class ZohoAPIService { logger.fine("│ ├── Response Body: " + response.body()); if (response.statusCode() >= 300) { throw new PluginException(this.getClass().getName(), "Zoho API error", - "Failed to find Contacts - Status code: " + response.statusCode() + ", Response: " + "Failed to find Taxes - Status code: " + response.statusCode() + ", Response: " + response.body()); } @@ -983,7 +1014,8 @@ public class ZohoAPIService { if (taxListResponse != null && taxListResponse.getTaxes() != null) { // Durchsuche die Ergebnisse nach exakter Übereinstimmung for (ZohoTax tax : taxListResponse.getTaxes()) { - if (tax_percentage == tax.getRate()) { + logger.fine("│ ├── compare rate=" + tax.getPercentage()); + if (tax_percentage == tax.getPercentage()) { logger.info("│ ├── taxID= " + tax.getTaxId()); return tax.getTaxId(); } 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 index 8f75583..7b7a8fa 100644 --- 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 @@ -54,25 +54,29 @@ public class ZohoExportAdapter implements SignalAdapter { */ @Override public ItemCollection execute(ItemCollection document, ItemCollection event) - throws AdapterException, PluginException { - // read the cargosoft export options - ItemCollection evalItemCollection = workflowService.evalWorkflowResult(event, "zoho", document, false); + throws AdapterException { + try { + // get access token + String accessToken = zohoOAuthManager.getValidAccessToken(); - // get access token - String accessToken = zohoOAuthManager.getValidAccessToken(); + // Rechnungsausgang + if (document.getModelVersion().startsWith("rechnungsausgang-")) { + logger.info("├── Invoice Export"); + exportRechnungsausgang(document, accessToken); + } - // Rechnungsausgang - if (document.getModelVersion().startsWith("rechnungsausgang-")) { - logger.info("├── Invoice Export"); - exportRechnungsausgang(document, accessToken); + // Rechnungseingang + if (document.getModelVersion().startsWith("rechnungseingang-")) { + logger.info("├── Bill Export"); + exportRechnungseingang(document, accessToken); + } + + } catch (PluginException e) { + // convert PluginException into a AdapterException to handle the error via the + // model! + logger.warning("Failed to export data to Zoho: " + e.getMessage()); + throw new AdapterException(e); } - - // Rechnungseingang - if (document.getModelVersion().startsWith("rechnungseingang-")) { - logger.info("├── Bill Export"); - exportRechnungseingang(document, accessToken); - } - return document; } diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoCreditnote.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoCreditnote.java index a2352d4..8f80001 100644 --- a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoCreditnote.java +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoCreditnote.java @@ -19,17 +19,16 @@ public class ZohoCreditnote { @JsonbDateFormat("yyyy-MM-dd") private LocalDate date; - @JsonbProperty("due_date") - @JsonbDateFormat("yyyy-MM-dd") - private LocalDate dueDate; - @JsonbProperty("creditnote_number") private String creditNoteNumber; + @JsonbProperty("reference_number") + private String referenceNumber; + @JsonbProperty("line_items") private List lineItems; - @JsonbProperty("exchange_rate") + @JsonbProperty("exchange_rate") private double exchangeRate; private double total; @@ -60,14 +59,6 @@ public class ZohoCreditnote { this.date = date; } - public LocalDate getDueDate() { - return dueDate; - } - - public void setDueDate(LocalDate duedate) { - this.dueDate = duedate; - } - public String getCreditNoteNumber() { return creditNoteNumber; } @@ -107,4 +98,12 @@ public class ZohoCreditnote { public void setExchangeRate(double exchangeRate) { this.exchangeRate = exchangeRate; } + + public String getReferenceNumber() { + return referenceNumber; + } + + public void setReferenceNumber(String referenceNumber) { + this.referenceNumber = referenceNumber; + } } diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoTax.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoTax.java index 87e6ff4..2e4467e 100644 --- a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoTax.java +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoTax.java @@ -7,8 +7,8 @@ public class ZohoTax { @JsonbProperty("tax_id") private String taxId; - @JsonbProperty("tax_factor") - private float rate; + @JsonbProperty("tax_percentage") + private float percentage; @JsonbProperty("tax_name") private String taxName; @@ -43,12 +43,12 @@ public class ZohoTax { this.taxType = contactType; } - public float getRate() { - return rate; + public float getPercentage() { + return percentage; } - public void setRate(float rate) { - this.rate = rate; + public void setPercentage(float percentage) { + this.percentage = percentage; } } diff --git a/workflow/dwc/rechnungsausgang-dwc-1.0.5.bpmn b/workflow/dwc/rechnungsausgang-dwc-1.0.5.bpmn index fa8ab3a..f566046 100644 --- a/workflow/dwc/rechnungsausgang-dwc-1.0.5.bpmn +++ b/workflow/dwc/rechnungsausgang-dwc-1.0.5.bpmn @@ -135,6 +135,8 @@ th { font-weight: bold;} task_qiTRPA event_Ce0BTw event_PbP1JQ + event_imKUgQ + event_ErVz5Q Task_1 @@ -145,6 +147,7 @@ th { font-weight: bold;} TextAnnotation_2 IntermediateCatchEvent_1 + event_ecAXHQ @@ -286,6 +289,7 @@ Bei Fragen wenden Sie sich bitte an info@imixs.com SequenceFlow_39 SequenceFlow_22 sequenceFlow_OttgXA + sequenceFlow_kqe1mA @@ -354,6 +358,7 @@ Bei Fragen wenden Sie sich bitte an info@imixs.com SequenceFlow_52 SequenceFlow_11 SequenceFlow_47 + sequenceFlow_cX24AA SequenceFlow_47 @@ -474,6 +479,7 @@ Bei Fragen wenden Sie sich bitte an info@imixs.com SequenceFlow_18 SequenceFlow_34 sequenceFlow_zhcE7Q + sequenceFlow_BLgAIQ SequenceFlow_61 @@ -1572,6 +1578,249 @@ Wiedervorlage wird um 7 bzw. 5 Tage erhöht + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + DataOutput_1 + + + DataOutput_1 + + + sequenceFlow_38nBkg + sequenceFlow_cX24AA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + DataOutput_1 + + + DataOutput_1 + + + sequenceFlow_38nBkg + sequenceFlow_kqe1mA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + DataOutput_1 + + + DataOutput_1 + + + sequenceFlow_38nBkg + sequenceFlow_BLgAIQ + + + + @@ -2073,6 +2322,42 @@ Wiedervorlage wird um 7 bzw. 5 Tage erhöht + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/workflow/dwc/rechnungseingang-dwc-1.0.6.bpmn b/workflow/dwc/rechnungseingang-dwc-1.0.6.bpmn index 6140b3a..fd18356 100644 --- a/workflow/dwc/rechnungseingang-dwc-1.0.6.bpmn +++ b/workflow/dwc/rechnungseingang-dwc-1.0.6.bpmn @@ -101,6 +101,11 @@ IntermediateCatchEvent_7 IntermediateCatchEvent_24 event_yosOIA + task_IJbghg + gateway_X0pLJQ + event_k30R3A + event_rr2FIg + event_SkBMdQ Task_5000 @@ -142,7 +147,8 @@ TextAnnotation_2 IntermediateCatchEvent_62 gateway_Al0gGg - event_RH72Rg + event_yPggjQ + event_bPBmfw @@ -650,6 +656,7 @@ if (b>0 && (a!=b) ) { SequenceFlow_88 sequenceFlow_W0RBHg sequenceFlow_IZAXAQ + sequenceFlow_eG2EJw @@ -875,7 +882,7 @@ if (paymentType=="no_sepa") { SequenceFlow_90 SequenceFlow_47 sequenceFlow_9rYDHA - sequenceFlow_0s8UKQ + sequenceFlow_aQ9k0Q SequenceFlow_47 @@ -3791,12 +3798,13 @@ Export erfolgt über eine asynchrone Verarbeitung im Modell 'cargosoft-export']] sequenceFlow_7wMzHA - sequenceFlow_LPXJdg + sequenceFlow_LuiXSA + sequenceFlow_TaR2iw - + @@ -3898,7 +3906,304 @@ Export erfolgt über eine asynchrone Verarbeitung im Modell 'cargosoft-export']] - + + + + + + + txtlastcomment]]> + + + + + + + + + _imgnumsequencenumber: cdtr.name invoice.number (invoice.currency invoice.total) space.name]]> + + + + + + + + + + + + + + + + + + + + + + + + + $workflowgroup - $workflowstatus +]]> + SequenceFlow_83 + SequenceFlow_134 + sequenceFlow_ZFDfeA + sequenceFlow_Te40Zg + sequenceFlow_1lhJLw + sequenceFlow_vDXFjw + + + + sequenceFlow_LPXJdg + sequenceFlow_LuiXSA + sequenceFlow_uiPbQA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ]]> + + + + + + + + + + + + false + + + + sequenceFlow_Te40Zg + sequenceFlow_TaR2iw + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ]]> + + + + + + + + + + + + false + + + + sequenceFlow_1lhJLw + + + + + + + + + + + + + + + + + + + + + + + adapter.error_code + +application.urlindex.jsf?workitem=$uniqueid]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ]]> + + + + + + + + + adapter.error_code]]> + + + false + + + + + + + + + + + + + adapter.error_code]]> + + + + + + + sequenceFlow_uiPbQA + sequenceFlow_vDXFjw + + + + + + @@ -3907,15 +4212,32 @@ Export erfolgt über eine asynchrone Verarbeitung im Modell 'cargosoft-export']] - - - sequenceFlow_0s8UKQ + + + sequenceFlow_TaR2iw + sequenceFlow_aQ9k0Q - - + + - - + + + + + + + + + + + + sequenceFlow_eG2EJw + + + + + + @@ -3923,6 +4245,9 @@ Export erfolgt über eine asynchrone Verarbeitung im Modell 'cargosoft-export']] + + + @@ -3932,10 +4257,10 @@ Export erfolgt über eine asynchrone Verarbeitung im Modell 'cargosoft-export']] - + - + @@ -4022,9 +4347,9 @@ Export erfolgt über eine asynchrone Verarbeitung im Modell 'cargosoft-export']] - + - + @@ -4079,7 +4404,7 @@ Export erfolgt über eine asynchrone Verarbeitung im Modell 'cargosoft-export']] - + @@ -4387,8 +4712,8 @@ Export erfolgt über eine asynchrone Verarbeitung im Modell 'cargosoft-export']] - - + + @@ -4441,8 +4766,8 @@ Export erfolgt über eine asynchrone Verarbeitung im Modell 'cargosoft-export']] - - + + @@ -4516,7 +4841,7 @@ Export erfolgt über eine asynchrone Verarbeitung im Modell 'cargosoft-export']] - + @@ -4783,18 +5108,18 @@ Export erfolgt über eine asynchrone Verarbeitung im Modell 'cargosoft-export']] - + - + - + - - - + + + @@ -4831,19 +5156,88 @@ Export erfolgt über eine asynchrone Verarbeitung im Modell 'cargosoft-export']] - - - - + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + +