diff --git a/internal/modules/daily-checklists/services/daily-checklist.service.go b/internal/modules/daily-checklists/services/daily-checklist.service.go index 6913f587..602f67a4 100644 --- a/internal/modules/daily-checklists/services/daily-checklist.service.go +++ b/internal/modules/daily-checklists/services/daily-checklist.service.go @@ -142,7 +142,7 @@ func (s dailyChecklistService) ensureChecklistAccess(c *fiber.Ctx, checklistID u db := s.Repository.DB().WithContext(c.Context()). Table("daily_checklists dc"). - Joins("JOIN kandangs k ON k.id = dc.kandang_id"). + Joins("JOIN kandang_groups k ON k.id = dc.kandang_id"). Joins("JOIN locations loc ON loc.id = k.location_id"). Joins("JOIN areas a ON a.id = loc.area_id"). Where("dc.id = ?", checklistID) @@ -168,7 +168,7 @@ func (s dailyChecklistService) ensureKandangAccess(c *fiber.Ctx, kandangID uint) } db := s.Repository.DB().WithContext(c.Context()). - Table("kandangs k"). + Table("kandang_groups k"). Joins("JOIN locations loc ON loc.id = k.location_id"). Joins("JOIN areas a ON a.id = loc.area_id"). Where("k.id = ?", kandangID) @@ -196,7 +196,7 @@ func (s dailyChecklistService) ensureTaskAccess(c *fiber.Ctx, taskID uint) error db := s.Repository.DB().WithContext(c.Context()). Table("daily_checklist_activity_tasks t"). Joins("JOIN daily_checklists dc ON dc.id = t.checklist_id"). - Joins("JOIN kandangs k ON k.id = dc.kandang_id"). + Joins("JOIN kandang_groups k ON k.id = dc.kandang_id"). Joins("JOIN locations loc ON loc.id = k.location_id"). Joins("JOIN areas a ON a.id = loc.area_id"). Where("t.id = ?", taskID) @@ -225,7 +225,7 @@ func (s dailyChecklistService) GetAll(c *fiber.Ctx, params *validation.Query) ([ db := s.Repository.DB().WithContext(c.Context()). Table("daily_checklists dc"). - Joins("JOIN kandangs k ON k.id = dc.kandang_id"). + Joins("JOIN kandang_groups k ON k.id = dc.kandang_id"). Joins("JOIN locations loc ON loc.id = k.location_id"). Joins("JOIN areas a ON a.id = loc.area_id") @@ -1019,7 +1019,7 @@ func (s dailyChecklistService) GetSummary(c *fiber.Ctx, params *validation.Summa MAX(a.updated_at) AS last_activity`). Joins("JOIN daily_checklist_activity_tasks t ON t.id = a.task_id"). Joins("JOIN daily_checklists d ON d.id = t.checklist_id"). - Joins("JOIN kandangs k ON k.id = d.kandang_id"). + Joins("JOIN kandang_groups k ON k.id = d.kandang_id"). Joins("JOIN employees e ON e.id = a.employee_id"). Joins("JOIN locations loc ON loc.id = k.location_id"). Joins("JOIN areas ar ON ar.id = loc.area_id"). @@ -1092,7 +1092,7 @@ func (s dailyChecklistService) GetReport(c *fiber.Ctx, params *validation.Report Joins("JOIN daily_checklist_activity_tasks dcat ON dcat.id = dca.task_id"). Joins("JOIN daily_checklists dc ON dc.id = dcat.checklist_id"). Joins("JOIN employees e ON e.id = dca.employee_id"). - Joins("JOIN kandangs k ON k.id = dc.kandang_id"). + Joins("JOIN kandang_groups k ON k.id = dc.kandang_id"). Joins("JOIN locations loc ON loc.id = k.location_id"). Joins("JOIN areas a ON a.id = loc.area_id"). Joins("JOIN phases p ON p.id = dcat.phase_id"). diff --git a/internal/modules/master/kandangs/repositories/kandang.repository.go b/internal/modules/master/kandangs/repositories/kandang.repository.go index 0cdbbca3..832126d9 100644 --- a/internal/modules/master/kandangs/repositories/kandang.repository.go +++ b/internal/modules/master/kandangs/repositories/kandang.repository.go @@ -4,10 +4,10 @@ import ( "context" "errors" + "github.com/gofiber/fiber/v2" "gitlab.com/mbugroup/lti-api.git/internal/common/repository" entity "gitlab.com/mbugroup/lti-api.git/internal/entities" "gitlab.com/mbugroup/lti-api.git/internal/utils" - "github.com/gofiber/fiber/v2" "gorm.io/gorm" ) @@ -15,6 +15,7 @@ type KandangRepository interface { repository.BaseRepository[entity.Kandang] LocationExists(ctx context.Context, areaId uint) (bool, error) PicExists(ctx context.Context, areaId uint) (bool, error) + KandangGroupExists(ctx context.Context, kandangGroupId uint) (bool, error) NameExists(ctx context.Context, name string, excludeID *uint) (bool, error) ProjectFlockExists(ctx context.Context, projectFlockID uint) (bool, error) GetFirstByProjectFlockID(ctx context.Context, projectFlockID uint) (*entity.Kandang, error) @@ -45,6 +46,10 @@ func (r *KandangRepositoryImpl) PicExists(ctx context.Context, picId uint) (bool return repository.Exists[entity.User](ctx, r.db, picId) } +func (r *KandangRepositoryImpl) KandangGroupExists(ctx context.Context, kandangGroupId uint) (bool, error) { + return repository.Exists[entity.KandangGroup](ctx, r.db, kandangGroupId) +} + func (r *KandangRepositoryImpl) NameExists(ctx context.Context, name string, excludeID *uint) (bool, error) { return repository.ExistsByName[entity.Kandang](ctx, r.db, name, excludeID) } diff --git a/internal/modules/master/kandangs/services/kandang.service.go b/internal/modules/master/kandangs/services/kandang.service.go index 159bc410..fbfddba5 100644 --- a/internal/modules/master/kandangs/services/kandang.service.go +++ b/internal/modules/master/kandangs/services/kandang.service.go @@ -3,13 +3,14 @@ package service import ( "errors" "fmt" + "strings" + common "gitlab.com/mbugroup/lti-api.git/internal/common/service" entity "gitlab.com/mbugroup/lti-api.git/internal/entities" m "gitlab.com/mbugroup/lti-api.git/internal/middleware" repository "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/repositories" validation "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/validations" "gitlab.com/mbugroup/lti-api.git/internal/utils" - "strings" "github.com/go-playground/validator/v10" "github.com/gofiber/fiber/v2" @@ -99,6 +100,28 @@ func (s kandangService) GetOne(c *fiber.Ctx, id uint) (*entity.Kandang, error) { return kandang, nil } +func (s kandangService) ensureKandangGroupAccess(c *fiber.Ctx, groupID uint, expectedLocationID *uint) error { + var kandangGroup entity.KandangGroup + if err := s.Repository.DB().WithContext(c.Context()). + Select("id", "location_id"). + First(&kandangGroup, groupID).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return fiber.NewError(fiber.StatusNotFound, "Kandang group not found") + } + return err + } + + if err := m.EnsureLocationAccess(c, s.Repository.DB(), kandangGroup.LocationId); err != nil { + return fiber.NewError(fiber.StatusNotFound, "Kandang group not found") + } + + if expectedLocationID != nil && kandangGroup.LocationId != *expectedLocationID { + return fiber.NewError(fiber.StatusBadRequest, "Kandang group location must match kandang location") + } + + return nil +} + func (s *kandangService) CreateOne(c *fiber.Ctx, req *validation.Create) (*entity.Kandang, error) { if err := s.Validate.Struct(req); err != nil { return nil, err @@ -116,10 +139,14 @@ func (s *kandangService) CreateOne(c *fiber.Ctx, req *validation.Create) (*entit if err := common.EnsureRelations(c.Context(), common.RelationCheck{Name: "Location", ID: &req.LocationId, Exists: s.Repository.LocationExists}, + common.RelationCheck{Name: "KandangGroup", ID: &req.GroupId, Exists: s.Repository.KandangGroupExists}, common.RelationCheck{Name: "Pic", ID: &req.PicId, Exists: s.Repository.PicExists}, ); err != nil { return nil, err } + if err := s.ensureKandangGroupAccess(c, req.GroupId, &req.LocationId); err != nil { + return nil, err + } status := strings.ToUpper(strings.TrimSpace(req.Status)) if status == "" { @@ -154,12 +181,13 @@ func (s *kandangService) CreateOne(c *fiber.Ctx, req *validation.Create) (*entit } createBody := &entity.Kandang{ - Name: req.Name, - LocationId: req.LocationId, - Capacity: req.Capacity, - Status: status, - PicId: req.PicId, - CreatedBy: actorID, + Name: req.Name, + LocationId: req.LocationId, + KandangGroupId: req.GroupId, + Capacity: req.Capacity, + Status: status, + PicId: req.PicId, + CreatedBy: actorID, } if err := s.Repository.CreateOne(c.Context(), createBody, nil); err != nil { @@ -212,6 +240,7 @@ func (s kandangService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uint) if err := common.EnsureRelations(c.Context(), common.RelationCheck{Name: "Location", ID: req.LocationId, Exists: s.Repository.LocationExists}, + common.RelationCheck{Name: "KandangGroup", ID: req.GroupId, Exists: s.Repository.KandangGroupExists}, common.RelationCheck{Name: "Pic", ID: req.PicId, Exists: s.Repository.PicExists}, ); err != nil { return nil, err @@ -220,6 +249,16 @@ func (s kandangService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uint) if req.LocationId != nil { updateBody["location_id"] = *req.LocationId } + if req.GroupId != nil { + targetLocationID := existing.LocationId + if req.LocationId != nil { + targetLocationID = *req.LocationId + } + if err := s.ensureKandangGroupAccess(c, *req.GroupId, &targetLocationID); err != nil { + return nil, err + } + updateBody["kandang_group_id"] = *req.GroupId + } if req.PicId != nil { updateBody["pic_id"] = *req.PicId diff --git a/internal/modules/master/kandangs/validations/kandang.validation.go b/internal/modules/master/kandangs/validations/kandang.validation.go index 63f03d12..9d5fe103 100644 --- a/internal/modules/master/kandangs/validations/kandang.validation.go +++ b/internal/modules/master/kandangs/validations/kandang.validation.go @@ -5,6 +5,7 @@ type Create struct { Status string `json:"status,omitempty" validate:"omitempty,min=3,max=50"` Capacity float64 `json:"capacity" validate:"required_strict,gt=0"` LocationId uint `json:"location_id" validate:"required_strict,number,gt=0"` + GroupId uint `json:"group_id" validate:"required_strict,number,gt=0"` PicId uint `json:"pic_id" validate:"required_strict,number,gt=0"` ProjectFlockId *uint `json:"project_flock_id" validate:"omitempty,number,gt=0"` } @@ -14,6 +15,7 @@ type Update struct { Status *string `json:"status,omitempty" validate:"omitempty,min=3,max=50"` Capacity *float64 `json:"capacity" validate:"omitempty,gt=0"` LocationId *uint `json:"location_id,omitempty" validate:"omitempty,number,gt=0"` + GroupId *uint `json:"group_id" validate:"required_strict,number,gt=0"` PicId *uint `json:"pic_id,omitempty" validate:"omitempty,number,gt=0"` ProjectFlockId *uint `json:"project_flock_id,omitempty" validate:"omitempty,number,gt=0"` }