add api bulk update status daily checklist; change hpp real to estimate

This commit is contained in:
giovanni
2026-04-20 16:08:43 +07:00
parent 5355fe0729
commit 916f1980e9
6 changed files with 200 additions and 3 deletions
@@ -29,6 +29,7 @@ type DailyChecklistService interface {
GetOne(ctx *fiber.Ctx, id uint) (*entity.DailyChecklist, error)
CreateOne(ctx *fiber.Ctx, req *validation.Create) (*entity.DailyChecklist, error)
UpdateOne(ctx *fiber.Ctx, req *validation.Update, id uint) (*entity.DailyChecklist, error)
BulkUpdate(ctx *fiber.Ctx, req *validation.BulkStatusUpdate) ([]entity.DailyChecklist, error)
DeleteOne(ctx *fiber.Ctx, id uint) error
AssignPhases(ctx *fiber.Ctx, id uint, req *validation.AssignPhases) error
AssignTasks(ctx *fiber.Ctx, id uint, req *validation.AssignTask) error
@@ -646,6 +647,67 @@ func (s dailyChecklistService) UpdateOne(c *fiber.Ctx, req *validation.Update, i
return s.GetOne(c, id)
}
func (s dailyChecklistService) BulkUpdate(c *fiber.Ctx, req *validation.BulkStatusUpdate) ([]entity.DailyChecklist, error) {
if err := s.Validate.Struct(req); err != nil {
return nil, err
}
status := strings.ToUpper(strings.TrimSpace(req.Status))
if status != "APPROVED" && status != "REJECTED" {
return nil, fiber.NewError(fiber.StatusBadRequest, "status must be APPROVED or REJECTED")
}
ids, err := parseChecklistIDs(req.IDs)
if err != nil {
return nil, fiber.NewError(fiber.StatusBadRequest, err.Error())
}
if len(ids) == 0 {
return nil, fiber.NewError(fiber.StatusBadRequest, "ids cannot be empty")
}
scopedIDs, err := s.Repository.ListScopedChecklistIDs(c, ids)
if err != nil {
s.Log.Errorf("Failed to validate daily checklist scope for bulk update: %+v", err)
return nil, err
}
if len(scopedIDs) != len(ids) {
return nil, fiber.NewError(fiber.StatusNotFound, "DailyChecklist not found")
}
var rejectReason *string
if status == "REJECTED" {
rejectReason = req.RejectReason
}
if err := s.Repository.BulkUpdateStatus(c.Context(), ids, status, rejectReason); err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fiber.NewError(fiber.StatusNotFound, "DailyChecklist not found")
}
s.Log.Errorf("Failed to bulk update daily checklist status: %+v", err)
return nil, err
}
updated, err := s.Repository.ListByIDsWithKandang(c.Context(), ids)
if err != nil {
s.Log.Errorf("Failed to fetch updated daily checklists: %+v", err)
return nil, err
}
if len(updated) != len(ids) {
return nil, fiber.NewError(fiber.StatusNotFound, "DailyChecklist not found")
}
orderByID := make(map[uint]int, len(ids))
for idx, id := range ids {
orderByID[id] = idx
}
sort.Slice(updated, func(i, j int) bool {
return orderByID[updated[i].Id] < orderByID[updated[j].Id]
})
return updated, nil
}
func (s dailyChecklistService) DeleteOne(c *fiber.Ctx, id uint) error {
if err := s.ensureChecklistAccess(c, id); err != nil {
return err
@@ -908,6 +970,33 @@ func parsePhaseIDs(raw string) ([]uint, error) {
return result, nil
}
func parseChecklistIDs(raw string) ([]uint, error) {
parts := strings.Split(raw, ",")
result := make([]uint, 0, len(parts))
seen := make(map[uint]struct{})
for _, part := range parts {
value := strings.TrimSpace(part)
if value == "" {
continue
}
num, err := strconv.ParseUint(value, 10, 64)
if err != nil || num == 0 {
return nil, errors.New("invalid daily checklist id: " + value)
}
u := uint(num)
if _, ok := seen[u]; ok {
continue
}
seen[u] = struct{}{}
result = append(result, u)
}
return result, nil
}
func parseIDs(raw string) ([]uint, error) {
parts := strings.Split(raw, ",")
result := make([]uint, 0, len(parts))