[bug] Cambiar el precio puede dejar el producto sin precio activo #19

Open
opened 2026-10-02 18:47:44 +00:00 by Carlos · 0 comments
Member

Qué pasa

Al cambiar el precio de un producto (apps/web/src/app/admin/inventario/productos/page.tsx:164-168), primero se archiva el precio actual y después se crea el nuevo, en dos requests separados. Si el segundo falla, el producto queda sin precio activo y el POS no lo deja vender.

Lo mismo pasa al guardar un producto: primero se crea y luego se sincronizan las categorías con varios requests en paralelo (syncCategories). Si alguno falla, el producto queda guardado sin todas sus categorías y el formulario muestra error, así que un segundo intento crea un producto duplicado o falla por SKU repetido.

Entorno

local

Módulos

Productos / precios / categorías, Punto de venta (POS), Web / frontend

Severidad

Bloquea un flujo

Pasos para reproducir

  1. Abrir Inventario → Productos y elegir un producto con precio.
  2. Cambiar el precio con un valor que el API rechace, o cortar la red justo después del primer request.
  3. Intentar vender el producto en el POS.

Esperado

El cambio de precio es atómico: o queda el precio nuevo activo, o se conserva el anterior.

Actual

El precio anterior queda archived y no hay precio active. El POS muestra "no tiene un precio configurado" y el producto no se puede vender hasta que alguien vuelva a capturar el precio.

Evidencia

Encontrado en auditoría de código; no reproducido en ejecución.

// productos/page.tsx:164-168
if (current) {
  await updateHistory.mutateAsync({ id: current.id, data: { status: "archived" } });
}
await createHistory.mutateAsync({ productId: pricing.id, unitPrice, costUnit, status: "active" });

Arreglo sugerido: endpoint POST /products/:id/price que archive y cree en una transacción; mientras tanto, crear el nuevo antes de archivar el anterior. Para categorías, un PUT /products/:id/categories que reemplace la lista en una transacción.

¿Está también en producción?

  • Sí — este issue no basta; hay que abrir un Incidente / hotfix
  • No — solo local / staging
  • No sé

Antes de abrir

  • Busqué un issue duplicado
### Qué pasa Al cambiar el precio de un producto (`apps/web/src/app/admin/inventario/productos/page.tsx:164-168`), primero se archiva el precio actual y después se crea el nuevo, en dos requests separados. Si el segundo falla, el producto queda sin precio activo y el POS no lo deja vender. Lo mismo pasa al guardar un producto: primero se crea y luego se sincronizan las categorías con varios requests en paralelo (`syncCategories`). Si alguno falla, el producto queda guardado sin todas sus categorías y el formulario muestra error, así que un segundo intento crea un producto duplicado o falla por SKU repetido. ### Entorno local ### Módulos Productos / precios / categorías, Punto de venta (POS), Web / frontend ### Severidad Bloquea un flujo ### Pasos para reproducir 1. Abrir **Inventario → Productos** y elegir un producto con precio. 2. Cambiar el precio con un valor que el API rechace, o cortar la red justo después del primer request. 3. Intentar vender el producto en el POS. ### Esperado El cambio de precio es atómico: o queda el precio nuevo activo, o se conserva el anterior. ### Actual El precio anterior queda `archived` y no hay precio `active`. El POS muestra "no tiene un precio configurado" y el producto no se puede vender hasta que alguien vuelva a capturar el precio. ### Evidencia ```shell Encontrado en auditoría de código; no reproducido en ejecución. // productos/page.tsx:164-168 if (current) { await updateHistory.mutateAsync({ id: current.id, data: { status: "archived" } }); } await createHistory.mutateAsync({ productId: pricing.id, unitPrice, costUnit, status: "active" }); ``` Arreglo sugerido: endpoint `POST /products/:id/price` que archive y cree en una transacción; mientras tanto, crear el nuevo antes de archivar el anterior. Para categorías, un `PUT /products/:id/categories` que reemplace la lista en una transacción. ### ¿Está también en producción? - [ ] Sí — este issue no basta; hay que abrir un Incidente / hotfix - [x] No — solo local / staging - [ ] No sé ### Antes de abrir - [x] Busqué un issue duplicado
Jose was assigned by Carlos 2026-10-02 20:04:27 +00:00
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: RynextTechnologies/PDV#19