first commit

This commit is contained in:
Dhananjaya99
2026-09-28 11:44:26 +05:30
parent 721743ae6b
commit bffc9b1686
424 changed files with 46474 additions and 0 deletions
+187
View File
@@ -0,0 +1,187 @@
using Fitness_core_BE.Exceptions;
using Fitness_core_BE.Helpers;
using Fitness_core_BE.Infra.UoW;
using Fitness_core_BE.Interfaces;
using Fitness_core_BE.Interfaces.Services;
using Fitness_core_BE.DTOs.PaymentsEnablement;
using Fitness_core_BE.DTOs.PaymentGateways;
using Fitness_core_BE.Models;
using Fitness_core_BE.Models.Enums;
namespace Fitness_core_BE.Services
{
public class PaymentsEnablementService : IPaymentsEnablementService
{
private readonly IPaymentsEnablementRepository _paymentsRepository;
private readonly IClientRepository _clientRepository;
private readonly IPaymentServiceClient _paymentServiceClient;
private readonly UserRoleHelper _userRoleHelper;
private readonly IUnitOfWork _uow;
public PaymentsEnablementService(
IPaymentsEnablementRepository paymentsRepository,
IClientRepository clientRepository,
IPaymentServiceClient paymentServiceClient,
UserRoleHelper userRoleHelper,
IUnitOfWork uow)
{
_paymentsRepository = paymentsRepository;
_clientRepository = clientRepository;
_paymentServiceClient = paymentServiceClient;
_userRoleHelper = userRoleHelper;
_uow = uow;
}
public Task<List<PaymentTrackOption>> GetTrackOptionsAsync()
{
return Task.FromResult(new List<PaymentTrackOption>
{
new(PaymentTrack.OwnGateway.ToString(), new { description = "Use your own PayHere/Stripe merchant account.", feePercentage = 0 }),
new(PaymentTrack.HexaFitness.ToString(), new { description = "Use HexaFitness's payment gateway; requires KYC before first payout.", feePercentage = 2.5 })
});
}
public async Task<PaymentTrackSelectionResult> SelectTrackAsync(HttpContext httpContext, SelectPaymentTrackRequest request)
{
var userId = DataExtractor.GetUserIdFromContext(httpContext);
var clientId = await _userRoleHelper.GetClientId(userId);
if (!Enum.TryParse<PaymentTrack>(request.Track, true, out var track))
throw new BadRequestException($"Unknown payment track '{request.Track}'.");
var client = await _clientRepository.GetClientEntityByIdAsync(clientId)
?? throw new NotFoundException("Client not found.");
client.PaymentTrack = track;
await _uow.SaveChangesAsync();
return new PaymentTrackSelectionResult(track.ToString(), track == PaymentTrack.HexaFitness);
}
public async Task<List<GatewayDefinitionDto>> GetAvailableGatewaysAsync(
CancellationToken ct = default)
{
return (await _paymentServiceClient.ListGatewaysAsync(ct))
.Where(gateway => gateway.IsEnabled)
.OrderByDescending(gateway => gateway.IsDefault)
.ThenBy(gateway => gateway.DisplayName)
.ToList();
}
public async Task<ClientPayoutKycDto> SubmitKycAsync(
HttpContext httpContext,
SubmitGatewayOnboardingRequest request,
CancellationToken ct = default)
{
var userId = DataExtractor.GetUserIdFromContext(httpContext);
var clientId = await _userRoleHelper.GetClientId(userId);
var gateway = (await GetAvailableGatewaysAsync(ct))
.FirstOrDefault(item => item.Id == request.GatewayId)
?? throw new BadRequestException("Select an available payment gateway.");
var client = await _clientRepository.GetClientEntityByIdAsync(clientId)
?? throw new NotFoundException("Client not found.");
var current = await _paymentsRepository.GetKycByClientIdAsync(clientId, ct);
if (current?.KycStatus == KycStatus.Pending)
throw new BadRequestException("A gateway KYC request is already pending review.");
if (current?.KycStatus == KycStatus.Approved)
throw new BadRequestException("Gateway KYC is already approved for this client.");
await _uow.BeginAsync();
try
{
// Catalog gateways are platform-managed, so this follows the
// HexaFitness payment track rather than client-owned credentials.
client.PaymentTrack = PaymentTrack.HexaFitness;
var kyc = new ClientPayoutKyc
{
Id = Guid.NewGuid(),
FKClientId = clientId,
SelectedGatewayId = gateway.Id,
SelectedGatewayName = gateway.DisplayName,
KycStatus = KycStatus.Pending,
SubmittedAt = DateTime.UtcNow
};
await _paymentsRepository.CreateKycAsync(kyc, ct);
await _uow.CommitAsync();
return ToDto(kyc, client);
}
catch
{
await _uow.RollbackAsync();
throw;
}
}
public async Task<GatewayOnboardingStatusDto> GetKycStatusAsync(HttpContext httpContext)
{
var userId = DataExtractor.GetUserIdFromContext(httpContext);
var clientId = await _userRoleHelper.GetClientId(userId);
var kyc = await _paymentsRepository.GetKycByClientIdAsync(clientId);
return kyc is null
? new GatewayOnboardingStatusDto("NotSubmitted", null, null, null)
: new GatewayOnboardingStatusDto(
kyc.KycStatus.ToString(),
kyc.SelectedGatewayId,
kyc.SelectedGatewayName,
kyc.RejectionReason);
}
public async Task<WalletDto> GetWalletAsync(HttpContext httpContext)
{
var userId = DataExtractor.GetUserIdFromContext(httpContext);
var clientId = await _userRoleHelper.GetClientId(userId);
var wallet = await _paymentsRepository.GetWalletByClientIdAsync(clientId)
?? throw new NotFoundException("Wallet not found for this client.");
var ledger = await _paymentsRepository.GetLedgerAsync(wallet.Id);
return new WalletDto(
wallet.Balance,
wallet.Currency,
ledger.Select(e => new WalletLedgerEntryDto(e.Id, e.EntryType.ToString(), e.Amount, e.Description, e.CreatedAt)).ToList(),
wallet.LastPayoutDate);
}
public async Task<PayoutScheduleDto> GetPayoutScheduleAsync(HttpContext httpContext)
{
var userId = DataExtractor.GetUserIdFromContext(httpContext);
var clientId = await _userRoleHelper.GetClientId(userId);
var wallet = await _paymentsRepository.GetWalletByClientIdAsync(clientId)
?? throw new NotFoundException("Wallet not found for this client.");
var today = DateTime.UtcNow.Date;
var daysUntilTuesday = ((int)DayOfWeek.Tuesday - (int)today.DayOfWeek + 7) % 7;
daysUntilTuesday = daysUntilTuesday == 0 ? 7 : daysUntilTuesday;
var nextPayoutDate = today.AddDays(daysUntilTuesday);
return new PayoutScheduleDto(nextPayoutDate, "Weekly (Tuesday)", wallet.Balance);
}
// NIC fields used to come from the multi-gym onboarding wizard's OwnerActivation record;
// that flow no longer exists for a single already-real club (see PayoutKycReviewService's
// ToDto for the same note) -- always null here now.
private static ClientPayoutKycDto ToDto(
ClientPayoutKyc kyc,
Client client)
=> new(
kyc.Id,
kyc.FKClientId,
client.ClientName,
kyc.SelectedGatewayId,
kyc.SelectedGatewayName,
kyc.KycStatus.ToString(),
kyc.SubmittedAt,
kyc.ReviewedAt,
kyc.RejectionReason,
null,
null,
null);
}
}