adjust calculate for week at recording list

This commit is contained in:
giovanni
2026-05-07 21:09:10 +07:00
parent 06070871c7
commit aa5d4ab818
3 changed files with 93 additions and 2 deletions
+87 -1
View File
@@ -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 {