feat: more clerk endpoints
This commit is contained in:
parent
fc2e993d31
commit
b8e64e2d2c
8 changed files with 267 additions and 117 deletions
|
@ -63,6 +63,6 @@ async fn main() -> Result<(), ApplicationError> {
|
||||||
async fn shutdown() {
|
async fn shutdown() {
|
||||||
match signal::ctrl_c().await {
|
match signal::ctrl_c().await {
|
||||||
Ok(()) => {},
|
Ok(()) => {},
|
||||||
Err(err) => {},
|
Err(_) => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -72,6 +72,11 @@ pub struct BookingQuery {
|
||||||
pub months: Option<i32>,
|
pub months: Option<i32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct ClerkMonthsQuery {
|
||||||
|
pub months: i32,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Clone)]
|
#[derive(Deserialize, Clone)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct BookingBody {
|
pub struct BookingBody {
|
||||||
|
|
|
@ -1,31 +1,7 @@
|
||||||
use axum::{Router, routing::BoxRoute, extract::{Extension, Path, Query}, response::IntoResponse, Json, handler::{get, put}};
|
use axum::{Json, extract::{Path, Extension, Query}, response::IntoResponse, Router, routing::BoxRoute, handler::{get, put}};
|
||||||
use hyper::StatusCode;
|
use hyper::StatusCode;
|
||||||
|
|
||||||
use crate::{Service, error::ServiceError, model::{BookingQuery, BookingBody, Booking}};
|
use crate::{Service, error::ServiceError, model::{BookingBody, Booking, BookingQuery}};
|
||||||
|
|
||||||
async fn rooms(
|
|
||||||
Extension(service): Extension<Service>,
|
|
||||||
) -> Result<impl IntoResponse, ServiceError> {
|
|
||||||
let rooms = service.get_rooms().await?;
|
|
||||||
Ok(Json(rooms))
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn room(
|
|
||||||
Path(id): Path<i32>,
|
|
||||||
Extension(service): Extension<Service>,
|
|
||||||
) -> Result<impl IntoResponse, ServiceError> {
|
|
||||||
let room = service.get_room(id).await?
|
|
||||||
.ok_or_else(|| ServiceError::ErrorResponse(StatusCode::NOT_FOUND, Some("room not found".to_string())))?;
|
|
||||||
Ok(Json(room))
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn cleaning_plans(
|
|
||||||
Path(id): Path<i32>,
|
|
||||||
Extension(service): Extension<Service>,
|
|
||||||
) -> Result<impl IntoResponse, ServiceError> {
|
|
||||||
let cleaning_plans = service.get_room_cleaning_plans(id).await?;
|
|
||||||
Ok(Json(cleaning_plans))
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn bookings(
|
async fn bookings(
|
||||||
Query(query): Query<BookingQuery>,
|
Query(query): Query<BookingQuery>,
|
||||||
|
@ -128,24 +104,13 @@ async fn update_booking(
|
||||||
Ok(StatusCode::NO_CONTENT)
|
Ok(StatusCode::NO_CONTENT)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn clerks(
|
|
||||||
Extension(service): Extension<Service>,
|
|
||||||
) -> Result<impl IntoResponse, ServiceError> {
|
|
||||||
let clerks = service.get_clerks().await?;
|
|
||||||
Ok(Json(clerks))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn routes() -> Router<BoxRoute> {
|
pub fn routes() -> Router<BoxRoute> {
|
||||||
Router::new()
|
Router::new()
|
||||||
.route("/rooms", get(rooms))
|
.route("/", get(bookings).post(add_booking))
|
||||||
.route("/rooms/:id", get(room))
|
.route("/:id", get(booking).delete(delete_booking).put(update_booking))
|
||||||
.route("/rooms/:id/cleaningPlans", get(cleaning_plans))
|
.route("/:id/rooms", get(booking_rooms))
|
||||||
.route("/bookings", get(bookings).post(add_booking))
|
.route("/:id/rooms/:roomid", put(add_booking_room).delete(delete_booking_room))
|
||||||
.route("/bookings/:id", get(booking).delete(delete_booking).put(update_booking))
|
.route("/:id/guests", get(booking_guests))
|
||||||
.route("/bookings/:id/rooms", get(booking_rooms))
|
.route("/:id/guests/:personid", put(add_booking_guest).delete(delete_booking_guest))
|
||||||
.route("/bookings/:id/rooms/:roomid", put(add_booking_room).delete(delete_booking_room))
|
|
||||||
.route("/bookings/:id/guests", get(booking_guests))
|
|
||||||
.route("/bookings/:id/guests/:personid", put(add_booking_guest).delete(delete_booking_guest))
|
|
||||||
.route("/clerks", get(clerks))
|
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
37
src/routes/clerks.rs
Normal file
37
src/routes/clerks.rs
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
use axum::{extract::{Extension, Query, Path}, response::IntoResponse, Json, routing::BoxRoute, Router, handler::get};
|
||||||
|
use hyper::StatusCode;
|
||||||
|
|
||||||
|
use crate::{error::ServiceError, Service, model::ClerkMonthsQuery};
|
||||||
|
|
||||||
|
async fn clerks(
|
||||||
|
Extension(service): Extension<Service>,
|
||||||
|
) -> Result<impl IntoResponse, ServiceError> {
|
||||||
|
let clerks = service.get_clerks().await?;
|
||||||
|
Ok(Json(clerks))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn clerk(
|
||||||
|
Path(id): Path<i32>,
|
||||||
|
Extension(service): Extension<Service>,
|
||||||
|
) -> Result<impl IntoResponse, ServiceError> {
|
||||||
|
let clerk = service.get_clerk(id).await?
|
||||||
|
.ok_or_else(|| ServiceError::ErrorResponse(StatusCode::NOT_FOUND, Some("clerk not found".to_string())))?;
|
||||||
|
Ok(Json(clerk))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn most_valuable_clerk(
|
||||||
|
Query(query): Query<ClerkMonthsQuery>,
|
||||||
|
Extension(service): Extension<Service>,
|
||||||
|
) -> Result<impl IntoResponse, ServiceError> {
|
||||||
|
let clerk = service.get_most_valuable_clerk(query.months).await?
|
||||||
|
.ok_or_else(|| ServiceError::ErrorResponse(StatusCode::NOT_FOUND, Some("clerk not found".to_string())))?;
|
||||||
|
Ok(Json(clerk))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn routes() -> Router<BoxRoute> {
|
||||||
|
Router::new()
|
||||||
|
.route("/", get(clerks))
|
||||||
|
.route("/:id", get(clerk))
|
||||||
|
.route("/mostValuable", get(most_valuable_clerk))
|
||||||
|
.boxed()
|
||||||
|
}
|
13
src/routes/mod.rs
Normal file
13
src/routes/mod.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
use axum::{Router, routing::BoxRoute};
|
||||||
|
|
||||||
|
mod rooms;
|
||||||
|
mod clerks;
|
||||||
|
mod bookings;
|
||||||
|
|
||||||
|
pub fn routes() -> Router<BoxRoute> {
|
||||||
|
Router::new()
|
||||||
|
.nest("/rooms", rooms::routes())
|
||||||
|
.nest("/bookings", bookings::routes())
|
||||||
|
.nest("/clerks", clerks::routes())
|
||||||
|
.boxed()
|
||||||
|
}
|
36
src/routes/rooms.rs
Normal file
36
src/routes/rooms.rs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
use axum::{extract::{Extension, Path}, response::IntoResponse, Json, Router, routing::BoxRoute, handler::get};
|
||||||
|
use hyper::StatusCode;
|
||||||
|
|
||||||
|
use crate::{error::ServiceError, Service};
|
||||||
|
|
||||||
|
async fn rooms(
|
||||||
|
Extension(service): Extension<Service>,
|
||||||
|
) -> Result<impl IntoResponse, ServiceError> {
|
||||||
|
let rooms = service.get_rooms().await?;
|
||||||
|
Ok(Json(rooms))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn room(
|
||||||
|
Path(id): Path<i32>,
|
||||||
|
Extension(service): Extension<Service>,
|
||||||
|
) -> Result<impl IntoResponse, ServiceError> {
|
||||||
|
let room = service.get_room(id).await?
|
||||||
|
.ok_or_else(|| ServiceError::ErrorResponse(StatusCode::NOT_FOUND, Some("room not found".to_string())))?;
|
||||||
|
Ok(Json(room))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn cleaning_plans(
|
||||||
|
Path(id): Path<i32>,
|
||||||
|
Extension(service): Extension<Service>,
|
||||||
|
) -> Result<impl IntoResponse, ServiceError> {
|
||||||
|
let cleaning_plans = service.get_room_cleaning_plans(id).await?;
|
||||||
|
Ok(Json(cleaning_plans))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn routes() -> Router<BoxRoute> {
|
||||||
|
Router::new()
|
||||||
|
.route("/", get(rooms))
|
||||||
|
.route("/:id", get(room))
|
||||||
|
.route("/:id/cleaningPlans", get(cleaning_plans))
|
||||||
|
.boxed()
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
use hyper::StatusCode;
|
use hyper::StatusCode;
|
||||||
|
|
||||||
use crate::{ServiceInner, model::{Room, Booking, Person, Address, BookingBody}, error::ServiceError};
|
use crate::{ServiceInner, model::{Booking, BookingBody, Room, Person, Address}, error::ServiceError};
|
||||||
|
|
||||||
impl ServiceInner {
|
impl ServiceInner {
|
||||||
|
|
||||||
|
@ -99,6 +99,78 @@ impl ServiceInner {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn add_booking(&self, booking: BookingBody) -> Result<i32, ServiceError> {
|
||||||
|
let session = self.pool.get_session().await?;
|
||||||
|
let stmt = session.prepare("
|
||||||
|
INSERT INTO BOOKING
|
||||||
|
(
|
||||||
|
bookingId,
|
||||||
|
arrivalDate,
|
||||||
|
departureDate,
|
||||||
|
cost,
|
||||||
|
pensionType,
|
||||||
|
lateCheckout,
|
||||||
|
clientId
|
||||||
|
)
|
||||||
|
VALUES
|
||||||
|
(
|
||||||
|
BOOKING_SEQ.nextval,
|
||||||
|
TO_DATE(:ARRDATE, 'YYYY-MM-DD'),
|
||||||
|
TO_DATE(:DEPDATE, 'YYYY-MM-DD'),
|
||||||
|
:COST,
|
||||||
|
:PENSION,
|
||||||
|
0,
|
||||||
|
:CLIENT
|
||||||
|
)
|
||||||
|
").await?;
|
||||||
|
stmt.execute((
|
||||||
|
(":ARRDATE", booking.arrival_date),
|
||||||
|
(":DEPDATE", booking.depature_date),
|
||||||
|
(":COST", booking.cost),
|
||||||
|
(":PENSION", booking.pension_type),
|
||||||
|
(":CLIENT", booking.client_id)
|
||||||
|
)).await?;
|
||||||
|
let stmt = session.prepare("SELECT BOOKING_SEQ.currval FROM dual").await?;
|
||||||
|
let row = stmt.query_single("").await?
|
||||||
|
.ok_or_else(|| ServiceError::ErrorResponse(StatusCode::INTERNAL_SERVER_ERROR, None))?;
|
||||||
|
let id: i32 = row.get(0)?;
|
||||||
|
session.commit().await?;
|
||||||
|
Ok(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn delete_booking(&self, booking: i32) -> Result<(), ServiceError> {
|
||||||
|
let session = self.pool.get_session().await?;
|
||||||
|
let stmt = session.prepare("
|
||||||
|
DELETE FROM Booking WHERE bookingId = :BOOKING
|
||||||
|
").await?;
|
||||||
|
stmt.execute(booking).await?;
|
||||||
|
session.commit().await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn update_booking(&self, id: i32, booking: BookingBody) -> Result<(), ServiceError> {
|
||||||
|
let session = self.pool.get_session().await?;
|
||||||
|
let stmt = session.prepare("
|
||||||
|
UPDATE BOOKING SET
|
||||||
|
arrivalDate = TO_DATE(:ARRDATE, 'YYYY-MM-DD'),
|
||||||
|
departureDate = TO_DATE(:DEPDATE, 'YYYY-MM-DD'),
|
||||||
|
cost = :COST,
|
||||||
|
pensionType = :PENSION,
|
||||||
|
clientId = :CLIENT
|
||||||
|
WHERE bookingId = :ID
|
||||||
|
").await?;
|
||||||
|
stmt.execute((
|
||||||
|
(":ID", id),
|
||||||
|
(":ARRDATE", booking.arrival_date),
|
||||||
|
(":DEPDATE", booking.depature_date),
|
||||||
|
(":COST", booking.cost),
|
||||||
|
(":PENSION", booking.pension_type),
|
||||||
|
(":CLIENT", booking.client_id)
|
||||||
|
)).await?;
|
||||||
|
session.commit().await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn get_rooms_for_booking(&self, booking: i32) -> Result<Vec<Room>, ServiceError> {
|
pub async fn get_rooms_for_booking(&self, booking: i32) -> Result<Vec<Room>, ServiceError> {
|
||||||
let session = self.pool.get_session().await?;
|
let session = self.pool.get_session().await?;
|
||||||
let stmt = session.prepare("
|
let stmt = session.prepare("
|
||||||
|
@ -218,76 +290,4 @@ impl ServiceInner {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn add_booking(&self, booking: BookingBody) -> Result<i32, ServiceError> {
|
|
||||||
let session = self.pool.get_session().await?;
|
|
||||||
let stmt = session.prepare("
|
|
||||||
INSERT INTO BOOKING
|
|
||||||
(
|
|
||||||
bookingId,
|
|
||||||
arrivalDate,
|
|
||||||
departureDate,
|
|
||||||
cost,
|
|
||||||
pensionType,
|
|
||||||
lateCheckout,
|
|
||||||
clientId
|
|
||||||
)
|
|
||||||
VALUES
|
|
||||||
(
|
|
||||||
BOOKING_SEQ.nextval,
|
|
||||||
TO_DATE(:ARRDATE, 'YYYY-MM-DD'),
|
|
||||||
TO_DATE(:DEPDATE, 'YYYY-MM-DD'),
|
|
||||||
:COST,
|
|
||||||
:PENSION,
|
|
||||||
0,
|
|
||||||
:CLIENT
|
|
||||||
)
|
|
||||||
").await?;
|
|
||||||
stmt.execute((
|
|
||||||
(":ARRDATE", booking.arrival_date),
|
|
||||||
(":DEPDATE", booking.depature_date),
|
|
||||||
(":COST", booking.cost),
|
|
||||||
(":PENSION", booking.pension_type),
|
|
||||||
(":CLIENT", booking.client_id)
|
|
||||||
)).await?;
|
|
||||||
let stmt = session.prepare("SELECT BOOKING_SEQ.currval FROM dual").await?;
|
|
||||||
let row = stmt.query_single("").await?
|
|
||||||
.ok_or_else(|| ServiceError::ErrorResponse(StatusCode::INTERNAL_SERVER_ERROR, None))?;
|
|
||||||
let id: i32 = row.get(0)?;
|
|
||||||
session.commit().await?;
|
|
||||||
Ok(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn delete_booking(&self, booking: i32) -> Result<(), ServiceError> {
|
|
||||||
let session = self.pool.get_session().await?;
|
|
||||||
let stmt = session.prepare("
|
|
||||||
DELETE FROM Booking WHERE bookingId = :BOOKING
|
|
||||||
").await?;
|
|
||||||
stmt.execute(booking).await?;
|
|
||||||
session.commit().await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn update_booking(&self, id: i32, booking: BookingBody) -> Result<(), ServiceError> {
|
|
||||||
let session = self.pool.get_session().await?;
|
|
||||||
let stmt = session.prepare("
|
|
||||||
UPDATE BOOKING SET
|
|
||||||
arrivalDate = TO_DATE(:ARRDATE, 'YYYY-MM-DD'),
|
|
||||||
departureDate = TO_DATE(:DEPDATE, 'YYYY-MM-DD'),
|
|
||||||
cost = :COST,
|
|
||||||
pensionType = :PENSION,
|
|
||||||
clientId = :CLIENT
|
|
||||||
WHERE bookingId = :ID
|
|
||||||
").await?;
|
|
||||||
stmt.execute((
|
|
||||||
(":ID", id),
|
|
||||||
(":ARRDATE", booking.arrival_date),
|
|
||||||
(":DEPDATE", booking.depature_date),
|
|
||||||
(":COST", booking.cost),
|
|
||||||
(":PENSION", booking.pension_type),
|
|
||||||
(":CLIENT", booking.client_id)
|
|
||||||
)).await?;
|
|
||||||
session.commit().await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -50,4 +50,98 @@ impl ServiceInner {
|
||||||
Ok(clerks)
|
Ok(clerks)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_clerk(&self, id: i32) -> Result<Option<Clerk>, ServiceError> {
|
||||||
|
let session = self.pool.get_session().await?;
|
||||||
|
let stmt = session.prepare("
|
||||||
|
SELECT
|
||||||
|
c.staff,
|
||||||
|
c.salary,
|
||||||
|
p.personId,
|
||||||
|
p.name,
|
||||||
|
p.lastName,
|
||||||
|
p.age,
|
||||||
|
ad.street,
|
||||||
|
ad.houseNumber,
|
||||||
|
ad.postalCode,
|
||||||
|
ad.city,
|
||||||
|
ad.country
|
||||||
|
FROM Clerk c
|
||||||
|
INNER JOIN Person p ON p.personId = c.personId
|
||||||
|
INNER JOIN Address ad ON p.addressId = ad.addressId
|
||||||
|
WHERE c.staff = :ID
|
||||||
|
").await?;
|
||||||
|
|
||||||
|
let row = stmt.query_single(id).await?;
|
||||||
|
|
||||||
|
Ok(match row {
|
||||||
|
Some(row) => {
|
||||||
|
Some(Clerk {
|
||||||
|
staff_number: row.get(0)?,
|
||||||
|
salary: row.get(1)?,
|
||||||
|
person_data: Person {
|
||||||
|
id: row.get(2)?,
|
||||||
|
first_name: row.get(3)?,
|
||||||
|
last_name: row.get(4)?,
|
||||||
|
age: row.get(5)?,
|
||||||
|
address: Address {
|
||||||
|
street: row.get(6)?,
|
||||||
|
house_number: row.get(7)?,
|
||||||
|
postal_code: row.get(8)?,
|
||||||
|
city: row.get(9)?,
|
||||||
|
country: row.get(10)?,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
None => None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_most_valuable_clerk(&self, months: i32) -> Result<Option<Clerk>, ServiceError> {
|
||||||
|
let session = self.pool.get_session().await?;
|
||||||
|
let stmt = session.prepare("
|
||||||
|
SELECT
|
||||||
|
c.staff,
|
||||||
|
c.salary,
|
||||||
|
p.personId,
|
||||||
|
p.name,
|
||||||
|
p.lastName,
|
||||||
|
p.age,
|
||||||
|
ad.street,
|
||||||
|
ad.houseNumber,
|
||||||
|
ad.postalCode,
|
||||||
|
ad.city,
|
||||||
|
ad.country
|
||||||
|
FROM Clerk c
|
||||||
|
INNER JOIN Person p ON p.personId = c.personId
|
||||||
|
INNER JOIN Address ad ON p.addressId = ad.addressId
|
||||||
|
WHERE p.personId = mostValuableClerk(:MONTHS)
|
||||||
|
").await?;
|
||||||
|
|
||||||
|
let row = stmt.query_single(months).await?;
|
||||||
|
|
||||||
|
Ok(match row {
|
||||||
|
Some(row) => {
|
||||||
|
Some(Clerk {
|
||||||
|
staff_number: row.get(0)?,
|
||||||
|
salary: row.get(1)?,
|
||||||
|
person_data: Person {
|
||||||
|
id: row.get(2)?,
|
||||||
|
first_name: row.get(3)?,
|
||||||
|
last_name: row.get(4)?,
|
||||||
|
age: row.get(5)?,
|
||||||
|
address: Address {
|
||||||
|
street: row.get(6)?,
|
||||||
|
house_number: row.get(7)?,
|
||||||
|
postal_code: row.get(8)?,
|
||||||
|
city: row.get(9)?,
|
||||||
|
country: row.get(10)?,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
None => None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in a new issue