backbone-banking 0.7.1

Cash & bank — bank/account master, statement import, reconciliation, and clearing postings (5th GL producer)
Documentation
//! Repository for Bank entities
//!
//! Originally generated by metaphor-schema; now **user-owned** — this exact path is declared under
//! `user_owned` in `metaphor.codegen.yaml`, so the generator skips it wholesale. The custom methods
//! below hold the hand-written Bank SQL (4-layer rule: services orchestrate, repos hold SQL).
//!
//! Thin newtype over `backbone_orm::GenericCrudRepository<Bank, backbone_orm::SoftDelete>`.
//! All standard CRUD methods are available via `Deref`.

use anyhow::Result;
use sqlx::PgPool;
use uuid::Uuid;

use backbone_orm::org_scope;

use crate::domain::entity::Bank;

/// Table name for Bank entities
pub const TABLE_NAME: &str = "banking.banks";

/// Repository for Bank entities.
///
/// All standard CRUD, soft-delete, pagination, and bulk methods are
/// provided automatically via `Deref` to `backbone_orm::GenericCrudRepository`.
pub struct BankRepository(backbone_orm::GenericCrudRepository<Bank, backbone_orm::SoftDelete>);

impl std::ops::Deref for BankRepository {
    type Target = backbone_orm::GenericCrudRepository<Bank, backbone_orm::SoftDelete>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl BankRepository {
    /// Create a new repository instance.
    pub fn new(pool: PgPool) -> Self {
        Self(backbone_orm::GenericCrudRepository::new(pool, TABLE_NAME))
    }
}

/// The exact row a bank registration writes.
///
/// `status` is not a field — the INSERT hard-codes `'active'`. `country` is already defaulted by the
/// caller, so it is not optional here.
pub struct NewBankRow<'a> {
    pub id: Uuid,
    pub name: &'a str,
    pub swift_bic: Option<&'a str>,
    pub country: &'a str,
}

/// Hand-written Bank SQL. Lives here (not in the write service) per the module's 4-layer rule:
/// services orchestrate and own the unit of work, repositories hold the SQL.
impl BankRepository {
    /// Register a bank.
    ///
    /// A write outside any transaction: takes the pool and runs `org_scope::execute_scoped`, which
    /// rides the request-dedicated connection carrying the composing service's org scope when one
    /// is bound — the decorator-installed row-level fence decides the INSERT's WITH CHECK — and
    /// executes plainly on the pool otherwise (unfenced by design, ADR-0029). The module invents
    /// no scope of its own.
    pub async fn insert_bank(&self, pool: &PgPool, b: &NewBankRow<'_>) -> Result<(), sqlx::Error> {
        org_scope::execute_scoped(
            pool,
            sqlx::query(
                r#"INSERT INTO banking.banks (id, name, swift_bic, country, status)
                   VALUES ($1,$2,$3,$4,'active')"#,
            )
            .bind(b.id)
            .bind(b.name)
            .bind(b.swift_bic)
            .bind(b.country),
        )
        .await?;
        Ok(())
    }
}

backbone_core::impl_crud_repository!(BankRepository, Bank, soft_delete);