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;
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;

View file

@ -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);

View file

@ -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

View file

@ -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);

View file

@ -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