170 lines
4.6 KiB
Go
170 lines
4.6 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"encoding/csv"
|
||
|
"fmt"
|
||
|
"log"
|
||
|
"os"
|
||
|
"strings"
|
||
|
"time"
|
||
|
|
||
|
"heating-monitor/internal/bot"
|
||
|
"heating-monitor/internal/config"
|
||
|
|
||
|
"github.com/spf13/cobra"
|
||
|
"gorm.io/gorm"
|
||
|
)
|
||
|
|
||
|
func main() {
|
||
|
var filePath string
|
||
|
var dryRun bool
|
||
|
|
||
|
// Define el comando principal
|
||
|
var cmd = &cobra.Command{
|
||
|
Use: "import",
|
||
|
Short: "Importa datos desde un CSV a la base de datos",
|
||
|
Run: func(cmd *cobra.Command, args []string) {
|
||
|
if filePath == "" {
|
||
|
log.Fatal("Debe especificar un archivo CSV con el flag -f o --file")
|
||
|
}
|
||
|
|
||
|
// Abre el archivo CSV
|
||
|
file, err := os.Open(filePath)
|
||
|
if err != nil {
|
||
|
log.Fatalf("No se pudo abrir el archivo: %v", err)
|
||
|
}
|
||
|
defer file.Close()
|
||
|
|
||
|
reader := csv.NewReader(file)
|
||
|
reader.Comma = ';' // Usamos punto y coma como separador
|
||
|
|
||
|
// Lee el archivo CSV
|
||
|
records, err := reader.ReadAll()
|
||
|
if err != nil {
|
||
|
log.Fatalf("Error al leer el archivo CSV: %v", err)
|
||
|
}
|
||
|
|
||
|
// Ignorar la primera línea de encabezado
|
||
|
records = records[1:]
|
||
|
|
||
|
insertedCount := 0
|
||
|
// Procesa cada línea del CSV
|
||
|
for _, record := range records {
|
||
|
// Ignorar encabezado
|
||
|
if strings.HasPrefix(record[0], ";") {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
// Parsear la fecha
|
||
|
fecha, err := time.Parse("2006-01-02", record[1])
|
||
|
if err != nil {
|
||
|
log.Printf("Error al parsear la fecha: %v", err)
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
// Procesar las columnas ON/OFF
|
||
|
for i := 2; i <= 6; i += 3 {
|
||
|
if record[i] != "" && record[i+1] != "" {
|
||
|
// Parsear las horas ON/OFF
|
||
|
onTime, err := time.Parse("15:04", record[i])
|
||
|
if err != nil {
|
||
|
log.Printf("Error al parsear hora ON: %v", err)
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
offTime, err := time.Parse("15:04", record[i+1])
|
||
|
if err != nil {
|
||
|
log.Printf("Error al parsear hora OFF: %v", err)
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
// Ajustar los tiempos a la fecha correcta
|
||
|
onTimestamp := time.Date(fecha.Year(), fecha.Month(), fecha.Day(), onTime.Hour(), onTime.Minute(), 0, 0, time.UTC)
|
||
|
offTimestamp := time.Date(fecha.Year(), fecha.Month(), fecha.Day(), offTime.Hour(), offTime.Minute(), 0, 0, time.UTC)
|
||
|
|
||
|
// Mostrar en dry-run
|
||
|
if dryRun {
|
||
|
fmt.Printf("ON: %v, OFF: %v\n", onTimestamp, offTimestamp)
|
||
|
} else {
|
||
|
// Inicializar la base de datos
|
||
|
config.InitDB()
|
||
|
|
||
|
// Insertar en la base de datos
|
||
|
existsOn, err := eventExists(config.DB, "ON", onTimestamp)
|
||
|
if err != nil {
|
||
|
log.Printf("Error al verificar existencia de evento ON: %v", err)
|
||
|
continue
|
||
|
}
|
||
|
if !existsOn {
|
||
|
err := insertHeatingEvent(config.DB, "ON", onTimestamp)
|
||
|
if err != nil {
|
||
|
log.Printf("Error al insertar evento ON: %v", err)
|
||
|
continue
|
||
|
}
|
||
|
insertedCount++
|
||
|
} else {
|
||
|
log.Printf("Evento ON ya existe: %v", onTimestamp)
|
||
|
}
|
||
|
|
||
|
existsOff, err := eventExists(config.DB, "OFF", offTimestamp)
|
||
|
if err != nil {
|
||
|
log.Printf("Error al verificar existencia de evento OFF: %v", err)
|
||
|
continue
|
||
|
}
|
||
|
if !existsOff {
|
||
|
err := insertHeatingEvent(config.DB, "OFF", offTimestamp)
|
||
|
if err != nil {
|
||
|
log.Printf("Error al insertar evento OFF: %v", err)
|
||
|
continue
|
||
|
}
|
||
|
insertedCount++
|
||
|
} else {
|
||
|
log.Printf("Evento OFF ya existe: %v", offTimestamp)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
log.Printf("Se insertaron %d registros en la base de datos", insertedCount)
|
||
|
},
|
||
|
}
|
||
|
|
||
|
// Añadir flags al comando
|
||
|
cmd.Flags().StringVarP(&filePath, "file", "f", "", "Ruta del archivo CSV")
|
||
|
cmd.Flags().BoolVarP(&dryRun, "dry-run", "", false, "Simula la importación y muestra los datos")
|
||
|
|
||
|
// Ejecutar el comando
|
||
|
if err := cmd.Execute(); err != nil {
|
||
|
log.Fatal(err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// insertHeatingEvent inserta un evento de calefacción en la base de datos
|
||
|
func insertHeatingEvent(db *gorm.DB, eventType string, timestamp time.Time) error {
|
||
|
event := bot.HeatingEvent{
|
||
|
EventType: eventType,
|
||
|
Timestamp: timestamp,
|
||
|
}
|
||
|
|
||
|
// Insertar el evento en la base de datos
|
||
|
if err := db.Create(&event).Error; err != nil {
|
||
|
return fmt.Errorf("no se pudo insertar el evento: %v", err)
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// eventExists verifica si un evento con el mismo tipo y timestamp ya existe
|
||
|
func eventExists(db *gorm.DB, eventType string, timestamp time.Time) (bool, error) {
|
||
|
var existingEvent bot.HeatingEvent
|
||
|
err := db.Where("event_type = ? AND timestamp = ?", eventType, timestamp).First(&existingEvent).Error
|
||
|
if err == nil {
|
||
|
// Si err es nil, significa que se encontró un evento existente
|
||
|
return true, nil
|
||
|
} else if err == gorm.ErrRecordNotFound {
|
||
|
// Si el error es ErrRecordNotFound, no existe el evento
|
||
|
return false, nil
|
||
|
}
|
||
|
// Si hay otro tipo de error
|
||
|
return false, err
|
||
|
}
|