Add endpoint to copy shift plan week

This commit is contained in:
Simon Goller 2024-06-14 09:53:57 +02:00
parent e7af89f1cd
commit f894bf325d
4 changed files with 102 additions and 2 deletions

View file

@ -1,14 +1,15 @@
use std::collections::HashMap;
use std::sync::Arc;
use axum::body::Body;
use axum::extract::Path;
use axum::extract::{Path, Query};
use axum::routing::{delete, get, post};
use axum::{extract::State, response::Response};
use axum::{Extension, Json, Router};
use rest_types::BookingTO;
use uuid::Uuid;
use crate::{error_handler, Context, RestStateDef};
use crate::{error_handler, Context, RestError, RestStateDef};
use service::booking::{Booking, BookingService};
pub fn generate_route<RestState: RestStateDef>() -> Router<RestState> {
@ -18,6 +19,7 @@ pub fn generate_route<RestState: RestStateDef>() -> Router<RestState> {
.route("/:id", get(get_booking::<RestState>))
.route("/", post(create_booking::<RestState>))
.route("/:id", delete(delete_booking::<RestState>))
.route("/copy", post(copy_calendar_week::<RestState>))
}
pub async fn get_all_bookings<RestState: RestStateDef>(
@ -109,6 +111,39 @@ pub async fn create_booking<RestState: RestStateDef>(
)
}
pub async fn copy_calendar_week<RestState: RestStateDef>(
rest_state: State<RestState>,
Extension(context): Extension<Context>,
Query(params): Query<HashMap<String, String>>,
) -> Response {
error_handler(
(async {
let from_year = params
.get("from_year")
.ok_or_else(|| RestError::BadRequest("year missing".to_string()))?
.parse()?;
let from_week = params
.get("from_week")
.ok_or_else(|| RestError::BadRequest("week missing".to_string()))?
.parse()?;
let to_year = params
.get("to_year")
.ok_or_else(|| RestError::BadRequest("year missing".to_string()))?
.parse()?;
let to_week = params
.get("to_week")
.ok_or_else(|| RestError::BadRequest("week missing".to_string()))?
.parse()?;
rest_state
.booking_service()
.copy_week(from_week, from_year, to_week, to_year, context.into())
.await?;
Ok(Response::builder().status(200).body(Body::empty()).unwrap())
})
.await,
)
}
pub async fn delete_booking<RestState: RestStateDef>(
rest_state: State<RestState>,
Extension(context): Extension<Context>,

View file

@ -107,6 +107,12 @@ pub enum RestError {
#[error("Inconsistent id. Got {0} in path but {1} in body")]
InconsistentId(Uuid, Uuid),
#[error("Bad request: {0}")]
BadRequest(String),
#[error("Parse int error: {0}")]
ParseIntError(#[from] std::num::ParseIntError),
}
fn error_handler(result: Result<Response, RestError>) -> Response {
@ -119,6 +125,14 @@ fn error_handler(result: Result<Response, RestError>) -> Response {
.status(400)
.body(Body::new(err.to_string()))
.unwrap(),
Err(err @ RestError::BadRequest(_)) => Response::builder()
.status(400)
.body(Body::new(err.to_string()))
.unwrap(),
Err(err @ RestError::ParseIntError(_)) => Response::builder()
.status(400)
.body(Body::new(err.to_string()))
.unwrap(),
Err(RestError::ServiceError(service::ServiceError::Forbidden)) => {
Response::builder().status(403).body(Body::empty()).unwrap()
}

View file

@ -75,6 +75,14 @@ pub trait BookingService {
booking: &Booking,
context: Authentication<Self::Context>,
) -> Result<Booking, ServiceError>;
async fn copy_week(
&self,
from_calendar_week: u8,
from_year: u32,
to_calendar_week: u8,
to_year: u32,
context: Authentication<Self::Context>,
) -> Result<(), ServiceError>;
async fn delete(
&self,
id: Uuid,

View file

@ -233,6 +233,49 @@ where
Ok(new_booking)
}
async fn copy_week(
&self,
from_calendar_week: u8,
from_year: u32,
to_calendar_week: u8,
to_year: u32,
context: Authentication<Self::Context>,
) -> Result<(), ServiceError> {
self.permission_service
.check_permission("hr", context.clone())
.await?;
let from_week = self
.get_for_week(from_calendar_week, from_year, Authentication::Full)
.await?;
let to_week = self
.get_for_week(to_calendar_week, to_year, Authentication::Full)
.await?;
// Remove entries which are already in the destination week
let to_week_ids: Arc<[(Uuid, Uuid)]> = to_week
.iter()
.map(|b| (b.sales_person_id, b.slot_id))
.collect();
let from_week: Arc<[Booking]> = from_week
.iter()
.filter(|b| !to_week_ids.contains(&(b.sales_person_id, b.slot_id)))
.map(|b| {
let mut new_booking = b.clone();
new_booking.id = Uuid::nil();
new_booking.calendar_week = to_calendar_week as i32;
new_booking.year = to_year;
new_booking.created = None;
new_booking.version = Uuid::nil();
new_booking
})
.collect();
for booking in from_week.into_iter() {
self.create(booking, Authentication::Full).await?;
}
Ok(())
}
async fn delete(
&self,
id: Uuid,