package handler import ( "net/http" "time" "sql-platform/internal/middleware" "sql-platform/internal/model" "github.com/gin-gonic/gin" ) // GET /api/v1/tickets/scheduled/list // Lists tickets that have scheduled_at set and status is "approved" (waiting for scheduled execution). func ListScheduledTasks(c *gin.Context) { userID, _, role := middleware.GetCurrentUser(c) query := model.DB.Model(&model.Ticket{}). Where("scheduled_at IS NOT NULL AND scheduled_at != '' AND status IN ?", []string{"approved", "scheduled"}). Order("scheduled_at ASC") // Filter by user role (same logic as ListTickets) switch role { case "developer": query = query.Where("applicant_id = ?", userID) case "dba", "auditor": query = query.Where( "applicant_id = ? OR id IN (SELECT ticket_id FROM ticket_approvals WHERE approver_id = ?)", userID, userID, ) // admin sees everything } var total int64 query.Count(&total) var tickets []model.Ticket query.Find(&tickets) // Enrich with instance_name and instance_db_type type ScheduledTicketItem struct { model.Ticket InstanceName string `json:"instance_name"` InstanceDBType string `json:"instance_db_type"` } items := make([]ScheduledTicketItem, 0, len(tickets)) for _, t := range tickets { item := ScheduledTicketItem{ Ticket: t, } var instance model.Instance if err := model.DB.Select("name, db_type").First(&instance, t.InstanceID).Error; err == nil { item.InstanceName = instance.Name item.InstanceDBType = instance.DBType } items = append(items, item) } c.JSON(http.StatusOK, gin.H{ "items": items, "total": total, }) } // POST /api/v1/tickets/:id/cancel-schedule // Cancels a scheduled task by clearing scheduled_at and setting status to "cancelled". func CancelScheduledTask(c *gin.Context) { id := c.Param("id") userID, _, role := middleware.GetCurrentUser(c) var ticket model.Ticket if err := model.DB.First(&ticket, id).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{"detail": "Ticket not found"}) return } // Only the applicant or admin/dba can cancel if ticket.ApplicantID != userID && role != "admin" && role != "dba" { c.JSON(http.StatusForbidden, gin.H{"detail": "Permission denied"}) return } // Only allow cancellation of scheduled tickets if !ticket.ScheduledAt.Valid { c.JSON(http.StatusBadRequest, gin.H{"detail": "Ticket is not scheduled"}) return } status := "cancelled" ticket.Status = &status ticket.ScheduledAt.Valid = false ticket.ScheduledAt.Time = time.Time{} model.DB.Save(&ticket) c.JSON(http.StatusOK, gin.H{"message": "Scheduled task cancelled", "ticket_id": ticket.ID}) }