Add REST endpoint to find bookings per week
This commit is contained in:
parent
47a3de3c54
commit
e1f9936b62
6 changed files with 110 additions and 0 deletions
|
|
@ -31,6 +31,11 @@ pub trait BookingDao {
|
||||||
calendar_week: i32,
|
calendar_week: i32,
|
||||||
year: u32,
|
year: u32,
|
||||||
) -> Result<Option<BookingEntity>, DaoError>;
|
) -> Result<Option<BookingEntity>, DaoError>;
|
||||||
|
async fn find_by_week(
|
||||||
|
&self,
|
||||||
|
calendar_week: i32,
|
||||||
|
year: u32,
|
||||||
|
) -> Result<Arc<[BookingEntity]>, DaoError>;
|
||||||
async fn create(&self, entity: &BookingEntity, process: &str) -> Result<(), DaoError>;
|
async fn create(&self, entity: &BookingEntity, process: &str) -> Result<(), DaoError>;
|
||||||
async fn update(&self, entity: &BookingEntity, process: &str) -> Result<(), DaoError>;
|
async fn update(&self, entity: &BookingEntity, process: &str) -> Result<(), DaoError>;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,26 @@ impl BookingDao for BookingDaoImpl {
|
||||||
.transpose()?)
|
.transpose()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn find_by_week(
|
||||||
|
&self,
|
||||||
|
calendar_week: i32,
|
||||||
|
year: u32,
|
||||||
|
) -> Result<Arc<[BookingEntity]>, DaoError> {
|
||||||
|
Ok(query_as!(
|
||||||
|
BookingDb,
|
||||||
|
"SELECT id, sales_person_id, slot_id, calendar_week, year, created, deleted, update_version FROM booking WHERE calendar_week = ? AND year = ? AND deleted IS NULL",
|
||||||
|
calendar_week,
|
||||||
|
year,
|
||||||
|
)
|
||||||
|
.fetch_all(self.pool.as_ref())
|
||||||
|
.await
|
||||||
|
.map_db_error()?
|
||||||
|
.iter()
|
||||||
|
.map(BookingEntity::try_from)
|
||||||
|
.collect::<Result<Arc<[BookingEntity]>, DaoError>>()?
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
async fn create(&self, entity: &BookingEntity, process: &str) -> Result<(), DaoError> {
|
async fn create(&self, entity: &BookingEntity, process: &str) -> Result<(), DaoError> {
|
||||||
let id_vec = entity.id.as_bytes().to_vec();
|
let id_vec = entity.id.as_bytes().to_vec();
|
||||||
let sales_person_id_vec = entity.sales_person_id.as_bytes().to_vec();
|
let sales_person_id_vec = entity.sales_person_id.as_bytes().to_vec();
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ use service::booking::{Booking, BookingService};
|
||||||
pub fn generate_route<RestState: RestStateDef>() -> Router<RestState> {
|
pub fn generate_route<RestState: RestStateDef>() -> Router<RestState> {
|
||||||
Router::new()
|
Router::new()
|
||||||
.route("/", get(get_all_bookings::<RestState>))
|
.route("/", get(get_all_bookings::<RestState>))
|
||||||
|
.route("/week/:year/:calendar_week", get(get_by_week::<RestState>))
|
||||||
.route("/:id", get(get_booking::<RestState>))
|
.route("/:id", get(get_booking::<RestState>))
|
||||||
.route("/", post(create_booking::<RestState>))
|
.route("/", post(create_booking::<RestState>))
|
||||||
.route("/:id", delete(delete_booking::<RestState>))
|
.route("/:id", delete(delete_booking::<RestState>))
|
||||||
|
|
@ -41,6 +42,29 @@ pub async fn get_all_bookings<RestState: RestStateDef>(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_by_week<RestState: RestStateDef>(
|
||||||
|
rest_state: State<RestState>,
|
||||||
|
Extension(context): Extension<Context>,
|
||||||
|
Path((calendar_week, year)): Path<(i32, u32)>,
|
||||||
|
) -> Response {
|
||||||
|
error_handler(
|
||||||
|
(async {
|
||||||
|
let bookings: Arc<[BookingTO]> = rest_state
|
||||||
|
.booking_service()
|
||||||
|
.get_for_week(calendar_week, year, context.into())
|
||||||
|
.await?
|
||||||
|
.iter()
|
||||||
|
.map(BookingTO::from)
|
||||||
|
.collect();
|
||||||
|
Ok(Response::builder()
|
||||||
|
.status(200)
|
||||||
|
.body(Body::new(serde_json::to_string(&bookings).unwrap()))
|
||||||
|
.unwrap())
|
||||||
|
})
|
||||||
|
.await,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn get_booking<RestState: RestStateDef>(
|
pub async fn get_booking<RestState: RestStateDef>(
|
||||||
rest_state: State<RestState>,
|
rest_state: State<RestState>,
|
||||||
Extension(context): Extension<Context>,
|
Extension(context): Extension<Context>,
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,12 @@ pub trait BookingService {
|
||||||
id: Uuid,
|
id: Uuid,
|
||||||
context: Authentication<Self::Context>,
|
context: Authentication<Self::Context>,
|
||||||
) -> Result<Booking, ServiceError>;
|
) -> Result<Booking, ServiceError>;
|
||||||
|
async fn get_for_week(
|
||||||
|
&self,
|
||||||
|
calendar_week: i32,
|
||||||
|
year: u32,
|
||||||
|
context: Authentication<Self::Context>,
|
||||||
|
) -> Result<Arc<[Booking]>, ServiceError>;
|
||||||
async fn create(
|
async fn create(
|
||||||
&self,
|
&self,
|
||||||
booking: &Booking,
|
booking: &Booking,
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ use service::{
|
||||||
ServiceError, ValidationFailureItem,
|
ServiceError, ValidationFailureItem,
|
||||||
};
|
};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use tokio::join;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
const BOOKING_SERVICE_PROCESS: &str = "booking-service";
|
const BOOKING_SERVICE_PROCESS: &str = "booking-service";
|
||||||
|
|
@ -122,6 +123,28 @@ where
|
||||||
Ok(booking)
|
Ok(booking)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_for_week(
|
||||||
|
&self,
|
||||||
|
calendar_week: i32,
|
||||||
|
year: u32,
|
||||||
|
context: Authentication<Self::Context>,
|
||||||
|
) -> Result<Arc<[Booking]>, ServiceError> {
|
||||||
|
let (hr_permission, sales_permission) = join!(
|
||||||
|
self.permission_service
|
||||||
|
.check_permission("hr", context.clone()),
|
||||||
|
self.permission_service.check_permission("sales", context),
|
||||||
|
);
|
||||||
|
hr_permission.or(sales_permission)?;
|
||||||
|
|
||||||
|
Ok(self
|
||||||
|
.booking_dao
|
||||||
|
.find_by_week(calendar_week, year)
|
||||||
|
.await?
|
||||||
|
.iter()
|
||||||
|
.map(Booking::from)
|
||||||
|
.collect())
|
||||||
|
}
|
||||||
|
|
||||||
async fn create(
|
async fn create(
|
||||||
&self,
|
&self,
|
||||||
booking: &Booking,
|
booking: &Booking,
|
||||||
|
|
|
||||||
|
|
@ -214,6 +214,38 @@ async fn test_get_no_permission() {
|
||||||
test_forbidden(&result);
|
test_forbidden(&result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_get_for_week() {
|
||||||
|
let mut deps = build_dependencies(true, "sales");
|
||||||
|
deps.booking_dao
|
||||||
|
.expect_find_by_week()
|
||||||
|
.with(eq(3), eq(2024))
|
||||||
|
.returning(|_, _| Ok([default_booking_entity()].into()));
|
||||||
|
let service = deps.build_service();
|
||||||
|
let result = service.get_for_week(3, 2024, ().auth()).await;
|
||||||
|
assert_eq!(result.unwrap(), [default_booking()].into());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_get_for_week_hr_role() {
|
||||||
|
let mut deps = build_dependencies(true, "hr");
|
||||||
|
deps.booking_dao
|
||||||
|
.expect_find_by_week()
|
||||||
|
.with(eq(3), eq(2024))
|
||||||
|
.returning(|_, _| Ok([default_booking_entity()].into()));
|
||||||
|
let service = deps.build_service();
|
||||||
|
let result = service.get_for_week(3, 2024, ().auth()).await;
|
||||||
|
assert_eq!(result.unwrap(), [default_booking()].into());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_get_for_week_no_permission() {
|
||||||
|
let deps = build_dependencies(false, "hr");
|
||||||
|
let service = deps.build_service();
|
||||||
|
let result = service.get_for_week(3, 2024, ().auth()).await;
|
||||||
|
test_forbidden(&result);
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_create() {
|
async fn test_create() {
|
||||||
let mut deps = build_dependencies(true, "hr");
|
let mut deps = build_dependencies(true, "hr");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue