refactor(network): improve network statistics calculations and update related DTOs
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 7m14s
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 7m14s
- Refactored GetNetworkStatisticsQueryHandler to enhance logic for counting active members in left and right legs. - Updated GetNetworkStatisticsResponseDto to include new properties for LeftLegCount and RightLegCount. - Modified Protobuf definitions to align with the updated response structure for network statistics. - Enhanced SQL script to differentiate between all subtree counts and active club member counts.
This commit is contained in:
+1
-1
@@ -7,7 +7,7 @@ COPY src/NuGet.config ./
|
|||||||
# Copy solution and project files
|
# Copy solution and project files
|
||||||
COPY src/ ./
|
COPY src/ ./
|
||||||
|
|
||||||
# Restore with Nexus config and publish
|
# Restore with Nexus config and publish
|
||||||
RUN dotnet restore "CMSMicroservice.WebApi/CMSMicroservice.WebApi.csproj" --configfile NuGet.config
|
RUN dotnet restore "CMSMicroservice.WebApi/CMSMicroservice.WebApi.csproj" --configfile NuGet.config
|
||||||
RUN dotnet publish "CMSMicroservice.WebApi/CMSMicroservice.WebApi.csproj" -c Release -o /app/publish --no-restore
|
RUN dotnet publish "CMSMicroservice.WebApi/CMSMicroservice.WebApi.csproj" -c Release -o /app/publish --no-restore
|
||||||
|
|
||||||
|
|||||||
+21
-14
@@ -35,17 +35,28 @@ public class GetNetworkStatisticsQueryHandler : IRequestHandler<GetNetworkStatis
|
|||||||
}
|
}
|
||||||
var allDescendants = GetAllDescendants(userId, allUsers);
|
var allDescendants = GetAllDescendants(userId, allUsers);
|
||||||
|
|
||||||
// Statistics for the user's network (all descendants)
|
|
||||||
var totalMembers = allDescendants.Count;
|
|
||||||
var activeMembers = allDescendants.Count(x => !x.IsDeleted);
|
|
||||||
|
|
||||||
// Get direct left and right children
|
// Get direct left and right children
|
||||||
var leftChild = allUsers.FirstOrDefault(x => x.NetworkParentId == userId && x.LegPosition == NetworkLeg.Left);
|
var leftChild = allUsers.FirstOrDefault(x => x.NetworkParentId == userId && x.LegPosition == NetworkLeg.Left);
|
||||||
var rightChild = allUsers.FirstOrDefault(x => x.NetworkParentId == userId && x.LegPosition == NetworkLeg.Right);
|
var rightChild = allUsers.FirstOrDefault(x => x.NetworkParentId == userId && x.LegPosition == NetworkLeg.Right);
|
||||||
|
|
||||||
// Count all descendants in left and right subtrees
|
var leftLegUserIds = leftChild != null ? GetSubtreeUserIds(leftChild.Id, allUsers) : new HashSet<long>();
|
||||||
var leftLegCount = leftChild != null ? GetAllDescendants(leftChild.Id, allUsers).Count + 1 : 0; // +1 for leftChild itself
|
var rightLegUserIds = rightChild != null ? GetSubtreeUserIds(rightChild.Id, allUsers) : new HashSet<long>();
|
||||||
var rightLegCount = rightChild != null ? GetAllDescendants(rightChild.Id, allUsers).Count + 1 : 0; // +1 for rightChild itself
|
var allLegUserIds = leftLegUserIds.Union(rightLegUserIds).ToList();
|
||||||
|
|
||||||
|
// سازمان چپ/راست = فقط اعضای فعال باشگاه در هر پا
|
||||||
|
var activeClubUserIds = allLegUserIds.Count == 0
|
||||||
|
? new HashSet<long>()
|
||||||
|
: (await _context.ClubMemberships
|
||||||
|
.AsNoTracking()
|
||||||
|
.Where(cm => cm.IsActive && !cm.IsDeleted && allLegUserIds.Contains(cm.UserId))
|
||||||
|
.Select(cm => cm.UserId)
|
||||||
|
.ToListAsync(cancellationToken))
|
||||||
|
.ToHashSet();
|
||||||
|
|
||||||
|
var leftLegCount = leftLegUserIds.Count(id => activeClubUserIds.Contains(id));
|
||||||
|
var rightLegCount = rightLegUserIds.Count(id => activeClubUserIds.Contains(id));
|
||||||
|
var totalMembers = leftLegCount + rightLegCount;
|
||||||
|
var activeMembers = totalMembers;
|
||||||
|
|
||||||
double leftPercentage = totalMembers > 0 ? (leftLegCount / (double)totalMembers) * 100 : 0;
|
double leftPercentage = totalMembers > 0 ? (leftLegCount / (double)totalMembers) * 100 : 0;
|
||||||
double rightPercentage = totalMembers > 0 ? (rightLegCount / (double)totalMembers) * 100 : 0;
|
double rightPercentage = totalMembers > 0 ? (rightLegCount / (double)totalMembers) * 100 : 0;
|
||||||
@@ -126,7 +137,7 @@ public class GetNetworkStatisticsQueryHandler : IRequestHandler<GetNetworkStatis
|
|||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
var (goldLeft, goldRight, silverLeft, silverRight) =
|
var (goldLeft, goldRight, silverLeft, silverRight) =
|
||||||
await LoadPackageHolderCountsByLegAsync(leftChild, rightChild, allUsers, cancellationToken);
|
await LoadPackageHolderCountsByLegAsync(leftLegUserIds, rightLegUserIds, cancellationToken);
|
||||||
|
|
||||||
return new GetNetworkStatisticsResponseDto
|
return new GetNetworkStatisticsResponseDto
|
||||||
{
|
{
|
||||||
@@ -152,14 +163,10 @@ public class GetNetworkStatisticsQueryHandler : IRequestHandler<GetNetworkStatis
|
|||||||
/// تعداد اعضای فعال باشگاه با پکیج جاری (IsCurrentCycle) در پای چپ/راست.
|
/// تعداد اعضای فعال باشگاه با پکیج جاری (IsCurrentCycle) در پای چپ/راست.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task<(int GoldLeft, int GoldRight, int SilverLeft, int SilverRight)> LoadPackageHolderCountsByLegAsync(
|
private async Task<(int GoldLeft, int GoldRight, int SilverLeft, int SilverRight)> LoadPackageHolderCountsByLegAsync(
|
||||||
User? leftChild,
|
HashSet<long> leftLegUserIds,
|
||||||
User? rightChild,
|
HashSet<long> rightLegUserIds,
|
||||||
List<User> allUsers,
|
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var leftLegUserIds = leftChild != null ? GetSubtreeUserIds(leftChild.Id, allUsers) : new HashSet<long>();
|
|
||||||
var rightLegUserIds = rightChild != null ? GetSubtreeUserIds(rightChild.Id, allUsers) : new HashSet<long>();
|
|
||||||
|
|
||||||
if (leftLegUserIds.Count == 0 && rightLegUserIds.Count == 0)
|
if (leftLegUserIds.Count == 0 && rightLegUserIds.Count == 0)
|
||||||
return (0, 0, 0, 0);
|
return (0, 0, 0, 0);
|
||||||
|
|
||||||
|
|||||||
+4
@@ -2,9 +2,13 @@ namespace CMSMicroservice.Application.NetworkMembershipCQ.Queries.GetNetworkStat
|
|||||||
|
|
||||||
public class GetNetworkStatisticsResponseDto
|
public class GetNetworkStatisticsResponseDto
|
||||||
{
|
{
|
||||||
|
/// <summary>مجموع اعضای فعال باشگاه در پای چپ و راست (= LeftLegCount + RightLegCount)</summary>
|
||||||
public int TotalMembers { get; set; }
|
public int TotalMembers { get; set; }
|
||||||
|
/// <summary>همان TotalMembers — اعضای فعال باشگاه در شبکه کاربر</summary>
|
||||||
public int ActiveMembers { get; set; }
|
public int ActiveMembers { get; set; }
|
||||||
|
/// <summary>تعداد اعضای فعال باشگاه در زیردرخت پای چپ</summary>
|
||||||
public int LeftLegCount { get; set; }
|
public int LeftLegCount { get; set; }
|
||||||
|
/// <summary>تعداد اعضای فعال باشگاه در زیردرخت پای راست</summary>
|
||||||
public int RightLegCount { get; set; }
|
public int RightLegCount { get; set; }
|
||||||
public double LeftPercentage { get; set; }
|
public double LeftPercentage { get; set; }
|
||||||
public double RightPercentage { get; set; }
|
public double RightPercentage { get; set; }
|
||||||
|
|||||||
@@ -315,6 +315,7 @@ message GetMyNetworkTreeResponse
|
|||||||
// GetMyNetworkStatistics - for frontend customer display
|
// GetMyNetworkStatistics - for frontend customer display
|
||||||
message GetMyNetworkStatisticsResponse
|
message GetMyNetworkStatisticsResponse
|
||||||
{
|
{
|
||||||
|
// اعضای فعال باشگاه: کل = چپ + راست
|
||||||
int32 total_members = 1;
|
int32 total_members = 1;
|
||||||
int32 active_members = 2;
|
int32 active_members = 2;
|
||||||
int32 left_leg_count = 3;
|
int32 left_leg_count = 3;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
-- =============================================
|
-- =============================================
|
||||||
-- Diagnose: Package holder counts per leg (read-only)
|
-- Diagnose: Leg counts — all subtree vs active-only vs gold/silver
|
||||||
-- Compares OLD source (NetworkWeeklyBalances) vs NEW (active members + current cycle)
|
|
||||||
-- Usage: SET @RootUserId to the tree owner UserId
|
-- Usage: SET @RootUserId to the tree owner UserId
|
||||||
-- =============================================
|
-- =============================================
|
||||||
|
|
||||||
@@ -44,6 +43,18 @@ Subtree AS (
|
|||||||
FROM Subtree s
|
FROM Subtree s
|
||||||
INNER JOIN CMS.Users u ON u.NetworkParentId = s.UserId AND u.IsDeleted = 0
|
INNER JOIN CMS.Users u ON u.NetworkParentId = s.UserId AND u.IsDeleted = 0
|
||||||
),
|
),
|
||||||
|
AllSubtreeCounts AS (
|
||||||
|
SELECT LegSide, COUNT(DISTINCT UserId) AS Cnt
|
||||||
|
FROM Subtree
|
||||||
|
GROUP BY LegSide
|
||||||
|
),
|
||||||
|
ActiveClubCounts AS (
|
||||||
|
SELECT s.LegSide, COUNT(DISTINCT s.UserId) AS Cnt
|
||||||
|
FROM Subtree s
|
||||||
|
INNER JOIN CMS.ClubMemberships cm
|
||||||
|
ON cm.UserId = s.UserId AND cm.IsActive = 1 AND cm.IsDeleted = 0
|
||||||
|
GROUP BY s.LegSide
|
||||||
|
),
|
||||||
ActivePackageHolders AS (
|
ActivePackageHolders AS (
|
||||||
SELECT
|
SELECT
|
||||||
s.LegSide,
|
s.LegSide,
|
||||||
@@ -53,25 +64,27 @@ ActivePackageHolders AS (
|
|||||||
INNER JOIN CMS.ClubMemberships cm ON cm.UserId = s.UserId AND cm.IsActive = 1 AND cm.IsDeleted = 0
|
INNER JOIN CMS.ClubMemberships cm ON cm.UserId = s.UserId AND cm.IsActive = 1 AND cm.IsDeleted = 0
|
||||||
INNER JOIN CMS.ClubMembershipCycles cc ON cc.UserId = s.UserId AND cc.IsCurrentCycle = 1
|
INNER JOIN CMS.ClubMembershipCycles cc ON cc.UserId = s.UserId AND cc.IsCurrentCycle = 1
|
||||||
GROUP BY s.LegSide, cc.PackageId
|
GROUP BY s.LegSide, cc.PackageId
|
||||||
),
|
|
||||||
LatestNwb AS (
|
|
||||||
SELECT PackageId, LeftLegTotal, RightLegTotal, WeekDefinitionId,
|
|
||||||
ROW_NUMBER() OVER (PARTITION BY PackageId ORDER BY WeekDefinitionId DESC) AS rn
|
|
||||||
FROM CMS.NetworkWeeklyBalances
|
|
||||||
WHERE UserId = @RootUserId
|
|
||||||
AND PackageId IN (@GoldPackageId, @SilverPackageId)
|
|
||||||
)
|
)
|
||||||
SELECT
|
SELECT
|
||||||
@RootUserId AS RootUserId,
|
@RootUserId AS RootUserId,
|
||||||
@GoldPackageId AS GoldPackageId,
|
-- All subtree (old سازمان چپ/راست)
|
||||||
@SilverPackageId AS SilverPackageId,
|
ISNULL((SELECT Cnt FROM AllSubtreeCounts WHERE LegSide = 0), 0) AS AllLeft,
|
||||||
-- NEW: real holder counts
|
ISNULL((SELECT Cnt FROM AllSubtreeCounts WHERE LegSide = 1), 0) AS AllRight,
|
||||||
ISNULL((SELECT HolderCount FROM ActivePackageHolders WHERE LegSide = 0 AND PackageId = @GoldPackageId), 0) AS New_GoldLeft,
|
-- Active club only (new سازمان چپ/راست / کل)
|
||||||
ISNULL((SELECT HolderCount FROM ActivePackageHolders WHERE LegSide = 1 AND PackageId = @GoldPackageId), 0) AS New_GoldRight,
|
ISNULL((SELECT Cnt FROM ActiveClubCounts WHERE LegSide = 0), 0) AS ActiveLeft,
|
||||||
ISNULL((SELECT HolderCount FROM ActivePackageHolders WHERE LegSide = 0 AND PackageId = @SilverPackageId), 0) AS New_SilverLeft,
|
ISNULL((SELECT Cnt FROM ActiveClubCounts WHERE LegSide = 1), 0) AS ActiveRight,
|
||||||
ISNULL((SELECT HolderCount FROM ActivePackageHolders WHERE LegSide = 1 AND PackageId = @SilverPackageId), 0) AS New_SilverRight,
|
ISNULL((SELECT Cnt FROM ActiveClubCounts WHERE LegSide = 0), 0)
|
||||||
-- OLD: weekly balance scores (previous wrong source)
|
+ ISNULL((SELECT Cnt FROM ActiveClubCounts WHERE LegSide = 1), 0) AS ActiveTotal,
|
||||||
ISNULL((SELECT LeftLegTotal FROM LatestNwb WHERE PackageId = @GoldPackageId AND rn = 1), 0) AS Old_Nwb_GoldLeft,
|
-- Gold / Silver package holders (active + current cycle)
|
||||||
ISNULL((SELECT RightLegTotal FROM LatestNwb WHERE PackageId = @GoldPackageId AND rn = 1), 0) AS Old_Nwb_GoldRight,
|
ISNULL((SELECT HolderCount FROM ActivePackageHolders WHERE LegSide = 0 AND PackageId = @GoldPackageId), 0) AS GoldLeft,
|
||||||
ISNULL((SELECT LeftLegTotal FROM LatestNwb WHERE PackageId = @SilverPackageId AND rn = 1), 0) AS Old_Nwb_SilverLeft,
|
ISNULL((SELECT HolderCount FROM ActivePackageHolders WHERE LegSide = 1 AND PackageId = @GoldPackageId), 0) AS GoldRight,
|
||||||
ISNULL((SELECT RightLegTotal FROM LatestNwb WHERE PackageId = @SilverPackageId AND rn = 1), 0) AS Old_Nwb_SilverRight;
|
ISNULL((SELECT HolderCount FROM ActivePackageHolders WHERE LegSide = 0 AND PackageId = @SilverPackageId), 0) AS SilverLeft,
|
||||||
|
ISNULL((SELECT HolderCount FROM ActivePackageHolders WHERE LegSide = 1 AND PackageId = @SilverPackageId), 0) AS SilverRight,
|
||||||
|
-- Gaps: Active − (Gold+Silver) per leg
|
||||||
|
ISNULL((SELECT Cnt FROM ActiveClubCounts WHERE LegSide = 0), 0)
|
||||||
|
- ISNULL((SELECT HolderCount FROM ActivePackageHolders WHERE LegSide = 0 AND PackageId = @GoldPackageId), 0)
|
||||||
|
- ISNULL((SELECT HolderCount FROM ActivePackageHolders WHERE LegSide = 0 AND PackageId = @SilverPackageId), 0) AS GapLeft_ActiveMinusPackages,
|
||||||
|
ISNULL((SELECT Cnt FROM ActiveClubCounts WHERE LegSide = 1), 0)
|
||||||
|
- ISNULL((SELECT HolderCount FROM ActivePackageHolders WHERE LegSide = 1 AND PackageId = @GoldPackageId), 0)
|
||||||
|
- ISNULL((SELECT HolderCount FROM ActivePackageHolders WHERE LegSide = 1 AND PackageId = @SilverPackageId), 0) AS GapRight_ActiveMinusPackages
|
||||||
|
OPTION (MAXRECURSION 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user