Folgezähler-Forms: Checkbox "Alten Zähler deaktivieren" (default an)

Beide Folgezähler-Forms (Kundenakte MeterModal + Vertragsansicht
SuccessorMeterForm) bekommen eine Checkbox, die standardmäßig
angehakt ist. Beim Speichern wird der Vorgänger automatisch
auf isActive=false gesetzt – ein-klick-fähiger Zählerwechsel.

Backend: createMeter mit successorOf und addSuccessorMeter
akzeptieren deactivatePredecessor (Default true).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-30 14:39:05 +02:00
parent 3a9cece929
commit 2ee06630b9
5 changed files with 49 additions and 3 deletions
@@ -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.
</p>
)}
<label className="flex items-center gap-2 mt-3 text-sm">
<input
type="checkbox"
checked={deactivatePredecessor}
onChange={(e) => setDeactivatePredecessor(e.target.checked)}
className="rounded"
/>
Alten Zähler deaktivieren
</label>
<div className="flex gap-2 mt-3">
<Button
size="sm"
@@ -458,6 +469,7 @@ function SuccessorMeterButton({
meterId: parseInt(selectedMeterId),
installedAt,
finalReadingPrevious: finalReading ? parseFloat(finalReading) : undefined,
deactivatePredecessor,
})}
disabled={!selectedMeterId || addMutation.isPending}
>
@@ -2854,6 +2854,7 @@ function MeterModal({
predecessorMeterId: '',
installedAt: today,
finalReadingPrevious: '',
deactivatePredecessor: true,
});
const [formData, setFormData] = useState(getInitialFormData);
@@ -2919,6 +2920,7 @@ function MeterModal({
finalReadingPrevious: formData.finalReadingPrevious
? parseFloat(formData.finalReadingPrevious)
: undefined,
deactivatePredecessor: formData.deactivatePredecessor,
};
}
if (isEditing) {
@@ -3037,6 +3039,15 @@ function MeterModal({
onChange={(e) => setFormData({ ...formData, finalReadingPrevious: e.target.value })}
placeholder="Optional"
/>
<label className="flex items-center gap-2 text-sm">
<input
type="checkbox"
checked={formData.deactivatePredecessor}
onChange={(e) => setFormData({ ...formData, deactivatePredecessor: e.target.checked })}
className="rounded"
/>
Alten Zähler deaktivieren
</label>
<p className="text-xs text-blue-700">
Typ, Adresse und Tarifmodell werden vom Vorgänger übernommen. Alle Verträge,
die den Vorgänger-Zähler verwenden, werden automatisch auf diesen neuen Zähler
+1 -1
View File
@@ -837,7 +837,7 @@ export const contractApi = {
return res.data;
},
// Folgezähler
addSuccessorMeter: async (contractId: number, data: { meterId: number; installedAt?: string; finalReadingPrevious?: number }) => {
addSuccessorMeter: async (contractId: number, data: { meterId: number; installedAt?: string; finalReadingPrevious?: number; deactivatePredecessor?: boolean }) => {
const res = await api.post<ApiResponse<any>>(`/contracts/${contractId}/successor-meter`, data);
return res.data;
},