Add tenant services, change id by _id and include delete endpoint for all entities

This commit is contained in:
Sergio Matias Urquin
2025-08-07 18:27:06 -06:00
parent f3d63ca0e3
commit 296aff13fe
47 changed files with 1183 additions and 118 deletions

View File

@@ -0,0 +1,19 @@
using Core.Thalos.Application.UseCases.Tenants.Ports;
using Core.Thalos.BuildingBlocks;
using Lib.Architecture.BuildingBlocks;
using Microsoft.AspNetCore.Mvc;
namespace Core.Thalos.Application.UseCases.Tenants.Adapter
{
public class TenantPort : BasePresenter, ITenantPort
{
public void Success(TenantAdapter output)
{
ViewModel = new OkObjectResult(output);
}
public void Success(List<TenantAdapter> output)
{
ViewModel = new OkObjectResult(output);
}
}
}

View File

@@ -0,0 +1,16 @@
using Core.Blueprint.Mongo;
using Lib.Architecture.BuildingBlocks;
namespace Core.Thalos.Application.UseCases.Tenants.Input
{
public class ChangeTenantStatusRequest : Notificator, ICommand
{
public string _Id { get; set; }
public StatusEnum Status { get; set; }
public bool Validate()
{
return _Id != null;
}
}
}

View File

@@ -0,0 +1,38 @@
using Lib.Architecture.BuildingBlocks;
namespace Core.Thalos.Application.UseCases.Tenants.Input
{
public class CreateTenantRequest : Notificator, ICommand
{
public string Name { get; set; } = null!;
public string TaxIdentifier { get; set; } = null!;
public string AddressLine1 { get; set; } = null!;
public string? AddressLine2 { get; set; }
public string City { get; set; } = null!;
public string State { get; set; } = null!;
public string Country { get; set; } = null!;
public string PostalCode { get; set; } = null!;
public string ContactEmail { get; set; } = null!;
public string ContactPhone { get; set; } = null!;
public string? Website { get; set; }
public string? ConnectionString { get; set; }
public bool Isolated { get; set; }
public bool Validate()
{
return Name != null;
}
}
}

View File

@@ -0,0 +1,13 @@
using Lib.Architecture.BuildingBlocks;
namespace Core.Thalos.Application.UseCases.Tenants.Input
{
public class DeleteTenantRequest : Notificator, ICommand
{
public string _Id { get; set; }
public bool Validate()
{
return _Id != null;
}
}
}

View File

@@ -0,0 +1,12 @@
using Lib.Architecture.BuildingBlocks;
namespace Core.Thalos.Application.UseCases.Tenants.Input
{
public class GetAllTenantsRequest : ICommand
{
public bool Validate()
{
return true;
}
}
}

View File

@@ -0,0 +1,13 @@
using Lib.Architecture.BuildingBlocks;
namespace Core.Thalos.Application.UseCases.Tenants.Input
{
public class GetTenantRequest : Notificator, ICommand
{
public string _Id { get; set; }
public bool Validate()
{
return _Id != null;
}
}
}

View File

@@ -0,0 +1,45 @@
using Lib.Architecture.BuildingBlocks;
namespace Core.Thalos.Application.UseCases.Tenants.Input
{
public class UpdateTenantRequest : Notificator, ICommand
{
public string Name { get; set; } = null!;
public string TaxIdentifier { get; set; } = null!;
public string AddressLine1 { get; set; } = null!;
public string? AddressLine2 { get; set; }
public string City { get; set; } = null!;
public string State { get; set; } = null!;
public string Country { get; set; } = null!;
public string PostalCode { get; set; } = null!;
public string ContactEmail { get; set; } = null!;
public string ContactPhone { get; set; } = null!;
public string? Website { get; set; }
public string? ConnectionString { get; set; }
public bool Isolated { get; set; }
public string _Id { get; set; } = null!;
public string Id { get; init; } = null!;
public DateTime CreatedAt { get; set; }
public string? CreatedBy { get; set; }
public DateTime? UpdatedAt { get; set; }
public string? UpdatedBy { get; set; }
public Blueprint.Mongo.StatusEnum Status { get; set; }
public bool Validate()
{
return _Id != null;
}
}
}

View File

@@ -0,0 +1,14 @@
using Core.Thalos.BuildingBlocks;
using Lib.Architecture.BuildingBlocks;
namespace Core.Thalos.Application.UseCases.Tenants.Ports
{
public interface ITenantPort : IBasePort,
ICommandSuccessPort<TenantAdapter>,
ICommandSuccessPort<List<TenantAdapter>>,
INoContentPort, IBusinessErrorPort, ITimeoutPort, IValidationErrorPort,
INotFoundPort, IForbiddenPort, IUnauthorizedPort, IInternalServerErrorPort,
IBadRequestPort
{
}
}

View File

@@ -0,0 +1,223 @@
using Core.Thalos.Application.UseCases.Tenants.Input;
using Core.Thalos.Application.UseCases.Tenants.Ports;
using Core.Thalos.BuildingBlocks;
using Core.Thalos.External.Clients;
using FluentValidation;
using Lib.Architecture.BuildingBlocks;
using Lib.Architecture.BuildingBlocks.Helpers;
namespace Core.Thalos.Application.UseCases.Tenants
{
public class TenantHandler :
IComponentHandler<ChangeTenantStatusRequest>,
IComponentHandler<GetAllTenantsRequest>,
IComponentHandler<UpdateTenantRequest>,
IComponentHandler<GetTenantRequest>,
IComponentHandler<DeleteTenantRequest>,
IComponentHandler<CreateTenantRequest>
{
private readonly ITenantPort _port;
private readonly IValidator<ChangeTenantStatusRequest> _changeTenantStatusValidator;
private readonly IValidator<CreateTenantRequest> _registerTenantValidator;
private readonly IValidator<UpdateTenantRequest> _updateTenantValidator;
private readonly IThalosServiceClient _thalosDALService;
public TenantHandler(
ITenantPort port,
IValidator<ChangeTenantStatusRequest> changeTenantStatusValidator,
IValidator<CreateTenantRequest> registerTenantValidator,
IValidator<UpdateTenantRequest> updateTenantValidator,
IThalosServiceClient thalosDALService)
{
_port = port ?? throw new ArgumentNullException(nameof(port));
_changeTenantStatusValidator = changeTenantStatusValidator ?? throw new ArgumentNullException(nameof(changeTenantStatusValidator));
_registerTenantValidator = registerTenantValidator ?? throw new ArgumentNullException(nameof(registerTenantValidator));
_updateTenantValidator = updateTenantValidator ?? throw new ArgumentNullException(nameof(updateTenantValidator));
_thalosDALService = thalosDALService ?? throw new ArgumentNullException(nameof(thalosDALService));
}
public async ValueTask ExecuteAsync(GetTenantRequest command, CancellationToken cancellationToken = default)
{
try
{
ArgumentNullException.ThrowIfNull(command);
var result = await _thalosDALService.GetTenantByIdAsync(command._Id, cancellationToken).ConfigureAwait(false);
if (result == null)
{
_port.NoContentSuccess();
return;
}
_port.Success(result);
}
catch (Exception ex)
{
ApiResponseHelper.EvaluatePort(ex, _port);
}
}
public async ValueTask ExecuteAsync(DeleteTenantRequest command, CancellationToken cancellationToken = default)
{
try
{
ArgumentNullException.ThrowIfNull(command);
var result = await _thalosDALService.DeleteTenantAsync(command._Id, cancellationToken).ConfigureAwait(false);
if (result == null)
{
_port.NoContentSuccess();
return;
}
_port.Success(result);
}
catch (Exception ex)
{
ApiResponseHelper.EvaluatePort(ex, _port);
}
}
public async ValueTask ExecuteAsync(GetAllTenantsRequest command, CancellationToken cancellationToken = default)
{
try
{
ArgumentNullException.ThrowIfNull(command);
var _result = await _thalosDALService.GetAllTenantsAsync().ConfigureAwait(false);
if (!_result.Any())
{
_port.NoContentSuccess();
return;
}
_port.Success(_result.ToList());
}
catch (Exception ex)
{
ApiResponseHelper.EvaluatePort(ex, _port);
}
}
public async ValueTask ExecuteAsync(ChangeTenantStatusRequest command, CancellationToken cancellationToken = default)
{
try
{
ArgumentNullException.ThrowIfNull(command);
if (!command.IsValid(_changeTenantStatusValidator))
{
_port.ValidationErrors(command.Notifications);
return;
}
var result = await _thalosDALService.ChangeStatusTenantAsync(command._Id, command.Status, cancellationToken).ConfigureAwait(false);
if (result == null)
{
_port.NoContentSuccess();
return;
}
_port.Success(result);
}
catch (Exception ex)
{
ApiResponseHelper.EvaluatePort(ex, _port);
}
}
public async ValueTask ExecuteAsync(CreateTenantRequest command, CancellationToken cancellationToken = default)
{
try
{
ArgumentNullException.ThrowIfNull(command);
if (!command.IsValid(_registerTenantValidator))
{
_port.ValidationErrors(command.Notifications);
return;
}
var request = new TenantRequest
{
Name = command.Name,
AddressLine1 = command.AddressLine1,
AddressLine2 = command.AddressLine2,
TaxIdentifier = command.TaxIdentifier,
City = command.City,
State = command.State,
Country = command.Country,
PostalCode = command.PostalCode,
ContactEmail = command.ContactEmail,
ContactPhone = command.ContactPhone,
Website = command.Website,
ConnectionString = command.ConnectionString,
Isolated = command.Isolated
};
var result = await _thalosDALService.CreateTenantAsync(request, cancellationToken).ConfigureAwait(false);
if (result == null)
{
_port.NoContentSuccess();
return;
}
_port.Success(result);
}
catch (Exception ex)
{
ApiResponseHelper.EvaluatePort(ex, _port);
}
}
public async ValueTask ExecuteAsync(UpdateTenantRequest command, CancellationToken cancellationToken = default)
{
try
{
ArgumentNullException.ThrowIfNull(command);
if (!command.IsValid(_updateTenantValidator))
{
_port.ValidationErrors(command.Notifications);
return;
}
var request = new TenantAdapter
{
_Id = command._Id,
Name = command.Name,
AddressLine1 = command.AddressLine1,
AddressLine2 = command.AddressLine2,
TaxIdentifier = command.TaxIdentifier,
City = command.City,
State = command.State,
Country = command.Country,
PostalCode = command.PostalCode,
ContactEmail = command.ContactEmail,
ContactPhone = command.ContactPhone,
Website = command.Website,
ConnectionString = command.ConnectionString,
Isolated = command.Isolated
};
string id = command._Id;
var result = await _thalosDALService.UpdateTenantAsync(request, id, cancellationToken).ConfigureAwait(false);
if (result == null)
{
_port.NoContentSuccess();
return;
}
_port.Success(result);
}
catch (Exception ex)
{
ApiResponseHelper.EvaluatePort(ex, _port);
}
}
}
}

View File

@@ -0,0 +1,15 @@
using Core.Thalos.Application.UseCases.Tenants.Input;
using FluentValidation;
namespace Core.Thalos.Application.UseCases.Tenants.Validator
{
public class ChangeTenantStatusValidator : AbstractValidator<ChangeTenantStatusRequest>
{
public ChangeTenantStatusValidator()
{
RuleFor(i => i._Id).NotEmpty().NotNull().OverridePropertyName(x => x._Id).WithName("Tenant ID").WithMessage("Tenant ID is Obligatory.");
RuleFor(i => i.Status).NotNull().OverridePropertyName(x => x.Status).WithName("Status").WithMessage("Status is Obligatory.");
}
}
}

View File

@@ -0,0 +1,74 @@
using Core.Thalos.Application.UseCases.Tenants.Input;
using FluentValidation;
namespace Core.Thalos.Application.UseCases.Tenants.Validator
{
public class CreateTenantValidator : AbstractValidator<CreateTenantRequest>
{
public CreateTenantValidator()
{
RuleFor(i => i.Name)
.NotEmpty()
.NotNull()
.OverridePropertyName(x => x.Name)
.WithName("Tenant Name")
.WithMessage("Tenant Name is obligatory.");
RuleFor(i => i.TaxIdentifier)
.NotEmpty()
.NotNull()
.OverridePropertyName(x => x.TaxIdentifier)
.WithName("Tax Identifier")
.WithMessage("Tax Identifier is obligatory.");
RuleFor(i => i.AddressLine1)
.NotEmpty()
.NotNull()
.OverridePropertyName(x => x.AddressLine1)
.WithName("Address Line 1")
.WithMessage("Address Line 1 is obligatory.");
RuleFor(i => i.City)
.NotEmpty()
.NotNull()
.OverridePropertyName(x => x.City)
.WithName("City")
.WithMessage("City is obligatory.");
RuleFor(i => i.State)
.NotEmpty()
.NotNull()
.OverridePropertyName(x => x.State)
.WithName("State")
.WithMessage("State is obligatory.");
RuleFor(i => i.Country)
.NotEmpty()
.NotNull()
.OverridePropertyName(x => x.Country)
.WithName("Country")
.WithMessage("Country is obligatory.");
RuleFor(i => i.PostalCode)
.NotEmpty()
.NotNull()
.OverridePropertyName(x => x.PostalCode)
.WithName("Postal Code")
.WithMessage("Postal Code is obligatory.");
RuleFor(i => i.ContactEmail)
.NotEmpty()
.NotNull()
.OverridePropertyName(x => x.ContactEmail)
.WithName("Contact Email")
.WithMessage("Contact Email is obligatory.");
RuleFor(i => i.ContactPhone)
.NotEmpty()
.NotNull()
.OverridePropertyName(x => x.ContactPhone)
.WithName("Contact Phone")
.WithMessage("Contact Phone is obligatory.");
}
}
}

View File

@@ -0,0 +1,66 @@
using Core.Thalos.Application.UseCases.Tenants.Input;
using FluentValidation;
namespace Core.Thalos.Application.UseCases.Tenants.Validator
{
public class UpdateTenantValidator : AbstractValidator<UpdateTenantRequest>
{
public UpdateTenantValidator()
{
RuleFor(i => i.Name)
.NotEmpty().NotNull()
.WithName("Tenant Name")
.WithMessage("Tenant Name is obligatory.");
RuleFor(i => i.TaxIdentifier)
.NotEmpty().NotNull()
.WithName("Tax Identifier")
.WithMessage("Tax Identifier is obligatory.");
RuleFor(i => i.AddressLine1)
.NotEmpty().NotNull()
.WithName("Address Line 1")
.WithMessage("Address Line 1 is obligatory.");
RuleFor(i => i.City)
.NotEmpty().NotNull()
.WithName("City")
.WithMessage("City is obligatory.");
RuleFor(i => i.State)
.NotEmpty().NotNull()
.WithName("State")
.WithMessage("State is obligatory.");
RuleFor(i => i.Country)
.NotEmpty().NotNull()
.WithName("Country")
.WithMessage("Country is obligatory.");
RuleFor(i => i.PostalCode)
.NotEmpty().NotNull()
.WithName("Postal Code")
.WithMessage("Postal Code is obligatory.");
RuleFor(i => i.ContactEmail)
.NotEmpty().NotNull()
.WithName("Contact Email")
.WithMessage("Contact Email is obligatory.");
RuleFor(i => i.ContactPhone)
.NotEmpty().NotNull()
.WithName("Contact Phone")
.WithMessage("Contact Phone is obligatory.");
RuleFor(i => i._Id)
.NotEmpty().NotNull()
.WithName("Internal ID")
.WithMessage("Internal ID is obligatory.");
RuleFor(i => i.Id)
.NotEmpty().NotNull()
.WithName("Tenant ID")
.WithMessage("Tenant ID is obligatory.");
}
}
}