Skip to content

fix(pharmacy): disponibilidad por producto, marca «sin stock» en gestión, catálogo oficial sin 500 y capas de inventario (test) - #1148

Merged
Leonardolv21 merged 4 commits into
testfrom
itzan/far-cierre-farmacia-test
Oct 30, 2026
Merged

Leonardolv21 merged 4 commits into
testfrom
itzan/far-cierre-farmacia-test

Conversation

@Jsaldias39

@Jsaldias39 Jsaldias39 commented Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator

Resumen

Cierre de FAR-05 y FAR-06 en la API, hacia test. Los mismos cuatro commits que el PR hacia dev (#1147), traídos por cherry-pick a una rama creada desde origin/test. Los 21 archivos de código y pruebas que tocan son idénticos en dev y en test antes del cambio; openapi/ difiere entre las dos bases y el campo se agregó en el mismo lugar.

1. Disponibilidad por producto, no por sede (D-06-3, arreglo de fondo). siteProductAvailabilitySql pasaba la sede entera al libro de inventario en cuanto tenía una posición, y desde ahí un producto publicado después no aparecía en esa sede hasta que alguien le escribiera una. SiteStockWriter lo tapaba rellenando, en la primera escritura, la posición de cada producto con lo que declaraba el catálogo, lo que además congelaba en la sede el conteo de ese día.

Ahora la regla decide cada par (sede, producto): con posición en la sede manda el libro; sin posición, lo declarado en el catálogo. «No tengo» de la farmacia y los borradores siguen sin ofrecerse nunca. El relleno se quita (findProductsWithoutPositionInSite, siteKeepsLedger e initialSiteQuantity quedan sin uso y se borran): «Lo tengo / No lo tengo» y la sincronización escriben solo los productos que tocan. Las tres lecturas que usan la regla (receta entre sucursales, buscador por sede, catálogo público) la toman sin cambios propios.

2. La marca «sin stock en catálogo» en la lectura de gestión. GET /pharmacy/products?managed=true y la respuesta del PATCH de producto sirven outOfStockDeclared. El front la deducía de inStock: false con conteo distinto de cero, que con conteo 0 no se podía distinguir. La lectura pública no la expone.

3. La búsqueda del catálogo oficial respondía 500. MedicineCatalogRepository pasaba arreglos a any(?::text[]) y array_position(?::text[], …); el driver los expande como lista y Postgres respondía con un error de sintaxis. Sin esa búsqueda no se podía dar de alta un producto desde el modal «Nuevo producto». Ahora va un marcador por valor, como reactions.repository.ts.

4. Capas de pharmacy_inventory. integration-read.service.ts (de FAR-07) importaba el tipo PharmacyIntegrationConnections de pharmacy/entities desde la capa de aplicación, y architecture/module-layering.spec.ts lo marcaba. El tipo sale ahora del repositorio de lectura.

Commits: 4d8f03244 (regla y marca), cbdcaf4e9 (catálogo oficial), 219a53daf (contrato), db3c693ef (capas).

Decisiones tomadas

  • Se quita el relleno de posiciones en vez de dejarlo junto a la regla nueva: con la regla por producto ya no evita nada, y dejarlo fijaba en cada sede el conteo que el catálogo tenía el día del primer cambio.
  • El contrato se actualiza solo en el campo nuevo. Regenerar openapi/ completo trae además rutas y esquemas de otros cambios (en dev, 27 rutas y 48 esquemas) que todavía no están en el documento; el campo se escribió tal como lo genera generate-openapi.mjs.
  • El inventario generado (docs/inventario, inventario/) no se regenera en este PR. Regenerarlo toca unos 300 archivos ajenos: la base ya estaba desfasada (números de línea de app.module.ts) y el generador hoy no encuentra el límite de 1 MB del cuerpo en src/main.ts (lo escribe como «no determinado»). Ningún endpoint ni tabla cambia acá.
  • La prueba de integración A1 se corrió contra una base local propia, nunca contra las compartidas.

Casilla documental (obligatoria)

Este PR cambia:

  • Rutas HTTP, DTO o controllers → PharmacyProductReadDto.outOfStockDeclared en openapi/openapi.{json,yaml}; yarn docs:openapi:lint en test falla con 4 errores y 11 avisos, los mismos con y sin este cambio (por ejemplo security-defined en /public/pharmacies/open-now y nullable sin type en PharmacyUpdateProductDto.unitPrice).
  • Entidades o el modelo de datos.
  • Eventos de dominio.
  • Permisos, roles o el mecanismo de autorización.
  • Un README de módulo → yarn docs:modules:sync no produjo cambios.
  • Una decisión arquitectónica nueva.
  • Nada de lo anterior.

Verificación

  • yarn build: verde en la rama de dev; en esta, yarn typecheck verde.
  • yarn test src/modules/pharmacy_inventory src/modules/pharmacy src/modules/public: 66 suites, 714 pruebas, verde, en esta rama.
  • Suite completa con cobertura (yarn test:cov) en esta rama: 1125 suites pasan, 1 omitida; 16 255 pruebas pasan, 0 fallan. module-layering 25/25. Cobertura global: 80 % sentencias, 74,31 % ramas, 67,28 % funciones, 80,97 % líneas.
  • Lint completo por grupos: los archivos de este PR, limpios. La base test trae 3 errores de prettier en billing (siat_simulated_invoices.entity.ts, siat_simulated_outbox.entity.ts, siat-schema.ts) y los 2 avisos de dev; ninguno es de este cambio.
  • yarn test:integration test/integration/a1-existencias-por-sede.int-spec.ts contra Postgres local, en la rama de dev (mismo código): 4/4.
  • yarn docs:validate / yarn docs:build: no se corrieron.

La verificación por HTTP y en el navegador está en #1147 (mismo código) y en mdavila-2001/mantra-core-health#1691 / mdavila-2001/mantra-core-health#1692.

…ck» en la lectura de gestión

La regla de existencias por sede pasaba la sede entera al libro en cuanto
tenía una posición: desde ahí, un producto publicado después no aparecía en
esa sede hasta que alguien le escribiera una. El escritor de stock por sede
lo tapaba rellenando la posición de cada producto en la primera escritura,
lo que además congelaba en la sede el conteo que el catálogo tenía ese día.

Ahora decide cada par (sede, producto): con posición en la sede manda el
libro; sin posición, lo declarado en el catálogo. El relleno ya no hace
falta y se quita: «Lo tengo / No lo tengo» y la sincronización escriben solo
los productos que tocan. La prueba de integración A1 cubre la sede que lleva
lotes de unos productos y sigue el catálogo en los demás.

La lectura de gestión (managed=true) y la respuesta del PATCH de producto
sirven `outOfStockDeclared`: el front ya no tiene que deducir la marca de
`inStock: false` con un conteo distinto de cero, que con conteo 0 no se
podía distinguir.
…ndía 500

`MedicineCatalogRepository` pasaba arreglos de JavaScript a `any(?::text[])`
y a `array_position(?::text[], …)`. El driver no los convierte en arreglos
de Postgres: llegaban como una lista separada por comas y la consulta
fallaba con un error de sintaxis. Sin esa búsqueda no se podía dar de alta
un producto desde el modal «Nuevo producto».

Ahora va un marcador por valor (`in (?, ?, …)` y `array[?, …]`), como ya
hace `reactions.repository.ts`; los valores siguen como parámetros. Las
pruebas exigían el arreglo como parámetro: ahora exigen que ningún arreglo
llegue al driver y que haya un valor por marcador.
El campo que suma la lectura con managed=true y la respuesta del PATCH de producto, tal como lo escribe el generador. Solo ese campo: regenerar el contrato entero arrastraría rutas y esquemas de otros cambios que todavía no están en el documento.
…es de pharmacy

integration-read.service.ts (capa de aplicación) importaba el tipo PharmacyIntegrationConnections de pharmacy/entities, y architecture/module-layering.spec.ts lo marcaba: sólo infrastructure/ habla con otros contextos. El tipo sale ahora del repositorio de lectura. Era el único rojo de la suite completa en dev.
@Jsaldias39 Jsaldias39 changed the title fix(pharmacy): disponibilidad por producto, marca «sin stock» en gestión y catálogo oficial sin 500 (test) fix(pharmacy): disponibilidad por producto, marca «sin stock» en gestión, catálogo oficial sin 500 y capas de inventario (test) Oct 30, 2026
@Leonardolv21
Leonardolv21 merged commit 8397b49 into test Oct 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants