fix(pos): TPV never blocks on stock — physical scanner always wins

This commit is contained in:
Deploy
2026-08-26 22:32:13 +02:00
parent 7df6a003dc
commit 92d151ee3d

View File

@@ -174,8 +174,6 @@ export class CreatePosSaleUseCase {
throw new AppError(400, 'POS_EMPTY_CART', 'El carrito está vacío'); throw new AppError(400, 'POS_EMPTY_CART', 'El carrito está vacío');
const lineDiscountsEnabled = session.terminal_settings?.lineDiscountsEnabled !== false; const lineDiscountsEnabled = session.terminal_settings?.lineDiscountsEnabled !== false;
// POS-FIX-12: physical TPV (cashier) trusts real stock — skip inventory check
const selfpayMode = session.terminal_settings?.selfpayMode === true;
let subtotalCents = 0; let subtotalCents = 0;
let discountCents = 0; let discountCents = 0;
let taxCents = 0; let taxCents = 0;
@@ -242,22 +240,15 @@ export class CreatePosSaleUseCase {
'Los descuentos están desactivados en este terminal', 'Los descuentos están desactivados en este terminal',
); );
} }
const stock = await client.query<{ available: number }>( // POS-FIX-12: TPV does not block on inventory_stock.
// Items are scanned physically (real stock). inventory_movements still records the sale,
// but inventory_stock.available is allowed to drift and may go negative.
await client.query(
`SELECT available FROM inventory_stock `SELECT available FROM inventory_stock
WHERE variant_id = $1 AND store_id = $2 WHERE variant_id = $1 AND store_id = $2
FOR UPDATE`, FOR UPDATE`,
[catalog.variant_id, session.store_id], [catalog.variant_id, session.store_id],
); );
const availableStock = Number(stock.rows[0]?.available ?? 0);
// POS-FIX-12: only selfpay terminals validate against inventory_stock.
// Physical (cashier) TPV trusts real stock — the count is allowed to drift.
if (selfpayMode && availableStock < inputItem.quantity) {
throw new AppError(
409,
'POS_STOCK_UNAVAILABLE',
`Stock insuficiente para ${catalog.name}`,
);
}
const netUnitPriceCents = const netUnitPriceCents =
catalog.offer_cents === null catalog.offer_cents === null
? Number(catalog.net_unit_amount_cents) ? Number(catalog.net_unit_amount_cents)