mas cambios 2
This commit is contained in:
parent
b8c258a963
commit
6ace09ec6c
@ -2539,7 +2539,11 @@ async function crearLibroAutorizacion(a) {
|
|||||||
sheet.mergeCells('O35:R35');
|
sheet.mergeCells('O35:R35');
|
||||||
sheet.mergeCells('B24:R24');
|
sheet.mergeCells('B24:R24');
|
||||||
sheet.mergeCells('B25:G30');
|
sheet.mergeCells('B25:G30');
|
||||||
sheet.mergeCells('H25:R29');
|
sheet.mergeCells('H25:R25');
|
||||||
|
sheet.mergeCells('H26:R26');
|
||||||
|
sheet.mergeCells('H27:R27');
|
||||||
|
sheet.mergeCells('H28:R28');
|
||||||
|
sheet.mergeCells('H29:R29');
|
||||||
sheet.mergeCells('H30:R30');
|
sheet.mergeCells('H30:R30');
|
||||||
sheet.mergeCells('B31:G32');
|
sheet.mergeCells('B31:G32');
|
||||||
sheet.mergeCells('H31:R31');
|
sheet.mergeCells('H31:R31');
|
||||||
@ -2658,6 +2662,32 @@ async function crearLibroAutorizacion(a) {
|
|||||||
.replace(/\s+/g, ' ')
|
.replace(/\s+/g, ' ')
|
||||||
.trim();
|
.trim();
|
||||||
|
|
||||||
|
const emptyIpsValues = new Set([
|
||||||
|
'NA',
|
||||||
|
'SD',
|
||||||
|
'SINDATO',
|
||||||
|
'SINDATOS',
|
||||||
|
'SININFO',
|
||||||
|
'SININFORMACION',
|
||||||
|
'NOAPLICA',
|
||||||
|
'NONE',
|
||||||
|
'NULL',
|
||||||
|
]);
|
||||||
|
|
||||||
|
const cleanIpsValue = (value) => {
|
||||||
|
const raw = String(value || '').trim();
|
||||||
|
if (!raw) return '';
|
||||||
|
const normalized = raw
|
||||||
|
.normalize('NFD')
|
||||||
|
.replace(/[\u0300-\u036f]/g, '')
|
||||||
|
.toUpperCase()
|
||||||
|
.replace(/[^A-Z0-9]/g, '');
|
||||||
|
if (!normalized || emptyIpsValues.has(normalized)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return raw;
|
||||||
|
};
|
||||||
|
|
||||||
// 1) Número de autorización (F8:I8)
|
// 1) Número de autorización (F8:I8)
|
||||||
['F8', 'G8', 'H8', 'I8'].forEach(celda => {
|
['F8', 'G8', 'H8', 'I8'].forEach(celda => {
|
||||||
sheet.getCell(celda).value = a.numero_autorizacion || '';
|
sheet.getCell(celda).value = a.numero_autorizacion || '';
|
||||||
@ -2692,12 +2722,12 @@ async function crearLibroAutorizacion(a) {
|
|||||||
sheet.getCell(celda).value = nombreIps;
|
sheet.getCell(celda).value = nombreIps;
|
||||||
});
|
});
|
||||||
|
|
||||||
const nitIps = a.nit || '';
|
const nitIps = cleanIpsValue(a.nit);
|
||||||
['D13', 'E13', 'F13', 'G13'].forEach(celda => {
|
['D13', 'E13', 'F13', 'G13'].forEach(celda => {
|
||||||
sheet.getCell(celda).value = nitIps;
|
sheet.getCell(celda).value = nitIps;
|
||||||
});
|
});
|
||||||
|
|
||||||
const telefonoIps = a.telefono_ips || '';
|
const telefonoIps = cleanIpsValue(a.telefono_ips);
|
||||||
['D14', 'E14', 'F14', 'G14', 'D15', 'E15', 'F15', 'G15', 'D16', 'E16', 'F16', 'G16'].forEach(celda => {
|
['D14', 'E14', 'F14', 'G14', 'D15', 'E15', 'F15', 'G15', 'D16', 'E16', 'F16', 'G16'].forEach(celda => {
|
||||||
sheet.getCell(celda).value = telefonoIps;
|
sheet.getCell(celda).value = telefonoIps;
|
||||||
});
|
});
|
||||||
@ -2710,8 +2740,9 @@ async function crearLibroAutorizacion(a) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 5) Dirección IPS (M16:N16)
|
// 5) Dirección IPS (M16:N16)
|
||||||
|
const direccionIps = cleanIpsValue(a.direccion);
|
||||||
['M13', 'N13','O13', 'P13','Q13', 'R13'].forEach(celda => {
|
['M13', 'N13','O13', 'P13','Q13', 'R13'].forEach(celda => {
|
||||||
sheet.getCell(celda).value = a.direccion || '';
|
sheet.getCell(celda).value = direccionIps;
|
||||||
});
|
});
|
||||||
|
|
||||||
['M23', 'N23','O23', 'P23','Q23', 'R23'].forEach(celda => {
|
['M23', 'N23','O23', 'P23','Q23', 'R23'].forEach(celda => {
|
||||||
@ -2719,12 +2750,12 @@ async function crearLibroAutorizacion(a) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
['M16', 'N16'].forEach(celda => {
|
['M16', 'N16'].forEach(celda => {
|
||||||
sheet.getCell(celda).value = a.municipio || '';
|
sheet.getCell(celda).value = cleanIpsValue(a.municipio);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 6) Departamento IPS (Q16:R16)
|
// 6) Departamento IPS (Q16:R16)
|
||||||
['Q16', 'R16'].forEach(celda => {
|
['Q16', 'R16'].forEach(celda => {
|
||||||
sheet.getCell(celda).value = a.departamento || '';
|
sheet.getCell(celda).value = cleanIpsValue(a.departamento);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 7) Nombre completo paciente (H18:R18)
|
// 7) Nombre completo paciente (H18:R18)
|
||||||
@ -2742,10 +2773,36 @@ async function crearLibroAutorizacion(a) {
|
|||||||
sheet.getCell(celda).value = a.numero_documento || '';
|
sheet.getCell(celda).value = a.numero_documento || '';
|
||||||
});
|
});
|
||||||
|
|
||||||
['H27','R27'].forEach(celda => {
|
['H29','R29'].forEach(celda => {
|
||||||
sheet.getCell(celda).value = a.nombre_establecimiento || '';
|
sheet.getCell(celda).value = a.nombre_establecimiento || '';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Tipo de servicio (consulta externa)
|
||||||
|
const servicioCols = ['H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R'];
|
||||||
|
const addBottomBorder = (row, style = 'thin') => {
|
||||||
|
servicioCols.forEach((col) => {
|
||||||
|
const cell = sheet.getCell(`${col}${row}`);
|
||||||
|
const border = cell.border || {};
|
||||||
|
cell.border = {
|
||||||
|
...border,
|
||||||
|
bottom: { style, color: { argb: 'FF000000' } },
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
sheet.getCell('B25').value = 'TIPO DE SERVICIO';
|
||||||
|
sheet.getCell('B25').alignment = {"horizontal":"center","vertical":"middle"};
|
||||||
|
sheet.getCell('H25').value = 'CONSULTA EXTERNA';
|
||||||
|
sheet.getCell('H25').alignment = {"horizontal":"center","vertical":"middle"};
|
||||||
|
sheet.getCell('H26').value = 'X';
|
||||||
|
sheet.getCell('H26').alignment = {"horizontal":"center","vertical":"middle"};
|
||||||
|
sheet.getCell('H27').value = '';
|
||||||
|
sheet.getCell('H27').alignment = {"horizontal":"center","vertical":"middle"};
|
||||||
|
sheet.getCell('H28').value = '';
|
||||||
|
sheet.getCell('H28').alignment = {"horizontal":"center","vertical":"middle"};
|
||||||
|
addBottomBorder(25);
|
||||||
|
addBottomBorder(26);
|
||||||
|
|
||||||
// 10) Observacion / servicios autorizados (H25:R25)
|
// 10) Observacion / servicios autorizados (H25:R25)
|
||||||
const cupCodigo = a.cup_codigo || '';
|
const cupCodigo = a.cup_codigo || '';
|
||||||
const cupDescripcion = a.cup_descripcion || '';
|
const cupDescripcion = a.cup_descripcion || '';
|
||||||
@ -2773,11 +2830,32 @@ async function crearLibroAutorizacion(a) {
|
|||||||
});
|
});
|
||||||
return partes.join(' | ');
|
return partes.join(' | ');
|
||||||
};
|
};
|
||||||
const observacionBase = limpiarObservacion(a.observacion || '');
|
const filtrarObservacionConsulta = (value) => {
|
||||||
|
const partes = String(value || '')
|
||||||
|
.split('|')
|
||||||
|
.map((parte) => parte.trim())
|
||||||
|
.filter(Boolean)
|
||||||
|
.filter((parte) => {
|
||||||
|
const lower = parte.toLowerCase();
|
||||||
|
return (
|
||||||
|
!lower.includes('solicitante') &&
|
||||||
|
!lower.includes('traslado a departamento')
|
||||||
|
);
|
||||||
|
});
|
||||||
|
return partes.join(' | ');
|
||||||
|
};
|
||||||
|
const esConsultaExterna =
|
||||||
|
String(a.tipo_autorizacion || '').toLowerCase() === 'consultas_externas';
|
||||||
|
let observacionBase = limpiarObservacion(a.observacion || '');
|
||||||
|
if (esConsultaExterna) {
|
||||||
|
observacionBase = filtrarObservacionConsulta(observacionBase);
|
||||||
|
}
|
||||||
const solicitanteNombre = String(a.nombre_solicitante || '').trim();
|
const solicitanteNombre = String(a.nombre_solicitante || '').trim();
|
||||||
const observacionLower = observacionBase.toLowerCase();
|
const observacionLower = observacionBase.toLowerCase();
|
||||||
const solicitanteInfo =
|
const solicitanteInfo =
|
||||||
solicitanteNombre && !observacionLower.includes('solicitante')
|
esConsultaExterna
|
||||||
|
? ''
|
||||||
|
: solicitanteNombre && !observacionLower.includes('solicitante')
|
||||||
? `Solicitante: ${solicitanteNombre}`
|
? `Solicitante: ${solicitanteNombre}`
|
||||||
: '';
|
: '';
|
||||||
const observacion = [cupInfo, observacionBase, solicitanteInfo]
|
const observacion = [cupInfo, observacionBase, solicitanteInfo]
|
||||||
|
|||||||
@ -2338,6 +2338,32 @@ async function crearLibroAutorizacionBrigadasAmbulanciasHospitalarios(a) {
|
|||||||
.replace(/\s+/g, ' ')
|
.replace(/\s+/g, ' ')
|
||||||
.trim();
|
.trim();
|
||||||
|
|
||||||
|
const emptyIpsValues = new Set([
|
||||||
|
'NA',
|
||||||
|
'SD',
|
||||||
|
'SINDATO',
|
||||||
|
'SINDATOS',
|
||||||
|
'SININFO',
|
||||||
|
'SININFORMACION',
|
||||||
|
'NOAPLICA',
|
||||||
|
'NONE',
|
||||||
|
'NULL',
|
||||||
|
]);
|
||||||
|
|
||||||
|
const cleanIpsValue = (value) => {
|
||||||
|
const raw = String(value || '').trim();
|
||||||
|
if (!raw) return '';
|
||||||
|
const normalized = raw
|
||||||
|
.normalize('NFD')
|
||||||
|
.replace(/[\u0300-\u036f]/g, '')
|
||||||
|
.toUpperCase()
|
||||||
|
.replace(/[^A-Z0-9]/g, '');
|
||||||
|
if (!normalized || emptyIpsValues.has(normalized)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return raw;
|
||||||
|
};
|
||||||
|
|
||||||
['F8', 'G8', 'H8', 'I8'].forEach((celda) => {
|
['F8', 'G8', 'H8', 'I8'].forEach((celda) => {
|
||||||
sheet.getCell(celda).value = a.numero_autorizacion || '';
|
sheet.getCell(celda).value = a.numero_autorizacion || '';
|
||||||
});
|
});
|
||||||
@ -2368,12 +2394,12 @@ async function crearLibroAutorizacionBrigadasAmbulanciasHospitalarios(a) {
|
|||||||
sheet.getCell(celda).value = nombreIps;
|
sheet.getCell(celda).value = nombreIps;
|
||||||
});
|
});
|
||||||
|
|
||||||
const nitIps = a.nit || '';
|
const nitIps = cleanIpsValue(a.nit);
|
||||||
['D13', 'E13', 'F13', 'G13'].forEach((celda) => {
|
['D13', 'E13', 'F13', 'G13'].forEach((celda) => {
|
||||||
sheet.getCell(celda).value = nitIps;
|
sheet.getCell(celda).value = nitIps;
|
||||||
});
|
});
|
||||||
|
|
||||||
const telefonoIps = a.telefono_ips || '';
|
const telefonoIps = cleanIpsValue(a.telefono_ips);
|
||||||
['D14', 'E14', 'F14', 'G14', 'D15', 'E15', 'F15', 'G15', 'D16', 'E16', 'F16', 'G16'].forEach((celda) => {
|
['D14', 'E14', 'F14', 'G14', 'D15', 'E15', 'F15', 'G15', 'D16', 'E16', 'F16', 'G16'].forEach((celda) => {
|
||||||
sheet.getCell(celda).value = telefonoIps;
|
sheet.getCell(celda).value = telefonoIps;
|
||||||
});
|
});
|
||||||
@ -2385,8 +2411,9 @@ async function crearLibroAutorizacionBrigadasAmbulanciasHospitalarios(a) {
|
|||||||
sheet.getCell(celda).value = a.sexo || '';
|
sheet.getCell(celda).value = a.sexo || '';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const direccionIps = cleanIpsValue(a.direccion);
|
||||||
['M13', 'N13', 'O13', 'P13', 'Q13', 'R13'].forEach((celda) => {
|
['M13', 'N13', 'O13', 'P13', 'Q13', 'R13'].forEach((celda) => {
|
||||||
sheet.getCell(celda).value = a.direccion || '';
|
sheet.getCell(celda).value = direccionIps;
|
||||||
});
|
});
|
||||||
|
|
||||||
['M23', 'N23', 'O23', 'P23', 'Q23', 'R23'].forEach((celda) => {
|
['M23', 'N23', 'O23', 'P23', 'Q23', 'R23'].forEach((celda) => {
|
||||||
@ -2394,11 +2421,11 @@ async function crearLibroAutorizacionBrigadasAmbulanciasHospitalarios(a) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
['M16', 'N16'].forEach((celda) => {
|
['M16', 'N16'].forEach((celda) => {
|
||||||
sheet.getCell(celda).value = a.municipio || '';
|
sheet.getCell(celda).value = cleanIpsValue(a.municipio);
|
||||||
});
|
});
|
||||||
|
|
||||||
['Q16', 'R16'].forEach((celda) => {
|
['Q16', 'R16'].forEach((celda) => {
|
||||||
sheet.getCell(celda).value = a.departamento || '';
|
sheet.getCell(celda).value = cleanIpsValue(a.departamento);
|
||||||
});
|
});
|
||||||
|
|
||||||
['H18', 'I18', 'J18', 'K18', 'L18', 'M18', 'N18', 'O18', 'P18', 'Q18', 'R18'].forEach((celda) => {
|
['H18', 'I18', 'J18', 'K18', 'L18', 'M18', 'N18', 'O18', 'P18', 'Q18', 'R18'].forEach((celda) => {
|
||||||
|
|||||||
@ -1507,6 +1507,28 @@ const normalizeDigits = (value) => String(value || '').replace(/\D/g, '');
|
|||||||
const normalizeNameKey = (value) =>
|
const normalizeNameKey = (value) =>
|
||||||
normalizeSearch(value).replace(/[^A-Z0-9]/g, '');
|
normalizeSearch(value).replace(/[^A-Z0-9]/g, '');
|
||||||
|
|
||||||
|
const IPS_EMPTY_MARKERS = new Set([
|
||||||
|
'NA',
|
||||||
|
'SD',
|
||||||
|
'SINDATO',
|
||||||
|
'SINDATOS',
|
||||||
|
'SININFO',
|
||||||
|
'SININFORMACION',
|
||||||
|
'NOAPLICA',
|
||||||
|
'NONE',
|
||||||
|
'NULL',
|
||||||
|
]);
|
||||||
|
|
||||||
|
const cleanIpsField = (value) => {
|
||||||
|
const raw = String(value || '').trim();
|
||||||
|
if (!raw) return '';
|
||||||
|
const normalized = normalizeSearch(raw).replace(/[^A-Z0-9]/g, '');
|
||||||
|
if (!normalized || IPS_EMPTY_MARKERS.has(normalized)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return raw;
|
||||||
|
};
|
||||||
|
|
||||||
const extractCupCodigo = (value) => {
|
const extractCupCodigo = (value) => {
|
||||||
const text = String(value || '').trim();
|
const text = String(value || '').trim();
|
||||||
if (!text) return '';
|
if (!text) return '';
|
||||||
@ -1667,19 +1689,18 @@ async function procesarExcelIps(inputFilePath) {
|
|||||||
|
|
||||||
for (let i = 2; i <= sheet.rowCount; i++) {
|
for (let i = 2; i <= sheet.rowCount; i++) {
|
||||||
const row = sheet.getRow(i);
|
const row = sheet.getRow(i);
|
||||||
const nit = getValueMulti(row, [
|
const nit = cleanIpsField(
|
||||||
'NIT',
|
getValueMulti(row, ['NIT', 'NITIPS', 'NITPRESTADOR', 'NITPRESTADORIPS'])
|
||||||
'NITIPS',
|
);
|
||||||
'NITPRESTADOR',
|
const nombre = cleanIpsField(
|
||||||
'NITPRESTADORIPS',
|
getValueMulti(row, [
|
||||||
]);
|
|
||||||
const nombre = getValueMulti(row, [
|
|
||||||
'PRESTADOR',
|
'PRESTADOR',
|
||||||
'PRESTADORDELSERVICIO',
|
'PRESTADORDELSERVICIO',
|
||||||
'PRESTADORDESERVICIO',
|
'PRESTADORDESERVICIO',
|
||||||
'NOMBREPRESTADOR',
|
'NOMBREPRESTADOR',
|
||||||
'NOMBREIPS',
|
'NOMBREIPS',
|
||||||
]);
|
])
|
||||||
|
);
|
||||||
|
|
||||||
if (!nit && !nombre) {
|
if (!nit && !nombre) {
|
||||||
continue;
|
continue;
|
||||||
@ -1687,15 +1708,13 @@ async function procesarExcelIps(inputFilePath) {
|
|||||||
|
|
||||||
resumen.total += 1;
|
resumen.total += 1;
|
||||||
|
|
||||||
const direccion = getValue(row, 'DIRECCION');
|
const direccion = cleanIpsField(getValue(row, 'DIRECCION'));
|
||||||
const departamento = getValue(row, 'DEPARTAMENTO');
|
const departamento = cleanIpsField(getValue(row, 'DEPARTAMENTO'));
|
||||||
const municipio = getValue(row, 'MUNICIPIO');
|
const municipio = cleanIpsField(getValue(row, 'MUNICIPIO'));
|
||||||
const telefono = getValue(row, 'TELEFONO');
|
const telefono = cleanIpsField(getValue(row, 'TELEFONO'));
|
||||||
const codigoIps = getValueMulti(row, [
|
const codigoIps = cleanIpsField(
|
||||||
'CODIGOIPS',
|
getValueMulti(row, ['CODIGOIPS', 'CODIGOPRESTADOR', 'CODIGOHABILITACION'])
|
||||||
'CODIGOPRESTADOR',
|
);
|
||||||
'CODIGOHABILITACION',
|
|
||||||
]);
|
|
||||||
|
|
||||||
const nitDigits = registerDigits(nitKeys, nit);
|
const nitDigits = registerDigits(nitKeys, nit);
|
||||||
const codigoDigits = registerDigits(codigoKeys, codigoIps);
|
const codigoDigits = registerDigits(codigoKeys, codigoIps);
|
||||||
@ -1777,16 +1796,18 @@ async function procesarExcelIps(inputFilePath) {
|
|||||||
await client.query(
|
await client.query(
|
||||||
`
|
`
|
||||||
UPDATE ips
|
UPDATE ips
|
||||||
SET nombre_ips = COALESCE($1, nombre_ips),
|
SET nit = COALESCE($1, nit),
|
||||||
codigo_ips = COALESCE($2, codigo_ips),
|
nombre_ips = COALESCE($2, nombre_ips),
|
||||||
direccion = COALESCE($3, direccion),
|
codigo_ips = COALESCE($3, codigo_ips),
|
||||||
telefono = COALESCE($4, telefono),
|
direccion = COALESCE($4, direccion),
|
||||||
departamento = COALESCE($5, departamento),
|
telefono = COALESCE($5, telefono),
|
||||||
municipio = COALESCE($6, municipio),
|
departamento = COALESCE($6, departamento),
|
||||||
|
municipio = COALESCE($7, municipio),
|
||||||
tiene_convenio = true
|
tiene_convenio = true
|
||||||
WHERE id_ips = $7
|
WHERE id_ips = $8
|
||||||
`,
|
`,
|
||||||
[
|
[
|
||||||
|
nit || null,
|
||||||
nombre || null,
|
nombre || null,
|
||||||
codigoIps || null,
|
codigoIps || null,
|
||||||
direccion || null,
|
direccion || null,
|
||||||
@ -5082,6 +5103,98 @@ app.patch('/api/autorizaciones/estado-masivo', verificarToken, esAdministrador,
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PATCH /api/autorizaciones/autorizante-masivo
|
||||||
|
* Body: { fecha_inicio, fecha_fin, numero_documento_autorizante, establecimiento?, ambito?, ips? }
|
||||||
|
* Solo administrador
|
||||||
|
*/
|
||||||
|
app.patch('/api/autorizaciones/autorizante-masivo', verificarToken, esAdministrador, async (req, res) => {
|
||||||
|
const fecha_inicio = req.body?.fecha_inicio || req.query?.fecha_inicio;
|
||||||
|
const fecha_fin = req.body?.fecha_fin || req.query?.fecha_fin;
|
||||||
|
const numeroDocumento =
|
||||||
|
req.body?.numero_documento_autorizante || req.query?.numero_documento_autorizante;
|
||||||
|
const establecimiento = String(
|
||||||
|
req.body?.establecimiento || req.query?.establecimiento || ''
|
||||||
|
).trim();
|
||||||
|
const ambito = String(req.body?.ambito || req.query?.ambito || '')
|
||||||
|
.trim()
|
||||||
|
.toLowerCase();
|
||||||
|
const ips = String(req.body?.ips || req.query?.ips || '').trim();
|
||||||
|
|
||||||
|
if (!fecha_inicio || !fecha_fin) {
|
||||||
|
return res.status(400).json({ error: 'fecha_inicio y fecha_fin son requeridos' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const numeroAutorizante = Number(numeroDocumento);
|
||||||
|
if (!Number.isFinite(numeroAutorizante)) {
|
||||||
|
return res.status(400).json({ error: 'numero_documento_autorizante invalido' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const ambitosPermitidos = ['intramural', 'extramural'];
|
||||||
|
if (ambito && !ambitosPermitidos.includes(ambito)) {
|
||||||
|
return res.status(400).json({ error: 'ambito invalido' });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const autorizanteRes = await pool.query(
|
||||||
|
'SELECT 1 FROM autorizante WHERE numero_documento = $1 LIMIT 1',
|
||||||
|
[numeroAutorizante]
|
||||||
|
);
|
||||||
|
if (autorizanteRes.rows.length === 0) {
|
||||||
|
return res.status(404).json({ error: 'Autorizante no encontrado' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const whereParts = ['a.fecha_autorizacion BETWEEN $2::date AND $3::date'];
|
||||||
|
const params = [numeroAutorizante, fecha_inicio, fecha_fin];
|
||||||
|
|
||||||
|
if (establecimiento) {
|
||||||
|
params.push(`%${establecimiento}%`);
|
||||||
|
whereParts.push(
|
||||||
|
`EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM ingreso i
|
||||||
|
JOIN establecimiento e ON i.codigo_establecimiento = e.codigo_establecimiento
|
||||||
|
WHERE i.interno = a.interno
|
||||||
|
AND (e.codigo_establecimiento ILIKE $${params.length} OR e.nombre_establecimiento ILIKE $${params.length})
|
||||||
|
)`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ambito) {
|
||||||
|
params.push(ambito);
|
||||||
|
whereParts.push(`a.ambito_atencion = $${params.length}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ips) {
|
||||||
|
params.push(`%${ips}%`);
|
||||||
|
whereParts.push(
|
||||||
|
`EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM ips i
|
||||||
|
WHERE i.id_ips = a.id_ips
|
||||||
|
AND (i.nombre_ips ILIKE $${params.length} OR i.nit ILIKE $${params.length} OR i.codigo_ips ILIKE $${params.length})
|
||||||
|
)`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const sql = `
|
||||||
|
UPDATE autorizacion a
|
||||||
|
SET numero_documento_autorizante = $1
|
||||||
|
WHERE ${whereParts.join('\n AND ')}
|
||||||
|
RETURNING a.numero_autorizacion;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const result = await pool.query(sql, params);
|
||||||
|
return res.json({
|
||||||
|
mensaje: 'Autorizantes actualizados',
|
||||||
|
actualizados: result.rowCount || 0,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error en autorizante masivo:', error.message);
|
||||||
|
return res.status(500).json({ error: 'Error actualizando autorizantes' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GET /api/autorizaciones-por-fecha/zip
|
* GET /api/autorizaciones-por-fecha/zip
|
||||||
* Query params: fecha_inicio, fecha_fin
|
* Query params: fecha_inicio, fecha_fin
|
||||||
|
|||||||
@ -242,6 +242,36 @@
|
|||||||
min-width: 180px;
|
min-width: 180px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.autorizante-masivo {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 6px 10px;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: var(--color-surface);
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.autorizante-masivo label {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.autorizante-masivo select {
|
||||||
|
min-width: 200px;
|
||||||
|
padding: 8px 10px;
|
||||||
|
border-radius: 6px;
|
||||||
|
border: 1px solid var(--color-input-border);
|
||||||
|
background: var(--color-input-bg);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: var(--color-text-main);
|
||||||
|
}
|
||||||
|
|
||||||
|
.autorizante-masivo button {
|
||||||
|
min-width: 180px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Table */
|
/* Table */
|
||||||
.table-container {
|
.table-container {
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
@ -503,6 +533,11 @@
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.autorizante-masivo {
|
||||||
|
width: 100%;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
.autorizaciones-table th,
|
.autorizaciones-table th,
|
||||||
.autorizaciones-table td {
|
.autorizaciones-table td {
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
@ -527,7 +562,9 @@
|
|||||||
.btn-exportar,
|
.btn-exportar,
|
||||||
.btn-descargar-todos,
|
.btn-descargar-todos,
|
||||||
.estado-masivo,
|
.estado-masivo,
|
||||||
.estado-masivo button {
|
.estado-masivo button,
|
||||||
|
.autorizante-masivo,
|
||||||
|
.autorizante-masivo button {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -537,11 +574,22 @@
|
|||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.autorizante-masivo {
|
||||||
|
width: 100%;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
.estado-masivo select,
|
.estado-masivo select,
|
||||||
.estado-masivo button {
|
.estado-masivo button {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.autorizante-masivo select,
|
||||||
|
.autorizante-masivo button {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.empty-state {
|
.empty-state {
|
||||||
padding: 40px 16px;
|
padding: 40px 16px;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -149,6 +149,32 @@
|
|||||||
{{ actualizandoMasivo ? 'Actualizando...' : 'Aplicar a todo el rango' }}
|
{{ actualizandoMasivo ? 'Actualizando...' : 'Aplicar a todo el rango' }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="autorizante-masivo" *ngIf="esAdmin">
|
||||||
|
<label for="autorizanteMasivo">Autorizante:</label>
|
||||||
|
<select
|
||||||
|
id="autorizanteMasivo"
|
||||||
|
[(ngModel)]="autorizanteMasivo"
|
||||||
|
[disabled]="actualizandoAutorizanteMasivo || cargandoAutorizantes"
|
||||||
|
>
|
||||||
|
<option value="">
|
||||||
|
{{ cargandoAutorizantes ? 'Cargando...' : 'Selecciona' }}
|
||||||
|
</option>
|
||||||
|
<option
|
||||||
|
*ngFor="let a of autorizantes"
|
||||||
|
[value]="a.numero_documento"
|
||||||
|
>
|
||||||
|
{{ a.nombre }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<button
|
||||||
|
class="btn btn-secondary"
|
||||||
|
type="button"
|
||||||
|
(click)="aplicarAutorizanteMasivo()"
|
||||||
|
[disabled]="actualizandoAutorizanteMasivo || !autorizanteMasivo || autorizaciones.length === 0"
|
||||||
|
>
|
||||||
|
{{ actualizandoAutorizanteMasivo ? 'Aplicando...' : 'Aplicar autorizante' }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<button
|
<button
|
||||||
class="btn btn-secondary btn-exportar"
|
class="btn btn-secondary btn-exportar"
|
||||||
*ngIf="puedeDescargarMasivo"
|
*ngIf="puedeDescargarMasivo"
|
||||||
|
|||||||
@ -27,6 +27,7 @@ export class AutorizacionesPorFechaComponent implements OnInit {
|
|||||||
actualizandoEstado: Record<string, boolean> = {};
|
actualizandoEstado: Record<string, boolean> = {};
|
||||||
actualizandoMasivo = false;
|
actualizandoMasivo = false;
|
||||||
estadoMasivo: 'pendiente' | 'autorizado' | 'no_autorizado' = 'autorizado';
|
estadoMasivo: 'pendiente' | 'autorizado' | 'no_autorizado' = 'autorizado';
|
||||||
|
actualizandoAutorizanteMasivo = false;
|
||||||
esAdmin = false;
|
esAdmin = false;
|
||||||
puedeGestionarEntrega = false;
|
puedeGestionarEntrega = false;
|
||||||
puedeDescargarMasivo = false;
|
puedeDescargarMasivo = false;
|
||||||
@ -36,6 +37,9 @@ export class AutorizacionesPorFechaComponent implements OnInit {
|
|||||||
ipsFiltro = '';
|
ipsFiltro = '';
|
||||||
autorizacionesFiltradas: any[] = [];
|
autorizacionesFiltradas: any[] = [];
|
||||||
actualizandoEntrega: Record<string, boolean> = {};
|
actualizandoEntrega: Record<string, boolean> = {};
|
||||||
|
autorizantes: any[] = [];
|
||||||
|
autorizanteMasivo = '';
|
||||||
|
cargandoAutorizantes = false;
|
||||||
|
|
||||||
// Para saber si ya buscamos algo
|
// Para saber si ya buscamos algo
|
||||||
hayResultados = false;
|
hayResultados = false;
|
||||||
@ -67,6 +71,10 @@ export class AutorizacionesPorFechaComponent implements OnInit {
|
|||||||
this.esAdmin || this.authService.isAdministrativoSede();
|
this.esAdmin || this.authService.isAdministrativoSede();
|
||||||
this.puedeDescargarMasivo = this.authService.puedeDescargarPdfs();
|
this.puedeDescargarMasivo = this.authService.puedeDescargarPdfs();
|
||||||
|
|
||||||
|
if (this.esAdmin) {
|
||||||
|
this.cargarAutorizantes();
|
||||||
|
}
|
||||||
|
|
||||||
// Rango por defecto: últimos 30 días
|
// Rango por defecto: últimos 30 días
|
||||||
const hoy = new Date();
|
const hoy = new Date();
|
||||||
const hace30Dias = new Date(hoy.getTime() - 30 * 24 * 60 * 60 * 1000);
|
const hace30Dias = new Date(hoy.getTime() - 30 * 24 * 60 * 60 * 1000);
|
||||||
@ -302,6 +310,77 @@ export class AutorizacionesPorFechaComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
aplicarAutorizanteMasivo(): void {
|
||||||
|
this.limpiarMensajes();
|
||||||
|
|
||||||
|
if (!this.esAdmin) {
|
||||||
|
this.errorMessage = 'No tienes permisos para actualizar autorizantes.';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.fechaInicioApi || !this.fechaFinApi) {
|
||||||
|
this.errorMessage = 'Primero realiza una busqueda por fechas.';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const autorizadoId = Number(this.autorizanteMasivo);
|
||||||
|
if (!Number.isFinite(autorizadoId)) {
|
||||||
|
this.errorMessage = 'Selecciona un autorizante valido.';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const autorizado = this.autorizantes.find(
|
||||||
|
(item) => String(item?.numero_documento) === String(this.autorizanteMasivo)
|
||||||
|
);
|
||||||
|
const autorizadoNombre = String(autorizado?.nombre || '').trim();
|
||||||
|
const autorizadoLabel = autorizadoNombre || String(autorizadoId);
|
||||||
|
|
||||||
|
const confirmacion = confirm(
|
||||||
|
`¿Seguro que deseas aplicar "${autorizadoLabel}" a todas las autorizaciones del rango?`
|
||||||
|
);
|
||||||
|
if (!confirmacion) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.actualizandoAutorizanteMasivo = true;
|
||||||
|
|
||||||
|
this.pacienteService
|
||||||
|
.actualizarAutorizanteMasivo(
|
||||||
|
this.fechaInicioApi,
|
||||||
|
this.fechaFinApi,
|
||||||
|
autorizadoId,
|
||||||
|
this.establecimientoFiltro || undefined,
|
||||||
|
this.ambitoFiltro || undefined,
|
||||||
|
this.ipsFiltro || undefined
|
||||||
|
)
|
||||||
|
.pipe(
|
||||||
|
finalize(() => {
|
||||||
|
this.actualizandoAutorizanteMasivo = false;
|
||||||
|
this.cdr.detectChanges();
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.subscribe({
|
||||||
|
next: (resp) => {
|
||||||
|
const total = resp?.actualizados ?? 0;
|
||||||
|
if (total > 0) {
|
||||||
|
const nombreMostrado = autorizadoNombre || autorizadoLabel;
|
||||||
|
this.autorizaciones = this.autorizaciones.map((aut) => ({
|
||||||
|
...aut,
|
||||||
|
nombre_autorizante: nombreMostrado,
|
||||||
|
numero_documento_autorizante: autorizadoId,
|
||||||
|
}));
|
||||||
|
this.aplicarFiltroNumero();
|
||||||
|
}
|
||||||
|
this.successMessage = `Se actualizaron ${total} autorizaciones.`;
|
||||||
|
},
|
||||||
|
error: (err) => {
|
||||||
|
console.error(err);
|
||||||
|
this.errorMessage =
|
||||||
|
err?.error?.error || 'Error actualizando autorizantes.';
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
actualizarEstadoEntrega(autorizacion: any, estado: string): void {
|
actualizarEstadoEntrega(autorizacion: any, estado: string): void {
|
||||||
if (!this.puedeGestionarEntrega || !autorizacion) {
|
if (!this.puedeGestionarEntrega || !autorizacion) {
|
||||||
return;
|
return;
|
||||||
@ -579,6 +658,29 @@ export class AutorizacionesPorFechaComponent implements OnInit {
|
|||||||
this.successMessage = null;
|
this.successMessage = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private cargarAutorizantes(): void {
|
||||||
|
this.cargandoAutorizantes = true;
|
||||||
|
const autorizantes$ = this.esAdmin
|
||||||
|
? this.pacienteService.obtenerAutorizantesAdmin()
|
||||||
|
: this.pacienteService.obtenerAutorizantes();
|
||||||
|
autorizantes$
|
||||||
|
.pipe(
|
||||||
|
finalize(() => {
|
||||||
|
this.cargandoAutorizantes = false;
|
||||||
|
this.cdr.detectChanges();
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.subscribe({
|
||||||
|
next: (data) => {
|
||||||
|
this.autorizantes = data || [];
|
||||||
|
},
|
||||||
|
error: (err) => {
|
||||||
|
console.error(err);
|
||||||
|
this.errorMessage = 'No se pudieron cargar los autorizantes.';
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// ========= GETTERS DEL FORM =========
|
// ========= GETTERS DEL FORM =========
|
||||||
get fecha_inicio() {
|
get fecha_inicio() {
|
||||||
return this.filtroForm.get('fecha_inicio');
|
return this.filtroForm.get('fecha_inicio');
|
||||||
|
|||||||
@ -287,7 +287,10 @@
|
|||||||
<div class="ips-helper" *ngIf="verMasIps">
|
<div class="ips-helper" *ngIf="verMasIps">
|
||||||
Mostrando IPS de todos los departamentos.
|
Mostrando IPS de todos los departamentos.
|
||||||
</div>
|
</div>
|
||||||
<div class="ips-traslado" *ngIf="observacionTraslado">
|
<div
|
||||||
|
class="ips-traslado"
|
||||||
|
*ngIf="observacionTraslado && formAutorizacion.tipo_autorizacion !== 'consultas_externas'"
|
||||||
|
>
|
||||||
Se agregara a observaciones: {{ observacionTraslado }}
|
Se agregara a observaciones: {{ observacionTraslado }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -268,7 +268,11 @@ export class AutorizacionesComponent {
|
|||||||
|
|
||||||
const deptoIps = String(ipsSeleccionada.departamento || '').trim();
|
const deptoIps = String(ipsSeleccionada.departamento || '').trim();
|
||||||
const deptoInterno = String(this.departamentoInterno || '').trim();
|
const deptoInterno = String(this.departamentoInterno || '').trim();
|
||||||
|
const esConsultaExterna =
|
||||||
|
String(this.formAutorizacion.tipo_autorizacion || '').toLowerCase() ===
|
||||||
|
'consultas_externas';
|
||||||
const requiereTraslado =
|
const requiereTraslado =
|
||||||
|
!esConsultaExterna &&
|
||||||
this.verMasIps &&
|
this.verMasIps &&
|
||||||
deptoIps &&
|
deptoIps &&
|
||||||
deptoInterno &&
|
deptoInterno &&
|
||||||
@ -339,6 +343,13 @@ export class AutorizacionesComponent {
|
|||||||
this.formAutorizacion.tipo_servicio = '';
|
this.formAutorizacion.tipo_servicio = '';
|
||||||
this.limpiarArchivosHospitalarios();
|
this.limpiarArchivosHospitalarios();
|
||||||
}
|
}
|
||||||
|
const esConsultaExterna =
|
||||||
|
String(this.formAutorizacion.tipo_autorizacion || '').toLowerCase() ===
|
||||||
|
'consultas_externas';
|
||||||
|
if (esConsultaExterna) {
|
||||||
|
this.observacionTraslado = '';
|
||||||
|
}
|
||||||
|
this.onIpsChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
onTipoServicioChange(): void {
|
onTipoServicioChange(): void {
|
||||||
@ -675,7 +686,11 @@ export class AutorizacionesComponent {
|
|||||||
baseSinTraslado = baseSinTraslado.replace(trasladoRegex, '').trim();
|
baseSinTraslado = baseSinTraslado.replace(trasladoRegex, '').trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!trasladoTexto) {
|
const esConsultaExterna =
|
||||||
|
String(this.formAutorizacion.tipo_autorizacion || '').toLowerCase() ===
|
||||||
|
'consultas_externas';
|
||||||
|
|
||||||
|
if (!trasladoTexto || esConsultaExterna) {
|
||||||
return baseSinTraslado || undefined;
|
return baseSinTraslado || undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -422,4 +422,35 @@ export class PacienteService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
actualizarAutorizanteMasivo(
|
||||||
|
fechaInicio: string,
|
||||||
|
fechaFin: string,
|
||||||
|
numeroDocumentoAutorizante: number,
|
||||||
|
establecimiento?: string,
|
||||||
|
ambito?: string,
|
||||||
|
ips?: string
|
||||||
|
): Observable<any> {
|
||||||
|
const payload: any = {
|
||||||
|
fecha_inicio: fechaInicio,
|
||||||
|
fecha_fin: fechaFin,
|
||||||
|
numero_documento_autorizante: numeroDocumentoAutorizante,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (establecimiento) {
|
||||||
|
payload.establecimiento = establecimiento;
|
||||||
|
}
|
||||||
|
if (ambito) {
|
||||||
|
payload.ambito = ambito;
|
||||||
|
}
|
||||||
|
if (ips) {
|
||||||
|
payload.ips = ips;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.http.patch(
|
||||||
|
`${this.API_URL}/autorizaciones/autorizante-masivo`,
|
||||||
|
payload,
|
||||||
|
{ headers: this.getAuthHeaders() }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user