adjust api hpp per kandang and implement common service hpp

This commit is contained in:
giovanni
2026-01-22 17:37:28 +07:00
parent 58b29501c0
commit 0d585a99a6
4 changed files with 47 additions and 207 deletions
@@ -6,7 +6,6 @@ import (
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"
)
@@ -133,60 +132,6 @@ func (r *hppPerKandangRepository) GetRowsByPeriod(ctx context.Context, start, en
func (r *hppPerKandangRepository) GetFeedOvkDocCostByPeriod(ctx context.Context, start, end time.Time, projectFlockKandangIDs []uint) ([]HppPerKandangCostRow, []HppPerKandangSupplierRow, error) {
var rows []HppPerKandangCostRow
purchaseStockableKey := fifo.StockableKeyPurchaseItems.String()
transferStockableKey := fifo.StockableKeyStockTransferIn.String()
latestApproval := r.db.WithContext(ctx).
Table("approvals AS a").
Select("a.approvable_id, a.action").
Joins(`
JOIN (
SELECT approvable_id, MAX(action_at) AS latest_action_at
FROM approvals
WHERE approvable_type = ?
GROUP BY approvable_id
) AS la ON la.approvable_id = a.approvable_id AND la.latest_action_at = a.action_at`,
string(utils.ApprovalWorkflowRecording),
)
query := r.db.WithContext(ctx).
Table("recordings AS r").
Select(`
pfk.id AS project_flock_kandang_id,
COALESCE(SUM(CASE
WHEN f.name = ? THEN COALESCE(sa.qty, 0) * COALESCE(pi.price, 0)
WHEN sa.stockable_type = ? AND tf.name = ? THEN COALESCE(std.total_qty, 0) * COALESCE(tpi.price, 0)
ELSE 0
END), 0) AS feed_cost,
COALESCE(SUM(CASE
WHEN f.name = ? THEN COALESCE(sa.qty, 0) * COALESCE(pi.price, 0)
WHEN sa.stockable_type = ? AND tf.name = ? THEN COALESCE(std.total_qty, 0) * COALESCE(tpi.price, 0)
ELSE 0
END), 0) AS ovk_cost`,
utils.FlagPakan, transferStockableKey, utils.FlagPakan,
utils.FlagOVK, transferStockableKey, utils.FlagOVK).
Joins("JOIN project_flock_kandangs AS pfk ON pfk.id = r.project_flock_kandangs_id").
Joins("JOIN kandangs AS k ON k.id = pfk.kandang_id").
Joins("LEFT JOIN (?) AS la ON la.approvable_id = r.id", latestApproval).
Joins("LEFT JOIN recording_stocks AS rs ON rs.recording_id = r.id").
Joins("LEFT JOIN stock_allocations AS sa ON sa.usable_type = ? AND sa.usable_id = rs.id AND sa.status = ?", fifo.UsableKeyRecordingStock.String(), entity.StockAllocationStatusActive).
Joins("LEFT JOIN purchase_items AS pi ON pi.id = sa.stockable_id AND sa.stockable_type = ?", purchaseStockableKey).
Joins("LEFT JOIN stock_transfer_details AS std ON std.id = sa.stockable_id AND sa.stockable_type = ?", transferStockableKey).
Joins("LEFT JOIN stock_transfers AS st ON st.id = std.stock_transfer_id").
Joins("LEFT JOIN purchase_items AS tpi ON tpi.product_id = std.product_id AND tpi.warehouse_id = st.from_warehouse_id").
Joins("LEFT JOIN flags AS f ON f.flagable_id = pi.product_id AND f.flagable_type = ?", entity.FlagableTypeProduct).
Joins("LEFT JOIN flags AS tf ON tf.flagable_id = std.product_id AND tf.flagable_type = ?", entity.FlagableTypeProduct).
Where("r.project_flock_kandangs_id IN ?", projectFlockKandangIDs).
Where("r.record_datetime < ?", end).
Where("r.deleted_at IS NULL").
Where("(la.action IS NULL OR la.action != ?)", string(entity.ApprovalActionRejected))
query = query.Group("pfk.id").Order("pfk.id ASC")
if err := query.Scan(&rows).Error; err != nil {
return nil, nil, err
}
docRows := make([]struct {
ProjectFlockKandangID uint
DocCost float64
@@ -262,127 +207,7 @@ func (r *hppPerKandangRepository) GetFeedOvkDocCostByPeriod(ctx context.Context,
}
}
budgetRows := make([]struct {
ProjectFlockKandangID uint
BudgetCost float64
}, 0)
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")
budgetQuery := r.db.WithContext(ctx).
Table("project_flock_kandangs AS pfk").
Select(`
pfk.id AS project_flock_kandang_id,
COALESCE(SUM((pb.qty * pb.price) * COALESCE(k_usage.kandang_usage_qty, 0) / NULLIF(p_usage.project_usage_qty, 0)), 0) AS budget_cost`).
Joins("JOIN kandangs AS k ON k.id = pfk.kandang_id").
Joins("JOIN locations AS loc ON loc.id = k.location_id").
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 IN (?)", projectFlockKandangIDs).
Group("pfk.id")
// budgetQuery = applyLocationFilters(budgetQuery, areaIDs, locationIDs, kandangIDs)
if err := budgetQuery.Scan(&budgetRows).Error; err != nil {
return nil, nil, err
}
for _, budget := range budgetRows {
entry, ok := costMap[budget.ProjectFlockKandangID]
if !ok {
rows = append(rows, HppPerKandangCostRow{
ProjectFlockKandangID: budget.ProjectFlockKandangID,
})
entry = &rows[len(rows)-1]
costMap[budget.ProjectFlockKandangID] = entry
}
entry.BudgetCost += budget.BudgetCost
}
expenseRows := make([]struct {
ProjectFlockKandangID uint
ExpenseCost float64
}, 0)
expenseQuery := r.db.WithContext(ctx).
Table("project_flock_kandangs AS pfk").
Select(`
pfk.id AS project_flock_kandang_id,
COALESCE(SUM(er.qty * er.price), 0) AS expense_cost`).
Joins("JOIN kandangs AS k ON k.id = pfk.kandang_id").
Joins("JOIN locations AS loc ON loc.id = k.location_id").
Joins("JOIN expense_nonstocks AS en ON en.project_flock_kandang_id = pfk.id").
Joins("JOIN expense_realizations AS er ON er.expense_nonstock_id = en.id").
Where("pfk.id IN (?)", projectFlockKandangIDs).
Group("pfk.id")
// expenseQuery = applyLocationFilters(expenseQuery, areaIDs, locationIDs, kandangIDs)
if err := expenseQuery.Scan(&expenseRows).Error; err != nil {
return nil, nil, err
}
for _, exp := range expenseRows {
entry, ok := costMap[exp.ProjectFlockKandangID]
if !ok {
rows = append(rows, HppPerKandangCostRow{
ProjectFlockKandangID: exp.ProjectFlockKandangID,
})
entry = &rows[len(rows)-1]
costMap[exp.ProjectFlockKandangID] = entry
}
entry.ExpenseCost += exp.ExpenseCost
}
feedSuppliers := make([]HppPerKandangSupplierRow, 0)
feedQuery := r.db.WithContext(ctx).
Table("recordings AS r").
Select("DISTINCT pfk.id AS project_flock_kandang_id, s.id AS supplier_id, s.name AS supplier_name, s.alias AS supplier_alias").
Joins("JOIN project_flock_kandangs AS pfk ON pfk.id = r.project_flock_kandangs_id").
Joins("JOIN kandangs AS k ON k.id = pfk.kandang_id").
Joins("JOIN locations AS loc ON loc.id = k.location_id").
Joins("LEFT JOIN recording_stocks AS rs ON rs.recording_id = r.id").
Joins("LEFT JOIN stock_allocations AS sa ON sa.usable_type = ? AND sa.usable_id = rs.id AND sa.status = ?", fifo.UsableKeyRecordingStock.String(), entity.StockAllocationStatusActive).
Joins("LEFT JOIN purchase_items AS pi ON pi.id = sa.stockable_id AND sa.stockable_type = ?", purchaseStockableKey).
Joins("LEFT JOIN purchases AS pur ON pur.id = pi.purchase_id").
Joins("LEFT JOIN suppliers AS s ON s.id = pur.supplier_id").
Joins("LEFT JOIN flags AS f ON f.flagable_id = pi.product_id AND f.flagable_type = ?", entity.FlagableTypeProduct).
Where("f.name IN ?", []utils.FlagType{utils.FlagPakan, utils.FlagOVK}).
Where("r.project_flock_kandangs_id IN (?)", projectFlockKandangIDs).
Where("r.record_datetime < ?", end).
Where("r.deleted_at IS NULL")
// feedQuery = applyLocationFilters(feedQuery, areaIDs, locationIDs, kandangIDs)
if err := feedQuery.Scan(&feedSuppliers).Error; err != nil {
return nil, nil, err
}
for i := range feedSuppliers {
if _, exists := costMap[feedSuppliers[i].ProjectFlockKandangID]; !exists {
rows = append(rows, HppPerKandangCostRow{
ProjectFlockKandangID: feedSuppliers[i].ProjectFlockKandangID,
})
costMap[feedSuppliers[i].ProjectFlockKandangID] = &rows[len(rows)-1]
}
feedSuppliers[i].Category = "FEED"
}
supplierRows := append(docSuppliers, feedSuppliers...)
return rows, supplierRows, nil
return rows, docSuppliers, nil
}
func (r *hppPerKandangRepository) GetEggProductionByProjectFlockKandangIDs(ctx context.Context, start, end time.Time, projectFlockKandangIDs []uint) (map[uint]HppPerKandangRow, error) {