feat(backend): Automatisierungen mit drei fest hinterlegten Triggern (Modul 30)

Neues AutomationModule mit AutomationRule-Modell (ein Row je Trigger-Typ,
per Unique Constraint erzwungen). Drei fest im Code hinterlegte Trigger,
die Admins nur aktivieren/deaktivieren bzw. deren Konfiguration/Aufgaben-
text anpassen können:

- QUEENLESS_NO_EGGS: Königin nicht gesehen UND keine Stifte vorhanden
  (bei Durchsicht) → Kontrollaufgabe
- VARROA_THRESHOLD: Varroa-Schwellenwert überschritten (konfigurierbar,
  Standard 10 Milben/Tag) → Behandlungsprüfung
- FEED_STATUS_CRITICAL: Futterstatus "kritisch" (bei Durchsicht) →
  Fütterungsaufgabe

Jeder ausgelöste Trigger erzeugt eine Task UND eine Notification sowie
einen Audit-Log-Eintrag; Tasks lösen zusätzlich das bestehende
task.created-Webhook aus. InspectionsService und VarroaService rufen
die Auswertung direkt nach dem jeweiligen Erstellen auf.

Neue Endpunkte (nur Administrator): GET/PATCH /automation-rules.

Unit-Tests für AutomationService (alle drei Trigger, Deaktivierung,
Update mit Audit-Log) sowie E2E-Tests (Rollen-Check, alle drei Trigger
end-to-end über echte Inspection-/Varroa-Endpunkte, Deaktivierung
verhindert weitere Trigger). E2E-Suite zweimal hintereinander grün
verifiziert (Idempotenz der globalen Regel-Zeilen sichergestellt).
Migration auf Dev- und Test-Datenbank angewendet.
This commit is contained in:
Nick Szaunig committed 2026-08-24 17:25:42 +02:00
1 parent 42a2be31b4
commit 3f47a6ae8d
15 files changed
+733

No files matched your search

@@ -0,0 +1,30 @@
import { Body, Controller, Get, Param, Patch } from '@nestjs/common';
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
import { Role } from '../../generated/prisma';
import { Roles } from '../auth/decorators/roles.decorator';
import { CurrentUser } from '../auth/decorators/current-user.decorator';
import type { AuthenticatedUser } from '../auth/types/authenticated-user';
import { AutomationService } from './automation.service';
import { UpdateAutomationRuleDto } from './dto/update-automation-rule.dto';
@ApiTags('automation-rules')
@ApiBearerAuth()
@Roles(Role.ADMIN)
@Controller('automation-rules')
export class AutomationController {
constructor(private readonly automationService: AutomationService) {}
@Get()
findAll() {
return this.automationService.findAll();
}
@Patch(':id')
update(
@Param('id') id: string,
@Body() dto: UpdateAutomationRuleDto,
@CurrentUser() actor: AuthenticatedUser,
) {
return this.automationService.update(id, dto, actor.id);
}
}