package handler import ( "crypto/md5" "encoding/hex" "fmt" "math/rand" "net/http" "strings" "time" "xboard-go/internal/database" "xboard-go/internal/model" "github.com/gin-gonic/gin" ) // AdminGiftCardFetch handles fetching of gift card templates and batch info. func AdminGiftCardFetch(c *gin.Context) { params := getFetchParams(c) id := params["id"] if id != "" { var template model.GiftCardTemplate if err := database.DB.Where("id = ?", id).First(&template).Error; err != nil { Fail(c, http.StatusNotFound, "Template not found") return } Success(c, template) return } var data []model.GiftCardTemplate database.DB.Order("sort ASC, id DESC").Find(&data) Success(c, data) } // AdminGiftCardSave creates or updates a gift card template. func AdminGiftCardSave(c *gin.Context) { var payload model.GiftCardTemplate if err := c.ShouldBindJSON(&payload); err != nil { Fail(c, http.StatusBadRequest, "invalid request body") return } if payload.ID > 0 { if err := database.DB.Model(&model.GiftCardTemplate{}).Where("id = ?", payload.ID).Updates(payload).Error; err != nil { Fail(c, http.StatusInternalServerError, "failed to update template") return } } else { payload.Status = true if err := database.DB.Create(&payload).Error; err != nil { Fail(c, http.StatusInternalServerError, "failed to create template") return } } Success(c, true) } // AdminGiftCardGenerate batches generation of codes for a template. func AdminGiftCardGenerate(c *gin.Context) { var payload struct { TemplateID int `json:"template_id"` Count int `json:"count"` Prefix string `json:"prefix"` ExpiresAt int64 `json:"expires_at"` } if err := c.ShouldBindJSON(&payload); err != nil || payload.TemplateID <= 0 || payload.Count <= 0 { Fail(c, http.StatusBadRequest, "template_id and count are required") return } batchID := fmt.Sprintf("batch_%d", time.Now().Unix()) prefix := payload.Prefix if prefix == "" { prefix = "GC" } tx := database.DB.Begin() for i := 0; i < payload.Count; i++ { code := generateGiftCode(prefix) item := model.GiftCardCode{ TemplateID: payload.TemplateID, Code: code, BatchID: batchID, Status: 0, // Unused MaxUsage: 1, ExpiresAt: &payload.ExpiresAt, } if payload.ExpiresAt == 0 { item.ExpiresAt = nil } if err := tx.Create(&item).Error; err != nil { tx.Rollback() Fail(c, http.StatusInternalServerError, "failed to generate codes") return } } tx.Commit() Success(c, gin.H{"batch_id": batchID}) } func AdminGiftCardDeleteTemplate(c *gin.Context) { var payload struct { ID int `json:"id"` } if err := c.ShouldBindJSON(&payload); err != nil || payload.ID <= 0 { Fail(c, http.StatusBadRequest, "template id is required") return } if err := database.DB.Delete(&model.GiftCardTemplate{}, payload.ID).Error; err != nil { Fail(c, http.StatusInternalServerError, "failed to delete template") return } Success(c, true) } func generateGiftCode(prefix string) string { r := rand.New(rand.NewSource(time.Now().UnixNano())) hash := md5.Sum([]byte(fmt.Sprintf("%d%d", time.Now().UnixNano(), r.Int63()))) return prefix + strings.ToUpper(hex.EncodeToString(hash[:])[:12]) }