feat: add manual membership payment and update commission queries
All checks were successful
Build and Deploy / build (push) Successful in 2m29s

This commit is contained in:
masoodafar-web
2025-12-12 10:23:52 +03:30
parent 19a717fc87
commit c6abee2650
18 changed files with 617 additions and 374 deletions

View File

@@ -1,24 +1,37 @@
namespace BackOffice.BFF.Application.CommissionCQ.Queries.GetUserPayouts; namespace BackOffice.BFF.Application.CommissionCQ.Queries.GetUserPayouts;
public record GetUserPayoutsQuery : IRequest<GetUserPayoutsResponseDto> public record GetUserPayoutsQuery : IRequest<GetUserPayoutsResponseDto>
{
/// <summary>
/// موقعیت صفحه‌بندی
/// </summary>
public PaginationState? PaginationState { get; init; }
/// <summary>
/// مرتب‌سازی بر اساس
/// </summary>
public string? SortBy { get; init; }
/// <summary>
/// فیلتر
/// </summary>
public GetUserPayoutsFilter? Filter { get; init; }
}
public class GetUserPayoutsFilter
{ {
/// <summary> /// <summary>
/// شناسه کاربر /// شناسه کاربر
/// </summary> /// </summary>
public long UserId { get; init; } public long? UserId { get; set; }
/// <summary> /// <summary>
/// شماره هفته (اختیاری - برای فیلتر) /// شماره هفته (اختیاری - برای فیلتر)
/// </summary> /// </summary>
public string? WeekNumber { get; init; } public string? WeekNumber { get; set; }
/// <summary> /// <summary>
/// شماره صفحه (پیش‌فرض: 1) /// وضعیت (اختیاری)
/// </summary> /// </summary>
public int PageNumber { get; init; } = 1; public int? Status { get; set; }
/// <summary>
/// تعداد در هر صفحه (پیش‌فرض: 10)
/// </summary>
public int PageSize { get; init; } = 10;
} }

View File

@@ -1,5 +1,3 @@
using CMSMicroservice.Protobuf.Protos.Commission; using CMSMicroservice.Protobuf.Protos.Commission;
namespace BackOffice.BFF.Application.CommissionCQ.Queries.GetUserPayouts; namespace BackOffice.BFF.Application.CommissionCQ.Queries.GetUserPayouts;
@@ -15,10 +13,55 @@ public class GetUserPayoutsQueryHandler : IRequestHandler<GetUserPayoutsQuery, G
public async Task<GetUserPayoutsResponseDto> Handle(GetUserPayoutsQuery request, CancellationToken cancellationToken) public async Task<GetUserPayoutsResponseDto> Handle(GetUserPayoutsQuery request, CancellationToken cancellationToken)
{ {
var cmsRequest = new GetUserCommissionPayoutsRequest
{
PageIndex = request.PaginationState?.PageNumber ?? 1,
PageSize = request.PaginationState?.PageSize ?? 10
};
if (request.Filter?.UserId.HasValue == true && request.Filter.UserId.Value > 0)
{
cmsRequest.UserId = request.Filter.UserId.Value;
}
if (!string.IsNullOrWhiteSpace(request.Filter?.WeekNumber))
{
cmsRequest.WeekNumber = request.Filter.WeekNumber;
}
if (request.Filter?.Status.HasValue == true)
{
cmsRequest.Status = request.Filter.Status.Value;
}
var response = await _context.Commissions.GetUserCommissionPayoutsAsync( var response = await _context.Commissions.GetUserCommissionPayoutsAsync(
request.Adapt<GetUserCommissionPayoutsRequest>(), cmsRequest,
cancellationToken: cancellationToken); cancellationToken: cancellationToken);
return response.Adapt<GetUserPayoutsResponseDto>(); return new GetUserPayoutsResponseDto
{
MetaData = new MetaData
{
CurrentPage = response.MetaData.CurrentPage,
PageSize = response.MetaData.PageSize,
TotalCount = response.MetaData.TotalCount,
TotalPage = response.MetaData.TotalPage
},
Models = response.Models.Select(m => new GetUserPayoutsResponseModel
{
Id = m.Id,
UserId = m.UserId,
UserName = m.UserName,
WeekNumber = m.WeekNumber,
BalancesEarned = m.BalancesEarned,
ValuePerBalance = m.ValuePerBalance,
TotalAmount = m.TotalAmount,
Status = m.Status,
WithdrawalMethod = m.WithdrawalMethod,
IbanNumber = m.IbanNumber,
Created = m.Created.ToDateTime(),
LastModified = m.LastModified?.ToDateTime()
}).ToList()
};
} }
} }

View File

@@ -0,0 +1,24 @@
namespace BackOffice.BFF.Application.CommissionCQ.Queries.GetUserPayouts;
public class GetUserPayoutsQueryValidator : AbstractValidator<GetUserPayoutsQuery>
{
public GetUserPayoutsQueryValidator()
{
RuleFor(x => x.PaginationState)
.NotNull()
.WithMessage("موقعیت صفحه‌بندی الزامی است");
When(x => x.Filter != null, () =>
{
RuleFor(x => x.Filter!.UserId)
.GreaterThan(0)
.When(x => x.Filter!.UserId.HasValue)
.WithMessage("شناسه کاربر معتبر نیست");
RuleFor(x => x.Filter!.WeekNumber)
.Matches(@"^\d{4}-W\d{2}$")
.When(x => !string.IsNullOrWhiteSpace(x.Filter!.WeekNumber))
.WithMessage("فرمت شماره هفته باید به صورت YYYY-Www باشد (مثال: 2025-W48)");
});
}
}

View File

@@ -3,27 +3,17 @@ namespace BackOffice.BFF.Application.CommissionCQ.Queries.GetUserPayouts;
public class GetUserPayoutsResponseDto public class GetUserPayoutsResponseDto
{ {
/// <summary> /// <summary>
/// لیست Payout ها /// متادیتا
/// </summary> /// </summary>
public List<UserPayoutDto> Payouts { get; set; } = new(); public MetaData MetaData { get; set; }
/// <summary> /// <summary>
/// تعداد کل رکوردها /// مدل خروجی
/// </summary> /// </summary>
public int TotalCount { get; set; } public List<GetUserPayoutsResponseModel>? Models { get; set; }
/// <summary>
/// شماره صفحه فعلی
/// </summary>
public int PageNumber { get; set; }
/// <summary>
/// تعداد در هر صفحه
/// </summary>
public int PageSize { get; set; }
} }
public class UserPayoutDto public class GetUserPayoutsResponseModel
{ {
/// <summary> /// <summary>
/// شناسه Payout /// شناسه Payout
@@ -35,43 +25,53 @@ public class UserPayoutDto
/// </summary> /// </summary>
public long UserId { get; set; } public long UserId { get; set; }
/// <summary>
/// نام کاربر
/// </summary>
public string UserName { get; set; } = string.Empty;
/// <summary> /// <summary>
/// شماره هفته /// شماره هفته
/// </summary> /// </summary>
public string WeekNumber { get; set; } = string.Empty; public string WeekNumber { get; set; } = string.Empty;
/// <summary> /// <summary>
/// بالانس Leg چپ /// تعداد تعادل‌های کسب شده
/// </summary> /// </summary>
public decimal LeftLegBalance { get; set; } public int BalancesEarned { get; set; }
/// <summary> /// <summary>
/// بالانس Leg راست /// ارزش هر تعادل
/// </summary> /// </summary>
public decimal RightLegBalance { get; set; } public long ValuePerBalance { get; set; }
/// <summary> /// <summary>
/// بالانس Leg ضعیف‌تر /// مبلغ کل
/// </summary> /// </summary>
public decimal WeakerLegBalance { get; set; } public long TotalAmount { get; set; }
/// <summary> /// <summary>
/// مبلغ کمیسیون (تومان) /// وضعیت (0=Pending, 1=Paid, 2=Failed)
/// </summary> /// </summary>
public decimal CommissionAmount { get; set; } public int Status { get; set; }
/// <summary> /// <summary>
/// وضعیت پرداخت /// روش برداشت
/// </summary> /// </summary>
public string Status { get; set; } = string.Empty; public int? WithdrawalMethod { get; set; }
/// <summary> /// <summary>
/// تاریخ پرداخت /// شماره شبا
/// </summary> /// </summary>
public DateTime? PaidAt { get; set; } public string IbanNumber { get; set; } = string.Empty;
/// <summary> /// <summary>
/// تاریخ ایجاد /// تاریخ ایجاد
/// </summary> /// </summary>
public DateTime CreatedAt { get; set; } public DateTime Created { get; set; }
/// <summary>
/// آخرین تغییر
/// </summary>
public DateTime? LastModified { get; set; }
} }

View File

@@ -1,29 +1,37 @@
namespace BackOffice.BFF.Application.CommissionCQ.Queries.GetUserWeeklyBalances; namespace BackOffice.BFF.Application.CommissionCQ.Queries.GetUserWeeklyBalances;
public record GetUserWeeklyBalancesQuery : IRequest<GetUserWeeklyBalancesResponseDto> public record GetUserWeeklyBalancesQuery : IRequest<GetUserWeeklyBalancesResponseDto>
{
/// <summary>
/// موقعیت صفحه‌بندی
/// </summary>
public PaginationState? PaginationState { get; init; }
/// <summary>
/// مرتب‌سازی بر اساس
/// </summary>
public string? SortBy { get; init; }
/// <summary>
/// فیلتر
/// </summary>
public GetUserWeeklyBalancesFilter? Filter { get; init; }
}
public class GetUserWeeklyBalancesFilter
{ {
/// <summary> /// <summary>
/// شناسه کاربر (فیلتر اختیاری) /// شناسه کاربر (فیلتر اختیاری)
/// </summary> /// </summary>
public long? UserId { get; init; } public long? UserId { get; set; }
/// <summary> /// <summary>
/// شماره هفته (فیلتر اختیاری) /// شماره هفته (فیلتر اختیاری)
/// </summary> /// </summary>
public string? WeekNumber { get; init; } public string? WeekNumber { get; set; }
/// <summary> /// <summary>
/// فقط تعادل‌های فعال (منقضی نشده) /// فقط تعادل‌های فعال (منقضی نشده)
/// </summary> /// </summary>
public bool OnlyActive { get; init; } public bool? OnlyActive { get; set; }
/// <summary>
/// شماره صفحه
/// </summary>
public int PageIndex { get; init; } = 1;
/// <summary>
/// تعداد در صفحه
/// </summary>
public int PageSize { get; init; } = 10;
} }

View File

@@ -17,19 +17,19 @@ public class GetUserWeeklyBalancesQueryHandler : IRequestHandler<GetUserWeeklyBa
{ {
var grpcRequest = new GetUserWeeklyBalancesRequest var grpcRequest = new GetUserWeeklyBalancesRequest
{ {
OnlyActive = request.OnlyActive, OnlyActive = request.Filter?.OnlyActive ?? false,
PageIndex = request.PageIndex, PageIndex = request.PaginationState?.PageNumber ?? 1,
PageSize = request.PageSize PageSize = request.PaginationState?.PageSize ?? 10
}; };
if (request.UserId.HasValue) if (request.Filter?.UserId.HasValue == true && request.Filter.UserId.Value > 0)
{ {
grpcRequest.UserId = request.UserId.Value; grpcRequest.UserId = request.Filter.UserId.Value;
} }
if (!string.IsNullOrWhiteSpace(request.WeekNumber)) if (!string.IsNullOrWhiteSpace(request.Filter?.WeekNumber))
{ {
grpcRequest.WeekNumber = request.WeekNumber; grpcRequest.WeekNumber = request.Filter.WeekNumber;
} }
var response = await _context.Commissions.GetUserWeeklyBalancesAsync(grpcRequest, cancellationToken: cancellationToken); var response = await _context.Commissions.GetUserWeeklyBalancesAsync(grpcRequest, cancellationToken: cancellationToken);

View File

@@ -0,0 +1,24 @@
namespace BackOffice.BFF.Application.CommissionCQ.Queries.GetUserWeeklyBalances;
public class GetUserWeeklyBalancesQueryValidator : AbstractValidator<GetUserWeeklyBalancesQuery>
{
public GetUserWeeklyBalancesQueryValidator()
{
RuleFor(x => x.PaginationState)
.NotNull()
.WithMessage("موقعیت صفحه‌بندی الزامی است");
When(x => x.Filter != null, () =>
{
RuleFor(x => x.Filter!.UserId)
.GreaterThan(0)
.When(x => x.Filter!.UserId.HasValue)
.WithMessage("شناسه کاربر معتبر نیست");
RuleFor(x => x.Filter!.WeekNumber)
.Matches(@"^\d{4}-W\d{2}$")
.When(x => !string.IsNullOrWhiteSpace(x.Filter!.WeekNumber))
.WithMessage("فرمت شماره هفته باید به صورت YYYY-Www باشد (مثال: 2025-W48)");
});
}
}

View File

@@ -0,0 +1,9 @@
namespace BackOffice.BFF.Application.ManualPaymentCQ.Commands.ProcessManualMembershipPayment;
public record ProcessManualMembershipPaymentCommand : IRequest<ProcessManualMembershipPaymentResponseDto>
{
public long UserId { get; init; }
public long Amount { get; init; }
public string ReferenceNumber { get; init; } = string.Empty;
public string? Description { get; init; }
}

View File

@@ -0,0 +1,55 @@
using CMSMicroservice.Protobuf.Protos.ManualPayment;
using Microsoft.Extensions.Logging;
namespace BackOffice.BFF.Application.ManualPaymentCQ.Commands.ProcessManualMembershipPayment;
public class ProcessManualMembershipPaymentCommandHandler : IRequestHandler<ProcessManualMembershipPaymentCommand, ProcessManualMembershipPaymentResponseDto>
{
private readonly IApplicationContractContext _context;
private readonly ICurrentUserService _currentUser;
private readonly ILogger<ProcessManualMembershipPaymentCommandHandler> _logger;
public ProcessManualMembershipPaymentCommandHandler(
IApplicationContractContext context,
ICurrentUserService currentUser,
ILogger<ProcessManualMembershipPaymentCommandHandler> logger)
{
_context = context;
_currentUser = currentUser;
_logger = logger;
}
public async Task<ProcessManualMembershipPaymentResponseDto> Handle(
ProcessManualMembershipPaymentCommand request,
CancellationToken cancellationToken)
{
_logger.LogInformation(
"Processing manual membership payment via BFF for UserId {UserId}, Amount {Amount}",
request.UserId,
request.Amount);
var grpcRequest = new ProcessManualMembershipPaymentRequest
{
UserId = request.UserId,
Amount = request.Amount,
ReferenceNumber = request.ReferenceNumber
};
if (!string.IsNullOrWhiteSpace(request.Description))
{
grpcRequest.Description = request.Description;
}
var response = await _context.ManualPayments.ProcessManualMembershipPaymentAsync(
grpcRequest,
cancellationToken: cancellationToken);
return new ProcessManualMembershipPaymentResponseDto
{
TransactionId = response.TransactionId,
OrderId = response.OrderId,
NewWalletBalance = response.NewWalletBalance,
Message = response.Message
};
}
}

View File

@@ -0,0 +1,21 @@
namespace BackOffice.BFF.Application.ManualPaymentCQ.Commands.ProcessManualMembershipPayment;
public class ProcessManualMembershipPaymentCommandValidator : AbstractValidator<ProcessManualMembershipPaymentCommand>
{
public ProcessManualMembershipPaymentCommandValidator()
{
RuleFor(x => x.UserId)
.GreaterThan(0)
.WithMessage("شناسه کاربر معتبر نیست");
RuleFor(x => x.Amount)
.GreaterThan(0)
.WithMessage("مبلغ باید بزرگتر از صفر باشد");
RuleFor(x => x.ReferenceNumber)
.NotEmpty()
.WithMessage("شماره مرجع الزامی است")
.MaximumLength(50)
.WithMessage("شماره مرجع نباید بیشتر از 50 کاراکتر باشد");
}
}

View File

@@ -0,0 +1,9 @@
namespace BackOffice.BFF.Application.ManualPaymentCQ.Commands.ProcessManualMembershipPayment;
public class ProcessManualMembershipPaymentResponseDto
{
public long TransactionId { get; set; }
public long OrderId { get; set; }
public long NewWalletBalance { get; set; }
public string Message { get; set; } = string.Empty;
}

View File

@@ -7,7 +7,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Afrino.FMSMicroservice.Protobuf" Version="0.0.122" /> <PackageReference Include="Afrino.FMSMicroservice.Protobuf" Version="0.0.122" />
<PackageReference Include="Foursat.CMSMicroservice.Protobuf" Version="0.0.148" /> <PackageReference Include="Foursat.CMSMicroservice.Protobuf" Version="0.0.149" />
<PackageReference Include="Google.Protobuf" Version="3.23.3" /> <PackageReference Include="Google.Protobuf" Version="3.23.3" />
<PackageReference Include="Grpc.Net.ClientFactory" Version="2.54.0" /> <PackageReference Include="Grpc.Net.ClientFactory" Version="2.54.0" />

View File

@@ -2,7 +2,9 @@ using BackOffice.BFF.Application.CommissionCQ.Queries.GetWeeklyPool;
using BackOffice.BFF.Application.CommissionCQ.Queries.GetAllWeeklyPools; using BackOffice.BFF.Application.CommissionCQ.Queries.GetAllWeeklyPools;
using BackOffice.BFF.Application.CommissionCQ.Queries.GetUserWeeklyBalances; using BackOffice.BFF.Application.CommissionCQ.Queries.GetUserWeeklyBalances;
using BackOffice.BFF.Application.CommissionCQ.Queries.GetAvailableWeeks; using BackOffice.BFF.Application.CommissionCQ.Queries.GetAvailableWeeks;
using BackOffice.BFF.Application.CommissionCQ.Queries.GetUserPayouts;
using Foursat.BackOffice.BFF.Commission.Protos; using Foursat.BackOffice.BFF.Commission.Protos;
using System.Collections.Generic;
namespace BackOffice.BFF.WebApi.Common.Mappings; namespace BackOffice.BFF.WebApi.Common.Mappings;
@@ -28,32 +30,34 @@ public class CommissionProfile : IRegister
}); });
// GetUserPayoutsResponseDto -> GetUserCommissionPayoutsResponse // GetUserPayoutsResponseDto -> GetUserCommissionPayoutsResponse
// config.NewConfig<GetUserPayoutsResponseDto, GetUserCommissionPayoutsResponse>() config.NewConfig<GetUserPayoutsResponseDto, GetUserCommissionPayoutsResponse>()
// .MapWith(src => new GetUserCommissionPayoutsResponse .MapWith(src => new GetUserCommissionPayoutsResponse
// { {
// MetaData = new BackOffice.BFF.Protobuf.Common.MetaData MetaData = new BackOffice.BFF.Protobuf.Common.MetaData
// { {
// CurrentPage = src.PageNumber, CurrentPage = src.MetaData.CurrentPage,
// PageSize = src.PageSize, PageSize = src.MetaData.PageSize,
// TotalCount = src.TotalCount, TotalCount = src.MetaData.TotalCount,
// TotalPage = src.TotalPages TotalPage = src.MetaData.TotalPage
// }, },
// Models = { src.Payouts.Select(m => new UserCommissionPayoutModel Models = { (src.Models ?? new List<GetUserPayoutsResponseModel>()).Select(m => new UserCommissionPayoutModel
// { {
// Id = m.Id, Id = m.Id,
// UserId = m.UserId, UserId = m.UserId,
// UserName = m.UserName ?? string.Empty, UserName = m.UserName,
// WeekNumber = m.WeekNumber ?? string.Empty, WeekNumber = m.WeekNumber,
// BalanceCount = m.BalanceCount, BalancesEarned = m.BalancesEarned,
// PayoutAmount = m.PayoutAmount, ValuePerBalance = m.ValuePerBalance,
// Status = m.Status, TotalAmount = m.TotalAmount,
// StatusDisplay = m.StatusDisplay ?? string.Empty, Status = m.Status,
// PayoutDate = m.PayoutDate.HasValue WithdrawalMethod = m.WithdrawalMethod,
// ? Timestamp.FromDateTime(DateTime.SpecifyKind(m.PayoutDate.Value, DateTimeKind.Utc)) IbanNumber = m.IbanNumber,
// : null, Created = Timestamp.FromDateTime(DateTime.SpecifyKind(m.Created, DateTimeKind.Utc)),
// Created = Timestamp.FromDateTime(DateTime.SpecifyKind(m.Created, DateTimeKind.Utc)) LastModified = m.LastModified.HasValue
// }) } ? Timestamp.FromDateTime(DateTime.SpecifyKind(m.LastModified.Value, DateTimeKind.Utc))
// }); : null
}) }
});
// GetAllWeeklyPoolsResponseDto -> GetAllWeeklyPoolsResponse // GetAllWeeklyPoolsResponseDto -> GetAllWeeklyPoolsResponse
config.NewConfig<GetAllWeeklyPoolsResponseDto, GetAllWeeklyPoolsResponse>() config.NewConfig<GetAllWeeklyPoolsResponseDto, GetAllWeeklyPoolsResponse>()

View File

@@ -3,6 +3,7 @@ using BackOffice.BFF.WebApi.Common.Services;
using BackOffice.BFF.Application.ManualPaymentCQ.Commands.CreateManualPayment; using BackOffice.BFF.Application.ManualPaymentCQ.Commands.CreateManualPayment;
using BackOffice.BFF.Application.ManualPaymentCQ.Commands.ApproveManualPayment; using BackOffice.BFF.Application.ManualPaymentCQ.Commands.ApproveManualPayment;
using BackOffice.BFF.Application.ManualPaymentCQ.Commands.RejectManualPayment; using BackOffice.BFF.Application.ManualPaymentCQ.Commands.RejectManualPayment;
using BackOffice.BFF.Application.ManualPaymentCQ.Commands.ProcessManualMembershipPayment;
using BackOffice.BFF.Application.ManualPaymentCQ.Queries.GetManualPayments; using BackOffice.BFF.Application.ManualPaymentCQ.Queries.GetManualPayments;
namespace BackOffice.BFF.WebApi.Services; namespace BackOffice.BFF.WebApi.Services;
@@ -70,4 +71,14 @@ public class ManualPaymentService : ManualPaymentContract.ManualPaymentContractB
return result.Adapt<GetManualPaymentsResponse>(); return result.Adapt<GetManualPaymentsResponse>();
} }
[RequiresPermission(PermissionNames.ManualPaymentsCreate)]
public override async Task<ProcessManualMembershipPaymentResponse> ProcessManualMembershipPayment(
ProcessManualMembershipPaymentRequest request,
ServerCallContext context)
{
return await _dispatchRequestToCQRS.Handle<ProcessManualMembershipPaymentRequest, ProcessManualMembershipPaymentCommand, ProcessManualMembershipPaymentResponse>(
request,
context);
}
} }

View File

@@ -6,7 +6,7 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<IsPackable>true</IsPackable> <IsPackable>true</IsPackable>
<PackageId>Foursat.BackOffice.BFF.Commission.Protobuf</PackageId> <PackageId>Foursat.BackOffice.BFF.Commission.Protobuf</PackageId>
<Version>0.0.7</Version> <Version>0.0.12</Version>
<Authors>FourSat</Authors> <Authors>FourSat</Authors>
<Company>FourSat</Company> <Company>FourSat</Company>
<Product>BackOffice.BFF.Commission.Protobuf</Product> <Product>BackOffice.BFF.Commission.Protobuf</Product>
@@ -32,7 +32,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Foursat.BackOffice.BFF.Common.Protobuf" Version="0.0.1" /> <PackageReference Include="Foursat.BackOffice.BFF.Common.Protobuf" Version="0.0.2" />
</ItemGroup> </ItemGroup>
<Target Name="PushPackage" AfterTargets="Pack"> <Target Name="PushPackage" AfterTargets="Pack">

View File

@@ -12,109 +12,109 @@ option csharp_namespace = "Foursat.BackOffice.BFF.Commission.Protos";
service CommissionContract service CommissionContract
{ {
// Commands // Commands
rpc CalculateWeeklyBalances(CalculateWeeklyBalancesRequest) returns (google.protobuf.Empty){ rpc CalculateWeeklyBalances(CalculateWeeklyBalancesRequest) returns (google.protobuf.Empty){
option (google.api.http) = { option (google.api.http) = {
post: "/CalculateWeeklyBalances" post: "/CalculateWeeklyBalances"
body: "*" body: "*"
};
}; };
rpc CalculateWeeklyCommissionPool(CalculateWeeklyCommissionPoolRequest) returns (google.protobuf.Empty){ };
option (google.api.http) = { rpc CalculateWeeklyCommissionPool(CalculateWeeklyCommissionPoolRequest) returns (google.protobuf.Empty){
post: "/CalculateWeeklyCommissionPool" option (google.api.http) = {
body: "*" post: "/CalculateWeeklyCommissionPool"
}; body: "*"
}; };
rpc ProcessUserPayouts(ProcessUserPayoutsRequest) returns (google.protobuf.Empty){ };
option (google.api.http) = { rpc ProcessUserPayouts(ProcessUserPayoutsRequest) returns (google.protobuf.Empty){
post: "/ProcessUserPayouts" option (google.api.http) = {
body: "*" post: "/ProcessUserPayouts"
}; body: "*"
}; };
rpc RequestWithdrawal(RequestWithdrawalRequest) returns (google.protobuf.Empty){ };
option (google.api.http) = { rpc RequestWithdrawal(RequestWithdrawalRequest) returns (google.protobuf.Empty){
post: "/RequestWithdrawal" option (google.api.http) = {
body: "*" post: "/RequestWithdrawal"
}; body: "*"
}; };
rpc ProcessWithdrawal(ProcessWithdrawalRequest) returns (google.protobuf.Empty){ };
option (google.api.http) = { rpc ProcessWithdrawal(ProcessWithdrawalRequest) returns (google.protobuf.Empty){
post: "/ProcessWithdrawal" option (google.api.http) = {
body: "*" post: "/ProcessWithdrawal"
}; body: "*"
}; };
};
// Queries
rpc GetWeeklyCommissionPool(GetWeeklyCommissionPoolRequest) returns (GetWeeklyCommissionPoolResponse){ // Queries
option (google.api.http) = { rpc GetWeeklyCommissionPool(GetWeeklyCommissionPoolRequest) returns (GetWeeklyCommissionPoolResponse){
get: "/GetWeeklyCommissionPool" option (google.api.http) = {
}; get: "/GetWeeklyCommissionPool"
}; };
rpc GetUserCommissionPayouts(GetUserCommissionPayoutsRequest) returns (GetUserCommissionPayoutsResponse){ };
option (google.api.http) = { rpc GetUserCommissionPayouts(GetUserCommissionPayoutsRequest) returns (GetUserCommissionPayoutsResponse){
get: "/GetUserCommissionPayouts" option (google.api.http) = {
}; get: "/GetUserCommissionPayouts"
}; };
rpc GetCommissionPayoutHistory(GetCommissionPayoutHistoryRequest) returns (GetCommissionPayoutHistoryResponse){ };
option (google.api.http) = { rpc GetCommissionPayoutHistory(GetCommissionPayoutHistoryRequest) returns (GetCommissionPayoutHistoryResponse){
get: "/GetCommissionPayoutHistory" option (google.api.http) = {
}; get: "/GetCommissionPayoutHistory"
}; };
rpc GetUserWeeklyBalances(GetUserWeeklyBalancesRequest) returns (GetUserWeeklyBalancesResponse){ };
option (google.api.http) = { rpc GetUserWeeklyBalances(GetUserWeeklyBalancesRequest) returns (GetUserWeeklyBalancesResponse){
get: "/GetUserWeeklyBalances" option (google.api.http) = {
}; get: "/GetUserWeeklyBalances"
}; };
rpc GetAllWeeklyPools(GetAllWeeklyPoolsRequest) returns (GetAllWeeklyPoolsResponse){ };
option (google.api.http) = { rpc GetAllWeeklyPools(GetAllWeeklyPoolsRequest) returns (GetAllWeeklyPoolsResponse){
get: "/GetAllWeeklyPools" option (google.api.http) = {
}; get: "/GetAllWeeklyPools"
}; };
rpc GetWithdrawalRequests(GetWithdrawalRequestsRequest) returns (GetWithdrawalRequestsResponse){ };
option (google.api.http) = { rpc GetWithdrawalRequests(GetWithdrawalRequestsRequest) returns (GetWithdrawalRequestsResponse){
get: "/GetWithdrawalRequests" option (google.api.http) = {
}; get: "/GetWithdrawalRequests"
}; };
rpc ApproveWithdrawal(ApproveWithdrawalRequest) returns (google.protobuf.Empty){ };
option (google.api.http) = { rpc ApproveWithdrawal(ApproveWithdrawalRequest) returns (google.protobuf.Empty){
post: "/ApproveWithdrawal" option (google.api.http) = {
body: "*" post: "/ApproveWithdrawal"
}; body: "*"
}; };
rpc RejectWithdrawal(RejectWithdrawalRequest) returns (google.protobuf.Empty){ };
option (google.api.http) = { rpc RejectWithdrawal(RejectWithdrawalRequest) returns (google.protobuf.Empty){
post: "/RejectWithdrawal" option (google.api.http) = {
body: "*" post: "/RejectWithdrawal"
}; body: "*"
}; };
};
// Worker Control APIs
rpc TriggerWeeklyCalculation(TriggerWeeklyCalculationRequest) returns (TriggerWeeklyCalculationResponse){ // Worker Control APIs
option (google.api.http) = { rpc TriggerWeeklyCalculation(TriggerWeeklyCalculationRequest) returns (TriggerWeeklyCalculationResponse){
post: "/TriggerWeeklyCalculation" option (google.api.http) = {
body: "*" post: "/TriggerWeeklyCalculation"
}; body: "*"
}; };
rpc GetWorkerStatus(GetWorkerStatusRequest) returns (GetWorkerStatusResponse){ };
option (google.api.http) = { rpc GetWorkerStatus(GetWorkerStatusRequest) returns (GetWorkerStatusResponse){
get: "/GetWorkerStatus" option (google.api.http) = {
}; get: "/GetWorkerStatus"
}; };
rpc GetWorkerExecutionLogs(GetWorkerExecutionLogsRequest) returns (GetWorkerExecutionLogsResponse){ };
option (google.api.http) = { rpc GetWorkerExecutionLogs(GetWorkerExecutionLogsRequest) returns (GetWorkerExecutionLogsResponse){
get: "/GetWorkerExecutionLogs" option (google.api.http) = {
}; get: "/GetWorkerExecutionLogs"
}; };
rpc GetAvailableWeeks(GetAvailableWeeksRequest) returns (GetAvailableWeeksResponse){ };
option (google.api.http) = { rpc GetAvailableWeeks(GetAvailableWeeksRequest) returns (GetAvailableWeeksResponse){
get: "/GetAvailableWeeks" option (google.api.http) = {
}; get: "/GetAvailableWeeks"
}; };
rpc GetWithdrawalReports(GetWithdrawalReportsRequest) returns (GetWithdrawalReportsResponse){ };
option (google.api.http) = { rpc GetWithdrawalReports(GetWithdrawalReportsRequest) returns (GetWithdrawalReportsResponse){
get: "/GetWithdrawalReports" option (google.api.http) = {
}; get: "/GetWithdrawalReports"
}; };
};
} }
// ============ Commands ============ // ============ Commands ============
@@ -122,51 +122,51 @@ service CommissionContract
// CalculateWeeklyBalances Command // CalculateWeeklyBalances Command
message CalculateWeeklyBalancesRequest message CalculateWeeklyBalancesRequest
{ {
string week_number = 1; // Format: "YYYY-Www" (e.g., "2025-W01") string week_number = 1; // Format: "YYYY-Www" (e.g., "2025-W01")
bool force_recalculate = 2; bool force_recalculate = 2;
} }
// CalculateWeeklyCommissionPool Command // CalculateWeeklyCommissionPool Command
message CalculateWeeklyCommissionPoolRequest message CalculateWeeklyCommissionPoolRequest
{ {
string week_number = 1; string week_number = 1;
} }
// ProcessUserPayouts Command // ProcessUserPayouts Command
message ProcessUserPayoutsRequest message ProcessUserPayoutsRequest
{ {
string week_number = 1; string week_number = 1;
bool force_reprocess = 2; bool force_reprocess = 2;
} }
// RequestWithdrawal Command // RequestWithdrawal Command
message RequestWithdrawalRequest message RequestWithdrawalRequest
{ {
int64 payout_id = 1; int64 payout_id = 1;
int32 withdrawal_method = 2; // WithdrawalMethod enum: Cash=0, Diamond=1 int32 withdrawal_method = 2; // WithdrawalMethod enum: Cash=0, Diamond=1
google.protobuf.StringValue iban_number = 3; // Required for Cash method google.protobuf.StringValue iban_number = 3; // Required for Cash method
} }
// ProcessWithdrawal Command // ProcessWithdrawal Command
message ProcessWithdrawalRequest message ProcessWithdrawalRequest
{ {
int64 payout_id = 1; int64 payout_id = 1;
bool is_approved = 2; bool is_approved = 2;
google.protobuf.StringValue reason = 3; // Required for rejection google.protobuf.StringValue reason = 3; // Required for rejection
} }
// ApproveWithdrawal Command // ApproveWithdrawal Command
message ApproveWithdrawalRequest message ApproveWithdrawalRequest
{ {
int64 payout_id = 1; int64 payout_id = 1;
google.protobuf.StringValue notes = 2; // Optional admin notes google.protobuf.StringValue notes = 2; // Optional admin notes
} }
// RejectWithdrawal Command // RejectWithdrawal Command
message RejectWithdrawalRequest message RejectWithdrawalRequest
{ {
int64 payout_id = 1; int64 payout_id = 1;
string reason = 2; // Required reason for rejection string reason = 2; // Required reason for rejection
} }
// ============ Queries ============ // ============ Queries ============
@@ -174,178 +174,183 @@ message RejectWithdrawalRequest
// GetWeeklyCommissionPool Query // GetWeeklyCommissionPool Query
message GetWeeklyCommissionPoolRequest message GetWeeklyCommissionPoolRequest
{ {
string week_number = 1; string week_number = 1;
} }
message GetWeeklyCommissionPoolResponse message GetWeeklyCommissionPoolResponse
{ {
int64 id = 1; int64 id = 1;
string week_number = 2; string week_number = 2;
int64 total_pool_amount = 3; // Rials int64 total_pool_amount = 3; // Rials
int32 total_balances = 4; int32 total_balances = 4;
int64 value_per_balance = 5; // Rials per balance int64 value_per_balance = 5; // Rials per balance
bool is_calculated = 6; bool is_calculated = 6;
google.protobuf.Timestamp calculated_at = 7; google.protobuf.Timestamp calculated_at = 7;
google.protobuf.Timestamp created = 8; google.protobuf.Timestamp created = 8;
} }
// GetUserCommissionPayouts Query // GetUserCommissionPayouts Query
message GetUserCommissionPayoutsRequest message GetUserCommissionPayoutsRequest
{ {
google.protobuf.Int64Value user_id = 1;
google.protobuf.Int32Value status = 2; // CommissionPayoutStatus enum messages.PaginationState pagination_state = 1;
google.protobuf.StringValue week_number = 3; GetUserPayoutsFilter filter = 2;
int32 page_index = 4;
int32 page_size = 5; }
message GetUserPayoutsFilter
{
google.protobuf.Int64Value user_id = 1;
google.protobuf.Int32Value status = 2; // CommissionPayoutStatus enum
google.protobuf.StringValue week_number = 3;
} }
message GetUserCommissionPayoutsResponse message GetUserCommissionPayoutsResponse
{ {
messages.MetaData meta_data = 1; messages.MetaData meta_data = 1;
repeated UserCommissionPayoutModel models = 2; repeated UserCommissionPayoutModel models = 2;
} }
message UserCommissionPayoutModel message UserCommissionPayoutModel
{ {
int64 id = 1; int64 id = 1;
int64 user_id = 2; int64 user_id = 2;
string user_name = 3; string user_name = 3;
string week_number = 4; string week_number = 4;
int32 balances_earned = 5; int32 balances_earned = 5;
int64 value_per_balance = 6; int64 value_per_balance = 6;
int64 total_amount = 7; int64 total_amount = 7;
int32 status = 8; // CommissionPayoutStatus enum int32 status = 8; // CommissionPayoutStatus enum (0=Pending, 1=Paid, 2=Failed)
google.protobuf.Int32Value withdrawal_method = 9; google.protobuf.Int32Value withdrawal_method = 9;
string iban_number = 10; string iban_number = 10;
google.protobuf.Timestamp created = 11; google.protobuf.Timestamp created = 11;
google.protobuf.Timestamp last_modified = 12; google.protobuf.Timestamp last_modified = 12;
} }
// GetCommissionPayoutHistory Query // GetCommissionPayoutHistory Query
message GetCommissionPayoutHistoryRequest message GetCommissionPayoutHistoryRequest
{ {
google.protobuf.Int64Value payout_id = 1; google.protobuf.Int64Value payout_id = 1;
google.protobuf.Int64Value user_id = 2; google.protobuf.Int64Value user_id = 2;
google.protobuf.StringValue week_number = 3; google.protobuf.StringValue week_number = 3;
int32 page_index = 4; messages.PaginationState pagination_state = 4;
int32 page_size = 5;
} }
message GetCommissionPayoutHistoryResponse message GetCommissionPayoutHistoryResponse
{ {
messages.MetaData meta_data = 1; messages.MetaData meta_data = 1;
repeated CommissionPayoutHistoryModel models = 2; repeated CommissionPayoutHistoryModel models = 2;
} }
message CommissionPayoutHistoryModel message CommissionPayoutHistoryModel
{ {
int64 id = 1; int64 id = 1;
int64 payout_id = 2; int64 payout_id = 2;
int64 user_id = 3; int64 user_id = 3;
string week_number = 4; string week_number = 4;
int64 amount_before = 5; int64 amount_before = 5;
int64 amount_after = 6; int64 amount_after = 6;
int32 old_status = 7; // CommissionPayoutStatus enum int32 old_status = 7; // CommissionPayoutStatus enum
int32 new_status = 8; int32 new_status = 8;
int32 action = 9; // CommissionPayoutAction enum int32 action = 9; // CommissionPayoutAction enum
string performed_by = 10; string performed_by = 10;
string reason = 11; string reason = 11;
google.protobuf.Timestamp created = 12; google.protobuf.Timestamp created = 12;
} }
// GetUserWeeklyBalances Query // GetUserWeeklyBalances Query
message GetUserWeeklyBalancesRequest message GetUserWeeklyBalancesRequest
{ {
google.protobuf.Int64Value user_id = 1; google.protobuf.Int64Value user_id = 1;
google.protobuf.StringValue week_number = 2; google.protobuf.StringValue week_number = 2;
bool only_active = 3; // Only non-expired balances bool only_active = 3; // Only non-expired balances
int32 page_index = 4; int32 page_index = 4;
int32 page_size = 5; int32 page_size = 5;
} }
message GetUserWeeklyBalancesResponse message GetUserWeeklyBalancesResponse
{ {
messages.MetaData meta_data = 1; messages.MetaData meta_data = 1;
repeated UserWeeklyBalanceModel models = 2; repeated UserWeeklyBalanceModel models = 2;
} }
message UserWeeklyBalanceModel message UserWeeklyBalanceModel
{ {
int64 id = 1; int64 id = 1;
int64 user_id = 2; int64 user_id = 2;
string week_number = 3; string week_number = 3;
int32 left_leg_balances = 4; int32 left_leg_balances = 4;
int32 right_leg_balances = 5; int32 right_leg_balances = 5;
int32 total_balances = 6; int32 total_balances = 6;
int64 weekly_pool_contribution = 7; int64 weekly_pool_contribution = 7;
google.protobuf.Timestamp calculated_at = 8; google.protobuf.Timestamp calculated_at = 8;
bool is_expired = 9; bool is_expired = 9;
google.protobuf.Timestamp created = 10; google.protobuf.Timestamp created = 10;
} }
// GetAllWeeklyPools Query // GetAllWeeklyPools Query
message GetAllWeeklyPoolsRequest message GetAllWeeklyPoolsRequest
{ {
google.protobuf.StringValue from_week = 1; // Format: "YYYY-Www" (optional) google.protobuf.StringValue from_week = 1; // Format: "YYYY-Www" (optional)
google.protobuf.StringValue to_week = 2; // Format: "YYYY-Www" (optional) google.protobuf.StringValue to_week = 2; // Format: "YYYY-Www" (optional)
google.protobuf.BoolValue only_calculated = 3; // Only show calculated pools google.protobuf.BoolValue only_calculated = 3; // Only show calculated pools
int32 page_index = 4; int32 page_index = 4;
int32 page_size = 5; int32 page_size = 5;
} }
message GetAllWeeklyPoolsResponse message GetAllWeeklyPoolsResponse
{ {
messages.MetaData meta_data = 1; messages.MetaData meta_data = 1;
repeated WeeklyCommissionPoolModel models = 2; repeated WeeklyCommissionPoolModel models = 2;
} }
message WeeklyCommissionPoolModel message WeeklyCommissionPoolModel
{ {
int64 id = 1; int64 id = 1;
string week_number = 2; string week_number = 2;
int64 total_pool_amount = 3; int64 total_pool_amount = 3;
int32 total_balances = 4; int32 total_balances = 4;
int64 value_per_balance = 5; int64 value_per_balance = 5;
bool is_calculated = 6; bool is_calculated = 6;
google.protobuf.Timestamp calculated_at = 7; google.protobuf.Timestamp calculated_at = 7;
google.protobuf.Timestamp created = 8; google.protobuf.Timestamp created = 8;
} }
// GetWithdrawalRequests Query // GetWithdrawalRequests Query
message GetWithdrawalRequestsRequest message GetWithdrawalRequestsRequest
{ {
google.protobuf.Int32Value status = 1; // CommissionPayoutStatus enum: Pending=1, Approved=2, Rejected=3 google.protobuf.Int32Value status = 1; // CommissionPayoutStatus enum: Pending=1, Approved=2, Rejected=3
google.protobuf.Int64Value user_id = 2; google.protobuf.Int64Value user_id = 2;
google.protobuf.StringValue week_number = 3; google.protobuf.StringValue week_number = 3;
int32 page_index = 4; int32 page_index = 4;
int32 page_size = 5; int32 page_size = 5;
string iban_number = 6; string iban_number = 6;
} }
message GetWithdrawalRequestsResponse message GetWithdrawalRequestsResponse
{ {
messages.MetaData meta_data = 1; messages.MetaData meta_data = 1;
repeated WithdrawalRequestModel models = 2; repeated WithdrawalRequestModel models = 2;
} }
message WithdrawalRequestModel message WithdrawalRequestModel
{ {
int64 id = 1; int64 id = 1;
int64 user_id = 2; int64 user_id = 2;
string user_name = 3; string user_name = 3;
string week_number = 4; string week_number = 4;
int64 amount = 5; int64 amount = 5;
int32 status = 6; // CommissionPayoutStatus enum int32 status = 6; // CommissionPayoutStatus enum
int32 withdrawal_method = 7; // WithdrawalMethod enum int32 withdrawal_method = 7; // WithdrawalMethod enum
string iban_number = 8; string iban_number = 8;
google.protobuf.Timestamp requested_at = 9; google.protobuf.Timestamp requested_at = 9;
google.protobuf.Timestamp processed_at = 10; google.protobuf.Timestamp processed_at = 10;
string processed_by = 11; string processed_by = 11;
string reason = 12; string reason = 12;
google.protobuf.Timestamp created = 13; google.protobuf.Timestamp created = 13;
string bank_reference_id = 14; string bank_reference_id = 14;
string bank_tracking_code = 15; string bank_tracking_code = 15;
string payment_failure_reason = 16; string payment_failure_reason = 16;
} }
// ============ Worker Control APIs ============ // ============ Worker Control APIs ============
@@ -353,141 +358,141 @@ message WithdrawalRequestModel
// TriggerWeeklyCalculation Command // TriggerWeeklyCalculation Command
message TriggerWeeklyCalculationRequest message TriggerWeeklyCalculationRequest
{ {
string week_number = 1; // Format: "YYYY-Www" (e.g., "2025-W48") string week_number = 1; // Format: "YYYY-Www" (e.g., "2025-W48")
bool force_recalculate = 2; // اگر true باشد، محاسبات قبلی را حذف و دوباره محاسبه می‌کند bool force_recalculate = 2; // اگر true باشد، محاسبات قبلی را حذف و دوباره محاسبه می‌کند
bool skip_balances = 3; // Skip balance calculation (only pool and payouts) bool skip_balances = 3; // Skip balance calculation (only pool and payouts)
bool skip_pool = 4; // Skip pool calculation (only balances and payouts) bool skip_pool = 4; // Skip pool calculation (only balances and payouts)
bool skip_payouts = 5; // Skip payout processing (only balances and pool) bool skip_payouts = 5; // Skip payout processing (only balances and pool)
} }
message TriggerWeeklyCalculationResponse message TriggerWeeklyCalculationResponse
{ {
bool success = 1; bool success = 1;
string message = 2; string message = 2;
string execution_id = 3; // Unique ID for tracking this execution string execution_id = 3; // Unique ID for tracking this execution
google.protobuf.Timestamp started_at = 4; google.protobuf.Timestamp started_at = 4;
} }
// GetWorkerStatus Query // GetWorkerStatus Query
message GetWorkerStatusRequest message GetWorkerStatusRequest
{ {
// Empty - returns current worker status // Empty - returns current worker status
} }
message GetWorkerStatusResponse message GetWorkerStatusResponse
{ {
bool is_running = 1; bool is_running = 1;
bool is_enabled = 2; bool is_enabled = 2;
google.protobuf.StringValue current_execution_id = 3; google.protobuf.StringValue current_execution_id = 3;
google.protobuf.StringValue current_week_number = 4; google.protobuf.StringValue current_week_number = 4;
google.protobuf.StringValue current_step = 5; // "Balances" | "Pool" | "Payouts" | "Idle" google.protobuf.StringValue current_step = 5; // "Balances" | "Pool" | "Payouts" | "Idle"
google.protobuf.Timestamp last_run_at = 6; google.protobuf.Timestamp last_run_at = 6;
google.protobuf.Timestamp next_scheduled_run = 7; google.protobuf.Timestamp next_scheduled_run = 7;
int32 total_executions = 8; int32 total_executions = 8;
int32 successful_executions = 9; int32 successful_executions = 9;
int32 failed_executions = 10; int32 failed_executions = 10;
} }
// GetWorkerExecutionLogs Query // GetWorkerExecutionLogs Query
message GetWorkerExecutionLogsRequest message GetWorkerExecutionLogsRequest
{ {
google.protobuf.StringValue week_number = 1; // Filter by week google.protobuf.StringValue week_number = 1; // Filter by week
google.protobuf.StringValue execution_id = 2; // Filter by specific execution google.protobuf.StringValue execution_id = 2; // Filter by specific execution
google.protobuf.BoolValue success_only = 3; // Show only successful runs google.protobuf.BoolValue success_only = 3; // Show only successful runs
google.protobuf.BoolValue failed_only = 4; // Show only failed runs google.protobuf.BoolValue failed_only = 4; // Show only failed runs
int32 page_index = 5; int32 page_index = 5;
int32 page_size = 6; int32 page_size = 6;
} }
message GetWorkerExecutionLogsResponse message GetWorkerExecutionLogsResponse
{ {
messages.MetaData meta_data = 1; messages.MetaData meta_data = 1;
repeated WorkerExecutionLogModel models = 2; repeated WorkerExecutionLogModel models = 2;
} }
message WorkerExecutionLogModel message WorkerExecutionLogModel
{ {
string execution_id = 1; string execution_id = 1;
string week_number = 2; string week_number = 2;
string step = 3; // "Balances" | "Pool" | "Payouts" | "Full" string step = 3; // "Balances" | "Pool" | "Payouts" | "Full"
bool success = 4; bool success = 4;
google.protobuf.StringValue error_message = 5; google.protobuf.StringValue error_message = 5;
google.protobuf.Timestamp started_at = 6; google.protobuf.Timestamp started_at = 6;
google.protobuf.Timestamp completed_at = 7; google.protobuf.Timestamp completed_at = 7;
int64 duration_ms = 8; // Duration in milliseconds int64 duration_ms = 8; // Duration in milliseconds
int32 records_processed = 9; int32 records_processed = 9;
google.protobuf.StringValue details = 10; // JSON or text details google.protobuf.StringValue details = 10; // JSON or text details
} }
// GetWithdrawalReports Query // GetWithdrawalReports Query
message GetWithdrawalReportsRequest message GetWithdrawalReportsRequest
{ {
google.protobuf.Timestamp start_date = 1; // Optional - default: 30 days ago google.protobuf.Timestamp start_date = 1; // Optional - default: 30 days ago
google.protobuf.Timestamp end_date = 2; // Optional - default: today google.protobuf.Timestamp end_date = 2; // Optional - default: today
int32 period_type = 3; // ReportPeriodType: Daily=1, Weekly=2, Monthly=3 int32 period_type = 3; // ReportPeriodType: Daily=1, Weekly=2, Monthly=3
google.protobuf.Int32Value status = 4; // CommissionPayoutStatus enum (optional) google.protobuf.Int32Value status = 4; // CommissionPayoutStatus enum (optional)
google.protobuf.Int64Value user_id = 5; // Optional user filter google.protobuf.Int64Value user_id = 5; // Optional user filter
} }
message GetWithdrawalReportsResponse message GetWithdrawalReportsResponse
{ {
repeated PeriodReport period_reports = 1; repeated PeriodReport period_reports = 1;
WithdrawalSummary summary = 2; WithdrawalSummary summary = 2;
} }
message PeriodReport message PeriodReport
{ {
string period_label = 1; // e.g., "2025-01-15", "هفته 3", "فروردین 1404" string period_label = 1; // e.g., "2025-01-15", "هفته 3", "فروردین 1404"
google.protobuf.Timestamp start_date = 2; google.protobuf.Timestamp start_date = 2;
google.protobuf.Timestamp end_date = 3; google.protobuf.Timestamp end_date = 3;
int32 total_requests = 4; int32 total_requests = 4;
int32 pending_count = 5; int32 pending_count = 5;
int32 approved_count = 6; int32 approved_count = 6;
int32 rejected_count = 7; int32 rejected_count = 7;
int32 completed_count = 8; int32 completed_count = 8;
int32 failed_count = 9; int32 failed_count = 9;
int64 total_amount = 10; int64 total_amount = 10;
int64 paid_amount = 11; int64 paid_amount = 11;
int64 pending_amount = 12; int64 pending_amount = 12;
} }
message WithdrawalSummary message WithdrawalSummary
{ {
int32 total_requests = 1; int32 total_requests = 1;
int64 total_amount = 2; int64 total_amount = 2;
int64 total_paid = 3; int64 total_paid = 3;
int64 total_pending = 4; int64 total_pending = 4;
int64 total_rejected = 5; int64 total_rejected = 5;
int64 average_amount = 6; int64 average_amount = 6;
int32 unique_users = 7; int32 unique_users = 7;
float success_rate = 8; // Percentage (0-100) float success_rate = 8; // Percentage (0-100)
} }
// ============ GetAvailableWeeks ============ // ============ GetAvailableWeeks ============
message GetAvailableWeeksRequest message GetAvailableWeeksRequest
{ {
int32 future_weeks_count = 1; // تعداد هفته‌های آینده (پیش‌فرض: 4) int32 future_weeks_count = 1; // تعداد هفته‌های آینده (پیش‌فرض: 4)
int32 past_weeks_count = 2; // تعداد هفته‌های گذشته (پیش‌فرض: 12) int32 past_weeks_count = 2; // تعداد هفته‌های گذشته (پیش‌فرض: 12)
} }
message GetAvailableWeeksResponse message GetAvailableWeeksResponse
{ {
WeekInfo current_week = 1; WeekInfo current_week = 1;
repeated WeekInfo calculated_weeks = 2; repeated WeekInfo calculated_weeks = 2;
repeated WeekInfo pending_weeks = 3; repeated WeekInfo pending_weeks = 3;
repeated WeekInfo future_weeks = 4; repeated WeekInfo future_weeks = 4;
} }
message WeekInfo message WeekInfo
{ {
string week_number = 1; // YYYY-Www format string week_number = 1; // YYYY-Www format
google.protobuf.Timestamp start_date = 2; google.protobuf.Timestamp start_date = 2;
google.protobuf.Timestamp end_date = 3; google.protobuf.Timestamp end_date = 3;
bool is_calculated = 4; bool is_calculated = 4;
google.protobuf.Timestamp calculated_at = 5; google.protobuf.Timestamp calculated_at = 5;
string last_execution_status = 6; string last_execution_status = 6;
int64 total_pool_amount = 7; int64 total_pool_amount = 7;
int32 eligible_users_count = 8; int32 eligible_users_count = 8;
string display_text = 9; // نمایش فارسی برای UI string display_text = 9; // نمایش فارسی برای UI
} }

View File

@@ -4,7 +4,7 @@
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<Version>0.0.2</Version> <Version>0.0.4</Version>
<DebugType>None</DebugType> <DebugType>None</DebugType>
<DebugSymbols>False</DebugSymbols> <DebugSymbols>False</DebugSymbols>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild> <GeneratePackageOnBuild>False</GeneratePackageOnBuild>

View File

@@ -15,6 +15,7 @@ service ManualPaymentContract
rpc ApproveManualPayment(ApproveManualPaymentRequest) returns (google.protobuf.Empty); rpc ApproveManualPayment(ApproveManualPaymentRequest) returns (google.protobuf.Empty);
rpc RejectManualPayment(RejectManualPaymentRequest) returns (google.protobuf.Empty); rpc RejectManualPayment(RejectManualPaymentRequest) returns (google.protobuf.Empty);
rpc GetManualPayments(GetManualPaymentsRequest) returns (GetManualPaymentsResponse); rpc GetManualPayments(GetManualPaymentsRequest) returns (GetManualPaymentsResponse);
rpc ProcessManualMembershipPayment(ProcessManualMembershipPaymentRequest) returns (ProcessManualMembershipPaymentResponse);
} }
message GetManualPaymentsRequest message GetManualPaymentsRequest
@@ -82,3 +83,19 @@ message RejectManualPaymentRequest
string rejection_reason = 2; string rejection_reason = 2;
} }
message ProcessManualMembershipPaymentRequest
{
int64 user_id = 1;
int64 amount = 2;
string reference_number = 3;
google.protobuf.StringValue description = 4;
}
message ProcessManualMembershipPaymentResponse
{
int64 transaction_id = 1;
int64 order_id = 2;
int64 new_wallet_balance = 3;
string message = 4;
}