feat(integrations): align shopify parity
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
@@ -30,10 +32,10 @@ func (h *ShopifyIntegrationHandler) Delete(c *gin.Context) {
|
||||
}
|
||||
|
||||
if svcErr := h.svc.Delete(c.Request.Context(), accountID); svcErr != nil {
|
||||
handleServiceError(c, svcErr)
|
||||
handleShopifyServiceError(c, svcErr)
|
||||
return
|
||||
}
|
||||
response.OK(c, gin.H{"message": "Shopify integration deleted"})
|
||||
c.Status(http.StatusOK)
|
||||
}
|
||||
|
||||
// Auth returns the Shopify OAuth authorize URL.
|
||||
@@ -46,17 +48,21 @@ func (h *ShopifyIntegrationHandler) Auth(c *gin.Context) {
|
||||
}
|
||||
|
||||
var req service.CreateShopifyAuthRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
if err := c.ShouldBind(&req); err != nil {
|
||||
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
if strings.TrimSpace(req.ShopDomain) == "" {
|
||||
c.JSON(http.StatusUnprocessableEntity, gin.H{"error": "Shop domain is required"})
|
||||
return
|
||||
}
|
||||
|
||||
redirect, svcErr := h.svc.BuildAuthRedirect(c.Request.Context(), accountID, req)
|
||||
if svcErr != nil {
|
||||
handleServiceError(c, svcErr)
|
||||
handleShopifyServiceError(c, svcErr)
|
||||
return
|
||||
}
|
||||
response.OK(c, redirect)
|
||||
c.JSON(http.StatusOK, redirect)
|
||||
}
|
||||
|
||||
// GetOrders retrieves Shopify orders for an account.
|
||||
@@ -68,16 +74,22 @@ func (h *ShopifyIntegrationHandler) GetOrders(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
orders, svcErr := h.svc.GetOrders(c.Request.Context(), accountID)
|
||||
if svcErr != nil {
|
||||
handleServiceError(c, svcErr)
|
||||
contactID, err := parseOptionalUintQueryParam(c, "contact_id")
|
||||
if err != nil {
|
||||
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid contact_id")
|
||||
return
|
||||
}
|
||||
response.OK(c, orders)
|
||||
orders, svcErr := h.svc.GetOrders(c.Request.Context(), accountID, contactID)
|
||||
if svcErr != nil {
|
||||
handleShopifyServiceError(c, svcErr)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"orders": orders})
|
||||
}
|
||||
|
||||
// RegisterShopifyIntegrationRoutes registers Shopify integration routes.
|
||||
func RegisterShopifyIntegrationRoutes(g *gin.RouterGroup, h *ShopifyIntegrationHandler) {
|
||||
g.DELETE("/shopify", h.Delete)
|
||||
shopify := g.Group("/shopify")
|
||||
{
|
||||
shopify.DELETE("/", h.Delete)
|
||||
@@ -85,3 +97,12 @@ func RegisterShopifyIntegrationRoutes(g *gin.RouterGroup, h *ShopifyIntegrationH
|
||||
shopify.GET("/orders", h.GetOrders)
|
||||
}
|
||||
}
|
||||
|
||||
func handleShopifyServiceError(c *gin.Context, err error) {
|
||||
var providerErr *service.ShopifyProviderError
|
||||
if errors.As(err, &providerErr) {
|
||||
c.JSON(http.StatusUnprocessableEntity, gin.H{"error": providerErr.Message})
|
||||
return
|
||||
}
|
||||
handleServiceError(c, err)
|
||||
}
|
||||
|
||||
@@ -74,6 +74,21 @@ func TestShopifyIntegration_Auth_InvalidJSON(t *testing.T) {
|
||||
assert.False(t, resp["success"].(bool))
|
||||
}
|
||||
|
||||
func TestShopifyIntegration_Auth_MissingShopDomain(t *testing.T) {
|
||||
r := setupShopifyIntegrationRouter()
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest("POST", "/api/v1/accounts/1/integrations/shopify/auth", bytes.NewReader([]byte(`{}`)))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
r.ServeHTTP(w, req)
|
||||
|
||||
assert.Equal(t, http.StatusUnprocessableEntity, w.Code)
|
||||
|
||||
var resp map[string]interface{}
|
||||
json.Unmarshal(w.Body.Bytes(), &resp)
|
||||
assert.Equal(t, "Shop domain is required", resp["error"])
|
||||
}
|
||||
|
||||
func TestShopifyIntegration_GetOrders_BadAccountID(t *testing.T) {
|
||||
r := setupShopifyIntegrationRouter()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user