module analytics.modules.category_spend; import handy_http_primitives : Optional; import std.algorithm; import std.array; import analytics.data; import profile.data; import util.money : Currency; import util.data : TimeRange; CategorySpendData[] computeCategorySpend( ProfileDataSource ds, in Currency currency, in TimeRange timeRange, in Optional!ulong parentId ) { AnalyticsRepository repo = ds.getAnalyticsRepository(); CategorySpendData[] allCategories = repo.getCategorySpendData(currency, timeRange); return allCategories .filter!(d => ( parentId ? d.parentCategoryId && d.parentCategoryId.value == parentId.value : d.parentCategoryId.isNull )) .map!((category) { // For each category that we're reporting on, recursively sum up // the amount of the category and all its children. long totalRecursiveSum = sumAllChildCategoriesRecursive(category, allCategories); return CategorySpendData( category.categoryId, category.categoryName, category.categoryColor, category.parentCategoryId, totalRecursiveSum ); }) .array(); } private long sumAllChildCategoriesRecursive(in CategorySpendData parentCategory, in CategorySpendData[] data) { long sum = parentCategory.amount; foreach (category; data) { if (category.parentCategoryId && category.parentCategoryId.value == parentCategory.categoryId) { sum += sumAllChildCategoriesRecursive(category, data); } } return sum; }