diff --git a/backend/src/controllers/contract.controller.ts b/backend/src/controllers/contract.controller.ts index 17fa3247..730b58c5 100644 --- a/backend/src/controllers/contract.controller.ts +++ b/backend/src/controllers/contract.controller.ts @@ -539,7 +539,7 @@ export async function getCockpit(req: AuthRequest, res: Response): Promise export async function addSuccessorMeter(req: AuthRequest, res: Response): Promise { try { const contractId = parseInt(req.params.id); - const { meterId, installedAt, finalReadingPrevious } = req.body; + const { meterId, installedAt, finalReadingPrevious, deactivatePredecessor } = req.body; const contract = await prisma.contract.findUnique({ where: { id: contractId }, @@ -648,6 +648,15 @@ export async function addSuccessorMeter(req: AuthRequest, res: Response): Promis ); } + // Alten Zähler deaktivieren (Default), sofern der Aufrufer das nicht + // explizit auf false setzt – ein-klick-fähiger Zählerwechsel. + if (predecessorMeterId && deactivatePredecessor !== false) { + await prisma.meter.update({ + where: { id: predecessorMeterId }, + data: { isActive: false }, + }); + } + await logChange({ req, action: 'CREATE', resourceType: 'ContractMeter', resourceId: contractMeter.id.toString(), diff --git a/backend/src/services/customer.service.ts b/backend/src/services/customer.service.ts index 5868e7f4..918f02d5 100644 --- a/backend/src/services/customer.service.ts +++ b/backend/src/services/customer.service.ts @@ -488,6 +488,10 @@ export async function createMeter( predecessorMeterId: number; installedAt?: string; finalReadingPrevious?: number; + // Default true im UI: alter Zähler wird nach dem Wechsel auf + // isActive=false gesetzt. Kann ausgeschaltet werden, wenn der alte + // Zähler aus irgendeinem Grund noch aktiv bleiben soll. + deactivatePredecessor?: boolean; }; } ) { @@ -622,6 +626,16 @@ export async function createMeter( data.successorOf.finalReadingPrevious, ); } + + // Alten Zähler deaktivieren (Default), sofern der Aufrufer das nicht + // explizit auf false setzt. Macht den typischen Zählerwechsel-Workflow + // ein-klick-fähig. + if (data.successorOf.deactivatePredecessor !== false) { + await prisma.meter.update({ + where: { id: predecessor.id }, + data: { isActive: false }, + }); + } } return created; diff --git a/frontend/src/pages/contracts/ContractDetail.tsx b/frontend/src/pages/contracts/ContractDetail.tsx index 10fa9995..ed90726f 100644 --- a/frontend/src/pages/contracts/ContractDetail.tsx +++ b/frontend/src/pages/contracts/ContractDetail.tsx @@ -361,6 +361,7 @@ function SuccessorMeterButton({ const [selectedMeterId, setSelectedMeterId] = useState(''); const [installedAt, setInstalledAt] = useState(new Date().toISOString().split('T')[0]); const [finalReading, setFinalReading] = useState(''); + const [deactivatePredecessor, setDeactivatePredecessor] = useState(true); const queryClient = useQueryClient(); const { data: metersData } = useQuery({ @@ -370,13 +371,14 @@ function SuccessorMeterButton({ }); const addMutation = useMutation({ - mutationFn: (data: { meterId: number; installedAt?: string; finalReadingPrevious?: number }) => + mutationFn: (data: { meterId: number; installedAt?: string; finalReadingPrevious?: number; deactivatePredecessor?: boolean }) => contractApi.addSuccessorMeter(contractId, data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['contract'] }); setShowForm(false); setSelectedMeterId(''); setFinalReading(''); + setDeactivatePredecessor(true); }, }); @@ -451,6 +453,15 @@ function SuccessorMeterButton({ erfasst und fließt damit in die Verbrauchsberechnung ein.

)} +