diff --git a/src/CMSMicroservice.Application/NetworkMembershipCQ/Queries/GetNetworkTree/GetNetworkTreeQueryHandler.cs b/src/CMSMicroservice.Application/NetworkMembershipCQ/Queries/GetNetworkTree/GetNetworkTreeQueryHandler.cs index da75e43..ab1bada 100644 --- a/src/CMSMicroservice.Application/NetworkMembershipCQ/Queries/GetNetworkTree/GetNetworkTreeQueryHandler.cs +++ b/src/CMSMicroservice.Application/NetworkMembershipCQ/Queries/GetNetworkTree/GetNetworkTreeQueryHandler.cs @@ -1,5 +1,4 @@ using System.Data; -using System.Data.Common; using Microsoft.EntityFrameworkCore; namespace CMSMicroservice.Application.NetworkMembershipCQ.Queries.GetNetworkTree; @@ -42,6 +41,11 @@ public class GetNetworkTreeQueryHandler : IRequestHandler n.NetworkLevel == 0); return rootNode != null ? nodeDict[rootNode.UserId] : null; } + + /// + /// آخرین Left/RightLegTotal طلایی و نقره‌ای برای هر نود درخت (برنامه‌ریزی پای چپ/راست). + /// + private async Task EnrichWithPackageLegScoresAsync( + NetworkTreeDto root, + List flatNodes, + CancellationToken cancellationToken) + { + var userIds = flatNodes.Select(n => n.UserId).Distinct().ToList(); + if (userIds.Count == 0) return; + + var packages = await _context.Packages + .AsNoTracking() + .Where(p => !p.IsDeleted && p.IsActive) + .Select(p => new { p.Id, p.Title, p.IsBasePackage, p.MaxBalancesPerLeg }) + .ToListAsync(cancellationToken); + + var goldPackageId = packages.FirstOrDefault(p => p.IsBasePackage)?.Id + ?? packages.FirstOrDefault(p => p.Title.Contains("طلایی") || p.Title.Contains("طلايی"))?.Id; + + var silverPackageId = packages.FirstOrDefault(p => + !p.IsBasePackage && (p.Title.Contains("نقره") || p.MaxBalancesPerLeg <= 30))?.Id + ?? packages.FirstOrDefault(p => !p.IsBasePackage)?.Id; + + if (!goldPackageId.HasValue && !silverPackageId.HasValue) + { + _logger.LogWarning("GetNetworkTree: no gold/silver packages found for leg score enrichment"); + return; + } + + var packageIds = new List(); + if (goldPackageId.HasValue) packageIds.Add(goldPackageId.Value); + if (silverPackageId.HasValue && silverPackageId != goldPackageId) + packageIds.Add(silverPackageId.Value); + + var rawBalances = await _context.NetworkWeeklyBalances + .AsNoTracking() + .Where(b => userIds.Contains(b.UserId) && packageIds.Contains(b.PackageId)) + .Select(b => new LegScoreRow( + b.UserId, + b.PackageId, + b.WeekDefinitionId, + b.LeftLegTotal, + b.RightLegTotal)) + .ToListAsync(cancellationToken); + + var latestByUserPackage = rawBalances + .GroupBy(b => (b.UserId, b.PackageId)) + .ToDictionary( + g => g.Key, + g => g.OrderByDescending(x => x.WeekDefinitionId).First()); + + ApplyLegScores(root, goldPackageId, silverPackageId, latestByUserPackage); + } + + private static void ApplyLegScores( + NetworkTreeDto node, + long? goldPackageId, + long? silverPackageId, + Dictionary<(long UserId, long PackageId), LegScoreRow> latestByUserPackage) + { + if (goldPackageId.HasValue && + latestByUserPackage.TryGetValue((node.UserId, goldPackageId.Value), out var gold)) + { + node.GoldLeftLegTotal = gold.LeftLegTotal; + node.GoldRightLegTotal = gold.RightLegTotal; + } + + if (silverPackageId.HasValue && + latestByUserPackage.TryGetValue((node.UserId, silverPackageId.Value), out var silver)) + { + node.SilverLeftLegTotal = silver.LeftLegTotal; + node.SilverRightLegTotal = silver.RightLegTotal; + } + + if (node.LeftChild != null) + ApplyLegScores(node.LeftChild, goldPackageId, silverPackageId, latestByUserPackage); + + if (node.RightChild != null) + ApplyLegScores(node.RightChild, goldPackageId, silverPackageId, latestByUserPackage); + } + + private sealed record LegScoreRow( + long UserId, + long PackageId, + long WeekDefinitionId, + int LeftLegTotal, + int RightLegTotal); } diff --git a/src/CMSMicroservice.Application/NetworkMembershipCQ/Queries/GetNetworkTree/NetworkTreeDto.cs b/src/CMSMicroservice.Application/NetworkMembershipCQ/Queries/GetNetworkTree/NetworkTreeDto.cs index 2d5ac4e..c273e84 100644 --- a/src/CMSMicroservice.Application/NetworkMembershipCQ/Queries/GetNetworkTree/NetworkTreeDto.cs +++ b/src/CMSMicroservice.Application/NetworkMembershipCQ/Queries/GetNetworkTree/NetworkTreeDto.cs @@ -60,6 +60,18 @@ public class NetworkTreeDto public long? PackageId { get; set; } + /// آخرین LeftLegTotal پکیج طلایی (پایه) + public int GoldLeftLegTotal { get; set; } + + /// آخرین RightLegTotal پکیج طلایی (پایه) + public int GoldRightLegTotal { get; set; } + + /// آخرین LeftLegTotal پکیج نقره‌ای + public int SilverLeftLegTotal { get; set; } + + /// آخرین RightLegTotal پکیج نقره‌ای + public int SilverRightLegTotal { get; set; } + public NetworkTreeDto? LeftChild { get; set; } public NetworkTreeDto? RightChild { get; set; } } diff --git a/src/CMSMicroservice.Protobuf/CMSMicroservice.Protobuf.csproj b/src/CMSMicroservice.Protobuf/CMSMicroservice.Protobuf.csproj index 685ed49..2de392c 100644 --- a/src/CMSMicroservice.Protobuf/CMSMicroservice.Protobuf.csproj +++ b/src/CMSMicroservice.Protobuf/CMSMicroservice.Protobuf.csproj @@ -3,7 +3,7 @@ net9.0 enable enable - 0.0.209 + 0.0.210 None False False diff --git a/src/CMSMicroservice.Protobuf/Protos/networkmembership.proto b/src/CMSMicroservice.Protobuf/Protos/networkmembership.proto index 6f7ec5d..39ee7f7 100644 --- a/src/CMSMicroservice.Protobuf/Protos/networkmembership.proto +++ b/src/CMSMicroservice.Protobuf/Protos/networkmembership.proto @@ -209,6 +209,11 @@ message NetworkTreeNodeModel google.protobuf.BoolValue is_new_activation = 22; // true=اولین فعال‌سازی، false=خرید مجدد، null=بدون Cycle string package_name = 23; // نام پکیج موثر google.protobuf.Int64Value package_id = 24; // شناسه پکیج + // آخرین NetworkWeeklyBalance: امتیاز پای چپ/راست برای پکیج طلایی و نقره‌ای (D3) + int32 gold_left_leg_total = 25; + int32 gold_right_leg_total = 26; + int32 silver_left_leg_total = 27; + int32 silver_right_leg_total = 28; } // GetHistory Query diff --git a/src/CMSMicroservice.WebApi/Common/Mappings/NetworkMembershipProfile.cs b/src/CMSMicroservice.WebApi/Common/Mappings/NetworkMembershipProfile.cs index 1c3913e..707baae 100644 --- a/src/CMSMicroservice.WebApi/Common/Mappings/NetworkMembershipProfile.cs +++ b/src/CMSMicroservice.WebApi/Common/Mappings/NetworkMembershipProfile.cs @@ -95,7 +95,11 @@ public class NetworkMembershipProfile : IRegister IsActivatedInTargetWeek = node.IsActivatedInTargetWeek, PackageName = node.PackageName ?? string.Empty, PackageId = node.PackageId.HasValue ? node.PackageId.Value : null, - IsNewActivation = node.IsNewActivation.HasValue ? node.IsNewActivation.Value : null + IsNewActivation = node.IsNewActivation.HasValue ? node.IsNewActivation.Value : null, + GoldLeftLegTotal = node.GoldLeftLegTotal, + GoldRightLegTotal = node.GoldRightLegTotal, + SilverLeftLegTotal = node.SilverLeftLegTotal, + SilverRightLegTotal = node.SilverRightLegTotal }; if (parentId.HasValue) diff --git a/src/CMSMicroservice.WebApi/Services/NetworkMembershipService.cs b/src/CMSMicroservice.WebApi/Services/NetworkMembershipService.cs index 8bb5d66..dc3dfb4 100644 --- a/src/CMSMicroservice.WebApi/Services/NetworkMembershipService.cs +++ b/src/CMSMicroservice.WebApi/Services/NetworkMembershipService.cs @@ -185,6 +185,11 @@ public class NetworkMembershipService : NetworkMembershipContract.NetworkMembers node.PackageId = dto.PackageId.Value; } + node.GoldLeftLegTotal = dto.GoldLeftLegTotal; + node.GoldRightLegTotal = dto.GoldRightLegTotal; + node.SilverLeftLegTotal = dto.SilverLeftLegTotal; + node.SilverRightLegTotal = dto.SilverRightLegTotal; + if (dto.IsNewActivation.HasValue) { node.IsNewActivation = dto.IsNewActivation.Value;