51 lines
1.3 KiB
Rust
51 lines
1.3 KiB
Rust
use sqlx::PgPool;
|
|
use email::Mailer;
|
|
use chrono::Utc;
|
|
|
|
pub async fn expire_stale_requirements(
|
|
pool: &PgPool,
|
|
mailer: &Mailer,
|
|
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
let now = Utc::now();
|
|
|
|
// Find stale requirements that are still OPEN
|
|
// Update them directly returning the affected customer info
|
|
use uuid::Uuid;
|
|
|
|
#[derive(sqlx::FromRow)]
|
|
struct ReqRecord {
|
|
requirement_id: Uuid,
|
|
title: String,
|
|
email: String,
|
|
full_name: String,
|
|
}
|
|
|
|
let records = sqlx::query_as::<_, ReqRecord>(
|
|
r#"
|
|
UPDATE requirements
|
|
SET status = 'EXPIRED'
|
|
FROM customers c
|
|
JOIN users u ON u.id = c.user_id
|
|
WHERE requirements.customer_id = c.id
|
|
AND requirements.status = 'OPEN'
|
|
AND requirements.expires_at < $1
|
|
RETURNING requirements.id as requirement_id, requirements.title, u.email, u.full_name
|
|
"#
|
|
)
|
|
.bind(now)
|
|
.fetch_all(pool)
|
|
.await?;
|
|
|
|
if records.is_empty() {
|
|
return Ok(());
|
|
}
|
|
|
|
tracing::info!("Expired {} stale requirements.", records.len());
|
|
|
|
for rec in records {
|
|
let _ = mailer.send_requirement_expired_email(&rec.email, &rec.full_name, &rec.title).await;
|
|
tracing::info!("Sent expiry email to {} for requirement {}", rec.email, rec.requirement_id);
|
|
}
|
|
|
|
Ok(())
|
|
}
|