refactor racing use cases
This commit is contained in:
@@ -4,65 +4,99 @@
|
||||
* Allows an entity owner to reject a sponsorship request.
|
||||
*/
|
||||
|
||||
import type { ISponsorshipRequestRepository } from '../../domain/repositories/ISponsorshipRequestRepository';
|
||||
import type { Logger, UseCaseOutputPort } from '@core/shared/application';
|
||||
import { Result } from '@core/shared/application/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { SponsorshipRejectionNotificationPort } from '../ports/output/SponsorshipRejectionNotificationPort';
|
||||
import type { ISponsorshipRequestRepository } from '../../domain/repositories/ISponsorshipRequestRepository';
|
||||
|
||||
export interface RejectSponsorshipRequestDTO {
|
||||
export type RejectSponsorshipRequestInput = {
|
||||
requestId: string;
|
||||
respondedBy: string; // driverId of the person rejecting
|
||||
respondedBy: string;
|
||||
reason?: string;
|
||||
}
|
||||
};
|
||||
|
||||
export interface RejectSponsorshipRequestResultDTO {
|
||||
export type RejectSponsorshipRequestResult = {
|
||||
requestId: string;
|
||||
status: 'rejected';
|
||||
rejectedAt: Date;
|
||||
reason?: string;
|
||||
}
|
||||
respondedAt: Date;
|
||||
rejectionReason: string | undefined;
|
||||
};
|
||||
|
||||
export type RejectSponsorshipRequestErrorCode =
|
||||
| 'SPONSORSHIP_REQUEST_NOT_FOUND'
|
||||
| 'SPONSORSHIP_REQUEST_NOT_PENDING'
|
||||
| 'REPOSITORY_ERROR';
|
||||
|
||||
export class RejectSponsorshipRequestUseCase {
|
||||
constructor(
|
||||
private readonly sponsorshipRequestRepo: ISponsorshipRequestRepository,
|
||||
private readonly sponsorshipRejectionNotificationPort: SponsorshipRejectionNotificationPort,
|
||||
private readonly logger: Logger,
|
||||
private readonly output: UseCaseOutputPort<RejectSponsorshipRequestResult>,
|
||||
) {}
|
||||
|
||||
async execute(dto: RejectSponsorshipRequestDTO): Promise<Result<RejectSponsorshipRequestResultDTO, ApplicationErrorCode<'SPONSORSHIP_REQUEST_NOT_FOUND' | 'SPONSORSHIP_REQUEST_NOT_PENDING'>>> {
|
||||
// Find the request
|
||||
const request = await this.sponsorshipRequestRepo.findById(dto.requestId);
|
||||
if (!request) {
|
||||
return Result.err({ code: 'SPONSORSHIP_REQUEST_NOT_FOUND' });
|
||||
}
|
||||
async execute(
|
||||
input: RejectSponsorshipRequestInput,
|
||||
): Promise<
|
||||
Result<void, ApplicationErrorCode<RejectSponsorshipRequestErrorCode, { message: string }>>
|
||||
> {
|
||||
const { requestId, respondedBy, reason } = input;
|
||||
|
||||
if (!request.isPending()) {
|
||||
return Result.err({ code: 'SPONSORSHIP_REQUEST_NOT_PENDING' });
|
||||
}
|
||||
|
||||
// Reject the request
|
||||
const rejectedRequest = request.reject(dto.respondedBy, dto.reason);
|
||||
await this.sponsorshipRequestRepo.update(rejectedRequest);
|
||||
|
||||
await this.sponsorshipRejectionNotificationPort.notifySponsorshipRequestRejected({
|
||||
requestId: request.id,
|
||||
sponsorId: request.sponsorId,
|
||||
entityType: request.entityType,
|
||||
entityId: request.entityId,
|
||||
tier: request.tier,
|
||||
offeredAmountCents: request.offeredAmount.amount,
|
||||
currency: request.offeredAmount.currency,
|
||||
rejectedAt: rejectedRequest.respondedAt!,
|
||||
rejectedBy: dto.respondedBy,
|
||||
rejectionReason: rejectedRequest.rejectionReason,
|
||||
this.logger.debug('Executing RejectSponsorshipRequestUseCase', {
|
||||
requestId,
|
||||
respondedBy,
|
||||
});
|
||||
|
||||
return Result.ok({
|
||||
requestId: rejectedRequest.id,
|
||||
status: 'rejected',
|
||||
rejectedAt: rejectedRequest.respondedAt!,
|
||||
...(rejectedRequest.rejectionReason !== undefined
|
||||
? { reason: rejectedRequest.rejectionReason }
|
||||
: {}),
|
||||
});
|
||||
try {
|
||||
const request = await this.sponsorshipRequestRepo.findById(requestId);
|
||||
if (!request) {
|
||||
this.logger.warn('Sponsorship request not found', { requestId, respondedBy });
|
||||
return Result.err({
|
||||
code: 'SPONSORSHIP_REQUEST_NOT_FOUND',
|
||||
details: { message: 'Sponsorship request not found' },
|
||||
});
|
||||
}
|
||||
|
||||
if (!request.isPending()) {
|
||||
this.logger.warn('Sponsorship request is not pending', {
|
||||
requestId,
|
||||
respondedBy,
|
||||
status: request.status,
|
||||
});
|
||||
return Result.err({
|
||||
code: 'SPONSORSHIP_REQUEST_NOT_PENDING',
|
||||
details: { message: 'Sponsorship request is not pending' },
|
||||
});
|
||||
}
|
||||
|
||||
const rejectedRequest = request.reject(respondedBy, reason);
|
||||
await this.sponsorshipRequestRepo.update(rejectedRequest);
|
||||
|
||||
const result: RejectSponsorshipRequestResult = {
|
||||
requestId: rejectedRequest.id,
|
||||
status: 'rejected',
|
||||
respondedAt: rejectedRequest.respondedAt ?? new Date(),
|
||||
rejectionReason: rejectedRequest.rejectionReason,
|
||||
};
|
||||
|
||||
this.output.present(result);
|
||||
|
||||
this.logger.info('Sponsorship request rejected successfully', {
|
||||
requestId,
|
||||
respondedBy,
|
||||
});
|
||||
|
||||
return Result.ok(undefined);
|
||||
} catch (error) {
|
||||
const err = error instanceof Error ? error : new Error('Unknown error');
|
||||
this.logger.error('Failed to reject sponsorship request', err, {
|
||||
requestId,
|
||||
respondedBy,
|
||||
});
|
||||
|
||||
return Result.err({
|
||||
code: 'REPOSITORY_ERROR',
|
||||
details: { message: err.message ?? 'Failed to reject sponsorship request' },
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user