diff --git a/src/app/features/store/pages/checkout-page/checkout-page.component.spec.ts b/src/app/features/store/pages/checkout-page/checkout-page.component.spec.ts index 2d312c5..ed184c7 100644 --- a/src/app/features/store/pages/checkout-page/checkout-page.component.spec.ts +++ b/src/app/features/store/pages/checkout-page/checkout-page.component.spec.ts @@ -14,7 +14,6 @@ import { GlobalLoadingService } from '../../../../core/services/global-loading/g import { TenantService } from '../../../../core/services/tenant.service'; import { ToastService } from '../../../../core/services/toast.service'; import { CartEditingPolicy } from '../../../../core/services/tenant.interface'; -import { ToastService } from '../../../../core/services/toast.service'; import { CheckoutPageComponent } from './checkout-page.component'; describe('CheckoutPageComponent payment validation', () => { diff --git a/src/app/features/store/pages/checkout-page/checkout-page.component.ts b/src/app/features/store/pages/checkout-page/checkout-page.component.ts index aedcefa..4ce7e59 100644 --- a/src/app/features/store/pages/checkout-page/checkout-page.component.ts +++ b/src/app/features/store/pages/checkout-page/checkout-page.component.ts @@ -69,7 +69,6 @@ export class CheckoutPageComponent implements OnInit, OnDestroy { private readonly globalLoadingService = inject(GlobalLoadingService); private readonly toastService = inject(ToastService); private readonly qrPollingIntervalMs = 5_000; - private readonly toastService = inject(ToastService); private readonly qrPollingMaxAttempts = 9; private readonly transferPollingIntervalMs = 3_000; private readonly transferPollingMaxAttempts = 4; @@ -194,9 +193,9 @@ export class CheckoutPageComponent implements OnInit, OnDestroy { return; } -<<<<<<< HEAD - if (editing && !this.canModifyCart()) { - const tenant = this.tenantService.tenant(); + const tenant = this.tenantService.tenant(); + const purchaseId = this.createdPurchaseId(); + if (!tenant || !purchaseId) { return; } @@ -217,9 +216,9 @@ export class CheckoutPageComponent implements OnInit, OnDestroy { } finally { this.globalLoadingService.stop(); this.isRestoringCart.set(false); ->>>>>>> feature/restore-cart-on-modify } } + protected async onStep1Continue(): Promise { if (this.form.invalid || this.isUpdatingPurchase()) return; @@ -409,10 +408,16 @@ export class CheckoutPageComponent implements OnInit, OnDestroy { } if (purchase.status === 'paid') { + this.navigateToPurchaseStatus(purchaseId); + return; + } this.scheduleTransferPoll(runId); - console.error('Failed to submit transfer payment for review:', error); - this.showRequestError(error, 'No se pudo enviar el pago para su validación.'); + } catch (error) { + const expired = this.handleCheckoutError( + error, + 'No se pudo enviar el pago para su validación.', + ); if (!expired && runId === this.transferPollingRunId) { this.transferValidationStatus.set('error'); @@ -660,4 +665,51 @@ export class CheckoutPageComponent implements OnInit, OnDestroy { this.toastService.danger(message); } + + private handleCheckoutError(error: unknown, fallbackMessage: string): boolean { + if (!(error instanceof HttpErrorResponse)) { + this.toastService.danger(fallbackMessage); + return false; + } + + const response = error.error as ApiErrorResponse | null; + + if (response?.code === 'purchase.expired' || this.hasExpiredPurchase()) { + this.navigationStarted = true; + this.stopQrPolling(); + this.stopTransferPolling(); + this.toastService.danger( + response?.code === 'purchase.expired' && response.message + ? response.message + : 'La compra venció. Iniciá una nueva compra.', + ); + void this.router.navigate(['/']); + return true; + } + + const validationMessage = response?.errors + ? Object.values(response.errors).flat().find(Boolean) + : undefined; + + this.toastService.danger(validationMessage ?? response?.message ?? fallbackMessage); + return false; + } + + private hasExpiredPurchase(): boolean { + const purchase = this.createdPurchase(); + + if (!purchase) { + return false; + } + + if (purchase.status === 'expired') { + return true; + } + + if (!purchase.expires_at) { + return false; + } + + return Date.parse(purchase.expires_at) <= Date.now(); + } }