From 217ef147ddf4504e64022070656c745af1e666c6 Mon Sep 17 00:00:00 2001 From: masoodafar-web Date: Fri, 5 Dec 2025 17:26:58 +0330 Subject: [PATCH] feat: Implement manual payment system with gRPC service and related commands/queries --- .../GetAllUserOrderByFilterQueryHandler.cs | 5 +- .../GetAllUserOrderByFilterResponseDto.cs | 4 + .../GetUserOrder/GetUserOrderQueryHandler.cs | 11 +- .../GetUserOrder/GetUserOrderResponseDto.cs | 34 ++++- .../CMSMicroservice.Protobuf.csproj | 2 + .../Protos/manualpayment.proto | 130 ++++++++++++++++++ .../Protos/userorder.proto | 17 ++- .../Services/ManualPaymentService.cs | 59 ++++++++ 8 files changed, 257 insertions(+), 5 deletions(-) create mode 100644 src/CMSMicroservice.Protobuf/Protos/manualpayment.proto create mode 100644 src/CMSMicroservice.WebApi/Services/ManualPaymentService.cs diff --git a/src/CMSMicroservice.Application/UserOrderCQ/Queries/GetAllUserOrderByFilter/GetAllUserOrderByFilterQueryHandler.cs b/src/CMSMicroservice.Application/UserOrderCQ/Queries/GetAllUserOrderByFilter/GetAllUserOrderByFilterQueryHandler.cs index e55b0f3..5864f7a 100644 --- a/src/CMSMicroservice.Application/UserOrderCQ/Queries/GetAllUserOrderByFilter/GetAllUserOrderByFilterQueryHandler.cs +++ b/src/CMSMicroservice.Application/UserOrderCQ/Queries/GetAllUserOrderByFilter/GetAllUserOrderByFilterQueryHandler.cs @@ -15,6 +15,7 @@ public class GetAllUserOrderByFilterQueryHandler : IRequestHandler i.User) .Include(i => i.FactorDetails) .ThenInclude(t => t.Product) + .Include(i => i.OrderVAT) .ApplyOrder(sortBy: request.SortBy) .AsNoTracking() .AsQueryable(); @@ -61,7 +62,9 @@ public class GetAllUserOrderByFilterQueryHandler : IRequestHandler i.User) .Include(i => i.FactorDetails) .ThenInclude(t => t.Product) + .Include(i => i.OrderVAT) .AsNoTracking() .Where(x => x.Id == request.Id) .Select(x => new GetUserOrderResponseDto @@ -43,7 +44,15 @@ public class GetUserOrderQueryHandler : IRequestHandler? FactorDetails { get; set; } // وضعیت ارسال سفارش public DeliveryStatus DeliveryStatus { get; set; } - // کد رهگیری مرسوله + // کدرهگیری مرسوله public string? TrackingCode { get; set; } // توضیحات ارسال public string? DeliveryDescription { get; set; } @@ -35,8 +35,38 @@ public class GetUserOrderResponseDto public string? UserFullName { get; set; } // کدملی کاربر public string? UserNationalCode { get; set; } + // اطلاعات مالیات بر ارزش افزوده + public OrderVATInfoDto? VatInfo { get; set; } +} -}public class GetUserOrderResponseFactorDetail +/// +/// اطلاعات مالیات بر ارزش افزوده +/// +public class OrderVATInfoDto +{ + /// + /// نرخ مالیات (مثلاً 0.09 = 9%) + /// + public decimal VatRate { get; set; } + /// + /// مبلغ پایه (قبل از مالیات) + /// + public long BaseAmount { get; set; } + /// + /// مبلغ مالیات + /// + public long VatAmount { get; set; } + /// + /// مبلغ کل (پایه + مالیات) + /// + public long TotalAmount { get; set; } + /// + /// آیا پرداخت شده + /// + public bool IsPaid { get; set; } +} + +public class GetUserOrderResponseFactorDetail { //شناسه public long ProductId { get; set; } diff --git a/src/CMSMicroservice.Protobuf/CMSMicroservice.Protobuf.csproj b/src/CMSMicroservice.Protobuf/CMSMicroservice.Protobuf.csproj index 9045bf2..5551e40 100644 --- a/src/CMSMicroservice.Protobuf/CMSMicroservice.Protobuf.csproj +++ b/src/CMSMicroservice.Protobuf/CMSMicroservice.Protobuf.csproj @@ -48,6 +48,8 @@ + + diff --git a/src/CMSMicroservice.Protobuf/Protos/manualpayment.proto b/src/CMSMicroservice.Protobuf/Protos/manualpayment.proto new file mode 100644 index 0000000..cf01439 --- /dev/null +++ b/src/CMSMicroservice.Protobuf/Protos/manualpayment.proto @@ -0,0 +1,130 @@ +syntax = "proto3"; + +package manualpayment; + +import "public_messages.proto"; +import "google/protobuf/empty.proto"; +import "google/protobuf/wrappers.proto"; +import "google/protobuf/timestamp.proto"; +import "google/api/annotations.proto"; + +option csharp_namespace = "CMSMicroservice.Protobuf.Protos.ManualPayment"; + +service ManualPaymentContract +{ + rpc CreateManualPayment(CreateManualPaymentRequest) returns (CreateManualPaymentResponse){ + option (google.api.http) = { + post: "/CreateManualPayment" + body: "*" + }; + }; + + rpc ApproveManualPayment(ApproveManualPaymentRequest) returns (google.protobuf.Empty){ + option (google.api.http) = { + post: "/ApproveManualPayment" + body: "*" + }; + }; + + rpc RejectManualPayment(RejectManualPaymentRequest) returns (google.protobuf.Empty){ + option (google.api.http) = { + post: "/RejectManualPayment" + body: "*" + }; + }; + + rpc GetAllManualPayments(GetAllManualPaymentsRequest) returns (GetAllManualPaymentsResponse){ + option (google.api.http) = { + get: "/GetAllManualPayments" + }; + }; +} + +// Enums mirroring CMSMicroservice.Domain.Enums.ManualPaymentType +enum ManualPaymentType +{ + ManualPaymentType_Unknown = 0; + ManualPaymentType_CashDeposit = 1; + ManualPaymentType_DiscountWalletCharge = 2; + ManualPaymentType_NetworkWalletCharge = 3; + ManualPaymentType_Settlement = 4; + ManualPaymentType_ErrorCorrection = 5; + ManualPaymentType_Refund = 6; + ManualPaymentType_Other = 99; +} + +// Enums mirroring CMSMicroservice.Domain.Enums.ManualPaymentStatus +enum ManualPaymentStatus +{ + ManualPaymentStatus_Pending = 0; + ManualPaymentStatus_Approved = 1; + ManualPaymentStatus_Rejected = 2; + ManualPaymentStatus_Cancelled = 3; +} + +message CreateManualPaymentRequest +{ + int64 user_id = 1; + int64 amount = 2; + ManualPaymentType type = 3; + string description = 4; + google.protobuf.StringValue reference_number = 5; +} + +message CreateManualPaymentResponse +{ + int64 id = 1; +} + +message ApproveManualPaymentRequest +{ + int64 manual_payment_id = 1; + google.protobuf.StringValue approval_note = 2; +} + +message RejectManualPaymentRequest +{ + int64 manual_payment_id = 1; + string rejection_reason = 2; +} + +message GetAllManualPaymentsRequest +{ + int32 page_number = 1; + int32 page_size = 2; + google.protobuf.Int64Value user_id = 3; + google.protobuf.Int32Value status = 4; + google.protobuf.Int32Value type = 5; + google.protobuf.Int64Value requested_by = 6; + google.protobuf.BoolValue order_by_descending = 7; +} + +message GetAllManualPaymentsResponse +{ + messages.MetaData meta_data = 1; + repeated ManualPaymentModel models = 2; +} + +message ManualPaymentModel +{ + int64 id = 1; + int64 user_id = 2; + string user_full_name = 3; + string user_mobile = 4; + int64 amount = 5; + ManualPaymentType type = 6; + string type_display = 7; + string description = 8; + google.protobuf.StringValue reference_number = 9; + ManualPaymentStatus status = 10; + string status_display = 11; + int64 requested_by = 12; + string requested_by_name = 13; + google.protobuf.Int64Value approved_by = 14; + google.protobuf.StringValue approved_by_name = 15; + google.protobuf.Timestamp approved_at = 16; + google.protobuf.StringValue rejection_reason = 17; + google.protobuf.Int64Value transaction_id = 18; + google.protobuf.Timestamp created = 19; +} + diff --git a/src/CMSMicroservice.Protobuf/Protos/userorder.proto b/src/CMSMicroservice.Protobuf/Protos/userorder.proto index eba196b..1c74810 100644 --- a/src/CMSMicroservice.Protobuf/Protos/userorder.proto +++ b/src/CMSMicroservice.Protobuf/Protos/userorder.proto @@ -163,7 +163,20 @@ message GetUserOrderResponse // نام کامل و کدملی کاربر google.protobuf.StringValue user_full_name = 15; google.protobuf.StringValue user_national_code = 16; + // اطلاعات مالیات بر ارزش افزوده + OrderVATInfo vat_info = 17; } + +// اطلاعات مالیات بر ارزش افزوده +message OrderVATInfo +{ + double vat_rate = 1; // نرخ مالیات (مثلاً 0.09) + int64 base_amount = 2; // مبلغ پایه (قبل از مالیات) + int64 vat_amount = 3; // مبلغ مالیات + int64 total_amount = 4; // مبلغ کل (پایه + مالیات) + bool is_paid = 5; // آیا پرداخت شده +} + message GetUserOrderResponseFactorDetail { int64 product_id = 1; @@ -236,6 +249,9 @@ message GetAllUserOrderByFilterResponseModel // نام کامل و کدملی کاربر google.protobuf.StringValue user_full_name = 15; google.protobuf.StringValue user_national_code = 16; + // مبلغ و درصد مالیات بر ارزش افزوده + int64 vat_amount = 17; + double vat_percentage = 18; } message GetAllUserOrderByFilterResponseModelFactorDetail { @@ -352,4 +368,3 @@ message ProductPVDto int64 unit_pv = 4; int64 total_pv = 5; } - diff --git a/src/CMSMicroservice.WebApi/Services/ManualPaymentService.cs b/src/CMSMicroservice.WebApi/Services/ManualPaymentService.cs new file mode 100644 index 0000000..2206ab0 --- /dev/null +++ b/src/CMSMicroservice.WebApi/Services/ManualPaymentService.cs @@ -0,0 +1,59 @@ +using CMSMicroservice.Protobuf.Protos.ManualPayment; +using CMSMicroservice.WebApi.Common.Services; +using CMSMicroservice.Application.ManualPaymentCQ.Commands.CreateManualPayment; +using CMSMicroservice.Application.ManualPaymentCQ.Commands.ApproveManualPayment; +using CMSMicroservice.Application.ManualPaymentCQ.Commands.RejectManualPayment; +using CMSMicroservice.Application.ManualPaymentCQ.Queries.GetAllManualPayments; +using Grpc.Core; +using Mapster; +using MediatR; + +namespace CMSMicroservice.WebApi.Services; + +public class ManualPaymentService : ManualPaymentContract.ManualPaymentContractBase +{ + private readonly IDispatchRequestToCQRS _dispatchRequestToCQRS; + private readonly ISender _sender; + + public ManualPaymentService( + IDispatchRequestToCQRS dispatchRequestToCQRS, + ISender sender) + { + _dispatchRequestToCQRS = dispatchRequestToCQRS; + _sender = sender; + } + + public override async Task CreateManualPayment( + CreateManualPaymentRequest request, + ServerCallContext context) + { + var command = request.Adapt(); + var id = await _sender.Send(command, context.CancellationToken); + + return new CreateManualPaymentResponse + { + Id = id + }; + } + + public override async Task ApproveManualPayment( + ApproveManualPaymentRequest request, + ServerCallContext context) + { + return await _dispatchRequestToCQRS.Handle(request, context); + } + + public override async Task RejectManualPayment( + RejectManualPaymentRequest request, + ServerCallContext context) + { + return await _dispatchRequestToCQRS.Handle(request, context); + } + + public override async Task GetAllManualPayments( + GetAllManualPaymentsRequest request, + ServerCallContext context) + { + return await _dispatchRequestToCQRS.Handle(request, context); + } +}