89 lines
3.2 KiB
TypeScript
89 lines
3.2 KiB
TypeScript
import { Result } from '@core/shared/application/Result';
|
|
import type { Logger } from '@core/shared/application';
|
|
import type { CheckoutServicePort } from '../ports/CheckoutServicePort';
|
|
import type { CheckoutConfirmationPort } from '../ports/CheckoutConfirmationPort';
|
|
import { CheckoutStateEnum } from '../../domain/value-objects/CheckoutState';
|
|
|
|
|
|
interface SessionMetadata {
|
|
sessionName: string;
|
|
trackId: string;
|
|
carIds: string[];
|
|
}
|
|
|
|
export class ConfirmCheckoutUseCase {
|
|
private static readonly DEFAULT_TIMEOUT_MS = 30000;
|
|
|
|
constructor(
|
|
private readonly checkoutService: CheckoutServicePort,
|
|
private readonly confirmationPort: CheckoutConfirmationPort,
|
|
private readonly logger: Logger,
|
|
) {}
|
|
|
|
async execute(sessionMetadata?: SessionMetadata): Promise<Result<void>> {
|
|
this.logger.debug('Executing ConfirmCheckoutUseCase', { sessionMetadata });
|
|
|
|
const infoResult = await this.checkoutService.extractCheckoutInfo();
|
|
|
|
if (infoResult.isErr()) {
|
|
this.logger.error('Failed to extract checkout info', infoResult.unwrapErr());
|
|
return Result.err(infoResult.unwrapErr());
|
|
}
|
|
|
|
const info = infoResult.unwrap();
|
|
this.logger.info('Extracted checkout info', { state: info.state.getValue(), price: info.price });
|
|
|
|
|
|
if (info.state.getValue() === CheckoutStateEnum.INSUFFICIENT_FUNDS) {
|
|
this.logger.error('Insufficient funds to complete checkout');
|
|
return Result.err(new Error('Insufficient funds to complete checkout'));
|
|
}
|
|
|
|
if (!info.price) {
|
|
this.logger.error('Could not extract price from checkout page');
|
|
return Result.err(new Error('Could not extract price from checkout page'));
|
|
}
|
|
|
|
this.logger.debug('Requesting checkout confirmation', { price: info.price, state: info.state.getValue(), sessionMetadata });
|
|
|
|
// Request confirmation via port with full checkout context
|
|
const confirmationResult = await this.confirmationPort.requestCheckoutConfirmation({
|
|
price: info.price,
|
|
state: info.state,
|
|
sessionMetadata: sessionMetadata || {
|
|
sessionName: 'Unknown Session',
|
|
trackId: 'unknown',
|
|
carIds: [],
|
|
},
|
|
timeoutMs: ConfirmCheckoutUseCase.DEFAULT_TIMEOUT_MS,
|
|
});
|
|
|
|
if (confirmationResult.isErr()) {
|
|
this.logger.error('Checkout confirmation failed', confirmationResult.unwrapErr());
|
|
return Result.err(confirmationResult.unwrapErr());
|
|
}
|
|
|
|
const confirmation = confirmationResult.unwrap();
|
|
this.logger.info('Checkout confirmation received', { confirmation });
|
|
|
|
if (confirmation.isCancelled()) {
|
|
this.logger.error('Checkout cancelled by user');
|
|
return Result.err(new Error('Checkout cancelled by user'));
|
|
}
|
|
|
|
if (confirmation.isTimeout()) {
|
|
this.logger.error('Checkout confirmation timeout');
|
|
return Result.err(new Error('Checkout confirmation timeout'));
|
|
}
|
|
|
|
this.logger.info('Proceeding with checkout');
|
|
const checkoutResult = await this.checkoutService.proceedWithCheckout();
|
|
|
|
if (checkoutResult.isOk()) {
|
|
this.logger.info('Checkout process completed successfully.');
|
|
} else {
|
|
this.logger.error('Checkout process failed', checkoutResult.unwrapErr());
|
|
}
|
|
return checkoutResult;
|
|
}
|
|
} |