Added new "payee" and "capture" directives
The payee directive allows for transformation of payee names during the parsing of a Ledger file. This means you can record the payee name in one form, but always have it reported in another form. The syntax is (and will be): payee PAYEE_NAME REGEXP or payee PAYEE_NAME REGEXP1 REGEXP2 ... The account directive sets the account automatically based on the payee iff the base account name is Unknown. For example, if you have a bunch of transaction in Expenses:Unknown, you can assign accounts for several automatically using: account ACCOUNT_NAME PAYEE_REGEXP or account ACCOUNT_NAME PAYEE_REGEXP1 PAYEE_REGEXP2 ...
This commit is contained in:
parent
dc1b390720
commit
3318722089
3 changed files with 62 additions and 1 deletions
|
|
@ -44,6 +44,7 @@
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "times.h"
|
#include "times.h"
|
||||||
|
#include "mask.h"
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
|
|
@ -58,6 +59,11 @@ typedef std::list<xact_t *> xacts_list;
|
||||||
typedef std::list<auto_xact_t *> auto_xacts_list;
|
typedef std::list<auto_xact_t *> auto_xacts_list;
|
||||||
typedef std::list<period_xact_t *> period_xacts_list;
|
typedef std::list<period_xact_t *> period_xacts_list;
|
||||||
|
|
||||||
|
typedef std::pair<mask_t, string> payee_mapping_t;
|
||||||
|
typedef std::list<payee_mapping_t> payee_mappings_t;
|
||||||
|
typedef std::pair<mask_t, account_t *> account_mapping_t;
|
||||||
|
typedef std::list<account_mapping_t> account_mappings_t;
|
||||||
|
|
||||||
class journal_t : public noncopyable
|
class journal_t : public noncopyable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -110,6 +116,8 @@ public:
|
||||||
period_xacts_list period_xacts;
|
period_xacts_list period_xacts;
|
||||||
std::list<fileinfo_t> sources;
|
std::list<fileinfo_t> sources;
|
||||||
bool was_loaded;
|
bool was_loaded;
|
||||||
|
payee_mappings_t payee_mappings;
|
||||||
|
account_mappings_t account_mappings;
|
||||||
|
|
||||||
journal_t();
|
journal_t();
|
||||||
journal_t(const path& pathname);
|
journal_t(const path& pathname);
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,9 @@ public:
|
||||||
|
|
||||||
mask_t& operator=(const string& other);
|
mask_t& operator=(const string& other);
|
||||||
|
|
||||||
|
bool operator<(const mask_t& other) const {
|
||||||
|
return expr < other.expr;
|
||||||
|
}
|
||||||
bool operator==(const mask_t& other) const {
|
bool operator==(const mask_t& other) const {
|
||||||
return expr == other.expr;
|
return expr == other.expr;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -144,6 +144,8 @@ namespace {
|
||||||
void end_directive(char * line);
|
void end_directive(char * line);
|
||||||
void alias_directive(char * line);
|
void alias_directive(char * line);
|
||||||
void fixed_directive(char * line);
|
void fixed_directive(char * line);
|
||||||
|
void payee_mapping_directive(char * line);
|
||||||
|
void account_mapping_directive(char * line);
|
||||||
void tag_directive(char * line);
|
void tag_directive(char * line);
|
||||||
void define_directive(char * line);
|
void define_directive(char * line);
|
||||||
bool general_directive(char * line);
|
bool general_directive(char * line);
|
||||||
|
|
@ -735,6 +737,24 @@ void instance_t::fixed_directive(char * line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void instance_t::payee_mapping_directive(char * line)
|
||||||
|
{
|
||||||
|
char * payee = skip_ws(line);
|
||||||
|
char * regex = next_element(payee, true);
|
||||||
|
|
||||||
|
context.journal.payee_mappings.push_back(payee_mapping_t(mask_t(regex), payee));
|
||||||
|
}
|
||||||
|
|
||||||
|
void instance_t::account_mapping_directive(char * line)
|
||||||
|
{
|
||||||
|
char * account_name = skip_ws(line);
|
||||||
|
char * payee_regex = next_element(account_name, true);
|
||||||
|
|
||||||
|
context.journal.account_mappings.push_back
|
||||||
|
(account_mapping_t(mask_t(payee_regex),
|
||||||
|
context.top_account()->find_account(account_name)));
|
||||||
|
}
|
||||||
|
|
||||||
void instance_t::tag_directive(char * line)
|
void instance_t::tag_directive(char * line)
|
||||||
{
|
{
|
||||||
string tag(trim_ws(line));
|
string tag(trim_ws(line));
|
||||||
|
|
@ -782,6 +802,13 @@ bool instance_t::general_directive(char * line)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'c':
|
||||||
|
if (std::strcmp(p, "capture") == 0) {
|
||||||
|
account_mapping_directive(arg);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case 'd':
|
case 'd':
|
||||||
if (std::strcmp(p, "def") == 0 || std::strcmp(p, "define") == 0) {
|
if (std::strcmp(p, "def") == 0 || std::strcmp(p, "define") == 0) {
|
||||||
define_directive(arg);
|
define_directive(arg);
|
||||||
|
|
@ -810,6 +837,13 @@ bool instance_t::general_directive(char * line)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'p':
|
||||||
|
if (std::strcmp(p, "payee") == 0) {
|
||||||
|
payee_mapping_directive(arg);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case 't':
|
case 't':
|
||||||
if (std::strcmp(p, "tag") == 0) {
|
if (std::strcmp(p, "tag") == 0) {
|
||||||
tag_directive(arg);
|
tag_directive(arg);
|
||||||
|
|
@ -929,6 +963,15 @@ post_t * instance_t::parse_post(char * line,
|
||||||
post->account->add_flags(ACCOUNT_KNOWN);
|
post->account->add_flags(ACCOUNT_KNOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (post->account->name == _("Unknown")) {
|
||||||
|
foreach (account_mapping_t& value, context.journal.account_mappings) {
|
||||||
|
if (value.first.match(xact->payee)) {
|
||||||
|
post->account = value.second;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Parse the optional amount
|
// Parse the optional amount
|
||||||
|
|
||||||
bool saw_amount = false;
|
bool saw_amount = false;
|
||||||
|
|
@ -1242,7 +1285,14 @@ xact_t * instance_t::parse_xact(char * line,
|
||||||
|
|
||||||
if (next && *next) {
|
if (next && *next) {
|
||||||
char * p = next_element(next, true);
|
char * p = next_element(next, true);
|
||||||
xact->payee = next;
|
foreach (payee_mapping_t& value, context.journal.payee_mappings) {
|
||||||
|
if (value.first.match(next)) {
|
||||||
|
xact->payee = value.second;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (xact->payee.empty())
|
||||||
|
xact->payee = next;
|
||||||
next = p;
|
next = p;
|
||||||
} else {
|
} else {
|
||||||
xact->payee = _("<Unspecified payee>");
|
xact->payee = _("<Unspecified payee>");
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue