76 lines
2.5 KiB
TypeScript
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 });
|
|
}
|
|
} |