SiLaju / controllers /report_controller.go
RyZ
refactor: cleaning magic variable and error
e02b818
package controllers
import (
"encoding/json"
"net/http"
"strconv"
"dinacom-11.0-backend/models/dto"
"dinacom-11.0-backend/services"
"dinacom-11.0-backend/utils"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
)
type ReportController interface {
CreateReport(ctx *gin.Context)
GetReports(ctx *gin.Context)
AssignWorker(ctx *gin.Context)
GetAssignedReports(ctx *gin.Context)
FinishReport(ctx *gin.Context)
GetUserReports(ctx *gin.Context)
GetWorkerAssignedReports(ctx *gin.Context)
GetWorkerHistory(ctx *gin.Context)
VerifyReport(ctx *gin.Context)
}
type reportController struct {
reportService services.ReportService
}
func NewReportController(reportService services.ReportService) ReportController {
return &reportController{reportService: reportService}
}
// @Summary Create Report
// @Description Submit a new report with image and location data
// @Tags Report
// @Accept multipart/form-data
// @Produce json
// @Param files formData file true "Image file (JPG, PNG, JPEG, max 32MB)"
// @Param json formData string true "JSON data" default({"longitude": 106.816666, "latitude": -6.200000, "road_name": "Jalan Sudirman", "description": "Lubang besar di tengah jalan"})
// @Security BearerAuth
// @Success 200 {object} dto.ReportResponse
// @Failure 400 {object} map[string]string
// @Router /api/user/report [post]
func (c *reportController) CreateReport(ctx *gin.Context) {
userIDVal, exists := ctx.Get("user_id")
if !exists {
utils.SendErrorResponse(ctx, http.StatusUnauthorized, "Unauthorized")
return
}
userID := userIDVal.(uuid.UUID)
file, header, err := ctx.Request.FormFile("files")
if err != nil {
utils.SendErrorResponse(ctx, http.StatusBadRequest, "Image file is required")
return
}
defer file.Close()
jsonData := ctx.PostForm("json")
if jsonData == "" {
utils.SendErrorResponse(ctx, http.StatusBadRequest, "JSON data is required")
return
}
var req dto.ReportRequest
if err := json.Unmarshal([]byte(jsonData), &req); err != nil {
utils.SendErrorResponse(ctx, http.StatusBadRequest, "Invalid JSON format")
return
}
response, err := c.reportService.CreateReport(userID, file, header, req)
if err != nil {
utils.SendErrorResponse(ctx, http.StatusBadRequest, err.Error())
return
}
utils.SendSuccessResponse(ctx, "Report created successfully", response)
}
// @Summary Get Reports
// @Description Get all completed reports with non-good destruct class
// @Tags Report
// @Produce json
// @Success 200 {array} dto.ReportLocationResponse
// @Failure 500 {object} map[string]string
// @Router /api/get_report [get]
func (c *reportController) GetReports(ctx *gin.Context) {
reports, err := c.reportService.GetReports()
if err != nil {
utils.SendErrorResponse(ctx, http.StatusInternalServerError, err.Error())
return
}
utils.SendSuccessResponse(ctx, "Reports retrieved", reports)
}
// @Summary Assign Worker to Report
// @Description Admin assigns a worker to a report
// @Tags Admin
// @Accept json
// @Produce json
// @Param request body dto.AssignWorkerRequest true "Assign Worker Request"
// @Security BearerAuth
// @Success 200 {object} map[string]string
// @Failure 400 {object} map[string]string
// @Router /api/admin/report/assign [patch]
func (c *reportController) AssignWorker(ctx *gin.Context) {
var req dto.AssignWorkerRequest
if err := ctx.ShouldBindJSON(&req); err != nil {
utils.SendErrorResponse(ctx, http.StatusBadRequest, err.Error())
return
}
message, err := c.reportService.AssignWorker(req)
if err != nil {
utils.SendErrorResponse(ctx, http.StatusBadRequest, err.Error())
return
}
utils.SendSuccessResponse(ctx, message, nil)
}
// @Summary Get Assigned Workers
// @Description Get all workers with assigned reports
// @Tags Admin
// @Produce json
// @Security BearerAuth
// @Success 200 {array} dto.AssignedWorkerResponse
// @Failure 500 {object} map[string]string
// @Router /api/admin/report/assign [get]
func (c *reportController) GetAssignedReports(ctx *gin.Context) {
reports, err := c.reportService.GetAssignedReports()
if err != nil {
utils.SendErrorResponse(ctx, http.StatusInternalServerError, err.Error())
return
}
utils.SendSuccessResponse(ctx, "Assigned reports retrieved", reports)
}
// @Summary Finish Report by Worker
// @Description Worker uploads after image and marks report as finished
// @Tags Worker
// @Accept multipart/form-data
// @Produce json
// @Param files formData file true "After image file"
// @Param json formData string true "JSON data" default({"report_id": "uuid-here"})
// @Security BearerAuth
// @Success 200 {object} map[string]string
// @Failure 400 {object} map[string]string
// @Router /api/worker/report [patch]
func (c *reportController) FinishReport(ctx *gin.Context) {
workerIDVal, exists := ctx.Get("user_id")
if !exists {
utils.SendErrorResponse(ctx, http.StatusUnauthorized, "Unauthorized")
return
}
workerID := workerIDVal.(uuid.UUID)
file, header, err := ctx.Request.FormFile("files")
if err != nil {
utils.SendErrorResponse(ctx, http.StatusBadRequest, "Image file is required")
return
}
defer file.Close()
jsonData := ctx.PostForm("json")
if jsonData == "" {
utils.SendErrorResponse(ctx, http.StatusBadRequest, "JSON data is required")
return
}
var req dto.WorkerReportRequest
if err := json.Unmarshal([]byte(jsonData), &req); err != nil {
utils.SendErrorResponse(ctx, http.StatusBadRequest, "Invalid JSON format")
return
}
if err := c.reportService.FinishReport(workerID, file, header, req.ReportID); err != nil {
utils.SendErrorResponse(ctx, http.StatusBadRequest, err.Error())
return
}
utils.SendSuccessResponse(ctx, "Report finished successfully", nil)
}
// @Summary Get User's Reports
// @Description Get all reports created by the logged-in user with pagination
// @Tags User
// @Produce json
// @Param page query int false "Page number" default(1)
// @Param limit query int false "Items per page" default(10)
// @Security BearerAuth
// @Success 200 {object} dto.PaginatedReportsResponse
// @Failure 401 {object} map[string]string
// @Router /api/user/report/me [get]
func (c *reportController) GetUserReports(ctx *gin.Context) {
userIDVal, exists := ctx.Get("user_id")
if !exists {
utils.SendErrorResponse(ctx, http.StatusUnauthorized, "Unauthorized")
return
}
userID := userIDVal.(uuid.UUID)
page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1"))
limit, _ := strconv.Atoi(ctx.DefaultQuery("limit", "10"))
if page < 1 {
page = 1
}
if limit < 1 || limit > 100 {
limit = 10
}
response, err := c.reportService.GetUserReports(userID, page, limit)
if err != nil {
utils.SendErrorResponse(ctx, http.StatusInternalServerError, err.Error())
return
}
utils.SendSuccessResponse(ctx, "User reports retrieved", response)
}
// @Summary Get Worker's Assigned Reports
// @Description Get all reports assigned to the logged-in worker with pagination
// @Tags Worker
// @Produce json
// @Param page query int false "Page number" default(1)
// @Param limit query int false "Items per page" default(10)
// @Security BearerAuth
// @Success 200 {object} dto.PaginatedReportsResponse
// @Failure 401 {object} map[string]string
// @Router /api/worker/report/assign/me [get]
func (c *reportController) GetWorkerAssignedReports(ctx *gin.Context) {
workerIDVal, exists := ctx.Get("user_id")
if !exists {
utils.SendErrorResponse(ctx, http.StatusUnauthorized, "Unauthorized")
return
}
workerID := workerIDVal.(uuid.UUID)
page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1"))
limit, _ := strconv.Atoi(ctx.DefaultQuery("limit", "10"))
if page < 1 {
page = 1
}
if limit < 1 || limit > 100 {
limit = 10
}
response, err := c.reportService.GetWorkerAssignedReports(workerID, page, limit)
if err != nil {
utils.SendErrorResponse(ctx, http.StatusInternalServerError, err.Error())
return
}
utils.SendSuccessResponse(ctx, "Worker assigned reports retrieved", response)
}
// @Summary Get Worker's History
// @Description Get worker's completed reports with pagination and status filter
// @Tags Worker
// @Produce json
// @Param page query int false "Page number" default(1)
// @Param limit query int false "Items per page" default(10)
// @Param verify_admin query bool false "True: finished, False: Finish by Worker" default(false)
// @Security BearerAuth
// @Success 200 {object} dto.PaginatedReportsResponse
// @Failure 401 {object} map[string]string
// @Router /api/worker/report/history/me [get]
func (c *reportController) GetWorkerHistory(ctx *gin.Context) {
workerIDVal, exists := ctx.Get("user_id")
if !exists {
utils.SendErrorResponse(ctx, http.StatusUnauthorized, "Unauthorized")
return
}
workerID := workerIDVal.(uuid.UUID)
page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1"))
limit, _ := strconv.Atoi(ctx.DefaultQuery("limit", "10"))
verifyAdmin := ctx.DefaultQuery("verify_admin", "false") == "true"
if page < 1 {
page = 1
}
if limit < 1 || limit > 100 {
limit = 10
}
response, err := c.reportService.GetWorkerHistory(workerID, verifyAdmin, page, limit)
if err != nil {
utils.SendErrorResponse(ctx, http.StatusInternalServerError, err.Error())
return
}
utils.SendSuccessResponse(ctx, "Worker history retrieved", response)
}
// @Summary Verify Report by Admin
// @Description Admin verifies a report with status 'Finish by Worker' to 'finished'
// @Tags Admin
// @Accept json
// @Produce json
// @Param request body dto.VerifyReportRequest true "Verify Report Request"
// @Security BearerAuth
// @Success 200 {object} map[string]string
// @Failure 400 {object} map[string]string
// @Router /api/admin/report/verify [patch]
func (c *reportController) VerifyReport(ctx *gin.Context) {
var req dto.VerifyReportRequest
if err := ctx.ShouldBindJSON(&req); err != nil {
utils.SendErrorResponse(ctx, http.StatusBadRequest, err.Error())
return
}
if err := c.reportService.VerifyReport(req.ReportID); err != nil {
utils.SendErrorResponse(ctx, http.StatusBadRequest, err.Error())
return
}
utils.SendSuccessResponse(ctx, "Report verified successfully", nil)
}