From f60564d673a2a3fa092691825ffd6d0a3c73e9a3 Mon Sep 17 00:00:00 2001 From: ragilap Date: Thu, 11 Dec 2025 11:27:50 +0700 Subject: [PATCH] fix projectflock approval with dto --- internal/middleware/auth.go | 115 +++++++++--------- .../project_flock_kandang.controller.go | 13 +- .../services/project_flock_kandang.service.go | 70 +++++++---- 3 files changed, 117 insertions(+), 81 deletions(-) diff --git a/internal/middleware/auth.go b/internal/middleware/auth.go index 85bb8146..a831c25b 100644 --- a/internal/middleware/auth.go +++ b/internal/middleware/auth.go @@ -4,7 +4,7 @@ import ( "strings" "github.com/gofiber/fiber/v2" - // "gitlab.com/mbugroup/lti-api.git/internal/config" + "gitlab.com/mbugroup/lti-api.git/internal/config" entity "gitlab.com/mbugroup/lti-api.git/internal/entities" "gitlab.com/mbugroup/lti-api.git/internal/modules/sso/session" service "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services" @@ -31,65 +31,65 @@ type AuthContext struct { // fine-grained authorization using the SSO access token scopes. func Auth(userService service.UserService, requiredScopes ...string) fiber.Handler { return func(c *fiber.Ctx) error { - // token := bearerToken(c) - // if token == "" { - // token = strings.TrimSpace(c.Cookies(config.SSOAccessCookieName)) - // } - // if token == "" { - // return fiber.NewError(fiber.StatusUnauthorized, "Please authenticate") - // } + token := bearerToken(c) + if token == "" { + token = strings.TrimSpace(c.Cookies(config.SSOAccessCookieName)) + } + if token == "" { + return fiber.NewError(fiber.StatusUnauthorized, "Please authenticate") + } - // verification, err := sso.VerifyAccessToken(token) - // if err != nil { - // utils.Log.WithError(err).Warn("auth: token verification failed") - // return fiber.NewError(fiber.StatusUnauthorized, "Please authenticate") - // } + verification, err := sso.VerifyAccessToken(token) + if err != nil { + utils.Log.WithError(err).Warn("auth: token verification failed") + return fiber.NewError(fiber.StatusUnauthorized, "Please authenticate") + } - // if verification.UserID == 0 { - // return fiber.NewError(fiber.StatusForbidden, "Service authentication is not permitted for this endpoint") - // } + if verification.UserID == 0 { + return fiber.NewError(fiber.StatusForbidden, "Service authentication is not permitted for this endpoint") + } - // if err := ensureNotRevoked(c, token, verification); err != nil { - // return err - // } + if err := ensureNotRevoked(c, token, verification); err != nil { + return err + } - // user, err := userService.GetBySSOUserID(c, verification.UserID) - // if err != nil || user == nil { - // utils.Log.WithError(err).Warn("auth: failed to resolve user from repository") - // return fiber.NewError(fiber.StatusUnauthorized, "Please authenticate") - // } + user, err := userService.GetBySSOUserID(c, verification.UserID) + if err != nil || user == nil { + utils.Log.WithError(err).Warn("auth: failed to resolve user from repository") + return fiber.NewError(fiber.StatusUnauthorized, "Please authenticate") + } - // if len(requiredScopes) > 0 { - // if verification.Claims == nil || !hasAllScopes(verification.Claims.Scopes(), requiredScopes) { - // return fiber.NewError(fiber.StatusForbidden, "Insufficient scope") - // } - // } + if len(requiredScopes) > 0 { + if verification.Claims == nil || !hasAllScopes(verification.Claims.Scopes(), requiredScopes) { + return fiber.NewError(fiber.StatusForbidden, "Insufficient scope") + } + } - // var roles []sso.Role - // permissions := make(map[string]struct{}) - // if verification.UserID != 0 { - // if profile, err := sso.FetchProfile(c.Context(), token, verification); err != nil { - // utils.Log.WithError(err).Warn("auth: failed to fetch sso profile") - // } else if profile != nil { - // roles = profile.Roles - // for _, perm := range profile.PermissionNames() { - // if perm != "" { - // permissions[perm] = struct{}{} - // } - // } - // } - // } + var roles []sso.Role + permissions := make(map[string]struct{}) + if verification.UserID != 0 { + if profile, err := sso.FetchProfile(c.Context(), token, verification); err != nil { + utils.Log.WithError(err).Warn("auth: failed to fetch sso profile") + } else if profile != nil { + roles = profile.Roles + for _, perm := range profile.PermissionNames() { + if perm != "" { + permissions[perm] = struct{}{} + } + } + } + } - // ctx := &AuthContext{ - // Token: token, - // Verification: verification, - // User: user, - // Roles: roles, - // Permissions: permissions, - // } + ctx := &AuthContext{ + Token: token, + Verification: verification, + User: user, + Roles: roles, + Permissions: permissions, + } - // c.Locals(authContextLocalsKey, ctx) - // c.Locals(authUserLocalsKey, user) + c.Locals(authContextLocalsKey, ctx) + c.Locals(authUserLocalsKey, user) return c.Next() } } @@ -104,12 +104,11 @@ func AuthenticatedUser(c *fiber.Ctx) (*entity.User, bool) { } func ActorIDFromContext(c *fiber.Ctx) (uint, error) { - // user, ok := AuthenticatedUser(c) - // if !ok || user == nil || user.Id == 0 { - // return 0, fiber.NewError(fiber.StatusUnauthorized, "Please authenticate") - // } - // return user.Id, nil - return 1, nil + user, ok := AuthenticatedUser(c) + if !ok || user == nil || user.Id == 0 { + return 0, fiber.NewError(fiber.StatusUnauthorized, "Please authenticate") + } + return user.Id, nil } // AuthDetails returns the full authentication context (token, claims, user). diff --git a/internal/modules/production/project-flock-kandangs/controllers/project_flock_kandang.controller.go b/internal/modules/production/project-flock-kandangs/controllers/project_flock_kandang.controller.go index dce7b02b..32ac0e38 100644 --- a/internal/modules/production/project-flock-kandangs/controllers/project_flock_kandang.controller.go +++ b/internal/modules/production/project-flock-kandangs/controllers/project_flock_kandang.controller.go @@ -101,13 +101,22 @@ func (u *ProjectFlockKandangController) Closing(c *fiber.Ctx) error { return err } + detail, availableQtys, productWarehouses, err := u.ProjectFlockKandangService.GetOne(c, result.Id) + if err != nil { + return err + } + + detailDTO := dto.ToProjectFlockKandangDetailDTOWithAvailableQty(*detail, availableQtys, productWarehouses) + return c.Status(fiber.StatusOK). JSON(response.Success{ Code: fiber.StatusOK, Status: "success", Message: "Status closing kandang diperbarui", - // Data: dto.ProjectFlockKandangDetailDTO(*result), - Data: result, + Data: fiber.Map{ + "detail": detailDTO, + "approval": detailDTO.Approval, + }, }) } diff --git a/internal/modules/production/project-flock-kandangs/services/project_flock_kandang.service.go b/internal/modules/production/project-flock-kandangs/services/project_flock_kandang.service.go index 87af4de1..7effdc35 100644 --- a/internal/modules/production/project-flock-kandangs/services/project_flock_kandang.service.go +++ b/internal/modules/production/project-flock-kandangs/services/project_flock_kandang.service.go @@ -432,16 +432,30 @@ func (s projectFlockKandangService) Closing(c *fiber.Ctx, id uint, req *validati } if s.ApprovalSvc != nil { closeAction := entity.ApprovalActionApproved - if _, aerr := s.ApprovalSvc.CreateApproval( - c.Context(), - utils.ApprovalWorkflowProjectFlockKandang, - id, - utils.ProjectFlockKandangStepClosed, - &closeAction, - actorID, - nil, - ); aerr != nil { - return nil, aerr + // Hindari duplikasi jika approval terakhir sudah Closed + Approved + latestPFK, lerr := s.ApprovalSvc.LatestByTarget(c.Context(), utils.ApprovalWorkflowProjectFlockKandang, id, nil) + if lerr != nil { + return nil, lerr + } + shouldCreate := true + if latestPFK != nil && + latestPFK.StepNumber == uint16(utils.ProjectFlockKandangStepClosed) && + latestPFK.Action != nil && *latestPFK.Action == closeAction { + shouldCreate = false + } + + if shouldCreate { + if _, aerr := s.ApprovalSvc.CreateApproval( + c.Context(), + utils.ApprovalWorkflowProjectFlockKandang, + id, + utils.ProjectFlockKandangStepClosed, + &closeAction, + actorID, + nil, + ); aerr != nil { + return nil, aerr + } } // Jika semua kandang dalam project sudah ditutup, set approval project flock ke SELESAI. @@ -500,17 +514,31 @@ func (s projectFlockKandangService) Closing(c *fiber.Ctx, id uint, req *validati } } if s.ApprovalSvc != nil { - reopenAction := entity.ApprovalActionApproved - if _, aerr := s.ApprovalSvc.CreateApproval( - c.Context(), - utils.ApprovalWorkflowProjectFlockKandang, - id, - utils.ProjectFlockKandangStepDisetujui, - &reopenAction, - actorID, - nil, - ); aerr != nil && !errors.Is(aerr, gorm.ErrDuplicatedKey) { - return nil, aerr + reopenAction := entity.ApprovalActionUpdated + // Hindari duplikasi jika approval terakhir sudah Disetujui + Updated + latestPFK, lerr := s.ApprovalSvc.LatestByTarget(c.Context(), utils.ApprovalWorkflowProjectFlockKandang, id, nil) + if lerr != nil { + return nil, lerr + } + shouldCreate := true + if latestPFK != nil && + latestPFK.StepNumber == uint16(utils.ProjectFlockKandangStepDisetujui) && + latestPFK.Action != nil && *latestPFK.Action == reopenAction { + shouldCreate = false + } + + if shouldCreate { + if _, aerr := s.ApprovalSvc.CreateApproval( + c.Context(), + utils.ApprovalWorkflowProjectFlockKandang, + id, + utils.ProjectFlockKandangStepDisetujui, + &reopenAction, + actorID, + nil, + ); aerr != nil && !errors.Is(aerr, gorm.ErrDuplicatedKey) { + return nil, aerr + } } } default: