Refactor(ADN): Migración de tools/adn a adn/tools en busca de la Armonía Integral del DIIAA
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'date'
|
||||
|
||||
module BitacorasDB
|
||||
module Exporters
|
||||
class MDExporter
|
||||
def initialize(db, logger = nil)
|
||||
@db = db
|
||||
@logger = logger || default_logger
|
||||
end
|
||||
|
||||
def exportar_bitacora(fecha, ruta_destino)
|
||||
@logger.info("Exportando bitácora #{fecha} a #{ruta_destino}...")
|
||||
|
||||
bitacora = @db.find_bitacora_by_fecha(fecha)
|
||||
unless bitacora
|
||||
@logger.error("No se encontró la bitácora para la fecha: #{fecha}")
|
||||
return false
|
||||
end
|
||||
|
||||
bitacora_id = bitacora['id']
|
||||
|
||||
# Obtener datos estructurados (incluyendo lo nuevo)
|
||||
entradas = @db.execute("
|
||||
SELECT e.*, n.nombre as nodo_nombre
|
||||
FROM bitacoras.entradas e
|
||||
LEFT JOIN bitacoras.nodos n ON e.nodo_id = n.id
|
||||
WHERE e.bitacora_id = $1
|
||||
ORDER BY n.nombre, e.inicio ASC
|
||||
", [bitacora_id])
|
||||
|
||||
gestion = @db.execute("
|
||||
SELECT g.*, n.nombre as nodo_nombre
|
||||
FROM bitacoras.gestion g
|
||||
LEFT JOIN bitacoras.nodos n ON g.nodo_id = n.id
|
||||
WHERE g.bitacora_id = $1 OR g.activo = true
|
||||
ORDER BY g.tipo, g.orden
|
||||
", [bitacora_id]) rescue [] # Por si la tabla no existe aún en otros entornos
|
||||
|
||||
resumenes = @db.execute("
|
||||
SELECT r.*, n.nombre as nodo_nombre
|
||||
FROM bitacoras.resumen_nodos r
|
||||
JOIN bitacoras.nodos n ON r.nodo_id = n.id
|
||||
WHERE r.bitacora_id = $1
|
||||
", [bitacora_id]) rescue []
|
||||
|
||||
# Generar contenido Markdown
|
||||
contenido = generar_markdown(fecha, bitacora['resumen'], gestion, resumenes, entradas)
|
||||
|
||||
File.write(ruta_destino, contenido)
|
||||
@logger.info("✅ Exportación completada con éxito.")
|
||||
true
|
||||
rescue => e
|
||||
@logger.error("Error exportando bitácora: #{e.message}")
|
||||
false
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def generar_markdown(fecha, resumen_gen, gestion, resumenes, entradas)
|
||||
y, m, d = fecha.to_s.split('-')
|
||||
md = String.new("<!-- GENERADO AUTOMÁTICAMENTE por adn db exportar:md — No editar manualmente -->\n")
|
||||
md << "# Bitácora de Operaciones - #{d}/#{m}/#{y}\n\n"
|
||||
|
||||
if gestion && gestion.ntuples > 0
|
||||
md << "## 📋 Control de Gestión\n\n"
|
||||
|
||||
pendientes = gestion.select { |g| g['tipo'] == 'pendiente' }
|
||||
if pendientes.any?
|
||||
md << "### 📝 Resumen de Actividades\n" # Formato ADN
|
||||
md << "| NODO | PENDIENTES |\n| :--- | :--- |\n"
|
||||
pendientes.each do |p|
|
||||
md << "| #{p['nodo_nombre'] || '—'} | #{p['detalle']} |\n"
|
||||
end
|
||||
md << "\n"
|
||||
end
|
||||
|
||||
en_proceso = gestion.select { |g| g['tipo'] == 'proceso' }
|
||||
if en_proceso.any?
|
||||
md << "### ⏳ En Proceso\n"
|
||||
md << "| NODO | ACTIVIDAD |\n| :--- | :--- |\n"
|
||||
en_proceso.each do |p|
|
||||
md << "| #{p['nodo_nombre'] || '—'} | #{p['detalle']} |\n"
|
||||
end
|
||||
md << "\n"
|
||||
end
|
||||
end
|
||||
|
||||
if resumenes && resumenes.ntuples > 0
|
||||
md << "### 📝 Resumen Integral\n"
|
||||
md << "| NODO | RESUMEN INTEGRAL |\n| :--- | :--- |\n"
|
||||
resumenes.each do |r|
|
||||
md << "| #{r['nodo_nombre']} | #{r['resumen']} |\n"
|
||||
end
|
||||
md << "\n"
|
||||
end
|
||||
|
||||
md << "## 📂 Actividades Detalladas\n\n"
|
||||
|
||||
por_nodo = entradas.group_by { |e| e['nodo_nombre'] || 'sin-nodo' }
|
||||
por_nodo.each do |nodo, entries|
|
||||
md << "### #{nodo}\n\n"
|
||||
md << "| I | F | Descripción | E |\n"
|
||||
md << "| :--- | :--- | :--- | :--- |\n"
|
||||
entries.each do |e|
|
||||
inicio = e['inicio'] ? e['inicio'][0..4] : '-'
|
||||
fin = e['fin'] ? e['fin'][0..4] : '-'
|
||||
ia = e['es_ia'] == 't' ? '(IA) ' : ''
|
||||
estado = "[#{e['modo']}] #{e['estado']}"
|
||||
md << "| #{inicio} | #{fin} | #{ia}#{e['descripcion']} | #{estado} |\n"
|
||||
end
|
||||
md << "\n"
|
||||
end
|
||||
|
||||
md << "---\n"
|
||||
md << "<!-- GENERADO AUTOMÁTICAMENTE desde PostgreSQL el #{Time.now.strftime('%Y-%m-%d %H:%M')} -->\n"
|
||||
md << "<!-- Fuente de verdad: DB. Regenerar con: adn db exportar:md #{fecha} -->\n"
|
||||
md
|
||||
end
|
||||
|
||||
def default_logger
|
||||
Class.new do
|
||||
def info(msg); puts "[INFO] #{msg}"; end
|
||||
def error(msg); puts "[ERROR] #{msg}"; end
|
||||
end.new
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user