feat: vehicle assignment time

This commit is contained in:
Max Hohlfeld 2024-12-19 13:21:19 +01:00
parent 049b6e81ee
commit c327b6e637
10 changed files with 399 additions and 47 deletions

View File

@ -0,0 +1,40 @@
{
"db_name": "PostgreSQL",
"query": "SELECT * FROM vehicleAssignement WHERE vehicleAssignement.eventId = $1;",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "eventid",
"type_info": "Int4"
},
{
"ordinal": 1,
"name": "vehicleid",
"type_info": "Int4"
},
{
"ordinal": 2,
"name": "starttime",
"type_info": "Time"
},
{
"ordinal": 3,
"name": "endtime",
"type_info": "Time"
}
],
"parameters": {
"Left": [
"Int4"
]
},
"nullable": [
false,
false,
false,
false
]
},
"hash": "126a17ad3fe8937dfbf70e9a8c2bd7aee56eb35fdff0d0e47037b9af3e08b34f"
}

View File

@ -0,0 +1,17 @@
{
"db_name": "PostgreSQL",
"query": "INSERT INTO vehicleassignement (eventId, vehicleId, startTime, endTime) VALUES ($1, $2, $3, $4);",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Int4",
"Int4",
"Time",
"Time"
]
},
"nullable": []
},
"hash": "57969291aa7b29162b3a39c00f37f260e027d55063f031c8fd0a2efbe7e3b414"
}

View File

@ -1,15 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "INSERT INTO vehicleassignement (eventId, vehicleId) VALUES ($1, $2);",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Int4",
"Int4"
]
},
"nullable": []
},
"hash": "5e7f7ea4cbc3d326e3ea6c694a106f21ecb353648108895ee6d33faa09caa3cc"
}

View File

@ -0,0 +1,40 @@
{
"db_name": "PostgreSQL",
"query": "SELECT * FROM vehicleAssignement WHERE vehicleAssignement.vehicleId = $1;",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "eventid",
"type_info": "Int4"
},
{
"ordinal": 1,
"name": "vehicleid",
"type_info": "Int4"
},
{
"ordinal": 2,
"name": "starttime",
"type_info": "Time"
},
{
"ordinal": 3,
"name": "endtime",
"type_info": "Time"
}
],
"parameters": {
"Left": [
"Int4"
]
},
"nullable": [
false,
false,
false,
false
]
},
"hash": "8897efc635987bca2c2d1a85e001c909404ad2356fc63872fdae5a0cf76e7099"
}

190
Cargo.lock generated
View File

@ -104,7 +104,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb"
dependencies = [
"quote",
"syn",
"syn 2.0.90",
]
[[package]]
@ -238,7 +238,7 @@ dependencies = [
"actix-router",
"proc-macro2",
"quote",
"syn",
"syn 2.0.90",
]
[[package]]
@ -361,6 +361,55 @@ dependencies = [
"libc",
]
[[package]]
name = "anstream"
version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
[[package]]
name = "anstyle-parse"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
dependencies = [
"anstyle",
"windows-sys 0.59.0",
]
[[package]]
name = "anyhow"
version = "1.0.94"
@ -379,6 +428,16 @@ dependencies = [
"password-hash",
]
[[package]]
name = "async-attributes"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5"
dependencies = [
"quote",
"syn 1.0.109",
]
[[package]]
name = "async-channel"
version = "1.9.0"
@ -495,6 +554,7 @@ version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c634475f29802fde2b8f0b505b1bd00dfe4df7d4a000f0b36f7671197d5c3615"
dependencies = [
"async-attributes",
"async-channel 1.9.0",
"async-global-executor",
"async-io 2.4.0",
@ -529,7 +589,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.90",
]
[[package]]
@ -669,7 +729,7 @@ name = "brass-macros"
version = "0.1.0"
dependencies = [
"quote",
"syn",
"syn 2.0.90",
]
[[package]]
@ -825,9 +885,62 @@ dependencies = [
"inout",
]
[[package]]
name = "clap"
version = "4.5.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
name = "clap_builder"
version = "4.5.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
version = "4.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn 2.0.90",
]
[[package]]
name = "clap_lex"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
[[package]]
name = "cli"
version = "0.1.0"
dependencies = [
"anyhow",
"async-std",
"brass-config",
"clap",
"sqlx",
]
[[package]]
name = "colorchoice"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
[[package]]
name = "concurrent-queue"
@ -985,7 +1098,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim",
"syn",
"syn 2.0.90",
]
[[package]]
@ -996,7 +1109,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
dependencies = [
"darling_core",
"quote",
"syn",
"syn 2.0.90",
]
[[package]]
@ -1037,7 +1150,7 @@ dependencies = [
"darling",
"proc-macro2",
"quote",
"syn",
"syn 2.0.90",
]
[[package]]
@ -1047,7 +1160,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c"
dependencies = [
"derive_builder_core",
"syn",
"syn 2.0.90",
]
[[package]]
@ -1060,7 +1173,7 @@ dependencies = [
"proc-macro2",
"quote",
"rustc_version",
"syn",
"syn 2.0.90",
]
[[package]]
@ -1080,7 +1193,7 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.90",
"unicode-xid",
]
@ -1110,7 +1223,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.90",
]
[[package]]
@ -1386,7 +1499,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.90",
]
[[package]]
@ -1755,7 +1868,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.90",
]
[[package]]
@ -1843,6 +1956,12 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "itertools"
version = "0.13.0"
@ -2192,7 +2311,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.90",
]
[[package]]
@ -2562,7 +2681,7 @@ dependencies = [
"rinja_parser",
"rustc-hash",
"serde",
"syn",
"syn 2.0.90",
]
[[package]]
@ -2751,7 +2870,7 @@ checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.90",
]
[[package]]
@ -2964,7 +3083,7 @@ dependencies = [
"quote",
"sqlx-core",
"sqlx-macros-core",
"syn",
"syn 2.0.90",
]
[[package]]
@ -2988,7 +3107,7 @@ dependencies = [
"sqlx-mysql",
"sqlx-postgres",
"sqlx-sqlite",
"syn",
"syn 2.0.90",
"tempfile",
"url",
]
@ -3152,6 +3271,17 @@ version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.90"
@ -3171,7 +3301,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.90",
]
[[package]]
@ -3204,7 +3334,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.90",
]
[[package]]
@ -3313,7 +3443,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.90",
]
[[package]]
@ -3415,6 +3545,12 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]]
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "v_htmlescape"
version = "0.15.8"
@ -3478,7 +3614,7 @@ dependencies = [
"log",
"proc-macro2",
"quote",
"syn",
"syn 2.0.90",
"wasm-bindgen-shared",
]
@ -3513,7 +3649,7 @@ checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.90",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@ -3774,7 +3910,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.90",
"synstructure",
]
@ -3796,7 +3932,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.90",
]
[[package]]
@ -3816,7 +3952,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.90",
"synstructure",
]
@ -3845,7 +3981,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.90",
]
[[package]]

View File

@ -78,6 +78,8 @@ CREATE TABLE vehicleassignement
(
eventId INTEGER REFERENCES event (id) ON DELETE CASCADE,
vehicleId INTEGER REFERENCES vehicle (id) ON DELETE CASCADE,
startTime TIME NOT NULL,
endTime TIME NOT NULL,
PRIMARY KEY (eventId, vehicleId)
);

View File

@ -11,6 +11,7 @@ mod location;
pub mod user;
mod imprint;
mod vehicle;
mod vehicle_assignment;
#[derive(Deserialize)]
pub struct IdPath {

View File

@ -0,0 +1 @@
pub mod post_new;

View File

@ -0,0 +1,71 @@
use actix_web::{web, HttpResponse, Responder};
use rinja::Template;
use serde::Deserialize;
use sqlx::PgPool;
use crate::{
endpoints::assignment::PlanEventPersonalTablePartialTemplate,
models::{Assignment, Availabillity, Event, Function, Role, User, Vehicle, VehicleAssignement},
utils::{
event_planning_template::{
generate_availabillity_assignment_list, generate_status_whether_staff_is_required,
},
ApplicationError,
},
};
#[derive(Deserialize)]
pub struct VehicleAssignmentQuery {
vehicle: i32,
event: i32,
}
#[actix_web::post("/vehicleassignments/new")]
pub async fn post(
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());
};
let existing_assignments_for_vehicle =
VehicleAssignement::read_all_by_vehicle(pool.get_ref(), vehicle.id).await?;
let has_start_time_during_event =
|a: &VehicleAssignement| a.start_time >= event.start_time && a.start_time <= event.end_time;
let has_end_time_during_event =
|a: &VehicleAssignement| a.end_time >= event.start_time && a.end_time <= event.end_time;
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."));
}
VehicleAssignement::create(
pool.get_ref(),
event.id,
vehicle.id,
event.start_time,
event.end_time,
)
.await?;
return Ok(HttpResponse::NotFound().finish());
}

View File

@ -1,18 +1,29 @@
use chrono::NaiveTime;
use sqlx::{query, PgPool};
use super::Result;
pub struct VehicleAssignement {
event_id: i32,
vehicle_id: i32,
pub event_id: i32,
pub vehicle_id: i32,
pub start_time: NaiveTime,
pub end_time: NaiveTime,
}
impl VehicleAssignement {
pub async fn create(pool: &PgPool, event_id: i32, vehicle_id: i32) -> Result<()> {
pub async fn create(
pool: &PgPool,
event_id: i32,
vehicle_id: i32,
start_time: NaiveTime,
end_time: NaiveTime,
) -> Result<()> {
query!(
"INSERT INTO vehicleassignement (eventId, vehicleId) VALUES ($1, $2);",
"INSERT INTO vehicleassignement (eventId, vehicleId, startTime, endTime) VALUES ($1, $2, $3, $4);",
event_id,
vehicle_id
vehicle_id,
start_time,
end_time
)
.execute(pool)
.await?;
@ -20,6 +31,54 @@ impl VehicleAssignement {
Ok(())
}
pub async fn read_all_by_event(
pool: &PgPool,
event_id: i32,
) -> Result<Vec<VehicleAssignement>> {
let records = query!(
"SELECT * FROM vehicleAssignement WHERE vehicleAssignement.eventId = $1;",
event_id
)
.fetch_all(pool)
.await?;
let vehicle_assignments = records
.iter()
.map(|r| VehicleAssignement {
event_id: r.eventid,
vehicle_id: r.vehicleid,
start_time: r.starttime,
end_time: r.endtime,
})
.collect();
Ok(vehicle_assignments)
}
pub async fn read_all_by_vehicle(
pool: &PgPool,
vehicle_id: i32,
) -> Result<Vec<VehicleAssignement>> {
let records = query!(
"SELECT * FROM vehicleAssignement WHERE vehicleAssignement.vehicleId = $1;",
vehicle_id
)
.fetch_all(pool)
.await?;
let vehicle_assignments = records
.iter()
.map(|r| VehicleAssignement {
event_id: r.eventid,
vehicle_id: r.vehicleid,
start_time: r.starttime,
end_time: r.endtime,
})
.collect();
Ok(vehicle_assignments)
}
pub async fn delete(pool: &PgPool, event_id: i32, vehicle_id: i32) -> Result<()> {
query!(
"DELETE FROM vehicleassignement WHERE eventId = $1 AND vehicleId = $2;",