zoho expense export
This commit is contained in:
parent
4b9da4d98a
commit
d47518224f
16 changed files with 906 additions and 105 deletions
|
|
@ -18,7 +18,7 @@ Base API URI= https://accounts.zoho.eu/
|
|||
|
||||
## 1. Client Einrichten
|
||||
|
||||
https://api-console.zoho.eu/client/1000.NLTM2KUEHI696MSLGEIANATVGGX7IN
|
||||
https://api-console.zoho.eu/
|
||||
|
||||
## 2. Generating Grant Token
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,60 @@ zoho.scope ZohoBooks.contacts.ALL ZohoBooks.invoices.CREATE ZohoBooks.i
|
|||
|
||||
```
|
||||
|
||||
## Forum
|
||||
|
||||
form@imixs.com
|
||||
imixs4zoho
|
||||
|
||||
https://api-console.zoho.eu/
|
||||
|
||||
ZohoBooks.contacts.ALL,ZohoBooks.invoices.ALL,ZohoBooks.bills.ALL
|
||||
|
||||
```
|
||||
zoho.accesstoken 1.....3
|
||||
zoho.apidomain https://www.zohoapis.eu
|
||||
zoho.clientid 1000.5SMVXH92JIA5BTIGJF27OY41TAFFAS
|
||||
zoho.clientsecret 64aabb5e819757e471c9d0dff6a072b1bcf2c7687d
|
||||
zoho.code 10-
|
||||
zoho.organization 886888983
|
||||
zoho.refreshtoken 10...ff440e
|
||||
zoho.scope ZohoBooks.contacts.ALL ZohoBooks.invoices.CREATE ZohoBooks.invoices.READ ZohoBooks.invoices.UPDATE
|
||||
|
||||
```
|
||||
|
||||
## Atari
|
||||
|
||||
atari.600xl@gmail.com
|
||||
800xlAtari
|
||||
|
||||
```
|
||||
zoho.apidomain https://www.zohoapis.eu
|
||||
zoho.clientid 1000.86O4P321HDYDRX0Q0N1G7YOJRJ9D5W
|
||||
zoho.clientsecret 2a67b6cfc364f5df27cc8eb33e9b0e4e8a0221ebc3
|
||||
zoho.code 1000.c7dc89c06111b93f1242b587fabed4ac.44c591dffbd978a316e3d90ed3fefc78
|
||||
zoho.organization 886924765
|
||||
zoho.scope ZohoBooks.contacts.ALL,ZohoBooks.invoices.ALL,ZohoBooks.bills.ALL
|
||||
```
|
||||
|
||||
## Prod DWC
|
||||
|
||||
info@imixs.com
|
||||
imixs4zoho
|
||||
|
||||
https://api-console.zoho.com/
|
||||
|
||||
ZohoBooks.contacts.ALL,ZohoBooks.invoices.ALL,ZohoBooks.bills.ALL
|
||||
|
||||
```
|
||||
|
||||
zoho.apidomain https://www.zohoapis.com
|
||||
zoho.clientid 1000.MQE1SU8UGY6F2PBPASOXGTLWYQD1FS
|
||||
zoho.clientsecret 1ca70e1ab803b3fed6b1b5e00858c316e2003d289b
|
||||
zoho.organization 884218508
|
||||
zoho.scope ZohoBooks.contacts.ALL,ZohoBooks.invoices.ALL,ZohoBooks.bills.ALL
|
||||
|
||||
```
|
||||
|
||||
# API Dokumentation
|
||||
|
||||
- API Docu: https://www.zoho.com/books/api/v3/introduction/
|
||||
|
|
|
|||
167
doc/zoho/bill-create-example.json
Normal file
167
doc/zoho/bill-create-example.json
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
{
|
||||
"code": 0,
|
||||
"message": "The bill has been created.",
|
||||
"bill": {
|
||||
"bill_id": "6206847000000103003",
|
||||
"vendor_id": "6206847000000100015",
|
||||
"vendor_name": "Feldmuehle GmbH",
|
||||
"source": "Api",
|
||||
"contact_category": "",
|
||||
"tax_treatment": "",
|
||||
"unused_credits_payable_amount": 0.00,
|
||||
"status": "paid",
|
||||
"color_code": "",
|
||||
"current_sub_status_id": "",
|
||||
"current_sub_status": "paid",
|
||||
"sub_statuses": [],
|
||||
"bill_number": "28195",
|
||||
"date": "2024-07-26",
|
||||
"due_date": "2024-07-26",
|
||||
"discount_setting": "flat",
|
||||
"tds_calculation_type": "tds_item_level",
|
||||
"payment_terms": 0,
|
||||
"payment_terms_label": "Due on Receipt",
|
||||
"payment_expected_date": "",
|
||||
"reference_number": "",
|
||||
"scanned_po_number": "",
|
||||
"recurring_bill_id": "",
|
||||
"due_by_days": 286,
|
||||
"due_in_days": "",
|
||||
"currency_id": "6206847000000000109",
|
||||
"currency_code": "EUR",
|
||||
"currency_symbol": "€",
|
||||
"currency_name_formatted": "EUR- Euro",
|
||||
"documents": [],
|
||||
"subject_content": "",
|
||||
"price_precision": 2,
|
||||
"exchange_rate": 1.00,
|
||||
"custom_fields": [],
|
||||
"custom_field_hash": {},
|
||||
"is_viewed_by_client": false,
|
||||
"client_viewed_time": "",
|
||||
"is_item_level_tax_calc": false,
|
||||
"is_inclusive_tax": false,
|
||||
"tax_rounding": "entity_level",
|
||||
"is_uber_bill": false,
|
||||
"is_tally_bill": false,
|
||||
"track_discount_in_account": true,
|
||||
"is_bill_reconciliation_violated": false,
|
||||
"bill_order_type": "",
|
||||
"line_items": [
|
||||
{
|
||||
"purchaseorder_id": "",
|
||||
"purchaseorder_item_id": "",
|
||||
"receive_id": "",
|
||||
"line_item_id": "6206847000000103013",
|
||||
"item_id": "",
|
||||
"name": "AB-DEFGHI-1234-567",
|
||||
"account_id": "6206847000000092271",
|
||||
"account_name": "TEst",
|
||||
"description": "",
|
||||
"bcy_rate": 0.00,
|
||||
"rate": 0.00,
|
||||
"sales_rate": "",
|
||||
"pricebook_id": "",
|
||||
"header_id": "",
|
||||
"header_name": "",
|
||||
"tags": [],
|
||||
"quantity": 1.00,
|
||||
"discount": 0.00,
|
||||
"discounts": [],
|
||||
"discount_account_id": "",
|
||||
"discount_account_name": "",
|
||||
"markup_percent": 0.00,
|
||||
"tax_id": "",
|
||||
"tax_name": "",
|
||||
"tax_type": "tax",
|
||||
"tax_percentage": 0,
|
||||
"line_item_taxes": [],
|
||||
"item_total": 0.00,
|
||||
"item_order": 1,
|
||||
"unit": "",
|
||||
"item_type": "",
|
||||
"image_name": "",
|
||||
"image_type": "",
|
||||
"is_billable": false,
|
||||
"customer_id": "",
|
||||
"receipt_line_item_id": "",
|
||||
"customer_name": "",
|
||||
"project_id": "",
|
||||
"project_name": "",
|
||||
"invoice_id": "",
|
||||
"invoice_number": "",
|
||||
"item_custom_fields": [],
|
||||
"purchase_request_items": [],
|
||||
"item_matching_type": ""
|
||||
}
|
||||
],
|
||||
"submitted_date": "",
|
||||
"submitted_by": "",
|
||||
"submitted_by_name": "",
|
||||
"submitted_by_email": "",
|
||||
"submitted_by_photo_url": "",
|
||||
"submitter_id": "",
|
||||
"approver_id": "",
|
||||
"adjustment": 0.00,
|
||||
"adjustment_description": "",
|
||||
"discount_amount": 0.00,
|
||||
"discount": 0.00,
|
||||
"discount_applied_on_amount": 0.00,
|
||||
"is_discount_before_tax": true,
|
||||
"discount_account_id": "",
|
||||
"discount_account_name": "",
|
||||
"discount_type": "entity_level",
|
||||
"sub_total": 0.00,
|
||||
"sub_total_inclusive_of_tax": 0.00,
|
||||
"tax_total": 0.00,
|
||||
"discount_total": 0.00,
|
||||
"discount_percent": 0.00,
|
||||
"total": 0.00,
|
||||
"payment_made": 0.00,
|
||||
"vendor_credits_applied": 0.00,
|
||||
"is_line_item_invoiced": false,
|
||||
"purchaseorders": [],
|
||||
"taxes": [],
|
||||
"computation_type": "basic",
|
||||
"tax_override_preference": "no_override",
|
||||
"tds_override_preference": "no_override",
|
||||
"balance": 0.00,
|
||||
"unprocessed_payment_amount": 0.00,
|
||||
"billing_address_id": "6206847000000100017",
|
||||
"billing_address": {
|
||||
"address": "",
|
||||
"street2": "",
|
||||
"city": "",
|
||||
"state": "",
|
||||
"zip": "",
|
||||
"country": "",
|
||||
"fax": "",
|
||||
"phone": "",
|
||||
"attention": ""
|
||||
},
|
||||
"payments": [],
|
||||
"vendor_credits": [],
|
||||
"created_time": "2025-05-08T21:36:04+0100",
|
||||
"created_by_id": "6206847000000092001",
|
||||
"last_modified_id": "6206847000000092001",
|
||||
"last_modified_time": "2025-05-08T21:36:04+0100",
|
||||
"reference_id": "",
|
||||
"notes": "",
|
||||
"terms": "",
|
||||
"attachment_name": "",
|
||||
"template_id": "6206847000000031017",
|
||||
"template_name": "Standard Template",
|
||||
"page_width": "8.27in",
|
||||
"page_height": "11.69in",
|
||||
"orientation": "portrait",
|
||||
"template_type": "standard",
|
||||
"is_approval_required": false,
|
||||
"allocated_landed_costs": [],
|
||||
"unallocated_landed_costs": [],
|
||||
"entity_type": "bill",
|
||||
"total_retention_amount": 0.00,
|
||||
"retention_items": [],
|
||||
"can_send_in_mail": false,
|
||||
"approvers_list": []
|
||||
}
|
||||
}
|
||||
|
|
@ -21,9 +21,15 @@ import org.imixs.workflow.ItemCollection;
|
|||
import org.imixs.workflow.exceptions.PluginException;
|
||||
|
||||
import com.alexanderlogistics.InvoiceUtil;
|
||||
import com.alexanderlogistics.zoho.dto.ZohoBill;
|
||||
import com.alexanderlogistics.zoho.dto.ZohoBillCreateResponse;
|
||||
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;
|
||||
|
|
@ -53,12 +59,12 @@ public class ZohoAPIService {
|
|||
|
||||
private static Logger logger = Logger.getLogger(ZohoAPIService.class.getName());
|
||||
|
||||
@Inject
|
||||
ZohoOAuthManager zohoOAuthManager;
|
||||
|
||||
private HttpClient httpClient;
|
||||
private Jsonb jsonb;
|
||||
|
||||
@Inject
|
||||
ZohoOAuthManager zohoOAuthManager;
|
||||
|
||||
@PostConstruct
|
||||
void init() {
|
||||
this.httpClient = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(10)).build();
|
||||
|
|
@ -68,10 +74,11 @@ public class ZohoAPIService {
|
|||
this.jsonb = JsonbBuilder.create(config);
|
||||
}
|
||||
|
||||
public String findContactIDByCompanyName(String companyName, String accessToken) throws PluginException {
|
||||
public String findContactIDByCompanyName(String companyName, String contactType, String accessToken)
|
||||
throws PluginException {
|
||||
|
||||
// Print JSON to console for verification
|
||||
logger.info("├── Zoho lookup contact '" + companyName + "'...");
|
||||
logger.info("├── Zoho lookup contact (" + contactType + ") '" + companyName + "'...");
|
||||
try {
|
||||
// https://www.zohoapis.com/books/v3/contacts?organization_id=10234695&company_name=xxx'
|
||||
String uri = zohoOAuthManager.getBaseURI() + "contacts?organization_id="
|
||||
|
|
@ -83,7 +90,9 @@ public class ZohoAPIService {
|
|||
.header("Authorization", "Zoho-oauthtoken " + accessToken)
|
||||
.header("Content-Type", "application/json").GET().build();
|
||||
|
||||
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
HttpResponse<String> response;
|
||||
|
||||
response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
|
||||
// Print response details to console
|
||||
logger.fine("├── Zoho Response:");
|
||||
|
|
@ -100,16 +109,18 @@ public class ZohoAPIService {
|
|||
if (contactsResponse != null && contactsResponse.getContacts() != null) {
|
||||
// Durchsuche die Ergebnisse nach exakter Übereinstimmung
|
||||
for (ZohoContact contact : contactsResponse.getContacts()) {
|
||||
if (companyName.equalsIgnoreCase(contact.getCompanyName())) {
|
||||
if (companyName.equalsIgnoreCase(contact.getCompanyName())
|
||||
&& contactType.equalsIgnoreCase((contact.getContactType()))) {
|
||||
logger.info("│ ├── contactID= " + contact.getContactId());
|
||||
return contact.getContactId();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
throw new PluginException(this.getClass().getName(), "Zoho API error", "Failed to find contacts", e);
|
||||
} catch (IOException | InterruptedException e) {
|
||||
throw new PluginException(this.getClass().getName(), "Zoho API error",
|
||||
"Failed to find Contacts: " + e.getMessage());
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -121,21 +132,12 @@ public class ZohoAPIService {
|
|||
* @param invoice
|
||||
* @throws PluginException
|
||||
*/
|
||||
public ZohoInvoice exportInvoice(ItemCollection invoice, List<FileData> files) throws PluginException {
|
||||
String accessToken = zohoOAuthManager.getValidAccessToken();
|
||||
public ZohoInvoice exportInvoice(ItemCollection invoice, String contactID, String accessToken)
|
||||
throws PluginException {
|
||||
logger.info("├── Zoho Export Invoice " + invoice.getItemValueString("invoice.number") + "...");
|
||||
|
||||
// first lookup contact!
|
||||
String contactID = "";
|
||||
contactID = findContactIDByCompanyName(invoice.getItemValueString("dbtr.name"), accessToken);
|
||||
if (contactID == null) {
|
||||
logger.info("│ ├── contact not found");
|
||||
ZohoContact contact = createContact(invoice.getItemValueString("dbtr.name"), accessToken);
|
||||
contactID = contact.getContactId();
|
||||
}
|
||||
|
||||
// Konvertiere ItemCollection zu ZohoInvoiceDTO
|
||||
ZohoInvoice zohoInvoice = convertToZohoInvoice(invoice, contactID, accessToken);
|
||||
ZohoInvoice zohoInvoice = convertToZohoInvoice(invoice, contactID);
|
||||
|
||||
try {
|
||||
String requestBody = jsonb.toJson(zohoInvoice);
|
||||
|
|
@ -173,52 +175,193 @@ public class ZohoAPIService {
|
|||
System.out.print(bodyContent);
|
||||
ZohoInvoiceCreateResponse createResponse = jsonb.fromJson(bodyContent, ZohoInvoiceCreateResponse.class);
|
||||
|
||||
if (createResponse != null) {
|
||||
logger.fine("│ ├── OK - customerID=" + createResponse.getInvoice().getCustomerId());
|
||||
logger.info("│ ├── OK - invoiceID=" + createResponse.getInvoice().getInvoiceId());
|
||||
|
||||
if (createResponse != null) {
|
||||
zohoInvoice = createResponse.getInvoice();
|
||||
|
||||
// now add attachments (optional)
|
||||
try {
|
||||
if (files != null) {
|
||||
for (FileData file : files) {
|
||||
attacheFileData(zohoInvoice.getInvoiceId(), file, "invoices", accessToken);
|
||||
}
|
||||
}
|
||||
// now mark the invoice as send
|
||||
markInvoiceAsSend(zohoInvoice.getInvoiceId(), "invoices", accessToken);
|
||||
} catch (PluginException e) {
|
||||
logger.warning("Failed to export Invoice: " + e.getMessage());
|
||||
}
|
||||
|
||||
logger.info("│ ├── Invoice Export successful.");
|
||||
return zohoInvoice;
|
||||
} else {
|
||||
throw new PluginException(this.getClass().getName(), "Zoho API error",
|
||||
"Failed to export invoice to Zoho: unable to resolve response");
|
||||
}
|
||||
|
||||
} 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 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 {
|
||||
logger.info("├── Zoho Export Bill " + invoice.getItemValueString("invoice.number") + "...");
|
||||
|
||||
// Konvertiere ItemCollection zu ZohoInvoiceDTO
|
||||
ZohoBill zohoBill = convertToZohoBill(invoice, contactID, accountID);
|
||||
|
||||
try {
|
||||
String requestBody = jsonb.toJson(zohoBill);
|
||||
|
||||
// Print JSON to console for verification
|
||||
logger.fine("├── Zoho Bill JSON Request...");
|
||||
logger.fine("│ ├── " + requestBody);
|
||||
|
||||
// https://www.zohoapis.com/books/v3/expenses?organization_id=10234695'
|
||||
String uri = zohoOAuthManager.getBaseURI() + "bills?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);
|
||||
ZohoBillCreateResponse createResponse = jsonb.fromJson(bodyContent, ZohoBillCreateResponse.class);
|
||||
|
||||
if (createResponse != null) {
|
||||
logger.info("│ ├── OK - customerID=" + createResponse.getBill().getVendorId());
|
||||
logger.info("│ ├── OK - billID=" + createResponse.getBill().getBillId());
|
||||
zohoBill = createResponse.getBill();
|
||||
|
||||
// now mark the invoice as send
|
||||
logger.info("│ ├── Bill Export successful.");
|
||||
return zohoBill;
|
||||
}
|
||||
|
||||
} catch (IOException | InterruptedException e) {
|
||||
throw new PluginException(this.getClass().getName(), "Zoho API error",
|
||||
"Failed to export bill to Zoho: " + e.getMessage(), e);
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
public String lookupContact(String companyName, String contactType, String accessToken) throws PluginException {
|
||||
// first lookup contact!
|
||||
String contactID = "";
|
||||
contactID = findContactIDByCompanyName(companyName, contactType, accessToken);
|
||||
if (contactID == null) {
|
||||
logger.info("│ ├── contact '" + companyName + "' not found");
|
||||
ZohoContact contact = createContact(companyName, contactType, accessToken);
|
||||
contactID = contact.getContactId();
|
||||
}
|
||||
return contactID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Erstellt einen neuen Contact in Zoho Books
|
||||
*
|
||||
* @param companyName Der Firmenname für den neuen Contact
|
||||
* @param contactType - customer/vendor
|
||||
* @return Der erstellte ZohoContact mit contact_id
|
||||
* @throws PluginException Wenn der API-Aufruf fehlschlägt
|
||||
*/
|
||||
public ZohoContact createContact(String companyName, String accessToken) throws PluginException {
|
||||
public ZohoContact createContact(String companyName, String contactType, String accessToken)
|
||||
throws PluginException {
|
||||
logger.info("├── Zoho create contact '" + companyName + "'...");
|
||||
try {
|
||||
// Contact-DTO vorbereiten
|
||||
ZohoContact newContact = new ZohoContact();
|
||||
newContact.setContactName(companyName); // Wir verwenden den Firmennamen auch als Contact Name
|
||||
newContact.setCompanyName(companyName);
|
||||
newContact.setContactType(contactType);
|
||||
|
||||
// JSON serialisieren
|
||||
String requestBody = jsonb.toJson(newContact);
|
||||
|
|
@ -258,8 +401,7 @@ public class ZohoAPIService {
|
|||
|
||||
}
|
||||
|
||||
private ZohoInvoice convertToZohoInvoice(ItemCollection invoice, String contactID, String accessToken)
|
||||
throws PluginException {
|
||||
private ZohoInvoice convertToZohoInvoice(ItemCollection invoice, String contactID) throws PluginException {
|
||||
|
||||
ZohoInvoice zohoInvoice = new ZohoInvoice();
|
||||
// Basisinformationen
|
||||
|
|
@ -290,6 +432,65 @@ 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)
|
||||
throws PluginException {
|
||||
|
||||
ZohoBill zohoBill = new ZohoBill();
|
||||
// Basisinformationen
|
||||
|
||||
zohoBill.setInvoiceNumber(invoice.getItemValueString("invoice.number"));
|
||||
zohoBill.setDate(
|
||||
LocalDate.ofInstant(invoice.getItemValueDate("invoice.date").toInstant(), ZoneId.systemDefault()));
|
||||
|
||||
zohoBill.setAmount(invoice.getItemValueDouble("invoice.total"));
|
||||
// Kunden-ID (muss angepasst werden je nachdem wie du sie speicherst)
|
||||
zohoBill.setVendorId(contactID);
|
||||
// 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],
|
||||
// tax=[0], category=[STORAGE], invoice.period=[]}
|
||||
List<ZohoBillItem> lineItems = positionen.stream().map(item -> {
|
||||
ItemCollection itemCol = (ItemCollection) item;
|
||||
ZohoBillItem lineItem = new ZohoBillItem();
|
||||
lineItem.setName(itemCol.getItemValueString("name"));
|
||||
lineItem.setAccountId(accountID);
|
||||
lineItem.setAmount(itemCol.getItemValueDouble("amount"));
|
||||
|
||||
return lineItem;
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
zohoBill.setLineItems(lineItems);
|
||||
return zohoBill;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method adds an attachment to an invoice
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.ApplicationScoped;
|
||||
import jakarta.enterprise.context.ConversationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Named;
|
||||
|
||||
|
|
@ -42,7 +42,8 @@ import jakarta.inject.Named;
|
|||
*
|
||||
*/
|
||||
@Named("zohoController")
|
||||
@ApplicationScoped
|
||||
// @ApplicationScoped
|
||||
@ConversationScoped
|
||||
public class ZohoController extends ConfigController {
|
||||
|
||||
public static final String ZOHO_CONFIGURATION = "ZOHO_CONFIGURATION";
|
||||
|
|
@ -64,7 +65,7 @@ public class ZohoController extends ConfigController {
|
|||
public void updateAccessToken() {
|
||||
//
|
||||
try {
|
||||
zohoOAuthManager.updateTokens(this.getWorkitem().getItemValueString("zoho.code"));
|
||||
zohoOAuthManager.updateTokens(this.getWorkitem());
|
||||
} catch (PluginException e) {
|
||||
String message = "Failed to generate token: " + e.getMessage();
|
||||
logger.warning(message);
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import org.imixs.workflow.engine.WorkflowService;
|
|||
import org.imixs.workflow.exceptions.AdapterException;
|
||||
import org.imixs.workflow.exceptions.PluginException;
|
||||
|
||||
import com.alexanderlogistics.zoho.dto.ZohoBill;
|
||||
import com.alexanderlogistics.zoho.dto.ZohoInvoice;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
|
|
@ -37,6 +38,8 @@ public class ZohoExportAdapter implements SignalAdapter {
|
|||
|
||||
@Inject
|
||||
SnapshotService snapshotService;
|
||||
@Inject
|
||||
ZohoOAuthManager zohoOAuthManager;
|
||||
|
||||
@Inject
|
||||
@ConfigProperty(name = ENV_ZOHO_EXPORT_MAX_ATTACHMENT_SIZE, defaultValue = "10485760")
|
||||
|
|
@ -50,21 +53,82 @@ public class ZohoExportAdapter implements SignalAdapter {
|
|||
@Override
|
||||
public ItemCollection execute(ItemCollection document, ItemCollection event)
|
||||
throws AdapterException, PluginException {
|
||||
logger.info("├── Invoice Export");
|
||||
|
||||
// Load attachments
|
||||
List<FileData> files = null;
|
||||
ItemCollection snapshot = snapshotService.findSnapshot(document);
|
||||
|
||||
if (snapshot != null) {
|
||||
files = snapshot.getFileData();
|
||||
}
|
||||
|
||||
// read the cargosoft export options
|
||||
ItemCollection evalItemCollection = workflowService.evalWorkflowResult(event, "zoho", document, false);
|
||||
|
||||
ZohoInvoice zohoInvoice = zohoAPIService.exportInvoice(document, files);
|
||||
// get access token
|
||||
String accessToken = zohoOAuthManager.getValidAccessToken();
|
||||
|
||||
// Rechnungsausgang
|
||||
if (document.getModelVersion().startsWith("rechnungsausgang-")) {
|
||||
logger.info("├── Invoice Export");
|
||||
exportRechnungsausgang(document, accessToken);
|
||||
}
|
||||
|
||||
// Rechnungseingang
|
||||
if (document.getModelVersion().startsWith("rechnungseingang-")) {
|
||||
logger.info("├── Bill Export");
|
||||
exportRechnungseingang(document, accessToken);
|
||||
}
|
||||
|
||||
return document;
|
||||
}
|
||||
|
||||
/**
|
||||
* Help method, - finds/updates - contact, - export invoice, - change state,
|
||||
* -attache files
|
||||
*
|
||||
* @param document
|
||||
* @param accessToken
|
||||
* @throws PluginException
|
||||
*/
|
||||
private void exportRechnungsausgang(ItemCollection document, String accessToken) throws PluginException {
|
||||
// find companyID
|
||||
String contactID = zohoAPIService.lookupContact(document.getItemValueString("dbtr.name"), "customer",
|
||||
accessToken);
|
||||
|
||||
ZohoInvoice zohoInvoice = zohoAPIService.exportInvoice(document, contactID, accessToken);
|
||||
|
||||
// Attache Files....
|
||||
List<FileData> files = null;
|
||||
ItemCollection snapshot = snapshotService.findSnapshot(document);
|
||||
if (snapshot != null) {
|
||||
files = snapshot.getFileData();
|
||||
if (files != null) {
|
||||
for (FileData file : files) {
|
||||
zohoAPIService.attacheFileData(zohoInvoice.getInvoiceId(), file, "invoices", accessToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Help method, - finds/updates - contact, - export invoice, - change state,
|
||||
* -attache files
|
||||
*
|
||||
* @param document
|
||||
* @param accessToken
|
||||
* @throws PluginException
|
||||
*/
|
||||
private void exportRechnungseingang(ItemCollection document, String accessToken) throws PluginException {
|
||||
// find companyID
|
||||
String contactID = zohoAPIService.lookupContact(document.getItemValueString("cdtr.name"), "vendor",
|
||||
accessToken);
|
||||
|
||||
String accountID = zohoOAuthManager.getAccountId();
|
||||
|
||||
ZohoBill zohoBill = zohoAPIService.exportBill(document, contactID, accountID, accessToken);
|
||||
|
||||
// Attache Files....
|
||||
List<FileData> files = null;
|
||||
ItemCollection snapshot = snapshotService.findSnapshot(document);
|
||||
if (snapshot != null) {
|
||||
files = snapshot.getFileData();
|
||||
if (files != null) {
|
||||
for (FileData file : files) {
|
||||
zohoAPIService.attacheFileData(zohoBill.getBillId(), file, "bills", accessToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -85,6 +85,14 @@ public class ZohoOAuthManager {
|
|||
return null;
|
||||
}
|
||||
|
||||
public String getAccountId() throws PluginException {
|
||||
ItemCollection zohoConfig = configService.loadConfiguration(ZohoController.ZOHO_CONFIGURATION, false);
|
||||
if (zohoConfig != null) {
|
||||
return zohoConfig.getItemValueString("zoho.accountid");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getBaseURI() throws PluginException {
|
||||
String uri = "";
|
||||
ItemCollection zohoConfig = configService.loadConfiguration(ZohoController.ZOHO_CONFIGURATION, false);
|
||||
|
|
@ -109,21 +117,27 @@ public class ZohoOAuthManager {
|
|||
* @throws PluginException
|
||||
*/
|
||||
@Lock(LockType.WRITE)
|
||||
public void updateTokens(String code) throws PluginException {
|
||||
public void updateTokens(ItemCollection zohoConfig) throws PluginException {
|
||||
logger.info("├── update Zoho tokens");
|
||||
try {
|
||||
|
||||
ItemCollection zohoConfig = configService.loadConfiguration(ZohoController.ZOHO_CONFIGURATION, false);
|
||||
String code = zohoConfig.getItemValueString("zoho.code");
|
||||
|
||||
String clientID = zohoConfig.getItemValueString("zoho.clientid");
|
||||
String clientSecret = zohoConfig.getItemValueString("zoho.clientsecret");
|
||||
String requestUrl = "https://accounts.zoho.eu/oauth/v2/token" + "?code="
|
||||
// String requestUrl = zohoConfig.getItemValueString("zoho.oauth.uri") +
|
||||
// "?code="
|
||||
// + URLEncoder.encode(code, StandardCharsets.UTF_8) + "&client_id="
|
||||
// + URLEncoder.encode(clientID, StandardCharsets.UTF_8) + "&client_secret="
|
||||
// + URLEncoder.encode(clientSecret, StandardCharsets.UTF_8) + "&redirect_uri="
|
||||
// + URLEncoder.encode(redirectURI, StandardCharsets.UTF_8) +
|
||||
// "&grant_type=authorization_code";
|
||||
|
||||
String requestUrl = zohoConfig.getItemValueString("zoho.oauth.uri") + "?code="
|
||||
+ URLEncoder.encode(code, StandardCharsets.UTF_8) + "&client_id="
|
||||
+ URLEncoder.encode(clientID, StandardCharsets.UTF_8) + "&client_secret="
|
||||
+ URLEncoder.encode(clientSecret, StandardCharsets.UTF_8) + "&redirect_uri="
|
||||
+ URLEncoder.encode(redirectURI, StandardCharsets.UTF_8) + "&grant_type=authorization_code";
|
||||
+ URLEncoder.encode(clientSecret, StandardCharsets.UTF_8) + "&grant_type=authorization_code";
|
||||
|
||||
logger.fine("│ ├── Request URI=" + requestUrl);
|
||||
logger.info("│ ├── Request URI=" + requestUrl);
|
||||
|
||||
HttpRequest request = HttpRequest.newBuilder().uri(URI.create(requestUrl))
|
||||
.header("Content-Type", "application/x-www-form-urlencoded")
|
||||
|
|
@ -133,10 +147,10 @@ public class ZohoOAuthManager {
|
|||
HttpResponse<String> response;
|
||||
response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
|
||||
logger.fine("│ ├── Response statusCode=" + response.statusCode());
|
||||
logger.info("│ ├── Response statusCode=" + response.statusCode());
|
||||
if (response.statusCode() == 200) {
|
||||
// 1. Response-Logging für Debugging
|
||||
logger.fine("│ ├── Response Body=" + response.body());
|
||||
logger.info("│ ├── Response Body=" + response.body());
|
||||
|
||||
if (response.body().contains("error")) {
|
||||
throw new PluginException(ZohoOAuthManager.class.getSimpleName(), ZohoOAuthManager.ERROR_CONFIG,
|
||||
|
|
@ -172,7 +186,7 @@ public class ZohoOAuthManager {
|
|||
|
||||
String refreshToken = zohoConfig.getItemValueString("zoho.refreshToken");
|
||||
try {
|
||||
String requestUrl = "https://accounts.zoho.eu/oauth/v2/token" + "?refresh_token="
|
||||
String requestUrl = zohoConfig.getItemValueString("zoho.oauth.uri") + "?refresh_token="
|
||||
+ URLEncoder.encode(refreshToken, StandardCharsets.UTF_8) + "&client_id="
|
||||
+ URLEncoder.encode(clientID, StandardCharsets.UTF_8) + "&client_secret="
|
||||
+ URLEncoder.encode(clientSecret, StandardCharsets.UTF_8) + "&grant_type=refresh_token";
|
||||
|
|
@ -218,33 +232,33 @@ public class ZohoOAuthManager {
|
|||
|
||||
String apiDomain = tokenResponse.getApi_domain();
|
||||
if (apiDomain != null && !apiDomain.isEmpty()) {
|
||||
logger.fine("│ ├── apiDomain=" + apiDomain);
|
||||
logger.info("│ ├── apiDomain=" + apiDomain);
|
||||
zohoConfig.setItemValue("zoho.apiDomain", apiDomain);
|
||||
}
|
||||
String scope = tokenResponse.getScope();
|
||||
if (scope != null && !scope.isEmpty()) {
|
||||
logger.fine("│ ├── scope=" + scope);
|
||||
logger.info("│ ├── scope=" + scope);
|
||||
zohoConfig.setItemValue("zoho.scope", scope);
|
||||
}
|
||||
|
||||
String accessToken = tokenResponse.getAccess_token();
|
||||
if (accessToken != null && !accessToken.isEmpty()) {
|
||||
logger.fine("│ ├── accessToken=" + accessToken);
|
||||
logger.info("│ ├── accessToken=" + accessToken);
|
||||
zohoConfig.setItemValue("zoho.accessToken", accessToken);
|
||||
}
|
||||
String refreshToken = tokenResponse.getRefresh_token();
|
||||
if (refreshToken != null && !refreshToken.isEmpty()) {
|
||||
logger.fine("│ ├── refreshToken=" + refreshToken);
|
||||
logger.info("│ ├── refreshToken=" + refreshToken);
|
||||
zohoConfig.setItemValue("zoho.refreshToken", refreshToken);
|
||||
}
|
||||
logger.fine("│ ├── expires_in=" + tokenResponse.getExpires_in());
|
||||
logger.info("│ ├── expires_in=" + tokenResponse.getExpires_in());
|
||||
// Expires-Zeit in Millisekunden berechnen
|
||||
long expiresInSeconds = tokenResponse.getExpires_in() - 60;
|
||||
long currentTimeMillis = System.currentTimeMillis();
|
||||
long expiresTimeMillis = currentTimeMillis + (expiresInSeconds * 1000);
|
||||
// Expires-Zeit in ein Date-Objekt konvertieren
|
||||
Date expiresDate = new Date(expiresTimeMillis);
|
||||
logger.fine("│ ├── expire date=" + expiresDate);
|
||||
logger.info("│ ├── expire date=" + expiresDate);
|
||||
zohoConfig.setItemValue("zoho.expires", expiresDate);
|
||||
zohoConfig.setItemValue("message", "Access Token OK");
|
||||
configService.save(zohoConfig);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,90 @@
|
|||
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 ZohoBill {
|
||||
|
||||
@JsonbProperty("bill_id")
|
||||
private String billId;
|
||||
|
||||
@JsonbProperty("vendor_id")
|
||||
private String vendorId;
|
||||
|
||||
@JsonbDateFormat("yyyy-MM-dd")
|
||||
private LocalDate date;
|
||||
|
||||
@JsonbProperty("due_date")
|
||||
@JsonbDateFormat("yyyy-MM-dd")
|
||||
private LocalDate dueDate;
|
||||
|
||||
@JsonbProperty("bill_number")
|
||||
private String invoiceNumber;
|
||||
|
||||
@JsonbProperty("line_items")
|
||||
private List<ZohoBillItem> lineItems;
|
||||
|
||||
private double amount;
|
||||
|
||||
// Getter und Setter
|
||||
|
||||
public String getBillId() {
|
||||
return billId;
|
||||
}
|
||||
|
||||
public void setBillId(String billId) {
|
||||
this.billId = billId;
|
||||
}
|
||||
|
||||
public String getVendorId() {
|
||||
return vendorId;
|
||||
}
|
||||
|
||||
public void setVendorId(String vendorId) {
|
||||
this.vendorId = vendorId;
|
||||
}
|
||||
|
||||
public LocalDate getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public void setDate(LocalDate date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
public LocalDate getDueDate() {
|
||||
return dueDate;
|
||||
}
|
||||
|
||||
public void setDueDate(LocalDate duedate) {
|
||||
this.dueDate = duedate;
|
||||
}
|
||||
|
||||
public String getInvoiceNumber() {
|
||||
return invoiceNumber;
|
||||
}
|
||||
|
||||
public void setInvoiceNumber(String invoiceNumber) {
|
||||
this.invoiceNumber = invoiceNumber;
|
||||
}
|
||||
|
||||
public List<ZohoBillItem> getLineItems() {
|
||||
return lineItems;
|
||||
}
|
||||
|
||||
public void setLineItems(List<ZohoBillItem> lineItems) {
|
||||
this.lineItems = lineItems;
|
||||
}
|
||||
|
||||
public double getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public void setAmount(double amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
package com.alexanderlogistics.zoho.dto;
|
||||
|
||||
import jakarta.json.bind.annotation.JsonbProperty;
|
||||
|
||||
public class ZohoBillCreateResponse {
|
||||
@JsonbProperty("code")
|
||||
private int code;
|
||||
|
||||
@JsonbProperty("message")
|
||||
private String message;
|
||||
|
||||
@JsonbProperty("bill")
|
||||
private ZohoBill bill;
|
||||
|
||||
// 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 ZohoBill getBill() {
|
||||
return bill;
|
||||
}
|
||||
|
||||
public void setBill(ZohoBill bill) {
|
||||
this.bill = bill;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
package com.alexanderlogistics.zoho.dto;
|
||||
|
||||
import jakarta.json.bind.annotation.JsonbProperty;
|
||||
|
||||
public class ZohoBillItem {
|
||||
private String description;
|
||||
private String name;
|
||||
private double amount;
|
||||
|
||||
@JsonbProperty("account_id")
|
||||
private String accountId;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
// Getter und Setter
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public void setAccountId(String accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
public double getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public void setAmount(double amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -13,6 +13,9 @@ public class ZohoContact {
|
|||
@JsonbProperty("company_name")
|
||||
private String companyName;
|
||||
|
||||
@JsonbProperty("contact_type")
|
||||
private String contactType;
|
||||
|
||||
// Weitere Felder nach Bedarf
|
||||
|
||||
// Getter und Setter
|
||||
|
|
@ -40,4 +43,12 @@ public class ZohoContact {
|
|||
this.companyName = companyName;
|
||||
}
|
||||
|
||||
public String getContactType() {
|
||||
return contactType;
|
||||
}
|
||||
|
||||
public void setContactType(String contactType) {
|
||||
this.contactType = contactType;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,32 +11,42 @@ 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("due_date")
|
||||
@JsonbDateFormat("yyyy-MM-dd")
|
||||
private LocalDate dueDate;
|
||||
|
||||
@JsonbProperty("reference_number")
|
||||
private String invoiceNumber;
|
||||
|
||||
@JsonbProperty("line_items")
|
||||
private List<ZohoInvoiceItem> lineItems;
|
||||
private List<ZohoExpenseItem> lineItems;
|
||||
|
||||
private double total;
|
||||
private double amount;
|
||||
|
||||
// Getter und Setter
|
||||
|
||||
public String getInvoiceId() {
|
||||
return invoiceId;
|
||||
public String getExpenseId() {
|
||||
return expenseId;
|
||||
}
|
||||
|
||||
public void setInvoiceId(String invoiceId) {
|
||||
this.invoiceId = invoiceId;
|
||||
public void setExpenseId(String expenseId) {
|
||||
this.expenseId = expenseId;
|
||||
}
|
||||
|
||||
public String getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public void setAccountId(String accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
public String getCustomerId() {
|
||||
|
|
@ -55,14 +65,6 @@ public class ZohoExpense {
|
|||
this.date = date;
|
||||
}
|
||||
|
||||
public LocalDate getDueDate() {
|
||||
return dueDate;
|
||||
}
|
||||
|
||||
public void setDueDate(LocalDate duedate) {
|
||||
this.dueDate = duedate;
|
||||
}
|
||||
|
||||
public String getInvoiceNumber() {
|
||||
return invoiceNumber;
|
||||
}
|
||||
|
|
@ -71,19 +73,27 @@ public class ZohoExpense {
|
|||
this.invoiceNumber = invoiceNumber;
|
||||
}
|
||||
|
||||
public List<ZohoInvoiceItem> getLineItems() {
|
||||
public List<ZohoExpenseItem> getLineItems() {
|
||||
return lineItems;
|
||||
}
|
||||
|
||||
public void setLineItems(List<ZohoInvoiceItem> lineItems) {
|
||||
public void setLineItems(List<ZohoExpenseItem> lineItems) {
|
||||
this.lineItems = lineItems;
|
||||
}
|
||||
|
||||
public double getTotal() {
|
||||
return total;
|
||||
public double getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public void setTotal(double total) {
|
||||
this.total = total;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -42,12 +42,28 @@
|
|||
<!-- API Tokens -->
|
||||
<div class="imixs-form-section-2">
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>API OAuth URL <span class="imixs-required">*</span>
|
||||
|
||||
</dt>
|
||||
<dd>
|
||||
<h:inputText required="true"
|
||||
value="#{zohoController.workitem.item['zoho.oauth.uri']}">
|
||||
</h:inputText>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>API Base URL <span class="imixs-required">*</span></dt>
|
||||
<dd>
|
||||
<h:inputText required="true"
|
||||
value="#{zohoController.workitem.item['zoho.uri']}">
|
||||
</h:inputText>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
|
@ -60,6 +76,17 @@
|
|||
</h:inputText>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dt>Accountant ID <span class="imixs-required">*</span></dt>
|
||||
<dd>
|
||||
<h:inputText required="true"
|
||||
value="#{zohoController.workitem.item['zoho.accountID']}">
|
||||
</h:inputText>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>Client ID <span class="imixs-required">*</span></dt>
|
||||
<dd>
|
||||
|
|
@ -106,7 +133,7 @@
|
|||
Generieren Sie einen neuen Access Code
|
||||
<br />
|
||||
Scope:
|
||||
<code>ZohoBooks.contacts.ALL,ZohoBooks.invoices.CREATE,ZohoBooks.invoices.READ,ZohoBooks.invoices.UPDATE</code>
|
||||
<code>ZohoBooks.contacts.ALL,ZohoBooks.invoices.ALL,ZohoBooks.bills.ALL</code>
|
||||
</li>
|
||||
<li>
|
||||
Code über den Button "Create" anfordern und in das Feld "Access Code"
|
||||
|
|
|
|||
|
|
@ -42,8 +42,23 @@ public class TestUpdateTokens {
|
|||
|
||||
private String redirectURI = "https://alexander-logistics-dwc.office-workflow.de/api/zoho/grant";
|
||||
|
||||
private String clientID = "1000.GR5FTPZYB06HEWSFSSX4DJU3OBD4EJ";
|
||||
private String clientSecret = "3f3e74c5212bbc924a7ebf77f887c6296db1106c47";
|
||||
// private String clientID = "1000.GR5FTPZYB06HEWSFSSX4DJU3OBD4EJ";
|
||||
// private String clientSecret = "3f3e74c5212bbc924a7ebf77f887c6296db1106c47";
|
||||
|
||||
// forum
|
||||
// private String clientID = "1000.ECQXCXYOTQ9LGLRK2V4PYU94OORJKR";
|
||||
// private String clientSecret = "ce93df3860fc3d804cd015a0bec9b92dcfcf6329b8";
|
||||
|
||||
// DWC
|
||||
// private String clientID = "1000.MQE1SU8UGY6F2PBPASOXGTLWYQD1FS";
|
||||
// private String clientSecret = "1ca70e1ab803b3fed6b1b5e00858c316e2003d289b";
|
||||
|
||||
// Atari
|
||||
private String clientID = "1000.86O4P321HDYDRX0Q0N1G7YOJRJ9D5W";
|
||||
private String clientSecret = "2a67b6cfc364f5df27cc8eb33e9b0e4e8a0221ebc3";
|
||||
|
||||
// ROLES
|
||||
// ZohoBooks.contacts.ALL,ZohoBooks.invoices.ALL,ZohoBooks.bills.ALL
|
||||
|
||||
private String code = null;
|
||||
private String accessToken = null;
|
||||
|
|
@ -67,14 +82,20 @@ public class TestUpdateTokens {
|
|||
logger.info("├── update Zoho tokens");
|
||||
refreshToken = null;
|
||||
accessToken = null;
|
||||
code = "1000.48bd85a3965cf724f4691757cfd8d93b.8ae5e3ee7d70f90d307da4d289a9b067";
|
||||
code = "1000.d2a4e3a9622fc4c5eebe1ae5ee1989b5.d6899d23da56e6d8f73125ebaa498a3e";
|
||||
try {
|
||||
|
||||
String requestUrl = "https://accounts.zoho.eu/oauth/v2/token" + "?code="
|
||||
// String requestUrl = "https://accounts.zoho.eu/oauth/v2/token" + "?code="
|
||||
// + URLEncoder.encode(code, StandardCharsets.UTF_8) + "&client_id="
|
||||
// + URLEncoder.encode(clientID, StandardCharsets.UTF_8) + "&client_secret="
|
||||
// + URLEncoder.encode(clientSecret, StandardCharsets.UTF_8) + "&redirect_uri="
|
||||
// + URLEncoder.encode(redirectURI, StandardCharsets.UTF_8) +
|
||||
// "&grant_type=authorization_code";
|
||||
|
||||
String requestUrl = "https://accounts.zoho.com/oauth/v2/token" + "?code="
|
||||
+ URLEncoder.encode(code, StandardCharsets.UTF_8) + "&client_id="
|
||||
+ URLEncoder.encode(clientID, StandardCharsets.UTF_8) + "&client_secret="
|
||||
+ URLEncoder.encode(clientSecret, StandardCharsets.UTF_8) + "&redirect_uri="
|
||||
+ URLEncoder.encode(redirectURI, StandardCharsets.UTF_8) + "&grant_type=authorization_code";
|
||||
+ URLEncoder.encode(clientSecret, StandardCharsets.UTF_8) + "&grant_type=authorization_code";
|
||||
|
||||
logger.info("│ ├── Request URI=" + requestUrl);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue