mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-06-09 15:07:49 +00:00
add command for normalize data recording population not match; adjust closing overhead and keuangan
This commit is contained in:
@@ -789,11 +789,56 @@ func (s closingService) GetOverhead(c *fiber.Ctx, projectFlockID uint, projectFl
|
||||
|
||||
totalActualPopulation := totalChickinQty - totalDepletion
|
||||
|
||||
// Prefer recording-based population (recordings.total_chick_qty) so closing stays
|
||||
// consistent with normalized cut-over flocks. For normal flocks this equals
|
||||
// chickin - depletion (no-op); it only differs when the recording population was
|
||||
// normalized separately from recording_depletions. Falls back if any kandang in
|
||||
// scope lacks a recording.
|
||||
scopeKandangs := projectFlockKandangs
|
||||
if projectFlockKandangID != nil {
|
||||
scopeKandangs = nil
|
||||
for _, k := range projectFlockKandangs {
|
||||
if k.Id == *projectFlockKandangID {
|
||||
scopeKandangs = append(scopeKandangs, k)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if recPop, ok := s.actualPopulationFromRecordings(c.Context(), scopeKandangs); ok {
|
||||
totalActualPopulation = recPop
|
||||
}
|
||||
|
||||
result := dto.ToOverheadListDTOs(budgets, realizations, totalChickinQty, totalActualPopulation, projectFlockKandangID != nil, totalKandangCount)
|
||||
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// actualPopulationFromRecordings sums the latest recordings.total_chick_qty across the
|
||||
// given kandangs (the production population source of truth). Returns ok=false if any
|
||||
// kandang lacks a recording, so the caller falls back to chickin-minus-depletion.
|
||||
// For normal flocks this equals chickin - depletion; it only differs for cut-over flocks
|
||||
// whose recording population was normalized separately from recording_depletions.
|
||||
func (s closingService) actualPopulationFromRecordings(ctx context.Context, kandangs []entity.ProjectFlockKandang) (float64, bool) {
|
||||
if s.RecordingRepo == nil || len(kandangs) == 0 {
|
||||
return 0, false
|
||||
}
|
||||
total := 0.0
|
||||
for _, k := range kandangs {
|
||||
latest, err := s.RecordingRepo.GetLatestByProjectFlockKandangID(ctx, k.Id)
|
||||
if err != nil {
|
||||
s.Log.Warnf("actualPopulationFromRecordings: latest recording pfk=%d: %v", k.Id, err)
|
||||
return 0, false
|
||||
}
|
||||
if latest == nil || latest.TotalChickQty == nil {
|
||||
return 0, false
|
||||
}
|
||||
if *latest.TotalChickQty > 0 {
|
||||
total += *latest.TotalChickQty
|
||||
}
|
||||
}
|
||||
return total, true
|
||||
}
|
||||
|
||||
type activeKandangMetricRow struct {
|
||||
ProjectFlockKandangID uint `gorm:"column:project_flock_kandang_id"`
|
||||
ProjectFlockID uint `gorm:"column:project_flock_id"`
|
||||
|
||||
@@ -156,7 +156,7 @@ func (s closingKeuanganService) calculateClosingKeuangan(c *fiber.Ctx, projectFl
|
||||
|
||||
hppSection := s.buildHPPSection(c, projectFlock, projectFlockKandangs, costs, productionData)
|
||||
|
||||
profitLossSection := s.buildProfitLossSection(projectFlock, costs, productionData)
|
||||
profitLossSection := s.buildProfitLossSection(c, projectFlock, projectFlockKandangs, costs, productionData)
|
||||
|
||||
data := dto.ToClosingKeuanganData(hppSection, profitLossSection)
|
||||
return &data, nil
|
||||
@@ -386,7 +386,7 @@ func (s closingKeuanganService) buildHPPSection(c *fiber.Ctx, projectFlock *enti
|
||||
return dto.ToHPPSection(hppItems, hppSummary)
|
||||
}
|
||||
|
||||
func (s closingKeuanganService) buildProfitLossSection(projectFlock *entity.ProjectFlock, costs *CostData, production *ProductionData) dto.ProfitLossSection {
|
||||
func (s closingKeuanganService) buildProfitLossSection(c *fiber.Ctx, projectFlock *entity.ProjectFlock, projectFlockKandangs []entity.ProjectFlockKandang, costs *CostData, production *ProductionData) dto.ProfitLossSection {
|
||||
|
||||
totalWeightProduced := production.TotalWeightProduced
|
||||
totalEggWeightKg := production.TotalEggWeightKg
|
||||
@@ -394,6 +394,11 @@ func (s closingKeuanganService) buildProfitLossSection(projectFlock *entity.Proj
|
||||
totalWeightSold := production.TotalWeightSold
|
||||
totalBirdSold := production.TotalBirdSold
|
||||
actualPopulation := production.TotalPopulationIn - production.TotalDepletion
|
||||
// Prefer recording-based population (consistent with buildHPPSection) so per-ekor
|
||||
// P&L matches the normalized recording population for cut-over flocks.
|
||||
if lastPopulation, ok := s.getLastPopulationFromRecordings(c, projectFlockKandangs); ok {
|
||||
actualPopulation = lastPopulation
|
||||
}
|
||||
|
||||
isLaying := projectFlock.Category == string(utils.ProjectFlockCategoryLaying)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user