From 13414d34fc204a98300aaca4187a22232d9bf83d Mon Sep 17 00:00:00 2001 From: Aravinth Manivannan Date: Tue, 23 Jul 2024 20:33:52 +0530 Subject: [PATCH] feat: db port to check duplicate Kot ID --- src/ordering/adapters/output/db/errors.rs | 4 +- .../adapters/output/db/kot_id_exists.rs | 83 +++++++++++++++++++ .../application/port/output/db/errors.rs | 2 + .../port/output/db/kot_id_exists.rs | 53 ++++++++++++ .../application/port/output/db/mod.rs | 1 + src/ordering/application/services/errors.rs | 7 ++ 6 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 src/ordering/adapters/output/db/kot_id_exists.rs create mode 100644 src/ordering/application/port/output/db/kot_id_exists.rs diff --git a/src/ordering/adapters/output/db/errors.rs b/src/ordering/adapters/output/db/errors.rs index 0c45084..f03a439 100644 --- a/src/ordering/adapters/output/db/errors.rs +++ b/src/ordering/adapters/output/db/errors.rs @@ -22,8 +22,10 @@ impl From for OrderingDBError { if msg.contains("cqrs_ordering_store_query_line_item_id_key") { return Self::DuplicateLineItemID; - } else if msg.contains("cqrs_ordering_store_query_order_id_key") { + } else if msg.contains("cqrs_ordering_order_order_id_query") { return Self::DuplicateOrderID; + } else if msg.contains("cqrs_ordering_kot_kot_id_query") { + return Self::DuplicateKotID; } else { println!("{msg}"); } diff --git a/src/ordering/adapters/output/db/kot_id_exists.rs b/src/ordering/adapters/output/db/kot_id_exists.rs new file mode 100644 index 0000000..5d3486f --- /dev/null +++ b/src/ordering/adapters/output/db/kot_id_exists.rs @@ -0,0 +1,83 @@ +// SPDX-FileCopyrightText: 2024 Aravinth Manivannan +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +use uuid::Uuid; + +use super::OrderingDBPostgresAdapter; +use crate::ordering::application::port::output::db::{errors::*, kot_id_exists::*}; + +#[async_trait::async_trait] +impl KotIDExistsDBPort for OrderingDBPostgresAdapter { + async fn kot_id_exists(&self, kot_id: &Uuid) -> OrderingDBResult { + let res = sqlx::query!( + "SELECT EXISTS ( + SELECT 1 + FROM cqrs_ordering_kot_query + WHERE + kot_id = $1 + );", + kot_id + ) + .fetch_one(&self.pool) + .await?; + if let Some(x) = res.exists { + Ok(x) + } else { + Ok(false) + } + } +} + +#[cfg(test)] +pub mod tests { + + use super::*; + // use crate::ordering::domain::add_product_command::tests::get_customizations; + use crate::ordering::domain::kot_aggregate::*; + + async fn create_dummy_kot(kot: &Kot, db: &OrderingDBPostgresAdapter) { + sqlx::query!( + "INSERT INTO cqrs_ordering_kot_query ( + version, + order_id, + kot_id, + created_time, + deleted + ) VALUES ( + $1, $2, $3, $4, $5 + );", + 1, + kot.order_id(), + kot.kot_id(), + kot.created_time(), + kot.deleted().clone(), + ) + .execute(&db.pool) + .await + .unwrap(); + } + + #[actix_rt::test] + async fn test_postgres_product_exists() { + let settings = crate::settings::tests::get_settings().await; + settings.create_db().await; + let db = super::OrderingDBPostgresAdapter::new( + sqlx::postgres::PgPool::connect(&settings.database.url) + .await + .unwrap(), + ); + + let kot = Kot::default(); + + // state doesn't exist + assert!(!db.kot_id_exists(kot.kot_id()).await.unwrap()); + + create_dummy_kot(&kot, &db).await; + + // state exists + assert!(db.kot_id_exists(kot.kot_id()).await.unwrap()); + + settings.drop_db().await; + } +} diff --git a/src/ordering/application/port/output/db/errors.rs b/src/ordering/application/port/output/db/errors.rs index 43f5eb1..3588c7c 100644 --- a/src/ordering/application/port/output/db/errors.rs +++ b/src/ordering/application/port/output/db/errors.rs @@ -14,4 +14,6 @@ pub enum OrderingDBError { InternalError, DuplicateOrderID, OrderIDNotFound, + DuplicateKotID, + KotIDNotFound, } diff --git a/src/ordering/application/port/output/db/kot_id_exists.rs b/src/ordering/application/port/output/db/kot_id_exists.rs new file mode 100644 index 0000000..628dabb --- /dev/null +++ b/src/ordering/application/port/output/db/kot_id_exists.rs @@ -0,0 +1,53 @@ +// SPDX-FileCopyrightText: 2024 Aravinth Manivannan +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +use mockall::predicate::*; +use mockall::*; +use uuid::Uuid; + +use super::errors::*; +#[cfg(test)] +#[allow(unused_imports)] +pub use tests::*; + +#[automock] +#[async_trait::async_trait] +pub trait KotIDExistsDBPort: Send + Sync { + async fn kot_id_exists(&self, kot_id: &Uuid) -> OrderingDBResult; +} + +pub type KotIDExistsDBPortObj = std::sync::Arc; + +#[cfg(test)] +pub mod tests { + use super::*; + + use std::sync::Arc; + + pub fn mock_kot_id_exists_db_port_false(times: Option) -> KotIDExistsDBPortObj { + let mut m = MockKotIDExistsDBPort::new(); + if let Some(times) = times { + m.expect_kot_id_exists() + .times(times) + .returning(|_| Ok(false)); + } else { + m.expect_kot_id_exists().returning(|_| Ok(false)); + } + + Arc::new(m) + } + + pub fn mock_kot_id_exists_db_port_true(times: Option) -> KotIDExistsDBPortObj { + let mut m = MockKotIDExistsDBPort::new(); + if let Some(times) = times { + m.expect_kot_id_exists() + .times(times) + .returning(|_| Ok(true)); + } else { + m.expect_kot_id_exists().returning(|_| Ok(true)); + } + + Arc::new(m) + } +} diff --git a/src/ordering/application/port/output/db/mod.rs b/src/ordering/application/port/output/db/mod.rs index 2db807b..14fe72e 100644 --- a/src/ordering/application/port/output/db/mod.rs +++ b/src/ordering/application/port/output/db/mod.rs @@ -3,5 +3,6 @@ // SPDX-License-Identifier: AGPL-3.0-or-later pub mod errors; +pub mod kot_id_exists; pub mod line_item_id_exists; pub mod order_id_exists; diff --git a/src/ordering/application/services/errors.rs b/src/ordering/application/services/errors.rs index de37b9e..f27978a 100644 --- a/src/ordering/application/services/errors.rs +++ b/src/ordering/application/services/errors.rs @@ -15,6 +15,7 @@ pub enum OrderingError { LineItemIDNotFound, InternalError, OrderIDNotFound, + KotIDNotFound, } // impl From for OrderingError { @@ -30,6 +31,12 @@ impl From for OrderingError { Self::InternalError } OrderingDBError::OrderIDNotFound => OrderingError::OrderIDNotFound, + + OrderingDBError::DuplicateKotID => { + error!("DuplicateKotID"); + Self::InternalError + } + OrderingDBError::KotIDNotFound => OrderingError::KotIDNotFound, OrderingDBError::InternalError => Self::InternalError, } }