feat: update protobuf versions and enhance club membership and commission queries
Build and Deploy / build (push) Successful in 1m41s

This commit is contained in:
masoodafar-web
2025-12-20 03:16:36 +03:30
parent 6b72e88780
commit f234af49e0
55 changed files with 352 additions and 150 deletions
@@ -2,7 +2,7 @@ namespace BackOffice.BFF.Application.CommissionCQ.Commands.TriggerWeeklyCalculat
public class TriggerWeeklyCalculationCommand : IRequest<TriggerWeeklyCalculationResponseDto>
{
public string WeekNumber { get; set; } = string.Empty;
public long WeekDefinitionId { get; set; }
public bool ForceRecalculate { get; set; }
public bool SkipBalances { get; set; }
public bool SkipPool { get; set; }
@@ -17,7 +17,7 @@ public class TriggerWeeklyCalculationCommandHandler : IRequestHandler<TriggerWee
{
var grpcRequest = new TriggerWeeklyCalculationRequest
{
WeekNumber = request.WeekNumber,
WeekDefinitionId = request.WeekDefinitionId,
ForceRecalculate = request.ForceRecalculate,
SkipBalances = request.SkipBalances,
SkipPool = request.SkipPool,
@@ -9,7 +9,8 @@ public record GetAllWeeklyPoolsResponseDto
public record WeeklyCommissionPoolDto
{
public long Id { get; init; }
public string WeekNumber { get; init; } = string.Empty;
public long WeekDefinitionId { get; init; }
public string WeekDisplayName { get; init; } = string.Empty;
public long TotalPoolAmount { get; init; }
public int TotalBalances { get; init; }
public long ValuePerBalance { get; init; }
@@ -39,7 +39,8 @@ public class GetAvailableWeeksQueryHandler : IRequestHandler<GetAvailableWeeksQu
{
return new WeekInfoDto
{
WeekNumber = weekInfo.WeekNumber,
WeekDefinitionId = weekInfo.WeekDefinitionId,
DisplayName = weekInfo.DisplayName,
StartDate = weekInfo.StartDate?.ToDateTime() ?? DateTime.MinValue,
EndDate = weekInfo.EndDate?.ToDateTime() ?? DateTime.MinValue,
IsCalculated = weekInfo.IsCalculated,
@@ -10,7 +10,8 @@ public class GetAvailableWeeksResponseDto
public class WeekInfoDto
{
public required string WeekNumber { get; init; }
public required long WeekDefinitionId { get; init; }
public required string DisplayName { get; init; }
public required DateTime StartDate { get; init; }
public required DateTime EndDate { get; init; }
public bool IsCalculated { get; init; }
@@ -26,9 +26,9 @@ public class GetUserPayoutsFilter
public long? UserId { get; set; }
/// <summary>
/// شماره هفته (اختیاری - برای فیلتر)
/// شناسه هفته (اختیاری - برای فیلتر)
/// </summary>
public string? WeekNumber { get; set; }
public long? WeekDefinitionId { get; set; }
/// <summary>
/// وضعیت (اختیاری)
@@ -24,9 +24,9 @@ public class GetUserPayoutsQueryHandler : IRequestHandler<GetUserPayoutsQuery, G
cmsRequest.UserId = request.Filter.UserId.Value;
}
if (!string.IsNullOrWhiteSpace(request.Filter?.WeekNumber))
if (request.Filter?.WeekDefinitionId.HasValue == true && request.Filter.WeekDefinitionId.Value > 0)
{
cmsRequest.WeekNumber = request.Filter.WeekNumber;
cmsRequest.WeekDefinitionId = request.Filter.WeekDefinitionId.Value;
}
if (request.Filter?.Status.HasValue == true)
@@ -52,7 +52,8 @@ public class GetUserPayoutsQueryHandler : IRequestHandler<GetUserPayoutsQuery, G
Id = m.Id,
UserId = m.UserId,
UserName = m.UserName,
WeekNumber = m.WeekNumber,
WeekDefinitionId = m.WeekDefinitionId,
WeekDisplayName = m.WeekDisplayName,
BalancesEarned = (int)m.BalancesEarned,
ValuePerBalance = m.ValuePerBalance,
TotalAmount = m.TotalAmount,
@@ -31,9 +31,14 @@ public class GetUserPayoutsResponseModel
public string UserName { get; set; } = string.Empty;
/// <summary>
/// شماره هفته
/// شناسه هفته
/// </summary>
public string WeekNumber { get; set; } = string.Empty;
public long WeekDefinitionId { get; set; }
/// <summary>
/// نام نمایشی هفته
/// </summary>
public string WeekDisplayName { get; set; } = string.Empty;
/// <summary>
/// تعداد تعادل‌های کسب شده
@@ -26,9 +26,9 @@ public class GetUserWeeklyBalancesFilter
public long? UserId { get; set; }
/// <summary>
/// شماره هفته (فیلتر اختیاری)
/// شناسه هفته (فیلتر اختیاری)
/// </summary>
public string? WeekNumber { get; set; }
public long? WeekDefinitionId { get; set; }
/// <summary>
/// فقط تعادل‌های فعال (منقضی نشده)
@@ -27,9 +27,9 @@ public class GetUserWeeklyBalancesQueryHandler : IRequestHandler<GetUserWeeklyBa
grpcRequest.UserId = request.Filter.UserId.Value;
}
if (!string.IsNullOrWhiteSpace(request.Filter?.WeekNumber))
if (request.Filter?.WeekDefinitionId.HasValue == true && request.Filter.WeekDefinitionId.Value > 0)
{
grpcRequest.WeekNumber = request.Filter.WeekNumber;
grpcRequest.WeekDefinitionId = request.Filter.WeekDefinitionId.Value;
}
var response = await _context.Commissions.GetUserWeeklyBalancesAsync(grpcRequest, cancellationToken: cancellationToken);
@@ -15,10 +15,10 @@ public class GetUserWeeklyBalancesQueryValidator : AbstractValidator<GetUserWeek
.When(x => x.Filter!.UserId.HasValue)
.WithMessage("شناسه کاربر معتبر نیست");
RuleFor(x => x.Filter!.WeekNumber)
.Matches(@"^\d{4}-W\d{2}$")
.When(x => !string.IsNullOrWhiteSpace(x.Filter!.WeekNumber))
.WithMessage("فرمت شماره هفته باید به صورت YYYY-Www باشد (مثال: 2025-W48)");
RuleFor(x => x.Filter!.WeekDefinitionId)
.GreaterThan(0)
.When(x => x.Filter!.WeekDefinitionId.HasValue)
.WithMessage("شناسه هفته معتبر نیست");
});
}
}
@@ -10,7 +10,8 @@ public record UserWeeklyBalanceDto
{
public long Id { get; init; }
public long UserId { get; init; }
public string WeekNumber { get; init; } = string.Empty;
public long WeekDefinitionId { get; init; }
public string WeekDisplayName { get; init; } = string.Empty;
public int LeftLegBalances { get; init; }
public int RightLegBalances { get; init; }
public int TotalBalances { get; init; }
@@ -3,7 +3,7 @@ namespace BackOffice.BFF.Application.CommissionCQ.Queries.GetWeeklyPool;
public record GetWeeklyPoolQuery : IRequest<GetWeeklyPoolResponseDto>
{
/// <summary>
/// شماره هفته (فرمت: YYYY-Www مثلاً 2025-W48)
/// شناسه هفته
/// </summary>
public string WeekNumber { get; init; } = string.Empty;
public long WeekDefinitionId { get; init; }
}
@@ -3,7 +3,7 @@ namespace BackOffice.BFF.Application.CommissionCQ.Queries.GetWeeklyPool;
public class GetWeeklyPoolResponseDto
{
public long Id { get; set; }
public string WeekNumber { get; set; } = string.Empty;
public long WeekDefinitionId { get; set; }
public long TotalPoolAmount { get; set; }
public long TotalBalances { get; set; }
public decimal ValuePerBalance { get; set; }
@@ -2,7 +2,7 @@ namespace BackOffice.BFF.Application.CommissionCQ.Queries.GetWorkerExecutionLogs
public class GetWorkerExecutionLogsQuery : IRequest<GetWorkerExecutionLogsResponseDto>
{
public string? WeekNumber { get; set; }
public long? WeekDefinitionId { get; set; }
public string? ExecutionId { get; set; }
public bool? SuccessOnly { get; set; }
public bool? FailedOnly { get; set; }
@@ -21,9 +21,9 @@ public class GetWorkerExecutionLogsQueryHandler : IRequestHandler<GetWorkerExecu
PageSize = request.PageSize
};
if (!string.IsNullOrWhiteSpace(request.WeekNumber))
if (request.WeekDefinitionId.HasValue && request.WeekDefinitionId.Value > 0)
{
grpcRequest.WeekNumber = request.WeekNumber;
grpcRequest.WeekDefinitionId = request.WeekDefinitionId.Value;
}
if (!string.IsNullOrWhiteSpace(request.ExecutionId))
@@ -9,7 +9,8 @@ public class GetWorkerExecutionLogsResponseDto
public class WorkerExecutionLogModel
{
public string ExecutionId { get; set; } = string.Empty;
public string WeekNumber { get; set; } = string.Empty;
public long WeekDefinitionId { get; set; }
public string WeekDisplayName { get; set; } = string.Empty;
public string Step { get; set; } = string.Empty;
public bool Success { get; set; }
public string? ErrorMessage { get; set; }
@@ -11,7 +11,7 @@ public class CommissionProfile : IRegister
.Map(dest => dest.Id, src => src.Id)
.Map(dest => dest.CalculatedAt, src => src.CalculatedAt)
.Map(dest => dest.IsCalculated, src => src.IsCalculated)
.Map(dest => dest.WeekNumber, src => src.WeekNumber)
.Map(dest => dest.WeekDefinitionId, src => src.WeekDefinitionId)
.Map(dest => dest.TotalPoolAmount, src => src.TotalPoolAmount)
.Map(dest => dest.ValuePerBalance, src => src.ValuePerBalance)
.Map(dest => dest.TotalBalances, src => src.TotalBalances)
@@ -16,18 +16,26 @@ public class GetAllConfigurationsQueryHandler : IRequestHandler<GetAllConfigurat
{
var grpcRequest = new GetAllConfigurationsRequest
{
PageIndex = request.PageIndex,
PageSize = request.PageSize
PaginationState = new CMSMicroservice.Protobuf.Protos.PaginationState
{
PageNumber = request.PageIndex,
PageSize = request.PageSize
}
};
if (request.Scope.HasValue)
if (request.Scope.HasValue || request.IsActive.HasValue)
{
grpcRequest.Scope = request.Scope.Value;
}
grpcRequest.Filter = new GetAllConfigurationsFilter();
if (request.Scope.HasValue)
{
grpcRequest.Filter.Scope = request.Scope.Value;
}
if (request.IsActive.HasValue)
{
grpcRequest.IsActive = request.IsActive.Value;
if (request.IsActive.HasValue)
{
grpcRequest.Filter.IsActive = request.IsActive.Value;
}
}
var response = await _context.Configurations.GetAllConfigurationsAsync(grpcRequest, cancellationToken: cancellationToken);
@@ -63,8 +63,11 @@ public class GetSystemHealthQueryHandler : IRequestHandler<GetSystemHealthQuery,
await _context.Configurations.GetAllConfigurationsAsync(
new GetAllConfigurationsRequest
{
PageIndex = 1,
PageSize = 1
PaginationState = new CMSMicroservice.Protobuf.Protos.PaginationState
{
PageNumber = 1,
PageSize = 1
}
},
cancellationToken: cancellationToken);
stopwatch.Stop();
@@ -25,5 +25,5 @@ public record GetNetworkTreeQuery : IRequest<GetNetworkTreeResponseDto>
/// <summary>
/// فیلتر براساس شماره هفته فعالسازی (مثال: 2025-W05)
/// </summary>
public string? ActivationWeekNumber { get; init; }
public long? ActivationWeekDefinitionId { get; init; }
}
@@ -59,7 +59,7 @@ public class NetworkTreeNodeDto
/// <summary>
/// شماره هفته فعال‌سازی
/// </summary>
public string ActivationWeekNumber { get; set; } = string.Empty;
public long? ActivationWeekDefinitionId { get; set; }
/// <summary>
/// تاریخ ایجاد کاربر
@@ -8,6 +8,7 @@ public record CreateNewProductsCommand : IRequest<CreateNewProductsResponseDto>
public long Price { get; init; }
public int Discount { get; init; }
public int Rate { get; init; }
public int RemainingCount { get; init; }
public ImageFileModel ImageFile { get; init; }
public ImageFileModel ThumbnailFile { get; init; }
// لیست شناسه دسته‌بندی‌های محصول
@@ -9,6 +9,7 @@ public record UpdateProductsCommand : IRequest<Unit>
public long Price { get; init; }
public int Discount { get; init; }
public int Rate { get; init; }
public int RemainingCount { get; init; }
public string ImagePath { get; init; }
public string ThumbnailPath { get; init; }
public ImageFileModel ImageFile { get; init; }
@@ -7,7 +7,7 @@
<ItemGroup>
<PackageReference Include="Afrino.FMSMicroservice.Protobuf" Version="0.0.122" />
<PackageReference Include="Foursat.CMSMicroservice.Protobuf" Version="0.0.155" />
<PackageReference Include="Foursat.CMSMicroservice.Protobuf" Version="0.0.156" />
<PackageReference Include="Google.Protobuf" Version="3.23.3" />
<PackageReference Include="Grpc.Net.ClientFactory" Version="2.54.0" />
@@ -1,29 +1,124 @@
using BackOffice.BFF.Application.ClubMembershipCQ.Queries.GetAllClubMembers;
using BackOffice.BFF.Application.ClubMembershipCQ.Queries.GetClubStatistics;
using Google.Protobuf.WellKnownTypes;
using BffProtos = Foursat.BackOffice.BFF.ClubMembership.Protos;
using CmsProtos = CMSMicroservice.Protobuf.Protos.ClubMembership;
namespace BackOffice.BFF.WebApi.Common.Mappings;
public class ClubMembershipProfile : IRegister
{
void IRegister.Register(TypeAdapterConfig config)
{
// GetAllClubMembersResponseDto -> GetAllClubMembershipsResponse
// config.NewConfig<GetAllClubMembersResponseDto, GetAllClubMembershipsResponse>()
// .MapWith(src => new GetAllClubMembershipsResponse
// {
// Members = { src.Members.Select(m => new ClubMemberModel
// {
// Id = m.Id,
// UserId = m.UserId,
// UserName = m.UserName ?? string.Empty,
// ActivationDate = Timestamp.FromDateTime(DateTime.SpecifyKind(m.ActivationDate, DateTimeKind.Utc)),
// InitialContribution = m.InitialContribution,
// CurrentBalance = m.CurrentBalance,
// TotalEarnings = m.TotalEarnings,
// IsActive = m.IsActive,
// ClubLevel = m.ClubLevel,
// ClubLevelDisplay = m.ClubLevelDisplay ?? string.Empty
// }) },
// TotalCount = src.TotalCount,
// PageNumber = src.PageNumber,
// PageSize = src.PageSize
// });
// =====================
// GetAllClubMemberships
// =====================
// BFF Proto Request -> Query
config.NewConfig<BffProtos.GetAllClubMembershipsRequest, GetAllClubMembersQuery>()
.MapWith(src => new GetAllClubMembersQuery
{
IsActive = src.IsActive,
PageNumber = src.PageIndex > 0 ? src.PageIndex : 1,
PageSize = src.PageSize > 0 ? src.PageSize : 20
});
// Query -> CMS Proto Request
config.NewConfig<GetAllClubMembersQuery, CmsProtos.GetAllClubMembershipsRequest>()
.MapWith(src => new CmsProtos.GetAllClubMembershipsRequest
{
IsActive = src.IsActive,
PageIndex = src.PageNumber,
PageSize = src.PageSize
});
// CMS Proto Response -> DTO
config.NewConfig<CmsProtos.GetAllClubMembershipsResponse, GetAllClubMembersResponseDto>()
.MapWith(src => new GetAllClubMembersResponseDto
{
TotalCount = (int)(src.MetaData != null ? src.MetaData.TotalCount : 0),
PageNumber = (int)(src.MetaData != null ? src.MetaData.CurrentPage : 1),
PageSize = (int)(src.MetaData != null ? src.MetaData.PageSize : 20),
Members = src.Models.Select(m => new ClubMemberDto
{
Id = m.Id,
UserId = m.UserId,
UserName = m.UserName ?? string.Empty,
ActivationDate = m.ActivatedAt != null ? m.ActivatedAt.ToDateTime() : DateTime.MinValue,
IsActive = m.IsActive
}).ToList()
});
// DTO -> BFF Proto Response
config.NewConfig<GetAllClubMembersResponseDto, BffProtos.GetAllClubMembershipsResponse>()
.MapWith(src => new BffProtos.GetAllClubMembershipsResponse
{
MetaData = new BackOffice.BFF.Protobuf.Common.MetaData
{
CurrentPage = src.PageNumber,
PageSize = src.PageSize,
TotalCount = src.TotalCount,
TotalPage = (int)Math.Ceiling((double)src.TotalCount / src.PageSize)
},
Models = { src.Members.Select(m => new BffProtos.ClubMembershipModel
{
Id = m.Id,
UserId = m.UserId,
UserName = m.UserName ?? string.Empty,
PackageId = 0,
PackageName = string.Empty,
ActivationCode = string.Empty,
ActivatedAt = Timestamp.FromDateTime(DateTime.SpecifyKind(m.ActivationDate, DateTimeKind.Utc)),
ExpiresAt = null,
IsActive = m.IsActive,
IsExpired = false,
Created = Timestamp.FromDateTime(DateTime.SpecifyKind(m.ActivationDate, DateTimeKind.Utc))
}) }
});
// =====================
// GetClubStatistics
// =====================
// BFF Proto Request -> Query
config.NewConfig<BffProtos.GetClubStatisticsRequest, GetClubStatisticsQuery>()
.MapWith(src => new GetClubStatisticsQuery());
// CMS Proto Response -> DTO
config.NewConfig<CmsProtos.GetClubStatisticsResponse, GetClubStatisticsResponseDto>()
.MapWith(src => new GetClubStatisticsResponseDto
{
TotalMemberships = src.TotalMembers,
ActiveMemberships = src.ActiveMembers,
InactiveMemberships = src.InactiveMembers,
ActivePercentage = src.ActivePercentage,
TotalRevenue = src.TotalRevenue,
AverageDurationDays = src.AverageMembershipDurationDays,
MonthlyTrends = src.MonthlyTrend.Select(t => new MonthlyMembershipTrendModel
{
Month = t.Month,
NewMemberships = t.Activations,
ExpiredMemberships = t.Expirations
}).ToList()
});
// DTO -> BFF Proto Response
config.NewConfig<GetClubStatisticsResponseDto, BffProtos.GetClubStatisticsResponse>()
.MapWith(src => new BffProtos.GetClubStatisticsResponse
{
TotalMembers = src.TotalMemberships,
ActiveMembers = src.ActiveMemberships,
InactiveMembers = src.InactiveMemberships,
ActivePercentage = src.ActivePercentage,
TotalRevenue = (long)src.TotalRevenue,
AverageMembershipDurationDays = src.AverageDurationDays,
MonthlyTrend = { src.MonthlyTrends.Select(t => new BffProtos.MonthlyMembershipTrend
{
Month = t.Month,
Activations = t.NewMemberships,
Expirations = t.ExpiredMemberships,
NetChange = t.NewMemberships - t.ExpiredMemberships
}) }
});
}
}
@@ -27,18 +27,35 @@ public class CommissionProfile : IRegister
? new BackOffice.BFF.Application.CommissionCQ.Queries.GetUserPayouts.GetUserPayoutsFilter
{
UserId = src.Filter.UserId,
WeekNumber = src.Filter.WeekNumber,
WeekDefinitionId = src.Filter.WeekDefinitionId,
Status = src.Filter.Status
}
: null
});
// GetUserWeeklyBalancesRequest -> GetUserWeeklyBalancesQuery
config.NewConfig<GetUserWeeklyBalancesRequest, GetUserWeeklyBalancesQuery>()
.MapWith(src => new GetUserWeeklyBalancesQuery
{
PaginationState = new BackOffice.BFF.Application.Common.Models.PaginationState
{
PageNumber = src.PageIndex > 0 ? src.PageIndex : 1,
PageSize = src.PageSize > 0 ? src.PageSize : 10
},
Filter = new GetUserWeeklyBalancesFilter
{
UserId = src.UserId,
WeekDefinitionId = src.WeekDefinitionId,
OnlyActive = src.OnlyActive
}
});
// GetWeeklyPoolResponseDto -> GetWeeklyCommissionPoolResponse
config.NewConfig<GetWeeklyPoolResponseDto, GetWeeklyCommissionPoolResponse>()
.MapWith(src => new GetWeeklyCommissionPoolResponse
{
Id = src.Id,
WeekNumber = src.WeekNumber ?? string.Empty,
WeekDefinitionId = src.WeekDefinitionId,
TotalBalances = (int)src.TotalBalances,
TotalPoolAmount = src.TotalPoolAmount,
@@ -94,7 +111,8 @@ public class CommissionProfile : IRegister
Models = { src.Models.Select(m => new WeeklyCommissionPoolModel
{
Id = m.Id,
WeekNumber = m.WeekNumber ?? string.Empty,
WeekDefinitionId = m.WeekDefinitionId,
WeekDisplayName = m.WeekDisplayName ?? string.Empty,
TotalPoolAmount = m.TotalPoolAmount,
TotalBalances = m.TotalBalances,
ValuePerBalance = m.ValuePerBalance,
@@ -121,7 +139,8 @@ public class CommissionProfile : IRegister
{
Id = m.Id,
UserId = m.UserId,
WeekNumber = m.WeekNumber ?? string.Empty,
WeekDefinitionId = m.WeekDefinitionId,
WeekDisplayName = m.WeekDisplayName ?? string.Empty,
LeftLegBalances = m.LeftLegBalances,
RightLegBalances = m.RightLegBalances,
TotalBalances = m.TotalBalances,
@@ -204,7 +223,8 @@ public class CommissionProfile : IRegister
{
return new WeekInfo
{
WeekNumber = dto.WeekNumber,
WeekDefinitionId = dto.WeekDefinitionId,
DisplayName = dto.DisplayName,
StartDate = Timestamp.FromDateTime(dto.StartDate.ToUniversalTime()),
EndDate = Timestamp.FromDateTime(dto.EndDate.ToUniversalTime()),
IsCalculated = dto.IsCalculated,
@@ -1,6 +1,7 @@
using BackOffice.BFF.Application.NetworkMembershipCQ.Queries.GetNetworkTree;
using BackOffice.BFF.Application.NetworkMembershipCQ.Queries.GetUserNetworkInfo;
using BackOffice.BFF.Application.NetworkMembershipCQ.Queries.GetNetworkHistory;
using BackOffice.BFF.Application.NetworkMembershipCQ.Queries.GetNetworkStatistics;
using Foursat.BackOffice.BFF.NetworkMembership.Protos;
namespace BackOffice.BFF.WebApi.Common.Mappings;
@@ -9,6 +10,10 @@ public class NetworkMembershipProfile : IRegister
{
void IRegister.Register(TypeAdapterConfig config)
{
// GetNetworkStatisticsRequest -> GetNetworkStatisticsQuery
config.NewConfig<GetNetworkStatisticsRequest, GetNetworkStatisticsQuery>()
.MapWith(src => new GetNetworkStatisticsQuery());
// GetNetworkTreeResponseDto -> GetNetworkTreeResponse
config.NewConfig<GetNetworkTreeResponseDto, GetNetworkTreeResponse>()
.MapWith(src => new GetNetworkTreeResponse
@@ -28,7 +33,7 @@ public class NetworkMembershipProfile : IRegister
? Timestamp.FromDateTime(DateTime.SpecifyKind(n.ClubActivatedAt.Value, DateTimeKind.Utc))
: null,
IsClubActive = n.IsClubActive,
ActivationWeekNumber = n.ActivationWeekNumber,
ActivationWeekDefinitionId = n.ActivationWeekDefinitionId,
IsActivatedInTargetWeek =n.IsActivatedInTargetWeek,
UserCreated = n.UserCreated.HasValue
? Timestamp.FromDateTime(DateTime.SpecifyKind(n.UserCreated.Value, DateTimeKind.Utc))
@@ -53,7 +58,7 @@ public class NetworkMembershipProfile : IRegister
? Timestamp.FromDateTime(DateTime.SpecifyKind(src.ClubActivatedAt.Value, DateTimeKind.Utc))
: null,
IsClubActive = src.IsClubActive,
ActivationWeekNumber = src.ActivationWeekNumber,
ActivationWeekDefinitionId = src.ActivationWeekDefinitionId,
UserCreated = src.UserCreated.HasValue
? Timestamp.FromDateTime(DateTime.SpecifyKind(src.UserCreated.Value, DateTimeKind.Utc))
: null
@@ -142,5 +147,38 @@ public class NetworkMembershipProfile : IRegister
Created = Timestamp.FromDateTime(DateTime.SpecifyKind(h.CreatedAt, DateTimeKind.Utc))
}) }
});
// GetNetworkStatisticsResponseDto -> GetNetworkStatisticsResponse
config.NewConfig<GetNetworkStatisticsResponseDto, GetNetworkStatisticsResponse>()
.MapWith(src => new GetNetworkStatisticsResponse
{
TotalMembers = src.TotalMembers,
ActiveMembers = src.ActiveMembers,
LeftLegCount = src.LeftLegCount,
RightLegCount = src.RightLegCount,
LeftPercentage = src.LeftPercentage,
RightPercentage = src.RightPercentage,
AverageDepth = src.AverageDepth,
MaxDepth = src.MaxDepth,
LevelDistribution = { src.LevelDistribution.Select(l => new LevelDistribution
{
Level = l.Level,
Count = l.Count
}) },
MonthlyGrowth = { src.MonthlyGrowth.Select(m => new MonthlyGrowth
{
Month = m.Month,
NewMembers = m.NewMembers
}) },
TopUsers = { src.TopUsers.Select(u => new TopNetworkUser
{
Rank = u.Rank,
UserId = u.UserId,
UserName = u.UserName,
TotalChildren = u.TotalChildren,
LeftCount = u.LeftCount,
RightCount = u.RightCount
}) }
});
}
}
@@ -1,6 +1,7 @@
using BackOffice.BFF.WebApi.Common.Services;
using BackOffice.BFF.Application.ClubMembershipCQ.Commands.ActivateClub;
using BackOffice.BFF.Application.ClubMembershipCQ.Queries.GetAllClubMembers;
using BackOffice.BFF.Application.ClubMembershipCQ.Queries.GetClubStatistics;
using Foursat.BackOffice.BFF.ClubMembership.Protos;
namespace BackOffice.BFF.WebApi.Services;
@@ -31,4 +32,13 @@ public class ClubMembershipService : ClubMembershipContract.ClubMembershipContra
request,
context);
}
public override async Task<GetClubStatisticsResponse> GetClubStatistics(
GetClubStatisticsRequest request,
ServerCallContext context)
{
return await _dispatchRequestToCQRS.Handle<GetClubStatisticsRequest, GetClubStatisticsQuery, GetClubStatisticsResponse>(
request,
context);
}
}
@@ -2,6 +2,7 @@ using BackOffice.BFF.WebApi.Common.Services;
using BackOffice.BFF.Application.NetworkMembershipCQ.Queries.GetUserNetworkInfo;
using BackOffice.BFF.Application.NetworkMembershipCQ.Queries.GetNetworkTree;
using BackOffice.BFF.Application.NetworkMembershipCQ.Queries.GetNetworkHistory;
using BackOffice.BFF.Application.NetworkMembershipCQ.Queries.GetNetworkStatistics;
using Foursat.BackOffice.BFF.NetworkMembership.Protos;
namespace BackOffice.BFF.WebApi.Services;
@@ -42,4 +43,13 @@ public class NetworkMembershipService : NetworkMembershipContract.NetworkMembers
request,
context);
}
public override async Task<GetNetworkStatisticsResponse> GetNetworkStatistics(
GetNetworkStatisticsRequest request,
ServerCallContext context)
{
return await _dispatchRequestToCQRS.Handle<GetNetworkStatisticsRequest, GetNetworkStatisticsQuery, GetNetworkStatisticsResponse>(
request,
context);
}
}
@@ -4,7 +4,7 @@
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>0.0.4</Version>
<Version>0.0.5</Version>
<DebugType>None</DebugType>
<DebugSymbols>False</DebugSymbols>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
@@ -6,7 +6,7 @@
<Nullable>enable</Nullable>
<IsPackable>true</IsPackable>
<PackageId>Foursat.BackOffice.BFF.ClubMembership.Protobuf</PackageId>
<Version>0.0.6</Version>
<Version>0.0.7</Version>
<Authors>FourSat</Authors>
<Company>FourSat</Company>
<Product>Foursat.BackOffice.BFF.ClubMembership.Protobuf</Product>
@@ -6,7 +6,7 @@
<Nullable>enable</Nullable>
<IsPackable>true</IsPackable>
<PackageId>Foursat.BackOffice.BFF.Commission.Protobuf</PackageId>
<Version>0.0.12</Version>
<Version>0.0.13</Version>
<Authors>FourSat</Authors>
<Company>FourSat</Company>
<Product>BackOffice.BFF.Commission.Protobuf</Product>
@@ -122,20 +122,20 @@ service CommissionContract
// CalculateWeeklyBalances Command
message CalculateWeeklyBalancesRequest
{
string week_number = 1; // Format: "YYYY-Www" (e.g., "2025-W01")
int64 week_definition_id = 1;
bool force_recalculate = 2;
}
// CalculateWeeklyCommissionPool Command
message CalculateWeeklyCommissionPoolRequest
{
string week_number = 1;
int64 week_definition_id = 1;
}
// ProcessUserPayouts Command
message ProcessUserPayoutsRequest
{
string week_number = 1;
int64 week_definition_id = 1;
bool force_reprocess = 2;
}
@@ -174,13 +174,13 @@ message RejectWithdrawalRequest
// GetWeeklyCommissionPool Query
message GetWeeklyCommissionPoolRequest
{
string week_number = 1;
int64 week_definition_id = 1;
}
message GetWeeklyCommissionPoolResponse
{
int64 id = 1;
string week_number = 2;
int64 week_definition_id = 2;
int64 total_pool_amount = 3; // Rials
int32 total_balances = 4;
int64 value_per_balance = 5; // Rials per balance
@@ -201,7 +201,7 @@ message GetUserPayoutsFilter
{
google.protobuf.Int64Value user_id = 1;
google.protobuf.Int32Value status = 2; // CommissionPayoutStatus enum
google.protobuf.StringValue week_number = 3;
google.protobuf.Int64Value week_definition_id = 3;
}
@@ -216,15 +216,16 @@ message UserCommissionPayoutModel
int64 id = 1;
int64 user_id = 2;
string user_name = 3;
string week_number = 4;
int32 balances_earned = 5;
int64 value_per_balance = 6;
int64 total_amount = 7;
int32 status = 8; // CommissionPayoutStatus enum (0=Pending, 1=Paid, 2=Failed)
google.protobuf.Int32Value withdrawal_method = 9;
string iban_number = 10;
google.protobuf.Timestamp created = 11;
google.protobuf.Timestamp last_modified = 12;
int64 week_definition_id = 4;
string week_display_name = 5;
int32 balances_earned = 6;
int64 value_per_balance = 7;
int64 total_amount = 8;
int32 status = 9; // CommissionPayoutStatus enum (0=Pending, 1=Paid, 2=Failed)
google.protobuf.Int32Value withdrawal_method = 10;
string iban_number = 11;
google.protobuf.Timestamp created = 12;
google.protobuf.Timestamp last_modified = 13;
}
// GetCommissionPayoutHistory Query
@@ -232,7 +233,7 @@ message GetCommissionPayoutHistoryRequest
{
google.protobuf.Int64Value payout_id = 1;
google.protobuf.Int64Value user_id = 2;
google.protobuf.StringValue week_number = 3;
google.protobuf.Int64Value week_definition_id = 3;
messages.PaginationState pagination_state = 4;
}
@@ -247,7 +248,7 @@ message CommissionPayoutHistoryModel
int64 id = 1;
int64 payout_id = 2;
int64 user_id = 3;
string week_number = 4;
int64 week_definition_id = 4;
int64 amount_before = 5;
int64 amount_after = 6;
int32 old_status = 7; // CommissionPayoutStatus enum
@@ -262,7 +263,7 @@ message CommissionPayoutHistoryModel
message GetUserWeeklyBalancesRequest
{
google.protobuf.Int64Value user_id = 1;
google.protobuf.StringValue week_number = 2;
google.protobuf.Int64Value week_definition_id = 2;
bool only_active = 3; // Only non-expired balances
int32 page_index = 4;
int32 page_size = 5;
@@ -278,14 +279,15 @@ message UserWeeklyBalanceModel
{
int64 id = 1;
int64 user_id = 2;
string week_number = 3;
int32 left_leg_balances = 4;
int32 right_leg_balances = 5;
int32 total_balances = 6;
int64 weekly_pool_contribution = 7;
google.protobuf.Timestamp calculated_at = 8;
bool is_expired = 9;
google.protobuf.Timestamp created = 10;
int64 week_definition_id = 3;
string week_display_name = 4;
int32 left_leg_balances = 5;
int32 right_leg_balances = 6;
int32 total_balances = 7;
int64 weekly_pool_contribution = 8;
google.protobuf.Timestamp calculated_at = 9;
bool is_expired = 10;
google.protobuf.Timestamp created = 11;
}
// GetAllWeeklyPools Query
@@ -307,13 +309,14 @@ message GetAllWeeklyPoolsResponse
message WeeklyCommissionPoolModel
{
int64 id = 1;
string week_number = 2;
int64 total_pool_amount = 3;
int32 total_balances = 4;
int64 value_per_balance = 5;
bool is_calculated = 6;
google.protobuf.Timestamp calculated_at = 7;
google.protobuf.Timestamp created = 8;
int64 week_definition_id = 2;
string week_display_name = 3;
int64 total_pool_amount = 4;
int32 total_balances = 5;
int64 value_per_balance = 6;
bool is_calculated = 7;
google.protobuf.Timestamp calculated_at = 8;
google.protobuf.Timestamp created = 9;
}
// GetWithdrawalRequests Query
@@ -321,7 +324,7 @@ message GetWithdrawalRequestsRequest
{
google.protobuf.Int32Value status = 1; // CommissionPayoutStatus enum: Pending=1, Approved=2, Rejected=3
google.protobuf.Int64Value user_id = 2;
google.protobuf.StringValue week_number = 3;
google.protobuf.Int64Value week_definition_id = 3;
int32 page_index = 4;
int32 page_size = 5;
string iban_number = 6;
@@ -338,7 +341,7 @@ message WithdrawalRequestModel
int64 id = 1;
int64 user_id = 2;
string user_name = 3;
string week_number = 4;
int64 week_definition_id = 4;
int64 amount = 5;
int32 status = 6; // CommissionPayoutStatus enum
int32 withdrawal_method = 7; // WithdrawalMethod enum
@@ -358,7 +361,7 @@ message WithdrawalRequestModel
// TriggerWeeklyCalculation Command
message TriggerWeeklyCalculationRequest
{
string week_number = 1; // Format: "YYYY-Www" (e.g., "2025-W48")
int64 week_definition_id = 1;
bool force_recalculate = 2; // اگر true باشد، محاسبات قبلی را حذف و دوباره محاسبه می‌کند
bool skip_balances = 3; // Skip balance calculation (only pool and payouts)
bool skip_pool = 4; // Skip pool calculation (only balances and payouts)
@@ -396,7 +399,7 @@ message GetWorkerStatusResponse
// GetWorkerExecutionLogs Query
message GetWorkerExecutionLogsRequest
{
google.protobuf.StringValue week_number = 1; // Filter by week
google.protobuf.Int64Value week_definition_id = 1; // Filter by week
google.protobuf.StringValue execution_id = 2; // Filter by specific execution
google.protobuf.BoolValue success_only = 3; // Show only successful runs
google.protobuf.BoolValue failed_only = 4; // Show only failed runs
@@ -413,15 +416,16 @@ message GetWorkerExecutionLogsResponse
message WorkerExecutionLogModel
{
string execution_id = 1;
string week_number = 2;
string step = 3; // "Balances" | "Pool" | "Payouts" | "Full"
bool success = 4;
google.protobuf.StringValue error_message = 5;
google.protobuf.Timestamp started_at = 6;
google.protobuf.Timestamp completed_at = 7;
int64 duration_ms = 8; // Duration in milliseconds
int32 records_processed = 9;
google.protobuf.StringValue details = 10; // JSON or text details
int64 week_definition_id = 2;
string week_display_name = 3;
string step = 4; // "Balances" | "Pool" | "Payouts" | "Full"
bool success = 5;
google.protobuf.StringValue error_message = 6;
google.protobuf.Timestamp started_at = 7;
google.protobuf.Timestamp completed_at = 8;
int64 duration_ms = 9; // Duration in milliseconds
int32 records_processed = 10;
google.protobuf.StringValue details = 11; // JSON or text details
}
// GetWithdrawalReports Query
@@ -486,13 +490,14 @@ message GetAvailableWeeksResponse
message WeekInfo
{
string week_number = 1; // YYYY-Www format
google.protobuf.Timestamp start_date = 2;
google.protobuf.Timestamp end_date = 3;
bool is_calculated = 4;
google.protobuf.Timestamp calculated_at = 5;
string last_execution_status = 6;
int64 total_pool_amount = 7;
int32 eligible_users_count = 8;
string display_text = 9; // نمایش فارسی برای UI
int64 week_definition_id = 1; // FK to WeekDefinition
string display_name = 2; // Display name for UI
google.protobuf.Timestamp start_date = 3;
google.protobuf.Timestamp end_date = 4;
bool is_calculated = 5;
google.protobuf.Timestamp calculated_at = 6;
string last_execution_status = 7;
int64 total_pool_amount = 8;
int32 eligible_users_count = 9;
string display_text = 10; // نمایش فارسی برای UI
}
@@ -6,7 +6,7 @@
<Nullable>enable</Nullable>
<IsPackable>true</IsPackable>
<PackageId>Foursat.BackOffice.BFF.Common.Protobuf</PackageId>
<Version>0.0.2</Version>
<Version>0.0.3</Version>
<Authors>FourSat</Authors>
<Company>FourSat</Company>
<Product>BackOffice.BFF.Common.Protobuf</Product>
@@ -6,7 +6,7 @@
<Nullable>enable</Nullable>
<IsPackable>true</IsPackable>
<PackageId>Foursat.BackOffice.BFF.Configuration.Protobuf</PackageId>
<Version>1.0.6</Version>
<Version>1.0.7</Version>
<Authors>FourSat</Authors>
<Company>FourSat</Company>
<Product>Foursat.BackOffice.BFF.Configuration.Protobuf</Product>
@@ -4,7 +4,7 @@
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>0.0.2</Version>
<Version>0.0.3</Version>
<DebugType>None</DebugType>
<DebugSymbols>False</DebugSymbols>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
@@ -4,7 +4,7 @@
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>0.0.2</Version>
<Version>0.0.3</Version>
<DebugType>None</DebugType>
<DebugSymbols>False</DebugSymbols>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
@@ -4,7 +4,7 @@
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>0.0.2</Version>
<Version>0.0.3</Version>
<DebugType>None</DebugType>
<DebugSymbols>False</DebugSymbols>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
@@ -4,7 +4,7 @@
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>0.0.2</Version>
<Version>0.0.3</Version>
<DebugType>None</DebugType>
<DebugSymbols>False</DebugSymbols>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
@@ -6,7 +6,7 @@
<Nullable>enable</Nullable>
<IsPackable>true</IsPackable>
<PackageId>Foursat.BackOffice.BFF.Health.Protobuf</PackageId>
<Version>1.0.4</Version>
<Version>1.0.5</Version>
<Authors>FourSat</Authors>
<Company>FourSat</Company>
<Product>Foursat.BackOffice.BFF.Health.Protobuf</Product>
@@ -4,7 +4,7 @@
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>0.0.4</Version>
<Version>0.0.5</Version>
<DebugType>None</DebugType>
<DebugSymbols>False</DebugSymbols>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
@@ -6,7 +6,7 @@
<Nullable>enable</Nullable>
<IsPackable>true</IsPackable>
<PackageId>Foursat.BackOffice.BFF.NetworkMembership.Protobuf</PackageId>
<Version>0.0.9</Version>
<Version>0.0.11</Version>
<Authors>FourSat</Authors>
<Company>FourSat</Company>
<Product>Foursat.BackOffice.BFF.NetworkMembership.Protobuf</Product>
@@ -156,7 +156,7 @@ message GetNetworkTreeRequest
google.protobuf.Int32Value max_depth = 2;
google.protobuf.BoolValue only_active = 3;
google.protobuf.BoolValue is_club_active = 4;
google.protobuf.StringValue activation_week_number = 5;
google.protobuf.Int64Value activation_week_definition_id = 5;
}
message GetNetworkTreeResponse
@@ -175,7 +175,7 @@ message NetworkTreeNodeModel
google.protobuf.Timestamp joined_at = 7;
google.protobuf.Timestamp club_activated_at = 8; // تاریخ فعال‌سازی در باشگاه
bool is_club_active = 9; // فعال بودن در باشگاه
string activation_week_number = 10; // شماره هفته فعال‌سازی
google.protobuf.Int64Value activation_week_definition_id = 10; // شماره هفته فعال‌سازی
bool is_activated_in_target_week = 11; // آیا در هفته هدف فعال شده
google.protobuf.Timestamp user_created = 12; // تاریخ ایجاد کاربر
}
@@ -4,7 +4,7 @@
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>0.0.112</Version>
<Version>0.0.113</Version>
<DebugType>None</DebugType>
<DebugSymbols>False</DebugSymbols>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
@@ -4,7 +4,7 @@
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>0.0.112</Version>
<Version>0.0.113</Version>
<DebugType>None</DebugType>
<DebugSymbols>False</DebugSymbols>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
@@ -4,7 +4,7 @@
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>0.0.2</Version>
<Version>0.0.3</Version>
<DebugType>None</DebugType>
<DebugSymbols>False</DebugSymbols>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
@@ -4,7 +4,7 @@
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>0.0.9</Version>
<Version>0.0.11</Version>
<DebugType>None</DebugType>
<DebugSymbols>False</DebugSymbols>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
@@ -4,7 +4,7 @@
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>0.0.4</Version>
<Version>0.0.5</Version>
<DebugType>None</DebugType>
<DebugSymbols>False</DebugSymbols>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
@@ -4,7 +4,7 @@
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>0.0.112</Version>
<Version>0.0.113</Version>
<DebugType>None</DebugType>
<DebugSymbols>False</DebugSymbols>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
@@ -4,7 +4,7 @@
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>0.0.2</Version>
<Version>0.0.4</Version>
<DebugType>None</DebugType>
<DebugSymbols>False</DebugSymbols>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
@@ -4,7 +4,7 @@
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>0.0.113</Version>
<Version>0.0.114</Version>
<DebugType>None</DebugType>
<DebugSymbols>False</DebugSymbols>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
@@ -4,7 +4,7 @@
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>0.0.112</Version>
<Version>0.0.113</Version>
<DebugType>None</DebugType>
<DebugSymbols>False</DebugSymbols>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
@@ -4,7 +4,7 @@
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>0.0.115</Version>
<Version>0.0.116</Version>
<DebugType>None</DebugType>
<DebugSymbols>False</DebugSymbols>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
@@ -4,7 +4,7 @@
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>0.0.112</Version>
<Version>0.0.113</Version>
<DebugType>None</DebugType>
<DebugSymbols>False</DebugSymbols>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>