From 58bcee940fa8590916dfee14c53962151ceafda7 Mon Sep 17 00:00:00 2001 From: Max Hohlfeld Date: Fri, 6 Dec 2024 21:30:38 +0100 Subject: [PATCH] feat: add function to db and event --- migrations/20230609121618_initial.sql | 3 +- src/endpoints/assignment/post_new.rs | 4 +-- src/endpoints/events/post_new.rs | 4 ++- src/endpoints/mod.rs | 1 + src/endpoints/user/get_profile.rs | 11 ++++-- src/endpoints/vehicle_assignment/mod.rs | 1 + src/endpoints/vehicle_assignment/post_new.rs | 36 ++++++++++++++++++++ src/models/event.rs | 12 +++++-- src/models/function.rs | 1 + src/models/vehicle.rs | 20 +++++++++++ src/utils/event_planning_template.rs | 3 +- templates/events/new.html | 15 ++++++++ templates/events/plan.html | 9 +---- templates/events/plan_personal_table.html | 9 +++++ templates/user/new_or_edit.html | 2 ++ templates/user/overview.html | 2 ++ templates/user/profile.html | 8 +---- 17 files changed, 113 insertions(+), 28 deletions(-) create mode 100644 src/endpoints/vehicle_assignment/mod.rs create mode 100644 src/endpoints/vehicle_assignment/post_new.rs diff --git a/migrations/20230609121618_initial.sql b/migrations/20230609121618_initial.sql index 089c0b90..ec3d5b6c 100644 --- a/migrations/20230609121618_initial.sql +++ b/migrations/20230609121618_initial.sql @@ -49,7 +49,8 @@ CREATE TABLE event endTime TIME NOT NULL, name TEXT NOT NULL, locationId INTEGER NOT NULL REFERENCES location (id) ON DELETE CASCADE, - voluntaryWachhabender BOOLEAN NOT NULL, + voluntaryWachhabender BOOLEAN NOT NULL, + voluntaryFuehrungsassistent BOOLEAN NOT NULL, amountOfPosten SMALLINT NOT NULL CHECK (amountOfPosten >= 0), clothing TEXT NOT NULL, note TEXT, diff --git a/src/endpoints/assignment/post_new.rs b/src/endpoints/assignment/post_new.rs index 4aec4261..c8e62190 100644 --- a/src/endpoints/assignment/post_new.rs +++ b/src/endpoints/assignment/post_new.rs @@ -1,5 +1,3 @@ -use std::ops::AddAssign; - use actix_web::{web, HttpResponse, Responder}; use askama_actix::TemplateToResponse; use serde::Deserialize; @@ -69,7 +67,7 @@ pub async fn post( let a = Assignment::count_by_event_and_function(pool.get_ref(), event.id, function).await?; let event_already_has_enough_assignments_for_function = match function { Function::Posten => a >= event.amount_of_posten as i64, - Function::Fuehrungsassistent => event.voluntary_wachhabender && a >= 1, + Function::Fuehrungsassistent => event.voluntary_fuehrungsassistent && a >= 1, Function::Wachhabender => event.voluntary_wachhabender && a >= 1, }; diff --git a/src/endpoints/events/post_new.rs b/src/endpoints/events/post_new.rs index 38c60582..c12a8947 100644 --- a/src/endpoints/events/post_new.rs +++ b/src/endpoints/events/post_new.rs @@ -13,6 +13,7 @@ pub struct NewEventForm { till: NaiveTime, location: i32, voluntarywachhabender: Option, + voluntaryfuehrungsassistent: Option, amount: i16, clothing: String, note: Option @@ -35,7 +36,8 @@ pub async fn post( &form.till, &form.name, form.location, - form.voluntarywachhabender.is_some() && form.voluntarywachhabender.unwrap(), + form.voluntarywachhabender.unwrap_or(false), + form.voluntaryfuehrungsassistent.unwrap_or(false), form.amount, &form.clothing, form.note.as_ref() diff --git a/src/endpoints/mod.rs b/src/endpoints/mod.rs index f4c6b645..17bb61ee 100644 --- a/src/endpoints/mod.rs +++ b/src/endpoints/mod.rs @@ -11,6 +11,7 @@ mod location; mod user; mod imprint; mod vehicle; +mod vehicle_assignment; #[derive(Deserialize)] pub struct IdPath { diff --git a/src/endpoints/user/get_profile.rs b/src/endpoints/user/get_profile.rs index 2f472d3d..5c1224db 100644 --- a/src/endpoints/user/get_profile.rs +++ b/src/endpoints/user/get_profile.rs @@ -3,17 +3,22 @@ use askama::Template; use askama_actix::TemplateToResponse; use sqlx::PgPool; -use crate::models::{Area, Function, Role, User}; +use crate::{ + filters, + models::{Area, Role, User}, +}; #[derive(Template)] #[template(path = "user/profile.html")] struct ProfileTemplate { - user: User + user: User, } #[actix_web::get("/profile")] pub async fn get(user: web::ReqData, pool: web::Data) -> impl Responder { - let area = Area::read_by_id(pool.get_ref(), user.area_id).await.unwrap(); + let area = Area::read_by_id(pool.get_ref(), user.area_id) + .await + .unwrap(); let mut user = user.into_inner(); user.area = area; diff --git a/src/endpoints/vehicle_assignment/mod.rs b/src/endpoints/vehicle_assignment/mod.rs new file mode 100644 index 00000000..07dc54c2 --- /dev/null +++ b/src/endpoints/vehicle_assignment/mod.rs @@ -0,0 +1 @@ +mod post_new; diff --git a/src/endpoints/vehicle_assignment/post_new.rs b/src/endpoints/vehicle_assignment/post_new.rs new file mode 100644 index 00000000..3f7675de --- /dev/null +++ b/src/endpoints/vehicle_assignment/post_new.rs @@ -0,0 +1,36 @@ +use actix_web::{web, HttpResponse, Responder}; +use sqlx::PgPool; + +use crate::{models::{Event, Role, User, Vehicle}, utils::ApplicationError}; + +pub struct VehicleAssignmentQuery { + event: i32, + vehicle: i32 +} + +#[actix_web::post("/vehicle-assignment")] +pub async fn post_new( + user: web::ReqData, + pool: web::Data, + 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(), query.vehicle).await? else { + return Ok(HttpResponse::NotFound().finish()); + }; + + + +} diff --git a/src/models/event.rs b/src/models/event.rs index 64b538a6..f7737cca 100644 --- a/src/models/event.rs +++ b/src/models/event.rs @@ -13,6 +13,7 @@ pub struct Event { pub location_id: i32, pub location: Option, pub voluntary_wachhabender: bool, + pub voluntary_fuehrungsassistent: bool, pub amount_of_posten: i16, pub clothing: String, pub canceled: bool, @@ -28,15 +29,16 @@ impl Event { name: &String, location_id: i32, voluntary_wachhabender: bool, + voluntary_fuehrungsassistent: bool, amount_of_posten: i16, clothing: &String, note: Option<&String>, ) -> Result<()> { query!(r#" - INSERT INTO event (date, startTime, endTime, name, locationId, voluntaryWachhabender, amountOfPosten, clothing, note) - VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9); + INSERT INTO event (date, startTime, endTime, name, locationId, voluntaryWachhabender, voluntaryFuehrungsassistent, amountOfPosten, clothing, note) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10); "#, - date, start_time, end_time, name, location_id, voluntary_wachhabender, amount_of_posten, clothing, note).execute(pool).await?; + date, start_time, end_time, name, location_id, voluntary_wachhabender, voluntary_fuehrungsassistent, amount_of_posten, clothing, note).execute(pool).await?; Ok(()) } @@ -56,6 +58,7 @@ impl Event { event.name, event.locationId, event.voluntaryWachhabender, + event.voluntaryFuehrungsassistent, event.amountOfPosten, event.clothing, event.canceled, @@ -90,6 +93,7 @@ impl Event { area: None, }), voluntary_wachhabender: record.voluntarywachhabender, + voluntary_fuehrungsassistent: record.voluntaryfuehrungsassistent, amount_of_posten: record.amountofposten, clothing: record.clothing.to_string(), canceled: record.canceled, @@ -111,6 +115,7 @@ impl Event { event.name, event.locationId, event.voluntaryWachhabender, + event.voluntaryFuehrungsassistent, event.amountOfPosten, event.clothing, event.canceled, @@ -142,6 +147,7 @@ impl Event { area: None, }), voluntary_wachhabender: record.voluntarywachhabender, + voluntary_fuehrungsassistent: record.voluntaryfuehrungsassistent, amount_of_posten: record.amountofposten, clothing: record.clothing.to_string(), canceled: record.canceled, diff --git a/src/models/function.rs b/src/models/function.rs index 584d99e7..4d0a79f4 100644 --- a/src/models/function.rs +++ b/src/models/function.rs @@ -28,6 +28,7 @@ impl TryFrom for Function { fn try_from(value: u8) -> Result { match value { 1 => Ok(Function::Posten), + 5 => Ok(Function::Fuehrungsassistent), 10 => Ok(Function::Wachhabender), _ => Err(ApplicationError::UnsupportedEnumValue { value: value.to_string(), diff --git a/src/models/vehicle.rs b/src/models/vehicle.rs index dafd0581..518fef3c 100644 --- a/src/models/vehicle.rs +++ b/src/models/vehicle.rs @@ -36,6 +36,26 @@ impl Vehicle { Ok(vehicles) } + pub async fn read_all_assignable_for_event(pool: &PgPool, event_id: i32) -> Result> { + let records = query!(r#" + SELECT * + FROM vehicle + + ;"#).fetch_all(pool).await?; + + let vehicles = records + .into_iter() + .map(|v| Vehicle { + id: v.id, + radio_call_name: v.radiocallname, + station: v.station, + }) + .collect(); + + Ok(vehicles) + } + + pub async fn read(pool: &PgPool, id: i32) -> Result> { let record = query!("SELECT * FROM vehicle WHERE id = $1;", id) .fetch_optional(pool) diff --git a/src/utils/event_planning_template.rs b/src/utils/event_planning_template.rs index 14e3f284..39cb5ddf 100644 --- a/src/utils/event_planning_template.rs +++ b/src/utils/event_planning_template.rs @@ -73,8 +73,7 @@ pub async fn generate_status_whether_staff_is_required( .count() < event.amount_of_posten as usize; - // TODO change to Fuehrungsassistent - let further_fuehrungsassistent_required = event.voluntary_wachhabender + let further_fuehrungsassistent_required = event.voluntary_fuehrungsassistent && existing_assignments_for_event .iter() .all(|a| a.function != Function::Fuehrungsassistent); diff --git a/templates/events/new.html b/templates/events/new.html index 65e26dda..57020a45 100644 --- a/templates/events/new.html +++ b/templates/events/new.html @@ -70,6 +70,21 @@ +
+
+ +
+
+
+
+ +
+
+
+
+
diff --git a/templates/events/plan.html b/templates/events/plan.html index 02ab6ff7..37207547 100644 --- a/templates/events/plan.html +++ b/templates/events/plan.html @@ -31,7 +31,7 @@
-

Führungsassistent: {% if event.voluntary_wachhabender %}FF{% else %}BF{% endif %}

+

Führungsassistent: {% if event.voluntary_fuehrungsassistent %}FF{% else %}BF{% endif %}

@@ -51,13 +51,6 @@
Einteilung Personal
-
- - - - Alle Plätze verplant! -
- {% include "plan_personal_table.html" %}
diff --git a/templates/events/plan_personal_table.html b/templates/events/plan_personal_table.html index 52858e8f..b6bc9720 100644 --- a/templates/events/plan_personal_table.html +++ b/templates/events/plan_personal_table.html @@ -1,3 +1,12 @@ +{% if !further_posten_required && !further_fuehrungsassistent_required && !further_wachhabender_required %} +
+ + + + Alle Plätze verplant! +
+{% endif %} + diff --git a/templates/user/new_or_edit.html b/templates/user/new_or_edit.html index b24b6a89..7f01432d 100644 --- a/templates/user/new_or_edit.html +++ b/templates/user/new_or_edit.html @@ -69,6 +69,8 @@
diff --git a/templates/user/overview.html b/templates/user/overview.html index a7df461b..1be014b4 100644 --- a/templates/user/overview.html +++ b/templates/user/overview.html @@ -59,6 +59,8 @@ {% match u.function %} {% when Function::Posten %} Posten + {% when Function::Fuehrungsassistent %} + Führungsassistent {% when Function::Wachhabender %} Wachhabender {% else %} diff --git a/templates/user/profile.html b/templates/user/profile.html index cd86118c..4d382dff 100644 --- a/templates/user/profile.html +++ b/templates/user/profile.html @@ -62,13 +62,7 @@
- {% match user.function %} - {% when Function::Posten %} - Posten - {% when Function::Wachhabender %} - Wachhabender - {% else %} - {% endmatch %} + {{ user.function|show_tree|safe }}