// Löschfristen je Datenklasse (Migration 0020) — schließt die in // rules/OPEN.md, Punkt 4 dokumentierte Lücke: loeschfrist_max_tage war // bisher nur als Anforderung "vorhanden", ohne Tageswerte, und wurde // deshalb nicht hart gefiltert. Die konkreten Tageswerte sind KEINE // gesetzliche Vorgabe (die DSGVO nennt keine festen Fristen, nur den // Grundsatz "so lange wie für den Zweck nötig", Art. 5 Abs. 1 lit. e) — // deshalb pro Mandant einstellbar statt hartkodiert, vom // Datenschutzbeauftragten hinterlegt. Bei Firmenanlage werden // risikogestaffelte Vorschlagswerte vorbelegt (siehe // internal/web/loeschfrist_handlers.go), frei editierbar. package store import ( "context" "fmt" "time" ) type LoeschfristEinstellung struct { ID string AccountID string DatenklasseID string MaxTage int UpdatedAt time.Time } // UpsertLoeschfristEinstellung legt eine Einstellung an oder // aktualisiert sie — ein Mandant hat höchstens eine Frist je // Datenklasse (UNIQUE-Constraint). func (s *Store) UpsertLoeschfristEinstellung(ctx context.Context, accountID, datenklasseID string, maxTage int) (LoeschfristEinstellung, error) { var e LoeschfristEinstellung err := s.db(ctx).QueryRow(ctx, ` INSERT INTO loeschfrist_einstellung (account_id, datenklasse_id, max_tage) VALUES ($1, $2, $3) ON CONFLICT (account_id, datenklasse_id) DO UPDATE SET max_tage = $3, updated_at = now() RETURNING id, account_id, datenklasse_id, max_tage, updated_at `, accountID, datenklasseID, maxTage).Scan(&e.ID, &e.AccountID, &e.DatenklasseID, &e.MaxTage, &e.UpdatedAt) if err != nil { return LoeschfristEinstellung{}, fmt.Errorf("store: upsert loeschfrist einstellung: %w", err) } return e, nil } // ListLoeschfristEinstellungenForAccount liefert alle konfigurierten // Fristen eines Mandanten. func (s *Store) ListLoeschfristEinstellungenForAccount(ctx context.Context, accountID string) ([]LoeschfristEinstellung, error) { rows, err := s.db(ctx).Query(ctx, ` SELECT id, account_id, datenklasse_id, max_tage, updated_at FROM loeschfrist_einstellung WHERE account_id = $1 ORDER BY datenklasse_id `, accountID) if err != nil { return nil, fmt.Errorf("store: list loeschfrist einstellungen: %w", err) } defer rows.Close() var out []LoeschfristEinstellung for rows.Next() { var e LoeschfristEinstellung if err := rows.Scan(&e.ID, &e.AccountID, &e.DatenklasseID, &e.MaxTage, &e.UpdatedAt); err != nil { return nil, fmt.Errorf("store: scan loeschfrist einstellung: %w", err) } out = append(out, e) } if err := rows.Err(); err != nil { return nil, fmt.Errorf("store: list loeschfrist einstellungen: %w", err) } return out, nil }