fix&feat: ordering: Aggregate creator provides ID #114

Merged
realaravinth merged 8 commits from ordering-fix-aggregate-id into master 2024-09-24 19:10:16 +05:30
8 changed files with 213 additions and 44 deletions
Showing only changes of commit c5d5dcb323 - Show all commits

View file

@ -1,18 +1,17 @@
{ {
"db_name": "PostgreSQL", "db_name": "PostgreSQL",
"query": "UPDATE\n cqrs_ordering_kot_query\n SET\n version = $1,\n order_id = $2,\n kot_id = $3,\n created_time = $4,\n deleted = $5;", "query": "UPDATE\n cqrs_ordering_kot_query\n SET\n version = $1,\n order_id = $2,\n created_time = $3,\n deleted = $4;",
"describe": { "describe": {
"columns": [], "columns": [],
"parameters": { "parameters": {
"Left": [ "Left": [
"Int8", "Int8",
"Uuid", "Uuid",
"Uuid",
"Timestamptz", "Timestamptz",
"Bool" "Bool"
] ]
}, },
"nullable": [] "nullable": []
}, },
"hash": "4b7100e5c7442066dbb4ea7c9733e038af635766f0be61a86ca7084b34a2109d" "hash": "97c136fd927b9a153a6093da6594e5fc2837b3943b8bbcbade97920a99019c86"
} }

View file

@ -197,12 +197,10 @@ impl ViewRepository<KotView, Kot> for OrderingDBPostgresAdapter {
SET SET
version = $1, version = $1,
order_id = $2, order_id = $2,
kot_id = $3, created_time = $3,
created_time = $4, deleted = $4;",
deleted = $5;",
version, version,
view.order_id, view.order_id,
view.kot_id,
view.created_time, view.created_time,
view.deleted, view.deleted,
) )
@ -230,3 +228,182 @@ impl Query<Kot> for OrderingDBPostgresAdapter {
self.update_view(view, view_context).await.unwrap(); self.update_view(view, view_context).await.unwrap();
} }
} }
#[cfg(test)]
mod tests {
use super::*;
use postgres_es::PostgresCqrs;
use time::macros::datetime;
use crate::{
db::migrate::*,
ordering::{
application::services::{
add_kot_service::AddKotServiceBuilder, delete_kot_service::DeleteKotServiceBuilder,
update_kot_service::*, MockOrderingServicesInterface,
},
domain::{
add_kot_command::*, commands::OrderingCommand,
delete_kot_command::DeleteKotCommandBuilder, order_aggregate::Order,
update_kot_command::*,
},
},
tests::bdd::*,
utils::{
random_string::GenerateRandomStringInterface,
uuid::{tests::UUID, *},
},
};
use std::sync::Arc;
#[actix_rt::test]
async fn pg_query_ordering_kot_view() {
let settings = crate::settings::tests::get_settings().await;
//let settings = crate::settings::Settings::new().unwrap();
settings.create_db().await;
let uuid = GenerateUUID {};
let db = crate::db::sqlx_postgres::Postgres::init(&settings.database.url).await;
db.migrate().await;
let db = OrderingDBPostgresAdapter::new(db.pool.clone());
let order = Order::default();
crate::ordering::adapters::output::db::order_id_exists::tests::create_dummy_order(
&order, &db,
)
.await;
let queries: Vec<Box<dyn Query<Kot>>> = vec![Box::new(db.clone())];
let mut mock_services = MockOrderingServicesInterface::new();
let db2 = db.clone();
mock_services
.expect_add_kot()
.times(IS_CALLED_ONLY_ONCE.unwrap())
.returning(move || {
Arc::new(
AddKotServiceBuilder::default()
.db_kot_id_exists(Arc::new(db2.clone()))
.db_order_id_exists(Arc::new(db2.clone()))
.build()
.unwrap(),
)
});
let db2 = db.clone();
mock_services
.expect_update_kot()
.times(IS_CALLED_ONLY_ONCE.unwrap())
.returning(move || {
Arc::new(
UpdateKotServiceBuilder::default()
.db_kot_id_exists(Arc::new(db2.clone()))
.db_order_id_exists(Arc::new(db2.clone()))
.build()
.unwrap(),
)
});
let db2 = db.clone();
mock_services
.expect_delete_kot()
.times(IS_CALLED_ONLY_ONCE.unwrap())
.returning(move || {
Arc::new(
DeleteKotServiceBuilder::default()
.db_kot_id_exists(Arc::new(db2.clone()))
.build()
.unwrap(),
)
});
let (cqrs, kot_query): (
Arc<PostgresCqrs<Kot>>,
Arc<dyn ViewRepository<KotView, Kot>>,
) = (
Arc::new(postgres_es::postgres_cqrs(
db.pool.clone(),
queries,
Arc::new(mock_services),
)),
Arc::new(db.clone()),
);
let cmd = AddKotCommandBuilder::default()
.adding_by(UUID)
.created_time(datetime!(1970-01-01 0:00 UTC))
.order_id(*order.order_id())
.kot_id(uuid.get_uuid())
.build()
.unwrap();
cqrs.execute(
&cmd.kot_id().to_string(),
OrderingCommand::AddKot(cmd.clone()),
)
.await
.unwrap();
let kot = kot_query
.load(&(*cmd.kot_id()).to_string())
.await
.unwrap()
.unwrap();
let kot: Kot = kot.into();
assert_eq!(kot.order_id(), cmd.order_id());
assert_eq!(kot.kot_id(), cmd.kot_id());
assert!(!kot.deleted());
// update
let update_kot_cmd = UpdateKotCommandBuilder::default()
.adding_by(UUID)
.created_time(datetime!(1970-01-01 1:00 UTC))
.order_id(*order.order_id())
.old_kot(kot.clone())
.build()
.unwrap();
cqrs.execute(
&cmd.kot_id().to_string(),
OrderingCommand::UpdateKot(update_kot_cmd.clone()),
)
.await
.unwrap();
let kot = kot_query
.load(&(*cmd.kot_id()).to_string())
.await
.unwrap()
.unwrap();
let kot: Kot = kot.into();
assert_eq!(kot.order_id(), update_kot_cmd.order_id());
assert_eq!(kot.kot_id(), update_kot_cmd.old_kot().kot_id());
assert!(!kot.deleted());
// delete
let delete_kot_command = DeleteKotCommandBuilder::default()
.kot(kot.clone())
.adding_by(UUID)
.build()
.unwrap();
cqrs.execute(
&cmd.kot_id().to_string(),
OrderingCommand::DeleteKot(delete_kot_command.clone()),
)
.await
.unwrap();
let kot = kot_query
.load(&(*cmd.kot_id()).to_string())
.await
.unwrap()
.unwrap();
let kot: Kot = kot.into();
assert_eq!(kot.order_id(), delete_kot_command.kot().order_id());
assert_eq!(kot.kot_id(), delete_kot_command.kot().kot_id());
assert!(kot.deleted());
settings.drop_db().await;
}
}

View file

@ -319,7 +319,6 @@ impl Query<LineItem> for OrderingDBPostgresAdapter {
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
@ -327,18 +326,18 @@ mod tests {
use postgres_es::PostgresCqrs; use postgres_es::PostgresCqrs;
use crate::{ use crate::{
db::migrate::*,
ordering::{ ordering::{
application::services::{ application::services::{
add_line_item_service::AddLineItemServiceBuilder, delete_line_item_service::*, add_line_item_service::AddLineItemServiceBuilder, delete_line_item_service::*,
update_line_item_service::*, MockOrderingServicesInterface, update_line_item_service::*, MockOrderingServicesInterface,
}, },
domain::{ domain::{
add_line_item_command::*, kot_aggregate::Kot, commands::OrderingCommand, add_line_item_command::*, commands::OrderingCommand,
delete_line_item_command::DeleteLineItemCommandBuilder, delete_line_item_command::DeleteLineItemCommandBuilder, kot_aggregate::Kot,
update_line_item_command::*, update_line_item_command::*,
}, },
}, },
db::migrate::*,
tests::bdd::*, tests::bdd::*,
types::quantity::*, types::quantity::*,
utils::{ utils::{
@ -363,10 +362,8 @@ mod tests {
let mut mock_services = MockOrderingServicesInterface::new(); let mut mock_services = MockOrderingServicesInterface::new();
let kot = Kot::default(); let kot = Kot::default();
crate::ordering::adapters::output::db::kot_id_exists::tests::create_dummy_kot( crate::ordering::adapters::output::db::kot_id_exists::tests::create_dummy_kot(&kot, &db)
&kot, &db, .await;
)
.await;
let db2 = db.clone(); let db2 = db.clone();
mock_services mock_services
@ -428,7 +425,6 @@ mod tests {
let cmd = AddLineItemCommandBuilder::default() let cmd = AddLineItemCommandBuilder::default()
.product_name(rand.get_random(10)) .product_name(rand.get_random(10))
.adding_by(UUID) .adding_by(UUID)
.quantity(Quantity::get_quantity()) .quantity(Quantity::get_quantity())
.product_id(UUID) .product_id(UUID)
.kot_id(*kot.kot_id()) .kot_id(*kot.kot_id())
@ -462,7 +458,6 @@ mod tests {
.product_id(UUID) .product_id(UUID)
.kot_id(*kot.kot_id()) .kot_id(*kot.kot_id())
.old_line_item(line_item.clone()) .old_line_item(line_item.clone())
.build() .build()
.unwrap() .unwrap()
.validate() .validate()

View file

@ -36,7 +36,7 @@ pub mod tests {
// use crate::ordering::domain::add_order_command::tests::get_customizations; // use crate::ordering::domain::add_order_command::tests::get_customizations;
use crate::ordering::domain::order_aggregate::*; use crate::ordering::domain::order_aggregate::*;
async fn create_dummy_order(order: &Order, db: &OrderingDBPostgresAdapter) { pub async fn create_dummy_order(order: &Order, db: &OrderingDBPostgresAdapter) {
sqlx::query!( sqlx::query!(
"INSERT INTO cqrs_ordering_order_query ( "INSERT INTO cqrs_ordering_order_query (
version, version,

View file

@ -7,7 +7,6 @@ use std::sync::Arc;
use derive_builder::Builder; use derive_builder::Builder;
use mockall::predicate::*; use mockall::predicate::*;
use mockall::*; use mockall::*;
use time::OffsetDateTime;
use super::errors::*; use super::errors::*;
use crate::ordering::{ use crate::ordering::{
@ -15,7 +14,6 @@ use crate::ordering::{
application::port::output::db::order_id_exists::*, application::port::output::db::order_id_exists::*,
domain::{add_kot_command::*, kot_added_event::*, kot_aggregate::*}, domain::{add_kot_command::*, kot_added_event::*, kot_aggregate::*},
}; };
use crate::utils::uuid::*;
#[automock] #[automock]
#[async_trait::async_trait] #[async_trait::async_trait]
@ -29,7 +27,6 @@ pub type AddKotServiceObj = Arc<dyn AddKotUseCase>;
pub struct AddKotService { pub struct AddKotService {
db_kot_id_exists: KotIDExistsDBPortObj, db_kot_id_exists: KotIDExistsDBPortObj,
db_order_id_exists: OrderIDExistsDBPortObj, db_order_id_exists: OrderIDExistsDBPortObj,
get_uuid: GetUUIDInterfaceObj,
} }
#[async_trait::async_trait] #[async_trait::async_trait]
@ -43,21 +40,14 @@ impl AddKotUseCase for AddKotService {
return Err(OrderingError::OrderIDNotFound); return Err(OrderingError::OrderIDNotFound);
} }
let mut kot_id = self.get_uuid.get_uuid(); if self.db_kot_id_exists.kot_id_exists(cmd.kot_id()).await? {
return Err(OrderingError::KotIDNotFound);
loop {
if self.db_kot_id_exists.kot_id_exists(&kot_id).await? {
kot_id = self.get_uuid.get_uuid();
continue;
} else {
break;
}
} }
let kot = KotBuilder::default() let kot = KotBuilder::default()
.created_time(cmd.created_time().clone()) .created_time(cmd.created_time().clone())
.order_id(*cmd.order_id()) .order_id(*cmd.order_id())
.kot_id(kot_id) .kot_id(*cmd.kot_id())
.deleted(false) .deleted(false)
.build() .build()
.unwrap(); .unwrap();
@ -75,8 +65,8 @@ pub mod tests {
use super::*; use super::*;
use crate::ordering::domain::kot_added_event::tests::get_added_kot_event_from_command; use crate::ordering::domain::kot_added_event::tests::get_added_kot_event_from_command;
use crate::tests::bdd::*;
use crate::utils::uuid::tests::UUID; use crate::utils::uuid::tests::UUID;
use crate::{tests::bdd::*, utils::uuid::tests::mock_get_uuid};
pub fn mock_add_kot_service(times: Option<usize>, cmd: AddKotCommand) -> AddKotServiceObj { pub fn mock_add_kot_service(times: Option<usize>, cmd: AddKotCommand) -> AddKotServiceObj {
let mut m = MockAddKotUseCase::new(); let mut m = MockAddKotUseCase::new();
@ -100,7 +90,6 @@ pub mod tests {
let s = AddKotServiceBuilder::default() let s = AddKotServiceBuilder::default()
.db_kot_id_exists(mock_kot_id_exists_db_port_false(IS_CALLED_ONLY_ONCE)) .db_kot_id_exists(mock_kot_id_exists_db_port_false(IS_CALLED_ONLY_ONCE))
.db_order_id_exists(mock_order_id_exists_db_port_true(IS_CALLED_ONLY_ONCE)) .db_order_id_exists(mock_order_id_exists_db_port_true(IS_CALLED_ONLY_ONCE))
.get_uuid(mock_get_uuid(IS_CALLED_ONLY_ONCE))
.build() .build()
.unwrap(); .unwrap();
@ -118,7 +107,6 @@ pub mod tests {
let s = AddKotServiceBuilder::default() let s = AddKotServiceBuilder::default()
.db_kot_id_exists(mock_kot_id_exists_db_port_false(IS_NEVER_CALLED)) .db_kot_id_exists(mock_kot_id_exists_db_port_false(IS_NEVER_CALLED))
.db_order_id_exists(mock_order_id_exists_db_port_false(IS_CALLED_ONLY_ONCE)) .db_order_id_exists(mock_order_id_exists_db_port_false(IS_CALLED_ONLY_ONCE))
.get_uuid(mock_get_uuid(IS_NEVER_CALLED))
.build() .build()
.unwrap(); .unwrap();

View file

@ -37,13 +37,13 @@ impl AddLineItemUseCase for AddLineItemService {
return Err(OrderingError::KotIDNotFound); return Err(OrderingError::KotIDNotFound);
} }
if self if self
.db_line_item_id_exists .db_line_item_id_exists
.line_item_id_exists(cmd.line_item_id()) .line_item_id_exists(cmd.line_item_id())
.await? .await?
{ {
return Err(OrderingError::DuplicateLineItemID); return Err(OrderingError::DuplicateLineItemID);
} }
let line_item = LineItemBuilder::default() let line_item = LineItemBuilder::default()
.created_time(cmd.created_time().clone()) .created_time(cmd.created_time().clone())
@ -69,8 +69,8 @@ pub mod tests {
use super::*; use super::*;
use crate::ordering::domain::line_item_added_event::tests::get_added_line_item_event_from_command; use crate::ordering::domain::line_item_added_event::tests::get_added_line_item_event_from_command;
use crate::utils::uuid::tests::UUID;
use crate::tests::bdd::*; use crate::tests::bdd::*;
use crate::utils::uuid::tests::UUID;
pub fn mock_add_line_item_service( pub fn mock_add_line_item_service(
times: Option<usize>, times: Option<usize>,

View file

@ -17,6 +17,7 @@ pub struct AddKotCommand {
#[builder(default = "OffsetDateTime::now_utc()")] #[builder(default = "OffsetDateTime::now_utc()")]
created_time: OffsetDateTime, created_time: OffsetDateTime,
order_id: Uuid, order_id: Uuid,
kot_id: Uuid,
} }
#[cfg(test)] #[cfg(test)]
@ -36,6 +37,7 @@ mod tests {
.adding_by(adding_by) .adding_by(adding_by)
.created_time(datetime!(1970-01-01 0:00 UTC)) .created_time(datetime!(1970-01-01 0:00 UTC))
.order_id(order_id) .order_id(order_id)
.kot_id(UUID)
.build() .build()
.unwrap() .unwrap()
} }
@ -49,10 +51,12 @@ mod tests {
let cmd = AddKotCommandBuilder::default() let cmd = AddKotCommandBuilder::default()
.adding_by(adding_by) .adding_by(adding_by)
.order_id(order_id) .order_id(order_id)
.kot_id(UUID)
.build() .build()
.unwrap(); .unwrap();
assert_eq!(*cmd.order_id(), order_id); assert_eq!(*cmd.order_id(), order_id);
assert_eq!(*cmd.kot_id(), UUID);
assert_eq!(*cmd.adding_by(), adding_by); assert_eq!(*cmd.adding_by(), adding_by);
} }
} }

View file

@ -20,12 +20,18 @@ pub struct KotAddedEvent {
#[cfg(test)] #[cfg(test)]
pub mod tests { pub mod tests {
use crate::ordering::domain::add_kot_command::AddKotCommand; use crate::ordering::domain::{add_kot_command::AddKotCommand, kot_aggregate::*};
use super::*; use super::*;
pub fn get_added_kot_event_from_command(cmd: &AddKotCommand) -> KotAddedEvent { pub fn get_added_kot_event_from_command(cmd: &AddKotCommand) -> KotAddedEvent {
let kot = Kot::get_kot(); let kot = KotBuilder::default()
.created_time(cmd.created_time().clone())
.order_id(*cmd.order_id())
.kot_id(*cmd.kot_id())
.deleted(false)
.build()
.unwrap();
KotAddedEventBuilder::default() KotAddedEventBuilder::default()
.added_by_user(cmd.adding_by().clone()) .added_by_user(cmd.adding_by().clone())