zoho credit note interface

This commit is contained in:
Ralph Soika 2025-06-25 09:54:33 +02:00
parent ffb0942737
commit e350ece8f3
6 changed files with 2926 additions and 3 deletions

View file

@ -20,6 +20,7 @@ import java.util.stream.Collectors;
import org.imixs.workflow.FileData;
import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.engine.DocumentService;
import org.imixs.workflow.exceptions.PluginException;
import com.alexanderlogistics.InvoiceUtil;
@ -33,6 +34,7 @@ import com.alexanderlogistics.zoho.dto.ZohoCreditnote;
import com.alexanderlogistics.zoho.dto.ZohoCreditnoteCreateResponse;
import com.alexanderlogistics.zoho.dto.ZohoInvoice;
import com.alexanderlogistics.zoho.dto.ZohoInvoiceCreateResponse;
import com.alexanderlogistics.zoho.dto.ZohoInvoiceFindResponse;
import com.alexanderlogistics.zoho.dto.ZohoInvoiceItem;
import com.alexanderlogistics.zoho.dto.ZohoTax;
import com.alexanderlogistics.zoho.dto.ZohoTaxListResponse;
@ -75,6 +77,9 @@ public class ZohoAPIService {
@Inject
ZohoOAuthManager zohoOAuthManager;
@Inject
DocumentService documentService;
@PostConstruct
void init() {
this.httpClient = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(10)).build();
@ -144,6 +149,61 @@ public class ZohoAPIService {
}
/**
* This finder method returns the invoice ID to a given invoice.number
* The method returns null if no invoice with this nubmer exists
*
* @param companyName
* @param accessToken
* @return
* @throws PluginException
*/
public ZohoInvoice findInvoiceIDByInvoiceNumber(String invoiceNumber, String accessToken)
throws PluginException {
// Print JSON to console for verification
logger.info("├── Zoho lookup invoice '" + invoiceNumber + "'...");
try {
// https://www.zohoapis.com/books/v3/contacts?organization_id=10234695&company_name=xxx'
String uri = zohoOAuthManager.getBaseURI() + "invoices?organization_id="
+ zohoOAuthManager.getOrganization() + "&invoice_number="
+ URLEncoder.encode(invoiceNumber, StandardCharsets.UTF_8);
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 invoice - Status code: " + response.statusCode() + ", Response: "
+ response.body());
}
ZohoInvoiceFindResponse invoicesResponse = jsonb.fromJson(response.body(), ZohoInvoiceFindResponse.class);
if (invoicesResponse != null && invoicesResponse.getInvoices() != null
&& invoicesResponse.getInvoices().size() > 0) {
// return 1 entry
ZohoInvoice invoice = invoicesResponse.getInvoices().get(0);
return invoice;
}
} catch (IOException | InterruptedException e) {
throw new PluginException(this.getClass().getName(), "Zoho API error",
"Failed to find Contacts: " + e.getMessage());
}
return null;
}
/**
* Exports an invocie document
*
@ -231,8 +291,19 @@ public class ZohoAPIService {
String currencyID = lookupCurrency(invoice.getItemValueString("invoice.currency"), accessToken);
// Lookup die Invoice ID in zOho
ZohoInvoice invoiceZoho = null;
String invoiceRefID = invoice.getItemValueString("invoice.ref");
ItemCollection invoiceRef = documentService.load(invoiceRefID);
if (invoiceRef != null) {
invoiceZoho = findInvoiceIDByInvoiceNumber(invoiceRef.getItemValueString("invoice.number"),
accessToken);
logger.info("├── Zoho fond invoice zoho ref: " + invoiceZoho.getInvoiceId());
}
// Konvertiere ItemCollection zu ZohoInvoiceDTO
ZohoCreditnote zohoCreditnote = convertToZohoCreditnote(invoice, contactID, currencyID);
ZohoCreditnote zohoCreditnote = convertToZohoCreditnote(invoice, contactID, currencyID, invoiceZoho);
try {
String requestBody = jsonb.toJson(zohoCreditnote);
@ -244,6 +315,10 @@ public class ZohoAPIService {
// https://www.zohoapis.com/books/v3/creditnotes?organization_id=10234695'
String uri = zohoOAuthManager.getBaseURI() + "creditnotes?organization_id="
+ zohoOAuthManager.getOrganization();
if (zohoCreditnote != null) {
uri = uri + "&invoice_id=" + invoiceZoho.getInvoiceId();
}
logger.fine("│ ├── uri= " + uri);
logger.fine("│ ├── accessToken=" + accessToken);
HttpRequest request = HttpRequest.newBuilder().uri(URI.create(uri))
@ -565,14 +640,15 @@ public class ZohoAPIService {
* @return
* @throws PluginException
*/
private ZohoCreditnote convertToZohoCreditnote(ItemCollection invoice, String contactID, String currencyID)
private ZohoCreditnote convertToZohoCreditnote(ItemCollection invoice, String contactID, String currencyID,
ZohoInvoice zohoInvoice)
throws PluginException {
ZohoCreditnote zohoCreditnote = new ZohoCreditnote();
// 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(
@ -586,6 +662,19 @@ public class ZohoAPIService {
zohoCreditnote.setCurrencyId(currencyID);
}
// do we have an invoice?
if (zohoInvoice != null) {
String placeOfSupply = zohoInvoice.getPlaceOfSupply();
if (placeOfSupply == null) {
placeOfSupply = "DU";
}
logger.info("│ ├── set place of supply=" + placeOfSupply);
zohoCreditnote.setPlaceOfSupply(placeOfSupply);
// logger.info("....assign invoice");
// ZohoCreditnoteInvoiceItem zcii = new ZohoCreditnoteInvoiceItem(zohoInvoice);
// zohoCreditnote.setInvoices(java.util.Arrays.asList(zcii));
}
// convert total by rate - negativer betrag!
zohoCreditnote.setTotal(Math.abs(invoice.getItemValueDouble("invoice.total")));
// set exchange Rate
@ -606,6 +695,30 @@ public class ZohoAPIService {
}).collect(Collectors.toList());
zohoCreditnote.setLineItems(lineItems);
// add line items...
// changes 24.06.2025 - Keine einzelPositionen mehr an Zoho senden, da diese von
// Cargosoft unbrauchbar sind.
// List<ItemCollection> positionen = InvoiceUtil.explodeChildList(invoice);
// List<ZohoInvoiceItem> lineItems = positionen.stream().map(item -> {
// ItemCollection itemCol = (ItemCollection) item;
// ZohoInvoiceItem lineItem = new ZohoInvoiceItem();
// 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());
// List<ZohoInvoiceItem> lineItems = new ArrayList<>();
// create only one single item!
ZohoInvoiceItem lineItem = new ZohoInvoiceItem();
lineItem.setName(invoice.getItemValueString("invoice.text"));
lineItem.setDescription("");
lineItem.setRate(invoice.getItemValueDouble("invoice.total"));
lineItem.setQuantity(1);
lineItems.add(lineItem);
return zohoCreditnote;
}

View file

@ -25,12 +25,18 @@ public class ZohoCreditnote {
@JsonbProperty("reference_number")
private String referenceNumber;
@JsonbProperty("place_of_supply")
private String placeOfSupply;
@JsonbProperty("line_items")
private List<ZohoInvoiceItem> lineItems;
@JsonbProperty("exchange_rate")
private double exchangeRate;
@JsonbProperty("invoices")
private List<ZohoCreditnoteInvoiceItem> invoices;
private double total;
// Getter und Setter
@ -106,4 +112,20 @@ public class ZohoCreditnote {
public void setReferenceNumber(String referenceNumber) {
this.referenceNumber = referenceNumber;
}
public List<ZohoCreditnoteInvoiceItem> getInvoices() {
return invoices;
}
public void setInvoices(List<ZohoCreditnoteInvoiceItem> invoices) {
this.invoices = invoices;
}
public String getPlaceOfSupply() {
return placeOfSupply;
}
public void setPlaceOfSupply(String placeOfSupply) {
this.placeOfSupply = placeOfSupply;
}
}

View file

@ -0,0 +1,49 @@
package com.alexanderlogistics.zoho.dto;
import jakarta.json.bind.annotation.JsonbProperty;
/**
* Referenz von Invoices in einer CreditNote
*/
public class ZohoCreditnoteInvoiceItem {
@JsonbProperty("invoice_id")
private String invoiceId;
@JsonbProperty("invoice_number")
private String invoiceNumber;
private double amount;
public ZohoCreditnoteInvoiceItem(ZohoInvoice invoice) {
this.invoiceId = invoice.getInvoiceId();
this.invoiceNumber = invoice.getInvoiceNumber();
this.amount = invoice.getTotal();
}
// Getter und Setter
public String getInvoiceId() {
return invoiceId;
}
public void setInvoiceId(String invoiceId) {
this.invoiceId = invoiceId;
}
public String getInvoiceNumber() {
return invoiceNumber;
}
public void setInvoiceNumber(String invoiceNumber) {
this.invoiceNumber = invoiceNumber;
}
public double getAmount() {
return amount;
}
public void setAmount(double amount) {
this.amount = amount;
}
}

View file

@ -33,6 +33,9 @@ public class ZohoInvoice {
@JsonbProperty("exchange_rate")
private double exchangeRate;
@JsonbProperty("place_of_supply")
private String placeOfSupply;
private double total;
// Getter und Setter
@ -108,4 +111,12 @@ public class ZohoInvoice {
public void setExchangeRate(double exchangeRate) {
this.exchangeRate = exchangeRate;
}
public String getPlaceOfSupply() {
return placeOfSupply;
}
public void setPlaceOfSupply(String placeOfSupply) {
this.placeOfSupply = placeOfSupply;
}
}

View file

@ -0,0 +1,41 @@
package com.alexanderlogistics.zoho.dto;
import java.util.List;
import jakarta.json.bind.annotation.JsonbProperty;
public class ZohoInvoiceFindResponse {
@JsonbProperty("code")
private int code;
@JsonbProperty("message")
private String message;
@JsonbProperty("invoices")
private List<ZohoInvoice> invoices;
// 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<ZohoInvoice> getInvoices() {
return invoices;
}
public void setInvoices(List<ZohoInvoice> invoices) {
this.invoices = invoices;
}
}

File diff suppressed because it is too large Load diff