refactoring inmemory metrics
This commit is contained in:
parent
cde1b2a2eb
commit
51ccd40f18
5 changed files with 148 additions and 455 deletions
|
|
@ -1,6 +1,5 @@
|
||||||
package com.alexanderlogistics.metrics;
|
package com.alexanderlogistics.metrics;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
|
@ -15,7 +14,6 @@ import jakarta.ejb.Stateless;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
import jakarta.ws.rs.GET;
|
import jakarta.ws.rs.GET;
|
||||||
import jakarta.ws.rs.Path;
|
import jakarta.ws.rs.Path;
|
||||||
import jakarta.ws.rs.PathParam;
|
|
||||||
import jakarta.ws.rs.Produces;
|
import jakarta.ws.rs.Produces;
|
||||||
import jakarta.ws.rs.core.MediaType;
|
import jakarta.ws.rs.core.MediaType;
|
||||||
import jakarta.ws.rs.core.Response;
|
import jakarta.ws.rs.core.Response;
|
||||||
|
|
@ -62,9 +60,6 @@ public class MetricCreditorRestService {
|
||||||
// first clear the metric cache
|
// first clear the metric cache
|
||||||
metricCreditorService.reset();
|
metricCreditorService.reset();
|
||||||
log("│ ├── reset metric cache", messageBuffer);
|
log("│ ├── reset metric cache", messageBuffer);
|
||||||
// run in new transaction!
|
|
||||||
metricDataService.deleteAllMetrics(MetricCreditorService.TYPE_METRIC_CREDITOR);
|
|
||||||
log("│ ├── delete metrics", messageBuffer);
|
|
||||||
|
|
||||||
computeMetrics();
|
computeMetrics();
|
||||||
log("│ ├── computing metrics finished in " + (System.currentTimeMillis() - l) + "ms", messageBuffer);
|
log("│ ├── computing metrics finished in " + (System.currentTimeMillis() - l) + "ms", messageBuffer);
|
||||||
|
|
@ -87,81 +82,6 @@ public class MetricCreditorRestService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This method initializes the metrics for all creditors with open invoices.
|
|
||||||
*
|
|
||||||
* The method deletes all existing metrics and creates new metric entires for
|
|
||||||
* each creditor.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@GET
|
|
||||||
@Path("/rebuild/{cdtrnumber}")
|
|
||||||
@Produces({ MediaType.TEXT_PLAIN })
|
|
||||||
public Response rebuildMetricsForCreditor(@PathParam("cdtrnumber") String cdtrnumber) {
|
|
||||||
StringBuffer messageBuffer = new StringBuffer();
|
|
||||||
long l = System.currentTimeMillis();
|
|
||||||
log("├── init cdtr metrics for " + cdtrnumber + "...", messageBuffer);
|
|
||||||
try {
|
|
||||||
|
|
||||||
logger.info("│ │ ├── group invoices by creditor " + cdtrnumber + "...");
|
|
||||||
|
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
// First we need to remove all metrics for this creditor
|
|
||||||
String bpID = InvoiceUtil.buildBPID(cdtrnumber);
|
|
||||||
logger.info("│ │ ├── delete metrics for " + bpID + "...");
|
|
||||||
List<String> oldMetricKeys = metricDataService
|
|
||||||
.deleteAllMetricsByBPID(MetricCreditorService.TYPE_METRIC_CREDITOR, bpID);
|
|
||||||
logger.info("│ │ ├── found " + oldMetricKeys.size() + " metrics for " + bpID + "...");
|
|
||||||
metricCreditorService.reset(oldMetricKeys);
|
|
||||||
// next rebuild gauges and metrics for this creditor
|
|
||||||
List<ItemCollection> invoices = documentService.find(
|
|
||||||
"($modelversion:rechnungseingang-* OR $modelversion:gutschriftabgleich-*) " +
|
|
||||||
" AND type:workitem AND cdtr.number:" + cdtrnumber,
|
|
||||||
9999, 0, "invoice.number", false);
|
|
||||||
logger.info("│ │ ├──found " + invoices.size() + " open invoices");
|
|
||||||
|
|
||||||
List<String> newMetricKeys = new ArrayList<>();
|
|
||||||
for (ItemCollection invoice : invoices) {
|
|
||||||
try {
|
|
||||||
ItemCollection metricData = metricCreditorService.getMetricByInvoice(invoice);
|
|
||||||
newMetricKeys.add(metricData.getItemValueString("name"));
|
|
||||||
// Jetzt Rechnung addieren
|
|
||||||
metricCreditorService.addInvoice(metricData, invoice);
|
|
||||||
logger.info("│ │ │ ├──update metric " + InvoiceUtil.getBPId(invoice) + " Invoice: "
|
|
||||||
+ invoice.getItemValueString("invoice.number") + " Saldo: "
|
|
||||||
+ invoice.getItemValueDouble(MetricCreditorService.ITEM_TOTAL));
|
|
||||||
|
|
||||||
metricCreditorService.putMetric(metricData);
|
|
||||||
count++;
|
|
||||||
} catch (PluginException e) {
|
|
||||||
// invalid invoice - e.g. no cdtr. number
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.info("│ │ ├── updated metric for " + count + " invoices.");
|
|
||||||
|
|
||||||
log("│ ├── computing metrics finished in " + (System.currentTimeMillis() - l) + "ms", messageBuffer);
|
|
||||||
|
|
||||||
logger.info("│ ├── save and init metrics...");
|
|
||||||
// run in new transaction!
|
|
||||||
metricCreditorService.refreshGauges(newMetricKeys);
|
|
||||||
|
|
||||||
String message = "├── rebuild cdtr metrics completed in "
|
|
||||||
+ (System.currentTimeMillis() - l)
|
|
||||||
+ "ms";
|
|
||||||
log(message, messageBuffer);
|
|
||||||
return Response.ok().entity(messageBuffer.toString()).build();
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return Response.serverError()
|
|
||||||
.entity("Failed to initialize metrics: " + e.getMessage())
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Diese Methode berechnet alle Metriken auf basis der existierenden Rechnungen
|
* Diese Methode berechnet alle Metriken auf basis der existierenden Rechnungen
|
||||||
* neu
|
* neu
|
||||||
|
|
@ -184,7 +104,7 @@ public class MetricCreditorRestService {
|
||||||
// Jetzt Rechnung addieren
|
// Jetzt Rechnung addieren
|
||||||
metricCreditorService.addInvoice(metricData, invoice);
|
metricCreditorService.addInvoice(metricData, invoice);
|
||||||
logger.info("│ │ │ ├──update metric " + InvoiceUtil.getBPId(invoice));
|
logger.info("│ │ │ ├──update metric " + InvoiceUtil.getBPId(invoice));
|
||||||
metricCreditorService.putMetric(metricData);
|
metricCreditorService.updateMetric(metricData);
|
||||||
count++;
|
count++;
|
||||||
} catch (PluginException e) {
|
} catch (PluginException e) {
|
||||||
// invalid invoice - e.g. no cdtr. number
|
// invalid invoice - e.g. no cdtr. number
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ import org.imixs.workflow.ItemCollection;
|
||||||
import org.imixs.workflow.engine.DocumentService;
|
import org.imixs.workflow.engine.DocumentService;
|
||||||
import org.imixs.workflow.engine.ProcessingEvent;
|
import org.imixs.workflow.engine.ProcessingEvent;
|
||||||
import org.imixs.workflow.exceptions.PluginException;
|
import org.imixs.workflow.exceptions.PluginException;
|
||||||
import org.imixs.workflow.exceptions.QueryException;
|
|
||||||
|
|
||||||
import com.alexanderlogistics.InvoiceUtil;
|
import com.alexanderlogistics.InvoiceUtil;
|
||||||
import com.alexanderlogistics.KreditorDebitorService;
|
import com.alexanderlogistics.KreditorDebitorService;
|
||||||
|
|
@ -24,8 +23,6 @@ import com.alexanderlogistics.KreditorDebitorService;
|
||||||
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.TransactionAttribute;
|
|
||||||
import jakarta.ejb.TransactionAttributeType;
|
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
import jakarta.enterprise.event.Observes;
|
import jakarta.enterprise.event.Observes;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
|
|
@ -60,8 +57,10 @@ public class MetricCreditorService {
|
||||||
private final Set<String> registeredGauges = ConcurrentHashMap.newKeySet();
|
private final Set<String> registeredGauges = ConcurrentHashMap.newKeySet();
|
||||||
|
|
||||||
public static final String TYPE_METRIC_CREDITOR = "metric.creditor";
|
public static final String TYPE_METRIC_CREDITOR = "metric.creditor";
|
||||||
public static final String ITEM_TOTAL = "invoice.total";
|
public static final String ITEM_INVOICE_TOTAL = "invoice.total";
|
||||||
public static final String ITEM_SALDO = "invoice.saldo";
|
public static final String ITEM_INVOICE_SALDO = "invoice.saldo";
|
||||||
|
public static final String ITEM_METRIC_BALANCE = "invoice.balance";
|
||||||
|
public static final String ITEM_METRIC_SALES = "invoice.sales";
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@RegistryScope(scope = MetricRegistry.APPLICATION_SCOPE)
|
@RegistryScope(scope = MetricRegistry.APPLICATION_SCOPE)
|
||||||
|
|
@ -88,17 +87,6 @@ public class MetricCreditorService {
|
||||||
registeredGauges.clear();
|
registeredGauges.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset the internal metricCache and clears all registered Gauges for a list of
|
|
||||||
* metric keys.
|
|
||||||
*/
|
|
||||||
public void reset(List<String> metricKeys) {
|
|
||||||
for (String metricKey : metricKeys) {
|
|
||||||
metricCache.remove(metricKey);
|
|
||||||
metricRegistry.remove(metricKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process Metric only if some data has changed....
|
* Process Metric only if some data has changed....
|
||||||
*
|
*
|
||||||
|
|
@ -124,9 +112,11 @@ public class MetricCreditorService {
|
||||||
if (lastInvoice != null) {
|
if (lastInvoice != null) {
|
||||||
try {
|
try {
|
||||||
ItemCollection lastMetricData = getMetricByInvoice(lastInvoice);
|
ItemCollection lastMetricData = getMetricByInvoice(lastInvoice);
|
||||||
subtractInvoice(lastMetricData, lastInvoice);
|
// update last metric only if exists...
|
||||||
putMetric(lastMetricData);
|
if (!isNewMetric(lastMetricData)) {
|
||||||
metricDataService.saveMetric(lastMetricData);
|
subtractInvoice(lastMetricData, lastInvoice);
|
||||||
|
updateMetric(lastMetricData);
|
||||||
|
}
|
||||||
} catch (PluginException e) {
|
} catch (PluginException e) {
|
||||||
// invalid invoice - e.g. no cdtr. number
|
// invalid invoice - e.g. no cdtr. number
|
||||||
}
|
}
|
||||||
|
|
@ -137,11 +127,7 @@ public class MetricCreditorService {
|
||||||
ItemCollection metricData = getMetricByInvoice(invoice);
|
ItemCollection metricData = getMetricByInvoice(invoice);
|
||||||
// Saldo-Berechnung
|
// Saldo-Berechnung
|
||||||
addInvoice(metricData, invoice);
|
addInvoice(metricData, invoice);
|
||||||
putMetric(metricData);
|
updateMetric(metricData);
|
||||||
metricDataService.saveMetric(metricData);
|
|
||||||
|
|
||||||
// Update the Gauge
|
|
||||||
updateGauge(metricData);
|
|
||||||
logger.info("Metric cdtr update took " + (System.currentTimeMillis() - l) + "ms");
|
logger.info("Metric cdtr update took " + (System.currentTimeMillis() - l) + "ms");
|
||||||
} catch (PluginException e) {
|
} catch (PluginException e) {
|
||||||
// invalid invoice - e.g. no cdtr. number
|
// invalid invoice - e.g. no cdtr. number
|
||||||
|
|
@ -150,6 +136,17 @@ public class MetricCreditorService {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the metric is not yet registered. This means we do not have
|
||||||
|
* sales or balances for this metric
|
||||||
|
*
|
||||||
|
* @param metricData
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean isNewMetric(ItemCollection metricData) {
|
||||||
|
return (!metricCache.containsKey(metricData.getItemValueString("name")));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the corresponding metric data object for an invoice. The method uses
|
* Returns the corresponding metric data object for an invoice. The method uses
|
||||||
* an internal cache. If the metric was not yet cached the method loads the
|
* an internal cache. If the metric was not yet cached the method loads the
|
||||||
|
|
@ -169,12 +166,9 @@ public class MetricCreditorService {
|
||||||
}
|
}
|
||||||
String metricKey = MetricDataService.buildKeyByInvoice(invoice);
|
String metricKey = MetricDataService.buildKeyByInvoice(invoice);
|
||||||
ItemCollection metricData = metricCache.get(metricKey);
|
ItemCollection metricData = metricCache.get(metricKey);
|
||||||
if (metricData == null) {
|
|
||||||
metricData = loadMetric(invoice);
|
|
||||||
}
|
|
||||||
// if metric still null we create a new metric data object.
|
// if metric still null we create a new metric data object.
|
||||||
if (metricData == null) {
|
if (metricData == null) {
|
||||||
metricData = createMetaData(invoice);
|
metricData = createMetricData(invoice);
|
||||||
}
|
}
|
||||||
return metricData;
|
return metricData;
|
||||||
}
|
}
|
||||||
|
|
@ -189,15 +183,6 @@ public class MetricCreditorService {
|
||||||
return metricCache.get(key);
|
return metricCache.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Puts a metric data object into the cache.
|
|
||||||
*
|
|
||||||
* @param metricData
|
|
||||||
*/
|
|
||||||
public void putMetric(ItemCollection metricData) {
|
|
||||||
metricCache.put(metricData.getItemValueString("name"), metricData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list with all cached metric keys.
|
* Returns a list with all cached metric keys.
|
||||||
* The method returns an unmodifiable list to prevent modifications.
|
* The method returns an unmodifiable list to prevent modifications.
|
||||||
|
|
@ -209,44 +194,17 @@ public class MetricCreditorService {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method loads a metric entity for a given invoice workitem. If no metric
|
* Creates an empty Creditor Metric Data Object (ItemCollection)
|
||||||
* entity exits, the method
|
|
||||||
* creates a new metric entity.
|
|
||||||
*
|
|
||||||
* @param invoice
|
|
||||||
* @return
|
|
||||||
* @throws PluginException
|
|
||||||
*/
|
|
||||||
private ItemCollection loadMetric(ItemCollection invoice) throws PluginException {
|
|
||||||
ItemCollection creditorMetric = null;
|
|
||||||
if (invoice == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
String metricKey = MetricDataService.buildKeyByInvoice(invoice);
|
|
||||||
String query = "(type:" + TYPE_METRIC_CREDITOR + ") AND (name:" + metricKey + ")";
|
|
||||||
List<ItemCollection> result = documentService.find(query, 1, 0, "$modified", true);
|
|
||||||
if (result.size() > 0) {
|
|
||||||
creditorMetric = result.get(0);
|
|
||||||
}
|
|
||||||
} catch (IllegalArgumentException | QueryException e) {
|
|
||||||
throw new PluginException(PluginException.class.getName(),
|
|
||||||
"Failed to load metric object for invoice " + invoice.getUniqueID() + ": ", e.getMessage(), e);
|
|
||||||
}
|
|
||||||
return creditorMetric;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an empty Creditor Meta Data Object (ItemCollection)
|
|
||||||
* <p>
|
* <p>
|
||||||
* The ItemCollection stores the name and number and also all saldos for all
|
* The ItemCollection stores the name and number and all categories.
|
||||||
* currencies
|
* A new metric object does not yet have the items 'invoice.saldo' and
|
||||||
|
* 'invoice.total'
|
||||||
*
|
*
|
||||||
* @param invoice - invoice ItemCollection
|
* @param invoice - invoice ItemCollection
|
||||||
* @return
|
* @return
|
||||||
* @throws PluginException
|
* @throws PluginException
|
||||||
*/
|
*/
|
||||||
private ItemCollection createMetaData(ItemCollection invoice) throws PluginException {
|
private ItemCollection createMetricData(ItemCollection invoice) throws PluginException {
|
||||||
if (invoice == null) {
|
if (invoice == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -269,17 +227,20 @@ public class MetricCreditorService {
|
||||||
* @param cdtrNumber - the creditor number
|
* @param cdtrNumber - the creditor number
|
||||||
* @param cdtrName - the creditor name
|
* @param cdtrName - the creditor name
|
||||||
*/
|
*/
|
||||||
public void updateGauge(ItemCollection metricData) {
|
public void updateMetric(ItemCollection metricData) {
|
||||||
|
|
||||||
String metricKey = metricData.getItemValueString("name");
|
String metricKey = metricData.getItemValueString("name");
|
||||||
String bpName = metricData.getItemValueString("bp.name");
|
// Cache aktualisieren
|
||||||
String bpId = metricData.getItemValueString("bp.id");
|
metricCache.put(metricKey, metricData);
|
||||||
String country = metricData.getItemValueString("country");
|
|
||||||
String department = metricData.getItemValueString("department");
|
|
||||||
String currency = metricData.getItemValueString("currency");
|
|
||||||
|
|
||||||
// Prüfen ob Gauge bereits registriert ist
|
// Prüfen ob Gauge bereits registriert ist
|
||||||
if (registeredGauges.add(metricKey)) { // returns true newly added
|
if (registeredGauges.add(metricKey)) { // returns true newly added
|
||||||
|
String bpName = metricData.getItemValueString("bp.name");
|
||||||
|
String bpId = metricData.getItemValueString("bp.id");
|
||||||
|
String country = metricData.getItemValueString("country");
|
||||||
|
String department = metricData.getItemValueString("department");
|
||||||
|
String currency = metricData.getItemValueString("currency");
|
||||||
|
|
||||||
List<Tag> tags = new ArrayList<>();
|
List<Tag> tags = new ArrayList<>();
|
||||||
tags.add(new Tag("type", "cdtr"));
|
tags.add(new Tag("type", "cdtr"));
|
||||||
tags.add(new Tag("id", bpId));
|
tags.add(new Tag("id", bpId));
|
||||||
|
|
@ -287,20 +248,24 @@ public class MetricCreditorService {
|
||||||
tags.add(new Tag("country", country));
|
tags.add(new Tag("country", country));
|
||||||
tags.add(new Tag("currency", currency));
|
tags.add(new Tag("currency", currency));
|
||||||
tags.add(new Tag("department", department));
|
tags.add(new Tag("department", department));
|
||||||
logger.fine("register new metric for department: " + department +
|
|
||||||
", " + metricData.getItemValueString(ITEM_SALDO) +
|
// Saldo Gauge
|
||||||
" " + currency);
|
Metadata balanceMetadata = Metadata.builder()
|
||||||
Metadata metadata = Metadata.builder()
|
|
||||||
.withName("cdtr.balance")
|
.withName("cdtr.balance")
|
||||||
.withDescription("Creditor Balance")
|
.withDescription("Creditor Balance")
|
||||||
.build();
|
.build();
|
||||||
|
metricRegistry.gauge(balanceMetadata,
|
||||||
metricCache.get(metricKey);
|
() -> metricCache.get(metricKey).getItemValueDouble(ITEM_METRIC_BALANCE),
|
||||||
metricRegistry.gauge(metadata,
|
tags.toArray(new Tag[0]));
|
||||||
() -> metricCache.get(metricKey).getItemValueDouble(ITEM_SALDO),
|
|
||||||
|
// Umsatz Gauge
|
||||||
|
Metadata revenueMetadata = Metadata.builder()
|
||||||
|
.withName("cdtr.sales")
|
||||||
|
.withDescription("Creditor Sales")
|
||||||
|
.build();
|
||||||
|
metricRegistry.gauge(revenueMetadata,
|
||||||
|
() -> metricCache.get(metricKey).getItemValueDouble(ITEM_METRIC_SALES),
|
||||||
tags.toArray(new Tag[0]));
|
tags.toArray(new Tag[0]));
|
||||||
} else {
|
|
||||||
logger.fine("Cdtr Gauge already registered for department: " + department);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -312,57 +277,54 @@ public class MetricCreditorService {
|
||||||
* @param invoice
|
* @param invoice
|
||||||
*/
|
*/
|
||||||
public void addInvoice(ItemCollection metricData, ItemCollection invoice) {
|
public void addInvoice(ItemCollection metricData, ItemCollection invoice) {
|
||||||
double invoiceTotal = invoice.getItemValueDouble(ITEM_TOTAL);
|
if (metricData == null || invoice == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
double invoiceSaldo = invoice.getItemValueDouble(ITEM_INVOICE_TOTAL);
|
||||||
|
double invoiceTotal = invoice.getItemValueDouble(ITEM_INVOICE_TOTAL);
|
||||||
if (!"workitem".equals(invoice.getType()) || invoice.getTaskID() >= 5800) {
|
if (!"workitem".equals(invoice.getType()) || invoice.getTaskID() >= 5800) {
|
||||||
// vorgang ist archiviert oder gelöscht worden => saldo = 0!
|
// vorgang ist archiviert oder gelöscht worden => saldo = 0!
|
||||||
invoiceTotal = 0.0;
|
invoiceSaldo = 0.0;
|
||||||
}
|
|
||||||
// is the metric new?
|
|
||||||
if (!metricData.hasItem(ITEM_SALDO)) {
|
|
||||||
// init metric with the total value!
|
|
||||||
metricData.setItemValue(ITEM_SALDO, InvoiceUtil.round(invoiceTotal));
|
|
||||||
} else {
|
|
||||||
double lastSaldo = metricData.getItemValueDouble(ITEM_SALDO);
|
|
||||||
metricData.setItemValue(ITEM_SALDO, InvoiceUtil.round(lastSaldo + invoiceTotal));
|
|
||||||
}
|
}
|
||||||
|
// update balance
|
||||||
|
double lastBalance = metricData.getItemValueDouble(ITEM_METRIC_BALANCE);
|
||||||
|
metricData.setItemValue(ITEM_METRIC_BALANCE, InvoiceUtil.round(lastBalance + invoiceSaldo));
|
||||||
|
|
||||||
|
// update sales
|
||||||
|
double lastTotal = metricData.getItemValueDouble(ITEM_METRIC_SALES);
|
||||||
|
metricData.setItemValue(ITEM_METRIC_SALES, InvoiceUtil.round(lastTotal + invoiceTotal));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void subtractInvoice(ItemCollection metricData, ItemCollection invoice) {
|
public void subtractInvoice(ItemCollection metricData, ItemCollection invoice) {
|
||||||
if (metricData == null || invoice == null) {
|
if (metricData == null || invoice == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
double invoiceTotal = invoice.getItemValueDouble(ITEM_TOTAL);
|
double invoiceTotal = invoice.getItemValueDouble(ITEM_INVOICE_TOTAL);
|
||||||
|
double invoiceSaldo = invoice.getItemValueDouble(ITEM_INVOICE_TOTAL);
|
||||||
if (!"workitem".equals(invoice.getType()) || invoice.getTaskID() >= 5800) {
|
if (!"workitem".equals(invoice.getType()) || invoice.getTaskID() >= 5800) {
|
||||||
// vorgang ist archiviert oder gelöscht worden => saldo = 0!
|
// vorgang ist archiviert oder gelöscht worden => saldo = 0!
|
||||||
invoiceTotal = 0.0;
|
invoiceSaldo = 0.0;
|
||||||
}
|
}
|
||||||
// subtract only if metric saldo exists
|
// subtract only if metric saldo exists
|
||||||
if (metricData.hasItem(ITEM_SALDO)) {
|
double lastBalance = metricData.getItemValueDouble(ITEM_METRIC_BALANCE);
|
||||||
double lastSaldo = metricData.getItemValueDouble(ITEM_SALDO);
|
metricData.setItemValue(ITEM_METRIC_BALANCE, InvoiceUtil.round(lastBalance - invoiceSaldo));
|
||||||
metricData.setItemValue(ITEM_SALDO, InvoiceUtil.round(lastSaldo - invoiceTotal));
|
|
||||||
}
|
// Neue Umsatz Logik
|
||||||
|
double lastSales = metricData.getItemValueDouble(ITEM_METRIC_SALES);
|
||||||
|
metricData.setItemValue(ITEM_METRIC_SALES, InvoiceUtil.round(lastSales - invoiceTotal));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper Method that refreshes all gauges. The method is called by the
|
* Helper Method that refreshes all gauges. The method is called by the
|
||||||
* RestService during a rebuild.
|
* RestService during a rebuild.
|
||||||
*/
|
*/
|
||||||
@TransactionAttribute(value = TransactionAttributeType.REQUIRES_NEW)
|
|
||||||
public void refreshGauges() {
|
public void refreshGauges() {
|
||||||
List<String> keys = getMetricKeys();
|
List<String> keys = getMetricKeys();
|
||||||
refreshGauges(keys);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper Method that refreshes all gauges. The method is called by the
|
|
||||||
* RestService during a rebuild.
|
|
||||||
*/
|
|
||||||
@TransactionAttribute(value = TransactionAttributeType.REQUIRES_NEW)
|
|
||||||
public void refreshGauges(List<String> keys) {
|
|
||||||
for (String hashKey : keys) {
|
for (String hashKey : keys) {
|
||||||
ItemCollection metricData = getMetric(hashKey);
|
ItemCollection metricData = getMetric(hashKey);
|
||||||
documentService.save(metricData);
|
updateMetric(metricData);
|
||||||
updateGauge(metricData);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,10 @@
|
||||||
package com.alexanderlogistics.metrics;
|
package com.alexanderlogistics.metrics;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import org.imixs.workflow.ItemCollection;
|
import org.imixs.workflow.ItemCollection;
|
||||||
import org.imixs.workflow.engine.DocumentService;
|
import org.imixs.workflow.engine.DocumentService;
|
||||||
import org.imixs.workflow.engine.index.SearchService;
|
|
||||||
import org.imixs.workflow.exceptions.PluginException;
|
import org.imixs.workflow.exceptions.PluginException;
|
||||||
import org.imixs.workflow.exceptions.QueryException;
|
|
||||||
|
|
||||||
import com.alexanderlogistics.InvoiceUtil;
|
import com.alexanderlogistics.InvoiceUtil;
|
||||||
|
|
||||||
|
|
@ -34,15 +30,6 @@ public class MetricDataService {
|
||||||
@Inject
|
@Inject
|
||||||
DocumentService documentService;
|
DocumentService documentService;
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs with Manager access
|
|
||||||
*
|
|
||||||
* @param metricData
|
|
||||||
*/
|
|
||||||
public void saveMetric(ItemCollection metricData) {
|
|
||||||
documentService.save(metricData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This helper method reads a 'dirty' workitem in a new transaction. This is
|
* This helper method reads a 'dirty' workitem in a new transaction. This is
|
||||||
* used for calculating the new metric values
|
* used for calculating the new metric values
|
||||||
|
|
@ -55,53 +42,6 @@ public class MetricDataService {
|
||||||
return dirtyInvoice;
|
return dirtyInvoice;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This method deletes all metrics
|
|
||||||
*
|
|
||||||
* @throws PluginException
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@TransactionAttribute(value = TransactionAttributeType.REQUIRES_NEW)
|
|
||||||
public void deleteAllMetrics(String metricType) throws PluginException {
|
|
||||||
try {
|
|
||||||
String query = "(type:" + metricType + ")";
|
|
||||||
List<ItemCollection> result = documentService.find(query, SearchService.DEFAULT_MAX_SEARCH_RESULT, 0);
|
|
||||||
for (ItemCollection metric : result) {
|
|
||||||
documentService.remove(metric);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (IllegalArgumentException | QueryException e) {
|
|
||||||
throw new PluginException(MetricDataService.class.getName(),
|
|
||||||
"Failed to delete metrics", e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method deletes all metrics for a given BP ID
|
|
||||||
*
|
|
||||||
* @throws PluginException
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@TransactionAttribute(value = TransactionAttributeType.REQUIRES_NEW)
|
|
||||||
public List<String> deleteAllMetricsByBPID(String metricType, String bpID) throws PluginException {
|
|
||||||
List<String> result = new ArrayList<>();
|
|
||||||
try {
|
|
||||||
String query = "(type:" + metricType + ")";
|
|
||||||
List<ItemCollection> metricList = documentService.find(query, SearchService.DEFAULT_MAX_SEARCH_RESULT, 0);
|
|
||||||
for (ItemCollection metric : metricList) {
|
|
||||||
if (metric.getItemValueString("bp.id").equals(bpID)) {
|
|
||||||
result.add(metric.getItemValueString("name"));
|
|
||||||
documentService.remove(metric);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (IllegalArgumentException | QueryException e) {
|
|
||||||
throw new PluginException(MetricDataService.class.getName(),
|
|
||||||
"Failed to delete metrics", e.getMessage(), e);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds the metric hash key by the invoice attributes. The returned key can be
|
* Builds the metric hash key by the invoice attributes. The returned key can be
|
||||||
* used for caching the metric.
|
* used for caching the metric.
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package com.alexanderlogistics.metrics;
|
package com.alexanderlogistics.metrics;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
|
@ -15,7 +14,6 @@ import jakarta.ejb.Stateless;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
import jakarta.ws.rs.GET;
|
import jakarta.ws.rs.GET;
|
||||||
import jakarta.ws.rs.Path;
|
import jakarta.ws.rs.Path;
|
||||||
import jakarta.ws.rs.PathParam;
|
|
||||||
import jakarta.ws.rs.Produces;
|
import jakarta.ws.rs.Produces;
|
||||||
import jakarta.ws.rs.core.MediaType;
|
import jakarta.ws.rs.core.MediaType;
|
||||||
import jakarta.ws.rs.core.Response;
|
import jakarta.ws.rs.core.Response;
|
||||||
|
|
@ -64,9 +62,6 @@ public class MetricDebitorRestService {
|
||||||
// first clear the metric cache
|
// first clear the metric cache
|
||||||
metricDebitorService.reset();
|
metricDebitorService.reset();
|
||||||
logger.info("│ ├── reset metric cache");
|
logger.info("│ ├── reset metric cache");
|
||||||
// run in new transaction!
|
|
||||||
metricDataService.deleteAllMetrics(MetricDebitorService.TYPE_METRIC_DEBITOR);
|
|
||||||
logger.info("│ ├── delete metrics");
|
|
||||||
|
|
||||||
computeMetrics();
|
computeMetrics();
|
||||||
logger.info("│ ├── computing metrics finished in " + (System.currentTimeMillis() - l) + "ms");
|
logger.info("│ ├── computing metrics finished in " + (System.currentTimeMillis() - l) + "ms");
|
||||||
|
|
@ -89,92 +84,6 @@ public class MetricDebitorRestService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This method initializes the metrics for all creditors with open invoices.
|
|
||||||
*
|
|
||||||
* The method deletes all existing metrics and creates new metric entires for
|
|
||||||
* each creditor.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@GET
|
|
||||||
@Path("/rebuild/{dbtrnumber}")
|
|
||||||
@Produces({ MediaType.TEXT_PLAIN })
|
|
||||||
public Response rebuildMetricsForDebitor(@PathParam("dbtrnumber") String dbtrnumber) {
|
|
||||||
StringBuffer messageBuffer = new StringBuffer();
|
|
||||||
long l = System.currentTimeMillis();
|
|
||||||
log("├── init dbtr metrics for " + dbtrnumber + "...", messageBuffer);
|
|
||||||
try {
|
|
||||||
|
|
||||||
logger.info("│ │ ├── group invoices by creditor " + dbtrnumber + "...");
|
|
||||||
|
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
// First we need to remove all metrics for this creditor
|
|
||||||
String bpID = InvoiceUtil.buildBPID(dbtrnumber);
|
|
||||||
logger.info("│ │ ├── delete metrics for " + bpID + "...");
|
|
||||||
List<String> oldMetricKeys = metricDataService
|
|
||||||
.deleteAllMetricsByBPID(MetricDebitorService.TYPE_METRIC_DEBITOR, bpID);
|
|
||||||
logger.info("│ │ ├── found " + oldMetricKeys.size() + " metrics for " + bpID + "...");
|
|
||||||
metricDebitorService.reset(oldMetricKeys);
|
|
||||||
// next rebuild gauges and metrics for this creditor
|
|
||||||
String queryDbtrNumber = dbtrnumber;
|
|
||||||
if (queryDbtrNumber.startsWith("D")) {
|
|
||||||
queryDbtrNumber = queryDbtrNumber.substring(1); // DAS IST DER CARGOSOFT IRRSINN
|
|
||||||
}
|
|
||||||
String query = "$modelversion:rechnungsausgang-* AND type:workitem " +
|
|
||||||
" AND type:workitem AND dbtr.number:" + queryDbtrNumber;
|
|
||||||
logger.fine("Query = " + query);
|
|
||||||
List<ItemCollection> invoices = documentService.find(
|
|
||||||
query,
|
|
||||||
9999, 0, "invoice.number", false);
|
|
||||||
logger.info("│ │ ├──found " + invoices.size() + " open invoices");
|
|
||||||
|
|
||||||
List<String> newMetricKeys = new ArrayList<>();
|
|
||||||
for (ItemCollection invoice : invoices) {
|
|
||||||
try {
|
|
||||||
ItemCollection metricData = metricDebitorService.getMetricByInvoice(invoice);
|
|
||||||
String metricKey = metricData.getItemValueString("name");
|
|
||||||
newMetricKeys.add(metricKey);
|
|
||||||
// Jetzt Rechnung addieren
|
|
||||||
logger.info("│ │ │ ├──update metric (" + metricKey + ")" + InvoiceUtil.getBPId(invoice)
|
|
||||||
+ " Invoice: "
|
|
||||||
+ invoice.getItemValueString("invoice.number") + " Saldo: "
|
|
||||||
+ invoice.getItemValueDouble(MetricDebitorService.ITEM_SALDO));
|
|
||||||
logger.info("│ │ │ │ ├── last metric saldo: "
|
|
||||||
+ metricData.getItemValueDouble(MetricDebitorService.ITEM_SALDO));
|
|
||||||
metricDebitorService.addInvoice(metricData, invoice);
|
|
||||||
logger.info("│ │ │ │ ├── new metric saldo: "
|
|
||||||
+ metricData.getItemValueDouble(MetricDebitorService.ITEM_SALDO));
|
|
||||||
metricDebitorService.putMetric(metricData);
|
|
||||||
count++;
|
|
||||||
} catch (PluginException e) {
|
|
||||||
// invalid invoice - e.g. no dbtr. number
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.info("│ │ ├── updated metric for " + count + " invoices.");
|
|
||||||
|
|
||||||
log("│ ├── computing metrics finished in " + (System.currentTimeMillis() - l) + "ms", messageBuffer);
|
|
||||||
|
|
||||||
logger.info("│ ├── save and init metrics...");
|
|
||||||
// run in new transaction!
|
|
||||||
metricDebitorService.refreshGauges(newMetricKeys);
|
|
||||||
|
|
||||||
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();
|
|
||||||
return Response.serverError()
|
|
||||||
.entity("Failed to initialize metrics: " + e.getMessage())
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Diese Methode berechnet alle Metriken auf basis der existierenden Rechnungen
|
* Diese Methode berechnet alle Metriken auf basis der existierenden Rechnungen
|
||||||
* neu
|
* neu
|
||||||
|
|
@ -199,7 +108,7 @@ public class MetricDebitorRestService {
|
||||||
// Jetzt Rechnung addieren
|
// Jetzt Rechnung addieren
|
||||||
metricDebitorService.addInvoice(metricData, invoice);
|
metricDebitorService.addInvoice(metricData, invoice);
|
||||||
logger.info("│ │ │ ├──update metric " + InvoiceUtil.getBPId(invoice));
|
logger.info("│ │ │ ├──update metric " + InvoiceUtil.getBPId(invoice));
|
||||||
metricDebitorService.putMetric(metricData);
|
metricDebitorService.updateMetric(metricData);
|
||||||
count++;
|
count++;
|
||||||
} catch (PluginException e) {
|
} catch (PluginException e) {
|
||||||
// invalid invoice - e.g. no dbtr. number
|
// invalid invoice - e.g. no dbtr. number
|
||||||
|
|
|
||||||
|
|
@ -16,15 +16,12 @@ import org.imixs.workflow.ItemCollection;
|
||||||
import org.imixs.workflow.engine.DocumentService;
|
import org.imixs.workflow.engine.DocumentService;
|
||||||
import org.imixs.workflow.engine.ProcessingEvent;
|
import org.imixs.workflow.engine.ProcessingEvent;
|
||||||
import org.imixs.workflow.exceptions.PluginException;
|
import org.imixs.workflow.exceptions.PluginException;
|
||||||
import org.imixs.workflow.exceptions.QueryException;
|
|
||||||
|
|
||||||
import com.alexanderlogistics.InvoiceUtil;
|
import com.alexanderlogistics.InvoiceUtil;
|
||||||
|
|
||||||
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.TransactionAttribute;
|
|
||||||
import jakarta.ejb.TransactionAttributeType;
|
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
import jakarta.enterprise.event.Observes;
|
import jakarta.enterprise.event.Observes;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
|
|
@ -56,7 +53,10 @@ public class MetricDebitorService {
|
||||||
private final Set<String> registeredGauges = ConcurrentHashMap.newKeySet();
|
private final Set<String> registeredGauges = ConcurrentHashMap.newKeySet();
|
||||||
|
|
||||||
public static final String TYPE_METRIC_DEBITOR = "metric.debitor";
|
public static final String TYPE_METRIC_DEBITOR = "metric.debitor";
|
||||||
public static final String ITEM_SALDO = "invoice.saldo";
|
public static final String ITEM_INVOICE_TOTAL = "invoice.total";
|
||||||
|
public static final String ITEM_INVOICE_SALDO = "invoice.saldo";
|
||||||
|
public static final String ITEM_METRIC_BALANCE = "invoice.balance";
|
||||||
|
public static final String ITEM_METRIC_SALES = "invoice.sales";
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@RegistryScope(scope = MetricRegistry.APPLICATION_SCOPE)
|
@RegistryScope(scope = MetricRegistry.APPLICATION_SCOPE)
|
||||||
|
|
@ -80,17 +80,6 @@ public class MetricDebitorService {
|
||||||
registeredGauges.clear();
|
registeredGauges.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset the internal metricCache and clears all registered Gauges for a list of
|
|
||||||
* metric keys.
|
|
||||||
*/
|
|
||||||
public void reset(List<String> metricKeys) {
|
|
||||||
for (String metricKey : metricKeys) {
|
|
||||||
metricCache.remove(metricKey);
|
|
||||||
metricRegistry.remove(metricKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process Metric only if some data has changed....
|
* Process Metric only if some data has changed....
|
||||||
*
|
*
|
||||||
|
|
@ -116,9 +105,10 @@ public class MetricDebitorService {
|
||||||
if (lastInvoice != null) {
|
if (lastInvoice != null) {
|
||||||
try {
|
try {
|
||||||
ItemCollection lastMetricData = getMetricByInvoice(lastInvoice);
|
ItemCollection lastMetricData = getMetricByInvoice(lastInvoice);
|
||||||
subtractInvoice(lastMetricData, lastInvoice);
|
if (!isNewMetric(lastMetricData)) {
|
||||||
putMetric(lastMetricData);
|
subtractInvoice(lastMetricData, lastInvoice);
|
||||||
metricDataService.saveMetric(lastMetricData);
|
updateMetric(lastMetricData);
|
||||||
|
}
|
||||||
} catch (PluginException e) {
|
} catch (PluginException e) {
|
||||||
// invalid invoice - e.g. no cdtr. number
|
// invalid invoice - e.g. no cdtr. number
|
||||||
}
|
}
|
||||||
|
|
@ -129,11 +119,8 @@ public class MetricDebitorService {
|
||||||
ItemCollection metricData = getMetricByInvoice(invoice);
|
ItemCollection metricData = getMetricByInvoice(invoice);
|
||||||
// Saldo-Berechnung
|
// Saldo-Berechnung
|
||||||
addInvoice(metricData, invoice);
|
addInvoice(metricData, invoice);
|
||||||
putMetric(metricData);
|
updateMetric(metricData);
|
||||||
metricDataService.saveMetric(metricData);
|
|
||||||
|
|
||||||
// Update the Gauge
|
|
||||||
updateGauge(metricData);
|
|
||||||
logger.info("Metric dbtr update took " + (System.currentTimeMillis() - l) + "ms");
|
logger.info("Metric dbtr update took " + (System.currentTimeMillis() - l) + "ms");
|
||||||
} catch (PluginException e) {
|
} catch (PluginException e) {
|
||||||
// invalid invoice - e.g. no dbtr. number
|
// invalid invoice - e.g. no dbtr. number
|
||||||
|
|
@ -142,6 +129,17 @@ public class MetricDebitorService {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the metric is not yet registered. This means we do not have
|
||||||
|
* sales or balances for this metric
|
||||||
|
*
|
||||||
|
* @param metricData
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean isNewMetric(ItemCollection metricData) {
|
||||||
|
return (!metricCache.containsKey(metricData.getItemValueString("name")));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the corresponding metric data object for an invoice. The method uses
|
* Returns the corresponding metric data object for an invoice. The method uses
|
||||||
* an internal cache. If the metric was not yet cached the method loads the
|
* an internal cache. If the metric was not yet cached the method loads the
|
||||||
|
|
@ -161,9 +159,6 @@ public class MetricDebitorService {
|
||||||
}
|
}
|
||||||
String metricKey = MetricDataService.buildKeyByInvoice(invoice);
|
String metricKey = MetricDataService.buildKeyByInvoice(invoice);
|
||||||
ItemCollection metricData = metricCache.get(metricKey);
|
ItemCollection metricData = metricCache.get(metricKey);
|
||||||
if (metricData == null) {
|
|
||||||
metricData = loadMetric(invoice);
|
|
||||||
}
|
|
||||||
// if metric still null we create a new metric data object.
|
// if metric still null we create a new metric data object.
|
||||||
if (metricData == null) {
|
if (metricData == null) {
|
||||||
metricData = createMetaData(invoice);
|
metricData = createMetaData(invoice);
|
||||||
|
|
@ -181,15 +176,6 @@ public class MetricDebitorService {
|
||||||
return metricCache.get(key);
|
return metricCache.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Puts a metric data object into the cache.
|
|
||||||
*
|
|
||||||
* @param metricData
|
|
||||||
*/
|
|
||||||
public void putMetric(ItemCollection metricData) {
|
|
||||||
metricCache.put(metricData.getItemValueString("name"), metricData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list with all cached metric keys.
|
* Returns a list with all cached metric keys.
|
||||||
* The method returns an unmodifiable list to prevent modifications.
|
* The method returns an unmodifiable list to prevent modifications.
|
||||||
|
|
@ -200,34 +186,6 @@ public class MetricDebitorService {
|
||||||
return Collections.unmodifiableList(new ArrayList<>(metricCache.keySet()));
|
return Collections.unmodifiableList(new ArrayList<>(metricCache.keySet()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This method loads a metric entity for a given invoice workitem. If no metric
|
|
||||||
* entity exits, the method
|
|
||||||
* creates a new metric entity.
|
|
||||||
*
|
|
||||||
* @param invoice
|
|
||||||
* @return
|
|
||||||
* @throws PluginException
|
|
||||||
*/
|
|
||||||
private ItemCollection loadMetric(ItemCollection invoice) throws PluginException {
|
|
||||||
ItemCollection debitorMetric = null;
|
|
||||||
if (invoice == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
String metricKey = MetricDataService.buildKeyByInvoice(invoice);
|
|
||||||
String query = "(type:" + TYPE_METRIC_DEBITOR + ") AND (name:" + metricKey + ")";
|
|
||||||
List<ItemCollection> result = documentService.find(query, 1, 0, "$modified", true);
|
|
||||||
if (result.size() > 0) {
|
|
||||||
debitorMetric = result.get(0);
|
|
||||||
}
|
|
||||||
} catch (IllegalArgumentException | QueryException e) {
|
|
||||||
throw new PluginException(PluginException.class.getName(),
|
|
||||||
"Failed to load metric object for invoice " + invoice.getUniqueID() + ": ", e.getMessage(), e);
|
|
||||||
}
|
|
||||||
return debitorMetric;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an empty Debitor Meta Data Object (ItemCollection)
|
* Creates an empty Debitor Meta Data Object (ItemCollection)
|
||||||
* <p>
|
* <p>
|
||||||
|
|
@ -260,17 +218,20 @@ public class MetricDebitorService {
|
||||||
*
|
*
|
||||||
* @param metricData - the metricData ItemCollection
|
* @param metricData - the metricData ItemCollection
|
||||||
*/
|
*/
|
||||||
public void updateGauge(ItemCollection metricData) {
|
public void updateMetric(ItemCollection metricData) {
|
||||||
|
|
||||||
String metricKey = metricData.getItemValueString("name");
|
String metricKey = metricData.getItemValueString("name");
|
||||||
String bpName = metricData.getItemValueString("bp.name");
|
|
||||||
String bpId = metricData.getItemValueString("bp.id");
|
// Cache aktualisieren
|
||||||
String country = metricData.getItemValueString("country");
|
metricCache.put(metricKey, metricData);
|
||||||
String department = metricData.getItemValueString("department");
|
|
||||||
String currency = metricData.getItemValueString("currency");
|
|
||||||
|
|
||||||
// Prüfen ob Gauge bereits registriert ist
|
// Prüfen ob Gauge bereits registriert ist
|
||||||
if (registeredGauges.add(metricKey)) { // returns true newly added
|
if (registeredGauges.add(metricKey)) { // returns true newly added
|
||||||
|
String bpName = metricData.getItemValueString("bp.name");
|
||||||
|
String bpId = metricData.getItemValueString("bp.id");
|
||||||
|
String country = metricData.getItemValueString("country");
|
||||||
|
String department = metricData.getItemValueString("department");
|
||||||
|
String currency = metricData.getItemValueString("currency");
|
||||||
|
|
||||||
List<Tag> tags = new ArrayList<>();
|
List<Tag> tags = new ArrayList<>();
|
||||||
tags.add(new Tag("type", "dbtr"));
|
tags.add(new Tag("type", "dbtr"));
|
||||||
tags.add(new Tag("id", bpId));
|
tags.add(new Tag("id", bpId));
|
||||||
|
|
@ -279,19 +240,25 @@ public class MetricDebitorService {
|
||||||
tags.add(new Tag("currency", currency));
|
tags.add(new Tag("currency", currency));
|
||||||
tags.add(new Tag("department", department));
|
tags.add(new Tag("department", department));
|
||||||
logger.fine("register new metric for department: " + department +
|
logger.fine("register new metric for department: " + department +
|
||||||
", " + metricData.getItemValueString(ITEM_SALDO) +
|
", " + metricData.getItemValueString(ITEM_METRIC_BALANCE) +
|
||||||
" " + currency);
|
" " + currency);
|
||||||
Metadata metadata = Metadata.builder()
|
// Saldo Gauge
|
||||||
|
Metadata balanceMetadata = Metadata.builder()
|
||||||
.withName("dbtr.balance")
|
.withName("dbtr.balance")
|
||||||
.withDescription("Debitor Balance")
|
.withDescription("Debitor Balance")
|
||||||
.build();
|
.build();
|
||||||
|
metricRegistry.gauge(balanceMetadata,
|
||||||
metricCache.get(metricKey);
|
() -> metricCache.get(metricKey).getItemValueDouble(ITEM_METRIC_BALANCE),
|
||||||
metricRegistry.gauge(metadata,
|
tags.toArray(new Tag[0]));
|
||||||
() -> metricCache.get(metricKey).getItemValueDouble(ITEM_SALDO),
|
|
||||||
|
// Umsatz Gauge
|
||||||
|
Metadata revenueMetadata = Metadata.builder()
|
||||||
|
.withName("dbtr.sales")
|
||||||
|
.withDescription("Debitor Sales")
|
||||||
|
.build();
|
||||||
|
metricRegistry.gauge(revenueMetadata,
|
||||||
|
() -> metricCache.get(metricKey).getItemValueDouble(ITEM_METRIC_SALES),
|
||||||
tags.toArray(new Tag[0]));
|
tags.toArray(new Tag[0]));
|
||||||
} else {
|
|
||||||
logger.fine("Gauge already registered for department: " + department);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -303,64 +270,59 @@ public class MetricDebitorService {
|
||||||
* @param invoice
|
* @param invoice
|
||||||
*/
|
*/
|
||||||
public void addInvoice(ItemCollection metricData, ItemCollection invoice) {
|
public void addInvoice(ItemCollection metricData, ItemCollection invoice) {
|
||||||
double invoiceTotal = invoice.getItemValueDouble(ITEM_SALDO);
|
double invoiceSaldo = invoice.getItemValueDouble(ITEM_INVOICE_SALDO);
|
||||||
|
double invoiceTotal = invoice.getItemValueDouble(ITEM_INVOICE_TOTAL);
|
||||||
if (!"workitem".equals(invoice.getType()) || invoice.getTaskID() >= 5800) {
|
if (!"workitem".equals(invoice.getType()) || invoice.getTaskID() >= 5800) {
|
||||||
// vorgang ist archiviert oder gelöscht worden => saldo = 0!
|
// vorgang ist archiviert oder gelöscht worden => saldo = 0!
|
||||||
invoiceTotal = 0.0;
|
invoiceSaldo = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.fine("│ │ │ │ ├── Invoice: " + invoice.getItemValueString("invoice.number") + " Saldo="
|
logger.fine("│ │ │ │ ├── Invoice: " + invoice.getItemValueString("invoice.number") + " Saldo="
|
||||||
+ invoiceTotal);
|
+ invoiceSaldo);
|
||||||
// is the metric new?
|
// update saldo
|
||||||
if (!metricData.hasItem(ITEM_SALDO)) {
|
double lastSaldo = metricData.getItemValueDouble(ITEM_METRIC_BALANCE);
|
||||||
// init metric with the total value!
|
logger.fine("│ │ │ │ ├── last metric balance=" + lastSaldo);
|
||||||
metricData.setItemValue(ITEM_SALDO, InvoiceUtil.round(invoiceTotal));
|
metricData.setItemValue(ITEM_METRIC_BALANCE, InvoiceUtil.round(lastSaldo + invoiceSaldo));
|
||||||
} else {
|
|
||||||
double lastSaldo = metricData.getItemValueDouble(ITEM_SALDO);
|
// Umsatz-Berechnung
|
||||||
logger.fine("│ │ │ │ ├──letzter Metric Saldo=" + lastSaldo);
|
double lastTotal = metricData.getItemValueDouble(ITEM_METRIC_SALES);
|
||||||
metricData.setItemValue(ITEM_SALDO, InvoiceUtil.round(lastSaldo + invoiceTotal));
|
metricData.setItemValue(ITEM_METRIC_SALES, InvoiceUtil.round(lastTotal + invoiceTotal));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void subtractInvoice(ItemCollection metricData, ItemCollection invoice) {
|
public void subtractInvoice(ItemCollection metricData, ItemCollection invoice) {
|
||||||
if (metricData == null || invoice == null) {
|
if (metricData == null || invoice == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
double invoiceTotal = invoice.getItemValueDouble(ITEM_SALDO);
|
double invoiceSaldo = invoice.getItemValueDouble(ITEM_INVOICE_SALDO);
|
||||||
|
double invoiceTotal = invoice.getItemValueDouble(ITEM_INVOICE_TOTAL);
|
||||||
logger.fine("│ │ │ │ ├──Invoice: " + invoice.getItemValueString("invoice.number") + " Saldo="
|
logger.fine("│ │ │ │ ├──Invoice: " + invoice.getItemValueString("invoice.number") + " Saldo="
|
||||||
+ invoiceTotal);
|
+ invoiceSaldo);
|
||||||
if (!"workitem".equals(invoice.getType()) || invoice.getTaskID() >= 5800) {
|
if (!"workitem".equals(invoice.getType()) || invoice.getTaskID() >= 5800) {
|
||||||
// vorgang ist archiviert oder gelöscht worden => saldo = 0!
|
// vorgang ist archiviert oder gelöscht worden => saldo = 0!
|
||||||
invoiceTotal = 0.0;
|
invoiceSaldo = 0.0;
|
||||||
}
|
}
|
||||||
// subtract only if metric saldo exists
|
// subtract only if metric saldo exists
|
||||||
if (metricData.hasItem(ITEM_SALDO)) {
|
double lastSaldo = metricData.getItemValueDouble(ITEM_METRIC_BALANCE);
|
||||||
double lastSaldo = metricData.getItemValueDouble(ITEM_SALDO);
|
logger.fine("│ │ │ │ ├── last Metric balance=" + lastSaldo);
|
||||||
logger.fine("│ │ │ │ ├──letzter Metric Saldo=" + lastSaldo);
|
metricData.setItemValue(ITEM_METRIC_BALANCE, InvoiceUtil.round(lastSaldo - invoiceSaldo));
|
||||||
metricData.setItemValue(ITEM_SALDO, InvoiceUtil.round(lastSaldo - invoiceTotal));
|
|
||||||
}
|
// update Umsatz
|
||||||
|
double lastTotal = metricData.getItemValueDouble(ITEM_METRIC_SALES);
|
||||||
|
metricData.setItemValue(ITEM_METRIC_SALES, InvoiceUtil.round(lastTotal - invoiceTotal));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper Method that refreshes all gauges. The method is called by the
|
* Helper Method that refreshes all gauges. The method is called by the
|
||||||
* RestService during a rebuild.
|
* RestService during a rebuild.
|
||||||
*/
|
*/
|
||||||
@TransactionAttribute(value = TransactionAttributeType.REQUIRES_NEW)
|
|
||||||
public void refreshGauges() {
|
public void refreshGauges() {
|
||||||
List<String> keys = getMetricKeys();
|
List<String> keys = getMetricKeys();
|
||||||
refreshGauges(keys);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper Method that refreshes all gauges. The method is called by the
|
|
||||||
* RestService during a rebuild.
|
|
||||||
*/
|
|
||||||
@TransactionAttribute(value = TransactionAttributeType.REQUIRES_NEW)
|
|
||||||
public void refreshGauges(List<String> keys) {
|
|
||||||
for (String hashKey : keys) {
|
for (String hashKey : keys) {
|
||||||
ItemCollection metricData = getMetric(hashKey);
|
ItemCollection metricData = getMetric(hashKey);
|
||||||
documentService.save(metricData);
|
updateMetric(metricData);
|
||||||
updateGauge(metricData);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue