From 478c2bde0024c922c10c915ecbeba14022022847 Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Wed, 10 Jun 2026 00:18:20 -0500 Subject: [PATCH] up --- pkg/models/contrato.go | 90 ++++++++----- resources/views/renovaciones/contratos.html | 133 +++++++++++--------- rest/controllers/contrato_controller.go | 47 +++---- 3 files changed, 156 insertions(+), 114 deletions(-) diff --git a/pkg/models/contrato.go b/pkg/models/contrato.go index ad03489..9bf0d9b 100644 --- a/pkg/models/contrato.go +++ b/pkg/models/contrato.go @@ -20,13 +20,10 @@ type Contrato struct { Estado string `json:"estado" gorm:"column:estado;default:'activo'"` // activo | vencido | cancelado | renovado AutoRenovar bool `json:"auto_renovar" gorm:"column:auto_renovar;default:false"` Notas string `json:"notas" gorm:"column:notas"` - // Infraestructura asociada (opcional) - ServidorID *uint `json:"servidor_id" gorm:"column:servidor_id"` - Servidor Servidor `json:"servidor" gorm:"foreignKey:ServidorID"` - ConxDbID *uint `json:"conx_db_id" gorm:"column:conx_db_id"` - ConxDb ConxDb `json:"conx_db" gorm:"foreignKey:ConxDbID"` - AiConfigID *uint `json:"ai_config_id" gorm:"column:ai_config_id"` - AiConfig AiConfig `json:"ai_config" gorm:"foreignKey:AiConfigID"` + // Infraestructura asociada (opcional, múltiple) + Servidores []Servidor `json:"servidores" gorm:"many2many:contrato_servidores"` + ConxDBs []ConxDb `json:"conx_dbs" gorm:"many2many:contrato_conx_dbs"` + AiConfigs []AiConfig `json:"ai_configs" gorm:"many2many:contrato_ai_configs"` // Enlace de pago Bold: único por ciclo de pago. // Se reutiliza en múltiples notificaciones del mismo ciclo. // Se anula (vacía) cuando SALE_APPROVED llega y se registra el pago. @@ -44,7 +41,7 @@ func GetAllContratos(limit, offset int, search, estado string) ([]Contrato, int6 var total int64 db := app.Http.Database.DB.Model(&Contrato{}). Preload("Cliente").Preload("Servicios"). - Preload("Servidor").Preload("ConxDb").Preload("AiConfig") + Preload("Servidores").Preload("ConxDBs").Preload("AiConfigs") if search != "" { db = db.Joins("JOIN clientes ON clientes.id = contratos.cliente_id"). Where("clientes.nombre ILIKE ? OR clientes.empresa ILIKE ?", @@ -64,7 +61,7 @@ func GetAllContratos(limit, offset int, search, estado string) ([]Contrato, int6 func GetContratoByID(id uint) (*Contrato, error) { var item Contrato - if err := app.Http.Database.DB.Preload("Cliente").Preload("Servicios").Preload("Servidor").Preload("ConxDb").Preload("AiConfig").First(&item, id).Error; err != nil { + if err := app.Http.Database.DB.Preload("Cliente").Preload("Servicios").Preload("Servidores").Preload("ConxDBs").Preload("AiConfigs").First(&item, id).Error; err != nil { return nil, err } return &item, nil @@ -154,17 +151,40 @@ func syncContratoServicios(contratoID uint, servicioIDs []uint) error { return nil } -func CreateContrato(c Contrato, servicioIDs []uint) error { - db := app.Http.Database.DB - if err := db.Omit("Servicios.*").Create(&c).Error; err != nil { +func syncContratoJoin(db *gorm.DB, table string, contratoID uint, ids []uint) error { + if err := db.Exec("DELETE FROM "+table+" WHERE contrato_id = ?", contratoID).Error; err != nil { return err } - return syncContratoServicios(c.ID, servicioIDs) + for _, id := range ids { + if err := db.Exec("INSERT INTO "+table+" (contrato_id, "+table[:len(table)-1]+"_id) VALUES (?, ?) ON CONFLICT DO NOTHING", + contratoID, id, + ).Error; err != nil { + return err + } + } + return nil } -func UpdateContrato(c Contrato, servicioIDs []uint) error { +func CreateContrato(c Contrato, servicioIDs, servidorIDs, conxDBIDs, aiConfigIDs []uint) error { db := app.Http.Database.DB - updates := map[string]interface{}{ + if err := db.Omit("Servicios.*", "Servidores.*", "ConxDBs.*", "AiConfigs.*").Create(&c).Error; err != nil { + return err + } + if err := syncContratoServicios(c.ID, servicioIDs); err != nil { + return err + } + if err := syncContratoJoin(db, "contrato_servidores", c.ID, servidorIDs); err != nil { + return err + } + if err := syncContratoJoin(db, "contrato_conx_dbs", c.ID, conxDBIDs); err != nil { + return err + } + return syncContratoJoin(db, "contrato_ai_configs", c.ID, aiConfigIDs) +} + +func UpdateContrato(c Contrato, servicioIDs, servidorIDs, conxDBIDs, aiConfigIDs []uint) error { + db := app.Http.Database.DB + if err := db.Model(&Contrato{}).Where("id = ?", c.ID).Updates(map[string]interface{}{ "cliente_id": c.ClienteID, "fecha_inicio": c.FechaInicio, "fecha_vencimiento": c.FechaVencimiento, @@ -173,27 +193,28 @@ func UpdateContrato(c Contrato, servicioIDs []uint) error { "estado": c.Estado, "auto_renovar": c.AutoRenovar, "notas": c.Notas, - } - if c.ServidorID != nil { - updates["servidor_id"] = *c.ServidorID - } else { - updates["servidor_id"] = nil - } - if c.ConxDbID != nil { - updates["conx_db_id"] = *c.ConxDbID - } else { - updates["conx_db_id"] = nil - } - if c.AiConfigID != nil { - updates["ai_config_id"] = *c.AiConfigID - } else { - updates["ai_config_id"] = nil - } - if err := db.Model(&Contrato{}).Where("id = ?", c.ID).Updates(updates).Error; err != nil { + }).Error; err != nil { return err } if servicioIDs != nil { - return syncContratoServicios(c.ID, servicioIDs) + if err := syncContratoServicios(c.ID, servicioIDs); err != nil { + return err + } + } + if servidorIDs != nil { + if err := syncContratoJoin(db, "contrato_servidores", c.ID, servidorIDs); err != nil { + return err + } + } + if conxDBIDs != nil { + if err := syncContratoJoin(db, "contrato_conx_dbs", c.ID, conxDBIDs); err != nil { + return err + } + } + if aiConfigIDs != nil { + if err := syncContratoJoin(db, "contrato_ai_configs", c.ID, aiConfigIDs); err != nil { + return err + } } return nil } @@ -205,6 +226,9 @@ func DeleteContrato(id uint) error { return err } db.Exec("DELETE FROM contrato_servicios WHERE contrato_id = ?", id) + db.Exec("DELETE FROM contrato_servidores WHERE contrato_id = ?", id) + db.Exec("DELETE FROM contrato_conx_dbs WHERE contrato_id = ?", id) + db.Exec("DELETE FROM contrato_ai_configs WHERE contrato_id = ?", id) return db.Delete(&c).Error } diff --git a/resources/views/renovaciones/contratos.html b/resources/views/renovaciones/contratos.html index d025362..a222270 100644 --- a/resources/views/renovaciones/contratos.html +++ b/resources/views/renovaciones/contratos.html @@ -52,25 +52,25 @@
-