Files
FrontOffice/src/FrontOffice.Main/Utilities/NetworkMembershipService.cs
T
masoodafar-web 8252e408b6
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 3m41s
feat(organization-chart): update registration date handling and styling
- Modified the OrganizationChart component to convert and display the registration date in Jalali format, enhancing user understanding of the date information.
- Updated the NetworkMembershipDtos class to include a comment in Persian for the JoinedAt property, clarifying its purpose.
- Adjusted the NetworkMembershipService to utilize the UserCreated date when available, improving data accuracy.
- Introduced new CSS styles for the registration date display, ensuring better visibility and presentation in the organization chart.

These changes enhance the clarity and usability of the organization chart by providing accurate registration date information in a user-friendly format.
2026-09-04 06:48:24 +03:30

159 lines
5.4 KiB
C#

using CMSMicroservice.Protobuf.Protos.NetworkMembership;
using Google.Protobuf.WellKnownTypes;
namespace FrontOffice.Main.Utilities;
/// <summary>
/// Service for Network Membership operations
/// Connected to FrontOffice.BFF gRPC NetworkMembershipCQ
/// </summary>
public class NetworkMembershipService
{
private readonly NetworkMembershipContract.NetworkMembershipContractClient _client;
public NetworkMembershipService(NetworkMembershipContract.NetworkMembershipContractClient client)
{
_client = client;
}
/// <summary>
/// Get current user's network tree
/// Maps to: NetworkMembershipCQ.GetMyNetworkTree
/// </summary>
public async Task<NetworkTreeDto> GetMyNetworkTreeAsync(int maxDepth = 3)
{
try
{
var request = new GetMyNetworkTreeRequest { MaxDepth = maxDepth };
var response = await _client.GetMyNetworkTreeAsync(request);
return new NetworkTreeDto
{
RootNode = MapNodeFromProto(response.RootNode),
TotalMembers = response.TotalMembers,
CurrentDepth = response.CurrentDepth
};
}
catch
{
// Return empty tree if backend is unavailable
return new NetworkTreeDto
{
CurrentDepth = 0,
TotalMembers = 0,
RootNode = null
};
}
}
/// <summary>
/// Get subordinate's network tree (with security check on backend)
/// Maps to: NetworkMembershipCQ.GetSubordinateTree
/// </summary>
public async Task<NetworkTreeDto> GetSubordinateTreeAsync(long targetUserId, int maxDepth = 3)
{
try
{
var request = new GetSubordinateTreeRequest
{
TargetUserId = targetUserId,
MaxDepth = maxDepth
};
var response = await _client.GetSubordinateTreeAsync(request);
return new NetworkTreeDto
{
RootNode = MapNodeFromProto(response.RootNode),
TotalMembers = response.TotalMembers,
CurrentDepth = response.CurrentDepth
};
}
catch (Grpc.Core.RpcException ex) when (ex.StatusCode == Grpc.Core.StatusCode.PermissionDenied)
{
throw new UnauthorizedAccessException("شما اجازه مشاهده درخت این کاربر را ندارید");
}
catch
{
// Fallback to current user's tree
return await GetMyNetworkTreeAsync(maxDepth);
}
}
/// <summary>
/// Get current user's network statistics
/// Maps to: NetworkMembershipCQ.GetMyNetworkStatistics
/// </summary>
public async Task<NetworkStatisticsDto> GetMyNetworkStatisticsAsync()
{
try
{
var response = await _client.GetMyNetworkStatisticsAsync(new Empty());
return new NetworkStatisticsDto
{
LeftLegCount = response.LeftLegCount,
RightLegCount = response.RightLegCount,
TotalMembers = response.TotalMembers,
TreeDepth = response.MaxDepth,
WeakerLeg = response.WeakerLeg,
GoldLeftLegTotal = response.GoldLeftLegTotal,
GoldRightLegTotal = response.GoldRightLegTotal,
SilverLeftLegTotal = response.SilverLeftLegTotal,
SilverRightLegTotal = response.SilverRightLegTotal,
LastMember = response.LastMember != null ? new LastMemberDto
{
UserId = response.LastMember.UserId,
FullName = response.LastMember.FullName,
Position = response.LastMember.Position,
JoinedAt = DateTime.Now // TODO: Add JoinedAt to proto
} : null
};
}
catch
{
// Return empty statistics if backend is unavailable
return new NetworkStatisticsDto
{
LeftLegCount = 0,
RightLegCount = 0,
TotalMembers = 0,
TreeDepth = 0,
WeakerLeg = string.Empty,
LastMember = null
};
}
}
#region Helper Methods
private static NetworkNodeDto? MapNodeFromProto(NetworkTreeNodeModel? node)
{
if (node == null) return null;
return new NetworkNodeDto
{
UserId = node.UserId,
FullName = node.FullName,
Mobile = node.Mobile,
Avatar = node.Avatar,
Position = node.Position,
Level = node.Level,
IsActive = node.IsActive,
IsClubActive = node.IsClubActive,
ReferralCode = node.ReferralCode,
PackageName = string.IsNullOrWhiteSpace(node.PackageName) ? null : node.PackageName,
GoldLeftLegTotal = node.GoldLeftLegTotal,
GoldRightLegTotal = node.GoldRightLegTotal,
SilverLeftLegTotal = node.SilverLeftLegTotal,
SilverRightLegTotal = node.SilverRightLegTotal,
ActivationWeekNumber = node.ActivationWeekDefinitionId?.ToString(),
JoinedAt = node.UserCreated?.ToDateTime()
?? node.JoinedAt?.ToDateTime(),
LeftChild = MapNodeFromProto(node.LeftChild),
RightChild = MapNodeFromProto(node.RightChild)
};
}
#endregion
}