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 b612cd8..40333c5 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 @@ -32,6 +32,8 @@ import com.alexanderlogistics.zoho.dto.ZohoContactFindResponse; import com.alexanderlogistics.zoho.dto.ZohoInvoice; import com.alexanderlogistics.zoho.dto.ZohoInvoiceCreateResponse; import com.alexanderlogistics.zoho.dto.ZohoInvoiceItem; +import com.alexanderlogistics.zoho.dto.ZohoVendorCredit; +import com.alexanderlogistics.zoho.dto.ZohoVendorCreditCreateResponse; import jakarta.annotation.PostConstruct; import jakarta.annotation.security.DeclareRoles; @@ -262,6 +264,76 @@ public class ZohoAPIService { } + /** + * Exports an Eingangsrechnung as a Vendor Credit + * + * @see https://www.zoho.com/books/api/v3/expenses/#create-an-expense + * + * @param invoice + * @throws PluginException + */ + public ZohoVendorCredit exportVendorCredit(ItemCollection invoice, String contactID, String accountID, + String accessToken) throws PluginException { + logger.info("├── Zoho Export VendorCredit " + invoice.getItemValueString("invoice.number") + "..."); + + // Konvertiere ItemCollection zu ZohoInvoiceDTO + ZohoVendorCredit zohoVendorCredit = convertToZohoVendorCredit(invoice, contactID, accountID); + + try { + String requestBody = jsonb.toJson(zohoVendorCredit); + + // Print JSON to console for verification + logger.fine("├── Zoho VendorCredit JSON Request..."); + logger.fine("│ ├── " + requestBody); + + // https://www.zohoapis.com/books/v3/expenses?organization_id=10234695' + String uri = zohoOAuthManager.getBaseURI() + "vendorcredits?organization_id=" + + zohoOAuthManager.getOrganization(); + logger.fine("│ ├── uri= " + uri); + logger.fine("│ ├── 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.fine("├── Zoho Response:"); + logger.fine("│ ├── Status Code: " + response.statusCode()); + + if (response.statusCode() >= 300) { + throw new PluginException(this.getClass().getName(), "Zoho API error", + "Failed to create expense. Status code: " + response.statusCode() + ", Response: " + + response.body()); + } + + // Erfolgreiche Erstellung + String bodyContent = response.body(); + logger.fine("│ ├── Response Body: " + bodyContent); + + System.out.print(bodyContent); + ZohoVendorCreditCreateResponse createResponse = jsonb.fromJson(bodyContent, + ZohoVendorCreditCreateResponse.class); + + if (createResponse != null) { + logger.info("│ ├── OK - customerID=" + createResponse.getVendorCredit().getVendorId()); + logger.info("│ ├── OK - creditID=" + createResponse.getVendorCredit().getCreditId()); + zohoVendorCredit = createResponse.getVendorCredit(); + + // now mark the invoice as send + logger.info("│ ├── VendorCredit Export successful."); + return zohoVendorCredit; + } + + } catch (IOException | InterruptedException e) { + throw new PluginException(this.getClass().getName(), "Zoho API error", + "Failed to export vendor credit to Zoho: " + e.getMessage(), e); + } + return null; + + } + public String lookupContact(String companyName, String contactType, String accessToken) throws PluginException { // first lookup contact! String contactID = ""; @@ -442,6 +514,41 @@ public class ZohoAPIService { return zohoBill; } + private ZohoVendorCredit convertToZohoVendorCredit(ItemCollection invoice, String contactID, String accountID) + throws PluginException { + + ZohoVendorCredit zohoVendorCredit = new ZohoVendorCredit(); + // Basisinformationen + + zohoVendorCredit.setInvoiceNumber(invoice.getItemValueString("invoice.number")); + zohoVendorCredit.setDate( + LocalDate.ofInstant(invoice.getItemValueDate("invoice.date").toInstant(), ZoneId.systemDefault())); + // convert total by rate + // zohoVendorCredit.setAmount(convertInvoiceTotalToAED(invoice, + // invoice.getItemValueDouble("invoice.total"))); + + // Kunden-ID (muss angepasst werden je nachdem wie du sie speicherst) + zohoVendorCredit.setVendorId(contactID); + + // zohoBill.setPaid_through_account_id("1700"); + List positionen = InvoiceUtil.explodeChildList(invoice); + // {amount=[11825.00], total=[11825.00], numpos=[1], name=[AB-DEFGHI-1234-567], + // tax=[0], category=[STORAGE], invoice.period=[]} + List lineItems = positionen.stream().map(item -> { + ItemCollection itemCol = (ItemCollection) item; + ZohoBillItem lineItem = new ZohoBillItem(); + lineItem.setName(itemCol.getItemValueString("name")); + lineItem.setAccountId(accountID); + lineItem.setQuantity(1); + lineItem.setRate(convertInvoiceTotalToAED(invoice, itemCol.getItemValueDouble("amount"))); + + return lineItem; + }).collect(Collectors.toList()); + + zohoVendorCredit.setLineItems(lineItems); + return zohoVendorCredit; + } + /** * This method adds an attachment to an invoice * 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 15926c7..0b5d505 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 @@ -14,6 +14,7 @@ import org.imixs.workflow.exceptions.PluginException; import com.alexanderlogistics.zoho.dto.ZohoBill; import com.alexanderlogistics.zoho.dto.ZohoInvoice; +import com.alexanderlogistics.zoho.dto.ZohoVendorCredit; import jakarta.inject.Inject; @@ -124,21 +125,46 @@ public class ZohoExportAdapter implements SignalAdapter { // accessToken); String accountID = zohoOAuthManager.getAccountId(); - ZohoBill zohoBill = zohoAPIService.exportBill(document, contactID, accountID, accessToken); + // Gutschrift?? + if ("credit".equalsIgnoreCase(document.getItemValueString("payment.type"))) { + // Gutschrift + logger.info("├── Vendor Credit Export"); + ZohoVendorCredit zohoVendorCredit = zohoAPIService.exportVendorCredit(document, contactID, accountID, + accessToken); - // Attache Files.... - List files = null; - ItemCollection snapshot = snapshotService.findSnapshot(document); - if (snapshot != null) { - files = snapshot.getFileData(); - if (files != null) { - for (FileData file : files) { - if (file.getName().toLowerCase().endsWith(".pdf")) { - zohoAPIService.attacheFileData(zohoBill.getBillId(), file, "bills", accessToken); + // Attache Files.... + List files = null; + ItemCollection snapshot = snapshotService.findSnapshot(document); + if (snapshot != null) { + files = snapshot.getFileData(); + if (files != null) { + for (FileData file : files) { + if (file.getName().toLowerCase().endsWith(".pdf")) { + zohoAPIService.attacheFileData(zohoVendorCredit.getCreditId(), file, "vendorcredits", + accessToken); + } + } + } + } + } else { + logger.info("├── Bill Export"); + ZohoBill zohoBill = zohoAPIService.exportBill(document, contactID, accountID, accessToken); + + // Attache Files.... + List files = null; + ItemCollection snapshot = snapshotService.findSnapshot(document); + if (snapshot != null) { + files = snapshot.getFileData(); + if (files != null) { + for (FileData file : files) { + if (file.getName().toLowerCase().endsWith(".pdf")) { + zohoAPIService.attacheFileData(zohoBill.getBillId(), file, "bills", accessToken); + } } } } } + } } \ No newline at end of file diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoVendorCredit.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoVendorCredit.java new file mode 100644 index 0000000..c1536b2 --- /dev/null +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoVendorCredit.java @@ -0,0 +1,79 @@ +package com.alexanderlogistics.zoho.dto; + +import java.time.LocalDate; +import java.util.List; + +import jakarta.json.bind.annotation.JsonbDateFormat; +import jakarta.json.bind.annotation.JsonbProperty; + +public class ZohoVendorCredit { + + @JsonbProperty("vendor_credit_id") + private String creditId; + + @JsonbProperty("vendor_id") + private String vendorId; + + @JsonbProperty("currency_id") + private String currencyId; + + @JsonbDateFormat("yyyy-MM-dd") + private LocalDate date; + + @JsonbProperty("vendor_credit_number") + private String invoiceNumber; + + @JsonbProperty("line_items") + private List lineItems; + + // Getter und Setter + + public String getCreditId() { + return creditId; + } + + public void setCreditId(String billId) { + this.creditId = billId; + } + + public String getVendorId() { + return vendorId; + } + + public void setVendorId(String vendorId) { + this.vendorId = vendorId; + } + + public LocalDate getDate() { + return date; + } + + public void setDate(LocalDate date) { + this.date = date; + } + + public String getInvoiceNumber() { + return invoiceNumber; + } + + public void setInvoiceNumber(String invoiceNumber) { + this.invoiceNumber = invoiceNumber; + } + + public List getLineItems() { + return lineItems; + } + + public void setLineItems(List lineItems) { + this.lineItems = lineItems; + } + + public String getCurrencyId() { + return currencyId; + } + + public void setCurrencyId(String currencyId) { + this.currencyId = currencyId; + } + +} diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoVendorCreditCreateResponse.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoVendorCreditCreateResponse.java new file mode 100644 index 0000000..2ab42b1 --- /dev/null +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoVendorCreditCreateResponse.java @@ -0,0 +1,39 @@ +package com.alexanderlogistics.zoho.dto; + +import jakarta.json.bind.annotation.JsonbProperty; + +public class ZohoVendorCreditCreateResponse { + @JsonbProperty("code") + private int code; + + @JsonbProperty("message") + private String message; + + @JsonbProperty("vendor_credit") + private ZohoVendorCredit vendorCredit; + + // Getter und Setter + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public ZohoVendorCredit getVendorCredit() { + return vendorCredit; + } + + public void setVendorCredit(ZohoVendorCredit credit) { + this.vendorCredit = credit; + } +} diff --git a/office-alexander-logistics-app/src/main/webapp/pages/admin/zoho.xhtml b/office-alexander-logistics-app/src/main/webapp/pages/admin/zoho.xhtml index 8e69122..f820aa0 100644 --- a/office-alexander-logistics-app/src/main/webapp/pages/admin/zoho.xhtml +++ b/office-alexander-logistics-app/src/main/webapp/pages/admin/zoho.xhtml @@ -125,7 +125,7 @@ Fordern Sie einen ZOHO API COde an
    -
  1. Melden Sie sich auf der Melden Sie sich auf der ZOHO API Console an
  2. Legen Sie einen API Self Client an @@ -137,7 +137,7 @@ Generieren Sie einen neuen Access Code
    Scope: - ZohoBooks.contacts.ALL,ZohoBooks.invoices.ALL,ZohoBooks.bills.ALL,ZohoBooks.settings.READ + ZohoBooks.contacts.ALL,ZohoBooks.invoices.ALL,ZohoBooks.bills.ALL,ZohoBooks.debitnotes.ALL,ZohoBooks.settings.READ
  3. Code über den Button "Create" anfordern und in das Feld "Access Code" diff --git a/workflow/dwc/posteingang-dwc-2.0.0.bpmn b/workflow/dwc/posteingang-dwc-2.0.0.bpmn index b452c9c..5a6ac28 100644 --- a/workflow/dwc/posteingang-dwc-2.0.0.bpmn +++ b/workflow/dwc/posteingang-dwc-2.0.0.bpmn @@ -683,8 +683,7 @@ Note: Output only the XML object! Don't add explanations or comments. Use only t false - + diff --git a/workflow/dwc/rechnungseingang-dwc-1.0.5.bpmn b/workflow/dwc/rechnungseingang-dwc-1.0.5.bpmn index 7a195a1..02ae29d 100644 --- a/workflow/dwc/rechnungseingang-dwc-1.0.5.bpmn +++ b/workflow/dwc/rechnungseingang-dwc-1.0.5.bpmn @@ -145,6 +145,9 @@ gateway_Al0gGg event_vjVWqA event_poLLDQ + event_RH72Rg + event_g4VN8Q + event_VKijpQ @@ -193,6 +196,7 @@ SequenceFlow_1 SequenceFlow_123 SequenceFlow_32 + sequenceFlow_0YsOgQ @@ -878,6 +882,7 @@ if (paymentType=="no_sepa") { SequenceFlow_90 SequenceFlow_47 sequenceFlow_9rYDHA + sequenceFlow_0s8UKQ SequenceFlow_47 @@ -1470,9 +1475,8 @@ result.isValid=true; - - - + + @@ -1941,9 +1945,8 @@ result.isValid=true; - - - + + @@ -3432,6 +3435,7 @@ result.isValid=true; SequenceFlow_129 SequenceFlow_133 sequenceFlow_MxzvVQ + sequenceFlow_dFaOwQ @@ -3935,6 +3939,57 @@ Export erfolgt über eine asynchrone Verarbeitung im Modell 'cargosoft-export']] + + + + + + + + + + + + sequenceFlow_0s8UKQ + + + + + + + + + + + + + + + + + + + sequenceFlow_0YsOgQ + + + + + + + + + + + + + + + + sequenceFlow_dFaOwQ + + + + @@ -4870,6 +4925,47 @@ Export erfolgt über eine asynchrone Verarbeitung im Modell 'cargosoft-export']] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/workflow/dwc/rechnungseingang-sachrechnung-dwc-1.0.3-draft.bpmn b/workflow/dwc/rechnungseingang-sachrechnung-dwc-1.0.3-draft.bpmn index fae123c..90ba3ea 100644 --- a/workflow/dwc/rechnungseingang-sachrechnung-dwc-1.0.3-draft.bpmn +++ b/workflow/dwc/rechnungseingang-sachrechnung-dwc-1.0.3-draft.bpmn @@ -72,6 +72,7 @@ DataObject_2 event_weGn1Q + task_RF3H2w @@ -2953,7 +2954,7 @@ result.isValid=true; stop false - + rechnungseingang-dwc-1.0 5000 10 @@ -2984,7 +2985,8 @@ result.isValid=true; SequenceFlow_83 - sequenceFlow_7p4puA + sequenceFlow_08r6Pw + @@ -3240,7 +3242,7 @@ Betrag: _amount (Brutto € _amount_brutto sequenceFlow_7p4puA - + @@ -3355,6 +3357,48 @@ Betrag: _amount (Brutto € _amount_brutto + + + + txtlastcomment]]> + + + + + + + + + numsequencenumber: cdtr.name invoice.number (invoice.currency invoice.total) space.name]]> + + + + + + + + + + + + + + + + + + + + + + $workflowgroup - $workflowstatus]]> + SequenceFlow_60 + sequenceFlow_7p4puA + sequenceFlow_08r6Pw + + + + @@ -3697,7 +3741,7 @@ Betrag: _amount (Brutto € _amount_brutto - + @@ -4050,14 +4094,14 @@ Betrag: _amount (Brutto € _amount_brutto - + - + - - - + + + @@ -4114,6 +4158,13 @@ Betrag: _amount (Brutto € _amount_brutto + + + + + + +