feat(lis): migración completa Firebird→MySQL + tracking de muestras en turnero
- Migraciones LIS 01-08: schema completo del nuevo LIS (secciones, protocolos, ítems de resultado, perfiles, tarifas, empresas, histórico transaccional) - ETL Firebird→MySQL: script CLI con conversión WIN1252→UTF-8, batches de 500, resolución de FKs y deduplicación de pacientes - turnero_muestras: tracking pendiente/recibida/rechazada por tipo de tubo - lugar.php: widget de recepción de muestras (solo tipo=muestras) - update_muestra_estado.php: API para marcar estado de muestra - create_solicitud.php: auto-crea muestras al guardar solicitud - get_consentimientos.php: incluye muestras[] en el response - 6 vistas SQL: v_muestras_hoy, v_recepcion_completa, v_examen_precio, etc. - numero_orden en encabezado del formulario firmado (D-/F- color diferenciado) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
86ed70db34
commit
5fedd233f4
@@ -166,6 +166,30 @@ try {
|
||||
}
|
||||
unset($c);
|
||||
|
||||
// ── Auto-crear muestras por tipo_muestra de los exámenes ──
|
||||
try {
|
||||
if (!$soloMuestras && !empty($examIds)) {
|
||||
$ph = implode(',', array_fill(0, count($examIds), '?'));
|
||||
$stmtTm = $pdo->prepare(
|
||||
"SELECT DISTINCT COALESCE(NULLIF(TRIM(tipo_muestra),''), codigo) AS tipo_key
|
||||
FROM exam_tipos WHERE id IN ($ph) AND activo = 1"
|
||||
);
|
||||
$stmtTm->execute($examIds);
|
||||
$stmtIm = $pdo->prepare(
|
||||
"INSERT IGNORE INTO turnero_muestras (solicitud_id, tipo_muestra) VALUES (?, ?)"
|
||||
);
|
||||
foreach ($stmtTm->fetchAll(PDO::FETCH_COLUMN) as $tipoKey) {
|
||||
$stmtIm->execute([$solicitudId, $tipoKey]);
|
||||
}
|
||||
} elseif ($soloMuestras) {
|
||||
$pdo->prepare(
|
||||
"INSERT IGNORE INTO turnero_muestras (solicitud_id, tipo_muestra) VALUES (?, 'MUESTRA')"
|
||||
)->execute([$solicitudId]);
|
||||
}
|
||||
} catch (\Throwable $_) {
|
||||
// Tabla aún no existe (migración pendiente) — continuar sin muestras
|
||||
}
|
||||
|
||||
$pdo->commit();
|
||||
notificarSSE(obtenerOCrearSesionHoy());
|
||||
|
||||
|
||||
@@ -217,9 +217,29 @@ if ($incluirSolicitud) {
|
||||
}
|
||||
}
|
||||
|
||||
// Muestras pendientes / recibidas del turno
|
||||
$muestras = [];
|
||||
if ($solicitud) {
|
||||
try {
|
||||
$stmtM = $pdo->prepare(
|
||||
"SELECT tm.id, tm.tipo_muestra, tm.estado, tm.motivo_rechazo, tm.recibida_at,
|
||||
COALESCE(lt.nombre, tm.tipo_muestra) AS label
|
||||
FROM turnero_muestras tm
|
||||
LEFT JOIN lab_tipos_muestra lt ON lt.codigo = tm.tipo_muestra
|
||||
WHERE tm.solicitud_id = ?
|
||||
ORDER BY tm.id ASC"
|
||||
);
|
||||
$stmtM->execute([$solicitud['id']]);
|
||||
$muestras = $stmtM->fetchAll(PDO::FETCH_ASSOC);
|
||||
} catch (\Throwable $_) {
|
||||
// Tabla aún no existe
|
||||
}
|
||||
}
|
||||
|
||||
$respuesta['solicitud'] = $solicitud;
|
||||
$respuesta['paciente'] = $paciente;
|
||||
$respuesta['examenes'] = $examenes;
|
||||
$respuesta['muestras'] = $muestras;
|
||||
}
|
||||
|
||||
jsonOk($respuesta);
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/**
|
||||
* POST /modules/turnero/api/update_muestra_estado.php
|
||||
* Marca una muestra como recibida o rechazada.
|
||||
* Solo accesible desde estaciones tipo "muestras".
|
||||
*
|
||||
* Body JSON:
|
||||
* muestra_id int requerido
|
||||
* estado string requerido 'recibida' | 'rechazada' | 'pendiente'
|
||||
* motivo_rechazo string opcional requerido si estado = 'rechazada'
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/_helpers.php';
|
||||
requireMethod('POST');
|
||||
requireTurnero();
|
||||
|
||||
$datos = inputJson();
|
||||
$muestraId = isset($datos['muestra_id']) ? (int)$datos['muestra_id'] : 0;
|
||||
$estado = trim($datos['estado'] ?? '');
|
||||
$motivo = isset($datos['motivo_rechazo']) ? trim($datos['motivo_rechazo']) : null;
|
||||
|
||||
if ($muestraId <= 0) jsonError('muestra_id inválido.');
|
||||
if (!in_array($estado, ['recibida', 'rechazada', 'pendiente'], true)) {
|
||||
jsonError('estado debe ser recibida, rechazada o pendiente.');
|
||||
}
|
||||
if ($motivo === '') $motivo = null;
|
||||
|
||||
$pdo = db();
|
||||
|
||||
// Verificar que la muestra existe
|
||||
$stmt = $pdo->prepare(
|
||||
"SELECT tm.id, tm.solicitud_id, tm.estado
|
||||
FROM turnero_muestras tm
|
||||
WHERE tm.id = ?"
|
||||
);
|
||||
$stmt->execute([$muestraId]);
|
||||
$muestra = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$muestra) jsonError('Muestra no encontrada.', 404);
|
||||
|
||||
// Construir campos a actualizar
|
||||
$ahora = date('Y-m-d H:i:s');
|
||||
$adminI = adminId();
|
||||
|
||||
if ($estado === 'recibida') {
|
||||
$pdo->prepare(
|
||||
"UPDATE turnero_muestras
|
||||
SET estado = 'recibida', recibida_por = ?, recibida_at = ?,
|
||||
motivo_rechazo = NULL
|
||||
WHERE id = ?"
|
||||
)->execute([$adminI, $ahora, $muestraId]);
|
||||
} elseif ($estado === 'rechazada') {
|
||||
$pdo->prepare(
|
||||
"UPDATE turnero_muestras
|
||||
SET estado = 'rechazada', recibida_por = ?, recibida_at = ?,
|
||||
motivo_rechazo = ?
|
||||
WHERE id = ?"
|
||||
)->execute([$adminI, $ahora, $motivo, $muestraId]);
|
||||
} else {
|
||||
// Revertir a pendiente
|
||||
$pdo->prepare(
|
||||
"UPDATE turnero_muestras
|
||||
SET estado = 'pendiente', recibida_por = NULL,
|
||||
recibida_at = NULL, motivo_rechazo = NULL
|
||||
WHERE id = ?"
|
||||
)->execute([$muestraId]);
|
||||
}
|
||||
|
||||
jsonOk(['muestra_id' => $muestraId, 'estado' => $estado], 'Muestra actualizada');
|
||||
Reference in New Issue
Block a user