use crate::model::{notification::Notification, role::Role}; use sqlx::SqlitePool; pub async fn cleanup_roles(db: &SqlitePool) -> Result<(), String> { log::info!("Starting yearly role cleanup..."); let mut tx = db.begin().await.map_err(|e| e.to_string())?; // Find all roles to remove let paid_role = Role::find_by_name_tx(&mut tx, "paid") .await .ok_or("Role 'paid' not found")?; let schueler_role = Role::find_by_name_tx(&mut tx, "Schüler") .await .ok_or("Role 'Schüler' not found")?; let student_role = Role::find_by_name_tx(&mut tx, "Student") .await .ok_or("Role 'Student' not found")?; let no_einschreibgebuehr_role = Role::find_by_name_tx(&mut tx, "no-einschreibgebuehr") .await .ok_or("Role 'no-einschreibgebuehr' not found")?; let half_rennrudern_role = Role::find_by_name_tx(&mut tx, "half-rennrudern") .await .ok_or("Role 'half-rennrudern' not found")?; let participated_schnupperkurs_role = Role::find_by_name_tx(&mut tx, "participated_schnupperkurs") .await .ok_or("Role 'participated_schnupperkurs' not found")?; // Find scheckbuch role (needed to exclude users from "paid" removal -> they have still paid // for the scheckbuch) let scheckbuch_role = Role::find_by_name_tx(&mut tx, "scheckbuch") .await .ok_or("Role 'scheckbuch' not found")?; // Remove "paid" role from all users EXCEPT those with scheckbuch role let paid_removed = sqlx::query!( "DELETE FROM user_role WHERE role_id = ? AND user_id NOT IN ( SELECT user_id FROM user_role WHERE role_id = ? )", paid_role.id, scheckbuch_role.id ) .execute(&mut *tx) .await .map_err(|e| e.to_string())? .rows_affected(); // Remove other roles from all users let schueler_removed = sqlx::query!("DELETE FROM user_role WHERE role_id = ?", schueler_role.id) .execute(&mut *tx) .await .map_err(|e| e.to_string())? .rows_affected(); let student_removed = sqlx::query!("DELETE FROM user_role WHERE role_id = ?", student_role.id) .execute(&mut *tx) .await .map_err(|e| e.to_string())? .rows_affected(); let no_einschreibgebuehr_removed = sqlx::query!( "DELETE FROM user_role WHERE role_id = ?", no_einschreibgebuehr_role.id ) .execute(&mut *tx) .await .map_err(|e| e.to_string())? .rows_affected(); let half_rennrudern_removed = sqlx::query!( "DELETE FROM user_role WHERE role_id = ?", half_rennrudern_role.id ) .execute(&mut *tx) .await .map_err(|e| e.to_string())? .rows_affected(); let participated_schnupperkurs_removed = sqlx::query!( "DELETE FROM user_role WHERE role_id = ?", participated_schnupperkurs_role.id ) .execute(&mut *tx) .await .map_err(|e| e.to_string())? .rows_affected(); // Send notifications to admins and Vorstand let admin_role = Role::find_by_name_tx(&mut tx, "admin") .await .ok_or("Role 'admin' not found")?; let vorstand_role = Role::find_by_name_tx(&mut tx, "Vorstand") .await .ok_or("Role 'Vorstand' not found")?; let notification_message_admin = format!( "Jährliche Rollenbereinigung abgeschlossen. Die folgenden Rollen wurden entfernt: \ paid ({} Benutzer, außer Scheckbuch-Mitglieder), \ Schüler/Student ({}/{} Benutzer), \ no-einschreibgebuehr ({} Benutzer), \ half-rennrudern ({} Benutzer), \ participated_schnupperkurs ({} Benutzer). \ Die aktualisierten Gebühren können unter https://app.rudernlinz.at/admin/user/fees eingesehen werden.", paid_removed, schueler_removed, student_removed, no_einschreibgebuehr_removed, half_rennrudern_removed, participated_schnupperkurs_removed ); let notification_message_vorstand = format!( "Jährliche Rollenbereinigung abgeschlossen. \ Die aktualisierten Gebühren können unter https://app.rudernlinz.at/admin/user/fees eingesehen werden.", ); // Notify admins Notification::create_for_role_tx( &mut tx, &admin_role, ¬ification_message_admin, "Systembenachrichtigung", Some("https://app.rudernlinz.at/admin/user/fees"), None, ) .await; // Notify Vorstand Notification::create_for_role_tx( &mut tx, &vorstand_role, ¬ification_message_vorstand, "Systembenachrichtigung", Some("https://app.rudernlinz.at/admin/user/fees"), None, ) .await; // Commit transaction tx.commit().await.map_err(|e| e.to_string())?; log::info!( "Yearly role cleanup completed successfully: \ paid={}, Schüler={}, Student={}, no-einschreibgebuehr={}, \ half-rennrudern={}, participated_schnupperkurs={} removals", paid_removed, schueler_removed, student_removed, no_einschreibgebuehr_removed, half_rennrudern_removed, participated_schnupperkurs_removed ); Ok(()) }