///|
/// Validation errors are explicit so importers can reject bad source data.
pub enum EntryValidation {
ValidEntry
EmptyAccount
InvalidEntryPeriod(String)
NegativeAmount
UnbalancedEntry
} derive(Debug, Eq)
///|
pub fn validate_entry(entry : Entry) -> EntryValidation {
if entry.account == "" {
return EmptyAccount
}
match validate_period(entry.period) {
InvalidPeriod(period) => return InvalidEntryPeriod(period)
ValidPeriod(_) => ()
}
if entry.debit < 0 || entry.credit < 0 {
return NegativeAmount
}
if (entry.debit > 0 && entry.credit > 0) ||
(entry.debit == 0 && entry.credit == 0) {
return UnbalancedEntry
}
ValidEntry
}
///|
pub struct TrialBalanceLine {
account : String
debit : Amount
credit : Amount
balance : Amount
} derive(Debug, Eq)
///|
pub struct TrialBalance {
lines : Array[TrialBalanceLine]
total_debit : Amount
total_credit : Amount
balanced : Bool
} derive(Debug, Eq)
///|
pub fn trial_balance(
entries : Array[Entry],
period? : String = "",
) -> TrialBalance {
let lines : Array[TrialBalanceLine] = []
let mut total_debit = 0
let mut total_credit = 0
for entry in entries {
if period != "" && entry.period != period {
continue
}
total_debit += entry.debit
total_credit += entry.credit
add_trial_line(lines, entry.account, entry.debit, entry.credit)
}
{ lines, total_debit, total_credit, balanced: total_debit == total_credit }
}
///|
pub fn account_balance(
entries : Array[Entry],
account : String,
period? : String = "",
) -> Amount {
let mut debit = 0
let mut credit = 0
for entry in entries {
if entry.account == account && (period == "" || entry.period == period) {
debit += entry.debit
credit += entry.credit
}
}
debit - credit
}
///|
pub fn find_trial_line(
balance : TrialBalance,
account : String,
) -> TrialBalanceLine? {
for line in balance.lines {
if line.account == account {
return Some(line)
}
}
None
}
///|
fn add_trial_line(
lines : Array[TrialBalanceLine],
account : String,
debit : Amount,
credit : Amount,
) -> Unit {
for i, line in lines {
if line.account == account {
lines[i] = {
..line,
debit: line.debit + debit,
credit: line.credit + credit,
balance: line.balance + debit - credit,
}
return
}
}
lines.push({ account, debit, credit, balance: debit - credit })
}