Add endpoint to add extra_hours
This commit is contained in:
parent
d4adcb182f
commit
c8f28e1f7b
11 changed files with 335 additions and 38 deletions
|
|
@ -49,6 +49,12 @@ type WorkingHoursService = service_impl::working_hours::WorkingHoursServiceImpl<
|
||||||
ClockService,
|
ClockService,
|
||||||
UuidService,
|
UuidService,
|
||||||
>;
|
>;
|
||||||
|
type ExtraHoursService = service_impl::extra_hours::ExtraHoursServiceImpl<
|
||||||
|
dao_impl::extra_hours::ExtraHoursDaoImpl,
|
||||||
|
PermissionService,
|
||||||
|
ClockService,
|
||||||
|
UuidService,
|
||||||
|
>;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct RestStateImpl {
|
pub struct RestStateImpl {
|
||||||
|
|
@ -59,6 +65,7 @@ pub struct RestStateImpl {
|
||||||
booking_service: Arc<BookingService>,
|
booking_service: Arc<BookingService>,
|
||||||
reporting_service: Arc<ReportingService>,
|
reporting_service: Arc<ReportingService>,
|
||||||
working_hours_service: Arc<WorkingHoursService>,
|
working_hours_service: Arc<WorkingHoursService>,
|
||||||
|
extra_hours_service: Arc<ExtraHoursService>,
|
||||||
}
|
}
|
||||||
impl rest::RestStateDef for RestStateImpl {
|
impl rest::RestStateDef for RestStateImpl {
|
||||||
type UserService = UserService;
|
type UserService = UserService;
|
||||||
|
|
@ -68,6 +75,7 @@ impl rest::RestStateDef for RestStateImpl {
|
||||||
type BookingService = BookingService;
|
type BookingService = BookingService;
|
||||||
type ReportingService = ReportingService;
|
type ReportingService = ReportingService;
|
||||||
type WorkingHoursService = WorkingHoursService;
|
type WorkingHoursService = WorkingHoursService;
|
||||||
|
type ExtraHoursService = ExtraHoursService;
|
||||||
|
|
||||||
fn user_service(&self) -> Arc<Self::UserService> {
|
fn user_service(&self) -> Arc<Self::UserService> {
|
||||||
self.user_service.clone()
|
self.user_service.clone()
|
||||||
|
|
@ -90,6 +98,9 @@ impl rest::RestStateDef for RestStateImpl {
|
||||||
fn working_hours_service(&self) -> Arc<Self::WorkingHoursService> {
|
fn working_hours_service(&self) -> Arc<Self::WorkingHoursService> {
|
||||||
self.working_hours_service.clone()
|
self.working_hours_service.clone()
|
||||||
}
|
}
|
||||||
|
fn extra_hours_service(&self) -> Arc<Self::ExtraHoursService> {
|
||||||
|
self.extra_hours_service.clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
impl RestStateImpl {
|
impl RestStateImpl {
|
||||||
pub fn new(pool: Arc<sqlx::Pool<sqlx::Sqlite>>) -> Self {
|
pub fn new(pool: Arc<sqlx::Pool<sqlx::Sqlite>>) -> Self {
|
||||||
|
|
@ -140,7 +151,7 @@ impl RestStateImpl {
|
||||||
slot_service.clone(),
|
slot_service.clone(),
|
||||||
));
|
));
|
||||||
let reporting_service = Arc::new(service_impl::reporting::ReportingServiceImpl::new(
|
let reporting_service = Arc::new(service_impl::reporting::ReportingServiceImpl::new(
|
||||||
extra_hours_dao,
|
extra_hours_dao.clone(),
|
||||||
shiftplan_report_dao,
|
shiftplan_report_dao,
|
||||||
working_hours_dao.clone(),
|
working_hours_dao.clone(),
|
||||||
sales_person_service.clone(),
|
sales_person_service.clone(),
|
||||||
|
|
@ -152,6 +163,12 @@ impl RestStateImpl {
|
||||||
Arc::new(service_impl::working_hours::WorkingHoursServiceImpl::new(
|
Arc::new(service_impl::working_hours::WorkingHoursServiceImpl::new(
|
||||||
working_hours_dao,
|
working_hours_dao,
|
||||||
permission_service.clone(),
|
permission_service.clone(),
|
||||||
|
clock_service.clone(),
|
||||||
|
uuid_service.clone(),
|
||||||
|
));
|
||||||
|
let extra_hours_service = Arc::new(service_impl::extra_hours::ExtraHoursServiceImpl::new(
|
||||||
|
extra_hours_dao,
|
||||||
|
permission_service.clone(),
|
||||||
clock_service,
|
clock_service,
|
||||||
uuid_service,
|
uuid_service,
|
||||||
));
|
));
|
||||||
|
|
@ -163,6 +180,7 @@ impl RestStateImpl {
|
||||||
booking_service,
|
booking_service,
|
||||||
reporting_service,
|
reporting_service,
|
||||||
working_hours_service,
|
working_hours_service,
|
||||||
|
extra_hours_service,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,9 @@ pub struct ExtraHoursEntity {
|
||||||
pub category: ExtraHoursCategoryEntity,
|
pub category: ExtraHoursCategoryEntity,
|
||||||
pub description: Arc<str>,
|
pub description: Arc<str>,
|
||||||
pub date_time: time::PrimitiveDateTime,
|
pub date_time: time::PrimitiveDateTime,
|
||||||
|
pub created: time::PrimitiveDateTime,
|
||||||
pub deleted: Option<time::PrimitiveDateTime>,
|
pub deleted: Option<time::PrimitiveDateTime>,
|
||||||
|
pub version: Uuid,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[automock]
|
#[automock]
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ use dao::{
|
||||||
extra_hours::{ExtraHoursCategoryEntity, ExtraHoursDao, ExtraHoursEntity},
|
extra_hours::{ExtraHoursCategoryEntity, ExtraHoursDao, ExtraHoursEntity},
|
||||||
DaoError,
|
DaoError,
|
||||||
};
|
};
|
||||||
use sqlx::query_as;
|
use sqlx::{query, query_as};
|
||||||
use time::{format_description::well_known::Iso8601, PrimitiveDateTime};
|
use time::{format_description::well_known::Iso8601, PrimitiveDateTime};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
|
@ -18,15 +18,17 @@ struct ExtraHoursDb {
|
||||||
category: String,
|
category: String,
|
||||||
description: Option<String>,
|
description: Option<String>,
|
||||||
date_time: String,
|
date_time: String,
|
||||||
|
created: String,
|
||||||
deleted: Option<String>,
|
deleted: Option<String>,
|
||||||
|
update_version: Vec<u8>,
|
||||||
}
|
}
|
||||||
impl TryFrom<&ExtraHoursDb> for ExtraHoursEntity {
|
impl TryFrom<&ExtraHoursDb> for ExtraHoursEntity {
|
||||||
type Error = DaoError;
|
type Error = DaoError;
|
||||||
|
|
||||||
fn try_from(extra_hours: &ExtraHoursDb) -> Result<Self, DaoError> {
|
fn try_from(extra_hours: &ExtraHoursDb) -> Result<Self, DaoError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
id: Uuid::from_slice(extra_hours.id.as_ref()).unwrap(),
|
id: Uuid::from_slice(extra_hours.id.as_ref())?,
|
||||||
sales_person_id: Uuid::from_slice(extra_hours.sales_person_id.as_ref()).unwrap(),
|
sales_person_id: Uuid::from_slice(extra_hours.sales_person_id.as_ref())?,
|
||||||
amount: extra_hours.amount as f32,
|
amount: extra_hours.amount as f32,
|
||||||
category: match extra_hours.category.as_str() {
|
category: match extra_hours.category.as_str() {
|
||||||
"ExtraWork" => ExtraHoursCategoryEntity::ExtraWork,
|
"ExtraWork" => ExtraHoursCategoryEntity::ExtraWork,
|
||||||
|
|
@ -44,14 +46,14 @@ impl TryFrom<&ExtraHoursDb> for ExtraHoursEntity {
|
||||||
date_time: PrimitiveDateTime::parse(
|
date_time: PrimitiveDateTime::parse(
|
||||||
extra_hours.date_time.as_str(),
|
extra_hours.date_time.as_str(),
|
||||||
&Iso8601::DATE_TIME,
|
&Iso8601::DATE_TIME,
|
||||||
)
|
)?,
|
||||||
.unwrap(),
|
created: PrimitiveDateTime::parse(extra_hours.created.as_str(), &Iso8601::DATE_TIME)?,
|
||||||
deleted: extra_hours
|
deleted: extra_hours
|
||||||
.deleted
|
.deleted
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|deleted| PrimitiveDateTime::parse(deleted, &Iso8601::DATE_TIME))
|
.map(|deleted| PrimitiveDateTime::parse(deleted, &Iso8601::DATE_TIME))
|
||||||
.transpose()
|
.transpose()?,
|
||||||
.unwrap(),
|
version: Uuid::from_slice(&extra_hours.update_version)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -76,7 +78,7 @@ impl ExtraHoursDao for ExtraHoursDaoImpl {
|
||||||
let id_vec = sales_person_id.as_bytes().to_vec();
|
let id_vec = sales_person_id.as_bytes().to_vec();
|
||||||
Ok(query_as!(
|
Ok(query_as!(
|
||||||
ExtraHoursDb,
|
ExtraHoursDb,
|
||||||
"SELECT id, sales_person_id, amount, category, description, date_time, deleted FROM extra_hours WHERE sales_person_id = ? AND strftime('%Y', date_time) = ? AND strftime('%m', date_time) <= ?",
|
"SELECT id, sales_person_id, amount, category, description, date_time, created, deleted, update_version FROM extra_hours WHERE sales_person_id = ? AND CAST(strftime('%Y', date_time) AS INTEGER) = ? AND CAST(strftime('%m', date_time) AS INTEGER) <= ?",
|
||||||
id_vec,
|
id_vec,
|
||||||
year,
|
year,
|
||||||
until_week,
|
until_week,
|
||||||
|
|
@ -90,10 +92,41 @@ impl ExtraHoursDao for ExtraHoursDaoImpl {
|
||||||
}
|
}
|
||||||
async fn create(
|
async fn create(
|
||||||
&self,
|
&self,
|
||||||
_entity: &ExtraHoursEntity,
|
entity: &ExtraHoursEntity,
|
||||||
_process: &str,
|
process: &str,
|
||||||
) -> Result<(), crate::DaoError> {
|
) -> Result<(), crate::DaoError> {
|
||||||
unimplemented!()
|
let id_vec = entity.id.as_bytes().to_vec();
|
||||||
|
let sales_person_id_vec = entity.sales_person_id.as_bytes().to_vec();
|
||||||
|
let category = match entity.category {
|
||||||
|
ExtraHoursCategoryEntity::ExtraWork => "ExtraWork",
|
||||||
|
ExtraHoursCategoryEntity::Vacation => "Vacation",
|
||||||
|
ExtraHoursCategoryEntity::SickLeave => "SickLeave",
|
||||||
|
ExtraHoursCategoryEntity::Holiday => "Holiday",
|
||||||
|
};
|
||||||
|
let description = entity.description.as_ref();
|
||||||
|
let date_time = entity.date_time.format(&Iso8601::DATE_TIME)?;
|
||||||
|
let created = entity.created.format(&Iso8601::DATE_TIME)?;
|
||||||
|
let deleted = entity
|
||||||
|
.deleted
|
||||||
|
.map(|deleted| deleted.format(&Iso8601::DATE_TIME))
|
||||||
|
.transpose()?;
|
||||||
|
let version_vec = entity.version.as_bytes().to_vec();
|
||||||
|
query!(
|
||||||
|
"INSERT INTO extra_hours (id, sales_person_id, amount, category, description, date_time, created, deleted, update_process, update_version) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||||
|
id_vec,
|
||||||
|
sales_person_id_vec,
|
||||||
|
entity.amount,
|
||||||
|
category,
|
||||||
|
description,
|
||||||
|
date_time,
|
||||||
|
created,
|
||||||
|
deleted,
|
||||||
|
process,
|
||||||
|
version_vec,
|
||||||
|
).execute(self.pool.as_ref())
|
||||||
|
.await
|
||||||
|
.map_db_error()?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
async fn update(
|
async fn update(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
||||||
|
|
@ -237,14 +237,14 @@ impl From<&service::reporting::ShortEmployeeReport> for ShortEmployeeReportTO {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub enum ExtraHoursCategoryTO {
|
pub enum ExtraHoursReportCategoryTO {
|
||||||
Shiftplan,
|
Shiftplan,
|
||||||
ExtraWork,
|
ExtraWork,
|
||||||
Vacation,
|
Vacation,
|
||||||
SickLeave,
|
SickLeave,
|
||||||
Holiday,
|
Holiday,
|
||||||
}
|
}
|
||||||
impl From<&service::reporting::ExtraHoursCategory> for ExtraHoursCategoryTO {
|
impl From<&service::reporting::ExtraHoursCategory> for ExtraHoursReportCategoryTO {
|
||||||
fn from(category: &service::reporting::ExtraHoursCategory) -> Self {
|
fn from(category: &service::reporting::ExtraHoursCategory) -> Self {
|
||||||
match category {
|
match category {
|
||||||
service::reporting::ExtraHoursCategory::Shiftplan => Self::Shiftplan,
|
service::reporting::ExtraHoursCategory::Shiftplan => Self::Shiftplan,
|
||||||
|
|
@ -260,7 +260,7 @@ impl From<&service::reporting::ExtraHoursCategory> for ExtraHoursCategoryTO {
|
||||||
pub struct WorkingHoursDayTO {
|
pub struct WorkingHoursDayTO {
|
||||||
pub date: time::Date,
|
pub date: time::Date,
|
||||||
pub hours: f32,
|
pub hours: f32,
|
||||||
pub category: ExtraHoursCategoryTO,
|
pub category: ExtraHoursReportCategoryTO,
|
||||||
}
|
}
|
||||||
impl From<&service::reporting::WorkingHoursDay> for WorkingHoursDayTO {
|
impl From<&service::reporting::WorkingHoursDay> for WorkingHoursDayTO {
|
||||||
fn from(day: &service::reporting::WorkingHoursDay) -> Self {
|
fn from(day: &service::reporting::WorkingHoursDay) -> Self {
|
||||||
|
|
@ -409,3 +409,79 @@ impl From<&WorkingHoursTO> for service::working_hours::WorkingHours {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub enum ExtraHoursCategoryTO {
|
||||||
|
ExtraWork,
|
||||||
|
Vacation,
|
||||||
|
SickLeave,
|
||||||
|
Holiday,
|
||||||
|
}
|
||||||
|
impl From<&service::extra_hours::ExtraHoursCategory> for ExtraHoursCategoryTO {
|
||||||
|
fn from(category: &service::extra_hours::ExtraHoursCategory) -> Self {
|
||||||
|
match category {
|
||||||
|
service::extra_hours::ExtraHoursCategory::ExtraWork => Self::ExtraWork,
|
||||||
|
service::extra_hours::ExtraHoursCategory::Vacation => Self::Vacation,
|
||||||
|
service::extra_hours::ExtraHoursCategory::SickLeave => Self::SickLeave,
|
||||||
|
service::extra_hours::ExtraHoursCategory::Holiday => Self::Holiday,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<&ExtraHoursCategoryTO> for service::extra_hours::ExtraHoursCategory {
|
||||||
|
fn from(category: &ExtraHoursCategoryTO) -> Self {
|
||||||
|
match category {
|
||||||
|
ExtraHoursCategoryTO::ExtraWork => Self::ExtraWork,
|
||||||
|
ExtraHoursCategoryTO::Vacation => Self::Vacation,
|
||||||
|
ExtraHoursCategoryTO::SickLeave => Self::SickLeave,
|
||||||
|
ExtraHoursCategoryTO::Holiday => Self::Holiday,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct ExtraHoursTO {
|
||||||
|
#[serde(default)]
|
||||||
|
pub id: Uuid,
|
||||||
|
pub sales_person_id: Uuid,
|
||||||
|
pub amount: f32,
|
||||||
|
pub category: ExtraHoursCategoryTO,
|
||||||
|
pub description: Arc<str>,
|
||||||
|
pub date_time: time::PrimitiveDateTime,
|
||||||
|
#[serde(default)]
|
||||||
|
pub created: Option<time::PrimitiveDateTime>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub deleted: Option<time::PrimitiveDateTime>,
|
||||||
|
#[serde(rename = "$version")]
|
||||||
|
#[serde(default)]
|
||||||
|
pub version: Uuid,
|
||||||
|
}
|
||||||
|
impl From<&service::extra_hours::ExtraHours> for ExtraHoursTO {
|
||||||
|
fn from(extra_hours: &service::extra_hours::ExtraHours) -> Self {
|
||||||
|
Self {
|
||||||
|
id: extra_hours.id,
|
||||||
|
sales_person_id: extra_hours.sales_person_id,
|
||||||
|
amount: extra_hours.amount,
|
||||||
|
category: (&extra_hours.category).into(),
|
||||||
|
description: extra_hours.description.clone(),
|
||||||
|
date_time: extra_hours.date_time,
|
||||||
|
created: extra_hours.created,
|
||||||
|
deleted: extra_hours.deleted,
|
||||||
|
version: extra_hours.version,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<&ExtraHoursTO> for service::extra_hours::ExtraHours {
|
||||||
|
fn from(extra_hours: &ExtraHoursTO) -> Self {
|
||||||
|
Self {
|
||||||
|
id: extra_hours.id,
|
||||||
|
sales_person_id: extra_hours.sales_person_id,
|
||||||
|
amount: extra_hours.amount,
|
||||||
|
category: (&extra_hours.category).into(),
|
||||||
|
description: extra_hours.description.clone(),
|
||||||
|
date_time: extra_hours.date_time,
|
||||||
|
created: extra_hours.created,
|
||||||
|
deleted: extra_hours.deleted,
|
||||||
|
version: extra_hours.version,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
34
rest/src/extra_hours.rs
Normal file
34
rest/src/extra_hours.rs
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
use axum::{
|
||||||
|
body::Body, extract::State, response::Response, routing::post, Extension, Json, Router,
|
||||||
|
};
|
||||||
|
use rest_types::ExtraHoursTO;
|
||||||
|
|
||||||
|
use service::extra_hours::ExtraHoursService;
|
||||||
|
|
||||||
|
use crate::{error_handler, Context, RestStateDef};
|
||||||
|
|
||||||
|
pub fn generate_route<RestState: RestStateDef>() -> Router<RestState> {
|
||||||
|
Router::new().route("/", post(create_extra_hours::<RestState>))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn create_extra_hours<RestState: RestStateDef>(
|
||||||
|
rest_state: State<RestState>,
|
||||||
|
Extension(context): Extension<Context>,
|
||||||
|
Json(sales_person): Json<ExtraHoursTO>,
|
||||||
|
) -> Response {
|
||||||
|
error_handler(
|
||||||
|
(async {
|
||||||
|
let extra_hours = ExtraHoursTO::from(
|
||||||
|
&rest_state
|
||||||
|
.extra_hours_service()
|
||||||
|
.create(&(&sales_person).into(), context.into())
|
||||||
|
.await?,
|
||||||
|
);
|
||||||
|
Ok(Response::builder()
|
||||||
|
.status(200)
|
||||||
|
.body(Body::new(serde_json::to_string(&extra_hours).unwrap()))
|
||||||
|
.unwrap())
|
||||||
|
})
|
||||||
|
.await,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use std::{convert::Infallible, sync::Arc};
|
use std::{convert::Infallible, sync::Arc};
|
||||||
|
|
||||||
mod booking;
|
mod booking;
|
||||||
|
mod extra_hours;
|
||||||
mod permission;
|
mod permission;
|
||||||
mod report;
|
mod report;
|
||||||
mod sales_person;
|
mod sales_person;
|
||||||
|
|
@ -231,6 +232,10 @@ pub trait RestStateDef: Clone + Send + Sync + 'static {
|
||||||
+ Send
|
+ Send
|
||||||
+ Sync
|
+ Sync
|
||||||
+ 'static;
|
+ 'static;
|
||||||
|
type ExtraHoursService: service::extra_hours::ExtraHoursService<Context = Context>
|
||||||
|
+ Send
|
||||||
|
+ Sync
|
||||||
|
+ 'static;
|
||||||
|
|
||||||
fn user_service(&self) -> Arc<Self::UserService>;
|
fn user_service(&self) -> Arc<Self::UserService>;
|
||||||
fn permission_service(&self) -> Arc<Self::PermissionService>;
|
fn permission_service(&self) -> Arc<Self::PermissionService>;
|
||||||
|
|
@ -239,6 +244,7 @@ pub trait RestStateDef: Clone + Send + Sync + 'static {
|
||||||
fn booking_service(&self) -> Arc<Self::BookingService>;
|
fn booking_service(&self) -> Arc<Self::BookingService>;
|
||||||
fn reporting_service(&self) -> Arc<Self::ReportingService>;
|
fn reporting_service(&self) -> Arc<Self::ReportingService>;
|
||||||
fn working_hours_service(&self) -> Arc<Self::WorkingHoursService>;
|
fn working_hours_service(&self) -> Arc<Self::WorkingHoursService>;
|
||||||
|
fn extra_hours_service(&self) -> Arc<Self::ExtraHoursService>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct OidcConfig {
|
pub struct OidcConfig {
|
||||||
|
|
@ -344,6 +350,7 @@ pub async fn start_server<RestState: RestStateDef>(rest_state: RestState) {
|
||||||
.nest("/booking", booking::generate_route())
|
.nest("/booking", booking::generate_route())
|
||||||
.nest("/report", report::generate_route())
|
.nest("/report", report::generate_route())
|
||||||
.nest("/working-hours", working_hours::generate_route())
|
.nest("/working-hours", working_hours::generate_route())
|
||||||
|
.nest("/extra-hours", extra_hours::generate_route())
|
||||||
.with_state(rest_state)
|
.with_state(rest_state)
|
||||||
.layer(middleware::from_fn(context_extractor));
|
.layer(middleware::from_fn(context_extractor));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
|
use std::fmt::Debug;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use mockall::automock;
|
use mockall::automock;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use dao::DaoError;
|
use crate::{permission::Authentication, ServiceError};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum ExtraHoursCategory {
|
pub enum ExtraHoursCategory {
|
||||||
|
|
@ -42,7 +43,9 @@ pub struct ExtraHours {
|
||||||
pub category: ExtraHoursCategory,
|
pub category: ExtraHoursCategory,
|
||||||
pub description: Arc<str>,
|
pub description: Arc<str>,
|
||||||
pub date_time: time::PrimitiveDateTime,
|
pub date_time: time::PrimitiveDateTime,
|
||||||
|
pub created: Option<time::PrimitiveDateTime>,
|
||||||
pub deleted: Option<time::PrimitiveDateTime>,
|
pub deleted: Option<time::PrimitiveDateTime>,
|
||||||
|
pub version: Uuid,
|
||||||
}
|
}
|
||||||
impl From<&dao::extra_hours::ExtraHoursEntity> for ExtraHours {
|
impl From<&dao::extra_hours::ExtraHoursEntity> for ExtraHours {
|
||||||
fn from(extra_hours: &dao::extra_hours::ExtraHoursEntity) -> Self {
|
fn from(extra_hours: &dao::extra_hours::ExtraHoursEntity) -> Self {
|
||||||
|
|
@ -53,34 +56,56 @@ impl From<&dao::extra_hours::ExtraHoursEntity> for ExtraHours {
|
||||||
category: (&extra_hours.category).into(),
|
category: (&extra_hours.category).into(),
|
||||||
description: extra_hours.description.clone(),
|
description: extra_hours.description.clone(),
|
||||||
date_time: extra_hours.date_time,
|
date_time: extra_hours.date_time,
|
||||||
|
created: Some(extra_hours.created),
|
||||||
deleted: extra_hours.deleted,
|
deleted: extra_hours.deleted,
|
||||||
|
version: extra_hours.version,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl From<&ExtraHours> for dao::extra_hours::ExtraHoursEntity {
|
impl TryFrom<&ExtraHours> for dao::extra_hours::ExtraHoursEntity {
|
||||||
fn from(extra_hours: &ExtraHours) -> Self {
|
type Error = ServiceError;
|
||||||
Self {
|
fn try_from(extra_hours: &ExtraHours) -> Result<Self, Self::Error> {
|
||||||
|
Ok(Self {
|
||||||
id: extra_hours.id,
|
id: extra_hours.id,
|
||||||
sales_person_id: extra_hours.sales_person_id,
|
sales_person_id: extra_hours.sales_person_id,
|
||||||
amount: extra_hours.amount,
|
amount: extra_hours.amount,
|
||||||
category: (&extra_hours.category).into(),
|
category: (&extra_hours.category).into(),
|
||||||
description: extra_hours.description.clone(),
|
description: extra_hours.description.clone(),
|
||||||
date_time: extra_hours.date_time,
|
date_time: extra_hours.date_time,
|
||||||
|
created: extra_hours
|
||||||
|
.created
|
||||||
|
.ok_or_else(|| ServiceError::InternalError)?,
|
||||||
deleted: extra_hours.deleted,
|
deleted: extra_hours.deleted,
|
||||||
}
|
version: extra_hours.version,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[automock]
|
#[automock(type Context=();)]
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait ExtraHoursService {
|
pub trait ExtraHoursService {
|
||||||
fn find_by_sales_person_id_and_year(
|
type Context: Clone + Debug + PartialEq + Eq + Send + Sync + 'static;
|
||||||
|
|
||||||
|
async fn find_by_sales_person_id_and_year(
|
||||||
&self,
|
&self,
|
||||||
sales_person_id: Uuid,
|
sales_person_id: Uuid,
|
||||||
year: u32,
|
year: u32,
|
||||||
until_week: u8,
|
until_week: u8,
|
||||||
) -> Result<Arc<[ExtraHours]>, DaoError>;
|
context: Authentication<Self::Context>,
|
||||||
fn create(&self, entity: &ExtraHours, process: &str) -> Result<(), DaoError>;
|
) -> Result<Arc<[ExtraHours]>, ServiceError>;
|
||||||
fn update(&self, entity: &ExtraHours, process: &str) -> Result<(), DaoError>;
|
async fn create(
|
||||||
fn delete(&self, id: Uuid, process: &str) -> Result<(), DaoError>;
|
&self,
|
||||||
|
entity: &ExtraHours,
|
||||||
|
context: Authentication<Self::Context>,
|
||||||
|
) -> Result<ExtraHours, ServiceError>;
|
||||||
|
async fn update(
|
||||||
|
&self,
|
||||||
|
entity: &ExtraHours,
|
||||||
|
context: Authentication<Self::Context>,
|
||||||
|
) -> Result<ExtraHours, ServiceError>;
|
||||||
|
async fn delete(
|
||||||
|
&self,
|
||||||
|
id: Uuid,
|
||||||
|
context: Authentication<Self::Context>,
|
||||||
|
) -> Result<ExtraHours, ServiceError>;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
111
service_impl/src/extra_hours.rs
Normal file
111
service_impl/src/extra_hours.rs
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use dao::extra_hours;
|
||||||
|
use service::{
|
||||||
|
extra_hours::ExtraHours,
|
||||||
|
permission::{Authentication, HR_PRIVILEGE},
|
||||||
|
ServiceError,
|
||||||
|
};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
pub struct ExtraHoursServiceImpl<
|
||||||
|
ExtraHoursDao: dao::extra_hours::ExtraHoursDao,
|
||||||
|
PermissionService: service::PermissionService,
|
||||||
|
ClockService: service::clock::ClockService,
|
||||||
|
UuidService: service::uuid_service::UuidService,
|
||||||
|
> {
|
||||||
|
extra_hours_dao: Arc<ExtraHoursDao>,
|
||||||
|
permission_service: Arc<PermissionService>,
|
||||||
|
clock_service: Arc<ClockService>,
|
||||||
|
uuid_service: Arc<UuidService>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<ExtraHoursDao, PermissionService, ClockService, UuidService>
|
||||||
|
ExtraHoursServiceImpl<ExtraHoursDao, PermissionService, ClockService, UuidService>
|
||||||
|
where
|
||||||
|
ExtraHoursDao: dao::extra_hours::ExtraHoursDao + Sync + Send,
|
||||||
|
PermissionService: service::PermissionService + Sync + Send,
|
||||||
|
ClockService: service::clock::ClockService + Sync + Send,
|
||||||
|
UuidService: service::uuid_service::UuidService + Sync + Send,
|
||||||
|
{
|
||||||
|
pub fn new(
|
||||||
|
extra_hours_dao: Arc<ExtraHoursDao>,
|
||||||
|
permission_service: Arc<PermissionService>,
|
||||||
|
clock_service: Arc<ClockService>,
|
||||||
|
uuid_service: Arc<UuidService>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
extra_hours_dao,
|
||||||
|
permission_service,
|
||||||
|
clock_service,
|
||||||
|
uuid_service,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl<
|
||||||
|
ExtraHoursDao: dao::extra_hours::ExtraHoursDao + Sync + Send,
|
||||||
|
PermissionService: service::PermissionService + Sync + Send,
|
||||||
|
ClockService: service::clock::ClockService + Sync + Send,
|
||||||
|
UuidService: service::uuid_service::UuidService + Sync + Send,
|
||||||
|
> service::extra_hours::ExtraHoursService
|
||||||
|
for ExtraHoursServiceImpl<ExtraHoursDao, PermissionService, ClockService, UuidService>
|
||||||
|
{
|
||||||
|
type Context = PermissionService::Context;
|
||||||
|
|
||||||
|
async fn find_by_sales_person_id_and_year(
|
||||||
|
&self,
|
||||||
|
_sales_person_id: Uuid,
|
||||||
|
_year: u32,
|
||||||
|
_until_week: u8,
|
||||||
|
_context: Authentication<Self::Context>,
|
||||||
|
) -> Result<Arc<[ExtraHours]>, ServiceError> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
async fn create(
|
||||||
|
&self,
|
||||||
|
extra_hours: &ExtraHours,
|
||||||
|
context: Authentication<Self::Context>,
|
||||||
|
) -> Result<ExtraHours, ServiceError> {
|
||||||
|
self.permission_service
|
||||||
|
.check_permission(HR_PRIVILEGE, context)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let mut extra_hours = extra_hours.to_owned();
|
||||||
|
if !extra_hours.id.is_nil() {
|
||||||
|
return Err(ServiceError::IdSetOnCreate);
|
||||||
|
}
|
||||||
|
if !extra_hours.version.is_nil() {
|
||||||
|
return Err(ServiceError::VersionSetOnCreate);
|
||||||
|
}
|
||||||
|
|
||||||
|
extra_hours.id = self.uuid_service.new_uuid("extra_hours_service::create id");
|
||||||
|
extra_hours.version = self
|
||||||
|
.uuid_service
|
||||||
|
.new_uuid("extra_hours_service::create version");
|
||||||
|
extra_hours.created = Some(self.clock_service.date_time_now());
|
||||||
|
|
||||||
|
let extra_hours_entity = extra_hours::ExtraHoursEntity::try_from(&extra_hours)?;
|
||||||
|
self.extra_hours_dao
|
||||||
|
.create(&extra_hours_entity, "extra_hours_service::create")
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(extra_hours.into())
|
||||||
|
}
|
||||||
|
async fn update(
|
||||||
|
&self,
|
||||||
|
_entity: &ExtraHours,
|
||||||
|
_context: Authentication<Self::Context>,
|
||||||
|
) -> Result<ExtraHours, ServiceError> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
async fn delete(
|
||||||
|
&self,
|
||||||
|
_id: Uuid,
|
||||||
|
_context: Authentication<Self::Context>,
|
||||||
|
) -> Result<ExtraHours, ServiceError> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,7 @@ use async_trait::async_trait;
|
||||||
|
|
||||||
pub mod booking;
|
pub mod booking;
|
||||||
pub mod clock;
|
pub mod clock;
|
||||||
|
pub mod extra_hours;
|
||||||
pub mod permission;
|
pub mod permission;
|
||||||
pub mod reporting;
|
pub mod reporting;
|
||||||
pub mod sales_person;
|
pub mod sales_person;
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,6 @@ pub fn find_working_hours_for_calendar_week(
|
||||||
year: u32,
|
year: u32,
|
||||||
week: u8,
|
week: u8,
|
||||||
) -> Option<&WorkingHoursEntity> {
|
) -> Option<&WorkingHoursEntity> {
|
||||||
dbg!((year, week));
|
|
||||||
working_hours.iter().find(|wh| {
|
working_hours.iter().find(|wh| {
|
||||||
(year, week) >= (wh.from_year, wh.from_calendar_week)
|
(year, week) >= (wh.from_year, wh.from_calendar_week)
|
||||||
&& (year, week) <= (wh.to_year, wh.to_calendar_week)
|
&& (year, week) <= (wh.to_year, wh.to_calendar_week)
|
||||||
|
|
|
||||||
|
|
@ -87,14 +87,10 @@ where
|
||||||
.await
|
.await
|
||||||
.is_err()
|
.is_err()
|
||||||
{
|
{
|
||||||
println!("No HR Role - remove sensitive data");
|
|
||||||
sales_persons.iter_mut().for_each(|sales_person| {
|
sales_persons.iter_mut().for_each(|sales_person| {
|
||||||
sales_person.is_paid = None;
|
sales_person.is_paid = None;
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
println!("HR ROLE - no sensitive data removal");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(sales_persons.into())
|
Ok(sales_persons.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -128,7 +124,6 @@ where
|
||||||
.check_permission(HR_PRIVILEGE, context.clone())
|
.check_permission(HR_PRIVILEGE, context.clone())
|
||||||
);
|
);
|
||||||
shiftplanner.or(sales).or(hr)?;
|
shiftplanner.or(sales).or(hr)?;
|
||||||
println!("Has roles");
|
|
||||||
let mut sales_person = self
|
let mut sales_person = self
|
||||||
.sales_person_dao
|
.sales_person_dao
|
||||||
.find_by_id(id)
|
.find_by_id(id)
|
||||||
|
|
@ -143,21 +138,17 @@ where
|
||||||
.await
|
.await
|
||||||
.is_err()
|
.is_err()
|
||||||
{
|
{
|
||||||
println!("No HR Role - futher checks required");
|
|
||||||
if let (Some(current_user_id), Some(assigned_user)) = (
|
if let (Some(current_user_id), Some(assigned_user)) = (
|
||||||
self.permission_service
|
self.permission_service
|
||||||
.current_user_id(context.clone())
|
.current_user_id(context.clone())
|
||||||
.await?,
|
.await?,
|
||||||
self.get_assigned_user(id, Authentication::Full).await?,
|
self.get_assigned_user(id, Authentication::Full).await?,
|
||||||
) {
|
) {
|
||||||
println!("Check if user ID matches");
|
|
||||||
current_user_id != assigned_user
|
current_user_id != assigned_user
|
||||||
} else {
|
} else {
|
||||||
println!("UserID or assigned user is missing - must remove sensitive data");
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
println!("HR Role - no sensitive data removal");
|
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue