From 5da1e7756d2a4eb04753b8a97bc00063b4d3f687 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Fri, 18 Jun 2010 02:26:50 -0400 Subject: Added new option --inject=KEY[,KEY...] If you have a typed metadata key which contains an amount, you can use --inject=KEY to inject a posting with that amount wherever a match occurs. There are two main forms of usage: 2010-06-18 Sample ; Key:: $100 Expenses:Food $100.00 Assets:Checking The command would be: ledger reg --inject=Key In the above, transactional form, a posting under the account "Key" will be injected before the first posting reported for this transaction. It's amount will be $100. This only happens once for the whole transaction. It is also possible to associate the key with a posting: 2010-06-18 Sample Expenses:Food $100.00 ; Key:: $100 Assets:Checking Now the injected posting is generated whenever that particular post is reported. --- src/filters.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'src/filters.h') diff --git a/src/filters.h b/src/filters.h index 9102d4f1..180253d2 100644 --- a/src/filters.h +++ b/src/filters.h @@ -929,6 +929,26 @@ class forecast_posts : public generate_posts } }; +class inject_posts : public item_handler +{ + typedef std::set tag_injected_set; + typedef std::pair tag_mapping_pair; + typedef std::pair tags_list_pair; + + std::list tags_list; + temporaries_t temps; + + public: + inject_posts(post_handler_ptr handler, const string& tag_list, + account_t * master); + + virtual ~inject_posts() throw() { + TRACE_DTOR(inject_posts); + } + + virtual void operator()(post_t& post); +}; + ////////////////////////////////////////////////////////////////////// // // Account filters -- cgit v1.2.3 From 6770380b6da5061857e0a15539f1b85669d24e62 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sat, 19 Jun 2010 16:07:54 -0400 Subject: Subsantial fixes and improvements to budgeting 1. A bounded budget "from DATE to DATE" will now generate entries throughout that entire range, if it is triggered. 2. An unbounded budget begins, as before, in the timeframe of the reported posting which triggered it, but now continues until the present date. --- src/chain.cc | 4 +- src/filters.cc | 45 +++++++++++++-- src/filters.h | 10 +++- test/baseline/opt-add-budget.test | 2 +- test/baseline/opt-budget.test | 2 +- test/baseline/opt-budget_range.test | 111 ++++++++++++++++++++++++++++++++++++ test/regress/8254755E.test | 6 +- 7 files changed, 164 insertions(+), 16 deletions(-) create mode 100644 test/baseline/opt-budget_range.test (limited to 'src/filters.h') 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 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 begin = pair.first.start; if (! begin) { - if (! pair.first.find_period(date)) + optional 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::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::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::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); }; diff --git a/test/baseline/opt-add-budget.test b/test/baseline/opt-add-budget.test index 535335d3..d2cd6945 100644 --- a/test/baseline/opt-add-budget.test +++ b/test/baseline/opt-add-budget.test @@ -1,4 +1,4 @@ -reg --add-budget books cards +reg --add-budget books cards --now=2009/12/31 <<< ~ monthly Expenses:Books $10.00 diff --git a/test/baseline/opt-budget.test b/test/baseline/opt-budget.test index eb2ade9d..67b4e85e 100644 --- a/test/baseline/opt-budget.test +++ b/test/baseline/opt-budget.test @@ -1,4 +1,4 @@ -reg --budget books +reg --budget books --now=2009/12/31 <<< ~ monthly Expenses:Books $10.00 diff --git a/test/baseline/opt-budget_range.test b/test/baseline/opt-budget_range.test new file mode 100644 index 00000000..7c8ee2d2 --- /dev/null +++ b/test/baseline/opt-budget_range.test @@ -0,0 +1,111 @@ +reg --now=2010/02 --sort=date exp --budget +<<< +~ monthly + Expenses:Food $100 + Expenses:Movies $20 + Assets:Cash + +~ monthly from 2009 + Expenses:Food $101 + Expenses:Movies $21 + Assets:Cash + +~ monthly to 2010 + Expenses:Food $102 + Expenses:Movies $22 + Assets:Cash + +~ monthly from 2009 to 2010 + Expenses:Food $103 + Expenses:Movies $23 + Assets:Cash + +2009/06/05 Grocery + Expenses:Food $5 + Assets:Cash +>>> +09-Jan-01 Budget transaction Expenses:Food $-101 $-101 +09-Jan-01 Budget transaction Expenses:Movies $-21 $-122 +09-Jan-01 Budget transaction Expenses:Food $-103 $-225 +09-Jan-01 Budget transaction Expenses:Movies $-23 $-248 +09-Feb-01 Budget transaction Expenses:Food $-101 $-349 +09-Feb-01 Budget transaction Expenses:Movies $-21 $-370 +09-Feb-01 Budget transaction Expenses:Food $-103 $-473 +09-Feb-01 Budget transaction Expenses:Movies $-23 $-496 +09-Mar-01 Budget transaction Expenses:Food $-101 $-597 +09-Mar-01 Budget transaction Expenses:Movies $-21 $-618 +09-Mar-01 Budget transaction Expenses:Food $-103 $-721 +09-Mar-01 Budget transaction Expenses:Movies $-23 $-744 +09-Apr-01 Budget transaction Expenses:Food $-101 $-845 +09-Apr-01 Budget transaction Expenses:Movies $-21 $-866 +09-Apr-01 Budget transaction Expenses:Food $-103 $-969 +09-Apr-01 Budget transaction Expenses:Movies $-23 $-992 +09-May-01 Budget transaction Expenses:Food $-101 $-1093 +09-May-01 Budget transaction Expenses:Movies $-21 $-1114 +09-May-01 Budget transaction Expenses:Food $-103 $-1217 +09-May-01 Budget transaction Expenses:Movies $-23 $-1240 +09-Jun-01 Budget transaction Expenses:Food $-100 $-1340 +09-Jun-01 Budget transaction Expenses:Movies $-20 $-1360 +09-Jun-01 Budget transaction Expenses:Food $-102 $-1462 +09-Jun-01 Budget transaction Expenses:Movies $-22 $-1484 +09-Jun-01 Budget transaction Expenses:Food $-101 $-1585 +09-Jun-01 Budget transaction Expenses:Movies $-21 $-1606 +09-Jun-01 Budget transaction Expenses:Food $-103 $-1709 +09-Jun-01 Budget transaction Expenses:Movies $-23 $-1732 +09-Jun-05 Grocery Expenses:Food $5 $-1727 +09-Jul-01 Budget transaction Expenses:Food $-100 $-1827 +09-Jul-01 Budget transaction Expenses:Movies $-20 $-1847 +09-Jul-01 Budget transaction Expenses:Food $-101 $-1948 +09-Jul-01 Budget transaction Expenses:Movies $-21 $-1969 +09-Jul-01 Budget transaction Expenses:Food $-102 $-2071 +09-Jul-01 Budget transaction Expenses:Movies $-22 $-2093 +09-Jul-01 Budget transaction Expenses:Food $-103 $-2196 +09-Jul-01 Budget transaction Expenses:Movies $-23 $-2219 +09-Aug-01 Budget transaction Expenses:Food $-100 $-2319 +09-Aug-01 Budget transaction Expenses:Movies $-20 $-2339 +09-Aug-01 Budget transaction Expenses:Food $-101 $-2440 +09-Aug-01 Budget transaction Expenses:Movies $-21 $-2461 +09-Aug-01 Budget transaction Expenses:Food $-102 $-2563 +09-Aug-01 Budget transaction Expenses:Movies $-22 $-2585 +09-Aug-01 Budget transaction Expenses:Food $-103 $-2688 +09-Aug-01 Budget transaction Expenses:Movies $-23 $-2711 +09-Sep-01 Budget transaction Expenses:Food $-100 $-2811 +09-Sep-01 Budget transaction Expenses:Movies $-20 $-2831 +09-Sep-01 Budget transaction Expenses:Food $-101 $-2932 +09-Sep-01 Budget transaction Expenses:Movies $-21 $-2953 +09-Sep-01 Budget transaction Expenses:Food $-102 $-3055 +09-Sep-01 Budget transaction Expenses:Movies $-22 $-3077 +09-Sep-01 Budget transaction Expenses:Food $-103 $-3180 +09-Sep-01 Budget transaction Expenses:Movies $-23 $-3203 +09-Oct-01 Budget transaction Expenses:Food $-100 $-3303 +09-Oct-01 Budget transaction Expenses:Movies $-20 $-3323 +09-Oct-01 Budget transaction Expenses:Food $-101 $-3424 +09-Oct-01 Budget transaction Expenses:Movies $-21 $-3445 +09-Oct-01 Budget transaction Expenses:Food $-102 $-3547 +09-Oct-01 Budget transaction Expenses:Movies $-22 $-3569 +09-Oct-01 Budget transaction Expenses:Food $-103 $-3672 +09-Oct-01 Budget transaction Expenses:Movies $-23 $-3695 +09-Nov-01 Budget transaction Expenses:Food $-100 $-3795 +09-Nov-01 Budget transaction Expenses:Movies $-20 $-3815 +09-Nov-01 Budget transaction Expenses:Food $-101 $-3916 +09-Nov-01 Budget transaction Expenses:Movies $-21 $-3937 +09-Nov-01 Budget transaction Expenses:Food $-102 $-4039 +09-Nov-01 Budget transaction Expenses:Movies $-22 $-4061 +09-Nov-01 Budget transaction Expenses:Food $-103 $-4164 +09-Nov-01 Budget transaction Expenses:Movies $-23 $-4187 +09-Dec-01 Budget transaction Expenses:Food $-100 $-4287 +09-Dec-01 Budget transaction Expenses:Movies $-20 $-4307 +09-Dec-01 Budget transaction Expenses:Food $-101 $-4408 +09-Dec-01 Budget transaction Expenses:Movies $-21 $-4429 +09-Dec-01 Budget transaction Expenses:Food $-102 $-4531 +09-Dec-01 Budget transaction Expenses:Movies $-22 $-4553 +09-Dec-01 Budget transaction Expenses:Food $-103 $-4656 +09-Dec-01 Budget transaction Expenses:Movies $-23 $-4679 +10-Jan-01 Budget transaction Expenses:Food $-100 $-4779 +10-Jan-01 Budget transaction Expenses:Movies $-20 $-4799 +10-Jan-01 Budget transaction Expenses:Food $-101 $-4900 +10-Jan-01 Budget transaction Expenses:Movies $-21 $-4921 +10-Feb-01 Budget transaction Expenses:Food $-100 $-5021 +10-Feb-01 Budget transaction Expenses:Movies $-20 $-5041 +10-Feb-01 Budget transaction Expenses:Food $-101 $-5142 +10-Feb-01 Budget transaction Expenses:Movies $-21 $-5163 diff --git a/test/regress/8254755E.test b/test/regress/8254755E.test index 26baf52d..98904d6e 100644 --- a/test/regress/8254755E.test +++ b/test/regress/8254755E.test @@ -1,4 +1,4 @@ -bal --flat food:out +bal --flat food:out --now=2009/12/31 <<< ~ Monthly Expenses:Auto:Fuel $120.00 @@ -13,8 +13,8 @@ bal --flat food:out $50.00 Expenses:Food:Out >>>2 === 0 -bal --flat --budget food:out +bal --flat --budget food:out --now=2009/12/31 >>>1 - $-50.00 Expenses:Food:Out + $-150.00 Expenses:Food:Out >>>2 === 0 -- cgit v1.2.3 From 3a5653e365b1572ee43fbfb8213edd1083de97cd Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sun, 20 Jun 2010 18:59:30 -0400 Subject: Rename dow_posts to day_of_week_posts, to be clearer --- src/chain.cc | 6 +++--- src/filters.cc | 2 +- src/filters.h | 12 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src/filters.h') diff --git a/src/chain.cc b/src/chain.cc index 228c3fec..67f2c8d5 100644 --- a/src/chain.cc +++ b/src/chain.cc @@ -202,8 +202,8 @@ post_handler_ptr chain_post_handlers(post_handler_ptr base_handler, // period_posts is like subtotal_posts, but it subtotals according to time // periods rather than totalling everything. // - // dow_posts is like period_posts, except that it reports all the posts - // that fall on each subsequent day of the week. + // day_of_week_posts is like period_posts, except that it reports + // all the posts that fall on each subsequent day of the week. if (report.HANDLED(equity)) handler.reset(new posts_as_equity(handler, expr)); else if (report.HANDLED(subtotal)) @@ -211,7 +211,7 @@ post_handler_ptr chain_post_handlers(post_handler_ptr base_handler, } if (report.HANDLED(dow)) - handler.reset(new dow_posts(handler, expr)); + handler.reset(new day_of_week_posts(handler, expr)); else if (report.HANDLED(by_payee)) handler.reset(new by_payee_posts(handler, expr)); diff --git a/src/filters.cc b/src/filters.cc index 9e06fb8b..4adf7203 100644 --- a/src/filters.cc +++ b/src/filters.cc @@ -1113,7 +1113,7 @@ void transfer_details::operator()(post_t& post) item_handler::operator()(temp); } -void dow_posts::flush() +void day_of_week_posts::flush() { for (int i = 0; i < 7; i++) { foreach (post_t * post, days_of_the_week[i]) diff --git a/src/filters.h b/src/filters.h index 72e8f19f..76648bee 100644 --- a/src/filters.h +++ b/src/filters.h @@ -813,19 +813,19 @@ public: } }; -class dow_posts : public subtotal_posts +class day_of_week_posts : public subtotal_posts { posts_list days_of_the_week[7]; - dow_posts(); + day_of_week_posts(); public: - dow_posts(post_handler_ptr handler, expr_t& amount_expr) + day_of_week_posts(post_handler_ptr handler, expr_t& amount_expr) : subtotal_posts(handler, amount_expr) { - TRACE_CTOR(dow_posts, "post_handler_ptr, bool"); + TRACE_CTOR(day_of_week_posts, "post_handler_ptr, bool"); } - virtual ~dow_posts() throw() { - TRACE_DTOR(dow_posts); + virtual ~day_of_week_posts() throw() { + TRACE_DTOR(day_of_week_posts); } virtual void flush(); -- cgit v1.2.3 From 7b6cc4c365758a293f914f7b3b61af78e4313d4a Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sun, 20 Jun 2010 20:55:24 -0400 Subject: Output budget even if no postings directly matched --- src/filters.cc | 3 +-- src/filters.h | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'src/filters.h') diff --git a/src/filters.cc b/src/filters.cc index d4fbae06..1dd410d3 100644 --- a/src/filters.cc +++ b/src/filters.cc @@ -1233,7 +1233,6 @@ void budget_posts::operator()(post_t& post) handle: if (post_in_budget && flags & BUDGET_BUDGETED) { report_budget_items(post.date()); - count++; item_handler::operator()(post); } else if (! post_in_budget && flags & BUDGET_UNBUDGETED) { @@ -1243,7 +1242,7 @@ void budget_posts::operator()(post_t& post) void budget_posts::flush() { - if (count > 0) + if (flags & BUDGET_BUDGETED) report_budget_items(terminus); item_handler::flush(); diff --git a/src/filters.h b/src/filters.h index 76648bee..08dd18d5 100644 --- a/src/filters.h +++ b/src/filters.h @@ -883,7 +883,6 @@ class budget_posts : public generate_posts uint_least8_t flags; date_t terminus; - std::size_t count; budget_posts(); @@ -891,7 +890,7 @@ public: budget_posts(post_handler_ptr handler, date_t _terminus, uint_least8_t _flags = BUDGET_BUDGETED) - : generate_posts(handler), flags(_flags), terminus(_terminus), count(0) { + : generate_posts(handler), flags(_flags), terminus(_terminus) { TRACE_CTOR(budget_posts, "post_handler_ptr, date_t, uint_least8_t"); } virtual ~budget_posts() throw() { -- cgit v1.2.3