package handler import ( "errors" "net/http" "strconv" "github.com/gin-gonic/gin" "github.com/google/uuid" "github.com/yuxingu/digital-psychology/apps/api/internal/middleware" "github.com/yuxingu/digital-psychology/apps/api/internal/service/admin" "github.com/yuxingu/digital-psychology/apps/api/pkg/response" ) func (h *AdminHandler) registerRedemption(authed *gin.RouterGroup) { authed.POST("/redemption-batches", middleware.RequireAdminPermission(h.Svc, admin.PermMembershipCodesWrite), h.CreateRedemptionBatch) authed.GET("/redemption-batches", middleware.RequireAdminPermission(h.Svc, admin.PermMembershipCodesRead), h.ListRedemptionBatches) authed.GET("/redemption-batches/:id/codes", middleware.RequireAdminPermission(h.Svc, admin.PermMembershipCodesRead), h.ListRedemptionCodes) authed.POST("/redemption-codes/:id/disable", middleware.RequireAdminPermission(h.Svc, admin.PermMembershipCodesWrite), h.DisableRedemptionCode) } func (h *AdminHandler) CreateRedemptionBatch(c *gin.Context) { adminID, ok := middleware.AdminIDFromContext(c) if !ok { response.Fail(c, http.StatusUnauthorized, 40102, "admin session invalid") return } var body struct { Label string `json:"label"` PlanCode string `json:"plan_code"` Quantity int `json:"quantity"` } if err := c.ShouldBindJSON(&body); err != nil { response.Fail(c, http.StatusBadRequest, 40000, "invalid body") return } batch, codes, err := h.Svc.CreateRedemptionBatch(c.Request.Context(), adminID, body.Label, body.PlanCode, body.Quantity) if errors.Is(err, admin.ErrBadBatchQty) || errors.Is(err, admin.ErrPlanNotFound) || errors.Is(err, admin.ErrInvalidPlanU) { response.Fail(c, http.StatusBadRequest, 40000, err.Error()) return } if err != nil { response.Fail(c, http.StatusInternalServerError, 50000, err.Error()) return } response.OK(c, gin.H{"batch": batch, "codes": codes}) } func (h *AdminHandler) ListRedemptionBatches(c *gin.Context) { limit, _ := strconv.Atoi(c.DefaultQuery("limit", "50")) items, err := h.Svc.ListRedemptionBatches(c.Request.Context(), limit) if err != nil { response.Fail(c, http.StatusInternalServerError, 50000, err.Error()) return } response.OK(c, gin.H{"items": items}) } func (h *AdminHandler) ListRedemptionCodes(c *gin.Context) { id, err := uuid.Parse(c.Param("id")) if err != nil { response.Fail(c, http.StatusBadRequest, 40000, "invalid id") return } items, err := h.Svc.ListRedemptionCodes(c.Request.Context(), id) if errors.Is(err, admin.ErrBatchNotFound) { response.Fail(c, http.StatusNotFound, 40400, "batch not found") return } if err != nil { response.Fail(c, http.StatusInternalServerError, 50000, err.Error()) return } response.OK(c, gin.H{"items": items}) } func (h *AdminHandler) DisableRedemptionCode(c *gin.Context) { adminID, ok := middleware.AdminIDFromContext(c) if !ok { response.Fail(c, http.StatusUnauthorized, 40102, "admin session invalid") return } id, err := uuid.Parse(c.Param("id")) if err != nil { response.Fail(c, http.StatusBadRequest, 40000, "invalid id") return } err = h.Svc.DisableRedemptionCode(c.Request.Context(), adminID, id) if errors.Is(err, admin.ErrCodeDisable) { response.Fail(c, http.StatusBadRequest, 40000, err.Error()) return } if err != nil { response.Fail(c, http.StatusInternalServerError, 50000, err.Error()) return } response.OK(c, gin.H{"ok": true}) }