feat[BE-384]: enhance closing reports by introducing calculation context and improving data handling; refactor related functions for better clarity and maintainability

This commit is contained in:
aguhh18
2025-12-19 08:30:05 +07:00
parent e551995c66
commit fa6d82b79a
8 changed files with 286 additions and 167 deletions
@@ -143,6 +143,10 @@ func (s *chickinService) CreateOne(c *fiber.Ctx, req *validation.Create) ([]enti
return nil, fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Product warehouse %d is not bound to kandang's warehouse", chickinReq.ProductWarehouseId))
}
if productWarehouse.ProjectFlockKandangId == nil || *productWarehouse.ProjectFlockKandangId != req.ProjectFlockKandangId {
return nil, fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Product warehouse %d is not attached to project_flock_kandang %d. Only product warehouses with matching project_flock_kandang_id can be chickin-ed", chickinReq.ProductWarehouseId, req.ProjectFlockKandangId))
}
chickinDate, err := utils.ParseDateString(chickinReq.ChickInDate)
if err != nil {
return nil, fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Invalid ChickInDate format for product warehouse %d", chickinReq.ProductWarehouseId))
@@ -450,7 +454,8 @@ func (s chickinService) Approval(c *fiber.Ctx, req *validation.Approve) ([]entit
return fiber.NewError(fiber.StatusInternalServerError, "Failed to get warehouse")
}
targetPW, err := s.getOrCreateProductWarehouse(c, warehouse.Id, "PULLET", dbTransaction, actorID)
pfkID := approvableID
targetPW, err := s.getOrCreateProductWarehouse(c, warehouse.Id, "PULLET", dbTransaction, actorID, &pfkID)
if err != nil {
return fiber.NewError(fiber.StatusInternalServerError, "Failed to get/create PULLET product warehouse")
}
@@ -466,7 +471,8 @@ func (s chickinService) Approval(c *fiber.Ctx, req *validation.Approve) ([]entit
return fiber.NewError(fiber.StatusInternalServerError, "Failed to get warehouse")
}
targetPW, err := s.getOrCreateProductWarehouse(c, warehouse.Id, "PULLET", dbTransaction, actorID)
pfkID := approvableID
targetPW, err := s.getOrCreateProductWarehouse(c, warehouse.Id, "PULLET", dbTransaction, actorID, &pfkID)
if err != nil {
return fiber.NewError(fiber.StatusInternalServerError, "Failed to get/create PULLET product warehouse")
}
@@ -538,11 +544,19 @@ func (s chickinService) Approval(c *fiber.Ctx, req *validation.Approve) ([]entit
return updated, nil
}
func (s *chickinService) getOrCreateProductWarehouse(ctx *fiber.Ctx, warehouseId uint, categoryCode string, dbTransaction *gorm.DB, actorID uint) (*entity.ProductWarehouse, error) {
func (s *chickinService) getOrCreateProductWarehouse(ctx *fiber.Ctx, warehouseId uint, categoryCode string, dbTransaction *gorm.DB, actorID uint, projectFlockKandangId *uint) (*entity.ProductWarehouse, error) {
products, err := s.ProductWarehouseRepo.GetByFlagAndWarehouseID(ctx.Context(), categoryCode, warehouseId)
if err == nil && len(products) > 0 {
return &products[0], nil
existingPW := &products[0]
// Update project_flock_kandang_id if not already set
if existingPW.ProjectFlockKandangId == nil && projectFlockKandangId != nil {
existingPW.ProjectFlockKandangId = projectFlockKandangId
if err := s.ProductWarehouseRepo.WithTx(dbTransaction).UpdateOne(ctx.Context(), existingPW.Id, existingPW, nil); err != nil {
return nil, fmt.Errorf("failed to update %s product warehouse with project_flock_kandang_id: %w", categoryCode, err)
}
}
return existingPW, nil
}
product, err := s.ProductWarehouseRepo.GetFirstProductByFlag(ctx.Context(), categoryCode)
@@ -554,9 +568,10 @@ func (s *chickinService) getOrCreateProductWarehouse(ctx *fiber.Ctx, warehouseId
}
newPW := &entity.ProductWarehouse{
ProductId: product.Id,
WarehouseId: warehouseId,
Quantity: 0,
ProductId: product.Id,
WarehouseId: warehouseId,
ProjectFlockKandangId: projectFlockKandangId,
Quantity: 0,
// CreatedBy: actorID,
}
@@ -190,13 +190,16 @@ func (s projectFlockKandangService) getAvailableQuantities(c *fiber.Ctx, project
result := make(map[uint]float64)
for _, pw := range products {
availableQty, err := s.calculateAvailableQuantityForProductWarehouse(c, projectFlockKandang, &pw)
if err != nil {
s.Log.Warnf("Failed to calculate available quantity for product warehouse %d: %v", pw.Id, err)
}
if availableQty > 0 {
result[pw.Id] = availableQty
if pw.ProjectFlockKandangId != nil && *pw.ProjectFlockKandangId == projectFlockKandang.Id {
availableQty, err := s.calculateAvailableQuantityForProductWarehouse(c, projectFlockKandang, &pw)
if err != nil {
s.Log.Warnf("Failed to calculate available quantity for product warehouse %d: %v", pw.Id, err)
}
if availableQty > 0 {
result[pw.Id] = availableQty
}
}
}
@@ -425,7 +425,7 @@ func (r *RecordingRepositoryImpl) GetLatestAvgWeightByProjectFlockID(ctx context
Joins("JOIN recordings ON recordings.id = recording_bws.recording_id").
Joins("JOIN project_flock_kandangs ON project_flock_kandangs.id = recordings.project_flock_kandangs_id").
Where("project_flock_kandangs.project_flock_id = ?", projectFlockID).
Where("recordings.record_datetime = (SELECT MAX(record_datetime) FROM recordings WHERE project_flock_kandangs_id = project_flock_kandangs.id)").
Where("recordings.record_datetime = (SELECT MAX(record_datetime) FROM recordings r2 WHERE r2.project_flock_kandangs_id IN (SELECT id FROM project_flock_kandangs WHERE project_flock_id = ?))", projectFlockID).
Scan(&result).Error
return result, err
}