Erweitere VoTiAn NG um Fachfunktionen und verbessere die Listenoberfläche

Ergänze Auftragsbearbeitung, Disposition, Stammdaten, Kunden- und
Transporteurportale, Lagerverwaltung, Abrechnung, Exporte und Statistik.
Füge Kontoeinstellungen, Mitteilungen, Automatikdienste und Betriebsstatus
sowie die zugehörigen Tests und PHP-Abgleichsdokumentation hinzu.

Vergrößere die persönlichen Auftragslisten auf einheitliche Höhen und
richte Statusanzeigen sowie die Ranking-Vorschau-Steuerelemente bündig aus.

Validierung: 44 Frontendtests und Produktionsbuild erfolgreich.
Backend funktional unverändert gegenüber dem vollständigen Lauf mit 1.624
erfolgreichen und drei übersprungenen Tests. Layout im Browser und lokale
Bereitstellung geprüft.
This commit is contained in:
Sven committed 2026-10-20 11:19:43 +02:00
1 parent 363bc27c26
commit 781a2b82dc
1165 files changed
+74986 -1028

No files matched your search

@@ -0,0 +1,28 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import {statisticsAmountColumns,statisticsAmountOptions} from '../src/statisticsAmountColumns.mjs';
import {statisticsMetric} from '../src/statisticsChartData.mjs';
test('each PHP amount choice keeps only its amount column',()=>{
for(const key of Object.keys(statisticsAmountOptions).filter(k=>k!=='ALL'))assert.deepEqual(statisticsAmountColumns({displayMetric:key}).map(c=>c.key),[key]);
assert.equal(statisticsAmountColumns({displayMetric:'ratio'})[0].kind,'percent');
assert.equal(statisticsAmountColumns({displayMetric:'kilometers'})[0].kind,'number');
assert.equal(statisticsAmountColumns({displayMetric:'co2eKg'})[0].kind,'number');
});
test('all values and older results include EAU and BSG in detail rows',()=>{
const keys=['revenue','courierRevenue','margin','ratio','serviceRevenue','fuelMarkup','courierService','kilometers','co2eKg'];
for(const displayMetric of [undefined,'ALL','unknown'])assert.deepEqual(statisticsAmountColumns({displayMetric}).map(c=>c.key),keys);
});
test('separate fuel columns follow the selected price basis without duplicates',()=>{
for(const [displayMetric,extra] of [['revenue','fuelMarkup'],['courierRevenue','courierFuelMarkup'],['margin','fuelMargin']])assert.deepEqual(statisticsAmountColumns({displayMetric,separateFuel:true}).map(c=>c.key),[displayMetric,extra]);
const all=statisticsAmountColumns({displayMetric:'ALL',separateFuel:true}).map(c=>c.key);assert.equal(new Set(all).size,all.length);
assert.deepEqual(statisticsAmountColumns({displayMetric:'kilometers',separateFuel:true}).map(c=>c.key),['kilometers']);
});
test('amount cells preserve unknown values and use aggregate BSG instead of averaging row ratios',()=>{
const rows=[{revenue:100,courierRevenue:50},{revenue:900,courierRevenue:810}];
assert.ok(Math.abs(statisticsMetric({revenue:1000,courierRevenue:860},'ratio')-14)<1e-10);
assert.notEqual((statisticsMetric(rows[0],'ratio')+statisticsMetric(rows[1],'ratio'))/2,14);
assert.equal(statisticsMetric({revenue:100,courierRevenue:null},'margin'),null);
assert.equal(statisticsMetric({revenue:0,courierRevenue:0},'ratio'),null);
assert.equal(statisticsMetric({co2eKg:0},'co2eKg'),0);
});