feat: delete order service
This commit is contained in:
parent
db72078e97
commit
93e4c18df5
9 changed files with 240 additions and 30 deletions
|
@ -38,7 +38,6 @@ pub struct LineItemView {
|
|||
deleted: bool,
|
||||
}
|
||||
|
||||
|
||||
impl Default for LineItemView {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
|
@ -57,8 +56,6 @@ impl Default for LineItemView {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl From<LineItemView> for LineItem {
|
||||
fn from(v: LineItemView) -> Self {
|
||||
let quantity = QuantityBuilder::default()
|
||||
|
|
115
src/ordering/application/services/delete_order_service.rs
Normal file
115
src/ordering/application/services/delete_order_service.rs
Normal file
|
@ -0,0 +1,115 @@
|
|||
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use derive_builder::Builder;
|
||||
use mockall::predicate::*;
|
||||
use mockall::*;
|
||||
use time::OffsetDateTime;
|
||||
|
||||
use super::errors::*;
|
||||
use crate::ordering::{
|
||||
application::port::output::db::order_id_exists::*,
|
||||
domain::{delete_order_command::*, order_aggregate::*, order_deleted_event::*},
|
||||
};
|
||||
use crate::utils::uuid::*;
|
||||
|
||||
#[automock]
|
||||
#[async_trait::async_trait]
|
||||
pub trait DeleteOrderUseCase: Send + Sync {
|
||||
async fn delete_order(&self, cmd: DeleteOrderCommand) -> OrderingResult<OrderDeletedEvent>;
|
||||
}
|
||||
|
||||
pub type DeleteOrderServiceObj = Arc<dyn DeleteOrderUseCase>;
|
||||
|
||||
#[derive(Clone, Builder)]
|
||||
pub struct DeleteOrderService {
|
||||
db_order_id_exists: OrderIDExistsDBPortObj,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl DeleteOrderUseCase for DeleteOrderService {
|
||||
async fn delete_order(&self, cmd: DeleteOrderCommand) -> OrderingResult<OrderDeletedEvent> {
|
||||
if !self
|
||||
.db_order_id_exists
|
||||
.order_id_exists(cmd.order().order_id())
|
||||
.await?
|
||||
{
|
||||
return Err(OrderingError::OrderIDNotFound);
|
||||
}
|
||||
|
||||
let deleted_order = OrderBuilder::default()
|
||||
.created_time(cmd.order().created_time().clone())
|
||||
.customer_name(cmd.order().customer_name().into())
|
||||
.order_id(*cmd.order().order_id())
|
||||
.deleted(true)
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
Ok(OrderDeletedEventBuilder::default()
|
||||
.added_by_user(*cmd.adding_by())
|
||||
.order(deleted_order)
|
||||
.build()
|
||||
.unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use super::*;
|
||||
|
||||
use crate::ordering::domain::order_deleted_event::tests::get_deleted_order_event_from_command;
|
||||
use crate::tests::bdd::*;
|
||||
|
||||
pub fn mock_delete_order_service(
|
||||
times: Option<usize>,
|
||||
cmd: DeleteOrderCommand,
|
||||
) -> DeleteOrderServiceObj {
|
||||
let mut m = MockDeleteOrderUseCase::new();
|
||||
|
||||
let res = get_deleted_order_event_from_command(&cmd);
|
||||
if let Some(times) = times {
|
||||
m.expect_delete_order()
|
||||
.times(times)
|
||||
.returning(move |_| Ok(res.clone()));
|
||||
} else {
|
||||
m.expect_delete_order().returning(move |_| Ok(res.clone()));
|
||||
}
|
||||
|
||||
Arc::new(m)
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_service() {
|
||||
let cmd = DeleteOrderCommand::get_cmd();
|
||||
|
||||
let s = DeleteOrderServiceBuilder::default()
|
||||
.db_order_id_exists(mock_order_id_exists_db_port_true(IS_CALLED_ONLY_ONCE))
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let res = s.delete_order(cmd.clone()).await.unwrap();
|
||||
assert_eq!(res.order().customer_name(), cmd.order().customer_name());
|
||||
assert_eq!(res.order().order_id(), cmd.order().order_id());
|
||||
assert!(res.order().deleted());
|
||||
|
||||
assert_eq!(res.added_by_user(), cmd.adding_by());
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_service_order_id_doesnt_exist() {
|
||||
let cmd = DeleteOrderCommand::get_cmd();
|
||||
|
||||
let s = DeleteOrderServiceBuilder::default()
|
||||
.db_order_id_exists(mock_order_id_exists_db_port_false(IS_CALLED_ONLY_ONCE))
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
s.delete_order(cmd.clone()).await,
|
||||
Err(OrderingError::OrderIDNotFound)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -12,6 +12,7 @@ pub mod errors;
|
|||
pub mod add_line_item_service;
|
||||
pub mod add_order_service;
|
||||
pub mod delete_line_item_service;
|
||||
pub mod delete_order_service;
|
||||
pub mod update_line_item_service;
|
||||
pub mod update_order_service;
|
||||
|
||||
|
@ -22,6 +23,7 @@ pub trait OrderingServicesInterface: Send + Sync {
|
|||
fn delete_line_item(&self) -> delete_line_item_service::DeleteLineItemServiceObj;
|
||||
fn add_order(&self) -> add_order_service::AddOrderServiceObj;
|
||||
fn update_order(&self) -> update_order_service::UpdateOrderServiceObj;
|
||||
fn delete_order(&self) -> delete_order_service::DeleteOrderServiceObj;
|
||||
}
|
||||
|
||||
#[derive(Clone, Builder)]
|
||||
|
@ -31,6 +33,7 @@ pub struct OrderingServices {
|
|||
delete_line_item: delete_line_item_service::DeleteLineItemServiceObj,
|
||||
add_order: add_order_service::AddOrderServiceObj,
|
||||
update_order: update_order_service::UpdateOrderServiceObj,
|
||||
delete_order: delete_order_service::DeleteOrderServiceObj,
|
||||
}
|
||||
|
||||
impl OrderingServicesInterface for OrderingServices {
|
||||
|
@ -52,4 +55,8 @@ impl OrderingServicesInterface for OrderingServices {
|
|||
fn update_order(&self) -> update_order_service::UpdateOrderServiceObj {
|
||||
self.update_order.clone()
|
||||
}
|
||||
|
||||
fn delete_order(&self) -> delete_order_service::DeleteOrderServiceObj {
|
||||
self.delete_order.clone()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize};
|
|||
|
||||
use super::{
|
||||
add_line_item_command::AddLineItemCommand, add_order_command::AddOrderCommand,
|
||||
delete_line_item_command::DeleteLineItemCommand,
|
||||
delete_line_item_command::DeleteLineItemCommand, delete_order_command::DeleteOrderCommand,
|
||||
update_line_item_command::UpdateLineItemCommand, update_order_command::UpdateOrderCommand,
|
||||
};
|
||||
|
||||
|
@ -18,4 +18,5 @@ pub enum OrderingCommand {
|
|||
DeleteLineItem(DeleteLineItemCommand),
|
||||
AddOrder(AddOrderCommand),
|
||||
UpdateOrder(UpdateOrderCommand),
|
||||
DeleteOrder(DeleteOrderCommand),
|
||||
}
|
||||
|
|
37
src/ordering/domain/delete_order_command.rs
Normal file
37
src/ordering/domain/delete_order_command.rs
Normal file
|
@ -0,0 +1,37 @@
|
|||
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
use derive_builder::Builder;
|
||||
use derive_getters::Getters;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
use super::order_aggregate::Order;
|
||||
|
||||
#[derive(
|
||||
Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Ord, PartialOrd, Builder, Getters,
|
||||
)]
|
||||
pub struct DeleteOrderCommand {
|
||||
adding_by: Uuid,
|
||||
order: Order,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::utils::uuid::tests::UUID;
|
||||
|
||||
use super::*;
|
||||
|
||||
impl DeleteOrderCommand {
|
||||
pub fn get_cmd() -> Self {
|
||||
let adding_by = UUID;
|
||||
|
||||
DeleteOrderCommandBuilder::default()
|
||||
.adding_by(adding_by)
|
||||
.order(Order::get_order())
|
||||
.build()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize};
|
|||
use super::{
|
||||
line_item_added_event::LineItemAddedEvent, line_item_deleted_event::LineItemDeletedEvent,
|
||||
line_item_updated_event::LineItemUpdatedEvent, order_added_event::OrderAddedEvent,
|
||||
order_updated_event::OrderUpdatedEvent,
|
||||
order_deleted_event::OrderDeletedEvent, order_updated_event::OrderUpdatedEvent,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Ord, PartialOrd)]
|
||||
|
@ -18,6 +18,7 @@ pub enum OrderingEvent {
|
|||
LineItemDeleted(LineItemDeletedEvent),
|
||||
OrderAdded(OrderAddedEvent),
|
||||
OrderUpdated(OrderUpdatedEvent),
|
||||
OrderDeleted(OrderDeletedEvent),
|
||||
}
|
||||
|
||||
impl DomainEvent for OrderingEvent {
|
||||
|
@ -32,6 +33,7 @@ impl DomainEvent for OrderingEvent {
|
|||
OrderingEvent::LineItemDeleted { .. } => "OrderingLineItemDeleted",
|
||||
OrderingEvent::OrderAdded { .. } => "OrderingOrderAdded",
|
||||
OrderingEvent::OrderUpdated { .. } => "OrderingOrderUpdated",
|
||||
OrderingEvent::OrderDeleted { .. } => "OrderingOrderDeleted",
|
||||
};
|
||||
|
||||
e.to_string()
|
||||
|
|
|
@ -12,6 +12,7 @@ pub mod add_line_item_command;
|
|||
pub mod add_order_command;
|
||||
pub mod commands;
|
||||
pub mod delete_line_item_command;
|
||||
pub mod delete_order_command;
|
||||
pub mod update_line_item_command;
|
||||
pub mod update_order_command;
|
||||
|
||||
|
@ -21,4 +22,5 @@ pub mod line_item_added_event;
|
|||
pub mod line_item_deleted_event;
|
||||
pub mod line_item_updated_event;
|
||||
pub mod order_added_event;
|
||||
pub mod order_deleted_event;
|
||||
pub mod order_updated_event;
|
||||
|
|
|
@ -87,6 +87,10 @@ impl Aggregate for Order {
|
|||
let res = services.update_order().update_order(cmd).await?;
|
||||
Ok(vec![OrderingEvent::OrderUpdated(res)])
|
||||
}
|
||||
OrderingCommand::DeleteOrder(cmd) => {
|
||||
let res = services.delete_order().delete_order(cmd).await?;
|
||||
Ok(vec![OrderingEvent::OrderDeleted(res)])
|
||||
}
|
||||
_ => Ok(Vec::default()),
|
||||
}
|
||||
}
|
||||
|
@ -95,7 +99,7 @@ impl Aggregate for Order {
|
|||
match event {
|
||||
OrderingEvent::OrderAdded(e) => *self = e.order().clone(),
|
||||
OrderingEvent::OrderUpdated(e) => *self = e.new_order().clone(),
|
||||
// OrderingEvent::OrderDeleted(e) => *self = e.order().clone(),
|
||||
OrderingEvent::OrderDeleted(e) => *self = e.order().clone(),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
@ -107,13 +111,13 @@ mod aggregate_tests {
|
|||
|
||||
use add_order_service::tests::mock_add_order_service;
|
||||
use cqrs_es::test::TestFramework;
|
||||
// use delete_order_service::tests::mock_delete_order_service;
|
||||
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::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::*;
|
||||
|
@ -159,25 +163,22 @@ mod aggregate_tests {
|
|||
.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]);
|
||||
// }
|
||||
|
||||
#[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]);
|
||||
}
|
||||
}
|
||||
|
|
48
src/ordering/domain/order_deleted_event.rs
Normal file
48
src/ordering/domain/order_deleted_event.rs
Normal file
|
@ -0,0 +1,48 @@
|
|||
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
use derive_builder::Builder;
|
||||
use derive_getters::Getters;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
use super::order_aggregate::*;
|
||||
|
||||
#[derive(
|
||||
Clone, Debug, Builder, Serialize, Deserialize, Getters, Eq, PartialEq, Ord, PartialOrd,
|
||||
)]
|
||||
pub struct OrderDeletedEvent {
|
||||
added_by_user: Uuid,
|
||||
|
||||
order: Order,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use crate::ordering::domain::delete_order_command::DeleteOrderCommand;
|
||||
|
||||
use super::*;
|
||||
|
||||
pub fn get_deleted_order_event_from_command(cmd: &DeleteOrderCommand) -> OrderDeletedEvent {
|
||||
let deleted_order = OrderBuilder::default()
|
||||
.created_time(cmd.order().created_time().clone())
|
||||
.customer_name(cmd.order().customer_name().into())
|
||||
.order_id(*cmd.order().order_id())
|
||||
.deleted(true)
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
OrderDeletedEventBuilder::default()
|
||||
.added_by_user(cmd.adding_by().clone())
|
||||
.order(deleted_order)
|
||||
.build()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_event() {
|
||||
let event = get_deleted_order_event_from_command(&DeleteOrderCommand::get_cmd());
|
||||
assert!(event.order().deleted());
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue