FEAT[BE]: implement expense report retrieval with filtering options

This commit is contained in:
aguhh18
2025-12-15 09:11:26 +07:00
parent c79e35c217
commit cbb3368141
12 changed files with 330 additions and 158 deletions
@@ -5,6 +5,8 @@ import (
"gitlab.com/mbugroup/lti-api.git/internal/common/repository"
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/repports/validations"
"gitlab.com/mbugroup/lti-api.git/internal/utils"
"gorm.io/gorm"
)
@@ -13,6 +15,7 @@ type ExpenseRealizationRepository interface {
IdExists(ctx context.Context, id uint64) (bool, error)
GetByExpenseNonstockID(ctx context.Context, expenseNonstockID uint64) (*entity.ExpenseRealization, error)
GetByProjectFlockID(ctx context.Context, projectFlockID uint) ([]entity.ExpenseRealization, error)
GetAllWithFilters(ctx context.Context, offset, limit int, filters *validation.Query) ([]entity.ExpenseRealization, int64, error)
}
type ExpenseRealizationRepositoryImpl struct {
@@ -50,3 +53,83 @@ func (r *ExpenseRealizationRepositoryImpl) GetByProjectFlockID(ctx context.Conte
Find(&realizations).Error
return realizations, err
}
func (r *ExpenseRealizationRepositoryImpl) GetAllWithFilters(ctx context.Context, offset, limit int, filters *validation.Query) ([]entity.ExpenseRealization, int64, error) {
var realizations []entity.ExpenseRealization
var total int64
db := r.DB().WithContext(ctx).
Model(&entity.ExpenseRealization{}).
Preload("ExpenseNonstock", func(db *gorm.DB) *gorm.DB {
return db.
Preload("Expense").
Preload("Expense.Supplier").
Preload("Kandang").
Preload("Kandang.Location").
Preload("Nonstock")
}).
Joins("JOIN expense_nonstocks ON expense_nonstocks.id = expense_realizations.expense_nonstock_id").
Joins("JOIN expenses ON expenses.id = expense_nonstocks.expense_id").
Joins("LEFT JOIN suppliers ON suppliers.id = expenses.supplier_id")
if filters.Search != "" {
db = db.Where("expenses.category LIKE ? OR expenses.reference_number LIKE ? OR expenses.po_number LIKE ? OR expenses.notes LIKE ? OR suppliers.name LIKE ?",
"%"+filters.Search+"%", "%"+filters.Search+"%", "%"+filters.Search+"%", "%"+filters.Search+"%", "%"+filters.Search+"%")
}
if filters.Category != "" {
db = db.Where("expenses.category = ?", filters.Category)
}
if filters.SupplierId > 0 {
db = db.Where("expenses.supplier_id = ?", filters.SupplierId)
}
if filters.KandangId > 0 {
db = db.Where("expense_nonstocks.kandang_id = ?", filters.KandangId)
}
if filters.ProjectFlockKandangId > 0 {
db = db.Where("expense_nonstocks.project_flock_kandang_id = ?", filters.ProjectFlockKandangId)
}
if filters.NonstockId > 0 {
db = db.Where("expense_nonstocks.nonstock_id = ?", filters.NonstockId)
}
locationID := filters.LocationId
areaID := filters.AreaId
if locationID > 0 || areaID > 0 {
db = db.Joins("JOIN kandangs ON kandangs.id = expense_nonstocks.kandang_id")
if locationID > 0 {
db = db.Where("kandangs.location_id = ?", uint(locationID))
}
if areaID > 0 {
db = db.Joins("JOIN locations ON locations.id = kandangs.location_id").
Where("locations.area_id = ?", uint(areaID))
}
}
if filters.RealizationDate != "" {
if realizationDate, err := utils.ParseDateString(filters.RealizationDate); err == nil {
db = db.Where("DATE(expenses.realization_date) = ?", realizationDate)
}
}
if err := db.Count(&total).Error; err != nil {
return nil, 0, err
}
if err := db.
Offset(offset).
Limit(limit).
Order("expense_realizations.created_at DESC").
Find(&realizations).Error; err != nil {
return nil, 0, err
}
return realizations, total, nil
}