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,214 @@
|
||||
module ADN
|
||||
module SubcomandoDBHito
|
||||
# Comando: hito:listar [PROYECTO]
|
||||
def comando_hito_listar(args)
|
||||
if args.empty?
|
||||
puts "#{Color::YELLOW}Uso: adn db hito:listar <CODIGO_PROYECTO> (ej: P2605)#{Color::RESET}"
|
||||
return
|
||||
end
|
||||
|
||||
codigo = args[0]
|
||||
puts "#{Color::CYAN}📋 Listando hitos del proyecto #{codigo.upcase}...#{Color::RESET}"
|
||||
|
||||
BitacorasDB::BitacoraDB.with_connection do |db|
|
||||
begin
|
||||
hitos = db.list_hitos(codigo)
|
||||
if hitos.empty?
|
||||
puts "#{Color::YELLOW}⚠ No se encontraron hitos o el proyecto no existe.#{Color::RESET}"
|
||||
return
|
||||
end
|
||||
|
||||
puts ""
|
||||
puts "#{Color::BOLD}#{"Hito".ljust(8)} #{"Fase".ljust(6)} #{"Estado".ljust(8)} #{"Hrs P/R".ljust(10)} #{"Título"}#{Color::RESET}"
|
||||
puts "#{"─" * 8} #{"─" * 6} #{"─" * 8} #{"─" * 10} #{"─" * 40}"
|
||||
|
||||
hitos.each do |h|
|
||||
hrs = "#{h['horas_presencial']}/#{h['horas_remoto']}"
|
||||
puts "#{h['id_hito'].ljust(8)} #{h['fase_num'].to_s.ljust(6)} #{h['estado'].ljust(8)} #{hrs.ljust(10)} #{h['titulo']}"
|
||||
end
|
||||
puts "\nTotal: #{hitos.size} hitos"
|
||||
rescue => e
|
||||
puts "#{Color::RED}✗ Error: #{e.message}#{Color::RESET}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Comando: hito:ordenar <PROYECTO> [--aplicar FILE]
|
||||
def comando_hito_ordenar(args)
|
||||
codigo = args.shift
|
||||
if !codigo
|
||||
puts "#{Color::YELLOW}Uso: adn db hito:ordenar <PROYECTO> [--aplicar /ruta/al/archivo.txt]#{Color::RESET}"
|
||||
return
|
||||
end
|
||||
|
||||
aplicar_path = nil
|
||||
if args[0] == '--aplicar' && args[1]
|
||||
aplicar_path = args[1]
|
||||
end
|
||||
|
||||
BitacorasDB::BitacoraDB.with_connection do |db|
|
||||
begin
|
||||
hitos = db.list_hitos(codigo)
|
||||
if hitos.empty?
|
||||
puts "#{Color::YELLOW}⚠ No se encontraron hitos para #{codigo.upcase}.#{Color::RESET}"
|
||||
return
|
||||
end
|
||||
|
||||
if aplicar_path
|
||||
unless File.exist?(aplicar_path)
|
||||
puts "#{Color::RED}✗ No se encontró el archivo: #{aplicar_path}#{Color::RESET}"
|
||||
return
|
||||
end
|
||||
|
||||
# Procesar el archivo y aplicarrenombramientos lógicos "Fase.Grupo.Paso"
|
||||
puts "#{Color::CYAN}📋 Aplicando ordenamiento desde #{aplicar_path}...#{Color::RESET}"
|
||||
lineas = File.readlines(aplicar_path).map(&:strip).reject { |l| l.empty? || l.start_with?('#') }
|
||||
|
||||
# Agrupar por fase según el orden de las líneas
|
||||
hitos_por_fase = Hash.new { |h, k| h[k] = [] }
|
||||
lineas.each do |linea|
|
||||
if linea =~ /^(\d+):\s*\[.+?\]\s*(.+)$/
|
||||
id_db = $1.to_i
|
||||
hito = hitos.find { |h| h['id'] == id_db }
|
||||
hitos_por_fase[hito['fase_num']] << hito if hito
|
||||
end
|
||||
end
|
||||
|
||||
# Iniciar renombrado secuencial
|
||||
hitos_por_fase.each do |fase, hitos_fase|
|
||||
grupo = 1
|
||||
letra = 65 # 'A'
|
||||
|
||||
hitos_fase.each do |h|
|
||||
nuevo_id = "#{fase}.#{grupo}.#{letra.chr}"
|
||||
|
||||
if h['id_hito'] != nuevo_id
|
||||
db.rename_hito_id(codigo, h['id_hito'], nuevo_id)
|
||||
puts " #{Color::GREEN}✔ #{h['id_hito'].ljust(8)} → #{nuevo_id.ljust(8)}#{Color::RESET} | #{h['titulo']}"
|
||||
else
|
||||
puts " #{Color::DIM}• #{nuevo_id.ljust(8)} (Sin cambios) | #{h['titulo']}#{Color::RESET}"
|
||||
end
|
||||
|
||||
letra += 1
|
||||
if letra > 67 # 'C'
|
||||
letra = 65
|
||||
grupo += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
puts "#{Color::GREEN}✅ Ordenamiento aplicado exitosamente a #{codigo.upcase}.#{Color::RESET}"
|
||||
|
||||
else
|
||||
# Generar archivo temporal para reordenamiento (Swarm-Ready)
|
||||
tmp_file = "/tmp/adn_ordenar_#{codigo.downcase}.txt"
|
||||
File.open(tmp_file, 'w') do |f|
|
||||
f.puts "# ==========================================================================="
|
||||
f.puts "# MODO ORDENAMIENTO DE HITOS - PROYECTO #{codigo.upcase}"
|
||||
f.puts "# ==========================================================================="
|
||||
f.puts "# Cambia el orden de las líneas (Cortar y Pegar) dentro de la misma FASE"
|
||||
f.puts "# para definir la secuencia lógica de ejecución."
|
||||
f.puts "# NO MODIFIQUES el número inicial ni los corchetes (ej: '42: [F3]')."
|
||||
f.puts "# Cuando termines de editar, guarda el archivo y ejecuta en la terminal:"
|
||||
f.puts "# adn db hito:ordenar #{codigo.upcase} --aplicar #{tmp_file}"
|
||||
f.puts "# ===========================================================================\n\n"
|
||||
|
||||
fases = hitos.group_by { |h| h['fase_num'] }.sort_by { |k, v| k }
|
||||
fases.each do |num_fase, hitos_fase|
|
||||
f.puts "# --- FASE #{num_fase} ---"
|
||||
hitos_fase.each do |h|
|
||||
f.puts "#{h['id']}: [F#{num_fase}] #{h['titulo']}"
|
||||
end
|
||||
f.puts "\n"
|
||||
end
|
||||
end
|
||||
|
||||
puts "#{Color::CYAN}✅ Archivo de configuración generado en: #{tmp_file}#{Color::RESET}"
|
||||
puts "1. Abre el archivo y reordena las líneas como necesites."
|
||||
puts "2. Ejecuta: #{Color::BOLD}adn db hito:ordenar #{codigo.upcase} --aplicar #{tmp_file}#{Color::RESET}"
|
||||
end
|
||||
rescue => e
|
||||
puts "#{Color::RED}✗ Error: #{e.message}#{Color::RESET}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Comando: hito:renombrar <PROYECTO> <ID_HITO_ACTUAL> <NUEVO_ID_HITO>
|
||||
def comando_hito_renombrar(args)
|
||||
if args.length < 3
|
||||
puts "#{Color::YELLOW}Uso: adn db hito:renombrar <PROYECTO> <ID_HITO_ACTUAL> <NUEVO_ID_HITO>#{Color::RESET}"
|
||||
return
|
||||
end
|
||||
|
||||
proyecto = args[0]
|
||||
id_actual = args[1]
|
||||
id_nuevo = args[2]
|
||||
|
||||
puts "#{Color::CYAN}🔄 Renombrando hito #{id_actual} → #{id_nuevo} (Proyecto #{proyecto.upcase})...#{Color::RESET}"
|
||||
|
||||
BitacorasDB::BitacoraDB.with_connection do |db|
|
||||
begin
|
||||
res = db.rename_hito_id(proyecto, id_actual, id_nuevo)
|
||||
puts "#{Color::GREEN}✅ Hito renombrado exitosamente. Título: #{res['titulo']}#{Color::RESET}"
|
||||
rescue => e
|
||||
puts "#{Color::RED}✗ Error: #{e.message}#{Color::RESET}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Comando: hito:actualizar <PROYECTO> <ID_HITO> [OPCIONES]
|
||||
def comando_hito_actualizar(args)
|
||||
if args.length < 2
|
||||
puts "#{Color::YELLOW}Uso: adn db hito:actualizar <PROYECTO> <ID_HITO> [OPCIONES]#{Color::RESET}"
|
||||
puts "Opciones soportadas: --estado=EJ, --horas-p=1.5, --horas-r=0, --desc=\"Texto\""
|
||||
return
|
||||
end
|
||||
|
||||
proyecto = args.shift
|
||||
id_hito = args.shift
|
||||
opts = { estado: nil, horas_presencial: nil, horas_remoto: nil, descripcion: nil }
|
||||
|
||||
parser = OptionParser.new do |opt|
|
||||
opt.banner = "Opciones:"
|
||||
opt.on("--estado ESTADO", "Nuevo estado (ej: ✅, ⏳, 📋)") { |e| opts[:estado] = e }
|
||||
opt.on("--horas-p HORAS", "Horas presenciales") { |h| opts[:horas_presencial] = h.to_f }
|
||||
opt.on("--horas-r HORAS", "Horas remotas") { |h| opts[:horas_remoto] = h.to_f }
|
||||
opt.on("--desc DESC", "Descripción o detalle para el hito") { |d| opts[:descripcion] = d }
|
||||
end
|
||||
|
||||
begin
|
||||
parser.parse!(args)
|
||||
rescue OptionParser::InvalidOption => e
|
||||
puts "#{Color::RED}✗ Error: #{e.message}#{Color::RESET}"
|
||||
exit 1
|
||||
end
|
||||
|
||||
if opts.values.all?(&:nil?)
|
||||
puts "#{Color::YELLOW}⚠ No se especificó nada para actualizar. Use --estado, --horas-p, --horas-r o --desc#{Color::RESET}"
|
||||
return
|
||||
end
|
||||
|
||||
puts "#{Color::CYAN}🔄 Actualizando hito #{id_hito} del proyecto #{proyecto.upcase}...#{Color::RESET}"
|
||||
|
||||
BitacorasDB::BitacoraDB.with_connection do |db|
|
||||
begin
|
||||
res = db.update_hito(
|
||||
proyecto, id_hito,
|
||||
estado: opts[:estado],
|
||||
horas_presencial: opts[:horas_presencial],
|
||||
horas_remoto: opts[:horas_remoto],
|
||||
descripcion: opts[:descripcion]
|
||||
)
|
||||
puts "#{Color::GREEN}✅ Hito actualizado exitosamente.#{Color::RESET}"
|
||||
hrs = "#{res['horas_presencial'].to_f}P / #{res['horas_remoto'].to_f}R"
|
||||
puts " Estado actual : #{res['estado']}"
|
||||
puts " Horas imputadas : #{hrs}"
|
||||
rescue => e
|
||||
puts "#{Color::RED}✗ Error: #{e.message}#{Color::RESET}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user