up
This commit is contained in:
@@ -0,0 +1,203 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/sujit-baniya/fiber-boilerplate/pkg/models"
|
||||
)
|
||||
|
||||
func FacturasIndex(c *fiber.Ctx) error {
|
||||
return c.Render("facturas", fiber.Map{
|
||||
"user": c.Locals("user"),
|
||||
"modules": c.Locals("userModules"),
|
||||
}, "layouts/main")
|
||||
}
|
||||
|
||||
func LoadFacturas(c *fiber.Ctx) error {
|
||||
page, _ := strconv.Atoi(c.Query("page", "1"))
|
||||
search := c.Query("search", "")
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
limit := 20
|
||||
offset := (page - 1) * limit
|
||||
items, total, err := models.GetAllFacturas(limit, offset, search)
|
||||
if err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
clientes, _, _ := models.GetAllClientes(200, 0, "")
|
||||
proyectos, _, _ := models.GetAllProyectos(200, 0, "")
|
||||
return c.JSON(fiber.Map{
|
||||
"items": items,
|
||||
"total": total,
|
||||
"totalPages": int(math.Ceil(float64(total) / float64(limit))),
|
||||
"page": page,
|
||||
"clientes": clientes,
|
||||
"proyectos": proyectos,
|
||||
})
|
||||
}
|
||||
|
||||
func CreateFactura(c *fiber.Ctx) error {
|
||||
type Req struct {
|
||||
ClienteID uint `json:"cliente_id"`
|
||||
ProyectoID *uint `json:"proyecto_id"`
|
||||
Numero string `json:"numero"`
|
||||
Descripcion string `json:"descripcion"`
|
||||
Monto float64 `json:"monto"`
|
||||
Moneda string `json:"moneda"`
|
||||
Estado string `json:"estado"`
|
||||
FechaEmision string `json:"fecha_emision"`
|
||||
FechaVencimiento string `json:"fecha_vencimiento"`
|
||||
Visible bool `json:"visible"`
|
||||
Notas string `json:"notas"`
|
||||
}
|
||||
var req Req
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return c.Status(400).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
if req.ClienteID == 0 {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "cliente_id es requerido"})
|
||||
}
|
||||
f := &models.Factura{
|
||||
ClienteID: req.ClienteID,
|
||||
ProyectoID: req.ProyectoID,
|
||||
Numero: req.Numero,
|
||||
Descripcion: req.Descripcion,
|
||||
Monto: req.Monto,
|
||||
Moneda: req.Moneda,
|
||||
Estado: req.Estado,
|
||||
Visible: req.Visible,
|
||||
Notas: req.Notas,
|
||||
FechaEmision: time.Now(),
|
||||
}
|
||||
if req.FechaEmision != "" {
|
||||
t, err := time.Parse("2006-01-02", req.FechaEmision)
|
||||
if err == nil {
|
||||
f.FechaEmision = t
|
||||
}
|
||||
}
|
||||
if req.FechaVencimiento != "" {
|
||||
t, err := time.Parse("2006-01-02", req.FechaVencimiento)
|
||||
if err == nil {
|
||||
f.FechaVencimiento = &t
|
||||
}
|
||||
}
|
||||
if f.Moneda == "" {
|
||||
f.Moneda = "COP"
|
||||
}
|
||||
if f.Estado == "" {
|
||||
f.Estado = "pendiente"
|
||||
}
|
||||
if err := models.CreateFactura(f); err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.Status(201).JSON(f)
|
||||
}
|
||||
|
||||
func UpdateFactura(c *fiber.Ctx) error {
|
||||
id, err := strconv.ParseUint(c.Params("id"), 10, 32)
|
||||
if err != nil {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "ID inválido"})
|
||||
}
|
||||
type Req struct {
|
||||
ClienteID uint `json:"cliente_id"`
|
||||
ProyectoID *uint `json:"proyecto_id"`
|
||||
Numero string `json:"numero"`
|
||||
Descripcion string `json:"descripcion"`
|
||||
Monto float64 `json:"monto"`
|
||||
Moneda string `json:"moneda"`
|
||||
Estado string `json:"estado"`
|
||||
FechaEmision string `json:"fecha_emision"`
|
||||
FechaVencimiento string `json:"fecha_vencimiento"`
|
||||
Visible bool `json:"visible"`
|
||||
Notas string `json:"notas"`
|
||||
}
|
||||
var req Req
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return c.Status(400).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
f := &models.Factura{
|
||||
ClienteID: req.ClienteID,
|
||||
ProyectoID: req.ProyectoID,
|
||||
Numero: req.Numero,
|
||||
Descripcion: req.Descripcion,
|
||||
Monto: req.Monto,
|
||||
Moneda: req.Moneda,
|
||||
Estado: req.Estado,
|
||||
Visible: req.Visible,
|
||||
Notas: req.Notas,
|
||||
}
|
||||
f.ID = uint(id)
|
||||
if req.FechaEmision != "" {
|
||||
t, err := time.Parse("2006-01-02", req.FechaEmision)
|
||||
if err == nil {
|
||||
f.FechaEmision = t
|
||||
}
|
||||
}
|
||||
if req.FechaVencimiento != "" {
|
||||
t, err := time.Parse("2006-01-02", req.FechaVencimiento)
|
||||
if err == nil {
|
||||
f.FechaVencimiento = &t
|
||||
}
|
||||
}
|
||||
if err := models.UpdateFactura(f); err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.JSON(fiber.Map{"ok": true})
|
||||
}
|
||||
|
||||
func DeleteFactura(c *fiber.Ctx) error {
|
||||
id, err := strconv.ParseUint(c.Params("id"), 10, 32)
|
||||
if err != nil {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "ID inválido"})
|
||||
}
|
||||
if err := models.DeleteFactura(uint(id)); err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.JSON(fiber.Map{"ok": true})
|
||||
}
|
||||
|
||||
func UploadFacturaPDF(c *fiber.Ctx) error {
|
||||
id, _ := strconv.ParseUint(c.Params("id"), 10, 32)
|
||||
file, err := c.FormFile("pdf")
|
||||
if err != nil {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "Archivo PDF requerido"})
|
||||
}
|
||||
if file.Size > 20*1024*1024 {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "Máximo 20MB"})
|
||||
}
|
||||
dir := "uploads/facturas"
|
||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": "Error al crear directorio"})
|
||||
}
|
||||
safeFile := safeFilenameProyecto(file.Filename)
|
||||
savePath := filepath.Join(dir, fmt.Sprintf("%d_%s", id, safeFile))
|
||||
if err := c.SaveFile(file, savePath); err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": "Error al guardar archivo"})
|
||||
}
|
||||
if err := models.UpdateFacturaArchivo(uint(id), savePath, file.Filename); err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.JSON(fiber.Map{"ok": true, "archivo": savePath})
|
||||
}
|
||||
|
||||
func DownloadFacturaPDF(c *fiber.Ctx) error {
|
||||
id, _ := strconv.ParseUint(c.Params("id"), 10, 32)
|
||||
f, err := models.GetFacturaByID(uint(id))
|
||||
if err != nil || f.Archivo == "" {
|
||||
return c.Status(404).JSON(fiber.Map{"error": "Archivo no encontrado"})
|
||||
}
|
||||
clean := filepath.Clean(f.Archivo)
|
||||
if !strings.HasPrefix(clean, "uploads/") {
|
||||
return c.Status(403).JSON(fiber.Map{"error": "Acceso denegado"})
|
||||
}
|
||||
c.Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, f.OriginalName))
|
||||
return c.SendFile(clean)
|
||||
}
|
||||
Reference in New Issue
Block a user