diff --git a/src/identity/adapters/input/web/errors.rs b/src/identity/adapters/input/web/errors.rs index 338608f..2fc271d 100644 --- a/src/identity/adapters/input/web/errors.rs +++ b/src/identity/adapters/input/web/errors.rs @@ -50,6 +50,7 @@ pub enum WebError { DuplicateRoleID, DuplicateRoleName, RoleIDNotFound, + RoleNotFound, } impl From for WebError { @@ -77,6 +78,7 @@ impl From for WebError { IdentityError::DuplicateRoleID => Self::DuplicateRoleID, IdentityError::DuplicateRoleName => Self::DuplicateRoleName, IdentityError::RoleIDNotFound => Self::RoleIDNotFound, + IdentityError::RoleNotFound => Self::RoleNotFound, } } } @@ -108,6 +110,7 @@ impl ResponseError for WebError { Self::DuplicateRoleID => StatusCode::INTERNAL_SERVER_ERROR, Self::DuplicateRoleName => StatusCode::BAD_REQUEST, Self::RoleIDNotFound => StatusCode::BAD_REQUEST, + Self::RoleNotFound => StatusCode::NOT_FOUND, } } @@ -139,6 +142,7 @@ impl ResponseError for WebError { Self::DuplicateRoleID => HttpResponse::InternalServerError().json(e), Self::DuplicateRoleName => HttpResponse::BadRequest().json(e), Self::RoleIDNotFound => HttpResponse::BadRequest().json(e), + Self::RoleNotFound => HttpResponse::NotFound().json(e), } } } diff --git a/src/identity/adapters/output/db/postgres/employee_view.rs b/src/identity/adapters/output/db/postgres/employee_view.rs index 7638f7e..f8c3cdd 100644 --- a/src/identity/adapters/output/db/postgres/employee_view.rs +++ b/src/identity/adapters/output/db/postgres/employee_view.rs @@ -117,6 +117,14 @@ impl View for EmployeeView { self.store_id = None; self.role_id = None; } + IdentityEvent::RoleAdded(e) => { + self.store_id = Some(*e.store_id()); + self.role_id = Some(*e.role_id()); + } + IdentityEvent::EmployeeRemovedFromRole(e) => { + self.role_id = None; + } + _ => (), } } diff --git a/src/identity/application/services/errors.rs b/src/identity/application/services/errors.rs index e4d9080..613cd35 100644 --- a/src/identity/application/services/errors.rs +++ b/src/identity/application/services/errors.rs @@ -35,6 +35,7 @@ pub enum IdentityError { DuplicateRoleID, DuplicateRoleName, RoleIDNotFound, + RoleNotFound, } pub type IdentityCommandResult = Result; diff --git a/src/identity/application/services/events.rs b/src/identity/application/services/events.rs index e2435c0..d745d15 100644 --- a/src/identity/application/services/events.rs +++ b/src/identity/application/services/events.rs @@ -12,7 +12,8 @@ use super::update_email::events::*; use super::update_password::events::*; use crate::identity::domain::{ - employee_logged_in_event::*, employee_registered_event::*, login_otp_sent_event::*, + employee_logged_in_event::*, employee_registered_event::*, + employee_removed_from_role::EmployeeRemovedFromRoleEvent, login_otp_sent_event::*, organization_exited_event::*, owner_added_employee_to_store_event::*, owner_removed_employee_from_store_event::*, phone_number_changed_event::*, phone_number_verified_event::*, resend_login_otp_event::*, role_added_event::*, @@ -33,6 +34,7 @@ pub enum IdentityEvent { OwnerAddedEmployeeToStore(OwnerAddedEmployeeToStoreEvent), OwnerRemovedEmployeeFromStore(OwnerRemovedEmployeeFromStoreEvent), RoleAdded(RoleAddedEvent), + EmployeeRemovedFromRole(EmployeeRemovedFromRoleEvent), // employee EmployeeRegistered(EmployeeRegisteredEvent), @@ -73,6 +75,7 @@ impl DomainEvent for IdentityEvent { "IdentityOwnerRemovedEmployeeFromStore" } IdentityEvent::RoleAdded { .. } => "IdentityRoleAddedEvent", + IdentityEvent::EmployeeRemovedFromRole { .. } => "IdentityEmployeeRemovedFromRole", // employee IdentityEvent::EmployeeRegistered { .. } => "EmployeeRegistered", IdentityEvent::EmployeeLoggedIn { .. } => "EmployeeLoggedIn", diff --git a/src/identity/application/services/mod.rs b/src/identity/application/services/mod.rs index 16adf7e..81b23c5 100644 --- a/src/identity/application/services/mod.rs +++ b/src/identity/application/services/mod.rs @@ -67,6 +67,7 @@ use crate::identity::domain::{ exit_organization_command::*, owner_add_employee_to_store_command::*, owner_remove_employee_from_store_command::*, + remove_employee_from_role_command::*, resend_login_otp_command::*, resend_verification_otp_command::*, update_store_command::*, @@ -113,6 +114,8 @@ pub enum IdentityCommand { OwnerAddEmployeeToStore(OwnerAddEmployeeToStoreCommand), OwnerRemoveEmployeeFromStore(OwnerRemoveEmployeeFromStoreCommand), AddRole(AddRoleCommand), + RemoveEmployeeFromRole(RemoveEmployeeFromRoleCommand), + // employee EmployeeRegister(EmployeeRegisterCommand), EmployeeInitLogin(EmployeeInitLoginCommand), @@ -327,6 +330,8 @@ impl IdentityServices { OwnerManageStoreEmployeesServiceBuilder::default() .db_store_id_exists_adapter(out_db_store_id_exists.clone()) .db_emp_id_exists_adapter(out_db_emp_id_exists.clone()) + .db_role_id_exists_adapter(out_db_role_id_exists.clone()) + .db_role_name_exists_for_store_adapter(out_db_role_name_exists_for_store.clone()) .build() .unwrap(), ); diff --git a/src/identity/application/services/owner_manage_store_employee_service.rs b/src/identity/application/services/owner_manage_store_employee_service.rs index 65200ab..80535fc 100644 --- a/src/identity/application/services/owner_manage_store_employee_service.rs +++ b/src/identity/application/services/owner_manage_store_employee_service.rs @@ -5,10 +5,14 @@ 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::application::port::output::db::{ + emp_id_exists::*, role_id_exists::*, role_name_exists_for_store::*, store_id_exists::*, +}; use crate::identity::domain::{ - owner_add_employee_to_store_command::*, owner_added_employee_to_store_event::*, - owner_remove_employee_from_store_command::*, owner_removed_employee_from_store_event::*, + employee_removed_from_role::*, owner_add_employee_to_store_command::*, + owner_added_employee_to_store_event::*, owner_remove_employee_from_store_command::*, + owner_removed_employee_from_store_event::*, remove_employee_from_role_command::*, + role_set_to_employee_event::*, set_role_to_employee_command::*, }; use super::errors::*; @@ -24,6 +28,14 @@ pub trait OwnerManageStoreEmployeesUseCase: Send + Sync { &self, cmd: OwnerRemoveEmployeeFromStoreCommand, ) -> IdentityResult; + async fn set_role_to_employee( + &self, + cmd: SetRoleToEmployeeCommand, + ) -> IdentityResult; + async fn remove_employee_from_role( + &self, + cmd: RemoveEmployeeFromRoleCommand, + ) -> IdentityResult; } pub type OwnerManageStoreEmployeesServiceObj = std::sync::Arc; @@ -32,6 +44,8 @@ pub type OwnerManageStoreEmployeesServiceObj = std::sync::Arc IdentityResult { + if !self + .db_store_id_exists_adapter + .store_id_exists(cmd.store_id()) + .await? + { + return Err(IdentityError::StoreNotFound); + } + + if !self + .db_emp_id_exists_adapter + .emp_id_exists(cmd.emp_id()) + .await? + { + return Err(IdentityError::EmployeeNotFound); + } + + if !self + .db_role_id_exists_adapter + .role_id_exists(cmd.role().role_id()) + .await? + { + return Err(IdentityError::RoleIDNotFound); + } + + if !self + .db_role_name_exists_for_store_adapter + .role_name_exists_for_store(cmd.role()) + .await? + { + return Err(IdentityError::RoleNotFound); + } + + Ok(RoleSetToEmployeeEventBuilder::default() + .emp_id(*cmd.emp_id()) + .store_id(*cmd.store_id()) + .added_by(*cmd.adding_by()) + .role(cmd.role().clone()) + .build() + .unwrap()) + } + + async fn remove_employee_from_role( + &self, + cmd: RemoveEmployeeFromRoleCommand, + ) -> IdentityResult { + if !self + .db_store_id_exists_adapter + .store_id_exists(cmd.store_id()) + .await? + { + return Err(IdentityError::StoreNotFound); + } + + if !self + .db_emp_id_exists_adapter + .emp_id_exists(cmd.employee().emp_id()) + .await? + { + return Err(IdentityError::EmployeeNotFound); + } + + if cmd.employee().role_id() != &Some(*cmd.role().role_id()) { + return Err(IdentityError::RoleNotFound); + } + + if !self + .db_role_id_exists_adapter + .role_id_exists(cmd.role().role_id()) + .await? + { + return Err(IdentityError::RoleIDNotFound); + } + + if !self + .db_role_name_exists_for_store_adapter + .role_name_exists_for_store(cmd.role()) + .await? + { + return Err(IdentityError::RoleNotFound); + } + + Ok(EmployeeRemovedFromRoleEventBuilder::default() + .emp_id(*cmd.employee().emp_id()) + .store_id(*cmd.store_id()) + .added_by(*cmd.adding_by()) + .role(cmd.role().clone()) + .build() + .unwrap()) + } } #[cfg(test)] mod tests { - use crate::{tests::bdd::*, utils::uuid::tests::*}; + use crate::{ + identity::domain::employee_aggregate::Employee, tests::bdd::*, utils::uuid::tests::*, + }; use super::*; @@ -125,16 +235,15 @@ mod tests { let s = OwnerManageStoreEmployeesServiceBuilder::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)) + .db_role_id_exists_adapter(mock_role_id_exists_db_port_true(IS_NEVER_CALLED)) + .db_role_name_exists_for_store_adapter(mock_role_name_exists_for_store_db_port_true( + IS_NEVER_CALLED, + )) .build() .unwrap(); { - let cmd = OwnerAddEmployeeToStoreCommandBuilder::default() - .emp_id(UUID) - .store_id(UUID) - .adding_by(UUID) - .build() - .unwrap(); + let cmd = OwnerAddEmployeeToStoreCommand::get_cmd(); let res = s.add_employee_to_store(cmd.clone()).await.unwrap(); assert_eq!(*res.emp_id(), *cmd.emp_id()); @@ -148,16 +257,15 @@ mod tests { let s = OwnerManageStoreEmployeesServiceBuilder::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_CALLED_ONLY_ONCE)) + .db_role_id_exists_adapter(mock_role_id_exists_db_port_false(IS_NEVER_CALLED)) + .db_role_name_exists_for_store_adapter(mock_role_name_exists_for_store_db_port_true( + IS_NEVER_CALLED, + )) .build() .unwrap(); { - let cmd = OwnerAddEmployeeToStoreCommandBuilder::default() - .emp_id(UUID) - .adding_by(UUID) - .store_id(UUID) - .build() - .unwrap(); + let cmd = OwnerAddEmployeeToStoreCommand::get_cmd(); assert_eq!( s.add_employee_to_store(cmd.clone()).await.err(), @@ -166,11 +274,38 @@ mod tests { } } + #[actix_rt::test] + async fn test_service_add_employee_store_no_exist() { + let s = OwnerManageStoreEmployeesServiceBuilder::default() + .db_emp_id_exists_adapter(mock_emp_id_exists_db_port(IS_NEVER_CALLED, false)) + .db_store_id_exists_adapter(mock_store_id_exists_db_port_false(IS_CALLED_ONLY_ONCE)) + .db_role_id_exists_adapter(mock_role_id_exists_db_port_false(IS_NEVER_CALLED)) + .db_role_name_exists_for_store_adapter(mock_role_name_exists_for_store_db_port_true( + IS_NEVER_CALLED, + )) + .build() + .unwrap(); + + { + let cmd = OwnerAddEmployeeToStoreCommand::get_cmd(); + + assert_eq!( + s.add_employee_to_store(cmd.clone()).await.err(), + Some(IdentityError::StoreNotFound) + ); + } + } + + // remove employee #[actix_rt::test] async fn test_service_remove_employee() { let s = OwnerManageStoreEmployeesServiceBuilder::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)) + .db_role_id_exists_adapter(mock_role_id_exists_db_port_false(IS_NEVER_CALLED)) + .db_role_name_exists_for_store_adapter(mock_role_name_exists_for_store_db_port_true( + IS_NEVER_CALLED, + )) .build() .unwrap(); @@ -189,6 +324,10 @@ mod tests { let s = OwnerManageStoreEmployeesServiceBuilder::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_CALLED_ONLY_ONCE)) + .db_role_id_exists_adapter(mock_role_id_exists_db_port_false(IS_NEVER_CALLED)) + .db_role_name_exists_for_store_adapter(mock_role_name_exists_for_store_db_port_true( + IS_NEVER_CALLED, + )) .build() .unwrap(); @@ -201,4 +340,259 @@ mod tests { ); } } + + #[actix_rt::test] + async fn test_service_remove_employee_store_no_exist() { + let s = OwnerManageStoreEmployeesServiceBuilder::default() + .db_emp_id_exists_adapter(mock_emp_id_exists_db_port(IS_NEVER_CALLED, true)) + .db_store_id_exists_adapter(mock_store_id_exists_db_port_false(IS_CALLED_ONLY_ONCE)) + .db_role_id_exists_adapter(mock_role_id_exists_db_port_false(IS_NEVER_CALLED)) + .db_role_name_exists_for_store_adapter(mock_role_name_exists_for_store_db_port_true( + IS_NEVER_CALLED, + )) + .build() + .unwrap(); + + { + let cmd = OwnerRemoveEmployeeFromStoreCommand::get_cmd(); + + assert_eq!( + s.remove_employee_from_store(cmd.clone()).await.err(), + Some(IdentityError::StoreNotFound) + ); + } + } + + // set role to employee + #[actix_rt::test] + async fn test_service_set_role_to_employee() { + let s = OwnerManageStoreEmployeesServiceBuilder::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)) + .db_role_id_exists_adapter(mock_role_id_exists_db_port_true(IS_CALLED_ONLY_ONCE)) + .db_role_name_exists_for_store_adapter(mock_role_name_exists_for_store_db_port_true( + IS_CALLED_ONLY_ONCE, + )) + .build() + .unwrap(); + + { + let cmd = SetRoleToEmployeeCommand::get_cmd(); + + let res = s.set_role_to_employee(cmd.clone()).await.unwrap(); + + assert_eq!(cmd.emp_id(), res.emp_id()); + assert_eq!(cmd.adding_by(), res.added_by()); + assert_eq!(cmd.store_id(), res.store_id()); + assert_eq!(cmd.role(), res.role()); + } + } + + #[actix_rt::test] + async fn test_service_set_role_to_employee_store_no_exist() { + let s = OwnerManageStoreEmployeesServiceBuilder::default() + .db_emp_id_exists_adapter(mock_emp_id_exists_db_port(IS_NEVER_CALLED, true)) + .db_store_id_exists_adapter(mock_store_id_exists_db_port_false(IS_CALLED_ONLY_ONCE)) + .db_role_id_exists_adapter(mock_role_id_exists_db_port_true(IS_NEVER_CALLED)) + .db_role_name_exists_for_store_adapter(mock_role_name_exists_for_store_db_port_true( + IS_NEVER_CALLED, + )) + .build() + .unwrap(); + + { + let cmd = SetRoleToEmployeeCommand::get_cmd(); + + assert_eq!( + s.set_role_to_employee(cmd.clone()).await.err(), + Some(IdentityError::StoreNotFound) + ); + } + } + + #[actix_rt::test] + async fn test_service_set_role_to_employee_role_id_no_exist() { + let s = OwnerManageStoreEmployeesServiceBuilder::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)) + .db_role_id_exists_adapter(mock_role_id_exists_db_port_false(IS_CALLED_ONLY_ONCE)) + .db_role_name_exists_for_store_adapter(mock_role_name_exists_for_store_db_port_true( + IS_NEVER_CALLED, + )) + .build() + .unwrap(); + + { + let cmd = SetRoleToEmployeeCommand::get_cmd(); + + assert_eq!( + s.set_role_to_employee(cmd.clone()).await.err(), + Some(IdentityError::RoleIDNotFound) + ); + } + } + + #[actix_rt::test] + async fn test_service_set_role_to_employee_role_name_no_exist_for_store() { + let s = OwnerManageStoreEmployeesServiceBuilder::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)) + .db_role_id_exists_adapter(mock_role_id_exists_db_port_true(IS_CALLED_ONLY_ONCE)) + .db_role_name_exists_for_store_adapter(mock_role_name_exists_for_store_db_port_false( + IS_CALLED_ONLY_ONCE, + )) + .build() + .unwrap(); + + { + let cmd = SetRoleToEmployeeCommand::get_cmd(); + + assert_eq!( + s.set_role_to_employee(cmd.clone()).await.err(), + Some(IdentityError::RoleNotFound) + ); + } + } + + // remove employee from role + #[actix_rt::test] + async fn test_service_remove_employee_from_role() { + let s = OwnerManageStoreEmployeesServiceBuilder::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)) + .db_role_id_exists_adapter(mock_role_id_exists_db_port_true(IS_CALLED_ONLY_ONCE)) + .db_role_name_exists_for_store_adapter(mock_role_name_exists_for_store_db_port_true( + IS_CALLED_ONLY_ONCE, + )) + .build() + .unwrap(); + + { + let cmd = RemoveEmployeeFromRoleCommand::get_cmd(); + + let res = s.remove_employee_from_role(cmd.clone()).await.unwrap(); + + assert_eq!(cmd.employee().emp_id(), res.emp_id()); + assert_eq!(cmd.adding_by(), res.added_by()); + assert_eq!(cmd.store_id(), res.store_id()); + assert_eq!(cmd.role(), res.role()); + } + } + + #[actix_rt::test] + async fn test_service_remove_employee_from_role_no_store() { + let s = OwnerManageStoreEmployeesServiceBuilder::default() + .db_emp_id_exists_adapter(mock_emp_id_exists_db_port(IS_NEVER_CALLED, true)) + .db_store_id_exists_adapter(mock_store_id_exists_db_port_false(IS_CALLED_ONLY_ONCE)) + .db_role_id_exists_adapter(mock_role_id_exists_db_port_true(IS_NEVER_CALLED)) + .db_role_name_exists_for_store_adapter(mock_role_name_exists_for_store_db_port_true( + IS_NEVER_CALLED, + )) + .build() + .unwrap(); + + { + let cmd = RemoveEmployeeFromRoleCommand::get_cmd(); + + assert_eq!( + s.remove_employee_from_role(cmd.clone()).await.err(), + Some(IdentityError::StoreNotFound) + ); + } + } + + #[actix_rt::test] + async fn test_service_remove_employee_from_role_no_employee() { + let s = OwnerManageStoreEmployeesServiceBuilder::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_CALLED_ONLY_ONCE)) + .db_role_id_exists_adapter(mock_role_id_exists_db_port_true(IS_NEVER_CALLED)) + .db_role_name_exists_for_store_adapter(mock_role_name_exists_for_store_db_port_true( + IS_NEVER_CALLED, + )) + .build() + .unwrap(); + + { + let cmd = RemoveEmployeeFromRoleCommand::get_cmd(); + + assert_eq!( + s.remove_employee_from_role(cmd.clone()).await.err(), + Some(IdentityError::EmployeeNotFound) + ); + } + } + + #[actix_rt::test] + async fn test_service_remove_employee_from_role_unremovable_role() { + let s = OwnerManageStoreEmployeesServiceBuilder::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)) + .db_role_id_exists_adapter(mock_role_id_exists_db_port_false(IS_NEVER_CALLED)) + .db_role_name_exists_for_store_adapter(mock_role_name_exists_for_store_db_port_true( + IS_NEVER_CALLED, + )) + .build() + .unwrap(); + + { + let cmd = RemoveEmployeeFromRoleCommand::get_cmd(); + let cmd = RemoveEmployeeFromRoleCommandBuilder::default() + .role(cmd.role().clone()) + .store_id(*cmd.store_id()) + .adding_by(*cmd.adding_by()) + .employee(Employee::default()) + .build() + .unwrap(); + + assert_eq!( + s.remove_employee_from_role(cmd.clone()).await.err(), + Some(IdentityError::RoleNotFound) + ); + } + } + + #[actix_rt::test] + async fn test_service_remove_employee_from_role_no_role() { + let s = OwnerManageStoreEmployeesServiceBuilder::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)) + .db_role_id_exists_adapter(mock_role_id_exists_db_port_false(IS_CALLED_ONLY_ONCE)) + .db_role_name_exists_for_store_adapter(mock_role_name_exists_for_store_db_port_true( + IS_NEVER_CALLED, + )) + .build() + .unwrap(); + + { + let cmd = RemoveEmployeeFromRoleCommand::get_cmd(); + + assert_eq!( + s.remove_employee_from_role(cmd.clone()).await.err(), + Some(IdentityError::RoleIDNotFound) + ); + } + } + + #[actix_rt::test] + async fn test_service_remove_employee_from_role_no_role_for_store() { + let s = OwnerManageStoreEmployeesServiceBuilder::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)) + .db_role_id_exists_adapter(mock_role_id_exists_db_port_true(IS_CALLED_ONLY_ONCE)) + .db_role_name_exists_for_store_adapter(mock_role_name_exists_for_store_db_port_false( + IS_CALLED_ONLY_ONCE, + )) + .build() + .unwrap(); + + { + let cmd = RemoveEmployeeFromRoleCommand::get_cmd(); + + assert_eq!( + s.remove_employee_from_role(cmd.clone()).await.err(), + Some(IdentityError::RoleNotFound) + ); + } + } } diff --git a/src/identity/domain/employee_aggregate.rs b/src/identity/domain/employee_aggregate.rs index d0364fa..3089584 100644 --- a/src/identity/domain/employee_aggregate.rs +++ b/src/identity/domain/employee_aggregate.rs @@ -171,6 +171,14 @@ impl Aggregate for Employee { self.store_id = None; self.role_id = None; } + IdentityEvent::RoleAdded(e) => { + self.store_id = Some(*e.store_id()); + self.role_id = Some(*e.role_id()); + } + IdentityEvent::EmployeeRemovedFromRole(e) => { + self.role_id = None; + } + _ => (), } } diff --git a/src/identity/domain/employee_removed_from_role.rs b/src/identity/domain/employee_removed_from_role.rs new file mode 100644 index 0000000..1e0dbb2 --- /dev/null +++ b/src/identity/domain/employee_removed_from_role.rs @@ -0,0 +1,40 @@ +// SPDX-FileCopyrightText: 2024 Aravinth Manivannan +// +// 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::role_aggregate::*; + +#[derive( + Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Ord, PartialOrd, Getters, Builder, +)] +pub struct EmployeeRemovedFromRoleEvent { + emp_id: Uuid, + added_by: Uuid, + store_id: Uuid, + role: Role, +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + identity::domain::remove_employee_from_role_command::RemoveEmployeeFromRoleCommand, + utils::uuid::tests::UUID, + }; + + impl EmployeeRemovedFromRoleEvent { + pub fn get_event(cmd: &RemoveEmployeeFromRoleCommand) -> Self { + Self { + emp_id: *cmd.employee().emp_id(), + added_by: *cmd.adding_by(), + store_id: *cmd.store_id(), + role: cmd.role().clone(), + } + } + } +} diff --git a/src/identity/domain/mod.rs b/src/identity/domain/mod.rs index 5c1af8b..27d42b5 100644 --- a/src/identity/domain/mod.rs +++ b/src/identity/domain/mod.rs @@ -13,6 +13,7 @@ pub mod store_aggregate; pub mod employee_logged_in_event; pub mod employee_registered_event; //pub mod invite_accepted_event; +pub mod employee_removed_from_role; pub mod login_otp_sent_event; pub mod organization_exited_event; pub mod owner_added_employee_to_store_event; @@ -21,6 +22,7 @@ pub mod phone_number_changed_event; pub mod phone_number_verified_event; pub mod resend_login_otp_event; pub mod role_added_event; +pub mod role_set_to_employee_event; pub mod store_added_event; pub mod store_updated_event; pub mod verification_otp_resent_event; @@ -36,7 +38,9 @@ pub mod employee_register_command; pub mod exit_organization_command; pub mod owner_add_employee_to_store_command; pub mod owner_remove_employee_from_store_command; +pub mod remove_employee_from_role_command; pub mod resend_login_otp_command; pub mod resend_verification_otp_command; +pub mod set_role_to_employee_command; pub mod update_store_command; pub mod verify_phone_number_command; diff --git a/src/identity/domain/remove_employee_from_role_command.rs b/src/identity/domain/remove_employee_from_role_command.rs new file mode 100644 index 0000000..fb9b979 --- /dev/null +++ b/src/identity/domain/remove_employee_from_role_command.rs @@ -0,0 +1,53 @@ +// SPDX-FileCopyrightText: 2024 Aravinth Manivannan +// +// 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::employee_aggregate::*; +use super::role_aggregate::Role; + +#[derive( + Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Ord, PartialOrd, Getters, Builder, +)] +pub struct RemoveEmployeeFromRoleCommand { + adding_by: Uuid, + store_id: Uuid, + role: Role, + employee: Employee, +} + +#[cfg(test)] +pub mod tests { + use crate::utils::uuid::tests::UUID; + + use super::*; + + impl RemoveEmployeeFromRoleCommand { + pub fn get_cmd() -> Self { + let role = Role::default(); + let employee = Employee::default(); + let employee = EmployeeBuilder::default() + .first_name(employee.first_name().clone()) + .last_name(employee.last_name().clone()) + .emp_id(*employee.emp_id()) + .phone_number(employee.phone_number().clone()) + .phone_verified(employee.phone_verified().clone()) + .store_id(Some(UUID)) + .deleted(false) + .role_id(Some(*role.role_id())) + .build() + .unwrap(); + + Self { + adding_by: UUID, + store_id: UUID, + role, + employee, + } + } + } +} diff --git a/src/identity/domain/role_set_to_employee_event.rs b/src/identity/domain/role_set_to_employee_event.rs new file mode 100644 index 0000000..f1a403f --- /dev/null +++ b/src/identity/domain/role_set_to_employee_event.rs @@ -0,0 +1,40 @@ +// SPDX-FileCopyrightText: 2024 Aravinth Manivannan +// +// 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::role_aggregate::*; + +#[derive( + Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Ord, PartialOrd, Getters, Builder, +)] +pub struct RoleSetToEmployeeEvent { + emp_id: Uuid, + added_by: Uuid, + store_id: Uuid, + role: Role, +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + identity::domain::set_role_to_employee_command::SetRoleToEmployeeCommand, + utils::uuid::tests::UUID, + }; + + impl RoleSetToEmployeeEvent { + pub fn get_event(cmd: &SetRoleToEmployeeCommand) -> Self { + Self { + emp_id: *cmd.emp_id(), + added_by: *cmd.adding_by(), + store_id: *cmd.store_id(), + role: cmd.role().clone(), + } + } + } +} diff --git a/src/identity/domain/set_role_to_employee_command.rs b/src/identity/domain/set_role_to_employee_command.rs new file mode 100644 index 0000000..32124aa --- /dev/null +++ b/src/identity/domain/set_role_to_employee_command.rs @@ -0,0 +1,39 @@ +// SPDX-FileCopyrightText: 2024 Aravinth Manivannan +// +// 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::employee_aggregate::*; +use super::role_aggregate::Role; + +#[derive( + Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Ord, PartialOrd, Getters, Builder, +)] +pub struct SetRoleToEmployeeCommand { + adding_by: Uuid, + emp_id: Uuid, + store_id: Uuid, + role: Role, +} + +#[cfg(test)] +pub mod tests { + use crate::utils::uuid::tests::UUID; + + use super::*; + + impl SetRoleToEmployeeCommand { + pub fn get_cmd() -> Self { + Self { + emp_id: UUID, + adding_by: UUID, + store_id: UUID, + role: Role::default(), + } + } + } +}