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,20 @@
package de.stadtbote.votian;
import de.stadtbote.votian.database.DatabaseService;
import java.util.*;
import static de.stadtbote.votian.AdminSupport.*;
import static de.stadtbote.votian.LegacyMapping.*;
import static de.stadtbote.votian.OrderEntryService.fields;
/** Explicit PHP contact-column settings; native defaults remain available without configuration. */
final class ContactPresentation {
record Settings(List<Integer> header,List<Integer> body,List<Integer> sort){}
static Settings settings(DatabaseService db){var c=new OrderEntryCatalog(db);return new Settings(ContactVcard.positions(c.parameter(0,"MASK_CONTACT_HEADER_FIELDS_DISPLAYED"),2),ContactVcard.positions(c.parameter(0,"MASK_CONTACT_BODY_FIELDS_DISPLAYED"),200),ContactVcard.positions(c.parameter(0,"MASK_CONTACT_SORT_FIELDS"),200));}
static List<Map<String,Object>> ordered(List<Map<String,Object>> definitions,List<Map<String,Object>> values){
var byId=new HashMap<Long,Map<String,Object>>();for(var value:values)if(byId.put(id(value,"fieldId"),value)!=null)throw bad("Doppelte Kontaktfelder im Bestand. Bitte zuerst bereinigen.");
return definitions.stream().map(d->{var row=byId.get(id(d,"id"));return row!=null?row:fields("fieldId",id(d,"id"),"label",text(d,"label"),"type",text(d,"type"),"value","");}).toList();
}
static String value(List<Map<String,Object>> fields,int index){return index<fields.size()?text(fields.get(index),"value"):"";}
static String title(Settings s,List<Map<String,Object>> values){return s.header().isEmpty()?"":String.join(", ",s.header().stream().map(i->value(values,i)).filter(v->!v.isBlank()).toList());}
static List<Long> body(Settings s,List<Map<String,Object>> values){return s.body().isEmpty()?null:java.util.stream.IntStream.range(0,values.size()).filter(s.body()::contains).mapToObj(i->id(values.get(i),"fieldId")).toList();}
static String sort(Settings s,List<Map<String,Object>> values,long contact){return s.sort().isEmpty()?ContactService.contactName(values).toLowerCase(Locale.ROOT):String.join(":",s.sort().stream().map(i->value(values,i)).toList())+":"+contact;}
}