summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--reconcile.cc69
-rw-r--r--reconcile.h23
3 files changed, 94 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am
index ae954adb..eea0b79d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -14,6 +14,7 @@ libledger_a_SOURCES = \
parser.cc \
qif.cc \
quotes.cc \
+ reconcile.cc \
textual.cc \
valexpr.cc \
value.cc \
@@ -52,6 +53,7 @@ pkginclude_HEADERS = \
pyledger.h \
qif.h \
quotes.h \
+ reconcile.h \
textual.h \
timing.h \
util.h \
diff --git a/reconcile.cc b/reconcile.cc
new file mode 100644
index 00000000..894175c2
--- /dev/null
+++ b/reconcile.cc
@@ -0,0 +1,69 @@
+#include "reconcile.h"
+
+namespace ledger {
+
+reconcile_results_t reconcile_account(journal_t& journal,
+ account_t& account,
+ const value_t& balance)
+{
+ // This routine attempts to reconcile an account against a given
+ // `balance' by marking transactions as "cleared" until the cleared
+ // balance matches the expected `balance'.
+ //
+ // The real difficulty is that sometimes there are transactions in
+ // the journal which never make it to the statement (they might be
+ // drawing from the wrong account), or there could be transactions
+ // which haven't been added yet. In both of these cases the best
+ // one can do is guess, and if that fails, to throw up their hands
+ // in despair.
+ //
+ // As such, this algorithm is very likely to fail. The hope is that
+ // sometimes it won't fail, and then it can save the user a fair bit
+ // of time.
+ //
+ // If the algorithm succeeds in auto-reconciling the account, then
+ // all the relevant data is return in the form of a
+ // `reconcile_results_t' structure (see reconcile.h).
+
+ // Compute the current balances for the given account.
+ value_t cleared_balance;
+ value_t pending_balance;
+
+ reconcile_results_t results;
+ transactions_list pending_xacts;
+
+ for (entries_list::iterator e = journal.entries.begin();
+ e != journal.entries.end();
+ e++)
+ for (transactions_list::iterator x = (*e)->transactions.begin();
+ x != (*e)->transactions.end();
+ x++)
+ if ((*x)->account == &account) {
+ switch ((*e)->state) {
+ case entry_t::CLEARED:
+ cleared_balance += (*x)->amount;
+ break;
+ case entry_t::UNCLEARED:
+ case entry_t::PENDING:
+ pending_balance += (*x)->amount;
+ pending_xacts.push_back(*x);
+ break;
+ }
+ }
+
+ results.previous_balance = cleared_balance;
+
+ value_t to_reconcile = balance - cleared_balance;
+
+ // If the amount to reconcile is the same as the pending balance,
+ // then assume an exact match and return the results right away.
+ if (to_reconcile == pending_balance) {
+ results.remaining_balance = 0L;
+ results.pending_xacts = pending_xacts;
+ return results;
+ }
+
+ throw error("Could not reconcile account");
+}
+
+} // namespace ledger
diff --git a/reconcile.h b/reconcile.h
new file mode 100644
index 00000000..2033f1ee
--- /dev/null
+++ b/reconcile.h
@@ -0,0 +1,23 @@
+#ifndef _RECONCILE_H
+#define _RECONCILE_H
+
+#include "journal.h"
+#include "walk.h"
+
+namespace ledger {
+
+struct reconcile_results_t
+{
+ value_t previous_balance;
+ value_t remaining_balance;
+
+ transactions_list pending_xacts;
+};
+
+reconcile_results_t reconcile_account(journal_t& journal,
+ account_t& account,
+ const value_t& balance);
+
+} // namespace ledger
+
+#endif // _RECONCILE_H