2026-10-13 08:09:07 -05:00
# Despliegue en Windows
La aplicación se ejecuta como **un solo servicio de Windows** : la API (NestJS) sirve también la web
2026-10-13 08:55:29 -05:00
compilada (Angular), por HTTPS y en un único puerto. El servicio lo administra **NSSM** .
2026-10-13 08:09:07 -05:00
```
Navegador ──HTTPS :443──▶ servicio "DevolucionProveedores" (node dist\main.js)
├─ sirve la web (Angular compilado)
├─ /api ──▶ Service Layer de SAP B1 (:50000)
└─ /api/…/pdf ──▶ web service de BES (HTTPS)
```
No hay base de datos propia ni otros servicios: todo se guarda en SAP. Como las sesiones viven en la
memoria de la API, **reiniciar el servicio cierra la sesión de todos los usuarios** .
> **Estado de esta guía.** La carpeta publicada, la API con HTTPS, la web servida por la API, la
> redirección HTTP→HTTPS y los logs sin colores se probaron en un Mac. Los scripts de PowerShell y
2026-10-13 08:55:29 -05:00
> NSSM **no se han ejecutado todavía en Windows** (se comprobó su sintaxis y los comandos de NSSM que
> generan, con `-SoloMostrar`). Tampoco se ha probado contra HANA. Haga la primera instalación en un servidor de pruebas.
2026-10-13 08:09:07 -05:00
## 1. Requisitos del servidor
| Qué | Detalle |
|---|---|
| Windows | Windows Server 2016 o superior. |
| Node.js | **22 LTS** o superior, instalado para todos los usuarios (`node -v` en una consola nueva). |
| Red | Acceso al Service Layer de SAP (puerto 50000) y al web service de BES (HTTPS de salida). |
2026-10-13 08:55:29 -05:00
| NSSM | `nssm.exe` de 64 bits (carpeta `win64` del `.zip` de <https://nssm.cc/download>). Ver la nota de abajo sobre la versión. |
2026-10-13 08:09:07 -05:00
| Certificado | Un `.pfx` (o `.key` + `.crt` ) para el nombre con que los usuarios abrirán la página. |
| Permisos | Una consola de PowerShell **como administrador** . |
2026-10-13 08:55:29 -05:00
> **Versión de NSSM.** Descargue la compilación **2.24-101** (*pre-release*, `nssm-2.24-101-g897c7ad.zip`,
> carpeta `win64`), no la estable. La estable (2.24, de 2014) puede fallar al iniciar servicios en Windows 10
> y 11 y en Windows Server 2019 o 2022 (mensajes como `Unexpected status SERVICE_PAUSED`); solo debería
> servir en Windows Server 2016. Compruebe con `nssm version` (debe decir `2.24-101-g897c7ad`). La página
> de descargas no publica sumas de verificación: revise el `.zip` según la política de su empresa.
2026-10-13 08:09:07 -05:00
## 2. Publicar (en su equipo de desarrollo o en el servidor)
Desde la raíz del proyecto, con Node 22:
```bash
npm install
npm run publicar
```
Genera `release\devolucion-proveedores\` con la API y la web compiladas y **solo las dependencias de
producción** (unos 55 MB). Si ya compiló (`npm run build` ), use `npm run publicar -- --sin-build` .
Las dependencias de la API son JavaScript puro, así que se puede publicar desde un Mac o Linux y
ejecutar en Windows.
## 3. Copiar al servidor
2026-10-13 14:30:06 -05:00
Copie **solo** la carpeta `release\devolucion-proveedores` (no el resto del proyecto) a, por ejemplo,
`C:\apps\devolucion-proveedores` . No contiene enlaces simbólicos, así que se puede copiar por red, USB o
comprimida en un `.zip` (más rápido: son miles de archivos pequeños; en el servidor, `Expand-Archive` ).
`nssm.exe` **no** viene en la carpeta: se descarga aparte y se indica con `-Nssm` .
2026-10-13 08:09:07 -05:00
```
C:\apps\devolucion-proveedores\
├── app\ la aplicación (no se edita, salvo el .env)
│ └── apps\api\.env ← se crea en el paso 4
├── certificados\ ← el certificado HTTPS (paso 5)
├── logs\ ← los logs del servicio
2026-10-13 08:55:29 -05:00
├── servicio\ ← lo crea el instalador (copia de nssm.exe)
2026-10-13 08:09:07 -05:00
├── instalar-servicio.ps1
├── desinstalar-servicio.ps1
└── DEPLOY.md
```
## 4. Configurar el `.env`
```powershell
cd C: \ apps \ devolucion-proveedores \ app \ apps \ api
Copy-Item . env . example . env
notepad . env
```
Ejemplo para producción (HANA, HTTPS en el puerto 443 y redirección desde el 80):
```ini
PORT = 443
SL_URL = https://servidor-hana:50000/b1s/v1
SL_COMPANY_DB = NombreDeLaSociedad
SL_REJECT_UNAUTHORIZED = false
DB_TYPE = HANA
COOKIE_SECURE = true
HTTPS_PFX_PATH = C:\apps\devolucion-proveedores\certificados\sitio.pfx
HTTPS_PFX_PASSPHRASE = la-clave-del-pfx
HTTP_REDIRECT_PORT = 80
```
- **El puerto es el que ponga en `PORT` **: 443 es solo el ejemplo (con él la URL no lleva `:puerto` ). Puede
usar cualquiera que esté libre, por ejemplo `PORT=8443` ; entonces la URL es `https://servidor:8443` .
2026-10-13 08:55:29 -05:00
NSSM no influye: solo arranca el servicio.
2026-10-13 08:09:07 -05:00
- `HTTP_REDIRECT_PORT` es opcional. Solo es útil con el 80 (la gente escribe `http://servidor` sin
puerto); con otro puerto solo redirige a quien escriba `http://servidor:<ese puerto>` . Déjelo vacío si
no lo necesita.
- **No** se configura el usuario ni la contraseña de SAP: cada persona los escribe en el login.
- `WEB_ORIGIN` no hace falta: la web y la API comparten origen.
- Con `.key` /`.crt` en vez de `.pfx` : `HTTPS_KEY_PATH` y `HTTPS_CERT_PATH` (no mezcle ambas formas).
- Si deja el `.env` con la clave del `.pfx` , restrinja quién puede leerlo:
```powershell
icacls C: \ apps \ devolucion-proveedores \ app \ apps \ api \. env / inheritance : r / grant : r "Administrators:F" "SYSTEM:F"
```
(Si el servicio correrá con una cuenta propia, agréguela con `/grant:r "EMPRESA\svc-devolucion:R"` .)
## 5. Certificado HTTPS
Lo normal es un certificado de la CA de la empresa, exportado como `.pfx` a `certificados\` . Para
una **prueba** puede crear uno autofirmado (los navegadores mostrarán una advertencia):
```powershell
$c = New-SelfSignedCertificate -DnsName 'devolucion.empresa.local' -CertStoreLocation Cert : \ LocalMachine \ My -NotAfter ( Get-Date ). AddYears ( 2 )
Export-PfxCertificate -Cert $c -FilePath C: \ apps \ devolucion-proveedores \ certificados \ sitio . pfx -Password ( Read-Host -AsSecureString 'Clave del pfx' )
```
HTTPS es obligatorio: el botón *Pegar desde el portapapeles* solo funciona con `localhost` o HTTPS, y
la cookie de sesión se marca `Secure` .
## 6. Abrir el firewall
Abra **el puerto que puso en `PORT`** (y el de `HTTP_REDIRECT_PORT` , si lo usa). Con los valores del
ejemplo (443 y 80):
```powershell
New-NetFirewallRule -DisplayName 'Devolucion Proveedores HTTPS' -Direction Inbound -Protocol TCP -LocalPort 443 -Action Allow
New-NetFirewallRule -DisplayName 'Devolucion Proveedores HTTP (redireccion)' -Direction Inbound -Protocol TCP -LocalPort 80 -Action Allow
```
## 7. Instalar el servicio
```powershell
cd C: \ apps \ devolucion-proveedores
2026-10-13 08:55:29 -05:00
.\ instalar-servicio . ps1 -Nssm C: \ descargas \ nssm - 2.24 - 101 -g897c7ad \ win64 \ nssm . exe
2026-10-13 08:09:07 -05:00
```
Opciones:
| Parámetro | Para qué |
|---|---|
| `-Cuenta 'EMPRESA\svc-devolucion'` | Ejecutar con una cuenta propia en vez de `LocalSystem` . Pide la contraseña y no la guarda en ningún archivo. Esa cuenta necesita el derecho *Iniciar sesión como servicio* y lectura sobre la carpeta. |
| `-UsarCertificadosDelSistema` | Agrega `NODE_OPTIONS=--use-system-ca` . Úselo si Fortinet (u otro firewall) inspecciona el HTTPS de salida con un certificado propio y la descarga de PDF falla por certificado. |
| `-NombreServicio` | Cambia el nombre del servicio (por defecto `DevolucionProveedores` ). |
2026-10-13 08:55:29 -05:00
| `-SoloMostrar` | Imprime los comandos de NSSM que ejecutaría y termina, sin instalar nada ni exigir administrador. Úselo para revisarlos antes. |
2026-10-13 08:09:07 -05:00
2026-10-13 08:55:29 -05:00
El script verifica Node 22, los archivos y el `.env` ; copia `nssm.exe` a `servicio\` ; instala el servicio
(arranque automático, reinicio a los 10 s si Node se cae, logs a `logs\` ) y lo inicia. Si algún ajuste
falla, quita el servicio a medio configurar.
2026-10-13 08:09:07 -05:00
## 8. Verificar
```powershell
Get-Service DevolucionProveedores
Invoke-WebRequest https : // devolucion . empresa . local / api / health -UseBasicParsing
Get-Content C: \ apps \ devolucion-proveedores \ logs \*. out . log -Tail 30
```
Debe verse `{"status":"ok"}` y, en el log, la línea `Escuchando en https://0.0.0.0:443` . Después abra la
dirección en un navegador, inicie sesión con un usuario de SAP y revise **Configuración → Metadatos** .
En una base nueva pulse **Reconstruir** para crear las tablas, campos y el objeto de usuario.
## 9. Logs
2026-10-13 08:55:29 -05:00
NSSM guarda lo que la API escribe por consola en `logs\devolucion-api.out.log` y `devolucion-api.err.log` ,
y los rota al llegar a 10 MB (los rotados llevan la fecha y la hora en el nombre). La aplicación no escribe
logs por su cuenta.
**NSSM no limita cuántos archivos rotados conserva** : se acumulan. Programe una limpieza periódica, por
ejemplo una tarea que borre los de más de 30 días:
```powershell
Get-ChildItem C: \ apps \ devolucion-proveedores \ logs -Filter 'devolucion-api.*-*.log' |
Where-Object LastWriteTime -lt ( Get-Date ). AddDays ( -30 ) | Remove-Item
```
2026-10-13 08:09:07 -05:00
- Los errores 4xx/5xx de la API, los fallos y las peticiones lentas al Service Layer, y los eventos de
negocio (planificación creada, PDF descargado) quedan registrados. Las peticiones correctas no.
- Para seguirlo en vivo: `Get-Content C:\apps\devolucion-proveedores\logs\*.out.log -Wait -Tail 50` .
- La contraseña del web service DTE (`@DTE_CONFC` ) y las de los usuarios **nunca** se registran.
2026-10-13 08:55:29 -05:00
## 10. Administrar el servicio
Con `servicio\nssm.exe` (la copia que dejó el instalador):
```powershell
cd C: \ apps \ devolucion-proveedores \ servicio
.\ nssm . exe status DevolucionProveedores
.\ nssm . exe restart DevolucionProveedores
.\ nssm . exe edit DevolucionProveedores # ventana gráfica con todos los ajustes
.\ nssm . exe get DevolucionProveedores AppEnvironmentExtra
```
Para cambiar una variable de entorno del servicio con `nssm set ... AppEnvironmentExtra` , indique **todas** las
variables juntas (reemplaza la lista completa): `NODE_ENV=production NO_COLOR=1 [NODE_OPTIONS=--use-system-ca]` .
Los valores de la aplicación (puerto, SAP, HTTPS) no van aquí: se cambian en el `.env` y se reinicia el servicio.
## 11. Actualizar a una versión nueva
2026-10-13 08:09:07 -05:00
1. Publique la versión nueva (paso 2) y copie la carpeta al servidor, por ejemplo a `C:\nueva\` .
2. Elija una hora en que haya pocos usuarios: **se perderán las sesiones** .
3. Ejecute:
```powershell
Stop-Service DevolucionProveedores
# Respaldo opcional de la versión actual
Copy-Item C: \ apps \ devolucion-proveedores \ app C: \ apps \ respaldo-app -Recurse
# Copia la nueva sin tocar el .env
robocopy C: \ nueva \ devolucion-proveedores \ app C: \ apps \ devolucion-proveedores \ app / MIR / XF . env
Start-Service DevolucionProveedores
```
`/MIR` borra de `app\` lo que ya no exista en la versión nueva; `/XF .env` conserva su configuración.
Los certificados, los logs y el servicio no cambian.
2026-10-13 08:55:29 -05:00
## 12. Desinstalar
2026-10-13 08:09:07 -05:00
```powershell
cd C: \ apps \ devolucion-proveedores
.\ desinstalar-servicio . ps1
```
Detiene y elimina el servicio. No borra archivos ni logs.
2026-10-13 08:55:29 -05:00
## 13. Seguridad
2026-10-13 08:09:07 -05:00
- **No publique la aplicación en Internet.** El login es el de SAP B1; manténgala en la red interna o
detrás de una VPN.
- Use un certificado válido de la CA de la empresa; el servicio envía `Strict-Transport-Security` .
- Dele al servicio la cuenta con menos permisos posible: solo lectura sobre su carpeta y escritura en `logs\` .
- Restrinja la lectura del `.env` si contiene la clave del `.pfx` (paso 4).
2026-10-13 08:55:29 -05:00
## 14. Problemas frecuentes
2026-10-13 08:09:07 -05:00
| Síntoma | Causa probable |
|---|---|
2026-10-13 08:55:29 -05:00
| El servicio no inicia (`SERVICE_PAUSED` , `Unexpected status` ) | Problema conocido de NSSM 2.24 estable en Windows recientes: use la compilación 2.24-101 (ver el paso 1) y reinstale el servicio. |
2026-10-13 08:09:07 -05:00
| El servicio se inicia y se detiene | Mire `logs\*.err.log` . Suele ser una ruta mal escrita en el `.env` (`No se pudo leer HTTPS_PFX_PATH (…)` ) o el puerto ocupado (`EADDRINUSE` ). |
| `WEB_DIST_DIR no contiene un index.html` | Se copió la carpeta `app` incompleta: falta `app\apps\web\dist\web\browser` . |
| Puerto 443 o 80 ocupado | IIS u otro programa lo usa. Cambie `PORT` / `HTTP_REDIRECT_PORT` en el `.env` y las reglas del firewall. |
| El navegador avisa que el sitio no es seguro | Certificado autofirmado, o el nombre de la URL no coincide con el del certificado. |
| Entra al login pero vuelve a pedirlo | Con `COOKIE_SECURE=true` la cookie solo se guarda por HTTPS: abra la página por `https://` . |
| `EHOSTUNREACH` o no conecta con SAP | Red o firewall hacia el Service Layer; reinicie el servicio tras un cambio de red. |
| La descarga de PDF falla por certificado | Fortinet inspecciona el HTTPS de salida: reinstale con `-UsarCertificadosDelSistema` , o importe el certificado raíz de Fortinet en Windows. |
| Cada acción tarda decenas de segundos | Mire el log: los avisos `Petición lenta al Service Layer` indican qué llamada y cuánto tardó. |
| `.\instalar-servicio.ps1` dice que no se puede ejecutar scripts | `Set-ExecutionPolicy -Scope Process Bypass` en esa consola y vuelva a intentarlo. |
## Antes de pasar a producción (HANA)
El sistema se probó contra SQL Server (`SBOLibros` ). Con HANA:
1. Pruebe primero con una **copia** de la sociedad: `DB_TYPE=HANA` , **Reconstruir** y una ejecución completa.
2. Compare los resultados del FIFO con los del addon .NET para el mismo listado.
3. Confirme que el Service Layer de HANA expone `/b1s/v1` (el paginado usa `$inlinecount` ).