feat: WIP new assignment

This commit is contained in:
Max Hohlfeld 2024-04-17 07:00:55 +02:00
parent 12702ab85d
commit 74acc02e47
8 changed files with 178 additions and 4 deletions

View File

@ -5,7 +5,7 @@ use askama_actix::TemplateToResponse;
use serde::Deserialize;
use sqlx::PgPool;
use crate::models::{Event, Role, User};
use crate::models::{Availabillity, Event, Function, Role, User};
#[derive(Deserialize)]
pub struct EventQuery {
@ -16,7 +16,9 @@ pub struct EventQuery {
#[template(path = "assignment/new.html")]
pub struct NewAssignmentTemplate {
user: User,
event: Event
event: Event,
available_wachhabende: Vec<Availabillity>,
available_posten: Vec<Availabillity>
}
#[actix_web::get("/assignments/new")]
@ -27,7 +29,10 @@ pub async fn get(user: Identity, pool: web::Data<PgPool>, query: web::Query<Even
if let Ok(event) = Event::read_by_id_including_location(pool.get_ref(), query.event).await {
if current_user.role == Role::Admin || current_user.role == Role::AreaManager && event.location.as_ref().unwrap().area_id == current_user.area_id {
let template = NewAssignmentTemplate { user: current_user, event };
let available_posten = Availabillity::read_not_assigned_by_date_including_user(pool.get_ref(), event.date).await.unwrap();
let available_wachhabende = available_posten.iter().filter(|a| a.user.as_ref().unwrap().function == Function::Wachhabender).map(|avl| avl.clone()).collect();
let template = NewAssignmentTemplate { user: current_user, event, available_wachhabende, available_posten };
return template.to_response();
}

View File

@ -1 +1,2 @@
pub mod get_new;
pub mod post_new;

View File

@ -0,0 +1,15 @@
use actix_web::{web, HttpResponse, Responder};
use serde::Deserialize;
use sqlx::PgPool;
#[derive(Deserialize)]
pub struct NewAssignmentsForm {
wachhabender: Option<i32>,
posten: Vec<i32>
}
#[actix_web::post("/assignments/new")]
pub async fn post(pool: web::Data<PgPool>, form: web::Form<NewAssignmentsForm>) -> impl Responder {
HttpResponse::Ok().finish()
}

View File

@ -0,0 +1,19 @@
use chrono::NaiveTime;
use sqlx::PgPool;
use super::Function;
pub struct Assignment {
pub event_id: i32,
pub availabillity_id: i32,
pub function: Function,
pub start_time: NaiveTime,
pub end_time: NaiveTime
}
impl Assignment {
pub async fn create(pool: &PgPool) -> anyhow::Result<i32> {
Ok(0)
}
}

View File

@ -3,6 +3,7 @@ use sqlx::{query, PgPool};
use super::{function::Function, role::Role, user::User};
#[derive(Clone)]
pub struct Availabillity {
pub id: i32,
pub user_id: i32,
@ -117,6 +118,65 @@ impl Availabillity {
Ok(availabillities)
}
pub async fn read_not_assigned_by_date_including_user(pool: &PgPool, date: NaiveDate) -> anyhow::Result<Vec<Availabillity>> {
let records = query!(
r##"
SELECT
availabillity.id,
availabillity.userId,
availabillity.date,
availabillity.startTime,
availabillity.endTime,
availabillity.comment,
user_.name,
user_.email,
user_.password,
user_.salt,
user_.role AS "role: Role",
user_.function AS "function: Function",
user_.areaId,
user_.locked,
user_.lastLogin,
user_.receiveNotifications
FROM availabillity
LEFT JOIN assignement ON availabillity.Id = assignement.availabillityId
JOIN user_ ON availabillity.userId = user_.id
WHERE availabillity.date = $1;
"##,
date
)
.fetch_all(pool)
.await?;
let availabillities = records
.iter()
.map(|r| Availabillity {
id: r.id,
user_id: r.userid,
user: Some(User {
id: r.userid,
name: r.name.clone(),
email: r.email.clone(),
password: r.password.clone(),
salt: r.salt.clone(),
role: r.role.clone(),
function: r.function.clone(),
area_id: r.areaid,
area: None,
locked: r.locked,
last_login: r.lastlogin,
receive_notifications: r.receivenotifications,
}),
date: r.date,
start_time: r.starttime,
end_time: r.endtime,
comment: r.comment.clone(),
})
.collect();
Ok(availabillities)
}
pub async fn read_by_id(pool: &PgPool, id: i32) -> anyhow::Result<Availabillity> {
let record = query!("SELECT * FROM availabillity WHERE id = $1", id)
.fetch_one(pool)

View File

@ -1,6 +1,6 @@
use std::fmt::Display;
#[derive(sqlx::Type, Debug, Clone, Copy)]
#[derive(sqlx::Type, Debug, Clone, Copy, PartialEq, Eq)]
#[sqlx(type_name = "function", rename_all = "lowercase")]
pub enum Function {
Posten = 1,

View File

@ -15,3 +15,4 @@ pub use function::Function;
pub use location::Location;
pub use role::Role;
pub use user::User;
pub use assignement::Assignment;

View File

@ -5,6 +5,79 @@
<div class="container">
<form method="post" action="/users/new">
<h1 class="title">Planung für {{ event.name }}</h1>
<div class="box">
{% if event.canceled %}<b>Veranstaltung abgesagt!</b>{% endif %}
<p>Ort: {{ event.location.as_ref().unwrap().name }}</p>
<p>Zeitraum: {{ event.start_time }} bis {{ event.end_time }}</p>
<p>Anzahl der Posten: {{ event.amount_of_posten }}</p>
<p>Wachhabender durch FF gestellt: {{ event.voluntary_wachhabender }}</p>
<p>Kleidungsordnung: {{ event.clothing }}</p>
</div>
{% if event.voluntary_wachhabender %}
<div class="field">
<label class="label">Wachhabender</label>
<div class="select">
<select name="wachhabender">
{% for a in available_wachhabende %}
{% let user = a.user.as_ref().unwrap() %}
<option value="{{ a.id }}">
{{ user.name }} -
{% match user.function %}
{% when Function::Posten %}
Posten
{% when Function::Wachhabender %}
Wachhabender
{% else %}
{% endmatch %}
-
{% if a.start_time.is_some() && a.end_time.is_some() %}
{{ a.start_time.as_ref().unwrap() }} - {{ a.end_time.as_ref().unwrap() }}
{% else %}
ganztägig
{% endif %}
</option>
{% endfor %}
</select>
</div>
</div>
{% endif %}
<div class="field">
<label class="label">Posten</label>
<div class="select is-multiple">
<select name="posten" multiple size="{{ available_posten.len() }}">
{% for a in available_posten %}
{% let user = a.user.as_ref().unwrap() %}
<option value="{{ a.id }}">
{{ user.name }} -
{% match user.function %}
{% when Function::Posten %}
Posten
{% when Function::Wachhabender %}
Wachhabender
{% else %}
{% endmatch %}
-
{% if a.start_time.is_some() && a.end_time.is_some() %}
{{ a.start_time.as_ref().unwrap() }} - {{ a.end_time.as_ref().unwrap() }}
{% else %}
ganztägig
{% endif %}
</option>
{% endfor %}
</select>
</div>
</div>
<div class="field">
<label class="label">Fahrzeug</label>
<div class="select">
<select>
<option>Fahrzeug</option>
</select>
</div>
</div>
</form>
</div>