Add basic employee hour balance report
This commit is contained in:
parent
0eb885216a
commit
d4adcb182f
31 changed files with 2155 additions and 5 deletions
|
|
@ -2,8 +2,10 @@ use std::{convert::Infallible, sync::Arc};
|
|||
|
||||
mod booking;
|
||||
mod permission;
|
||||
mod report;
|
||||
mod sales_person;
|
||||
mod slot;
|
||||
mod working_hours;
|
||||
|
||||
#[cfg(feature = "oidc")]
|
||||
use axum::error_handling::HandleErrorLayer;
|
||||
|
|
@ -199,6 +201,12 @@ fn error_handler(result: Result<Response, RestError>) -> Response {
|
|||
.body(Body::new(err.to_string()))
|
||||
.unwrap()
|
||||
}
|
||||
Err(RestError::ServiceError(err @ service::ServiceError::TimeComponentRangeError(_))) => {
|
||||
Response::builder()
|
||||
.status(500)
|
||||
.body(Body::new(err.to_string()))
|
||||
.unwrap()
|
||||
}
|
||||
Err(RestError::ServiceError(ServiceError::InternalError)) => Response::builder()
|
||||
.status(500)
|
||||
.body(Body::new("Internal server error".to_string()))
|
||||
|
|
@ -215,12 +223,22 @@ pub trait RestStateDef: Clone + Send + Sync + 'static {
|
|||
+ Sync
|
||||
+ 'static;
|
||||
type BookingService: service::booking::BookingService<Context = Context> + Send + Sync + 'static;
|
||||
type ReportingService: service::reporting::ReportingService<Context = Context>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static;
|
||||
type WorkingHoursService: service::working_hours::WorkingHoursService<Context = Context>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static;
|
||||
|
||||
fn user_service(&self) -> Arc<Self::UserService>;
|
||||
fn permission_service(&self) -> Arc<Self::PermissionService>;
|
||||
fn slot_service(&self) -> Arc<Self::SlotService>;
|
||||
fn sales_person_service(&self) -> Arc<Self::SalesPersonService>;
|
||||
fn booking_service(&self) -> Arc<Self::BookingService>;
|
||||
fn reporting_service(&self) -> Arc<Self::ReportingService>;
|
||||
fn working_hours_service(&self) -> Arc<Self::WorkingHoursService>;
|
||||
}
|
||||
|
||||
pub struct OidcConfig {
|
||||
|
|
@ -324,6 +342,8 @@ pub async fn start_server<RestState: RestStateDef>(rest_state: RestState) {
|
|||
.nest("/slot", slot::generate_route())
|
||||
.nest("/sales-person", sales_person::generate_route())
|
||||
.nest("/booking", booking::generate_route())
|
||||
.nest("/report", report::generate_route())
|
||||
.nest("/working-hours", working_hours::generate_route())
|
||||
.with_state(rest_state)
|
||||
.layer(middleware::from_fn(context_extractor));
|
||||
|
||||
|
|
|
|||
77
rest/src/report.rs
Normal file
77
rest/src/report.rs
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use axum::{
|
||||
body::Body,
|
||||
extract::{Path, Query, State},
|
||||
response::Response,
|
||||
routing::get,
|
||||
Extension, Router,
|
||||
};
|
||||
use rest_types::{EmployeeReportTO, ShortEmployeeReportTO};
|
||||
use serde::Deserialize;
|
||||
use service::reporting::ReportingService;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{error_handler, Context, RestStateDef};
|
||||
|
||||
pub fn generate_route<RestState: RestStateDef>() -> Router<RestState> {
|
||||
Router::new()
|
||||
.route("/", get(get_short_report_for_all::<RestState>))
|
||||
.route("/:id", get(get_report::<RestState>))
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
pub struct ReportRequest {
|
||||
year: u32,
|
||||
until_week: u8,
|
||||
}
|
||||
|
||||
pub async fn get_short_report_for_all<RestState: RestStateDef>(
|
||||
rest_state: State<RestState>,
|
||||
query: Query<ReportRequest>,
|
||||
Extension(context): Extension<Context>,
|
||||
) -> Response {
|
||||
error_handler(
|
||||
(async {
|
||||
let short_report: Arc<[ShortEmployeeReportTO]> = rest_state
|
||||
.reporting_service()
|
||||
.get_reports_for_all_employees(query.year, query.until_week, context.into())
|
||||
.await?
|
||||
.iter()
|
||||
.map(ShortEmployeeReportTO::from)
|
||||
.collect();
|
||||
Ok(Response::builder()
|
||||
.status(200)
|
||||
.body(Body::new(serde_json::to_string(&short_report).unwrap()))
|
||||
.unwrap())
|
||||
})
|
||||
.await,
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn get_report<RestState: RestStateDef>(
|
||||
rest_state: State<RestState>,
|
||||
query: Query<ReportRequest>,
|
||||
Path(sales_person_id): Path<Uuid>,
|
||||
Extension(context): Extension<Context>,
|
||||
) -> Response {
|
||||
error_handler(
|
||||
(async {
|
||||
let report: EmployeeReportTO = (&rest_state
|
||||
.reporting_service()
|
||||
.get_report_for_employee(
|
||||
&sales_person_id,
|
||||
query.year,
|
||||
query.until_week,
|
||||
context.into(),
|
||||
)
|
||||
.await?)
|
||||
.into();
|
||||
Ok(Response::builder()
|
||||
.status(200)
|
||||
.body(Body::new(serde_json::to_string(&report).unwrap()))
|
||||
.unwrap())
|
||||
})
|
||||
.await,
|
||||
)
|
||||
}
|
||||
34
rest/src/working_hours.rs
Normal file
34
rest/src/working_hours.rs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
use axum::{
|
||||
body::Body, extract::State, response::Response, routing::post, Extension, Json, Router,
|
||||
};
|
||||
use rest_types::WorkingHoursTO;
|
||||
|
||||
use service::working_hours::WorkingHoursService;
|
||||
|
||||
use crate::{error_handler, Context, RestStateDef};
|
||||
|
||||
pub fn generate_route<RestState: RestStateDef>() -> Router<RestState> {
|
||||
Router::new().route("/", post(create_working_hours::<RestState>))
|
||||
}
|
||||
|
||||
pub async fn create_working_hours<RestState: RestStateDef>(
|
||||
rest_state: State<RestState>,
|
||||
Extension(context): Extension<Context>,
|
||||
Json(working_hours): Json<WorkingHoursTO>,
|
||||
) -> Response {
|
||||
error_handler(
|
||||
(async {
|
||||
let working_hours = WorkingHoursTO::from(
|
||||
&rest_state
|
||||
.working_hours_service()
|
||||
.create(&(&working_hours).into(), context.into())
|
||||
.await?,
|
||||
);
|
||||
Ok(Response::builder()
|
||||
.status(200)
|
||||
.body(Body::new(serde_json::to_string(&working_hours).unwrap()))
|
||||
.unwrap())
|
||||
})
|
||||
.await,
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue