automatic apply on church jobs

This commit is contained in:
Torsten Schulz (local)
2026-01-29 11:20:45 +01:00
parent 55a86f75f1
commit 9f1c54fde9
2 changed files with 162 additions and 0 deletions

View File

@@ -32,6 +32,8 @@ use crate::worker::sql::{
QUERY_REJECT_CHURCH_APPLICATION,
QUERY_CREATE_CHURCH_APPLICATION_JOB,
QUERY_GET_CHARACTERS_FOR_CHURCH_OFFICE,
QUERY_GET_OLD_PENDING_CHURCH_APPLICATIONS,
QUERY_AUTO_APPROVE_CHURCH_APPLICATION,
};
pub struct PoliticsWorker {
@@ -106,6 +108,7 @@ impl PoliticsWorker {
fn run_loop(pool: ConnectionPool, broker: MessageBroker, state: Arc<WorkerState>) {
let mut last_execution: Option<Instant> = None;
let mut last_church_office_run: Option<Instant> = None;
let mut last_auto_approve_run: Option<Instant> = None;
while state.running_worker.load(Ordering::Relaxed) {
let now = Instant::now();
@@ -140,6 +143,21 @@ impl PoliticsWorker {
}
}
// Automatische Annahme alter Applications (stündlich)
let should_run_auto_approve = match last_auto_approve_run {
None => true,
Some(prev) => {
now.saturating_duration_since(prev) >= Duration::from_secs(3600)
}
};
if should_run_auto_approve {
if let Err(err) = Self::auto_approve_old_church_applications(&pool, &broker) {
eprintln!("[PoliticsWorker] Fehler bei auto_approve_old_church_applications: {err}");
}
last_auto_approve_run = Some(now);
}
// Entspricht ungefähr der 5-Sekunden-Schleife im C++-Code
for _ in 0..5 {
if !state.running_worker.load(Ordering::Relaxed) {
@@ -999,6 +1017,94 @@ impl PoliticsWorker {
Ok(())
}
/// Automatische Annahme von Church Applications, die älter als 36 Stunden sind
fn auto_approve_old_church_applications(
pool: &ConnectionPool,
broker: &MessageBroker,
) -> Result<(), DbError> {
let mut conn = pool
.get()
.map_err(|e| DbError::new(format!("DB-Verbindung fehlgeschlagen: {e}")))?;
// Alle alten pending Applications abrufen
conn.prepare(
"get_old_pending_church_applications",
QUERY_GET_OLD_PENDING_CHURCH_APPLICATIONS,
)
.map_err(|e| {
DbError::new(format!(
"[PoliticsWorker] prepare get_old_pending_church_applications: {e}"
))
})?;
let rows = conn
.execute("get_old_pending_church_applications", &[])
.map_err(|e| {
DbError::new(format!(
"[PoliticsWorker] exec get_old_pending_church_applications: {e}"
))
})?;
let mut old_applications = Vec::new();
for row in rows {
let application_id = parse_i32(&row, "application_id", -1);
let character_id = parse_i32(&row, "character_id", -1);
if application_id >= 0 {
old_applications.push((application_id, character_id));
}
}
if old_applications.is_empty() {
return Ok(());
}
eprintln!(
"[PoliticsWorker] Gefunden: {} alte Church Applications (36h+), automatische Annahme",
old_applications.len()
);
// Prepare auto-approve query
conn.prepare(
"auto_approve_church_application",
QUERY_AUTO_APPROVE_CHURCH_APPLICATION,
)
.map_err(|e| {
DbError::new(format!(
"[PoliticsWorker] prepare auto_approve_church_application: {e}"
))
})?;
// Alle alten Applications automatisch annehmen
for (application_id, character_id) in &old_applications {
let approve_rows = conn
.execute("auto_approve_church_application", &[application_id])
.map_err(|e| {
DbError::new(format!(
"[PoliticsWorker] exec auto_approve_church_application: {e}"
))
})?;
if !approve_rows.is_empty() {
eprintln!(
"[PoliticsWorker] Church Application {} automatisch angenommen (36h+ alt, character_id={})",
application_id, character_id
);
// Benachrichtigung senden
if let Some(user_id) = Self::get_user_id_for_character(pool, *character_id)? {
let msg = format!(
r#"{{"event":"falukantUpdateStatus","user_id":{}}}"#,
user_id
);
broker.publish(msg);
}
}
}
Ok(())
}
fn get_user_id_for_character(
pool: &ConnectionPool,
character_id: i32,

View File

@@ -1836,6 +1836,62 @@ pub const QUERY_REJECT_CHURCH_APPLICATION: &str = r#"
RETURNING id;
"#;
pub const QUERY_GET_OLD_PENDING_CHURCH_APPLICATIONS: &str = r#"
SELECT
ca.id AS application_id,
ca.office_type_id,
ca.character_id,
ca.region_id,
ca.supervisor_id
FROM falukant_data.church_application ca
WHERE ca.status = 'pending'
AND ca.created_at <= NOW() - INTERVAL '36 hours'
ORDER BY ca.created_at ASC;
"#;
pub const QUERY_AUTO_APPROVE_CHURCH_APPLICATION: &str = r#"
WITH updated_application AS (
UPDATE falukant_data.church_application
SET status = 'approved',
decision_date = NOW(),
updated_at = NOW()
WHERE id = $1
AND status = 'pending'
AND created_at <= NOW() - INTERVAL '36 hours'
RETURNING
office_type_id,
character_id,
region_id,
supervisor_id
),
inserted_office AS (
INSERT INTO falukant_data.church_office
(office_type_id, character_id, region_id, supervisor_id, created_at, updated_at)
SELECT
office_type_id,
character_id,
region_id,
supervisor_id,
NOW(),
NOW()
FROM updated_application
WHERE NOT EXISTS(
SELECT 1
FROM falukant_data.church_office co
WHERE co.office_type_id = updated_application.office_type_id
AND co.region_id = updated_application.region_id
AND co.character_id = updated_application.character_id
)
RETURNING id, office_type_id, character_id, region_id
)
SELECT
id AS office_id,
office_type_id,
character_id,
region_id
FROM inserted_office;
"#;
pub const QUERY_CREATE_CHURCH_APPLICATION_JOB: &str = r#"
INSERT INTO falukant_data.church_application
(office_type_id, character_id, region_id, supervisor_id, status, created_at, updated_at)