/** * Application Use Case: UpdateMemberPaymentUseCase * * Updates a member payment record. */ import type { IMembershipFeeRepository, IMemberPaymentRepository } from '../../domain/repositories/IMembershipFeeRepository'; import type { MemberPaymentStatus, MemberPayment } from '../../domain/entities/MemberPayment'; import type { IUpdateMemberPaymentPresenter, UpdateMemberPaymentResultDTO, UpdateMemberPaymentViewModel, } from '../presenters/IUpdateMemberPaymentPresenter'; import type { UseCase } from '@core/shared/application/UseCase'; const PLATFORM_FEE_RATE = 0.10; export interface UpdateMemberPaymentInput { feeId: string; driverId: string; status?: MemberPaymentStatus; paidAt?: Date | string; } export class UpdateMemberPaymentUseCase implements UseCase { constructor( private readonly membershipFeeRepository: IMembershipFeeRepository, private readonly memberPaymentRepository: IMemberPaymentRepository, ) {} async execute( input: UpdateMemberPaymentInput, presenter: IUpdateMemberPaymentPresenter, ): Promise { presenter.reset(); const { feeId, driverId, status, paidAt } = input; const fee = await this.membershipFeeRepository.findById(feeId); if (!fee) { throw new Error('Membership fee configuration not found'); } 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: 'pending' as MemberPaymentStatus, dueDate: new Date(), }; payment = await this.memberPaymentRepository.create(newPayment); } if (status) { payment.status = status; } if (paidAt || status === ('paid' as MemberPaymentStatus)) { payment.paidAt = paidAt ? new Date(paidAt as string) : new Date(); } const updatedPayment = await this.memberPaymentRepository.update(payment); const dto: UpdateMemberPaymentResultDTO = { payment: { id: updatedPayment.id, feeId: updatedPayment.feeId, driverId: updatedPayment.driverId, amount: updatedPayment.amount, platformFee: updatedPayment.platformFee, netAmount: updatedPayment.netAmount, status: updatedPayment.status, dueDate: updatedPayment.dueDate, paidAt: updatedPayment.paidAt, }, }; presenter.present(dto); } }