fix: compilar agent/dist en builder stage y agregar módulos contabilidad/websms
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
ca6a44f64e
commit
e28e2823dc
@@ -0,0 +1,603 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"math"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/sujit-baniya/fiber-boilerplate/pkg/models"
|
||||
)
|
||||
|
||||
// ─── Render de vistas ────────────────────────────────────────────────────────
|
||||
|
||||
func ContabilidadIndex(c *fiber.Ctx) error {
|
||||
return c.Render("contabilidad/contabilidad", fiber.Map{
|
||||
"user": c.Locals("user"),
|
||||
"modules": c.Locals("userModules"),
|
||||
}, "layouts/main")
|
||||
}
|
||||
|
||||
func ContabilidadTransaccionesView(c *fiber.Ctx) error {
|
||||
return c.Render("contabilidad/transacciones", fiber.Map{
|
||||
"user": c.Locals("user"),
|
||||
"modules": c.Locals("userModules"),
|
||||
}, "layouts/main")
|
||||
}
|
||||
|
||||
func ContabilidadCuentasView(c *fiber.Ctx) error {
|
||||
return c.Render("contabilidad/cuentas", fiber.Map{
|
||||
"user": c.Locals("user"),
|
||||
"modules": c.Locals("userModules"),
|
||||
}, "layouts/main")
|
||||
}
|
||||
|
||||
func ContabilidadEntidadesView(c *fiber.Ctx) error {
|
||||
return c.Render("contabilidad/entidades", fiber.Map{
|
||||
"user": c.Locals("user"),
|
||||
"modules": c.Locals("userModules"),
|
||||
}, "layouts/main")
|
||||
}
|
||||
|
||||
func ContabilidadCobroView(c *fiber.Ctx) error {
|
||||
return c.Render("contabilidad/cuentas_cobro", fiber.Map{
|
||||
"user": c.Locals("user"),
|
||||
"modules": c.Locals("userModules"),
|
||||
}, "layouts/main")
|
||||
}
|
||||
|
||||
func ContabilidadPagarView(c *fiber.Ctx) error {
|
||||
return c.Render("contabilidad/cuentas_pagar", fiber.Map{
|
||||
"user": c.Locals("user"),
|
||||
"modules": c.Locals("userModules"),
|
||||
}, "layouts/main")
|
||||
}
|
||||
|
||||
// ─── Dashboard ───────────────────────────────────────────────────────────────
|
||||
|
||||
func ContabilidadDashboard(c *fiber.Ctx) error {
|
||||
now := time.Now()
|
||||
mes, _ := strconv.Atoi(c.Query("mes", strconv.Itoa(int(now.Month()))))
|
||||
anio, _ := strconv.Atoi(c.Query("anio", strconv.Itoa(now.Year())))
|
||||
if mes < 1 || mes > 12 {
|
||||
mes = int(now.Month())
|
||||
}
|
||||
if anio < 2000 {
|
||||
anio = now.Year()
|
||||
}
|
||||
data, err := models.GetDashboardData(mes, anio)
|
||||
if err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.JSON(data)
|
||||
}
|
||||
|
||||
func ContabilidadConsolidado(ctx *fiber.Ctx) error {
|
||||
now := time.Now()
|
||||
mes, _ := strconv.Atoi(ctx.Query("mes", strconv.Itoa(int(now.Month()))))
|
||||
anio, _ := strconv.Atoi(ctx.Query("anio", strconv.Itoa(now.Year())))
|
||||
if mes < 1 || mes > 12 {
|
||||
mes = int(now.Month())
|
||||
}
|
||||
if anio < 2000 {
|
||||
anio = now.Year()
|
||||
}
|
||||
data, err := models.CalcularYGuardarConsolidado(mes, anio)
|
||||
if err != nil {
|
||||
return ctx.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return ctx.JSON(data)
|
||||
}
|
||||
|
||||
func ContabilidadListConsolidados(c *fiber.Ctx) error {
|
||||
anio, _ := strconv.Atoi(c.Query("anio", "0"))
|
||||
items, err := models.ListConsolidados(anio)
|
||||
if err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.JSON(items)
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// ─── CRUD: Cuentas ──────────────────────────────────────────────────────────
|
||||
// =============================================================================
|
||||
|
||||
func GetCuentas(c *fiber.Ctx) error {
|
||||
page, _ := strconv.Atoi(c.Query("page", "1"))
|
||||
search := c.Query("search", "")
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
limit := 50
|
||||
offset := (page - 1) * limit
|
||||
items, total, err := models.GetAllCuentas(limit, offset, search)
|
||||
if err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.JSON(fiber.Map{
|
||||
"items": items,
|
||||
"total": total,
|
||||
"totalPages": int(math.Ceil(float64(total) / float64(limit))),
|
||||
"page": page,
|
||||
})
|
||||
}
|
||||
|
||||
func GetCuentasSelect(c *fiber.Ctx) error {
|
||||
items, err := models.GetAllCuentasSelect()
|
||||
if err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.JSON(items)
|
||||
}
|
||||
|
||||
func CreateCuenta(c *fiber.Ctx) error {
|
||||
var req models.Cuenta
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return c.Status(400).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
if req.Nombre == "" {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "nombre es requerido"})
|
||||
}
|
||||
if req.Tipo == "" {
|
||||
req.Tipo = "egreso"
|
||||
}
|
||||
req.Activo = true
|
||||
if err := models.CreateCuenta(&req); err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.Status(201).JSON(req)
|
||||
}
|
||||
|
||||
func UpdateCuenta(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"})
|
||||
}
|
||||
var req models.Cuenta
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return c.Status(400).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
req.ID = uint(id)
|
||||
if err := models.UpdateCuenta(&req); err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.JSON(fiber.Map{"ok": true})
|
||||
}
|
||||
|
||||
func DeleteCuenta(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.DeleteCuenta(uint(id)); err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.JSON(fiber.Map{"ok": true})
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// ─── CRUD: Entidades ────────────────────────────────────────────────────────
|
||||
// =============================================================================
|
||||
|
||||
func GetEntidades(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.GetAllEntidades(limit, offset, search)
|
||||
if err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.JSON(fiber.Map{
|
||||
"items": items,
|
||||
"total": total,
|
||||
"totalPages": int(math.Ceil(float64(total) / float64(limit))),
|
||||
"page": page,
|
||||
})
|
||||
}
|
||||
|
||||
func GetEntidadesSelect(c *fiber.Ctx) error {
|
||||
items, err := models.GetAllEntidadesSelect()
|
||||
if err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.JSON(items)
|
||||
}
|
||||
|
||||
func CreateEntidad(c *fiber.Ctx) error {
|
||||
var req models.Entidad
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return c.Status(400).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
if req.Nombre == "" {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "nombre es requerido"})
|
||||
}
|
||||
req.Activo = true
|
||||
if err := models.CreateEntidad(&req); err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.Status(201).JSON(req)
|
||||
}
|
||||
|
||||
func UpdateEntidad(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"})
|
||||
}
|
||||
var req models.Entidad
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return c.Status(400).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
req.ID = uint(id)
|
||||
if err := models.UpdateEntidad(&req); err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.JSON(fiber.Map{"ok": true})
|
||||
}
|
||||
|
||||
func DeleteEntidad(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.DeleteEntidad(uint(id)); err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.JSON(fiber.Map{"ok": true})
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// ─── CRUD: Transacciones ────────────────────────────────────────────────────
|
||||
// =============================================================================
|
||||
|
||||
func GetTransacciones(c *fiber.Ctx) error {
|
||||
page, _ := strconv.Atoi(c.Query("page", "1"))
|
||||
search := c.Query("search", "")
|
||||
filtroTipo := c.Query("tipo", "")
|
||||
mes, _ := strconv.Atoi(c.Query("mes", "0"))
|
||||
anio, _ := strconv.Atoi(c.Query("anio", "0"))
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
limit := 30
|
||||
offset := (page - 1) * limit
|
||||
items, total, err := models.GetAllTransacciones(limit, offset, search, filtroTipo, mes, anio)
|
||||
if err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.JSON(fiber.Map{
|
||||
"items": items,
|
||||
"total": total,
|
||||
"totalPages": int(math.Ceil(float64(total) / float64(limit))),
|
||||
"page": page,
|
||||
})
|
||||
}
|
||||
|
||||
func CreateTransaccion(c *fiber.Ctx) error {
|
||||
type Req struct {
|
||||
Fecha string `json:"fecha"`
|
||||
Tipo string `json:"tipo"`
|
||||
Descripcion string `json:"descripcion"`
|
||||
Valor float64 `json:"valor"`
|
||||
CuentaID *uint `json:"cuenta_id"`
|
||||
EntidadID *uint `json:"entidad_id"`
|
||||
FormaPago string `json:"forma_pago"`
|
||||
Estado string `json:"estado"`
|
||||
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.Descripcion == "" {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "descripcion es requerida"})
|
||||
}
|
||||
if req.Valor <= 0 {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "valor debe ser mayor a 0"})
|
||||
}
|
||||
t := &models.Transaccion{
|
||||
Tipo: req.Tipo,
|
||||
Descripcion: req.Descripcion,
|
||||
Valor: req.Valor,
|
||||
CuentaID: req.CuentaID,
|
||||
EntidadID: req.EntidadID,
|
||||
FormaPago: req.FormaPago,
|
||||
Estado: req.Estado,
|
||||
Notas: req.Notas,
|
||||
Fecha: time.Now(),
|
||||
}
|
||||
if t.Tipo == "" {
|
||||
t.Tipo = "ingreso"
|
||||
}
|
||||
if t.Estado == "" {
|
||||
t.Estado = "registrada"
|
||||
}
|
||||
if req.Fecha != "" {
|
||||
if parsed, err := time.Parse("2006-01-02", req.Fecha); err == nil {
|
||||
t.Fecha = parsed
|
||||
}
|
||||
}
|
||||
if err := models.CreateTransaccion(t); err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.Status(201).JSON(t)
|
||||
}
|
||||
|
||||
func UpdateTransaccion(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 {
|
||||
Fecha string `json:"fecha"`
|
||||
Tipo string `json:"tipo"`
|
||||
Descripcion string `json:"descripcion"`
|
||||
Valor float64 `json:"valor"`
|
||||
CuentaID *uint `json:"cuenta_id"`
|
||||
EntidadID *uint `json:"entidad_id"`
|
||||
FormaPago string `json:"forma_pago"`
|
||||
Estado string `json:"estado"`
|
||||
Notas string `json:"notas"`
|
||||
}
|
||||
var req Req
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return c.Status(400).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
t := &models.Transaccion{
|
||||
Tipo: req.Tipo,
|
||||
Descripcion: req.Descripcion,
|
||||
Valor: req.Valor,
|
||||
CuentaID: req.CuentaID,
|
||||
EntidadID: req.EntidadID,
|
||||
FormaPago: req.FormaPago,
|
||||
Estado: req.Estado,
|
||||
Notas: req.Notas,
|
||||
Fecha: time.Now(),
|
||||
}
|
||||
t.ID = uint(id)
|
||||
if req.Fecha != "" {
|
||||
if parsed, err := time.Parse("2006-01-02", req.Fecha); err == nil {
|
||||
t.Fecha = parsed
|
||||
}
|
||||
}
|
||||
|
||||
if err := models.UpdateTransaccion(t); err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.JSON(fiber.Map{"ok": true})
|
||||
}
|
||||
|
||||
func DeleteTransaccion(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.DeleteTransaccion(uint(id)); err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.JSON(fiber.Map{"ok": true})
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// ─── CRUD: Cuentas por Cobrar ──────────────────────────────────────────────
|
||||
// =============================================================================
|
||||
|
||||
func GetCuentasCobro(c *fiber.Ctx) error {
|
||||
page, _ := strconv.Atoi(c.Query("page", "1"))
|
||||
search := c.Query("search", "")
|
||||
estado := c.Query("estado", "")
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
limit := 20
|
||||
offset := (page - 1) * limit
|
||||
items, total, err := models.GetAllCuentasCobro(limit, offset, search, estado)
|
||||
if err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.JSON(fiber.Map{
|
||||
"items": items,
|
||||
"total": total,
|
||||
"totalPages": int(math.Ceil(float64(total) / float64(limit))),
|
||||
"page": page,
|
||||
})
|
||||
}
|
||||
|
||||
func CreateCuentaCobro(c *fiber.Ctx) error {
|
||||
type Req struct {
|
||||
EntidadID uint `json:"entidad_id"`
|
||||
Fecha string `json:"fecha"`
|
||||
Descripcion string `json:"descripcion"`
|
||||
Valor float64 `json:"valor"`
|
||||
FechaVencimiento string `json:"fecha_vencimiento"`
|
||||
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.EntidadID == 0 {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "entidad_id es requerido"})
|
||||
}
|
||||
cc := &models.CuentaCobro{
|
||||
EntidadID: req.EntidadID,
|
||||
Descripcion: req.Descripcion,
|
||||
Valor: req.Valor,
|
||||
Estado: "pendiente",
|
||||
Notas: req.Notas,
|
||||
Fecha: time.Now(),
|
||||
}
|
||||
if req.Fecha != "" {
|
||||
if parsed, err := time.Parse("2006-01-02", req.Fecha); err == nil {
|
||||
cc.Fecha = parsed
|
||||
}
|
||||
}
|
||||
if req.FechaVencimiento != "" {
|
||||
if parsed, err := time.Parse("2006-01-02", req.FechaVencimiento); err == nil {
|
||||
cc.FechaVencimiento = &parsed
|
||||
}
|
||||
}
|
||||
if err := models.CreateCuentaCobro(cc); err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.Status(201).JSON(cc)
|
||||
}
|
||||
|
||||
func UpdateCuentaCobro(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 {
|
||||
Estado string `json:"estado"`
|
||||
FechaPago string `json:"fecha_pago"`
|
||||
TransaccionID *uint `json:"transaccion_id"`
|
||||
Notas string `json:"notas"`
|
||||
FechaVencimiento string `json:"fecha_vencimiento"`
|
||||
Descripcion string `json:"descripcion"`
|
||||
Valor float64 `json:"valor"`
|
||||
}
|
||||
var req Req
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return c.Status(400).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
cc := &models.CuentaCobro{}
|
||||
cc.ID = uint(id)
|
||||
if req.Estado != "" {
|
||||
cc.Estado = req.Estado
|
||||
}
|
||||
if req.FechaPago != "" {
|
||||
if parsed, err := time.Parse("2006-01-02", req.FechaPago); err == nil {
|
||||
cc.FechaPago = &parsed
|
||||
}
|
||||
}
|
||||
cc.TransaccionID = req.TransaccionID
|
||||
cc.Notas = req.Notas
|
||||
if err := models.UpdateCuentaCobro(cc); err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.JSON(fiber.Map{"ok": true})
|
||||
}
|
||||
|
||||
func DeleteCuentaCobro(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.DeleteCuentaCobro(uint(id)); err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.JSON(fiber.Map{"ok": true})
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// ─── CRUD: Cuentas por Pagar ────────────────────────────────────────────────
|
||||
// =============================================================================
|
||||
|
||||
func GetCuentasPagar(c *fiber.Ctx) error {
|
||||
page, _ := strconv.Atoi(c.Query("page", "1"))
|
||||
search := c.Query("search", "")
|
||||
estado := c.Query("estado", "")
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
limit := 20
|
||||
offset := (page - 1) * limit
|
||||
items, total, err := models.GetAllCuentasPagar(limit, offset, search, estado)
|
||||
if err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.JSON(fiber.Map{
|
||||
"items": items,
|
||||
"total": total,
|
||||
"totalPages": int(math.Ceil(float64(total) / float64(limit))),
|
||||
"page": page,
|
||||
})
|
||||
}
|
||||
|
||||
func CreateCuentaPagar(c *fiber.Ctx) error {
|
||||
type Req struct {
|
||||
EntidadID uint `json:"entidad_id"`
|
||||
Fecha string `json:"fecha"`
|
||||
Descripcion string `json:"descripcion"`
|
||||
Valor float64 `json:"valor"`
|
||||
Vencimiento string `json:"vencimiento"`
|
||||
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.EntidadID == 0 {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "entidad_id es requerido"})
|
||||
}
|
||||
cp := &models.CuentaPagar{
|
||||
EntidadID: req.EntidadID,
|
||||
Descripcion: req.Descripcion,
|
||||
Valor: req.Valor,
|
||||
Estado: "pendiente",
|
||||
Notas: req.Notas,
|
||||
Fecha: time.Now(),
|
||||
}
|
||||
if req.Fecha != "" {
|
||||
if parsed, err := time.Parse("2006-01-02", req.Fecha); err == nil {
|
||||
cp.Fecha = parsed
|
||||
}
|
||||
}
|
||||
if req.Vencimiento != "" {
|
||||
if parsed, err := time.Parse("2006-01-02", req.Vencimiento); err == nil {
|
||||
cp.Vencimiento = &parsed
|
||||
}
|
||||
}
|
||||
if err := models.CreateCuentaPagar(cp); err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.Status(201).JSON(cp)
|
||||
}
|
||||
|
||||
func UpdateCuentaPagar(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 {
|
||||
Estado string `json:"estado"`
|
||||
FechaPago string `json:"fecha_pago"`
|
||||
TransaccionID *uint `json:"transaccion_id"`
|
||||
Notas string `json:"notas"`
|
||||
}
|
||||
var req Req
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return c.Status(400).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
cp := &models.CuentaPagar{}
|
||||
cp.ID = uint(id)
|
||||
if req.Estado != "" {
|
||||
cp.Estado = req.Estado
|
||||
}
|
||||
if req.FechaPago != "" {
|
||||
if parsed, err := time.Parse("2006-01-02", req.FechaPago); err == nil {
|
||||
cp.FechaPago = &parsed
|
||||
}
|
||||
}
|
||||
cp.TransaccionID = req.TransaccionID
|
||||
cp.Notas = req.Notas
|
||||
if err := models.UpdateCuentaPagar(cp); err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.JSON(fiber.Map{"ok": true})
|
||||
}
|
||||
|
||||
func DeleteCuentaPagar(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.DeleteCuentaPagar(uint(id)); err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.JSON(fiber.Map{"ok": true})
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/sujit-baniya/fiber-boilerplate/pkg/models"
|
||||
"github.com/sujit-baniya/fiber-boilerplate/pkg/services"
|
||||
)
|
||||
|
||||
// ─── Vistas ──────────────────────────────────────────────────────────────────
|
||||
|
||||
func WebSmsConfigPage(c *fiber.Ctx) error {
|
||||
cfg, _ := models.GetWebSmsConfig()
|
||||
return c.Render("websms_config", fiber.Map{
|
||||
"user": c.Locals("user"),
|
||||
"modules": c.Locals("userModules"),
|
||||
"cfg": cfg,
|
||||
}, "layouts/main")
|
||||
}
|
||||
|
||||
// ─── API ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
func GetWebSmsConfig(c *fiber.Ctx) error {
|
||||
cfg, err := models.GetWebSmsConfig()
|
||||
if err != nil {
|
||||
return c.JSON(fiber.Map{"data": nil})
|
||||
}
|
||||
return c.JSON(fiber.Map{"data": cfg})
|
||||
}
|
||||
|
||||
func SaveWebSmsConfig(c *fiber.Ctx) error {
|
||||
type body struct {
|
||||
ID uint `json:"id"`
|
||||
Username string `json:"username"`
|
||||
ApiToken string `json:"api_token"`
|
||||
Sender string `json:"sender"`
|
||||
Notas string `json:"notas"`
|
||||
}
|
||||
var b body
|
||||
if err := c.BodyParser(&b); err != nil {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "body inválido"})
|
||||
}
|
||||
if b.Username == "" {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "username es requerido"})
|
||||
}
|
||||
if b.ApiToken == "" {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "api_token es requerido"})
|
||||
}
|
||||
|
||||
cfg := models.WebSmsConfig{
|
||||
Username: b.Username,
|
||||
ApiToken: b.ApiToken,
|
||||
Sender: b.Sender,
|
||||
Notas: b.Notas,
|
||||
}
|
||||
cfg.ID = b.ID
|
||||
|
||||
if err := models.SaveWebSmsConfig(cfg); err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.JSON(fiber.Map{"message": "Configuración WebSMS guardada"})
|
||||
}
|
||||
|
||||
func TestWebSms(c *fiber.Ctx) error {
|
||||
type body struct {
|
||||
Para string `json:"para"`
|
||||
Mensaje string `json:"mensaje"`
|
||||
}
|
||||
var b body
|
||||
if err := c.BodyParser(&b); err != nil {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "body inválido"})
|
||||
}
|
||||
if b.Para == "" {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "número de destino requerido"})
|
||||
}
|
||||
if b.Mensaje == "" {
|
||||
b.Mensaje = "[TEST] Notificación desde U-site vía WebSMS"
|
||||
}
|
||||
|
||||
cfg, err := models.GetWebSmsConfig()
|
||||
if err != nil {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "WebSMS no configurado"})
|
||||
}
|
||||
|
||||
resp, err := services.SendWebSms(cfg, b.Para, b.Mensaje)
|
||||
if err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
|
||||
models.CreateWebSmsLog(&models.WebSmsLog{
|
||||
Para: b.Para,
|
||||
Mensaje: b.Mensaje,
|
||||
Status: resp.Code,
|
||||
MsgID: resp.ID,
|
||||
})
|
||||
|
||||
return c.JSON(fiber.Map{"ok": true, "response": resp})
|
||||
}
|
||||
|
||||
func GetWebSmsLogs(c *fiber.Ctx) error {
|
||||
logs, err := models.GetWebSmsLogs(50)
|
||||
if err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.JSON(logs)
|
||||
}
|
||||
|
||||
func GetWebSmsWebhookLogs(c *fiber.Ctx) error {
|
||||
logs, err := models.GetWebSmsWebhookLogs(50)
|
||||
if err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.JSON(logs)
|
||||
}
|
||||
|
||||
// ─── Webhooks entrantes ─────────────────────────────────────────────────────
|
||||
|
||||
func WebSmsDeliveryWebhook(c *fiber.Ctx) error {
|
||||
var payload services.WebSmsAckPayload
|
||||
if err := c.BodyParser(&payload); err != nil {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "body inválido"})
|
||||
}
|
||||
raw := c.Body()
|
||||
models.CreateWebSmsWebhookLog(&models.WebSmsWebhookLog{
|
||||
Tipo: "delivery",
|
||||
MsgID: payload.ID,
|
||||
Para: payload.Msisdn,
|
||||
Status: payload.Status,
|
||||
Raw: string(raw),
|
||||
})
|
||||
return c.SendStatus(200)
|
||||
}
|
||||
|
||||
func WebSmsClickWebhook(c *fiber.Ctx) error {
|
||||
var payload services.WebSmsClickPayload
|
||||
if err := c.BodyParser(&payload); err != nil {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "body inválido"})
|
||||
}
|
||||
raw := c.Body()
|
||||
models.CreateWebSmsWebhookLog(&models.WebSmsWebhookLog{
|
||||
Tipo: "click",
|
||||
MsgID: payload.ID,
|
||||
Para: payload.Msisdn,
|
||||
Status: "clicked",
|
||||
Raw: string(raw),
|
||||
})
|
||||
return c.SendStatus(200)
|
||||
}
|
||||
|
||||
func WebSmsIncomingWebhook(c *fiber.Ctx) error {
|
||||
var payload services.WebSmsIncomingPayload
|
||||
if err := c.BodyParser(&payload); err != nil {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "body inválido"})
|
||||
}
|
||||
raw := c.Body()
|
||||
models.CreateWebSmsWebhookLog(&models.WebSmsWebhookLog{
|
||||
Tipo: "incoming",
|
||||
MsgID: payload.ID,
|
||||
Para: payload.Msisdn,
|
||||
Status: "received",
|
||||
Raw: string(raw),
|
||||
})
|
||||
return c.SendStatus(200)
|
||||
}
|
||||
Reference in New Issue
Block a user