Skip to content

Commit

Permalink
Add convenient constructor and swap name <-> number order.
Browse files Browse the repository at this point in the history
Add convert method for AccountNumber

Add indexes to AccountGroup

Add getindex for AccountGroup

Rename add_account! -> add_account
  • Loading branch information
EricForgy committed Jul 10, 2020
1 parent ed93080 commit 0d67602
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 34 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ keywords = ["Finance", "Ledger"]
license = "MIT"
desc = "Financial ledgers"
authors = ["Eric Forgy <[email protected]>", "ScottPJones <[email protected]>"]
version = "0.6.0"
version = "0.7.0"

[deps]
AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
Expand Down
80 changes: 52 additions & 28 deletions src/Ledgers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ using UUIDs, StructArrays, AbstractTrees
using Assets, Instruments, Currencies

export Identifier, AccountId, AccountType, AccountNumber
export LedgerAccount, Ledger, Entry, Account, AccountGroup, ledgeraccount, add_account!
export LedgerAccount, Ledger, Entry, Account, AccountGroup, ledgeraccount, add_account
export id, balance, credit!, debit!, post!, instrument, currency, symbol, amount

abstract type Identifier end

Base.convert(::Type{I}, value::String) where {I <: Identifier} = I(UUID(value))

struct AccountId <: Identifier
value::UUID
end
Expand All @@ -32,11 +34,13 @@ end

AccountNumber() = AccountNumber("")

Base.convert(::Type{AccountNumber}, value::String) = AccountNumber(value)

abstract type AccountType{P <: Position} end

accounttype(::A) where {A<:AccountType} = A
accounttype(::A) where {A <: AccountType} = A

accounttype(::StructArray{A}) where {A<:AccountType} = A
accounttype(::StructArray{A}) where {A <: AccountType} = A

mutable struct LedgerAccount{P <: Position} <: AccountType{P}
id::AccountId
Expand Down Expand Up @@ -67,18 +71,7 @@ struct Account{P <: Position} <: AccountType{P}
iscontra::Bool
end

function Account(::Type{P}, number::AccountNumber, name, isdebit=true; parent=nothing, ledger=nothing) where {P <: Position}
account = LedgerAccount(P, ledger=ledger)
parent === nothing && return Account{P}(account, number, name, isdebit, false)
acc = Account{P}(account, number, name, isdebit, parent.isdebit !== isdebit)
add_account!(parent.accounts, acc)
acc
end

Account{P}(acc::Account{P}) where {P<:Position} = acc

Account(::Type{P}=Assets.USD, number::String="",name::String="Default Account";ledger=nothing) where {P <: Position} =
Account(P, AccountNumber(number), name, ledger=ledger)
Account{P}(acc::Account{P}) where {P <: Position} = acc

ledgeraccount(acc::Account) = acc.account

Expand All @@ -100,7 +93,7 @@ end

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

function add_account!(ledger::Ledger, acc)
function add_account(ledger::Ledger, acc)
push!(ledger.accounts, ledgeraccount(acc))
ledger.indexes[id(acc)] = length(ledger.accounts)
ledger
Expand All @@ -112,34 +105,57 @@ struct AccountGroup{A <: AccountType}
name::String
isdebit::Bool
iscontra::Bool
indexes::Dict{AccountId,Int}
accounts::StructArray{A}
subgroups::StructArray{AccountGroup{A}}
end

function AccountGroup(
::Type{A},
number,
name,
::Type{A}=Account{Assets.USD},
name::String="$(symbol(P)) Accounts",
number="",
isdebit=true;
id=AccountId(),
accounts=StructArray(Vector{A}()),
subgroups=StructArray(Vector{AccountGroup{A}}()),
parent=nothing
) where {A <: AccountType}
parent::Union{Nothing,AccountGroup{A}}=nothing
) where {P <: Position,A <: AccountType{P}}
indexes = Dict{AccountId,Int}()
accounts = StructArray(Vector{A}())
subgroups = StructArray(Vector{AccountGroup{A}}())
if parent === nothing
return AccountGroup{A}(id, number, name, isdebit, false, accounts, subgroups)
return AccountGroup{A}(id, number, name, isdebit, false, indexes, accounts, subgroups)
else
acc = AccountGroup{A}(id, number, name, isdebit, parent.isdebit !== isdebit, accounts, subgroups)
acc = AccountGroup{A}(id, number, name, isdebit, parent.isdebit !== isdebit, indexes, accounts, subgroups)
push!(parent.subgroups, acc)
return acc
end
end

add_account!(grp::AccountGroup{A}, acc::AccountType) where {A<:AccountType} = push!(grp.accounts, A(acc))
function Account(
::Type{P}=Assets.USD,
name::String="$(symbol(P)) Account",
number="",
isdebit=true;
parent::Union{Nothing,<:AccountGroup}=nothing,
ledger::Union{Nothing,<:Ledger}=nothing
) where {P <: Position}
account = LedgerAccount(P, ledger=ledger)
parent === nothing &&
return Account{P}(account, number, name, isdebit, false)
acc = Account{P}(account, number, name, isdebit, parent.isdebit !== isdebit)
add_account(parent, acc)
acc
end

add_account!(grp::AccountGroup, acc::AccountGroup) = push!(grp.subgroups, acc)
function add_account(grp::AccountGroup{A}, acc::AccountType) where {A <: AccountType}
push!(grp.accounts, A(acc))
grp.indexes[id(acc)] = length(grp.accounts)
grp
end

add_account!(grp::StructArray{A}, acc::AccountType) where {A<:AccountType} = push!(grp,A(acc))
function add_account(grp::AccountGroup, acc::AccountGroup)
push!(grp.subgroups, acc)
grp
end

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

Base.getindex(grp::AccountGroup, ix) = grp.accounts.accounts[ix]

Base.getindex(grp::AccountGroup, id::AccountId) =
grp.accounts.accounts[grp.indexes[id]]

Base.getindex(grp::AccountGroup, array::AbstractVector{<:AccountId}) =
grp.accounts[broadcast(id -> grp.indexes[id], array)]

struct EntityId <: Identifier
value::UUID
end
Expand Down
10 changes: 5 additions & 5 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import Test; using Test: @testset, @test
using Assets: USD

function example()
group = AccountGroup(USD, AccountNumber("0000000"), "Account Group", true)
assets = AccountGroup(USD, AccountNumber("1000000"), "Assets", true, parent=group)
liabilities = AccountGroup(USD, AccountNumber("2000000"), "Liabilities", false, parent=group)
cash = Account(USD, AccountNumber("1010000"), "Cash", true, parent=assets)
payable = Account(USD, AccountNumber("2010000"), "Accounts Payable", false, parent=liabilities)
group = AccountGroup(Account{USD}, "Account Group", "0000000", true)
assets = AccountGroup(Account{USD}, "Assets", "1000000", true, parent=group)
liabilities = AccountGroup(Account{USD}, "Liabilities", "2000000", false, parent=group)
cash = Account(USD, "Cash", "1010000", true, parent=assets)
payable = Account(USD, "Accounts Payable", "2010000", false, parent=liabilities)

entry = Entry(cash, payable)
group, assets, liabilities, cash, payable, entry
Expand Down

0 comments on commit 0d67602

Please sign in to comment.