diff options
author | John Wiegley <johnw@newartisans.com> | 2003-10-11 23:21:14 +0000 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2003-10-11 23:21:14 +0000 |
commit | fb4fed00ba3dede4c649e21ce64cf29a8244c8bd (patch) | |
tree | 7107662d45768b11ccd9b9c24f69798155d001d2 | |
parent | ac8a1b741aa975e7957930d2ad89c0bec9675f7f (diff) | |
download | fork-ledger-fb4fed00ba3dede4c649e21ce64cf29a8244c8bd.tar.gz fork-ledger-fb4fed00ba3dede4c649e21ce64cf29a8244c8bd.tar.bz2 fork-ledger-fb4fed00ba3dede4c649e21ce64cf29a8244c8bd.zip |
c
-rw-r--r-- | gnucash.cc | 2 | ||||
-rw-r--r-- | ledger.cc | 45 | ||||
-rw-r--r-- | ledger.h | 7 | ||||
-rw-r--r-- | parse.cc | 2 | ||||
-rw-r--r-- | reports.cc | 249 |
5 files changed, 143 insertions, 162 deletions
@@ -64,7 +64,7 @@ static void startElement(void *userData, const char *name, const char **atts) action = COMM_PREC; else if (std::strcmp(name, "gnc:transaction") == 0) { assert(! curr_entry); - curr_entry = new entry; + curr_entry = new entry(main_ledger); } else if (std::strcmp(name, "trn:num") == 0) action = ENTRY_NUM; @@ -220,10 +220,10 @@ bool entry::finalize(bool do_compute) // transactions and create new virtual transactions for all that // apply. - for (book::virtual_map_iterator m = main_ledger->virtual_mapping.begin(); - m != main_ledger->virtual_mapping.end(); + for (book::virtual_map_iterator m = ledger->virtual_mapping.begin(); + m != ledger->virtual_mapping.end(); m++) { - std::list<transaction *> xacts; + std::list<transaction *> new_xacts; for (std::list<transaction *>::iterator x = xacts.begin(); x != xacts.end(); @@ -248,40 +248,7 @@ bool entry::finalize(bool do_compute) t->is_virtual = (*i)->is_virtual; t->must_balance = (*i)->must_balance; - // If there is already a virtual transaction for the - // account under consideration, and it's `must_balance' - // flag matches, then simply add this amount to that - // transaction. - - bool added = false; - - for (std::list<transaction *>::iterator y = xacts.begin(); - y != xacts.end(); - y++) { - if ((*y)->is_virtual && (*y)->acct == t->acct && - (*y)->must_balance == t->must_balance) { - (*y)->cost->credit(t->cost); - delete t; - added = true; - break; - } - } - - if (! added) - for (std::list<transaction *>::iterator y = xacts.begin(); - y != xacts.end(); - y++) { - if ((*y)->is_virtual && (*y)->acct == t->acct && - (*y)->must_balance == t->must_balance) { - (*y)->cost->credit(t->cost); - delete t; - added = true; - break; - } - } - - if (! added) - xacts.push_back(t); + new_xacts.push_back(t); } } @@ -290,8 +257,8 @@ bool entry::finalize(bool do_compute) // iteration above is screwed up if we try adding new // transactions during the traversal. - for (std::list<transaction *>::iterator x = xacts.begin(); - x != xacts.end(); + for (std::list<transaction *>::iterator x = new_xacts.begin(); + x != new_xacts.end(); x++) { xacts.push_back(*x); @@ -1,5 +1,5 @@ #ifndef _LEDGER_H -#define _LEDGER_H "$Revision: 1.26 $" +#define _LEDGER_H "$Revision: 1.27 $" ////////////////////////////////////////////////////////////////////// // @@ -152,11 +152,14 @@ class transaction }; +class book; class entry { entry(const entry&); public: + book * ledger; + std::time_t date; std::string code; std::string desc; @@ -165,7 +168,7 @@ class entry std::list<transaction *> xacts; - explicit entry() : cleared(false) {} + explicit entry(book * l) : ledger(l), cleared(false) {} // If we're running as a command-line tool, it's cheaper to just // throw away the heap on exit, than spend time freeing things up @@ -188,7 +188,7 @@ transaction * parse_transaction(std::istream& in, book * ledger) entry * parse_entry(std::istream& in, book * ledger) { - entry * curr = new entry; + entry * curr = new entry(ledger); static char line[MAX_LINE + 1]; in.getline(line, MAX_LINE); @@ -308,7 +308,7 @@ static void equity_entry(account * acct, regexps_map& regexps, { if (! acct->balance.is_zero() && (regexps.empty() || matches(regexps, acct->as_str()))) { - entry opening; + entry opening(main_ledger); opening.date = std::time(NULL); opening.cleared = true; @@ -357,6 +357,128 @@ void equity_ledger(std::ostream& out, regexps_map& regexps) equity_entry((*i).second, regexps, out); } +// Add a new entry, using hueristic logic to simplify the entry +// requirements + +void add_new_entry(int index, int argc, char **argv) +{ + regexps_map regexps; + entry added(main_ledger); + entry * matching = NULL; + + if (! parse_date(argv[index++], &added.date)) { + std::cerr << "Error: Bad add date: " << argv[index - 1] + << std::endl; + std::exit(1); + } + + added.cleared = show_cleared; + + if (index == argc) { + std::cerr << "Error: Too few arguments to 'add'." << std::endl; + std::exit(1); + } + + regexps.clear(); + regexps.push_back(mask(argv[index++])); + + for (entries_list_reverse_iterator i = main_ledger->entries.rbegin(); + i != main_ledger->entries.rend(); + i++) { + if ((*i)->matches(regexps)) { + matching = *i; + break; + } + } + + added.desc = matching ? matching->desc : regexps.front().pattern; + + if (index == argc) { + std::cerr << "Error: Too few arguments to 'add'." << std::endl; + std::exit(1); + } + + if (argv[index][0] == '-' || std::isdigit(argv[index][0])) { + if (! matching) { + std::cerr << "Error: Missing account name for non-matching entry." + << std::endl; + std::exit(1); + } + + transaction * m_xact, * xact, * first; + + m_xact = matching->xacts.front(); + + first = xact = new transaction(); + xact->acct = m_xact->acct; + xact->cost = create_amount(argv[index++]); + xact->cost->set_commdty(m_xact->cost->commdty()); + + added.xacts.push_back(xact); + + m_xact = matching->xacts.back(); + + xact = new transaction(); + xact->acct = m_xact->acct; + xact->cost = first->cost->copy(); + xact->cost->negate(); + + added.xacts.push_back(xact); + + if ((index + 1) < argc && std::string(argv[index]) == "-from") + if (account * acct = main_ledger->re_find_account(argv[++index])) + added.xacts.back()->acct = acct; + } else { + while (index < argc && std::string(argv[index]) != "-from") { + transaction * xact = new transaction(); + + mask acct_regex(argv[index++]); + + account * acct = NULL; + for (std::list<transaction *>::iterator x = matching->xacts.begin(); + x != matching->xacts.end(); + x++) { + if (acct_regex.match((*x)->acct->as_str())) { + acct = (*x)->acct; + break; + } + } + + if (acct) + xact->acct = acct; + else + xact->acct = main_ledger->re_find_account(acct_regex.pattern); + + if (! xact->acct) { + std::cerr << "Error: Could not find account name '" + << acct_regex.pattern << "'." << std::endl; + std::exit(1); + } + + if (index == argc) { + std::cerr << "Error: Too few arguments to 'add'." << std::endl; + std::exit(1); + } + + xact->cost = create_amount(argv[index++]); + + added.xacts.push_back(xact); + } + + if ((index + 1) < argc && std::string(argv[index]) == "-from") + if (account * acct = main_ledger->re_find_account(argv[++index])) { + transaction * xact = new transaction(); + xact->acct = acct; + xact->cost = NULL; + + added.xacts.push_back(xact); + } + } + + if (added.finalize()) + added.print(std::cout); +} + // Print out the entire ledger that was read in, sorted by date. // This can be used to "wash" ugly ledger files. It's written here, // instead of ledger.cc, in order to access the static globals above. @@ -431,7 +553,7 @@ int main(int argc, char * argv[]) have_beginning = true; if (! parse_date(optarg, &begin_date)) { std::cerr << "Error: Bad begin date: " << optarg << std::endl; - return 1; + std::exit(1); } break; @@ -439,7 +561,7 @@ int main(int argc, char * argv[]) have_ending = true; if (! parse_date(optarg, &end_date)) { std::cerr << "Error: Bad end date: " << optarg << std::endl; - return 1; + std::exit(1); } break; @@ -452,7 +574,7 @@ int main(int argc, char * argv[]) have_date_mask = true; if (! parse_date_mask(optarg, &date_mask)) { std::cerr << "Error: Bad date mask: " << optarg << std::endl; - return 1; + std::exit(1); } break; @@ -498,7 +620,7 @@ int main(int argc, char * argv[]) if (optind == argc) { show_help(std::cout); - return 1; + std::exit(1); } index = optind; @@ -514,7 +636,7 @@ int main(int argc, char * argv[]) std::cerr << ("Please specify ledger file using -f option " "or LEDGER environment variable.") << std::endl; - return 1; + std::exit(1); } } @@ -527,7 +649,7 @@ int main(int argc, char * argv[]) if (optind == argc) { std::cerr << ("Error: Must specify an account name " "after the 'register' command.") << std::endl; - return 1; + std::exit(1); } index++; } @@ -592,118 +714,7 @@ int main(int argc, char * argv[]) equity_ledger(std::cout, regexps); } else if (command == "add") { - entry added, * matching = NULL; - - if (! parse_date(argv[index++], &added.date)) { - std::cerr << "Error: Bad add date: " << argv[index - 1] - << std::endl; - return 1; - } - - added.cleared = show_cleared; - - if (index == argc) { - std::cerr << "Error: Too few arguments to 'add'." << std::endl; - return 1; - } - - regexps.clear(); - regexps.push_back(mask(argv[index++])); - - for (entries_list_reverse_iterator i = main_ledger->entries.rbegin(); - i != main_ledger->entries.rend(); - i++) { - if ((*i)->matches(regexps)) { - matching = *i; - break; - } - } - - added.desc = matching ? matching->desc : regexps.front().pattern; - - if (index == argc) { - std::cerr << "Error: Too few arguments to 'add'." << std::endl; - return 1; - } - - if (argv[index][0] == '-' || std::isdigit(argv[index][0])) { - if (! matching) { - std::cerr << "Error: Missing account name for non-matching entry." - << std::endl; - return 1; - } - - transaction * m_xact, * xact, * first; - - m_xact = matching->xacts.front(); - - first = xact = new transaction(); - xact->acct = m_xact->acct; - xact->cost = create_amount(argv[index++]); - xact->cost->set_commdty(m_xact->cost->commdty()); - - added.xacts.push_back(xact); - - m_xact = matching->xacts.back(); - - xact = new transaction(); - xact->acct = m_xact->acct; - xact->cost = first->cost->copy(); - xact->cost->negate(); - - added.xacts.push_back(xact); - - if ((index + 1) < argc && std::string(argv[index]) == "-from") - if (account * acct = main_ledger->re_find_account(argv[++index])) - added.xacts.back()->acct = acct; - } else { - while (index < argc && std::string(argv[index]) != "-from") { - transaction * xact = new transaction(); - - mask acct_regex(argv[index++]); - - account * acct = NULL; - for (std::list<transaction *>::iterator x = matching->xacts.begin(); - x != matching->xacts.end(); - x++) { - if (acct_regex.match((*x)->acct->as_str())) { - acct = (*x)->acct; - break; - } - } - - if (acct) - xact->acct = acct; - else - xact->acct = main_ledger->re_find_account(acct_regex.pattern); - - if (! xact->acct) { - std::cerr << "Error: Could not find account name '" - << acct_regex.pattern << "'." << std::endl; - return 1; - } - - if (index == argc) { - std::cerr << "Error: Too few arguments to 'add'." << std::endl; - return 1; - } - - xact->cost = create_amount(argv[index++]); - added.xacts.push_back(xact); - } - - if ((index + 1) < argc && std::string(argv[index]) == "-from") - if (account * acct = main_ledger->re_find_account(argv[++index])) { - transaction * xact = new transaction(); - xact->acct = acct; - xact->cost = NULL; - - added.xacts.push_back(xact); - } - } - - if (added.finalize()) - added.print(std::cout); + add_new_entry(index, argc, argv); } #ifdef DEBUG |