diff --git a/internal/modules/production/project-flock-kandangs/controllers/project_flock_kandang.controller.go b/internal/modules/production/project-flock-kandangs/controllers/project_flock_kandang.controller.go index 8e4c23a5..383006bf 100644 --- a/internal/modules/production/project-flock-kandangs/controllers/project_flock_kandang.controller.go +++ b/internal/modules/production/project-flock-kandangs/controllers/project_flock_kandang.controller.go @@ -24,9 +24,16 @@ func NewProjectFlockKandangController(projectFlockKandangService service.Project func (u *ProjectFlockKandangController) GetAll(c *fiber.Ctx) error { query := &validation.Query{ - Page: c.QueryInt("page", 1), - Limit: c.QueryInt("limit", 10), - Search: c.Query("search", ""), + Page: c.QueryInt("page", 1), + Limit: c.QueryInt("limit", 10), + Search: c.Query("search", ""), + ProjectFlockId: uint(c.QueryInt("project_flock_id", 0)), + KandangId: uint(c.QueryInt("kandang_id", 0)), + Category: c.Query("category", ""), + AreaId: uint(c.QueryInt("area_id", 0)), + SortBy: c.Query("sort_by", ""), + SortOrder: c.Query("sort_order", ""), + StepName: c.Query("step_name", ""), } if query.Page < 1 || query.Limit < 1 { @@ -38,7 +45,7 @@ func (u *ProjectFlockKandangController) GetAll(c *fiber.Ctx) error { return err } - var data []dto.ProjectFlockKandangListDTO + data := make([]dto.ProjectFlockKandangListDTO, 0) for _, result := range results { data = append(data, dto.ToProjectFlockKandangListDTO(result.Entity)) } diff --git a/internal/modules/production/project-flock-kandangs/services/project_flock_kandang.service.go b/internal/modules/production/project-flock-kandangs/services/project_flock_kandang.service.go index ee6687c0..90e85882 100644 --- a/internal/modules/production/project-flock-kandangs/services/project_flock_kandang.service.go +++ b/internal/modules/production/project-flock-kandangs/services/project_flock_kandang.service.go @@ -45,22 +45,6 @@ func NewProjectFlockKandangService(repo repository.ProjectFlockKandangRepository } } -func (s projectFlockKandangService) withRelations(db *gorm.DB) *gorm.DB { - return db. - Preload("ProjectFlock"). - Preload("ProjectFlock.Fcr"). - Preload("ProjectFlock.Area"). - Preload("ProjectFlock.Location"). - Preload("ProjectFlock.CreatedUser"). - Preload("ProjectFlock.Kandangs"). - Preload("ProjectFlock.KandangHistory"). - Preload("Kandang"). - Preload("Chickins"). - Preload("Chickins.CreatedUser"). - Preload("Chickins.ProductWarehouse") - -} - func (s projectFlockKandangService) GetAll(c *fiber.Ctx, params *validation.Query) ([]dto.ProjectFlockKandangWithAvailableQtysDTO, int64, error) { if err := s.Validate.Struct(params); err != nil { return nil, 0, err @@ -75,55 +59,33 @@ func (s projectFlockKandangService) GetAll(c *fiber.Ctx, params *validation.Quer offset := (params.Page - 1) * params.Limit - projectFlockKandangs, total, err := s.Repository.GetAll(c.Context(), offset, params.Limit, func(db *gorm.DB) *gorm.DB { - db = s.withRelations(db) - - if params.Search != "" { - db = db.Where( - db.Where("LOWER(kandang.name) LIKE LOWER(?)", "%"+params.Search+"%"). - Or("LOWER(project_flock.flock_name) LIKE LOWER(?)", "%"+params.Search+"%"), - ) - } - - if params.ProjectFlockId > 0 { - db = db.Where("project_flock_kandangs.project_flock_id = ?", params.ProjectFlockId) - } - - if params.KandangId > 0 { - db = db.Where("project_flock_kandangs.kandang_id = ?", params.KandangId) - } - - if params.Category != "" { - db = db.Where("project_flock.category = ?", params.Category) - } - if params.AreaId > 0 { - db = db.Where("project_flock.area_id = ?", params.AreaId) - } - - sortBy := "project_flock_id ASC, created_at ASC" - if params.SortBy != "" { - sortOrder := "ASC" - if params.SortOrder == "DESC" { - sortOrder = "DESC" - } - - switch params.SortBy { - case "created_at": - sortBy = "project_flock_kandangs.created_at " + sortOrder - case "period": - sortBy = "project_flock.period " + sortOrder - } - } - - return db.Order(sortBy) - }) + projectFlockKandangs, total, err := s.Repository.GetAllWithFilters(c.Context(), offset, params.Limit, params) if err != nil { s.Log.Errorf("Failed to get projectFlockKandangs: %+v", err) return nil, 0, err } - var results []dto.ProjectFlockKandangWithAvailableQtysDTO + if s.ApprovalSvc != nil { + projectFlockKandangIDs := make([]uint, len(projectFlockKandangs)) + for i, pfk := range projectFlockKandangs { + projectFlockKandangIDs[i] = pfk.Id + } + + approvalMap, err := s.ApprovalSvc.LatestByTargets(c.Context(), utils.ApprovalWorkflowProjectFlockKandang, projectFlockKandangIDs, func(db *gorm.DB) *gorm.DB { + return db.Preload("ActionUser") + }) + if err != nil { + s.Log.Warnf("Failed to fetch approvals for projectFlockKandangs: %+v", err) + } else { + for i := range projectFlockKandangs { + if approval, ok := approvalMap[projectFlockKandangs[i].Id]; ok { + projectFlockKandangs[i].LatestApproval = approval + } + } + } + } + results := make([]dto.ProjectFlockKandangWithAvailableQtysDTO, 0) for i := range projectFlockKandangs { availableQtys, err := s.getAvailableQuantities(c, &projectFlockKandangs[i]) if err != nil { diff --git a/internal/modules/production/project-flock-kandangs/validations/project_flock_kandang.validation.go b/internal/modules/production/project-flock-kandangs/validations/project_flock_kandang.validation.go index e635ff92..93e0256a 100644 --- a/internal/modules/production/project-flock-kandangs/validations/project_flock_kandang.validation.go +++ b/internal/modules/production/project-flock-kandangs/validations/project_flock_kandang.validation.go @@ -20,4 +20,5 @@ type Query struct { AreaId uint `query:"area_id" validate:"omitempty"` SortBy string `query:"sort_by" validate:"omitempty,oneof=created_at period"` SortOrder string `query:"sort_order" validate:"omitempty,oneof=ASC DESC"` + StepName string `query:"step_name" validate:"omitempty,max=50"` } diff --git a/internal/modules/production/project_flocks/repositories/projectflock_kandang.repository.go b/internal/modules/production/project_flocks/repositories/projectflock_kandang.repository.go index 6c39464b..1a05acff 100644 --- a/internal/modules/production/project_flocks/repositories/projectflock_kandang.repository.go +++ b/internal/modules/production/project_flocks/repositories/projectflock_kandang.repository.go @@ -6,6 +6,7 @@ import ( "gitlab.com/mbugroup/lti-api.git/internal/common/repository" entity "gitlab.com/mbugroup/lti-api.git/internal/entities" + validation "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project-flock-kandangs/validations" "gorm.io/gorm" ) @@ -15,6 +16,7 @@ type ProjectFlockKandangRepository interface { 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) + GetAllWithFilters(ctx context.Context, offset int, limit int, params interface{}) ([]entity.ProjectFlockKandang, int64, error) ListExistingKandangIDs(ctx context.Context, projectFlockID uint, kandangIDs []uint) ([]uint, error) HasKandangsLinkedToOtherProject(ctx context.Context, kandangIDs []uint, exceptProjectID *uint) (bool, error) FindKandangsWithRecordings(ctx context.Context, projectFlockID uint, kandangIDs []uint) ([]entity.Kandang, error) @@ -56,17 +58,14 @@ func (r *projectFlockKandangRepositoryImpl) GetAll(ctx context.Context, offset i q := r.db.WithContext(ctx) - // Apply modifier function if modifier != nil { q = modifier(q) } - // Count total if err := q.Model(&entity.ProjectFlockKandang{}).Count(&total).Error; err != nil { return nil, 0, err } - // Apply pagination and fetch if err := q.Offset(offset).Limit(limit).Find(&records).Error; err != nil { return nil, 0, err } @@ -74,6 +73,97 @@ func (r *projectFlockKandangRepositoryImpl) GetAll(ctx context.Context, offset i return records, total, nil } +func (r *projectFlockKandangRepositoryImpl) GetAllWithFilters(ctx context.Context, offset int, limit int, params interface{}) ([]entity.ProjectFlockKandang, int64, error) { + var records []entity.ProjectFlockKandang + var total int64 + + query, ok := params.(*validation.Query) + + q := r.db.WithContext(ctx). + Joins("JOIN \"kandangs\" ON \"project_flock_kandangs\".\"kandang_id\" = \"kandangs\".\"id\""). + Joins("JOIN \"project_flocks\" ON \"project_flock_kandangs\".\"project_flock_id\" = \"project_flocks\".\"id\""). + Preload("ProjectFlock"). + Preload("ProjectFlock.Fcr"). + Preload("ProjectFlock.Area"). + Preload("ProjectFlock.Location"). + Preload("ProjectFlock.CreatedUser"). + Preload("ProjectFlock.Kandangs"). + Preload("ProjectFlock.KandangHistory"). + Preload("Kandang"). + Preload("Chickins"). + Preload("Chickins.CreatedUser"). + Preload("Chickins.ProductWarehouse") + + if ok && query != nil && query.StepName != "" { + q = q.Where(` + EXISTS ( + SELECT 1 FROM "approvals" + WHERE "approvals"."approvable_id" = "project_flock_kandangs"."id" + AND "approvals"."approvable_type" = ? + AND LOWER("approvals"."step_name") = LOWER(?) + AND "approvals"."id" IN ( + SELECT "id" FROM "approvals" + WHERE "approvable_id" = "project_flock_kandangs"."id" + AND "approvable_type" = ? + ORDER BY "action_at" DESC + LIMIT 1 + ) + ) + `, "PROJECT_FLOCK_KANDANGS", query.StepName, "PROJECT_FLOCK_KANDANGS") + } + + if ok && query != nil { + if query.Search != "" { + escapedSearch := strings.NewReplacer("\\", "\\\\", "%", "\\%", "_", "\\_").Replace(query.Search) + q = q.Where( + r.db.Where("LOWER(\"kandangs\".\"name\") LIKE LOWER(?) ESCAPE '\\'", "%"+escapedSearch+"%"). + Or("LOWER(\"project_flocks\".\"flock_name\") LIKE LOWER(?) ESCAPE '\\'", "%"+escapedSearch+"%"), + ) + } + + if query.ProjectFlockId > 0 { + q = q.Where("\"project_flock_kandangs\".\"project_flock_id\" = ?", query.ProjectFlockId) + } + + if query.KandangId > 0 { + q = q.Where("\"project_flock_kandangs\".\"kandang_id\" = ?", query.KandangId) + } + + if query.Category != "" { + q = q.Where("\"project_flocks\".\"category\" = ?", query.Category) + } + + if query.AreaId > 0 { + q = q.Where("\"project_flocks\".\"area_id\" = ?", query.AreaId) + } + } + + if err := q.Model(&entity.ProjectFlockKandang{}).Count(&total).Error; err != nil { + return nil, 0, err + } + + sortBy := "\"project_flock_kandangs\".\"created_at\" DESC" + if ok && query != nil && query.SortBy != "" { + sortOrder := "DESC" + if query.SortOrder == "ASC" { + sortOrder = "ASC" + } + + switch query.SortBy { + case "created_at": + sortBy = "\"project_flock_kandangs\".\"created_at\" " + sortOrder + case "period": + sortBy = "\"project_flocks\".\"period\" " + sortOrder + } + } + + if err := q.Order(sortBy).Offset(offset).Limit(limit).Find(&records).Error; err != nil { + return nil, 0, err + } + + return records, total, nil +} + func (r *projectFlockKandangRepositoryImpl) WithTx(tx *gorm.DB) ProjectFlockKandangRepository { return &projectFlockKandangRepositoryImpl{db: tx} }