feat: export input progress report for expenses, marketings, purchases, and recordings

This commit is contained in:
Adnan Zahir
2026-04-21 21:24:19 +07:00
parent a98a709766
commit 5e7c51e9c2
18 changed files with 1378 additions and 0 deletions
@@ -6,6 +6,7 @@ import (
"fmt"
"time"
"gitlab.com/mbugroup/lti-api.git/internal/common/exportprogress"
"gitlab.com/mbugroup/lti-api.git/internal/common/repository"
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
"gitlab.com/mbugroup/lti-api.git/internal/utils"
@@ -20,6 +21,7 @@ type ExpenseRepository interface {
WithProjectFlockKandangFilter(pfkID, kandangID uint) func(*gorm.DB) *gorm.DB
CountUnfinishedByProjectFlockKandang(ctx context.Context, pfkID, kandangID uint, isFinished func(*entity.Approval) bool) (int64, error)
DeleteOne(ctx context.Context, id uint) error
GetProgressRows(ctx context.Context, startDate, endDate time.Time, allowedLocationIDs []uint, restrict bool) ([]exportprogress.Row, error)
}
type ExpenseRepositoryImpl struct {
@@ -130,3 +132,64 @@ func (r *ExpenseRepositoryImpl) DeleteOne(ctx context.Context, id uint) error {
}
return nil
}
func (r *ExpenseRepositoryImpl) GetProgressRows(ctx context.Context, startDate, endDate time.Time, allowedLocationIDs []uint, restrict bool) ([]exportprogress.Row, error) {
const unassignedSQL = "'" + exportprogress.UnassignedKandangName + "'"
query := r.DB().WithContext(ctx).
Table("expenses AS e").
Select(`
'Expenses' AS module,
COALESCE(pf.flock_name, loc.name, fallback_loc.name, 'Unknown Farm') AS farm_name,
COALESCE(k.name, `+unassignedSQL+`, 'Unknown Kandang') AS kandang_name,
DATE(e.transaction_date) AS activity_date,
COUNT(*) AS count
`).
Joins("LEFT JOIN (SELECT DISTINCT expense_id, project_flock_kandang_id, kandang_id FROM expense_nonstocks) en ON en.expense_id = e.id").
Joins("LEFT JOIN project_flock_kandangs pfk ON pfk.id = en.project_flock_kandang_id").
Joins("LEFT JOIN project_flocks pf ON pf.id = pfk.project_flock_id").
Joins("LEFT JOIN kandangs k ON k.id = COALESCE(en.kandang_id, pfk.kandang_id)").
Joins("LEFT JOIN locations loc ON loc.id = k.location_id").
Joins("LEFT JOIN locations fallback_loc ON fallback_loc.id = e.location_id").
Where("e.deleted_at IS NULL").
Where("DATE(e.transaction_date) >= DATE(?)", startDate).
Where("DATE(e.transaction_date) <= DATE(?)", endDate)
if restrict {
if len(allowedLocationIDs) == 0 {
return []exportprogress.Row{}, nil
}
query = query.Where("e.location_id IN ?", allowedLocationIDs)
}
type progressRowResult struct {
Module string
FarmName string
KandangName string
ActivityDate string
Count int
}
scanned := make([]progressRowResult, 0)
err := query.
Group("DATE(e.transaction_date), COALESCE(pf.flock_name, loc.name, fallback_loc.name, 'Unknown Farm'), COALESCE(k.name, " + unassignedSQL + ", 'Unknown Kandang')").
Order("activity_date ASC, farm_name ASC, kandang_name ASC").
Scan(&scanned).Error
if err != nil {
return nil, err
}
rows := make([]exportprogress.Row, 0, len(scanned))
for _, item := range scanned {
activityDate, err := time.Parse("2006-01-02", item.ActivityDate)
if err != nil {
return nil, err
}
rows = append(rows, exportprogress.Row{
Module: item.Module,
FarmName: item.FarmName,
KandangName: item.KandangName,
ActivityDate: activityDate,
Count: item.Count,
})
}
return rows, nil
}