Last active
July 30, 2022 00:55
-
-
Save IvanRainbolt/8f69cf26d512353013da54934a3d5523 to your computer and use it in GitHub Desktop.
The first General Journal attempt | Using F# to model Financial Accounting
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// related to blog post: | |
// The first General Journal attempt | |
// Using F# to model Financial Accounting | |
// https://crazyivan.blog/the-first-general-journal-attempt | |
open System | |
type Transaction = exn | |
type AccountData = { AccountName : string } | |
type Account = | |
| Assets of AccountData | |
| Liabilities of AccountData | |
| Equity of AccountData | |
| Revenue of AccountData | |
| Expenses of AccountData | |
type ChartOfAccounts = { Accounts : Account list } | |
type Debit = | |
{ Account : Account | |
Amount : decimal } | |
type Credit = | |
{ Account : Account | |
Amount : decimal } | |
type JournalEntry = | |
{ Date : DateOnly | |
Debits : Debit list | |
Credits : Credit list } | |
type Journal = { JournalEntries : JournalEntry list } | |
let Cash : Account = Assets {AccountName = "Cash"} | |
let Loan : Account = Liabilities {AccountName = "Loan"} | |
let IssuedEquity : Account = Equity {AccountName = "Issued Equity"} | |
let cashDebit :Debit = {Account=Cash;Amount=30000.00m} | |
let loanCredit :Credit = {Account=Loan;Amount=30000.00m} | |
let jeLoan = {Date=DateOnly(2022,01,01);Debits=[cashDebit];Credits=[loanCredit]} | |
let generalJournal = {JournalEntries=[jeLoan]} | |
printfn $"%A{generalJournal}" | |
let equityInjectionDebit :Debit = {Account=Cash;Amount=20000.00m} | |
let equityInjectionCredit :Credit = {Account=IssuedEquity;Amount=20000.00m} | |
let jeEquityInjection = | |
{ Date=DateOnly(2022,01,02) | |
Debits=[equityInjectionDebit] | |
Credits=[equityInjectionCredit]} | |
let generalJournal2 = {JournalEntries=(generalJournal.JournalEntries @ [jeEquityInjection])} | |
printfn $"%A{generalJournal2}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
It might be a good idea to structure this such that a journal entry can be added only if the debits and credits for a transaction are equal.
The best way to do that might be to create a type that can only be instantiated from within its module and a creator function that validates the input and if everything is okay, creates the type. In concrete terms,
would turn to something like
and
ValidatedJournalEntry
will be in its module