CAT-001
Alta de producto padre
Registrar un nuevo tipo de medicina en el catálogo de la organización, de modo que pueda recibir formatos y quedar disponible para la asignación de lotes y la posterior dispensación.
CAT-001 — Alta de producto padre
1. Objetivo
Definir el procedimiento mediante el cual el administrador de catálogo de la organización sin fines de lucro registra un nuevo tipo de medicina en el sistema. El registro del producto padre es el primer eslabón de la cadena de trazabilidad: sin él, no puede existir un formato de presentación ni una asignación de lote.
2. Alcance
Aplica a toda incorporación de un nuevo tipo de medicina al catálogo activo de la organización. No aplica a la edición de fichas existentes (CAT-002) ni a la creación de formatos de presentación (CAT-003).
3. Definiciones
- Producto padre: registro en la tabla
productsconparent_product_id = NULL. Define el tipo de medicina. No tiene stock ni lote propio: esos atributos viven en sus hijos (formatos). - Formato: producto hijo en
productsconparent_product_idapuntando al padre. Contieneunit_grams,stockylot_inventory_id. - Catálogo: conjunto de productos padres activos en el tenant.
4. Roles y responsables
| Rol | Responsabilidad |
|---|---|
| Admin catálogo | Único rol autorizado para crear productos padres. Verificado por profile.role = "admin" en la server action. |
5. Disparador de inicio
La organización resuelve incorporar un tipo de medicina que hoy no figura en su catálogo. El administrador de catálogo ingresa a /admin/medicina y selecciona la opción de nueva medicina.
6. Requisitos previos
- El usuario ha iniciado sesión con rol
adminen el panel de la organización. - La medicina a registrar no existe aún en el catálogo activo (verificación manual; sin restricción de unicidad de nombre en base de datos — ver §17).
- Se cuenta con la denominación técnica correcta de la medicina.
7. Entradas
Datos del producto padre, cargados en el formulario de nueva medicina:
- Nombre de la medicina.
- Descripción.
- Sucursal (
branch_id). - Estado inicial.
No hay documentos adjuntos ni datos de socios en este flujo: las entradas son exclusivamente información de catálogo de la organización.
8. Procedimiento paso a paso
-
Acceso al módulo de catálogo. El administrador ingresa a
/admin/medicinay selecciona la opción de nueva medicina. -
Carga de datos del producto padre. El sistema presenta un formulario con los campos mínimos: nombre de la medicina, descripción, sucursal (
branch_id) y estado inicial. El administrador completa los campos y confirma. -
Registro en base de datos. La server action
createMedicinevalida la sesión y el rol del usuario (profile.role = "admin"). Si la validación falla, retorna{ error: "No autorizado" }sin operar. Si pasa, inserta el registro enproductsconparent_product_id = NULL. -
Disponibilidad del producto padre. El sistema redirige al listado de medicinas y el nuevo producto padre aparece disponible para la creación de formatos.
9. Puntos de control
| Punto de control | Tipo | Evidencia |
|---|---|---|
| Autenticación activa | Auth check en server action | supabase.auth.getUser() en createMedicine |
| Rol admin | Role check en server action | profile.role !== "admin" → error (CONFIRMADO) |
Inserción en products | DB write | Server action retorna { error } si falla; no lanza |
10. Criterios de decisión
Este protocolo resuelve una sola cosa: si el producto padre queda registrado o no registrado.
| Situación | Resultado |
|---|---|
Sesión activa, rol admin y campos mínimos completos | Producto padre registrado en products con active = true y parent_product_id = NULL; visible en /admin/medicina; habilitado para recibir formatos (CAT-003) |
Falta sesión o el rol no es admin | No registrado; la server action retorna error antes de operar |
| La inserción en base de datos falla | No registrado; la server action retorna { error } con el código de la base |
11. Excepciones y escalamiento
Caminos de error del sistema:
| Situación | Respuesta del sistema |
|---|---|
| Usuario sin sesión | La server action retorna error antes de operar |
| Usuario con rol no admin | { error: "No autorizado" } |
| Error de base de datos | { error: "Error al crear..." } con código; log en consola del servidor |
Envío duplicado del formulario. No hay mecanismo de idempotencia confirmado para la creación de producto padre. Dos envíos del formulario generan dos filas en products. La unicidad depende de la UI o del operador (ver §17). Ante un duplicado detectado, el administrador de catálogo da de baja la ficha sobrante y deja constancia del motivo; no se borra el registro.
Escalamiento. Un error de base de datos persistente se escala al responsable de TI de la organización. La creación no se fuerza por vías directas a la base de datos: hacerlo saltearía la guarda de rol de la server action.
12. Registros generados
- Fila en la tabla
productsconparent_product_id = NULL. - No se generan documentos clínicos ni PDFs.
- No se genera evento en
iso_system_events— ver brecha 1 en §17.
13. Indicadores
| Indicador | Fórmula | Meta | Fuente |
|---|---|---|---|
| Productos padre con al menos un formato activo | Padres con ≥1 hijo activo ÷ total de padres activos | ≥ 90 % | Tabla products |
| Tiempo entre alta del padre y primer formato disponible | Fecha del primer hijo − fecha del padre | ≤ 5 días hábiles | Tabla products |
14. Riesgos y controles
| Riesgo | Control | Tipo |
|---|---|---|
| Creación de producto padre por un usuario sin autorización | Guarda profile.role !== "admin" en createMedicine (§9) | Preventivo |
| Alta de producto padre sin rastro de autoría ni fecha auditable | Sin control en el sistema — brecha 1 declarada en §17. Mitigación operativa: el administrador de catálogo deja constancia del alta en el registro interno de la organización | Correctivo |
| Dos productos padre con el mismo nombre en el mismo tenant | Sin control en base de datos — brecha 2 declarada en §17. Mitigación operativa: verificación manual del catálogo antes del alta (§6, requisito 2) | Detectivo |
| Trazabilidad ambigua por nombre ante una discrepancia de inventario | Revisión del catálogo contra lot_product_assignments (LOT-001) | Detectivo |
| Aparecer como establecimiento comercial | El catálogo registra medicina de la organización, no oferta de venta. No se publican precios ni condiciones de compra en este flujo | Preventivo |
Privacidad. Los datos de este flujo son información de catálogo de la organización, no datos personales de socios. No aplica tratamiento de datos sensibles.
15. Normativa y referencias
| Norma | Referencia | Qué cubre en este protocolo |
|---|---|---|
| ISO 9001:2015 | §8.5.2 | Identificación y trazabilidad: el producto padre es el identificador raíz de la cadena |
| ISO 9001:2015 | §8.5.4 | Preservación: la ficha del padre preserva la identidad de la medicina a lo largo del ciclo |
| Ley 20.000 | Custodia y trazabilidad | La sustancia debe identificarse unívocamente desde su ingreso al catálogo |
| Decreto 84/2015 MINSAL | Registro de dispensación | El producto padre es el primer eslabón del registro que sostiene cada dispensación |
El cumplimiento de estas normas no está certificado por ninguna autoridad. Este protocolo declara qué controles ejecuta la organización, no que un tercero los haya auditado.
16. Anexos y formularios vinculados
- Creación de formato / presentación ([[wiki/entities/dispensai/protocolos/CAT-003]])
- Edición de ficha de medicina ([[wiki/entities/dispensai/protocolos/CAT-002]])
- Asignación de lote a producto ([[wiki/entities/dispensai/protocolos/LOT-001]])
17. Implementación en el sistema
El protocolo está implementado en su paso de registro. La autorización está en la server action; no existe restricción de base de datos que impida la creación de duplicados por nombre.
| Elemento del protocolo | Dónde vive |
|---|---|
| Guardia de autenticación (paso 3) | supabase.auth.getUser() en createMedicine — server action "use server" |
| Guardia de rol admin (paso 3) | profile.role !== "admin" → { error: "No autorizado" } en createMedicine |
Inserción en products sin parent_product_id (paso 3) | Tabla products, columna parent_product_id = NULL |
| Visibilidad en panel (paso 4) | Ruta /admin/medicina, revalidatePath tras inserción |
Brechas conocidas:
-
Sin evento ISO al crear producto padre. Confirmado por lectura del archivo
app/actions/medicines.ts:createMedicineno contiene llamada alogISOSystemEvent. SóloupdateMedicineemite eventos ISO (product_stock_changed,product_updated). El alta de un producto padre no deja rastro eniso_system_events. Si el catálogo se audita, no hay evento que identifique quién creó el producto ni cuándo. El audit trail de inventario comienza con un hueco en su primer paso. -
Sin restricción de unicidad de nombre de producto padre en base de datos. No se encontró un
UNIQUEsobreproducts.nameen las migraciones revisadas. Dos productos padres con el mismo nombre en el mismo tenant son posibles si la UI no lo impide. La trazabilidad por nombre queda ambigua ante una discrepancia de inventario.
Brecha observada en auditoría 2026-08-31
- Ruta no encontrada exacta:
/admin/medicina/nueva— puede ser variante (singular/plural, /admin vs /dashboard) o ruta renombrada. Acción correctora: actualizar el frontmatter con la ruta real que usa el sistema.
18. Historial de versiones
| Versión | Fecha | Cambio | Autor |
|---|---|---|---|
| 1.0 | 2026-08-28 | Versión inicial. Redactada desde la corrida de evidencia 2026-08-28-CAT-LOT. Dos brechas declaradas. | Catálogo |
| 1.1 | 2026-08-29 | Cierre de INFERIDO: confirmada la guarda profile.role !== "admin" en createMedicine (ya figuraba CONFIRMADO en §9). Confirmada la ausencia de logISOSystemEvent en createMedicine por lectura directa de app/actions/medicines.ts (brecha 1 pasa de INFERIDO a CONFIRMADO). Sin UNIQUE en products.name — confirmado sin hallazgo en migraciones (brecha 2 CONFIRMADO). Estado ascendido a Vigente. | Catálogo |
| 1.2 | 2026-08-29 | Realineamiento estructural al contrato del catálogo (_template.md): los 18 títulos de sección pasan a los de la plantilla y el contenido se redistribuye según lo que cada sección exige. Definiciones pasan de §4 a §3; roles de §5 a §4; requisitos previos de §6 a §6 con su título de contrato. Se escriben desde cero §5 Disparador de inicio y §7 Entradas, ambas derivadas de la evidencia ya presente en §8. Los criterios de éxito pasan a §10 Criterios de decisión; caminos de error e idempotencia se consolidan en §11 Excepciones y escalamiento; §14 pasa de privacidad a Riesgos y controles conservando la declaración de privacidad. El antiguo §3 Marco normativo se absorbe en §15, que ya cubría las mismas tres normas. Sin cambios en §17: las dos brechas se mantienen íntegras con su evidencia. | Catálogo |
| 1.0+audit-2026-08-31 | 2026-08-31 | Detectados gaps en auditoría: /admin/medicina/nueva. §17 actualizada para documentar la brecha con evidencia de código. Estado documental sin cambio. | Auditoría automática |
Documentos asociados
- Ficha de producto
- Especificación técnica de la medicina
Registros y evidencia
- Registro de creación en tabla products
- Sin evento ISO al crear producto padre (brecha confirmada — createMedicine no llama a logISOSystemEvent)
Indicadores
- % de productos padre con al menos un formato activo
- Tiempo entre alta de padre y primer formato disponible
Normativa y referencias
- Ley 20.000
- ISO 9001:2015 §8.5.2
- ISO 9001:2015 §8.5.4
Dónde deja rastro en el sistema
- Rutas
-
- /admin/medicina
- /admin/medicina/nueva
- Tablas
-
- products