diff --git a/internal/modules/closings/dto/closing.dto.go b/internal/modules/closings/dto/closing.dto.go index 429495b7..c05bd741 100644 --- a/internal/modules/closings/dto/closing.dto.go +++ b/internal/modules/closings/dto/closing.dto.go @@ -204,3 +204,20 @@ func ToClosingDetailDTO(e entity.ProjectFlock) ClosingDetailDTO { ClosingListDTO: ToClosingListDTO(e), } } + +func CalculateAgeFromChickinDataProduksi(projectFlockKandang *entity.ProjectFlockKandang, deliveryDate *time.Time) int { + if projectFlockKandang == nil || deliveryDate == nil || len(projectFlockKandang.Chickins) == 0 { + return 0 + } + + earliestChickinDate := projectFlockKandang.Chickins[0].ChickInDate + for _, chickin := range projectFlockKandang.Chickins { + if chickin.ChickInDate.Before(earliestChickinDate) { + earliestChickinDate = chickin.ChickInDate + } + } + + ageInDays := int(deliveryDate.Sub(earliestChickinDate).Hours() / 24) + ageInWeeks := ageInDays / 7 + return ageInWeeks +} diff --git a/internal/modules/closings/services/closing.service.go b/internal/modules/closings/services/closing.service.go index 895f05f7..10007fd9 100644 --- a/internal/modules/closings/services/closing.service.go +++ b/internal/modules/closings/services/closing.service.go @@ -469,8 +469,11 @@ func (s closingService) GetClosingDataProduksi(c *fiber.Ctx, projectFlockID uint return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch FCR standard data") } } - // masih dummy, karena tab penjualan agenya masih dummy - age := 1.0 + age, err := s.calculateAverageSalesAge(c.Context(), projectFlockID) + if err != nil { + s.Log.Errorf("Failed to calculate sales age for project flock %d: %+v", projectFlockID, err) + return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch sales age data") + } feedUsedPerHead := 0.0 if population > 0 { @@ -599,6 +602,40 @@ func (s closingService) GetClosingDataProduksi(c *fiber.Ctx, projectFlockID uint return &result, nil } +func (s closingService) calculateAverageSalesAge(ctx context.Context, projectFlockID uint) (float64, error) { + deliveryProducts, err := s.MarketingDeliveryProductRepo.GetDeliveryProductsByProjectFlockID(ctx, projectFlockID, func(db *gorm.DB) *gorm.DB { + return db. + Preload("MarketingProduct"). + Preload("MarketingProduct.ProductWarehouse"). + Preload("MarketingProduct.ProductWarehouse.ProjectFlockKandang"). + Preload("MarketingProduct.ProductWarehouse.ProjectFlockKandang.Chickins") + }) + if err != nil { + return 0, err + } + + var ( + totalQty float64 + totalAgeWeeks float64 + ) + + for _, product := range deliveryProducts { + if product.Qty == 0 { + continue + } + projectFlockKandang := product.MarketingProduct.ProductWarehouse.ProjectFlockKandang + ageWeeks := dto.CalculateAgeFromChickinDataProduksi(projectFlockKandang, product.DeliveryDate) + totalAgeWeeks += float64(ageWeeks) * product.Qty + totalQty += product.Qty + } + + if totalQty == 0 { + return 0, nil + } + + return totalAgeWeeks / totalQty, nil +} + func calculatePerformanceMetrics(averageWeight, totalWeight, feedUsed, basePopulation, depletion, age float64, standards []entity.FcrStandard) dto.ClosingPerformanceDTO { mortalityStd, fcrStd := closestFcrValues(standards, averageWeight) @@ -612,8 +649,8 @@ func calculatePerformanceMetrics(averageWeight, totalWeight, feedUsed, basePopul mortalityAct = (depletion / basePopulation) * 100 } - deffMortality := mortalityStd - mortalityAct - deffFcr := fcrStd - fcrAct + deffMortality := mortalityAct - mortalityStd + deffFcr := fcrAct - fcrStd awg := 0.0 if age > 0 {