62 lines
2.0 KiB
Rust
62 lines
2.0 KiB
Rust
use std::collections::HashSet;
|
|
|
|
use uuid::Uuid;
|
|
|
|
use crate::error::{AppError, AppResult};
|
|
|
|
use super::CorrespondentAssignmentInput;
|
|
|
|
pub const CORRESPONDENT_ROLES: &[&str] = &["sender", "receiver", "other"];
|
|
|
|
pub fn normalize_role(value: &str) -> String {
|
|
value.trim().to_lowercase()
|
|
}
|
|
|
|
pub fn is_valid_correspondent_role(role: &str) -> bool {
|
|
CORRESPONDENT_ROLES.iter().any(|allowed| *allowed == role)
|
|
}
|
|
|
|
pub fn normalize_correspondent_assignments(
|
|
assignments: &[CorrespondentAssignmentInput],
|
|
) -> AppResult<(Vec<(Uuid, String)>, Vec<Uuid>, Vec<String>)> {
|
|
let mut unique_pairs: HashSet<(Uuid, String)> = HashSet::new();
|
|
let mut normalized_pairs: Vec<(Uuid, String)> = Vec::new();
|
|
let mut role_set: HashSet<String> = HashSet::new();
|
|
let mut correspondent_ids: HashSet<Uuid> = HashSet::new();
|
|
|
|
for assignment in assignments {
|
|
let role = normalize_role(&assignment.role);
|
|
if role.is_empty() {
|
|
return Err(AppError::bad_request("role must not be empty"));
|
|
}
|
|
if !is_valid_correspondent_role(&role) {
|
|
return Err(AppError::bad_request(format!(
|
|
"invalid correspondent role '{role}'. Allowed roles: {}",
|
|
CORRESPONDENT_ROLES.join(", ")
|
|
)));
|
|
}
|
|
|
|
if !unique_pairs.insert((assignment.correspondent_id, role.clone())) {
|
|
continue;
|
|
}
|
|
|
|
normalized_pairs.push((assignment.correspondent_id, role.clone()));
|
|
role_set.insert(role);
|
|
correspondent_ids.insert(assignment.correspondent_id);
|
|
}
|
|
|
|
if normalized_pairs.is_empty() {
|
|
return Err(AppError::bad_request(
|
|
"assignments must contain at least one unique correspondent/role pair",
|
|
));
|
|
}
|
|
|
|
let mut correspondents_vec: Vec<Uuid> = correspondent_ids.into_iter().collect();
|
|
correspondents_vec.sort();
|
|
|
|
let mut roles_vec: Vec<String> = role_set.into_iter().collect();
|
|
roles_vec.sort();
|
|
|
|
Ok((normalized_pairs, correspondents_vec, roles_vec))
|
|
}
|