Skip to main content

backbone_pos/
lib.rs

1//! Pos 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;
26// <<< CUSTOM
27/// Stable integration surface for composing services (the deliberate public API consumers depend on).
28pub mod integration;
29// END CUSTOM
30pub mod exports;
31
32// <<< CUSTOM
33// The hand-owned request-pool shim (the composing service's tenant pool
34// resolution): a generated-tree declaration the regenerator drops, so it
35// lives in the preserved block (#447 cause-2 class).
36pub mod request_pool;
37// END CUSTOM
38
39// Re-exports for convenience - Domain entities
40pub use domain::entity::*;
41
42// Re-exports - Infrastructure
43pub use infrastructure::persistence::*;
44
45// Re-exports - Application services
46pub use application::service::PosClosingEntryService;
47pub use application::service::PosInvoiceService;
48pub use application::service::PosInvoiceItemService;
49pub use application::service::PosPaymentService;
50pub use application::service::PosProfileService;
51pub use application::service::PosOpeningEntryService;
52pub use application::service::PosCashMovementService;
53pub use application::service::PosDiscountService;
54pub use application::service::PosManagerPinService;
55pub use application::service::PosFloorPlanService;
56pub use application::service::PosTableService;
57
58// Re-exports - Validation
59pub use application::validator::{ValidationError, ValidationResult};
60
61use std::sync::Arc;
62use axum::Router;
63use sqlx::PgPool;
64
65/// Pos module configuration
66///
67/// Use the builder pattern to configure and register this module:
68///
69/// ```text
70/// let pos = PosModule::builder()
71///     .with_database(pool.clone())
72///     .build()?;
73///
74/// // Unguarded full CRUD (trusted/admin); compose a guarded router for production.
75/// let router = pos.all_crud_routes();
76/// ```
77pub struct PosModule {
78    pub(crate) pos_closing_entry_service: Arc<PosClosingEntryService>,
79    pub(crate) pos_invoice_service: Arc<PosInvoiceService>,
80    pub(crate) pos_invoice_item_service: Arc<PosInvoiceItemService>,
81    pub(crate) pos_payment_service: Arc<PosPaymentService>,
82    pub(crate) pos_profile_service: Arc<PosProfileService>,
83    pub(crate) pos_opening_entry_service: Arc<PosOpeningEntryService>,
84    pub(crate) pos_cash_movement_service: Arc<PosCashMovementService>,
85    pub(crate) pos_discount_service: Arc<PosDiscountService>,
86    pub(crate) pos_manager_pin_service: Arc<PosManagerPinService>,
87    pub(crate) pos_floor_plan_service: Arc<PosFloorPlanService>,
88    pub(crate) pos_table_service: Arc<PosTableService>,
89    // <<< CUSTOM FIELDS
90    // END CUSTOM
91}
92
93impl PosModule {
94    /// Create a new module builder
95    pub fn builder() -> PosModuleBuilder {
96        PosModuleBuilder::new()
97    }
98
99    /// Mount ALL generated CRUD endpoints (12 per entity) with NO domain
100    /// validation — the fully **unguarded** surface. A well-formed request can
101    /// create invalid rows or soft-delete a referenced master out from under its
102    /// dependents. Prefer a guarded composition (read + validated writes) for any
103    /// real deployment; use this only in trusted/admin/seeding contexts.
104    pub fn all_crud_routes(&self) -> Router {
105        use presentation::http::{
106            create_pos_closing_entry_routes,
107            create_pos_invoice_routes,
108            create_pos_invoice_item_routes,
109            create_pos_payment_routes,
110            create_pos_profile_routes,
111            create_pos_opening_entry_routes,
112            create_pos_cash_movement_routes,
113            create_pos_discount_routes,
114            create_pos_manager_pin_routes,
115            create_pos_floor_plan_routes,
116            create_pos_table_routes,
117        };
118
119        Router::new()
120            .merge(create_pos_closing_entry_routes(self.pos_closing_entry_service.clone()))
121            .merge(create_pos_invoice_routes(self.pos_invoice_service.clone()))
122            .merge(create_pos_invoice_item_routes(self.pos_invoice_item_service.clone()))
123            .merge(create_pos_payment_routes(self.pos_payment_service.clone()))
124            .merge(create_pos_profile_routes(self.pos_profile_service.clone()))
125            .merge(create_pos_opening_entry_routes(self.pos_opening_entry_service.clone()))
126            .merge(create_pos_cash_movement_routes(self.pos_cash_movement_service.clone()))
127            .merge(create_pos_discount_routes(self.pos_discount_service.clone()))
128            .merge(create_pos_manager_pin_routes(self.pos_manager_pin_service.clone()))
129            .merge(create_pos_floor_plan_routes(self.pos_floor_plan_service.clone()))
130            .merge(create_pos_table_routes(self.pos_table_service.clone()))
131    }
132
133    /// Deprecated alias for [`Self::all_crud_routes`]. `routes()` reads like
134    /// "the routes" but mounts UNVALIDATED generic CRUD on every entity — a naive
135    /// mount exposes unguarded writes. Compose a guarded router (read + validated
136    /// writes) for production, or call `all_crud_routes()` to opt into the full
137    /// unguarded surface explicitly.
138    #[deprecated(note = "mounts unvalidated generic CRUD; prefer readonly_routes() + validated writes, or all_crud_routes() for the full/unguarded surface")]
139    pub fn routes(&self) -> Router {
140        self.all_crud_routes()
141    }
142
143    /// Read-only routes for every entity (GET endpoints only) — the safe base.
144    ///
145    /// Generic mutation can't reach here, so this surface cannot bypass a
146    /// validated write service's invariants. Use this as the production base and
147    /// merge validated write routes (or a write service's HTTP layer) onto it.
148    pub fn readonly_routes(&self) -> Router {
149        use presentation::http::{
150            create_pos_closing_entry_read_routes,
151            create_pos_invoice_read_routes,
152            create_pos_invoice_item_read_routes,
153            create_pos_payment_read_routes,
154            create_pos_profile_read_routes,
155            create_pos_opening_entry_read_routes,
156            create_pos_cash_movement_read_routes,
157            create_pos_discount_read_routes,
158            create_pos_manager_pin_read_routes,
159            create_pos_floor_plan_read_routes,
160            create_pos_table_read_routes,
161        };
162
163        Router::new()
164            .merge(create_pos_closing_entry_read_routes(self.pos_closing_entry_service.clone()))
165            .merge(create_pos_invoice_read_routes(self.pos_invoice_service.clone()))
166            .merge(create_pos_invoice_item_read_routes(self.pos_invoice_item_service.clone()))
167            .merge(create_pos_payment_read_routes(self.pos_payment_service.clone()))
168            .merge(create_pos_profile_read_routes(self.pos_profile_service.clone()))
169            .merge(create_pos_opening_entry_read_routes(self.pos_opening_entry_service.clone()))
170            .merge(create_pos_cash_movement_read_routes(self.pos_cash_movement_service.clone()))
171            .merge(create_pos_discount_read_routes(self.pos_discount_service.clone()))
172            .merge(create_pos_manager_pin_read_routes(self.pos_manager_pin_service.clone()))
173            .merge(create_pos_floor_plan_read_routes(self.pos_floor_plan_service.clone()))
174            .merge(create_pos_table_read_routes(self.pos_table_service.clone()))
175    }
176
177    // <<< CUSTOM METHODS
178    // END CUSTOM
179}
180
181/// Builder for PosModule
182pub struct PosModuleBuilder {
183    db_pool: Option<PgPool>,
184}
185
186impl PosModuleBuilder {
187    /// Create a new builder
188    pub fn new() -> Self {
189        Self {
190            db_pool: None,
191        }
192    }
193
194    /// Set the database connection pool
195    pub fn with_database(mut self, pool: PgPool) -> Self {
196        self.db_pool = Some(pool);
197        self
198    }
199
200    // <<< CUSTOM - custom builder methods
201    // END CUSTOM
202
203    /// Build the module with configured dependencies
204    pub fn build(self) -> anyhow::Result<PosModule> {
205        let db_pool = self.db_pool
206            .ok_or_else(|| anyhow::anyhow!("Database pool not configured"))?;
207
208        // PosClosingEntry service
209        let pos_closing_entry_repository = Arc::new(PosClosingEntryRepository::new(db_pool.clone()));
210        let pos_closing_entry_service = Arc::new(PosClosingEntryService::with_repository(pos_closing_entry_repository.clone()));
211
212        // PosInvoice service
213        let pos_invoice_repository = Arc::new(PosInvoiceRepository::new(db_pool.clone()));
214        let pos_invoice_service = Arc::new(PosInvoiceService::with_repository(pos_invoice_repository.clone()));
215
216        // PosInvoiceItem service
217        let pos_invoice_item_repository = Arc::new(PosInvoiceItemRepository::new(db_pool.clone()));
218        let pos_invoice_item_service = Arc::new(PosInvoiceItemService::with_repository(pos_invoice_item_repository.clone()));
219
220        // PosPayment service
221        let pos_payment_repository = Arc::new(PosPaymentRepository::new(db_pool.clone()));
222        let pos_payment_service = Arc::new(PosPaymentService::with_repository(pos_payment_repository.clone()));
223
224        // PosProfile service
225        let pos_profile_repository = Arc::new(PosProfileRepository::new(db_pool.clone()));
226        let pos_profile_service = Arc::new(PosProfileService::with_repository(pos_profile_repository.clone()));
227
228        // PosOpeningEntry service
229        let pos_opening_entry_repository = Arc::new(PosOpeningEntryRepository::new(db_pool.clone()));
230        let pos_opening_entry_service = Arc::new(PosOpeningEntryService::with_repository(pos_opening_entry_repository.clone()));
231
232        // PosCashMovement service
233        let pos_cash_movement_repository = Arc::new(PosCashMovementRepository::new(db_pool.clone()));
234        let pos_cash_movement_service = Arc::new(PosCashMovementService::with_repository(pos_cash_movement_repository.clone()));
235
236        // PosDiscount service
237        let pos_discount_repository = Arc::new(PosDiscountRepository::new(db_pool.clone()));
238        let pos_discount_service = Arc::new(PosDiscountService::with_repository(pos_discount_repository.clone()));
239
240        // PosManagerPin service
241        let pos_manager_pin_repository = Arc::new(PosManagerPinRepository::new(db_pool.clone()));
242        let pos_manager_pin_service = Arc::new(PosManagerPinService::with_repository(pos_manager_pin_repository.clone()));
243
244        // PosFloorPlan service
245        let pos_floor_plan_repository = Arc::new(PosFloorPlanRepository::new(db_pool.clone()));
246        let pos_floor_plan_service = Arc::new(PosFloorPlanService::with_repository(pos_floor_plan_repository.clone()));
247
248        // PosTable service
249        let pos_table_repository = Arc::new(PosTableRepository::new(db_pool.clone()));
250        let pos_table_service = Arc::new(PosTableService::with_repository(pos_table_repository.clone()));
251
252        // <<< CUSTOM
253        // END CUSTOM
254
255        Ok(PosModule {
256            pos_closing_entry_service,
257            pos_invoice_service,
258            pos_invoice_item_service,
259            pos_payment_service,
260            pos_profile_service,
261            pos_opening_entry_service,
262            pos_cash_movement_service,
263            pos_discount_service,
264            pos_manager_pin_service,
265            pos_floor_plan_service,
266            pos_table_service,
267            // <<< CUSTOM
268            // END CUSTOM
269        })
270    }
271}
272
273impl Default for PosModuleBuilder {
274    fn default() -> Self {
275        Self::new()
276    }
277}