mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
569 lines
18 KiB
Go
569 lines
18 KiB
Go
package dto
|
|
|
|
import (
|
|
"slices"
|
|
"strings"
|
|
|
|
"gitlab.com/mbugroup/lti-api.git/internal/entities"
|
|
"gitlab.com/mbugroup/lti-api.git/internal/utils"
|
|
)
|
|
|
|
// === CONSTANTS ===
|
|
const (
|
|
HPPGroupPengeluaran = "HPP dan Pengeluaran"
|
|
HPPGroupBahanBaku = "HPP dan Bahan Baku"
|
|
HPPLabelOverhead = "Pengeluaran Overhead"
|
|
HPPLabelEkspedisi = "Beban Ekspedisi"
|
|
HPPSummaryLabel = "HPP"
|
|
|
|
PLSalesTypeChicken = "Penjualan Ayam Besar"
|
|
PLSalesTypeEgg = "Penjualan Telur"
|
|
|
|
PLItemTypeSapronak = "Pembelian Sapronak"
|
|
PLItemTypeOverhead = "Pengeluaran Overhead"
|
|
PLItemTypeEkspedisi = "Beban Ekspedisi"
|
|
|
|
PLSummaryLabelGrossProfit = "LABA RUGI BRUTTO"
|
|
PLSummaryLabelSubTotal = "SUB TOTAL"
|
|
PLSummaryLabelNetProfit = "LABA RUGI NETTO"
|
|
|
|
PurchaseLabelPrefix = "Pembelian "
|
|
)
|
|
|
|
// === CONTEXT STRUCTS ===
|
|
|
|
type CalculationContext struct {
|
|
TotalPopulation float64
|
|
TotalWeightProduced float64
|
|
TotalDepletion float64
|
|
TotalWeightSold float64
|
|
ActualPopulation float64
|
|
}
|
|
|
|
type ClosingKeuanganInput struct {
|
|
ProjectFlockCategory string
|
|
PurchaseItems []entities.PurchaseItem
|
|
Budgets []entities.ProjectBudget
|
|
Realizations []entities.ExpenseRealization
|
|
DeliveryProducts []entities.MarketingDeliveryProduct
|
|
Chickins []entities.ProjectChickin
|
|
TotalWeightProduced float64
|
|
TotalDepletion float64
|
|
}
|
|
|
|
// === BASE METRICS ===
|
|
|
|
type FinancialMetrics struct {
|
|
RpPerBird float64 `json:"rp_per_bird"`
|
|
RpPerKg float64 `json:"rp_per_kg"`
|
|
Amount float64 `json:"amount"`
|
|
}
|
|
|
|
type Comparison struct {
|
|
Budgeting FinancialMetrics `json:"budgeting"`
|
|
Realization FinancialMetrics `json:"realization"`
|
|
}
|
|
|
|
// === HPP PURCHASES PACKAGE ===
|
|
|
|
type HppItem struct {
|
|
Type string `json:"type"`
|
|
Comparison
|
|
}
|
|
|
|
type HppGroup struct {
|
|
GroupName string `json:"group_name"`
|
|
Data []HppItem `json:"data"`
|
|
}
|
|
|
|
type SummaryHpp struct {
|
|
Label string `json:"label"`
|
|
Comparison
|
|
}
|
|
|
|
type HppPurchasesSection struct {
|
|
Hpp []HppGroup `json:"hpp"`
|
|
SummaryHpp SummaryHpp `json:"summary_hpp"`
|
|
}
|
|
|
|
// === PROFIT LOSS PACKAGE ===
|
|
|
|
type PLItem struct {
|
|
Type string `json:"type"`
|
|
FinancialMetrics
|
|
}
|
|
|
|
type PLSummaryItem struct {
|
|
Label string `json:"label"`
|
|
FinancialMetrics
|
|
}
|
|
|
|
type PLSummaryGroup struct {
|
|
GrossProfit PLSummaryItem `json:"gross_profit"`
|
|
SubTotal PLSummaryItem `json:"sub_total"`
|
|
NetProfit PLSummaryItem `json:"net_profit"`
|
|
}
|
|
|
|
type ProfitLossData struct {
|
|
Penjualan []PLItem `json:"penjualan"`
|
|
Pembelian []PLItem `json:"pembelian"`
|
|
Overhead PLItem `json:"overhead"`
|
|
Ekspedisi PLItem `json:"ekspedisi"`
|
|
Summary PLSummaryGroup `json:"summary"`
|
|
}
|
|
|
|
type ProfitLossSection struct {
|
|
Data ProfitLossData `json:"data"`
|
|
}
|
|
|
|
// === RESPONSE DTO (ROOT) ===
|
|
|
|
type ReportResponse struct {
|
|
HppPurchases HppPurchasesSection `json:"hpp_purchases"`
|
|
ProfitLoss ProfitLossSection `json:"profit_loss"`
|
|
}
|
|
|
|
// === MAPPER FUNCTIONS ===
|
|
|
|
func ToFinancialMetrics(rpPerBird, rpPerKg, amount float64) FinancialMetrics {
|
|
return FinancialMetrics{
|
|
RpPerBird: rpPerBird,
|
|
RpPerKg: rpPerKg,
|
|
Amount: amount,
|
|
}
|
|
}
|
|
|
|
func ToComparison(budgeting, realization FinancialMetrics) Comparison {
|
|
return Comparison{
|
|
Budgeting: budgeting,
|
|
Realization: realization,
|
|
}
|
|
}
|
|
|
|
// === HPP PENGELUARAN (from Purchase Items) ===
|
|
|
|
func getFlagLabel(flagType utils.FlagType) string {
|
|
return PurchaseLabelPrefix + string(flagType)
|
|
}
|
|
|
|
func buildHppItemsByPurchaseFlags(purchaseItems []entities.PurchaseItem, ctx CalculationContext) []HppItem {
|
|
flags := []utils.FlagType{
|
|
utils.FlagDOC, utils.FlagPullet, utils.FlagLayer, utils.FlagPakan,
|
|
utils.FlagPreStarter, utils.FlagStarter, utils.FlagFinisher,
|
|
utils.FlagOVK, utils.FlagObat, utils.FlagVitamin, utils.FlagKimia,
|
|
}
|
|
|
|
items := []HppItem{}
|
|
seenFlags := make(map[utils.FlagType]bool)
|
|
|
|
for _, item := range purchaseItems {
|
|
if item.Product == nil || len(item.Product.Flags) == 0 {
|
|
continue
|
|
}
|
|
|
|
for _, flag := range item.Product.Flags {
|
|
flagType := utils.FlagType(flag.Name)
|
|
|
|
if slices.Contains(flags, flagType) && !seenFlags[flagType] {
|
|
amount := sumPurchasesByFlag(purchaseItems, flagType)
|
|
rpPerBird, rpPerKg := calculatePerUnitMetrics(amount, ctx.TotalPopulation, ctx.TotalWeightProduced)
|
|
|
|
items = append(items, HppItem{
|
|
Type: getFlagLabel(flagType),
|
|
Comparison: ToComparison(
|
|
ToFinancialMetrics(rpPerBird, rpPerKg, amount),
|
|
ToFinancialMetrics(rpPerBird, rpPerKg, amount),
|
|
),
|
|
})
|
|
seenFlags[flagType] = true
|
|
}
|
|
}
|
|
}
|
|
|
|
return items
|
|
}
|
|
|
|
// === HPP BAHAN BAKU (from ProjectBudget + ExpenseRealization) ===
|
|
|
|
func createHppOverheadItem(budgetAmount, realizationAmount float64, ctx CalculationContext) HppItem {
|
|
budgetRpPerBird, budgetRpPerKg := calculatePerUnitMetrics(budgetAmount, ctx.TotalPopulation, ctx.TotalWeightProduced)
|
|
realizationRpPerBird, realizationRpPerKg := calculatePerUnitMetrics(realizationAmount, ctx.TotalPopulation, ctx.TotalWeightProduced)
|
|
|
|
return HppItem{
|
|
Type: HPPLabelOverhead,
|
|
Comparison: ToComparison(
|
|
ToFinancialMetrics(budgetRpPerBird, budgetRpPerKg, budgetAmount),
|
|
ToFinancialMetrics(realizationRpPerBird, realizationRpPerKg, realizationAmount),
|
|
),
|
|
}
|
|
}
|
|
|
|
func createHppEkspedisiItem(ekspedisiAmount float64, ctx CalculationContext) HppItem {
|
|
ekspedisiRpPerBird, ekspedisiRpPerKg := calculatePerUnitMetrics(ekspedisiAmount, ctx.TotalPopulation, ctx.TotalWeightProduced)
|
|
|
|
return HppItem{
|
|
Type: HPPLabelEkspedisi,
|
|
Comparison: ToComparison(
|
|
ToFinancialMetrics(ekspedisiRpPerBird, ekspedisiRpPerKg, ekspedisiAmount),
|
|
ToFinancialMetrics(ekspedisiRpPerBird, ekspedisiRpPerKg, ekspedisiAmount),
|
|
),
|
|
}
|
|
}
|
|
|
|
func ToHppBahanBakuGroup(budgets []entities.ProjectBudget, realizations []entities.ExpenseRealization, ctx CalculationContext) HppGroup {
|
|
items := []HppItem{}
|
|
|
|
budgetAmount := sumBudgetsByFilter(budgets, func(*entities.ProjectBudget) bool { return true })
|
|
realizationAmount := getOperationalExpenses(realizations)
|
|
|
|
if budgetAmount > 0 || realizationAmount > 0 {
|
|
items = append(items, createHppOverheadItem(budgetAmount, realizationAmount, ctx))
|
|
}
|
|
|
|
ekspedisiAmount := sumRealizationsByFilter(realizations, filterRealizationByNonstockFlag(utils.FlagEkspedisi))
|
|
items = append(items, createHppEkspedisiItem(ekspedisiAmount, ctx))
|
|
|
|
return HppGroup{
|
|
GroupName: HPPGroupBahanBaku,
|
|
Data: items,
|
|
}
|
|
}
|
|
|
|
// === HPP SUMMARY ===
|
|
|
|
func ToSummaryHpp(label string, purchaseItems []entities.PurchaseItem, budgets []entities.ProjectBudget, realizations []entities.ExpenseRealization, ctx CalculationContext) SummaryHpp {
|
|
purchaseTotal := sumPurchaseTotal(purchaseItems)
|
|
budgetTotal := sumBudgetsByFilter(budgets, func(*entities.ProjectBudget) bool { return true })
|
|
totalBudget := purchaseTotal + budgetTotal
|
|
|
|
totalRealization := sumRealizationsByFilter(realizations, func(*entities.ExpenseRealization) bool { return true })
|
|
|
|
budgetRpPerBird, budgetRpPerKg := calculatePerUnitMetrics(totalBudget, ctx.TotalPopulation, ctx.TotalWeightProduced)
|
|
realizationRpPerBird, realizationRpPerKg := calculatePerUnitMetrics(totalRealization, ctx.TotalPopulation, ctx.TotalWeightProduced)
|
|
|
|
return SummaryHpp{
|
|
Label: label,
|
|
Comparison: ToComparison(
|
|
ToFinancialMetrics(budgetRpPerBird, budgetRpPerKg, totalBudget),
|
|
ToFinancialMetrics(realizationRpPerBird, realizationRpPerKg, totalRealization),
|
|
),
|
|
}
|
|
}
|
|
|
|
func ToHppPurchasesSection(purchaseItems []entities.PurchaseItem, budgets []entities.ProjectBudget, realizations []entities.ExpenseRealization, ctx CalculationContext) HppPurchasesSection {
|
|
hppGroups := []HppGroup{
|
|
{
|
|
GroupName: HPPGroupPengeluaran,
|
|
Data: buildHppItemsByPurchaseFlags(purchaseItems, ctx),
|
|
},
|
|
ToHppBahanBakuGroup(budgets, realizations, ctx),
|
|
}
|
|
|
|
summaryHpp := ToSummaryHpp(HPPSummaryLabel, purchaseItems, budgets, realizations, ctx)
|
|
|
|
return HppPurchasesSection{
|
|
Hpp: hppGroups,
|
|
SummaryHpp: summaryHpp,
|
|
}
|
|
}
|
|
|
|
// === PROFIT & LOSS ===
|
|
|
|
func ToPLItem(itemType string, metrics FinancialMetrics) PLItem {
|
|
return PLItem{
|
|
Type: itemType,
|
|
FinancialMetrics: metrics,
|
|
}
|
|
}
|
|
|
|
func ToPLSummaryItem(label string, metrics FinancialMetrics) PLSummaryItem {
|
|
return PLSummaryItem{
|
|
Label: label,
|
|
FinancialMetrics: metrics,
|
|
}
|
|
}
|
|
|
|
func createPLItemWithMetrics(itemType string, amount float64, ctx CalculationContext) PLItem {
|
|
rpPerBird, rpPerKg := calculatePerUnitMetrics(amount, ctx.ActualPopulation, ctx.TotalWeightProduced)
|
|
return ToPLItem(itemType, ToFinancialMetrics(rpPerBird, rpPerKg, amount))
|
|
}
|
|
|
|
func sumPLItems(items []PLItem) (totalAmount, totalPerBird float64) {
|
|
for _, item := range items {
|
|
totalAmount += item.Amount
|
|
totalPerBird += item.RpPerBird
|
|
}
|
|
return
|
|
}
|
|
|
|
func createPenjualanItem(salesType string, amount float64, ctx CalculationContext) PLItem {
|
|
rpPerBird, rpPerKg := calculatePerUnitMetrics(amount, ctx.ActualPopulation, ctx.TotalWeightSold)
|
|
return ToPLItem(salesType, ToFinancialMetrics(rpPerBird, rpPerKg, amount))
|
|
}
|
|
|
|
func ToPenjualanItems(projectFlockCategory string, deliveryProducts []entities.MarketingDeliveryProduct, ctx CalculationContext) []PLItem {
|
|
items := []PLItem{}
|
|
|
|
categorized := categorizeDeliveriesBySalesType(deliveryProducts)
|
|
|
|
if projectFlockCategory == string(utils.ProjectFlockCategoryLaying) {
|
|
ayamAmount := sumDeliveriesByCategory(categorized[PLSalesTypeChicken])
|
|
telurAmount := sumDeliveriesByCategory(categorized[PLSalesTypeEgg])
|
|
|
|
items = append(items, createPenjualanItem(PLSalesTypeChicken, ayamAmount, ctx))
|
|
items = append(items, createPenjualanItem(PLSalesTypeEgg, telurAmount, ctx))
|
|
} else {
|
|
ayamAmount := sumDeliveriesByCategory(categorized[PLSalesTypeChicken])
|
|
items = append(items, createPenjualanItem(PLSalesTypeChicken, ayamAmount, ctx))
|
|
}
|
|
|
|
return items
|
|
}
|
|
|
|
func ToPembelianItems(purchases []entities.PurchaseItem, realizations []entities.ExpenseRealization, ctx CalculationContext) []PLItem {
|
|
purchaseAmount := sumPurchaseTotal(purchases)
|
|
bopAmount := getOperationalExpenses(realizations)
|
|
totalCost := purchaseAmount + bopAmount
|
|
|
|
return []PLItem{
|
|
createPLItemWithMetrics(PLItemTypeSapronak, totalCost, ctx),
|
|
}
|
|
}
|
|
|
|
func ToOverheadItems(realizations []entities.ExpenseRealization, ctx CalculationContext) []PLItem {
|
|
realizationAmount := getOperationalExpenses(realizations)
|
|
return []PLItem{
|
|
createPLItemWithMetrics(PLItemTypeOverhead, realizationAmount, ctx),
|
|
}
|
|
}
|
|
|
|
func ToEkspedisiItems(realizations []entities.ExpenseRealization, ctx CalculationContext) []PLItem {
|
|
amount := sumRealizationsByFilter(realizations, filterRealizationByNonstockFlag(utils.FlagEkspedisi))
|
|
return []PLItem{
|
|
createPLItemWithMetrics(PLItemTypeEkspedisi, amount, ctx),
|
|
}
|
|
}
|
|
|
|
func ToPLSummaryGroup(penjualanItems, pembelianItems, overheadItems, ekspedisiItems []PLItem) PLSummaryGroup {
|
|
totalPenjualan, totalPenjualanPerBird := sumPLItems(penjualanItems)
|
|
totalPembelian, totalPembelianPerBird := sumPLItems(pembelianItems)
|
|
totalOverhead, totalOverheadPerBird := sumPLItems(overheadItems)
|
|
totalEkspedisi, totalEkspedisiPerBird := sumPLItems(ekspedisiItems)
|
|
|
|
grossProfit := totalPenjualan - totalPembelian
|
|
grossProfitPerBird := totalPenjualanPerBird - totalPembelianPerBird
|
|
|
|
totalOtherExpenses := totalOverhead + totalEkspedisi
|
|
totalOtherExpensesPerBird := totalOverheadPerBird + totalEkspedisiPerBird
|
|
|
|
netProfit := grossProfit - totalOtherExpenses
|
|
netProfitPerBird := grossProfitPerBird - totalOtherExpensesPerBird
|
|
|
|
return PLSummaryGroup{
|
|
GrossProfit: ToPLSummaryItem(PLSummaryLabelGrossProfit, ToFinancialMetrics(grossProfitPerBird, 0, grossProfit)),
|
|
SubTotal: ToPLSummaryItem(PLSummaryLabelSubTotal, ToFinancialMetrics(totalOtherExpensesPerBird, 0, totalOtherExpenses)),
|
|
NetProfit: ToPLSummaryItem(PLSummaryLabelNetProfit, ToFinancialMetrics(netProfitPerBird, 0, netProfit)),
|
|
}
|
|
}
|
|
|
|
func ToProfitLossData(penjualanItems, pembelianItems, overheadItems, ekspedisiItems []PLItem) ProfitLossData {
|
|
summary := ToPLSummaryGroup(penjualanItems, pembelianItems, overheadItems, ekspedisiItems)
|
|
|
|
totalOverhead := aggregatePLItems(overheadItems, PLItemTypeOverhead)
|
|
totalEkspedisi := aggregatePLItems(ekspedisiItems, PLItemTypeEkspedisi)
|
|
|
|
return ProfitLossData{
|
|
Penjualan: penjualanItems,
|
|
Pembelian: pembelianItems,
|
|
Overhead: totalOverhead,
|
|
Ekspedisi: totalEkspedisi,
|
|
Summary: summary,
|
|
}
|
|
}
|
|
|
|
func ToProfitLossSection(penjualanItems, pembelianItems, overheadItems, ekspedisiItems []PLItem) ProfitLossSection {
|
|
return ProfitLossSection{
|
|
Data: ToProfitLossData(penjualanItems, pembelianItems, overheadItems, ekspedisiItems),
|
|
}
|
|
}
|
|
|
|
func aggregatePLItems(items []PLItem, label string) PLItem {
|
|
totalAmount, totalPerBird := sumPLItems(items)
|
|
return ToPLItem(label, ToFinancialMetrics(totalPerBird, 0, totalAmount))
|
|
}
|
|
|
|
func ToReportResponse(hppPurchases HppPurchasesSection, profitLoss ProfitLossSection) ReportResponse {
|
|
return ReportResponse{
|
|
HppPurchases: hppPurchases,
|
|
ProfitLoss: profitLoss,
|
|
}
|
|
}
|
|
|
|
func ToClosingKeuanganReport(input ClosingKeuanganInput) ReportResponse {
|
|
var totalPopulation float64
|
|
var totalWeightSold float64
|
|
|
|
for _, chickin := range input.Chickins {
|
|
totalPopulation += chickin.UsageQty
|
|
}
|
|
|
|
for _, delivery := range input.DeliveryProducts {
|
|
totalWeightSold += delivery.TotalWeight
|
|
}
|
|
|
|
ctx := CalculationContext{
|
|
TotalPopulation: totalPopulation,
|
|
TotalWeightProduced: input.TotalWeightProduced,
|
|
TotalDepletion: input.TotalDepletion,
|
|
TotalWeightSold: totalWeightSold,
|
|
ActualPopulation: totalPopulation - input.TotalDepletion,
|
|
}
|
|
|
|
hppSection := ToHppPurchasesSection(input.PurchaseItems, input.Budgets, input.Realizations, ctx)
|
|
penjualanItems := ToPenjualanItems(input.ProjectFlockCategory, input.DeliveryProducts, ctx)
|
|
pembelianItems := ToPembelianItems(input.PurchaseItems, input.Realizations, ctx)
|
|
overheadItems := ToOverheadItems(input.Realizations, ctx)
|
|
ekspedisiItems := ToEkspedisiItems(input.Realizations, ctx)
|
|
plSection := ToProfitLossSection(penjualanItems, pembelianItems, overheadItems, ekspedisiItems)
|
|
|
|
return ToReportResponse(hppSection, plSection)
|
|
}
|
|
|
|
// === HELPER FUNCTIONS ===
|
|
|
|
func calculatePerUnitMetrics(amount, totalPopulation, totalWeightSold float64) (rpPerBird, rpPerKg float64) {
|
|
if totalPopulation > 0 {
|
|
rpPerBird = amount / totalPopulation
|
|
}
|
|
if totalWeightSold > 0 {
|
|
rpPerKg = amount / totalWeightSold
|
|
}
|
|
return rpPerBird, rpPerKg
|
|
}
|
|
|
|
func hasProductFlag(flags []entities.Flag, flagType utils.FlagType) bool {
|
|
for _, flag := range flags {
|
|
if strings.ToUpper(flag.Name) == string(flagType) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func filterByPurchaseFlag(flagType utils.FlagType) func(*entities.PurchaseItem) bool {
|
|
return func(item *entities.PurchaseItem) bool {
|
|
if item.Product == nil || len(item.Product.Flags) == 0 {
|
|
return false
|
|
}
|
|
return hasProductFlag(item.Product.Flags, flagType)
|
|
}
|
|
}
|
|
|
|
func filterRealizationByNonstockFlag(flagType utils.FlagType) func(*entities.ExpenseRealization) bool {
|
|
return func(realization *entities.ExpenseRealization) bool {
|
|
if realization.ExpenseNonstock == nil || realization.ExpenseNonstock.Nonstock == nil {
|
|
return false
|
|
}
|
|
return hasProductFlag(realization.ExpenseNonstock.Nonstock.Flags, flagType)
|
|
}
|
|
}
|
|
|
|
func filterRealizationExceptFlag(flagType utils.FlagType) func(*entities.ExpenseRealization) bool {
|
|
hasFlag := filterRealizationByNonstockFlag(flagType)
|
|
return func(realization *entities.ExpenseRealization) bool {
|
|
return !hasFlag(realization)
|
|
}
|
|
}
|
|
|
|
func sumByFilter[T any](items []T, extractor func(*T) float64, filter func(*T) bool) float64 {
|
|
amount := 0.0
|
|
for i := range items {
|
|
if filter(&items[i]) {
|
|
amount += extractor(&items[i])
|
|
}
|
|
}
|
|
return amount
|
|
}
|
|
|
|
func sumPurchasesByFilter(purchases []entities.PurchaseItem, filter func(*entities.PurchaseItem) bool) float64 {
|
|
return sumByFilter(purchases, func(p *entities.PurchaseItem) float64 { return p.TotalPrice }, filter)
|
|
}
|
|
|
|
func sumPurchasesByFlag(purchases []entities.PurchaseItem, flagType utils.FlagType) float64 {
|
|
return sumPurchasesByFilter(purchases, filterByPurchaseFlag(flagType))
|
|
}
|
|
|
|
func sumPurchaseTotal(purchases []entities.PurchaseItem) float64 {
|
|
return sumByFilter(purchases, func(p *entities.PurchaseItem) float64 { return p.TotalPrice }, func(*entities.PurchaseItem) bool { return true })
|
|
}
|
|
|
|
func sumBudgetsByFilter(budgets []entities.ProjectBudget, filter func(*entities.ProjectBudget) bool) float64 {
|
|
return sumByFilter(budgets, func(b *entities.ProjectBudget) float64 { return b.Price * b.Qty }, filter)
|
|
}
|
|
|
|
func sumRealizationsByFilter(realizations []entities.ExpenseRealization, filter func(*entities.ExpenseRealization) bool) float64 {
|
|
return sumByFilter(realizations, func(r *entities.ExpenseRealization) float64 { return r.Price * r.Qty }, filter)
|
|
}
|
|
|
|
func getOperationalExpenses(realizations []entities.ExpenseRealization) float64 {
|
|
return sumRealizationsByFilter(realizations, filterRealizationExceptFlag(utils.FlagEkspedisi))
|
|
}
|
|
|
|
func isChickenProductFlag(flagType utils.FlagType) bool {
|
|
switch flagType {
|
|
case utils.FlagDOC, utils.FlagPullet, utils.FlagLayer,
|
|
utils.FlagAyamAfkir, utils.FlagAyamCulling, utils.FlagAyamMati:
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func isEggProductFlag(flagType utils.FlagType) bool {
|
|
switch flagType {
|
|
case utils.FlagTelur, utils.FlagTelurUtuh, utils.FlagTelurPecah,
|
|
utils.FlagTelurPutih, utils.FlagTelurRetak:
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func getSalesTypeFromProductFlags(product *entities.Product) string {
|
|
if product == nil || len(product.Flags) == 0 {
|
|
return PLSalesTypeChicken
|
|
}
|
|
|
|
for _, flag := range product.Flags {
|
|
flagType := utils.FlagType(strings.ToUpper(flag.Name))
|
|
|
|
if isEggProductFlag(flagType) {
|
|
return PLSalesTypeEgg
|
|
}
|
|
if isChickenProductFlag(flagType) {
|
|
return PLSalesTypeChicken
|
|
}
|
|
}
|
|
|
|
return PLSalesTypeChicken
|
|
}
|
|
|
|
func categorizeDeliveriesBySalesType(deliveries []entities.MarketingDeliveryProduct) map[string][]entities.MarketingDeliveryProduct {
|
|
categorized := make(map[string][]entities.MarketingDeliveryProduct)
|
|
|
|
for _, delivery := range deliveries {
|
|
product := delivery.MarketingProduct.ProductWarehouse.Product
|
|
salesType := getSalesTypeFromProductFlags(&product)
|
|
|
|
categorized[salesType] = append(categorized[salesType], delivery)
|
|
}
|
|
|
|
return categorized
|
|
}
|
|
|
|
func sumDeliveriesByCategory(deliveries []entities.MarketingDeliveryProduct) float64 {
|
|
amount := 0.0
|
|
for _, delivery := range deliveries {
|
|
amount += delivery.TotalPrice
|
|
}
|
|
return amount
|
|
}
|