Files
gridpilot.gg/core/payments/application/use-cases/UpdateMemberPaymentUseCase.ts
2026-01-16 19:46:49 +01:00

76 lines
2.5 KiB
TypeScript

/**
* 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<UpdateMemberPaymentInput, UpdateMemberPaymentResult, UpdateMemberPaymentErrorCode>
{
constructor(
private readonly membershipFeeRepository: MembershipFeeRepository,
private readonly memberPaymentRepository: MemberPaymentRepository,
) {}
async execute(input: UpdateMemberPaymentInput): Promise<Result<UpdateMemberPaymentResult, ApplicationErrorCode<UpdateMemberPaymentErrorCode>>> {
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 });
}
}