2025-05-17 11:36:26 -04:00

241 lines
6.4 KiB
Go

package api
import (
"context"
"net/http"
"time"
"api-soap-facturacion/internal/config"
"api-soap-facturacion/internal/database"
"api-soap-facturacion/internal/logger"
"api-soap-facturacion/internal/soap"
"api-soap-facturacion/internal/soap/api2"
//"api-soap-facturacion/pkg/errors"
soapPkg "api-soap-facturacion/pkg/soap"
"github.com/gin-gonic/gin"
"github.com/jmoiron/sqlx"
)
// Handler maneja las solicitudes HTTP
type Handler struct {
config *config.Config
logger logger.Logger
db *sqlx.DB
soapClients *soap.Clients
}
// NewHandler crea un nuevo handler
func NewHandler(cfg *config.Config, log logger.Logger, db *sqlx.DB, soapClients *soap.Clients) *Handler {
return &Handler{
config: cfg,
logger: log,
db: db,
soapClients: soapClients,
}
}
// HealthCheck verifica el estado de la aplicación
func (h *Handler) HealthCheck(c *gin.Context) {
// Verificar conexión a la base de datos
dbErr := h.db.Ping()
status := "ok"
statusCode := http.StatusOK
if dbErr != nil {
status = "degraded"
statusCode = http.StatusServiceUnavailable
}
c.JSON(statusCode, gin.H{
"status": status,
"timestamp": time.Now().Format(time.RFC3339),
"version": "1.0.0",
"services": gin.H{
"database": dbErr == nil,
},
})
}
// API2ProcessTransaction maneja solicitudes de transacción para API2
func (h *Handler) API2ProcessTransaction(c *gin.Context) {
// Obtener logger
log := getLogger(c)
// Obtener contexto con timeout
ctx, cancel := context.WithTimeout(c.Request.Context(), h.config.App.RequestTimeout*time.Second)
defer cancel()
// Agregar ID de solicitud al contexto
requestID := c.GetHeader("X-Request-ID")
ctx = context.WithValue(ctx, soapPkg.RequestIDKey{}, requestID)
// Parsear solicitud
var requestData struct {
TransactionID string `json:"transactionId" binding:"required"`
AccountID string `json:"accountId" binding:"required"`
Amount float64 `json:"amount" binding:"required"`
Currency string `json:"currency" binding:"required"`
Description string `json:"description"`
}
if err := c.ShouldBindJSON(&requestData); err != nil {
log.Error("Error al parsear solicitud", logger.NewField("error", err))
c.JSON(http.StatusBadRequest, gin.H{
"error": "Error al parsear solicitud",
})
return
}
// Crear solicitud SOAP
request := api2.TransactionRequest{
Namespace: "http://api2.example.com/soap",
TransactionID: requestData.TransactionID,
AccountID: requestData.AccountID,
Amount: requestData.Amount,
Currency: requestData.Currency,
Description: requestData.Description,
}
// Llamar a API2
response, err := h.soapClients.API2.ProcessTransaction(ctx, request)
if err != nil {
log.Error("Error al llamar a API2", logger.NewField("error", err))
c.JSON(http.StatusInternalServerError, gin.H{
"error": "Error al realizar solicitud a API2",
})
return
}
// Retornar respuesta
c.JSON(http.StatusOK, gin.H{
"resultCode": response.ResultCode,
"resultMessage": response.ResultMessage,
"transactionId": response.TransactionID,
"confirmationCode": response.ConfirmationCode,
"timestamp": response.Timestamp,
})
}
// GetAllParameters retorna todos los parámetros
func (h *Handler) GetAllParameters(c *gin.Context) {
// Obtener logger
log := getLogger(c)
// Consultar parámetros
var params []database.Parameter
query := `SELECT id, key, value, description, active, created_at, updated_at FROM parameters`
err := h.db.Select(&params, query)
if err != nil {
log.Error("Error al obtener parámetros", logger.NewField("error", err))
c.JSON(http.StatusInternalServerError, gin.H{
"error": "Error al obtener parámetros",
})
return
}
// Retornar parámetros
c.JSON(http.StatusOK, params)
}
// GetParameter retorna un parámetro por clave
func (h *Handler) GetParameter(c *gin.Context) {
// Obtener logger
log := getLogger(c)
// Obtener clave
key := c.Param("key")
// Consultar parámetro
var param database.Parameter
query := `SELECT id, key, value, description, active, created_at, updated_at FROM parameters WHERE key = $1`
err := h.db.Get(&param, query, key)
if err != nil {
log.Error("Error al obtener parámetro",
logger.NewField("error", err),
logger.NewField("key", key),
)
c.JSON(http.StatusNotFound, gin.H{
"error": "Parámetro no encontrado",
})
return
}
// Retornar parámetro
c.JSON(http.StatusOK, param)
}
// UpdateParameter actualiza un parámetro
func (h *Handler) UpdateParameter(c *gin.Context) {
// Obtener logger
log := getLogger(c)
// Obtener clave
key := c.Param("key")
// Parsear solicitud
var requestData struct {
Value string `json:"value" binding:"required"`
Description string `json:"description"`
Active bool `json:"active"`
}
if err := c.ShouldBindJSON(&requestData); err != nil {
log.Error("Error al parsear solicitud", logger.NewField("error", err))
c.JSON(http.StatusBadRequest, gin.H{
"error": "Error al parsear solicitud",
})
return
}
// Actualizar parámetro
query := `
UPDATE parameters
SET value = $1, description = $2, active = $3, updated_at = NOW()
WHERE key = $4
RETURNING id, key, value, description, active, created_at, updated_at
`
var param database.Parameter
err := h.db.Get(&param, query,
requestData.Value,
requestData.Description,
requestData.Active,
key,
)
if err != nil {
log.Error("Error al actualizar parámetro",
logger.NewField("error", err),
logger.NewField("key", key),
)
c.JSON(http.StatusInternalServerError, gin.H{
"error": "Error al actualizar parámetro",
})
return
}
// Retornar parámetro actualizado
c.JSON(http.StatusOK, param)
}
// getLogger obtiene el logger del contexto
func getLogger(c *gin.Context) logger.Logger {
if log, exists := c.Get("logger"); exists {
return log.(logger.Logger)
}
// Si no hay logger en el contexto, retornar un logger por defecto
return &defaultLogger{}
}
// defaultLogger es un logger por defecto
type defaultLogger struct{}
func (l *defaultLogger) Debug(msg string, fields ...logger.Field) {}
func (l *defaultLogger) Info(msg string, fields ...logger.Field) {}
func (l *defaultLogger) Warn(msg string, fields ...logger.Field) {}
func (l *defaultLogger) Error(msg string, fields ...logger.Field) {}
func (l *defaultLogger) Fatal(msg string, fields ...logger.Field) {}
func (l *defaultLogger) With(fields ...logger.Field) logger.Logger { return l }