Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' # Genera un DOCX válido (Office Open XML) con formato tipo presentación # Uso: # powershell -ExecutionPolicy Bypass -File tools\generate_presentacion_docx.ps1 $baseDir = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path $outFile = Join-Path $baseDir 'Presentacion_ERP_para_cliente.docx' function Escape-Xml([string]$text) { if ($null -eq $text) { return '' } return [System.Security.SecurityElement]::Escape($text) } function W-Paragraph([string]$text, [bool]$Bold = $false, [int]$Size = 22, [int]$After = 120, [string]$Align = 'left') { $rPr = '' if ($Bold) { $rPr += '' } $rPr += "" $pPrAlign = '' switch ($Align) { 'center' { $pPrAlign = '' } 'right' { $pPrAlign = '' } Default { $pPrAlign = '' } } $lines = $text -split "\r\n|\r|\n" $runs = New-Object System.Text.StringBuilder for ($i = 0; $i -lt $lines.Length; $i++) { if ($i -gt 0) { [void]$runs.Append('') } $escaped = Escape-Xml $lines[$i] [void]$runs.Append('') [void]$runs.Append($escaped) [void]$runs.Append('') } return "$pPrAlign$rPr$($runs.ToString())" } function Title([string]$text) { W-Paragraph -text $text -Bold $true -Size 44 -After 240 -Align 'center' } function Subtitle([string]$text) { W-Paragraph -text $text -Bold $false -Size 26 -After 180 -Align 'center' } function H1([string]$text) { W-Paragraph -text $text -Bold $true -Size 34 -After 160 } function H2([string]$text) { W-Paragraph -text $text -Bold $true -Size 28 -After 120 } function Bullet([string]$text) { W-Paragraph -text ("• " + $text) -Bold $false -Size 24 -After 80 } function PageBreak() { return '' } # Contenido basado en menu.php $modulos = @( [pscustomobject]@{ Nombre = 'Facturación' Pantallas = @('Facturas', 'Clientes', 'Reporte de facturas') Enfoque = @( 'Emisión y control de facturas de venta.', 'Consulta por periodos y por cliente.', 'Soporte de reportes con exportación e impresión.' ) }, [pscustomobject]@{ Nombre = 'Inventario' Pantallas = @('Artículos', 'Categorías', 'Unidades de medida', 'Almacenes', 'Movimientos', 'Reporte general de artículos') Enfoque = @( 'Catálogo de productos y clasificación por categorías.', 'Control de existencias por almacén y movimientos.', 'Estandarización con unidades de medida y reportes.' ) }, [pscustomobject]@{ Nombre = 'Clientes y Cuentas por Cobrar (CXC)' Pantallas = @('Clientes', 'Cargos a clientes', 'Pago de clientes', 'Estado de cuenta', 'Notas de crédito', 'Antigüedad de saldos', 'Reportes') Enfoque = @( 'Gestión integral de cartera: cargos, cobros y notas de crédito.', 'Estado de cuenta por cliente y seguimiento de saldos.', 'Antigüedad para control de mora y cobranza.' ) }, [pscustomobject]@{ Nombre = 'Proveedores y Cuentas por Pagar (CXP)' Pantallas = @('Proveedores', 'Cargos a proveedores', 'Pagos a proveedores', 'Estado de cuenta', 'Notas de crédito', 'Antigüedad de saldos', 'Reportes') Enfoque = @( 'Control de compromisos: cargos, pagos y notas de crédito.', 'Estado de cuenta por proveedor y planeación de pagos.', 'Antigüedad para priorizar obligaciones.' ) }, [pscustomobject]@{ Nombre = 'Compras' Pantallas = @('Cotizaciones', 'Órdenes de compra', 'Compras de mercancías', 'Proveedores', 'Reporte de compras') Enfoque = @( 'Proceso de compras desde cotización hasta orden de compra.', 'Registro de compras y trazabilidad por proveedor.', 'Reportes para análisis de compras.' ) }, [pscustomobject]@{ Nombre = 'Gastos' Pantallas = @('Registro de gastos', 'Reporte de gastos') Enfoque = @( 'Registro y clasificación de gastos operativos.', 'Reportes para análisis y control presupuestario.' ) }, [pscustomobject]@{ Nombre = 'Bancos' Pantallas = @('Bancos/Disponibilidad', 'Cuentas bancarias', 'Movimientos bancarios', 'Conciliación bancaria', 'Extractos', 'Importar extracto', 'Cheques', 'Reporte conciliación') Enfoque = @( 'Control de movimientos bancarios y disponibilidad.', 'Conciliación bancaria contra extractos (importación y revisión).', 'Soporte de cheques y reportes de conciliación.' ) }, [pscustomobject]@{ Nombre = 'Contabilidad' Pantallas = @('Contabilidad general') Enfoque = @( 'Registro y control contable (según configuración del sistema).', 'Soporte para reportes financieros y análisis de gestión.' ) }, [pscustomobject]@{ Nombre = 'Activos Fijos' Pantallas = @('Activos fijos', 'Depreciación de activos') Enfoque = @( 'Registro, control y seguimiento de activos.', 'Cálculo y control de depreciación.' ) }, [pscustomobject]@{ Nombre = 'Nómina y RRHH' Pantallas = @('Nómina y Recursos Humanos') Enfoque = @( 'Gestión de procesos de nómina y personal (según parametrización).' ) }, [pscustomobject]@{ Nombre = 'Administración' Pantallas = @('Usuarios', 'Empresa', 'Configuración', 'Impuestos') Enfoque = @( 'Gestión de usuarios/roles y parámetros por empresa.', 'Configuración de impuestos y reglas generales.' ) }, [pscustomobject]@{ Nombre = 'Reportes' Pantallas = @('Módulo de reportes') Enfoque = @( 'Reportes exportables a Excel e impresión para control y auditoría.' ) } ) $today = Get-Date -Format 'yyyy-MM-dd' $docParts = New-Object System.Collections.Generic.List[string] # Portada $docParts.Add((Title 'Presentación Comercial – Sistema ERP')) | Out-Null $docParts.Add((Subtitle 'Módulos, procesos y beneficios principales')) | Out-Null $docParts.Add((W-Paragraph -text ("Fecha: $today") -Size 22 -After 180 -Align 'center')) | Out-Null $docParts.Add((W-Paragraph -text 'Objetivo: presentar el alcance funcional del ERP para apoyar una decisión de compra.' -Size 22 -After 200 -Align 'center')) | Out-Null $docParts.Add((PageBreak)) | Out-Null # Agenda $docParts.Add((H1 'Agenda')) | Out-Null $docParts.Add((Bullet 'Visión general del ERP')) | Out-Null $docParts.Add((Bullet 'Módulos principales (uno por sección)')) | Out-Null $docParts.Add((Bullet 'Flujos clave: ventas/cobranza, compras/pagos, inventario, bancos/conciliación')) | Out-Null $docParts.Add((Bullet 'Beneficios y siguientes pasos')) | Out-Null $docParts.Add((PageBreak)) | Out-Null # Visión general $docParts.Add((H1 'Visión General')) | Out-Null $docParts.Add((Bullet 'Plataforma integrada para operación y finanzas: ventas, compras, inventario, cartera, proveedores, bancos, contabilidad, activos y RRHH.')) | Out-Null $docParts.Add((Bullet 'Centraliza información y reduce reprocesos (una sola fuente de datos).')) | Out-Null $docParts.Add((Bullet 'Reportes exportables e impresión para control y toma de decisiones.')) | Out-Null $docParts.Add((PageBreak)) | Out-Null # Módulos foreach ($m in $modulos) { $docParts.Add((H1 $m.Nombre)) | Out-Null $docParts.Add((H2 'Pantallas principales')) | Out-Null foreach ($p in $m.Pantallas) { $docParts.Add((Bullet $p)) | Out-Null } $docParts.Add((H2 'Qué resuelve / beneficios')) | Out-Null foreach ($e in $m.Enfoque) { $docParts.Add((Bullet $e)) | Out-Null } $docParts.Add((PageBreak)) | Out-Null } # Flujos $docParts.Add((H1 'Flujos Clave del Sistema')) | Out-Null $docParts.Add((H2 'Ventas y cobranza')) | Out-Null $docParts.Add((Bullet 'Cliente → Factura → Cobro/Aplicación → Estado de cuenta → Antigüedad de saldos')) | Out-Null $docParts.Add((H2 'Compras y pagos')) | Out-Null $docParts.Add((Bullet 'Proveedor → Cotización/OC → Compra/Cargo → Pago → Estado de cuenta → Antigüedad')) | Out-Null $docParts.Add((H2 'Inventario')) | Out-Null $docParts.Add((Bullet 'Artículos/Almacenes → Movimientos → Reportes de existencias')) | Out-Null $docParts.Add((H2 'Bancos y conciliación')) | Out-Null $docParts.Add((Bullet 'Movimientos → Extractos (importación) → Conciliación → Reporte')) | Out-Null $docParts.Add((PageBreak)) | Out-Null # Cierre $docParts.Add((H1 'Siguiente Paso')) | Out-Null $docParts.Add((Bullet 'Demostración guiada con escenarios reales del cliente.')) | Out-Null $docParts.Add((Bullet 'Validación de alcance y parametrización inicial.')) | Out-Null $docParts.Add((Bullet 'Plan de implementación (migración, capacitación, puesta en marcha).')) | Out-Null $documentXml = @" $($docParts -join "") "@ $contentTypes = @" "@ $rels = @" "@ $docRels = @" "@ $created = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ") $core = @" Presentación Comercial – Sistema ERP ERP ERP $created $created "@ $app = @" ERP "@ $tmpRoot = Join-Path $baseDir 'tools\._tmp_docx_presentacion' if (Test-Path $tmpRoot) { Remove-Item -Recurse -Force $tmpRoot } New-Item -ItemType Directory -Force -Path (Join-Path $tmpRoot '_rels') | Out-Null New-Item -ItemType Directory -Force -Path (Join-Path $tmpRoot 'word\_rels') | Out-Null New-Item -ItemType Directory -Force -Path (Join-Path $tmpRoot 'docProps') | Out-Null $utf8NoBom = New-Object System.Text.UTF8Encoding($false) [System.IO.File]::WriteAllText((Join-Path $tmpRoot '[Content_Types].xml'), $contentTypes, $utf8NoBom) [System.IO.File]::WriteAllText((Join-Path $tmpRoot '_rels\.rels'), $rels, $utf8NoBom) [System.IO.File]::WriteAllText((Join-Path $tmpRoot 'word\document.xml'), $documentXml, $utf8NoBom) [System.IO.File]::WriteAllText((Join-Path $tmpRoot 'word\_rels\document.xml.rels'), $docRels, $utf8NoBom) [System.IO.File]::WriteAllText((Join-Path $tmpRoot 'docProps\core.xml'), $core, $utf8NoBom) [System.IO.File]::WriteAllText((Join-Path $tmpRoot 'docProps\app.xml'), $app, $utf8NoBom) Add-Type -AssemblyName System.IO.Compression.FileSystem if (Test-Path $outFile) { Remove-Item -Force $outFile } [System.IO.Compression.ZipFile]::CreateFromDirectory($tmpRoot, $outFile) Remove-Item -Recurse -Force $tmpRoot Write-Host "OK: DOCX generado en: $outFile"