From 794dd01ac0c2293e5848a461d65d252b71c90967 Mon Sep 17 00:00:00 2001 From: masoodafar-web Date: Sun, 1 Feb 2026 22:16:36 +0330 Subject: [PATCH] feat: update Protobuf definitions and add customer-facing APIs for various services --- .../GetAllProductsByFilterQueryHandler.cs | 69 ++++++++++++++ .../CMSMicroservice.Protobuf.csproj | 10 +- .../Protos/category.proto | 2 +- .../Protos/clubmembership.proto | 2 + .../Protos/commission.proto | 94 +++++++++++++++++++ .../Protos/configuration.proto | 40 ++++++++ .../Protos/networkmembership.proto | 74 +++++++++++++++ .../Protos/package.proto | 16 +++- .../Protos/user.proto | 1 + .../Protos/usercarts.proto | 5 +- .../Protos/userorder.proto | 14 +++ .../Services/PackageService.cs | 8 ++ src/NuGet.config | 5 + 13 files changed, 329 insertions(+), 11 deletions(-) create mode 100644 src/CMSMicroservice.Application/ProductsCQ/Queries/GetAllProductsByFilter/GetAllProductsByFilterQueryHandler.cs diff --git a/src/CMSMicroservice.Application/ProductsCQ/Queries/GetAllProductsByFilter/GetAllProductsByFilterQueryHandler.cs b/src/CMSMicroservice.Application/ProductsCQ/Queries/GetAllProductsByFilter/GetAllProductsByFilterQueryHandler.cs new file mode 100644 index 0000000..427a783 --- /dev/null +++ b/src/CMSMicroservice.Application/ProductsCQ/Queries/GetAllProductsByFilter/GetAllProductsByFilterQueryHandler.cs @@ -0,0 +1,69 @@ +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using CMSMicroservice.Application.Common.Interfaces; +using Mapster; +using MediatR; + +namespace CMSMicroservice.Application.ProductsCQ.Queries.GetAllProductsByFilter; + +public class + GetAllProductsByFilterQueryHandler : IRequestHandler +{ + private readonly IApplicationDbContext _context; + + public GetAllProductsByFilterQueryHandler(IApplicationDbContext context) + { + _context = context; + } + + public async Task Handle(GetAllProductsByFilterQuery request, + CancellationToken cancellationToken) + { + var grpcRequest = new CmsProductsProtos.GetAllProductsByFilterRequest + { + PaginationState = request.PaginationState is { } pagination + ? new CmsPaginationState + { + PageNumber = pagination.PageNumber, + PageSize = pagination.PageSize + } + : null, + SortBy = request.SortBy, + Filter = BuildFilter(request.Filter) + }; + + var result = await _context.Product.GetAllProductsByFilterAsync(grpcRequest, + cancellationToken: cancellationToken); + + if (request.Filter?.CategoryId is { } categoryId) + { + var matchingModels = result.Models + .Where(model => model.CategoryIds.Contains(categoryId)) + .ToList(); + result.Models.Clear(); + result.Models.AddRange(matchingModels); + } + return result.Adapt(); + } + + private static CmsProductsProtos.GetAllProductsByFilterFilter? BuildFilter(GetAllProductsByFilterFilter? filter) + { + if (filter is null) + { + return null; + } + + return new CmsProductsProtos.GetAllProductsByFilterFilter + { + Id = filter.Id, + Title = filter.Title, + Description = filter.Description, + ShortInfomation = filter.ShortInfomation, + FullInformation = filter.FullInformation, + Price = filter.Price, + Discount = filter.Discount, + Rate = filter.Rate + }; + } +} \ No newline at end of file diff --git a/src/CMSMicroservice.Protobuf/CMSMicroservice.Protobuf.csproj b/src/CMSMicroservice.Protobuf/CMSMicroservice.Protobuf.csproj index b3fb976..4c3266f 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.169 + 0.0.177 None False False @@ -66,12 +66,12 @@ - + - $(PackageOutputPath)$(PackageId).$(Version).nupkg - dotnet nuget push **/*.nupkg --source http://194.5.195.53:32081/repository/foursat-nuget-hosted/index.json --api-key admin:87zH26nbqT --skip-duplicate --allow-insecure-connections + $(PackageOutputPath)/$(PackageId).$(Version).nupkg + dotnet nuget push "$(NugetPackagePath)" --source foursat-hosted --api-key admin:87zH26nbqT --skip-duplicate --configfile "$(MSBuildThisFileDirectory)../NuGet.config" - + diff --git a/src/CMSMicroservice.Protobuf/Protos/category.proto b/src/CMSMicroservice.Protobuf/Protos/category.proto index 5ce8e35..8a3d500 100644 --- a/src/CMSMicroservice.Protobuf/Protos/category.proto +++ b/src/CMSMicroservice.Protobuf/Protos/category.proto @@ -166,7 +166,7 @@ message GetAllCategoriesForCustomerRequest { message GetAllCategoriesForCustomerResponse { messages.MetaData meta_data = 1; - repeated GetAllCategoryFilterResponseModel categories = 2; + repeated GetAllCategoryFilterResponseModel models = 2; } message GetCategoryByIdForCustomerRequest { diff --git a/src/CMSMicroservice.Protobuf/Protos/clubmembership.proto b/src/CMSMicroservice.Protobuf/Protos/clubmembership.proto index 356588d..9951376 100644 --- a/src/CMSMicroservice.Protobuf/Protos/clubmembership.proto +++ b/src/CMSMicroservice.Protobuf/Protos/clubmembership.proto @@ -116,6 +116,8 @@ message GetClubMembershipResponse bool is_active = 8; google.protobuf.Timestamp created = 9; repeated MembershipFeatureModel features = 10; + string status = 11; // Trial/Active/Expired/Inactive - for frontend compatibility + int32 days_remaining = 12; // Days until expiration - calculated field } message MembershipFeatureModel diff --git a/src/CMSMicroservice.Protobuf/Protos/commission.proto b/src/CMSMicroservice.Protobuf/Protos/commission.proto index fab3faa..2c5a2b1 100644 --- a/src/CMSMicroservice.Protobuf/Protos/commission.proto +++ b/src/CMSMicroservice.Protobuf/Protos/commission.proto @@ -117,6 +117,19 @@ service CommissionContract get: "/Commission/GetWeekDefinitions" }; }; + + // Customer-facing APIs + rpc GetMyCommissionPayouts(GetMyCommissionPayoutsRequest) returns (GetMyCommissionPayoutsResponse){ + option (google.api.http) = { + get: "/Commission/Customer/MyPayouts" + }; + }; + + rpc GetMyWeeklyBalances(GetMyWeeklyBalancesRequest) returns (GetMyWeeklyBalancesResponse){ + option (google.api.http) = { + get: "/Commission/Customer/MyWeeklyBalances" + }; + }; // Financial Reports rpc GetWithdrawalReports(GetWithdrawalReportsRequest) returns (GetWithdrawalReportsResponse){ @@ -525,6 +538,14 @@ message GetWeekDefinitionsRequest google.protobuf.StringValue sort_by = 2; //فیلتر GetWeekDefinitionsFilter filter = 3; + + // Frontend compatibility fields (aliases) + int32 page_number = 20; + int32 page_size = 21; + string search_text = 22; + google.protobuf.Int32Value gregorian_year = 23; + google.protobuf.Int32Value persian_year = 24; + google.protobuf.BoolValue is_active = 25; } message GetWeekDefinitionsFilter @@ -564,4 +585,77 @@ message WeekDefinitionItem int32 persian_year = 9; bool is_active = 10; bool is_current_week = 11; + string start_date_persian = 12; // Frontend expects Persian date string + string end_date_persian = 13; // Frontend expects Persian date string +} + +// ============ Customer APIs ============ + +// GetMyCommissionPayouts - for frontend customer display +message GetMyCommissionPayoutsRequest +{ + int32 page_number = 1; + int32 page_size = 2; + google.protobuf.Int64Value week_definition_id = 3; + google.protobuf.Int32Value status = 4; // 0=Pending, 1=Calculated, 2=Paid, 3=Withdrawn +} + +message GetMyCommissionPayoutsResponse +{ + CustomerMetaData meta_data = 1; + repeated CustomerCommissionPayoutModel payouts = 2; +} + +message CustomerMetaData +{ + int64 total_count = 1; +} + +message CustomerCommissionPayoutModel +{ + int64 id = 1; + int64 week_definition_id = 2; + string week_display_name = 3; + int32 balances_earned = 4; + int64 total_amount = 5; + string amount_formatted = 6; + int32 status = 7; // 0=Pending, 1=Paid, 2=WithdrawRequested, 3=Withdrawn, 4=PaymentFailed, 5=Cancelled + google.protobuf.Timestamp calculated_date = 8; + string date_persian = 9; +} + +// GetMyWeeklyBalances - for frontend customer display +message GetMyWeeklyBalancesRequest +{ + int32 page_number = 1; + int32 page_size = 2; + google.protobuf.Int64Value week_definition_id = 3; + bool only_active = 4; +} + +message GetMyWeeklyBalancesResponse +{ + CustomerMetaData meta_data = 1; + repeated CustomerWeeklyBalanceModel balances = 2; + int32 total_left_balances = 3; + int32 total_right_balances = 4; + string weaker_leg = 5; +} + +message CustomerWeeklyBalanceModel +{ + int64 id = 1; + int64 week_definition_id = 2; + string week_display_name = 3; + int32 left_leg_balances = 4; + int32 right_leg_balances = 5; + int32 total_balances = 6; + int64 weekly_pool_contribution = 7; + bool is_expired = 8; + google.protobuf.Timestamp calculated_at = 9; + string date_persian = 10; + int32 left_leg_carryover = 11; + int32 right_leg_carryover = 12; + int32 left_leg_new_members = 13; + int32 right_leg_new_members = 14; } diff --git a/src/CMSMicroservice.Protobuf/Protos/configuration.proto b/src/CMSMicroservice.Protobuf/Protos/configuration.proto index 4cbda2b..125c1e6 100644 --- a/src/CMSMicroservice.Protobuf/Protos/configuration.proto +++ b/src/CMSMicroservice.Protobuf/Protos/configuration.proto @@ -39,6 +39,19 @@ service ConfigurationContract get: "/Configuration/GetHistory" }; }; + + // Customer-facing APIs + rpc GetClubConfiguration(google.protobuf.Empty) returns (GetClubConfigurationResponse){ + option (google.api.http) = { + get: "/Configuration/Customer/Club" + }; + }; + + rpc GetClubFeatures(google.protobuf.Empty) returns (GetClubFeaturesResponse){ + option (google.api.http) = { + get: "/Configuration/Customer/ClubFeatures" + }; + }; } // CreateOrUpdate Command @@ -138,3 +151,30 @@ message ConfigurationHistoryModel string reason = 11; google.protobuf.Timestamp created = 12; } + +// ============ Customer APIs ============ + +// GetClubConfiguration - for frontend customer display +message GetClubConfigurationResponse +{ + int64 activation_fee = 1; + int64 membership_gift_value = 2; +} + +// GetClubFeatures - for frontend customer display +message GetClubFeaturesResponse +{ + repeated ClubFeatureModel features = 1; +} + +message ClubFeatureModel +{ + int64 id = 1; + string title = 2; + string description = 3; + bool is_enabled = 4; + int32 display_order = 5; + google.protobuf.Timestamp granted_at = 6; + google.protobuf.Timestamp created_at = 7; + string notes = 8; +} diff --git a/src/CMSMicroservice.Protobuf/Protos/networkmembership.proto b/src/CMSMicroservice.Protobuf/Protos/networkmembership.proto index 651e709..be37c2a 100644 --- a/src/CMSMicroservice.Protobuf/Protos/networkmembership.proto +++ b/src/CMSMicroservice.Protobuf/Protos/networkmembership.proto @@ -50,6 +50,25 @@ service NetworkMembershipContract get: "/NetworkMembership/GetStatistics" }; }; + + // Customer-facing APIs + rpc GetMyNetworkTree(GetMyNetworkTreeRequest) returns (GetMyNetworkTreeResponse){ + option (google.api.http) = { + get: "/NetworkMembership/Customer/MyTree" + }; + }; + + rpc GetSubordinateTree(GetSubordinateTreeRequest) returns (GetMyNetworkTreeResponse){ + option (google.api.http) = { + get: "/NetworkMembership/Customer/SubordinateTree/{target_user_id}" + }; + }; + + rpc GetMyNetworkStatistics(google.protobuf.Empty) returns (GetMyNetworkStatisticsResponse){ + option (google.api.http) = { + get: "/NetworkMembership/Customer/MyStats" + }; + }; } // JoinNetwork Command @@ -168,9 +187,11 @@ message NetworkTreeNodeModel { int64 user_id = 1; string user_name = 2; + string full_name = 20; // Alias for frontend compatibility google.protobuf.Int64Value parent_id = 3; int32 network_leg = 4; int32 network_level = 5; + int32 level = 21; // Alias for frontend compatibility bool is_active = 6; google.protobuf.Timestamp joined_at = 7; google.protobuf.Timestamp club_activated_at = 8; // تاریخ فعال‌سازی در باشگاه @@ -179,6 +200,11 @@ message NetworkTreeNodeModel bool is_activated_in_target_week = 11; // آیا در هفته هدف فعال شده google.protobuf.Timestamp user_created = 12; // تاریخ ایجاد کاربر string referral_code = 13; // کد معرف کاربر + string mobile = 14; // Mobile number for display + google.protobuf.StringValue avatar = 15; // Avatar path + string position = 16; // Root/Left/Right position indicator + NetworkTreeNodeModel left_child = 17; // Left child node + NetworkTreeNodeModel right_child = 18; // Right child node } // GetHistory Query @@ -254,3 +280,51 @@ message TopNetworkUser int32 left_count = 5; int32 right_count = 6; } + +// ============ Customer APIs ============ + +// GetMyNetworkTree - for frontend customer display +message GetMyNetworkTreeRequest +{ + int32 max_depth = 1; // Default: 3 +} + +// GetSubordinateTree - for frontend customer display +message GetSubordinateTreeRequest +{ + int64 target_user_id = 1; + int32 max_depth = 2; // Default: 3 +} + +message GetMyNetworkTreeResponse +{ + NetworkTreeNodeModel root_node = 1; + int32 total_members = 2; + int32 current_depth = 3; +} + +// GetMyNetworkStatistics - for frontend customer display +message GetMyNetworkStatisticsResponse +{ + int32 total_members = 1; + int32 active_members = 2; + int32 left_leg_count = 3; + int32 right_leg_count = 4; + double left_percentage = 5; + double right_percentage = 6; + double average_depth = 7; + int32 max_depth = 8; + string weaker_leg = 9; + int32 my_network_level = 10; + string my_network_leg = 11; + string my_referral_code = 12; + CustomerLastMemberModel last_member = 13; +} + +message CustomerLastMemberModel +{ + int64 user_id = 1; + string full_name = 2; + string position = 3; + int32 total_children = 4; +} diff --git a/src/CMSMicroservice.Protobuf/Protos/package.proto b/src/CMSMicroservice.Protobuf/Protos/package.proto index b3f192a..cdb9175 100644 --- a/src/CMSMicroservice.Protobuf/Protos/package.proto +++ b/src/CMSMicroservice.Protobuf/Protos/package.proto @@ -226,6 +226,7 @@ message GetUserPackageStatusResponse message InitiateBasePackagePaymentRequest { int64 user_id = 1; + string callback_url = 2; // Payment gateway callback URL } message InitiateBasePackagePaymentResponse @@ -235,6 +236,7 @@ message InitiateBasePackagePaymentResponse int64 order_id = 3; int64 transaction_id = 4; int64 amount = 5; + string payment_gateway_url = 6; } message VerifyBasePackagePaymentRequest @@ -267,7 +269,7 @@ message GetCustomerPackagesRequest message GetCustomerPackagesResponse { - repeated CustomerPackageModel packages = 1; + repeated CustomerPackageModel models = 1; } message GetCustomerPackageDetailsRequest @@ -277,9 +279,13 @@ message GetCustomerPackageDetailsRequest message GetCustomerPackageDetailsResponse { - CustomerPackageModel package = 1; - repeated PackageFeature features = 2; - PurchaseRequirements requirements = 3; + int64 id = 1; + string title = 2; + string description = 3; + int64 price = 4; + google.protobuf.StringValue image_path = 5; + repeated PackageFeature features = 6; + PurchaseRequirements requirements = 7; } message CustomerPurchasePackageRequest @@ -342,6 +348,8 @@ message CustomerPackageModel int32 validity_days = 9; bool is_popular = 10; string short_description = 11; + string title = 12; // Alias for frontend compatibility (uses name) + string image_path = 13; // Alias for frontend compatibility (uses image_url) } message PackageFeature diff --git a/src/CMSMicroservice.Protobuf/Protos/user.proto b/src/CMSMicroservice.Protobuf/Protos/user.proto index 0e808c2..367470c 100644 --- a/src/CMSMicroservice.Protobuf/Protos/user.proto +++ b/src/CMSMicroservice.Protobuf/Protos/user.proto @@ -331,6 +331,7 @@ message GetUserForCustomerResponse bool sms_notifications = 13; bool push_notifications = 14; google.protobuf.Timestamp birth_date = 15; + string token = 16; // JWT token for authentication refresh } // ============= Customer Profile Messages ============= diff --git a/src/CMSMicroservice.Protobuf/Protos/usercarts.proto b/src/CMSMicroservice.Protobuf/Protos/usercarts.proto index 982db19..5e0894e 100644 --- a/src/CMSMicroservice.Protobuf/Protos/usercarts.proto +++ b/src/CMSMicroservice.Protobuf/Protos/usercarts.proto @@ -85,6 +85,7 @@ message AddNewUserCartResponse message UpdateUserCartRequest { int64 id = 1; + int64 user_cart_id = 11; // Alias for frontend compatibility int32 count = 2; } message DeleteUserCartRequest @@ -145,7 +146,7 @@ message GetUserCartForCustomerRequest } message GetUserCartForCustomerResponse { - repeated UserCartItem items = 1; + repeated UserCartItem models = 1; int64 total_price = 2; int32 total_items_count = 3; string message = 4; @@ -156,11 +157,13 @@ message UserCartItem int64 product_id = 2; string product_title = 3; string product_short_information = 4; + string product_short_infomation = 14; // Alias for typo compatibility int64 product_price = 5; int32 product_discount = 6; string product_thumbnail_path = 7; int32 count = 8; int64 total_item_price = 9; + google.protobuf.Timestamp created = 10; // Creation timestamp for frontend } message GetAllUserCartsByFilterRequest { diff --git a/src/CMSMicroservice.Protobuf/Protos/userorder.proto b/src/CMSMicroservice.Protobuf/Protos/userorder.proto index 1dd98c7..f170dd4 100644 --- a/src/CMSMicroservice.Protobuf/Protos/userorder.proto +++ b/src/CMSMicroservice.Protobuf/Protos/userorder.proto @@ -128,6 +128,12 @@ service UserOrderContract body: "*" }; }; + + rpc GetVATRate(google.protobuf.Empty) returns (GetVATRateResponse){ + option (google.api.http) = { + get: "/Customer/GetVATRate" + }; + }; } message CreateNewUserOrderRequest { @@ -526,3 +532,11 @@ message ProductPVDto int64 unit_pv = 4; int64 total_pv = 5; } + +// GetVATRate - for frontend customer display +message GetVATRateResponse +{ + double vat_rate = 1; + int32 vat_percentage = 2; + bool is_enabled = 3; +} diff --git a/src/CMSMicroservice.WebApi/Services/PackageService.cs b/src/CMSMicroservice.WebApi/Services/PackageService.cs index 83b70c0..05bfb4e 100644 --- a/src/CMSMicroservice.WebApi/Services/PackageService.cs +++ b/src/CMSMicroservice.WebApi/Services/PackageService.cs @@ -81,12 +81,14 @@ public class PackageService : PackageContract.PackageContractBase { Id = 1, Name = "پکیج طلایی", + Title = "پکیج طلایی", // Populate alias field Description = "پکیج کامل با امکانات ویژه برای کاربران فعال", Price = 5600000, Currency = "IRR", PackageType = PackageTypeEnum.PackageTypeGolden, IsAvailable = true, ImageUrl = "/images/packages/golden.jpg", + ImagePath = "/images/packages/golden.jpg", // Populate alias field ValidityDays = 365, IsPopular = true, ShortDescription = "بهترین انتخاب برای درآمد بیشتر" @@ -95,12 +97,14 @@ public class PackageService : PackageContract.PackageContractBase { Id = 2, Name = "پکیج پریمیوم", + Title = "پکیج پریمیوم", // Populate alias field Description = "پکیج پیشرفته با امکانات حرفه‌ای", Price = 3200000, Currency = "IRR", PackageType = PackageTypeEnum.PackageTypePremium, IsAvailable = true, ImageUrl = "/images/packages/premium.jpg", + ImagePath = "/images/packages/premium.jpg", // Populate alias field ValidityDays = 180, IsPopular = false, ShortDescription = "برای کسب و کارهای متوسط" @@ -109,12 +113,14 @@ public class PackageService : PackageContract.PackageContractBase { Id = 3, Name = "پکیج ابتدایی", + Title = "پکیج ابتدایی", // Populate alias field Description = "پکیج مقدماتی برای شروع کار", Price = 1500000, Currency = "IRR", PackageType = PackageTypeEnum.PackageTypeBasic, IsAvailable = true, ImageUrl = "/images/packages/basic.jpg", + ImagePath = "/images/packages/basic.jpg", // Populate alias field ValidityDays = 90, IsPopular = false, ShortDescription = "مناسب برای شروع کننده‌ها" @@ -161,12 +167,14 @@ public class PackageService : PackageContract.PackageContractBase { Id = request.PackageId, Name = "پکیج طلایی", + Title = "پکیج طلایی", // Populate alias field Description = "پکیج کامل با تمام امکانات برای کاربران حرفه‌ای", Price = 5600000, Currency = "IRR", PackageType = PackageTypeEnum.PackageTypeGolden, IsAvailable = true, ImageUrl = "/images/packages/golden-detail.jpg", + ImagePath = "/images/packages/golden-detail.jpg", // Populate alias field ValidityDays = 365, IsPopular = true, ShortDescription = "بهترین انتخاب برای کسب درآمد حداکثری" diff --git a/src/NuGet.config b/src/NuGet.config index f875436..59d2375 100644 --- a/src/NuGet.config +++ b/src/NuGet.config @@ -4,11 +4,16 @@ + + + + + \ No newline at end of file