office-alexander-logistics/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/api/CargosoftMigrationRestService.java
2025-04-26 13:28:35 +02:00

314 lines
11 KiB
Java

/*******************************************************************************
* Imixs Workflow
* Copyright (C) 2001, 2011 Imixs Software Solutions GmbH,
* http://www.imixs.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You can receive a copy of the GNU General Public
* License at http://www.gnu.org/licenses/gpl.html
*
* Project:
* http://www.imixs.org
* http://java.net/projects/imixs-workflow
*
* Contributors:
* Imixs Software Solutions GmbH - initial API and implementation
* Ralph Soika - Software Developer
*******************************************************************************/
package com.alexanderlogistics.api;
import java.io.Serializable;
import java.util.List;
import java.util.logging.Logger;
import org.imixs.marty.team.TeamService;
import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.engine.DocumentService;
import org.imixs.workflow.engine.WorkflowService;
import org.imixs.workflow.engine.index.UpdateService;
import org.imixs.workflow.exceptions.AccessDeniedException;
import org.imixs.workflow.exceptions.ModelException;
import org.imixs.workflow.exceptions.PluginException;
import org.imixs.workflow.exceptions.ProcessingErrorException;
import org.imixs.workflow.exceptions.QueryException;
import com.alexanderlogistics.BusinessPartnerService;
import com.alexanderlogistics.InvoiceUtil;
import com.alexanderlogistics.mahnlauf.MahnlaufService;
import jakarta.ejb.TransactionAttribute;
import jakarta.ejb.TransactionAttributeType;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.MediaType;
/**
** Dieser Service korrigiert falsch importierte Cargosoft daten.
* Ausgangsrechnungen die ein falsches Jahr haben.
*
* Oder DAten die über die XML Schnittstelle falsch reinkamen...
*
* @author rsoika
* @version 1.1
*/
@ApplicationScoped
@Produces({ MediaType.TEXT_HTML, MediaType.APPLICATION_XHTML_XML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON,
MediaType.TEXT_XML })
@Path("/cargosoft")
public class CargosoftMigrationRestService implements Serializable {
private static final long serialVersionUID = 1L;
String log = "";
int errors = 0;
int count = 0;
boolean isRunning = false;
@Inject
DocumentService documentService;
@Inject
WorkflowService workflowService;
@Inject
MahnlaufService mahnlaufService;
@Inject
UpdateService updateService;
@Inject
TeamService teamService;
@Inject
BusinessPartnerService businessPartnerService;
private static Logger logger = Logger.getLogger(CargosoftMigrationRestService.class.getName());
public CargosoftMigrationRestService() {
super();
}
/**
* Dieser agent prüft ob es für Cargosoft Krediotren/Debitoren Daten schon ein
* passendes Businesspartner Workitem gibt.
* Wenn nicht speichert der Service einmal das cargosft entity was dann zur
* automatischen Neuanlage des businesspartner workflows führt.
*
*
* curl -H "Cookie:
* JSESSIONID=ShAegfNiXmqLFLSFwcUZ7hrLLQDKZGKiu4oj_xeX.imixs-office-workflow-8586d7d58d-h6k4q"
* https://alexander-logistics-dwc.office-workflow.de/api/cargosoft/bp-sync?maxcount=1000
*
* @return
* @throws QueryException
* @throws AccessDeniedException
* @throws ProcessingErrorException
* @throws PluginException
* @throws ModelException
*/
@GET
@Path("/bp-sync")
@Produces({ MediaType.TEXT_PLAIN })
public String syncBusinessPartner(@QueryParam("maxcount") int maxcount)
throws QueryException, AccessDeniedException, ProcessingErrorException, PluginException, ModelException {
StringBuffer messageBuffer = new StringBuffer();
if (maxcount <= 0) {
maxcount = 100;
}
String query = "(type:cargosoftkreditor)";
int syncs = 0;
long l = System.currentTimeMillis();
int batchSize = 100;
int totalObjects = 0;
log("├── sync business partner objects....", messageBuffer);
if (isRunning) {
log("├── sync process already running!", messageBuffer);
return messageBuffer.toString();
}
isRunning = true;
int totalCount = documentService.count(query);
log("│   ├── found " + totalCount + " cargosoft entries",
messageBuffer);
// Berechne Anzahl der benötigten Pages
int totalPages = (int) Math.ceil((double) totalCount / batchSize);
// Verarbeite Page für Page
for (int pageIndex = 0; pageIndex < totalPages; pageIndex++) {
List<ItemCollection> cargosoftDataList = documentService.find(query, batchSize, pageIndex);
for (ItemCollection cargosoftItemCol : cargosoftDataList) {
totalObjects++;
if (syncBusinessPartner(cargosoftItemCol)) {
syncs++;
// Explicit flush the lucene search event log
updateService.updateIndex();
}
if (syncs >= maxcount)
break;
}
// Fortschritt loggen
log("│ ├── Processed page " + (pageIndex + 1) + " of " + totalPages +
" (" + syncs + " total syncs)", messageBuffer);
// Optional: Kurze Pause nach jedem 5. Batch
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (syncs >= maxcount)
break;
}
long duration = System.currentTimeMillis() - l;
double objectsPerSecond = totalObjects / (duration / 1000.0);
log("├── Successfully " + syncs + " business partner objects synced in " +
duration + "ms (" + String.format("%.1f", objectsPerSecond) + " objects/sec)", messageBuffer);
isRunning = false;
return messageBuffer.toString();
}
/**
* Hilfsmethode speichert eine cargoosft kreditor object...
*
* @param bpID
* @param messageBuffer
* @return
*/
@TransactionAttribute(value = TransactionAttributeType.REQUIRES_NEW)
public boolean syncBusinessPartner(ItemCollection cargosoftItemCol) {
String bpip = InvoiceUtil.buildBPID(cargosoftItemCol.getItemValueString("name"));
if (businessPartnerService.getBusinessPartnerByID(bpip) == null) {
// not available so we save just the cargosoft entry once...
documentService.save(cargosoftItemCol);
return true;
}
return false;
}
/**
* Dieser agent löscht einfach alle Businesspartner objekte. Wird eigentlich
* nicht mehr benötigt.
*
* curl -H "Cookie:
* JSESSIONID=ShAegfNiXmqLFLSFwcUZ7hrLLQDKZGKiu4oj_xeX.imixs-office-workflow-8586d7d58d-h6k4q"
* https://alexander-logistics-dwc.office-workflow.de/api/cargosoft/bp-delete?maxcount=10000
*
* @return
* @throws QueryException
* @throws AccessDeniedException
* @throws ProcessingErrorException
* @throws PluginException
* @throws ModelException
*/
@GET
@Path("/bp-delete")
@Produces({ MediaType.TEXT_PLAIN })
public String deleteBusinessPartner(@QueryParam("maxcount") int maxcount)
throws QueryException, AccessDeniedException, ProcessingErrorException, PluginException, ModelException {
StringBuffer messageBuffer = new StringBuffer();
String query = "(type:workitem*) AND ($modelversion: businesspartner*)";
int deletions = 0;
long l = System.currentTimeMillis();
int batchSize = 100;
int totalObjects = 0;
log("├── delete old business partner objects....", messageBuffer);
if (isRunning) {
log("├── sync process already running!", messageBuffer);
return messageBuffer.toString();
}
isRunning = true;
log("│   ├── maxcount= " + maxcount, messageBuffer);
int totalCount = documentService.count(query);
log("│   ├── found " + totalCount + " entities ", messageBuffer);
// Berechne Anzahl der benötigten Pages
int totalPages = (int) Math.ceil((double) totalCount / batchSize);
// Verarbeite Page für Page
int iterations = 0;
while (deletions < maxcount) {
List<ItemCollection> cargosoftDataList = documentService.find(query, batchSize, 0);
if (cargosoftDataList.size() == 0) {
break;
}
for (ItemCollection cargosoftItemCol : cargosoftDataList) {
totalObjects++;
if (deleteBusinessPartner(cargosoftItemCol, messageBuffer)) {
deletions++;
}
if (deletions >= maxcount)
break;
}
// Explicit flush the lucene search event log
updateService.updateIndex();
// Fortschritt loggen
iterations++;
log("│ ├── Processed page " + (iterations) + " of " + totalPages +
" (" + deletions + " total deletions)", messageBuffer);
// Optional: Kurze Pause nach jedem 5. Batch
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (deletions >= maxcount)
break;
}
long duration = System.currentTimeMillis() - l;
double objectsPerSecond = totalObjects / (duration / 1000.0);
log("├── Successfully " + deletions + " business partner objects deleted in " +
duration + "ms (" + String.format("%.1f", objectsPerSecond) + " objects/sec)", messageBuffer);
isRunning = false;
return messageBuffer.toString();
}
/**
* Hilfsmethode - löscht ein cargoosoft object...
*
* @param bpID
* @param messageBuffer
* @return
*/
@TransactionAttribute(value = TransactionAttributeType.REQUIRES_NEW)
public boolean deleteBusinessPartner(ItemCollection cargosoftItemCol, StringBuffer messageBuffer) {
documentService.remove(cargosoftItemCol);
return true;
}
private void log(String message, StringBuffer messageLog) {
logger.info(message);
messageLog.append(message + "\n");
}
}