feat: define order aggregate
This commit is contained in:
parent
95dcf0bae1
commit
a47810e4e7
1 changed files with 185 additions and 0 deletions
185
src/ordering/domain/order_aggregate.rs
Normal file
185
src/ordering/domain/order_aggregate.rs
Normal file
|
@ -0,0 +1,185 @@
|
|||
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
use async_trait::async_trait;
|
||||
use cqrs_es::Aggregate;
|
||||
use derive_builder::Builder;
|
||||
use derive_getters::Getters;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use time::OffsetDateTime;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::ordering::{
|
||||
application::services::{errors::*, *},
|
||||
domain::{commands::*, events::*},
|
||||
};
|
||||
|
||||
|
||||
#[derive(
|
||||
Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Ord, PartialOrd, Builder, Getters,
|
||||
)]
|
||||
pub struct Order {
|
||||
#[builder(default = "OffsetDateTime::now_utc()")]
|
||||
created_time: OffsetDateTime,
|
||||
// kot_ids: Vec<Kot>,
|
||||
order_id: Uuid,
|
||||
#[builder(default = "false")]
|
||||
deleted: bool,
|
||||
customer_name: String,
|
||||
}
|
||||
|
||||
impl Default for Order {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
created_time: OffsetDateTime::now_utc(),
|
||||
order_id: Default::default(),
|
||||
deleted: false,
|
||||
customer_name: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{ordering::domain::add_order_command::AddOrderCommand, utils::uuid::tests::UUID};
|
||||
|
||||
use super::*;
|
||||
|
||||
impl Order {
|
||||
pub fn get_order() -> Self {
|
||||
let cmd = AddOrderCommand::get_cmd();
|
||||
|
||||
OrderBuilder::default()
|
||||
.created_time(cmd.created_time().clone())
|
||||
.customer_name("test_product".into())
|
||||
.order_id(UUID)
|
||||
.build()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[async_trait]
|
||||
impl Aggregate for Order {
|
||||
type Command = OrderingCommand;
|
||||
type Event = OrderingEvent;
|
||||
type Error = OrderingError;
|
||||
type Services = std::sync::Arc<dyn OrderingServicesInterface>;
|
||||
|
||||
// This identifier should be unique to the system.
|
||||
fn aggregate_type() -> String {
|
||||
"ordering.order".to_string()
|
||||
}
|
||||
|
||||
// The aggregate logic goes here. Note that this will be the _bulk_ of a CQRS system
|
||||
// so expect to use helper functions elsewhere to keep the code clean.
|
||||
async fn handle(
|
||||
&self,
|
||||
command: Self::Command,
|
||||
services: &Self::Services,
|
||||
) -> Result<Vec<Self::Event>, Self::Error> {
|
||||
match command {
|
||||
OrderingCommand::AddOrder(cmd) => {
|
||||
let res = services.add_order().add_order(cmd).await?;
|
||||
Ok(vec![OrderingEvent::OrderAdded(res)])
|
||||
}
|
||||
_ => Ok(Vec::default()),
|
||||
}
|
||||
}
|
||||
|
||||
fn apply(&mut self, event: Self::Event) {
|
||||
match event {
|
||||
OrderingEvent::OrderAdded(e) => *self = e.order().clone(),
|
||||
// OrderingEvent::OrderUpdated(e) => *self = e.new_order().clone(),
|
||||
// OrderingEvent::OrderDeleted(e) => *self = e.order().clone(),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod aggregate_tests {
|
||||
use std::sync::Arc;
|
||||
|
||||
use add_order_service::tests::mock_add_order_service;
|
||||
use cqrs_es::test::TestFramework;
|
||||
// use delete_order_service::tests::mock_delete_order_service;
|
||||
// use update_order_service::tests::mock_update_order_service;
|
||||
|
||||
use super::*;
|
||||
|
||||
// use crate::ordering::domain::delete_order_command::DeleteOrderCommand;
|
||||
// use crate::ordering::domain::order_deleted_event::tests::get_deleted_order_event_from_command;
|
||||
// use crate::ordering::domain::order_updated_event::tests::get_updated_order_event_from_command;
|
||||
// use crate::ordering::domain::update_order_command::UpdateOrderCommand;
|
||||
use crate::tests::bdd::*;
|
||||
|
||||
use crate::ordering::domain::{
|
||||
add_order_command::*,
|
||||
order_added_event::tests::get_added_order_event_from_command,
|
||||
};
|
||||
|
||||
type OrderTestFramework = TestFramework<Order>;
|
||||
|
||||
#[test]
|
||||
fn test_add_order() {
|
||||
let cmd = AddOrderCommand::get_cmd();
|
||||
let expected = get_added_order_event_from_command(&cmd);
|
||||
let expected = OrderingEvent::OrderAdded(expected);
|
||||
|
||||
let mut services = MockOrderingServicesInterface::new();
|
||||
services
|
||||
.expect_add_order()
|
||||
.times(IS_CALLED_ONLY_ONCE.unwrap())
|
||||
.return_const(mock_add_order_service(IS_CALLED_ONLY_ONCE, cmd.clone()));
|
||||
|
||||
OrderTestFramework::with(Arc::new(services))
|
||||
.given_no_previous_events()
|
||||
.when(OrderingCommand::AddOrder(cmd))
|
||||
.then_expect_events(vec![expected]);
|
||||
}
|
||||
//
|
||||
// #[test]
|
||||
// fn test_update_order() {
|
||||
// let cmd = UpdateOrderCommand::get_cmd();
|
||||
// let expected = get_updated_order_event_from_command(&cmd);
|
||||
// let expected = OrderingEvent::OrderUpdated(expected);
|
||||
//
|
||||
// let mut services = MockOrderingServicesInterface::new();
|
||||
// services
|
||||
// .expect_update_order()
|
||||
// .times(IS_CALLED_ONLY_ONCE.unwrap())
|
||||
// .return_const(mock_update_order_service(
|
||||
// IS_CALLED_ONLY_ONCE,
|
||||
// cmd.clone(),
|
||||
// ));
|
||||
//
|
||||
// OrderTestFramework::with(Arc::new(services))
|
||||
// .given_no_previous_events()
|
||||
// .when(OrderingCommand::UpdateOrder(cmd))
|
||||
// .then_expect_events(vec![expected]);
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn test_delete_order() {
|
||||
// let cmd = DeleteOrderCommand::get_cmd();
|
||||
// let expected = get_deleted_order_event_from_command(&cmd);
|
||||
// let expected = OrderingEvent::OrderDeleted(expected);
|
||||
//
|
||||
// let mut services = MockOrderingServicesInterface::new();
|
||||
// services
|
||||
// .expect_delete_order()
|
||||
// .times(IS_CALLED_ONLY_ONCE.unwrap())
|
||||
// .return_const(mock_delete_order_service(
|
||||
// IS_CALLED_ONLY_ONCE,
|
||||
// cmd.clone(),
|
||||
// ));
|
||||
//
|
||||
// OrderTestFramework::with(Arc::new(services))
|
||||
// .given_no_previous_events()
|
||||
// .when(OrderingCommand::DeleteOrder(cmd))
|
||||
// .then_expect_events(vec![expected]);
|
||||
// }
|
||||
}
|
Loading…
Reference in a new issue