This commit is contained in:
Lizandro Guarnizo
2026-06-10 00:18:20 -05:00
parent d701534537
commit 478c2bde00
3 changed files with 156 additions and 114 deletions
+57 -33
View File
@@ -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
}