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