Skip to content

Commit

Permalink
Allow OR type match of more than one different category type (#30)
Browse files Browse the repository at this point in the history
* allow rule match mode for multiple different rules

* grr type litrerals eh

* dependencies
  • Loading branch information
errietta committed Mar 7, 2020
1 parent d1c6098 commit 3a1d445
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 15 deletions.
12 changes: 6 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 14 additions & 5 deletions src/lib/categoriser.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Transaction } from './transaction';

import { parse_string_rules, parse_number_rules, parse_identifier_rules } from './rule/matcher';
import { Category } from '../types/category';
import { CategoryRule } from '../types/category-rule';
import { NumericMatchConfig, StringMatchConfig } from '../types/match-config';

import { RuleMatchMode } from '../lib/enums';

import moment from 'moment';

export class Categoriser {
Expand All @@ -25,7 +26,15 @@ export class Categoriser {
}

static transaction_matches_rule(txn: Transaction, rule: CategoryRule): boolean {
let match: boolean = true;
let mode = rule['mode'] || RuleMatchMode.Strict;
// Start with true for strict mode (if anything doesn't match it's false,
// if all match it's true) or false for flex mode (if any of the things
// match it's true, if none match it's false)
let match: boolean = mode == RuleMatchMode.Strict;

const _cmp = (first: boolean, second: boolean) => (
mode === RuleMatchMode.Strict ? first && second : first || second
);

// identifier match is most important
if (
Expand All @@ -38,15 +47,15 @@ export class Categoriser {
['type', 'description', 'source'].forEach((prop: string) => {
let match_config: StringMatchConfig = rule[prop];
if (match_config) {
match = match && parse_string_rules(txn[prop], match_config);
match = _cmp(match, parse_string_rules(txn[prop], match_config));
}
});

['creditAmount','debitAmount'].forEach((prop: string) => {
let match_config: NumericMatchConfig = rule[prop];

if (match_config) {
match = match && parse_number_rules(txn[prop], match_config);
match = _cmp(match, parse_number_rules(txn[prop], match_config));
}
});

Expand All @@ -55,7 +64,7 @@ export class Categoriser {
let match_config: NumericMatchConfig = rule['txn_day'];

let day: number = moment(txn.date).utc().date();
match = match && parse_number_rules(day, match_config);
match = _cmp(match, parse_number_rules(day, match_config));
}

return match;
Expand Down
2 changes: 2 additions & 0 deletions src/types/category-rule.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { NumericMatchConfig, StringMatchConfig, IdentifierMatchConfig } from "./match-config";
import { RuleMatchMode } from "../lib/enums";

export type CategoryRule = {
identifier?: IdentifierMatchConfig,
Expand All @@ -8,5 +9,6 @@ export type CategoryRule = {
source?: StringMatchConfig;
debitAmount?: NumericMatchConfig;
creditAmount?: NumericMatchConfig;
mode?: RuleMatchMode;
[key: string]: any,
};
24 changes: 20 additions & 4 deletions test/categoriser.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
//mocha -r ts-node/register t/report.spec.ts
import { expect, assert } from 'chai';
import 'mocha';

import { Transaction } from '../src/lib/transaction';
import { Categoriser } from '../src/lib/categoriser';
import { Category } from '../src/types/category';

import { expect, assert } from 'chai';
import 'mocha';
import { RuleMatchMode } from '../src/lib/enums';
import { Category } from '../src/types/category';

describe('Categoriser', () => {
it('Can parse rules', () => {
let transaction = new Transaction({
Expand Down Expand Up @@ -183,6 +184,12 @@ describe('Categoriser', () => {
["=", "CDE"],
]
},
"description": {
"rules": [
["=~", "this is a bill"]
]
},
"mode": RuleMatchMode.Flex
},
"className": "cat-bills",
"id": "bills"
Expand Down Expand Up @@ -350,10 +357,18 @@ describe('Categoriser', () => {
debitAmount: 5000,
creditAmount: 0,
identifier: 'CDE',
}),
new Transaction({
date: '20/01/2017',
type: 'DEB',
description: 'this is a bill',
debitAmount: 99.99,
creditAmount: 0,
})
];

return categoriser.categorise_transactions(transactions).then(() => {
console.log(transactions)
expect(transactions[0].calculatedMonth).to.equal('201701');
expect(transactions[0].categories.map((cat) => cat.id)).to.deep.equal(['tfr-pers']);
expect(Categoriser.is_internal_transfer(transactions[0])).to.be.true;
Expand All @@ -375,6 +390,7 @@ describe('Categoriser', () => {
expect(transactions[8].categories.map((cat) => cat.id)).to.deep.equal(['income']);
expect(transactions[9].categories.map((cat) => cat.id)).to.deep.equal(['exp', 'bills']);
expect(transactions[10].categories.map((cat) => cat.id)).to.deep.equal(['exp', 'bills']);
expect(transactions[11].categories.map((cat) => cat.id)).to.deep.equal(['exp', 'bills']);
});
});
});

0 comments on commit 3a1d445

Please sign in to comment.