feat(network): enrich network tree with package leg scores and update Protobuf definitions
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 12m47s
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 12m47s
- Added logic to enrich the network tree with the latest left/right leg totals for gold and silver packages in GetNetworkTreeQueryHandler. - Introduced new properties in NetworkTreeDto for GoldLeftLegTotal, GoldRightLegTotal, SilverLeftLegTotal, and SilverRightLegTotal. - Updated Protobuf definitions to include new fields for leg scores in NetworkTreeNodeModel. - Enhanced mapping in NetworkMembershipProfile and NetworkMembershipService to accommodate new leg score properties. - Bumped Protobuf project version to reflect the addition of new features.
This commit is contained in:
+94
-1
@@ -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<GetNetworkTreeQuery, N
|
||||
|
||||
// تبدیل نتایج flat به ساختار درختی
|
||||
var tree = BuildTreeFromFlatNodes(flatNodes);
|
||||
if (tree != null)
|
||||
{
|
||||
await EnrichWithPackageLegScoresAsync(tree, flatNodes, cancellationToken);
|
||||
}
|
||||
|
||||
return tree;
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -194,4 +198,93 @@ public class GetNetworkTreeQueryHandler : IRequestHandler<GetNetworkTreeQuery, N
|
||||
var rootNode = flatNodes.FirstOrDefault(n => n.NetworkLevel == 0);
|
||||
return rootNode != null ? nodeDict[rootNode.UserId] : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// آخرین Left/RightLegTotal طلایی و نقرهای برای هر نود درخت (برنامهریزی پای چپ/راست).
|
||||
/// </summary>
|
||||
private async Task EnrichWithPackageLegScoresAsync(
|
||||
NetworkTreeDto root,
|
||||
List<NetworkTreeNodeDto> 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<long>();
|
||||
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);
|
||||
}
|
||||
|
||||
+12
@@ -60,6 +60,18 @@ public class NetworkTreeDto
|
||||
|
||||
public long? PackageId { get; set; }
|
||||
|
||||
/// <summary>آخرین LeftLegTotal پکیج طلایی (پایه)</summary>
|
||||
public int GoldLeftLegTotal { get; set; }
|
||||
|
||||
/// <summary>آخرین RightLegTotal پکیج طلایی (پایه)</summary>
|
||||
public int GoldRightLegTotal { get; set; }
|
||||
|
||||
/// <summary>آخرین LeftLegTotal پکیج نقرهای</summary>
|
||||
public int SilverLeftLegTotal { get; set; }
|
||||
|
||||
/// <summary>آخرین RightLegTotal پکیج نقرهای</summary>
|
||||
public int SilverRightLegTotal { get; set; }
|
||||
|
||||
public NetworkTreeDto? LeftChild { get; set; }
|
||||
public NetworkTreeDto? RightChild { get; set; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user