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 b79a346..1cf8fb0 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 @@ -35,6 +35,8 @@ import com.alexanderlogistics.zoho.dto.ZohoCreditnoteCreateResponse; import com.alexanderlogistics.zoho.dto.ZohoInvoice; import com.alexanderlogistics.zoho.dto.ZohoInvoiceCreateResponse; import com.alexanderlogistics.zoho.dto.ZohoInvoiceItem; +import com.alexanderlogistics.zoho.dto.ZohoTax; +import com.alexanderlogistics.zoho.dto.ZohoTaxListResponse; import com.alexanderlogistics.zoho.dto.ZohoVendorCredit; import com.alexanderlogistics.zoho.dto.ZohoVendorCreditCreateResponse; @@ -78,6 +80,16 @@ public class ZohoAPIService { this.jsonb = JsonbBuilder.create(config); } + /** + * This finder method returns the contact ID to a given company name. + * The method returns null if no company with this name exists + * + * @param companyName + * @param contactType + * @param accessToken + * @return + * @throws PluginException + */ public String findContactIDByCompanyName(String companyName, String contactType, String accessToken) throws PluginException { @@ -128,6 +140,63 @@ public class ZohoAPIService { } + /** + * This finder method returns the tax ID to a given percentage. + * The method returns null if no tax with this percentage exists + * + * @param tax_percentage + * @param accessToken + * @return taxID + * @throws PluginException + */ + public String findTaxIDByPercentage(float tax_percentage, String accessToken) + throws PluginException { + + // Print JSON to console for verification + logger.info("├── Zoho lookup tax '" + tax_percentage + "'..."); + try { + // https://www.zohoapis.com/books/v3/settings/taxes?organization_id=10234695&company_name=xxx' + String uri = zohoOAuthManager.getBaseURI() + "settings/taxes?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").GET().build(); + + HttpResponse response; + + response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); + + // Print response details to console + logger.fine("├── Zoho Response:"); + logger.fine("│ ├── Status Code: " + response.statusCode()); + 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: " + + response.body()); + } + + ZohoTaxListResponse taxListResponse = jsonb.fromJson(response.body(), ZohoTaxListResponse.class); + + if (taxListResponse != null && taxListResponse.getTaxes() != null) { + // Durchsuche die Ergebnisse nach exakter Übereinstimmung + for (ZohoTax tax : taxListResponse.getTaxes()) { + if (tax_percentage == tax.getRate()) { + logger.info("│ ├── taxID= " + tax.getTaxId()); + return tax.getTaxId(); + } + } + } + } catch (IOException | InterruptedException e) { + throw new PluginException(this.getClass().getName(), "Zoho API error", + "Failed to find tax: " + e.getMessage()); + } + return null; + + } + /** * Exports an invocie document * @@ -588,7 +657,7 @@ public class ZohoAPIService { if (!currency.isEmpty() && !currency.equalsIgnoreCase("AED")) { // es ist eine Fremdwährung - // Herr Heolzl 15.05.2025 + // Herr Hoelzl 15.05.2025 // However the backend reports the P&L & Balance sheet will reflect in AED as // AGL Dubai books are maintained in AED therefore we need to have an exchange // rate which can be fixed @3.6725 AED for 1 USD. @@ -641,6 +710,17 @@ public class ZohoAPIService { lineItem.setQuantity(1); lineItem.setRate(convertInvoiceTotalToAED(invoice, itemCol.getItemValueDouble("amount"))); + // tax - tax_id, tax_percentage + try { + float tax = itemCol.getItemValueFloat("tax"); + String taxID = findTaxIDByPercentage(tax, accountID); + if (taxID != null && !taxID.isEmpty()) { + lineItem.setTaxId(taxID); + } + } catch (PluginException e) { + logger.info("│ ├── failed to compute taxId: " + e.getMessage()); + } + return lineItem; }).collect(Collectors.toList()); @@ -676,6 +756,17 @@ public class ZohoAPIService { lineItem.setQuantity(1); lineItem.setRate(convertInvoiceTotalToAED(invoice, itemCol.getItemValueDouble("amount"))); + // tax - tax_id, tax_percentage + try { + float tax = itemCol.getItemValueFloat("tax"); + String taxID = findTaxIDByPercentage(tax, accountID); + if (taxID != null && !taxID.isEmpty()) { + lineItem.setTaxId(taxID); + } + } catch (PluginException e) { + logger.info("│ ├── failed to compute taxId: " + e.getMessage()); + } + return lineItem; }).collect(Collectors.toList()); diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoBillItem.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoBillItem.java index 802a4ba..b0f8a6e 100644 --- a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoBillItem.java +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoBillItem.java @@ -8,6 +8,9 @@ public class ZohoBillItem { private double rate; private double quantity; + @JsonbProperty("tax_id") + private String taxId; + @JsonbProperty("account_id") private String accountId; @@ -53,4 +56,12 @@ public class ZohoBillItem { this.quantity = quantity; } + public String getTaxId() { + return taxId; + } + + public void setTaxId(String taxId) { + this.taxId = taxId; + } + } 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 new file mode 100644 index 0000000..87e6ff4 --- /dev/null +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoTax.java @@ -0,0 +1,54 @@ +package com.alexanderlogistics.zoho.dto; + +import jakarta.json.bind.annotation.JsonbProperty; + +public class ZohoTax { + + @JsonbProperty("tax_id") + private String taxId; + + @JsonbProperty("tax_factor") + private float rate; + + @JsonbProperty("tax_name") + private String taxName; + + @JsonbProperty("tax_type") + private String taxType; + + // Weitere Felder nach Bedarf + + // Getter und Setter + public String getTaxId() { + return taxId; + } + + public void setTaxId(String taxId) { + this.taxId = taxId; + } + + public String getTaxName() { + return taxName; + } + + public void setTaxName(String companyName) { + this.taxName = companyName; + } + + public String getTaxType() { + return taxType; + } + + public void setTaxType(String contactType) { + this.taxType = contactType; + } + + public float getRate() { + return rate; + } + + public void setRate(float rate) { + this.rate = rate; + } + +} diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoTaxListResponse.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoTaxListResponse.java new file mode 100644 index 0000000..ca4116f --- /dev/null +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoTaxListResponse.java @@ -0,0 +1,41 @@ +package com.alexanderlogistics.zoho.dto; + +import java.util.List; + +import jakarta.json.bind.annotation.JsonbProperty; + +public class ZohoTaxListResponse { + @JsonbProperty("code") + private int code; + + @JsonbProperty("message") + private String message; + + @JsonbProperty("taxes") + private List taxes; + + // 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 List getTaxes() { + return taxes; + } + + public void setTaxes(List taxes) { + this.taxes = taxes; + } +}