diff --git a/src/inventory/adapters/input/mod.rs b/src/inventory/adapters/input/mod.rs index 56f60de..810dc4e 100644 --- a/src/inventory/adapters/input/mod.rs +++ b/src/inventory/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/inventory/adapters/input/web/category.rs b/src/inventory/adapters/input/web/category.rs new file mode 100644 index 0000000..5aee4fd --- /dev/null +++ b/src/inventory/adapters/input/web/category.rs @@ -0,0 +1,16 @@ +// SPDX-FileCopyrightText: 2024 Aravinth Manivannan +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +use actix_identity::Identity; +use actix_web::{get, http::header::ContentType, post, web, HttpRequest, HttpResponse, Responder}; +use derive_builder::Builder; +use serde::{Deserialize, Serialize}; +use url::Url; +use uuid::Uuid; + +use super::errors::*; +use super::types; +//use crate::utils::uuid::WebGetUUIDInterfaceObj; + +pub fn services(cfg: &mut web::ServiceConfig) {} diff --git a/src/inventory/adapters/input/web/errors.rs b/src/inventory/adapters/input/web/errors.rs new file mode 100644 index 0000000..7a5371f --- /dev/null +++ b/src/inventory/adapters/input/web/errors.rs @@ -0,0 +1,110 @@ +// 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::inventory::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, + + DuplicateCategoryName, + DuplicateStoreName, + DuplicateProductName, + DuplicateCustomizationName, + DuplicateCustomizationID, + DuplicateStoreID, + DuplicateCategoryID, + DuplicateProductID, + ProductIDNotFound, + CategoryIDNotFound, + CustomizationIDNotFound, + StoreIDNotFound, +} + +impl From for WebError { + fn from(v: InventoryError) -> Self { + match v { + InventoryError::InternalError => Self::InternalError, + InventoryError::DuplicateCategoryName => Self::BadRequest, + InventoryError::DuplicateStoreName => Self::BadRequest, + InventoryError::DuplicateProductName => Self::BadRequest, + InventoryError::DuplicateCustomizationName => Self::BadRequest, + InventoryError::DuplicateCustomizationID => Self::InternalError, + InventoryError::DuplicateStoreID => Self::InternalError, + InventoryError::DuplicateCategoryID => Self::InternalError, + InventoryError::DuplicateProductID => Self::InternalError, + InventoryError::ProductIDNotFound => Self::BadRequest, + InventoryError::CategoryIDNotFound => Self::BadRequest, + InventoryError::CustomizationIDNotFound => Self::BadRequest, + InventoryError::StoreIDNotFound => Self::BadRequest, + } + } +} + +impl ResponseError for WebError { + fn status_code(&self) -> StatusCode { + match self { + Self::InternalError => StatusCode::INTERNAL_SERVER_ERROR, + Self::BadRequest => StatusCode::BAD_REQUEST, + + Self::DuplicateCategoryName => StatusCode::BAD_REQUEST, + Self::DuplicateStoreName => StatusCode::BAD_REQUEST, + Self::DuplicateProductName => StatusCode::BAD_REQUEST, + Self::DuplicateCustomizationName => StatusCode::BAD_REQUEST, + Self::DuplicateCustomizationID => StatusCode::INTERNAL_SERVER_ERROR, + Self::DuplicateStoreID => StatusCode::INTERNAL_SERVER_ERROR, + Self::DuplicateCategoryID => StatusCode::INTERNAL_SERVER_ERROR, + Self::DuplicateProductID => StatusCode::INTERNAL_SERVER_ERROR, + Self::ProductIDNotFound => StatusCode::BAD_REQUEST, + Self::CategoryIDNotFound => StatusCode::BAD_REQUEST, + Self::CustomizationIDNotFound => StatusCode::BAD_REQUEST, + Self::StoreIDNotFound => StatusCode::BAD_REQUEST, + } + } + + 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::DuplicateCategoryName => HttpResponse::BadRequest().json(e), + Self::DuplicateStoreName => HttpResponse::BadRequest().json(e), + Self::DuplicateProductName => HttpResponse::BadRequest().json(e), + Self::DuplicateCustomizationName => HttpResponse::BadRequest().json(e), + Self::DuplicateCustomizationID => HttpResponse::InternalServerError().json(e), + Self::DuplicateStoreID => HttpResponse::InternalServerError().json(e), + Self::DuplicateCategoryID => HttpResponse::InternalServerError().json(e), + Self::DuplicateProductID => HttpResponse::InternalServerError().json(e), + Self::ProductIDNotFound => HttpResponse::BadRequest().json(e), + Self::CategoryIDNotFound => HttpResponse::BadRequest().json(e), + Self::CustomizationIDNotFound => HttpResponse::BadRequest().json(e), + Self::StoreIDNotFound => HttpResponse::BadRequest().json(e), + } + } +} + +pub type WebJsonRepsonse = Result; diff --git a/src/inventory/adapters/input/web/mod.rs b/src/inventory/adapters/input/web/mod.rs new file mode 100644 index 0000000..88a4b6e --- /dev/null +++ b/src/inventory/adapters/input/web/mod.rs @@ -0,0 +1,29 @@ +// SPDX-FileCopyrightText: 2024 Aravinth Manivannan +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +use std::sync::Arc; + +use actix_web::web; + +use crate::inventory::adapters::types; + +//mod employee; +mod category; +mod errors; +mod routes; + +pub use errors::WebJsonRepsonse; + +pub use routes::RoutesRepository; + +pub fn load_ctx() -> impl FnOnce(&mut web::ServiceConfig) { + let routes = types::WebInventoryRoutesRepository::new(Arc::new(RoutesRepository::default())); + + let f = move |cfg: &mut web::ServiceConfig| { + cfg.app_data(routes); + cfg.configure(category::services); + }; + + Box::new(f) +} diff --git a/src/inventory/adapters/input/web/routes.rs b/src/inventory/adapters/input/web/routes.rs new file mode 100644 index 0000000..4bbce66 --- /dev/null +++ b/src/inventory/adapters/input/web/routes.rs @@ -0,0 +1,34 @@ +// 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 { + add_category: String, + add_product: String, + add_customization: String, + update_product: String, + update_customization: String, + update_category: String, +} + +impl Default for RoutesRepository { + fn default() -> Self { + Self { + add_category: "/inventory/category/add".into(), + update_category: "/inventory/{category_uuid}/update".into(), + + add_product: "/inventory/{category_uuid}/product/add".into(), + update_product: "/inventory/{category_uuid}/update".into(), + + add_customization: "/inventory/{category_uuid}/{product_uuid}/customization/add".into(), + update_customization: + "/inventory/{category_uuid}/{product_uuid}/{customization_uuid}/update".into(), + } + } +} + +impl RoutesRepository {} diff --git a/src/inventory/adapters/mod.rs b/src/inventory/adapters/mod.rs index 622ecf3..01bdf7b 100644 --- a/src/inventory/adapters/mod.rs +++ b/src/inventory/adapters/mod.rs @@ -63,7 +63,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/inventory/adapters/types.rs b/src/inventory/adapters/types.rs index 1463fcf..a2879c4 100644 --- a/src/inventory/adapters/types.rs +++ b/src/inventory/adapters/types.rs @@ -15,7 +15,7 @@ use postgres_es::PostgresCqrs; use crate::inventory::{ adapters::{ - // input::web::RoutesRepository, + input::web::RoutesRepository, output::db::postgres::{ category_view::CategoryView, customization_view::CustomizationView, product_view::ProductView, store_view::StoreView, InventoryDBPostgresAdapter, @@ -28,7 +28,7 @@ use crate::inventory::{ }, }; -//pub type WebInventoryRoutesRepository = Data>; +pub type WebInventoryRoutesRepository = Data>; pub type WebInventoryCqrsExec = Data>;