Skip to main content

backbone_banking/
lib.rs

1//! Banking Module
2//!
3//! Generated by metaphor-schema. Enhanced with runtime implementations.
4//!
5//! This module provides:
6//! - Domain entities and repositories
7//! - Application services
8//! - HTTP and gRPC handlers
9//! - Route configuration
10//! - State machine enforcement
11//! - Validation rules runtime
12//! - RBAC middleware
13//! - Trigger execution system
14//! - Computed fields
15//! - Workflow orchestrator
16
17#![recursion_limit = "1024"]
18#![allow(unused_imports)]
19
20// Generated modules
21pub mod domain;
22pub mod infrastructure;
23pub mod application;
24pub mod presentation;
25pub mod seeders;
26pub mod exports;
27// <<< CUSTOM MODULES
28pub mod request_pool;
29// END CUSTOM
30
31// Re-exports for convenience - Domain entities
32pub use domain::entity::*;
33
34// Re-exports - Infrastructure
35pub use infrastructure::persistence::*;
36
37// Re-exports - Application services
38pub use application::service::BankService;
39pub use application::service::BankAccountService;
40pub use application::service::BankClearanceService;
41pub use application::service::BankReconciliationService;
42pub use application::service::BankStatementImportService;
43pub use application::service::BankTransactionService;
44pub use application::service::FxGainLossService;
45pub use application::service::ReconcilePresetService;
46
47// Re-exports - Workflows
48pub use application::workflows::*;
49
50use std::sync::Arc;
51use axum::Router;
52use sqlx::PgPool;
53
54/// Banking module configuration
55///
56/// Use the builder pattern to configure and register this module:
57///
58/// ```text
59/// let banking = BankingModule::builder()
60///     .with_database(pool.clone())
61///     .build()?;
62///
63/// // Unguarded full CRUD (trusted/admin); compose a guarded router for production.
64/// let router = banking.all_crud_routes();
65/// ```
66pub struct BankingModule {
67    pub(crate) bank_service: Arc<BankService>,
68    pub(crate) bank_account_service: Arc<BankAccountService>,
69    pub(crate) bank_clearance_service: Arc<BankClearanceService>,
70    pub(crate) bank_reconciliation_service: Arc<BankReconciliationService>,
71    pub(crate) bank_statement_import_service: Arc<BankStatementImportService>,
72    pub(crate) bank_transaction_service: Arc<BankTransactionService>,
73    pub(crate) fx_gain_loss_service: Arc<FxGainLossService>,
74    pub(crate) reconcile_preset_service: Arc<ReconcilePresetService>,
75    // <<< CUSTOM FIELDS
76    // END CUSTOM
77}
78
79impl BankingModule {
80    /// Create a new module builder
81    pub fn builder() -> BankingModuleBuilder {
82        BankingModuleBuilder::new()
83    }
84
85    /// Mount ALL generated CRUD endpoints (12 per entity) with NO domain
86    /// validation — the fully **unguarded** surface. A well-formed request can
87    /// create invalid rows or soft-delete a referenced master out from under its
88    /// dependents. Prefer a guarded composition (read + validated writes) for any
89    /// real deployment; use this only in trusted/admin/seeding contexts.
90    pub fn all_crud_routes(&self) -> Router {
91        use presentation::http::{
92            create_bank_routes,
93            create_bank_account_routes,
94            create_bank_clearance_routes,
95            create_bank_reconciliation_routes,
96            create_bank_statement_import_routes,
97            create_bank_transaction_routes,
98            create_fx_gain_loss_routes,
99            create_reconcile_preset_routes,
100        };
101
102        Router::new()
103            .merge(create_bank_routes(self.bank_service.clone()))
104            .merge(create_bank_account_routes(self.bank_account_service.clone()))
105            .merge(create_bank_clearance_routes(self.bank_clearance_service.clone()))
106            .merge(create_bank_reconciliation_routes(self.bank_reconciliation_service.clone()))
107            .merge(create_bank_statement_import_routes(self.bank_statement_import_service.clone()))
108            .merge(create_bank_transaction_routes(self.bank_transaction_service.clone()))
109            .merge(create_fx_gain_loss_routes(self.fx_gain_loss_service.clone()))
110            .merge(create_reconcile_preset_routes(self.reconcile_preset_service.clone()))
111    }
112
113    /// Deprecated alias for [`Self::all_crud_routes`]. `routes()` reads like
114    /// "the routes" but mounts UNVALIDATED generic CRUD on every entity — a naive
115    /// mount exposes unguarded writes. Compose a guarded router (read + validated
116    /// writes) for production, or call `all_crud_routes()` to opt into the full
117    /// unguarded surface explicitly.
118    #[deprecated(note = "mounts unvalidated generic CRUD; prefer readonly_routes() + validated writes, or all_crud_routes() for the full/unguarded surface")]
119    pub fn routes(&self) -> Router {
120        self.all_crud_routes()
121    }
122
123    /// Read-only routes for every entity (GET endpoints only) — the safe base.
124    ///
125    /// Generic mutation can't reach here, so this surface cannot bypass a
126    /// validated write service's invariants. Use this as the production base and
127    /// merge validated write routes (or a write service's HTTP layer) onto it.
128    pub fn readonly_routes(&self) -> Router {
129        use presentation::http::{
130            create_bank_read_routes,
131            create_bank_account_read_routes,
132            create_bank_clearance_read_routes,
133            create_bank_reconciliation_read_routes,
134            create_bank_statement_import_read_routes,
135            create_bank_transaction_read_routes,
136            create_fx_gain_loss_read_routes,
137            create_reconcile_preset_read_routes,
138        };
139
140        Router::new()
141            .merge(create_bank_read_routes(self.bank_service.clone()))
142            .merge(create_bank_account_read_routes(self.bank_account_service.clone()))
143            .merge(create_bank_clearance_read_routes(self.bank_clearance_service.clone()))
144            .merge(create_bank_reconciliation_read_routes(self.bank_reconciliation_service.clone()))
145            .merge(create_bank_statement_import_read_routes(self.bank_statement_import_service.clone()))
146            .merge(create_bank_transaction_read_routes(self.bank_transaction_service.clone()))
147            .merge(create_fx_gain_loss_read_routes(self.fx_gain_loss_service.clone()))
148            .merge(create_reconcile_preset_read_routes(self.reconcile_preset_service.clone()))
149    }
150
151    // <<< CUSTOM METHODS
152    // END CUSTOM
153}
154
155/// Builder for BankingModule
156pub struct BankingModuleBuilder {
157    db_pool: Option<PgPool>,
158    // <<< CUSTOM BUILDER FIELDS
159    // END CUSTOM
160}
161
162impl BankingModuleBuilder {
163    /// Create a new builder
164    pub fn new() -> Self {
165        Self {
166            db_pool: None,
167            // <<< CUSTOM BUILDER DEFAULTS
168            // END CUSTOM
169        }
170    }
171
172    /// Set the database connection pool
173    pub fn with_database(mut self, pool: PgPool) -> Self {
174        self.db_pool = Some(pool);
175        self
176    }
177
178    // <<< CUSTOM - custom builder methods
179    // END CUSTOM
180
181    /// Build the module with configured dependencies
182    pub fn build(self) -> anyhow::Result<BankingModule> {
183        let db_pool = self.db_pool
184            .ok_or_else(|| anyhow::anyhow!("Database pool not configured"))?;
185
186        // Bank service
187        let bank_repository = Arc::new(BankRepository::new(db_pool.clone()));
188        let bank_service = Arc::new(BankService::with_repository(bank_repository.clone()));
189
190        // BankAccount service
191        let bank_account_repository = Arc::new(BankAccountRepository::new(db_pool.clone()));
192        let bank_account_service = Arc::new(BankAccountService::with_repository(bank_account_repository.clone()));
193
194        // BankClearance service
195        let bank_clearance_repository = Arc::new(BankClearanceRepository::new(db_pool.clone()));
196        let bank_clearance_service = Arc::new(BankClearanceService::with_repository(bank_clearance_repository.clone()));
197
198        // BankReconciliation service
199        let bank_reconciliation_repository = Arc::new(BankReconciliationRepository::new(db_pool.clone()));
200        let bank_reconciliation_service = Arc::new(BankReconciliationService::with_repository(bank_reconciliation_repository.clone()));
201
202        // BankStatementImport service
203        let bank_statement_import_repository = Arc::new(BankStatementImportRepository::new(db_pool.clone()));
204        let bank_statement_import_service = Arc::new(BankStatementImportService::with_repository(bank_statement_import_repository.clone()));
205
206        // BankTransaction service
207        let bank_transaction_repository = Arc::new(BankTransactionRepository::new(db_pool.clone()));
208        let bank_transaction_service = Arc::new(BankTransactionService::with_repository(bank_transaction_repository.clone()));
209
210        // FxGainLoss service
211        let fx_gain_loss_repository = Arc::new(FxGainLossRepository::new(db_pool.clone()));
212        let fx_gain_loss_service = Arc::new(FxGainLossService::with_repository(fx_gain_loss_repository.clone()));
213
214        // ReconcilePreset service
215        let reconcile_preset_repository = Arc::new(ReconcilePresetRepository::new(db_pool.clone()));
216        let reconcile_preset_service = Arc::new(ReconcilePresetService::with_repository(reconcile_preset_repository.clone()));
217
218        // <<< CUSTOM
219        // END CUSTOM
220
221        Ok(BankingModule {
222            bank_service,
223            bank_account_service,
224            bank_clearance_service,
225            bank_reconciliation_service,
226            bank_statement_import_service,
227            bank_transaction_service,
228            fx_gain_loss_service,
229            reconcile_preset_service,
230            // <<< CUSTOM
231            // END CUSTOM
232        })
233    }
234}
235
236impl Default for BankingModuleBuilder {
237    fn default() -> Self {
238        Self::new()
239    }
240}