diff --git a/Bank.cs b/Bank.cs
index 974c318..6aacf17 100644
--- a/Bank.cs
+++ b/Bank.cs
@@ -1,6 +1,7 @@
namespace BunyMuny {
public enum Bank {
ME,
- NAB
+ NAB,
+ Other
}
}
diff --git a/Program.cs b/Program.cs
index 2982572..0787d93 100644
--- a/Program.cs
+++ b/Program.cs
@@ -2,64 +2,98 @@
using System.Collections.Generic;
using System.Globalization;
using System.IO;
+using System.Text.Json;
using System.CommandLine.DragonFruit;
+using System.Text.Json.Serialization;
using CsvHelper;
-using CsvHelper.Configuration.Attributes;
namespace BunyMuny {
- class Program {
+ internal class Program {
///
/// BunyMuny parses the CSV output of various bank statement listings and converts it to something more human readable with nice visualisations.
///
/// The CSV file to read
- /// The JSON file to use for rules when parsing statement descriptions
+ /// The JSON file to use for rules when parsing statement descriptions
///
- static int Main(string file = "test.csv", string rules = "rules.json") {
- Bank bank = Bank.ME;
+ static int Main(string file = "test.csv", string ruleFile = "rules.json") {
+ var bank = Bank.Other;
var statements = new List();
+ List rules;
- using (var sr = new StreamReader(file)) {
- using (var csv = new CsvReader(sr, CultureInfo.InvariantCulture)) {
- csv.Read();
- csv.ReadHeader();
- // get the first line of the CSV file (the header) as a string
- string header = csv.Parser.Context.RawRecord;
- if (header == null) {
- Console.WriteLine("File is empty 0uo");
+ using (var ruleStreamReader = new StreamReader(ruleFile)) {
+ var jsonOptions = new JsonSerializerOptions();
+ jsonOptions.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase));
+ jsonOptions.WriteIndented = true;
+ rules = JsonSerializer.Deserialize>(ruleStreamReader.ReadToEnd(), jsonOptions);
+ }
+
+ using var sr = new StreamReader(file);
+ using var csv = new CsvReader(sr, CultureInfo.InvariantCulture);
+
+ csv.Read();
+ csv.ReadHeader();
+
+ // get the first line of the CSV file (the header) as a string
+ var header = csv.Parser.Context.RawRecord.Trim();
+ switch (header) {
+ case null:
+ Console.WriteLine("File is empty 0uo");
+ return 1;
+ case "Date,Description,Debits and credits,Balance":
+ bank = Bank.ME;
+ break;
+ case "Whatever NAB uses I guess":
+ bank = Bank.NAB;
+ break;
+ default:
+ Console.WriteLine($"Unknown header: [{header}]");
+ break;
+ }
+
+ while (csv.Read()) {
+ switch (bank) {
+ case Bank.ME:
+ var value = double.Parse(csv.GetField("Debits and credits").TrimStart().Replace("$", ""));
+ var ruleValues = MatchAgainstRules(rules, csv.GetField("Description"));
+
+ statements.Add(new Statement() {
+ Date = DateTime.ParseExact(csv.GetField("Date"), "dd/MM/yyyy", CultureInfo.InvariantCulture),
+ OriginalDescription = csv.GetField("Description"),
+ Description = ruleValues.Description,
+ Category = ruleValues.Category,
+ Value = value
+ });
+ break;
+
+ case Bank.NAB:
+ Console.WriteLine("Unimplemented");
return 1;
- }
- else if (header == "Date,Description,Debits and credits,Balance") {
- bank = Bank.ME;
- }
- else if (header == "Whatever NAB uses I guess") {
- bank = Bank.NAB;
- }
- while (csv.Read()) {
- switch (bank) {
- case Bank.ME:
- double value = double.Parse(csv.GetField("Debits and credits").TrimStart().Replace("$", ""));
- statements.Add(new Statement() {
- Date = DateTime.ParseExact(csv.GetField("Date"), "dd/MM/yyyy", CultureInfo.InvariantCulture),
- Description = csv.GetField("Description"),
- Category = "Unknown",
- Value = value
- });
- break;
+ case Bank.Other:
+ Console.WriteLine("Unknown bank!");
+ return 1;
- default:
- Console.WriteLine(":(");
- return 1;
- }
- }
-
- foreach (var statement in statements) {
- Console.WriteLine(statement);
- }
+ default:
+ Console.WriteLine(":(");
+ return 1;
}
}
+ foreach (var statement in statements) {
+ Console.WriteLine(statement);
+ }
+
return 0;
}
+
+ private static (string Category, string Description) MatchAgainstRules(List rules, string value) {
+ foreach (var rule in rules) {
+ if (rule.Check(value)) {
+ return (rule.Category, rule.Description);
+ }
+ }
+
+ return (null, null);
+ }
}
}
diff --git a/Statement.cs b/Statement.cs
index 855b75e..587c909 100644
--- a/Statement.cs
+++ b/Statement.cs
@@ -1,4 +1,5 @@
using System;
+using System.Text;
namespace BunyMuny {
public class Statement {
@@ -14,7 +15,16 @@ namespace BunyMuny {
public string Category;
public override string ToString() {
- return $"${Math.Abs(Value)} {(Value < 0 ? "to" : "from")} {(Description)} on {Date.ToString("MMM d yyyy")}";
+ // e.g.: Debit: $5.00 --> Lynnear Software (Personal) on Apr 2 2020
+ return String.Format(
+ "{0} ${1:0.##} {2} {3} ({4}) on {5:MMM d yyyy}",
+ Value < 0 ? "Credit:" : "Debit: ",
+ Math.Abs(Value),
+ Value < 0 ? "-->" : "<--",
+ Description,
+ Category ?? "Unknown",
+ Date
+ );
}
}
}