add api update periode flock/project flock kandang

This commit is contained in:
giovanni
2026-04-23 21:56:17 +07:00
parent e6010fe47e
commit be440af1c2
5 changed files with 108 additions and 8 deletions
@@ -359,6 +359,40 @@ func applyCutOverLayingLookupOverride(result *dto.ProjectFlockKandangDTO) {
result.IsLaying = true
}
func (u *ProjectflockController) UpdateOne(c *fiber.Ctx) error {
param := c.Params("id")
req := new(validation.Update)
id, err := strconv.Atoi(param)
if err != nil || id <= 0 {
return fiber.NewError(fiber.StatusBadRequest, "Invalid Id")
}
if err := c.BodyParser(req); err != nil {
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
}
result, err := u.ProjectflockService.UpdateOne(c, req, uint(id))
if err != nil {
return err
}
var period int
if periods, err := u.ProjectflockService.GetProjectPeriods(c, []uint{uint(id)}); err == nil {
if p, ok := periods[uint(id)]; ok {
period = p
}
}
return c.Status(fiber.StatusOK).
JSON(response.Success{
Code: fiber.StatusOK,
Status: "success",
Message: "Update projectflock successfully",
Data: dto.ToProjectFlockListDTOWithPeriod(*result, period),
})
}
func (u *ProjectflockController) Resubmit(c *fiber.Ctx) error {
param := c.Params("id")
req := new(validation.Resubmit)
@@ -17,6 +17,7 @@ type ProjectFlockKandangRepository interface {
GetByProjectFlockAndKandang(ctx context.Context, projectFlockID uint, kandangID uint) (*entity.ProjectFlockKandang, error)
GetActiveByKandangID(ctx context.Context, kandangID uint) (*entity.ProjectFlockKandang, error)
UpdateClosedAt(ctx context.Context, id uint, t *time.Time) error
UpdatePeriodByProjectFlockID(ctx context.Context, projectFlockID uint, period int) (int64, error)
CreateMany(ctx context.Context, records []*entity.ProjectFlockKandang) error
DeleteMany(ctx context.Context, projectFlockID uint, kandangIDs []uint) error
GetAll(ctx context.Context, offset int, limit int, modifier func(*gorm.DB) *gorm.DB) ([]entity.ProjectFlockKandang, int64, error)
@@ -525,6 +526,19 @@ func (r *projectFlockKandangRepositoryImpl) UpdateClosedAt(ctx context.Context,
Update("closed_at", t).Error
}
// UpdatePeriodByProjectFlockID updates the period column on every pivot row that
// belongs to the given project flock. Returns the number of rows affected.
func (r *projectFlockKandangRepositoryImpl) UpdatePeriodByProjectFlockID(ctx context.Context, projectFlockID uint, period int) (int64, error) {
result := r.db.WithContext(ctx).
Model(&entity.ProjectFlockKandang{}).
Where("project_flock_id = ?", projectFlockID).
Update("period", period)
if result.Error != nil {
return 0, result.Error
}
return result.RowsAffected, nil
}
func (r *projectFlockKandangRepositoryImpl) HasOpenNewerPeriod(ctx context.Context, kandangID uint, currentPeriod int, excludeID *uint) (bool, error) {
if kandangID == 0 {
return false, nil
@@ -15,13 +15,14 @@ func ProjectflockRoutes(v1 fiber.Router, u user.UserService, s projectflock.Proj
route := v1.Group("/project-flocks")
route.Use(m.Auth(u))
route.Get("/",m.RequirePermissions(m.P_ProjectFlockGetAll),ctrl.GetAll)
route.Post("/",m.RequirePermissions(m.P_ProjectFlockCreate), ctrl.CreateOne)
route.Get("/:id",m.RequirePermissions(m.P_ProjectFlockGetOne), ctrl.GetOne)
route.Delete("/:id",m.RequirePermissions(m.P_ProjectFlockGetAll), ctrl.DeleteOne)
route.Get("/kandangs/lookup",m.RequirePermissions(m.P_ProjectFlockLookup), ctrl.LookupProjectFlockKandang)
route.Post("/approvals",m.RequirePermissions(m.P_ProjectFlockApprove), ctrl.Approval)
route.Get("/locations/:location_id/periods",m.RequirePermissions(m.P_ProjectFlockNextPeriod), ctrl.GetPeriodSummary)
route.Put("/:id/resubmit",m.RequirePermissions(m.P_ProjectFlockResubmit), ctrl.Resubmit)
route.Get("/", m.RequirePermissions(m.P_ProjectFlockGetAll), ctrl.GetAll)
route.Post("/", m.RequirePermissions(m.P_ProjectFlockCreate), ctrl.CreateOne)
route.Get("/:id", m.RequirePermissions(m.P_ProjectFlockGetOne), ctrl.GetOne)
route.Patch("/:id", m.RequirePermissions(m.P_ProjectFlockCreate), ctrl.UpdateOne)
route.Delete("/:id", m.RequirePermissions(m.P_ProjectFlockGetAll), ctrl.DeleteOne)
route.Get("/kandangs/lookup", m.RequirePermissions(m.P_ProjectFlockLookup), ctrl.LookupProjectFlockKandang)
route.Post("/approvals", m.RequirePermissions(m.P_ProjectFlockApprove), ctrl.Approval)
route.Get("/locations/:location_id/periods", m.RequirePermissions(m.P_ProjectFlockNextPeriod), ctrl.GetPeriodSummary)
route.Put("/:id/resubmit", m.RequirePermissions(m.P_ProjectFlockResubmit), ctrl.Resubmit)
}
@@ -51,6 +51,7 @@ type ProjectflockService interface {
GetProjectPeriods(ctx *fiber.Ctx, projectIDs []uint) (map[uint]int, error)
Approval(ctx *fiber.Ctx, req *validation.Approve) ([]entity.ProjectFlock, error)
Resubmit(ctx *fiber.Ctx, req *validation.Resubmit, id uint) (*entity.ProjectFlock, error)
UpdateOne(ctx *fiber.Ctx, req *validation.Update, id uint) (*entity.ProjectFlock, error)
EnsureProjectFlockApproved(ctx context.Context, projectFlockID uint) error
}
@@ -1273,6 +1274,52 @@ func (s projectflockService) Resubmit(c *fiber.Ctx, req *validation.Resubmit, id
return s.getOneEntityOnly(c, id)
}
// UpdateOne updates mutable fields of a project flock.
// Currently only the `period` is updatable; the value is applied to every
// project_flock_kandang pivot row belonging to the project flock so it stays
// consistent with how periods are provisioned in CreateOne/Resubmit.
func (s projectflockService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uint) (*entity.ProjectFlock, error) {
if err := s.Validate.Struct(req); err != nil {
return nil, err
}
if req.Period == nil {
return nil, fiber.NewError(fiber.StatusBadRequest, "period is required")
}
existing, err := s.Repository.GetByID(c.Context(), id, nil)
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fiber.NewError(fiber.StatusNotFound, "Projectflock not found")
}
if err != nil {
s.Log.Errorf("Failed to fetch projectflock %d before update: %+v", id, err)
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch project flock")
}
err = s.Repository.DB().WithContext(c.Context()).Transaction(func(dbTransaction *gorm.DB) error {
affected, err := s.pivotRepoWithTx(dbTransaction).UpdatePeriodByProjectFlockID(c.Context(), existing.Id, *req.Period)
if err != nil {
return err
}
if affected == 0 {
return fiber.NewError(fiber.StatusBadRequest, "Project flock tidak memiliki kandang yang dapat diperbarui periodenya")
}
return nil
})
if err != nil {
if fiberErr, ok := err.(*fiber.Error); ok {
return nil, fiberErr
}
if errors.Is(err, gorm.ErrDuplicatedKey) {
return nil, fiber.NewError(fiber.StatusConflict, "Project flock period already exists")
}
s.Log.Errorf("Failed to update projectflock %d period: %+v", id, err)
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to update project flock")
}
return s.getOneEntityOnly(c, id)
}
func (s projectflockService) UpsertProjectBudget(ctx context.Context, dbTransaction *gorm.DB, projectFlockID uint, budgets []validation.ProjectBudget) error {
if len(budgets) == 0 {
@@ -41,3 +41,7 @@ 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"`
}
type Update struct {
Period *int `json:"period" validate:"required,number,gt=0"`
}