Add rest service for booking
This commit is contained in:
parent
d8dcc7099d
commit
8ea16624ad
4 changed files with 162 additions and 4 deletions
|
|
@ -18,17 +18,26 @@ type SalesPersonService = service_impl::sales_person::SalesPersonServiceImpl<
|
||||||
ClockService,
|
ClockService,
|
||||||
UuidService,
|
UuidService,
|
||||||
>;
|
>;
|
||||||
|
type BookingService = service_impl::booking::BookingServiceImpl<
|
||||||
|
dao_impl::booking::BookingDaoImpl,
|
||||||
|
PermissionService,
|
||||||
|
ClockService,
|
||||||
|
UuidService,
|
||||||
|
>;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct RestStateImpl {
|
pub struct RestStateImpl {
|
||||||
permission_service: Arc<PermissionService>,
|
permission_service: Arc<PermissionService>,
|
||||||
slot_service: Arc<SlotService>,
|
slot_service: Arc<SlotService>,
|
||||||
sales_person_service: Arc<SalesPersonService>,
|
sales_person_service: Arc<SalesPersonService>,
|
||||||
|
booking_service: Arc<BookingService>,
|
||||||
|
|
||||||
}
|
}
|
||||||
impl rest::RestStateDef for RestStateImpl {
|
impl rest::RestStateDef for RestStateImpl {
|
||||||
type PermissionService = PermissionService;
|
type PermissionService = PermissionService;
|
||||||
type SlotService = SlotService;
|
type SlotService = SlotService;
|
||||||
type SalesPersonService = SalesPersonService;
|
type SalesPersonService = SalesPersonService;
|
||||||
|
type BookingService = BookingService;
|
||||||
|
|
||||||
fn permission_service(&self) -> Arc<Self::PermissionService> {
|
fn permission_service(&self) -> Arc<Self::PermissionService> {
|
||||||
self.permission_service.clone()
|
self.permission_service.clone()
|
||||||
|
|
@ -39,12 +48,16 @@ impl rest::RestStateDef for RestStateImpl {
|
||||||
fn sales_person_service(&self) -> Arc<Self::SalesPersonService> {
|
fn sales_person_service(&self) -> Arc<Self::SalesPersonService> {
|
||||||
self.sales_person_service.clone()
|
self.sales_person_service.clone()
|
||||||
}
|
}
|
||||||
|
fn booking_service(&self) -> Arc<Self::BookingService> {
|
||||||
|
self.booking_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 {
|
||||||
let permission_dao = dao_impl::PermissionDaoImpl::new(pool.clone());
|
let permission_dao = dao_impl::PermissionDaoImpl::new(pool.clone());
|
||||||
let slot_dao = dao_impl::slot::SlotDaoImpl::new(pool.clone());
|
let slot_dao = dao_impl::slot::SlotDaoImpl::new(pool.clone());
|
||||||
let sales_person_dao = dao_impl::sales_person::SalesPersonDaoImpl::new(pool);
|
let sales_person_dao = dao_impl::sales_person::SalesPersonDaoImpl::new(pool.clone());
|
||||||
|
let booking_dao = dao_impl::booking::BookingDaoImpl::new(pool);
|
||||||
|
|
||||||
// Always authenticate with DEVUSER during development.
|
// Always authenticate with DEVUSER during development.
|
||||||
// This is used to test the permission service locally without a login service.
|
// This is used to test the permission service locally without a login service.
|
||||||
|
|
@ -69,13 +82,20 @@ impl RestStateImpl {
|
||||||
Arc::new(service_impl::sales_person::SalesPersonServiceImpl::new(
|
Arc::new(service_impl::sales_person::SalesPersonServiceImpl::new(
|
||||||
sales_person_dao.into(),
|
sales_person_dao.into(),
|
||||||
permission_service.clone(),
|
permission_service.clone(),
|
||||||
clock_service,
|
clock_service.clone(),
|
||||||
uuid_service,
|
uuid_service.clone(),
|
||||||
));
|
));
|
||||||
|
let booking_service = Arc::new(service_impl::booking::BookingServiceImpl::new(
|
||||||
|
booking_dao.into(),
|
||||||
|
permission_service.clone(),
|
||||||
|
clock_service,
|
||||||
|
uuid_service,
|
||||||
|
));
|
||||||
Self {
|
Self {
|
||||||
permission_service,
|
permission_service,
|
||||||
slot_service,
|
slot_service,
|
||||||
sales_person_service,
|
sales_person_service,
|
||||||
|
booking_service,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
135
rest/src/booking.rs
Normal file
135
rest/src/booking.rs
Normal file
|
|
@ -0,0 +1,135 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use axum::body::Body;
|
||||||
|
use axum::extract::Path;
|
||||||
|
use axum::routing::{delete, get, post};
|
||||||
|
use axum::{extract::State, response::Response};
|
||||||
|
use axum::{Json, Router};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use time::PrimitiveDateTime;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::{error_handler, RestStateDef};
|
||||||
|
use service::booking::{BookingService, Booking};
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
pub struct BookingTO {
|
||||||
|
#[serde(default)]
|
||||||
|
pub id: Uuid,
|
||||||
|
pub sales_person_id: Uuid,
|
||||||
|
pub slot_id: Uuid,
|
||||||
|
pub calendar_week: i32,
|
||||||
|
pub year: u32,
|
||||||
|
#[serde(default)]
|
||||||
|
pub created: Option<PrimitiveDateTime>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub deleted: Option<PrimitiveDateTime>,
|
||||||
|
#[serde(rename = "$version")]
|
||||||
|
#[serde(default)]
|
||||||
|
pub version: Uuid,
|
||||||
|
}
|
||||||
|
impl From<&Booking> for BookingTO {
|
||||||
|
fn from(booking: &Booking) -> Self {
|
||||||
|
Self {
|
||||||
|
id: booking.id,
|
||||||
|
sales_person_id: booking.sales_person_id,
|
||||||
|
slot_id: booking.slot_id,
|
||||||
|
calendar_week: booking.calendar_week,
|
||||||
|
year: booking.year,
|
||||||
|
created: booking.created,
|
||||||
|
deleted: booking.deleted,
|
||||||
|
version: booking.version,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<&BookingTO> for Booking {
|
||||||
|
fn from(booking: &BookingTO) -> Self {
|
||||||
|
Self {
|
||||||
|
id: booking.id,
|
||||||
|
sales_person_id: booking.sales_person_id,
|
||||||
|
slot_id: booking.slot_id,
|
||||||
|
calendar_week: booking.calendar_week,
|
||||||
|
year: booking.year,
|
||||||
|
created: booking.created,
|
||||||
|
deleted: booking.deleted,
|
||||||
|
version: booking.version,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate_route<RestState: RestStateDef>() -> Router<RestState> {
|
||||||
|
Router::new()
|
||||||
|
.route("/", get(get_all_bookings::<RestState>))
|
||||||
|
.route("/:id", get(get_booking::<RestState>))
|
||||||
|
.route("/", post(create_booking::<RestState>))
|
||||||
|
.route("/:id", delete(delete_booking::<RestState>))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_all_bookings<RestState: RestStateDef>(
|
||||||
|
rest_state: State<RestState>,
|
||||||
|
) -> Response {
|
||||||
|
error_handler(
|
||||||
|
(async {
|
||||||
|
let bookings: Arc<[BookingTO]> = rest_state
|
||||||
|
.booking_service()
|
||||||
|
.get_all(())
|
||||||
|
.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>(
|
||||||
|
rest_state: State<RestState>,
|
||||||
|
Path(booking_id): Path<Uuid>,
|
||||||
|
) -> Response {
|
||||||
|
error_handler(
|
||||||
|
(async {
|
||||||
|
let booking = rest_state.booking_service().get(booking_id, ()).await?;
|
||||||
|
Ok(Response::builder()
|
||||||
|
.status(200)
|
||||||
|
.body(Body::new(serde_json::to_string(&BookingTO::from(&booking)).unwrap()))
|
||||||
|
.unwrap())
|
||||||
|
})
|
||||||
|
.await,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn create_booking<RestState: RestStateDef>(
|
||||||
|
rest_state: State<RestState>,
|
||||||
|
Json(booking): Json<BookingTO>,
|
||||||
|
) -> Response {
|
||||||
|
error_handler(
|
||||||
|
(async {
|
||||||
|
let booking = rest_state.booking_service().create(&Booking::from(&booking), ()).await?;
|
||||||
|
Ok(Response::builder()
|
||||||
|
.status(200)
|
||||||
|
.body(Body::new(serde_json::to_string(&BookingTO::from(&booking)).unwrap()))
|
||||||
|
.unwrap())
|
||||||
|
})
|
||||||
|
.await,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn delete_booking<RestState: RestStateDef>(
|
||||||
|
rest_state: State<RestState>,
|
||||||
|
Path(booking_id): Path<Uuid>,
|
||||||
|
) -> Response {
|
||||||
|
error_handler(
|
||||||
|
(async {
|
||||||
|
rest_state.booking_service().delete(booking_id, ()).await?;
|
||||||
|
Ok(Response::builder()
|
||||||
|
.status(200)
|
||||||
|
.body(Body::empty())
|
||||||
|
.unwrap())
|
||||||
|
})
|
||||||
|
.await,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use std::{convert::Infallible, sync::Arc};
|
use std::{convert::Infallible, sync::Arc};
|
||||||
|
|
||||||
|
mod booking;
|
||||||
mod permission;
|
mod permission;
|
||||||
mod sales_person;
|
mod sales_person;
|
||||||
mod slot;
|
mod slot;
|
||||||
|
|
@ -139,10 +140,12 @@ pub trait RestStateDef: Clone + Send + Sync + 'static {
|
||||||
+ Send
|
+ Send
|
||||||
+ Sync
|
+ Sync
|
||||||
+ 'static;
|
+ 'static;
|
||||||
|
type BookingService: service::booking::BookingService<Context = Context> + Send + Sync + 'static;
|
||||||
|
|
||||||
fn permission_service(&self) -> Arc<Self::PermissionService>;
|
fn permission_service(&self) -> Arc<Self::PermissionService>;
|
||||||
fn slot_service(&self) -> Arc<Self::SlotService>;
|
fn slot_service(&self) -> Arc<Self::SlotService>;
|
||||||
fn sales_person_service(&self) -> Arc<Self::SalesPersonService>;
|
fn sales_person_service(&self) -> Arc<Self::SalesPersonService>;
|
||||||
|
fn booking_service(&self) -> Arc<Self::BookingService>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn start_server<RestState: RestStateDef>(rest_state: RestState) {
|
pub async fn start_server<RestState: RestStateDef>(rest_state: RestState) {
|
||||||
|
|
@ -150,6 +153,7 @@ pub async fn start_server<RestState: RestStateDef>(rest_state: RestState) {
|
||||||
.nest("/permission", permission::generate_route())
|
.nest("/permission", permission::generate_route())
|
||||||
.nest("/slot", slot::generate_route())
|
.nest("/slot", slot::generate_route())
|
||||||
.nest("/sales-person", sales_person::generate_route())
|
.nest("/sales-person", sales_person::generate_route())
|
||||||
|
.nest("/booking", booking::generate_route())
|
||||||
.with_state(rest_state);
|
.with_state(rest_state);
|
||||||
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
.await
|
.await
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use dao::booking;
|
|
||||||
use service::{
|
use service::{
|
||||||
booking::{Booking, BookingService},
|
booking::{Booking, BookingService},
|
||||||
ServiceError, ValidationFailureItem,
|
ServiceError, ValidationFailureItem,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue