diff --git a/internal/common/repository/common.hpp.repository.go b/internal/common/repository/common.hpp.repository.go index f9bbaa3c..74ed5261 100644 --- a/internal/common/repository/common.hpp.repository.go +++ b/internal/common/repository/common.hpp.repository.go @@ -11,11 +11,15 @@ import ( ) type HppCostRepository interface { - GetDocCost(ctx context.Context, projectFlockKandangId uint) (float64, error) - GetBudgetCost(ctx context.Context, projectFlockKandangId uint) (float64, error) - GetExpedisionCost(ctx context.Context, projectFlockKandangId uint) (float64, error) - GetFeedCost(ctx context.Context, projectFlockKandangId uint, date *time.Time) (float64, error) - GetOvkCost(ctx context.Context, projectFlockKandangId uint, date *time.Time) (float64, error) + GetProjectFlockKandangIDs(ctx context.Context, projectFlockId uint) ([]uint, error) + GetDocCost(ctx context.Context, kandangIDs []uint) (float64, error) + GetBudgetCostByProjectFlockId(ctx context.Context, projectFlockId uint) (float64, error) + GetExpedisionCost(ctx context.Context, kandangIDs []uint) (float64, error) + GetFeedCost(ctx context.Context, kandangIDs []uint, date *time.Time) (float64, error) + GetOvkCost(ctx context.Context, kandangIDs []uint, date *time.Time) (float64, error) + GetTotalPopulation(ctx context.Context, kandangIDs []uint) (float64, error) + GetPulletCost(ctx context.Context, projectFlockKandangId uint) (float64, error) + GetTransferSourceSummary(ctx context.Context, projectFlockKandangId uint) (uint, float64, error) } type HppRepositoryImpl struct { @@ -26,14 +30,28 @@ func NewHppCostRepository(db *gorm.DB) HppCostRepository { return &HppRepositoryImpl{db: db} } -func (r *HppRepositoryImpl) GetDocCost(ctx context.Context, projectFlockKandangId uint) (float64, error) { +func (r *HppRepositoryImpl) GetProjectFlockKandangIDs(ctx context.Context, projectFlockId uint) ([]uint, error) { + var ids []uint + err := r.db.WithContext(ctx). + Table("project_flock_kandangs"). + Select("id"). + Where("project_flock_id = ?", projectFlockId). + Scan(&ids).Error + if err != nil { + return nil, err + } + + return ids, nil +} + +func (r *HppRepositoryImpl) GetDocCost(ctx context.Context, kandangIDs []uint) (float64, error) { var total float64 err := r.db.WithContext(ctx). Table("project_chickins AS pc"). Select("COALESCE(SUM(pc.usage_qty * COALESCE(pi.price, 0)), 0)"). Joins("JOIN stock_allocations AS sa ON sa.usable_type = ? AND sa.usable_id = pc.id AND sa.stockable_type = ?", fifo.UsableKeyProjectChickin.String(), fifo.StockableKeyPurchaseItems.String()). Joins("JOIN purchase_items AS pi ON pi.id = sa.stockable_id"). - Where("pc.project_flock_kandang_id = ?", projectFlockKandangId). + Where("pc.project_flock_kandang_id IN (?)", kandangIDs). Scan(&total).Error if err != nil { return 0, err @@ -42,31 +60,12 @@ func (r *HppRepositoryImpl) GetDocCost(ctx context.Context, projectFlockKandangI return total, nil } -func (r *HppRepositoryImpl) GetBudgetCost(ctx context.Context, projectFlockKandangId uint) (float64, error) { - pfkUsageSub := r.db. - Table("project_chickins AS pc"). - Select(` - pc.project_flock_kandang_id, - SUM(pc.usage_qty) AS kandang_usage_qty`). - Group("pc.project_flock_kandang_id") - - projectUsageSub := r.db. - Table("project_chickins AS pc"). - Select(` - pfk.project_flock_id, - SUM(pc.usage_qty) AS project_usage_qty`). - Joins("JOIN project_flock_kandangs AS pfk ON pfk.id = pc.project_flock_kandang_id"). - Group("pfk.project_flock_id") - +func (r *HppRepositoryImpl) GetBudgetCostByProjectFlockId(ctx context.Context, projectFlockId uint) (float64, error) { var total float64 err := r.db.WithContext(ctx). - Table("project_flock_kandangs AS pfk"). - Select(` - COALESCE(SUM((pb.qty * pb.price) * COALESCE(k_usage.kandang_usage_qty, 0) / NULLIF(p_usage.project_usage_qty, 0)), 0)`). - Joins("JOIN project_budgets AS pb ON pb.project_flock_id = pfk.project_flock_id"). - Joins("LEFT JOIN (?) AS k_usage ON k_usage.project_flock_kandang_id = pfk.id", pfkUsageSub). - Joins("LEFT JOIN (?) AS p_usage ON p_usage.project_flock_id = pfk.project_flock_id", projectUsageSub). - Where("pfk.id = ?", projectFlockKandangId). + Table("project_chickin_details AS pcd"). + Select("COALESCE(SUM(pcd.qty * pcd.price), 0)"). + Where("pcd.project_flock_id = ?", projectFlockId). Scan(&total).Error if err != nil { return 0, err @@ -75,13 +74,15 @@ func (r *HppRepositoryImpl) GetBudgetCost(ctx context.Context, projectFlockKanda return total, nil } -func (r *HppRepositoryImpl) GetExpedisionCost(ctx context.Context, projectFlockKandangId uint) (float64, error) { +func (r *HppRepositoryImpl) GetExpedisionCost(ctx context.Context, kandangIDs []uint) (float64, error) { var total float64 err := r.db.WithContext(ctx). Table("expense_nonstocks AS en"). Select("COALESCE(SUM(er.qty * er.price), 0)"). Joins("JOIN expense_realizations AS er ON er.expense_nonstock_id = en.id"). - Where("en.project_flock_kandang_id = ?", projectFlockKandangId). + Joins("JOIN flags AS f ON f.flagable_id = en.nonstock_id AND f.flagable_type = ?", entity.FlagableTypeNonstock). + Where("en.project_flock_kandang_id IN (?)", kandangIDs). + Where("f.name = ?", utils.FlagEkspedisi). Scan(&total).Error if err != nil { return 0, err @@ -90,7 +91,7 @@ func (r *HppRepositoryImpl) GetExpedisionCost(ctx context.Context, projectFlockK return total, nil } -func (r *HppRepositoryImpl) GetFeedCost(ctx context.Context, projectFlockKandangId uint, date *time.Time) (float64, error) { +func (r *HppRepositoryImpl) GetFeedCost(ctx context.Context, kandangIDs []uint, date *time.Time) (float64, error) { if date == nil { now := time.Now() date = &now @@ -105,7 +106,7 @@ func (r *HppRepositoryImpl) GetFeedCost(ctx context.Context, projectFlockKandang Joins("JOIN flags AS f ON f.flagable_id = pw.product_id AND f.flagable_type = ?", entity.FlagableTypeProduct). Joins("JOIN stock_allocations AS sa ON sa.usable_type = ? AND sa.usable_id = rs.id AND sa.stockable_type = ?", fifo.UsableKeyRecordingStock.String(), fifo.StockableKeyPurchaseItems.String()). Joins("JOIN purchase_items AS pi ON pi.id = sa.stockable_id"). - Where("r.project_flock_kandangs_id = ?", projectFlockKandangId). + Where("r.project_flock_kandangs_id IN (?)", kandangIDs). Where("r.record_datetime <= ?", *date). Where("f.name = ?", utils.FlagPakan). Scan(&total).Error @@ -116,7 +117,7 @@ func (r *HppRepositoryImpl) GetFeedCost(ctx context.Context, projectFlockKandang return total, nil } -func (r *HppRepositoryImpl) GetOvkCost(ctx context.Context, projectFlockKandangId uint, date *time.Time) (float64, error) { +func (r *HppRepositoryImpl) GetOvkCost(ctx context.Context, kandangIDs []uint, date *time.Time) (float64, error) { if date == nil { now := time.Now() date = &now @@ -138,7 +139,7 @@ func (r *HppRepositoryImpl) GetOvkCost(ctx context.Context, projectFlockKandangI Joins("JOIN flags AS f ON f.flagable_id = pw.product_id AND f.flagable_type = ?", entity.FlagableTypeProduct). Joins("JOIN stock_allocations AS sa ON sa.usable_type = ? AND sa.usable_id = rs.id AND sa.stockable_type = ?", fifo.UsableKeyRecordingStock.String(), fifo.StockableKeyPurchaseItems.String()). Joins("JOIN purchase_items AS pi ON pi.id = sa.stockable_id"). - Where("r.project_flock_kandangs_id = ?", projectFlockKandangId). + Where("r.project_flock_kandangs_id IN (?)", kandangIDs). Where("r.record_datetime <= ?", *date). Where("f.name IN ?", flags). Scan(&total).Error @@ -148,3 +149,63 @@ func (r *HppRepositoryImpl) GetOvkCost(ctx context.Context, projectFlockKandangI return total, nil } + +func (r *HppRepositoryImpl) GetTotalPopulation(ctx context.Context, kandangIDs []uint) (float64, error) { + var total float64 + err := r.db.WithContext(ctx). + Table("project_chickins AS pc"). + Select("COALESCE(SUM(pc.usage_qty), 0)"). + Where("pc.project_flock_kandang_id IN (?)", kandangIDs). + Scan(&total).Error + if err != nil { + return 0, err + } + + return total, nil +} + +func (r *HppRepositoryImpl) GetPulletCost(ctx context.Context, projectFlockKandangId uint) (float64, error) { + stockablePurchase := fifo.StockableKeyPurchaseItems.String() + stockableTransferIn := fifo.StockableKeyStockTransferIn.String() + usableProjectChickin := fifo.UsableKeyProjectChickin.String() + + var total float64 + err := r.db.WithContext(ctx). + Table("project_chickins AS pc"). + Select(` + COALESCE(SUM(pc.usage_qty * CASE + WHEN sa.stockable_type = ? THEN COALESCE(pi.price, 0) + WHEN sa.stockable_type = ? THEN COALESCE(tpi.price, 0) + ELSE 0 + END), 0)`, + stockablePurchase, stockableTransferIn). + Joins("JOIN stock_allocations AS sa ON sa.usable_type = ? AND sa.usable_id = pc.id", usableProjectChickin). + Joins("LEFT JOIN purchase_items AS pi ON pi.id = sa.stockable_id AND sa.stockable_type = ?", stockablePurchase). + Joins("LEFT JOIN stock_allocations AS tsa ON tsa.usable_type = ? AND tsa.usable_id = sa.stockable_id AND sa.stockable_type = ? AND tsa.stockable_type = ?", stockableTransferIn, stockableTransferIn, stockablePurchase). + Joins("LEFT JOIN purchase_items AS tpi ON tpi.id = tsa.stockable_id"). + Where("pc.project_flock_kandang_id = ?", projectFlockKandangId). + Scan(&total).Error + if err != nil { + return 0, err + } + + return total, nil +} + +func (r *HppRepositoryImpl) GetTransferSourceSummary(ctx context.Context, projectFlockKandangId uint) (uint, float64, error) { + var summary struct { + ProjectFlockID uint + TotalQty float64 + } + err := r.db.WithContext(ctx). + Table("laying_transfer_targets AS ltt"). + Select("lt.from_project_flock_id AS project_flock_id, COALESCE(SUM(ltt.total_qty), 0) AS total_qty"). + Joins("JOIN laying_transfers AS lt ON lt.id = ltt.laying_transfer_id"). + Where("ltt.target_project_flock_kandang_id = ?", projectFlockKandangId). + Scan(&summary).Error + if err != nil { + return 0, 0, err + } + + return summary.ProjectFlockID, summary.TotalQty, nil +} diff --git a/internal/common/service/common.hpp.service.go b/internal/common/service/common.hpp.service.go index 5ef9091e..8a78aded 100644 --- a/internal/common/service/common.hpp.service.go +++ b/internal/common/service/common.hpp.service.go @@ -9,7 +9,8 @@ import ( type HppService interface { CalculateHppCost(projectFlockKandangId uint, date *time.Time) (*HppCostResponse, error) - GetTotalDepresiasi(projectFlockKandangId uint, date *time.Time) (float64, error) + GetTotalDepresiasiFlockGrowing(sourceProjectFlockID uint, date *time.Time) (float64, error) + GetTotalProductionCost(projectFlockKandangId uint, date *time.Time, totalDepresiasiGrowing float64) (float64, error) } type HppCostResponse struct { @@ -39,8 +40,36 @@ func (s *hppService) CalculateHppCost(projectFlockKandangId uint, date *time.Tim date = &now } - // _ = projectFlockKandangId - _ = date + var sourceProjectFlockID uint + var transferTotalQty float64 + var err error + sourceProjectFlockID, transferTotalQty, err = s.hppRepo.GetTransferSourceSummary(context.Background(), projectFlockKandangId) + if err != nil { + return nil, err + } + + kandangIDsGrowing, err := s.hppRepo.GetProjectFlockKandangIDs(context.Background(), sourceProjectFlockID) + + if err != nil { + return nil, err + } + + totalPopulationFlockGrowing, err := s.hppRepo.GetTotalPopulation(context.Background(), kandangIDsGrowing) + if err != nil { + return nil, err + } + + totalDepresiasiFlockGrowing, err := s.GetTotalDepresiasiFlockGrowing(sourceProjectFlockID, date) + if err != nil { + return nil, err + } + + depresiasiTransfer := (totalDepresiasiFlockGrowing * transferTotalQty) / totalPopulationFlockGrowing + + _, err = s.GetTotalProductionCost(projectFlockKandangId, date, depresiasiTransfer) + if err != nil { + return nil, err + } return &HppCostResponse{ Estimation: HppCostDetail{}, @@ -48,7 +77,7 @@ func (s *hppService) CalculateHppCost(projectFlockKandangId uint, date *time.Tim }, nil } -func (s *hppService) GetTotalDepresiasi(projectFlockKandangId uint, date *time.Time) (float64, error) { +func (s *hppService) GetTotalDepresiasiFlockGrowing(sourceProjectFlockID uint, date *time.Time) (float64, error) { if date == nil { now := time.Now() date = &now @@ -58,32 +87,52 @@ func (s *hppService) GetTotalDepresiasi(projectFlockKandangId uint, date *time.T return 0, nil } - docCost, err := s.hppRepo.GetDocCost(context.Background(), projectFlockKandangId) + kandangIDs, err := s.hppRepo.GetProjectFlockKandangIDs(context.Background(), sourceProjectFlockID) if err != nil { return 0, err } - budgetCost, err := s.hppRepo.GetBudgetCost(context.Background(), projectFlockKandangId) + docCost, err := s.hppRepo.GetDocCost(context.Background(), kandangIDs) if err != nil { return 0, err } - expedisionCost, err := s.hppRepo.GetExpedisionCost(context.Background(), projectFlockKandangId) + budgetCost, err := s.hppRepo.GetBudgetCostByProjectFlockId(context.Background(), sourceProjectFlockID) if err != nil { return 0, err } - feedCost, err := s.hppRepo.GetFeedCost(context.Background(), projectFlockKandangId, date) + expedisionCost, err := s.hppRepo.GetExpedisionCost(context.Background(), kandangIDs) if err != nil { return 0, err } - ovkCost, err := s.hppRepo.GetOvkCost(context.Background(), projectFlockKandangId, date) + feedCost, err := s.hppRepo.GetFeedCost(context.Background(), kandangIDs, date) if err != nil { return 0, err } + ovkCost, err := s.hppRepo.GetOvkCost(context.Background(), kandangIDs, date) + if err != nil { + return 0, err + } + + return docCost + budgetCost + expedisionCost + feedCost + ovkCost, nil +} + +func (s *hppService) GetTotalProductionCost(projectFlockKandangId uint, date *time.Time, depresiasiTransfer float64) (float64, error) { + if date == nil { + now := time.Now() + date = &now + } + + costPullet, err := s.hppRepo.GetPulletCost(context.Background(), projectFlockKandangId) + if err != nil { + return 0, err + + } + _ = date - return docCost + budgetCost + expedisionCost + feedCost + ovkCost, nil + return depresiasiTransfer + costPullet, nil }