Files
devolucion_proveedores/scripts/publicar.mjs
T
georgeandClaude Sonnet 5.5 287b187c14 Aplicación web de Devolución a Proveedores para SAP Business One
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>
2026-10-13 08:09:07 -05:00

82 lines
3.6 KiB
JavaScript

// Arma una carpeta lista para copiar al servidor: release/devolucion-proveedores/
//
// npm run publicar compila todo y arma la carpeta
// npm run publicar -- --sin-build reutiliza los builds que ya existen (libs/shared/dist, apps/*/dist)
//
// Contenido: la API compilada, la web compilada y solo las dependencias de producción de la API
// (sin Angular CLI ni herramientas de desarrollo). Las dependencias de la API son JavaScript puro,
// así que se puede publicar desde un Mac o Linux y ejecutar en Windows.
import { spawnSync } from 'node:child_process';
import { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from 'node:fs';
import { dirname, join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
const raiz = resolve(dirname(fileURLToPath(import.meta.url)), '..');
const destino = join(raiz, 'release', 'devolucion-proveedores');
const app = join(destino, 'app');
const sinBuild = process.argv.includes('--sin-build');
const npm = process.platform === 'win32' ? 'npm.cmd' : 'npm';
function ejecutar(comando, args, cwd) {
console.log(`\n$ ${comando} ${args.join(' ')} (${cwd})`);
// shell: true en Windows porque npm es un .cmd
const r = spawnSync(comando, args, { cwd, stdio: 'inherit', shell: process.platform === 'win32' });
if (r.status !== 0) {
console.error(`\nFalló: ${comando} ${args.join(' ')}`);
process.exit(r.status ?? 1);
}
}
function copiar(origen, destinoRelativo) {
const desde = join(raiz, origen);
if (!existsSync(desde)) {
console.error(`Falta ${origen}. Ejecute "npm run publicar" sin --sin-build (o "npm run build" antes).`);
process.exit(1);
}
cpSync(desde, join(app, destinoRelativo ?? origen), { recursive: true });
}
function tamano(carpeta) {
let total = 0;
for (const e of readdirSync(carpeta, { withFileTypes: true, recursive: true })) {
if (e.isFile()) total += statSync(join(e.parentPath, e.name)).size;
}
return `${(total / 1024 / 1024).toFixed(1)} MB`;
}
console.log('Publicando Devolución a Proveedores');
if (!sinBuild) ejecutar(npm, ['run', 'build'], raiz);
rmSync(destino, { recursive: true, force: true });
mkdirSync(app, { recursive: true });
// Lo mínimo para que `npm ci` resuelva los mismos paquetes del package-lock: el package.json raíz
// y el de cada workspace (la web no se instala, pero debe estar declarada para que el lock coincida).
copiar('package.json');
copiar('package-lock.json');
copiar('libs/shared/package.json');
copiar('libs/shared/dist');
copiar('apps/api/package.json');
copiar('apps/api/dist');
copiar('apps/api/.env.example');
copiar('apps/web/package.json');
copiar('apps/web/dist/web/browser');
ejecutar(npm, ['ci', '--omit=dev', '--workspace=@dp/shared', '--workspace=api', '--no-audit', '--no-fund'], app);
// Archivos de despliegue para Windows junto a la carpeta app/
for (const archivo of readdirSync(join(raiz, 'deploy', 'windows'))) {
cpSync(join(raiz, 'deploy', 'windows', archivo), join(destino, archivo));
}
for (const carpeta of ['logs', 'certificados']) mkdirSync(join(destino, carpeta), { recursive: true });
writeFileSync(join(destino, 'certificados', 'LEEME.txt'), 'Ponga aquí el certificado HTTPS (.pfx, o .key y .crt) y apunte el .env a estos archivos.\n');
const version = JSON.parse(readFileSync(join(raiz, 'package.json'), 'utf8')).name;
writeFileSync(
join(destino, 'VERSION.txt'),
`${version}\nPublicado: ${new Date().toISOString()}\nNode de la publicación: ${process.version}\nSistema: ${process.platform}\n`,
);
console.log(`\nListo: ${destino} (${tamano(destino)})`);
console.log('Siguiente paso: copie esa carpeta al servidor y siga DEPLOY.md.');