mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-06-09 15:07:49 +00:00
initial refactori trasnfer to laying, and depretitation to 25 week
This commit is contained in:
@@ -1191,26 +1191,72 @@ func (s *hppV2Service) getDepreciationComponent(
|
||||
}, nil
|
||||
}
|
||||
|
||||
if totalPulletCost <= 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
transferInput, err := s.hppRepo.GetLatestTransferInputByProjectFlockKandangID(context.Background(), projectFlockKandangId, periodDate)
|
||||
// Multi-source support: 1 target kandang bisa menerima dari MULTIPLE transfer terpisah
|
||||
// (tiap transfer = 1 source kandang). Depresiasi per target = SUM dari per-transfer depresiasi.
|
||||
// Setiap transfer dihitung dengan chick_in_date source-nya sendiri dan cost basis pro-rated
|
||||
// berdasarkan qty share (transfer.qty / totalTransferQty).
|
||||
transferInputs, err := s.hppRepo.GetAllTransferInputsByProjectFlockKandangID(context.Background(), projectFlockKandangId, periodDate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var part *HppV2ComponentPart
|
||||
if transferInput != nil && transferInput.SourceProjectFlockID > 0 {
|
||||
part, err = s.buildNormalTransferDepreciationPart(contextRow, transferInput, periodDate, totalPulletCost)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// Filter valid transfers (punya source flock id)
|
||||
validTransfers := make([]commonRepo.HppV2LatestTransferInputRow, 0, len(transferInputs))
|
||||
totalTransferQty := 0.0
|
||||
for _, t := range transferInputs {
|
||||
if t.SourceProjectFlockID == 0 {
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
part, err = s.buildManualCutoverDepreciationPart(projectFlockKandangId, contextRow, periodDate, totalPulletCost)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
validTransfers = append(validTransfers, t)
|
||||
totalTransferQty += t.TransferQty
|
||||
}
|
||||
|
||||
if len(validTransfers) > 0 {
|
||||
if totalPulletCost <= 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
totalDepreciation := 0.0
|
||||
parts := make([]HppV2ComponentPart, 0, len(validTransfers))
|
||||
for i := range validTransfers {
|
||||
t := validTransfers[i]
|
||||
// Pro-rate cost basis per transfer berdasarkan qty share.
|
||||
// CATATAN: pendekatan ini AKURAT kalau cost per ekor sama antar source flock.
|
||||
// Kalau cost per ekor berbeda signifikan antar source, follow-up: refactor
|
||||
// `buildGrowingUsagePart` untuk multi-source-flock cost computation.
|
||||
transferCostBasis := totalPulletCost
|
||||
if totalTransferQty > 0 && len(validTransfers) > 1 {
|
||||
transferCostBasis = totalPulletCost * (t.TransferQty / totalTransferQty)
|
||||
}
|
||||
|
||||
part, partErr := s.buildNormalTransferDepreciationPart(contextRow, &t, periodDate, transferCostBasis)
|
||||
if partErr != nil {
|
||||
return nil, partErr
|
||||
}
|
||||
if part == nil {
|
||||
continue
|
||||
}
|
||||
totalDepreciation += part.Total
|
||||
parts = append(parts, *part)
|
||||
}
|
||||
|
||||
if len(parts) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return &HppV2Component{
|
||||
Code: hppV2ComponentDepreciation,
|
||||
Title: "Depreciation",
|
||||
Scopes: []string{hppV2ScopeProductionCost},
|
||||
Total: totalDepreciation,
|
||||
Parts: parts,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Fallback: manual cut-over (kandang tanpa transfer record)
|
||||
part, err := s.buildManualCutoverDepreciationPart(projectFlockKandangId, contextRow, periodDate, totalPulletCost)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if part == nil {
|
||||
return nil, nil
|
||||
@@ -1344,20 +1390,22 @@ func (s *hppV2Service) buildNormalTransferDepreciationPart(
|
||||
}
|
||||
|
||||
houseType := NormalizeDepreciationHouseType(contextRow.HouseType)
|
||||
percentByHouseType, err := s.hppRepo.GetDepreciationPercents(context.Background(), []string{houseType}, scheduleDay)
|
||||
multiplicationByHouseType, err := s.hppRepo.GetMultiplicationPercentages(context.Background(), []string{houseType}, scheduleDay)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pulletCostDayN, depreciationValue, depreciationPercent := CalculateDepreciationAtDayN(
|
||||
pulletCostDayN, depreciationValue, multiplicationPercentage := CalculateDepreciationAtDayN(
|
||||
totalPulletCost,
|
||||
scheduleDay,
|
||||
contextRow.HouseType,
|
||||
percentByHouseType,
|
||||
multiplicationByHouseType,
|
||||
)
|
||||
if depreciationValue <= 0 {
|
||||
if depreciationValue <= 0 && pulletCostDayN <= 0 {
|
||||
return nil, nil
|
||||
}
|
||||
totalValueAfter := pulletCostDayN * multiplicationPercentage
|
||||
depreciationPercent := (1.0 - multiplicationPercentage) * 100.0
|
||||
|
||||
return &HppV2ComponentPart{
|
||||
Code: hppV2PartDepreciationNormal,
|
||||
@@ -1365,13 +1413,15 @@ func (s *hppV2Service) buildNormalTransferDepreciationPart(
|
||||
Scopes: []string{hppV2ScopeProductionCost},
|
||||
Total: depreciationValue,
|
||||
Details: map[string]any{
|
||||
"basis_total": totalPulletCost,
|
||||
"pullet_cost_day_n": pulletCostDayN,
|
||||
"depreciation_percent": depreciationPercent,
|
||||
"schedule_day": scheduleDay,
|
||||
"origin_date": formatDateOnly(*originDate),
|
||||
"transfer_date": formatDateOnly(transferInput.TransferDate),
|
||||
"source_project_flock_id": transferInput.SourceProjectFlockID,
|
||||
"basis_total": totalPulletCost,
|
||||
"pullet_cost_day_n": pulletCostDayN,
|
||||
"multiplication_percentage": multiplicationPercentage,
|
||||
"total_value_pullet_after_depreciation": totalValueAfter,
|
||||
"depreciation_percent": depreciationPercent,
|
||||
"schedule_day": scheduleDay,
|
||||
"origin_date": formatDateOnly(*originDate),
|
||||
"transfer_date": formatDateOnly(transferInput.TransferDate),
|
||||
"source_project_flock_id": transferInput.SourceProjectFlockID,
|
||||
},
|
||||
References: []HppV2Reference{
|
||||
{
|
||||
@@ -1392,7 +1442,7 @@ func (s *hppV2Service) buildManualCutoverDepreciationPart(
|
||||
periodDate time.Time,
|
||||
totalPulletCost float64,
|
||||
) (*HppV2ComponentPart, error) {
|
||||
if contextRow == nil || totalPulletCost <= 0 {
|
||||
if contextRow == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -1407,6 +1457,21 @@ func (s *hppV2Service) buildManualCutoverDepreciationPart(
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
populations, err := s.hppRepo.GetChickinPopulationByPFKForFarm(context.Background(), contextRow.ProjectFlockID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var totalPopulation float64
|
||||
for _, qty := range populations {
|
||||
totalPopulation += qty
|
||||
}
|
||||
kandangPopulation := populations[projectFlockKandangId]
|
||||
if totalPopulation <= 0 || kandangPopulation <= 0 {
|
||||
return nil, nil
|
||||
}
|
||||
populationShare := kandangPopulation / totalPopulation
|
||||
basis := manualInput.TotalCost * populationShare
|
||||
|
||||
originDate, err := s.hppRepo.GetEarliestChickInDateByProjectFlockID(context.Background(), contextRow.ProjectFlockID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1427,21 +1492,24 @@ func (s *hppV2Service) buildManualCutoverDepreciationPart(
|
||||
}
|
||||
|
||||
houseType := NormalizeDepreciationHouseType(contextRow.HouseType)
|
||||
percentByHouseType, err := s.hppRepo.GetDepreciationPercents(context.Background(), []string{houseType}, reportScheduleDay)
|
||||
multiplicationByHouseType, err := s.hppRepo.GetMultiplicationPercentages(context.Background(), []string{houseType}, reportScheduleDay)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pulletCostDayN, depreciationValue, depreciationPercent := CalculateDepreciationFromDayRange(
|
||||
totalPulletCost,
|
||||
pulletCostDayN, depreciationValue, multiplicationPercentage := CalculateDepreciationFromDayRange(
|
||||
basis,
|
||||
startDay,
|
||||
reportScheduleDay,
|
||||
contextRow.HouseType,
|
||||
percentByHouseType,
|
||||
multiplicationByHouseType,
|
||||
)
|
||||
if depreciationValue <= 0 {
|
||||
if depreciationValue <= 0 && pulletCostDayN <= 0 {
|
||||
return nil, nil
|
||||
}
|
||||
totalValueAfter := pulletCostDayN * multiplicationPercentage
|
||||
depreciationPercent := (1.0 - multiplicationPercentage) * 100.0
|
||||
_ = totalPulletCost
|
||||
|
||||
return &HppV2ComponentPart{
|
||||
Code: hppV2PartDepreciationCutover,
|
||||
@@ -1449,15 +1517,19 @@ func (s *hppV2Service) buildManualCutoverDepreciationPart(
|
||||
Scopes: []string{hppV2ScopeProductionCost},
|
||||
Total: depreciationValue,
|
||||
Details: map[string]any{
|
||||
"basis_total": totalPulletCost,
|
||||
"pullet_cost_day_n": pulletCostDayN,
|
||||
"depreciation_percent": depreciationPercent,
|
||||
"schedule_day": reportScheduleDay,
|
||||
"start_schedule_day": startDay,
|
||||
"origin_date": formatDateOnly(*originDate),
|
||||
"cutover_date": formatDateOnly(manualInput.CutoverDate),
|
||||
"manual_input_id": manualInput.ID,
|
||||
"project_flock_kandang": projectFlockKandangId,
|
||||
"basis_total": basis,
|
||||
"manual_input_total": manualInput.TotalCost,
|
||||
"population_share": populationShare,
|
||||
"pullet_cost_day_n": pulletCostDayN,
|
||||
"multiplication_percentage": multiplicationPercentage,
|
||||
"total_value_pullet_after_depreciation": totalValueAfter,
|
||||
"depreciation_percent": depreciationPercent,
|
||||
"schedule_day": reportScheduleDay,
|
||||
"start_schedule_day": startDay,
|
||||
"origin_date": formatDateOnly(*originDate),
|
||||
"cutover_date": formatDateOnly(manualInput.CutoverDate),
|
||||
"manual_input_id": manualInput.ID,
|
||||
"project_flock_kandang": projectFlockKandangId,
|
||||
},
|
||||
References: []HppV2Reference{
|
||||
{
|
||||
@@ -1465,7 +1537,7 @@ func (s *hppV2Service) buildManualCutoverDepreciationPart(
|
||||
ID: manualInput.ID,
|
||||
Date: formatDateOnly(manualInput.CutoverDate),
|
||||
Qty: 1,
|
||||
Total: totalPulletCost,
|
||||
Total: manualInput.TotalCost,
|
||||
AppliedTotal: depreciationValue,
|
||||
},
|
||||
},
|
||||
@@ -1724,7 +1796,7 @@ func partHasScope(part *HppV2ComponentPart, scope string) bool {
|
||||
}
|
||||
|
||||
func dateOnly(value time.Time) time.Time {
|
||||
return time.Date(value.Year(), value.Month(), value.Day(), 0, 0, 0, 0, value.Location())
|
||||
return time.Date(value.Year(), value.Month(), value.Day(), 0, 0, 0, 0, time.UTC)
|
||||
}
|
||||
|
||||
func formatDateOnly(value time.Time) string {
|
||||
|
||||
Reference in New Issue
Block a user