Repository navigation
fix(pharmacy): disponibilidad por producto, marca «sin stock» en gestión, catálogo oficial sin 500 y capas de inventario - #1147
Merged
Conversation
…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.
This was referenced Oct 30, 2026
…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.
Leonardolv21
approved these changes
Oct 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Resumen
Cierre de FAR-05 y FAR-06 en la API. Cuatro cambios.
1. Disponibilidad por producto, no por sede (D-06-3, arreglo de fondo).
siteProductAvailabilitySqlpasaba 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.SiteStockWriterlo 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,siteKeepsLedgereinitialSiteQuantityquedan 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=truey la respuesta delPATCHde producto sirvenoutOfStockDeclared. El front la deducía deinStock: falsecon 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.
MedicineCatalogRepositorypasaba arreglos aany(?::text[])yarray_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, comoreactions.repository.ts.4. Capas de
pharmacy_inventory.integration-read.service.ts(de FAR-07, ya endev) importaba el tipoPharmacyIntegrationConnectionsdepharmacy/entitiesdesde la capa de aplicación, yarchitecture/module-layering.spec.tsfallaba: era el único rojo de la suite completa. El tipo sale ahora del repositorio de lectura.Commits:
3686ec2d6(regla y marca),c8c32c837(catálogo oficial),a697afaf7(contrato),2c06bf2b8(capas).Decisiones tomadas
openapi/completo trae además 27 rutas y 48 esquemas de otros cambios que todavía no están en el documento; el campo se escribió tal como lo generagenerate-openapi.mjs.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 deapp.module.ts) y el generador hoy no encuentra el límite de 1 MB del cuerpo ensrc/main.ts(lo escribe como «no determinado»). Ningún endpoint ni tabla cambia acá.Casilla documental (obligatoria)
Este PR cambia:
PharmacyProductReadDto.outOfStockDeclaredenopenapi/openapi.{json,yaml};yarn docs:openapi:lintválido (10 avisos).yarn docs:modules:syncno produjo cambios.Verificación
yarn build: verde.yarn test src/modules/pharmacy_inventory src/modules/pharmacy src/modules/public: 66 suites, 714 pruebas, verde.yarn typecheck: verde (también después del commit de capas).eslintsobre los archivos tocados: verde.yarn test:integration test/integration/a1-existencias-por-sede.int-spec.tscontra Postgres local: 4/4. La tabla del escenario suma la sede que lleva lotes de unos productos y sigue el catálogo en los demás.yarn test:cov) antes del commit de capas: 1124 suites pasan, 1 falla (module-layering.spec.ts, la violación que corrige2c06bf2b8), 1 omitida; 16 254 pruebas pasan. Después del arreglo,module-layeringeinventory-sync38/38. Cobertura global: 80 % sentencias, 74,31 % ramas, 67,28 % funciones, 80,97 % líneas.src/orm/catalog/schemas.catalog.ts, ignorado por patrón, yadmissions-expire-sweep.job.spec.ts).yarn lintno usa--max-warnings.yarn docs:validate/yarn docs:build: no se corrieron.Contra la API levantada en local, con cuentas
@alovida.test:POST /pharmacies/:id/productsde un producto nuevo, publicado y sin conteoGET /pharmacy-inventory/availabilitydel producto nuevoPUT …/sites/<Sur 2>/products/<nuevo>/availability {available:false}availabilitydel producto nuevoGET /pharmacy/products?managed=truestock=4 inStock=false outOfStockDeclared=true; el restofalseGET /pharmacy/productssinmanagedoutOfStockDeclaredGET /pharmacy/catalog-products?search=paracetamolEn el navegador (front, mdavila-2001/mantra-core-health#1691): el producto nuevo sale en Casa central como «Como en el catálogo», «Lo tengo» con cantidad y el rechazo 422 en su fila funcionan contra esta API.