This commit is contained in:
John Wiegley 2003-10-11 23:21:14 +00:00
parent ac8a1b741a
commit fb4fed00ba
5 changed files with 143 additions and 162 deletions

View file

@ -64,7 +64,7 @@ static void startElement(void *userData, const char *name, const char **atts)
action = COMM_PREC; action = COMM_PREC;
else if (std::strcmp(name, "gnc:transaction") == 0) { else if (std::strcmp(name, "gnc:transaction") == 0) {
assert(! curr_entry); assert(! curr_entry);
curr_entry = new entry; curr_entry = new entry(main_ledger);
} }
else if (std::strcmp(name, "trn:num") == 0) else if (std::strcmp(name, "trn:num") == 0)
action = ENTRY_NUM; action = ENTRY_NUM;

View file

@ -220,10 +220,10 @@ bool entry::finalize(bool do_compute)
// transactions and create new virtual transactions for all that // transactions and create new virtual transactions for all that
// apply. // apply.
for (book::virtual_map_iterator m = main_ledger->virtual_mapping.begin(); for (book::virtual_map_iterator m = ledger->virtual_mapping.begin();
m != main_ledger->virtual_mapping.end(); m != ledger->virtual_mapping.end();
m++) { m++) {
std::list<transaction *> xacts; std::list<transaction *> new_xacts;
for (std::list<transaction *>::iterator x = xacts.begin(); for (std::list<transaction *>::iterator x = xacts.begin();
x != xacts.end(); x != xacts.end();
@ -248,40 +248,7 @@ bool entry::finalize(bool do_compute)
t->is_virtual = (*i)->is_virtual; t->is_virtual = (*i)->is_virtual;
t->must_balance = (*i)->must_balance; t->must_balance = (*i)->must_balance;
// If there is already a virtual transaction for the new_xacts.push_back(t);
// 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);
} }
} }
@ -290,8 +257,8 @@ bool entry::finalize(bool do_compute)
// iteration above is screwed up if we try adding new // iteration above is screwed up if we try adding new
// transactions during the traversal. // transactions during the traversal.
for (std::list<transaction *>::iterator x = xacts.begin(); for (std::list<transaction *>::iterator x = new_xacts.begin();
x != xacts.end(); x != new_xacts.end();
x++) { x++) {
xacts.push_back(*x); xacts.push_back(*x);

View file

@ -1,5 +1,5 @@
#ifndef _LEDGER_H #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 class entry
{ {
entry(const entry&); entry(const entry&);
public: public:
book * ledger;
std::time_t date; std::time_t date;
std::string code; std::string code;
std::string desc; std::string desc;
@ -165,7 +168,7 @@ class entry
std::list<transaction *> xacts; 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 // 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 // throw away the heap on exit, than spend time freeing things up

View file

@ -188,7 +188,7 @@ transaction * parse_transaction(std::istream& in, book * ledger)
entry * parse_entry(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]; static char line[MAX_LINE + 1];
in.getline(line, MAX_LINE); in.getline(line, MAX_LINE);

View file

@ -308,7 +308,7 @@ static void equity_entry(account * acct, regexps_map& regexps,
{ {
if (! acct->balance.is_zero() && if (! acct->balance.is_zero() &&
(regexps.empty() || matches(regexps, acct->as_str()))) { (regexps.empty() || matches(regexps, acct->as_str()))) {
entry opening; entry opening(main_ledger);
opening.date = std::time(NULL); opening.date = std::time(NULL);
opening.cleared = true; opening.cleared = true;
@ -357,6 +357,128 @@ void equity_ledger(std::ostream& out, regexps_map& regexps)
equity_entry((*i).second, regexps, out); 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. // 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, // 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. // 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; have_beginning = true;
if (! parse_date(optarg, &begin_date)) { if (! parse_date(optarg, &begin_date)) {
std::cerr << "Error: Bad begin date: " << optarg << std::endl; std::cerr << "Error: Bad begin date: " << optarg << std::endl;
return 1; std::exit(1);
} }
break; break;
@ -439,7 +561,7 @@ int main(int argc, char * argv[])
have_ending = true; have_ending = true;
if (! parse_date(optarg, &end_date)) { if (! parse_date(optarg, &end_date)) {
std::cerr << "Error: Bad end date: " << optarg << std::endl; std::cerr << "Error: Bad end date: " << optarg << std::endl;
return 1; std::exit(1);
} }
break; break;
@ -452,7 +574,7 @@ int main(int argc, char * argv[])
have_date_mask = true; have_date_mask = true;
if (! parse_date_mask(optarg, &date_mask)) { if (! parse_date_mask(optarg, &date_mask)) {
std::cerr << "Error: Bad date mask: " << optarg << std::endl; std::cerr << "Error: Bad date mask: " << optarg << std::endl;
return 1; std::exit(1);
} }
break; break;
@ -498,7 +620,7 @@ int main(int argc, char * argv[])
if (optind == argc) { if (optind == argc) {
show_help(std::cout); show_help(std::cout);
return 1; std::exit(1);
} }
index = optind; index = optind;
@ -514,7 +636,7 @@ int main(int argc, char * argv[])
std::cerr << ("Please specify ledger file using -f option " std::cerr << ("Please specify ledger file using -f option "
"or LEDGER environment variable.") "or LEDGER environment variable.")
<< std::endl; << std::endl;
return 1; std::exit(1);
} }
} }
@ -527,7 +649,7 @@ int main(int argc, char * argv[])
if (optind == argc) { if (optind == argc) {
std::cerr << ("Error: Must specify an account name " std::cerr << ("Error: Must specify an account name "
"after the 'register' command.") << std::endl; "after the 'register' command.") << std::endl;
return 1; std::exit(1);
} }
index++; index++;
} }
@ -592,118 +714,7 @@ int main(int argc, char * argv[])
equity_ledger(std::cout, regexps); equity_ledger(std::cout, regexps);
} }
else if (command == "add") { else if (command == "add") {
entry added, * matching = NULL; add_new_entry(index, argc, argv);
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);
} }
#ifdef DEBUG #ifdef DEBUG