///|
fn find_line(lines : Array[SettlementLine], code : String) -> SettlementLine? {
for line in lines {
if line.code == code {
break Some(line)
}
} nobreak {
None
}
}
///|
pub fn reconcile_lines(
expected : Array[SettlementLine],
actual : Array[SettlementLine],
tolerance : Money,
) -> ReconciliationReport {
let items : Array[ReconciliationItem] = []
let mut matched = 0
let mut exceptions = 0
let mut net = Money::zero()
for line in expected {
match find_line(actual, line.code) {
Some(other) => {
let difference = other.amount.sub(line.amount)
let status = if difference.abs().cents <= tolerance.abs().cents {
Matched
} else {
Difference
}
if status == Matched {
matched += 1
} else {
exceptions += 1
}
net = net.add(difference)
items.push({
code: line.code,
expected: line.amount,
actual: other.amount,
difference,
status,
})
}
None => {
exceptions += 1
net = net.sub(line.amount)
items.push({
code: line.code,
expected: line.amount,
actual: Money::zero(),
difference: line.amount.negate(),
status: MissingExpected,
})
}
}
}
for line in actual {
if find_line(expected, line.code) is None {
exceptions += 1
net = net.add(line.amount)
items.push({
code: line.code,
expected: Money::zero(),
actual: line.amount,
difference: line.amount,
status: UnexpectedActual,
})
}
}
{ items, matched, exceptions, net_difference: net }
}
///|
pub fn ReconciliationReport::is_matched(self : ReconciliationReport) -> Bool {
self.exceptions == 0
}
///|
pub fn ReconciliationReport::item_count(self : ReconciliationReport) -> Int {
self.items.length()
}
///|
pub fn ReconciliationReport::absolute_difference(
self : ReconciliationReport,
) -> Money {
self.net_difference.abs()
}