vanikam/src/inventory/application/services/update_store_service.rs
Aravinth Manivannan bc1245894b
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline was successful
ci/woodpecker/pull_request_closed/woodpecker Pipeline was successful
feat: update Store aggregate cmd, event and service
2024-07-16 22:41:12 +05:30

146 lines
4.6 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::inventory::{
application::port::output::db::{store_id_exists::*, store_name_exists::*},
domain::{
store_aggregate::*, store_updated_event::*, update_store_command::UpdateStoreCommand,
},
};
use crate::utils::uuid::*;
#[automock]
#[async_trait::async_trait]
pub trait UpdateStoreUseCase: Send + Sync {
async fn update_store(&self, cmd: UpdateStoreCommand) -> InventoryResult<StoreUpdatedEvent>;
}
pub type UpdateStoreServiceObj = Arc<dyn UpdateStoreUseCase>;
#[derive(Clone, Builder)]
pub struct UpdateStoreService {
db_store_id_exists: StoreIDExistsDBPortObj,
db_store_name_exists: StoreNameExistsDBPortObj,
}
#[async_trait::async_trait]
impl UpdateStoreUseCase for UpdateStoreService {
async fn update_store(&self, cmd: UpdateStoreCommand) -> InventoryResult<StoreUpdatedEvent> {
if !self
.db_store_id_exists
.store_id_exists(cmd.old_store().store_id())
.await?
{
return Err(InventoryError::StoreIDNotFound);
}
let store = StoreBuilder::default()
.name(cmd.name().into())
.address(cmd.address().as_ref().map(|s| s.to_string()))
.owner(*cmd.owner())
.store_id(*cmd.old_store().store_id())
.build()
.unwrap();
if cmd.name() != cmd.old_store().name() {
if self.db_store_name_exists.store_name_exists(&store).await? {
return Err(InventoryError::DuplicateStoreName);
}
}
Ok(StoreUpdatedEventBuilder::default()
.added_by_user(*cmd.adding_by())
.new_store(store)
.old_store(cmd.old_store().clone())
.build()
.unwrap())
}
}
#[cfg(test)]
pub mod tests {
use super::*;
use crate::inventory::domain::store_updated_event::tests::get_store_updated_event_from_command;
use crate::inventory::domain::update_store_command::tests::get_update_store_cmd;
use crate::tests::bdd::*;
use crate::utils::uuid::tests::*;
pub fn mock_update_store_service(
times: Option<usize>,
cmd: UpdateStoreCommand,
) -> UpdateStoreServiceObj {
let mut m = MockUpdateStoreUseCase::new();
let res = get_store_updated_event_from_command(&cmd);
if let Some(times) = times {
m.expect_update_store()
.times(times)
.returning(move |_| Ok(res.clone()));
} else {
m.expect_update_store().returning(move |_| Ok(res.clone()));
}
Arc::new(m)
}
#[actix_rt::test]
async fn test_service() {
let cmd = get_update_store_cmd();
let s = UpdateStoreServiceBuilder::default()
.db_store_id_exists(mock_store_id_exists_db_port_true(IS_CALLED_ONLY_ONCE))
.db_store_name_exists(mock_store_name_exists_db_port_false(IS_CALLED_ONLY_ONCE))
.build()
.unwrap();
let res = s.update_store(cmd.clone()).await.unwrap();
assert_eq!(res.new_store().name(), cmd.name());
assert_eq!(res.new_store().address(), cmd.address());
assert_eq!(res.new_store().owner(), cmd.owner());
assert_eq!(res.new_store().store_id(), cmd.old_store().store_id());
assert_eq!(res.old_store(), cmd.old_store());
assert_eq!(res.added_by_user(), cmd.adding_by());
}
#[actix_rt::test]
async fn test_service_store_name_exists() {
let cmd = get_update_store_cmd();
let s = UpdateStoreServiceBuilder::default()
.db_store_id_exists(mock_store_id_exists_db_port_true(IS_CALLED_ONLY_ONCE))
.db_store_name_exists(mock_store_name_exists_db_port_true(IS_CALLED_ONLY_ONCE))
.build()
.unwrap();
assert_eq!(
s.update_store(cmd.clone()).await,
Err(InventoryError::DuplicateStoreName)
);
}
#[actix_rt::test]
async fn test_service_store_id_doesnt_exist() {
let cmd = get_update_store_cmd();
let s = UpdateStoreServiceBuilder::default()
.db_store_id_exists(mock_store_id_exists_db_port_false(IS_CALLED_ONLY_ONCE))
.db_store_name_exists(mock_store_name_exists_db_port_false(IS_NEVER_CALLED))
.build()
.unwrap();
assert_eq!(
s.update_store(cmd.clone()).await,
Err(InventoryError::StoreIDNotFound)
);
}
}