diff --git a/internal/common/repository/common.hpp.repository.go b/internal/common/repository/common.hpp.repository.go new file mode 100644 index 00000000..f9bbaa3c --- /dev/null +++ b/internal/common/repository/common.hpp.repository.go @@ -0,0 +1,150 @@ +package repository + +import ( + "context" + "time" + + entity "gitlab.com/mbugroup/lti-api.git/internal/entities" + "gitlab.com/mbugroup/lti-api.git/internal/utils" + "gitlab.com/mbugroup/lti-api.git/internal/utils/fifo" + "gorm.io/gorm" +) + +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) +} + +type HppRepositoryImpl struct { + db *gorm.DB +} + +func NewHppCostRepository(db *gorm.DB) HppCostRepository { + return &HppRepositoryImpl{db: db} +} + +func (r *HppRepositoryImpl) GetDocCost(ctx context.Context, projectFlockKandangId 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). + Scan(&total).Error + if err != nil { + return 0, err + } + + 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") + + 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). + Scan(&total).Error + if err != nil { + return 0, err + } + + return total, nil +} + +func (r *HppRepositoryImpl) GetExpedisionCost(ctx context.Context, projectFlockKandangId 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). + Scan(&total).Error + if err != nil { + return 0, err + } + + return total, nil +} + +func (r *HppRepositoryImpl) GetFeedCost(ctx context.Context, projectFlockKandangId uint, date *time.Time) (float64, error) { + if date == nil { + now := time.Now() + date = &now + } + + var total float64 + err := r.db.WithContext(ctx). + Table("recordings AS r"). + Select("COALESCE(SUM(rs.usage_qty * COALESCE(pi.price, 0)), 0)"). + Joins("JOIN recording_stocks AS rs ON rs.recording_id = r.id"). + Joins("JOIN product_warehouses AS pw ON pw.id = rs.product_warehouse_id"). + 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.record_datetime <= ?", *date). + Where("f.name = ?", utils.FlagPakan). + Scan(&total).Error + if err != nil { + return 0, err + } + + return total, nil +} + +func (r *HppRepositoryImpl) GetOvkCost(ctx context.Context, projectFlockKandangId uint, date *time.Time) (float64, error) { + if date == nil { + now := time.Now() + date = &now + } + + flags := []utils.FlagType{ + utils.FlagOVK, + utils.FlagObat, + utils.FlagVitamin, + utils.FlagKimia, + } + + var total float64 + err := r.db.WithContext(ctx). + Table("recordings AS r"). + Select("COALESCE(SUM(rs.usage_qty * COALESCE(pi.price, 0)), 0)"). + Joins("JOIN recording_stocks AS rs ON rs.recording_id = r.id"). + Joins("JOIN product_warehouses AS pw ON pw.id = rs.product_warehouse_id"). + 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.record_datetime <= ?", *date). + Where("f.name IN ?", flags). + Scan(&total).Error + if err != nil { + return 0, err + } + + return total, nil +} diff --git a/internal/common/service/common.hpp.service.go b/internal/common/service/common.hpp.service.go new file mode 100644 index 00000000..5ef9091e --- /dev/null +++ b/internal/common/service/common.hpp.service.go @@ -0,0 +1,89 @@ +package service + +import ( + "context" + "time" + + commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository" +) + +type HppService interface { + CalculateHppCost(projectFlockKandangId uint, date *time.Time) (*HppCostResponse, error) + GetTotalDepresiasi(projectFlockKandangId uint, date *time.Time) (float64, error) +} + +type HppCostResponse struct { + Estimation HppCostDetail `json:"estimation"` + Real HppCostDetail `json:"real"` +} + +type HppCostDetail struct { + HargaKg float64 `json:"harga_kg"` + HargaButir float64 `json:"harga_butir"` + Total float64 `json:"total"` + Kg float64 `json:"kg"` + Butir float64 `json:"butir"` +} + +type hppService struct { + hppRepo commonRepo.HppCostRepository +} + +func NewHppService(hppRepo commonRepo.HppCostRepository) HppService { + return &hppService{hppRepo: hppRepo} +} + +func (s *hppService) CalculateHppCost(projectFlockKandangId uint, date *time.Time) (*HppCostResponse, error) { + if date == nil { + now := time.Now() + date = &now + } + + // _ = projectFlockKandangId + _ = date + + return &HppCostResponse{ + Estimation: HppCostDetail{}, + Real: HppCostDetail{}, + }, nil +} + +func (s *hppService) GetTotalDepresiasi(projectFlockKandangId uint, date *time.Time) (float64, error) { + if date == nil { + now := time.Now() + date = &now + } + + if s.hppRepo == nil { + return 0, nil + } + + docCost, err := s.hppRepo.GetDocCost(context.Background(), projectFlockKandangId) + if err != nil { + return 0, err + } + + budgetCost, err := s.hppRepo.GetBudgetCost(context.Background(), projectFlockKandangId) + if err != nil { + return 0, err + } + + expedisionCost, err := s.hppRepo.GetExpedisionCost(context.Background(), projectFlockKandangId) + if err != nil { + return 0, err + } + + feedCost, err := s.hppRepo.GetFeedCost(context.Background(), projectFlockKandangId, date) + if err != nil { + return 0, err + } + + ovkCost, err := s.hppRepo.GetOvkCost(context.Background(), projectFlockKandangId, date) + if err != nil { + return 0, err + } + + _ = date + + return docCost + budgetCost + expedisionCost + feedCost + ovkCost, nil +}