package controllers import ( "nearle/db" "nearle/models" "net/http" "strconv" "github.com/gofiber/fiber/v2" "gorm.io/gorm/clause" ) func GetSubstitutions(c *fiber.Ctx) error { tenantID, _ := strconv.Atoi(c.Query("tenant_id")) if tenantID == 0 { return c.Status(http.StatusBadRequest).JSON(fiber.Map{ "code": http.StatusBadRequest, "message": "Missing tenant_id", "status": false, }) } date := c.Query("date") fromDate := c.Query("from_date") toDate := c.Query("to_date") status := c.Query("status") query := db.DB.Model(&models.RiderSubstitution{}).Where("tenant_id = ?", tenantID) if date != "" { query = query.Where("sub_date = ?", date) } if fromDate != "" && toDate != "" { query = query.Where("sub_date >= ? AND sub_date <= ?", fromDate, toDate) } if status != "" { query = query.Where("status = ?", status) } var results []models.RiderSubstitution if err := query.Find(&results).Error; err != nil { return c.Status(http.StatusInternalServerError).JSON(fiber.Map{ "code": http.StatusInternalServerError, "message": err.Error(), "status": false, }) } return c.JSON(fiber.Map{ "code": http.StatusOK, "count": len(results), "details": results, "status": true, }) } func GetSubstitutionByID(c *fiber.Ctx) error { id := c.Params("id") tenantID, _ := strconv.Atoi(c.Query("tenant_id")) var result models.RiderSubstitution if err := db.DB.Where("id = ? AND tenant_id = ?", id, tenantID).First(&result).Error; err != nil { return c.Status(http.StatusNotFound).JSON(fiber.Map{ "code": http.StatusNotFound, "message": "Record not found", "status": false, }) } return c.JSON(fiber.Map{ "code": http.StatusOK, "details": result, "status": true, }) } type CreateSubstitutionsRequest struct { TenantID int `json:"tenant_id"` Substitutions []models.RiderSubstitution `json:"substitutions"` } func CreateSubstitutions(c *fiber.Ctx) error { var req CreateSubstitutionsRequest if err := c.BodyParser(&req); err != nil { return c.Status(http.StatusBadRequest).JSON(fiber.Map{ "code": http.StatusBadRequest, "message": err.Error(), "status": false, }) } for i := range req.Substitutions { req.Substitutions[i].TenantID = req.TenantID if req.Substitutions[i].Status == "" { req.Substitutions[i].Status = "scheduled" } } if len(req.Substitutions) == 0 { return c.Status(http.StatusBadRequest).JSON(fiber.Map{ "code": http.StatusBadRequest, "message": "No substitutions provided", "status": false, }) } // Upsert to handle unique constraint on (tenant_id, sub_date, absent_rider_id) if err := db.DB.Clauses(clause.OnConflict{ Columns: []clause.Column{{Name: "tenant_id"}, {Name: "sub_date"}, {Name: "absent_rider_id"}}, UpdateAll: true, }).Create(&req.Substitutions).Error; err != nil { return c.Status(http.StatusInternalServerError).JSON(fiber.Map{ "code": http.StatusInternalServerError, "message": err.Error(), "status": false, }) } return c.JSON(fiber.Map{ "code": http.StatusOK, "registered": len(req.Substitutions), "details": req.Substitutions, "status": true, }) } func UpdateSubstitution(c *fiber.Ctx) error { id := c.Params("id") var updateData map[string]interface{} if err := c.BodyParser(&updateData); err != nil { return c.Status(http.StatusBadRequest).JSON(fiber.Map{ "code": http.StatusBadRequest, "message": err.Error(), "status": false, }) } tenantIDStr := updateData["tenant_id"] if tenantIDStr == nil { return c.Status(http.StatusBadRequest).JSON(fiber.Map{ "code": http.StatusBadRequest, "message": "Missing tenant_id in body", "status": false, }) } var tenantID int switch v := tenantIDStr.(type) { case float64: tenantID = int(v) case string: tenantID, _ = strconv.Atoi(v) } if err := db.DB.Model(&models.RiderSubstitution{}).Where("id = ? AND tenant_id = ?", id, tenantID).Updates(updateData).Error; err != nil { return c.Status(http.StatusInternalServerError).JSON(fiber.Map{ "code": http.StatusInternalServerError, "message": err.Error(), "status": false, }) } return c.JSON(fiber.Map{ "code": http.StatusOK, "message": "Updated successfully", "status": true, }) } func UpdateSubstitutionStatus(c *fiber.Ctx) error { id := c.Params("id") var req struct { TenantID int `json:"tenant_id"` Status string `json:"status"` } if err := c.BodyParser(&req); err != nil { return c.Status(http.StatusBadRequest).JSON(fiber.Map{ "code": http.StatusBadRequest, "message": err.Error(), "status": false, }) } if req.TenantID == 0 || req.Status == "" { return c.Status(http.StatusBadRequest).JSON(fiber.Map{ "code": http.StatusBadRequest, "message": "Missing tenant_id or status", "status": false, }) } if err := db.DB.Model(&models.RiderSubstitution{}).Where("id = ? AND tenant_id = ?", id, req.TenantID).Update("status", req.Status).Error; err != nil { return c.Status(http.StatusInternalServerError).JSON(fiber.Map{ "code": http.StatusInternalServerError, "message": err.Error(), "status": false, }) } return c.JSON(fiber.Map{ "code": http.StatusOK, "message": "Status updated successfully", "status": true, }) } func DeleteSubstitution(c *fiber.Ctx) error { id := c.Params("id") tenantID, _ := strconv.Atoi(c.Query("tenant_id")) if tenantID == 0 { return c.Status(http.StatusBadRequest).JSON(fiber.Map{ "code": http.StatusBadRequest, "message": "Missing tenant_id", "status": false, }) } // Soft delete by updating status to 'cancelled' if err := db.DB.Model(&models.RiderSubstitution{}).Where("id = ? AND tenant_id = ?", id, tenantID).Update("status", "cancelled").Error; err != nil { return c.Status(http.StatusInternalServerError).JSON(fiber.Map{ "code": http.StatusInternalServerError, "message": err.Error(), "status": false, }) } return c.JSON(fiber.Map{ "code": http.StatusOK, "message": "Deleted successfully", "status": true, }) }