From 4b69afe4facf29ac2bd8eace1b97948b44979676 Mon Sep 17 00:00:00 2001 From: aguhh18 Date: Thu, 6 Nov 2025 14:03:47 +0700 Subject: [PATCH] Feat[BE-127] create get all with param on project flock kandang --- .../project_flock_kandang.controller.go | 9 +- .../dto/project_flock_kandang.dto.go | 6 ++ .../services/project_flock_kandang.service.go | 92 +++++++++++++++++-- .../project_flock_kandang.validation.go | 12 ++- .../projectflock_kandang.repository.go | 39 ++++---- 5 files changed, 129 insertions(+), 29 deletions(-) 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 92743035..8e4c23a5 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 @@ -33,11 +33,16 @@ func (u *ProjectFlockKandangController) GetAll(c *fiber.Ctx) error { return fiber.NewError(fiber.StatusBadRequest, "page and limit must be greater than 0") } - result, totalResults, err := u.ProjectFlockKandangService.GetAll(c, query) + results, totalResults, err := u.ProjectFlockKandangService.GetAll(c, query) if err != nil { return err } + var data []dto.ProjectFlockKandangListDTO + for _, result := range results { + data = append(data, dto.ToProjectFlockKandangListDTO(result.Entity)) + } + return c.Status(fiber.StatusOK). JSON(response.SuccessWithPaginate[dto.ProjectFlockKandangListDTO]{ Code: fiber.StatusOK, @@ -49,7 +54,7 @@ func (u *ProjectFlockKandangController) GetAll(c *fiber.Ctx) error { TotalPages: int64(math.Ceil(float64(totalResults) / float64(query.Limit))), TotalResults: totalResults, }, - Data: dto.ToProjectFlockKandangListDTOs(result), + Data: data, }) } diff --git a/internal/modules/production/project-flock-kandangs/dto/project_flock_kandang.dto.go b/internal/modules/production/project-flock-kandangs/dto/project_flock_kandang.dto.go index 163de6a3..de74723f 100644 --- a/internal/modules/production/project-flock-kandangs/dto/project_flock_kandang.dto.go +++ b/internal/modules/production/project-flock-kandangs/dto/project_flock_kandang.dto.go @@ -68,6 +68,12 @@ type ProjectFlockKandangDetailDTO struct { ProjectFlockKandangListDTO } +// Wrapper untuk GetAll dengan available quantities sudah included +type ProjectFlockKandangWithAvailableQtysDTO struct { + Entity entity.ProjectFlockKandang + AvailableQtys []map[string]interface{} +} + // === Mapper Functions (ordered) === func ToProjectFlockKandangBaseDTO(e entity.ProjectFlockKandang) ProjectFlockKandangBaseDTO { 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 52b2570a..ee6687c0 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 @@ -7,6 +7,7 @@ import ( entity "gitlab.com/mbugroup/lti-api.git/internal/entities" rProductWarehouse "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/repositories" rWarehouse "gitlab.com/mbugroup/lti-api.git/internal/modules/master/warehouses/repositories" + dto "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project-flock-kandangs/dto" validation "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project-flock-kandangs/validations" repository "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/repositories" "gitlab.com/mbugroup/lti-api.git/internal/utils" @@ -18,7 +19,7 @@ import ( ) type ProjectFlockKandangService interface { - GetAll(ctx *fiber.Ctx, params *validation.Query) ([]entity.ProjectFlockKandang, int64, error) + GetAll(ctx *fiber.Ctx, params *validation.Query) ([]dto.ProjectFlockKandangWithAvailableQtysDTO, int64, error) GetOne(ctx *fiber.Ctx, id uint) (*entity.ProjectFlockKandang, []map[string]interface{}, error) } @@ -44,19 +45,99 @@ func NewProjectFlockKandangService(repo repository.ProjectFlockKandangRepository } } -func (s projectFlockKandangService) GetAll(c *fiber.Ctx, params *validation.Query) ([]entity.ProjectFlockKandang, int64, error) { +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 } - projectFlockKandangs, err := s.Repository.GetAll(c.Context()) + if params.Page <= 0 { + params.Page = 1 + } + if params.Limit <= 0 { + params.Limit = 10 + } + + 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) + }) + if err != nil { s.Log.Errorf("Failed to get projectFlockKandangs: %+v", err) return nil, 0, err } - total := int64(len(projectFlockKandangs)) - return projectFlockKandangs, total, nil + var results []dto.ProjectFlockKandangWithAvailableQtysDTO + for i := range projectFlockKandangs { + availableQtys, err := s.getAvailableQuantities(c, &projectFlockKandangs[i]) + if err != nil { + s.Log.Warnf("Failed to fetch available quantities for kandang %d: %+v", projectFlockKandangs[i].Kandang.Id, err) + availableQtys = nil + } + + results = append(results, dto.ProjectFlockKandangWithAvailableQtysDTO{ + Entity: projectFlockKandangs[i], + AvailableQtys: availableQtys, + }) + } + + return results, total, nil } func (s projectFlockKandangService) GetOne(c *fiber.Ctx, id uint) (*entity.ProjectFlockKandang, []map[string]interface{}, error) { @@ -65,7 +146,6 @@ func (s projectFlockKandangService) GetOne(c *fiber.Ctx, id uint) (*entity.Proje return nil, nil, fiber.NewError(fiber.StatusNotFound, "ProjectFlockKandang not found") } if err != nil { - s.Log.Errorf("Failed get projectFlockKandang by id: %+v", err) return nil, nil, err } 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 1e95fd2c..e635ff92 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 @@ -11,7 +11,13 @@ type Update struct { } type Query struct { - Page int `query:"page" validate:"omitempty,number,min=1,gt=0"` - Limit int `query:"limit" validate:"omitempty,number,min=1,max=100,gt=0"` - Search string `query:"search" validate:"omitempty,max=50"` + Page int `query:"page" validate:"omitempty,number,min=1,gt=0"` + Limit int `query:"limit" validate:"omitempty,number,min=1,max=100,gt=0"` + Search string `query:"search" validate:"omitempty,max=50"` + ProjectFlockId uint `query:"project_flock_id" validate:"omitempty"` + KandangId uint `query:"kandang_id" validate:"omitempty"` + Category string `query:"category" validate:"omitempty,oneof=Growing Laying"` + 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"` } 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 101d01ab..6c39464b 100644 --- a/internal/modules/production/project_flocks/repositories/projectflock_kandang.repository.go +++ b/internal/modules/production/project_flocks/repositories/projectflock_kandang.repository.go @@ -14,7 +14,7 @@ type ProjectFlockKandangRepository interface { GetByProjectFlockAndKandang(ctx context.Context, projectFlockID uint, kandangID uint) (*entity.ProjectFlockKandang, error) CreateMany(ctx context.Context, records []*entity.ProjectFlockKandang) error DeleteMany(ctx context.Context, projectFlockID uint, kandangIDs []uint) error - GetAll(ctx context.Context) ([]entity.ProjectFlockKandang, error) + GetAll(ctx context.Context, offset int, limit int, modifier func(*gorm.DB) *gorm.DB) ([]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) @@ -50,25 +50,28 @@ func (r *projectFlockKandangRepositoryImpl) DeleteMany(ctx context.Context, proj Delete(&entity.ProjectFlockKandang{}).Error } -func (r *projectFlockKandangRepositoryImpl) GetAll(ctx context.Context) ([]entity.ProjectFlockKandang, error) { +func (r *projectFlockKandangRepositoryImpl) GetAll(ctx context.Context, offset int, limit int, modifier func(*gorm.DB) *gorm.DB) ([]entity.ProjectFlockKandang, int64, error) { var records []entity.ProjectFlockKandang - if err := r.db.WithContext(ctx). - 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"). - Order("project_flock_id ASC, created_at ASC"). - Find(&records).Error; err != nil { - return nil, err + var total int64 + + q := r.db.WithContext(ctx) + + // Apply modifier function + if modifier != nil { + q = modifier(q) } - return records, nil + + // 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 + } + + return records, total, nil } func (r *projectFlockKandangRepositoryImpl) WithTx(tx *gorm.DB) ProjectFlockKandangRepository {