From aa5d4ab8185bd8020c3c307fa8076130251ed9ab Mon Sep 17 00:00:00 2001 From: giovanni Date: Thu, 7 May 2026 21:09:10 +0700 Subject: [PATCH] adjust calculate for week at recording list --- internal/entities/recording.go | 1 + .../recordings/dto/recording.dto.go | 6 +- internal/utils/recording/recording_helpers.go | 88 ++++++++++++++++++- 3 files changed, 93 insertions(+), 2 deletions(-) diff --git a/internal/entities/recording.go b/internal/entities/recording.go index 19b757a4..f19161c4 100644 --- a/internal/entities/recording.go +++ b/internal/entities/recording.go @@ -43,6 +43,7 @@ type Recording struct { StandardEggMass *float64 `gorm:"-"` StandardEggWeight *float64 `gorm:"-"` StandardFcr *float64 `gorm:"-"` + StandardWeek *int `gorm:"-"` PopulationCanChange *bool `gorm:"-"` TransferExecuted *bool `gorm:"-"` IsTransition *bool `gorm:"-"` diff --git a/internal/modules/production/recordings/dto/recording.dto.go b/internal/modules/production/recordings/dto/recording.dto.go index a4e3ee47..6eb39544 100644 --- a/internal/modules/production/recordings/dto/recording.dto.go +++ b/internal/modules/production/recordings/dto/recording.dto.go @@ -314,9 +314,13 @@ func toRecordingProjectFlockDTO(e entity.Recording) RecordingProjectFlockDTO { result.Period = pfk.Period if pfk.ProjectFlock.ProductionStandard.Id != 0 { + week := recordingWeekValue(e) + if e.StandardWeek != nil && *e.StandardWeek > 0 { + week = *e.StandardWeek + } result.ProductionStandart = &RecordingProductionStandardDTO{ Id: pfk.ProjectFlock.ProductionStandard.Id, - Week: recordingWeekValue(e), + Week: week, Name: pfk.ProjectFlock.ProductionStandard.Name, HenDayStd: floatValue(e.StandardHenDay), HenHouseStd: floatValue(e.StandardHenHouse), diff --git a/internal/utils/recording/recording_helpers.go b/internal/utils/recording/recording_helpers.go index ff95a2f7..be96d12c 100644 --- a/internal/utils/recording/recording_helpers.go +++ b/internal/utils/recording/recording_helpers.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "strings" + "time" commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service" "gitlab.com/mbugroup/lti-api.git/internal/config" @@ -243,6 +244,31 @@ func AttachProductionStandards(ctx context.Context, db *gorm.DB, warnOnly bool, growthDetailByStd[standardID] = growthMap } + // Batch-load laying transfer targets → source PFK chick_in_dates + // untuk menentukan actual chicken week (bukan hardcode LayingWeekStart offset) + type transferChickIn struct { + TargetPFKID uint + ChickInDate time.Time + } + layingPFKIDs := collectLayingPFKIDs(items) + sourceChickInByTarget := make(map[uint]time.Time, len(layingPFKIDs)) + if len(layingPFKIDs) > 0 { + var results []transferChickIn + db.Raw(` + SELECT ltt.target_project_flock_kandang_id AS target_pfk_id, pc.chick_in_date + FROM laying_transfer_targets ltt + JOIN laying_transfer_sources lts ON lts.laying_transfer_id = ltt.laying_transfer_id + JOIN project_chickins pc ON pc.project_flock_kandang_id = lts.source_project_flock_kandang_id + WHERE ltt.target_project_flock_kandang_id IN ? + AND ltt.deleted_at IS NULL + AND lts.deleted_at IS NULL + AND pc.deleted_at IS NULL + `, layingPFKIDs).Scan(&results) + for _, r := range results { + sourceChickInByTarget[r.TargetPFKID] = r.ChickInDate + } + } + for _, item := range items { if item == nil || item.ProjectFlockKandang == nil || item.ProjectFlockKandang.ProjectFlock.Id == 0 { continue @@ -251,7 +277,8 @@ func AttachProductionStandards(ctx context.Context, db *gorm.DB, warnOnly bool, if standardID == 0 { continue } - week := RecordingWeekValue(*item) + week := computeTransferAwareWeek(item, sourceChickInByTarget) + item.StandardWeek = &week cacheKey := standardKey{standardID: standardID, week: week} if cached, ok := cache[cacheKey]; ok { applyProductionStandardValues(item, cached.values, cached.fcr) @@ -291,6 +318,65 @@ func applyProductionStandardValues(item *entity.Recording, values productionStan item.StandardFcr = fcr } +// collectLayingPFKIDs mengumpulkan semua project_flock_kandang_id dari recording laying +func collectLayingPFKIDs(items []*entity.Recording) []uint { + seen := make(map[uint]struct{}) + var ids []uint + for _, item := range items { + if item == nil || item.ProjectFlockKandang == nil { + continue + } + if strings.EqualFold(item.ProjectFlockKandang.ProjectFlock.Category, string(utils.ProjectFlockCategoryLaying)) { + id := item.ProjectFlockKandang.Id + if _, ok := seen[id]; !ok { + seen[id] = struct{}{} + ids = append(ids, id) + } + } + } + return ids +} + +// computeTransferAwareWeek menghitung production standard week untuk recording. +// Laying dengan transfer: actual chicken age dari source PFK chick_in_date. +// Laying cut-over (tanpa transfer): langsung dari recording.day (tanpa offset LayingWeekStart). +// Non-laying: ((day-1)/7) + 1. +func computeTransferAwareWeek(item *entity.Recording, sourceChickInByTarget map[uint]time.Time) int { + day := intValue(item.Day) + if item == nil || item.ProjectFlockKandang == nil { + if day > 0 { + return ((day - 1) / 7) + 1 + } + return 0 + } + + isLaying := strings.EqualFold(item.ProjectFlockKandang.ProjectFlock.Category, string(utils.ProjectFlockCategoryLaying)) + if !isLaying { + if day > 0 { + return ((day - 1) / 7) + 1 + } + return 0 + } + + // Laying recording — cek apakah PFK ini adalah target dari laying transfer + if sourceChickIn, ok := sourceChickInByTarget[item.ProjectFlockKandang.Id]; ok && !sourceChickIn.IsZero() { + // Ada laying transfer: hitung umur aktual dari source PFK chick_in_date + rDate := time.Date(item.RecordDatetime.Year(), item.RecordDatetime.Month(), item.RecordDatetime.Day(), 0, 0, 0, 0, item.RecordDatetime.Location()) + sDate := time.Date(sourceChickIn.Year(), sourceChickIn.Month(), sourceChickIn.Day(), 0, 0, 0, 0, sourceChickIn.Location()) + actualDay := int(rDate.Sub(sDate).Hours() / 24) + if actualDay > 0 { + return ((actualDay - 1) / 7) + 1 + } + return 0 + } + + // Cut-over laying (tanpa transfer): chick_in_date di PFK sudah umur asli DOC + if day > 0 { + return ((day - 1) / 7) + 1 + } + return 0 +} + func RecordingWeekValue(e entity.Recording) int { day := intValue(e.Day) if day <= 0 {