diff --git a/.env.prod b/.env.prod index 00cde05..86b2978 100644 --- a/.env.prod +++ b/.env.prod @@ -107,4 +107,13 @@ MAX_IMAGES_PER_TX=9 ALIYUN_ACCESS_KEY_ID= ALIYUN_ACCESS_KEY_SECRET= ALIYUN_SIGN_NAME= -ALIYUN_TEMPLATE_CODE= \ No newline at end of file +ALIYUN_TEMPLATE_CODE= + +# ============================================ +# SMTP 邮件配置 (发送通知邮件) +# ============================================ +SMTP_HOST=smtp.qq.com +SMTP_PORT=587 +SMTP_USER= +SMTP_PASSWORD= +SMTP_FROM= \ No newline at end of file diff --git a/internal/repository/budget_repository.go b/internal/repository/budget_repository.go index ce3f8db..51e6477 100644 --- a/internal/repository/budget_repository.go +++ b/internal/repository/budget_repository.go @@ -144,11 +144,13 @@ func (r *BudgetRepository) GetSpentAmount(budget *models.Budget, startDate, endD // Filter by category if specified if budget.CategoryID != nil { - // Get sub-categories - var subCategoryIDs []uint - r.db.Model(&models.Category{}).Where("parent_id = ?", *budget.CategoryID).Pluck("id", &subCategoryIDs) + // Get all sub-categories recursively + subCategoryIDs, err := r.getAllSubCategoryIDs(*budget.CategoryID) + if err != nil { + return 0, fmt.Errorf("failed to get sub-categories: %w", err) + } - // Include the category itself and all its children + // Include the category itself and all its descendant children categoryIDs := append(subCategoryIDs, *budget.CategoryID) query = query.Where("category_id IN ?", categoryIDs) } @@ -165,6 +167,29 @@ func (r *BudgetRepository) GetSpentAmount(budget *models.Budget, startDate, endD return totalSpent, nil } +// getAllSubCategoryIDs helps to find all descendant category IDs +func (r *BudgetRepository) getAllSubCategoryIDs(parentID uint) ([]uint, error) { + var allIDs []uint + var currentLevelIDs = []uint{parentID} + + // Iteratively find children level by level + for len(currentLevelIDs) > 0 { + var nextLevelIDs []uint + if err := r.db.Model(&models.Category{}).Where("parent_id IN ?", currentLevelIDs).Pluck("id", &nextLevelIDs).Error; err != nil { + return nil, err + } + + if len(nextLevelIDs) == 0 { + break + } + + allIDs = append(allIDs, nextLevelIDs...) + currentLevelIDs = nextLevelIDs + } + + return allIDs, nil +} + // ExistsByID checks if a budget with the given ID exists for a user func (r *BudgetRepository) ExistsByID(userID, id uint) (bool, error) { var count int64