fix(pos-selfpay): use confirmSaleWith to avoid stale state when confirming from modal

This commit is contained in:
Deploy
2026-08-26 22:24:14 +02:00
parent c43a8527f1
commit 15f36c3a7e

View File

@@ -525,6 +525,66 @@ export default function RegisterPage() {
}
};
// POS-SELFPAY-FLOW: confirm sale with explicit payment list (avoids stale state in selfpay modal)
const confirmSaleWith = async (allocations: PaymentAllocation[]) => {
if (!config?.session) {
setError('No hay sesión abierta');
return;
}
if (cart.length === 0) {
setError('Carrito vacío');
return;
}
const totalAllocated = allocations.reduce((sum, a) => sum + a.amountCents, 0);
if (totalAllocated > totals.total) {
setError('Los pagos asignados superan el total');
return;
}
setPayments(allocations);
setProcessing(true);
setError('');
try {
const saleItems = cart.map((item) => {
if (item.kind === 'free' || !item.variantId) {
return {
kind: 'free' as const,
name: item.name,
unitPriceCents: item.unitPriceCents,
quantity: item.quantity,
};
}
return {
kind: 'stock' as const,
variantId: item.variantId,
quantity: item.quantity,
discountCents: item.discountCents,
};
});
const result = await posApi.createSale<PosSaleResponse>({
idempotencyKey: generateIdempotencyKey(),
cashSessionId: config.session.id,
terminalId: config.terminal.id,
items: saleItems,
payments: allocations.map((payment) => ({
methodCode: payment.methodCode,
amountCents: payment.amountCents,
...(payment.kind === 'cash' ? { tenderedCents: payment.tenderedCents } : {}),
})),
...(customer ? { customerId: customer.id } : {}),
});
setReceipt(result.receipt);
setRestPaymentFor(null);
if (isSelfpayMode && selfpayEmail.trim()) {
void posApi.emailReceipt(result.receipt.orderId, selfpayEmail.trim()).catch(() => {});
}
void loadPendingSales();
} catch (err) {
setError(err instanceof Error ? err.message : 'No se pudo confirmar la venta');
} finally {
setProcessing(false);
}
};
const parkSale = async () => {
if (!config?.session) {
setError('No hay sesión abierta');
@@ -1857,8 +1917,7 @@ export default function RegisterPage() {
...(method.kind === 'cash' ? { tenderedCents: remainingCents } : {}),
changeCents: 0,
};
setPayments([allocation]);
void confirmSale();
void confirmSaleWith([allocation]);
}}
disabled={remainingCents === 0}
className={`min-h-16 rounded-xl px-2 font-bold text-white disabled:opacity-40 ${method.kind === 'cash' ? 'bg-green-600' : method.kind === 'card' ? 'bg-blue-600' : 'bg-slate-700'}`}