Files
whatsapp/migrations/etl/helpers.php
Lizandro GuarnizoandClaude Sonnet 4.6 5fedd233f4 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>
2026-07-04 21:44:22 -05:00

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();
}