```dataviewjs
// Code for https://medium.com/@geetduggal/the-power-of-obsidian-for-personal-finance-accounting-f00bbcb1b66f

// Step 1: SUPER shameful poor-man parsing of a ledger journal file

const ledgerFile = await dv.io.load("2 Areas/Notes/ledger journal.md")
let allTransactions = ledgerFile.split(/\n\n/).
  filter((transactionText) => {
     return !(transactionText.startsWith(";") || transactionText.startsWith("alias") || transactionText.match(/^\s*$/))
  }).
  map((transactionText) => {
    let transactionLines =  transactionText.split("\n")
    let transaction = {}
    transaction.date = transactionLines[0].slice(0,10)
    transaction.description = transactionLines[0].slice(10)    
    transaction.entries = transactionLines.slice(1).map((e)=>{
      let eSplit = e.trim().split("₩")  
      return {account: eSplit[0].trim(), amount: parseFloat(eSplit[1]), date: transaction.date, description:transaction.description}    
    })
    let transactionSum = transaction.entries.map((e)=>e.amount).filter((x)=>!isNaN(x)).reduce((a,b)=>a+b)
    transaction.entries = transaction.entries.map((e)=>{
      if (isNaN(e.amount)) { e.amount = -1*transactionSum}
      return e
    })
    return transaction
})

// Step 2

let currentDate = new Date().toISOString().slice(0,10)

let accountsSummary = allTransactions.map((t)=>t.entries).flat().reduce((acc, t)=>{
   let subAccounts = t.account.split(":")
   let prefixAccount = ""
   subAccounts.forEach((a)=>{
     prefixAccount += a
     if (!acc[prefixAccount]) { 
         acc[prefixAccount] = {balance: 0, futureBalance:0, transactions: []}
     }
     if (t.date <= currentDate) { acc[prefixAccount].balance += t.amount }
     acc[prefixAccount].futureBalance += t.amount
     acc[prefixAccount].transactions.push(t)
     prefixAccount += ":"
   })
   return acc
}, {})

// Step 3

function bold(x) {return `<b>${x}</b>`}
function dollars(x) {return "₩"+Math.round(x)}
function color(c,x) { return "<font style='color:" + c + "'>" + x + "</font>" }


dv.header(1, "Balance Summary")
dv.table(
  ["Account", "Balance", "Future Balance"],
  Object.keys(accountsSummary).sort().map((a)=>{
    let balance = accountsSummary[a].balance
    let futureBalance = accountsSummary[a].futureBalance
    balance = dollars(balance)
    futureBalance = dollars(futureBalance)
    if (accountsSummary[a].futureBalance < 0) {
      futureBalance = color("red", futureBalance)
    }
    if(a.split(":").length == 1) {
      a = bold(a)
      balance = bold(balance)
      futureBalance = bold(futureBalance)
    }
    return [a, balance, futureBalance]
  })
) 

function cdate( a, b ) {
  if ( a.date < b.date ){
    return -1;
  }
  if ( a.date > b.date ){
    return 1;
  }
  return 0;
}

let fileDate = dv.current().file.name.slice(0,10)

// Check to see if the first characters match ISO 8601 validation
if (!fileDate.match(/^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24\:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/)) { fileDate = "!"}

// Step 4
dv.header(2, "Unknown")
let total = 0 
dv.table(
    ["Date", "Account", "Description", "Amount"],
    allTransactions.map((x)=>x.entries).flat().sort(cdate).filter((x)=>x.date >= fileDate && (x.account.includes("Unknown") || x.description.includes("Unknown")) && x.account.slice(0,1) === "E").map((x)=> {
      let amount = x.amount
      if (x.amount > 0) { total += x.amount }
      if (Math.abs(x.amount) > 100) { 
        amount = bold(amount) 
        x.description = bold(x.description)
      }
      return [x.date, x.account, x.description, amount]
    })
)
dv.paragraph(bold('<div style="text-align: right">Total Unknown: '+Math.round(total)+'</div>'))

Object.keys(accountsSummary).sort().forEach((a)=>{
 let total = 0   
 if(a.split(":").length != 1) {
      dv.header(2, a)
      dv.table(
        ["Date", "Account", "Description", "Amount"],
        accountsSummary[a].transactions.sort(cdate).filter((x)=>x.date >= fileDate).map((x)=> {
          let amount = x.amount
          if (x.amount > 0) { total += x.amount }
          if (Math.abs(x.amount) > 100) { 
            amount = bold(amount) 
            x.description = bold(x.description)
          }
          return [x.date, x.account, x.description, amount]
        })
      )
      if (a.slice(0,1) === "E") {
        dv.paragraph(bold('<div style="text-align: right">Total Expenses: $'+Math.round(total)+'</div>'))
      }
  }
})
```