// SPDX-FileCopyrightText: 2024 Aravinth Manivannan // // SPDX-License-Identifier: AGPL-3.0-or-later use derive_builder::Builder; use mockall::predicate::*; use mockall::*; use crate::identity::application::port::output::db::{emp_id_exists::*, store_id_exists::*}; use crate::identity::domain::{exit_organization_command::*, organization_exited_event::*}; use super::errors::*; #[automock] #[async_trait::async_trait] pub trait EmployeeExitOrganizationUseCase: Send + Sync { async fn exit_organization( &self, cmd: ExitOrganizationCommand, ) -> IdentityResult; } pub type EmployeeExitOrganizationServiceObj = std::sync::Arc; #[derive(Clone, Builder)] pub struct EmployeeExitOrganizationService { db_emp_id_exists_adapter: EmpIDExistsOutDBPortObj, db_store_id_exists_adapter: StoreIDExistsDBPortObj, } #[async_trait::async_trait] impl EmployeeExitOrganizationUseCase for EmployeeExitOrganizationService { async fn exit_organization( &self, cmd: ExitOrganizationCommand, ) -> IdentityResult { if !self .db_emp_id_exists_adapter .emp_id_exists(cmd.emp_id()) .await? { return Err(IdentityError::EmployeeNotFound); } if !self .db_store_id_exists_adapter .store_id_exists(cmd.emp_id()) .await? { return Err(IdentityError::StoreNotFound); } Ok(OrganizationExitedEventBuilder::default() .emp_id(*cmd.emp_id()) .store_id(*cmd.store_id()) .build() .unwrap()) } } #[cfg(test)] mod tests { use crate::{tests::bdd::*, utils::uuid::tests::*}; use super::*; impl EmployeeExitOrganizationService { pub fn mock_service( times: Option, cmd: ExitOrganizationCommand, ) -> EmployeeExitOrganizationServiceObj { let res = OrganizationExitedEvent::get_event(&cmd); let mut m = MockEmployeeExitOrganizationUseCase::default(); if let Some(times) = times { m.expect_exit_organization() .times(times) .returning(move |_| Ok(res.clone())); } else { m.expect_exit_organization() .returning(move |_| Ok(res.clone())); } std::sync::Arc::new(m) } } #[actix_rt::test] async fn test_service() { let s = EmployeeExitOrganizationServiceBuilder::default() .db_emp_id_exists_adapter(mock_emp_id_exists_db_port(IS_CALLED_ONLY_ONCE, true)) .db_store_id_exists_adapter(mock_store_id_exists_db_port_true(IS_CALLED_ONLY_ONCE)) .build() .unwrap(); { let cmd = ExitOrganizationCommandBuilder::default() .emp_id(UUID) .store_id(UUID) .build() .unwrap(); let res = s.exit_organization(cmd.clone()).await.unwrap(); assert_eq!(*res.emp_id(), UUID); assert_eq!(*res.store_id(), UUID); } } #[actix_rt::test] async fn test_service_store_no_exist() { let s = EmployeeExitOrganizationServiceBuilder::default() .db_emp_id_exists_adapter(mock_emp_id_exists_db_port(IS_CALLED_ONLY_ONCE, true)) .db_store_id_exists_adapter(mock_store_id_exists_db_port_false(IS_CALLED_ONLY_ONCE)) .build() .unwrap(); { let cmd = ExitOrganizationCommandBuilder::default() .emp_id(UUID) .store_id(UUID) .build() .unwrap(); assert_eq!( s.exit_organization(cmd.clone()).await.err(), Some(IdentityError::StoreNotFound) ); } } #[actix_rt::test] async fn test_service_emp_no_exist() { let s = EmployeeExitOrganizationServiceBuilder::default() .db_emp_id_exists_adapter(mock_emp_id_exists_db_port(IS_CALLED_ONLY_ONCE, false)) .db_store_id_exists_adapter(mock_store_id_exists_db_port_true(IS_NEVER_CALLED)) .build() .unwrap(); { let cmd = ExitOrganizationCommandBuilder::default() .emp_id(UUID) .store_id(UUID) .build() .unwrap(); assert_eq!( s.exit_organization(cmd.clone()).await.err(), Some(IdentityError::EmployeeNotFound) ); } } }