210 lines
7.1 KiB
Rust
210 lines
7.1 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 super::errors::*;
|
|
use crate::ordering::{
|
|
application::port::output::db::{
|
|
customization_id_exists::*, customization_name_exists_for_product::*, product_id_exists::*,
|
|
},
|
|
domain::{
|
|
customization_aggregate::*, customization_updated_event::*, update_customization_command::*,
|
|
},
|
|
};
|
|
use crate::utils::uuid::*;
|
|
|
|
#[automock]
|
|
#[async_trait::async_trait]
|
|
pub trait UpdateCustomizationUseCase: Send + Sync {
|
|
async fn update_customization(
|
|
&self,
|
|
cmd: UpdateCustomizationCommand,
|
|
) -> OrderingResult<CustomizationUpdatedEvent>;
|
|
}
|
|
|
|
pub type UpdateCustomizationServiceObj = Arc<dyn UpdateCustomizationUseCase>;
|
|
|
|
#[derive(Clone, Builder)]
|
|
pub struct UpdateCustomizationService {
|
|
// TODO: check if product ID exists
|
|
db_customization_name_exists_for_product: CustomizationNameExistsForProductDBPortObj,
|
|
db_customization_id_exists: CustomizationIDExistsDBPortObj,
|
|
db_product_id_exists: ProductIDExistsDBPortObj,
|
|
}
|
|
|
|
#[async_trait::async_trait]
|
|
impl UpdateCustomizationUseCase for UpdateCustomizationService {
|
|
async fn update_customization(
|
|
&self,
|
|
cmd: UpdateCustomizationCommand,
|
|
) -> OrderingResult<CustomizationUpdatedEvent> {
|
|
if !self
|
|
.db_customization_id_exists
|
|
.customization_id_exists(cmd.old_customization().customization_id())
|
|
.await?
|
|
{
|
|
return Err(OrderingError::CustomizationIDNotFound);
|
|
}
|
|
|
|
if !self
|
|
.db_product_id_exists
|
|
.product_id_exists(cmd.old_customization().product_id())
|
|
.await?
|
|
{
|
|
return Err(OrderingError::ProductIDNotFound);
|
|
}
|
|
|
|
let updated_customization = CustomizationBuilder::default()
|
|
.name(cmd.name().into())
|
|
.product_id(*cmd.old_customization().product_id())
|
|
.customization_id(*cmd.old_customization().customization_id())
|
|
.deleted(*cmd.old_customization().deleted())
|
|
.build()
|
|
.unwrap();
|
|
|
|
if updated_customization.name() != cmd.old_customization().name() {
|
|
if self
|
|
.db_customization_name_exists_for_product
|
|
.customization_name_exists_for_product(&updated_customization)
|
|
.await?
|
|
{
|
|
return Err(OrderingError::DuplicateCustomizationName);
|
|
}
|
|
}
|
|
|
|
Ok(CustomizationUpdatedEventBuilder::default()
|
|
.added_by_user(*cmd.adding_by())
|
|
.old_customization(cmd.old_customization().clone())
|
|
.new_customization(updated_customization)
|
|
.build()
|
|
.unwrap())
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
pub mod tests {
|
|
use super::*;
|
|
|
|
use crate::ordering::domain::customization_updated_event;
|
|
use crate::ordering::domain::update_customization_command::tests::get_update_customization_command;
|
|
use crate::tests::bdd::*;
|
|
|
|
pub fn mock_update_customization_service(
|
|
times: Option<usize>,
|
|
cmd: UpdateCustomizationCommand,
|
|
) -> UpdateCustomizationServiceObj {
|
|
let mut m = MockUpdateCustomizationUseCase::new();
|
|
|
|
let res =
|
|
customization_updated_event::tests::get_customization_updated_event_from_command(&cmd);
|
|
|
|
if let Some(times) = times {
|
|
m.expect_update_customization()
|
|
.times(times)
|
|
.returning(move |_| Ok(res.clone()));
|
|
} else {
|
|
m.expect_update_customization()
|
|
.returning(move |_| Ok(res.clone()));
|
|
}
|
|
|
|
Arc::new(m)
|
|
}
|
|
|
|
#[actix_rt::test]
|
|
async fn test_service() {
|
|
let cmd = get_update_customization_command();
|
|
|
|
let s = UpdateCustomizationServiceBuilder::default()
|
|
.db_product_id_exists(mock_product_id_exists_db_port_true(IS_CALLED_ONLY_ONCE))
|
|
.db_customization_name_exists_for_product(
|
|
mock_customization_name_exists_for_product_db_port_false(IS_CALLED_ONLY_ONCE),
|
|
)
|
|
.db_customization_id_exists(mock_customization_id_exists_db_port_true(
|
|
IS_CALLED_ONLY_ONCE,
|
|
))
|
|
.build()
|
|
.unwrap();
|
|
|
|
let res = s.update_customization(cmd.clone()).await.unwrap();
|
|
assert_eq!(res.new_customization().name(), cmd.name());
|
|
assert_eq!(
|
|
res.new_customization().product_id(),
|
|
cmd.old_customization().product_id()
|
|
);
|
|
assert_eq!(
|
|
res.new_customization().customization_id(),
|
|
cmd.old_customization().customization_id()
|
|
);
|
|
assert_eq!(res.old_customization(), cmd.old_customization());
|
|
assert_eq!(res.added_by_user(), cmd.adding_by());
|
|
}
|
|
|
|
#[actix_rt::test]
|
|
async fn test_service_product_doesnt_exist() {
|
|
let cmd = get_update_customization_command();
|
|
|
|
let s = UpdateCustomizationServiceBuilder::default()
|
|
.db_product_id_exists(mock_product_id_exists_db_port_false(IS_CALLED_ONLY_ONCE))
|
|
.db_customization_name_exists_for_product(
|
|
mock_customization_name_exists_for_product_db_port_false(IS_NEVER_CALLED),
|
|
)
|
|
.db_customization_id_exists(mock_customization_id_exists_db_port_true(
|
|
IS_CALLED_ONLY_ONCE,
|
|
))
|
|
.build()
|
|
.unwrap();
|
|
|
|
assert_eq!(
|
|
s.update_customization(cmd.clone()).await,
|
|
Err(OrderingError::ProductIDNotFound)
|
|
);
|
|
}
|
|
|
|
#[actix_rt::test]
|
|
async fn test_customization_id_not_found() {
|
|
let cmd = get_update_customization_command();
|
|
|
|
let s = UpdateCustomizationServiceBuilder::default()
|
|
.db_product_id_exists(mock_product_id_exists_db_port_true(IS_NEVER_CALLED))
|
|
.db_customization_name_exists_for_product(
|
|
mock_customization_name_exists_for_product_db_port_false(IS_NEVER_CALLED),
|
|
)
|
|
.db_customization_id_exists(mock_customization_id_exists_db_port_false(
|
|
IS_CALLED_ONLY_ONCE,
|
|
))
|
|
.build()
|
|
.unwrap();
|
|
|
|
assert_eq!(
|
|
s.update_customization(cmd.clone()).await,
|
|
Err(OrderingError::CustomizationIDNotFound)
|
|
);
|
|
}
|
|
|
|
#[actix_rt::test]
|
|
async fn test_duplicate_new_name() {
|
|
let cmd = get_update_customization_command();
|
|
|
|
let s = UpdateCustomizationServiceBuilder::default()
|
|
.db_product_id_exists(mock_product_id_exists_db_port_true(IS_CALLED_ONLY_ONCE))
|
|
.db_customization_name_exists_for_product(
|
|
mock_customization_name_exists_for_product_db_port_true(IS_CALLED_ONLY_ONCE),
|
|
)
|
|
.db_customization_id_exists(mock_customization_id_exists_db_port_true(
|
|
IS_CALLED_ONLY_ONCE,
|
|
))
|
|
.build()
|
|
.unwrap();
|
|
|
|
assert_eq!(
|
|
s.update_customization(cmd.clone()).await,
|
|
Err(OrderingError::DuplicateCustomizationName)
|
|
);
|
|
}
|
|
}
|