summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/account.cc15
-rw-r--r--src/account.h17
-rw-r--r--src/journal.cc17
-rw-r--r--src/post.h1
-rw-r--r--src/textual.cc6
-rw-r--r--src/xact.cc5
-rw-r--r--test/baseline/feat-balance_assert_split.test55
7 files changed, 107 insertions, 9 deletions
diff --git a/src/account.cc b/src/account.cc
index 4b3a4e97..a702cf11 100644
--- a/src/account.cc
+++ b/src/account.cc
@@ -139,6 +139,21 @@ void account_t::add_post(post_t * post)
}
}
+void account_t::add_deferred_post(const string& uuid, post_t * post)
+{
+ if (! deferred_posts)
+ deferred_posts = deferred_posts_map_t();
+
+ deferred_posts_map_t::iterator i = deferred_posts->find(uuid);
+ if (i == deferred_posts->end()) {
+ posts_list lst;
+ lst.push_back(post);
+ deferred_posts->insert(deferred_posts_map_t::value_type(uuid, lst));
+ } else {
+ (*i).second.push_back(post);
+ }
+}
+
bool account_t::remove_post(post_t * post)
{
// It's possible that 'post' wasn't yet in this account, but try to
diff --git a/src/account.h b/src/account.h
index f6f764cc..3ce93fba 100644
--- a/src/account.h
+++ b/src/account.h
@@ -52,6 +52,7 @@ class post_t;
typedef std::list<post_t *> posts_list;
typedef std::map<string, account_t *> accounts_map;
+typedef std::map<string, posts_list> deferred_posts_map_t;
class account_t : public supports_flags<>, public scope_t
{
@@ -61,13 +62,14 @@ class account_t : public supports_flags<>, public scope_t
#define ACCOUNT_GENERATED 0x04 // account never actually existed
public:
- account_t * parent;
- string name;
- optional<string> note;
- unsigned short depth;
- accounts_map accounts;
- posts_list posts;
- optional<expr_t> value_expr;
+ account_t * parent;
+ string name;
+ optional<string> note;
+ unsigned short depth;
+ accounts_map accounts;
+ posts_list posts;
+ optional<deferred_posts_map_t> deferred_posts;
+ optional<expr_t> value_expr;
mutable string _fullname;
#if DOCUMENT_MODEL
@@ -136,6 +138,7 @@ public:
}
void add_post(post_t * post);
+ void add_deferred_post(const string& uuid, post_t * post);
bool remove_post(post_t * post);
posts_list::iterator posts_begin() {
diff --git a/src/journal.cc b/src/journal.cc
index ef35722c..94a535d7 100644
--- a/src/journal.cc
+++ b/src/journal.cc
@@ -385,9 +385,24 @@ bool journal_t::add_xact(xact_t * xact)
// will have been performed by extend_xact, so asserts can still be
// applied to it.
if (optional<value_t> ref = xact->get_tag(_("UUID"))) {
+ std::string uuid = ref->to_string();
std::pair<checksum_map_t::iterator, bool> result
- = checksum_map.insert(checksum_map_t::value_type(ref->to_string(), xact));
+ = checksum_map.insert(checksum_map_t::value_type(uuid, xact));
if (! result.second) {
+ // This UUID has been seen before; apply any postings which the
+ // earlier version may have deferred.
+ foreach (post_t * post, xact->posts) {
+ account_t * acct = post->account;
+ if (acct->deferred_posts) {
+ deferred_posts_map_t::iterator
+ i = acct->deferred_posts->find(uuid);
+ if (i != acct->deferred_posts->end()) {
+ foreach (post_t * rpost, (*i).second)
+ acct->add_post(rpost);
+ }
+ }
+ }
+
// jww (2012-02-27): Confirm that the xact in
// (*result.first).second is exact match in its significant
// details to xact.
diff --git a/src/post.h b/src/post.h
index 379844dc..51a75ade 100644
--- a/src/post.h
+++ b/src/post.h
@@ -60,6 +60,7 @@ public:
#define POST_COST_FIXATED 0x0200 // cost is fixed using = indicator
#define POST_COST_VIRTUAL 0x0400 // cost is virtualized: (@)
#define POST_ANONYMIZED 0x0800 // a temporary, anonymous posting
+#define POST_DEFERRED 0x1000 // the account was specified with <angles>
xact_t * xact; // only set for posts of regular xacts
account_t * account;
diff --git a/src/textual.cc b/src/textual.cc
index fa84d6de..6f8f0492 100644
--- a/src/textual.cc
+++ b/src/textual.cc
@@ -1432,6 +1432,12 @@ post_t * instance_t::parse_post(char * line,
}
p++; e--;
}
+ else if (*p == '<' && *(e - 1) == '>') {
+ post->add_flags(POST_DEFERRED);
+ DEBUG("textual.parse", "line " << context.linenum << ": "
+ << "Parsed a deferred account name");
+ p++; e--;
+ }
string name(p, static_cast<string::size_type>(e - p));
DEBUG("textual.parse", "line " << context.linenum << ": "
diff --git a/src/xact.cc b/src/xact.cc
index 58d2ac33..c7a9c6e3 100644
--- a/src/xact.cc
+++ b/src/xact.cc
@@ -393,7 +393,10 @@ bool xact_base_t::finalize()
some_null = true;
}
- post->account->add_post(post);
+ if (post->has_flags(POST_DEFERRED))
+ post->account->add_deferred_post(id(), post);
+ else
+ post->account->add_post(post);
post->xdata().add_flags(POST_EXT_VISITED);
post->account->xdata().add_flags(ACCOUNT_EXT_VISITED);
diff --git a/test/baseline/feat-balance_assert_split.test b/test/baseline/feat-balance_assert_split.test
new file mode 100644
index 00000000..7c2450b6
--- /dev/null
+++ b/test/baseline/feat-balance_assert_split.test
@@ -0,0 +1,55 @@
+;; a.dat
+
+2012-01-01 Test
+ Expenses:Unknown $100.00
+ Liabilities:MasterCard
+
+2012-01-02 Test
+ Expenses:Unknown $100.00
+ Liabilities:MasterCard
+
+2012-01-03 Test
+ Expenses:Unknown $100.00
+ Liabilities:MasterCard
+
+2012-01-04 Test
+ ; UUID: foo
+ Liabilities:MasterCard $150.00 = $-300
+ <Assets:Checking>
+
+2012-01-04 Test
+ ; UUID: bar
+ Liabilities:MasterCard $150.00 = $0
+ <Assets:Checking>
+
+;; b.dat
+
+2012-01-01 Test
+ Assets:Checking $150.00
+ Income
+
+2012-01-02 Test
+ Assets:Checking $150.00
+ Income
+
+2012-01-03 Test
+ Assets:Checking $150.00
+ Income
+
+2012-01-04 Test
+ ; UUID: foo
+ Liabilities:MasterCard $150.00
+ Assets:Checking $-150.00 = $300.00
+
+2012-01-04 Test
+ ; UUID: bar
+ Liabilities:MasterCard $150.00
+ Assets:Checking $-150.00 = $150.00
+
+test balance
+ $150.00 Assets:Checking
+ $300.00 Expenses:Unknown
+ $-450.00 Income
+--------------------
+ 0
+end test