Bisher loeschte die Report-Pipeline die Unterschriften nach erfolgreichem DOCUframe-Upload. Wir brauchen die Signatur-Dateien aber weiterhin, daher: - ProcessDeliveryReportUseCase: Signatur-Loeschung (delete_for_delivery) aus dem Cleanup entfernt + SignatureStorage-Dependency raus (Report-PDF/Bild-Notiz- Cleanup bleibt). - SignatureStorage: neue Methode delete_older_than(max_age) -> Anzahl; lokaler Adapter loescht PNGs aelter als die Frist (per mtime). - Config [signature]: retention_days (Default 90, 0 = aus) + cleanup_cron (Default taeglich 04:00). - main.rs: Signatur-Cleanup-Scheduler (gated retention_days > 0). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
63 lines
2.4 KiB
Rust
63 lines
2.4 KiB
Rust
//! Port für den Unterschriften-Speicher.
|
|
//!
|
|
//! Im Gegensatz zu Notiz-Bildern (die nach DOCUframe gehen) liegen
|
|
//! Unterschriften bewusst **lokal im Backend-Server** — ein einfacher
|
|
//! Datei-Speicher reicht, und die Daten verlassen die Maschine nicht.
|
|
//!
|
|
//! Die konkrete Impl (lokales Dateisystem) lebt in
|
|
//! `holzleitner-infrastructure`. Der Use Case erhält eine relative
|
|
//! Referenz zurück, die in `delivery_completions` persistiert wird.
|
|
|
|
use std::time::Duration;
|
|
|
|
use async_trait::async_trait;
|
|
use uuid::Uuid;
|
|
|
|
use crate::error::ApplicationError;
|
|
|
|
/// Wer hat unterschrieben — bestimmt den Dateinamen.
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub enum SignatureRole {
|
|
Customer,
|
|
Driver,
|
|
}
|
|
|
|
impl SignatureRole {
|
|
pub fn as_str(self) -> &'static str {
|
|
match self {
|
|
SignatureRole::Customer => "customer",
|
|
SignatureRole::Driver => "driver",
|
|
}
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
pub trait SignatureStorage: Send + Sync {
|
|
/// Speichert eine Unterschrift (PNG-Bytes) für eine Lieferung+Rolle und
|
|
/// liefert die persistente, relative Referenz (Dateiname) zurück.
|
|
/// Deterministisch über `delivery_id`+`role` — ein Retry überschreibt
|
|
/// dieselbe Datei statt Müll anzuhäufen.
|
|
async fn save(
|
|
&self,
|
|
delivery_id: Uuid,
|
|
role: SignatureRole,
|
|
bytes: Vec<u8>,
|
|
) -> Result<String, ApplicationError>;
|
|
|
|
/// Lädt die gespeicherten PNG-Bytes einer Unterschrift über ihre relative
|
|
/// Referenz (Dateiname, wie von [`save`](Self::save) geliefert) — fürs
|
|
/// Einbetten in den PDF-Report. `None`, wenn die Datei fehlt.
|
|
async fn load(&self, reference: &str) -> Result<Option<Vec<u8>>, ApplicationError>;
|
|
|
|
/// Löscht beide Unterschriften (Kunde + Fahrer) einer Lieferung. Idempotent
|
|
/// (fehlende Datei = ok). Hinweis: Wird NICHT mehr beim Report-Upload
|
|
/// aufgerufen — Unterschriften bleiben erhalten und werden per Cron über
|
|
/// [`delete_older_than`](Self::delete_older_than) nach Frist entfernt.
|
|
async fn delete_for_delivery(&self, delivery_id: Uuid) -> Result<(), ApplicationError>;
|
|
|
|
/// Löscht alle Unterschrifts-Dateien, deren letzte Änderung länger als
|
|
/// `max_age` zurückliegt (Aufbewahrungsfrist). Für den periodischen
|
|
/// Cron-Cleanup. Liefert die Anzahl gelöschter Dateien.
|
|
async fn delete_older_than(&self, max_age: Duration) -> Result<u64, ApplicationError>;
|
|
}
|