mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-24 15:25:43 +00:00
fix(BE): req body approval and fix projectflock.dto
This commit is contained in:
@@ -191,29 +191,33 @@ func (u *ProjectflockController) DeleteOne(c *fiber.Ctx) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *ProjectflockController) Approval(c *fiber.Ctx) error {
|
func (u *ProjectflockController) Approval(c *fiber.Ctx) error {
|
||||||
param := c.Params("id")
|
|
||||||
|
|
||||||
id, err := strconv.Atoi(param)
|
|
||||||
if err != nil {
|
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid Id")
|
|
||||||
}
|
|
||||||
|
|
||||||
req := new(validation.Approve)
|
req := new(validation.Approve)
|
||||||
if err := c.BodyParser(req); err != nil {
|
if err := c.BodyParser(req); err != nil {
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := u.ProjectflockService.Approval(c, uint(id), req)
|
results, err := u.ProjectflockService.Approval(c, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
data interface{}
|
||||||
|
message = "Submit projectflock approval successfully"
|
||||||
|
)
|
||||||
|
if len(results) == 1 {
|
||||||
|
data = dto.ToProjectFlockListDTO(results[0])
|
||||||
|
} else {
|
||||||
|
message = "Submit projectflock approvals successfully"
|
||||||
|
data = dto.ToProjectFlockListDTOs(results)
|
||||||
|
}
|
||||||
|
|
||||||
return c.Status(fiber.StatusOK).
|
return c.Status(fiber.StatusOK).
|
||||||
JSON(response.Success{
|
JSON(response.Success{
|
||||||
Code: fiber.StatusOK,
|
Code: fiber.StatusOK,
|
||||||
Status: "success",
|
Status: "success",
|
||||||
Message: "Submit projectflock approval successfully",
|
Message: message,
|
||||||
Data: dto.ToProjectFlockListDTO(*result),
|
Data: data,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,30 @@ func ToProjectFlockListDTO(e entity.ProjectFlock) ProjectFlockListDTO {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var flockSummary *flockDTO.FlockBaseDTO
|
||||||
|
if e.Flock.Id != 0 {
|
||||||
|
mapped := flockDTO.ToFlockBaseDTO(e.Flock)
|
||||||
|
flockSummary = &mapped
|
||||||
|
}
|
||||||
|
|
||||||
|
var areaSummary *areaDTO.AreaBaseDTO
|
||||||
|
if e.Area.Id != 0 {
|
||||||
|
mapped := areaDTO.ToAreaBaseDTO(e.Area)
|
||||||
|
areaSummary = &mapped
|
||||||
|
}
|
||||||
|
|
||||||
|
var fcrSummary *fcrDTO.FcrBaseDTO
|
||||||
|
if e.Fcr.Id != 0 {
|
||||||
|
mapped := fcrDTO.ToFcrBaseDTO(e.Fcr)
|
||||||
|
fcrSummary = &mapped
|
||||||
|
}
|
||||||
|
|
||||||
|
var locationSummary *locationDTO.LocationBaseDTO
|
||||||
|
if e.Location.Id != 0 {
|
||||||
|
mapped := locationDTO.ToLocationBaseDTO(e.Location)
|
||||||
|
locationSummary = &mapped
|
||||||
|
}
|
||||||
|
|
||||||
latestApproval := defaultProjectFlockLatestApproval(e)
|
latestApproval := defaultProjectFlockLatestApproval(e)
|
||||||
if e.LatestApproval != nil {
|
if e.LatestApproval != nil {
|
||||||
snapshot := approvalDTO.ToApprovalDTO(*e.LatestApproval)
|
snapshot := approvalDTO.ToApprovalDTO(*e.LatestApproval)
|
||||||
@@ -66,8 +90,12 @@ func ToProjectFlockListDTO(e entity.ProjectFlock) ProjectFlockListDTO {
|
|||||||
|
|
||||||
return ProjectFlockListDTO{
|
return ProjectFlockListDTO{
|
||||||
ProjectFlockBaseDTO: createProjectFlockBaseDTO(e),
|
ProjectFlockBaseDTO: createProjectFlockBaseDTO(e),
|
||||||
|
Flock: flockSummary,
|
||||||
|
Area: areaSummary,
|
||||||
Kandangs: kandangSummaries,
|
Kandangs: kandangSummaries,
|
||||||
Category: e.Category,
|
Category: e.Category,
|
||||||
|
Fcr: fcrSummary,
|
||||||
|
Location: locationSummary,
|
||||||
CreatedAt: e.CreatedAt,
|
CreatedAt: e.CreatedAt,
|
||||||
UpdatedAt: e.UpdatedAt,
|
UpdatedAt: e.UpdatedAt,
|
||||||
CreatedUser: createdUser,
|
CreatedUser: createdUser,
|
||||||
@@ -101,13 +129,6 @@ func defaultProjectFlockLatestApproval(e entity.ProjectFlock) approvalDTO.Approv
|
|||||||
result.StepName = label
|
result.StepName = label
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if result.StepName == "" {
|
|
||||||
result.StepName = "Pengajuan"
|
|
||||||
}
|
|
||||||
|
|
||||||
if !e.CreatedAt.IsZero() {
|
|
||||||
result.ActionAt = e.CreatedAt
|
|
||||||
}
|
|
||||||
|
|
||||||
if e.CreatedUser.Id != 0 {
|
if e.CreatedUser.Id != 0 {
|
||||||
result.ActionBy = userDTO.ToUserBaseDTO(e.CreatedUser)
|
result.ActionBy = userDTO.ToUserBaseDTO(e.CreatedUser)
|
||||||
|
|||||||
@@ -25,6 +25,6 @@ func ProjectflockRoutes(v1 fiber.Router, u user.UserService, s projectflock.Proj
|
|||||||
route.Get("/:id", ctrl.GetOne)
|
route.Get("/:id", ctrl.GetOne)
|
||||||
route.Patch("/:id", ctrl.UpdateOne)
|
route.Patch("/:id", ctrl.UpdateOne)
|
||||||
route.Delete("/:id", ctrl.DeleteOne)
|
route.Delete("/:id", ctrl.DeleteOne)
|
||||||
route.Post("/:id/approvals", ctrl.Approval)
|
route.Post("/approvals", ctrl.Approval)
|
||||||
route.Get("/flocks/:flock_id/periods", ctrl.GetFlockPeriodSummary)
|
route.Get("/flocks/:flock_id/periods", ctrl.GetFlockPeriodSummary)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ type ProjectflockService interface {
|
|||||||
UpdateOne(ctx *fiber.Ctx, req *validation.Update, id uint) (*entity.ProjectFlock, error)
|
UpdateOne(ctx *fiber.Ctx, req *validation.Update, id uint) (*entity.ProjectFlock, error)
|
||||||
DeleteOne(ctx *fiber.Ctx, id uint) error
|
DeleteOne(ctx *fiber.Ctx, id uint) error
|
||||||
GetFlockPeriodSummary(ctx *fiber.Ctx, flockID uint) (*FlockPeriodSummary, error)
|
GetFlockPeriodSummary(ctx *fiber.Ctx, flockID uint) (*FlockPeriodSummary, error)
|
||||||
Approval(ctx *fiber.Ctx, id uint, req *validation.Approve) (*entity.ProjectFlock, error)
|
Approval(ctx *fiber.Ctx, req *validation.Approve) ([]entity.ProjectFlock, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type projectflockService struct {
|
type projectflockService struct {
|
||||||
@@ -501,17 +501,11 @@ func (s projectflockService) UpdateOne(c *fiber.Ctx, req *validation.Update, id
|
|||||||
return s.GetOne(c, id)
|
return s.GetOne(c, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s projectflockService) Approval(c *fiber.Ctx, id uint, req *validation.Approve) (*entity.ProjectFlock, error) {
|
func (s projectflockService) Approval(c *fiber.Ctx, req *validation.Approve) ([]entity.ProjectFlock, error) {
|
||||||
if err := s.Validate.Struct(req); err != nil {
|
if err := s.Validate.Struct(req); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
project, err := s.GetOne(c, id)
|
|
||||||
if err != nil {
|
|
||||||
s.Log.Errorf("Failed to fetch projectflock %d before approval: %+v", id, err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
actorID := uint(1) // TODO: change from auth context
|
actorID := uint(1) // TODO: change from auth context
|
||||||
var action entity.ApprovalAction
|
var action entity.ApprovalAction
|
||||||
switch strings.ToUpper(strings.TrimSpace(req.Action)) {
|
switch strings.ToUpper(strings.TrimSpace(req.Action)) {
|
||||||
@@ -523,42 +517,58 @@ func (s projectflockService) Approval(c *fiber.Ctx, id uint, req *validation.App
|
|||||||
return nil, fiber.NewError(fiber.StatusBadRequest, "action must be APPROVED or REJECTED")
|
return nil, fiber.NewError(fiber.StatusBadRequest, "action must be APPROVED or REJECTED")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
approvableIDs := uniqueUintSlice(req.ApprovableIds)
|
||||||
|
if len(approvableIDs) == 0 {
|
||||||
|
return nil, fiber.NewError(fiber.StatusBadRequest, "approvable_ids must contain at least one id")
|
||||||
|
}
|
||||||
|
|
||||||
step := utils.ProjectFlockStepPengajuan
|
step := utils.ProjectFlockStepPengajuan
|
||||||
if action == entity.ApprovalActionApproved {
|
if action == entity.ApprovalActionApproved {
|
||||||
step = utils.ProjectFlockStepAktif
|
step = utils.ProjectFlockStepAktif
|
||||||
}
|
}
|
||||||
|
|
||||||
err = s.Repository.DB().WithContext(c.Context()).Transaction(func(dbTransaction *gorm.DB) error {
|
err := s.Repository.DB().WithContext(c.Context()).Transaction(func(dbTransaction *gorm.DB) error {
|
||||||
approvalSvc := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(dbTransaction))
|
approvalSvc := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(dbTransaction))
|
||||||
if _, err := approvalSvc.CreateApproval(
|
|
||||||
c.Context(),
|
|
||||||
utils.ApprovalWorkflowProjectFlock,
|
|
||||||
project.Id,
|
|
||||||
step,
|
|
||||||
&action,
|
|
||||||
actorID,
|
|
||||||
req.Notes,
|
|
||||||
); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
kandangRepoTx := kandangRepository.NewKandangRepository(dbTransaction)
|
kandangRepoTx := kandangRepository.NewKandangRepository(dbTransaction)
|
||||||
switch action {
|
projectRepoTx := repository.NewProjectflockRepository(dbTransaction)
|
||||||
case entity.ApprovalActionApproved:
|
|
||||||
if err := kandangRepoTx.UpdateStatusByProjectFlockID(
|
for _, approvableID := range approvableIDs {
|
||||||
|
if _, err := projectRepoTx.GetByID(c.Context(), approvableID, nil); err != nil {
|
||||||
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
|
return fiber.NewError(fiber.StatusNotFound, fmt.Sprintf("Projectflock %d not found", approvableID))
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := approvalSvc.CreateApproval(
|
||||||
c.Context(),
|
c.Context(),
|
||||||
project.Id,
|
utils.ApprovalWorkflowProjectFlock,
|
||||||
utils.KandangStatusActive,
|
approvableID,
|
||||||
|
step,
|
||||||
|
&action,
|
||||||
|
actorID,
|
||||||
|
req.Notes,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case entity.ApprovalActionRejected:
|
|
||||||
if err := kandangRepoTx.UpdateStatusByProjectFlockID(
|
switch action {
|
||||||
c.Context(),
|
case entity.ApprovalActionApproved:
|
||||||
project.Id,
|
if err := kandangRepoTx.UpdateStatusByProjectFlockID(
|
||||||
utils.KandangStatusNonActive,
|
c.Context(),
|
||||||
); err != nil {
|
approvableID,
|
||||||
return err
|
utils.KandangStatusActive,
|
||||||
|
); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case entity.ApprovalActionRejected:
|
||||||
|
if err := kandangRepoTx.UpdateStatusByProjectFlockID(
|
||||||
|
c.Context(),
|
||||||
|
approvableID,
|
||||||
|
utils.KandangStatusNonActive,
|
||||||
|
); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -566,14 +576,26 @@ func (s projectflockService) Approval(c *fiber.Ctx, id uint, req *validation.App
|
|||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if fiberErr, ok := err.(*fiber.Error); ok {
|
||||||
|
return nil, fiberErr
|
||||||
|
}
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return nil, fiber.NewError(fiber.StatusNotFound, "Projectflock not found")
|
return nil, fiber.NewError(fiber.StatusNotFound, "Projectflock not found")
|
||||||
}
|
}
|
||||||
s.Log.Errorf("Failed to record approval for projectflock %d: %+v", id, err)
|
s.Log.Errorf("Failed to record approval for projectflocks %+v: %+v", approvableIDs, err)
|
||||||
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to record approval")
|
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to record approval")
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.GetOne(c, id)
|
updated := make([]entity.ProjectFlock, 0, len(approvableIDs))
|
||||||
|
for _, approvableID := range approvableIDs {
|
||||||
|
project, err := s.GetOne(c, approvableID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
updated = append(updated, *project)
|
||||||
|
}
|
||||||
|
|
||||||
|
return updated, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s projectflockService) DeleteOne(c *fiber.Ctx, id uint) error {
|
func (s projectflockService) DeleteOne(c *fiber.Ctx, id uint) error {
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ type Query struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Approve struct {
|
type Approve struct {
|
||||||
Action string `json:"action" validate:"required_strict"`
|
Action string `json:"action" validate:"required_strict"`
|
||||||
Notes *string `json:"notes,omitempty" validate:"omitempty,max=500"`
|
ApprovableIds []uint `json:"approvable_ids" validate:"required_strict,min=1,dive,gt=0"`
|
||||||
|
Notes *string `json:"notes,omitempty" validate:"omitempty,max=500"`
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user