- 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>
91 lines
2.8 KiB
PHP
91 lines
2.8 KiB
PHP
<?php
|
|
/**
|
|
* Funciones auxiliares compartidas por el ETL
|
|
*/
|
|
|
|
/**
|
|
* Convierte un string de WIN1252 a UTF-8.
|
|
* Si el valor ya es UTF-8 válido, lo devuelve sin cambios.
|
|
*/
|
|
function toUtf8(?string $val, string $srcEncoding = 'WIN1252'): ?string {
|
|
if ($val === null) return null;
|
|
if (mb_check_encoding($val, 'UTF-8')) return $val;
|
|
return iconv($srcEncoding, 'UTF-8//TRANSLIT//IGNORE', $val);
|
|
}
|
|
|
|
/**
|
|
* Convierte un array completo de strings (resultado de Firebird) a UTF-8.
|
|
*/
|
|
function rowToUtf8(array $row, string $srcEncoding = 'WIN1252'): array {
|
|
foreach ($row as $k => $v) {
|
|
if (is_string($v)) {
|
|
$row[$k] = toUtf8($v, $srcEncoding);
|
|
}
|
|
}
|
|
return $row;
|
|
}
|
|
|
|
/**
|
|
* Limpia un VARCHAR de Firebird: recorta espacios y convierte encoding.
|
|
*/
|
|
function cleanStr(?string $val, string $srcEncoding = 'WIN1252'): ?string {
|
|
if ($val === null) return null;
|
|
$val = trim(toUtf8($val, $srcEncoding) ?? '');
|
|
return $val === '' ? null : $val;
|
|
}
|
|
|
|
/**
|
|
* Convierte fecha Firebird (puede ser DATE o string 'YYYY-MM-DD') a MySQL DATE.
|
|
* Devuelve null si la fecha es inválida o vacía.
|
|
*/
|
|
function fbDate($val): ?string {
|
|
if ($val === null) return null;
|
|
if ($val instanceof DateTime) return $val->format('Y-m-d');
|
|
$str = trim((string)$val);
|
|
if ($str === '' || $str === '0000-00-00') return null;
|
|
try {
|
|
return (new DateTime($str))->format('Y-m-d');
|
|
} catch (\Exception $e) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* INSERT en batch.
|
|
* $pdo → conexión MySQL
|
|
* $table → nombre de la tabla
|
|
* $rows → array de arrays asociativos con los mismos keys
|
|
* $ignore → usa INSERT IGNORE para saltar duplicados
|
|
*/
|
|
function batchInsert(PDO $pdo, string $table, array $rows, bool $ignore = false): int {
|
|
if (empty($rows)) return 0;
|
|
|
|
$cols = array_keys($rows[0]);
|
|
$colList = implode(', ', array_map(fn($c) => "`$c`", $cols));
|
|
$phRow = '(' . implode(', ', array_fill(0, count($cols), '?')) . ')';
|
|
|
|
$inserted = 0;
|
|
foreach (array_chunk($rows, 500) as $chunk) {
|
|
$placeholders = implode(', ', array_fill(0, count($chunk), $phRow));
|
|
$keyword = $ignore ? 'INSERT IGNORE' : 'INSERT';
|
|
$sql = "$keyword INTO `$table` ($colList) VALUES $placeholders";
|
|
$flat = array_merge(...array_map('array_values', $chunk));
|
|
$stmt = $pdo->prepare($sql);
|
|
$stmt->execute($flat);
|
|
$inserted += $stmt->rowCount();
|
|
}
|
|
return $inserted;
|
|
}
|
|
|
|
/** Escribe al log y a stdout simultáneamente. */
|
|
function etlLog(string $msg, $logFp = null): void {
|
|
$line = '[' . date('H:i:s') . '] ' . $msg . PHP_EOL;
|
|
echo $line;
|
|
if ($logFp) fwrite($logFp, $line);
|
|
}
|
|
|
|
/** Devuelve conteo de filas de una tabla Firebird. */
|
|
function fbCount(PDO $fb, string $table): int {
|
|
return (int) $fb->query("SELECT COUNT(*) FROM $table")->fetchColumn();
|
|
}
|