feat(sprint9): Phase 6 — Compliance dashboard, RetentionService, testing
Backend: - ComplianceDashboardService: traffic-light status per ComplianceArea (KCANG/FINANCE/DSGVO/VEREIN) based on deadlines, payments, board positions - RetentionService: scheduled anonymization of expired member data (KCanG §24, 5 years), with dry-run preview and retention report endpoints - ComplianceDeadlineSeeder: seeds 5 standard recurring deadlines on club creation - ComplianceDashboardController: GET /api/v1/compliance/dashboard, GET /retention, POST /retention/preview - Repository additions: countOverdue, countActive board positions/members Frontend: - /compliance page with traffic-light status cards per area - Overdue deadlines section (highlighted red) with 'days overdue' badges - Upcoming deadlines with 'days until due' badges and 'Complete' buttons - Retention info cards (KCanG §24: 5y, AO §147: 10y, DSGVO: 2y) - Navigation: added 'Compliance-Status' to sidebar under Compliance group - compliance-dashboard.ts service with mock data for dev mode Build verified: pnpm build passes clean.
This commit is contained in:
+73
@@ -0,0 +1,73 @@
|
||||
package de.cannamanage.api.controller;
|
||||
|
||||
import de.cannamanage.domain.entity.ComplianceDeadline;
|
||||
import de.cannamanage.domain.entity.TenantContext;
|
||||
import de.cannamanage.domain.enums.ComplianceArea;
|
||||
import de.cannamanage.domain.enums.ComplianceStatus;
|
||||
import de.cannamanage.service.ComplianceDashboardService;
|
||||
import de.cannamanage.service.RetentionService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Compliance Dashboard controller.
|
||||
* Provides traffic-light compliance status, upcoming/overdue deadlines,
|
||||
* and retention management endpoints.
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/compliance/dashboard")
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "Compliance Dashboard", description = "Compliance status overview and retention management")
|
||||
public class ComplianceDashboardController {
|
||||
|
||||
private final ComplianceDashboardService dashboardService;
|
||||
private final RetentionService retentionService;
|
||||
|
||||
@GetMapping
|
||||
@Operation(summary = "Get compliance dashboard status",
|
||||
description = "Returns traffic-light status per compliance area + upcoming and overdue deadlines")
|
||||
@PreAuthorize("hasRole('ADMIN') or @staffPermissions.has(authentication, T(de.cannamanage.domain.enums.StaffPermission).VIEW_COMPLIANCE)")
|
||||
public ResponseEntity<ComplianceDashboardResponse> getDashboard(
|
||||
@RequestParam(defaultValue = "30") int upcomingDays) {
|
||||
|
||||
UUID clubId = TenantContext.getCurrentTenant();
|
||||
|
||||
Map<ComplianceArea, ComplianceStatus> statusMap = dashboardService.getComplianceStatus(clubId);
|
||||
List<ComplianceDeadline> upcoming = dashboardService.getUpcomingDeadlines(clubId, upcomingDays);
|
||||
List<ComplianceDeadline> overdue = dashboardService.getOverdueDeadlines(clubId);
|
||||
|
||||
return ResponseEntity.ok(new ComplianceDashboardResponse(statusMap, upcoming, overdue));
|
||||
}
|
||||
|
||||
@GetMapping("/retention")
|
||||
@Operation(summary = "Get retention report",
|
||||
description = "Shows what was deleted, what will be deleted, and retention schedule")
|
||||
@PreAuthorize("hasRole('ADMIN') or @staffPermissions.has(authentication, T(de.cannamanage.domain.enums.StaffPermission).MANAGE_COMPLIANCE)")
|
||||
public ResponseEntity<RetentionService.RetentionReport> getRetentionReport() {
|
||||
UUID clubId = TenantContext.getCurrentTenant();
|
||||
return ResponseEntity.ok(retentionService.getRetentionReport(clubId));
|
||||
}
|
||||
|
||||
@PostMapping("/retention/preview")
|
||||
@Operation(summary = "Preview retention actions (dry-run)",
|
||||
description = "Shows what WOULD be affected by retention processing without making changes")
|
||||
@PreAuthorize("hasRole('ADMIN') or @staffPermissions.has(authentication, T(de.cannamanage.domain.enums.StaffPermission).MANAGE_COMPLIANCE)")
|
||||
public ResponseEntity<RetentionService.RetentionPreview> previewRetention() {
|
||||
UUID clubId = TenantContext.getCurrentTenant();
|
||||
return ResponseEntity.ok(retentionService.previewRetention(clubId));
|
||||
}
|
||||
|
||||
public record ComplianceDashboardResponse(
|
||||
Map<ComplianceArea, ComplianceStatus> status,
|
||||
List<ComplianceDeadline> upcomingDeadlines,
|
||||
List<ComplianceDeadline> overdueDeadlines
|
||||
) {}
|
||||
}
|
||||
Reference in New Issue
Block a user