Files
CMS/src/CMSMicroservice.WebApi/Services/UserWalletService.cs
T
masoodafar-web b42d9e141d
Build and Deploy to Kubernetes / build-and-deploy (push) Failing after 3m9s
feat: Implement file management and authorization features
- Add RequiresPermissionAttribute for gRPC method access control.
- Create IFileManagementService interface for file upload and management.
- Implement AddProductImageCommand and handler for adding product images.
- Implement CreateNewProductsCommand and handler for creating new products with image uploads.
- Implement DeleteProductsCommand and handler for deleting products and their associations.
- Implement RemoveProductImageCommand and handler for removing product images from galleries.
- Implement UpdateProductsCommand and handler for updating product details and images.
- Create GetProductGalleryQuery and handler for retrieving product galleries.
- Implement PermissionService for role-based access control using JWT claims.
- Implement FileManagementService for handling file uploads and image optimization.
- Define gRPC service and messages for file management in fms.proto.
- Add FluentValidation for request validation in various commands.
- Create PermissionInterceptor for enforcing permissions on gRPC methods.
2026-02-10 22:04:54 +03:30

199 lines
8.8 KiB
C#

using CMSMicroservice.Protobuf.Protos.UserWallet;
using CMSMicroservice.WebApi.Common.Services;
using CMSMicroservice.Application.UserWalletCQ.Commands.CreateNewUserWallet;
using CMSMicroservice.Application.UserWalletCQ.Commands.UpdateUserWallet;
using CMSMicroservice.Application.UserWalletCQ.Commands.DeleteUserWallet;
using CMSMicroservice.Application.UserWalletCQ.Queries.GetUserWallet;
using CMSMicroservice.Application.UserWalletCQ.Queries.GetAllUserWalletByFilter;
using CMSMicroservice.Application.UserWalletCQ.Queries.GetCustomerWalletChangeLog;
using CMSMicroservice.Application.UserWalletCQ.Queries.GetCustomerWithdrawals;
using CMSMicroservice.Application.UserWalletCQ.Queries.GetCustomerWithdrawalSettings;
using CMSMicroservice.Application.Common.Interfaces;
using Grpc.Core;
using Microsoft.EntityFrameworkCore;
using System.Linq;
namespace CMSMicroservice.WebApi.Services;
public class UserWalletService : UserWalletContract.UserWalletContractBase
{
private readonly IDispatchRequestToCQRS _dispatchRequestToCQRS;
private readonly ISender _sender;
private readonly IApplicationDbContext _context;
private readonly ICurrentUserService _currentUserService;
public UserWalletService(
IDispatchRequestToCQRS dispatchRequestToCQRS,
ISender sender,
IApplicationDbContext context,
ICurrentUserService currentUserService)
{
_dispatchRequestToCQRS = dispatchRequestToCQRS;
_sender = sender;
_context = context;
_currentUserService = currentUserService;
}
public override async Task<CreateNewUserWalletResponse> CreateNewUserWallet(CreateNewUserWalletRequest request, ServerCallContext context)
{
return await _dispatchRequestToCQRS.Handle<CreateNewUserWalletRequest, CreateNewUserWalletCommand, CreateNewUserWalletResponse>(request, context);
}
public override async Task<Empty> UpdateUserWallet(UpdateUserWalletRequest request, ServerCallContext context)
{
return await _dispatchRequestToCQRS.Handle<UpdateUserWalletRequest, UpdateUserWalletCommand>(request, context);
}
public override async Task<Empty> DeleteUserWallet(DeleteUserWalletRequest request, ServerCallContext context)
{
return await _dispatchRequestToCQRS.Handle<DeleteUserWalletRequest, DeleteUserWalletCommand>(request, context);
}
public override async Task<GetUserWalletResponse> GetUserWallet(GetUserWalletRequest request, ServerCallContext context)
{
return await _dispatchRequestToCQRS.Handle<GetUserWalletRequest, GetUserWalletQuery, GetUserWalletResponse>(request, context);
}
public override async Task<GetAllUserWalletByFilterResponse> GetAllUserWalletByFilter(GetAllUserWalletByFilterRequest request, ServerCallContext context)
{
return await _dispatchRequestToCQRS.Handle<GetAllUserWalletByFilterRequest, GetAllUserWalletByFilterQuery, GetAllUserWalletByFilterResponse>(request, context);
}
// ============= Customer-specific Methods =============
public override async Task<GetCustomerWalletResponse> GetCustomerWallet(Google.Protobuf.WellKnownTypes.Empty request, ServerCallContext context)
{
// Use GetUserWallet with Id=0 to automatically use current user from JWT
var walletQuery = new GetUserWalletQuery { Id = 0 };
var wallet = await _sender.Send(walletQuery, context.CancellationToken);
return new GetCustomerWalletResponse
{
Balance = wallet.Balance,
NetworkBalance = wallet.NetworkBalance,
DiscountBalance = wallet.DiscountBalance
};
}
public override async Task<GetCustomerWalletChangeLogResponse> GetCustomerWalletChangeLog(GetCustomerWalletChangeLogRequest request, ServerCallContext context)
{
var query = new GetCustomerWalletChangeLogQuery
{
ReferenceId = request.ReferenceId,
IsIncrease = request.IsIncrease
};
var changeLogs = await _sender.Send(query, context.CancellationToken);
var response = new GetCustomerWalletChangeLogResponse
{
MetaData = new CMSMicroservice.Protobuf.Protos.MetaData
{
CurrentPage = 1,
TotalPage = 1,
PageSize = changeLogs.Count,
TotalCount = changeLogs.Count,
HasPrevious = false,
HasNext = false
}
};
foreach (var log in changeLogs)
{
response.Models.Add(new CustomerWalletChangeLogModel
{
CurrentBalance = log.CurrentBalance,
ChangeValue = log.ChangeValue,
CurrentNetworkBalance = log.CurrentNetworkBalance,
ChangeNerworkValue = log.ChangeNerworkValue,
CurrentDiscountBalance = log.CurrentDiscountBalance,
ChangeDiscountValue = log.ChangeDiscountValue,
IsIncrease = log.IsIncrease,
RefrenceId = log.RefrenceId,
CreatedAt = Google.Protobuf.WellKnownTypes.Timestamp.FromDateTime(DateTime.SpecifyKind(log.Created, DateTimeKind.Utc))
});
}
return response;
}
public override async Task<Google.Protobuf.WellKnownTypes.Empty> CustomerWithdrawBalance(CustomerWithdrawBalanceRequest request, ServerCallContext context)
{
var userId = GetCurrentUserId();
// Find the commission payout record
var payout = await _context.UserCommissionPayouts
.Where(p => p.Id == request.PayoutId && p.UserId == userId && !p.IsDeleted)
.FirstOrDefaultAsync(context.CancellationToken);
if (payout == null)
throw new RpcException(new Status(StatusCode.NotFound, "رکورد پرداخت کمیسیون یافت نشد"));
// Validate status - can only withdraw if already paid to wallet
if (payout.Status != Domain.Enums.CommissionPayoutStatus.Paid)
throw new RpcException(new Status(StatusCode.FailedPrecondition,
"فقط کمیسیون‌های واریز شده به کیف پول قابل برداشت هستند"));
// Update payout with withdrawal info
payout.WithdrawalMethod = (Domain.Enums.WithdrawalMethod)request.WithdrawalMethod;
payout.IbanNumber = request.IbanNumber;
payout.Status = Domain.Enums.CommissionPayoutStatus.WithdrawRequested;
await _context.SaveChangesAsync(context.CancellationToken);
return new Google.Protobuf.WellKnownTypes.Empty();
}
private long GetCurrentUserId()
{
if (long.TryParse(_currentUserService.UserId, out var userId) && userId > 0)
return userId;
throw new RpcException(new Status(StatusCode.Unauthenticated, "لطفاً وارد حساب کاربری خود شوید"));
}
public override async Task<GetCustomerWithdrawalsResponse> GetCustomerWithdrawals(GetCustomerWithdrawalsRequest request, ServerCallContext context)
{
var query = new GetCustomerWithdrawalsQuery
{
Status = request.Status
};
var withdrawals = await _sender.Send(query, context.CancellationToken);
var response = new GetCustomerWithdrawalsResponse
{
MetaData = new CMSMicroservice.Protobuf.Protos.MetaData
{
CurrentPage = 1,
TotalPage = 1,
PageSize = withdrawals.Count,
TotalCount = withdrawals.Count,
HasPrevious = false,
HasNext = false
}
};
foreach (var withdrawal in withdrawals)
{
response.Models.Add(new CustomerWithdrawalModel
{
Id = withdrawal.Id,
WeekDefinitionId = withdrawal.WeekDefinitionId,
WeekDisplayName = withdrawal.WeekDisplayName,
TotalAmount = withdrawal.TotalAmount,
Status = withdrawal.Status,
WithdrawalMethod = withdrawal.WithdrawalMethod,
IbanNumber = withdrawal.IbanNumber,
Created = Google.Protobuf.WellKnownTypes.Timestamp.FromDateTime(DateTime.SpecifyKind(withdrawal.Created, DateTimeKind.Utc))
});
}
return response;
}
public override async Task<GetCustomerWithdrawalSettingsResponse> GetCustomerWithdrawalSettings(Google.Protobuf.WellKnownTypes.Empty request, ServerCallContext context)
{
var query = new GetCustomerWithdrawalSettingsQuery();
var settings = await _sender.Send(query, context.CancellationToken);
return new GetCustomerWithdrawalSettingsResponse
{
MinWithdrawalAmount = settings.MinWithdrawalAmount
};
}
}