80 lines
2.5 KiB
Rust
80 lines
2.5 KiB
Rust
use actix_web::{web, HttpResponse, Responder};
|
|
use serde::Deserialize;
|
|
use sqlx::PgPool;
|
|
|
|
use crate::{
|
|
endpoints::vehicle_assignment::PlanVehiclesPartialTemplate,
|
|
utils::{
|
|
event_planning_template::generate_vehicles_assigned_and_available, ApplicationError,
|
|
TemplateResponse,
|
|
},
|
|
};
|
|
use brass_db::models::{Event, Role, User, Vehicle, VehicleAssignment};
|
|
|
|
#[derive(Deserialize)]
|
|
pub struct VehicleAssignmentQuery {
|
|
event: i32,
|
|
}
|
|
|
|
#[derive(Deserialize)]
|
|
pub struct VehicleAssignmentForm {
|
|
vehicle: i32,
|
|
}
|
|
|
|
#[actix_web::post("/vehicleassignments/new")]
|
|
pub async fn post(
|
|
user: web::ReqData<User>,
|
|
pool: web::Data<PgPool>,
|
|
form: web::Form<VehicleAssignmentForm>,
|
|
query: web::Query<VehicleAssignmentQuery>,
|
|
) -> 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(vehicle) = Vehicle::read(pool.get_ref(), form.vehicle).await? else {
|
|
return Ok(HttpResponse::NotFound().finish());
|
|
};
|
|
|
|
let existing_assignments_for_vehicle = VehicleAssignment::read_all_by_vehicle_and_date(
|
|
pool.get_ref(),
|
|
vehicle.id,
|
|
event.start.date(),
|
|
)
|
|
.await?;
|
|
let has_start_time_during_event =
|
|
|a: &VehicleAssignment| a.start >= event.start && a.start <= event.end;
|
|
let has_end_time_during_event =
|
|
|a: &VehicleAssignment| a.end >= event.start && a.end <= event.end;
|
|
|
|
let availability_already_assigned = existing_assignments_for_vehicle
|
|
.iter()
|
|
.any(|a| has_start_time_during_event(a) || has_end_time_during_event(a));
|
|
|
|
if availability_already_assigned {
|
|
return Ok(HttpResponse::BadRequest()
|
|
.body("Vehicle already assigned to a timely conflicting event."));
|
|
}
|
|
|
|
VehicleAssignment::create(pool.get_ref(), event.id, vehicle.id, event.start, event.end).await?;
|
|
|
|
let (vehicles_assigned, vehicles_available) =
|
|
generate_vehicles_assigned_and_available(pool.get_ref(), &event).await?;
|
|
let template = PlanVehiclesPartialTemplate {
|
|
event,
|
|
vehicles_assigned,
|
|
vehicles_available,
|
|
};
|
|
|
|
Ok(template.to_response()?)
|
|
}
|