diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/chain.cc | 4 | ||||
-rw-r--r-- | src/filters.cc | 45 | ||||
-rw-r--r-- | src/filters.h | 10 |
3 files changed, 48 insertions, 11 deletions
diff --git a/src/chain.cc b/src/chain.cc index 8010ba74..228c3fec 100644 --- a/src/chain.cc +++ b/src/chain.cc @@ -67,8 +67,8 @@ post_handler_ptr chain_pre_post_handlers(post_handler_ptr base_handler, // future balance. if (report.budget_flags != BUDGET_NO_BUDGET) { - budget_posts * budget_handler = new budget_posts(handler, - report.budget_flags); + budget_posts * budget_handler = + new budget_posts(handler, report.terminus.date(), report.budget_flags); budget_handler->add_period_xacts(report.session.journal->period_xacts); handler.reset(budget_handler); diff --git a/src/filters.cc b/src/filters.cc index 1a45ee8a..1a0ecd50 100644 --- a/src/filters.cc +++ b/src/filters.cc @@ -1143,20 +1143,44 @@ void budget_posts::report_budget_items(const date_t& date) bool reported; do { + std::list<pending_posts_list::iterator> posts_to_erase; + reported = false; - foreach (pending_posts_list::value_type& pair, pending_posts) { + for (pending_posts_list::iterator i = pending_posts.begin(); + i != pending_posts.end(); + i++) { + pending_posts_list::value_type& pair(*i); + optional<date_t> begin = pair.first.start; if (! begin) { - if (! pair.first.find_period(date)) + optional<date_t> range_begin; + if (pair.first.range) + range_begin = pair.first.range->begin(); + + DEBUG("budget.generate", "Finding period for pending post"); + if (! pair.first.find_period(range_begin ? *range_begin : date)) continue; + if (! pair.first.start) + throw_(std::logic_error, + _("Failed to find period for periodic transaction")); begin = pair.first.start; } - assert(begin); + +#if defined(DEBUG_ON) + DEBUG("budget.generate", "begin = " << *begin); + DEBUG("budget.generate", "date = " << date); + if (pair.first.finish) + DEBUG("budget.generate", "pair.first.finish = " << *pair.first.finish); +#endif if (*begin <= date && (! pair.first.finish || *begin < *pair.first.finish)) { post_t& post = *pair.second; + ++pair.first; + if (! pair.first.start) + posts_to_erase.push_back(i); + DEBUG("budget.generate", "Reporting budget for " << post.reported_account()->fullname()); @@ -1176,14 +1200,14 @@ void budget_posts::report_budget_items(const date_t& date) temp.xdata().add_flags(POST_EXT_COMPOUND); } - ++pair.first; - begin = *pair.first.start; - item_handler<post_t>::operator()(temp); reported = true; } } + + foreach (pending_posts_list::iterator& i, posts_to_erase) + pending_posts.erase(i); } while (reported); } @@ -1208,6 +1232,7 @@ void budget_posts::operator()(post_t& post) handle: if (post_in_budget && flags & BUDGET_BUDGETED) { report_budget_items(post.date()); + count++; item_handler<post_t>::operator()(post); } else if (! post_in_budget && flags & BUDGET_UNBUDGETED) { @@ -1215,6 +1240,14 @@ void budget_posts::operator()(post_t& post) } } +void budget_posts::flush() +{ + if (count > 0) + report_budget_items(terminus); + + item_handler<post_t>::flush(); +} + void forecast_posts::add_post(const date_interval_t& period, post_t& post) { date_interval_t i(period); diff --git a/src/filters.h b/src/filters.h index 180253d2..72e8f19f 100644 --- a/src/filters.h +++ b/src/filters.h @@ -882,14 +882,17 @@ class budget_posts : public generate_posts #define BUDGET_WRAP_VALUES 0x04 uint_least8_t flags; + date_t terminus; + std::size_t count; budget_posts(); public: budget_posts(post_handler_ptr handler, - uint_least8_t _flags = BUDGET_BUDGETED) - : generate_posts(handler), flags(_flags) { - TRACE_CTOR(budget_posts, "post_handler_ptr, uint_least8_t"); + date_t _terminus, + uint_least8_t _flags = BUDGET_BUDGETED) + : generate_posts(handler), flags(_flags), terminus(_terminus), count(0) { + TRACE_CTOR(budget_posts, "post_handler_ptr, date_t, uint_least8_t"); } virtual ~budget_posts() throw() { TRACE_DTOR(budget_posts); @@ -897,6 +900,7 @@ public: void report_budget_items(const date_t& date); + virtual void flush(); virtual void operator()(post_t& post); }; |