modbus: add explicit cascade delete (device + readings + toggles + HA cleanup)
frontend / frontend (push) Successful in 2m4s
pytest / test (push) Successful in 7m32s

A disabled device with historical readings still cannot be deleted by default
(409 guard stays, to prevent accidental data loss). A new explicit opt-in lets
the user remove it for real:

- DELETE /api/modbus/devices/{uuid}?cascade=true removes the device's readings
  and exposed_entity_toggle rows, then the device, in one transaction (FK order:
  readings before device). Best-effort clears the HA discovery configs first
  (MQTT not connected -> no-op, never blocks the delete). Default (no cascade)
  unchanged. Returns 200 with deletion counts.
- Frontend: a 'Force Delete (all data)' button appears only after the 409, with
  a red irreversible warning; cascade is sent only on that explicit action.
- Also corrected a stale comment: FK RESTRICT IS enforced at runtime now.
This commit is contained in:
2026-06-24 17:38:52 +02:00
parent d7f0731d1c
commit 682e06d256
11 changed files with 499 additions and 42 deletions
+11 -2
View File
@@ -115,12 +115,21 @@ export function useUpdateDevice() {
// Mutation: delete device
// ---------------------------------------------------------------------------
export interface DeleteDeviceParams {
uuid: string
/** When true, perform a cascade delete (removes readings + expose toggles). */
cascade?: boolean
}
export function useDeleteDevice() {
const qc = useQueryClient()
return useMutation({
mutationFn: (uuid: string) =>
mutationFn: ({ uuid, cascade }: DeleteDeviceParams) =>
apiClient.DELETE('/api/modbus/devices/{uuid}', {
params: { path: { uuid } },
params: {
path: { uuid },
...(cascade ? { query: { cascade: true } } : {}),
},
}),
onSuccess: () => qc.invalidateQueries({ queryKey: ['modbus-devices'] }),
})