Kreditoren Statistik
This commit is contained in:
parent
ff6ff80506
commit
520c0e996c
6 changed files with 301 additions and 27 deletions
|
|
@ -1,6 +1,12 @@
|
||||||
# Versionen
|
# Versionen
|
||||||
|
### 1.2.13
|
||||||
|
|
||||||
### 1.2.12 (Development)
|
- Payment Statistik
|
||||||
|
- Neue Indexfelder 'invoice.date' 'payment.date'
|
||||||
|
|
||||||
|
**WICHTIG:** Es muss nach dem Update einmal der Index neu berechnet werden.
|
||||||
|
|
||||||
|
### 1.2.12
|
||||||
|
|
||||||
- Neue Debitoren/Kreditoren Verwaltung - Zusätzliche E-Mail
|
- Neue Debitoren/Kreditoren Verwaltung - Zusätzliche E-Mail
|
||||||
Realisiert über neue Custom Feld 'textlist'
|
Realisiert über neue Custom Feld 'textlist'
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,19 @@ import java.io.Serializable;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.YearMonth;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TreeMap;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.enterprise.context.ConversationScoped;
|
import javax.enterprise.context.ConversationScoped;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
@ -37,6 +44,8 @@ public class DebitorStatistikController implements Serializable {
|
||||||
@Inject
|
@Inject
|
||||||
protected DocumentService documentService;
|
protected DocumentService documentService;
|
||||||
|
|
||||||
|
TreeMap<String, DebitorStatistikData> stats = null;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected WorkflowController workflowController;
|
protected WorkflowController workflowController;
|
||||||
|
|
||||||
|
|
@ -141,29 +150,42 @@ public class DebitorStatistikController implements Serializable {
|
||||||
* Zahlungszeitspanne gruppiert nach monaten
|
* Zahlungszeitspanne gruppiert nach monaten
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public void collect(Date from, Date to) {
|
public Map<String, DebitorStatistikData> getStats() {
|
||||||
|
|
||||||
Map<String, DebitorStatistikData> stats = new HashMap<String, DebitorStatistikData>();
|
if (stats != null) {
|
||||||
|
return stats;
|
||||||
|
}
|
||||||
|
|
||||||
|
// recompute
|
||||||
|
stats = new TreeMap<String, DebitorStatistikData>();
|
||||||
|
|
||||||
// invoice.date:[20210101 TO 20210201]
|
// invoice.date:[20210101 TO 20210201]
|
||||||
DateFormat df = new SimpleDateFormat("yyyymmdd");
|
DateFormat df = new SimpleDateFormat("yyyymmdd");
|
||||||
|
|
||||||
String query = "(type:workitemarchive) AND dbtr.number:" + getDbtNr()
|
String query = "(type:workitemarchive) AND dbtr.number:" + getDbtNr()
|
||||||
+ " AND $workflowgroup:\"Rechnungsausgang\" AND ($taskid:[5300 TO 5399])";
|
+ " AND $workflowgroup:\"Rechnungsausgang\" AND ($taskid:[5900 TO 5999])";
|
||||||
|
|
||||||
query = query + " AND (invoice.date:[" + df.format(from) + " TO " + df.format(to) + "])";
|
// query = query + " AND (invoice.date:[" + df.format(from) + " TO " +
|
||||||
|
// df.format(to) + "])";
|
||||||
logger.info("query = " + query);
|
logger.info("query = " + query);
|
||||||
try {
|
try {
|
||||||
List<ItemCollection> invoices = documentService
|
List<ItemCollection> invoices = documentService
|
||||||
.find(query, 9999, 0);
|
.findStubs(query, 9999, 0, "$created", false);
|
||||||
|
|
||||||
for (ItemCollection invoice : invoices) {
|
for (ItemCollection invoice : invoices) {
|
||||||
try {
|
try {
|
||||||
|
logger.warning("Rechnung: " + invoice.getUniqueID());
|
||||||
Date invoiceDate = invoice.getItemValueDate("invoice.date");
|
Date invoiceDate = invoice.getItemValueDate("invoice.date");
|
||||||
Date paymentDate = findLastEventDate(invoice);
|
Date invoiceDueDate = invoice.getItemValueDate("invoice.duedate");
|
||||||
|
Date paymentDate = findPaymentDateByWorkitem(invoice);
|
||||||
|
if (paymentDate == null) {
|
||||||
|
// fall back method
|
||||||
|
logger.warning("Es wurde kein Zahlungseingang gefunden");
|
||||||
|
// paymentDate = findPaymentDateByLog(invoice);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (invoiceDate != null && paymentDate != null) {
|
if (invoiceDate != null && paymentDate != null && invoiceDueDate != null) {
|
||||||
// do we have a stats object?
|
// do we have a stats object?
|
||||||
DebitorStatistikData statData = stats.get(getYearMonth(invoiceDate));
|
DebitorStatistikData statData = stats.get(getYearMonth(invoiceDate));
|
||||||
if (statData == null) {
|
if (statData == null) {
|
||||||
|
|
@ -172,6 +194,7 @@ public class DebitorStatistikController implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
// jetzt irgendwas ausrechnen
|
// jetzt irgendwas ausrechnen
|
||||||
|
statData.compute(invoiceDate, invoiceDueDate, paymentDate);
|
||||||
|
|
||||||
// .. und wieder speichern
|
// .. und wieder speichern
|
||||||
stats.put(statData.toString(), statData);
|
stats.put(statData.toString(), statData);
|
||||||
|
|
@ -189,8 +212,53 @@ public class DebitorStatistikController implements Serializable {
|
||||||
logger.severe("Failed to get statistic: " + e.getMessage());
|
logger.severe("Failed to get statistic: " + e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Step 2: Sort the list based on the alphanumeric order of the keys
|
||||||
|
|
||||||
|
// stats = new TreeMap<>(stats);
|
||||||
|
completeMissingMonths();
|
||||||
|
return stats;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hilfsmethode ergänzt die fehlenden Monate
|
||||||
|
*
|
||||||
|
* @param yearMonths
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private void completeMissingMonths() {
|
||||||
|
if (stats == null || stats.size() < 3) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the list of strings to a list of LocalDate objects
|
||||||
|
List<LocalDate> dates = new ArrayList<>();
|
||||||
|
Set<String> yearMonths = this.stats.keySet();
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMM");
|
||||||
|
for (String yearMonth : yearMonths) {
|
||||||
|
dates.add(YearMonth.parse(yearMonth, formatter).atDay(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the lowest and highest dates
|
||||||
|
LocalDate lowestDate = Collections.min(dates);
|
||||||
|
LocalDate highestDate = Collections.max(dates);
|
||||||
|
|
||||||
|
LocalDate current = lowestDate;
|
||||||
|
current = current.plusMonths(1);
|
||||||
|
while (!current.isAfter(highestDate)) {
|
||||||
|
|
||||||
|
// existiert der monat?
|
||||||
|
String formattedDate = current.format(formatter);
|
||||||
|
DebitorStatistikData entry = stats.get(formattedDate);
|
||||||
|
if (entry == null) {
|
||||||
|
// add missing entry
|
||||||
|
stats.put(formattedDate, new DebitorStatistikData(current.getYear(), current.getMonthValue()));
|
||||||
|
}
|
||||||
|
current = current.plusMonths(1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* returns
|
* returns
|
||||||
*
|
*
|
||||||
|
|
@ -214,7 +282,49 @@ public class DebitorStatistikController implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the date when a workitem last reached the current task
|
* Finds the payment.date for a invoice.
|
||||||
|
*
|
||||||
|
* Wir suchen alle zugeordneten Zahlungseingägne und nehmen den letzten.
|
||||||
|
*
|
||||||
|
* WICHTIG: Es muss ggf. der index neu aufgebaut werden, da payment.date nun ein
|
||||||
|
* index feld ist
|
||||||
|
*
|
||||||
|
* @param invoice
|
||||||
|
* @return
|
||||||
|
* @throws ParseException
|
||||||
|
*/
|
||||||
|
public Date findPaymentDateByWorkitem(ItemCollection invoice) throws ParseException {
|
||||||
|
|
||||||
|
// Wir selektieren alle Zahlungseingänge interessieren usn aber nur für den
|
||||||
|
// letzten
|
||||||
|
String sQuery = " (type:\"workitem\" OR type:\"workitemarchive\") " + //
|
||||||
|
" AND ($workflowgroup:Zahlungseingang) AND ($workitemref:\""
|
||||||
|
+ invoice.getUniqueID() + "\" )";
|
||||||
|
|
||||||
|
List<ItemCollection> workitems = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
workitems = documentService.findStubs(sQuery, 99, 0,
|
||||||
|
"payment.date", true);
|
||||||
|
if (workitems.size() > 0) {
|
||||||
|
return workitems.get(0).getItemValueDate("payment.date");
|
||||||
|
}
|
||||||
|
} catch (QueryException e) {
|
||||||
|
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
// no date found!
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the date when a workitem last reached the current task 5900 by reading
|
||||||
|
* the eventLog
|
||||||
|
*
|
||||||
|
* This method is not so save as the method findPaymentDateByWorkitem that is
|
||||||
|
* searching the payment workitem.
|
||||||
*
|
*
|
||||||
* 2023-06-28T12:40:17.437|rechnungsausgang-de-1.0|5001.50|5900|
|
* 2023-06-28T12:40:17.437|rechnungsausgang-de-1.0|5001.50|5900|
|
||||||
*
|
*
|
||||||
|
|
@ -222,7 +332,7 @@ public class DebitorStatistikController implements Serializable {
|
||||||
* @return
|
* @return
|
||||||
* @throws ParseException
|
* @throws ParseException
|
||||||
*/
|
*/
|
||||||
public Date findLastEventDate(ItemCollection invoice) throws ParseException {
|
public Date findPaymentDateByLog(ItemCollection invoice) throws ParseException {
|
||||||
|
|
||||||
// Create a SimpleDateFormat instance with the desired format
|
// Create a SimpleDateFormat instance with the desired format
|
||||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
|
||||||
|
|
@ -248,4 +358,92 @@ public class DebitorStatistikController implements Serializable {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Diese Methode baut die Datenstruktur für das Chart Diagram zusammen
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
{
|
||||||
|
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||||
|
datasets: [{
|
||||||
|
label: 'Dataset 1',
|
||||||
|
//backgroundColor: color(window.chartColors.red).alpha(0.5).rgbString(),
|
||||||
|
//borderColor: window.chartColors.red,
|
||||||
|
borderWidth: 1,
|
||||||
|
data: [
|
||||||
|
70, 70, 70, 70, 79, 50, 50
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
label: 'Dataset 2',
|
||||||
|
//backgroundColor: color(window.chartColors.blue).alpha(0.5).rgbString(),
|
||||||
|
//borderColor: window.chartColors.blue,
|
||||||
|
borderWidth: 1,
|
||||||
|
data: [
|
||||||
|
70, 70, 170, 7, 79, 50, 50
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String buildChartData() {
|
||||||
|
|
||||||
|
getStats();
|
||||||
|
|
||||||
|
// build a list of all lables....
|
||||||
|
List<String> statusLabels = new ArrayList<String>();
|
||||||
|
|
||||||
|
Set<String> keys = stats.keySet();
|
||||||
|
for (String _key : keys) {
|
||||||
|
statusLabels.add(_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
String result = "{";
|
||||||
|
|
||||||
|
// Lables
|
||||||
|
result = result + "labels : [ ";
|
||||||
|
result = result + statusLabels.stream().collect(Collectors.joining("','", "'", "'"));
|
||||||
|
result = result + "],";
|
||||||
|
result = result + "datasets: [";
|
||||||
|
|
||||||
|
// Datasets 1
|
||||||
|
result = result + "{label: 'Zahlungsziel',borderWidth: 1,";
|
||||||
|
result = result + " \"backgroundColor\" : [\"#EBA05F\"],";
|
||||||
|
|
||||||
|
result = result + "data: [";
|
||||||
|
for (Map.Entry<String, DebitorStatistikData> entry : stats.entrySet()) {
|
||||||
|
result = result + entry.getValue().getAverageDueDays() + ",";
|
||||||
|
}
|
||||||
|
// cut last comma
|
||||||
|
result = result.substring(0, result.length() - 1);
|
||||||
|
result = result + "]";
|
||||||
|
result = result + "}, ";
|
||||||
|
|
||||||
|
// Datasets 2
|
||||||
|
result = result + "{label: 'Zahldauer',borderWidth: 1,";
|
||||||
|
result = result + " \"backgroundColor\" : [\"#70B088\" ],";
|
||||||
|
|
||||||
|
result = result
|
||||||
|
+ " trendlineLinear: { colorMin: \"red\", colorMax: \"green\", lineStyle: \"dotted\", width: 2 , projection: true },";
|
||||||
|
|
||||||
|
// result = result
|
||||||
|
// + "trendlineLinear: {colorMin: \"red\",colorMax: \"green\", lineStyle:
|
||||||
|
// \"dotted\",width: 2,projection: true},";
|
||||||
|
|
||||||
|
result = result + "data: [";
|
||||||
|
for (Map.Entry<String, DebitorStatistikData> entry : stats.entrySet()) {
|
||||||
|
result = result + entry.getValue().getAveragePaymentDays() + ",";
|
||||||
|
}
|
||||||
|
// cut last comma
|
||||||
|
result = result.substring(0, result.length() - 1);
|
||||||
|
result = result + "]";
|
||||||
|
result = result + "} ";
|
||||||
|
|
||||||
|
// ende
|
||||||
|
result = result + "] }";
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,18 +2,20 @@ package com.alexanderlogistics;
|
||||||
|
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Speichert Payment statistik
|
* Speichert Payment statistik
|
||||||
*/
|
*/
|
||||||
public class DebitorStatistikData {
|
public class DebitorStatistikData {
|
||||||
|
private static Logger logger = Logger.getLogger(DebitorStatistikData.class.getName());
|
||||||
|
|
||||||
int month;
|
int month;
|
||||||
int year;
|
int year;
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int paymentTime; // Zahlungsziel
|
int averageDueDays; // Zahlungsziel
|
||||||
int paymentDays; // Tatsächliche Zahlung
|
int averagePaymentDays; // Tatsächliche Zahlung
|
||||||
|
|
||||||
public DebitorStatistikData(Date date) {
|
public DebitorStatistikData(Date date) {
|
||||||
// Create a Calendar instance and set the date
|
// Create a Calendar instance and set the date
|
||||||
|
|
@ -40,8 +42,40 @@ public class DebitorStatistikData {
|
||||||
* @param invoiceDate
|
* @param invoiceDate
|
||||||
* @param paymentDate
|
* @param paymentDate
|
||||||
*/
|
*/
|
||||||
public void compute(Date invoiceDate, Date paymentDate) {
|
public void compute(Date invoiceDate, Date invoiceDueDate, Date paymentDate) {
|
||||||
// und was nun?
|
// und was nun?
|
||||||
|
count++;
|
||||||
|
|
||||||
|
logger.info("...invoiceDate= " + invoiceDate);
|
||||||
|
logger.info("...invoiceDueDate= " + invoiceDueDate);
|
||||||
|
logger.info("...paymentDate= " + paymentDate);
|
||||||
|
|
||||||
|
// Fälligkeit in Tagen
|
||||||
|
long milliseconds1 = invoiceDate.getTime();
|
||||||
|
long milliseconds2 = invoiceDueDate.getTime();
|
||||||
|
// Berechnen Sie die Differenz in Millisekunden
|
||||||
|
long diffMilliseconds = milliseconds2 - milliseconds1;
|
||||||
|
long dueTime = diffMilliseconds / (24 * 60 * 60 * 1000);
|
||||||
|
logger.info("...Fälligkeit in tagen= " + dueTime);
|
||||||
|
averageDueDays = (int) (averageDueDays + dueTime / count);
|
||||||
|
|
||||||
|
// Bezahlt nach Tagen
|
||||||
|
milliseconds1 = invoiceDate.getTime();
|
||||||
|
milliseconds2 = paymentDate.getTime();
|
||||||
|
// Berechnen Sie die Differenz in Millisekunden
|
||||||
|
diffMilliseconds = milliseconds2 - milliseconds1;
|
||||||
|
long paymentTime = diffMilliseconds / (24 * 60 * 60 * 1000);
|
||||||
|
logger.info("...Zahlung erfolgte nach tagen= " + paymentTime);
|
||||||
|
averagePaymentDays = (int) (averagePaymentDays + paymentTime / count);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAverageDueDays() {
|
||||||
|
return averageDueDays;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAveragePaymentDays() {
|
||||||
|
return averagePaymentDays;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@
|
||||||
lucence.indexDir=${imixs-office.IndexDir}
|
lucence.indexDir=${imixs-office.IndexDir}
|
||||||
index.fields=txtsearchstring,txtSubject,txtname,txtEmail,txtUserName,namCreator,txtworkflowgroup,txtworkflowstatus,txtWorkflowAbstract,txtWorkflowSummary,txtworkflowhistory,txtspacename,txtprocessname,_subject,_description,_name,_projectnumber,_projectname,_ordernumber,_contractnumber,datDueDate,txtcommentlog,htmldescription,htmldocumentation,dms,dms_names,invoice.number.stripped,_childitems,$file.names,_VENDOR_NAME,dbtr.number,cdtr.number
|
index.fields=txtsearchstring,txtSubject,txtname,txtEmail,txtUserName,namCreator,txtworkflowgroup,txtworkflowstatus,txtWorkflowAbstract,txtWorkflowSummary,txtworkflowhistory,txtspacename,txtprocessname,_subject,_description,_name,_projectnumber,_projectname,_ordernumber,_contractnumber,datDueDate,txtcommentlog,htmldescription,htmldocumentation,dms,dms_names,invoice.number.stripped,_childitems,$file.names,_VENDOR_NAME,dbtr.number,cdtr.number
|
||||||
index.fields.analyze=txtUsername
|
index.fields.analyze=txtUsername
|
||||||
index.fields.noanalyze=type,$UniqueIDRef,$created,$modified,$ModelVersion,$participants,namCreator,$ProcessID,datDate,txtWorkflowGroup,txtemail, datdate, datfrom, datto, numsequencenumber,dms_count,invoice.number,invoice.number.stripped,invoice.duedate,taxonomy.verteilung.stop,taxonomy.sachpruefung.stop,taxonomy.verteilung.start,taxonomy.sachpruefung.start,taxonomy.buchhaltung.start,taxonomy.buchhaltung.stop,dbtr.number,cdtr.number
|
index.fields.noanalyze=type,$UniqueIDRef,$created,$modified,$ModelVersion,$participants,namCreator,$ProcessID,datDate,txtWorkflowGroup,txtemail, datdate, datfrom, datto, numsequencenumber,dms_count,invoice.number,invoice.number.stripped,invoice.date,invoice.duedate,taxonomy.verteilung.stop,taxonomy.sachpruefung.stop,taxonomy.verteilung.start,taxonomy.sachpruefung.start,taxonomy.buchhaltung.start,taxonomy.buchhaltung.stop,dbtr.number,cdtr.number,payment.date
|
||||||
index.fields.store=process.name,txtProcessName,txtWorkflowImageURL
|
index.fields.store=process.name,txtProcessName,txtWorkflowImageURL,payment.date,invoice.number,invoice.date,invoice.duedate
|
||||||
index.fields.category=space.name,space.ref,taxonomy.verteilung.stop.by,taxonomy.sachpruefung.stop.by,taxonomy.buchhaltung.stop.by
|
index.fields.category=space.name,space.ref,taxonomy.verteilung.stop.by,taxonomy.sachpruefung.stop.by,taxonomy.buchhaltung.stop.by
|
||||||
office.search.noanalyze=invoice.number,invoice.number.stripped
|
office.search.noanalyze=invoice.number,invoice.number.stripped
|
||||||
|
|
||||||
|
|
|
||||||
18
office-alexander-logistics-app/src/main/webapp/js/chartjs-plugin-trendline.min.js
vendored
Normal file
18
office-alexander-logistics-app/src/main/webapp/js/chartjs-plugin-trendline.min.js
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
/**
|
||||||
|
* Minified by jsDelivr using Terser v5.17.1.
|
||||||
|
* Original file: /npm/chartjs-plugin-trendline@2.0.3/src/chartjs-plugin-trendline.js
|
||||||
|
*
|
||||||
|
* Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
|
||||||
|
*/
|
||||||
|
/*!
|
||||||
|
* chartjs-plugin-trendline.js
|
||||||
|
* Version: 2.0.3
|
||||||
|
*
|
||||||
|
* Copyright 2023 Marcus Alsterfjord
|
||||||
|
* Released under the MIT license
|
||||||
|
* https://github.com/Makanz/chartjs-plugin-trendline/blob/master/README.md
|
||||||
|
*
|
||||||
|
* Mod by: vesal: accept also xy-data so works with scatter
|
||||||
|
*/
|
||||||
|
var pluginTrendlineLinear={id:"chartjs-plugin-trendline",afterDatasetsDraw:function(t){var i,e;for(var s in t.scales)if("x"==s[0]?e=t.scales[s]:i=t.scales[s],e&&i)break;var a=t.ctx;t.data.datasets.forEach((function(i,s){var n=i.alwaysShowTrendline||t.isDatasetVisible(s);if(i.trendlineLinear&&n&&i.data.length>1){var r=t.getDatasetMeta(s);addFitter(r,a,i,e,t.scales[r.yAxisID])}})),a.setLineDash([])}};function addFitter(t,i,e,s,a){var n=e.borderColor||"rgba(169,169,169, .6)",r=e.trendlineLinear.colorMin||n,o=e.trendlineLinear.colorMax||n,l=e.trendlineLinear.width||e.borderWidth,h=e.trendlineLinear.lineStyle||"solid",u=e.trendlineLinear.fillColor;l=void 0!==l?l:3;var d=new LineFitter,m=e.data.findIndex((t=>null!=t)),c=e.data.length-1,x=t.data[m].x,f=t.data[c].x,X="object"==typeof e.data[m];e.data.forEach((function(t,i){if(null!=t)if(["time","timeseries"].includes(s.options.type)){var e=null!=t.x?t.x:t.t;d.add(new Date(e).getTime(),t.y)}else X?isNaN(t.x)||isNaN(t.y)?isNaN(t.x)?isNaN(t.y)||d.add(i,t.y):d.add(i,t.x):d.add(t.x,t.y):d.add(i,t)}));var p,g,v=s.getPixelForValue(d.minx),y=a.getPixelForValue(d.f(d.minx));if(e.trendlineLinear.projection&&d.scale()<0){var w=d.fo();w<d.minx&&(w=d.maxx),p=s.getPixelForValue(w),g=a.getPixelForValue(d.f(w))}else p=s.getPixelForValue(d.maxx),g=a.getPixelForValue(d.f(d.maxx));X||(v=x,p=f);var L=t.controller.chart.chartArea.bottom,F=t.controller.chart.width;if(y>L){var Y=y-L,T=y-g;y=L,v+=F*(Y/T)}else if(g>L){Y=g-L,T=g-y;g=L,p=F-(p-(F-F*(Y/T)))}i.lineWidth=l,"dotted"===h&&i.setLineDash([2,3]),i.beginPath(),i.moveTo(v,y),i.lineTo(p,g);var P=i.createLinearGradient(v,y,p,g);g<y?(P.addColorStop(0,o),P.addColorStop(1,r)):(P.addColorStop(0,r),P.addColorStop(1,o)),i.strokeStyle=P,i.stroke(),i.closePath(),u&&(i.fillStyle=u,i.beginPath(),i.moveTo(v,y),i.lineTo(p,g),i.lineTo(p,L),i.lineTo(v,L),i.closePath(),i.fill())}function LineFitter(){this.count=0,this.sumX=0,this.sumX2=0,this.sumXY=0,this.sumY=0,this.minx=1e100,this.maxx=-1e100,this.maxy=-1e100}LineFitter.prototype={add:function(t,i){t=parseFloat(t),i=parseFloat(i),this.count++,this.sumX+=t,this.sumX2+=t*t,this.sumXY+=t*i,this.sumY+=i,t<this.minx&&(this.minx=t),t>this.maxx&&(this.maxx=t),i>this.maxy&&(this.maxy=i)},f:function(t){t=parseFloat(t);var i=this.count*this.sumX2-this.sumX*this.sumX;return(this.sumX2*this.sumY-this.sumX*this.sumXY)/i+t*((this.count*this.sumXY-this.sumX*this.sumY)/i)},fo:function(){var t=this.count*this.sumX2-this.sumX*this.sumX;return-((this.sumX2*this.sumY-this.sumX*this.sumXY)/t)/((this.count*this.sumXY-this.sumX*this.sumY)/t)},scale:function(){var t=this.count*this.sumX2-this.sumX*this.sumX;return(this.count*this.sumXY-this.sumX*this.sumY)/t}},"undefined"!=typeof window&&window.Chart&&(window.Chart.hasOwnProperty("register")?window.Chart.register(pluginTrendlineLinear):window.Chart.plugins.register(pluginTrendlineLinear));try{module.exports=exports=pluginTrendlineLinear}catch(t){}
|
||||||
|
//# sourceMappingURL=/sm/a0bca30b6b7f4fbdef5c66a04bd36e4926fa058e81cc14753a8b9dbb36676c5d.map
|
||||||
|
|
@ -49,25 +49,43 @@
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</h:panelGroup>
|
</h:panelGroup>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Chart Diagramm -->
|
||||||
|
<div id="container" style="width: 75%;">
|
||||||
|
<canvas id="canvas"></canvas>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript"
|
||||||
|
src="#{facesContext.externalContext.requestContextPath}/js/chartjs/chart.min.js?build=#{app.application_build_timestamp}"></script>
|
||||||
|
<script type="text/javascript"
|
||||||
|
src="#{facesContext.externalContext.requestContextPath}/js/chartjs-plugin-trendline.min.js?build=#{app.application_build_timestamp}"></script>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
/*<![CDATA[*/
|
/*<![CDATA[*/
|
||||||
|
var barChartData = #{ debitorStatistikController.buildChartData() };
|
||||||
$(document).ready(
|
$(document).ready(
|
||||||
function () {
|
function () {
|
||||||
// update the checkboxes of the stored invoice uniqueIDs
|
|
||||||
// updateInvoiceSelection();
|
// update the diagram
|
||||||
|
var ctx = document.getElementById("canvas").getContext("2d");
|
||||||
|
window.myBar = new Chart(ctx, {
|
||||||
|
type: 'bar',
|
||||||
|
data: barChartData,
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
legend: {
|
||||||
|
position: 'top',
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: 'Zahlungsstatistik'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*]]>*/
|
/*]]>*/
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue