package controllers import ( "strconv" "abdanhafidz.com/go-boilerplate/models/dto" entity "abdanhafidz.com/go-boilerplate/models/entity" http_error "abdanhafidz.com/go-boilerplate/models/error" "abdanhafidz.com/go-boilerplate/services" "github.com/gin-gonic/gin" "github.com/google/uuid" ) type AdminAccountController interface { ListAccounts(ctx *gin.Context) CreateAccount(ctx *gin.Context) UpdateAccount(ctx *gin.Context) DeleteAccount(ctx *gin.Context) SetAccountOrganization(ctx *gin.Context) } type adminAccountController struct { accountService services.AccountService } func NewAdminAccountController(accountService services.AccountService) AdminAccountController { return &adminAccountController{accountService: accountService} } func (c *adminAccountController) ListAccounts(ctx *gin.Context) { limit, _ := strconv.Atoi(ctx.DefaultQuery("limit", "10")) page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1")) role := ctx.DefaultQuery("role", "") search := ctx.DefaultQuery("search", "") sortBy := ctx.DefaultQuery("sortBy", "") order := ctx.DefaultQuery("order", "") if limit < 1 { limit = 10 } else if limit > 50 { limit = 50 } if page < 1 { page = 1 } validRoles := map[string]bool{ "user": true, "admin": true, "super_admin": true, "teacher": true, "organizer": true, } if role != "" && !validRoles[role] { ResponseJSON(ctx, gin.H{}, []dto.AdminAccountResponse{}, http_error.BAD_REQUEST_ERROR) return } offset := (page - 1) * limit p := entity.Pagination{ Limit: limit, Offset: offset, Role: role, Search: search, SortBy: sortBy, Order: order, } callerID := ParseAccountId(ctx) accounts, total, err := c.accountService.AdminListAccounts(ctx.Request.Context(), callerID, p) if err != nil { ResponseJSON(ctx, gin.H{}, []dto.AdminAccountResponse{}, err) return } var users []dto.AdminAccountResponse for _, acc := range accounts { fullName := "" if acc.AccountDetail != nil && acc.AccountDetail.FullName != nil { fullName = *acc.AccountDetail.FullName } var orgName *string if acc.Organization != nil { orgName = &acc.Organization.Name } users = append(users, dto.AdminAccountResponse{ Id: acc.Id, Username: acc.Username, Email: acc.Email, FullName: fullName, Role: acc.Role, Privileges: dto.Privileges{ EventManagement: acc.EventManagement, ExamManagement: acc.ExamManagement, AcademyManagement: acc.AcademyManagement, ContentManagement: acc.ContentManagement, }, IsEmailVerified: acc.IsEmailVerified, IsDetailCompleted: acc.IsDetailCompleted, OrganizationId: acc.OrganizationId, OrganizationName: orgName, CreatedAt: acc.CreatedAt.Format("2006-01-02T15:04:05Z07:00"), }) } var totalPages int if total == 0 { totalPages = 1 } else { totalPages = int((total + int64(limit) - 1) / int64(limit)) } if page > totalPages { page = totalPages } meta := gin.H{ "totalItems": total, "totalPages": totalPages, "currentPage": page, "limit": limit, } ResponseJSON(ctx, meta, users, nil) } func (c *adminAccountController) CreateAccount(ctx *gin.Context) { req := RequestJSON[dto.AdminCreateAccountRequest](ctx) callerID := ParseAccountId(ctx) account, err := c.accountService.AdminCreateAccount(ctx.Request.Context(), callerID, req) if err != nil { ResponseJSON(ctx, req, dto.AdminAccountResponse{}, err) return } fullName := "" if account.AccountDetail != nil && account.AccountDetail.FullName != nil { fullName = *account.AccountDetail.FullName } var orgName *string if account.Organization != nil { orgName = &account.Organization.Name } res := dto.AdminAccountResponse{ Id: account.Id, Username: account.Username, Email: account.Email, FullName: fullName, Role: account.Role, Privileges: dto.Privileges{ EventManagement: account.EventManagement, ExamManagement: account.ExamManagement, AcademyManagement: account.AcademyManagement, ContentManagement: account.ContentManagement, }, IsEmailVerified: account.IsEmailVerified, IsDetailCompleted: account.IsDetailCompleted, OrganizationId: account.OrganizationId, OrganizationName: orgName, CreatedAt: account.CreatedAt.Format("2006-01-02T15:04:05Z07:00"), } ResponseJSON(ctx, req, res, nil) } func (c *adminAccountController) UpdateAccount(ctx *gin.Context) { idParam := ctx.Param("account_id") accountID, err := uuid.Parse(idParam) if err != nil { ResponseJSON(ctx, gin.H{"id": idParam}, dto.AdminAccountResponse{}, http_error.INVALID_TOKEN) return } req := RequestJSON[dto.AdminUpdateAccountRequest](ctx) callerID := ParseAccountId(ctx) account, err := c.accountService.AdminUpdateAccount(ctx.Request.Context(), callerID, accountID, req) if err != nil { ResponseJSON(ctx, req, dto.AdminAccountResponse{}, err) return } fullName := "" if account.AccountDetail != nil && account.AccountDetail.FullName != nil { fullName = *account.AccountDetail.FullName } var orgName *string if account.Organization != nil { orgName = &account.Organization.Name } res := dto.AdminAccountResponse{ Id: account.Id, Username: account.Username, Email: account.Email, FullName: fullName, Role: account.Role, Privileges: dto.Privileges{ EventManagement: account.EventManagement, ExamManagement: account.ExamManagement, AcademyManagement: account.AcademyManagement, ContentManagement: account.ContentManagement, }, IsEmailVerified: account.IsEmailVerified, IsDetailCompleted: account.IsDetailCompleted, OrganizationId: account.OrganizationId, OrganizationName: orgName, CreatedAt: account.CreatedAt.Format("2006-01-02T15:04:05Z07:00"), } ResponseJSON(ctx, req, res, nil) } func (c *adminAccountController) DeleteAccount(ctx *gin.Context) { idParam := ctx.Param("account_id") accountID, err := uuid.Parse(idParam) if err != nil { ResponseJSON[any](ctx, gin.H{"id": idParam}, nil, http_error.INVALID_TOKEN) return } callerID := ParseAccountId(ctx) err = c.accountService.AdminDeleteAccount(ctx.Request.Context(), callerID, accountID) if err != nil { ResponseJSON[any](ctx, gin.H{"id": accountID}, nil, err) return } ResponseJSON(ctx, gin.H{"id": accountID}, gin.H{"message": "Account deleted successfully"}, nil) } func (c *adminAccountController) SetAccountOrganization(ctx *gin.Context) { idParam := ctx.Param("account_id") accountID, err := uuid.Parse(idParam) if err != nil { ResponseJSON(ctx, gin.H{"id": idParam}, dto.SetAccountOrganizationResponse{}, err) return } req := RequestJSON[dto.SetAccountOrganizationRequest](ctx) callerID := ParseAccountId(ctx) result, err := c.accountService.SetAccountOrganization(ctx.Request.Context(), callerID, accountID, req.OrganizationID) if err != nil { ResponseJSON(ctx, req, dto.SetAccountOrganizationResponse{}, err) return } ResponseJSON(ctx, req, result, nil) }