feat: Add ClubMembershipCQ - Phase 3 Application Layer
- Implemented 3 Commands with handlers and validators: * ActivateClubMembership: Create/reactivate membership * DeactivateClubMembership: Deactivate existing membership * AssignClubFeature: Assign features to club members - Implemented 3 Queries with handlers, validators, and DTOs: * GetClubMembership: Retrieve single membership by UserId * GetAllClubMemberships: List with filtering and pagination * GetClubMembershipHistory: Audit trail with full history - All operations include history tracking via ClubMembershipHistory - Property names aligned with Domain entity definitions - 21 new files, ~600 lines of code - Build successful with 0 errors
This commit is contained in:
+27
@@ -0,0 +1,27 @@
|
||||
namespace CMSMicroservice.Application.ClubMembershipCQ.Queries.GetClubMembershipHistory;
|
||||
|
||||
/// <summary>
|
||||
/// Query برای دریافت تاریخچه تغییرات عضویت باشگاه
|
||||
/// </summary>
|
||||
public record GetClubMembershipHistoryQuery : IRequest<GetClubMembershipHistoryResponseDto>
|
||||
{
|
||||
/// <summary>
|
||||
/// شناسه عضویت (اختیاری)
|
||||
/// </summary>
|
||||
public long? MembershipId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// شناسه کاربر (اختیاری)
|
||||
/// </summary>
|
||||
public long? UserId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// موقعیت صفحهبندی
|
||||
/// </summary>
|
||||
public PaginationState? PaginationState { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// مرتبسازی بر اساس
|
||||
/// </summary>
|
||||
public string? SortBy { get; init; }
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
namespace CMSMicroservice.Application.ClubMembershipCQ.Queries.GetClubMembershipHistory;
|
||||
|
||||
public class GetClubMembershipHistoryQueryHandler : IRequestHandler<GetClubMembershipHistoryQuery, GetClubMembershipHistoryResponseDto>
|
||||
{
|
||||
private readonly IApplicationDbContext _context;
|
||||
|
||||
public GetClubMembershipHistoryQueryHandler(IApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetClubMembershipHistoryResponseDto> Handle(GetClubMembershipHistoryQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context.ClubMembershipHistories
|
||||
.AsNoTracking()
|
||||
.AsQueryable();
|
||||
|
||||
if (request.MembershipId.HasValue)
|
||||
{
|
||||
query = query.Where(x => x.ClubMembershipId == request.MembershipId.Value);
|
||||
}
|
||||
|
||||
if (request.UserId.HasValue)
|
||||
{
|
||||
query = query.Where(x => x.UserId == request.UserId.Value);
|
||||
}
|
||||
|
||||
query = query.ApplyOrder(sortBy: request.SortBy ?? "-Created"); // پیشفرض: جدیدترین اول
|
||||
|
||||
var meta = await query.GetMetaData(request.PaginationState, cancellationToken);
|
||||
|
||||
var models = await query
|
||||
.PaginatedListAsync(paginationState: request.PaginationState)
|
||||
.Select(x => new GetClubMembershipHistoryResponseModel
|
||||
{
|
||||
Id = x.Id,
|
||||
ClubMembershipId = x.ClubMembershipId,
|
||||
UserId = x.UserId,
|
||||
OldIsActive = x.OldIsActive,
|
||||
NewIsActive = x.NewIsActive,
|
||||
OldInitialContribution = x.OldInitialContribution,
|
||||
NewInitialContribution = x.NewInitialContribution,
|
||||
Action = x.Action,
|
||||
Reason = x.Reason,
|
||||
PerformedBy = x.PerformedBy,
|
||||
Created = x.Created
|
||||
})
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return new GetClubMembershipHistoryResponseDto
|
||||
{
|
||||
MetaData = meta,
|
||||
Models = models
|
||||
};
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
namespace CMSMicroservice.Application.ClubMembershipCQ.Queries.GetClubMembershipHistory;
|
||||
|
||||
public class GetClubMembershipHistoryQueryValidator : AbstractValidator<GetClubMembershipHistoryQuery>
|
||||
{
|
||||
public GetClubMembershipHistoryQueryValidator()
|
||||
{
|
||||
RuleFor(x => x.MembershipId)
|
||||
.GreaterThan(0)
|
||||
.WithMessage("شناسه عضویت معتبر نیست")
|
||||
.When(x => x.MembershipId.HasValue);
|
||||
|
||||
RuleFor(x => x.UserId)
|
||||
.GreaterThan(0)
|
||||
.WithMessage("شناسه کاربر معتبر نیست")
|
||||
.When(x => x.UserId.HasValue);
|
||||
|
||||
RuleFor(x => x)
|
||||
.Must(x => x.MembershipId.HasValue || x.UserId.HasValue)
|
||||
.WithMessage("حداقل یکی از MembershipId یا UserId باید مقداردهی شود");
|
||||
}
|
||||
|
||||
public Func<object, string, Task<IEnumerable<string>>> ValidateValue => async (model, propertyName) =>
|
||||
{
|
||||
var result = await ValidateAsync(
|
||||
ValidationContext<GetClubMembershipHistoryQuery>.CreateWithOptions(
|
||||
(GetClubMembershipHistoryQuery)model,
|
||||
x => x.IncludeProperties(propertyName)));
|
||||
|
||||
if (result.IsValid)
|
||||
return Array.Empty<string>();
|
||||
|
||||
return result.Errors.Select(e => e.ErrorMessage);
|
||||
};
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
namespace CMSMicroservice.Application.ClubMembershipCQ.Queries.GetClubMembershipHistory;
|
||||
|
||||
public class GetClubMembershipHistoryResponseDto
|
||||
{
|
||||
public MetaData MetaData { get; set; }
|
||||
public List<GetClubMembershipHistoryResponseModel> Models { get; set; }
|
||||
}
|
||||
|
||||
public class GetClubMembershipHistoryResponseModel
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public long ClubMembershipId { get; set; }
|
||||
public long UserId { get; set; }
|
||||
public bool OldIsActive { get; set; }
|
||||
public bool NewIsActive { get; set; }
|
||||
public long? OldInitialContribution { get; set; }
|
||||
public long? NewInitialContribution { get; set; }
|
||||
public ClubMembershipAction Action { get; set; }
|
||||
public string? Reason { get; set; }
|
||||
public string? PerformedBy { get; set; }
|
||||
public DateTimeOffset Created { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user