/** * Application Use Case: UpdateMemberPaymentUseCase * * Updates a member payment record. */ import type { UseCase } from '@core/shared/application/UseCase'; import { Result } from '@core/shared/domain/Result'; import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode'; import type { MemberPayment } from '../../domain/entities/MemberPayment'; import { MemberPaymentStatus } from '../../domain/entities/MemberPayment'; import type { MemberPaymentRepository, MembershipFeeRepository } from '../../domain/repositories/MembershipFeeRepository'; const PLATFORM_FEE_RATE = 0.10; export interface UpdateMemberPaymentInput { feeId: string; driverId: string; status?: MemberPaymentStatus; paidAt?: Date | string; } export interface UpdateMemberPaymentResult { payment: MemberPayment; } export type UpdateMemberPaymentErrorCode = 'MEMBERSHIP_FEE_NOT_FOUND'; export class UpdateMemberPaymentUseCase implements UseCase { constructor( private readonly membershipFeeRepository: MembershipFeeRepository, private readonly memberPaymentRepository: MemberPaymentRepository, ) {} async execute(input: UpdateMemberPaymentInput): Promise>> { const { feeId, driverId, status, paidAt } = input; const fee = await this.membershipFeeRepository.findById(feeId); if (!fee) { return Result.err({ code: 'MEMBERSHIP_FEE_NOT_FOUND' as const }); } let payment = await this.memberPaymentRepository.findByFeeIdAndDriverId(feeId, driverId); if (!payment) { const platformFee = fee.amount * PLATFORM_FEE_RATE; const netAmount = fee.amount - platformFee; const paymentId = `mp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; const newPayment: MemberPayment = { id: paymentId, feeId, driverId, amount: fee.amount, platformFee, netAmount, status: MemberPaymentStatus.PENDING, dueDate: new Date(), }; payment = await this.memberPaymentRepository.create(newPayment); } if (status) { payment.status = status; } if (paidAt || status === MemberPaymentStatus.PAID) { payment.paidAt = paidAt ? new Date(paidAt as string) : new Date(); } const updatedPayment = await this.memberPaymentRepository.update(payment); return Result.ok({ payment: updatedPayment }); } }