FEAT[BE] :enhance production data calculations by adding TotalBirdSold and refining profit/loss metrics

This commit is contained in:
aguhh18
2026-02-02 15:36:06 +07:00
parent 5b80081d05
commit ce108da847
@@ -41,6 +41,7 @@ type ProductionData struct {
TotalWeightProduced float64 TotalWeightProduced float64
TotalEggWeightKg float64 TotalEggWeightKg float64
TotalWeightSold float64 TotalWeightSold float64
TotalBirdSold float64
TotalSalesAmount float64 TotalSalesAmount float64
} }
@@ -283,6 +284,7 @@ func (s closingKeuanganService) calculateProductionData(c *fiber.Ctx, projectFlo
continue continue
} }
data.TotalWeightSold += delivery.TotalWeight data.TotalWeightSold += delivery.TotalWeight
data.TotalBirdSold += delivery.UsageQty
data.TotalSalesAmount += delivery.TotalPrice data.TotalSalesAmount += delivery.TotalPrice
} }
@@ -383,46 +385,77 @@ func (s closingKeuanganService) buildHPPSection(c *fiber.Ctx, projectFlock *enti
func (s closingKeuanganService) buildProfitLossSection(projectFlock *entity.ProjectFlock, costs *CostData, production *ProductionData) dto.ProfitLossSection { func (s closingKeuanganService) buildProfitLossSection(projectFlock *entity.ProjectFlock, costs *CostData, production *ProductionData) dto.ProfitLossSection {
totalPopulationIn := production.TotalPopulationIn
totalWeightProduced := production.TotalWeightProduced totalWeightProduced := production.TotalWeightProduced
totalEggWeightKg := production.TotalEggWeightKg totalEggWeightKg := production.TotalEggWeightKg
totalSalesAmount := production.TotalSalesAmount totalSalesAmount := production.TotalSalesAmount
totalWeightSold := production.TotalWeightSold totalWeightSold := production.TotalWeightSold
totalBirdSold := production.TotalBirdSold
actualPopulation := production.TotalPopulationIn - production.TotalDepletion
weightForSales := totalWeightSold isLaying := projectFlock.Category == string(utils.ProjectFlockCategoryLaying)
weightForCalculation := totalWeightProduced
if projectFlock.Category == string(utils.ProjectFlockCategoryLaying) {
weightForSales = totalWeightSold
weightForCalculation = totalEggWeightKg
}
calculateProfitLossMetrics := func(amount float64) (rpPerBird, rpPerKg float64) { // Fungsi untuk sales: LAYING = populasi aktual, GROWING = ekor terjual
if totalPopulationIn > 0 { calculateSalesMetrics := func(amount float64) (rpPerBird, rpPerKg float64) {
rpPerBird = amount / totalPopulationIn if isLaying {
} if actualPopulation > 0 {
if weightForSales > 0 { rpPerBird = amount / actualPopulation
rpPerKg = amount / weightForSales }
if totalWeightSold > 0 {
rpPerKg = amount / totalWeightSold
}
} else {
if totalBirdSold > 0 {
rpPerBird = amount / totalBirdSold
}
if totalWeightSold > 0 {
rpPerKg = amount / totalWeightSold
}
} }
return return
} }
actualPopulation := production.TotalPopulationIn - production.TotalDepletion // Fungsi untuk cost: per ekor = populasi aktual, per kg = LAYING telur produksi / GROWING ayam produksi
calculateCostMetrics := func(amount float64) (rpPerBird, rpPerKg float64) {
calculateMetrics := func(amount float64) (rpPerBird, rpPerKg float64) {
if actualPopulation > 0 { if actualPopulation > 0 {
rpPerBird = amount / actualPopulation rpPerBird = amount / actualPopulation
} }
if weightForCalculation > 0 { if isLaying {
rpPerKg = amount / weightForCalculation if totalEggWeightKg > 0 {
rpPerKg = amount / totalEggWeightKg
}
} else {
if totalWeightProduced > 0 {
rpPerKg = amount / totalWeightProduced
}
}
return
}
// Fungsi untuk overhead/ekspedisi: LAYING = populasi aktual, GROWING = ekor terjual
calculateOverheadMetrics := func(amount float64) (rpPerBird, rpPerKg float64) {
if isLaying {
if actualPopulation > 0 {
rpPerBird = amount / actualPopulation
}
if totalWeightSold > 0 {
rpPerKg = amount / totalWeightSold
}
} else {
if totalBirdSold > 0 {
rpPerBird = amount / totalBirdSold
}
if totalWeightSold > 0 {
rpPerKg = amount / totalWeightSold
}
} }
return return
} }
plItems := []dto.ProfitLossItem{} plItems := []dto.ProfitLossItem{}
salesRpPerBird, salesRpPerKg := calculateProfitLossMetrics(totalSalesAmount) salesRpPerBird, salesRpPerKg := calculateSalesMetrics(totalSalesAmount)
salesLabel := "Penjualan Ayam" salesLabel := "Penjualan Ayam"
if projectFlock.Category == string(utils.ProjectFlockCategoryLaying) { if isLaying {
salesLabel = "Penjualan Telur" salesLabel = "Penjualan Telur"
} }
plItems = append(plItems, dto.ToProfitLossItem( plItems = append(plItems, dto.ToProfitLossItem(
@@ -435,23 +468,23 @@ func (s closingKeuanganService) buildProfitLossSection(projectFlock *entity.Proj
)) ))
totalSapronakAmount := costs.ChickenCost + costs.FeedCost + costs.OvkCost totalSapronakAmount := costs.ChickenCost + costs.FeedCost + costs.OvkCost
_, sapronakRpPerKg := calculateMetrics(totalSapronakAmount)
sapronakRpPerBird := 0.0 sapronakRpPerBird := 0.0
sapronakRpPerKg := 0.0
for _, amount := range []float64{costs.ChickenCost, costs.FeedCost, costs.OvkCost} { for _, amount := range []float64{costs.ChickenCost, costs.FeedCost, costs.OvkCost} {
rpPerBird, _ := calculateMetrics(amount) rpPerBird, rpPerKg := calculateCostMetrics(amount)
sapronakRpPerBird += rpPerBird sapronakRpPerBird += rpPerBird
sapronakRpPerKg += rpPerKg
} }
sapronakLabel := "Pengeluaran Sapronak"
plItems = append(plItems, dto.ToProfitLossItem( plItems = append(plItems, dto.ToProfitLossItem(
string(dto.PLCodeSapronak), string(dto.PLCodeSapronak),
sapronakLabel, "Pengeluaran Sapronak",
"purchase", "purchase",
sapronakRpPerBird, sapronakRpPerBird,
sapronakRpPerKg, sapronakRpPerKg,
totalSapronakAmount, totalSapronakAmount,
)) ))
overheadRpPerBird, overheadRpPerKg := calculateProfitLossMetrics(costs.RealizationOperational) overheadRpPerBird, overheadRpPerKg := calculateOverheadMetrics(costs.RealizationOperational)
plItems = append(plItems, dto.ToProfitLossItem( plItems = append(plItems, dto.ToProfitLossItem(
string(dto.PLCodeOverhead), string(dto.PLCodeOverhead),
"Overhead", "Overhead",
@@ -461,7 +494,7 @@ func (s closingKeuanganService) buildProfitLossSection(projectFlock *entity.Proj
costs.RealizationOperational, costs.RealizationOperational,
)) ))
ekspedisiRpPerBird, ekspedisiRpPerKg := calculateProfitLossMetrics(costs.ExpeditionCost) ekspedisiRpPerBird, ekspedisiRpPerKg := calculateOverheadMetrics(costs.ExpeditionCost)
plItems = append(plItems, dto.ToProfitLossItem( plItems = append(plItems, dto.ToProfitLossItem(
string(dto.PLCodeEkspedisi), string(dto.PLCodeEkspedisi),
"Ekspedisi", "Ekspedisi",