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,121 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# adn/tools/db/cli/verificar_migracion.rb
|
||||
# ================================================
|
||||
# Verifica que todas las bitácoras MD existentes estén correctamente
|
||||
# migradas en la base de datos. Reporta faltantes y discrepancias.
|
||||
#
|
||||
# Uso:
|
||||
# ruby adn/tools/db/cli/verificar_migracion.rb
|
||||
# — o vía enjambre —
|
||||
# ./adn/tools/run db verificar
|
||||
|
||||
require 'date'
|
||||
require_relative '../core/bitacora_db'
|
||||
|
||||
module BitacorasDB
|
||||
module CLI
|
||||
class VerificarMigracion
|
||||
COLORES = {
|
||||
reset: "\e[0m", bold: "\e[1m", red: "\e[31m",
|
||||
green: "\e[32m", yellow: "\e[33m", cyan: "\e[36m", dim: "\e[2m"
|
||||
}.freeze
|
||||
|
||||
def initialize(bitacoras_dir)
|
||||
@bitacoras_dir = bitacoras_dir
|
||||
@resultados = { ok: [], sin_entradas: [], no_migrada: [], sin_md: [] }
|
||||
end
|
||||
|
||||
def ejecutar
|
||||
puts "#{COLORES[:cyan]}🔍 Verificación de migración MD ↔ DB#{COLORES[:reset]}\n\n"
|
||||
|
||||
archivos_md = Dir.glob(File.join(@bitacoras_dir, '*.md')).sort
|
||||
puts "#{COLORES[:dim]}Archivos MD encontrados: #{archivos_md.size}#{COLORES[:reset]}"
|
||||
|
||||
BitacorasDB::BitacoraDB.with_connection do |db|
|
||||
# 1. Validar cada MD contra la DB
|
||||
archivos_md.each do |archivo|
|
||||
fecha = File.basename(archivo, '.md')
|
||||
bitacora = db.find_bitacora_by_fecha(fecha)
|
||||
|
||||
unless bitacora
|
||||
@resultados[:no_migrada] << fecha
|
||||
next
|
||||
end
|
||||
|
||||
entradas = db.execute(
|
||||
"SELECT COUNT(*) as total FROM bitacoras.entradas WHERE bitacora_id = $1",
|
||||
[bitacora['id']]
|
||||
)
|
||||
total = entradas.first['total'].to_i
|
||||
|
||||
if total > 0
|
||||
@resultados[:ok] << { fecha: fecha, entradas: total }
|
||||
else
|
||||
@resultados[:sin_entradas] << fecha
|
||||
end
|
||||
end
|
||||
|
||||
# 2. Bitácoras en DB que no tienen MD
|
||||
todas_db = db.list_bitacoras(limit: 500)
|
||||
fechas_md = archivos_md.map { |a| File.basename(a, '.md') }
|
||||
todas_db.each do |b|
|
||||
f = b['fecha'].to_s
|
||||
f = f.split('T').first if f.include?('T') # por si viene con timestamp
|
||||
@resultados[:sin_md] << f unless fechas_md.include?(f)
|
||||
end
|
||||
end
|
||||
|
||||
mostrar_resultados
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def mostrar_resultados
|
||||
puts "\n#{COLORES[:bold]}📊 Resultado de verificación:#{COLORES[:reset]}\n"
|
||||
|
||||
# OK
|
||||
puts "#{COLORES[:green]}✅ Migradas correctamente: #{@resultados[:ok].size}#{COLORES[:reset]}"
|
||||
@resultados[:ok].each do |r|
|
||||
puts " #{COLORES[:dim]}#{r[:fecha]} (#{r[:entradas]} entradas)#{COLORES[:reset]}"
|
||||
end
|
||||
|
||||
# Sin entradas
|
||||
if @resultados[:sin_entradas].any?
|
||||
puts "\n#{COLORES[:yellow]}⚠ En DB pero sin entradas: #{@resultados[:sin_entradas].size}#{COLORES[:reset]}"
|
||||
@resultados[:sin_entradas].each { |f| puts " #{f}" }
|
||||
end
|
||||
|
||||
# No migradas
|
||||
if @resultados[:no_migrada].any?
|
||||
puts "\n#{COLORES[:red]}❌ No migradas (MD existe, DB no): #{@resultados[:no_migrada].size}#{COLORES[:reset]}"
|
||||
@resultados[:no_migrada].each { |f| puts " #{f}" }
|
||||
puts " #{COLORES[:dim]}Ejecuta: ./adn/tools/run db migrar:md FECHA#{COLORES[:reset]}"
|
||||
end
|
||||
|
||||
# Sin MD
|
||||
if @resultados[:sin_md].any?
|
||||
puts "\n#{COLORES[:cyan]}ℹ En DB sin archivo MD: #{@resultados[:sin_md].size}#{COLORES[:reset]}"
|
||||
@resultados[:sin_md].each { |f| puts " #{f}" }
|
||||
puts " #{COLORES[:dim]}Ejecuta: ./adn/tools/run db exportar:md FECHA#{COLORES[:reset]}"
|
||||
end
|
||||
|
||||
total = @resultados[:ok].size + @resultados[:sin_entradas].size
|
||||
total_md = @resultados[:ok].size + @resultados[:sin_entradas].size + @resultados[:no_migrada].size
|
||||
pct = total_md > 0 ? ((@resultados[:ok].size.to_f / total_md) * 100).round(1) : 0
|
||||
|
||||
puts "\n#{COLORES[:bold]}📈 Cobertura: #{pct}% (#{@resultados[:ok].size}/#{total_md})#{COLORES[:reset]}"
|
||||
|
||||
if @resultados[:no_migrada].empty? && @resultados[:sin_entradas].empty?
|
||||
puts "#{COLORES[:green]}#{COLORES[:bold]}🎉 ¡Migración completa! Todas las bitácoras están en la DB.#{COLORES[:reset]}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Ejecución directa
|
||||
if __FILE__ == $0
|
||||
bitacoras_dir = File.expand_path('../../../docs/bitacoras', __dir__)
|
||||
BitacorasDB::CLI::VerificarMigracion.new(bitacoras_dir).ejecutar
|
||||
end
|
||||
Reference in New Issue
Block a user