mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-04 02:32:57 +00:00
dev day #90 🥳
This commit is contained in:
@@ -21,6 +21,29 @@ type EngagementController struct {
|
||||
Email email.EmailService
|
||||
}
|
||||
|
||||
// parseMetaTime tries to parse time from metadata value which can be string (RFC3339 or YYYY-MM-DD) or numeric unix seconds.
|
||||
func parseMetaTime(v interface{}) time.Time {
|
||||
switch t := v.(type) {
|
||||
case string:
|
||||
s := strings.TrimSpace(t)
|
||||
if s == "" { return time.Time{} }
|
||||
if ts, err := time.Parse(time.RFC3339, s); err == nil { return ts }
|
||||
if ts, err := time.Parse("2006-01-02T15:04", s); err == nil { return ts }
|
||||
if ts, err := time.Parse("2006-01-02", s); err == nil { return ts }
|
||||
case float64:
|
||||
// JSON numbers decode to float64
|
||||
if t <= 0 { return time.Time{} }
|
||||
return time.Unix(int64(t), 0)
|
||||
case int64:
|
||||
if t <= 0 { return time.Time{} }
|
||||
return time.Unix(t, 0)
|
||||
case int:
|
||||
if t <= 0 { return time.Time{} }
|
||||
return time.Unix(int64(t), 0)
|
||||
}
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
func NewEngagementController(db *gorm.DB, es email.EmailService) *EngagementController {
|
||||
return &EngagementController{DB: db, Email: es}
|
||||
}
|
||||
@@ -224,7 +247,31 @@ func (ec *EngagementController) GetRewards(c *gin.Context) {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to load rewards"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, items)
|
||||
// Filter by optional validity window in metadata (valid_from, valid_to). Also accept legacy expires_at as valid_to.
|
||||
now := time.Now()
|
||||
filtered := make([]models.RewardItem, 0, len(items))
|
||||
for _, it := range items {
|
||||
// Mandatory unlock reward is always available
|
||||
if strings.EqualFold(strings.TrimSpace(it.Type), "avatar_upload_unlock") {
|
||||
filtered = append(filtered, it)
|
||||
continue
|
||||
}
|
||||
var startPtr, endPtr *time.Time
|
||||
if it.Metadata != nil {
|
||||
if v, ok := it.Metadata["valid_from"]; ok {
|
||||
if ts := parseMetaTime(v); !ts.IsZero() { startPtr = &ts }
|
||||
}
|
||||
if v, ok := it.Metadata["valid_to"]; ok {
|
||||
if ts := parseMetaTime(v); !ts.IsZero() { endPtr = &ts }
|
||||
} else if v2, ok2 := it.Metadata["expires_at"]; ok2 { // alias
|
||||
if ts := parseMetaTime(v2); !ts.IsZero() { endPtr = &ts }
|
||||
}
|
||||
}
|
||||
if startPtr != nil && now.Before(*startPtr) { continue }
|
||||
if endPtr != nil && now.After(*endPtr) { continue }
|
||||
filtered = append(filtered, it)
|
||||
}
|
||||
c.JSON(http.StatusOK, filtered)
|
||||
}
|
||||
|
||||
// POST /api/v1/engagement/redeem (auth)
|
||||
@@ -252,6 +299,27 @@ func (ec *EngagementController) Redeem(c *gin.Context) {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Reward is not active"})
|
||||
return
|
||||
}
|
||||
// Check validity window (metadata.valid_from/valid_to or expires_at)
|
||||
if item.Metadata != nil {
|
||||
var startPtr, endPtr *time.Time
|
||||
if v, ok := item.Metadata["valid_from"]; ok {
|
||||
if ts := parseMetaTime(v); !ts.IsZero() { startPtr = &ts }
|
||||
}
|
||||
if v, ok := item.Metadata["valid_to"]; ok {
|
||||
if ts := parseMetaTime(v); !ts.IsZero() { endPtr = &ts }
|
||||
} else if v2, ok2 := item.Metadata["expires_at"]; ok2 {
|
||||
if ts := parseMetaTime(v2); !ts.IsZero() { endPtr = &ts }
|
||||
}
|
||||
now := time.Now()
|
||||
if startPtr != nil && now.Before(*startPtr) {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Reward is not currently available"})
|
||||
return
|
||||
}
|
||||
if endPtr != nil && now.After(*endPtr) {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Reward validity has ended"})
|
||||
return
|
||||
}
|
||||
}
|
||||
if item.Stock == 0 {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Out of stock"})
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user