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 7c28bdd..4ec5d99 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 @@ -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 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 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 lineItems = new ArrayList<>(); List positionen = InvoiceUtil.explodeChildList(invoice); - List lineItems = positionen.stream() + List 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")); diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoContact.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoContact.java new file mode 100644 index 0000000..d715136 --- /dev/null +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoContact.java @@ -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; + } + +} diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoContactsResponse.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoContactsResponse.java new file mode 100644 index 0000000..cf86850 --- /dev/null +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoContactsResponse.java @@ -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 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 getContacts() { + return contacts; + } + + public void setContacts(List contacts) { + this.contacts = contacts; + } +} diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoInvoiceDTO.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoInvoice.java similarity index 86% rename from office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoInvoiceDTO.java rename to office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoInvoice.java index 025faa7..c957598 100644 --- a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoInvoiceDTO.java +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoInvoice.java @@ -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 lineItems; + private List lineItems; private double total; // Getter und Setter @@ -52,11 +52,11 @@ public class ZohoInvoiceDTO { } @JsonbProperty("line_items") - public List getLineItems() { + public List getLineItems() { return lineItems; } - public void setLineItems(List lineItems) { + public void setLineItems(List lineItems) { this.lineItems = lineItems; } diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoInvoiceItemDTO.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoInvoiceItem.java similarity index 96% rename from office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoInvoiceItemDTO.java rename to office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoInvoiceItem.java index e5ebb6f..8971bd5 100644 --- a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoInvoiceItemDTO.java +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/dto/ZohoInvoiceItem.java @@ -1,6 +1,6 @@ package com.alexanderlogistics.zoho.dto; -public class ZohoInvoiceItemDTO { +public class ZohoInvoiceItem { private String name; private String description; private double rate; 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 7e1112e..ec6009e 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 @@ -94,7 +94,7 @@ Generieren Sie einen neuen Access Code
Scope: - ZohoBooks.invoices.CREATE,ZohoBooks.invoices.READ,ZohoBooks.invoices.UPDATE + zohocontacts.contactapi.ALL,ZohoBooks.invoices.CREATE,ZohoBooks.invoices.READ,ZohoBooks.invoices.UPDATE
  • Code über den Button "Create" anfordern und in das Feld "Access Code"