package controllers import ( "strings" "abdanhafidz.com/go-boilerplate/models/dto" http_error "abdanhafidz.com/go-boilerplate/models/error" "abdanhafidz.com/go-boilerplate/services" "github.com/gin-gonic/gin" ) type SuperAdminInjectController interface { InjectProblemSet(ctx *gin.Context) InjectZip(ctx *gin.Context) } type superAdminInjectController struct { problemSetService services.ProblemSetService zipInjectService services.ZipInjectService } func NewSuperAdminInjectController(problemSetService services.ProblemSetService, zipInjectService services.ZipInjectService) SuperAdminInjectController { return &superAdminInjectController{problemSetService: problemSetService, zipInjectService: zipInjectService} } // InjectProblemSet godoc // @Summary Super Admin: Inject Problem Sets from CSV Upload // @Description Inject problem sets and questions from an uploaded CSV (normalized_questions.csv format) // @Tags Super Admin Inject // @Accept multipart/form-data // @Produce json // @Param file formData file true "CSV file (normalized_questions.csv format)" // @Security BearerAuth // @Success 200 {object} dto.SuccessResponse[dto.ProblemSetInjectResponse] // @Failure 400 {object} dto.ErrorResponse // @Failure 401 {object} dto.ErrorResponse // @Failure 403 {object} dto.ErrorResponse // @Failure 404 {object} dto.ErrorResponse // @Failure 409 {object} dto.ErrorResponse // @Failure 500 {object} dto.ErrorResponse // @Router /api/v1/super-admin/inject/probset [post] func (c *superAdminInjectController) InjectProblemSet(ctx *gin.Context) { fileHeader, err := ctx.FormFile("file") if err != nil { ResponseJSON(ctx, gin.H{"file": ""}, dto.ProblemSetInjectResponse{}, http_error.BAD_REQUEST_ERROR) return } file, err := fileHeader.Open() if err != nil { ResponseJSON(ctx, gin.H{"file": fileHeader.Filename}, dto.ProblemSetInjectResponse{}, http_error.INTERNAL_SERVER_ERROR) return } defer file.Close() result, err := c.problemSetService.InjectProblemSetsFromCSV(ctx.Request.Context(), fileHeader.Filename, file) ResponseJSON(ctx, gin.H{"file": result.File}, result, err) } // InjectZip godoc // @Summary Super Admin: Inject Zip to Storage // @Description Upload a zip file and mirror its directory structure to storage // @Tags Super Admin Inject // @Accept multipart/form-data // @Produce json // @Param file formData file true "Zip file" // @Param base_path formData string false "Base path prefix in storage" // @Security BearerAuth // @Success 200 {object} dto.SuccessResponse[dto.ZipInjectResponse] // @Failure 400 {object} dto.ErrorResponse // @Failure 401 {object} dto.ErrorResponse // @Failure 403 {object} dto.ErrorResponse // @Failure 500 {object} dto.ErrorResponse // @Router /api/v1/super-admin/inject/zip [post] func (c *superAdminInjectController) InjectZip(ctx *gin.Context) { fileHeader, err := ctx.FormFile("file") if err != nil { ResponseJSON(ctx, gin.H{"file": ""}, dto.ZipInjectResponse{}, http_error.BAD_REQUEST_ERROR) return } file, err := fileHeader.Open() if err != nil { ResponseJSON(ctx, gin.H{"file": fileHeader.Filename}, dto.ZipInjectResponse{}, http_error.INTERNAL_SERVER_ERROR) return } defer file.Close() basePath := strings.TrimSpace(ctx.PostForm("base_path")) result, err := c.zipInjectService.InjectZipToStorage(ctx.Request.Context(), file, fileHeader.Size, basePath) result.File = fileHeader.Filename ResponseJSON(ctx, gin.H{"file": result.File}, result, err) }