102 lines
3.2 KiB
Rust

use actix_web::{web, HttpResponse, Responder};
use garde::Validate;
use serde::Deserialize;
use sqlx::PgPool;
use crate::{
endpoints::assignment::PlanEventPersonalTablePartialTemplate,
models::{
Assignment, AssignmentChangeset, AssignmentContext, Availability, Event, Function, Role,
User,
},
utils::{
event_planning_template::{
generate_availability_assignment_list, generate_status_whether_staff_is_required,
},
ApplicationError, TemplateResponse,
},
};
#[derive(Deserialize)]
pub struct AssignmentQuery {
availability: i32,
function: u8,
event: i32,
}
#[actix_web::post("/assignments/new")]
pub async fn post(
user: web::ReqData<User>,
pool: web::Data<PgPool>,
query: web::Query<AssignmentQuery>,
) -> Result<impl Responder, ApplicationError> {
let Some(event) = Event::read_by_id_including_location(pool.get_ref(), query.event).await?
else {
return Ok(HttpResponse::NotFound().finish());
};
let user_is_admin_or_area_manager_of_event_area = user.role == Role::Admin
|| (user.role == Role::AreaManager
&& user.area_id == event.location.as_ref().unwrap().area_id);
if !user_is_admin_or_area_manager_of_event_area {
return Err(ApplicationError::Unauthorized);
}
let Some(availability) =
Availability::read_by_id_including_user(pool.get_ref(), query.availability).await?
else {
return Ok(HttpResponse::NotFound().finish());
};
let availability_user_not_in_event_location_area =
availability.user.as_ref().unwrap().area_id != event.location.as_ref().unwrap().area_id;
if availability_user_not_in_event_location_area {
return Ok(HttpResponse::BadRequest()
.body("availability user is not in the same area as event location"));
}
let function = Function::try_from(query.function)?;
let changeset = AssignmentChangeset {
function,
time: (event.start, event.end),
};
let assignments_for_event = Assignment::read_all_by_event(pool.get_ref(), event.id).await?;
let assignments_for_availability =
Assignment::read_all_by_availability(pool.get_ref(), availability.id).await?;
let context = AssignmentContext {
event: event.clone(),
availability: availability.clone(),
user_function: availability.user.as_ref().unwrap().function.clone(),
assignments_for_event,
assignments_for_availability,
};
if let Err(e) = changeset.validate_with(&context) {
return Ok(HttpResponse::BadRequest().body(e.to_string()));
};
Assignment::create(pool.get_ref(), event.id, availability.id, changeset).await?;
let availabilities = generate_availability_assignment_list(pool.get_ref(), &event).await?;
let (
further_posten_required,
further_fuehrungsassistent_required,
further_wachhabender_required,
) = generate_status_whether_staff_is_required(pool.get_ref(), &event).await?;
let template = PlanEventPersonalTablePartialTemplate {
event,
availabilities,
further_posten_required,
further_fuehrungsassistent_required,
further_wachhabender_required,
};
Ok(template.to_response()?)
}