From 9726303eeba010175eb24c533c8bc40636fa3a12 Mon Sep 17 00:00:00 2001 From: giovanni Date: Mon, 27 Apr 2026 10:54:02 +0700 Subject: [PATCH] add feature edit periode project flock --- .../services/projectflock.service.go | 58 ++++++++++++++++++- .../validations/projectflock.validation.go | 1 + 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/internal/modules/production/project_flocks/services/projectflock.service.go b/internal/modules/production/project_flocks/services/projectflock.service.go index beaa0899..a99228e4 100644 --- a/internal/modules/production/project_flocks/services/projectflock.service.go +++ b/internal/modules/production/project_flocks/services/projectflock.service.go @@ -1225,12 +1225,34 @@ func (s projectflockService) Resubmit(c *fiber.Ctx, req *validation.Resubmit, id } } + // Hitung newFlockName sebelum membuka transaksi (fast-path conflict check) + var newFlockName string + if req.Periode != nil { + lastSpace := strings.LastIndex(existing.FlockName, " ") + if lastSpace < 0 { + return nil, fiber.NewError(fiber.StatusInternalServerError, "Format flock name tidak valid") + } + baseName := strings.TrimSpace(existing.FlockName[:lastSpace]) + newFlockName = fmt.Sprintf("%s %03d", baseName, *req.Periode) + + taken, err := s.Repository.ExistsByFlockName(c.Context(), newFlockName, &id) + if err != nil { + return nil, fiber.NewError(fiber.StatusInternalServerError, "Gagal memeriksa nama flock") + } + if taken { + return nil, fiber.NewError(fiber.StatusConflict, + fmt.Sprintf("Nama flock '%s' sudah digunakan oleh project flock lain", newFlockName)) + } + } + err = s.Repository.DB().WithContext(c.Context()).Transaction(func(dbTransaction *gorm.DB) error { approvalSvc := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(dbTransaction)) var period int = 1 - if len(existing.KandangHistory) > 0 { + if req.Periode != nil { + period = *req.Periode + } else if len(existing.KandangHistory) > 0 { period = existing.KandangHistory[0].Period } @@ -1242,6 +1264,40 @@ func (s projectflockService) Resubmit(c *fiber.Ctx, req *validation.Resubmit, id if err := s.attachKandangs(c.Context(), dbTransaction, existing.Id, kandangIDs, periods); err != nil { return err } + + // Update period pada SEMUA row project_flock_kandangs milik flock ini. + // attachKandangs hanya INSERT baris baru dan melewati yang sudah ada, + // sehingga period pada baris lama tidak terupdate tanpa langkah ini. + if req.Periode != nil { + if err := dbTransaction.WithContext(c.Context()). + Model(&entity.ProjectFlockKandang{}). + Where("project_flock_id = ?", existing.Id). + Update("period", *req.Periode).Error; err != nil { + return fiber.NewError(fiber.StatusInternalServerError, "Gagal memperbarui periode kandang") + } + } + + // Update flock_name sesuai periode baru. + if req.Periode != nil { + projectRepoTx := repository.NewProjectflockRepository(dbTransaction) + + // Re-check di dalam transaksi untuk cegah race condition. + taken, err := projectRepoTx.ExistsByFlockName(c.Context(), newFlockName, &existing.Id) + if err != nil { + return fiber.NewError(fiber.StatusInternalServerError, "Gagal memeriksa nama flock") + } + if taken { + return fiber.NewError(fiber.StatusConflict, + fmt.Sprintf("Nama flock '%s' sudah digunakan oleh project flock lain", newFlockName)) + } + + if err := projectRepoTx.PatchOne(c.Context(), existing.Id, map[string]any{ + "flock_name": newFlockName, + }, nil); err != nil { + return fiber.NewError(fiber.StatusInternalServerError, "Gagal memperbarui nama flock") + } + } + if err := s.UpsertProjectBudget(c.Context(), dbTransaction, existing.Id, req.ProjectBudgets); err != nil { return err } diff --git a/internal/modules/production/project_flocks/validations/projectflock.validation.go b/internal/modules/production/project_flocks/validations/projectflock.validation.go index c6370133..d74e3637 100644 --- a/internal/modules/production/project_flocks/validations/projectflock.validation.go +++ b/internal/modules/production/project_flocks/validations/projectflock.validation.go @@ -40,4 +40,5 @@ type ProjectBudget struct { type Resubmit struct { KandangIds []uint `json:"kandang_ids" validate:"required_strict,min=1,dive,gt=0"` ProjectBudgets []ProjectBudget `json:"project_budgets" validate:"required_strict,min=1,dive"` + Periode *int `json:"periode" validate:"omitempty,gt=0"` }