package repository import ( "context" "strings" "time" "github.com/google/uuid" "apskel-pos-be/internal/entities" "gorm.io/gorm" ) type ExpenseRepositoryImpl struct { db *gorm.DB } func NewExpenseRepositoryImpl(db *gorm.DB) *ExpenseRepositoryImpl { return &ExpenseRepositoryImpl{ db: db, } } func (r *ExpenseRepositoryImpl) Create(ctx context.Context, expense *entities.Expense) error { return r.db.WithContext(ctx).Create(expense).Error } func (r *ExpenseRepositoryImpl) GetByID(ctx context.Context, id uuid.UUID) (*entities.Expense, error) { var expense entities.Expense err := r.db.WithContext(ctx). Preload("Items.ChartOfAccount"). First(&expense, "id = ?", id).Error if err != nil { return nil, err } return &expense, nil } func (r *ExpenseRepositoryImpl) GetByIDAndOrganizationID(ctx context.Context, id, organizationID uuid.UUID) (*entities.Expense, error) { var expense entities.Expense err := r.db.WithContext(ctx). Preload("Items.ChartOfAccount"). Where("id = ? AND organization_id = ?", id, organizationID). First(&expense).Error if err != nil { return nil, err } return &expense, nil } func (r *ExpenseRepositoryImpl) Update(ctx context.Context, expense *entities.Expense) error { return r.db.WithContext(ctx).Save(expense).Error } func (r *ExpenseRepositoryImpl) Delete(ctx context.Context, id uuid.UUID) error { return r.db.WithContext(ctx).Delete(&entities.Expense{}, "id = ?", id).Error } func (r *ExpenseRepositoryImpl) List(ctx context.Context, organizationID uuid.UUID, filters map[string]interface{}, limit, offset int) ([]*entities.Expense, int64, error) { var expenses []*entities.Expense var total int64 query := r.db.WithContext(ctx).Model(&entities.Expense{}).Where("organization_id = ?", organizationID) for key, value := range filters { switch key { case "search": if searchStr, ok := value.(string); ok && searchStr != "" { searchPattern := "%" + strings.ToLower(searchStr) + "%" query = query.Where(` LOWER(receiver) LIKE ? OR LOWER(code_number) LIKE ? OR LOWER(description) LIKE ? OR EXISTS ( SELECT 1 FROM expense_items ei WHERE ei.expense_id = expenses.id AND LOWER(ei.item) LIKE ? ) `, searchPattern, searchPattern, searchPattern, searchPattern) } case "outlet_id": if outletID, ok := value.(uuid.UUID); ok { query = query.Where("outlet_id = ?", outletID) } case "start_date": if startDate, ok := value.(time.Time); ok { query = query.Where("transaction_date >= ?", startDate) } case "end_date": if endDate, ok := value.(time.Time); ok { query = query.Where("transaction_date <= ?", endDate) } default: query = query.Where(key+" = ?", value) } } if err := query.Count(&total).Error; err != nil { return nil, 0, err } err := query. Preload("Items.ChartOfAccount"). Order("created_at DESC"). Limit(limit). Offset(offset). Find(&expenses).Error return expenses, total, err } func (r *ExpenseRepositoryImpl) CreateItem(ctx context.Context, item *entities.ExpenseItem) error { return r.db.WithContext(ctx).Create(item).Error } func (r *ExpenseRepositoryImpl) DeleteItemsByExpenseID(ctx context.Context, expenseID uuid.UUID) error { return r.db.WithContext(ctx).Delete(&entities.ExpenseItem{}, "expense_id = ?", expenseID).Error }