office-alexander-logistics/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/metrics/MetricDebitorRestService.java
2025-02-06 15:44:33 +01:00

180 lines
6.4 KiB
Java

package com.alexanderlogistics.metrics;
import java.util.List;
import java.util.logging.Logger;
import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.engine.DocumentService;
import org.imixs.workflow.exceptions.PluginException;
import org.imixs.workflow.exceptions.QueryException;
import com.alexanderlogistics.InvoiceUtil;
import jakarta.ejb.Stateless;
import jakarta.ejb.TransactionAttribute;
import jakarta.ejb.TransactionAttributeType;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
@Path("metrics/dbtr")
@Stateless
public class MetricDebitorRestService {
private static Logger logger = Logger.getLogger(MetricDebitorRestService.class.getName());
@Inject
DocumentService documentService;
@Inject
MetricDebitorService metricDebitorService;
@Inject
MetricDataService metricDataService;
@GET
@Path("/ping")
@Produces({ MediaType.TEXT_PLAIN })
public String ping() {
logger.info("GET ping");
return "ping: " + System.currentTimeMillis();
}
/**
* This method initializes the metrics for all debitors with open invoices.
*
* The method first deletes all existing metrics and than creates or updates the
* metric entires for each debitor.
*
* @return
*/
@GET
@Path("/rebuild")
@Produces({ MediaType.TEXT_PLAIN })
public Response rebuildMetrics() {
StringBuffer messageBuffer = new StringBuffer();
long l = System.currentTimeMillis();
log("├── rebuild dbtr metrics...", messageBuffer);
try {
log("│   ├── delete all metrics", messageBuffer);
// first clear the metric cache
metricDebitorService.reset();
log("│   ├── reset metric cache", messageBuffer);
computeMetrics(messageBuffer);
String message = "├── rebuild dbtr metrics completed in "
+ (System.currentTimeMillis() - l)
+ "ms";
log(message, messageBuffer);
return Response.ok().entity(messageBuffer.toString()).build();
} catch (Exception e) {
e.printStackTrace();
log("Failed to initialize metrics: " + e.getMessage(), messageBuffer);
return Response.serverError()
.entity(messageBuffer.toString() + e.getMessage())
.build();
}
}
/**
* Diese Methode berechnet alle Metriken auf basis der existierenden Rechnungen
* neu
*
* @throws QueryException
* @throws InterruptedException
* @throws PluginException
*
*/
public void computeMetrics(StringBuffer messageBuffer)
throws QueryException, InterruptedException, PluginException {
long l = System.currentTimeMillis();
int batchSize = 500;
int totalInvoices = 0;
log("│   │   ├── recalculate metrics...", messageBuffer);
String query = "$modelversion:rechnungsausgang-* AND type:workitem";
// Gesamtanzahl ermitteln
int totalCount = documentService.count(query);
log("│   │   ├── found " + totalCount + " open invoices", 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++) {
totalInvoices = totalInvoices + computeInvoiceMetrics(query, batchSize, pageIndex);
// List<ItemCollection> invoices = documentService.find(query, batchSize,
// pageIndex);
// for (ItemCollection invoice : invoices) {
// try {
// ItemCollection metricData = metricDebitorService.getMetricByInvoice(invoice);
// // Jetzt Rechnung addieren
// metricDebitorService.addInvoice(metricData, invoice);
// logger.fine("│   │   │   ├── update metric " + InvoiceUtil.getBPId(invoice));
// metricDebitorService.updateMetric(metricData, true);
// totalInvoices++;
// } catch (PluginException e) {
// // invalid invoice - e.g. no dbtr. number
// }
// }
// Fortschritt loggen
log("│   │ ├── Processed page " + (pageIndex + 1) + " of " + totalPages +
" (" + totalInvoices + " of " + totalCount + " invoices)", messageBuffer);
// Optional: Kurze Pause nach jedem 5. Batch
Thread.sleep(100);
}
long duration = System.currentTimeMillis() - l;
double invoicesPerSecond = totalInvoices / (duration / 1000.0);
log("│   │   ├── Successfully processed " + totalInvoices + " invoices in " +
duration + "ms (" + String.format("%.1f", invoicesPerSecond) + " invoices/sec)", messageBuffer);
log("│   │   ├── Updated " + metricDebitorService.getMetricCount() + " metrics.", messageBuffer);
}
/**
* Helper method runs in new transaction
*
* @param query
* @param batchSize
* @param pageIndex
* @throws PluginException
* @throws QueryException
*/
@TransactionAttribute(value = TransactionAttributeType.REQUIRES_NEW)
public int computeInvoiceMetrics(String query, int batchSize, int pageIndex)
throws PluginException, QueryException {
int updates = 0;
List<ItemCollection> invoices = documentService.find(query, batchSize, pageIndex);
for (ItemCollection invoice : invoices) {
try {
ItemCollection metricData = metricDebitorService.getMetricByInvoice(invoice);
// Jetzt Rechnung addieren
metricDebitorService.addInvoice(metricData, invoice);
logger.fine("│   │   │   ├── update metric " + InvoiceUtil.getBPId(invoice));
metricDebitorService.updateMetric(metricData, true);
updates++;
} catch (PluginException e) {
// invalid invoice - e.g. no dbtr. number
}
}
return updates;
}
private void log(String message, StringBuffer messageLog) {
logger.info(message);
messageLog.append(message + "\n");
}
}