feat: create new assignment

This commit is contained in:
Max Hohlfeld 2024-05-12 15:23:39 +02:00
parent 74acc02e47
commit 2f5cc33261
6 changed files with 120 additions and 10 deletions

View File

@ -55,13 +55,13 @@ CREATE TABLE event
canceled BOOLEAN NOT NULL DEFAULT false
);
CREATE TABLE assignement
CREATE TABLE assignment
(
eventId INTEGER REFERENCES event (id),
availabillityId INTEGER REFERENCES availabillity (id),
function function NOT NULL,
startTime TIME,
endTime TIME,
startTime TIME NOT NULL,
endTime TIME NOT NULL,
PRIMARY KEY (eventId, availabillityId)
);

View File

@ -2,8 +2,11 @@ use actix_web::{web, HttpResponse, Responder};
use serde::Deserialize;
use sqlx::PgPool;
use crate::models::{Assignment, Event, Function};
#[derive(Deserialize)]
pub struct NewAssignmentsForm {
event: i32,
wachhabender: Option<i32>,
posten: Vec<i32>
}
@ -11,5 +14,41 @@ pub struct NewAssignmentsForm {
#[actix_web::post("/assignments/new")]
pub async fn post(pool: web::Data<PgPool>, form: web::Form<NewAssignmentsForm>) -> impl Responder {
let event = Event::read_by_id_including_location(&pool, form.event).await.unwrap(); // TODO: Check if location is needed
if event.voluntary_wachhabender && form.wachhabender.is_some() && form.posten.contains(&form.wachhabender.unwrap()) {
return HttpResponse::BadRequest().body("Wachhabender kann nicht zugleich Posten sein!");
}
let mut joined_ids = form.posten.clone();
if let Some(id) = form.wachhabender {
joined_ids.push(id);
}
for availabillity_id in joined_ids {
let assignments = Assignment::read_by_availabillity(pool.get_ref(), availabillity_id).await.unwrap();
let mut can_be_used = true;
for assignment in assignments {
if event.start_time >= assignment.start_time && event.start_time <= assignment.end_time {
can_be_used = false;
break;
}
}
if !can_be_used {
return HttpResponse::BadRequest().body("availabillity time slot bereits genutzt!");
}
}
if let Some(id) = form.wachhabender {
Assignment::create(pool.get_ref(), id, event.id, Function::Wachhabender, event.start_time, event.end_time).await.unwrap();
}
for id in &form.posten {
Assignment::create(pool.get_ref(), *id, event.id, Function::Posten, event.start_time, event.end_time).await.unwrap();
}
HttpResponse::Ok().finish()
}

View File

@ -1,5 +1,5 @@
use chrono::NaiveTime;
use sqlx::PgPool;
use sqlx::{query, PgPool};
use super::Function;
@ -8,12 +8,66 @@ pub struct Assignment {
pub availabillity_id: i32,
pub function: Function,
pub start_time: NaiveTime,
pub end_time: NaiveTime
pub end_time: NaiveTime,
}
impl Assignment {
pub async fn create(pool: &PgPool) -> anyhow::Result<i32> {
pub async fn create(
pool: &PgPool,
availabillity_id: i32,
event_id: i32,
function: Function,
start_time: NaiveTime,
end_time: NaiveTime,
) -> anyhow::Result<()> {
query!(
r##"
INSERT INTO assignment (eventId, availabillityId, function, startTime, endTime)
VALUES ($1, $2, $3, $4, $5);
"##,
availabillity_id,
event_id,
function as Function,
start_time,
end_time
)
.execute(pool)
.await?;
Ok(0)
Ok(())
}
pub async fn read_by_availabillity(
pool: &PgPool,
availabillity_id: i32,
) -> anyhow::Result<Vec<Assignment>> {
let records = query!(
r##"
SELECT
assignment.eventId,
assignment.availabillityId,
assignment.function AS "function: Function",
assignment.startTime,
assignment.endTime
FROM assignment
WHERE assignment.AvailabillityId = $1;
"##,
availabillity_id
)
.fetch_all(pool)
.await?;
let assignemnets = records
.iter()
.map(|r| Assignment {
event_id: r.eventid,
availabillity_id: r.availabillityid,
function: r.function,
start_time: r.starttime,
end_time: r.endtime,
})
.collect();
Ok(assignemnets)
}
}

View File

@ -139,7 +139,7 @@ impl Availabillity {
user_.lastLogin,
user_.receiveNotifications
FROM availabillity
LEFT JOIN assignement ON availabillity.Id = assignement.availabillityId
LEFT JOIN assignment ON availabillity.Id = assignment.availabillityId
JOIN user_ ON availabillity.userId = user_.id
WHERE availabillity.date = $1;
"##,

View File

@ -1,5 +1,5 @@
use chrono::{DateTime, Utc};
use sqlx::{Execute, PgPool};
use sqlx::PgPool;
use super::{Area, Function, Role};

View File

@ -3,7 +3,9 @@
{% block content %}
<section class="section">
<div class="container">
<form method="post" action="/users/new">
<form method="post" action="/assignments/new">
<input type="hidden" name="event" value="{{ event.id }}" />
<h1 class="title">Planung für {{ event.name }}</h1>
<div class="box">
{% if event.canceled %}<b>Veranstaltung abgesagt!</b>{% endif %}
@ -45,6 +47,7 @@
<div class="field">
<label class="label">Posten</label>
<p class="help">Mehrfachauswahl mit Strg+Mausklick</p>
<div class="select is-multiple">
<select name="posten" multiple size="{{ available_posten.len() }}">
{% for a in available_posten %}
@ -79,6 +82,20 @@
</div>
</div>
<div class="field is-horizontal">
<div class="field-label"></div>
<div class="field-body">
<div class="field is-grouped">
<div class="control">
<input class="button is-link" type="submit" value="Erstellen">
</div>
<div class="control">
<a class="button is-link is-light" href="/">Zurück</a>
</div>
</div>
</div>
</div>
</form>
</div>
</section>