module ADN module SubcomandoDBBitacora # Comando: bitacora:crear [FECHA] - Crear nueva bitácora diaria def comando_bitacora_crear(args) opts = { fecha: Date.today, resumen: nil } parser = OptionParser.new do |opt| opt.banner = "Uso: adn db bitacora:crear [FECHA] [OPCIONES]" opt.on("--resumen TEXTO", "Resumen inicial de la bitácora") do |r| opts[:resumen] = r end opt.on("-h", "--help", "Mostrar ayuda") do puts opt exit end end begin parser.parse!(args) # Si queda un argumento sin procesar, asumimos que es la fecha opts[:fecha] = Date.parse(args[0]) if args[0] rescue OptionParser::InvalidOption, Date::Error => e puts "#{Color::RED}✗ Error: #{e.message}#{Color::RESET}" puts parser exit 1 end puts "#{Color::CYAN}📝 Creando bitácora para #{opts[:fecha]}...#{Color::RESET}" BitacorasDB::BitacoraDB.with_connection do |db| begin bitacora = db.create_bitacora(fecha: opts[:fecha], resumen: opts[:resumen]) puts "#{Color::GREEN}✅ Bitácora creada exitosamente#{Color::RESET}" puts "" puts " #{Color::BOLD}ID:#{Color::RESET} #{bitacora['id']}" puts " #{Color::BOLD}Fecha:#{Color::RESET} #{bitacora['fecha']}" puts " #{Color::BOLD}Resumen:#{Color::RESET} #{bitacora['resumen'] || '(sin resumen)'}" puts " #{Color::BOLD}Creada:#{Color::RESET} #{bitacora['created_at']}" rescue PG::UniqueViolation puts "#{Color::YELLOW}⚠ Ya existe una bitácora para la fecha #{opts[:fecha]}#{Color::RESET}" puts " Usa #{Color::DIM}adn db bitacora:listar#{Color::RESET} para ver bitácoras existentes" end end end # Comando: bitacora:listar [OPCIONES] - Listar bitácoras existentes def comando_bitacora_listar(args) opts = { limit: 10, offset: 0, desde: nil, hasta: nil } parser = OptionParser.new do |opt| opt.banner = "Uso: adn db bitacora:listar [OPCIONES]" opt.on("--limit N", Integer, "Número máximo de resultados (default: 10)") do |n| opts[:limit] = n end opt.on("--offset N", Integer, "Desplazamiento para paginación (default: 0)") do |n| opts[:offset] = n end opt.on("--desde FECHA", "Filtrar desde fecha (YYYY-MM-DD)") do |d| opts[:desde] = d end opt.on("--hasta FECHA", "Filtrar hasta fecha (YYYY-MM-DD)") do |h| opts[:hasta] = h end opt.on("-h", "--help", "Mostrar ayuda") do puts opt exit end end begin parser.parse!(args) rescue OptionParser::InvalidOption => e puts "#{Color::RED}✗ Error: #{e.message}#{Color::RESET}" puts parser exit 1 end puts "#{Color::CYAN}📋 Listando bitácoras...#{Color::RESET}" BitacorasDB::BitacoraDB.with_connection do |db| bitacoras = db.list_bitacoras( limit: opts[:limit], offset: opts[:offset], desde: opts[:desde], hasta: opts[:hasta] ) if bitacoras.empty? puts "#{Color::YELLOW}⚠ No se encontraron bitácoras#{Color::RESET}" return end puts "" puts "#{Color::BOLD}#{"ID".ljust(5)} #{"Fecha".ljust(12)} #{"Resumen".ljust(40)} #{"Creada".ljust(20)}#{Color::RESET}" puts "#{"─" * 5} #{"─" * 12} #{"─" * 40} #{"─" * 20}" bitacoras.each do |b| fecha = b['fecha'] resumen = b['resumen'] || '' resumen = resumen[0..37] + '...' if resumen.length > 40 creada = Time.parse(b['created_at']).strftime('%Y-%m-%d %H:%M') puts "#{b['id'].to_s.ljust(5)} #{fecha.ljust(12)} #{resumen.ljust(40)} #{creada.ljust(20)}" end puts "" puts "Total: #{bitacoras.length} bitácoras" end end end end