113 lines
3.5 KiB
Rust
113 lines
3.5 KiB
Rust
// 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::line_item_id_exists::*,
|
|
domain::{add_line_item_command::*, line_item_added_event::*, line_item_aggregate::*},
|
|
};
|
|
use crate::utils::uuid::*;
|
|
|
|
#[automock]
|
|
#[async_trait::async_trait]
|
|
pub trait AddLineItemUseCase: Send + Sync {
|
|
async fn add_line_item(&self, cmd: AddLineItemCommand) -> OrderingResult<LineItemAddedEvent>;
|
|
}
|
|
|
|
pub type AddLineItemServiceObj = Arc<dyn AddLineItemUseCase>;
|
|
|
|
#[derive(Clone, Builder)]
|
|
pub struct AddLineItemService {
|
|
db_line_item_id_exists: LineItemIDExistsDBPortObj,
|
|
get_uuid: GetUUIDInterfaceObj,
|
|
}
|
|
|
|
#[async_trait::async_trait]
|
|
impl AddLineItemUseCase for AddLineItemService {
|
|
async fn add_line_item(&self, cmd: AddLineItemCommand) -> OrderingResult<LineItemAddedEvent> {
|
|
let mut line_item_id = self.get_uuid.get_uuid();
|
|
|
|
loop {
|
|
if self
|
|
.db_line_item_id_exists
|
|
.line_item_id_exists(&line_item_id)
|
|
.await?
|
|
{
|
|
line_item_id = self.get_uuid.get_uuid();
|
|
continue;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
let line_item = LineItemBuilder::default()
|
|
.sale_time(OffsetDateTime::now_utc())
|
|
.product_name(cmd.product_name().into())
|
|
.product_id(*cmd.product_id())
|
|
.line_item_id(line_item_id)
|
|
.quantity(cmd.quantity().clone())
|
|
.deleted(false)
|
|
.build()
|
|
.unwrap();
|
|
|
|
Ok(LineItemAddedEventBuilder::default()
|
|
.added_by_user(*cmd.adding_by())
|
|
.line_item(line_item)
|
|
.build()
|
|
.unwrap())
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
pub mod tests {
|
|
use super::*;
|
|
|
|
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::*, utils::uuid::tests::mock_get_uuid};
|
|
|
|
pub fn mock_add_line_item_service(
|
|
times: Option<usize>,
|
|
cmd: AddLineItemCommand,
|
|
) -> AddLineItemServiceObj {
|
|
let mut m = MockAddLineItemUseCase::new();
|
|
|
|
let res = get_added_line_item_event_from_command(&cmd);
|
|
if let Some(times) = times {
|
|
m.expect_add_line_item()
|
|
.times(times)
|
|
.returning(move |_| Ok(res.clone()));
|
|
} else {
|
|
m.expect_add_line_item().returning(move |_| Ok(res.clone()));
|
|
}
|
|
|
|
Arc::new(m)
|
|
}
|
|
|
|
#[actix_rt::test]
|
|
async fn test_service() {
|
|
let cmd = AddLineItemCommand::get_cmd();
|
|
|
|
let s = AddLineItemServiceBuilder::default()
|
|
.db_line_item_id_exists(mock_line_item_id_exists_db_port_false(IS_CALLED_ONLY_ONCE))
|
|
.get_uuid(mock_get_uuid(IS_CALLED_ONLY_ONCE))
|
|
.build()
|
|
.unwrap();
|
|
|
|
let res = s.add_line_item(cmd.clone()).await.unwrap();
|
|
assert_eq!(res.line_item().product_name(), cmd.product_name());
|
|
assert_eq!(res.line_item().product_id(), cmd.product_id());
|
|
assert_eq!(res.line_item().quantity(), cmd.quantity());
|
|
assert_eq!(res.line_item().quantity(), cmd.quantity());
|
|
assert!(!res.line_item().deleted());
|
|
assert_eq!(res.added_by_user(), cmd.adding_by());
|
|
}
|
|
}
|