This commit is contained in:
Ralph Soika 2025-04-25 16:30:41 +02:00
parent 27f7b2b4f6
commit cbe256a962
6 changed files with 226 additions and 17 deletions

View file

@ -1,9 +1,11 @@
package com.alexanderlogistics.zoho;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.List;
import java.util.Locale;
@ -14,8 +16,10 @@ import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.exceptions.PluginException;
import com.alexanderlogistics.InvoiceUtil;
import com.alexanderlogistics.zoho.dto.ZohoInvoiceDTO;
import com.alexanderlogistics.zoho.dto.ZohoInvoiceItemDTO;
import com.alexanderlogistics.zoho.dto.ZohoContact;
import com.alexanderlogistics.zoho.dto.ZohoContactsResponse;
import com.alexanderlogistics.zoho.dto.ZohoInvoice;
import com.alexanderlogistics.zoho.dto.ZohoInvoiceItem;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.security.DeclareRoles;
@ -60,6 +64,57 @@ public class ZohoAPIService {
}
public String findContactIDByCompanyName(String companyName, String accessToken) throws PluginException {
// Print JSON to console for verification
logger.info("├── Zoho getcontact Request...");
try {
// https://www.zohoapis.com/books/v3/contacts?organization_id=10234695&company_name=xxx'
String uri = ZOHO_API_BASE_URL + "contacts?organization_id="
+ zohoOAuthManager.getOrganization() + "&company_name="
+ URLEncoder.encode(companyName, StandardCharsets.UTF_8);
logger.info("│ ├── 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 = httpClient.send(
request, HttpResponse.BodyHandlers.ofString());
// Print response details to console
logger.info("├── Zoho Response:");
logger.info("│ ├── Status Code: " + response.statusCode());
logger.info("│ ├── 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());
}
ZohoContactsResponse contactsResponse = jsonb.fromJson(response.body(),
ZohoContactsResponse.class);
if (contactsResponse != null && contactsResponse.getContacts() != null) {
// Durchsuche die Ergebnisse nach exakter Übereinstimmung
for (ZohoContact contact : contactsResponse.getContacts()) {
if (companyName.equalsIgnoreCase(contact.getCompanyName())) {
return contact.getContactId();
}
}
}
return null;
} catch (Exception e) {
throw new PluginException(this.getClass().getName(), "Zoho API error",
"Failed to find contacts", e);
}
}
/**
* Exports an invocie document
*
@ -72,7 +127,7 @@ public class ZohoAPIService {
String accessToken = zohoOAuthManager.getValidAccessToken();
// Konvertiere ItemCollection zu ZohoInvoiceDTO
ZohoInvoiceDTO zohoInvoice = convertToZohoInvoice(invoice);
ZohoInvoice zohoInvoice = convertToZohoInvoice(invoice, accessToken);
try {
String requestBody = jsonb.toJson(zohoInvoice);
@ -82,9 +137,10 @@ public class ZohoAPIService {
logger.info("│ ├── " + requestBody);
// https://www.zohoapis.com/books/v3/invoices?organization_id=10234695'
String uri = ZOHO_API_BASE_URL + "invoices?organization_id=" + zohoOAuthManager.getOrganization();
String uri = ZOHO_API_BASE_URL + "invoices?organization_id="
+ zohoOAuthManager.getOrganization();
logger.info("│ ├── uri= " + uri);
logger.info("│ ├── accessToken=" + accessToken);
logger.fine("│ ├── accessToken=" + accessToken);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(uri))
.header("Authorization", "Zoho-oauthtoken " + accessToken)
@ -115,8 +171,77 @@ public class ZohoAPIService {
}
}
private ZohoInvoiceDTO convertToZohoInvoice(ItemCollection invoice) {
ZohoInvoiceDTO zohoInvoice = new ZohoInvoiceDTO();
/**
* Erstellt einen neuen Contact in Zoho Books
*
* @param companyName Der Firmenname für den neuen Contact
* @return Der erstellte ZohoContact mit contact_id
* @throws PluginException Wenn der API-Aufruf fehlschlägt
*/
public ZohoContact createContact(String companyName, String accessToken) throws PluginException {
try {
// Contact-DTO vorbereiten
ZohoContact newContact = new ZohoContact();
newContact.setContactName(companyName); // Wir verwenden den Firmennamen auch als Contact Name
newContact.setCompanyName(companyName);
// JSON serialisieren
String requestBody = jsonb.toJson(newContact);
logger.info("├── Zoho Contact Creation...");
logger.info("│ ├── " + requestBody);
String uri = ZOHO_API_BASE_URL + "contacts?organization_id="
+ zohoOAuthManager.getOrganization();
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());
logger.info("├── Zoho Response:");
logger.info("│ ├── Status Code: " + response.statusCode());
logger.info("│ ├── Response Body: " + response.body());
if (response.statusCode() == 201) {
// Erfolgreiche Erstellung
ZohoContact createResponse = jsonb.fromJson(response.body(), ZohoContact.class);
if (createResponse != null) {
return createResponse;
}
}
throw new PluginException(this.getClass().getName(), "Zoho API error",
"Failed to create contact. Status code: " + response.statusCode() +
", Response: " + response.body());
} catch (Exception e) {
throw new PluginException(this.getClass().getName(), "Zoho API error",
"Failed to create contact", e);
}
}
private ZohoInvoice convertToZohoInvoice(ItemCollection invoice, String accessToken) throws PluginException {
// teste ob wir einen contact finden
String contactID = "";
try {
contactID = findContactIDByCompanyName(invoice.getItemValueString("dbtr.name"), accessToken);
if (contactID == null) {
ZohoContact contact = createContact(invoice.getItemValueString("dbtr.name"), accessToken);
contactID = contact.getContactId();
}
} catch (PluginException ef) {
logger.severe("Failed to find Contact by company name: " + ef.getMessage());
}
ZohoInvoice zohoInvoice = new ZohoInvoice();
// Basisinformationen
// zohoInvoice.setInvoiceNumber(invoice.getItemValueString("invoice.number"));
@ -129,17 +254,17 @@ public class ZohoAPIService {
zohoInvoice.setTotal(invoice.getItemValueDouble("invoice.total"));
// Kunden-ID (muss angepasst werden je nachdem wie du sie speicherst)
// zohoInvoice.setCustomerId(invoice.getItemValueString("dbtr.number"));
zohoInvoice.setCustomerId("777249000000055569");
zohoInvoice.setCustomerId(contactID);
// zohoInvoice.setCustomerId("777249000000055569");
// Positionen (muss angepasst werden je nach Datenstruktur)
// List<ZohoInvoiceItemDTO> lineItems = new ArrayList<>();
List<ItemCollection> positionen = InvoiceUtil.explodeChildList(invoice);
List<ZohoInvoiceItemDTO> lineItems = positionen.stream()
List<ZohoInvoiceItem> lineItems = positionen.stream()
.map(item -> {
ItemCollection itemCol = (ItemCollection) item;
ZohoInvoiceItemDTO lineItem = new ZohoInvoiceItemDTO();
ZohoInvoiceItem lineItem = new ZohoInvoiceItem();
lineItem.setName(itemCol.getItemValueString("datev.text"));
lineItem.setDescription(itemCol.getItemValueString("billingtext"));
lineItem.setRate(itemCol.getItemValueDouble("datev.umsatz"));

View file

@ -0,0 +1,43 @@
package com.alexanderlogistics.zoho.dto;
import jakarta.json.bind.annotation.JsonbProperty;
public class ZohoContact {
@JsonbProperty("contact_id")
private String contactId;
@JsonbProperty("contact_name")
private String contactName;
@JsonbProperty("company_name")
private String companyName;
// Weitere Felder nach Bedarf
// Getter und Setter
public String getContactId() {
return contactId;
}
public void setContactId(String contactId) {
this.contactId = contactId;
}
public String getContactName() {
return contactName;
}
public void setContactName(String contactName) {
this.contactName = contactName;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
}

View file

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

View file

@ -5,13 +5,13 @@ import java.util.List;
import jakarta.json.bind.annotation.JsonbProperty;
public class ZohoInvoiceDTO {
public class ZohoInvoice {
private String customerId;
private Date date;
private Date dueDate;
private String invoiceNumber;
private List<ZohoInvoiceItemDTO> lineItems;
private List<ZohoInvoiceItem> lineItems;
private double total;
// Getter und Setter
@ -52,11 +52,11 @@ public class ZohoInvoiceDTO {
}
@JsonbProperty("line_items")
public List<ZohoInvoiceItemDTO> getLineItems() {
public List<ZohoInvoiceItem> getLineItems() {
return lineItems;
}
public void setLineItems(List<ZohoInvoiceItemDTO> lineItems) {
public void setLineItems(List<ZohoInvoiceItem> lineItems) {
this.lineItems = lineItems;
}

View file

@ -1,6 +1,6 @@
package com.alexanderlogistics.zoho.dto;
public class ZohoInvoiceItemDTO {
public class ZohoInvoiceItem {
private String name;
private String description;
private double rate;

View file

@ -94,7 +94,7 @@
Generieren Sie einen neuen Access Code
<br />
Scope:
<code>ZohoBooks.invoices.CREATE,ZohoBooks.invoices.READ,ZohoBooks.invoices.UPDATE</code>
<code>zohocontacts.contactapi.ALL,ZohoBooks.invoices.CREATE,ZohoBooks.invoices.READ,ZohoBooks.invoices.UPDATE</code>
</li>
<li>
Code über den Button "Create" anfordern und in das Feld "Access Code"