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(¶ms, 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(¶m, 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(¶m, 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 }