122 lines
4.4 KiB
Ruby
122 lines
4.4 KiB
Ruby
# frozen_string_literal: true
|
||
|
||
# tools/bitacoras-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 tools/bitacoras-db/cli/verificar_migracion.rb
|
||
# — o vía enjambre —
|
||
# ./tools/adn/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: ./tools/adn/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: ./tools/adn/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
|