- El agente creaba tareas con estado='pendiente' (default), pero el tablero Kanban del dashboard solo reconoce por_hacer/en_progreso/revision/hecho. La tarea se guardaba bien (por eso llegaba el correo de notificación) pero no aparecía en ninguna columna. Se corrigen los enums y el default de las tools crear_tarea/actualizar_estado_tarea, y se agrega una reparación única al arranque que corrige las tareas ya creadas con el estado inválido. - adjuntar_factura siempre asumía factura de VENTA (ligada a un cliente). Se agrega adjuntar_factura_compra: cuando un proveedor le factura a U-SITE (no al revés), busca/crea la Entidad proveedor y registra una cuenta por pagar con el documento adjunto (se agregan campos archivo/original_name/tipo_mime a CuentaPagar, que no los tenía). El prompt del sistema instruye a Claude a decidir la dirección leyendo quién emite y quién recibe el documento. De paso: endpoint de descarga del soporte de la factura de compra, expuesto también en el dashboard (/app/contabilidad/cuentas-pagar). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
77 lines
2.1 KiB
Go
77 lines
2.1 KiB
Go
package services
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/sujit-baniya/fiber-boilerplate/pkg/models"
|
|
)
|
|
|
|
// CrearTareaAsignada crea una tarea, opcionalmente ya asignada a alguien, y
|
|
// dispara la notificación correspondiente (Telegram/email/sistema, según la
|
|
// config de notif_evento_configs) si quedó asignada a un usuario.
|
|
func CrearTareaAsignada(titulo, descripcion, estado, prioridad string, asignadoID *uint, fechaLimite *time.Time) (*models.Tarea, error) {
|
|
if titulo == "" {
|
|
return nil, fmt.Errorf("titulo requerido")
|
|
}
|
|
if estado == "" {
|
|
// Debe coincidir con las columnas del Kanban (tareas.html): por_hacer,
|
|
// en_progreso, revision, hecho. "pendiente" no es ninguna de esas — una
|
|
// tarea con ese estado se guarda pero no aparece en ninguna columna.
|
|
estado = "por_hacer"
|
|
}
|
|
if prioridad == "" {
|
|
prioridad = "media"
|
|
}
|
|
t := &models.Tarea{
|
|
Titulo: titulo,
|
|
Descripcion: descripcion,
|
|
Estado: estado,
|
|
Prioridad: prioridad,
|
|
AsignadoID: asignadoID,
|
|
FechaLimite: fechaLimite,
|
|
}
|
|
if err := models.CreateTarea(t); err != nil {
|
|
return nil, fmt.Errorf("no se pudo crear la tarea: %w", err)
|
|
}
|
|
if asignadoID != nil {
|
|
if full, err := models.GetTareaByID(t.ID); err == nil {
|
|
go NotificarTareaAsignada(full)
|
|
}
|
|
}
|
|
return t, nil
|
|
}
|
|
|
|
// AsignarTarea cambia el responsable de una tarea existente y notifica al nuevo
|
|
// asignado si el responsable realmente cambió. asignadoID puede ser nil para
|
|
// dejar la tarea sin asignar.
|
|
func AsignarTarea(id uint, asignadoID *uint) (*models.Tarea, error) {
|
|
if id == 0 {
|
|
return nil, fmt.Errorf("id requerido")
|
|
}
|
|
tarea, err := models.GetTareaByID(id)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("tarea no encontrada: %w", err)
|
|
}
|
|
prevAsignado := tarea.AsignadoID
|
|
tarea.AsignadoID = asignadoID
|
|
if err := models.SaveTarea(tarea); err != nil {
|
|
return nil, fmt.Errorf("no se pudo asignar la tarea: %w", err)
|
|
}
|
|
full, _ := models.GetTareaByID(id)
|
|
if cambioAsignado(prevAsignado, asignadoID) && full != nil {
|
|
go NotificarTareaAsignada(full)
|
|
}
|
|
return full, nil
|
|
}
|
|
|
|
func cambioAsignado(a, b *uint) bool {
|
|
if a == nil && b == nil {
|
|
return false
|
|
}
|
|
if a == nil || b == nil {
|
|
return true
|
|
}
|
|
return *a != *b
|
|
}
|