Skip to content

Commit d475b81

Browse files
committed
Initial commit
0 parents  commit d475b81

30 files changed

+1479
-0
lines changed

Finance.Accounting/.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# .NET build files
2+
bin/
3+
obj/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net6.0</TargetFramework>
5+
<ImplicitUsings>false</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
8+
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
9+
</PropertyGroup>
10+
11+
<PropertyGroup>
12+
<PackageId>Finance.Accounting</PackageId>
13+
<Version>0.1.0</Version>
14+
</PropertyGroup>
15+
16+
<ItemGroup>
17+
<PackageReference Include="CsvHelper" Version="29.0.0" />
18+
<PackageReference Include="Timeline" Version="0.1.0" />
19+
</ItemGroup>
20+
21+
</Project>

Finance.Accounting/src/Account.cs

+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Diagnostics.CodeAnalysis;
4+
using System.Text;
5+
6+
namespace Finance
7+
{
8+
public readonly struct Account : IEquatable<Account>, IComparable<Account>
9+
{
10+
private readonly string[] _branch = Array.Empty<string>();
11+
12+
public Account(params string[] branch)
13+
{
14+
if (branch == null)
15+
{
16+
throw new ArgumentException();
17+
}
18+
_branch = branch;
19+
}
20+
21+
public string[] Branch => _branch;
22+
23+
public override string ToString()
24+
{
25+
return string.Join(":", _branch);
26+
}
27+
28+
public bool IsUnder(Account parent)
29+
{
30+
if (parent.Branch.Length >= this.Branch.Length)
31+
{
32+
return false;
33+
}
34+
35+
for (var i = 0; i < parent.Branch.Length; i++)
36+
{
37+
if (parent.Branch[i] != Branch[i])
38+
{
39+
return false;
40+
}
41+
}
42+
43+
return true;
44+
}
45+
46+
public static bool operator ==(Account first, Account other)
47+
{
48+
return first.Equals(other);
49+
}
50+
51+
public static bool operator !=(Account first, Account other)
52+
{
53+
return !first.Equals(other);
54+
}
55+
56+
public bool Equals(Account other)
57+
{
58+
if (other._branch.Length != this._branch.Length)
59+
{
60+
return false;
61+
}
62+
63+
for (var i = 0; i < _branch.Length; i++)
64+
{
65+
if (other.Branch[i] != Branch[i])
66+
{
67+
return false;
68+
}
69+
}
70+
71+
return true;
72+
}
73+
74+
public override int GetHashCode()
75+
{
76+
var hashCode = 0;
77+
foreach (var part in _branch)
78+
{
79+
hashCode ^= part.GetHashCode();
80+
}
81+
82+
return hashCode;
83+
}
84+
85+
public int CompareTo(Account other)
86+
{
87+
for (var i = 0; ; i++)
88+
{
89+
if (i < this.Branch.Length && i < other.Branch.Length)
90+
{
91+
var order = string.Compare(this.Branch[i], other.Branch[i], StringComparison.Ordinal);
92+
if (order != 0)
93+
{
94+
return order;
95+
}
96+
}
97+
else if (i < this.Branch.Length)
98+
{
99+
return 1;
100+
}
101+
else if (i < other.Branch.Length)
102+
{
103+
return -1;
104+
}
105+
else
106+
{
107+
return 0;
108+
}
109+
}
110+
}
111+
}
112+
}

Finance.Accounting/src/AccountFlow.cs

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using System.Collections.Generic;
2+
3+
namespace Finance
4+
{
5+
public class AccountFlow
6+
{
7+
private readonly DefaultDictionary<Account, DefaultDictionary<Account, Amount>> _forward;
8+
private readonly DefaultDictionary<Account, DefaultDictionary<Account, Amount>> _backward;
9+
10+
public ICollection<Account> Sources => _forward.Keys;
11+
public ICollection<Account> Sinks => _backward.Keys;
12+
13+
public AccountFlow()
14+
{
15+
_forward = new DefaultDictionary<Account, DefaultDictionary<Account, Amount>>(() =>
16+
{
17+
return new DefaultDictionary<Account, Amount>(() => new());
18+
});
19+
_backward = new DefaultDictionary<Account, DefaultDictionary<Account, Amount>>(() =>
20+
{
21+
return new DefaultDictionary<Account, Amount>(() => new());
22+
});
23+
}
24+
25+
public void Add(Movement movement)
26+
{
27+
var from = movement.From;
28+
var to = movement.To;
29+
30+
_forward[from][to] += movement.Amount;
31+
_backward[to][from] += movement.Amount;
32+
}
33+
34+
public IEnumerable<Account> GetSinks(Account from)
35+
{
36+
return _forward[from].Keys;
37+
}
38+
39+
public IEnumerable<Account> GetSources(Account to)
40+
{
41+
return _backward[to].Keys;
42+
}
43+
44+
public Amount GetFlows(Account from, Account to)
45+
{
46+
return _forward[from][to];
47+
}
48+
}
49+
}

Finance.Accounting/src/AccountTree.cs

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
6+
namespace Finance
7+
{
8+
public class AccountTree : IEnumerable<Account>
9+
{
10+
private readonly Dictionary<string, AccountTree> _children;
11+
12+
public AccountTree()
13+
{
14+
_children = new();
15+
}
16+
17+
public void Add(Account account)
18+
{
19+
Add(account.Branch);
20+
}
21+
22+
private void Add(string[] account)
23+
{
24+
if (account.Length == 0)
25+
{
26+
return;
27+
}
28+
29+
var childRoot = account[0];
30+
31+
if (!_children.ContainsKey(childRoot))
32+
{
33+
_children[childRoot] = new AccountTree();
34+
}
35+
36+
_children[childRoot].Add(account[1..]);
37+
}
38+
39+
public IEnumerable<Account> GetUnder(Account parent)
40+
{
41+
var branch = parent.Branch;
42+
43+
var tree = this;
44+
for (var depth = 0; depth < branch.Length; depth++)
45+
{
46+
var topAccount = branch[depth];
47+
if (tree._children.ContainsKey(topAccount))
48+
{
49+
tree = tree._children[topAccount];
50+
continue;
51+
}
52+
else
53+
{
54+
tree = new AccountTree();
55+
break;
56+
}
57+
}
58+
59+
yield return parent;
60+
foreach (var child in tree)
61+
{
62+
var account = parent.Branch.Concat(child.Branch).ToArray();
63+
64+
yield return new Account(account);
65+
}
66+
}
67+
68+
public IEnumerator<Account> GetEnumerator()
69+
{
70+
var topAccounts = _children.Keys.OrderBy(x => x);
71+
72+
foreach (var topAccount in topAccounts)
73+
{
74+
yield return new Account(topAccount);
75+
76+
foreach (var child in _children[topAccount])
77+
{
78+
var account = new[] { topAccount }.Concat(child.Branch).ToArray();
79+
80+
yield return new Account(account);
81+
}
82+
}
83+
}
84+
85+
IEnumerator IEnumerable.GetEnumerator()
86+
{
87+
return this.GetEnumerator();
88+
}
89+
}
90+
}

0 commit comments

Comments
 (0)