package models import ( "time" "github.com/sujit-baniya/fiber-boilerplate/app" "gorm.io/gorm" ) // ─── Factura ────────────────────────────────────────────────────────────────── type Factura struct { gorm.Model ClienteID uint `json:"cliente_id" gorm:"column:cliente_id;index;not null"` Cliente Cliente `json:"cliente" gorm:"foreignKey:ClienteID"` ProyectoID *uint `json:"proyecto_id" gorm:"column:proyecto_id;index"` Proyecto *Proyecto `json:"proyecto" gorm:"foreignKey:ProyectoID"` Numero string `json:"numero" gorm:"column:numero"` Descripcion string `json:"descripcion" gorm:"column:descripcion;type:text"` Monto float64 `json:"monto" gorm:"column:monto"` Moneda string `json:"moneda" gorm:"column:moneda;default:'COP'"` Estado string `json:"estado" gorm:"column:estado;default:'pendiente'"` // pendiente|pagada|vencida|cancelada FechaEmision time.Time `json:"fecha_emision" gorm:"column:fecha_emision"` FechaVencimiento *time.Time `json:"fecha_vencimiento" gorm:"column:fecha_vencimiento"` Archivo string `json:"archivo" gorm:"column:archivo"` OriginalName string `json:"original_name" gorm:"column:original_name"` Visible bool `json:"visible" gorm:"column:visible;default:true"` Notas string `json:"notas" gorm:"column:notas;type:text"` } func (Factura) TableName() string { return "facturas" } // ─── CRUD ───────────────────────────────────────────────────────────────────── func GetAllFacturas(limit, offset int, search string) ([]Factura, int64, error) { var items []Factura var total int64 db := app.Http.Database.DB.Model(&Factura{}).Preload("Cliente").Preload("Proyecto") if search != "" { db = db.Joins("JOIN clientes ON clientes.id = facturas.cliente_id"). Where("facturas.numero ILIKE ? OR clientes.nombre ILIKE ? OR clientes.empresa ILIKE ?", "%"+search+"%", "%"+search+"%", "%"+search+"%") } if err := db.Count(&total).Error; err != nil { return nil, 0, err } if err := db.Order("facturas.fecha_emision DESC").Limit(limit).Offset(offset).Find(&items).Error; err != nil { return nil, 0, err } return items, total, nil } func GetFacturasByCliente(clienteID uint, soloVisibles bool) ([]Factura, error) { var items []Factura db := app.Http.Database.DB.Where("cliente_id = ?", clienteID) if soloVisibles { db = db.Where("visible = true") } err := db.Preload("Proyecto").Order("fecha_emision DESC").Find(&items).Error return items, err } func GetFacturaByID(id uint) (*Factura, error) { var item Factura err := app.Http.Database.DB.Preload("Cliente").Preload("Proyecto").First(&item, id).Error return &item, err } func CreateFactura(f *Factura) error { return app.Http.Database.DB.Create(f).Error } func UpdateFactura(f *Factura) error { return app.Http.Database.DB.Model(&Factura{}).Where("id = ?", f.ID).Updates(map[string]interface{}{ "cliente_id": f.ClienteID, "proyecto_id": f.ProyectoID, "numero": f.Numero, "descripcion": f.Descripcion, "monto": f.Monto, "moneda": f.Moneda, "estado": f.Estado, "fecha_emision": f.FechaEmision, "fecha_vencimiento": f.FechaVencimiento, "visible": f.Visible, "notas": f.Notas, }).Error } func DeleteFactura(id uint) error { return app.Http.Database.DB.Delete(&Factura{}, id).Error } func UpdateFacturaArchivo(id uint, archivo, originalName string) error { return app.Http.Database.DB.Model(&Factura{}).Where("id = ?", id).Updates(map[string]interface{}{ "archivo": archivo, "original_name": originalName, }).Error }