@@ -14,7 +14,8 @@ module Ledgers
1414using UUIDs, StructArrays, AbstractTrees
1515using Instruments
1616import Instruments: instrument, symbol, amount, name, currency
17- using Assets: USD
17+ using Assets
18+ @cash USD
1819
1920export Account, Ledger, Entry, AccountId, AccountCode, AccountInfo, AccountGroup
2021export id, balance, credit!, debit!, post!, instrument, symbol, amount, code, name, currency
@@ -32,65 +33,60 @@ struct AccountCode
3233 value:: String
3334end
3435
35- abstract type AccountType{B <: Position } end
36+ abstract type AccountType{P <: Position } end
3637
37- mutable struct Account{B <: Position } <: AccountType{B }
38+ mutable struct Account{P <: Position } <: AccountType{P }
3839 id:: AccountId
39- balance:: B
40+ balance:: P
4041end
4142
4243Account (balance:: Position ) = Account {typeof(balance)} (AccountId (), balance)
4344
44- abstract type AccountNode{B <: Position } <: AccountType{B } end
45+ abstract type AccountNode{P <: Position } <: AccountType{P } end
4546
46- struct AccountInfo{B <: Position } <: AccountNode{B }
47- account:: Account{B }
47+ struct AccountInfo{P <: Position } <: AccountNode{P }
48+ account:: Account{P }
4849 code:: AccountCode
4950 name:: String
5051 isdebit:: Bool
5152
52- function AccountInfo {B} (account:: Account{B} , code, name, isdebit= true , parent= nothing ) where {B <: Position }
53- acc = new {B} (account, code, name, isdebit)
53+ function AccountInfo {P} (account:: Account{P} , code, name, isdebit= true , parent= nothing
54+ ) where {P<: Position }
55+ # println("Create a new AccountInfo{$P}, id=$id, code=$code, name=$name")
56+ acc = new {P} (account, code, name, isdebit)
5457 parent === nothing || push! (parent. subaccounts, acc)
5558 acc
5659 end
5760end
5861
59- AccountInfo (account:: Account{B } , code, name, isdebit = true , parent = nothing ) where {B <: Position } =
60- AccountInfo {B } (account, code, name, isdebit, parent )
62+ AccountInfo (account:: Account{P } , code, name, args ... ) where {P <: Position } =
63+ AccountInfo {P } (account, code, name, args ... )
6164
62- struct AccountGroup{B <: Position } <: AccountNode{B }
65+ mutable struct AccountGroup{P <: Position } <: AccountNode{P }
6366 id:: AccountId
6467 code:: AccountCode
6568 name:: String
6669 isdebit:: Bool
67- parent :: Union{Nothing,AccountGroup{B}}
68- subaccounts :: StructArray{AccountInfo{B }}
69- subgroups :: StructArray{AccountGroup{B }}
70-
71- function AccountGroup {B} (
72- id ,
73- code ,
74- name ,
75- isdebit = true ,
76- parent = nothing ,
77- subaccounts = StructArray ( Vector {AccountInfo{B}} ()),
78- subgroups = StructArray ( Vector { AccountGroup{B}} ())) where {B <: Position }
79- acc = new {B } (id, code, name, isdebit, parent, subaccounts, subgroups)
70+
71+ parent :: Union{Nothing,AccountGroup{P }}
72+ subaccounts :: Vector{AccountInfo{P }}
73+ subgroups :: Vector{AccountGroup{P}}
74+
75+ function AccountGroup {P} (id, code, name ,
76+ isdebit = true ,
77+ parent = nothing ,
78+ subaccounts = Vector {AccountInfo{P}} () ,
79+ subgroups = Vector {AccountGroup{P}} ()
80+ ) where {P <: Position }
81+ # println("Create a new AccountGroup{$P}, id=$id, code=$code, name=$name")
82+ acc = new {P } (id, code, name, isdebit, parent, subaccounts, subgroups)
8083 parent === nothing || push! (parent. subgroups, acc)
8184 acc
8285 end
8386end
8487
85- AccountGroup (
86- :: B ,
87- code,
88- name,
89- isdebit= true ,
90- parent= nothing ,
91- subaccounts= StructArray (Vector {AccountInfo{B}} ()),
92- subgroups= StructArray (Vector {AccountGroup{B}} ())) where {B <: Position } =
93- AccountGroup {B} (AccountId (), code, name, isdebit, parent, subaccounts, subgroups)
88+ AccountGroup (:: P , code, name, args... ) where {P<: Position } =
89+ AccountGroup {P} (AccountId (), code, name, args... )
9490
9591# Identity function (to make code more generic)
9692account (acc:: AccountType ) = acc
@@ -107,24 +103,27 @@ subgroups(group::AccountGroup) = group.subgroups
107103id (acc:: AccountType ) = account (acc). id
108104
109105balance (acc) = account (acc). balance
110- balance (group:: AccountGroup ) = isempty (subgroups (group)) ?
111- sum (balance .(subaccounts (group))) :
112- sum (balance .(subaccounts (group))) + sum (balance .(subgroups (group)))
113106
114- instrument (:: AccountType{B} ) where {B <: Position } = instrument (B)
107+ function balance (grp:: AccountGroup{P} ) where {P<: Position }
108+ sa = subaccounts (grp)
109+ sg = subgroups (grp)
110+ (isempty (sa) ? zero (P) : sum (balance, sa)) + (isempty (sg) ? zero (P) : sum (balance, sg))
111+ end
112+
113+ instrument (:: AccountType{P} ) where {P<: Position } = instrument (P)
115114
116- symbol (:: AccountType{B } ) where {B <: Position } = symbol (B )
115+ symbol (:: AccountType{P } ) where {P <: Position } = symbol (P )
117116
118- currency (:: AccountType{B } ) where {B <: Position } = currency (B )
117+ currency (:: AccountType{P } ) where {P <: Position } = currency (P )
119118
120119amount (acc:: AccountType ) = amount (balance (acc))
121120
122121debit! (acc:: Account , amt:: Position ) = (acc. balance += amt)
123122credit! (acc:: Account , amt:: Position ) = (acc. balance -= amt)
124123
125- struct Entry{B <: Position }
126- debit:: AccountInfo{B }
127- credit:: AccountInfo{B }
124+ struct Entry{P <: Position }
125+ debit:: AccountInfo{P }
126+ credit:: AccountInfo{P }
128127end
129128
130129function post! (entry:: Entry , amt:: Position )
@@ -133,11 +132,12 @@ function post!(entry::Entry, amt::Position)
133132 entry
134133end
135134
136- struct Ledger{P <: Position }
135+ # SPJ: we should probably retain the id of the Ledger here
136+ struct Ledger{P<: Position }
137137 indexes:: Dict{AccountId,Int}
138138 accounts:: StructArray{Account{P}}
139139
140- function Ledger (accounts:: Vector{Account{P}} ) where {P <: Position }
140+ function Ledger (accounts:: Vector{Account{P}} ) where {P<: Position }
141141 indexes = Dict {AccountId,Int} ()
142142 for (index, account) in enumerate (accounts)
143143 indexes[id (account)] = index
0 commit comments