use uuid::Uuid;
use crate::infrastructure::persistence::NewReconciliationRow;
use super::banking_events::{BankReconciliationClosed, BankingEvent};
use super::banking_write_service::{
money, BankingError, BankingWriteService, NewReconciliation, ReconcileOutcome,
};
impl BankingWriteService {
pub async fn reconcile(&self, r: NewReconciliation) -> Result<ReconcileOutcome, BankingError> {
let diff = money(r.statement_closing_balance - r.ledger_balance);
let id = Uuid::new_v4();
let unreconciled: i64 = self
.repos
.transactions
.count_open_in_period(&self.rpool(), r.bank_account_id, r.from_date, r.to_date)
.await?;
let status = if !diff.is_zero() {
"open"
} else if unreconciled > 0 {
"balanced"
} else {
"closed"
};
self.repos
.reconciliations
.insert_reconciliation(
&self.rpool(),
&NewReconciliationRow {
id,
bank_account_id: r.bank_account_id,
from_date: r.from_date,
to_date: r.to_date,
statement_closing_balance: money(r.statement_closing_balance),
ledger_balance: money(r.ledger_balance),
computed_difference: diff,
unreconciled_count: unreconciled as i32,
status,
},
)
.await?;
if status == "closed" {
self.sink.publish(BankingEvent::BankReconciliationClosed(
BankReconciliationClosed {
reconciliation_id: id,
bank_account_id: r.bank_account_id,
difference: diff,
},
));
}
Ok(ReconcileOutcome {
id,
difference: diff,
unreconciled_count: unreconciled,
status: status.to_string(),
})
}
}