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, pool: web::Data, form: web::Form, query: web::Query, ) -> Result { 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()?) }