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 }