mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-24 15:25:43 +00:00
feat[BE]: update HPP calculations to use totalWeightProduced and totalActualPopulation
This commit is contained in:
@@ -96,7 +96,7 @@ func getFlagLabel(flagType utils.FlagType) string {
|
||||
return "Pembelian " + string(flagType)
|
||||
}
|
||||
|
||||
func buildHppItemsByPurchaseFlags(purchaseItems []entities.PurchaseItem, totalWeightSold, totalPopulation float64) []HppItem {
|
||||
func buildHppItemsByPurchaseFlags(purchaseItems []entities.PurchaseItem, totalWeightProduced, totalPopulation float64) []HppItem {
|
||||
flags := []utils.FlagType{
|
||||
utils.FlagDOC, utils.FlagPullet, utils.FlagLayer, utils.FlagPakan,
|
||||
utils.FlagPreStarter, utils.FlagStarter, utils.FlagFinisher,
|
||||
@@ -125,7 +125,7 @@ func buildHppItemsByPurchaseFlags(purchaseItems []entities.PurchaseItem, totalWe
|
||||
|
||||
if isValid && !seenFlags[flagType] {
|
||||
amount := sumPurchasesByFlag(purchaseItems, flagType)
|
||||
rpPerBird, rpPerKg := calculatePerUnitMetrics(amount, totalPopulation, totalWeightSold)
|
||||
rpPerBird, rpPerKg := calculatePerUnitMetrics(amount, totalPopulation, totalWeightProduced)
|
||||
|
||||
items = append(items, HppItem{
|
||||
Type: getFlagLabel(flagType),
|
||||
@@ -144,14 +144,14 @@ func buildHppItemsByPurchaseFlags(purchaseItems []entities.PurchaseItem, totalWe
|
||||
|
||||
// === HPP BAHAN BAKU (from ProjectBudget + ExpenseRealization) ===
|
||||
|
||||
func ToHppBahanBakuGroup(budgets []entities.ProjectBudget, realizations []entities.ExpenseRealization, totalWeightSold, totalPopulation float64) HppGroup {
|
||||
func ToHppBahanBakuGroup(budgets []entities.ProjectBudget, realizations []entities.ExpenseRealization, totalWeightProduced, totalPopulation float64) HppGroup {
|
||||
items := []HppItem{}
|
||||
|
||||
// Overhead: all budgets vs (all expenses EXCEPT ekspedisi)
|
||||
budgetAmount := sumBudgetsByFilter(budgets, func(*entities.ProjectBudget) bool { return true })
|
||||
realizationAmount := sumRealizationsByFilter(realizations, filterRealizationExceptFlag(utils.FlagEkspedisi))
|
||||
budgetRpPerBird, budgetRpPerKg := calculatePerUnitMetrics(budgetAmount, totalPopulation, totalWeightSold)
|
||||
realizationRpPerBird, realizationRpPerKg := calculatePerUnitMetrics(realizationAmount, totalPopulation, totalWeightSold)
|
||||
budgetRpPerBird, budgetRpPerKg := calculatePerUnitMetrics(budgetAmount, totalPopulation, totalWeightProduced)
|
||||
realizationRpPerBird, realizationRpPerKg := calculatePerUnitMetrics(realizationAmount, totalPopulation, totalWeightProduced)
|
||||
|
||||
if budgetAmount > 0 || realizationAmount > 0 {
|
||||
items = append(items, HppItem{
|
||||
@@ -165,7 +165,7 @@ func ToHppBahanBakuGroup(budgets []entities.ProjectBudget, realizations []entiti
|
||||
|
||||
// Ekspedisi: no budgeting, only expenses WITH flag EKSPEDISI
|
||||
ekspedisiAmount := sumRealizationsByFilter(realizations, filterRealizationByNonstockFlag(utils.FlagEkspedisi))
|
||||
ekspedisiRpPerBird, ekspedisiRpPerKg := calculatePerUnitMetrics(ekspedisiAmount, totalPopulation, totalWeightSold)
|
||||
ekspedisiRpPerBird, ekspedisiRpPerKg := calculatePerUnitMetrics(ekspedisiAmount, totalPopulation, totalWeightProduced)
|
||||
|
||||
if ekspedisiAmount > 0 {
|
||||
items = append(items, HppItem{
|
||||
@@ -185,7 +185,7 @@ func ToHppBahanBakuGroup(budgets []entities.ProjectBudget, realizations []entiti
|
||||
|
||||
// === HPP SUMMARY ===
|
||||
|
||||
func ToSummaryHpp(label string, purchaseItems []entities.PurchaseItem, budgets []entities.ProjectBudget, realizations []entities.ExpenseRealization, totalWeightSold, totalPopulation float64) SummaryHpp {
|
||||
func ToSummaryHpp(label string, purchaseItems []entities.PurchaseItem, budgets []entities.ProjectBudget, realizations []entities.ExpenseRealization, totalWeightProduced, totalPopulation float64) SummaryHpp {
|
||||
// Budget: purchases + budgets
|
||||
purchaseTotal := sumPurchaseTotal(purchaseItems)
|
||||
budgetTotal := sumBudgetsByFilter(budgets, func(*entities.ProjectBudget) bool { return true })
|
||||
@@ -194,8 +194,8 @@ func ToSummaryHpp(label string, purchaseItems []entities.PurchaseItem, budgets [
|
||||
// Realization: all expenses
|
||||
totalRealization := sumRealizationsByFilter(realizations, func(*entities.ExpenseRealization) bool { return true })
|
||||
|
||||
budgetRpPerBird, budgetRpPerKg := calculatePerUnitMetrics(totalBudget, totalPopulation, totalWeightSold)
|
||||
realizationRpPerBird, realizationRpPerKg := calculatePerUnitMetrics(totalRealization, totalPopulation, totalWeightSold)
|
||||
budgetRpPerBird, budgetRpPerKg := calculatePerUnitMetrics(totalBudget, totalPopulation, totalWeightProduced)
|
||||
realizationRpPerBird, realizationRpPerKg := calculatePerUnitMetrics(totalRealization, totalPopulation, totalWeightProduced)
|
||||
|
||||
return SummaryHpp{
|
||||
Label: label,
|
||||
@@ -206,16 +206,16 @@ func ToSummaryHpp(label string, purchaseItems []entities.PurchaseItem, budgets [
|
||||
}
|
||||
}
|
||||
|
||||
func ToHppPurchasesSection(purchaseItems []entities.PurchaseItem, budgets []entities.ProjectBudget, realizations []entities.ExpenseRealization, totalWeightSold, totalPopulation float64) HppPurchasesSection {
|
||||
func ToHppPurchasesSection(purchaseItems []entities.PurchaseItem, budgets []entities.ProjectBudget, realizations []entities.ExpenseRealization, totalWeightProduced, totalPopulation float64) HppPurchasesSection {
|
||||
hppGroups := []HppGroup{
|
||||
{
|
||||
GroupName: "HPP dan Pengeluaran",
|
||||
Data: buildHppItemsByPurchaseFlags(purchaseItems, totalWeightSold, totalPopulation),
|
||||
Data: buildHppItemsByPurchaseFlags(purchaseItems, totalWeightProduced, totalPopulation),
|
||||
},
|
||||
ToHppBahanBakuGroup(budgets, realizations, totalWeightSold, totalPopulation),
|
||||
ToHppBahanBakuGroup(budgets, realizations, totalWeightProduced, totalPopulation),
|
||||
}
|
||||
|
||||
summaryHpp := ToSummaryHpp("HPP", purchaseItems, budgets, realizations, totalWeightSold, totalPopulation)
|
||||
summaryHpp := ToSummaryHpp("HPP", purchaseItems, budgets, realizations, totalWeightProduced, totalPopulation)
|
||||
|
||||
return HppPurchasesSection{
|
||||
Hpp: hppGroups,
|
||||
@@ -266,37 +266,33 @@ func ToPenjualanItems(projectFlockCategory string, deliveryProducts []entities.M
|
||||
return items
|
||||
}
|
||||
|
||||
func ToPembelianItems(purchases []entities.PurchaseItem, totalPopulation, totalWeightSold float64) []PLItem {
|
||||
amount := sumPurchasesByFilter(purchases, func(item *entities.PurchaseItem) bool {
|
||||
if item.Product == nil || len(item.Product.Flags) == 0 {
|
||||
return false
|
||||
}
|
||||
for _, flag := range item.Product.Flags {
|
||||
flagType := strings.ToUpper(flag.Name)
|
||||
if flagType == string(utils.FlagDOC) || flagType == string(utils.FlagOVK) || flagType == string(utils.FlagPakan) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
func ToPembelianItems(purchases []entities.PurchaseItem, budgets []entities.ProjectBudget, realizations []entities.ExpenseRealization, totalPopulation, totalWeightProduced float64) []PLItem {
|
||||
// Calculate total cost using same logic as report penjualan:
|
||||
// Total Cost = All Purchase Items + All BOP Expenses
|
||||
purchaseAmount := sumPurchaseTotal(purchases)
|
||||
|
||||
rpPerBird, rpPerKg := calculatePerUnitMetrics(amount, totalPopulation, totalWeightSold)
|
||||
// Get BOP expenses (all expenses except ekspedisi)
|
||||
bopAmount := sumRealizationsByFilter(realizations, filterRealizationExceptFlag(utils.FlagEkspedisi))
|
||||
|
||||
totalCost := purchaseAmount + bopAmount
|
||||
|
||||
rpPerBird, rpPerKg := calculatePerUnitMetrics(totalCost, totalPopulation, totalWeightProduced)
|
||||
return []PLItem{
|
||||
ToPLItem("Pembelian Sapronak Supplier", ToFinancialMetrics(rpPerBird, rpPerKg, amount)),
|
||||
ToPLItem("Harga Pokok Penjualan (HPP)", ToFinancialMetrics(rpPerBird, rpPerKg, totalCost)),
|
||||
}
|
||||
}
|
||||
|
||||
func ToOverheadItems(budgets []entities.ProjectBudget, realizations []entities.ExpenseRealization, totalPopulation, totalWeightSold float64) []PLItem {
|
||||
func ToOverheadItems(budgets []entities.ProjectBudget, realizations []entities.ExpenseRealization, totalPopulation, totalWeightProduced float64) []PLItem {
|
||||
realizationAmount := sumRealizationsByFilter(realizations, filterRealizationExceptFlag(utils.FlagEkspedisi))
|
||||
rpPerBird, rpPerKg := calculatePerUnitMetrics(realizationAmount, totalPopulation, totalWeightSold)
|
||||
rpPerBird, rpPerKg := calculatePerUnitMetrics(realizationAmount, totalPopulation, totalWeightProduced)
|
||||
return []PLItem{
|
||||
ToPLItem("Pengeluaran Overhead", ToFinancialMetrics(rpPerBird, rpPerKg, realizationAmount)),
|
||||
}
|
||||
}
|
||||
|
||||
func ToEkspedisiItems(realizations []entities.ExpenseRealization, totalPopulation, totalWeightSold float64) []PLItem {
|
||||
func ToEkspedisiItems(realizations []entities.ExpenseRealization, totalPopulation, totalWeightProduced float64) []PLItem {
|
||||
amount := sumRealizationsByFilter(realizations, filterRealizationByNonstockFlag(utils.FlagEkspedisi))
|
||||
rpPerBird, rpPerKg := calculatePerUnitMetrics(amount, totalPopulation, totalWeightSold)
|
||||
rpPerBird, rpPerKg := calculatePerUnitMetrics(amount, totalPopulation, totalWeightProduced)
|
||||
return []PLItem{
|
||||
ToPLItem("Beban Ekspedisi", ToFinancialMetrics(rpPerBird, rpPerKg, amount)),
|
||||
}
|
||||
@@ -348,7 +344,7 @@ func ToReportResponse(hppPurchases HppPurchasesSection, profitLoss ProfitLossSec
|
||||
|
||||
// === MAIN BUILDER ===
|
||||
|
||||
func ToClosingKeuanganReport(projectFlockCategory string, purchaseItems []entities.PurchaseItem, budgets []entities.ProjectBudget, realizations []entities.ExpenseRealization, deliveryProducts []entities.MarketingDeliveryProduct, chickins []entities.ProjectChickin) ReportResponse {
|
||||
func ToClosingKeuanganReport(projectFlockCategory string, purchaseItems []entities.PurchaseItem, budgets []entities.ProjectBudget, realizations []entities.ExpenseRealization, deliveryProducts []entities.MarketingDeliveryProduct, chickins []entities.ProjectChickin, totalWeightProduced float64) ReportResponse {
|
||||
var totalPopulation float64
|
||||
var totalWeightSold float64
|
||||
|
||||
@@ -360,12 +356,13 @@ func ToClosingKeuanganReport(projectFlockCategory string, purchaseItems []entiti
|
||||
totalWeightSold += delivery.TotalWeight
|
||||
}
|
||||
|
||||
hppSection := ToHppPurchasesSection(purchaseItems, budgets, realizations, totalWeightSold, totalPopulation)
|
||||
// Use totalWeightProduced for HPP calculation (not totalWeightSold)
|
||||
hppSection := ToHppPurchasesSection(purchaseItems, budgets, realizations, totalWeightProduced, totalPopulation)
|
||||
|
||||
penjualanItems := ToPenjualanItems(projectFlockCategory, deliveryProducts, totalPopulation, totalWeightSold)
|
||||
pembelianItems := ToPembelianItems(purchaseItems, totalPopulation, totalWeightSold)
|
||||
overheadItems := ToOverheadItems(budgets, realizations, totalPopulation, totalWeightSold)
|
||||
ekspedisiItems := ToEkspedisiItems(realizations, totalPopulation, totalWeightSold)
|
||||
pembelianItems := ToPembelianItems(purchaseItems, budgets, realizations, totalPopulation, totalWeightProduced)
|
||||
overheadItems := ToOverheadItems(budgets, realizations, totalPopulation, totalWeightProduced)
|
||||
ekspedisiItems := ToEkspedisiItems(realizations, totalPopulation, totalWeightProduced)
|
||||
plSection := ToProfitLossSection(penjualanItems, pembelianItems, overheadItems, ekspedisiItems)
|
||||
|
||||
return ToReportResponse(hppSection, plSection)
|
||||
|
||||
@@ -69,7 +69,7 @@ func ToOverheadDTO(budget *entity.ProjectBudget, realization *entity.ExpenseReal
|
||||
return dto
|
||||
}
|
||||
|
||||
func ToOverheadListDTOs(budgets []entity.ProjectBudget, realizations []entity.ExpenseRealization, totalChickinQty float64) OverheadListDTO {
|
||||
func ToOverheadListDTOs(budgets []entity.ProjectBudget, realizations []entity.ExpenseRealization, totalChickinQty, totalActualPopulation float64) OverheadListDTO {
|
||||
overheadsByNonstockID := make(map[uint]*OverheadDTO)
|
||||
latestDateByNonstockID := make(map[uint]string)
|
||||
|
||||
@@ -119,7 +119,8 @@ func ToOverheadListDTOs(budgets []entity.ProjectBudget, realizations []entity.Ex
|
||||
|
||||
for nonstockID, overhead := range overheadsByNonstockID {
|
||||
overhead.ActualDate = latestDateByNonstockID[nonstockID]
|
||||
overhead.CostPerBird = calculateCostPerBird(overhead.ActualTotalAmount, totalChickinQty)
|
||||
|
||||
overhead.CostPerBird = calculateCostPerBird(overhead.ActualTotalAmount, totalActualPopulation)
|
||||
|
||||
if overhead.ActualQuantity > 0 {
|
||||
overhead.ActualUnitPrice = overhead.ActualTotalAmount / overhead.ActualQuantity
|
||||
@@ -139,7 +140,7 @@ func ToOverheadListDTOs(budgets []entity.ProjectBudget, realizations []entity.Ex
|
||||
BudgetTotalAmount: totalBudgetAmount,
|
||||
ActualQuantity: totalActualQuantity,
|
||||
ActualTotalAmount: totalActualAmount,
|
||||
CostPerBird: calculateCostPerBird(totalActualAmount, totalChickinQty),
|
||||
CostPerBird: calculateCostPerBird(totalActualAmount, totalActualPopulation),
|
||||
},
|
||||
Overheads: overheadItems,
|
||||
}
|
||||
@@ -158,9 +159,9 @@ func calculateTotal(qty, price float64) float64 {
|
||||
return qty * price
|
||||
}
|
||||
|
||||
func calculateCostPerBird(totalPrice, totalChickinQty float64) float64 {
|
||||
if totalChickinQty > 0 {
|
||||
return totalPrice / totalChickinQty
|
||||
func calculateCostPerBird(totalPrice, totalActualPopulation float64) float64 {
|
||||
if totalActualPopulation > 0 {
|
||||
return totalPrice / totalActualPopulation
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user