use uuid::Uuid;
use crate::infrastructure::persistence::StaleSessionRow;
use super::pos_events::{PosEvent, PosStaleSessionAlerted};
use super::pos_write_service::{legacy_company_echo, relay_ambient_scope, PosError, PosWriteService};
pub const DEFAULT_STALE_SESSION_AGE_DAYS: i64 = 7;
pub const STALE_SESSION_BATCH_LIMIT: i64 = 500;
impl PosWriteService {
pub async fn alert_old_sessions(
&self,
older_than: chrono::Duration,
) -> Result<Vec<PosStaleSessionAlerted>, PosError> {
let cutoff = chrono::Utc::now().naive_utc() - older_than;
let mut tx = self.rpool().begin().await?;
relay_ambient_scope(&mut tx).await?;
let claimed = self
.openings
.claim_stale_sessions(&mut tx, cutoff, STALE_SESSION_BATCH_LIMIT)
.await?;
if claimed.is_empty() {
tx.rollback().await?;
return Ok(Vec::new());
}
let at = chrono::Utc::now();
let ids: Vec<Uuid> = claimed.iter().map(|s| s.opening_entry_id).collect();
self.openings.mark_stale_alerted(&mut tx, &ids, at).await?;
tx.commit().await?;
let claimed: Vec<StaleSessionRow> = claimed;
let alerts = claimed
.into_iter()
.map(|s| PosStaleSessionAlerted {
opening_entry_id: s.opening_entry_id,
pos_profile_id: s.pos_profile_id,
company_id: legacy_company_echo(),
cashier_party_id: s.cashier_party_id,
opened_at: s.opened_at,
})
.collect::<Vec<_>>();
for a in &alerts {
self.sink.publish(PosEvent::PosStaleSessionAlerted(a.clone()));
}
Ok(alerts)
}
}