L13 Planung: Datenmodell (Kolonnenkapazität, Dauer, Geocoding-Cache) und Planungsregeln

Migration 20260915120000_planung (nur Spalten): Team.dailyCapacityMinutes/workingDays, OrderType.defaultDurationMinutes (+ Backfill Standardarten), WorkOrder.plannedDurationMinutes, Site.geocodedAt/geocodeStatus/geocodeQuery. Client-sichere Regeln: Haversine, Tage/Werktage, Dauer, Kolonnenkapazität, Konflikte inkl. Hinweis crew_incomplete, Vereinigung von Arbeitssegmenten, Fahrzeitschätzung.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-15 10:13:18 +02:00
co-authored by Claude Opus 5
parent d3bc7f2d29
commit 604f2bfdc5
7 changed files with 424 additions and 10 deletions
@@ -0,0 +1,32 @@
-- L13 Planung: capacity planning + geocoding cache. Columns only (no new table → RLS unchanged,
-- no TENANT_MODELS change). No personal references (no DSGVO pii-fields change).
-- AlterTable
ALTER TABLE "order_types" ADD COLUMN "default_duration_minutes" INTEGER;
-- AlterTable
ALTER TABLE "sites" ADD COLUMN "geocode_query" TEXT,
ADD COLUMN "geocode_status" TEXT,
ADD COLUMN "geocoded_at" TIMESTAMP(3);
-- AlterTable
-- Team = crew (Kolonne): capacity is the crew's working day in minutes, not person-hours.
ALTER TABLE "teams" ADD COLUMN "daily_capacity_minutes" INTEGER NOT NULL DEFAULT 480,
ADD COLUMN "working_days" INTEGER NOT NULL DEFAULT 31;
-- AlterTable
ALTER TABLE "work_orders" ADD COLUMN "planned_duration_minutes" INTEGER;
-- Backfill: default durations of the standard order types (spec §10.2) for existing tenants.
UPDATE "order_types" SET "default_duration_minutes" = CASE "key"
WHEN 'montage' THEN 480
WHEN 'reparatur' THEN 180
WHEN 'wartung' THEN 120
WHEN 'stoerung' THEN 120
WHEN 'notdienst' THEN 120
WHEN 'besichtigung' THEN 60
WHEN 'abnahme' THEN 60
WHEN 'nacharbeit' THEN 120
END
WHERE "default_duration_minutes" IS NULL
AND "key" IN ('montage', 'reparatur', 'wartung', 'stoerung', 'notdienst', 'besichtigung', 'abnahme', 'nacharbeit');
+14 -1
View File
@@ -472,6 +472,8 @@ model OrderType {
active Boolean @default(true)
signatureRequired Boolean @default(true) @map("signature_required")
sortOrder Int @default(0) @map("sort_order")
// L13 Planung: default duration for capacity planning when the order has no own duration
defaultDurationMinutes Int? @map("default_duration_minutes")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
@@ -597,6 +599,11 @@ model Site {
status SiteStatus @default(active)
latitude Float?
longitude Float?
// L13 Planung: geocoding cache (services/geo) — status ok | not_found | failed | skipped,
// geocodeQuery = normalized address the coordinates belong to (change detection)
geocodedAt DateTime? @map("geocoded_at")
geocodeStatus String? @map("geocode_status")
geocodeQuery String? @map("geocode_query")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
deletedAt DateTime? @map("deleted_at")
@@ -627,6 +634,10 @@ model Team {
vehicle String?
area String?
notes String?
// L13 Planung: a team is a crew (Kolonne) working together — capacity = crew working day in minutes
// (not person-hours); workingDays = bit mask Mon=1 … Sun=64 (31 = Mo–Fr)
dailyCapacityMinutes Int @default(480) @map("daily_capacity_minutes")
workingDays Int @default(31) @map("working_days")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
deletedAt DateTime? @map("deleted_at")
@@ -700,7 +711,9 @@ model WorkOrder {
scope String? // Leistungsumfang
plannedStart DateTime? @map("planned_start")
plannedEnd DateTime? @map("planned_end")
assignedTeamId String? @map("assigned_team_id")
// L13 Planung: explicit duration; fallback plannedStart/End → OrderType.defaultDurationMinutes → 120
plannedDurationMinutes Int? @map("planned_duration_minutes")
assignedTeamId String? @map("assigned_team_id")
teamLeadUserId String? @map("team_lead_user_id")
signatureRequired Boolean @default(true) @map("signature_required")
billingType String? @map("billing_type") // fixed | time_material | maintenance_contract | warranty