use crate::{
application::dto::{
CreateTenantRequest, CreateTenantResponse, ListTenantsResponse, TenantDto,
UpdateTenantRequest, UpdateTenantResponse,
},
domain::{entities::Tenant, value_objects::TenantId},
error::Result,
};
pub struct CreateTenantUseCase;
impl CreateTenantUseCase {
pub fn execute(request: CreateTenantRequest) -> Result<CreateTenantResponse> {
let tenant_id = TenantId::new(request.tenant_id)?;
let tenant = if let Some(quotas_dto) = request.quotas {
Tenant::new(tenant_id, request.name, quotas_dto.into())?
} else {
Tenant::new(
tenant_id,
request.name,
crate::domain::entities::TenantQuotas::free_tier(),
)?
};
Ok(CreateTenantResponse {
tenant: TenantDto::from(&tenant),
})
}
}
pub struct UpdateTenantUseCase;
impl UpdateTenantUseCase {
pub fn execute(
mut tenant: Tenant,
request: UpdateTenantRequest,
) -> Result<UpdateTenantResponse> {
if let Some(name) = request.name {
tenant.update_name(name)?;
}
if let Some(quotas_dto) = request.quotas {
tenant.update_quotas(quotas_dto.into());
}
Ok(UpdateTenantResponse {
tenant: TenantDto::from(&tenant),
})
}
}
pub struct ActivateTenantUseCase;
impl ActivateTenantUseCase {
pub fn execute(mut tenant: Tenant) -> Result<TenantDto> {
tenant.activate();
Ok(TenantDto::from(&tenant))
}
}
pub struct DeactivateTenantUseCase;
impl DeactivateTenantUseCase {
pub fn execute(mut tenant: Tenant) -> Result<TenantDto> {
tenant.deactivate();
Ok(TenantDto::from(&tenant))
}
}
pub struct ListTenantsUseCase;
impl ListTenantsUseCase {
pub fn execute(tenants: &[Tenant]) -> ListTenantsResponse {
let tenant_dtos: Vec<TenantDto> = tenants.iter().map(TenantDto::from).collect();
let count = tenant_dtos.len();
ListTenantsResponse {
tenants: tenant_dtos,
count,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::application::dto::TenantQuotasDto;
#[test]
fn test_create_tenant_with_default_quotas() {
let request = CreateTenantRequest {
tenant_id: "test-tenant".to_string(),
name: "Test Tenant".to_string(),
quotas: None,
};
let response = CreateTenantUseCase::execute(request);
assert!(response.is_ok());
let response = response.unwrap();
assert_eq!(response.tenant.name, "Test Tenant");
assert_eq!(response.tenant.tenant_id, "test-tenant");
assert!(response.tenant.is_active);
}
#[test]
fn test_create_tenant_with_custom_quotas() {
let request = CreateTenantRequest {
tenant_id: "premium-tenant".to_string(),
name: "Premium Tenant".to_string(),
quotas: Some(TenantQuotasDto {
max_events_per_day: Some(1_000_000),
max_storage_bytes: Some(10_000_000_000),
max_queries_per_hour: Some(10_000),
max_api_keys: Some(50),
max_projections: Some(100),
max_pipelines: Some(50),
}),
};
let response = CreateTenantUseCase::execute(request);
assert!(response.is_ok());
let response = response.unwrap();
assert_eq!(response.tenant.quotas.max_events_per_day, Some(1_000_000));
}
#[test]
fn test_update_tenant_name() {
let tenant_id = TenantId::new("test-tenant".to_string()).unwrap();
let tenant = Tenant::new(
tenant_id,
"Old Name".to_string(),
crate::domain::entities::TenantQuotas::free_tier(),
)
.unwrap();
let request = UpdateTenantRequest {
name: Some("New Name".to_string()),
quotas: None,
};
let response = UpdateTenantUseCase::execute(tenant, request);
assert!(response.is_ok());
let response = response.unwrap();
assert_eq!(response.tenant.name, "New Name");
}
#[test]
fn test_activate_deactivate_tenant() {
let tenant_id = TenantId::new("test-tenant".to_string()).unwrap();
let tenant = Tenant::new(
tenant_id,
"Test".to_string(),
crate::domain::entities::TenantQuotas::free_tier(),
)
.unwrap();
let result = DeactivateTenantUseCase::execute(tenant.clone());
assert!(result.is_ok());
assert!(!result.unwrap().is_active);
let mut deactivated = tenant.clone();
deactivated.deactivate();
let result = ActivateTenantUseCase::execute(deactivated);
assert!(result.is_ok());
assert!(result.unwrap().is_active);
}
#[test]
fn test_list_tenants() {
let tenants = vec![
Tenant::new(
TenantId::new("tenant-1".to_string()).unwrap(),
"Tenant 1".to_string(),
crate::domain::entities::TenantQuotas::free_tier(),
)
.unwrap(),
Tenant::new(
TenantId::new("tenant-2".to_string()).unwrap(),
"Tenant 2".to_string(),
crate::domain::entities::TenantQuotas::standard(),
)
.unwrap(),
];
let response = ListTenantsUseCase::execute(&tenants);
assert_eq!(response.count, 2);
assert_eq!(response.tenants.len(), 2);
}
}