diff --git a/include/data_cache.hpp b/include/data_cache.hpp index ad5caa3..d1f1ba5 100644 --- a/include/data_cache.hpp +++ b/include/data_cache.hpp @@ -97,23 +97,23 @@ inline auto all_earnings_between(data_cache & cache, budget::year year, budget:: } inline auto all_expenses_year(data_cache & cache, budget::year year) { - return cache.expenses() | filter_by_year(year); + return cache.expenses() | persistent | filter_by_year(year); } inline auto all_expenses_month(data_cache & cache, budget::year year, budget::month month){ - return cache.expenses() | filter_by_year(year) | filter_by_month(month); + return cache.expenses() | persistent | filter_by_year(year) | filter_by_month(month); } inline auto all_expenses_month(data_cache & cache, size_t account_id, budget::year year, budget::month month){ - return cache.expenses() | filter_by_account(account_id) | filter_by_year(year) | filter_by_month(month); + return cache.expenses() | persistent | filter_by_account(account_id) | filter_by_year(year) | filter_by_month(month); } inline auto all_expenses_between(data_cache & cache, budget::year year, budget::month sm, budget::month month){ - return cache.expenses() | filter_by_year(year) | between(sm, month); + return cache.expenses() | persistent | filter_by_year(year) | between(sm, month); } inline auto all_expenses_between(data_cache & cache, size_t account_id, budget::year year, budget::month sm, budget::month month){ - return cache.expenses() | filter_by_account(account_id) | filter_by_year(year) | between(sm, month); + return cache.expenses() | persistent | filter_by_account(account_id) | filter_by_year(year) | between(sm, month); } diff --git a/src/accounts.cpp b/src/accounts.cpp index 76e2f64..7b335be 100644 --- a/src/accounts.cpp +++ b/src/accounts.cpp @@ -65,7 +65,7 @@ void migrate_account(const std::string& source_account_name, const std::string& destination_account.amount += account.amount; - for (auto& expense : all_expenses() | filter_by_account(source_id)) { + for (auto& expense : all_expenses() | persistent | filter_by_account(source_id)) { expense.account = destination_id; indirect_edit_expense(expense, false); } @@ -166,7 +166,7 @@ void budget::archive_accounts_impl(bool month){ mapping[sources[i]] = id; } - for (auto& expense : all_expenses() | since(since_date)) { + for (auto& expense : all_expenses() | persistent | since(since_date)) { if (mapping.contains(expense.account)) { expense.account = mapping[expense.account]; indirect_edit_expense(expense, false); diff --git a/src/date.cpp b/src/date.cpp index 50d60db..8e37b44 100644 --- a/src/date.cpp +++ b/src/date.cpp @@ -89,13 +89,13 @@ std::string budget::date_to_string(const budget::date& date) { } budget::month budget::start_month(data_cache & cache, budget::year year){ - const budget::month m = min_with_default(cache.expenses() | filter_by_year(year) | to_month, budget::month(12)); + const budget::month m = min_with_default(cache.expenses() | persistent | filter_by_year(year) | to_month, budget::month(12)); return min_with_default(cache.earnings() | filter_by_year(year) | to_month, m); } budget::year budget::start_year(data_cache & cache){ auto today = budget::local_day(); - const budget::year y = min_with_default(cache.expenses() | not_template | to_year, today.year()); + const budget::year y = min_with_default(cache.expenses() | persistent | not_template | to_year, today.year()); return min_with_default(cache.earnings() | not_template | to_year, y); } diff --git a/src/overview.cpp b/src/overview.cpp index 0845cd5..e92216c 100644 --- a/src/overview.cpp +++ b/src/overview.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include "cpp_utils/assert.hpp" @@ -211,19 +212,19 @@ std::vector compute_total_budget(data_cache & cache, budget::mont return total_budgets; } -template -void add_values_column(budget::month month, - budget::year year, - const std::string& title, - std::vector>& contents, - cpp::string_hash_map& indexes, - size_t columns, - const std::vector& values, - std::vector& total) { +template +void add_values_column(budget::month month, + budget::year year, + const std::string& title, + std::vector>& contents, + cpp::string_hash_map& indexes, + size_t columns, + R&& values, + std::vector& total) { std::vector current(columns, contents.size()); - std::vector sorted_values = values; - std::ranges::sort(sorted_values, [](const T& a, const T& b) { return a.date < b.date; }); + auto sorted_values = to_vector(std::forward(values)); + std::ranges::sort(sorted_values, [](const auto& a, const auto& b) { return a.date < b.date; }); for (auto& expense : sorted_values | filter_by_date(year, month)) { if (indexes.contains(get_account(expense.account).name)) { @@ -251,13 +252,13 @@ void add_values_column(budget::month month, using acc_data_t = cpp::string_hash_map>; -template -std::pair aggregate(data_cache & cache, const Data & data, bool full, bool disable_groups, const std::string& separator, Functor&& func){ +template +std::pair aggregate(data_cache & cache, R && data, bool full, bool disable_groups, const std::string& separator, Functor&& func){ budget::money total; acc_data_t acc_data; //Accumulate all the data - for (auto& element : data) { + for (const auto& element : std::forward(data)) { if (func(element)) { auto name = element.name; @@ -292,9 +293,9 @@ std::pair aggregate(data_cache & cache, const Data & return {total, acc_data}; } -template -void aggregate_overview(const Data & data, budget::writer& w, bool full, bool disable_groups, const std::string& separator, Functor&& func){ - auto [total, acc_data] = aggregate(w.cache, data, full, disable_groups, separator, func); +template +void aggregate_overview(R && data, budget::writer& w, bool full, bool disable_groups, const std::string& separator, Functor&& func){ + auto [total, acc_data] = aggregate(w.cache, std::forward(data), full, disable_groups, separator, func); cpp::string_hash_map totals; @@ -349,8 +350,8 @@ void aggregate_overview(const Data & data, budget::writer& w, bool full, bool di w.display_table(columns, contents, 3); } -template -void aggregate_overview_month(const Data & data, budget::writer& w, bool full, bool disable_groups, const std::string& separator, budget::year year, Functor&& func){ +template +void aggregate_overview_month(R && data, budget::writer& w, bool full, bool disable_groups, const std::string& separator, budget::year year, Functor&& func){ int months = 1; if (year == budget::local_day().year()) { months = budget::local_day().month(); @@ -358,7 +359,7 @@ void aggregate_overview_month(const Data & data, budget::writer& w, bool full, b months = 12 - budget::start_month(w.cache, year) + 1; } - auto [total, acc_data] = aggregate(w.cache, data, full, disable_groups, separator, func); + auto [total, acc_data] = aggregate(w.cache, std::forward(data), full, disable_groups, separator, func); cpp::string_hash_map totals; @@ -423,9 +424,9 @@ budget::money future_value(budget::money start) { return value; } -template -void aggregate_overview_fv(const Data & data, budget::writer& w, bool full, bool disable_groups, const std::string& separator, Functor&& func){ - auto [total, acc_data] = aggregate(w.cache, data, full, disable_groups, separator, func); +template +void aggregate_overview_fv(R && data, budget::writer& w, bool full, bool disable_groups, const std::string& separator, Functor&& func){ + auto [total, acc_data] = aggregate(w.cache, std::forward(data), full, disable_groups, separator, func); cpp::string_hash_map totals; @@ -530,8 +531,8 @@ inline void generate_total_line(data_cache & cache, std::vector -void display_values(budget::writer& w, budget::year year, const std::string& title, const std::vector& values, bool current = true, bool relaxed = true, bool last = false){ +template +void display_values(budget::writer& w, budget::year year, const std::string& title, R&& values, bool current = true, bool relaxed = true, bool last = false){ std::vector columns; std::vector> contents; @@ -569,9 +570,9 @@ void display_values(budget::writer& w, budget::year year, const std::string& tit budget::money month_total; if (relaxed) { - month_total = fold_left_auto(values | filter_by_account_name(account.name) | filter_by_date(year, m) | to_amount); + month_total = fold_left_auto(std::forward(values) | filter_by_account_name(account.name) | filter_by_date(year, m) | to_amount); } else { - month_total = fold_left_auto(values | filter_by_account(account.id) | filter_by_date(year, m) | to_amount); + month_total = fold_left_auto(std::forward(values) | filter_by_account(account.id) | filter_by_date(year, m) | to_amount); } contents[row_mapping[account.name]].push_back(to_string(month_total)); @@ -782,7 +783,7 @@ void budget::overview_module::handle(std::vector& args) { } void budget::display_expenses(budget::writer& w, budget::year year, bool current, bool relaxed, bool last){ - display_values(w, year, "Expenses", all_expenses(), current, relaxed, last); + display_values(w, year, "Expenses", all_expenses() | persistent, current, relaxed, last); } void budget::display_earnings(budget::writer& w, budget::year year, bool current, bool relaxed, bool last){ @@ -830,7 +831,7 @@ void budget::display_local_balance(budget::writer& w, budget::year year, bool cu if(relaxed){ auto relaxed_filter = [account](const auto & e){return get_account(e.account).name == account.name; }; - total_expenses = fold_left_auto(w.cache.expenses() | filter_by_date(year, m) | std::views::filter(relaxed_filter) | to_amount); + total_expenses = fold_left_auto(w.cache.expenses() | persistent | filter_by_date(year, m) | std::views::filter(relaxed_filter) | to_amount); total_earnings = fold_left_auto(w.cache.earnings() | filter_by_date(year, m) | std::views::filter(relaxed_filter) | to_amount); } else { total_expenses = fold_left_auto(all_expenses_month(w.cache, account.id, year, m) | to_amount); @@ -1004,7 +1005,7 @@ void budget::display_balance(budget::writer& w, budget::year year, bool relaxed, if(relaxed){ auto relaxed_filter = [account](const auto & e){return get_account(e.account).name == account.name; }; - total_expenses = fold_left_auto(w.cache.expenses() | filter_by_date(year, m) | std::views::filter(relaxed_filter) | to_amount); + total_expenses = fold_left_auto(w.cache.expenses() | persistent | filter_by_date(year, m) | std::views::filter(relaxed_filter) | to_amount); total_earnings = fold_left_auto(w.cache.earnings() | filter_by_date(year, m) | std::views::filter(relaxed_filter) | to_amount); } else { total_expenses = fold_left_auto(all_expenses_month(w.cache, account.id, year, m) | to_amount); @@ -1058,7 +1059,7 @@ void budget::display_month_overview(budget::month month, budget::year year, budg } //Expenses - add_values_column(month, year, "Expenses", contents, indexes, columns.size(), writer.cache.expenses(), total_expenses); + add_values_column(month, year, "Expenses", contents, indexes, columns.size(), writer.cache.expenses() | persistent, total_expenses); //Earnings contents.emplace_back(columns.size() * 3, ""); @@ -1180,7 +1181,7 @@ void budget::display_month_account_overview(size_t account_id, budget::month mon std::vector total_earnings(1, budget::money()); //Expenses - add_values_column(month, year, "Expenses", contents, indexes, columns.size(), writer.cache.expenses(), total_expenses); + add_values_column(month, year, "Expenses", contents, indexes, columns.size(), writer.cache.expenses() | persistent, total_expenses); //Earnings contents.emplace_back(columns.size() * 3, ""); @@ -1306,7 +1307,7 @@ void budget::aggregate_all_overview(budget::writer& w, bool full, bool disable_g w << title_begin << "Aggregate overview of all time" << title_end; w << p_begin << "Expenses" << p_end; - aggregate_overview(all_expenses(), w, full, disable_groups, separator, [](const budget::expense& /*expense*/){ return true; }); + aggregate_overview(all_expenses() | persistent, w, full, disable_groups, separator, [](const budget::expense& /*expense*/){ return true; }); w << p_begin << "Earnings" << p_end; aggregate_overview(all_earnings(), w, full, disable_groups, separator, [](const budget::earning& /*earning*/){ return true; }); @@ -1320,7 +1321,7 @@ void budget::aggregate_year_overview(budget::writer& w, bool full, bool disable_ w << title_begin << "Aggregate overview of " << year << year_selector{"overview/aggregate/year", year} << title_end; w << p_begin << "Expenses" << p_end; - aggregate_overview(all_expenses(), w, full, disable_groups, separator, [year](const budget::expense& expense){ return expense.date.year() == year; }); + aggregate_overview(all_expenses() | persistent, w, full, disable_groups, separator, [year](const budget::expense& expense){ return expense.date.year() == year; }); w << p_begin << "Earnings" << p_end; aggregate_overview(all_earnings(), w, full, disable_groups, separator, [year](const budget::earning& earning){ return earning.date.year() == year; }); @@ -1334,7 +1335,7 @@ void budget::aggregate_year_month_overview(budget::writer& w, bool full, bool di w << title_begin << "Aggregate overview of " << year << year_selector{"overview/aggregate/year_month", year} << title_end; w << p_begin << "Expenses" << p_end; - aggregate_overview_month(all_expenses(), w, full, disable_groups, separator, year, [year](const budget::expense& expense){ return expense.date.year() == year; }); + aggregate_overview_month(all_expenses() | persistent, w, full, disable_groups, separator, year, [year](const budget::expense& expense){ return expense.date.year() == year; }); w << p_begin << "Earnings" << p_end; aggregate_overview_month(all_earnings(), w, full, disable_groups, separator, year, [year](const budget::earning& earning){ return earning.date.year() == year; }); @@ -1348,7 +1349,7 @@ void budget::aggregate_year_fv_overview(budget::writer& w, bool full, bool disab w << title_begin << "Aggregate FV overview of " << year << year_selector{"overview/aggregate/year_fv", year} << title_end; w << p_begin << "Expenses" << p_end; - aggregate_overview_fv(all_expenses(), w, full, disable_groups, separator, [year](const budget::expense& expense){ return expense.date.year() == year; }); + aggregate_overview_fv(all_expenses() | persistent, w, full, disable_groups, separator, [year](const budget::expense& expense){ return expense.date.year() == year; }); w << p_begin << "Earnings" << p_end; aggregate_overview_fv(all_earnings(), w, full, disable_groups, separator, [year](const budget::earning& earning){ return earning.date.year() == year; }); @@ -1358,7 +1359,7 @@ void budget::aggregate_month_overview(budget::writer& w, bool full, bool disable w << title_begin << "Aggregate overview of " << month << " " << year << year_month_selector{"overview/aggregate/month", year, month} << title_end; w << p_begin << "Expenses" << p_end; - aggregate_overview(all_expenses(), w, full, disable_groups, separator, [month,year](const budget::expense& expense){ return expense.date.month() == month && expense.date.year() == year; }); + aggregate_overview(all_expenses() | persistent, w, full, disable_groups, separator, [month,year](const budget::expense& expense){ return expense.date.month() == month && expense.date.year() == year; }); w << p_begin << "Earnings" << p_end; aggregate_overview(all_earnings(), w, full, disable_groups, separator, [month,year](const budget::earning& earning){ return earning.date.month() == month && earning.date.year() == year; }); @@ -1372,7 +1373,7 @@ void budget::add_expenses_column(budget::month month, size_t columns, const std::vector& values, std::vector& total) { - add_values_column(month, year, title, contents, indexes, columns, values, total); + add_values_column(month, year, title, contents, indexes, columns, values | persistent, total); } void budget::add_earnings_column(budget::month month, diff --git a/src/predict.cpp b/src/predict.cpp index 0f0bfd0..8caa5a5 100644 --- a/src/predict.cpp +++ b/src/predict.cpp @@ -53,7 +53,7 @@ void predict_overview(){ ++i; } - for(auto& expense : expenses){ + for(auto& expense : expenses | persistent){ if(account_mappings.contains(get_account(expense.account).name)){ expense.amount *= (expense_multipliers[account_mappings[get_account(expense.account).name]] / 100.0); } @@ -68,7 +68,7 @@ void predict_overview(){ if (today.month() < budget::month(12)) { budget::year prev_year = today.year() - date_type(1); for (budget::month m = today.month() + date_type(1); m.is_valid(); ++m) { - for (auto& expense : expenses | filter_by_date(prev_year, m)) { + for (auto& expense : expenses | persistent | filter_by_date(prev_year, m)) { expense.date = {today.year(), expense.date.month(), expense.date.day()}; } diff --git a/src/recurring.cpp b/src/recurring.cpp index 64242e8..07ef58d 100644 --- a/src/recurring.cpp +++ b/src/recurring.cpp @@ -35,7 +35,7 @@ budget::date last_date(const budget::recurring& recurring) { budget::date last(1400, 1, 1); if (recurring.type == "expense") { - for (const auto& expense : all_expenses() | filter_by_name(recurring.name) | filter_by_amount(recurring.amount)) { + for (const auto& expense : all_expenses() | persistent | filter_by_name(recurring.name) | filter_by_amount(recurring.amount)) { if (get_account(expense.account).name == recurring.account && expense.date > last) { last = expense.date; } @@ -437,7 +437,7 @@ bool budget::edit_recurring(const budget::recurring& recurring, const budget::re auto now = budget::local_day(); if (recurring.type == "expense") { - for (auto& expense : all_expenses()) { + for (auto& expense : all_expenses() | persistent) { if (expense.date.year() == now.year() && expense.date.month() == now.month() && expense.name == previous_recurring.name && expense.amount == previous_recurring.amount && get_account(expense.account).name == previous_recurring.account) { expense.name = recurring.name; diff --git a/src/summary.cpp b/src/summary.cpp index d98a27a..6babd9b 100644 --- a/src/summary.cpp +++ b/src/summary.cpp @@ -233,7 +233,7 @@ void budget::account_summary(budget::writer& w, budget::month month, budget::yea for (budget::month m = sm; m <= month; ++m) { for (const auto& account : all_accounts(w.cache, year, m)) { - auto total_expenses = fold_left_auto(w.cache.expenses() | filter_by_account(account.id) | filter_by_date(year, m) | to_amount); + auto total_expenses = fold_left_auto(w.cache.expenses() | persistent | filter_by_account(account.id) | filter_by_date(year, m) | to_amount); auto total_earnings = fold_left_auto(w.cache.earnings() | filter_by_account(account.id) | filter_by_date(year, m) | to_amount); auto balance = account_previous[account.name] + account.amount - total_expenses + total_earnings;