From 354188d8b00afd8e6b6ffe972334e10ccd6afbf4 Mon Sep 17 00:00:00 2001 From: Aravinth Manivannan Date: Fri, 10 Jan 2025 21:54:40 +0530 Subject: [PATCH] feat: bootstrap ordering web adapter --- src/ordering/adapters/input/mod.rs | 1 + src/ordering/adapters/input/web/errors.rs | 114 ++++++++++++++++++++++ src/ordering/adapters/input/web/mod.rs | 26 +++++ src/ordering/adapters/input/web/routes.rs | 17 ++++ src/ordering/adapters/mod.rs | 2 +- src/ordering/adapters/types.rs | 4 +- 6 files changed, 161 insertions(+), 3 deletions(-) create mode 100644 src/ordering/adapters/input/web/errors.rs create mode 100644 src/ordering/adapters/input/web/mod.rs create mode 100644 src/ordering/adapters/input/web/routes.rs diff --git a/src/ordering/adapters/input/mod.rs b/src/ordering/adapters/input/mod.rs index 56f60de..810dc4e 100644 --- a/src/ordering/adapters/input/mod.rs +++ b/src/ordering/adapters/input/mod.rs @@ -1,3 +1,4 @@ // SPDX-FileCopyrightText: 2024 Aravinth Manivannan // // SPDX-License-Identifier: AGPL-3.0-or-later +pub mod web; diff --git a/src/ordering/adapters/input/web/errors.rs b/src/ordering/adapters/input/web/errors.rs new file mode 100644 index 0000000..a8b19fa --- /dev/null +++ b/src/ordering/adapters/input/web/errors.rs @@ -0,0 +1,114 @@ +// SPDX-FileCopyrightText: 2024 Aravinth Manivannan +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +use actix_web::http::StatusCode; +use actix_web::{HttpResponse, ResponseError}; +use derive_more::Display; +use serde::{Deserialize, Serialize}; + +use crate::ordering::application::services::errors::*; + +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] +struct ErrorResponse { + error: String, +} + +impl From for ErrorResponse { + fn from(value: WebError) -> Self { + ErrorResponse { + error: serde_json::to_string(&value).unwrap_or_else(|_| { + log::error!("Unable to serialize error"); + "Unable to serialize error".into() + }), + } + } +} + +#[derive(Debug, Display, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] +pub enum WebError { + InternalError, + BadRequest, + + LineItemIDNotFound, + OrderIDNotFound, + KotIDNotFound, + DuplicateStoreName, + StoreIDNotFound, + CategoryIDNotFound, + DuplicateCategoryName, + DuplicateProductName, + ProductIDNotFound, + DuplicateCustomizationName, + CustomizationIDNotFound, +} + +impl From for WebError { + fn from(v: OrderingError) -> Self { + match v { + OrderingError::InternalError => Self::InternalError, + + OrderingError::LineItemIDNotFound => Self::LineItemIDNotFound, + OrderingError::OrderIDNotFound => Self::OrderIDNotFound, + OrderingError::KotIDNotFound => Self::KotIDNotFound, + OrderingError::DuplicateStoreName => Self::DuplicateStoreName, + OrderingError::StoreIDNotFound => Self::StoreIDNotFound, + OrderingError::CategoryIDNotFound => Self::CategoryIDNotFound, + OrderingError::DuplicateCategoryName => Self::DuplicateCategoryName, + OrderingError::DuplicateProductName => Self::DuplicateProductName, + OrderingError::ProductIDNotFound => Self::ProductIDNotFound, + OrderingError::DuplicateCustomizationName => Self::DuplicateCustomizationName, + OrderingError::CustomizationIDNotFound => Self::CustomizationIDNotFound, + OrderingError::DuplicateKotID + | OrderingError::DuplicateKotID + | OrderingError::DuplicateOrderID + | OrderingError::DuplicateStoreID + | OrderingError::DuplicateCustomizationID + | OrderingError::DuplicateProductID + | OrderingError::DuplicateCategoryID + | OrderingError::DuplicateLineItemID => Self::InternalError, + } + } +} + +impl ResponseError for WebError { + fn status_code(&self) -> StatusCode { + match self { + Self::InternalError => StatusCode::INTERNAL_SERVER_ERROR, + Self::BadRequest => StatusCode::BAD_REQUEST, + Self::LineItemIDNotFound => StatusCode::NOT_FOUND, + Self::OrderIDNotFound => StatusCode::NOT_FOUND, + Self::KotIDNotFound => StatusCode::NOT_FOUND, + Self::DuplicateStoreName => StatusCode::BAD_REQUEST, + Self::StoreIDNotFound => StatusCode::NOT_FOUND, + Self::CategoryIDNotFound => StatusCode::NOT_FOUND, + Self::DuplicateCategoryName => StatusCode::BAD_REQUEST, + Self::DuplicateProductName => StatusCode::BAD_REQUEST, + Self::ProductIDNotFound => StatusCode::NOT_FOUND, + Self::DuplicateCustomizationName => StatusCode::BAD_REQUEST, + Self::CustomizationIDNotFound => StatusCode::NOT_FOUND, + } + } + + fn error_response(&self) -> actix_web::HttpResponse { + let e: ErrorResponse = self.clone().into(); + match self { + Self::InternalError => HttpResponse::InternalServerError().json(e), + Self::BadRequest => HttpResponse::BadRequest().json(e), + + Self::LineItemIDNotFound => HttpResponse::NotFound().json(e), + Self::OrderIDNotFound => HttpResponse::NotFound().json(e), + Self::KotIDNotFound => HttpResponse::NotFound().json(e), + Self::DuplicateStoreName => HttpResponse::BadRequest().json(e), + Self::StoreIDNotFound => HttpResponse::NotFound().json(e), + Self::CategoryIDNotFound => HttpResponse::NotFound().json(e), + Self::DuplicateCategoryName => HttpResponse::BadRequest().json(e), + Self::DuplicateProductName => HttpResponse::BadRequest().json(e), + Self::ProductIDNotFound => HttpResponse::NotFound().json(e), + Self::DuplicateCustomizationName => HttpResponse::BadRequest().json(e), + Self::CustomizationIDNotFound => HttpResponse::NotFound().json(e), + } + } +} + +pub type WebJsonRepsonse = Result; diff --git a/src/ordering/adapters/input/web/mod.rs b/src/ordering/adapters/input/web/mod.rs new file mode 100644 index 0000000..9bf19d3 --- /dev/null +++ b/src/ordering/adapters/input/web/mod.rs @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: 2024 Aravinth Manivannan +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +use std::sync::Arc; + +use actix_web::web; + +use crate::ordering::adapters::types; + +mod errors; +mod routes; + +pub use errors::WebJsonRepsonse; + +pub use routes::RoutesRepository; + +pub fn load_ctx() -> impl FnOnce(&mut web::ServiceConfig) { + let routes = types::WebOrderingRoutesRepository::new(Arc::new(RoutesRepository::default())); + + let f = move |cfg: &mut web::ServiceConfig| { + cfg.app_data(routes); + }; + + Box::new(f) +} diff --git a/src/ordering/adapters/input/web/routes.rs b/src/ordering/adapters/input/web/routes.rs new file mode 100644 index 0000000..2c2d1bd --- /dev/null +++ b/src/ordering/adapters/input/web/routes.rs @@ -0,0 +1,17 @@ +// SPDX-FileCopyrightText: 2024 Aravinth Manivannan +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +use url::Url; +use uuid::Uuid; + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct RoutesRepository {} + +impl Default for RoutesRepository { + fn default() -> Self { + Self {} + } +} + +impl RoutesRepository {} diff --git a/src/ordering/adapters/mod.rs b/src/ordering/adapters/mod.rs index c6bf8cf..d301400 100644 --- a/src/ordering/adapters/mod.rs +++ b/src/ordering/adapters/mod.rs @@ -68,7 +68,7 @@ pub fn load_adapters(pool: PgPool, settings: Settings) -> impl FnOnce(&mut web:: )); let f = move |cfg: &mut web::ServiceConfig| { - //cfg.configure(input::web::load_ctx()); + cfg.configure(input::web::load_ctx()); cfg.app_data(Data::new(category_cqrs_query.clone())); cfg.app_data(Data::new(product_cqrs_query.clone())); cfg.app_data(Data::new(customization_cqrs_query.clone())); diff --git a/src/ordering/adapters/types.rs b/src/ordering/adapters/types.rs index 5b1c66b..b02e145 100644 --- a/src/ordering/adapters/types.rs +++ b/src/ordering/adapters/types.rs @@ -15,7 +15,7 @@ use postgres_es::PostgresCqrs; use crate::ordering::{ adapters::{ - // input::web::RoutesRepository, + input::web::RoutesRepository, output::db::{ category_view::CategoryView, customization_view::CustomizationView, kot_view::KotView, line_item_view::LineItemView, order_view::OrderView, product_view::ProductView, @@ -30,7 +30,7 @@ use crate::ordering::{ }, }; -//pub type WebOrderingRoutesRepository = Data>; +pub type WebOrderingRoutesRepository = Data>; pub type OrderingOrderCqrsExec = Arc>; pub type OrderingOrderCqrsView = Arc>;