feat(lab_empresas): módulo CRUD de empresas, convenios y tarifas
- Nuevo módulo lab_empresas: lista paginada, modal create/edit empresa, gestión de subgrupos inline y CRUD de catálogo lab_tarifas_id - APIs: empresas.php (list/get/save/toggle/delete), empresa_subgrupos.php, tarifas_id.php - Migración 09 registra el módulo en system_modules y asigna permiso admin Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
5fedd233f4
commit
b9bb4fc628
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/**
|
||||
* /api/lab/empresa_subgrupos.php
|
||||
*
|
||||
* GET ?nit_empresa= → subgrupos de la empresa
|
||||
* POST {action:save, ...} → upsert subgrupo
|
||||
* POST {action:delete, id} → elimina subgrupo
|
||||
*/
|
||||
require_once __DIR__ . '/_helpers.php';
|
||||
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
|
||||
if ($method === 'GET') {
|
||||
$nit = trim($_GET['nit_empresa'] ?? '');
|
||||
if ($nit === '') jsonError('nit_empresa requerido');
|
||||
$pdo = db();
|
||||
$s = $pdo->prepare(
|
||||
"SELECT es.*, ti.nombre AS tarifa_nombre
|
||||
FROM lab_empresa_subgrupos es
|
||||
LEFT JOIN lab_tarifas_id ti ON ti.id = es.tarifa_id
|
||||
WHERE es.nit_empresa = ?
|
||||
ORDER BY es.subgrupo ASC"
|
||||
);
|
||||
$s->execute([$nit]);
|
||||
jsonOk(['subgrupos' => $s->fetchAll(PDO::FETCH_ASSOC)]);
|
||||
}
|
||||
|
||||
requireMethod('POST');
|
||||
$data = json_decode(file_get_contents('php://input'), true) ?? [];
|
||||
$action = $data['action'] ?? '';
|
||||
$pdo = db();
|
||||
|
||||
if ($action === 'delete') {
|
||||
$id = (int)($data['id'] ?? 0);
|
||||
if ($id <= 0) jsonError('id requerido');
|
||||
$pdo->prepare("DELETE FROM lab_empresa_subgrupos WHERE id = ?")->execute([$id]);
|
||||
jsonOk(['deleted' => true]);
|
||||
}
|
||||
|
||||
if ($action === 'save') {
|
||||
$id = (int)($data['id'] ?? 0);
|
||||
$nitEmpresa = trim($data['nit_empresa'] ?? '');
|
||||
$subgrupo = trim($data['subgrupo'] ?? '');
|
||||
if ($nitEmpresa === '') jsonError('nit_empresa requerido');
|
||||
if ($subgrupo === '') jsonError('subgrupo requerido');
|
||||
|
||||
$tarifaId = isset($data['tarifa_id']) && $data['tarifa_id'] !== '' ? (int)$data['tarifa_id'] : null;
|
||||
$refSub = trim($data['ref_subgrupo'] ?? '') ?: null;
|
||||
$codCon = trim($data['cod_contrato'] ?? '') ?: null;
|
||||
|
||||
if ($id > 0) {
|
||||
$pdo->prepare(
|
||||
"UPDATE lab_empresa_subgrupos
|
||||
SET subgrupo=?, tarifa_id=?, ref_subgrupo=?, cod_contrato=?
|
||||
WHERE id=? AND nit_empresa=?"
|
||||
)->execute([$subgrupo, $tarifaId, $refSub, $codCon, $id, $nitEmpresa]);
|
||||
} else {
|
||||
$pdo->prepare(
|
||||
"INSERT INTO lab_empresa_subgrupos (nit_empresa, subgrupo, tarifa_id, ref_subgrupo, cod_contrato)
|
||||
VALUES (?, ?, ?, ?, ?)"
|
||||
)->execute([$nitEmpresa, $subgrupo, $tarifaId, $refSub, $codCon]);
|
||||
$id = (int)$pdo->lastInsertId();
|
||||
}
|
||||
jsonOk(['id' => $id]);
|
||||
}
|
||||
|
||||
jsonError('Acción no reconocida', 400);
|
||||
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
/**
|
||||
* /api/lab/empresas.php
|
||||
*
|
||||
* GET ?action=list [search, activa, page, limit] → lista paginada
|
||||
* GET ?action=get &nit= → empresa + subgrupos
|
||||
* POST {action:save, nit, nombre, ...} → upsert empresa
|
||||
* POST {action:toggle, nit} → activa/inactiva
|
||||
* POST {action:delete, nit} → elimina (si sin recepciones)
|
||||
*/
|
||||
require_once __DIR__ . '/_helpers.php';
|
||||
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
|
||||
// ─── GET ─────────────────────────────────────────────────────────────────────
|
||||
if ($method === 'GET') {
|
||||
$action = $_GET['action'] ?? 'list';
|
||||
$pdo = db();
|
||||
|
||||
if ($action === 'get') {
|
||||
$nit = trim($_GET['nit'] ?? '');
|
||||
if ($nit === '') jsonError('nit requerido');
|
||||
|
||||
$e = $pdo->prepare(
|
||||
"SELECT e.*, ti.nombre AS tarifa_nombre
|
||||
FROM lab_empresas e
|
||||
LEFT JOIN lab_tarifas_id ti ON ti.id = e.tarifa_id
|
||||
WHERE e.nit = ?"
|
||||
);
|
||||
$e->execute([$nit]);
|
||||
$empresa = $e->fetch(PDO::FETCH_ASSOC);
|
||||
if (!$empresa) jsonError('Empresa no encontrada', 404);
|
||||
|
||||
$s = $pdo->prepare(
|
||||
"SELECT es.*, ti.nombre AS tarifa_nombre
|
||||
FROM lab_empresa_subgrupos es
|
||||
LEFT JOIN lab_tarifas_id ti ON ti.id = es.tarifa_id
|
||||
WHERE es.nit_empresa = ?
|
||||
ORDER BY es.subgrupo ASC"
|
||||
);
|
||||
$s->execute([$nit]);
|
||||
$empresa['subgrupos'] = $s->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
jsonOk(['empresa' => $empresa]);
|
||||
}
|
||||
|
||||
// list
|
||||
$search = trim($_GET['search'] ?? '');
|
||||
$activa = isset($_GET['activa']) && $_GET['activa'] !== '' ? (int)$_GET['activa'] : null;
|
||||
$page = max(1, (int)($_GET['page'] ?? 1));
|
||||
$limit = max(1, min(100, (int)($_GET['limit'] ?? 30)));
|
||||
$offset = ($page - 1) * $limit;
|
||||
|
||||
$where = [];
|
||||
$params = [];
|
||||
if ($search !== '') {
|
||||
$where[] = '(e.nombre LIKE ? OR e.nit LIKE ? OR e.razon_social LIKE ?)';
|
||||
$like = "%{$search}%";
|
||||
$params[] = $like; $params[] = $like; $params[] = $like;
|
||||
}
|
||||
if ($activa !== null) {
|
||||
$where[] = 'e.activa = ?';
|
||||
$params[] = $activa;
|
||||
}
|
||||
|
||||
$wSql = $where ? 'WHERE ' . implode(' AND ', $where) : '';
|
||||
|
||||
$total = $pdo->prepare("SELECT COUNT(*) FROM lab_empresas e $wSql");
|
||||
$total->execute($params);
|
||||
$totalRows = (int)$total->fetchColumn();
|
||||
|
||||
$rows = $pdo->prepare(
|
||||
"SELECT e.nit, e.nombre, e.razon_social, e.tarifa_id, ti.nombre AS tarifa_nombre,
|
||||
e.descuento_pct, e.codigo_eps, e.tipo_usuario, e.req_autoriza, e.activa,
|
||||
(SELECT COUNT(*) FROM lab_empresa_subgrupos es WHERE es.nit_empresa = e.nit) AS total_subgrupos
|
||||
FROM lab_empresas e
|
||||
LEFT JOIN lab_tarifas_id ti ON ti.id = e.tarifa_id
|
||||
$wSql
|
||||
ORDER BY e.nombre ASC
|
||||
LIMIT $limit OFFSET $offset"
|
||||
);
|
||||
$rows->execute($params);
|
||||
|
||||
jsonOk([
|
||||
'empresas' => $rows->fetchAll(PDO::FETCH_ASSOC),
|
||||
'total' => $totalRows,
|
||||
'page' => $page,
|
||||
'limit' => $limit,
|
||||
'pages' => (int)ceil($totalRows / $limit),
|
||||
]);
|
||||
}
|
||||
|
||||
// ─── POST ────────────────────────────────────────────────────────────────────
|
||||
requireMethod('POST');
|
||||
$data = json_decode(file_get_contents('php://input'), true) ?? [];
|
||||
$action = $data['action'] ?? '';
|
||||
$pdo = db();
|
||||
|
||||
if ($action === 'toggle') {
|
||||
$nit = trim($data['nit'] ?? '');
|
||||
if ($nit === '') jsonError('nit requerido');
|
||||
$pdo->prepare("UPDATE lab_empresas SET activa = 1 - activa WHERE nit = ?")->execute([$nit]);
|
||||
$activa = (int)$pdo->prepare("SELECT activa FROM lab_empresas WHERE nit=?")->execute([$nit]);
|
||||
$row = $pdo->prepare("SELECT activa FROM lab_empresas WHERE nit=?");
|
||||
$row->execute([$nit]);
|
||||
jsonOk(['activa' => (bool)(int)$row->fetchColumn()]);
|
||||
}
|
||||
|
||||
if ($action === 'delete') {
|
||||
$nit = trim($data['nit'] ?? '');
|
||||
if ($nit === '') jsonError('nit requerido');
|
||||
// Block deletion if empresa has recepciones (historical)
|
||||
$chk = $pdo->prepare("SELECT COUNT(*) FROM lab_recepciones WHERE nit_empresa = ? LIMIT 1");
|
||||
$chk->execute([$nit]);
|
||||
if ((int)$chk->fetchColumn() > 0) {
|
||||
jsonError('No se puede eliminar: la empresa tiene recepciones históricas registradas.', 409);
|
||||
}
|
||||
$pdo->prepare("DELETE FROM lab_empresas WHERE nit = ?")->execute([$nit]);
|
||||
jsonOk(['deleted' => true]);
|
||||
}
|
||||
|
||||
if ($action === 'save') {
|
||||
$nit = trim($data['nit'] ?? '');
|
||||
$nombre = trim($data['nombre'] ?? '');
|
||||
if ($nit === '') jsonError('El NIT es obligatorio');
|
||||
if ($nombre === '') jsonError('El nombre es obligatorio');
|
||||
|
||||
$fields = [
|
||||
'nombre' => $nombre,
|
||||
'razon_social' => trim($data['razon_social'] ?? '') ?: null,
|
||||
'tarifa_id' => isset($data['tarifa_id']) && $data['tarifa_id'] !== '' ? (int)$data['tarifa_id'] : null,
|
||||
'descuento_pct' => isset($data['descuento_pct']) ? (float)$data['descuento_pct'] : 0,
|
||||
'codigo_eps' => trim($data['codigo_eps'] ?? '') ?: null,
|
||||
'tipo_usuario' => trim($data['tipo_usuario'] ?? '') ?: null,
|
||||
'tipo_usuario_sispro'=> trim($data['tipo_usuario_sispro']?? '') ?: null,
|
||||
'cod_contrato' => trim($data['cod_contrato'] ?? '') ?: null,
|
||||
'cod_tercero' => trim($data['cod_tercero'] ?? '') ?: null,
|
||||
'centro_costo' => trim($data['centro_costo'] ?? '') ?: null,
|
||||
'req_autoriza' => isset($data['req_autoriza']) ? (int)(bool)$data['req_autoriza'] : 0,
|
||||
'activa' => isset($data['activa']) ? (int)(bool)$data['activa'] : 1,
|
||||
];
|
||||
|
||||
// Check if exists
|
||||
$exists = $pdo->prepare("SELECT nit FROM lab_empresas WHERE nit = ?");
|
||||
$exists->execute([$nit]);
|
||||
$isNew = !$exists->fetch();
|
||||
|
||||
if ($isNew) {
|
||||
$cols = implode(', ', array_map(fn($k) => "`$k`", array_keys($fields)));
|
||||
$ph = implode(', ', array_fill(0, count($fields), '?'));
|
||||
$pdo->prepare("INSERT INTO lab_empresas (nit, $cols) VALUES (?, $ph)")
|
||||
->execute(array_merge([$nit], array_values($fields)));
|
||||
} else {
|
||||
$sets = implode(', ', array_map(fn($k) => "`$k` = ?", array_keys($fields)));
|
||||
$pdo->prepare("UPDATE lab_empresas SET $sets WHERE nit = ?")
|
||||
->execute(array_merge(array_values($fields), [$nit]));
|
||||
}
|
||||
|
||||
jsonOk(['nit' => $nit, 'created' => $isNew]);
|
||||
}
|
||||
|
||||
jsonError('Acción no reconocida', 400);
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
/**
|
||||
* /api/lab/tarifas_id.php
|
||||
*
|
||||
* GET → lista todas las tarifas (para selects en formularios)
|
||||
* POST {action:save, id?, nombre, porcentaje, tarifa_origen?} → upsert
|
||||
* POST {action:delete, id} → elimina si sin precios asociados
|
||||
*/
|
||||
require_once __DIR__ . '/_helpers.php';
|
||||
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
$pdo = db();
|
||||
|
||||
if ($method === 'GET') {
|
||||
$rows = $pdo->query(
|
||||
"SELECT t.id, t.nombre, t.porcentaje, t.tarifa_origen,
|
||||
tb.nombre AS tarifa_origen_nombre
|
||||
FROM lab_tarifas_id t
|
||||
LEFT JOIN lab_tarifas_id tb ON tb.id = t.tarifa_origen
|
||||
ORDER BY t.id ASC"
|
||||
)->fetchAll(PDO::FETCH_ASSOC);
|
||||
jsonOk(['tarifas' => $rows]);
|
||||
}
|
||||
|
||||
requireMethod('POST');
|
||||
$data = json_decode(file_get_contents('php://input'), true) ?? [];
|
||||
$action = $data['action'] ?? '';
|
||||
|
||||
if ($action === 'delete') {
|
||||
$id = (int)($data['id'] ?? 0);
|
||||
if ($id <= 0) jsonError('id requerido');
|
||||
$chk = $pdo->prepare("SELECT COUNT(*) FROM lab_tarifas WHERE tarifa_id = ? LIMIT 1");
|
||||
$chk->execute([$id]);
|
||||
if ((int)$chk->fetchColumn() > 0) {
|
||||
jsonError('No se puede eliminar: la tarifa tiene precios de exámenes asociados.', 409);
|
||||
}
|
||||
$pdo->prepare("DELETE FROM lab_tarifas_id WHERE id = ?")->execute([$id]);
|
||||
jsonOk(['deleted' => true]);
|
||||
}
|
||||
|
||||
if ($action === 'save') {
|
||||
$id = isset($data['id']) && $data['id'] !== '' ? (int)$data['id'] : null;
|
||||
$nombre = trim($data['nombre'] ?? '');
|
||||
$porcentaje = isset($data['porcentaje']) ? (float)$data['porcentaje'] : 0;
|
||||
$origen = isset($data['tarifa_origen']) && $data['tarifa_origen'] !== '' ? (int)$data['tarifa_origen'] : null;
|
||||
|
||||
if ($nombre === '') jsonError('nombre requerido');
|
||||
|
||||
if ($id !== null) {
|
||||
$chk = $pdo->prepare("SELECT id FROM lab_tarifas_id WHERE id = ?");
|
||||
$chk->execute([$id]);
|
||||
if ($chk->fetch()) {
|
||||
$pdo->prepare(
|
||||
"UPDATE lab_tarifas_id SET nombre=?, porcentaje=?, tarifa_origen=? WHERE id=?"
|
||||
)->execute([$nombre, $porcentaje, $origen, $id]);
|
||||
} else {
|
||||
$pdo->prepare(
|
||||
"INSERT INTO lab_tarifas_id (id, nombre, porcentaje, tarifa_origen) VALUES (?,?,?,?)"
|
||||
)->execute([$id, $nombre, $porcentaje, $origen]);
|
||||
}
|
||||
} else {
|
||||
$maxId = (int)$pdo->query("SELECT COALESCE(MAX(id),0)+1 FROM lab_tarifas_id")->fetchColumn();
|
||||
$pdo->prepare(
|
||||
"INSERT INTO lab_tarifas_id (id, nombre, porcentaje, tarifa_origen) VALUES (?,?,?,?)"
|
||||
)->execute([$maxId, $nombre, $porcentaje, $origen]);
|
||||
$id = $maxId;
|
||||
}
|
||||
jsonOk(['id' => $id]);
|
||||
}
|
||||
|
||||
jsonError('Acción no reconocida', 400);
|
||||
Reference in New Issue
Block a user