zoho currency lookup

This commit is contained in:
Ralph Soika 2025-05-09 12:24:15 +02:00
parent 919ad796de
commit 6cd3d5d258
9 changed files with 98 additions and 269 deletions

View file

@ -14,6 +14,8 @@ 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;
@ -27,9 +29,6 @@ import com.alexanderlogistics.zoho.dto.ZohoBillItem;
import com.alexanderlogistics.zoho.dto.ZohoContact;
import com.alexanderlogistics.zoho.dto.ZohoContactCreateResponse;
import com.alexanderlogistics.zoho.dto.ZohoContactFindResponse;
import com.alexanderlogistics.zoho.dto.ZohoExpense;
import com.alexanderlogistics.zoho.dto.ZohoExpenseCreateResponse;
import com.alexanderlogistics.zoho.dto.ZohoExpenseItem;
import com.alexanderlogistics.zoho.dto.ZohoInvoice;
import com.alexanderlogistics.zoho.dto.ZohoInvoiceCreateResponse;
import com.alexanderlogistics.zoho.dto.ZohoInvoiceItem;
@ -132,12 +131,12 @@ public class ZohoAPIService {
* @param invoice
* @throws PluginException
*/
public ZohoInvoice exportInvoice(ItemCollection invoice, String contactID, String accessToken)
public ZohoInvoice exportInvoice(ItemCollection invoice, String contactID, String currencyID, String accessToken)
throws PluginException {
logger.info("├── Zoho Export Invoice " + invoice.getItemValueString("invoice.number") + "...");
// Konvertiere ItemCollection zu ZohoInvoiceDTO
ZohoInvoice zohoInvoice = convertToZohoInvoice(invoice, contactID);
ZohoInvoice zohoInvoice = convertToZohoInvoice(invoice, contactID, currencyID);
try {
String requestBody = jsonb.toJson(zohoInvoice);
@ -203,82 +202,12 @@ public class ZohoAPIService {
* @param invoice
* @throws PluginException
*/
public ZohoExpense exportExpense(ItemCollection invoice, String contactID, String accessToken)
throws PluginException {
logger.info("├── Zoho Export Expense " + invoice.getItemValueString("invoice.number") + "...");
// Konvertiere ItemCollection zu ZohoInvoiceDTO
ZohoExpense zohoExpense = convertToZohoExpense(invoice, contactID);
try {
String requestBody = jsonb.toJson(zohoExpense);
// Print JSON to console for verification
logger.fine("├── Zoho Expense JSON Request...");
logger.fine("│ ├── " + requestBody);
// https://www.zohoapis.com/books/v3/expenses?organization_id=10234695'
String uri = zohoOAuthManager.getBaseURI() + "expenses?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<String> 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);
ZohoExpenseCreateResponse createResponse = jsonb.fromJson(bodyContent, ZohoExpenseCreateResponse.class);
if (createResponse != null) {
logger.info("│ ├── OK - customerID=" + createResponse.getExpense().getCustomerId());
logger.info("│ ├── OK - expenseID=" + createResponse.getExpense().getExpenseId());
zohoExpense = createResponse.getExpense();
// now mark the invoice as send
logger.info("│ ├── Invoice Export successful.");
return zohoExpense;
}
} catch (IOException | InterruptedException e) {
throw new PluginException(this.getClass().getName(), "Zoho API error",
"Failed to export invoice to Zoho: " + e.getMessage(), e);
}
return null;
}
/**
* Exports an Eingangsrechnung document
*
* @see https://www.zoho.com/books/api/v3/expenses/#create-an-expense
*
* @param invoice
* @throws PluginException
*/
public ZohoBill exportBill(ItemCollection invoice, String contactID, String accountID, String accessToken)
throws PluginException {
public ZohoBill exportBill(ItemCollection invoice, String contactID, String currencyID, String accountID,
String accessToken) throws PluginException {
logger.info("├── Zoho Export Bill " + invoice.getItemValueString("invoice.number") + "...");
// Konvertiere ItemCollection zu ZohoInvoiceDTO
ZohoBill zohoBill = convertToZohoBill(invoice, contactID, accountID);
ZohoBill zohoBill = convertToZohoBill(invoice, contactID, currencyID, accountID);
try {
String requestBody = jsonb.toJson(zohoBill);
@ -401,7 +330,8 @@ public class ZohoAPIService {
}
private ZohoInvoice convertToZohoInvoice(ItemCollection invoice, String contactID) throws PluginException {
private ZohoInvoice convertToZohoInvoice(ItemCollection invoice, String contactID, String currencyID)
throws PluginException {
ZohoInvoice zohoInvoice = new ZohoInvoice();
// Basisinformationen
@ -414,8 +344,10 @@ public class ZohoAPIService {
LocalDate.ofInstant(invoice.getItemValueDate("invoice.duedate").toInstant(), ZoneId.systemDefault()));
zohoInvoice.setTotal(invoice.getItemValueDouble("invoice.total"));
// Kunden-ID (muss angepasst werden je nachdem wie du sie speicherst)
zohoInvoice.setCustomerId(contactID);
if (currencyID != null && !currencyID.isEmpty()) {
zohoInvoice.setCurrencyId(currencyID);
}
List<ItemCollection> positionen = InvoiceUtil.explodeChildList(invoice);
List<ZohoInvoiceItem> lineItems = positionen.stream().map(item -> {
@ -432,35 +364,7 @@ public class ZohoAPIService {
return zohoInvoice;
}
private ZohoExpense convertToZohoExpense(ItemCollection invoice, String contactID) throws PluginException {
ZohoExpense zohoExpense = new ZohoExpense();
// Basisinformationen
zohoExpense.setInvoiceNumber(invoice.getItemValueString("invoice.number"));
zohoExpense.setDate(
LocalDate.ofInstant(invoice.getItemValueDate("invoice.date").toInstant(), ZoneId.systemDefault()));
zohoExpense.setAmount(invoice.getItemValueDouble("invoice.total"));
// Kunden-ID (muss angepasst werden je nachdem wie du sie speicherst)
zohoExpense.setCustomerId(contactID);
zohoExpense.setPaid_through_account_id("1700");
List<ItemCollection> positionen = InvoiceUtil.explodeChildList(invoice);
// {amount=[11825.00], total=[11825.00], numpos=[1], name=[AB-DEFGHI-1234-567],
// tax=[0], category=[STORAGE], invoice.period=[]}
List<ZohoExpenseItem> lineItems = positionen.stream().map(item -> {
ItemCollection itemCol = (ItemCollection) item;
ZohoExpenseItem lineItem = new ZohoExpenseItem();
lineItem.setDescription(itemCol.getItemValueString("name"));
return lineItem;
}).collect(Collectors.toList());
zohoExpense.setLineItems(lineItems);
return zohoExpense;
}
private ZohoBill convertToZohoBill(ItemCollection invoice, String contactID, String accountID)
private ZohoBill convertToZohoBill(ItemCollection invoice, String contactID, String currencyID, String accountID)
throws PluginException {
ZohoBill zohoBill = new ZohoBill();
@ -473,6 +377,9 @@ public class ZohoAPIService {
zohoBill.setAmount(invoice.getItemValueDouble("invoice.total"));
// Kunden-ID (muss angepasst werden je nachdem wie du sie speicherst)
zohoBill.setVendorId(contactID);
if (currencyID != null && !currencyID.isEmpty()) {
zohoBill.setCurrencyId(currencyID);
}
// zohoBill.setPaid_through_account_id("1700");
List<ItemCollection> positionen = InvoiceUtil.explodeChildList(invoice);
// {amount=[11825.00], total=[11825.00], numpos=[1], name=[AB-DEFGHI-1234-567],
@ -603,4 +510,56 @@ public class ZohoAPIService {
}
}
/**
* Sucht eine currency ID Wegen eifnachheit parsen wir hier direkt die JSON
* struktur
*
* @param currency
* @param accessToken
* @return
* @throws PluginException
*/
public String lookupCurrency(String currency, String accessToken) throws PluginException {
// Print JSON to console for verification
logger.info("├── Zoho lookup currency '" + currency + "'...");
try {
// https://www.zohoapis.com/books/v3/contacts?organization_id=10234695&company_name=xxx'
String uri = zohoOAuthManager.getBaseURI() + "settings/currencies?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<String> 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 currencies - Status code: " + response.statusCode() + ", Response: "
+ response.body());
}
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;
logger.info("│ ├── Currency ID=" + result);
return result;
} catch (IOException | InterruptedException e) {
throw new PluginException(this.getClass().getName(), "Zoho API error",
"Failed to find Contacts: " + e.getMessage());
}
}
}

View file

@ -29,7 +29,7 @@ import java.util.logging.Logger;
import org.imixs.workflow.exceptions.PluginException;
import org.imixs.workflow.office.config.ConfigController;
import jakarta.enterprise.context.ConversationScoped;
import jakarta.enterprise.context.SessionScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;
@ -43,7 +43,7 @@ import jakarta.inject.Named;
*/
@Named("zohoController")
// @ApplicationScoped
@ConversationScoped
@SessionScoped
public class ZohoController extends ConfigController {
public static final String ZOHO_CONFIGURATION = "ZOHO_CONFIGURATION";

View file

@ -86,8 +86,8 @@ public class ZohoExportAdapter implements SignalAdapter {
// find companyID
String contactID = zohoAPIService.lookupContact(document.getItemValueString("dbtr.name"), "customer",
accessToken);
ZohoInvoice zohoInvoice = zohoAPIService.exportInvoice(document, contactID, accessToken);
String currencyID = zohoAPIService.lookupCurrency(document.getItemValueString("invoice.currency"), accessToken);
ZohoInvoice zohoInvoice = zohoAPIService.exportInvoice(document, contactID, currencyID, accessToken);
// Attache Files....
List<FileData> files = null;
@ -117,9 +117,10 @@ public class ZohoExportAdapter implements SignalAdapter {
String contactID = zohoAPIService.lookupContact(document.getItemValueString("cdtr.name"), "vendor",
accessToken);
String currencyID = zohoAPIService.lookupCurrency(document.getItemValueString("invoice.currency"), accessToken);
String accountID = zohoOAuthManager.getAccountId();
ZohoBill zohoBill = zohoAPIService.exportBill(document, contactID, accountID, accessToken);
ZohoBill zohoBill = zohoAPIService.exportBill(document, contactID, currencyID, accountID, accessToken);
// Attache Files....
List<FileData> files = null;
@ -135,4 +136,5 @@ public class ZohoExportAdapter implements SignalAdapter {
}
}
}
}

View file

@ -14,6 +14,9 @@ public class ZohoBill {
@JsonbProperty("vendor_id")
private String vendorId;
@JsonbProperty("currency_id")
private String currencyId;
@JsonbDateFormat("yyyy-MM-dd")
private LocalDate date;
@ -87,4 +90,12 @@ public class ZohoBill {
this.amount = amount;
}
public String getCurrencyId() {
return currencyId;
}
public void setCurrencyId(String currencyId) {
this.currencyId = currencyId;
}
}

View file

@ -1,99 +0,0 @@
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 ZohoExpense {
@JsonbProperty("expense_id")
private String expenseId;
@JsonbProperty("account_id")
private String accountId;
@JsonbProperty("paid_through_account_id")
private String paid_through_account_id;
@JsonbProperty("customer_id")
private String customerId;
@JsonbDateFormat("yyyy-MM-dd")
private LocalDate date;
@JsonbProperty("reference_number")
private String invoiceNumber;
@JsonbProperty("line_items")
private List<ZohoExpenseItem> lineItems;
private double amount;
// Getter und Setter
public String getExpenseId() {
return expenseId;
}
public void setExpenseId(String expenseId) {
this.expenseId = expenseId;
}
public String getAccountId() {
return accountId;
}
public void setAccountId(String accountId) {
this.accountId = accountId;
}
public String getCustomerId() {
return customerId;
}
public void setCustomerId(String customerId) {
this.customerId = customerId;
}
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<ZohoExpenseItem> getLineItems() {
return lineItems;
}
public void setLineItems(List<ZohoExpenseItem> lineItems) {
this.lineItems = lineItems;
}
public double getAmount() {
return amount;
}
public void setAmount(double amount) {
this.amount = amount;
}
public String getPaid_through_account_id() {
return paid_through_account_id;
}
public void setPaid_through_account_id(String paid_through_account_id) {
this.paid_through_account_id = paid_through_account_id;
}
}

View file

@ -1,39 +0,0 @@
package com.alexanderlogistics.zoho.dto;
import jakarta.json.bind.annotation.JsonbProperty;
public class ZohoExpenseCreateResponse {
@JsonbProperty("code")
private int code;
@JsonbProperty("message")
private String message;
@JsonbProperty("expense")
private ZohoExpense expense;
// 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 ZohoExpense getExpense() {
return expense;
}
public void setExpense(ZohoExpense expense) {
this.expense = expense;
}
}

View file

@ -1,16 +0,0 @@
package com.alexanderlogistics.zoho.dto;
public class ZohoExpenseItem {
private String description;
// Getter und Setter
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}

View file

@ -14,6 +14,9 @@ public class ZohoInvoice {
@JsonbProperty("customer_id")
private String customerId;
@JsonbProperty("currency_id")
private String currencyId;
@JsonbDateFormat("yyyy-MM-dd")
private LocalDate date;
@ -86,4 +89,12 @@ public class ZohoInvoice {
public void setTotal(double total) {
this.total = total;
}
public String getCurrencyId() {
return currencyId;
}
public void setCurrencyId(String currencyId) {
this.currencyId = currencyId;
}
}

View file

@ -137,7 +137,7 @@
Generieren Sie einen neuen Access Code
<br />
Scope:
<code>ZohoBooks.contacts.ALL,ZohoBooks.invoices.ALL,ZohoBooks.bills.ALL</code>
<code>ZohoBooks.contacts.ALL,ZohoBooks.invoices.ALL,ZohoBooks.bills.ALL,ZohoBooks.settings.READ</code>
</li>
<li>
Code über den Button "Create" anfordern und in das Feld "Access Code"