Add console credits, README with documentation and U-SITE credits
This commit is contained in:
@@ -0,0 +1,83 @@
|
|||||||
|
# RIPS Manager
|
||||||
|
|
||||||
|
**Desarrollado por [U-SITE SAS BIC](https://u-site.app/)**
|
||||||
|
|
||||||
|
Sistema web para la generación y envío de JSON de RIPS (Registro Individual de Prestación de Servicios de Salud) según la **Resolución 2275 de 2023** del Ministerio de Salud y Protección Social de Colombia.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Requisitos del sistema
|
||||||
|
|
||||||
|
- **Python 3.9+** (el script `run.ps1` lo descarga automáticamente si no está instalado)
|
||||||
|
- **Git** (para actualizaciones via `git pull`)
|
||||||
|
- **Conexión a base de datos Firebird** (servidor remoto o local)
|
||||||
|
- **API destino** para recepción de RIPS (configurable)
|
||||||
|
- **Sistema operativo**: Windows 10/11, macOS, Linux
|
||||||
|
|
||||||
|
## Instalación
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
git clone https://github.com/U-SITE-SAS-BIC/rips_manager.git
|
||||||
|
cd rips_manager
|
||||||
|
powershell -ExecutionPolicy Bypass -File run.ps1
|
||||||
|
```
|
||||||
|
|
||||||
|
El script descarga Python automáticamente si es necesario.
|
||||||
|
|
||||||
|
### macOS / Linux
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/U-SITE-SAS-BIC/rips_manager.git
|
||||||
|
cd rips_manager
|
||||||
|
chmod +x arrancar.sh
|
||||||
|
./arrancar.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Una vez iniciado, abrir en el navegador:
|
||||||
|
|
||||||
|
- **http://localhost:8080** (en la misma máquina)
|
||||||
|
- **http://<IP_LOCAL>:8080** (desde otros equipos en la red)
|
||||||
|
|
||||||
|
## Primer uso
|
||||||
|
|
||||||
|
1. Registrar un usuario en `/auth/register`
|
||||||
|
2. Iniciar sesión
|
||||||
|
3. Configurar conexión Firebird y datos del prestador en `/config`
|
||||||
|
4. Ajustar consultas SQL en `/queries` según los nombres reales de tablas
|
||||||
|
5. Usar la sección **Terceros**, **Transacción RIPS** o **Automatización**
|
||||||
|
|
||||||
|
## Funcionalidades
|
||||||
|
|
||||||
|
| Módulo | Descripción |
|
||||||
|
|---|---|
|
||||||
|
| **Dashboard** | Estadísticas de envíos, últimos registros |
|
||||||
|
| **Configuración** | Conexión Firebird, API destino, datos del prestador |
|
||||||
|
| **Consultas SQL** | Editor de consultas con parámetros (`:doc_num`, `:fecha_ini`, etc.) |
|
||||||
|
| **Terceros** | Genera y envía JSON de datos maestros del paciente |
|
||||||
|
| **Transacción RIPS** | Genera y envía JSON de procedimientos (20 campos P01-P20) |
|
||||||
|
| **Automatización** | Paso 1 (terceros) + Paso 2 (transacción) por rango de fechas |
|
||||||
|
| **Historial** | Logs de todos los envíos realizados |
|
||||||
|
|
||||||
|
## Stack tecnológico
|
||||||
|
|
||||||
|
- **Backend**: Python / FastAPI + Uvicorn
|
||||||
|
- **Frontend**: Jinja2 + Tailwind CSS + FontAwesome
|
||||||
|
- **Autenticación**: JWT + bcrypt + HttpOnly cookies
|
||||||
|
- **Base de datos app**: SQLite
|
||||||
|
- **Base de datos datos**: Firebird (vía `fdb`)
|
||||||
|
- **Cliente HTTP**: httpx
|
||||||
|
|
||||||
|
## Créditos
|
||||||
|
|
||||||
|
© 2026 **U-SITE SAS BIC** — Todos los derechos reservados.
|
||||||
|
|
||||||
|
- **Web**: [https://u-site.app/](https://u-site.app/)
|
||||||
|
- **Sistema**: RIPS Manager v1.0
|
||||||
|
- **Propósito**: Generación y envío de RIPS según Res. 2275/2023
|
||||||
|
- **Campos cubiertos**: Procedimientos (20 campos P01-P20 del Anexo Técnico 1)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Documentación técnica completa en [DOCUMENTACION.md](DOCUMENTACION.md)*
|
||||||
+127
-122
@@ -1,122 +1,127 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="es" class="h-full bg-gray-50">
|
<html lang="es" class="h-full bg-gray-50">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>RIPS Manager - {% block title %}Dashboard{% endblock %}</title>
|
<title>RIPS Manager - {% block title %}Dashboard{% endblock %}</title>
|
||||||
<script src="https://cdn.tailwindcss.com"></script>
|
<script src="https://cdn.tailwindcss.com"></script>
|
||||||
<script>
|
<script>
|
||||||
tailwind.config = {
|
tailwind.config = {
|
||||||
theme: {
|
theme: {
|
||||||
extend: {
|
extend: {
|
||||||
colors: {
|
colors: {
|
||||||
primary: {'50': '#eff6ff','100': '#dbeafe','200': '#bfdbfe','300': '#93c5fd','400': '#60a5fa','500': '#3b82f6','600': '#2563eb','700': '#1d4ed8','800': '#1e40af','900': '#1e3a8a'}
|
primary: {'50': '#eff6ff','100': '#dbeafe','200': '#bfdbfe','300': '#93c5fd','400': '#60a5fa','500': '#3b82f6','600': '#2563eb','700': '#1d4ed8','800': '#1e40af','900': '#1e3a8a'}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
|
||||||
</head>
|
</head>
|
||||||
<body class="h-full">
|
<body class="h-full">
|
||||||
<div class="min-h-full">
|
<div class="min-h-full">
|
||||||
{% if user %}
|
{% if user %}
|
||||||
<!-- Sidebar -->
|
<!-- Sidebar -->
|
||||||
<div class="fixed inset-y-0 left-0 w-64 bg-gray-900 text-white z-30">
|
<div class="fixed inset-y-0 left-0 w-64 bg-gray-900 text-white z-30">
|
||||||
<div class="flex items-center h-16 px-6 border-b border-gray-700">
|
<div class="flex items-center h-16 px-6 border-b border-gray-700">
|
||||||
<i class="fas fa-file-medical text-blue-400 text-xl mr-3"></i>
|
<i class="fas fa-file-medical text-blue-400 text-xl mr-3"></i>
|
||||||
<span class="font-bold text-lg">RIPS Manager</span>
|
<span class="font-bold text-lg">RIPS Manager</span>
|
||||||
</div>
|
</div>
|
||||||
<nav class="mt-4 px-3 space-y-1">
|
<nav class="mt-4 px-3 space-y-1">
|
||||||
<a href="/dashboard" class="flex items-center px-3 py-2.5 rounded-lg text-sm font-medium {% if request.url.path == '/dashboard' %}bg-blue-600 text-white{% else %}text-gray-300 hover:bg-gray-700{% endif %}">
|
<a href="/dashboard" class="flex items-center px-3 py-2.5 rounded-lg text-sm font-medium {% if request.url.path == '/dashboard' %}bg-blue-600 text-white{% else %}text-gray-300 hover:bg-gray-700{% endif %}">
|
||||||
<i class="fas fa-chart-pie w-5 mr-2"></i> Dashboard
|
<i class="fas fa-chart-pie w-5 mr-2"></i> Dashboard
|
||||||
</a>
|
</a>
|
||||||
<a href="/config" class="flex items-center px-3 py-2.5 rounded-lg text-sm font-medium {% if request.url.path == '/config' %}bg-blue-600 text-white{% else %}text-gray-300 hover:bg-gray-700{% endif %}">
|
<a href="/config" class="flex items-center px-3 py-2.5 rounded-lg text-sm font-medium {% if request.url.path == '/config' %}bg-blue-600 text-white{% else %}text-gray-300 hover:bg-gray-700{% endif %}">
|
||||||
<i class="fas fa-cog w-5 mr-2"></i> Configuración
|
<i class="fas fa-cog w-5 mr-2"></i> Configuración
|
||||||
</a>
|
</a>
|
||||||
<a href="/queries" class="flex items-center px-3 py-2.5 rounded-lg text-sm font-medium {% if request.url.path == '/queries' %}bg-blue-600 text-white{% else %}text-gray-300 hover:bg-gray-700{% endif %}">
|
<a href="/queries" class="flex items-center px-3 py-2.5 rounded-lg text-sm font-medium {% if request.url.path == '/queries' %}bg-blue-600 text-white{% else %}text-gray-300 hover:bg-gray-700{% endif %}">
|
||||||
<i class="fas fa-database w-5 mr-2"></i> Consultas SQL
|
<i class="fas fa-database w-5 mr-2"></i> Consultas SQL
|
||||||
</a>
|
</a>
|
||||||
<hr class="my-3 border-gray-700">
|
<hr class="my-3 border-gray-700">
|
||||||
<p class="px-3 text-xs font-semibold text-gray-400 uppercase tracking-wider">Envíos</p>
|
<p class="px-3 text-xs font-semibold text-gray-400 uppercase tracking-wider">Envíos</p>
|
||||||
<a href="/terceros" class="flex items-center px-3 py-2.5 rounded-lg text-sm font-medium {% if request.url.path == '/terceros' %}bg-blue-600 text-white{% else %}text-gray-300 hover:bg-gray-700{% endif %}">
|
<a href="/terceros" class="flex items-center px-3 py-2.5 rounded-lg text-sm font-medium {% if request.url.path == '/terceros' %}bg-blue-600 text-white{% else %}text-gray-300 hover:bg-gray-700{% endif %}">
|
||||||
<i class="fas fa-user w-5 mr-2"></i> Terceros
|
<i class="fas fa-user w-5 mr-2"></i> Terceros
|
||||||
</a>
|
</a>
|
||||||
<a href="/transaccion" class="flex items-center px-3 py-2.5 rounded-lg text-sm font-medium {% if request.url.path == '/transaccion' %}bg-blue-600 text-white{% else %}text-gray-300 hover:bg-gray-700{% endif %}">
|
<a href="/transaccion" class="flex items-center px-3 py-2.5 rounded-lg text-sm font-medium {% if request.url.path == '/transaccion' %}bg-blue-600 text-white{% else %}text-gray-300 hover:bg-gray-700{% endif %}">
|
||||||
<i class="fas fa-exchange-alt w-5 mr-2"></i> Transacción RIPS
|
<i class="fas fa-exchange-alt w-5 mr-2"></i> Transacción RIPS
|
||||||
</a>
|
</a>
|
||||||
<a href="/automation" class="flex items-center px-3 py-2.5 rounded-lg text-sm font-medium {% if request.url.path == '/automation' %}bg-blue-600 text-white{% else %}text-gray-300 hover:bg-gray-700{% endif %}">
|
<a href="/automation" class="flex items-center px-3 py-2.5 rounded-lg text-sm font-medium {% if request.url.path == '/automation' %}bg-blue-600 text-white{% else %}text-gray-300 hover:bg-gray-700{% endif %}">
|
||||||
<i class="fas fa-robot w-5 mr-2"></i> Automatización
|
<i class="fas fa-robot w-5 mr-2"></i> Automatización
|
||||||
</a>
|
</a>
|
||||||
<hr class="my-3 border-gray-700">
|
<hr class="my-3 border-gray-700">
|
||||||
<a href="/logs" class="flex items-center px-3 py-2.5 rounded-lg text-sm font-medium {% if request.url.path == '/logs' %}bg-blue-600 text-white{% else %}text-gray-300 hover:bg-gray-700{% endif %}">
|
<a href="/logs" class="flex items-center px-3 py-2.5 rounded-lg text-sm font-medium {% if request.url.path == '/logs' %}bg-blue-600 text-white{% else %}text-gray-300 hover:bg-gray-700{% endif %}">
|
||||||
<i class="fas fa-history w-5 mr-2"></i> Historial
|
<i class="fas fa-history w-5 mr-2"></i> Historial
|
||||||
</a>
|
</a>
|
||||||
<a href="/auth/logout" class="flex items-center px-3 py-2.5 rounded-lg text-sm font-medium text-gray-300 hover:bg-gray-700">
|
<a href="/auth/logout" class="flex items-center px-3 py-2.5 rounded-lg text-sm font-medium text-gray-300 hover:bg-gray-700">
|
||||||
<i class="fas fa-sign-out-alt w-5 mr-2"></i> Salir
|
<i class="fas fa-sign-out-alt w-5 mr-2"></i> Salir
|
||||||
</a>
|
</a>
|
||||||
</nav>
|
</nav>
|
||||||
<div class="absolute bottom-0 left-0 right-0 px-4 py-3 border-t border-gray-700">
|
<div class="absolute bottom-0 left-0 right-0 px-4 py-3 border-t border-gray-700">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<div class="w-8 h-8 bg-blue-500 rounded-full flex items-center justify-center text-sm font-bold">
|
<div class="w-8 h-8 bg-blue-500 rounded-full flex items-center justify-center text-sm font-bold">
|
||||||
{{ user.username[0]|upper }}
|
{{ user.username[0]|upper }}
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-3">
|
<div class="ml-3">
|
||||||
<p class="text-sm font-medium text-white">{{ user.username }}</p>
|
<p class="text-sm font-medium text-white">{{ user.username }}</p>
|
||||||
<p class="text-xs text-gray-400">Sesión activa</p>
|
<p class="text-xs text-gray-400">Sesión activa</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Main content -->
|
<!-- Main content -->
|
||||||
<div class="pl-64">
|
<div class="pl-64">
|
||||||
<header class="bg-white shadow-sm border-b border-gray-200">
|
<header class="bg-white shadow-sm border-b border-gray-200">
|
||||||
<div class="flex items-center justify-between h-16 px-8">
|
<div class="flex items-center justify-between h-16 px-8">
|
||||||
<h1 class="text-xl font-semibold text-gray-800">{% block header %}Dashboard{% endblock %}</h1>
|
<h1 class="text-xl font-semibold text-gray-800">{% block header %}Dashboard{% endblock %}</h1>
|
||||||
<div class="flex items-center space-x-4">
|
<div class="flex items-center space-x-4">
|
||||||
<span class="text-sm text-gray-500">
|
<span class="text-sm text-gray-500">
|
||||||
<i class="far fa-calendar-alt mr-1"></i>
|
<i class="far fa-calendar-alt mr-1"></i>
|
||||||
<script>document.write(new Date().toLocaleDateString('es-CO', {year:'numeric',month:'long',day:'numeric'}))</script>
|
<script>document.write(new Date().toLocaleDateString('es-CO', {year:'numeric',month:'long',day:'numeric'}))</script>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<main class="p-8">
|
<main class="p-8">
|
||||||
{% block content %}{% endblock %}
|
{% block content %}{% endblock %}
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<main>
|
<main>
|
||||||
{% block auth_content %}{% endblock %}
|
{% block auth_content %}{% endblock %}
|
||||||
</main>
|
</main>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
async function fetchJSON(url, options = {}) {
|
console.log('%c RIPS Manager v1.0 ', 'background:#1e3a8a;color:white;font-size:18px;font-weight:bold;padding:8px 12px;border-radius:4px;');
|
||||||
const resp = await fetch(url, options);
|
console.log('%c Desarrollado por U-SITE SAS BIC', 'font-size:14px;');
|
||||||
return await resp.json();
|
console.log('%c https://u-site.app/', 'color:#2563eb;font-size:12px;');
|
||||||
}
|
console.log('%c Sistema de generacion y envio de RIPS (Res. 2275/2023)', 'font-style:italic;font-size:12px;');
|
||||||
|
|
||||||
function showToast(message, type = 'success') {
|
async function fetchJSON(url, options = {}) {
|
||||||
const colors = {success: 'bg-green-500', error: 'bg-red-500', info: 'bg-blue-500', warning: 'bg-yellow-500'};
|
const resp = await fetch(url, options);
|
||||||
const toast = document.createElement('div');
|
return await resp.json();
|
||||||
toast.className = `fixed top-4 right-4 z-50 ${colors[type]} text-white px-6 py-3 rounded-lg shadow-lg transition-all duration-500`;
|
}
|
||||||
toast.textContent = message;
|
|
||||||
document.body.appendChild(toast);
|
function showToast(message, type = 'success') {
|
||||||
setTimeout(() => { toast.style.opacity = '0'; setTimeout(() => toast.remove(), 500); }, 4000);
|
const colors = {success: 'bg-green-500', error: 'bg-red-500', info: 'bg-blue-500', warning: 'bg-yellow-500'};
|
||||||
}
|
const toast = document.createElement('div');
|
||||||
|
toast.className = `fixed top-4 right-4 z-50 ${colors[type]} text-white px-6 py-3 rounded-lg shadow-lg transition-all duration-500`;
|
||||||
function showLoading(btn) {
|
toast.textContent = message;
|
||||||
btn.disabled = true;
|
document.body.appendChild(toast);
|
||||||
btn.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i> Procesando...';
|
setTimeout(() => { toast.style.opacity = '0'; setTimeout(() => toast.remove(), 500); }, 4000);
|
||||||
}
|
}
|
||||||
|
|
||||||
function hideLoading(btn, text) {
|
function showLoading(btn) {
|
||||||
btn.disabled = false;
|
btn.disabled = true;
|
||||||
btn.innerHTML = text;
|
btn.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i> Procesando...';
|
||||||
}
|
}
|
||||||
</script>
|
|
||||||
</body>
|
function hideLoading(btn, text) {
|
||||||
</html>
|
btn.disabled = false;
|
||||||
|
btn.innerHTML = text;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user