Skip to content

Commit 0d67602

Browse files
Eric ForgyEric Forgy
Eric Forgy
authored and
Eric Forgy
committed
Add convenient constructor and swap name <-> number order.
Add convert method for AccountNumber Add indexes to AccountGroup Add getindex for AccountGroup Rename add_account! -> add_account
1 parent ed93080 commit 0d67602

File tree

3 files changed

+58
-34
lines changed

3 files changed

+58
-34
lines changed

Project.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ keywords = ["Finance", "Ledger"]
44
license = "MIT"
55
desc = "Financial ledgers"
66
authors = ["Eric Forgy <[email protected]>", "ScottPJones <[email protected]>"]
7-
version = "0.6.0"
7+
version = "0.7.0"
88

99
[deps]
1010
AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"

src/Ledgers.jl

+52-28
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@ using UUIDs, StructArrays, AbstractTrees
1515
using Assets, Instruments, Currencies
1616

1717
export Identifier, AccountId, AccountType, AccountNumber
18-
export LedgerAccount, Ledger, Entry, Account, AccountGroup, ledgeraccount, add_account!
18+
export LedgerAccount, Ledger, Entry, Account, AccountGroup, ledgeraccount, add_account
1919
export id, balance, credit!, debit!, post!, instrument, currency, symbol, amount
2020

2121
abstract type Identifier end
2222

23+
Base.convert(::Type{I}, value::String) where {I <: Identifier} = I(UUID(value))
24+
2325
struct AccountId <: Identifier
2426
value::UUID
2527
end
@@ -32,11 +34,13 @@ end
3234

3335
AccountNumber() = AccountNumber("")
3436

37+
Base.convert(::Type{AccountNumber}, value::String) = AccountNumber(value)
38+
3539
abstract type AccountType{P <: Position} end
3640

37-
accounttype(::A) where {A<:AccountType} = A
41+
accounttype(::A) where {A <: AccountType} = A
3842

39-
accounttype(::StructArray{A}) where {A<:AccountType} = A
43+
accounttype(::StructArray{A}) where {A <: AccountType} = A
4044

4145
mutable struct LedgerAccount{P <: Position} <: AccountType{P}
4246
id::AccountId
@@ -67,18 +71,7 @@ struct Account{P <: Position} <: AccountType{P}
6771
iscontra::Bool
6872
end
6973

70-
function Account(::Type{P}, number::AccountNumber, name, isdebit=true; parent=nothing, ledger=nothing) where {P <: Position}
71-
account = LedgerAccount(P, ledger=ledger)
72-
parent === nothing && return Account{P}(account, number, name, isdebit, false)
73-
acc = Account{P}(account, number, name, isdebit, parent.isdebit !== isdebit)
74-
add_account!(parent.accounts, acc)
75-
acc
76-
end
77-
78-
Account{P}(acc::Account{P}) where {P<:Position} = acc
79-
80-
Account(::Type{P}=Assets.USD, number::String="",name::String="Default Account";ledger=nothing) where {P <: Position} =
81-
Account(P, AccountNumber(number), name, ledger=ledger)
74+
Account{P}(acc::Account{P}) where {P <: Position} = acc
8275

8376
ledgeraccount(acc::Account) = acc.account
8477

@@ -100,7 +93,7 @@ end
10093

10194
Ledger(::Type{P}=Assets.USD) where {P <: Position} = Ledger(Vector{Account{P}}())
10295

103-
function add_account!(ledger::Ledger, acc)
96+
function add_account(ledger::Ledger, acc)
10497
push!(ledger.accounts, ledgeraccount(acc))
10598
ledger.indexes[id(acc)] = length(ledger.accounts)
10699
ledger
@@ -112,34 +105,57 @@ struct AccountGroup{A <: AccountType}
112105
name::String
113106
isdebit::Bool
114107
iscontra::Bool
108+
indexes::Dict{AccountId,Int}
115109
accounts::StructArray{A}
116110
subgroups::StructArray{AccountGroup{A}}
117111
end
118112

119113
function AccountGroup(
120-
::Type{A},
121-
number,
122-
name,
114+
::Type{A}=Account{Assets.USD},
115+
name::String="$(symbol(P)) Accounts",
116+
number="",
123117
isdebit=true;
124118
id=AccountId(),
125-
accounts=StructArray(Vector{A}()),
126-
subgroups=StructArray(Vector{AccountGroup{A}}()),
127-
parent=nothing
128-
) where {A <: AccountType}
119+
parent::Union{Nothing,AccountGroup{A}}=nothing
120+
) where {P <: Position,A <: AccountType{P}}
121+
indexes = Dict{AccountId,Int}()
122+
accounts = StructArray(Vector{A}())
123+
subgroups = StructArray(Vector{AccountGroup{A}}())
129124
if parent === nothing
130-
return AccountGroup{A}(id, number, name, isdebit, false, accounts, subgroups)
125+
return AccountGroup{A}(id, number, name, isdebit, false, indexes, accounts, subgroups)
131126
else
132-
acc = AccountGroup{A}(id, number, name, isdebit, parent.isdebit !== isdebit, accounts, subgroups)
127+
acc = AccountGroup{A}(id, number, name, isdebit, parent.isdebit !== isdebit, indexes, accounts, subgroups)
133128
push!(parent.subgroups, acc)
134129
return acc
135130
end
136131
end
137132

138-
add_account!(grp::AccountGroup{A}, acc::AccountType) where {A<:AccountType} = push!(grp.accounts, A(acc))
133+
function Account(
134+
::Type{P}=Assets.USD,
135+
name::String="$(symbol(P)) Account",
136+
number="",
137+
isdebit=true;
138+
parent::Union{Nothing,<:AccountGroup}=nothing,
139+
ledger::Union{Nothing,<:Ledger}=nothing
140+
) where {P <: Position}
141+
account = LedgerAccount(P, ledger=ledger)
142+
parent === nothing &&
143+
return Account{P}(account, number, name, isdebit, false)
144+
acc = Account{P}(account, number, name, isdebit, parent.isdebit !== isdebit)
145+
add_account(parent, acc)
146+
acc
147+
end
139148

140-
add_account!(grp::AccountGroup, acc::AccountGroup) = push!(grp.subgroups, acc)
149+
function add_account(grp::AccountGroup{A}, acc::AccountType) where {A <: AccountType}
150+
push!(grp.accounts, A(acc))
151+
grp.indexes[id(acc)] = length(grp.accounts)
152+
grp
153+
end
141154

142-
add_account!(grp::StructArray{A}, acc::AccountType) where {A<:AccountType} = push!(grp,A(acc))
155+
function add_account(grp::AccountGroup, acc::AccountGroup)
156+
push!(grp.subgroups, acc)
157+
grp
158+
end
143159

144160
struct Entry{P <: Position}
145161
debit::Account{P}
@@ -191,6 +207,14 @@ Base.getindex(ledger::Ledger, id::AccountId) =
191207
Base.getindex(ledger::Ledger, array::AbstractVector{<:AccountId}) =
192208
ledger.accounts[broadcast(id -> ledger.indexes[id], array)]
193209

210+
Base.getindex(grp::AccountGroup, ix) = grp.accounts.accounts[ix]
211+
212+
Base.getindex(grp::AccountGroup, id::AccountId) =
213+
grp.accounts.accounts[grp.indexes[id]]
214+
215+
Base.getindex(grp::AccountGroup, array::AbstractVector{<:AccountId}) =
216+
grp.accounts[broadcast(id -> grp.indexes[id], array)]
217+
194218
struct EntityId <: Identifier
195219
value::UUID
196220
end

test/runtests.jl

+5-5
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ import Test; using Test: @testset, @test
33
using Assets: USD
44

55
function example()
6-
group = AccountGroup(USD, AccountNumber("0000000"), "Account Group", true)
7-
assets = AccountGroup(USD, AccountNumber("1000000"), "Assets", true, parent=group)
8-
liabilities = AccountGroup(USD, AccountNumber("2000000"), "Liabilities", false, parent=group)
9-
cash = Account(USD, AccountNumber("1010000"), "Cash", true, parent=assets)
10-
payable = Account(USD, AccountNumber("2010000"), "Accounts Payable", false, parent=liabilities)
6+
group = AccountGroup(Account{USD}, "Account Group", "0000000", true)
7+
assets = AccountGroup(Account{USD}, "Assets", "1000000", true, parent=group)
8+
liabilities = AccountGroup(Account{USD}, "Liabilities", "2000000", false, parent=group)
9+
cash = Account(USD, "Cash", "1010000", true, parent=assets)
10+
payable = Account(USD, "Accounts Payable", "2010000", false, parent=liabilities)
1111

1212
entry = Entry(cash, payable)
1313
group, assets, liabilities, cash, payable, entry

0 commit comments

Comments
 (0)