From 0f4cc6e3791ead16b42cf1fd698bd53e594dff97 Mon Sep 17 00:00:00 2001 From: MacBook Air M1 Date: Tue, 13 Jan 2026 15:32:43 +0700 Subject: [PATCH] adjust api closing data produksi --- .../closings/services/closing.service.go | 44 ++++++++--------- .../repositories/recording.repository.go | 48 +++++++++++-------- 2 files changed, 49 insertions(+), 43 deletions(-) diff --git a/internal/modules/closings/services/closing.service.go b/internal/modules/closings/services/closing.service.go index 8b00475f..76f3e024 100644 --- a/internal/modules/closings/services/closing.service.go +++ b/internal/modules/closings/services/closing.service.go @@ -586,11 +586,21 @@ func (s closingService) GetClosingDataProduksi(c *fiber.Ctx, projectFlockID uint averageFeedIntake := targetAverages.FeedIntakeAvg feedIntakeStd := 0.0 + var mortalityStdFromGrowth *float64 if project.ProductionStandardId > 0 && currentWeek > 0 && s.StandardGrowthDetailRepo != nil { - feedIntakeStd, err = s.calculateFeedIntakeStd(c.Context(), project.ProductionStandardId, currentWeek) - if err != nil { - s.Log.Errorf("Failed to compute feed intake std for project flock %d: %+v", projectFlockID, err) - return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch feed intake standard data") + growthDetail, growthErr := s.StandardGrowthDetailRepo.GetByStandardIDAndWeek(c.Context(), project.ProductionStandardId, currentWeek) + if growthErr != nil { + if !errors.Is(growthErr, gorm.ErrRecordNotFound) { + s.Log.Errorf("Failed to fetch growth detail for project flock %d: %+v", projectFlockID, growthErr) + return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch growth standard data") + } + } else if growthDetail != nil { + if growthDetail.FeedIntake != nil { + feedIntakeStd = *growthDetail.FeedIntake + } + if growthDetail.MaxDepletion != nil { + mortalityStdFromGrowth = growthDetail.MaxDepletion + } } } @@ -754,6 +764,14 @@ func (s closingService) GetClosingDataProduksi(c *fiber.Ctx, projectFlockID uint } performance.FeedIntake = averageFeedIntake performance.FeedIntakeStd = feedIntakeStd + if targetAverages.CumDepletionRateCount > 0 { + performance.MortalityAct = targetAverages.CumDepletionRateAvg + performance.DeffMortality = performance.MortalityAct - performance.MortalityStd + } + if mortalityStdFromGrowth != nil { + performance.MortalityStd = *mortalityStdFromGrowth + performance.DeffMortality = performance.MortalityAct - performance.MortalityStd + } if !isGrowing { if targetAverages.HenDayCount > 0 { henDayAct := targetAverages.HenDayAvg @@ -876,24 +894,6 @@ func (s closingService) determineProductionWeek(ctx context.Context, projectFloc return week, nil } -func (s closingService) calculateFeedIntakeStd(ctx context.Context, productionStandardID uint, week int) (float64, error) { - if productionStandardID == 0 || week <= 0 || s.StandardGrowthDetailRepo == nil { - return 0, nil - } - - detail, err := s.StandardGrowthDetailRepo.GetByStandardIDAndWeek(ctx, productionStandardID, week) - if err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - return 0, nil - } - return 0, err - } - if detail == nil || detail.FeedIntake == nil { - return 0, nil - } - return *detail.FeedIntake, nil -} - func calculatePerformanceMetrics(averageWeight, totalWeight, feedUsed, basePopulation, depletion, age float64, standards []entity.FcrStandard) dto.ClosingPerformanceDTO { mortalityStd, fcrStd := closestFcrValues(standards, averageWeight) diff --git a/internal/modules/production/recordings/repositories/recording.repository.go b/internal/modules/production/recordings/repositories/recording.repository.go index d15b934d..bf08b78b 100644 --- a/internal/modules/production/recordings/repositories/recording.repository.go +++ b/internal/modules/production/recordings/repositories/recording.repository.go @@ -56,18 +56,20 @@ type RecordingRepositoryImpl struct { } type RecordingTargetAverages struct { - HenDayAvg float64 - HenDayCount int64 - HenHouseAvg float64 - HenHouseCount int64 - EggWeightAvg float64 - EggWeightCount int64 - EggMassAvg float64 - EggMassCount int64 - FeedIntakeAvg float64 - FeedIntakeCount int64 - FcrAvg float64 - FcrCount int64 + HenDayAvg float64 + HenDayCount int64 + HenHouseAvg float64 + HenHouseCount int64 + EggWeightAvg float64 + EggWeightCount int64 + EggMassAvg float64 + EggMassCount int64 + FeedIntakeAvg float64 + FeedIntakeCount int64 + FcrAvg float64 + FcrCount int64 + CumDepletionRateAvg float64 + CumDepletionRateCount int64 } func NewRecordingRepository(db *gorm.DB) RecordingRepository { @@ -451,18 +453,20 @@ func (r *RecordingRepositoryImpl) GetTotalEggProductionWeightByProjectFlockID(ct func (r *RecordingRepositoryImpl) GetAverageTargetMetricsByProjectFlockKandangID(ctx context.Context, projectFlockKandangID uint, includeTargets bool) (RecordingTargetAverages, error) { var row struct { - HenDayTotal float64 - HenHouseTotal float64 - EggWeightTotal float64 - EggMassTotal float64 - FeedIntakeTotal float64 - FcrTotal float64 - TotalCount int64 + HenDayTotal float64 + HenHouseTotal float64 + EggWeightTotal float64 + EggMassTotal float64 + FeedIntakeTotal float64 + FcrTotal float64 + CumDepletionRateTotal float64 + TotalCount int64 } selectParts := []string{ "COALESCE(SUM(feed_intake), 0) AS feed_intake_total", "COALESCE(SUM(fcr_value), 0) AS fcr_total", + "COALESCE(SUM(cum_depletion_rate), 0) AS cum_depletion_rate_total", "COUNT(*) AS total_count", } if includeTargets { @@ -483,8 +487,9 @@ func (r *RecordingRepositoryImpl) GetAverageTargetMetricsByProjectFlockKandangID } result := RecordingTargetAverages{ - FeedIntakeCount: row.TotalCount, - FcrCount: row.TotalCount, + FeedIntakeCount: row.TotalCount, + FcrCount: row.TotalCount, + CumDepletionRateCount: row.TotalCount, } if includeTargets { result.HenDayCount = row.TotalCount @@ -501,6 +506,7 @@ func (r *RecordingRepositoryImpl) GetAverageTargetMetricsByProjectFlockKandangID } result.FeedIntakeAvg = row.FeedIntakeTotal / float64(row.TotalCount) result.FcrAvg = row.FcrTotal / float64(row.TotalCount) + result.CumDepletionRateAvg = row.CumDepletionRateTotal } return result, nil