Skip to main content

BankingWriteService

Struct BankingWriteService 

Source
pub struct BankingWriteService { /* private fields */ }

Implementations§

Source§

impl BankingWriteService

Source

pub fn new(db_pool: PgPool) -> Self

Source

pub fn with_sink(db_pool: PgPool, sink: Arc<dyn BankingEventSink>) -> Self

Source

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).

Source

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.

Source

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).

Source

pub async fn create_bank(&self, b: NewBank) -> Result<Uuid, BankingError>

Source

pub async fn create_bank_account( &self, a: NewBankAccount, ) -> Result<Uuid, BankingError>

Source§

impl BankingWriteService

Source

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.

Source

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

Source

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)
  • = 0 but exceptions remain → balanced (agree, NOT finalized, no event)
  • = 0 and zero exceptions → closed (+ emit BankReconciliationClosed) unreconciled_count is persisted as the exception snapshot at sign-off (audit-reconstructable). Note: period-scoped by txn_date ∈ [from_date, to_date]. ledger_balance is still supplied (recompute is parked — see ADR-001); the line-count is reconcile’s real assertion.
Source§

impl BankingWriteService

Source

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.

Source

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

Source

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§

Source§

impl Clone for BankingWriteService

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more