Reemplaza al addon .NET Framework (SolucionLibros). Genera Devoluciones de mercancías enlazadas a sus Entradas por compra a partir de un listado pegado desde Excel. - libs/shared (@dp/shared): modelos y lógica de dominio pura (FIFO, consolidación por proveedor, parseo del portapapeles), portada del addon. - apps/api (NestJS): cliente del Service Layer con cola por sesión, login con la sesión de SAP, metadatos (UDT/UDF/UDO) y botón Reconstruir, catálogos, planificaciones (pegar, procesar, reprocesar, marcar líneas, crear Devoluciones, cerrar), listado paginado con filtros y descarga de PDF de la Guía de despacho desde BES. Sirve también la web compilada, con HTTPS opcional. - apps/web (Angular): login, Configuración → Metadatos y Planificaciones (listado, nueva, detalle). - deploy/windows y scripts/publicar.mjs: despliegue como servicio de Windows con WinSW. Verificado contra el Service Layer de SQL Server. Sin probar aún: SAP HANA y la instalación del servicio en Windows (ver CLAUDE.md, sección "Sin verificar"). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
10 KiB
Despliegue en Windows
La aplicación se ejecuta como un solo servicio de Windows: la API (NestJS) sirve también la web compilada (Angular), por HTTPS y en un único puerto. El servicio lo administra WinSW.
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 WinSW no se han ejecutado todavía en Windows (se comprobó su sintaxis y la generación del XML). Tampoco se ha probado contra HANA. Haga la primera instalación en un servidor de pruebas.
1. Requisitos del servidor
| Qué | Detalle |
|---|---|
| Windows | Windows Server 2016 o superior. |
| .NET Framework | 4.6.1 o superior (lo necesita WinSW; viene con Windows Server 2016+). |
| 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). |
| WinSW | WinSW-x64.exe de https://github.com/winsw/winsw/releases (rama 2.x). Verifique el hash que publica el proyecto. |
| 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. |
2. Publicar (en su equipo de desarrollo o en el servidor)
Desde la raíz del proyecto, con Node 22:
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
Copie toda la carpeta devolucion-proveedores a, por ejemplo, C:\apps\devolucion-proveedores:
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
├── instalar-servicio.ps1
├── desinstalar-servicio.ps1
├── devolucion-api.xml.plantilla
└── DEPLOY.md
4. Configurar el .env
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):
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 ejemploPORT=8443; entonces la URL eshttps://servidor:8443. WinSW no influye: solo arranca el servicio. HTTP_REDIRECT_PORTes opcional. Solo es útil con el 80 (la gente escribehttp://servidorsin puerto); con otro puerto solo redirige a quien escribahttp://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_ORIGINno hace falta: la web y la API comparten origen.- Con
.key/.crten vez de.pfx:HTTPS_KEY_PATHyHTTPS_CERT_PATH(no mezcle ambas formas). - Si deja el
.envcon la clave del.pfx, restrinja quién puede leerlo:
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):
$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):
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
cd C:\apps\devolucion-proveedores
.\instalar-servicio.ps1 -WinSW C:\descargas\WinSW-x64.exe
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). |
El script verifica Node 22, los archivos y el .env; genera servicio\devolucion-api.xml y
servicio\devolucion-api.exe; instala el servicio (arranque automático y reinicio si falla) y lo inicia.
8. Verificar
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
WinSW guarda lo que la API escribe por consola en logs\ (*.out.log y *.err.log), rotado por
tamaño: 10 MB y 8 archivos. La aplicación no escribe logs por su cuenta.
- 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.
10. Actualizar a una versión nueva
- Publique la versión nueva (paso 2) y copie la carpeta al servidor, por ejemplo a
C:\nueva\. - Elija una hora en que haya pocos usuarios: se perderán las sesiones.
- Ejecute:
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.
11. Desinstalar
cd C:\apps\devolucion-proveedores
.\desinstalar-servicio.ps1
Detiene y elimina el servicio. No borra archivos ni logs.
12. Seguridad
- 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
.envsi contiene la clave del.pfx(paso 4).
13. Problemas frecuentes
| Síntoma | Causa probable |
|---|---|
| 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:
- Pruebe primero con una copia de la sociedad:
DB_TYPE=HANA, Reconstruir y una ejecución completa. - Compare los resultados del FIFO con los del addon .NET para el mismo listado.
- Confirme que el Service Layer de HANA expone
/b1s/v1(el paginado usa$inlinecount).