package handlers import ( "math" "net/http" "strconv" "sale/internal/models" "sale/internal/schemas" "sale/internal/utils" "github.com/gin-gonic/gin" ) type TicketHandler struct{} func NewTicketHandler() *TicketHandler { return &TicketHandler{} } func (h *TicketHandler) List(c *gin.Context) { userID := c.GetUint("user_id") page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20")) var total int64 utils.DB.Model(&models.Ticket{}).Where("user_id = ?", userID).Count(&total) var tickets []models.Ticket offset := (page - 1) * pageSize utils.DB.Where("user_id = ?", userID).Order("created_at DESC").Offset(offset).Limit(pageSize).Find(&tickets) totalPages := int(math.Ceil(float64(total) / float64(pageSize))) c.JSON(http.StatusOK, gin.H{ "data": tickets, "pagination": gin.H{ "page": page, "page_size": pageSize, "total": total, "total_pages": totalPages, }, }) } func (h *TicketHandler) Create(c *gin.Context) { userID := c.GetUint("user_id") var req schemas.CreateTicketRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } category := req.Category if category == "" { category = models.TicketCategoryOther } ticket := models.Ticket{ UserID: userID, Title: req.Title, Content: req.Content, Category: category, Status: models.TicketStatusPending, } utils.DB.Create(&ticket) c.JSON(http.StatusCreated, gin.H{"data": ticket}) } func (h *TicketHandler) GetByID(c *gin.Context) { userID := c.GetUint("user_id") id, _ := strconv.Atoi(c.Param("id")) var ticket models.Ticket if err := utils.DB.Where("id = ? AND user_id = ?", id, userID).First(&ticket).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "Ticket not found"}) return } c.JSON(http.StatusOK, gin.H{"data": ticket}) } func (h *TicketHandler) AdminList(c *gin.Context) { page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20")) status := c.Query("status") var total int64 query := utils.DB.Model(&models.Ticket{}) if status != "" { query = query.Where("status = ?", status) } query.Count(&total) var tickets []models.Ticket offset := (page - 1) * pageSize q := utils.DB.Preload("User").Preload("Assignee") if status != "" { q = q.Where("status = ?", status) } q.Order("created_at DESC").Offset(offset).Limit(pageSize).Find(&tickets) totalPages := int(math.Ceil(float64(total) / float64(pageSize))) c.JSON(http.StatusOK, gin.H{ "data": tickets, "pagination": gin.H{ "page": page, "page_size": pageSize, "total": total, "total_pages": totalPages, }, }) } func (h *TicketHandler) Update(c *gin.Context) { id, _ := strconv.Atoi(c.Param("id")) var ticket models.Ticket if err := utils.DB.First(&ticket, id).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "Ticket not found"}) return } var req schemas.UpdateTicketRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } updates := make(map[string]interface{}) if req.Status != nil { updates["status"] = *req.Status } if req.AssignedTo != nil { updates["assigned_to"] = *req.AssignedTo } if req.Reply != nil { updates["reply"] = *req.Reply } utils.DB.Model(&ticket).Updates(updates) c.JSON(http.StatusOK, gin.H{"data": ticket}) } func (h *TicketHandler) Assign(c *gin.Context) { id, _ := strconv.Atoi(c.Param("id")) var ticket models.Ticket if err := utils.DB.First(&ticket, id).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "Ticket not found"}) return } var req struct { AssignedTo uint `json:"assigned_to" binding:"required"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } utils.DB.Model(&ticket).Updates(map[string]interface{}{ "assigned_to": req.AssignedTo, "status": models.TicketStatusProcessing, }) c.JSON(http.StatusOK, gin.H{"message": "Ticket assigned successfully"}) }