cambios finales
This commit is contained in:
parent
5844cfe523
commit
123fdf5d91
21
README.md
21
README.md
@ -36,16 +36,14 @@ tar -xzf /opt/saludut/saludut-backend.tar.gz -C /opt/saludut/
|
||||
tar -xzf /opt/saludut/saludut-frontend.tar.gz -C /opt/saludut/
|
||||
```
|
||||
|
||||
### 4) Inicializar esquema y datos
|
||||
Primero genera el hash del admin y reemplaza `<HASH_BCRYPT>` en `backend/src/comandos.sql`:
|
||||
### 4) Inicializar esquema minimo
|
||||
Ejecuta el script minimo (schema + roles base):
|
||||
```bash
|
||||
node /opt/saludut/backend/src/generate-hash.js
|
||||
psql -U saludut_user -d saludut_db -f /opt/saludut/backend/src/insert.sql
|
||||
```
|
||||
|
||||
Luego ejecuta el setup unico (esquema + CUPS + roles/admin):
|
||||
```bash
|
||||
psql -U saludut_user -d saludut_db -f /opt/saludut/backend/src/setup.sql
|
||||
```
|
||||
El admin se crea automaticamente al iniciar el backend si defines
|
||||
`ADMIN_USER` y `ADMIN_PASS` en el `.env`.
|
||||
|
||||
Opcional: cargar datos masivos desde archivos:
|
||||
```bash
|
||||
@ -54,6 +52,13 @@ psql -U saludut_user -d saludut_db -f /opt/saludut/backend/src/paciente.sql
|
||||
psql -U saludut_user -d saludut_db -f /opt/saludut/backend/src/ingreso.sql
|
||||
```
|
||||
|
||||
Opcional (solo si quieres cargar CUPS por SQL y no por la UI):
|
||||
```bash
|
||||
psql -U saludut_user -d saludut_db -f /opt/saludut/backend/src/cups_schema.sql
|
||||
psql -U saludut_user -d saludut_db -f /opt/saludut/backend/src/cups_referencia.sql
|
||||
psql -U saludut_user -d saludut_db -f /opt/saludut/backend/src/cups_cubiertos.sql
|
||||
```
|
||||
|
||||
### 5) Backend (.env)
|
||||
Crear `backend/.env` en el servidor:
|
||||
```
|
||||
@ -73,7 +78,7 @@ ADMIN_EMAIL=admin@saludut.gov.co
|
||||
ADMIN_NAME=Administrador Sistema
|
||||
```
|
||||
|
||||
### 6) Crear usuario admin (manual)
|
||||
### 6) Crear usuario admin (automatico)
|
||||
Si defines `ADMIN_USER` y `ADMIN_PASS` en `.env`, el backend crea/actualiza el admin automaticamente al iniciar.
|
||||
|
||||
### 7) Backend (instalar y correr)
|
||||
|
||||
10
backend/src/insert.sql
Normal file
10
backend/src/insert.sql
Normal file
@ -0,0 +1,10 @@
|
||||
\\set ON_ERROR_STOP on
|
||||
|
||||
\\i schema.sql
|
||||
|
||||
-- Roles base (minimo para funcionar)
|
||||
INSERT INTO rol (nombre_rol, descripcion)
|
||||
VALUES
|
||||
('administrador', 'Puede cargar pacientes, descargar PDFs y ver todas las autorizaciones'),
|
||||
('administrativo_sede', 'Solo puede generar autorizaciones para su sede')
|
||||
ON CONFLICT (nombre_rol) DO NOTHING;
|
||||
@ -2755,7 +2755,17 @@ async function crearLibroAutorizacion(a) {
|
||||
if (nivelTexto) cupInfoParts.push(nivelTexto);
|
||||
const cupInfo = cupInfoParts.join(' - ');
|
||||
const observacionBase = a.observacion || '';
|
||||
const observacion = [cupInfo, observacionBase].filter(Boolean).join(' | ');
|
||||
const tipoAutorizacion = (a.tipo_autorizacion || 'consultas_externas').toLowerCase();
|
||||
const tipoServicioRaw = String(a.tipo_servicio || '').trim();
|
||||
let tipoServicioTexto = '';
|
||||
if (tipoServicioRaw) {
|
||||
tipoServicioTexto = `Tipo servicio: ${tipoServicioRaw}`;
|
||||
} else if (tipoAutorizacion === 'consultas_externas') {
|
||||
tipoServicioTexto = 'Tipo servicio: Consulta externa';
|
||||
}
|
||||
const observacion = [cupInfo, tipoServicioTexto, observacionBase]
|
||||
.filter(Boolean)
|
||||
.join(' | ');
|
||||
['H31','R31'].forEach(celda => {
|
||||
sheet.getCell(celda).value = observacion;
|
||||
});
|
||||
|
||||
@ -3136,6 +3136,11 @@ app.get('/api/generar-excel-autorizaciones', async (req, res) => {
|
||||
|
||||
// Agregar las filas a la hoja de trabajo
|
||||
rows.forEach(row => {
|
||||
const tipoServicio = row.tipo_servicio || (
|
||||
String(row.tipo_autorizacion || '').toLowerCase() === 'consultas_externas'
|
||||
? 'consulta externa'
|
||||
: ''
|
||||
);
|
||||
worksheet.addRow({
|
||||
numero_autorizacion: row.numero_autorizacion,
|
||||
version: row.version,
|
||||
@ -3144,7 +3149,7 @@ app.get('/api/generar-excel-autorizaciones', async (req, res) => {
|
||||
cup_codigo: row.cup_codigo,
|
||||
cup_nivel: row.cup_nivel,
|
||||
tipo_autorizacion: row.tipo_autorizacion,
|
||||
tipo_servicio: row.tipo_servicio,
|
||||
tipo_servicio: tipoServicio,
|
||||
nombre_ips: row.nombre_ips,
|
||||
fecha_autorizacion: row.fecha_autorizacion,
|
||||
observacion: row.observacion,
|
||||
|
||||
@ -182,49 +182,6 @@
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.sedes-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.sedes-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.sedes-meta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.sedes-count {
|
||||
font-size: 0.85rem;
|
||||
color: var(--color-text-muted);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.sedes-toggle {
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: var(--color-primary);
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.sedes-toggle:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.sedes-empty {
|
||||
font-size: 0.85rem;
|
||||
color: var(--color-text-muted);
|
||||
}
|
||||
|
||||
.sede-badge {
|
||||
background: var(--color-primary-soft);
|
||||
|
||||
@ -232,39 +232,6 @@
|
||||
</div>
|
||||
|
||||
<!-- Sedes asignadas (solo para administrativos) -->
|
||||
<div
|
||||
class="role-item"
|
||||
*ngIf="currentUser.nombre_rol === 'administrativo_sede'"
|
||||
>
|
||||
<span class="role-label">Sedes asignadas:</span>
|
||||
<div class="sedes-info">
|
||||
<div class="sedes-meta" *ngIf="getSedesUsuario().length > 0">
|
||||
<span class="sedes-count">
|
||||
{{ getSedesUsuario().length }} sedes
|
||||
</span>
|
||||
<button
|
||||
class="sedes-toggle"
|
||||
*ngIf="getSedesUsuario().length > 8"
|
||||
(click)="toggleSedesAsignadas()"
|
||||
type="button"
|
||||
>
|
||||
{{ getTextoToggleSedes() }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="sedes-list" *ngIf="getSedesUsuario().length > 0; else sinSedes">
|
||||
<span
|
||||
class="sede-badge"
|
||||
*ngFor="let sede of getSedesMostradas()"
|
||||
[title]="sede.nombre_establecimiento"
|
||||
>
|
||||
{{ sede.nombre_establecimiento }}
|
||||
</span>
|
||||
</div>
|
||||
<ng-template #sinSedes>
|
||||
<span class="sedes-empty">Sin sedes asignadas</span>
|
||||
</ng-template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
@ -20,7 +20,6 @@ export class DashboardComponent implements OnInit, OnDestroy {
|
||||
currentUser: any = null;
|
||||
errorMessage: string | null = null;
|
||||
private subscriptions: Subscription[] = [];
|
||||
mostrarTodasSedes = false;
|
||||
|
||||
constructor(
|
||||
private authService: AuthService,
|
||||
@ -184,26 +183,6 @@ export class DashboardComponent implements OnInit, OnDestroy {
|
||||
return this.authService.isLoggedIn();
|
||||
}
|
||||
|
||||
getSedesUsuario(): any[] {
|
||||
return this.currentUser?.sedes || [];
|
||||
}
|
||||
|
||||
getSedesMostradas(): any[] {
|
||||
const sedes = this.getSedesUsuario();
|
||||
if (this.mostrarTodasSedes || sedes.length <= 8) {
|
||||
return sedes;
|
||||
}
|
||||
return sedes.slice(0, 8);
|
||||
}
|
||||
|
||||
toggleSedesAsignadas(): void {
|
||||
this.mostrarTodasSedes = !this.mostrarTodasSedes;
|
||||
}
|
||||
|
||||
getTextoToggleSedes(): string {
|
||||
return this.mostrarTodasSedes ? 'Ocultar' : 'Ver todas';
|
||||
}
|
||||
|
||||
cerrarMensajeError(): void {
|
||||
this.errorMessage = null;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user