fix(pos-selfpay): use confirmSaleWith to avoid stale state when confirming from modal
This commit is contained in:
@@ -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'}`}
|
||||
|
||||
Reference in New Issue
Block a user