zoho invoice export - draft
This commit is contained in:
parent
39099700fe
commit
27f7b2b4f6
7 changed files with 2430 additions and 45 deletions
|
|
@ -1,17 +1,34 @@
|
||||||
package com.alexanderlogistics.zoho;
|
package com.alexanderlogistics.zoho;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.http.HttpClient;
|
||||||
|
import java.net.http.HttpRequest;
|
||||||
|
import java.net.http.HttpResponse;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
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 jakarta.annotation.PostConstruct;
|
||||||
import jakarta.annotation.security.DeclareRoles;
|
import jakarta.annotation.security.DeclareRoles;
|
||||||
import jakarta.annotation.security.RolesAllowed;
|
import jakarta.annotation.security.RolesAllowed;
|
||||||
import jakarta.annotation.security.RunAs;
|
import jakarta.annotation.security.RunAs;
|
||||||
import jakarta.ejb.Lock;
|
|
||||||
import jakarta.ejb.LockType;
|
|
||||||
import jakarta.ejb.Singleton;
|
import jakarta.ejb.Singleton;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import jakarta.json.bind.Jsonb;
|
||||||
|
import jakarta.json.bind.JsonbBuilder;
|
||||||
|
import jakarta.json.bind.JsonbConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Der ZohoAPIService stellt methoden für den Zugriff auf die Zoho API bereit.
|
* Der ZohoAPIService stellt methoden für den Zugriff auf die Zoho API bereit.
|
||||||
* Er handelt auch die Authentifizeirung über einen Access Token. Der
|
|
||||||
* ZohoOAuhtGrantService der dazu dient einen AccessCode von Zoho zu ermitteln
|
|
||||||
* übergibt den code an diesesn Servcie. Er dietn also als Singelton
|
|
||||||
*/
|
*/
|
||||||
@DeclareRoles({ "org.imixs.ACCESSLEVEL.NOACCESS", "org.imixs.ACCESSLEVEL.READERACCESS",
|
@DeclareRoles({ "org.imixs.ACCESSLEVEL.NOACCESS", "org.imixs.ACCESSLEVEL.READERACCESS",
|
||||||
"org.imixs.ACCESSLEVEL.AUTHORACCESS", "org.imixs.ACCESSLEVEL.EDITORACCESS",
|
"org.imixs.ACCESSLEVEL.AUTHORACCESS", "org.imixs.ACCESSLEVEL.EDITORACCESS",
|
||||||
|
|
@ -23,18 +40,116 @@ import jakarta.ejb.Singleton;
|
||||||
@RunAs("org.imixs.ACCESSLEVEL.MANAGERACCESS")
|
@RunAs("org.imixs.ACCESSLEVEL.MANAGERACCESS")
|
||||||
public class ZohoAPIService {
|
public class ZohoAPIService {
|
||||||
|
|
||||||
private String accessToken;
|
private static Logger logger = Logger.getLogger(ZohoAPIService.class.getName());
|
||||||
private String clientID;
|
private static final String ZOHO_API_BASE_URL = "https://www.zohoapis.eu/books/v3/";
|
||||||
private String clientSecret;
|
|
||||||
|
@Inject
|
||||||
|
ZohoOAuthManager zohoOAuthManager;
|
||||||
|
|
||||||
|
private HttpClient httpClient;
|
||||||
|
private Jsonb jsonb;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
void init() {
|
||||||
|
this.httpClient = HttpClient.newBuilder()
|
||||||
|
.connectTimeout(Duration.ofSeconds(10))
|
||||||
|
.build();
|
||||||
|
// this.jsonb = JsonbBuilder.create();
|
||||||
|
this.jsonb = JsonbBuilder.create(new JsonbConfig()
|
||||||
|
.withDateFormat("yyyy-MM-dd", Locale.getDefault()));
|
||||||
|
|
||||||
@Lock(LockType.WRITE) // Standardmäßig ist @Lock(LockType.READ)
|
|
||||||
public void setAccessToken(String token) {
|
|
||||||
this.accessToken = token;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Lock(LockType.READ) // Erlaubt parallele Lesezugriffe
|
/**
|
||||||
public String getAccessToken() {
|
* Exports an invocie document
|
||||||
return accessToken;
|
*
|
||||||
|
* @see https://www.zoho.com/books/api/v3/invoices/#create-an-invoice
|
||||||
|
*
|
||||||
|
* @param invoice
|
||||||
|
* @throws PluginException
|
||||||
|
*/
|
||||||
|
public void exportInvoice(ItemCollection invoice) throws PluginException {
|
||||||
|
String accessToken = zohoOAuthManager.getValidAccessToken();
|
||||||
|
|
||||||
|
// Konvertiere ItemCollection zu ZohoInvoiceDTO
|
||||||
|
ZohoInvoiceDTO zohoInvoice = convertToZohoInvoice(invoice);
|
||||||
|
|
||||||
|
try {
|
||||||
|
String requestBody = jsonb.toJson(zohoInvoice);
|
||||||
|
|
||||||
|
// Print JSON to console for verification
|
||||||
|
logger.info("├── Zoho Invoice JSON Request...");
|
||||||
|
logger.info("│ ├── " + requestBody);
|
||||||
|
|
||||||
|
// https://www.zohoapis.com/books/v3/invoices?organization_id=10234695'
|
||||||
|
String uri = ZOHO_API_BASE_URL + "invoices?organization_id=" + zohoOAuthManager.getOrganization();
|
||||||
|
logger.info("│ ├── uri= " + uri);
|
||||||
|
logger.info("│ ├── 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.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 create invoice. Status code: " + response.statusCode() +
|
||||||
|
", Response: " + response.body());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Erfolgreiche Verarbeitung hier
|
||||||
|
// Optional: Response auswerten
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new PluginException(this.getClass().getName(), "Zoho API error",
|
||||||
|
"Failed to export invoice to Zoho", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ZohoInvoiceDTO convertToZohoInvoice(ItemCollection invoice) {
|
||||||
|
ZohoInvoiceDTO zohoInvoice = new ZohoInvoiceDTO();
|
||||||
|
|
||||||
|
// Basisinformationen
|
||||||
|
// zohoInvoice.setInvoiceNumber(invoice.getItemValueString("invoice.number"));
|
||||||
|
|
||||||
|
logger.info("invoice.date=" + invoice.getItemValueDate("invoice.date"));
|
||||||
|
logger.info("invoice.duedate=" + invoice.getItemValueDate("invoice.duedate"));
|
||||||
|
|
||||||
|
zohoInvoice.setDate(invoice.getItemValueDate("invoice.date"));
|
||||||
|
zohoInvoice.setDueDate(invoice.getItemValueDate("invoice.duedate"));
|
||||||
|
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");
|
||||||
|
|
||||||
|
// Positionen (muss angepasst werden je nach Datenstruktur)
|
||||||
|
// List<ZohoInvoiceItemDTO> lineItems = new ArrayList<>();
|
||||||
|
List<ItemCollection> positionen = InvoiceUtil.explodeChildList(invoice);
|
||||||
|
|
||||||
|
List<ZohoInvoiceItemDTO> lineItems = positionen.stream()
|
||||||
|
.map(item -> {
|
||||||
|
ItemCollection itemCol = (ItemCollection) item;
|
||||||
|
ZohoInvoiceItemDTO lineItem = new ZohoInvoiceItemDTO();
|
||||||
|
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());
|
||||||
|
|
||||||
|
zohoInvoice.setLineItems(lineItems);
|
||||||
|
|
||||||
|
return zohoInvoice;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,130 @@
|
||||||
|
package com.alexanderlogistics.zoho;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||||
|
import org.imixs.archive.core.SnapshotService;
|
||||||
|
import org.imixs.workflow.FileData;
|
||||||
|
import org.imixs.workflow.ItemCollection;
|
||||||
|
import org.imixs.workflow.SignalAdapter;
|
||||||
|
import org.imixs.workflow.engine.WorkflowService;
|
||||||
|
import org.imixs.workflow.exceptions.AdapterException;
|
||||||
|
import org.imixs.workflow.exceptions.PluginException;
|
||||||
|
|
||||||
|
import com.alexanderlogistics.InvoicePlugin;
|
||||||
|
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This adapter exports the invoice data to zoho
|
||||||
|
*
|
||||||
|
* @version 1.0
|
||||||
|
* @author rsoika
|
||||||
|
*/
|
||||||
|
public class ZohoExportAdapter implements SignalAdapter {
|
||||||
|
|
||||||
|
public static final String CONFIG_ERROR = "CONFIG_ERROR";
|
||||||
|
public static final String ENV_ZOHO_EXPORT_MAX_ATTACHMENT_SIZE = "zoho.export.maxattachmentsize";
|
||||||
|
|
||||||
|
private static Logger logger = Logger.getLogger(ZohoExportAdapter.class.getName());
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ZohoAPIService zohoAPIService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
WorkflowService workflowService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
SnapshotService snapshotService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
@ConfigProperty(name = ENV_ZOHO_EXPORT_MAX_ATTACHMENT_SIZE, defaultValue = "10485760")
|
||||||
|
long maxAttachmentSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method calls the zoho api
|
||||||
|
*
|
||||||
|
* @throws PluginException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ItemCollection execute(ItemCollection document, ItemCollection event)
|
||||||
|
throws AdapterException, PluginException {
|
||||||
|
|
||||||
|
logger.info("......starting export...");
|
||||||
|
|
||||||
|
// read the cargosoft export options
|
||||||
|
ItemCollection evalItemCollection = workflowService.evalWorkflowResult(event, "zoho", document, false);
|
||||||
|
|
||||||
|
zohoAPIService.exportInvoice(document);
|
||||||
|
return document;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method lookups the origin snapshot data and add the content of the $file
|
||||||
|
* to the export document
|
||||||
|
* <p>
|
||||||
|
* Change 14.10.2021 - Wir senden maximal 5MB and Daten, da die Cargosoft
|
||||||
|
* Schnittstelle größere Datensätze mit großen Dateianhängen einfach verschluckt
|
||||||
|
* ohne eine Fehlermeldugn zu liefern.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param document
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private ItemCollection loadFileDataFromSnapshot(ItemCollection document) {
|
||||||
|
ItemCollection origin = null;
|
||||||
|
ItemCollection result = (ItemCollection) document.clone();
|
||||||
|
|
||||||
|
// find the origin document
|
||||||
|
List<String> refs = document.getItemValue(WorkflowService.UNIQUEIDREF);
|
||||||
|
for (String ref : refs) {
|
||||||
|
origin = workflowService.getWorkItem(ref);
|
||||||
|
// "Rechnungseingang".equals(origin.getWorkflowGroup())
|
||||||
|
if (InvoicePlugin.isCargoRechnung(origin)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
origin = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we should have found the origin...
|
||||||
|
if (origin != null) {
|
||||||
|
ItemCollection snapshot = snapshotService.findSnapshot(origin);
|
||||||
|
// we should have found a snapshot...
|
||||||
|
if (snapshot != null) {
|
||||||
|
List<FileData> fileDataList = snapshot.getFileData();
|
||||||
|
// transfer origin file content
|
||||||
|
result.removeItem("$file");
|
||||||
|
long currentAttachmentSize = 0;
|
||||||
|
// we do only accept .pdf files and a maximum size of 10MB
|
||||||
|
for (FileData filedata : fileDataList) {
|
||||||
|
if (filedata.getName().toLowerCase().endsWith(".pdf")) {
|
||||||
|
// test if the size of the file is below the
|
||||||
|
// "cargosoft.export.ftp.maxattachmentsize"
|
||||||
|
if ((currentAttachmentSize + filedata.getContent().length) > maxAttachmentSize) {
|
||||||
|
long maxSizeInMB = maxAttachmentSize / 1024 / 1024;
|
||||||
|
String message = "Attachment '" + filedata.getName()
|
||||||
|
+ "' can not be exported to cargosoft - max file size exeeded (" + maxSizeInMB
|
||||||
|
+ "MB)!";
|
||||||
|
logger.warning(message);
|
||||||
|
// add comment
|
||||||
|
document.setItemValue("txtComment", message);
|
||||||
|
} else {
|
||||||
|
result.addFileData(filedata);
|
||||||
|
currentAttachmentSize = currentAttachmentSize + filedata.getContent().length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.warning("...did not found snapshot for origin workitem " + origin.getUniqueID());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.warning("...did not found origin workitem " + document.getUniqueID());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -48,9 +48,12 @@ import jakarta.ws.rs.core.MediaType;
|
||||||
*
|
*
|
||||||
* https://www.zoho.com/books/api/v3/oauth/
|
* https://www.zoho.com/books/api/v3/oauth/
|
||||||
*
|
*
|
||||||
* Er dient als redirect URL wenn jemand einen solchen Token über den Browser
|
* Der Service wird aktuell nicht benötigt, das wir sogenannte Zoho Self-Clients
|
||||||
* anfordert.
|
* verwenden!
|
||||||
* Der URL muss hier als CallBack URL angegeben sein!
|
*
|
||||||
|
* Der Service stellt im Grunde nur eine Callback URL für einen normalen Zoho
|
||||||
|
* Client ein. Also wenn jemand einen solchen Token über den Browser
|
||||||
|
* anfordert. Der URL muss dann odrt als CallBack URL angegeben sein!
|
||||||
*
|
*
|
||||||
* Beispiel:
|
* Beispiel:
|
||||||
*
|
*
|
||||||
|
|
@ -60,9 +63,10 @@ import jakarta.ws.rs.core.MediaType;
|
||||||
* @author rsoika
|
* @author rsoika
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
@Path("/zoho")
|
@Path("/zoho")
|
||||||
@Stateless
|
@Stateless
|
||||||
public class ZohoOAuthGrantService {
|
public class ZohoOAuthCallbackService {
|
||||||
|
|
||||||
@Context
|
@Context
|
||||||
private HttpServletRequest servletRequest;
|
private HttpServletRequest servletRequest;
|
||||||
|
|
@ -70,7 +74,7 @@ public class ZohoOAuthGrantService {
|
||||||
@EJB
|
@EJB
|
||||||
ZohoOAuthManager zohoOAuthManager;
|
ZohoOAuthManager zohoOAuthManager;
|
||||||
|
|
||||||
private static Logger logger = Logger.getLogger(ZohoOAuthGrantService.class.getName());
|
private static Logger logger = Logger.getLogger(ZohoOAuthCallbackService.class.getName());
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("/ping")
|
@Path("/ping")
|
||||||
|
|
@ -117,8 +121,6 @@ public class ZohoOAuthGrantService {
|
||||||
logger.info("│ ├── location=" + location);
|
logger.info("│ ├── location=" + location);
|
||||||
logger.info("│ ├── accounts-server=" + accountsServer);
|
logger.info("│ ├── accounts-server=" + accountsServer);
|
||||||
|
|
||||||
// zohoOAuthManager.updateTokens(code);
|
|
||||||
|
|
||||||
return "Zoho Callback received!";
|
return "Zoho Callback received!";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -35,12 +35,8 @@ import jakarta.json.bind.JsonbBuilder;
|
||||||
public class ZohoOAuthManager {
|
public class ZohoOAuthManager {
|
||||||
|
|
||||||
private static Logger logger = Logger.getLogger(ZohoOAuthManager.class.getName());
|
private static Logger logger = Logger.getLogger(ZohoOAuthManager.class.getName());
|
||||||
|
|
||||||
private String refreshToken;
|
|
||||||
private String accessToken;
|
|
||||||
private long accessTokenExpiry; // Timestamp (System.currentTimeMillis() + expires_in*1000)
|
|
||||||
|
|
||||||
private String redirectURI = "https://alexander-logistics-dwc.office-workflow.de/api/zoho/grant";
|
private String redirectURI = "https://alexander-logistics-dwc.office-workflow.de/api/zoho/grant";
|
||||||
|
|
||||||
public static final String ERROR_CONFIG = "CONFIG_ERROR";
|
public static final String ERROR_CONFIG = "CONFIG_ERROR";
|
||||||
|
|
||||||
@EJB
|
@EJB
|
||||||
|
|
@ -57,11 +53,40 @@ public class ZohoOAuthManager {
|
||||||
this.jsonb = JsonbBuilder.create();
|
this.jsonb = JsonbBuilder.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gibt den aktuellen Access Token zurück. Falls dieser expired ist wird
|
||||||
|
* automatisch ein refresh durchgeführt. Somit liefert die Methode immer einen
|
||||||
|
* gültigen token.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* @throws PluginException
|
||||||
|
*/
|
||||||
@Lock(LockType.READ)
|
@Lock(LockType.READ)
|
||||||
public String getValidAccessToken() {
|
public String getValidAccessToken() throws PluginException {
|
||||||
|
logger.info("├── get Zoho AccessTokens");
|
||||||
|
ItemCollection zohoConfig = configService.loadConfiguration(ZohoController.ZOHO_CONFIGURATION, false);
|
||||||
|
String accessToken = zohoConfig.getItemValueString("zoho.accessToken");
|
||||||
|
logger.fine("│ ├── accessToken=" + accessToken);
|
||||||
|
logger.fine("│ ├── refresh=" + zohoConfig.getItemValueString("zoho.refreshToken"));
|
||||||
|
logger.fine("│ ├── expires_in=" + zohoConfig.getItemValueDate("zoho.expires"));
|
||||||
|
|
||||||
|
Date expireDate = zohoConfig.getItemValueDate("zoho.expires");
|
||||||
|
if (expireDate.getTime() < System.currentTimeMillis()) {
|
||||||
|
logger.info("│ ├── Access Token expired (" + expireDate + ")");
|
||||||
|
accessToken = refreshAccessToken();
|
||||||
|
}
|
||||||
|
|
||||||
return accessToken;
|
return accessToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getOrganization() throws PluginException {
|
||||||
|
ItemCollection zohoConfig = configService.loadConfiguration(ZohoController.ZOHO_CONFIGURATION, false);
|
||||||
|
if (zohoConfig != null) {
|
||||||
|
return zohoConfig.getItemValueString("zoho.organization");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Step 3: Generate Access and Refresh Token
|
* Step 3: Generate Access and Refresh Token
|
||||||
*
|
*
|
||||||
|
|
@ -75,14 +100,10 @@ public class ZohoOAuthManager {
|
||||||
*/
|
*/
|
||||||
@Lock(LockType.WRITE)
|
@Lock(LockType.WRITE)
|
||||||
public void updateTokens(String code) throws PluginException {
|
public void updateTokens(String code) throws PluginException {
|
||||||
|
|
||||||
logger.info("├── update Zoho tokens");
|
logger.info("├── update Zoho tokens");
|
||||||
refreshToken = null;
|
|
||||||
accessToken = null;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
ItemCollection zohoConfig = configService.loadConfiguration(ZohoController.ZOHO_CONFIGURATION);
|
ItemCollection zohoConfig = configService.loadConfiguration(ZohoController.ZOHO_CONFIGURATION, false);
|
||||||
|
|
||||||
String clientID = zohoConfig.getItemValueString("zoho.clientid");
|
String clientID = zohoConfig.getItemValueString("zoho.clientid");
|
||||||
String clientSecret = zohoConfig.getItemValueString("zoho.clientsecret");
|
String clientSecret = zohoConfig.getItemValueString("zoho.clientsecret");
|
||||||
|
|
@ -138,18 +159,15 @@ public class ZohoOAuthManager {
|
||||||
* @throws PluginException
|
* @throws PluginException
|
||||||
*/
|
*/
|
||||||
@Lock(LockType.WRITE)
|
@Lock(LockType.WRITE)
|
||||||
public void refreshAccessToken() throws PluginException {
|
public String refreshAccessToken() throws PluginException {
|
||||||
|
|
||||||
logger.info("├── refresh Zoho access token");
|
logger.info("├── refresh Zoho access token");
|
||||||
|
ItemCollection zohoConfig = configService.loadConfiguration(ZohoController.ZOHO_CONFIGURATION, false);
|
||||||
ItemCollection zohoConfig = configService.loadConfiguration(ZohoController.ZOHO_CONFIGURATION);
|
|
||||||
|
|
||||||
String clientID = zohoConfig.getItemValueString("zoho.clientid");
|
String clientID = zohoConfig.getItemValueString("zoho.clientid");
|
||||||
String clientSecret = zohoConfig.getItemValueString("zoho.clientsecret");
|
String clientSecret = zohoConfig.getItemValueString("zoho.clientsecret");
|
||||||
|
|
||||||
refreshToken = zohoConfig.getItemValueString("zoho.refreshToken");
|
String refreshToken = zohoConfig.getItemValueString("zoho.refreshToken");
|
||||||
try {
|
try {
|
||||||
|
|
||||||
String requestUrl = "https://accounts.zoho.eu/oauth/v2/token" +
|
String requestUrl = "https://accounts.zoho.eu/oauth/v2/token" +
|
||||||
"?refresh_token=" + URLEncoder.encode(refreshToken, StandardCharsets.UTF_8) +
|
"?refresh_token=" + URLEncoder.encode(refreshToken, StandardCharsets.UTF_8) +
|
||||||
"&client_id=" + URLEncoder.encode(clientID, StandardCharsets.UTF_8) +
|
"&client_id=" + URLEncoder.encode(clientID, StandardCharsets.UTF_8) +
|
||||||
|
|
@ -179,12 +197,9 @@ public class ZohoOAuthManager {
|
||||||
|
|
||||||
TokenResponse tokenResponse = jsonb.fromJson(response.body(),
|
TokenResponse tokenResponse = jsonb.fromJson(response.body(),
|
||||||
TokenResponse.class);
|
TokenResponse.class);
|
||||||
|
|
||||||
saveTokenData(zohoConfig, tokenResponse);
|
saveTokenData(zohoConfig, tokenResponse);
|
||||||
|
return zohoConfig.getItemValueString("zoho.accessToken");
|
||||||
|
|
||||||
// String accessToken = tokenResponse.getAccess_token();
|
|
||||||
// logger.info("│ ├── accessToken=" + accessToken);
|
|
||||||
// logger.info("│ ├── expires_in=" + tokenResponse.getExpires_in());
|
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("Failed to get tokens: " +
|
throw new RuntimeException("Failed to get tokens: " +
|
||||||
response.statusCode() + " - " + response.body());
|
response.statusCode() + " - " + response.body());
|
||||||
|
|
@ -194,7 +209,6 @@ public class ZohoOAuthManager {
|
||||||
throw new PluginException(ZohoOAuthManager.class.getSimpleName(),
|
throw new PluginException(ZohoOAuthManager.class.getSimpleName(),
|
||||||
ZohoOAuthManager.ERROR_CONFIG, "Unable to refresh access tokens: " + e.getMessage());
|
ZohoOAuthManager.ERROR_CONFIG, "Unable to refresh access tokens: " + e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -216,12 +230,12 @@ public class ZohoOAuthManager {
|
||||||
zohoConfig.setItemValue("zoho.scope", scope);
|
zohoConfig.setItemValue("zoho.scope", scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
accessToken = tokenResponse.getAccess_token();
|
String accessToken = tokenResponse.getAccess_token();
|
||||||
if (accessToken != null && !accessToken.isEmpty()) {
|
if (accessToken != null && !accessToken.isEmpty()) {
|
||||||
logger.info("│ ├── accessToken=" + accessToken);
|
logger.info("│ ├── accessToken=" + accessToken);
|
||||||
zohoConfig.setItemValue("zoho.accessToken", accessToken);
|
zohoConfig.setItemValue("zoho.accessToken", accessToken);
|
||||||
}
|
}
|
||||||
refreshToken = tokenResponse.getRefresh_token();
|
String refreshToken = tokenResponse.getRefresh_token();
|
||||||
if (refreshToken != null && !refreshToken.isEmpty()) {
|
if (refreshToken != null && !refreshToken.isEmpty()) {
|
||||||
logger.info("│ ├── refreshToken=" + refreshToken);
|
logger.info("│ ├── refreshToken=" + refreshToken);
|
||||||
zohoConfig.setItemValue("zoho.refreshToken", refreshToken);
|
zohoConfig.setItemValue("zoho.refreshToken", refreshToken);
|
||||||
|
|
@ -233,6 +247,7 @@ public class ZohoOAuthManager {
|
||||||
long expiresTimeMillis = currentTimeMillis + (expiresInSeconds * 1000);
|
long expiresTimeMillis = currentTimeMillis + (expiresInSeconds * 1000);
|
||||||
// Expires-Zeit in ein Date-Objekt konvertieren
|
// Expires-Zeit in ein Date-Objekt konvertieren
|
||||||
Date expiresDate = new Date(expiresTimeMillis);
|
Date expiresDate = new Date(expiresTimeMillis);
|
||||||
|
logger.info("│ ├── expire date=" + expiresDate);
|
||||||
zohoConfig.setItemValue("zoho.expires", expiresDate);
|
zohoConfig.setItemValue("zoho.expires", expiresDate);
|
||||||
zohoConfig.setItemValue("message", "Access Token OK");
|
zohoConfig.setItemValue("message", "Access Token OK");
|
||||||
configService.save(zohoConfig);
|
configService.save(zohoConfig);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
package com.alexanderlogistics.zoho.dto;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import jakarta.json.bind.annotation.JsonbProperty;
|
||||||
|
|
||||||
|
public class ZohoInvoiceDTO {
|
||||||
|
|
||||||
|
private String customerId;
|
||||||
|
private Date date;
|
||||||
|
private Date dueDate;
|
||||||
|
private String invoiceNumber;
|
||||||
|
private List<ZohoInvoiceItemDTO> lineItems;
|
||||||
|
private double total;
|
||||||
|
|
||||||
|
// Getter und Setter
|
||||||
|
|
||||||
|
@JsonbProperty("customer_id")
|
||||||
|
public String getCustomerId() {
|
||||||
|
return customerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCustomerId(String customerId) {
|
||||||
|
this.customerId = customerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getDate() {
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDate(Date date) {
|
||||||
|
this.date = date;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonbProperty("due_date")
|
||||||
|
public Date getDueDate() {
|
||||||
|
return dueDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDueDate(Date duedate) {
|
||||||
|
this.dueDate = duedate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonbProperty("invoice_number")
|
||||||
|
public String getInvoiceNumber() {
|
||||||
|
return invoiceNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInvoiceNumber(String invoiceNumber) {
|
||||||
|
this.invoiceNumber = invoiceNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonbProperty("line_items")
|
||||||
|
public List<ZohoInvoiceItemDTO> getLineItems() {
|
||||||
|
return lineItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLineItems(List<ZohoInvoiceItemDTO> lineItems) {
|
||||||
|
this.lineItems = lineItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getTotal() {
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTotal(double total) {
|
||||||
|
this.total = total;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
package com.alexanderlogistics.zoho.dto;
|
||||||
|
|
||||||
|
public class ZohoInvoiceItemDTO {
|
||||||
|
private String name;
|
||||||
|
private String description;
|
||||||
|
private double rate;
|
||||||
|
private int quantity;
|
||||||
|
|
||||||
|
// Getter und Setter
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getRate() {
|
||||||
|
return rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRate(double rate) {
|
||||||
|
this.rate = rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getQuantity() {
|
||||||
|
return quantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setQuantity(int quantity) {
|
||||||
|
this.quantity = quantity;
|
||||||
|
}
|
||||||
|
}
|
||||||
2011
workflow/dwc/rechnungsausgang-dwc-1.0.3-draft.bpmn
Normal file
2011
workflow/dwc/rechnungsausgang-dwc-1.0.3-draft.bpmn
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue