{"size": 5145, "ext": "js", "max_stars_repo_path": "server/controllers/yearly-report.controller.js", "max_stars_repo_name": "LaeticiaW/expense-tracker", "max_stars_repo_stars_event_min_datetime": null, "max_stars_repo_stars_event_max_datetime": null, "max_issues_repo_path": "server/controllers/yearly-report.controller.js", "max_issues_repo_name": "LaeticiaW/expense-tracker", "max_issues_repo_issues_event_min_datetime": "2022-02-13T14:33:43.000Z", "max_issues_repo_issues_event_max_datetime": "2022-03-02T08:50:57.000Z", "max_forks_repo_path": "server/controllers/yearly-report.controller.js", "max_forks_repo_name": "LaeticiaW/expense-tracker", "max_forks_repo_forks_event_min_datetime": null, "max_forks_repo_forks_event_max_datetime": null}
{"max_stars_count": null, "max_issues_count": 2, "max_forks_count": null, "avg_line_length": 35.979020979, "max_line_length": 100, "alphanum_fraction": 0.3638483965}
var Report = require('mongoose').model('MonthlyExpenses'),
    Category = require('mongoose').model('Category');

exports.getYearlyExpenses = function(req, res, next) {

    Report.aggregate([
        {
            $project: {
                year: {$year: "$trxDate"},
                category: "$categoryId",
                subcategory: "$subcategory",
                amount: "$amount"
            }
        },
        {
            $sort: {category: 1, subcategory: 1, year: 1}
        },
        {
            $group: {
                _id: {category: "$category", subcategory: "$subcategory", year: "$year"},
                total: {$sum: "$amount"}
            }
        },
        {
            $sort: {_id: 1}
        },
        {
            "$group": {
                "_id": {category: "$_id.category", subcategory: "$_id.subcategory"},
                "years": {
                    "$push": {
                        "year": "$_id.year",
                        "yearTotal": "$total"
                    }
                }
            }
        },
        {
            $sort: {_id: 1}
        }
    ], function(err, result) {
        if (err) {
            console.log("Server report controller getYearlyExpenses error:", err);
            return next(err);
        } else {

            Category.populate(result, {path: "_id.category"}, function(err, data) {

                if (err) {
                    console.log("Server report controller getMonthlyExpenses populate error:", err);
                } else {

                    var currentCategory = '',
                        categoryExpense,
                        minYear = 9999,
                        maxYear = 0,
                        report = {},
                        yr;

                    report.expenses = [];
                    report.yearlyTotals = {};
                    report.reportYears = [];

                    // Find the min and max years
                    data.forEach(function(expense) {
                        expense.years.forEach(function(yearObj) {
                            if (yearObj.year < minYear) { minYear = yearObj.year; }
                            if (yearObj.year > maxYear) { maxYear = yearObj.year; }
                        });
                    });

                    for (yr = minYear; yr <= maxYear; yr++) {
                        report.reportYears.push(yr);
                        report.yearlyTotals[yr] = 0;
                    }

                    // Convert years array to a hash/map
                    data.forEach(function(expense) {

                        if (expense._id.category.name !== currentCategory.name) {
                            currentCategory = expense._id.category;

                            categoryExpense = {
                                _id: {
                                    category: currentCategory,
                                    subcategory: ''
                                },
                                yearMap: {},
                                yearTotal: 0,
                                isCategoryRow: true
                            };

                            report.expenses.push(categoryExpense);

                            for (yr = minYear; yr <= maxYear; yr++) {
                               categoryExpense.yearMap[yr] = 0;
                            }
                        }

                        report.yearlyTotal += expense.yearTotal;
                        categoryExpense.yearTotal += expense.yearTotal;

                        expense.isCategoryRow = false;
                        expense.yearMap = {};

                        expense.years.forEach(function(yearObj) {
                            expense.yearMap[yearObj.year] = yearObj.yearTotal;
                            categoryExpense.yearMap[yearObj.year] += yearObj.yearTotal;
                        });

                        for (yr = minYear; yr <= maxYear; yr++) {
                            if (!expense.yearMap[yr]) {
                                expense.yearMap[yr] = 0;
                            }
                           report.yearlyTotals[yr] += expense.yearMap[yr];
                        }
                        report.expenses.push(expense);
                    });

                    report.expenses.sort(function(exp1, exp2) {
                        if (exp1._id.category.name > exp2._id.category.name) {
                            return 1;
                        } else if (exp1._id.category.name < exp2._id.category.name) {
                            return -1;
                        } else {
                            if (exp1._id.subcategory > exp2._id.subcategory) {
                                return 1;
                            } else if (exp1._id.subcategory < exp2._id.subcategory) {
                                return -1;
                            } else {
                                return 0;
                            }
                        }
                    });

                    res.json(report);
                }
            });

        }

    });
};