diff --git a/src/CMSMicroservice.Application/Common/Interfaces/IApplicationDbContext.cs b/src/CMSMicroservice.Application/Common/Interfaces/IApplicationDbContext.cs index f496789..578d774 100644 --- a/src/CMSMicroservice.Application/Common/Interfaces/IApplicationDbContext.cs +++ b/src/CMSMicroservice.Application/Common/Interfaces/IApplicationDbContext.cs @@ -23,5 +23,16 @@ public interface IApplicationDbContext DbSet UserOrders { get; } DbSet UserWallets { get; } DbSet UserWalletChangeLogs { get; } + DbSet SystemConfigurations { get; } + DbSet SystemConfigurationHistories { get; } + DbSet ClubMemberships { get; } + DbSet ClubMembershipHistories { get; } + DbSet ClubFeatures { get; } + DbSet UserClubFeatures { get; } + DbSet NetworkWeeklyBalances { get; } + DbSet NetworkMembershipHistories { get; } + DbSet WeeklyCommissionPools { get; } + DbSet UserCommissionPayouts { get; } + DbSet CommissionPayoutHistories { get; } Task SaveChangesAsync(CancellationToken cancellationToken = default); } \ No newline at end of file diff --git a/src/CMSMicroservice.Application/ConfigurationCQ/Commands/DeactivateConfiguration/DeactivateConfigurationCommand.cs b/src/CMSMicroservice.Application/ConfigurationCQ/Commands/DeactivateConfiguration/DeactivateConfigurationCommand.cs new file mode 100644 index 0000000..589e7a9 --- /dev/null +++ b/src/CMSMicroservice.Application/ConfigurationCQ/Commands/DeactivateConfiguration/DeactivateConfigurationCommand.cs @@ -0,0 +1,17 @@ +namespace CMSMicroservice.Application.ConfigurationCQ.Commands.DeactivateConfiguration; + +/// +/// Command برای غیرفعال کردن یک Configuration +/// +public record DeactivateConfigurationCommand : IRequest +{ + /// + /// شناسه Configuration + /// + public long ConfigurationId { get; init; } + + /// + /// دلیل غیرفعال‌سازی + /// + public string? Reason { get; init; } +} diff --git a/src/CMSMicroservice.Application/ConfigurationCQ/Commands/DeactivateConfiguration/DeactivateConfigurationCommandHandler.cs b/src/CMSMicroservice.Application/ConfigurationCQ/Commands/DeactivateConfiguration/DeactivateConfigurationCommandHandler.cs new file mode 100644 index 0000000..4e2d9d9 --- /dev/null +++ b/src/CMSMicroservice.Application/ConfigurationCQ/Commands/DeactivateConfiguration/DeactivateConfigurationCommandHandler.cs @@ -0,0 +1,47 @@ +namespace CMSMicroservice.Application.ConfigurationCQ.Commands.DeactivateConfiguration; + +public class DeactivateConfigurationCommandHandler : IRequestHandler +{ + private readonly IApplicationDbContext _context; + + public DeactivateConfigurationCommandHandler(IApplicationDbContext context) + { + _context = context; + } + + public async Task Handle(DeactivateConfigurationCommand request, CancellationToken cancellationToken) + { + var entity = await _context.SystemConfigurations + .FirstOrDefaultAsync(x => x.Id == request.ConfigurationId, cancellationToken) + ?? throw new NotFoundException(nameof(SystemConfiguration), request.ConfigurationId); + + // اگر از قبل غیرفعال است، خطا ندهیم + if (!entity.IsActive) + { + return Unit.Value; + } + + var oldValue = entity.Value; + entity.IsActive = false; + + _context.SystemConfigurations.Update(entity); + await _context.SaveChangesAsync(cancellationToken); + + // ثبت تاریخچه + var history = new SystemConfigurationHistory + { + ConfigurationId = entity.Id, + Scope = entity.Scope, + Key = entity.Key, + OldValue = oldValue, + NewValue = entity.Value, + Reason = request.Reason ?? "Configuration deactivated", + PerformedBy = "System" // TODO: باید از Current User گرفته شود + }; + + await _context.SystemConfigurationHistories.AddAsync(history, cancellationToken); + await _context.SaveChangesAsync(cancellationToken); + + return Unit.Value; + } +} diff --git a/src/CMSMicroservice.Application/ConfigurationCQ/Commands/DeactivateConfiguration/DeactivateConfigurationCommandValidator.cs b/src/CMSMicroservice.Application/ConfigurationCQ/Commands/DeactivateConfiguration/DeactivateConfigurationCommandValidator.cs new file mode 100644 index 0000000..74a0d8a --- /dev/null +++ b/src/CMSMicroservice.Application/ConfigurationCQ/Commands/DeactivateConfiguration/DeactivateConfigurationCommandValidator.cs @@ -0,0 +1,29 @@ +namespace CMSMicroservice.Application.ConfigurationCQ.Commands.DeactivateConfiguration; + +public class DeactivateConfigurationCommandValidator : AbstractValidator +{ + public DeactivateConfigurationCommandValidator() + { + RuleFor(x => x.ConfigurationId) + .GreaterThan(0) + .WithMessage("شناسه Configuration معتبر نیست"); + + RuleFor(x => x.Reason) + .MaximumLength(500) + .WithMessage("دلیل غیرفعال‌سازی نمی‌تواند بیشتر از 500 کاراکتر باشد") + .When(x => !string.IsNullOrEmpty(x.Reason)); + } + + public Func>> ValidateValue => async (model, propertyName) => + { + var result = await ValidateAsync( + ValidationContext.CreateWithOptions( + (DeactivateConfigurationCommand)model, + x => x.IncludeProperties(propertyName))); + + if (result.IsValid) + return Array.Empty(); + + return result.Errors.Select(e => e.ErrorMessage); + }; +} diff --git a/src/CMSMicroservice.Application/ConfigurationCQ/Commands/SetConfigurationValue/SetConfigurationValueCommand.cs b/src/CMSMicroservice.Application/ConfigurationCQ/Commands/SetConfigurationValue/SetConfigurationValueCommand.cs new file mode 100644 index 0000000..0189024 --- /dev/null +++ b/src/CMSMicroservice.Application/ConfigurationCQ/Commands/SetConfigurationValue/SetConfigurationValueCommand.cs @@ -0,0 +1,32 @@ +namespace CMSMicroservice.Application.ConfigurationCQ.Commands.SetConfigurationValue; + +/// +/// Command برای تنظیم یا به‌روزرسانی یک Configuration +/// +public record SetConfigurationValueCommand : IRequest +{ + /// + /// محدوده تنظیمات (System, Network, Club, Commission) + /// + public ConfigurationScope Scope { get; init; } + + /// + /// کلید یکتا برای تنظیمات + /// + public string Key { get; init; } + + /// + /// مقدار تنظیمات (JSON format) + /// + public string Value { get; init; } + + /// + /// توضیحات تنظیمات + /// + public string? Description { get; init; } + + /// + /// دلیل تغییر (برای History) + /// + public string? ChangeReason { get; init; } +} diff --git a/src/CMSMicroservice.Application/ConfigurationCQ/Commands/SetConfigurationValue/SetConfigurationValueCommandHandler.cs b/src/CMSMicroservice.Application/ConfigurationCQ/Commands/SetConfigurationValue/SetConfigurationValueCommandHandler.cs new file mode 100644 index 0000000..c86837c --- /dev/null +++ b/src/CMSMicroservice.Application/ConfigurationCQ/Commands/SetConfigurationValue/SetConfigurationValueCommandHandler.cs @@ -0,0 +1,74 @@ +namespace CMSMicroservice.Application.ConfigurationCQ.Commands.SetConfigurationValue; + +public class SetConfigurationValueCommandHandler : IRequestHandler +{ + private readonly IApplicationDbContext _context; + + public SetConfigurationValueCommandHandler(IApplicationDbContext context) + { + _context = context; + } + + public async Task Handle(SetConfigurationValueCommand request, CancellationToken cancellationToken) + { + // بررسی وجود Configuration با همین Scope و Key + var existingConfig = await _context.SystemConfigurations + .FirstOrDefaultAsync(x => + x.Scope == request.Scope && + x.Key == request.Key, + cancellationToken); + + SystemConfiguration entity; + bool isNewRecord = existingConfig == null; + string oldValue = null; + + if (isNewRecord) + { + // ایجاد Configuration جدید + entity = new SystemConfiguration + { + Scope = request.Scope, + Key = request.Key, + Value = request.Value, + Description = request.Description, + IsActive = true + }; + + await _context.SystemConfigurations.AddAsync(entity, cancellationToken); + } + else + { + // به‌روزرسانی Configuration موجود + entity = existingConfig; + oldValue = entity.Value; + + entity.Value = request.Value; + + if (!string.IsNullOrEmpty(request.Description)) + { + entity.Description = request.Description; + } + + _context.SystemConfigurations.Update(entity); + } + + await _context.SaveChangesAsync(cancellationToken); + + // ثبت تاریخچه + var history = new SystemConfigurationHistory + { + ConfigurationId = entity.Id, + Scope = entity.Scope, + Key = entity.Key, + OldValue = oldValue, + NewValue = entity.Value, + Reason = request.ChangeReason ?? (isNewRecord ? "Initial creation" : "Value updated"), + PerformedBy = "System" // TODO: باید از Current User گرفته شود + }; + + await _context.SystemConfigurationHistories.AddAsync(history, cancellationToken); + await _context.SaveChangesAsync(cancellationToken); + + return entity.Id; + } +} diff --git a/src/CMSMicroservice.Application/ConfigurationCQ/Commands/SetConfigurationValue/SetConfigurationValueCommandValidator.cs b/src/CMSMicroservice.Application/ConfigurationCQ/Commands/SetConfigurationValue/SetConfigurationValueCommandValidator.cs new file mode 100644 index 0000000..b648bd8 --- /dev/null +++ b/src/CMSMicroservice.Application/ConfigurationCQ/Commands/SetConfigurationValue/SetConfigurationValueCommandValidator.cs @@ -0,0 +1,48 @@ +namespace CMSMicroservice.Application.ConfigurationCQ.Commands.SetConfigurationValue; + +public class SetConfigurationValueCommandValidator : AbstractValidator +{ + public SetConfigurationValueCommandValidator() + { + RuleFor(x => x.Scope) + .IsInEnum() + .WithMessage("محدوده تنظیمات معتبر نیست"); + + RuleFor(x => x.Key) + .NotEmpty() + .WithMessage("کلید تنظیمات الزامی است") + .MaximumLength(100) + .WithMessage("کلید تنظیمات نمی‌تواند بیشتر از 100 کاراکتر باشد") + .Matches(@"^[a-zA-Z0-9_\.]+$") + .WithMessage("کلید تنظیمات فقط می‌تواند شامل حروف انگلیسی، اعداد، نقطه و آندرلاین باشد"); + + RuleFor(x => x.Value) + .NotEmpty() + .WithMessage("مقدار تنظیمات الزامی است") + .MaximumLength(2000) + .WithMessage("مقدار تنظیمات نمی‌تواند بیشتر از 2000 کاراکتر باشد"); + + RuleFor(x => x.Description) + .MaximumLength(500) + .WithMessage("توضیحات نمی‌تواند بیشتر از 500 کاراکتر باشد") + .When(x => !string.IsNullOrEmpty(x.Description)); + + RuleFor(x => x.ChangeReason) + .MaximumLength(500) + .WithMessage("دلیل تغییر نمی‌تواند بیشتر از 500 کاراکتر باشد") + .When(x => !string.IsNullOrEmpty(x.ChangeReason)); + } + + public Func>> ValidateValue => async (model, propertyName) => + { + var result = await ValidateAsync( + ValidationContext.CreateWithOptions( + (SetConfigurationValueCommand)model, + x => x.IncludeProperties(propertyName))); + + if (result.IsValid) + return Array.Empty(); + + return result.Errors.Select(e => e.ErrorMessage); + }; +} diff --git a/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetAllConfigurations/GetAllConfigurationsQuery.cs b/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetAllConfigurations/GetAllConfigurationsQuery.cs new file mode 100644 index 0000000..a7cb564 --- /dev/null +++ b/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetAllConfigurations/GetAllConfigurationsQuery.cs @@ -0,0 +1,40 @@ +namespace CMSMicroservice.Application.ConfigurationCQ.Queries.GetAllConfigurations; + +/// +/// Query برای دریافت لیست تمام Configuration ها با فیلتر +/// +public record GetAllConfigurationsQuery : IRequest +{ + /// + /// موقعیت صفحه‌بندی + /// + public PaginationState? PaginationState { get; init; } + + /// + /// مرتب‌سازی بر اساس + /// + public string? SortBy { get; init; } + + /// + /// فیلتر + /// + public GetAllConfigurationsFilter? Filter { get; init; } +} + +public class GetAllConfigurationsFilter +{ + /// + /// فیلتر بر اساس محدوده + /// + public ConfigurationScope? Scope { get; set; } + + /// + /// جستجو در کلید + /// + public string? KeyContains { get; set; } + + /// + /// فقط Configuration های فعال + /// + public bool? IsActive { get; set; } +} diff --git a/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetAllConfigurations/GetAllConfigurationsQueryHandler.cs b/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetAllConfigurations/GetAllConfigurationsQueryHandler.cs new file mode 100644 index 0000000..ba54924 --- /dev/null +++ b/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetAllConfigurations/GetAllConfigurationsQueryHandler.cs @@ -0,0 +1,50 @@ +namespace CMSMicroservice.Application.ConfigurationCQ.Queries.GetAllConfigurations; + +public class GetAllConfigurationsQueryHandler : IRequestHandler +{ + private readonly IApplicationDbContext _context; + + public GetAllConfigurationsQueryHandler(IApplicationDbContext context) + { + _context = context; + } + + public async Task Handle(GetAllConfigurationsQuery request, CancellationToken cancellationToken) + { + var query = _context.SystemConfigurations + .ApplyOrder(sortBy: request.SortBy) + .AsNoTracking() + .AsQueryable(); + + if (request.Filter is not null) + { + query = query + .Where(x => request.Filter.Scope == null || x.Scope == request.Filter.Scope) + .Where(x => request.Filter.KeyContains == null || x.Key.Contains(request.Filter.KeyContains)) + .Where(x => request.Filter.IsActive == null || x.IsActive == request.Filter.IsActive); + } + + var meta = await query.GetMetaData(request.PaginationState, cancellationToken); + + var models = await query + .PaginatedListAsync(paginationState: request.PaginationState) + .Select(x => new GetAllConfigurationsResponseModel + { + Id = x.Id, + Scope = x.Scope, + Key = x.Key, + Value = x.Value, + Description = x.Description, + IsActive = x.IsActive, + Created = x.Created, + LastModified = x.LastModified + }) + .ToListAsync(cancellationToken); + + return new GetAllConfigurationsResponseDto + { + MetaData = meta, + Models = models + }; + } +} diff --git a/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetAllConfigurations/GetAllConfigurationsQueryValidator.cs b/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetAllConfigurations/GetAllConfigurationsQueryValidator.cs new file mode 100644 index 0000000..f4fe276 --- /dev/null +++ b/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetAllConfigurations/GetAllConfigurationsQueryValidator.cs @@ -0,0 +1,25 @@ +namespace CMSMicroservice.Application.ConfigurationCQ.Queries.GetAllConfigurations; + +public class GetAllConfigurationsQueryValidator : AbstractValidator +{ + public GetAllConfigurationsQueryValidator() + { + RuleFor(x => x.Filter.Scope) + .IsInEnum() + .WithMessage("محدوده تنظیمات معتبر نیست") + .When(x => x.Filter?.Scope != null); + } + + public Func>> ValidateValue => async (model, propertyName) => + { + var result = await ValidateAsync( + ValidationContext.CreateWithOptions( + (GetAllConfigurationsQuery)model, + x => x.IncludeProperties(propertyName))); + + if (result.IsValid) + return Array.Empty(); + + return result.Errors.Select(e => e.ErrorMessage); + }; +} diff --git a/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetAllConfigurations/GetAllConfigurationsResponseDto.cs b/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetAllConfigurations/GetAllConfigurationsResponseDto.cs new file mode 100644 index 0000000..052d7d3 --- /dev/null +++ b/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetAllConfigurations/GetAllConfigurationsResponseDto.cs @@ -0,0 +1,19 @@ +namespace CMSMicroservice.Application.ConfigurationCQ.Queries.GetAllConfigurations; + +public class GetAllConfigurationsResponseDto +{ + public MetaData MetaData { get; set; } + public List Models { get; set; } +} + +public class GetAllConfigurationsResponseModel +{ + public long Id { get; set; } + public ConfigurationScope Scope { get; set; } + public string Key { get; set; } + public string Value { get; set; } + public string? Description { get; set; } + public bool IsActive { get; set; } + public DateTimeOffset Created { get; set; } + public DateTimeOffset? LastModified { get; set; } +} diff --git a/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetConfigurationByKey/ConfigurationDto.cs b/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetConfigurationByKey/ConfigurationDto.cs new file mode 100644 index 0000000..0796d8b --- /dev/null +++ b/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetConfigurationByKey/ConfigurationDto.cs @@ -0,0 +1,16 @@ +namespace CMSMicroservice.Application.ConfigurationCQ.Queries.GetConfigurationByKey; + +/// +/// DTO برای نمایش اطلاعات Configuration +/// +public class ConfigurationDto +{ + public long Id { get; set; } + public ConfigurationScope Scope { get; set; } + public string Key { get; set; } + public string Value { get; set; } + public string? Description { get; set; } + public bool IsActive { get; set; } + public DateTimeOffset Created { get; set; } + public DateTimeOffset? LastModified { get; set; } +} diff --git a/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetConfigurationByKey/GetConfigurationByKeyQuery.cs b/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetConfigurationByKey/GetConfigurationByKeyQuery.cs new file mode 100644 index 0000000..9f273f3 --- /dev/null +++ b/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetConfigurationByKey/GetConfigurationByKeyQuery.cs @@ -0,0 +1,17 @@ +namespace CMSMicroservice.Application.ConfigurationCQ.Queries.GetConfigurationByKey; + +/// +/// Query برای دریافت یک Configuration بر اساس Scope و Key +/// +public record GetConfigurationByKeyQuery : IRequest +{ + /// + /// محدوده تنظیمات + /// + public ConfigurationScope Scope { get; init; } + + /// + /// کلید تنظیمات + /// + public string Key { get; init; } +} diff --git a/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetConfigurationByKey/GetConfigurationByKeyQueryHandler.cs b/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetConfigurationByKey/GetConfigurationByKeyQueryHandler.cs new file mode 100644 index 0000000..7a9e7e8 --- /dev/null +++ b/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetConfigurationByKey/GetConfigurationByKeyQueryHandler.cs @@ -0,0 +1,34 @@ +namespace CMSMicroservice.Application.ConfigurationCQ.Queries.GetConfigurationByKey; + +public class GetConfigurationByKeyQueryHandler : IRequestHandler +{ + private readonly IApplicationDbContext _context; + + public GetConfigurationByKeyQueryHandler(IApplicationDbContext context) + { + _context = context; + } + + public async Task Handle(GetConfigurationByKeyQuery request, CancellationToken cancellationToken) + { + var config = await _context.SystemConfigurations + .AsNoTracking() + .Where(x => x.Scope == request.Scope && x.Key == request.Key) + .FirstOrDefaultAsync(cancellationToken); + + if (config == null) + return null; + + return new ConfigurationDto + { + Id = config.Id, + Scope = config.Scope, + Key = config.Key, + Value = config.Value, + Description = config.Description, + IsActive = config.IsActive, + Created = config.Created, + LastModified = config.LastModified + }; + } +} diff --git a/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetConfigurationByKey/GetConfigurationByKeyQueryValidator.cs b/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetConfigurationByKey/GetConfigurationByKeyQueryValidator.cs new file mode 100644 index 0000000..f743d22 --- /dev/null +++ b/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetConfigurationByKey/GetConfigurationByKeyQueryValidator.cs @@ -0,0 +1,28 @@ +namespace CMSMicroservice.Application.ConfigurationCQ.Queries.GetConfigurationByKey; + +public class GetConfigurationByKeyQueryValidator : AbstractValidator +{ + public GetConfigurationByKeyQueryValidator() + { + RuleFor(x => x.Scope) + .IsInEnum() + .WithMessage("محدوده تنظیمات معتبر نیست"); + + RuleFor(x => x.Key) + .NotEmpty() + .WithMessage("کلید تنظیمات الزامی است"); + } + + public Func>> ValidateValue => async (model, propertyName) => + { + var result = await ValidateAsync( + ValidationContext.CreateWithOptions( + (GetConfigurationByKeyQuery)model, + x => x.IncludeProperties(propertyName))); + + if (result.IsValid) + return Array.Empty(); + + return result.Errors.Select(e => e.ErrorMessage); + }; +} diff --git a/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetConfigurationHistory/GetConfigurationHistoryQuery.cs b/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetConfigurationHistory/GetConfigurationHistoryQuery.cs new file mode 100644 index 0000000..44d9274 --- /dev/null +++ b/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetConfigurationHistory/GetConfigurationHistoryQuery.cs @@ -0,0 +1,22 @@ +namespace CMSMicroservice.Application.ConfigurationCQ.Queries.GetConfigurationHistory; + +/// +/// Query برای دریافت تاریخچه تغییرات یک Configuration +/// +public record GetConfigurationHistoryQuery : IRequest +{ + /// + /// شناسه Configuration + /// + public long ConfigurationId { get; init; } + + /// + /// موقعیت صفحه‌بندی + /// + public PaginationState? PaginationState { get; init; } + + /// + /// مرتب‌سازی بر اساس + /// + public string? SortBy { get; init; } +} diff --git a/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetConfigurationHistory/GetConfigurationHistoryQueryHandler.cs b/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetConfigurationHistory/GetConfigurationHistoryQueryHandler.cs new file mode 100644 index 0000000..70d47c6 --- /dev/null +++ b/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetConfigurationHistory/GetConfigurationHistoryQueryHandler.cs @@ -0,0 +1,53 @@ +namespace CMSMicroservice.Application.ConfigurationCQ.Queries.GetConfigurationHistory; + +public class GetConfigurationHistoryQueryHandler : IRequestHandler +{ + private readonly IApplicationDbContext _context; + + public GetConfigurationHistoryQueryHandler(IApplicationDbContext context) + { + _context = context; + } + + public async Task Handle(GetConfigurationHistoryQuery request, CancellationToken cancellationToken) + { + // بررسی وجود Configuration + var configExists = await _context.SystemConfigurations + .AnyAsync(x => x.Id == request.ConfigurationId, cancellationToken); + + if (!configExists) + { + throw new NotFoundException(nameof(SystemConfiguration), request.ConfigurationId); + } + + var query = _context.SystemConfigurationHistories + .Where(x => x.ConfigurationId == request.ConfigurationId) + .ApplyOrder(sortBy: request.SortBy ?? "-Created") // پیش‌فرض: جدیدترین اول + .AsNoTracking() + .AsQueryable(); + + var meta = await query.GetMetaData(request.PaginationState, cancellationToken); + + var models = await query + .PaginatedListAsync(paginationState: request.PaginationState) + .Select(x => new GetConfigurationHistoryResponseModel + { + Id = x.Id, + ConfigurationId = x.ConfigurationId, + Scope = x.Scope, + Key = x.Key, + OldValue = x.OldValue, + NewValue = x.NewValue, + ChangeReason = x.Reason, + ChangedBy = x.PerformedBy, + Created = x.Created + }) + .ToListAsync(cancellationToken); + + return new GetConfigurationHistoryResponseDto + { + MetaData = meta, + Models = models + }; + } +} diff --git a/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetConfigurationHistory/GetConfigurationHistoryQueryValidator.cs b/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetConfigurationHistory/GetConfigurationHistoryQueryValidator.cs new file mode 100644 index 0000000..8c71a50 --- /dev/null +++ b/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetConfigurationHistory/GetConfigurationHistoryQueryValidator.cs @@ -0,0 +1,24 @@ +namespace CMSMicroservice.Application.ConfigurationCQ.Queries.GetConfigurationHistory; + +public class GetConfigurationHistoryQueryValidator : AbstractValidator +{ + public GetConfigurationHistoryQueryValidator() + { + RuleFor(x => x.ConfigurationId) + .GreaterThan(0) + .WithMessage("شناسه Configuration معتبر نیست"); + } + + public Func>> ValidateValue => async (model, propertyName) => + { + var result = await ValidateAsync( + ValidationContext.CreateWithOptions( + (GetConfigurationHistoryQuery)model, + x => x.IncludeProperties(propertyName))); + + if (result.IsValid) + return Array.Empty(); + + return result.Errors.Select(e => e.ErrorMessage); + }; +} diff --git a/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetConfigurationHistory/GetConfigurationHistoryResponseDto.cs b/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetConfigurationHistory/GetConfigurationHistoryResponseDto.cs new file mode 100644 index 0000000..48f795e --- /dev/null +++ b/src/CMSMicroservice.Application/ConfigurationCQ/Queries/GetConfigurationHistory/GetConfigurationHistoryResponseDto.cs @@ -0,0 +1,20 @@ +namespace CMSMicroservice.Application.ConfigurationCQ.Queries.GetConfigurationHistory; + +public class GetConfigurationHistoryResponseDto +{ + public MetaData MetaData { get; set; } + public List Models { get; set; } +} + +public class GetConfigurationHistoryResponseModel +{ + public long Id { get; set; } + public long ConfigurationId { get; set; } + public ConfigurationScope Scope { get; set; } + public string Key { get; set; } + public string? OldValue { get; set; } + public string NewValue { get; set; } + public string ChangeReason { get; set; } + public string ChangedBy { get; set; } + public DateTimeOffset Created { get; set; } +} diff --git a/src/CMSMicroservice.Application/GlobalUsings.cs b/src/CMSMicroservice.Application/GlobalUsings.cs index da6b801..a4f52a1 100644 --- a/src/CMSMicroservice.Application/GlobalUsings.cs +++ b/src/CMSMicroservice.Application/GlobalUsings.cs @@ -3,6 +3,12 @@ global using FluentValidation; global using Mapster; global using CMSMicroservice.Domain.Entities; +global using CMSMicroservice.Domain.Entities.Club; +global using CMSMicroservice.Domain.Entities.Network; +global using CMSMicroservice.Domain.Entities.Commission; +global using CMSMicroservice.Domain.Entities.Configuration; +global using CMSMicroservice.Domain.Entities.History; +global using CMSMicroservice.Domain.Enums; global using CMSMicroservice.Application.Common.Interfaces; global using System.Threading; global using System.Threading.Tasks;