Script Python que genera Manual_Instalacion.docx con: - Portada y requisitos - Instalacion paso a paso (ejecutar como administrador) - Configuracion .env - Primer uso y FAQ Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
430 lines
17 KiB
Python
Executable File
430 lines
17 KiB
Python
Executable File
"""
|
|
Genera el manual de instalación y primeros pasos de Utilerías RECON 2.
|
|
"""
|
|
from docx import Document
|
|
from docx.shared import Pt, RGBColor, Cm
|
|
from docx.enum.text import WD_ALIGN_PARAGRAPH
|
|
from docx.oxml.ns import qn
|
|
from docx.oxml import OxmlElement
|
|
import datetime, os
|
|
|
|
doc = Document()
|
|
|
|
for sec in doc.sections:
|
|
sec.top_margin = Cm(2.5)
|
|
sec.bottom_margin = Cm(2.5)
|
|
sec.left_margin = Cm(2.2)
|
|
sec.right_margin = Cm(2.2)
|
|
|
|
style = doc.styles['Normal']
|
|
style.font.name = 'Calibri'
|
|
style.font.size = Pt(11)
|
|
|
|
|
|
# ── Helpers ──────────────────────────────────────────────────────────────────
|
|
def h1(text):
|
|
p = doc.add_heading(text, level=1)
|
|
for r in p.runs: r.font.color.rgb = RGBColor(0x15, 0x65, 0xC0)
|
|
|
|
def h2(text):
|
|
p = doc.add_heading(text, level=2)
|
|
for r in p.runs: r.font.color.rgb = RGBColor(0x1E, 0x88, 0xE5)
|
|
|
|
def h3(text):
|
|
p = doc.add_heading(text, level=3)
|
|
for r in p.runs: r.font.color.rgb = RGBColor(0x42, 0xA5, 0xF5)
|
|
|
|
def parr(text, bold=False):
|
|
p = doc.add_paragraph()
|
|
r = p.add_run(text)
|
|
r.bold = bold
|
|
return p
|
|
|
|
def code_block(text):
|
|
p = doc.add_paragraph()
|
|
p.paragraph_format.left_indent = Cm(0.4)
|
|
r = p.add_run(text)
|
|
r.font.name = 'Consolas'
|
|
r.font.size = Pt(9.5)
|
|
pPr = p._p.get_or_add_pPr()
|
|
shd = OxmlElement('w:shd')
|
|
shd.set(qn('w:val'), 'clear')
|
|
shd.set(qn('w:color'), 'auto')
|
|
shd.set(qn('w:fill'), 'F0F0F0')
|
|
pPr.append(shd)
|
|
return p
|
|
|
|
def bullet(text, level=0):
|
|
p = doc.add_paragraph(text, style='List Bullet')
|
|
p.paragraph_format.left_indent = Cm(0.6 + level * 0.6)
|
|
return p
|
|
|
|
def numbered(text):
|
|
p = doc.add_paragraph(text, style='List Number')
|
|
p.paragraph_format.left_indent = Cm(0.6)
|
|
return p
|
|
|
|
def nota(titulo, text):
|
|
p = doc.add_paragraph()
|
|
p.paragraph_format.left_indent = Cm(0.4)
|
|
pPr = p._p.get_or_add_pPr()
|
|
shd = OxmlElement('w:shd')
|
|
shd.set(qn('w:val'), 'clear'); shd.set(qn('w:color'), 'auto')
|
|
shd.set(qn('w:fill'), 'FFF8E1')
|
|
pPr.append(shd)
|
|
r = p.add_run(titulo + ': '); r.bold = True
|
|
r.font.color.rgb = RGBColor(0xE6, 0x5C, 0x00)
|
|
p.add_run(text)
|
|
|
|
def alerta(titulo, text):
|
|
p = doc.add_paragraph()
|
|
p.paragraph_format.left_indent = Cm(0.4)
|
|
pPr = p._p.get_or_add_pPr()
|
|
shd = OxmlElement('w:shd')
|
|
shd.set(qn('w:val'), 'clear'); shd.set(qn('w:color'), 'auto')
|
|
shd.set(qn('w:fill'), 'FFEBEE')
|
|
pPr.append(shd)
|
|
r = p.add_run(titulo + ': '); r.bold = True
|
|
r.font.color.rgb = RGBColor(0xC6, 0x28, 0x28)
|
|
p.add_run(text)
|
|
|
|
def tip(titulo, text):
|
|
p = doc.add_paragraph()
|
|
p.paragraph_format.left_indent = Cm(0.4)
|
|
pPr = p._p.get_or_add_pPr()
|
|
shd = OxmlElement('w:shd')
|
|
shd.set(qn('w:val'), 'clear'); shd.set(qn('w:color'), 'auto')
|
|
shd.set(qn('w:fill'), 'E8F5E9')
|
|
pPr.append(shd)
|
|
r = p.add_run(titulo + ': '); r.bold = True
|
|
r.font.color.rgb = RGBColor(0x2E, 0x7D, 0x32)
|
|
p.add_run(text)
|
|
|
|
def table_simple(headers, rows, col_widths_cm=None):
|
|
t = doc.add_table(rows=1 + len(rows), cols=len(headers))
|
|
t.style = 'Light Grid Accent 1'
|
|
hdr = t.rows[0].cells
|
|
for i, h in enumerate(headers):
|
|
hdr[i].text = h
|
|
for p in hdr[i].paragraphs:
|
|
for r in p.runs:
|
|
r.bold = True
|
|
r.font.color.rgb = RGBColor(0xFF, 0xFF, 0xFF)
|
|
tcPr = hdr[i]._tc.get_or_add_tcPr()
|
|
shd = OxmlElement('w:shd')
|
|
shd.set(qn('w:val'), 'clear')
|
|
shd.set(qn('w:fill'), '1565C0')
|
|
tcPr.append(shd)
|
|
for r_idx, row in enumerate(rows, start=1):
|
|
cells = t.rows[r_idx].cells
|
|
for c_idx, val in enumerate(row):
|
|
cells[c_idx].text = str(val)
|
|
if col_widths_cm:
|
|
for i, w in enumerate(col_widths_cm):
|
|
for row in t.rows:
|
|
row.cells[i].width = Cm(w)
|
|
return t
|
|
|
|
|
|
# ── PORTADA ───────────────────────────────────────────────────────────────────
|
|
title = doc.add_paragraph()
|
|
title.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
|
r = title.add_run('\n\n\nSistema de Utilerías RECON 2')
|
|
r.bold = True; r.font.size = Pt(34); r.font.color.rgb = RGBColor(0x15, 0x65, 0xC0)
|
|
|
|
sub = doc.add_paragraph()
|
|
sub.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
|
r = sub.add_run('Guía de Instalación y Primeros Pasos')
|
|
r.font.size = Pt(20); r.font.color.rgb = RGBColor(0x42, 0xA5, 0xF5)
|
|
|
|
p = doc.add_paragraph()
|
|
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
|
r = p.add_run(f'\n\nVersión {datetime.date.today().isoformat()}')
|
|
r.font.size = Pt(12); r.italic = True
|
|
|
|
doc.add_page_break()
|
|
|
|
|
|
# ── ÍNDICE ────────────────────────────────────────────────────────────────────
|
|
h1('Contenido')
|
|
for item in [
|
|
'1. Requisitos previos',
|
|
'2. Instalación paso a paso',
|
|
'3. Configuración inicial (.env)',
|
|
'4. Primer uso de la aplicación',
|
|
'5. Preguntas frecuentes',
|
|
]:
|
|
doc.add_paragraph(item)
|
|
|
|
doc.add_page_break()
|
|
|
|
|
|
# ── 1. REQUISITOS ─────────────────────────────────────────────────────────────
|
|
h1('1. Requisitos previos')
|
|
parr('Antes de instalar, verifica que la computadora cumple con lo siguiente:')
|
|
|
|
table_simple(
|
|
['Requisito', 'Detalle'],
|
|
[
|
|
['Sistema operativo', 'Windows 10 / Windows 11 (64 bits)'],
|
|
['Permisos', 'Cuenta con permisos de Administrador local'],
|
|
['ODBC Driver', 'Microsoft ODBC Driver 17 o 18 for SQL Server'],
|
|
['Acceso a red', 'Conexión al servidor donde está la base de datos SCAII'],
|
|
['Espacio en disco', 'Mínimo 500 MB libres en la unidad de instalación'],
|
|
],
|
|
col_widths_cm=[4.5, 11]
|
|
)
|
|
|
|
doc.add_paragraph()
|
|
alerta(
|
|
'IMPORTANTE — Permisos de Administrador',
|
|
'La aplicación DEBE instalarse y ejecutarse como Administrador. '
|
|
'Sin este permiso, el instalador no podrá registrar los componentes necesarios '
|
|
'y la aplicación fallará al intentar conectarse a la base de datos.'
|
|
)
|
|
|
|
doc.add_paragraph()
|
|
h3('Cómo verificar si tienes el ODBC Driver instalado')
|
|
numbered('Presiona Windows + R, escribe odbcad32 y presiona Enter')
|
|
numbered('En la pestaña "Controladores" busca "ODBC Driver 17 for SQL Server" o "ODBC Driver 18 for SQL Server"')
|
|
numbered('Si no aparece, solicita al área de sistemas que lo instale antes de continuar')
|
|
|
|
|
|
# ── 2. INSTALACIÓN ────────────────────────────────────────────────────────────
|
|
doc.add_page_break()
|
|
h1('2. Instalación paso a paso')
|
|
|
|
alerta(
|
|
'Ejecutar como Administrador',
|
|
'Todos los pasos de esta sección deben realizarse con permisos de Administrador. '
|
|
'Si no lo haces, la instalación puede completarse pero la aplicación no funcionará correctamente.'
|
|
)
|
|
|
|
doc.add_paragraph()
|
|
h2('Paso 1 — Obtener el instalador')
|
|
parr('El archivo instalador tiene un nombre similar a:')
|
|
code_block('UtileriasReconV2_Setup.exe')
|
|
parr('Solicítalo al área técnica o descárgalo de la ubicación que te indiquen.')
|
|
|
|
doc.add_paragraph()
|
|
h2('Paso 2 — Ejecutar el instalador como Administrador')
|
|
numbered('Localiza el archivo UtileriasReconV2_Setup.exe en tu computadora')
|
|
numbered('Haz clic derecho sobre el archivo')
|
|
numbered('Selecciona "Ejecutar como administrador"')
|
|
numbered('Si Windows muestra una ventana de Control de Cuentas de Usuario (UAC), haz clic en "Sí"')
|
|
|
|
doc.add_paragraph()
|
|
nota(
|
|
'Clic derecho → Ejecutar como administrador',
|
|
'Es fundamental este paso. Si haces doble clic normal y tu cuenta no es administrador, '
|
|
'la instalación puede parecer exitosa pero la app fallará al abrir.'
|
|
)
|
|
|
|
doc.add_paragraph()
|
|
h2('Paso 3 — Seguir el asistente de instalación')
|
|
numbered('Se abre el asistente de instalación. Haz clic en "Siguiente"')
|
|
numbered('Lee y acepta los términos de uso, luego haz clic en "Siguiente"')
|
|
numbered('Elige la carpeta de instalación (se recomienda dejar la carpeta predeterminada)')
|
|
code_block('C:\\Program Files\\UtileriasReconV2\\')
|
|
numbered('Haz clic en "Instalar" y espera a que termine el proceso (tarda aproximadamente 1-2 minutos)')
|
|
numbered('Al terminar, haz clic en "Finalizar"')
|
|
|
|
tip(
|
|
'Carpeta de instalación',
|
|
'Si instalas en una ruta diferente a la predeterminada, anota la ruta. '
|
|
'La necesitarás para el paso de configuración.'
|
|
)
|
|
|
|
doc.add_paragraph()
|
|
h2('Paso 4 — Verificar la instalación')
|
|
parr('Al finalizar, deberías ver en la carpeta de instalación los siguientes archivos principales:')
|
|
table_simple(
|
|
['Archivo / Carpeta', 'Descripción'],
|
|
[
|
|
['UtileriasReconV2.exe', 'El ejecutable principal de la aplicación'],
|
|
['app.ipynb', 'El notebook con toda la lógica de la app'],
|
|
['.env.example', 'Plantilla de configuración — debes renombrarlo a .env'],
|
|
['_internal/', 'Carpeta con dependencias internas (no modificar)'],
|
|
],
|
|
col_widths_cm=[5, 10]
|
|
)
|
|
|
|
|
|
# ── 3. CONFIGURACIÓN ─────────────────────────────────────────────────────────
|
|
doc.add_page_break()
|
|
h1('3. Configuración inicial (.env)')
|
|
|
|
parr(
|
|
'La aplicación usa un archivo llamado .env para saber a qué servidor conectarse '
|
|
'y con qué credenciales. Este archivo NO viene incluido en el instalador por seguridad — '
|
|
'debes crearlo tú a partir de la plantilla.'
|
|
)
|
|
|
|
doc.add_paragraph()
|
|
h2('Crear el archivo .env')
|
|
numbered('Ve a la carpeta de instalación')
|
|
numbered('Localiza el archivo .env.example')
|
|
numbered('Copia ese archivo y renombra la copia como .env (sin el .example)')
|
|
numbered('Abre el archivo .env con el Bloc de notas o cualquier editor de texto')
|
|
numbered('Modifica los valores según los datos de tu servidor:')
|
|
|
|
doc.add_paragraph()
|
|
code_block(
|
|
'# Servidor SCAII (SQL Server)\n'
|
|
'SCAII_SERVER=nombre-o-ip-de-tu-servidor\n'
|
|
'SCAII_USER=tu_usuario\n'
|
|
'SCAII_PASSWORD=tu_contraseña\n'
|
|
'\n'
|
|
'# Autenticación Windows (opcional)\n'
|
|
'# Si tu servidor usa Windows Auth en lugar de usuario/contraseña,\n'
|
|
'# cambia el valor a "yes"\n'
|
|
'SCAII_TRUSTED=no\n'
|
|
'\n'
|
|
'# Ruta donde están los archivos .asc del DataStage\n'
|
|
'DATASTAGE_PATH=C:\\ruta\\a\\tus\\archivos\\asc\n'
|
|
)
|
|
|
|
nota(
|
|
'Archivo sensible',
|
|
'El archivo .env contiene contraseñas. No lo compartas por correo ni lo subas a ningún '
|
|
'repositorio. Mantenlo solo en la computadora de trabajo.'
|
|
)
|
|
|
|
doc.add_paragraph()
|
|
h2('Autenticación Windows vs. usuario y contraseña')
|
|
table_simple(
|
|
['Escenario', 'Configuración en .env'],
|
|
[
|
|
['Tu servidor pide usuario y contraseña de SQL Server',
|
|
'SCAII_TRUSTED=no\nSCAII_USER=sa\nSCAII_PASSWORD=TuContraseña'],
|
|
['Tu servidor usa Windows Authentication (credenciales de Windows)',
|
|
'SCAII_TRUSTED=yes\n(SCAII_USER y SCAII_PASSWORD se ignoran)'],
|
|
],
|
|
col_widths_cm=[6, 9]
|
|
)
|
|
|
|
|
|
# ── 4. PRIMER USO ─────────────────────────────────────────────────────────────
|
|
doc.add_page_break()
|
|
h1('4. Primer uso de la aplicación')
|
|
|
|
alerta(
|
|
'Ejecutar como Administrador',
|
|
'Cada vez que abras la aplicación, hazlo con clic derecho → '
|
|
'"Ejecutar como administrador". De lo contrario puede fallar la conexión a la base de datos.'
|
|
)
|
|
|
|
doc.add_paragraph()
|
|
h2('Abrir la aplicación')
|
|
numbered('Localiza el acceso directo en el escritorio o ve a la carpeta de instalación')
|
|
numbered('Haz clic derecho sobre UtileriasReconV2.exe')
|
|
numbered('Selecciona "Ejecutar como administrador"')
|
|
numbered('Aparece una ventana negra de consola — NO la cierres, es normal')
|
|
numbered('Después de unos segundos, tu navegador (Edge o Chrome) abre automáticamente la aplicación')
|
|
|
|
tip(
|
|
'Si el navegador no abre solo',
|
|
'Escribe manualmente en la barra de direcciones: http://127.0.0.1:8866/'
|
|
)
|
|
|
|
doc.add_paragraph()
|
|
nota(
|
|
'La consola negra',
|
|
'La ventana negra debe permanecer abierta todo el tiempo que uses la aplicación. '
|
|
'Si la cierras, la app se apaga. Cuando termines de trabajar, primero cierra el '
|
|
'navegador y luego cierra la consola.'
|
|
)
|
|
|
|
doc.add_paragraph()
|
|
h2('Verificar la conexión a la base de datos')
|
|
parr(
|
|
'Al cargar la aplicación, en la parte superior verás una barra de estado. '
|
|
'Su color te indica si la conexión es correcta:'
|
|
)
|
|
table_simple(
|
|
['Color de la barra', 'Significado'],
|
|
[
|
|
['Azul / Verde', 'Conexión exitosa. Puedes trabajar normalmente.'],
|
|
['Rojo', 'Error de conexión. Revisa el archivo .env y que el servidor esté disponible.'],
|
|
],
|
|
col_widths_cm=[4, 11]
|
|
)
|
|
|
|
doc.add_paragraph()
|
|
h2('Navegar por las pestañas')
|
|
parr('La aplicación tiene varias pestañas en la parte superior. Cada una corresponde a una función:')
|
|
table_simple(
|
|
['Pestaña', 'Para qué sirve'],
|
|
[
|
|
['Conexión / Config', 'Seleccionar la base de datos activa y ver el estado de la conexión'],
|
|
['Descargas', 'Generar y complementar descargas de inventario contra facturas'],
|
|
['Análisis de Saldos', 'Ver el estado del inventario: saldos, comparativos, exportar a Excel'],
|
|
['Sustitutos NLP', 'Sugerir automáticamente números de parte similares'],
|
|
['Descarga % KGS', 'Descargas basadas en porcentaje de peso (BOMs con cantidades en %)'],
|
|
['DataStage', 'Cargar archivos .asc del SAAIM3 y generar estructuras SCAII'],
|
|
['Estructuras SCAII', 'Generar los Excel de partidas y encabezados para importar en SCAII'],
|
|
],
|
|
col_widths_cm=[4, 11]
|
|
)
|
|
|
|
|
|
# ── 5. FAQ ────────────────────────────────────────────────────────────────────
|
|
doc.add_page_break()
|
|
h1('5. Preguntas frecuentes')
|
|
|
|
h3('¿Por qué tengo que ejecutarlo como Administrador?')
|
|
parr(
|
|
'La aplicación necesita permisos de administrador para dos cosas: '
|
|
'(1) conectarse al servidor de SQL Server a través del driver ODBC, y '
|
|
'(2) escribir los archivos temporales que genera Jupyter internamente. '
|
|
'Sin estos permisos, la app puede abrir visualmente pero falla al intentar '
|
|
'cualquier operación con la base de datos.'
|
|
)
|
|
|
|
doc.add_paragraph()
|
|
h3('¿Puedo instalarla sin ser administrador?')
|
|
parr(
|
|
'No. El instalador requiere privilegios de administrador para registrar los '
|
|
'componentes de Jupyter y el driver ODBC. Si no tienes estos permisos en tu '
|
|
'equipo, solicita al área de sistemas que haga la instalación.'
|
|
)
|
|
|
|
doc.add_paragraph()
|
|
h3('La app abre pero dice "Error de conexión"')
|
|
bullet('Verifica que el archivo .env existe en la carpeta de instalación (no solo .env.example)')
|
|
bullet('Revisa que el servidor SCAII_SERVER sea correcto (nombre o IP)')
|
|
bullet('Confirma que el usuario y contraseña sean correctos')
|
|
bullet('Asegúrate de que el servidor SQL Server esté encendido y accesible desde tu red')
|
|
bullet('Si usas Windows Auth (SCAII_TRUSTED=yes), verifica que tu usuario de Windows tenga acceso al servidor')
|
|
|
|
doc.add_paragraph()
|
|
h3('¿Cómo sé que la instalación fue exitosa?')
|
|
parr('Si puedes abrir la app como Administrador y la barra superior muestra azul o verde sin errores, '
|
|
'la instalación está correcta.')
|
|
|
|
doc.add_paragraph()
|
|
h3('¿Tengo que instalarla cada vez que actualicen la app?')
|
|
parr(
|
|
'Depende del tipo de actualización. Si el área técnica entrega un nuevo instalador '
|
|
'(.exe de setup), sí hay que reinstalar. Si solo entregan un nuevo archivo app.ipynb, '
|
|
'basta con reemplazar ese archivo en la carpeta de instalación sin reinstalar todo.'
|
|
)
|
|
|
|
doc.add_paragraph()
|
|
alerta(
|
|
'Soporte',
|
|
'Para cualquier problema de instalación o configuración que no esté cubierto en este manual, '
|
|
'contacta al área técnica de Aduanasoft.'
|
|
)
|
|
|
|
|
|
# ── GUARDAR ───────────────────────────────────────────────────────────────────
|
|
out_path = 'Manual_Instalacion.docx'
|
|
try:
|
|
doc.save(out_path)
|
|
except PermissionError:
|
|
out_path = f'Manual_Instalacion_{datetime.datetime.now().strftime("%Y%m%d_%H%M%S")}.docx'
|
|
doc.save(out_path)
|
|
print('(El anterior estaba abierto en Word. Generado con nombre alternativo.)')
|
|
print(f'Manual generado: {os.path.abspath(out_path)}')
|