initial commit

This commit is contained in:
2026-07-21 15:36:49 +07:00
commit 77f66132bc
2640 changed files with 850901 additions and 0 deletions
@@ -0,0 +1,34 @@
using MediatR;
using Microsoft.Extensions.Logging;
namespace Application.Common.Behaviors;
public class LoggingBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> where TRequest : notnull
{
private readonly ILogger<TRequest> _logger;
public LoggingBehaviour(ILogger<TRequest> logger)
{
_logger = logger;
}
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)
{
var requestName = typeof(TRequest).Name;
try
{
_logger.LogInformation($"Try executing {requestName} at {DateTime.UtcNow.ToString()}");
return await next();
}
catch (Exception ex)
{
_logger.LogError(ex, $"Error executing {requestName} at {DateTime.UtcNow.ToString()}");
throw;
}
}
}
@@ -0,0 +1,37 @@
using FluentValidation;
using MediatR;
namespace Application.Common.Behaviors;
public class ValidationBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
where TRequest : notnull
{
private readonly IEnumerable<IValidator<TRequest>> _validators;
public ValidationBehaviour(IEnumerable<IValidator<TRequest>> validators)
{
_validators = validators;
}
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)
{
if (_validators.Any())
{
var context = new ValidationContext<TRequest>(request);
var validationResults = await Task.WhenAll(
_validators.Select(v =>
v.ValidateAsync(context, cancellationToken)));
var failures = validationResults
.Where(r => r.Errors.Any())
.SelectMany(r => r.Errors)
.ToList();
if (failures.Any())
throw new ValidationException(failures);
}
return await next();
}
}
@@ -0,0 +1,5 @@
namespace Application.Common.CQS.Commands;
public interface ICommandContext
{
}
@@ -0,0 +1,9 @@
using Application.Common.Repositories;
namespace Application.Common.CQS.Queries;
public interface IQueryContext : IEntityDbSet
{
IQueryable<T> Set<T>() where T : class;
}
@@ -0,0 +1,16 @@
using System.ComponentModel;
using System.Reflection;
namespace Application.Common.Extensions;
public static class EnumExtensions
{
public static string ToFriendlyName<TEnum>(this TEnum value) where TEnum : Enum
{
var memberInfo = typeof(TEnum).GetMember(value.ToString());
var descriptionAttribute = memberInfo[0]
.GetCustomAttribute<DescriptionAttribute>();
return descriptionAttribute?.Description ?? value.ToString();
}
}
@@ -0,0 +1,20 @@
using Domain.Common;
namespace Application.Common.Extensions;
public static class QueryableExtensions
{
public static IQueryable<T> IsDeletedEqualTo<T>(this IQueryable<T> query, bool isDeleted = false) where T : class
{
if (typeof(IHasIsDeleted).IsAssignableFrom(typeof(T)))
{
query = query.Where(x => (x as IHasIsDeleted)!.IsDeleted == isDeleted);
}
return query;
}
}
@@ -0,0 +1,24 @@
using Domain.Common;
namespace Application.Common.Repositories;
public interface ICommandRepository<T> where T : BaseEntity
{
Task CreateAsync(T entity, CancellationToken cancellationToken = default);
void Create(T entity);
void Update(T entity);
void Delete(T entity);
void Purge(T entity);
Task<T?> GetAsync(string id, CancellationToken cancellationToken = default);
T? Get(string id);
IQueryable<T> GetQuery();
}
@@ -0,0 +1,43 @@
using Domain.Entities;
using Microsoft.EntityFrameworkCore;
namespace Application.Common.Repositories;
public interface IEntityDbSet
{
public DbSet<Token> Token { get; set; }
public DbSet<Todo> Todo { get; set; }
public DbSet<TodoItem> TodoItem { get; set; }
public DbSet<Company> Company { get; set; }
public DbSet<FileImage> FileImage { get; set; }
public DbSet<FileDocument> FileDocument { get; set; }
public DbSet<NumberSequence> NumberSequence { get; set; }
public DbSet<CustomerGroup> CustomerGroup { get; set; }
public DbSet<CustomerCategory> CustomerCategory { get; set; }
public DbSet<VendorGroup> VendorGroup { get; set; }
public DbSet<VendorCategory> VendorCategory { get; set; }
public DbSet<Customer> Customer { get; set; }
public DbSet<Vendor> Vendor { get; set; }
public DbSet<UnitMeasure> UnitMeasure { get; set; }
public DbSet<ProductGroup> ProductGroup { get; set; }
public DbSet<Product> Product { get; set; }
public DbSet<CustomerContact> CustomerContact { get; set; }
public DbSet<VendorContact> VendorContact { get; set; }
public DbSet<Tax> Tax { get; set; }
public DbSet<SalesOrder> SalesOrder { get; set; }
public DbSet<SalesOrderItem> SalesOrderItem { get; set; }
public DbSet<PurchaseOrder> PurchaseOrder { get; set; }
public DbSet<PurchaseOrderItem> PurchaseOrderItem { get; set; }
public DbSet<Campaign> Campaign { get; set; }
public DbSet<Budget> Budget { get; set; }
public DbSet<Expense> Expense { get; set; }
public DbSet<Lead> Lead { get; set; }
public DbSet<LeadContact> LeadContact { get; set; }
public DbSet<LeadActivity> LeadActivity { get; set; }
public DbSet<SalesTeam> SalesTeam { get; set; }
public DbSet<SalesRepresentative> SalesRepresentative { get; set; }
}
@@ -0,0 +1,7 @@
namespace Application.Common.Repositories;
public interface IUnitOfWork
{
Task SaveAsync(CancellationToken cancellationToken = default);
void Save();
}
@@ -0,0 +1,7 @@
namespace Application.Common.Services.EmailManager;
public interface IEmailService
{
Task SendEmailAsync(string email, string subject, string htmlMessage);
}
@@ -0,0 +1,14 @@
namespace Application.Common.Services.FileDocumentManager;
public interface IFileDocumentService
{
Task<string> UploadAsync(
string? originalFileName,
string? docExtension,
byte[]? fileData,
long? size,
string? description = "",
string? createdById = "",
CancellationToken cancellationToken = default);
Task<byte[]> GetFileAsync(string fileName, CancellationToken cancellationToken = default);
}
@@ -0,0 +1,13 @@
namespace Application.Common.Services.FileImageManager;
public interface IFileImageService
{
Task<string> UploadAsync(
string? originalFileName,
string? docExtension,
byte[]? fileData,
long? size,
string? description = "",
string? createdById = "",
CancellationToken cancellationToken = default);
Task<byte[]> GetFileAsync(string fileName, CancellationToken cancellationToken = default);
}
@@ -0,0 +1,12 @@
namespace Application.Common.Services.SecurityManager;
public record CreateUserResultDto
{
public string? UserId { get; init; }
public string? Email { get; init; }
public string? FirstName { get; init; }
public string? LastName { get; init; }
public bool? EmailConfirmed { get; init; }
public bool? IsBlocked { get; init; }
public bool? IsDeleted { get; init; }
}
@@ -0,0 +1,12 @@
namespace Application.Common.Services.SecurityManager;
public record DeleteUserResultDto
{
public string? UserId { get; init; }
public string? Email { get; init; }
public string? FirstName { get; init; }
public string? LastName { get; init; }
public bool? EmailConfirmed { get; init; }
public bool? IsBlocked { get; init; }
public bool? IsDeleted { get; init; }
}
@@ -0,0 +1,9 @@
namespace Application.Common.Services.SecurityManager;
public record GetMyProfileListResultDto
{
public string? Id { get; init; }
public string? FirstName { get; init; }
public string? LastName { get; init; }
public string? CompanyName { get; init; }
}
@@ -0,0 +1,6 @@
namespace Application.Common.Services.SecurityManager;
public record GetRoleListResultDto
{
public string? Id { get; init; }
public string? Name { get; init; }
}
@@ -0,0 +1,13 @@
namespace Application.Common.Services.SecurityManager;
public record GetUserListResultDto
{
public string? Id { get; init; }
public string? FirstName { get; init; }
public string? LastName { get; init; }
public string? Email { get; init; }
public bool? EmailConfirmed { get; init; }
public bool? IsBlocked { get; init; }
public bool? IsDeleted { get; init; }
public DateTime? CreatedAt { get; init; }
}
@@ -0,0 +1,131 @@
namespace Application.Common.Services.SecurityManager;
public interface ISecurityService
{
public Task<LoginResultDto> LoginAsync(
string email,
string password,
CancellationToken cancellationToken = default
);
public Task<LogoutResultDto> LogoutAsync(
string userId,
CancellationToken cancellationToken = default
);
public Task<RegisterResultDto> RegisterAsync(
string email,
string password,
string confirmPassword,
string firstName,
string lastName,
string companyName = "",
CancellationToken cancellationToken = default
);
public Task<string> ConfirmEmailAsync(
string email,
string code,
CancellationToken cancellationToken = default
);
public Task<string> ForgotPasswordAsync(
string email,
CancellationToken cancellationToken = default
);
public Task<string> ForgotPasswordConfirmationAsync(
string email,
string tempPassword,
string code,
CancellationToken cancellationToken = default
);
public Task<RefreshTokenResultDto> RefreshTokenAsync(
string refreshToken,
CancellationToken cancellationToken
);
public Task<List<GetMyProfileListResultDto>> GetMyProfileListAsync(
string userId,
CancellationToken cancellationToken
);
public Task UpdateMyProfileAsync(
string userId,
string firstName,
string lastName,
string companyName,
CancellationToken cancellationToken
);
public Task ChangePasswordAsync(
string userId,
string oldPassword,
string newPassword,
string confirmNewPassword,
CancellationToken cancellationToken
);
public Task<List<GetRoleListResultDto>> GetRoleListAsync(
CancellationToken cancellationToken
);
public Task<List<GetUserListResultDto>> GetUserListAsync(
CancellationToken cancellationToken
);
public Task<CreateUserResultDto> CreateUserAsync(
string email,
string password,
string confirmPassword,
string firstName,
string lastName,
bool emailConfirmed = true,
bool isBlocked = false,
bool isDeleted = false,
string createdById = "",
CancellationToken cancellationToken = default
);
public Task<UpdateUserResultDto> UpdateUserAsync(
string userId,
string firstName,
string lastName,
bool emailConfirmed = true,
bool isBlocked = false,
bool isDeleted = false,
string updatedById = "",
CancellationToken cancellationToken = default
);
public Task<DeleteUserResultDto> DeleteUserAsync(
string userId,
string deletedById = "",
CancellationToken cancellationToken = default
);
public Task UpdatePasswordUserAsync(
string userId,
string newPassword,
CancellationToken cancellationToken
);
public Task<List<string>> GetUserRolesAsync(
string userId,
CancellationToken cancellationToken = default
);
public Task<List<string>> UpdateUserRoleAsync(
string userId,
string roleName,
bool accessGranted,
CancellationToken cancellationToken = default
);
public Task ChangeAvatarAsync(
string userId,
string avatar,
CancellationToken cancellationToken
);
}
@@ -0,0 +1,15 @@
namespace Application.Common.Services.SecurityManager;
public record LoginResultDto
{
public string? AccessToken { get; init; }
public string? RefreshToken { get; init; }
public string? UserId { get; init; }
public string? Email { get; init; }
public string? FirstName { get; init; }
public string? LastName { get; init; }
public string? CompanyName { get; init; }
public string? Avatar { get; init; }
public List<MenuNavigationTreeNodeDto>? MenuNavigation { get; init; }
public List<string>? Roles { get; init; }
}
@@ -0,0 +1,13 @@
namespace Application.Common.Services.SecurityManager;
public record LogoutResultDto
{
public string? AccessToken { get; init; }
public string? RefreshToken { get; init; }
public string? UserId { get; init; }
public string? Email { get; init; }
public string? FirstName { get; init; }
public string? LastName { get; init; }
public string? CompanyName { get; init; }
public List<string>? UserClaims { get; init; }
}
@@ -0,0 +1,23 @@
namespace Application.Common.Services.SecurityManager;
public class MenuNavigationTreeNodeDto
{
public string Id { get; set; }
public string Name { get; set; }
public string? Pid { get; set; }
public string? NavURL { get; set; }
public bool HasChild { get; set; }
public bool Expanded { get; set; }
public bool IsSelected { get; set; }
public MenuNavigationTreeNodeDto(string param_id, string param_name, string? param_pid = null, string? param_navURL = null, bool param_hasChild = false, bool param_expanded = false, bool param_selected = false)
{
Id = param_id;
Name = param_name;
Pid = param_pid;
NavURL = param_navURL;
HasChild = param_hasChild;
Expanded = param_expanded;
IsSelected = param_selected;
}
}
@@ -0,0 +1,15 @@
namespace Application.Common.Services.SecurityManager;
public record RefreshTokenResultDto
{
public string? AccessToken { get; init; }
public string? RefreshToken { get; init; }
public string? UserId { get; init; }
public string? Email { get; init; }
public string? FirstName { get; init; }
public string? LastName { get; init; }
public string? CompanyName { get; init; }
public string? Avatar { get; init; }
public List<MenuNavigationTreeNodeDto>? MenuNavigation { get; init; }
public List<string>? Roles { get; init; }
}
@@ -0,0 +1,10 @@
namespace Application.Common.Services.SecurityManager;
public record RegisterResultDto
{
public string? UserId { get; init; }
public string? Email { get; init; }
public string? FirstName { get; init; }
public string? LastName { get; init; }
public string? CompanyName { get; init; }
}
@@ -0,0 +1,12 @@
namespace Application.Common.Services.SecurityManager;
public record UpdateUserResultDto
{
public string? UserId { get; init; }
public string? Email { get; init; }
public string? FirstName { get; init; }
public string? LastName { get; init; }
public bool? EmailConfirmed { get; init; }
public bool? IsBlocked { get; init; }
public bool? IsDeleted { get; init; }
}