package handler import ( "strconv" "strings" "affiliate_dash/internal/middleware" "affiliate_dash/internal/model" "affiliate_dash/internal/pkg/response" "affiliate_dash/internal/service" "github.com/gin-gonic/gin" ) func (h *MerchantHandler) ListProducts(c *gin.Context) { page, size := pageParams(c) list, total, err := h.merchantSvc.ListMerchantProductsWithOptions(middleware.GetMerchantID(c), page, size, service.ListMerchantProductsOptions{ Status: strings.TrimSpace(c.Query("status")), Keyword: strings.TrimSpace(c.Query("keyword")), }) if err != nil { if err.Error() == "无效的商品状态" { response.BadRequest(c, err.Error()) return } response.ServerError(c, err.Error()) return } response.Page(c, list, total, page, size) } type merchantProductStatusReq struct { Status string `json:"status" binding:"required"` } // UpdateProductStatus PATCH /api/merchant/products/:id/status // 商户仅能上架/下架商品,价格、成本等配置由平台管理员维护。 // UpdateProduct PATCH /api/merchant/products/:id — 编辑商品(显示名称、售价、成本、库存、状态)。 // 严格风控门禁:仅平台超级管理员(model.RoleAdmin)拥有修改商品价格、成本、库存与名称的权限,普通分销商严禁修改。 func (h *MerchantHandler) UpdateProduct(c *gin.Context) { if middleware.GetRole(c) != model.RoleAdmin { response.Forbidden(c, "权限不足:仅平台超级管理员可编辑商品价格、成本与库存") return } id, _ := strconv.ParseUint(c.Param("id"), 10, 64) if id == 0 { response.BadRequest(c, "参数错误") return } var req merchantProductUpdateReq if err := c.ShouldBindJSON(&req); err != nil { response.BadRequest(c, "参数错误") return } if err := h.merchantSvc.UpdateMerchantProduct(middleware.GetMerchantID(c), uint(id), service.UpdateMerchantProductInput{ DisplayName: req.DisplayName, PriceAmount: req.PriceAmount, CostAmount: req.CostAmount, Stock: req.Stock, Status: req.Status, FulfillmentConfig: req.FulfillmentConfig, }, middleware.GetUserID(c)); err != nil { response.BadRequest(c, err.Error()) return } response.OK(c, nil) } func (h *MerchantHandler) UpdateProductStatus(c *gin.Context) { var req merchantProductStatusReq if err := c.ShouldBindJSON(&req); err != nil { response.BadRequest(c, "参数错误:status 必填") return } id, _ := strconv.ParseUint(c.Param("id"), 10, 64) if err := h.merchantSvc.UpdateMerchantProduct(middleware.GetMerchantID(c), uint(id), service.UpdateMerchantProductInput{ Status: &req.Status, }, middleware.GetUserID(c)); err != nil { response.BadRequest(c, err.Error()) return } response.OK(c, nil) } // DeleteProduct DELETE /api/merchant/products/:id — 仅已下架可删(软删除)。 func (h *MerchantHandler) DeleteProduct(c *gin.Context) { id, _ := strconv.ParseUint(c.Param("id"), 10, 64) if err := h.merchantSvc.DeleteMerchantProduct(middleware.GetMerchantID(c), uint(id), middleware.GetUserID(c)); err != nil { response.BadRequest(c, err.Error()) return } response.OK(c, nil) } // ListManualOrderProducts returns active products for order creation without granting product-management access. func (h *MerchantHandler) ListManualOrderProducts(c *gin.Context) { list, _, err := h.merchantSvc.ListMerchantProductsForClient(middleware.GetMerchantID(c), 1, 100) if err != nil { response.ServerError(c, err.Error()) return } response.OK(c, list) } // ListProductCatalog 返回自营商户的全部可售商品,作为平台默认商品目录供分配。 func (h *MerchantHandler) ListProductCatalog(c *gin.Context) { list, err := h.merchantSvc.ListProductCatalog() if err != nil { response.ServerError(c, err.Error()) return } response.OK(c, list) } // ListMerchantProductsByAdmin 供平台管理员查看指定商户的可售商品。 func (h *MerchantHandler) ListMerchantProductsByAdmin(c *gin.Context) { id, _ := strconv.ParseUint(c.Param("id"), 10, 64) list, err := h.merchantSvc.ListMerchantProductsByAdmin(uint(id)) if err != nil { response.ServerError(c, err.Error()) return } response.OK(c, list) } type merchantProductUpdateReq struct { DisplayName *string `json:"display_name"` PriceAmount *int64 `json:"price_amount"` CostAmount *int64 `json:"cost_amount"` Stock *int64 `json:"stock"` Status *string `json:"status"` FulfillmentConfig *string `json:"fulfillment_config"` } // AdminUpdateMerchantProduct 供平台管理员编辑指定商户的商品(价格、成本、库存、状态等)。 func (h *MerchantHandler) AdminUpdateMerchantProduct(c *gin.Context) { merchantID, _ := strconv.ParseUint(c.Param("id"), 10, 64) productID, _ := strconv.ParseUint(c.Param("pid"), 10, 64) if merchantID == 0 || productID == 0 { response.BadRequest(c, "参数错误") return } var req merchantProductUpdateReq if err := c.ShouldBindJSON(&req); err != nil { response.BadRequest(c, "参数错误") return } if err := h.merchantSvc.UpdateMerchantProduct(uint(merchantID), uint(productID), service.UpdateMerchantProductInput{ DisplayName: req.DisplayName, PriceAmount: req.PriceAmount, CostAmount: req.CostAmount, Stock: req.Stock, Status: req.Status, FulfillmentConfig: req.FulfillmentConfig, }, middleware.GetUserID(c)); err != nil { response.BadRequest(c, err.Error()) return } response.OK(c, nil) } type assignProductsReq struct { CatalogIDs []uint `json:"catalog_ids"` } // AssignProducts 按商品目录 ID 批量同步商户的可售商品。 func (h *MerchantHandler) AssignProducts(c *gin.Context) { id, _ := strconv.ParseUint(c.Param("id"), 10, 64) var req assignProductsReq if err := c.ShouldBindJSON(&req); err != nil { response.BadRequest(c, "参数错误") return } count, err := h.merchantSvc.AssignProducts(uint(id), service.AssignProductsInput{ CatalogIDs: req.CatalogIDs, }, middleware.GetUserID(c)) if err != nil { response.BadRequest(c, err.Error()) return } response.OK(c, gin.H{"assigned": count}) }