Files
whatsapp/modules/turnero/api/get_precios_examenes.php
T
Lizandro GuarnizoandClaude Sonnet 4.6 a7aac706ee feat(recepcion): motor de precios + selector empresa/convenio
- Nueva sección empresa/convenio en recepcion.php: búsqueda live por
  nombre/NIT, selector de subgrupo, campo autorización (cuando req_autoriza),
  diagnóstico CIE-10
- Tabla de precios calculados en tiempo real: resolución por tarifa de la
  empresa o subgrupo, descuento empresa aplicado, botón "Aplicar al cobro"
- Al agregar/quitar exámenes o cambiar empresa/subgrupo se recalcula automáticamente
- Nuevo API get_precios_examenes.php: resuelve precios desde lab_tarifas
  con soporte de tarifas derivadas por porcentaje
- create_solicitud.php guarda nit_empresa, subgrupo_id, autorizacion,
  diag_ppal, items_precio (snapshot JSON al momento de la recepción)
- Migración 10: ALTER turnero_solicitudes añade los 5 campos nuevos

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-04 22:09:26 -05:00

150 lines
5.1 KiB
PHP

<?php
/**
* GET /modules/turnero/api/get_precios_examenes.php
*
* Calcula precios de exámenes según empresa/tarifa.
*
* Query params:
* exam_ids[] int[] IDs de exam_tipos
* nit_empresa string opcional
* subgrupo_id int opcional
*
* Response:
* items[] { exam_tipo_id, codigo, nombre, valor_base, valor_final, tiene_precio }
* subtotal precio antes de descuento empresa
* descuento_pct porcentaje de descuento empresa
* descuento_val valor del descuento
* total total a cobrar
* tarifa_id tarifa aplicada
* tarifa_nombre nombre de la tarifa
*/
require_once __DIR__ . '/_helpers.php';
requireMethod('GET');
$examIds = array_filter(array_map('intval', (array)($_GET['exam_ids'] ?? [])));
$nitEmpresa = trim($_GET['nit_empresa'] ?? '');
$subgrupoId = (int)($_GET['subgrupo_id'] ?? 0);
if (empty($examIds)) jsonOk([
'items' => [],
'subtotal' => 0,
'descuento_pct' => 0,
'descuento_val' => 0,
'total' => 0,
'tarifa_id' => null,
'tarifa_nombre' => null,
]);
$pdo = db();
// ── Resolver tarifa efectiva ───────────────────────────────────
$tarifaId = null;
$tarifaNombre = null;
$descuentoPct = 0;
if ($nitEmpresa !== '') {
$stmtE = $pdo->prepare(
"SELECT e.tarifa_id, e.descuento_pct, ti.nombre AS tarifa_nombre
FROM lab_empresas e
LEFT JOIN lab_tarifas_id ti ON ti.id = e.tarifa_id
WHERE e.nit = ?"
);
$stmtE->execute([$nitEmpresa]);
$empresa = $stmtE->fetch(PDO::FETCH_ASSOC);
if ($empresa) {
$tarifaId = $empresa['tarifa_id'];
$tarifaNombre = $empresa['tarifa_nombre'];
$descuentoPct = (float)$empresa['descuento_pct'];
// Si el subgrupo tiene tarifa propia, override
if ($subgrupoId > 0) {
$stmtS = $pdo->prepare(
"SELECT es.tarifa_id, ti.nombre AS tarifa_nombre
FROM lab_empresa_subgrupos es
LEFT JOIN lab_tarifas_id ti ON ti.id = es.tarifa_id
WHERE es.id = ? AND es.nit_empresa = ? AND es.tarifa_id IS NOT NULL"
);
$stmtS->execute([$subgrupoId, $nitEmpresa]);
$sub = $stmtS->fetch(PDO::FETCH_ASSOC);
if ($sub) {
$tarifaId = $sub['tarifa_id'];
$tarifaNombre = $sub['tarifa_nombre'];
}
}
}
}
// ── Obtener nombre/codigo de los exámenes ─────────────────────
$ph = implode(',', array_fill(0, count($examIds), '?'));
$stmtX = $pdo->prepare(
"SELECT id AS exam_tipo_id, codigo, nombre FROM exam_tipos WHERE id IN ($ph)"
);
$stmtX->execute($examIds);
$examMap = [];
foreach ($stmtX->fetchAll(PDO::FETCH_ASSOC) as $r) {
$examMap[(int)$r['exam_tipo_id']] = $r;
}
// ── Obtener precios desde lab_tarifas (con derivación por %) ──
$items = [];
$subtotal = 0;
foreach ($examIds as $examId) {
$examen = $examMap[$examId] ?? ['codigo' => '?', 'nombre' => 'Desconocido'];
$valorFinal = null;
$valorBase = null;
$tienePrecio = false;
if ($tarifaId !== null) {
// Intentar precio en la tarifa exacta
$stmtP = $pdo->prepare(
"SELECT lt.valor, ti.porcentaje, ti.tarifa_origen,
lt_base.valor AS valor_origen
FROM lab_tarifas lt
JOIN lab_tarifas_id ti ON ti.id = lt.tarifa_id
LEFT JOIN lab_tarifas lt_base ON lt_base.exam_tipo_id = lt.exam_tipo_id
AND lt_base.tarifa_id = ti.tarifa_origen
WHERE lt.exam_tipo_id = ? AND lt.tarifa_id = ?"
);
$stmtP->execute([$examId, $tarifaId]);
$precio = $stmtP->fetch(PDO::FETCH_ASSOC);
if ($precio) {
$tienePrecio = true;
$valorBase = (float)$precio['valor'];
if ((float)$precio['porcentaje'] > 0 && $precio['tarifa_origen'] && $precio['valor_origen'] !== null) {
$valorFinal = round((float)$precio['valor_origen'] * (1 + (float)$precio['porcentaje'] / 100), 0);
} else {
$valorFinal = $valorBase;
}
}
}
// Si no hay precio, dejar null (sin tarifa o sin mapeo)
$subtotal += $valorFinal ?? 0;
$items[] = [
'exam_tipo_id' => $examId,
'codigo' => $examen['codigo'],
'nombre' => $examen['nombre'],
'valor_base' => $valorBase,
'valor_final' => $valorFinal,
'tiene_precio' => $tienePrecio,
];
}
// ── Aplicar descuento empresa ─────────────────────────────────
$descuentoVal = round($subtotal * $descuentoPct / 100, 0);
$total = $subtotal - $descuentoVal;
jsonOk([
'items' => $items,
'subtotal' => $subtotal,
'descuento_pct' => $descuentoPct,
'descuento_val' => $descuentoVal,
'total' => $total,
'tarifa_id' => $tarifaId,
'tarifa_nombre' => $tarifaNombre,
]);