From c22b8457eff27f5227fdf452e036b33e41e229c2 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Wed, 11 Nov 2009 18:29:21 -0500 Subject: Did away with the "finalizer" abstraction This was from an earlier time, when it was intended to be used by Python. But it's not needed anymore. --- src/xact.h | 70 -------------------------------------------------------------- 1 file changed, 70 deletions(-) (limited to 'src/xact.h') diff --git a/src/xact.h b/src/xact.h index ff1f65fa..271340f8 100644 --- a/src/xact.h +++ b/src/xact.h @@ -140,11 +140,6 @@ private: #endif // HAVE_BOOST_SERIALIZATION }; -struct xact_finalizer_t { - virtual ~xact_finalizer_t() {} - virtual bool operator()(xact_t& xact) = 0; -}; - class auto_xact_t : public xact_base_t { public: @@ -183,39 +178,6 @@ private: #endif // HAVE_BOOST_SERIALIZATION }; -struct auto_xact_finalizer_t : public xact_finalizer_t -{ - journal_t * journal; - - auto_xact_finalizer_t() : journal(NULL) { - TRACE_CTOR(auto_xact_finalizer_t, ""); - } - auto_xact_finalizer_t(const auto_xact_finalizer_t& other) - : xact_finalizer_t(), journal(other.journal) { - TRACE_CTOR(auto_xact_finalizer_t, "copy"); - } - auto_xact_finalizer_t(journal_t * _journal) : journal(_journal) { - TRACE_CTOR(auto_xact_finalizer_t, "journal_t *"); - } - ~auto_xact_finalizer_t() throw() { - TRACE_DTOR(auto_xact_finalizer_t); - } - - virtual bool operator()(xact_t& xact); - -#if defined(HAVE_BOOST_SERIALIZATION) -private: - /** Serialization. */ - - friend class boost::serialization::access; - - template - void serialize(Archive& ar, const unsigned int /* version */) { - ar & journal; - } -#endif // HAVE_BOOST_SERIALIZATION -}; - class period_xact_t : public xact_base_t { public: @@ -253,38 +215,6 @@ private: #endif // HAVE_BOOST_SERIALIZATION }; -class func_finalizer_t : public xact_finalizer_t -{ - func_finalizer_t(); - -public: - typedef function func_t; - - func_t func; - - func_finalizer_t(func_t _func) : func(_func) { - TRACE_CTOR(func_finalizer_t, "func_t"); - } - func_finalizer_t(const func_finalizer_t& other) : - xact_finalizer_t(), func(other.func) { - TRACE_CTOR(func_finalizer_t, "copy"); - } - ~func_finalizer_t() throw() { - TRACE_DTOR(func_finalizer_t); - } - - virtual bool operator()(xact_t& xact) { - return func(xact); - } -}; - -void extend_xact_base(journal_t * journal, xact_base_t& xact); - -inline bool auto_xact_finalizer_t::operator()(xact_t& xact) { - extend_xact_base(journal, xact); - return true; -} - typedef std::list xacts_list; typedef std::list auto_xacts_list; typedef std::list period_xacts_list; -- cgit v1.2.3 From b6ff8f19d5158977dcb09ea6cf94b07b00937f4a Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Wed, 11 Nov 2009 21:33:07 -0500 Subject: Transactions now verified after applying auto xacts This way you cannot violate the balancing rules, not even by adding a stray posting via an automated transaction. --- src/xact.cc | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/xact.h | 3 ++- 2 files changed, 59 insertions(+), 1 deletion(-) (limited to 'src/xact.h') diff --git a/src/xact.cc b/src/xact.cc index 8ac5280a..86b55dd5 100644 --- a/src/xact.cc +++ b/src/xact.cc @@ -372,6 +372,55 @@ bool xact_base_t::finalize() return true; } +bool xact_base_t::verify() +{ + // Scan through and compute the total balance for the xact. + + value_t balance; + + foreach (post_t * post, posts) { + if (! post->must_balance()) + continue; + + amount_t& p(post->cost ? *post->cost : post->amount); + assert(! p.is_null()); + + // If the amount was a cost, it very likely has the "keep_precision" flag + // set, meaning commodity display precision is ignored when displaying the + // amount. We never want this set for the balance, so we must clear the + // flag in a temporary to avoid it propagating into the balance. + add_or_set_value(balance, p.keep_precision() ? + p.rounded().reduced() : p.reduced()); + } + VERIFY(balance.valid()); + + // Now that the post list has its final form, calculate the balance once + // more in terms of total cost, accounting for any possible gain/loss + // amounts. + + foreach (post_t * post, posts) { + if (! post->cost) + continue; + + if (post->amount.commodity() == post->cost->commodity()) + throw_(balance_error, + _("A posting's cost must be of a different commodity than its amount")); + } + + if (! balance.is_null() && ! balance.is_zero()) { + add_error_context(item_context(*this, _("While balancing transaction"))); + add_error_context(_("Unbalanced remainder is:")); + add_error_context(value_context(balance)); + add_error_context(_("Amount to balance against:")); + add_error_context(value_context(magnitude())); + throw_(balance_error, _("Transaction does not balance")); + } + + VERIFY(valid()); + + return true; +} + xact_t::xact_t(const xact_t& e) : xact_base_t(e), code(e.code), payee(e.payee) { @@ -486,6 +535,8 @@ void auto_xact_t::extend_xact(xact_base_t& xact) try { + bool needs_further_verification = false; + foreach (post_t * initial_post, initial_posts) { if (! initial_post->has_flags(ITEM_GENERATED) && predicate(*initial_post)) { @@ -555,10 +606,16 @@ void auto_xact_t::extend_xact(xact_base_t& xact) xact.add_post(new_post); new_post->account->add_post(new_post); + + if (new_post->must_balance()) + needs_further_verification = true; } } } + if (needs_further_verification) + xact.verify(); + } catch (const std::exception& err) { add_error_context(item_context(*this, _("While applying automated transaction"))); diff --git a/src/xact.h b/src/xact.h index 271340f8..933a5fd7 100644 --- a/src/xact.h +++ b/src/xact.h @@ -77,7 +77,8 @@ public: value_t magnitude() const; - virtual bool finalize(); + bool finalize(); + bool verify(); void clear_xdata(); -- cgit v1.2.3 From 48dc654eda27c01d0bad88674d21d0e33e5472f6 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Thu, 12 Nov 2009 05:09:25 -0500 Subject: Added has_xdata() methods for journal_t and xact_t --- src/account.cc | 13 +++++++++++-- src/account.h | 1 + src/journal.cc | 20 ++++++++++++++++++++ src/journal.h | 1 + src/py_journal.cc | 1 + src/py_xact.cc | 1 + src/xact.cc | 9 +++++++++ src/xact.h | 1 + 8 files changed, 45 insertions(+), 2 deletions(-) (limited to 'src/xact.h') diff --git a/src/account.cc b/src/account.cc index 5cc7e070..da43745a 100644 --- a/src/account.cc +++ b/src/account.cc @@ -327,16 +327,25 @@ bool account_t::valid() const return true; } +bool account_t::children_with_xdata() const +{ + foreach (const accounts_map::value_type& pair, accounts) + if (pair.second->has_xdata() || + pair.second->children_with_xdata()) + return true; + + return false; +} + std::size_t account_t::children_with_flags(xdata_t::flags_t flags) const { std::size_t count = 0; bool grandchildren_visited = false; - foreach (const accounts_map::value_type& pair, accounts) { + foreach (const accounts_map::value_type& pair, accounts) if (pair.second->has_xflags(flags) || pair.second->children_with_flags(flags)) count++; - } // Although no immediately children were visited, if any progeny at all were // visited, it counts as one. diff --git a/src/account.h b/src/account.h index 0ac1aeb6..1e56fe23 100644 --- a/src/account.h +++ b/src/account.h @@ -241,6 +241,7 @@ public: bool has_xflags(xdata_t::flags_t flags) const { return xdata_ && xdata_->has_flags(flags); } + bool children_with_xdata() const; std::size_t children_with_flags(xdata_t::flags_t flags) const; #if defined(HAVE_BOOST_SERIALIZATION) diff --git a/src/journal.cc b/src/journal.cc index c764dbce..2366ce30 100644 --- a/src/journal.cc +++ b/src/journal.cc @@ -211,6 +211,26 @@ std::size_t journal_t::read(const path& pathname, return count; } +bool journal_t::has_xdata() +{ + foreach (xact_t * xact, xacts) + if (xact->has_xdata()) + return true; + + foreach (auto_xact_t * xact, auto_xacts) + if (xact->has_xdata()) + return true; + + foreach (period_xact_t * xact, period_xacts) + if (xact->has_xdata()) + return true; + + if (master->has_xdata() || master->children_with_xdata()) + return true; + + return false; +} + void journal_t::clear_xdata() { foreach (xact_t * xact, xacts) diff --git a/src/journal.h b/src/journal.h index 68fde517..f7124736 100644 --- a/src/journal.h +++ b/src/journal.h @@ -172,6 +172,7 @@ public: const path * original_file = NULL, bool strict = false); + bool has_xdata(); void clear_xdata(); bool valid() const; diff --git a/src/py_journal.cc b/src/py_journal.cc index 7fc1561d..51979438 100644 --- a/src/py_journal.cc +++ b/src/py_journal.cc @@ -197,6 +197,7 @@ void export_journal() .def("read", py_read) + .def("has_xdata", &journal_t::has_xdata) .def("clear_xdata", &journal_t::clear_xdata) .def("valid", &journal_t::valid) diff --git a/src/py_xact.cc b/src/py_xact.cc index 81847656..59c599d9 100644 --- a/src/py_xact.cc +++ b/src/py_xact.cc @@ -122,6 +122,7 @@ void export_xact() .def("lookup", &xact_t::lookup) + .def("has_xdata", &xact_t::has_xdata) .def("clear_xdata", &xact_t::clear_xdata) .def("valid", &xact_t::valid) diff --git a/src/xact.cc b/src/xact.cc index 86b55dd5..1cece187 100644 --- a/src/xact.cc +++ b/src/xact.cc @@ -76,6 +76,15 @@ bool xact_base_t::remove_post(post_t * post) return true; } +bool xact_base_t::has_xdata() +{ + foreach (post_t * post, posts) + if (post->has_xdata()) + return true; + + return false; +} + void xact_base_t::clear_xdata() { foreach (post_t * post, posts) diff --git a/src/xact.h b/src/xact.h index 933a5fd7..fe748fcc 100644 --- a/src/xact.h +++ b/src/xact.h @@ -80,6 +80,7 @@ public: bool finalize(); bool verify(); + bool has_xdata(); void clear_xdata(); virtual bool valid() const { -- cgit v1.2.3