# LicenciasMiG

Panel web dedicado a la **aprobación de solicitudes de licencia MIG**.

Reemplaza el flujo viejo basado en correo SMTP por:

1. El cliente MIG envía la solicitud vía SOAP (`RegistrarSolicitud`).
2. La solicitud queda en estado `Pendiente` en la BD.
3. Un asesor entra al panel, la revisa y la **Aprueba** o **Rechaza**.
4. El cliente MIG hace polling (`ConsultarEstadoSolicitud` cada 10s) y al detectar la aprobación, escribe automáticamente la `claveproducto` en su `app.config` y se reinicia.

Comparte BD (`LicenciasMIG` en SQL Server del VPS) con el panel viejo. Al aprobar, se inserta en `LicenciasEmpresas` con `licenciaactiva=true` para mantener compatibilidad con `ValidarEmpresa` (que es el otro flujo de validación en cada arranque del cliente).

---

## Stack

- **Backend**: Flask 2.3 + SQLAlchemy 2.0 + spyne 2.14 (SOAP)
- **DB**: SQL Server (vía pyodbc + ODBC Driver 17)
- **Frontend**: Bootstrap 5 + JS vanilla
- **Deploy**: Apache 2 + mod_wsgi (puerto 89 en VPS)

## Estructura

```
LicenciasMiG\
├── app.py                  # Factory Flask + bootstrap
├── wsgi.py                 # Entry mod_wsgi
├── config.py               # Lectura de variables .env
├── models.py               # Solicitud, Empresa, LicenciaEmpresa, Usuario
├── crypto.py               # AES (compatibilidad con cliente MIG)
├── soap_service.py         # Endpoints SOAP (Spyne)
├── routes\
│   ├── auth.py             # Login/logout
│   └── solicitudes.py      # Lista/detalle/aprobar/rechazar
├── templates\
│   ├── base.html
│   ├── login.html
│   └── solicitudes\
│       ├── lista.html
│       └── detalle.html
├── static\
│   ├── css\custom.css
│   └── js\app.js           # Badge auto-refresh + beep
├── migrations\
│   └── 001_create_solicitudes.sql
└── requirements.txt
```

## Setup local

```powershell
# 1. Crear virtualenv
python -m venv .venv
.venv\Scripts\Activate.ps1

# 2. Instalar dependencias
pip install -r requirements.txt

# 3. Copiar .env.example a .env y editar credenciales
copy .env.example .env

# 4. Aplicar migration en SQL Server
sqlcmd -S 194.163.45.32 -U sa -P "Sistemas123*/" -d LicenciasMIG -i migrations\001_create_solicitudes.sql

# 5. Arrancar
python app.py
```

Abrir `http://localhost:89/login` con credenciales del panel viejo (`admin / admin123`).

## Deploy al VPS

```bash
# Desde local
scp -r * root@194.163.45.32:/var/www/html/LicenciasMiG/

# En el VPS
ssh root@194.163.45.32
cd /var/www/html/LicenciasMiG
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt

# Aplicar migration
sqlcmd -S localhost -U sa -P "Sistemas123*/" -d LicenciasMIG -i migrations/001_create_solicitudes.sql

# VirtualHost Apache (puerto 89)
cat > /etc/apache2/sites-available/licenciasmig-new.conf << 'EOF'
Listen 89
<VirtualHost *:89>
    ServerName 194.163.45.32
    WSGIDaemonProcess licmig-new python-home=/var/www/html/LicenciasMiG/venv python-path=/var/www/html/LicenciasMiG
    WSGIProcessGroup licmig-new
    WSGIScriptAlias / /var/www/html/LicenciasMiG/wsgi.py
    <Directory /var/www/html/LicenciasMiG>
        Require all granted
    </Directory>
    ErrorLog ${APACHE_LOG_DIR}/licmig-new-error.log
    CustomLog ${APACHE_LOG_DIR}/licmig-new-access.log combined
</VirtualHost>
EOF

a2ensite licenciasmig-new
systemctl reload apache2
```

## URLs

| URL | Para |
|---|---|
| `http://194.163.45.32:89/login` | Login del panel |
| `http://194.163.45.32:89/` | Lista de solicitudes |
| `http://194.163.45.32:89/SolicitudesService.asmx?wsdl` | WSDL para `wsdl.exe` (cliente MIG) |
| `http://194.163.45.32:89/health` | Liveness |

## Endpoints SOAP

### `RegistrarSolicitud`

Crea una solicitud nueva. El cliente MIG la llama cuando el usuario envía el form `rbfSolicitarLicencia`.

**Parámetros**: `usuario, contrasenia, nit, razonsocial, nombrecomercial, direccion, telefono, celular, departamento, ciudad, licenciatemporal, responsable, correoresponsable, telefonoresponsable, motivo, claveproducto, clavemes, nombreequipo, osversion, modulo`

**Retorno**: `OK|<SolicitudID>` o `ERROR|<mensaje>`

### `ConsultarEstadoSolicitud`

Polling del cliente para saber si ya fue aprobada.

**Parámetros**: `usuario, contrasenia, nit, claveproducto, nombreequipo`

**Retorno**: `<Estado>|<FechaResolucion>|<Observaciones>|<FechaVencimiento>`

Estados: `Pendiente | Aprobada | Rechazada | NoEncontrada | ERROR`

## Cambios necesarios en el cliente MIG

Ver `docs/CLIENTE_MIG_CHANGES.md` (próximo paso).
