diff --git a/internal/modules/marketing/repositories/salesorder_delivery_product.repository.go b/internal/modules/marketing/repositories/salesorder_delivery_product.repository.go index b908681e..ba2c1133 100644 --- a/internal/modules/marketing/repositories/salesorder_delivery_product.repository.go +++ b/internal/modules/marketing/repositories/salesorder_delivery_product.repository.go @@ -90,6 +90,7 @@ func (r *MarketingDeliveryProductRepositoryImpl) GetAllWithFilters(ctx context.C Preload("Marketing.SalesPerson"). Preload("ProductWarehouse"). Preload("ProductWarehouse.Product"). + Preload("ProductWarehouse.Product.Flags"). Preload("ProductWarehouse.Warehouse"). Preload("ProductWarehouse.ProjectFlockKandang"). Preload("ProductWarehouse.ProjectFlockKandang.ProjectFlock") diff --git a/internal/modules/production/chickins/repositories/project_chickin.repository.go b/internal/modules/production/chickins/repositories/project_chickin.repository.go index bef062f5..43cafaac 100644 --- a/internal/modules/production/chickins/repositories/project_chickin.repository.go +++ b/internal/modules/production/chickins/repositories/project_chickin.repository.go @@ -15,6 +15,7 @@ type ProjectChickinRepository interface { GetByProjectFlockKandangID(ctx context.Context, projectFlockKandangID uint) ([]entity.ProjectChickin, error) GetPendingByProjectFlockKandangID(ctx context.Context, projectFlockKandangID uint) ([]entity.ProjectChickin, error) GetTotalPendingUsageQtyByProjectFlockKandangID(ctx context.Context, projectFlockKandangID uint) (float64, error) + GetTotalChickinQtyByProjectFlockID(ctx context.Context, projectFlockID uint) (float64, error) } type ChickinRepositoryImpl struct { @@ -90,3 +91,14 @@ func (r *ChickinRepositoryImpl) GetTotalPendingUsageQtyByProjectFlockKandangID(c } return total, nil } + +func (r *ChickinRepositoryImpl) GetTotalChickinQtyByProjectFlockID(ctx context.Context, projectFlockID uint) (float64, error) { + var result float64 + err := r.db.WithContext(ctx). + Table("project_chickins"). + Select("COALESCE(SUM(project_chickins.usage_qty), 0)"). + Joins("JOIN project_flock_kandangs ON project_flock_kandangs.id = project_chickins.project_flock_kandang_id"). + Where("project_flock_kandangs.project_flock_id = ?", projectFlockID). + Scan(&result).Error + return result, err +} diff --git a/internal/modules/production/recordings/repositories/recording.repository.go b/internal/modules/production/recordings/repositories/recording.repository.go index 4a7e627c..85c9a7fe 100644 --- a/internal/modules/production/recordings/repositories/recording.repository.go +++ b/internal/modules/production/recordings/repositories/recording.repository.go @@ -48,6 +48,7 @@ type RecordingRepository interface { GetProductionWeightAndQtyByProjectFlockID(ctx context.Context, projectFlockID uint) (totalWeight float64, totalQty float64, err error) GetTotalDepletionByProjectFlockID(ctx context.Context, projectFlockID uint) (totalDepletion float64, err error) GetLatestAvgWeightByProjectFlockID(ctx context.Context, projectFlockID uint) (avgWeight float64, err error) + GetTotalEggProductionWeightByProjectFlockID(ctx context.Context, projectFlockID uint) (totalWeightKg float64, err error) } type RecordingRepositoryImpl struct { @@ -371,28 +372,23 @@ func (r *RecordingRepositoryImpl) GetProductionWeightAndQtyByProjectFlockID(ctx return 0, 0, nil } - // Get total chickin quantity for this ProjectFlock totalChickinQty, err := r.getTotalChickinQtyByProjectFlockID(ctx, projectFlockID) if err != nil { return 0, 0, err } - // Get total depletion for this ProjectFlock totalDepletion, err := r.GetTotalDepletionByProjectFlockID(ctx, projectFlockID) if err != nil { return 0, 0, err } - // Calculate actual quantity produced actualQty := totalChickinQty - totalDepletion - // Get latest average weight from RecordingBW avgWeight, err := r.GetLatestAvgWeightByProjectFlockID(ctx, projectFlockID) if err != nil { return 0, 0, err } - // Calculate total weight totalWeight = actualQty * avgWeight return totalWeight, actualQty, nil @@ -434,6 +430,22 @@ func (r *RecordingRepositoryImpl) GetLatestAvgWeightByProjectFlockID(ctx context return result, err } +func (r *RecordingRepositoryImpl) GetTotalEggProductionWeightByProjectFlockID(ctx context.Context, projectFlockID uint) (float64, error) { + if projectFlockID == 0 { + return 0, nil + } + + var result float64 + err := r.DB().WithContext(ctx). + Table("recording_eggs"). + Select("COALESCE(SUM(recording_eggs.qty * recording_eggs.weight), 0) / 1000"). + Joins("JOIN recordings ON recordings.id = recording_eggs.recording_id"). + Joins("JOIN project_flock_kandangs ON project_flock_kandangs.id = recordings.project_flock_kandangs_id"). + Where("project_flock_kandangs.project_flock_id = ?", projectFlockID). + Scan(&result).Error + return result, err +} + func nextRecordingDay(days []int) int { if len(days) == 0 { return 1 diff --git a/internal/modules/repports/dto/repportMarketing.dto.go b/internal/modules/repports/dto/repportMarketing.dto.go index deadf3b8..9c026590 100644 --- a/internal/modules/repports/dto/repportMarketing.dto.go +++ b/internal/modules/repports/dto/repportMarketing.dto.go @@ -1,14 +1,15 @@ package dto import ( - "fmt" "time" entity "gitlab.com/mbugroup/lti-api.git/internal/entities" + marketingDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/dto" customerDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/customers/dto" productDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/products/dto" warehouseDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/warehouses/dto" userDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/users/dto" + "gitlab.com/mbugroup/lti-api.git/internal/utils" ) type RepportMarketingItemDTO struct { @@ -45,7 +46,7 @@ type RepportMarketingResponseDTO struct { Total *Summary `json:"total,omitempty"` } -func ToRepportMarketingItemDTO(mdp entity.MarketingDeliveryProduct, hppPricePerKg float64) RepportMarketingItemDTO { +func ToRepportMarketingItemDTO(mdp entity.MarketingDeliveryProduct, hppPricePerKg float64, category string) RepportMarketingItemDTO { soDate := time.Time{} agingDays := 0 if mdp.MarketingProduct.Marketing.SoDate.Year() > 1 { @@ -58,11 +59,17 @@ func ToRepportMarketingItemDTO(mdp entity.MarketingDeliveryProduct, hppPricePerK realizationDate = *mdp.DeliveryDate } - doNumber := generateDoNumber(mdp.MarketingProduct.Marketing.SoNumber, mdp.DeliveryDate, mdp.MarketingProduct.ProductWarehouse.WarehouseId) + doNumber := marketingDTO.GenerateDeliveryOrderNumber(mdp.MarketingProduct.Marketing.SoNumber, mdp.DeliveryDate, mdp.MarketingProduct.ProductWarehouse.WarehouseId) totalWeightKg := mdp.Qty * mdp.AvgWeight salesAmount := totalWeightKg * mdp.UnitPrice - hppAmount := totalWeightKg * hppPricePerKg + + var hpp float64 + var hppAmount float64 + if isProductEligibleForHpp(mdp, category) { + hpp = hppPricePerKg + hppAmount = totalWeightKg * hppPricePerKg + } item := RepportMarketingItemDTO{ ID: int(mdp.Id), @@ -70,12 +77,12 @@ func ToRepportMarketingItemDTO(mdp entity.MarketingDeliveryProduct, hppPricePerK RealizationDate: realizationDate, AgingDays: agingDays, DoNumber: doNumber, - MarketingType: "ayam", + MarketingType: getMarketingType(mdp), Qty: mdp.Qty, AverageWeightKg: mdp.AvgWeight, TotalWeightKg: totalWeightKg, SalesPricePerKg: mdp.UnitPrice, - HppPricePerKg: hppPricePerKg, + HppPricePerKg: hpp, SalesAmount: salesAmount, HppAmount: hppAmount, } @@ -105,10 +112,10 @@ func ToRepportMarketingItemDTO(mdp entity.MarketingDeliveryProduct, hppPricePerK return item } -func ToRepportMarketingItemDTOs(mdps []entity.MarketingDeliveryProduct, hppPricePerKg float64) []RepportMarketingItemDTO { +func ToRepportMarketingItemDTOs(mdps []entity.MarketingDeliveryProduct, hppPricePerKg float64, category string) []RepportMarketingItemDTO { items := make([]RepportMarketingItemDTO, 0, len(mdps)) for _, mdp := range mdps { - items = append(items, ToRepportMarketingItemDTO(mdp, hppPricePerKg)) + items = append(items, ToRepportMarketingItemDTO(mdp, hppPricePerKg, category)) } return items } @@ -117,23 +124,72 @@ func ToRepportMarketingItemDTOsWithHppMap(mdps []entity.MarketingDeliveryProduct items := make([]RepportMarketingItemDTO, 0, len(mdps)) for _, mdp := range mdps { hppPerKg := float64(0) + category := "" if projectFlockKandang := mdp.MarketingProduct.ProductWarehouse.ProjectFlockKandang; projectFlockKandang != nil { if hpp, exists := hppMap[projectFlockKandang.ProjectFlockId]; exists { hppPerKg = hpp } + category = projectFlockKandang.ProjectFlock.Category } - items = append(items, ToRepportMarketingItemDTO(mdp, hppPerKg)) + + item := ToRepportMarketingItemDTO(mdp, hppPerKg, category) + items = append(items, item) } return items } -func ToSummary(mdps []entity.MarketingDeliveryProduct, hppPricePerKg float64) *Summary { +func getMarketingType(mdp entity.MarketingDeliveryProduct) string { + hasAyam, hasTelur := checkProductFlags(mdp.MarketingProduct.ProductWarehouse.Product.Flags) + + if hasAyam { + return "ayam" + } + if hasTelur { + return "telur" + } + return "trading" +} + +func checkProductFlags(flags []entity.Flag) (hasAyam, hasTelur bool) { + if len(flags) == 0 { + return false, false + } + + for _, flag := range flags { + ft := utils.FlagType(flag.Name) + + if ft == utils.FlagAyamAfkir || ft == utils.FlagAyamCulling || ft == utils.FlagAyamMati || + ft == utils.FlagDOC || ft == utils.FlagPullet || ft == utils.FlagLayer { + hasAyam = true + } + + if ft == utils.FlagTelur || ft == utils.FlagTelurUtuh || ft == utils.FlagTelurPecah || + ft == utils.FlagTelurPutih || ft == utils.FlagTelurRetak { + hasTelur = true + } + } + + return hasAyam, hasTelur +} + +func isProductEligibleForHpp(mdp entity.MarketingDeliveryProduct, category string) bool { + hasAyam, hasTelur := checkProductFlags(mdp.MarketingProduct.ProductWarehouse.Product.Flags) + + if utils.ProjectFlockCategory(category) == utils.ProjectFlockCategoryGrowing { + return hasAyam + } + + return hasAyam || hasTelur +} + +func ToSummary(mdps []entity.MarketingDeliveryProduct, hppPricePerKg float64, category string) *Summary { if len(mdps) == 0 { return nil } totalQty := 0 totalWeightKg := 0.0 + totalEligibleWeightKg := 0.0 totalSalesAmount := int64(0) totalHppAmount := int64(0) @@ -142,12 +198,16 @@ func ToSummary(mdps []entity.MarketingDeliveryProduct, hppPricePerKg float64) *S totalQty += int(mdp.Qty) totalWeightKg += calculatedTotalWeight totalSalesAmount += int64(calculatedTotalWeight * mdp.UnitPrice) - totalHppAmount += int64(calculatedTotalWeight * hppPricePerKg) + + if isProductEligibleForHpp(mdp, category) { + totalEligibleWeightKg += calculatedTotalWeight + totalHppAmount += int64(calculatedTotalWeight * hppPricePerKg) + } } totalHppPricePerKg := float64(0) - if totalWeightKg > 0 { - totalHppPricePerKg = float64(totalHppAmount) / totalWeightKg + if totalEligibleWeightKg > 0 { + totalHppPricePerKg = float64(totalHppAmount) / totalEligibleWeightKg } return &Summary{ @@ -159,14 +219,6 @@ func ToSummary(mdps []entity.MarketingDeliveryProduct, hppPricePerKg float64) *S } } -func generateDoNumber(soNumber string, deliveryDate *time.Time, warehouseId uint) string { - dateStr := "" - if deliveryDate != nil { - dateStr = deliveryDate.Format("20060102") - } - return fmt.Sprintf("%s-%s-%d", soNumber, dateStr, warehouseId) -} - func ToSummaryFromDTOItems(items []RepportMarketingItemDTO) *Summary { if len(items) == 0 { return nil @@ -198,9 +250,9 @@ func ToSummaryFromDTOItems(items []RepportMarketingItemDTO) *Summary { } } -func ToRepportMarketingResponseDTO(mdps []entity.MarketingDeliveryProduct, hppPricePerKg float64) RepportMarketingResponseDTO { - items := ToRepportMarketingItemDTOs(mdps, hppPricePerKg) - total := ToSummary(mdps, hppPricePerKg) +func ToRepportMarketingResponseDTO(mdps []entity.MarketingDeliveryProduct, hppPricePerKg float64, category string) RepportMarketingResponseDTO { + items := ToRepportMarketingItemDTOs(mdps, hppPricePerKg, category) + total := ToSummary(mdps, hppPricePerKg, category) return RepportMarketingResponseDTO{ Items: items, diff --git a/internal/modules/repports/module.go b/internal/modules/repports/module.go index f347ab69..95d77dc1 100644 --- a/internal/modules/repports/module.go +++ b/internal/modules/repports/module.go @@ -11,6 +11,7 @@ import ( expenseRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/expenses/repositories" marketingRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/repositories" + chickinRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/production/chickins/repositories" recordingRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/production/recordings/repositories" purchaseRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/purchases/repositories" ) @@ -22,11 +23,12 @@ func (RepportModule) RegisterRoutes(router fiber.Router, db *gorm.DB, validate * expenseRealizationRepository := expenseRepo.NewExpenseRealizationRepository(db) marketingDeliveryProductRepository := marketingRepo.NewMarketingDeliveryProductRepository(db) purchaseRepository := purchaseRepo.NewPurchaseRepository(db) + chickinRepository := chickinRepo.NewChickinRepository(db) recordingRepository := recordingRepo.NewRecordingRepository(db) approvalRepository := commonRepo.NewApprovalRepository(db) approvalSvc := approvalService.NewApprovalService(approvalRepository) - repportService := sRepport.NewRepportService(validate, expenseRealizationRepository, marketingDeliveryProductRepository, purchaseRepository, recordingRepository, approvalSvc) + repportService := sRepport.NewRepportService(validate, expenseRealizationRepository, marketingDeliveryProductRepository, purchaseRepository, chickinRepository, recordingRepository, approvalSvc) RepportRoutes(router, repportService) } diff --git a/internal/modules/repports/services/repport.service.go b/internal/modules/repports/services/repport.service.go index 5458a28d..7513cbb1 100644 --- a/internal/modules/repports/services/repport.service.go +++ b/internal/modules/repports/services/repport.service.go @@ -3,7 +3,6 @@ package service import ( "context" - entity "gitlab.com/mbugroup/lti-api.git/internal/entities" "gitlab.com/mbugroup/lti-api.git/internal/modules/repports/dto" validation "gitlab.com/mbugroup/lti-api.git/internal/modules/repports/validations" "gitlab.com/mbugroup/lti-api.git/internal/utils" @@ -12,6 +11,7 @@ import ( approvalDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/approvals/dto" expenseRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/expenses/repositories" marketingRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/repositories" + chickinRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/production/chickins/repositories" recordingRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/production/recordings/repositories" purchaseRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/purchases/repositories" @@ -32,17 +32,19 @@ type repportService struct { ExpenseRealizationRepo expenseRepo.ExpenseRealizationRepository MarketingDeliveryRepo marketingRepo.MarketingDeliveryProductRepository PurchaseRepo purchaseRepo.PurchaseRepository + ChickinRepo chickinRepo.ProjectChickinRepository RecordingRepo recordingRepo.RecordingRepository ApprovalSvc approvalService.ApprovalService } -func NewRepportService(validate *validator.Validate, expenseRealizationRepo expenseRepo.ExpenseRealizationRepository, marketingDeliveryRepo marketingRepo.MarketingDeliveryProductRepository, purchaseRepo purchaseRepo.PurchaseRepository, recordingRepo recordingRepo.RecordingRepository, approvalSvc approvalService.ApprovalService) RepportService { +func NewRepportService(validate *validator.Validate, expenseRealizationRepo expenseRepo.ExpenseRealizationRepository, marketingDeliveryRepo marketingRepo.MarketingDeliveryProductRepository, purchaseRepo purchaseRepo.PurchaseRepository, chickinRepo chickinRepo.ProjectChickinRepository, recordingRepo recordingRepo.RecordingRepository, approvalSvc approvalService.ApprovalService) RepportService { return &repportService{ Log: utils.Log, Validate: validate, ExpenseRealizationRepo: expenseRealizationRepo, MarketingDeliveryRepo: marketingDeliveryRepo, PurchaseRepo: purchaseRepo, + ChickinRepo: chickinRepo, RecordingRepo: recordingRepo, ApprovalSvc: approvalSvc, } @@ -98,74 +100,63 @@ func (s *repportService) GetMarketing(c *fiber.Ctx, params *validation.Marketing return nil, 0, err } - projectFlockIDs := s.collectProjectFlockIDs(deliveryProducts) - hppMap := s.buildHppMap(c.Context(), projectFlockIDs, deliveryProducts) - items := dto.ToRepportMarketingItemDTOsWithHppMap(deliveryProducts, hppMap) + projectFlockIDMap := make(map[uint]bool) + hppMap := make(map[uint]float64) + for _, dp := range deliveryProducts { + if projectFlockKandang := dp.MarketingProduct.ProductWarehouse.ProjectFlockKandang; projectFlockKandang != nil { + projectFlockID := projectFlockKandang.ProjectFlockId + if projectFlockID > 0 && !projectFlockIDMap[projectFlockID] { + projectFlockIDMap[projectFlockID] = true + + category := projectFlockKandang.ProjectFlock.Category + hppPerKg := s.calculateHppPricePerKg(c.Context(), projectFlockID, category) + hppMap[projectFlockID] = hppPerKg + } + } + } + + items := dto.ToRepportMarketingItemDTOsWithHppMap(deliveryProducts, hppMap) return items, total, nil } -func (s *repportService) collectProjectFlockIDs(deliveryProducts []entity.MarketingDeliveryProduct) []uint { - projectFlockIDMap := make(map[uint]bool) - projectFlockIDs := make([]uint, 0) - - for _, dp := range deliveryProducts { - if projectFlockKandang := dp.MarketingProduct.ProductWarehouse.ProjectFlockKandang; projectFlockKandang != nil { - if projectFlockKandang.ProjectFlockId > 0 && !projectFlockIDMap[projectFlockKandang.ProjectFlockId] { - projectFlockIDs = append(projectFlockIDs, projectFlockKandang.ProjectFlockId) - projectFlockIDMap[projectFlockKandang.ProjectFlockId] = true - } - } - } - - return projectFlockIDs -} - -func (s *repportService) buildHppMap(ctx context.Context, projectFlockIDs []uint, deliveryProducts []entity.MarketingDeliveryProduct) map[uint]float64 { - hppMap := make(map[uint]float64) - for _, projectFlockID := range projectFlockIDs { - category := s.getProjectFlockCategory(deliveryProducts, projectFlockID) - hppPerKg := s.calculateHppByCategory(ctx, category, projectFlockID, deliveryProducts) - hppMap[projectFlockID] = hppPerKg - } - return hppMap -} - -func (s *repportService) calculateHppByCategory(ctx context.Context, category string, projectFlockID uint, deliveryProducts []entity.MarketingDeliveryProduct) float64 { - switch utils.ProjectFlockCategory(category) { - case utils.ProjectFlockCategoryGrowing: - return s.calculateHppPricePerKg(ctx, projectFlockID, deliveryProducts) - case utils.ProjectFlockCategoryLaying: - return 0 - default: +func (s *repportService) calculateHppPricePerKg(ctx context.Context, projectFlockID uint, category string) float64 { + totalCost := s.getTotalProjectCost(ctx, projectFlockID) + if totalCost == 0 { return 0 } -} -func (s *repportService) getProjectFlockCategory(deliveryProducts []entity.MarketingDeliveryProduct, projectFlockID uint) string { - for _, dp := range deliveryProducts { - if projectFlockKandang := dp.MarketingProduct.ProductWarehouse.ProjectFlockKandang; projectFlockKandang != nil { - if projectFlockKandang.ProjectFlockId == projectFlockID { - return projectFlockKandang.ProjectFlock.Category - } - } + chickinQty, _ := s.ChickinRepo.GetTotalChickinQtyByProjectFlockID(ctx, projectFlockID) + depletion, _ := s.RecordingRepo.GetTotalDepletionByProjectFlockID(ctx, projectFlockID) + avgWeight, _ := s.RecordingRepo.GetLatestAvgWeightByProjectFlockID(ctx, projectFlockID) + + var totalWeight float64 + if utils.ProjectFlockCategory(category) == utils.ProjectFlockCategoryGrowing { + totalWeight = (chickinQty - depletion) * avgWeight + } else { + eggWeight, _ := s.RecordingRepo.GetTotalEggProductionWeightByProjectFlockID(ctx, projectFlockID) + totalWeight = (chickinQty-depletion)*avgWeight + eggWeight } - return "" + + if totalWeight == 0 { + return 0 + } + return totalCost / totalWeight } -func (s *repportService) calculateHppPricePerKg(ctx context.Context, projectFlockID uint, deliveryProducts []entity.MarketingDeliveryProduct) float64 { +func (s *repportService) getTotalProjectCost(ctx context.Context, projectFlockID uint) float64 { if projectFlockID == 0 { return 0 } - purchaseItems, err := s.PurchaseRepo.GetItemsByProjectFlockID(ctx, projectFlockID) + purchases, err := s.PurchaseRepo.GetItemsByProjectFlockID(ctx, projectFlockID) if err != nil { s.Log.Warnf("GetItemsByProjectFlockID error: %v", err) } - costPurchase := float64(0) - for _, item := range purchaseItems { - costPurchase += item.TotalPrice + cost := float64(0) + for _, p := range purchases { + cost += p.TotalPrice } realizations, err := s.ExpenseRealizationRepo.GetByProjectFlockID(ctx, projectFlockID) @@ -173,34 +164,11 @@ func (s *repportService) calculateHppPricePerKg(ctx context.Context, projectFloc s.Log.Warnf("GetByProjectFlockID error: %v", err) } - costBop := float64(0) - for _, realization := range realizations { - cost := realization.Price * realization.Qty - category := "" - if realization.ExpenseNonstock != nil && realization.ExpenseNonstock.Expense != nil { - category = realization.ExpenseNonstock.Expense.Category - } - - if category == "BOP" { - costBop += cost + for _, r := range realizations { + if r.ExpenseNonstock != nil && r.ExpenseNonstock.Expense != nil && + r.ExpenseNonstock.Expense.Category == string(utils.ExpenseCategoryBOP) { + cost += r.Price * r.Qty } } - - totalActualCost := costPurchase + costBop - - if totalActualCost == 0 { - return 0 - } - - totalWeightProduced, _, err := s.RecordingRepo.GetProductionWeightAndQtyByProjectFlockID(ctx, projectFlockID) - if err != nil { - s.Log.Warnf("GetProductionWeightAndQtyByProjectFlockID error: %v", err) - } - - if totalWeightProduced == 0 { - return 0 - } - - hppPerKg := totalActualCost / totalWeightProduced - return hppPerKg + return cost }