use a CSV file for the rules instead
This commit is contained in:
parent
161ad4e220
commit
6aa366c714
3 changed files with 17 additions and 27 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -2,4 +2,4 @@
|
||||||
bin/
|
bin/
|
||||||
obj/
|
obj/
|
||||||
test.csv
|
test.csv
|
||||||
rules.json
|
rules.csv
|
||||||
|
|
19
Program.cs
19
Program.cs
|
@ -20,10 +20,8 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text.Json;
|
|
||||||
using System.CommandLine.DragonFruit;
|
using System.CommandLine.DragonFruit;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
using CsvHelper;
|
using CsvHelper;
|
||||||
|
|
||||||
namespace BunyMuny {
|
namespace BunyMuny {
|
||||||
|
@ -32,18 +30,16 @@ namespace BunyMuny {
|
||||||
/// BunyMuny parses the CSV output of various bank statement listings and converts it to something more human readable with nice visualisations.
|
/// BunyMuny parses the CSV output of various bank statement listings and converts it to something more human readable with nice visualisations.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="file">The CSV file to read</param>
|
/// <param name="file">The CSV file to read</param>
|
||||||
/// <param name="ruleFile">The JSON file to use for rules when parsing statement descriptions</param>
|
/// <param name="ruleFile">The CSV file to use for rules when parsing statement descriptions</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private static int Main(string file = "test.csv", string ruleFile = "rules.json") {
|
private static int Main(string file = "test.csv", string ruleFile = "rules.csv") {
|
||||||
var bank = Bank.Other;
|
var bank = Bank.Other;
|
||||||
var statements = new List<Statement>();
|
var statements = new List<Statement>();
|
||||||
List<Rule> rules;
|
List<Rule> rules;
|
||||||
|
|
||||||
using (var ruleStreamReader = new StreamReader(ruleFile)) {
|
using (var ruleStreamReader = new StreamReader(ruleFile)) {
|
||||||
var jsonOptions = new JsonSerializerOptions();
|
using var ruleCsv = new CsvReader(ruleStreamReader,CultureInfo.InvariantCulture);
|
||||||
jsonOptions.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase));
|
rules = ruleCsv.GetRecords<Rule>().ToList();
|
||||||
jsonOptions.WriteIndented = true;
|
|
||||||
rules = JsonSerializer.Deserialize<List<Rule>>(ruleStreamReader.ReadToEnd(), jsonOptions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
using var sr = new StreamReader(file);
|
using var sr = new StreamReader(file);
|
||||||
|
@ -73,14 +69,13 @@ namespace BunyMuny {
|
||||||
switch (bank) {
|
switch (bank) {
|
||||||
case Bank.ME:
|
case Bank.ME:
|
||||||
var value = double.Parse(csv.GetField("Debits and credits").TrimStart().Replace("$", ""));
|
var value = double.Parse(csv.GetField("Debits and credits").TrimStart().Replace("$", ""));
|
||||||
// SHOW PET THIS
|
var (category, description) = MatchAgainstRules(rules, csv.GetField("Description"));
|
||||||
var ruleValues = MatchAgainstRules(rules, csv.GetField("Description"));
|
|
||||||
|
|
||||||
statements.Add(new Statement() {
|
statements.Add(new Statement() {
|
||||||
Date = DateTime.ParseExact(csv.GetField("Date"), "dd/MM/yyyy", CultureInfo.InvariantCulture),
|
Date = DateTime.ParseExact(csv.GetField("Date"), "dd/MM/yyyy", CultureInfo.InvariantCulture),
|
||||||
OriginalDescription = csv.GetField("Description"),
|
OriginalDescription = csv.GetField("Description"),
|
||||||
Description = ruleValues.Description,
|
Description = description,
|
||||||
Category = ruleValues.Category,
|
Category = category,
|
||||||
Value = value
|
Value = value
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
23
README.md
23
README.md
|
@ -13,24 +13,19 @@ dotnet build
|
||||||
|
|
||||||
## The rules file
|
## The rules file
|
||||||
By default, BunyMuny checks for rules in `rules.json` in the current directory. An example rules file might look like this:
|
By default, BunyMuny checks for rules in `rules.json` in the current directory. An example rules file might look like this:
|
||||||
```json
|
```csv
|
||||||
[
|
Match,Value,Category,Description,CaseSensitive
|
||||||
{
|
Start,Purchase Cash Converters,Personal,Cashies,true
|
||||||
"Match":"Start",
|
|
||||||
"Value": "Purchase Cash Converters",
|
|
||||||
"Category":"Personal",
|
|
||||||
"Description":"Cashies"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
```
|
```
|
||||||
This means that any statement that starts with "Purchase Cash Converters" will be assigned the category "Personal", and the description "Cashies".
|
This means that any statement that starts with "Purchase Cash Converters" (case sensitive) will be assigned the category "Personal", and the description "Cashies".
|
||||||
|
|
||||||
- `"Match"` specifies the type of matching to perform. It can be any of the following:
|
- `Match` specifies the type of matching to perform. It can be any of the following:
|
||||||
- "Start": Match the start of the description.
|
- "Start": Match the start of the description.
|
||||||
- "End": Match the end of the description.
|
- "End": Match the end of the description.
|
||||||
- "Contains": Match anywhere in the description.
|
- "Contains": Match anywhere in the description.
|
||||||
- "Exact": Only match if the bank statement's description is exactly equal to the provided value.
|
- "Exact": Only match if the bank statement's description is exactly equal to the provided value.
|
||||||
- "Regex": Match with [regular expressions](https://en.wikipedia.org/wiki/Regular_expression).
|
- "Regex": Match with [regular expressions](https://en.wikipedia.org/wiki/Regular_expression).
|
||||||
- `"Value"` specifies the value to match against.
|
- `Value` specifies the value to match against.
|
||||||
- `"Category"` is the category that the statement should be filed under.
|
- `Category` is the category that the statement should be filed under.
|
||||||
- `"Description"` is a short description to distinguish the particular merchant.
|
- `Description` is a short description to distinguish the particular merchant.
|
||||||
|
- `CaseSensitive` specifies whether or not the match should be case sensitive.
|
||||||
|
|
Loading…
Reference in a new issue