diff --git a/.sqlx/query-14d111d7453b89f2346966a9fdd725d269ef36288ed5e7fe1f7ad452deaab0e6.json b/.sqlx/query-c9bee14e15dae80b7af9b0fdca43a97b964024252bed2d0caeebee175acd55d9.json similarity index 62% rename from .sqlx/query-14d111d7453b89f2346966a9fdd725d269ef36288ed5e7fe1f7ad452deaab0e6.json rename to .sqlx/query-c9bee14e15dae80b7af9b0fdca43a97b964024252bed2d0caeebee175acd55d9.json index eb6f222..10d0d3b 100644 --- a/.sqlx/query-14d111d7453b89f2346966a9fdd725d269ef36288ed5e7fe1f7ad452deaab0e6.json +++ b/.sqlx/query-c9bee14e15dae80b7af9b0fdca43a97b964024252bed2d0caeebee175acd55d9.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "UPDATE\n cqrs_inventory_category_query\n SET\n version = $1,\n name = $2,\n description = $3,\n category_id = $4,\n store_id = $5,\n deleted = $6;", + "query": "UPDATE\n cqrs_inventory_category_query\n SET\n version = $1,\n name = $2,\n description = $3,\n store_id = $4,\n deleted = $5;", "describe": { "columns": [], "parameters": { @@ -9,11 +9,10 @@ "Text", "Text", "Uuid", - "Uuid", "Bool" ] }, "nullable": [] }, - "hash": "14d111d7453b89f2346966a9fdd725d269ef36288ed5e7fe1f7ad452deaab0e6" + "hash": "c9bee14e15dae80b7af9b0fdca43a97b964024252bed2d0caeebee175acd55d9" } diff --git a/.sqlx/query-e88a5dae732c3f8180664f306b4bb1d21f97a2f1391860eb8714a52ef4439d81.json b/.sqlx/query-d46bb69f4e2afbae01ab08beb48a67b2cade64d9ebd47f3fc6143b057671cc1b.json similarity index 64% rename from .sqlx/query-e88a5dae732c3f8180664f306b4bb1d21f97a2f1391860eb8714a52ef4439d81.json rename to .sqlx/query-d46bb69f4e2afbae01ab08beb48a67b2cade64d9ebd47f3fc6143b057671cc1b.json index 64c9c18..510d21f 100644 --- a/.sqlx/query-e88a5dae732c3f8180664f306b4bb1d21f97a2f1391860eb8714a52ef4439d81.json +++ b/.sqlx/query-d46bb69f4e2afbae01ab08beb48a67b2cade64d9ebd47f3fc6143b057671cc1b.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "UPDATE\n cqrs_inventory_product_customizations_query\n SET\n version = $1,\n name = $2,\n customization_id = $3,\n product_id = $4,\n deleted = $5;", + "query": "UPDATE\n cqrs_inventory_product_customizations_query\n SET\n version = $1,\n name = $2,\n product_id = $3,\n deleted = $4;", "describe": { "columns": [], "parameters": { @@ -8,11 +8,10 @@ "Int8", "Text", "Uuid", - "Uuid", "Bool" ] }, "nullable": [] }, - "hash": "e88a5dae732c3f8180664f306b4bb1d21f97a2f1391860eb8714a52ef4439d81" + "hash": "d46bb69f4e2afbae01ab08beb48a67b2cade64d9ebd47f3fc6143b057671cc1b" } diff --git a/src/inventory/adapters/output/db/postgres/category_view.rs b/src/inventory/adapters/output/db/postgres/category_view.rs index 34beb61..ca05a38 100644 --- a/src/inventory/adapters/output/db/postgres/category_view.rs +++ b/src/inventory/adapters/output/db/postgres/category_view.rs @@ -10,7 +10,7 @@ use uuid::Uuid; use super::errors::*; use super::InventoryDBPostgresAdapter; -use crate::inventory::domain::category_aggregate::Category; +use crate::inventory::domain::category_aggregate::{Category, CategoryBuilder}; use crate::inventory::domain::events::InventoryEvent; use crate::utils::parse_aggregate_id::parse_aggregate_id; @@ -27,6 +27,19 @@ pub struct CategoryView { deleted: bool, } +impl From for Category { + fn from(v: CategoryView) -> Self { + CategoryBuilder::default() + .name(v.name) + .description(v.description) + .category_id(v.category_id) + .store_id(v.store_id) + .deleted(v.deleted) + .build() + .unwrap() + } +} + // This updates the view with events as they are committed. // The logic should be minimal here, e.g., don't calculate the account balance, // design the events to carry the balance information instead. @@ -164,13 +177,11 @@ impl ViewRepository for InventoryDBPostgresAdapter { version = $1, name = $2, description = $3, - category_id = $4, - store_id = $5, - deleted = $6;", + store_id = $4, + deleted = $5;", version, view.name, view.description, - view.category_id, view.store_id, view.deleted ) @@ -217,3 +228,143 @@ impl Query for InventoryDBPostgresAdapter { self.update_view(view, view_context).await.unwrap(); } } + +#[cfg(test)] +mod tests { + use super::*; + + use postgres_es::PostgresCqrs; + + use crate::{ + db::migrate::*, + inventory::{ + application::services::{ + add_category_service::*, update_category_service::*, MockInventoryServicesInterface, + }, + domain::{ + add_category_command::*, category_aggregate::*, commands::*, events::*, + store_aggregate::*, update_category_command::*, + }, + }, + tests::bdd::*, + utils::{random_string::GenerateRandomStringInterface, uuid::tests::UUID}, + }; + use std::sync::Arc; + + #[actix_rt::test] + async fn pg_query_inventory_category_view() { + let settings = crate::settings::tests::get_settings().await; + //let settings = crate::settings::Settings::new().unwrap(); + settings.create_db().await; + + let db = crate::db::sqlx_postgres::Postgres::init(&settings.database.url).await; + db.migrate().await; + let db = InventoryDBPostgresAdapter::new(db.pool.clone()); + + let store = Store::default(); + crate::inventory::adapters::output::db::postgres::store_id_exists::tests::create_dummy_store_record(&store, &db).await; + + let queries: Vec>> = vec![Box::new(db.clone())]; + + let mut mock_services = MockInventoryServicesInterface::new(); + + let db2 = Arc::new(db.clone()); + mock_services + .expect_add_category() + .times(IS_CALLED_ONLY_ONCE.unwrap()) + .returning(move || { + Arc::new( + AddCategoryServiceBuilder::default() + .db_store_id_exists(db2.clone()) + .db_category_name_exists_for_store(db2.clone()) + .db_category_id_exists(db2.clone()) + .build() + .unwrap(), + ) + }); + + let db2 = Arc::new(db.clone()); + mock_services + .expect_update_category() + .times(IS_CALLED_ONLY_ONCE.unwrap()) + .returning(move || { + Arc::new( + UpdateCategoryServiceBuilder::default() + .db_store_id_exists(db2.clone()) + .db_category_name_exists_for_store(db2.clone()) + .db_category_id_exists(db2.clone()) + .build() + .unwrap(), + ) + }); + + let (cqrs, category_query): ( + Arc>, + Arc>, + ) = ( + Arc::new(postgres_es::postgres_cqrs( + db.pool.clone(), + queries, + Arc::new(mock_services), + )), + Arc::new(db.clone()), + ); + + let rand = crate::utils::random_string::GenerateRandomString {}; + + let cmd = AddCategoryCommandBuilder::default() + .name(rand.get_random(10)) + .description(None) + .store_id(*store.store_id()) + .adding_by(UUID) + .category_id(UUID) + .build() + .unwrap(); + + cqrs.execute( + &cmd.category_id().to_string(), + InventoryCommand::AddCategory(cmd.clone()), + ) + .await + .unwrap(); + + let category = category_query + .load(&(*cmd.category_id()).to_string()) + .await + .unwrap() + .unwrap(); + let category: Category = category.into(); + assert_eq!(category.name(), cmd.name()); + assert_eq!(category.description(), cmd.description()); + assert_eq!(category.category_id(), cmd.category_id()); + assert_eq!(category.store_id(), cmd.store_id()); + assert!(!store.deleted()); + + let update_category_cmd = UpdateCategoryCommand::new( + rand.get_random(10), + Some(rand.get_random(10)), + category, + UUID, + ) + .unwrap(); + cqrs.execute( + &cmd.category_id().to_string(), + InventoryCommand::UpdateCategory(update_category_cmd.clone()), + ) + .await + .unwrap(); + let category = category_query + .load(&(*cmd.category_id()).to_string()) + .await + .unwrap() + .unwrap(); + let category: Category = category.into(); + assert_eq!(category.name(), update_category_cmd.name()); + assert_eq!(category.description(), update_category_cmd.description()); + assert_eq!(category.category_id(), cmd.category_id()); + assert_eq!(category.store_id(), cmd.store_id()); + assert!(!category.deleted()); + + settings.drop_db().await; + } +} diff --git a/src/inventory/adapters/output/db/postgres/store_id_exists.rs b/src/inventory/adapters/output/db/postgres/store_id_exists.rs index c333ceb..4702e8a 100644 --- a/src/inventory/adapters/output/db/postgres/store_id_exists.rs +++ b/src/inventory/adapters/output/db/postgres/store_id_exists.rs @@ -45,7 +45,7 @@ pub mod tests { VALUES ($1, $2, $3, $4, $5 ,$6);", 1, s.name(), - s.address().as_ref().unwrap(), + s.address().as_ref().map(|s| s.as_str()), s.store_id(), s.owner(), false