feat: identity: add&rm employee to store
This commit is contained in:
parent
3595560058
commit
9d20e45489
13 changed files with 501 additions and 19 deletions
|
@ -47,6 +47,9 @@ pub enum WebError {
|
|||
DuplicateStoreName,
|
||||
StoreIDNotFound,
|
||||
DuplicateStoreID,
|
||||
DuplicateRoleID,
|
||||
DuplicateRoleName,
|
||||
RoleIDNotFound,
|
||||
}
|
||||
|
||||
impl From<IdentityError> for WebError {
|
||||
|
@ -71,6 +74,9 @@ impl From<IdentityError> for WebError {
|
|||
IdentityError::DuplicateStoreName => Self::DuplicateStoreName,
|
||||
IdentityError::StoreIDNotFound => Self::StoreIDNotFound,
|
||||
IdentityError::DuplicateStoreID => Self::DuplicateStoreID,
|
||||
IdentityError::DuplicateRoleID => Self::DuplicateRoleID,
|
||||
IdentityError::DuplicateRoleName => Self::DuplicateRoleName,
|
||||
IdentityError::RoleIDNotFound => Self::RoleIDNotFound,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -99,6 +105,9 @@ impl ResponseError for WebError {
|
|||
Self::DuplicateStoreName => StatusCode::BAD_REQUEST,
|
||||
Self::StoreIDNotFound => StatusCode::NOT_FOUND,
|
||||
Self::DuplicateStoreID => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
Self::DuplicateRoleID => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
Self::DuplicateRoleName => StatusCode::BAD_REQUEST,
|
||||
Self::RoleIDNotFound => StatusCode::BAD_REQUEST,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,6 +136,9 @@ impl ResponseError for WebError {
|
|||
Self::DuplicateStoreName => HttpResponse::BadRequest().json(e),
|
||||
Self::StoreIDNotFound => HttpResponse::NotFound().json(e),
|
||||
Self::DuplicateStoreID => HttpResponse::InternalServerError().json(e),
|
||||
Self::DuplicateRoleID => HttpResponse::InternalServerError().json(e),
|
||||
Self::DuplicateRoleName => HttpResponse::BadRequest().json(e),
|
||||
Self::RoleIDNotFound => HttpResponse::BadRequest().json(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,11 +11,13 @@ use sqlx::postgres::PgPool;
|
|||
|
||||
use crate::identity::{
|
||||
application::services::{IdentityServices, IdentityServicesObj},
|
||||
domain::{aggregate::User, employee_aggregate::Employee, store_aggregate::Store},
|
||||
domain::{
|
||||
aggregate::User, employee_aggregate::Employee, role_aggregate::Role, store_aggregate::Store,
|
||||
},
|
||||
};
|
||||
use crate::settings::Settings;
|
||||
use output::{
|
||||
db::postgres::{employee_view, store_view, user_view, DBOutPostgresAdapter},
|
||||
db::postgres::{employee_view, role_view, store_view, user_view, DBOutPostgresAdapter},
|
||||
mailer::lettre::LettreMailer,
|
||||
phone::twilio::Phone,
|
||||
};
|
||||
|
@ -48,6 +50,8 @@ pub fn load_adapters(pool: PgPool, settings: Settings) -> impl FnOnce(&mut web::
|
|||
Arc::new(db.clone()),
|
||||
Arc::new(db.clone()),
|
||||
Arc::new(db.clone()),
|
||||
Arc::new(db.clone()),
|
||||
Arc::new(db.clone()),
|
||||
Arc::new(mailer.clone()),
|
||||
Arc::new(phone.clone()),
|
||||
Arc::new(phone.clone()),
|
||||
|
@ -60,11 +64,13 @@ pub fn load_adapters(pool: PgPool, settings: Settings) -> impl FnOnce(&mut web::
|
|||
let (store_cqrs_exec, store_cqrs_query) = store_view::init_cqrs(db.clone(), services.clone());
|
||||
let (employee_cqrs_exec, employee_cqrs_query) =
|
||||
employee_view::init_cqrs(db.clone(), services.clone());
|
||||
let (role_cqrs_exec, role_cqrs_query) = role_view::init_cqrs(db.clone(), services.clone());
|
||||
|
||||
let identity_cqrs_exec = types::WebIdentityCqrsExec::new(Arc::new(
|
||||
types::IdentityCqrsExecBuilder::default()
|
||||
.user(user_cqrs_exec)
|
||||
.employee(employee_cqrs_exec)
|
||||
.role(role_cqrs_exec)
|
||||
.store(store_cqrs_exec)
|
||||
.build()
|
||||
.unwrap(),
|
||||
|
@ -74,6 +80,7 @@ pub fn load_adapters(pool: PgPool, settings: Settings) -> impl FnOnce(&mut web::
|
|||
cfg.configure(input::web::load_ctx());
|
||||
|
||||
cfg.app_data(Data::new(user_cqrs_query.clone()));
|
||||
cfg.app_data(Data::new(role_cqrs_query.clone()));
|
||||
cfg.app_data(Data::new(store_cqrs_query.clone()));
|
||||
cfg.app_data(Data::new(employee_cqrs_query.clone()));
|
||||
cfg.app_data(identity_cqrs_exec.clone());
|
||||
|
|
|
@ -17,12 +17,14 @@ use crate::identity::{
|
|||
adapters::{
|
||||
input::web::RoutesRepository,
|
||||
output::db::postgres::{
|
||||
employee_view::EmployeeView, store_view::StoreView, user_view::UserView,
|
||||
DBOutPostgresAdapter,
|
||||
employee_view::EmployeeView, role_view::RoleView, store_view::StoreView,
|
||||
user_view::UserView, DBOutPostgresAdapter,
|
||||
},
|
||||
},
|
||||
application::services::{errors::IdentityError, IdentityCommand, IdentityServicesObj},
|
||||
domain::{aggregate::User, employee_aggregate::Employee, store_aggregate::Store},
|
||||
domain::{
|
||||
aggregate::User, employee_aggregate::Employee, role_aggregate::Role, store_aggregate::Store,
|
||||
},
|
||||
};
|
||||
|
||||
pub type WebIdentityRoutesRepository = Data<Arc<RoutesRepository>>;
|
||||
|
@ -56,6 +58,7 @@ pub struct IdentityCqrsExec {
|
|||
user: IdentityUserCqrsExec,
|
||||
store: IdentityStoreCqrsExec,
|
||||
employee: IdentityEmployeeCqrsExec,
|
||||
role: IdentityRoleCqrsExec,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
|
@ -67,8 +70,13 @@ impl IdentityCqrsExecutor for IdentityCqrsExec {
|
|||
) -> Result<(), AggregateError<IdentityError>> {
|
||||
self.user.execute(aggregate_id, command.clone()).await?;
|
||||
self.store.execute(aggregate_id, command.clone()).await?;
|
||||
self.role.execute(aggregate_id, command.clone()).await?;
|
||||
self.employee.execute(aggregate_id, command).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub type IdentityRoleCqrsExec = Arc<PostgresCqrs<Role>>;
|
||||
pub type IdentityRoleCqrsView = Arc<dyn ViewRepository<RoleView, Role>>;
|
||||
pub type WebidentityRoleCqrsView = Data<IdentityRoleCqrsView>;
|
||||
|
|
|
@ -32,6 +32,9 @@ pub enum IdentityError {
|
|||
DuplicateStoreName,
|
||||
StoreIDNotFound,
|
||||
DuplicateStoreID,
|
||||
DuplicateRoleID,
|
||||
DuplicateRoleName,
|
||||
RoleIDNotFound,
|
||||
}
|
||||
|
||||
pub type IdentityCommandResult<V> = Result<V, IdentityCommandError>;
|
||||
|
@ -80,6 +83,8 @@ impl From<OutDBPortError> for IdentityError {
|
|||
OutDBPortError::DuplicateStoreName => Self::DuplicateStoreName,
|
||||
OutDBPortError::DuplicateStoreID => Self::DuplicateStoreID,
|
||||
OutDBPortError::StoreIDNotFound => Self::StoreIDNotFound,
|
||||
OutDBPortError::RoleIDNotFound => Self::RoleIDNotFound,
|
||||
OutDBPortError::DuplicateRoleName => Self::DuplicateRoleName,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,16 +12,11 @@ use super::update_email::events::*;
|
|||
use super::update_password::events::*;
|
||||
|
||||
use crate::identity::domain::{
|
||||
employee_logged_in_event::*,
|
||||
employee_registered_event::*, //invite_accepted_event::*,
|
||||
login_otp_sent_event::*,
|
||||
organization_exited_event::*,
|
||||
phone_number_changed_event::*,
|
||||
phone_number_verified_event::*,
|
||||
resend_login_otp_event::*,
|
||||
store_added_event::*,
|
||||
store_updated_event::*,
|
||||
verification_otp_resent_event::*,
|
||||
employee_logged_in_event::*, employee_registered_event::*, 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::*,
|
||||
store_added_event::*, store_updated_event::*, verification_otp_resent_event::*,
|
||||
verification_otp_sent_event::*,
|
||||
};
|
||||
|
||||
|
@ -35,6 +30,9 @@ pub enum IdentityEvent {
|
|||
UserVerified,
|
||||
VerificationEmailResent,
|
||||
UserPromotedToAdmin(UserPromotedToAdminEvent),
|
||||
OwnerAddedEmployeeToStore(OwnerAddedEmployeeToStoreEvent),
|
||||
OwnerRemovedEmployeeFromStore(OwnerRemovedEmployeeFromStoreEvent),
|
||||
RoleAdded(RoleAddedEvent),
|
||||
|
||||
// employee
|
||||
EmployeeRegistered(EmployeeRegisteredEvent),
|
||||
|
@ -70,6 +68,11 @@ impl DomainEvent for IdentityEvent {
|
|||
IdentityEvent::UserVerified => "IdentityUserIsVerified",
|
||||
IdentityEvent::UserPromotedToAdmin { .. } => "IdentityUserPromotedToAdmin",
|
||||
IdentityEvent::VerificationEmailResent => "IdentityVerficationEmailResent",
|
||||
IdentityEvent::OwnerAddedEmployeeToStore { .. } => "IdentityOwnerAddedEmployeeToStore",
|
||||
IdentityEvent::OwnerRemovedEmployeeFromStore { .. } => {
|
||||
"IdentityOwnerRemovedEmployeeFromStore"
|
||||
}
|
||||
IdentityEvent::RoleAdded { .. } => "IdentityRoleAddedEvent",
|
||||
// employee
|
||||
IdentityEvent::EmployeeRegistered { .. } => "EmployeeRegistered",
|
||||
IdentityEvent::EmployeeLoggedIn { .. } => "EmployeeLoggedIn",
|
||||
|
|
|
@ -11,6 +11,7 @@ use serde::{Deserialize, Serialize};
|
|||
|
||||
pub mod delete_user;
|
||||
//pub mod employee_accept_invite_service;
|
||||
pub mod add_role_to_store_service;
|
||||
pub mod employee_exit_organization_service;
|
||||
pub mod employee_login_service;
|
||||
pub mod employee_register_service;
|
||||
|
@ -21,11 +22,14 @@ pub mod errors;
|
|||
pub mod events;
|
||||
pub mod login;
|
||||
pub mod mark_user_verified;
|
||||
pub mod owner_manage_store_employee_service;
|
||||
pub mod register_user;
|
||||
pub mod resend_verification_email;
|
||||
pub mod set_user_admin;
|
||||
pub mod update_email;
|
||||
pub mod update_password;
|
||||
//pub mod owner_set_role_to_employee_service;
|
||||
//pub mod owner_remove_employee_from_role_service;
|
||||
|
||||
pub mod add_store_service;
|
||||
pub mod update_store_service;
|
||||
|
@ -33,6 +37,8 @@ pub mod update_store_service;
|
|||
use add_store_service::*;
|
||||
use delete_user::{service::*, *};
|
||||
//use employee_accept_invite_service::*;
|
||||
use add_role_to_store_service::*;
|
||||
use add_role_to_store_service::*;
|
||||
use employee_exit_organization_service::*;
|
||||
use employee_login_service::*;
|
||||
use employee_register_service::*;
|
||||
|
@ -52,12 +58,15 @@ use errors::*;
|
|||
use events::*;
|
||||
|
||||
use crate::identity::domain::{
|
||||
add_role_command::*,
|
||||
// accept_invite_command::*,
|
||||
add_store_command::*,
|
||||
change_phone_number_command::*,
|
||||
employee_login_command::*,
|
||||
employee_register_command::*,
|
||||
exit_organization_command::*,
|
||||
owner_add_employee_to_store_command::*,
|
||||
owner_remove_employee_from_store_command::*,
|
||||
resend_login_otp_command::*,
|
||||
resend_verification_otp_command::*,
|
||||
update_store_command::*,
|
||||
|
@ -71,6 +80,7 @@ use crate::utils::{
|
|||
use delete_user::command::*;
|
||||
use login::command::*;
|
||||
use mark_user_verified::command::*;
|
||||
use owner_manage_store_employee_service::*;
|
||||
use register_user::command::*;
|
||||
use resend_verification_email::command::*;
|
||||
use set_user_admin::command::*;
|
||||
|
@ -82,8 +92,9 @@ use crate::identity::application::port::output::{
|
|||
create_login_otp::*, create_verification_otp::*, create_verification_secret::*,
|
||||
delete_login_otp::*, delete_verification_otp::*, delete_verification_secret::*,
|
||||
email_exists::*, emp_id_exists::*, get_emp_id_from_phone_number::*, get_login_otp::*,
|
||||
get_verification_otp::*, get_verification_secret::*, phone_exists::*, store_id_exists::*,
|
||||
store_name_exists::*, user_id_exists::*, verification_secret_exists::*,
|
||||
get_verification_otp::*, get_verification_secret::*, phone_exists::*, role_id_exists::*,
|
||||
role_name_exists_for_store::*, store_id_exists::*, store_name_exists::*, user_id_exists::*,
|
||||
verification_secret_exists::*,
|
||||
},
|
||||
mailer::account_validation_link::*,
|
||||
phone::{account_login_otp::*, account_validation_otp::*},
|
||||
|
@ -99,6 +110,9 @@ pub enum IdentityCommand {
|
|||
MarkUserVerified(MarkUserVerifiedCommand),
|
||||
SetAdmin(SetAdminCommand),
|
||||
ResendVerificationEmail(ResendVerificationEmailCommand),
|
||||
OwnerAddEmployeeToStore(OwnerAddEmployeeToStoreCommand),
|
||||
OwnerRemoveEmployeeFromStore(OwnerRemoveEmployeeFromStoreCommand),
|
||||
AddRole(AddRoleCommand),
|
||||
// employee
|
||||
EmployeeRegister(EmployeeRegisterCommand),
|
||||
EmployeeInitLogin(EmployeeInitLoginCommand),
|
||||
|
@ -124,6 +138,8 @@ pub trait IdentityServicesInterface: Send + Sync {
|
|||
fn set_user_admin(&self) -> SetUserAdminServiceObj;
|
||||
fn update_email(&self) -> UpdateEmailServiceObj;
|
||||
fn update_password(&self) -> UpdatePasswordServiceObj;
|
||||
fn owner_manage_employee(&self) -> OwnerManageStoreEmployeesServiceObj;
|
||||
fn add_role_to_store(&self) -> AddRoleToStoreServiceObj;
|
||||
|
||||
// employee
|
||||
// fn employee_accept_invite_service(&self) -> EmployeeAcceptInviteServiceObj;
|
||||
|
@ -151,6 +167,8 @@ pub struct IdentityServices {
|
|||
set_user_admin: SetUserAdminServiceObj,
|
||||
update_email: UpdateEmailServiceObj,
|
||||
update_password: UpdatePasswordServiceObj,
|
||||
owner_manage_store_employee: OwnerManageStoreEmployeesServiceObj,
|
||||
add_role_to_store: AddRoleToStoreServiceObj,
|
||||
|
||||
// employee_accept_invite_service: EmployeeAcceptInviteServiceObj,
|
||||
employee_exit_organization_service: EmployeeExitOrganizationServiceObj,
|
||||
|
@ -190,6 +208,14 @@ impl IdentityServicesInterface for IdentityServices {
|
|||
self.update_password.clone()
|
||||
}
|
||||
|
||||
fn owner_manage_employee(&self) -> OwnerManageStoreEmployeesServiceObj {
|
||||
self.owner_manage_store_employee.clone()
|
||||
}
|
||||
|
||||
fn add_role_to_store(&self) -> AddRoleToStoreServiceObj {
|
||||
self.add_role_to_store.clone()
|
||||
}
|
||||
|
||||
// employee
|
||||
// fn employee_accept_invite_service(&self) -> EmployeeAcceptInviteServiceObj {
|
||||
// self.employee_accept_invite_service.clone()
|
||||
|
@ -240,6 +266,8 @@ impl IdentityServices {
|
|||
out_db_store_name_exists: StoreNameExistsDBPortObj,
|
||||
out_db_user_id_exists: UserIDExistsOutDBPortObj,
|
||||
out_db_verification_secret_exists: VerificationSecretExistsOutDBPortObj,
|
||||
out_db_role_id_exists: RoleIDExistsDBPortObj,
|
||||
out_db_role_name_exists_for_store: RoleNameExistsForStoreDBPortObj,
|
||||
|
||||
out_mailer_account_validating_link: AccountValidationLinkOutMailerPortObj,
|
||||
|
||||
|
@ -295,6 +323,23 @@ impl IdentityServices {
|
|||
|
||||
let update_password: UpdatePasswordServiceObj = Arc::new(UpdatePasswordService);
|
||||
|
||||
let owner_manage_store_employee: OwnerManageStoreEmployeesServiceObj = Arc::new(
|
||||
OwnerManageStoreEmployeesServiceBuilder::default()
|
||||
.db_store_id_exists_adapter(out_db_store_id_exists.clone())
|
||||
.db_emp_id_exists_adapter(out_db_emp_id_exists.clone())
|
||||
.build()
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
let add_role_to_store: AddRoleToStoreServiceObj = Arc::new(
|
||||
AddRoleToStoreServiceBuilder::default()
|
||||
.db_store_id_exists_adapter(out_db_store_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(),
|
||||
);
|
||||
|
||||
// let employee_accept_invite_service: EmployeeAcceptInviteServiceObj = Arc::new(
|
||||
// EmployeeAcceptInviteServiceBuilder::default()
|
||||
// .db_get_invite_adapter(unimplemented!())
|
||||
|
@ -397,6 +442,8 @@ impl IdentityServices {
|
|||
set_user_admin,
|
||||
update_email,
|
||||
update_password,
|
||||
owner_manage_store_employee,
|
||||
add_role_to_store,
|
||||
|
||||
// employee_accept_invite_service,
|
||||
employee_exit_organization_service,
|
||||
|
@ -443,6 +490,8 @@ mod tests {
|
|||
mock_store_name_exists_db_port_true(IS_NEVER_CALLED),
|
||||
mock_user_id_exists_db_port(IS_NEVER_CALLED, false),
|
||||
mock_verification_secret_exists_db_port(IS_NEVER_CALLED, false),
|
||||
mock_role_id_exists_db_port_true(IS_NEVER_CALLED),
|
||||
mock_role_name_exists_for_store_db_port_true(IS_NEVER_CALLED),
|
||||
mock_account_validation_link_mailer_port(IS_NEVER_CALLED),
|
||||
mock_account_validation_otp_phone_port(IS_NEVER_CALLED),
|
||||
mock_account_login_otp_phone_port(IS_NEVER_CALLED),
|
||||
|
|
|
@ -0,0 +1,204 @@
|
|||
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
//
|
||||
// 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::{
|
||||
owner_add_employee_to_store_command::*, owner_added_employee_to_store_event::*,
|
||||
owner_remove_employee_from_store_command::*, owner_removed_employee_from_store_event::*,
|
||||
};
|
||||
|
||||
use super::errors::*;
|
||||
|
||||
#[automock]
|
||||
#[async_trait::async_trait]
|
||||
pub trait OwnerManageStoreEmployeesUseCase: Send + Sync {
|
||||
async fn add_employee_to_store(
|
||||
&self,
|
||||
cmd: OwnerAddEmployeeToStoreCommand,
|
||||
) -> IdentityResult<OwnerAddedEmployeeToStoreEvent>;
|
||||
async fn remove_employee_from_store(
|
||||
&self,
|
||||
cmd: OwnerRemoveEmployeeFromStoreCommand,
|
||||
) -> IdentityResult<OwnerRemovedEmployeeFromStoreEvent>;
|
||||
}
|
||||
|
||||
pub type OwnerManageStoreEmployeesServiceObj = std::sync::Arc<dyn OwnerManageStoreEmployeesUseCase>;
|
||||
|
||||
#[derive(Clone, Builder)]
|
||||
pub struct OwnerManageStoreEmployeesService {
|
||||
db_emp_id_exists_adapter: EmpIDExistsOutDBPortObj,
|
||||
db_store_id_exists_adapter: StoreIDExistsDBPortObj,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl OwnerManageStoreEmployeesUseCase for OwnerManageStoreEmployeesService {
|
||||
async fn remove_employee_from_store(
|
||||
&self,
|
||||
cmd: OwnerRemoveEmployeeFromStoreCommand,
|
||||
) -> IdentityResult<OwnerRemovedEmployeeFromStoreEvent> {
|
||||
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);
|
||||
}
|
||||
|
||||
Ok(OwnerRemovedEmployeeFromStoreEventBuilder::default()
|
||||
.emp_id(*cmd.emp_id())
|
||||
.store_id(*cmd.store_id())
|
||||
.added_by(*cmd.adding_by())
|
||||
.build()
|
||||
.unwrap())
|
||||
}
|
||||
|
||||
async fn add_employee_to_store(
|
||||
&self,
|
||||
cmd: OwnerAddEmployeeToStoreCommand,
|
||||
) -> IdentityResult<OwnerAddedEmployeeToStoreEvent> {
|
||||
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);
|
||||
}
|
||||
|
||||
Ok(OwnerAddedEmployeeToStoreEventBuilder::default()
|
||||
.emp_id(*cmd.emp_id())
|
||||
.store_id(*cmd.store_id())
|
||||
.added_by(*cmd.adding_by())
|
||||
.build()
|
||||
.unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{tests::bdd::*, utils::uuid::tests::*};
|
||||
|
||||
use super::*;
|
||||
|
||||
impl OwnerManageStoreEmployeesService {
|
||||
pub fn mock_service(
|
||||
times: Option<usize>,
|
||||
cmd: OwnerAddEmployeeToStoreCommand,
|
||||
) -> OwnerManageStoreEmployeesServiceObj {
|
||||
let res = OwnerAddedEmployeeToStoreEvent::get_event(&cmd);
|
||||
let mut m = MockOwnerManageStoreEmployeesUseCase::default();
|
||||
|
||||
if let Some(times) = times {
|
||||
m.expect_add_employee_to_store()
|
||||
.times(times)
|
||||
.returning(move |_| Ok(res.clone()));
|
||||
} else {
|
||||
m.expect_add_employee_to_store()
|
||||
.returning(move |_| Ok(res.clone()));
|
||||
}
|
||||
|
||||
std::sync::Arc::new(m)
|
||||
}
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_service_add_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))
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
{
|
||||
let cmd = OwnerAddEmployeeToStoreCommandBuilder::default()
|
||||
.emp_id(UUID)
|
||||
.store_id(UUID)
|
||||
.adding_by(UUID)
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let res = s.add_employee_to_store(cmd.clone()).await.unwrap();
|
||||
assert_eq!(*res.emp_id(), *cmd.emp_id());
|
||||
assert_eq!(*res.added_by(), *cmd.adding_by());
|
||||
assert_eq!(*res.store_id(), *cmd.store_id());
|
||||
}
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_service_add_employee_emp_no_exist() {
|
||||
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))
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
{
|
||||
let cmd = OwnerAddEmployeeToStoreCommandBuilder::default()
|
||||
.emp_id(UUID)
|
||||
.adding_by(UUID)
|
||||
.store_id(UUID)
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
s.add_employee_to_store(cmd.clone()).await.err(),
|
||||
Some(IdentityError::EmployeeNotFound)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[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))
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
{
|
||||
let cmd = OwnerRemoveEmployeeFromStoreCommand::get_cmd();
|
||||
|
||||
let res = s.remove_employee_from_store(cmd.clone()).await.unwrap();
|
||||
assert_eq!(*res.emp_id(), *cmd.emp_id());
|
||||
assert_eq!(*res.added_by(), *cmd.adding_by());
|
||||
assert_eq!(*res.store_id(), *cmd.store_id());
|
||||
}
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_service_remove_employee_emp_no_exist() {
|
||||
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))
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
{
|
||||
let cmd = OwnerRemoveEmployeeFromStoreCommand::get_cmd();
|
||||
|
||||
assert_eq!(
|
||||
s.remove_employee_from_store(cmd.clone()).await.err(),
|
||||
Some(IdentityError::EmployeeNotFound)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -134,6 +134,20 @@ impl Aggregate for User {
|
|||
.await?;
|
||||
Ok(vec![IdentityEvent::VerificationEmailResent])
|
||||
}
|
||||
IdentityCommand::OwnerAddEmployeeToStore(cmd) => {
|
||||
let res = services
|
||||
.owner_manage_employee()
|
||||
.add_employee_to_store(cmd)
|
||||
.await?;
|
||||
Ok(vec![IdentityEvent::OwnerAddedEmployeeToStore(res)])
|
||||
}
|
||||
IdentityCommand::OwnerRemoveEmployeeFromStore(cmd) => {
|
||||
let res = services
|
||||
.owner_manage_employee()
|
||||
.remove_employee_from_store(cmd)
|
||||
.await?;
|
||||
Ok(vec![IdentityEvent::OwnerRemovedEmployeeFromStore(res)])
|
||||
}
|
||||
_ => Ok(Vec::new()),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@ pub struct Employee {
|
|||
#[builder(default = "None")]
|
||||
store_id: Option<Uuid>,
|
||||
deleted: bool,
|
||||
#[builder(default = "None")]
|
||||
role_id: Option<Uuid>,
|
||||
}
|
||||
#[derive(
|
||||
Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Ord, PartialOrd, Getters, Builder,
|
||||
|
@ -62,6 +64,7 @@ impl Default for Employee {
|
|||
first_name: "".to_string(),
|
||||
last_name: "".to_string(),
|
||||
phone_number: Default::default(),
|
||||
role_id: None,
|
||||
phone_verified: false,
|
||||
deleted: false,
|
||||
emp_id: Uuid::new_v4(),
|
||||
|
@ -160,7 +163,14 @@ impl Aggregate for Employee {
|
|||
IdentityEvent::PhoneNumberChanged(e) => unimplemented!(),
|
||||
// IdentityEvent::InviteAccepted(e) => self.store_id = Some(*e.store_id()),
|
||||
IdentityEvent::OrganizationExited(e) => self.store_id = None,
|
||||
|
||||
IdentityEvent::OwnerAddedEmployeeToStore(e) => {
|
||||
self.store_id = Some(*e.store_id());
|
||||
self.role_id = None;
|
||||
}
|
||||
IdentityEvent::OwnerRemovedEmployeeFromStore(e) => {
|
||||
self.store_id = None;
|
||||
self.role_id = None;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
@ -185,8 +195,9 @@ mod tests {
|
|||
employee_register_command::EmployeeRegisterCommand,
|
||||
employee_registered_event::EmployeeRegisteredEvent,
|
||||
exit_organization_command::ExitOrganizationCommand,
|
||||
// invite_accepted_event::InviteAcceptedEvent,
|
||||
organization_exited_event::OrganizationExitedEvent,
|
||||
owner_add_employee_to_store_command::OwnerAddEmployeeToStoreCommand,
|
||||
owner_added_employee_to_store_event::OwnerAddedEmployeeToStoreEvent,
|
||||
phone_number_verified_event::PhoneNumberVerifiedEvent,
|
||||
resend_login_otp_command::ResendLoginOTPCommand,
|
||||
resend_login_otp_event::ResentLoginOTPEvent,
|
||||
|
@ -368,4 +379,25 @@ mod tests {
|
|||
.when(IdentityCommand::EmployeeExitOrganization(cmd))
|
||||
.then_expect_events(vec![expected]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_owner_added_employee_to_store() {
|
||||
let cmd = OwnerAddEmployeeToStoreCommand::get_cmd();
|
||||
let expected = OwnerAddedEmployeeToStoreEvent::get_event(&cmd);
|
||||
let expected = IdentityEvent::OwnerAddedEmployeeToStore(expected);
|
||||
|
||||
// let mut services = MockIdentityServicesInterface::new();
|
||||
// services
|
||||
// .expect_employee_accept_invite_service()
|
||||
// .times(IS_CALLED_ONLY_ONCE.unwrap())
|
||||
// .return_const(EmployeeAcceptInviteService::mock_service(
|
||||
// IS_CALLED_ONLY_ONCE,
|
||||
// cmd.clone(),
|
||||
// ));
|
||||
//
|
||||
// EmployeeTestFramework::with(Arc::new(services))
|
||||
// .given_no_previous_events()
|
||||
// .when(IdentityCommand::EmployeeAcceptInvite(cmd))
|
||||
// .then_expect_events(vec![expected]);
|
||||
}
|
||||
}
|
||||
|
|
36
src/identity/domain/owner_add_employee_to_store_command.rs
Normal file
36
src/identity/domain/owner_add_employee_to_store_command.rs
Normal file
|
@ -0,0 +1,36 @@
|
|||
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
//
|
||||
// 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::*;
|
||||
|
||||
#[derive(
|
||||
Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Ord, PartialOrd, Getters, Builder,
|
||||
)]
|
||||
pub struct OwnerAddEmployeeToStoreCommand {
|
||||
adding_by: Uuid,
|
||||
emp_id: Uuid,
|
||||
store_id: Uuid,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use crate::utils::uuid::tests::UUID;
|
||||
|
||||
use super::*;
|
||||
|
||||
impl OwnerAddEmployeeToStoreCommand {
|
||||
pub fn get_cmd() -> Self {
|
||||
Self {
|
||||
emp_id: UUID,
|
||||
adding_by: UUID,
|
||||
store_id: UUID,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
38
src/identity/domain/owner_added_employee_to_store_event.rs
Normal file
38
src/identity/domain/owner_added_employee_to_store_event.rs
Normal file
|
@ -0,0 +1,38 @@
|
|||
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
//
|
||||
// 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 OwnerAddedEmployeeToStoreEvent {
|
||||
emp_id: Uuid,
|
||||
added_by: Uuid,
|
||||
store_id: Uuid,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{
|
||||
identity::domain::owner_add_employee_to_store_command::OwnerAddEmployeeToStoreCommand,
|
||||
utils::uuid::tests::UUID,
|
||||
};
|
||||
|
||||
impl OwnerAddedEmployeeToStoreEvent {
|
||||
pub fn get_event(cmd: &OwnerAddEmployeeToStoreCommand) -> Self {
|
||||
Self {
|
||||
emp_id: *cmd.emp_id(),
|
||||
added_by: *cmd.adding_by(),
|
||||
store_id: *cmd.store_id(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
//
|
||||
// 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::*;
|
||||
|
||||
#[derive(
|
||||
Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Ord, PartialOrd, Getters, Builder,
|
||||
)]
|
||||
pub struct OwnerRemoveEmployeeFromStoreCommand {
|
||||
adding_by: Uuid,
|
||||
emp_id: Uuid,
|
||||
store_id: Uuid,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use crate::utils::uuid::tests::UUID;
|
||||
|
||||
use super::*;
|
||||
|
||||
impl OwnerRemoveEmployeeFromStoreCommand {
|
||||
pub fn get_cmd() -> Self {
|
||||
Self {
|
||||
emp_id: UUID,
|
||||
adding_by: UUID,
|
||||
store_id: UUID,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
//
|
||||
// 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::*;
|
||||
|
||||
#[derive(
|
||||
Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Ord, PartialOrd, Getters, Builder,
|
||||
)]
|
||||
pub struct OwnerRemovedEmployeeFromStoreEvent {
|
||||
emp_id: Uuid,
|
||||
added_by: Uuid,
|
||||
store_id: Uuid,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{
|
||||
identity::domain::owner_remove_employee_from_store_command::OwnerRemoveEmployeeFromStoreCommand,
|
||||
utils::uuid::tests::UUID,
|
||||
};
|
||||
|
||||
impl OwnerRemovedEmployeeFromStoreEvent {
|
||||
pub fn get_event(cmd: &OwnerRemoveEmployeeFromStoreCommand) -> Self {
|
||||
Self {
|
||||
emp_id: *cmd.emp_id(),
|
||||
added_by: *cmd.adding_by(),
|
||||
store_id: *cmd.store_id(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue