mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
feat[BE-384]: enhance reporting by adding chickin quantity and egg production weight calculations; refactor HPP calculations to consider product categories
This commit is contained in:
@@ -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")
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user