summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config.cc2
-rw-r--r--main.cc11
-rw-r--r--reconcile.cc48
-rw-r--r--reconcile.h1
4 files changed, 56 insertions, 6 deletions
diff --git a/config.cc b/config.cc
index 8bdbc4e1..34dc4840 100644
--- a/config.cc
+++ b/config.cc
@@ -168,7 +168,7 @@ void config_t::process_options(const std::string& command,
// Process remaining command-line arguments
- if (command != "e" && command != "w") {
+ if (command != "e" && command != "w" && command != "R") {
// Treat the remaining command-line arguments as regular
// expressions, used for refining report results.
diff --git a/main.cc b/main.cc
index f01b60b1..c2ff8694 100644
--- a/main.cc
+++ b/main.cc
@@ -374,8 +374,15 @@ def vmax(d, val):\n\
walk_transactions(new_entry->transactions, *formatter);
else if (command == "P" || command == "D")
walk_commodities(commodity_t::commodities, *formatter);
- else if (command == "R")
- reconcile_account(*journal, *journal->master, value_t(long(0)));
+ else if (command == "R") {
+ account_t * account = journal->find_account_re(*arg);
+ if (! account)
+ throw error(std::string("Could not find account matching '") +
+ *arg + "'");
+ reconcile_results_t results = reconcile_account(*journal, *account,
+ value_t(*++arg));
+ walk_transactions(results.pending_xacts, *formatter);
+ }
else if (command == "w")
write_textual_journal(*journal, *arg, *formatter, *out);
else
diff --git a/reconcile.cc b/reconcile.cc
index 894175c2..5579da21 100644
--- a/reconcile.cc
+++ b/reconcile.cc
@@ -2,6 +2,27 @@
namespace ledger {
+unsigned long called = 0;
+bool search_for_balance(const value_t& balance,
+ const value_t& amount,
+ transactions_list::iterator beg,
+ transactions_list::iterator end)
+{
+ called++;
+ if (balance == amount)
+ return true;
+
+ for (transactions_list::iterator i = beg; i != end; ) {
+ transactions_list::iterator x = i;
+ (*x)->data = (void *)true;
+ if (search_for_balance(balance, amount + (*x)->amount, ++i, end))
+ return true;
+ (*x)->data = NULL;
+ }
+
+ return false;
+}
+
reconcile_results_t reconcile_account(journal_t& journal,
account_t& account,
const value_t& balance)
@@ -53,17 +74,38 @@ reconcile_results_t reconcile_account(journal_t& journal,
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.
+ value_t to_reconcile = balance - cleared_balance;
if (to_reconcile == pending_balance) {
results.remaining_balance = 0L;
+ results.pending_balance = pending_balance;
results.pending_xacts = pending_xacts;
return results;
}
- throw error("Could not reconcile account");
+ if (search_for_balance(to_reconcile, value_t(),
+ pending_xacts.begin(), pending_xacts.end())) {
+ results.remaining_balance = pending_balance - to_reconcile;
+ results.pending_balance = to_reconcile;
+
+ for (transactions_list::iterator i = pending_xacts.begin();
+ i != pending_xacts.end();
+ i++)
+ if ((*i)->data) {
+ (*i)->data = NULL;
+ results.pending_xacts.push_back(*i);
+ }
+ return results;
+ }
+
+ // At this point we have an uncleared amount X, and a known desired
+ // amount of Y. X != Y because not all of the transactions in
+ // `pending_xacts' are desired, or some are missing, or both. In
+ // the case that none are missing, we now attempt a permutative
+ // search to discover which should be removed to yield the amount Y.
+
+ throw error("Could not reconcile account!");
}
} // namespace ledger
diff --git a/reconcile.h b/reconcile.h
index 2033f1ee..c1494be2 100644
--- a/reconcile.h
+++ b/reconcile.h
@@ -9,6 +9,7 @@ namespace ledger {
struct reconcile_results_t
{
value_t previous_balance;
+ value_t pending_balance;
value_t remaining_balance;
transactions_list pending_xacts;