feat: add function to db and event
This commit is contained in:
parent
7bf892207a
commit
58bcee940f
@ -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,
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -13,6 +13,7 @@ pub struct NewEventForm {
|
||||
till: NaiveTime,
|
||||
location: i32,
|
||||
voluntarywachhabender: Option<bool>,
|
||||
voluntaryfuehrungsassistent: Option<bool>,
|
||||
amount: i16,
|
||||
clothing: String,
|
||||
note: Option<String>
|
||||
@ -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()
|
||||
|
@ -11,6 +11,7 @@ mod location;
|
||||
mod user;
|
||||
mod imprint;
|
||||
mod vehicle;
|
||||
mod vehicle_assignment;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct IdPath {
|
||||
|
@ -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<User>, pool: web::Data<PgPool>) -> 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;
|
||||
|
1
src/endpoints/vehicle_assignment/mod.rs
Normal file
1
src/endpoints/vehicle_assignment/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
mod post_new;
|
36
src/endpoints/vehicle_assignment/post_new.rs
Normal file
36
src/endpoints/vehicle_assignment/post_new.rs
Normal file
@ -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<User>,
|
||||
pool: web::Data<PgPool>,
|
||||
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(), query.vehicle).await? else {
|
||||
return Ok(HttpResponse::NotFound().finish());
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
@ -13,6 +13,7 @@ pub struct Event {
|
||||
pub location_id: i32,
|
||||
pub location: Option<Location>,
|
||||
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,
|
||||
|
@ -28,6 +28,7 @@ impl TryFrom<u8> for Function {
|
||||
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
1 => Ok(Function::Posten),
|
||||
5 => Ok(Function::Fuehrungsassistent),
|
||||
10 => Ok(Function::Wachhabender),
|
||||
_ => Err(ApplicationError::UnsupportedEnumValue {
|
||||
value: value.to_string(),
|
||||
|
@ -36,6 +36,26 @@ impl Vehicle {
|
||||
Ok(vehicles)
|
||||
}
|
||||
|
||||
pub async fn read_all_assignable_for_event(pool: &PgPool, event_id: i32) -> Result<Vec<Vehicle>> {
|
||||
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<Option<Vehicle>> {
|
||||
let record = query!("SELECT * FROM vehicle WHERE id = $1;", id)
|
||||
.fetch_optional(pool)
|
||||
|
@ -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);
|
||||
|
@ -70,6 +70,21 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field is-horizontal">
|
||||
<div class="field-label">
|
||||
<label class="label">Führungsassistent durch FF gestellt?</label>
|
||||
</div>
|
||||
<div class="field-body">
|
||||
<div class="field is-narrow">
|
||||
<div class="control">
|
||||
<label class="checkbox">
|
||||
<input class="checkbox" type="checkbox" name="voluntaryfuehrungsassistent" value="true">
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field is-horizontal">
|
||||
<div class="field-label">
|
||||
<label class="label">Anzahl der Posten</label>
|
||||
|
@ -31,7 +31,7 @@
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<p><b>Führungsassistent:</b> {% if event.voluntary_wachhabender %}FF{% else %}BF{% endif %}</p>
|
||||
<p><b>Führungsassistent:</b> {% if event.voluntary_fuehrungsassistent %}FF{% else %}BF{% endif %}</p>
|
||||
</div>
|
||||
|
||||
<div class="cell is-col-span-2">
|
||||
@ -51,13 +51,6 @@
|
||||
|
||||
<div class="box">
|
||||
<h5 class="title is-5">Einteilung Personal</h5>
|
||||
<div class="icon-text">
|
||||
<svg class="icon has-text-success">
|
||||
<use href="/static/feather-sprite.svg#check" />
|
||||
</svg>
|
||||
<span>Alle Plätze verplant!</span>
|
||||
</div>
|
||||
|
||||
{% include "plan_personal_table.html" %}
|
||||
</div>
|
||||
|
||||
|
@ -1,3 +1,12 @@
|
||||
{% if !further_posten_required && !further_fuehrungsassistent_required && !further_wachhabender_required %}
|
||||
<div class="icon-text">
|
||||
<svg class="icon has-text-success">
|
||||
<use href="/static/feather-sprite.svg#check" />
|
||||
</svg>
|
||||
<span>Alle Plätze verplant!</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<table class="table is-fullwidth">
|
||||
<thead>
|
||||
<tr>
|
||||
|
@ -69,6 +69,8 @@
|
||||
<div class="select is-fullwidth">
|
||||
<select name="function">
|
||||
<option value="1" {{ function|is_some_and_eq(1|as_ref)|cond_show("selected") }}>Posten</option>
|
||||
<option value="5" {{ function|is_some_and_eq(5|as_ref)|cond_show("selected") }}>Führungsassistent
|
||||
</option>
|
||||
<option value="10" {{ function|is_some_and_eq(10|as_ref)|cond_show("selected") }}>Wachhabender
|
||||
</option>
|
||||
</select>
|
||||
|
@ -59,6 +59,8 @@
|
||||
{% match u.function %}
|
||||
{% when Function::Posten %}
|
||||
<span class="tag is-primary is-light">Posten</span>
|
||||
{% when Function::Fuehrungsassistent %}
|
||||
<span class="tag is-primary is-light">Führungsassistent</span>
|
||||
{% when Function::Wachhabender %}
|
||||
<span class="tag is-primary">Wachhabender</span>
|
||||
{% else %}
|
||||
|
@ -62,13 +62,7 @@
|
||||
<div class="field-body">
|
||||
<div class="field">
|
||||
<div class="control">
|
||||
{% match user.function %}
|
||||
{% when Function::Posten %}
|
||||
<span class="tag is-primary is-light">Posten</span>
|
||||
{% when Function::Wachhabender %}
|
||||
<span class="tag is-primary">Wachhabender</span>
|
||||
{% else %}
|
||||
{% endmatch %}
|
||||
{{ user.function|show_tree|safe }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
x
Reference in New Issue
Block a user