Folgezähler-Deklaration in der Kundenakte (Auto-Propagation)

- Meter.predecessorMeterId (Self-Relation) + Migration
  20260530140000_meter_predecessor mit IF NOT EXISTS
- createMeter akzeptiert optional successorOf:
  {predecessorMeterId, installedAt?, finalReadingPrevious?}.
  Vorgänger wird validiert (gleicher Kunde + Typ); alle Verträge
  mit dem Vorgänger als aktuellen Zähler werden analog zu
  addSuccessorMeter automatisch auf den neuen Zähler umgestellt
  (ContractMeter-Eintrag mit removedAt/finalReading für den
  Vorgänger, neuer ContractMeter mit installedAt + nächster
  Position, energyDetails.meterId aktualisiert)
- MeterModal: Checkbox "Als Folgezähler deklarieren" + Dropdown
  Vorgänger + Wechseldatum + Endstand. Typ/Tarifmodell/Adresse
  werden vom Vorgänger übernommen und disabled. Info-Banner über
  Vertragsauto-Update

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-30 13:48:23 +02:00
parent 6f378d750c
commit ad4c2bae1d
6 changed files with 278 additions and 5 deletions
@@ -0,0 +1,46 @@
-- Folgezähler-Kette: Meter zeigt optional auf den Vorgänger.
-- Beim Wechsel können wir dann sowohl die Kette für die UI anzeigen
-- als auch alle Verträge mit dem Vorgänger automatisch auf den
-- Nachfolger umstellen.
--
-- ON DELETE SET NULL, damit ein versehentlich gelöschter Vorgänger
-- den Nachfolger nicht killt.
--
-- IF NOT EXISTS macht den Re-Deploy auf Prod sicher, falls jemand
-- schon `prisma db push` gefahren hat.
ALTER TABLE `Meter`
ADD COLUMN IF NOT EXISTS `predecessorMeterId` INT NULL;
-- Index nur anlegen, wenn er noch nicht da ist
SET @idx_exists := (
SELECT COUNT(*) FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'Meter'
AND INDEX_NAME = 'Meter_predecessorMeterId_fkey'
);
SET @sql := IF(
@idx_exists = 0,
'CREATE INDEX `Meter_predecessorMeterId_fkey` ON `Meter`(`predecessorMeterId`)',
'SELECT "Index existiert bereits"'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- Foreign Key nur anlegen, wenn er noch nicht da ist
SET @fk_exists := (
SELECT COUNT(*) FROM information_schema.TABLE_CONSTRAINTS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'Meter'
AND CONSTRAINT_NAME = 'Meter_predecessorMeterId_fkey'
AND CONSTRAINT_TYPE = 'FOREIGN KEY'
);
SET @sql := IF(
@fk_exists = 0,
'ALTER TABLE `Meter` ADD CONSTRAINT `Meter_predecessorMeterId_fkey` FOREIGN KEY (`predecessorMeterId`) REFERENCES `Meter`(`id`) ON DELETE SET NULL ON UPDATE CASCADE',
'SELECT "FK existiert bereits"'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;