Initialisiere VoTiAn NG mit Docker-Build, .env-Konfiguration und Cookie-Sitzungen

This commit is contained in:
Sven committed 2026-10-05 17:45:38 +02:00
commit 1a30233269
63 files changed
+12138

No files matched your search

@@ -0,0 +1,75 @@
package de.stadtbote.votian;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import static de.stadtbote.votian.Models.*;
/** Mappings traced to include/mcglobal.inc.php and the corresponding PHP job/customer/courier modules. */
final class LegacyMapping {
private LegacyMapping() {}
static Object value(Map<String,Object> row,String key) {
Object result = row.get(key);
if (result == null) result = row.get(key.toUpperCase(java.util.Locale.ROOT));
return result;
}
static String text(Map<String,Object> row,String key) { Object v=value(row,key); return v==null ? "" : v.toString(); }
static long id(Map<String,Object> row,String key) {
Object v=value(row,key);
if(v==null || v.toString().isBlank()) return 0;
// JDBC may return Boolean for legacy TINYINT(1) flags, such as cmp_archived.
if(v instanceof Boolean flag) return flag ? 1 : 0;
return v instanceof Number n ? n.longValue() : Long.parseLong(v.toString());
}
static Long nullableId(Map<String,Object> row,String key) { long n=id(row,key); return n>0?n:null; }
static BigDecimal decimal(Map<String,Object> row,String key) { Object v=value(row,key); if(v==null || v.toString().isBlank()) return null; return v instanceof BigDecimal d ? d : new BigDecimal(v.toString()); }
static LocalDateTime dateTime(Map<String,Object> row,String key) {
Object v=value(row,key); if(v==null) return null;
if(v instanceof Timestamp t) return t.toLocalDateTime();
if(v instanceof LocalDateTime t) return t;
String s=v.toString(); if(s.isBlank() || s.startsWith("0000-")) return null;
if(s.matches("\\d{14}")) return LocalDateTime.parse(s,DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
return LocalDateTime.parse(s.replace(' ','T'));
}
static String join(String a,String b) { return (a+" "+b).trim(); }
static Customer customer(Map<String,Object> row) {
Customer c=new Customer();c.id=id(row,"cs_id");c.number=text(row,"cs_eid");c.name=text(row,"cmp_comp");
c.street=join(text(row,"ad_street"),text(row,"cmp_hsno"));c.postalCode=text(row,"ad_zipcode");c.city=text(row,"ad_city");
c.contact=join(text(row,"usr_firstname"),text(row,"usr_name"));c.phone=text(row,"usr_phone");c.email=text(row,"usr_email");
String days=text(row,"cs_payment_term");c.paymentDays=days.matches("\\d+")?Integer.valueOf(days):null;
c.active=id(row,"cmp_archived")==0 && id(row,"cmp_visible")==1 && id(row,"cmp_authenticated")==1;
return c;
}
static Courier courier(Map<String,Object> row) {
Courier c=new Courier();c.id=id(row,"cr_id");c.number=text(row,"cr_eid");c.name=text(row,"cmp_comp");
if(c.name.isBlank()) c.name=join(text(row,"usr_firstname"),text(row,"usr_name"));
c.phone=text(row,"usr_phone");c.vehicle=text(row,"vehicle_label");c.plate=text(row,"crvh_vh_sign");
c.active=id(row,"cmp_archived")==0 && id(row,"cmp_visible")==1 && id(row,"cmp_authenticated")==1;
c.status=!c.active?CourierStatus.OFFLINE:(id(row,"active_jobs")>0?CourierStatus.BUSY:(id(row,"cr_available")==1?CourierStatus.AVAILABLE:CourierStatus.OFFLINE));
return c;
}
static DeliveryOrder order(Map<String,Object> row) {
DeliveryOrder o=new DeliveryOrder();o.id=id(row,"jb_id");o.number=Long.toString(o.id);o.version=id(row,"jb_version");
o.customerId=nullableId(row,"app_customer_id");o.payerCustomerId=nullableId(row,"app_payer_customer_id");o.courierId=nullableId(row,"cr_id");
o.legacyStatus=(int)id(row,"jb_status");int storno=(int)id(row,"jb_storno");o.legacyStorno=storno;o.isCreditNote=storno==3||storno==4;
o.cancelMode=storno==1 || storno==3?CancelMode.CHARGEABLE:storno==2 || storno==4?CancelMode.FREE:null;
o.status=o.cancelMode!=null?OrderStatus.CANCELLED:switch(o.legacyStatus){case 0->OrderStatus.OFFERED;case 1->OrderStatus.IN_PROGRESS;case 2->OrderStatus.COMPLETED;default->OrderStatus.DISPOSITION;};
o.legacyStatusLabel=switch(o.legacyStatus){case 9->"Disposition";case 8->"Autoranking";case 0->"Offen / angeboten";case 1->"Laufend";case 2->"Erledigt";default->"Legacy-Status "+o.legacyStatus;};
if(o.cancelMode!=null) o.legacyStatusLabel=switch(storno){case 1->"Storniert · kostenpflichtig";case 2->"Storniert · kostenfrei";case 3->"Storno-Gutschrift · kostenpflichtiges Storno";case 4->"Storno-Gutschrift · kostenfreies Storno";default->"Storno";};
o.legacyService=id(row,"jb_service");o.service=text(row,"service_label");o.vehicle=text(row,"vehicle_label");
o.pickupAt=dateTime(row,"jb_ordertime");o.reference=text(row,"jb_commission_no");o.costCenter=text(row,"app_cost_center");o.notes=text(row,"jb_dispoinfo");
o.weight=decimal(row,"jb_weight");o.netPrice=decimal(row,"jb_totalprice");o.courierPrice=decimal(row,"jb_cr_price");o.vatRate=decimal(row,"jb_sales_tax_rate");
o.createdAt=dateTime(row,"jb_createtime");o.updatedAt=dateTime(row,"jb_modify");o.deliveredAt=dateTime(row,"jb_finishtime");
return o;
}
static Stop stop(Map<String,Object> row) {
Stop s=new Stop();s.id=id(row,"tr_id");s.sequence=(int)id(row,"tr_sort");
// Existing VoTiAn tour field is preserved through the explicit warehouse direction mapping.
s.type=switch((int)id(row,"tr_ware_from_to")){case 1->StopType.PICKUP;case 2->StopType.DELIVERY;case 3->StopType.BOTH;default->s.sequence==1?StopType.PICKUP:StopType.DELIVERY;};
s.name=join(text(row,"tr_comp"),text(row,"tr_comp2"));s.street=join(text(row,"ad_street"),text(row,"tr_hsno"));
s.postalCode=text(row,"ad_zipcode");s.city=text(row,"ad_city");s.contact=text(row,"tr_person");s.phone=text(row,"tr_phone");s.note=text(row,"tr_remark");
s.completedAt=id(row,"tr_status")==1?dateTime(row,"tr_finishtime"):null;s.recipientName=text(row,"tr_signname");return s;
}
}