From 7a704c4ec4ee32c4ac15da5c92fce3f7e9786071 Mon Sep 17 00:00:00 2001 From: aguhh18 Date: Mon, 26 Jan 2026 18:03:54 +0700 Subject: [PATCH] Feat[BE]: implement max target quantity retrieval for kandangs and update routes --- .../projectflock_kandang.repository.go | 1 + .../controllers/transfer_laying.controller.go | 26 +++++++++++++ .../dto/transfer_laying.dto.go | 26 +++++++++++++ .../production/transfer_layings/route.go | 15 ++++---- .../services/transfer_laying.service.go | 37 +++++++++++++++++++ 5 files changed, 98 insertions(+), 7 deletions(-) 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 474a53c2..f5b55a78 100644 --- a/internal/modules/production/project_flocks/repositories/projectflock_kandang.repository.go +++ b/internal/modules/production/project_flocks/repositories/projectflock_kandang.repository.go @@ -85,6 +85,7 @@ func (r *projectFlockKandangRepositoryImpl) GetByProjectFlockID(ctx context.Cont var records []entity.ProjectFlockKandang if err := r.db.WithContext(ctx). Where("project_flock_id = ?", projectFlockID). + Preload("Kandang"). Find(&records).Error; err != nil { return nil, err } diff --git a/internal/modules/production/transfer_layings/controllers/transfer_laying.controller.go b/internal/modules/production/transfer_layings/controllers/transfer_laying.controller.go index d0ee5061..c299c3e8 100644 --- a/internal/modules/production/transfer_layings/controllers/transfer_laying.controller.go +++ b/internal/modules/production/transfer_layings/controllers/transfer_laying.controller.go @@ -218,3 +218,29 @@ func (u *TransferLayingController) GetAvailableQtyPerKandang(c *fiber.Ctx) error Data: resp, }) } + +func (u *TransferLayingController) GetMaxTargetQtyPerKandang(c *fiber.Ctx) error { + projectFlockID, err := strconv.ParseUint(c.Params("project_flock_id"), 10, 32) + if err != nil { + return fiber.NewError(fiber.StatusBadRequest, "Invalid project_flock_id") + } + kandangMaxTargetQty, err := u.TransferLayingService.GetMaxTargetQtyPerKandang(c, uint(projectFlockID)) + if err != nil { + return err + } + + kandangs := make([]dto.KandangMaxTargetQtyDTO, 0, len(kandangMaxTargetQty)) + for pfkId, maxTargetQty := range kandangMaxTargetQty { + kandangs = append(kandangs, dto.ToKandangMaxTargetQtyDTO(pfkId, maxTargetQty)) + } + + resp := dto.ToMaxTargetQtyForTransferDTO(uint(projectFlockID), kandangs) + + return c.Status(fiber.StatusOK). + JSON(response.Success{ + Code: fiber.StatusOK, + Status: "success", + Message: "Get max target quantity successfully", + Data: resp, + }) +} diff --git a/internal/modules/production/transfer_layings/dto/transfer_laying.dto.go b/internal/modules/production/transfer_layings/dto/transfer_laying.dto.go index dfc5e5d9..5e440971 100644 --- a/internal/modules/production/transfer_layings/dto/transfer_laying.dto.go +++ b/internal/modules/production/transfer_layings/dto/transfer_laying.dto.go @@ -94,6 +94,18 @@ type AvailableQtyForTransferDTO struct { Kandangs []KandangAvailableQtyDTO `json:"kandangs"` } +// === Max Target Quantity DTOs === + +type KandangMaxTargetQtyDTO struct { + ProjectFlockKandangId uint `json:"project_flock_kandang_id"` + MaxTargetQty float64 `json:"max_target_qty"` +} + +type MaxTargetQtyForTransferDTO struct { + ProjectFlockId uint `json:"project_flock_id"` + ProjectFlockKandangs []KandangMaxTargetQtyDTO `json:"project_flock_kandangs"` +} + // === Mapper Functions === func ToProjectFlockSummaryDTO(pf *entity.ProjectFlock) *ProjectFlockSummaryDTO { @@ -285,3 +297,17 @@ func ToTransferLayingListDTOs(items []entity.LayingTransfer) []TransferLayingLis } return result } + +func ToKandangMaxTargetQtyDTO(pfkId uint, maxTargetQTY float64) KandangMaxTargetQtyDTO { + return KandangMaxTargetQtyDTO{ + ProjectFlockKandangId: uint(pfkId), + MaxTargetQty: maxTargetQTY, + } +} + +func ToMaxTargetQtyForTransferDTO(pfId uint, kandangs []KandangMaxTargetQtyDTO) MaxTargetQtyForTransferDTO { + return MaxTargetQtyForTransferDTO{ + ProjectFlockId: pfId, + ProjectFlockKandangs: kandangs, + } +} diff --git a/internal/modules/production/transfer_layings/route.go b/internal/modules/production/transfer_layings/route.go index 8f7a62c0..c16ba1a8 100644 --- a/internal/modules/production/transfer_layings/route.go +++ b/internal/modules/production/transfer_layings/route.go @@ -21,11 +21,12 @@ func TransferLayingRoutes(v1 fiber.Router, u user.UserService, s transferLaying. // route.Delete("/:id", m.Auth(u), ctrl.DeleteOne) // route.Post("/approval", m.Auth(u), ctrl.Approval) - route.Get("/",m.RequirePermissions(m.P_TransferToLaying_GetAll), ctrl.GetAll) - route.Post("/",m.RequirePermissions(m.P_TransferToLaying_CreateOne), ctrl.CreateOne) - route.Get("/:id",m.RequirePermissions(m.P_TransferToLaying_GetOne), ctrl.GetOne) - route.Patch("/:id",m.RequirePermissions(m.P_TransferToLaying_UpdateOne), ctrl.UpdateOne) - route.Delete("/:id",m.RequirePermissions(m.P_TransferToLaying_DeleteOne), ctrl.DeleteOne) - route.Post("/approvals",m.RequirePermissions(m.P_TransferToLaying_Approval), ctrl.Approval) - route.Get("/project-flocks/:project_flock_id/available-qty",m.RequirePermissions(m.P_TransferToLaying_GetAvailableQty), ctrl.GetAvailableQtyPerKandang) + route.Get("/", m.RequirePermissions(m.P_TransferToLaying_GetAll), ctrl.GetAll) + route.Post("/", m.RequirePermissions(m.P_TransferToLaying_CreateOne), ctrl.CreateOne) + route.Get("/:id", m.RequirePermissions(m.P_TransferToLaying_GetOne), ctrl.GetOne) + route.Patch("/:id", m.RequirePermissions(m.P_TransferToLaying_UpdateOne), ctrl.UpdateOne) + route.Delete("/:id", m.RequirePermissions(m.P_TransferToLaying_DeleteOne), ctrl.DeleteOne) + route.Post("/approvals", m.RequirePermissions(m.P_TransferToLaying_Approval), ctrl.Approval) + route.Get("/project-flocks/:project_flock_id/available-qty", m.RequirePermissions(m.P_TransferToLaying_GetAvailableQty), ctrl.GetAvailableQtyPerKandang) + route.Get("/project-flocks/:project_flock_id/max-target-qty", m.RequirePermissions(m.P_TransferToLaying_CreateOne), ctrl.GetMaxTargetQtyPerKandang) } diff --git a/internal/modules/production/transfer_layings/services/transfer_laying.service.go b/internal/modules/production/transfer_layings/services/transfer_laying.service.go index 8e0269cf..bfdfab0f 100644 --- a/internal/modules/production/transfer_layings/services/transfer_laying.service.go +++ b/internal/modules/production/transfer_layings/services/transfer_laying.service.go @@ -34,6 +34,7 @@ type TransferLayingService interface { DeleteOne(ctx *fiber.Ctx, id uint) error Approval(ctx *fiber.Ctx, req *validation.Approve) ([]entity.LayingTransfer, error) GetAvailableQtyPerKandang(ctx *fiber.Ctx, projectFlockID uint) (*entity.ProjectFlock, map[uint]float64, error) + GetMaxTargetQtyPerKandang(ctx *fiber.Ctx, projectFlockID uint) (map[uint]float64, error) } type transferLayingService struct { @@ -888,3 +889,39 @@ func (s *transferLayingService) validateKandangOwnership( return nil } + +func (s transferLayingService) GetMaxTargetQtyPerKandang(c *fiber.Ctx, projectFlockID uint) (map[uint]float64, error) { + + if err := commonSvc.EnsureRelations(c.Context(), + commonSvc.RelationCheck{Name: "Project Flock", ID: &projectFlockID, Exists: s.ProjectFlockRepo.IdExists}, + ); err != nil { + return nil, err + } + + projectFlockKandangs, err := s.ProjectFlockKandangRepo.GetByProjectFlockID(c.Context(), projectFlockID) + if err != nil { + return nil, err + } + + kandangMaxTargetQty := make(map[uint]float64) + for _, projectFlockKandang := range projectFlockKandangs { + + capacity := projectFlockKandang.Kandang.Capacity + + availableQty, err := s.ProjectFlockPopulationRepo.GetAvailableQtyByProjectFlockKandangID( + c.Context(), + projectFlockKandang.Id, + ) + if err != nil { + return nil, err + } + + kandangMaxTargetQty[projectFlockKandang.Id] = capacity - availableQty + + if kandangMaxTargetQty[projectFlockKandang.Id] < 0 { + kandangMaxTargetQty[projectFlockKandang.Id] = 0 + } + } + + return kandangMaxTargetQty, nil +}