pub struct BankingWriteService { /* private fields */ }Implementations§
Source§impl BankingWriteService
impl BankingWriteService
pub fn new(db_pool: PgPool) -> Self
pub fn with_sink(db_pool: PgPool, sink: Arc<dyn BankingEventSink>) -> Self
Sourcepub fn with_iban_policy(self, policy: IbanValidationPolicy) -> Self
pub fn with_iban_policy(self, policy: IbanValidationPolicy) -> Self
Explicit IBAN validation posture for this service instance. Hosts wiring the named
escape pass IbanValidationPolicy::ALLOW_UNKNOWN_COUNTRIES (or
IbanValidationPolicy::from_env() to honor BANKING_IBAN_ALLOW_UNKNOWN_COUNTRIES).
Sourcepub fn with_outbox_schema(self, schema: impl Into<String>) -> Self
pub fn with_outbox_schema(self, schema: impl Into<String>) -> Self
Enable crash-safe BankClearanceRecorded emission via the durable outbox in schema
(e.g. "banking"). Requires backbone_outbox::outbox::migrate to have created
<schema>.outbox_events.
Sourcepub fn with_candidate_port(self, port: Arc<dyn CandidatePoolPort>) -> Self
pub fn with_candidate_port(self, port: Arc<dyn CandidatePoolPort>) -> Self
Inject the reconcile-preset candidate-pool read (module tests inject a stub; the default
reads posted payment headers through a to_regclass guard).
pub async fn create_bank(&self, b: NewBank) -> Result<Uuid, BankingError>
pub async fn create_bank_account( &self, a: NewBankAccount, ) -> Result<Uuid, BankingError>
Source§impl BankingWriteService
impl BankingWriteService
Sourcepub async fn clear_transaction(
&self,
c: NewClearance,
sink: &dyn GlPostSink,
reconcile: &dyn ReconcileSink,
) -> Result<ClearOutcome, BankingError>
pub async fn clear_transaction( &self, c: NewClearance, sink: &dyn GlPostSink, reconcile: &dyn ReconcileSink, ) -> Result<ClearOutcome, BankingError>
Clear a matched statement line through the GL — the bank-side leg. received (deposit):
Dr Bank · Cr Clearing; paid (withdrawal): Dr Clearing · Cr Bank. Bounded: the clearance
cannot exceed the line’s un-allocated remainder. Records a BankClearance, advances the line’s
allocated_amount + status, and emits BankTransactionMatched + BankTransactionCleared.
When the line was matched to a payment, the same unit of work also writes the
reconciliation-graph edge on the clearing account: the payment’s clearing leg meets the
clearance’s clearing leg (the pair that nets the undeposited-funds position to zero), through
the shared ReconcileSink port with origin Clearing. Receipt: the payment DEPOSITED into
clearing (Dr Clearing) and the clearance withdraws it (Cr Clearing); paid-out mirrors.
Fail-closed: if the sink refuses the pair (unposted payment journal, a clearing account
that is not flagged reconcilable, a clamp disagreement) the clearance row and the allocation
advance roll back — banking refuses to record a clear whose ledger-side edge cannot exist.
The clearing post itself is committed by its own sink before the edge; a refusal therefore
strands that journal. The stranded post is NOT re-posted on retry: the clearance identity and
its posting idempotency key are derived deterministically from the fenced cumulative-cleared
position, so the retry reuses the stranded journal (the accounting sink dedups the key), the
edge locator resolves against its lines, and the clear completes — the strand heals itself
once the operator fixes the refusal’s cause. (Re-clearing a DIFFERENT amount after a
stranded attempt still lands as a residual mismatch — an integrity-probe finding, not silent
money.) Matched-source kinds other than payment keep the bounded clearance only — their
graph convergence is the statement-side reconciliation surface.
Sourcepub async fn recognize_bank_charge(
&self,
ch: NewCharge,
sink: &dyn GlPostSink,
) -> Result<ClearOutcome, BankingError>
pub async fn recognize_bank_charge( &self, ch: NewCharge, sink: &dyn GlPostSink, ) -> Result<ClearOutcome, BankingError>
Recognise an outflow line as a bank charge: Dr Bank Charges · Cr Bank. Marks the line
reconciled and emits BankChargeRecognized.
Source§impl BankingWriteService
impl BankingWriteService
Sourcepub async fn reconcile(
&self,
r: NewReconciliation,
) -> Result<ReconcileOutcome, BankingError>
pub async fn reconcile( &self, r: NewReconciliation, ) -> Result<ReconcileOutcome, BankingError>
Open/close a reconciliation session (council 2026-07-05 — line-completeness close-gate). A
session cannot close on the two supplied balances agreeing alone — it must also have zero
open lines in the period, or it would sign off “the bank agrees with our books” while
transactions sit unreconciled (a false attestation). Three-state (activating ReconStatus):
computed_difference ≠ 0→ open (numbers disagree)= 0but exceptions remain → balanced (agree, NOT finalized, no event)= 0and zero exceptions → closed (+ emitBankReconciliationClosed)unreconciled_countis persisted as the exception snapshot at sign-off (audit-reconstructable). Note: period-scoped bytxn_date ∈ [from_date, to_date].ledger_balanceis still supplied (recompute is parked — see ADR-001); the line-count isreconcile’s real assertion.
Source§impl BankingWriteService
impl BankingWriteService
Sourcepub async fn import_statement(
&self,
imp: NewStatementImport,
) -> Result<Uuid, BankingError>
pub async fn import_statement( &self, imp: NewStatementImport, ) -> Result<Uuid, BankingError>
Import a statement: validate balance continuity (opening + Σdeposit − Σwithdrawal = closing),
persist the import + its lines, and emit BankStatementImported.
Sourcepub async fn propose_match(
&self,
bank_transaction_id: Uuid,
candidates: &[MatchCandidate],
) -> Result<Option<MatchCandidate>, BankingError>
pub async fn propose_match( &self, bank_transaction_id: Uuid, candidates: &[MatchCandidate], ) -> Result<Option<MatchCandidate>, BankingError>
Propose a match for a statement line from supplied candidates: prefer an exact amount + exact
reference (exact), else an exact amount (fuzzy). Pure selection — persists nothing.
Source§impl BankingWriteService
impl BankingWriteService
Sourcepub async fn order_candidates(
&self,
preset_id: Uuid,
line_id: Uuid,
) -> Result<Vec<RankedCandidate>, BankingError>
pub async fn order_candidates( &self, preset_id: Uuid, line_id: Uuid, ) -> Result<Vec<RankedCandidate>, BankingError>
Order the candidates for one statement line under one preset. Pure ranking over reads —
no writes, no watermark, no events. Deterministic: equal scores break on payment_number
ascending, so the same committed state always yields the same list (the ordering probe’s
pin).
Trait Implementations§
Auto Trait Implementations§
impl !RefUnwindSafe for BankingWriteService
impl !UnwindSafe for BankingWriteService
impl Freeze for BankingWriteService
impl Send for BankingWriteService
impl Sync for BankingWriteService
impl Unpin for BankingWriteService
impl UnsafeUnpin for BankingWriteService
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more