From 92d151ee3d21f149581b388175998f368c870db9 Mon Sep 17 00:00:00 2001 From: Deploy Date: Wed, 26 Aug 2026 22:32:13 +0200 Subject: [PATCH] =?UTF-8?q?fix(pos):=20TPV=20never=20blocks=20on=20stock?= =?UTF-8?q?=20=E2=80=94=20physical=20scanner=20always=20wins?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/pos/application/create-pos-sale.ts | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/project/src/modules/pos/application/create-pos-sale.ts b/project/src/modules/pos/application/create-pos-sale.ts index 7012d94..cc574d5 100644 --- a/project/src/modules/pos/application/create-pos-sale.ts +++ b/project/src/modules/pos/application/create-pos-sale.ts @@ -174,8 +174,6 @@ export class CreatePosSaleUseCase { throw new AppError(400, 'POS_EMPTY_CART', 'El carrito está vacío'); 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 discountCents = 0; let taxCents = 0; @@ -242,22 +240,15 @@ export class CreatePosSaleUseCase { '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 WHERE variant_id = $1 AND store_id = $2 FOR UPDATE`, [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 = catalog.offer_cents === null ? Number(catalog.net_unit_amount_cents)