Files
gridpilot.gg/core/payments/application/use-cases/UpdateMemberPaymentUseCase.ts
2025-12-16 11:52:26 +01:00

91 lines
2.8 KiB
TypeScript

/**
* 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<UpdateMemberPaymentInput, UpdateMemberPaymentResultDTO, UpdateMemberPaymentViewModel, IUpdateMemberPaymentPresenter>
{
constructor(
private readonly membershipFeeRepository: IMembershipFeeRepository,
private readonly memberPaymentRepository: IMemberPaymentRepository,
) {}
async execute(
input: UpdateMemberPaymentInput,
presenter: IUpdateMemberPaymentPresenter,
): Promise<void> {
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);
}
}