c
This commit is contained in:
parent
ac8a1b741a
commit
fb4fed00ba
5 changed files with 143 additions and 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;
|
||||
|
|
|
|||
45
ledger.cc
45
ledger.cc
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
7
ledger.h
7
ledger.h
|
|
@ -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
|
||||
|
|
|
|||
2
parse.cc
2
parse.cc
|
|
@ -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);
|
||||
|
|
|
|||
249
reports.cc
249
reports.cc
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue