Saltar al contenido principal

Muestras de laboratorio

La muestra de laboratorio (/lab) es donde TankOS captura las propiedades que el laboratorio mide sobre el producto de un tanque —densidad, BSW (agua y sedimento), agua libre, temperatura, presión— y las hace llegar, ya aprobadas, al motor de cálculo custody. Es la máquina de estados más compleja del sistema: 7 estados y 7 acciones, con separación de funciones (SoD) reforzada por el servidor, adjuntos auditables en MinIO y una proyección de propiedades que deja la densidad y el BSW de la muestra disponibles para el cálculo sin re-consultarlos.

Esta página está orientada al técnico de laboratorio: cómo registrar una muestra y moverla por su ciclo de vida, paso a paso.

Por qué la muestra es custody-crítica

La densidad y el BSW que aprueba el laboratorio entran directamente en la cadena MPMS (CTL, CSW → NSV y masa). Una muestra mal aprobada se traduce en un NSV mal facturado. Por eso el flujo es estricto: nadie aprueba su propia muestra, los datos erróneos se invalidan (no se borran), y cada paso queda en la auditoría.

Quién hace qué

El acceso a cada acción lo decide la autoridad del rol (RBAC), no el botón de la pantalla. El UI oculta lo que no se puede hacer, pero el servidor es la autoridad.

RolCrear / editar / enviar (lab:submit)Aprobar / rechazar (lab:approve)Anular (lab:void)Invalidar (lab:invalidate)
Técnico de laboratorio
Operador
Supervisor

El técnico de laboratorio y el operador capturan, editan y envían muestras. El supervisor es quien aprueba o rechaza, y el único que puede anular o invalidar una muestra ya aprobada.

El ciclo de vida en 7 estados

Una muestra nace como borrador (DRAFT) y avanza por las transiciones de abajo. Cada flecha indica la autoridad que la dispara y la guardia que la protege.

La tabla de transiciones completa (cualquier par estado/acción fuera de esta tabla es un INVALID_TRANSITION):

Estado origenAcciónEstado destinoAutoridadGuardia / SoD
DRAFTEnviarSUBMITTEDlab:submit
DRAFTCancelarCANCELLEDlab:submitSolo el submitter
DRAFTEliminar (hard delete)lab:submitSolo el submitter
SUBMITTEDAprobarAPPROVEDlab:approveSoD: aprobador ≠ submitter
SUBMITTEDRechazarREJECTEDlab:approveSoD: rechazador ≠ submitter
SUBMITTEDCancelarCANCELLEDlab:submitSolo el submitter
REJECTEDReenviarSUBMITTEDlab:submitSolo el submitter
APPROVEDAnularVOIDEDlab:voidSupervisor + SoD: anulador ≠ submitter
APPROVEDInvalidarINVALIDATEDlab:invalidateSoD: invalidador ≠ aprobador

REJECTED es el único estado editable además de DRAFT: el técnico corrige la muestra y la reenvía (rework) conservando el mismo identificador, de modo que su historia completa queda en la auditoría.

Paso a paso

1. Crear el borrador (DRAFT)

Desde el botón "Nueva muestra" del workspace se abre /lab/new. El técnico selecciona el tanque, el producto, el método de laboratorio y la fecha/hora de muestreo (sampledAt), y captura las propiedades medidas: densidad (kg/m³), BSW (fracción), agua libre (mm), temperatura (°C) y presión (kPa). Todo se almacena en unidades SI; la conversión a imperial es solo de presentación.

Validación de la fecha de muestreo

sampledAt no puede ser futura. Un retroceso (backdate) de más de 7 días requiere un backdateReason obligatorio y la autoridad admin:system (D-20). El panel de backdate solo aparece para el administrador.

2. Editar (solo DRAFT o REJECTED)

Mientras la muestra esté en DRAFT o REJECTED, solo su submitter original puede editarla. En cualquier otro estado el formulario es de solo lectura.

3. Adjuntar archivos (MinIO)

Antes de enviar, el técnico puede subir certificados o evidencia de laboratorio. Los adjuntos solo se permiten en DRAFT y REJECTED (ver Adjuntos).

4. Enviar (DRAFT → SUBMITTED)

Al enviar, la muestra pasa a SUBMITTED y queda visible en la cola de aprobación del supervisor. A partir de aquí el técnico ya no puede editarla (salvo que sea rechazada).

5. Aprobar o rechazar (SUBMITTED → APPROVED | REJECTED)

El supervisor revisa la muestra y la aprueba o la rechaza (con una razón). Ambas acciones están sujetas a la separación de funciones: quien envió la muestra no puede aprobarla ni rechazarla (ver Separación de funciones).

6. Reenviar tras rechazo (REJECTED → SUBMITTED)

Una muestra rechazada vuelve a ser editable. Solo el submitter original la corrige y la reenvía: el identificador no cambia, así que la cadena rechazo → corrección → reenvío queda completa en la auditoría.

7. Cancelar (DRAFT | SUBMITTED → CANCELLED)

El submitter puede cancelar su muestra mientras esté en DRAFT o SUBMITTED. La cancelación es un estado terminal: la muestra no participa de ningún cálculo.

8. Anular e invalidar una muestra aprobada

Una muestra aprobada que ya no debe usarse se retira por una de dos vías terminales distintas, ambas exclusivas del supervisor (ver VOIDED vs INVALIDATED).

Formulario de nueva muestra

Formulario de nueva muestra de laboratorio

El formulario de /lab/new agrupa: el selector de tanque, el producto, la fecha/hora de muestra, el método, la ubicación, la API gravity 60 °F, el BSW, el agua, el sedimento, la API gravity observada, la temperatura observada y las notas. Los campos se validan contra el contrato Zod compartido (SubmitSampleBody), de modo que el formulario y la API exigen exactamente lo mismo.

Captura pendiente

Screenshot pendiente del barrido diferido — ver 61-DEFERRED-SWEEP.md (/lab/new BackdateOverridePanel admin). El panel de backdate del administrador (retroceso > 7 días con razón obligatoria) aún no tiene captura.

Adjuntos (MinIO)

Cada muestra admite hasta 5 archivos × 5 MBPDF, CSV o imágenes— para respaldar el resultado de laboratorio.

Cómo se almacenan y se descargan los adjuntos
  • El servicio olfatea los bytes del archivo (byte-sniff) para verificar su tipo real, no solo la extensión (D-13).
  • Los blobs se guardan en MinIO; la tabla lab_sample_attachments retiene solo los metadatos y la minioKey.
  • Solo se pueden adjuntar (o quitar) archivos en estados DRAFT y REJECTED.
  • La descarga se hace con una URL presignada con TTL; su emisión queda auditada y la URL en sí nunca se persiste.

Separación de funciones — el "segundo par de ojos"

La separación de funciones (SoD) es el corazón custody de este flujo: quien captura nunca aprueba.

SoD servidor-side — un intento directo devuelve 403

La SoD se aplica en el servidor, antes de la mutación, con el interceptor de separación de funciones y CHECK constraints en la base de datos. El UI espeja la regla (oculta el botón), pero la autoridad es el servidor:

  • Aprobar / rechazar: el aprobador no puede ser el submitter (submitterId ≠ approver).
  • Anular: el anulador no puede ser el submitter (submitterId ≠ voider).
  • Invalidar: el invalidador no puede ser el aprobador original (approverId ≠ invalidater).

Un cliente que llame al endpoint directamente —saltándose el UI— recibe 403.

La revisión se hace en la cola de aprobación del supervisor (/lab/approval), donde cada muestra SUBMITTED se aprueba o se rechaza en línea.

Captura pendiente — requiere sembrar datos

La captura disponible de /lab/approval no ilustra de forma fiable la feature (la cola de aprobación con muestras SUBMITTED reales). Para documentarla con datos se debe sembrar datos: enviar una muestra como técnico y volver a capturar la cola como supervisor (superficie: /lab/approval cola con muestras SUBMITTED). Pendiente del barrido diferido — ver 61-DEFERRED-SWEEP.md (LAB-08).

VOIDED vs INVALIDATED

Una muestra aprobada se retira por dos vías terminales distintas —no son sinónimos—:

Estado terminalAcciónSignificadoAutoridad
VOIDEDAnularAnulación administrativa de una muestra aprobada (se requiere reasonCode + reasonText opcional).lab:void (supervisor)
INVALIDATEDInvalidarLos datos de laboratorio resultaron erróneos — la muestra estaba mal, no se trata de una decisión administrativa.lab:invalidate

La distinción importa para la auditoría: VOIDED dice "esta muestra ya no aplica"; INVALIDATED dice "esta muestra nunca debió usarse porque sus números eran incorrectos".

Proyección de propiedades

Aquí es donde el laboratorio se conecta con el cálculo custody. Cuando una muestra llega a APPROVED, sus propiedades se proyectan a la snapshot del tanque: la densidad y el BSW quedan disponibles para el motor de cálculo sin re-consultar la muestra.

Solo las muestras APPROVED alimentan el cálculo

Los resolvedores resolveDensity y resolveBsw solo consideran muestras en estado APPROVED. Una muestra en DRAFT, SUBMITTED, REJECTED, VOIDED o INVALIDATED no influye en ningún factor custody. Así, el valor de densidad o BSW que se ve en el detalle de tanque siempre proviene de una muestra revisada y aprobada — y la ProvenanceTable de esa pantalla muestra exactamente de qué muestra salió.

Workspace y modos de la muestra

El workspace de laboratorio (/lab) organiza las muestras en 5 pestañas (la pestaña activa persiste en localStorage): Borradores, En revisión (pending), Rechazadas, Aprobadas y Anuladas e invalidadas (terminal). El CTA "Nueva muestra" solo aparece para quien tiene lab:submit.

Workspace de muestras de laboratorio con sus 5 pestañas

El detalle de una muestra (/lab/[sampleId]) cambia de modo según su estado:

EstadoModo del detalle
DRAFTEdición
REJECTEDRework (corregir y reenviar)
SUBMITTED · APPROVED · VOIDED · INVALIDATEDSolo lectura

Cada detalle muestra el ID en mono, el LabStateBadge de estado y el bloque de rastro de auditoría.

Captura pendiente

Screenshot pendiente del barrido diferido — ver 61-DEFERRED-SWEEP.md (/lab/[sampleId] modos edit / rework / readonly).

Historial por tanque

/lab/history/[tankId] presenta el timeline cronológico descendente de todas las muestras de un tanque, con estilo receipt en mono fixed-grid y chips de supersedes (hacia adelante y hacia atrás). Es de solo lectura, sin acciones.

Captura pendiente

Screenshot pendiente del barrido diferido — ver 61-DEFERRED-SWEEP.md (/lab/history timeline).

Páginas relacionadas

  • Los aforos manuales del operador —la lectura física de nivel/temperatura/agua libre— se documentan en Aforos manuales.
  • Para ver dónde se consumen la densidad y el BSW aprobados (los factores custody y su procedencia), ver el detalle de tanque.
  • El rastro de auditoría completo de las acciones de laboratorio se cubrirá en la guía de auditoría (próximamente).