|
| 1 | +--- |
| 2 | +title: Enterprise Patterns |
| 3 | +description: Handling complex ERP/CRM business logic (State Machines, Calculations, RBAC) using the Protocol-Driven approach. |
| 4 | +sidebar_position: 4 |
| 5 | +slug: /concepts/enterprise-patterns |
| 6 | +--- |
| 7 | + |
| 8 | +# Enterprise Patterns |
| 9 | + |
| 10 | +A common misconception about "Low-Code" or "Protocol-Driven" platforms is that they are only suitable for simple CRUD applications. |
| 11 | + |
| 12 | +While true for many visual builders, **ObjectStack** is architected specifically for the complexity of Enterprise Resource Planning (ERP) and Customer Relationship Management (CRM) systems. We handle complexity not by hiding it, but by **modeling it** explicitly in the protocol. |
| 13 | + |
| 14 | +Here is how we map common Enterprise Patterns to the ObjectStack architecture. |
| 15 | + |
| 16 | +## 1. Workflows as State Machines (FSM) |
| 17 | + |
| 18 | +In enterprise software, a record (e.g., a "Purchase Order") is rarely just static data. It is a living entity that moves through a lifecycle. |
| 19 | + |
| 20 | +**The Anti-Pattern:** |
| 21 | +Writing scattered `if/else` logic in controllers: |
| 22 | +```javascript |
| 23 | +// Don't do this |
| 24 | +if (order.status === 'draft' && user.role === 'manager') { |
| 25 | + order.status = 'approved'; |
| 26 | +} |
| 27 | + |
| 28 | +``` |
| 29 | + |
| 30 | +**The ObjectStack Pattern:** |
| 31 | +We define the lifecycle as a **Finite State Machine (FSM)** in the ObjectOS Protocol. This makes the business process deterministic and visualizeable. |
| 32 | + |
| 33 | +```yaml |
| 34 | +# workflows/purchase_order.yaml |
| 35 | +name: purchase_approval |
| 36 | +object: purchase_order |
| 37 | +states: |
| 38 | + draft: |
| 39 | + initial: true |
| 40 | + on_exit: ['validate_budget'] |
| 41 | + transitions: |
| 42 | + submit: pending_approval |
| 43 | + pending_approval: |
| 44 | + transitions: |
| 45 | + approve: approved |
| 46 | + reject: rejected |
| 47 | + guards: |
| 48 | + approve: "user.has_permission('approve_budget')" |
| 49 | + approved: |
| 50 | + final: true |
| 51 | + |
| 52 | +``` |
| 53 | + |
| 54 | +* **Deterministic:** An order *cannot* jump from `draft` to `shipped` unless the protocol allows it. |
| 55 | +* **Audit:** The engine automatically logs every transition (Who moved it? When? Why?). |
| 56 | + |
| 57 | +## 2. High-Precision Calculations (Virtual Columns) |
| 58 | + |
| 59 | +ERPs are essentially databases mixed with complex spreadsheets. You need to calculate tax, aggregate line items, and compute margins—often across millions of rows. |
| 60 | + |
| 61 | +**The Anti-Pattern:** |
| 62 | +Fetching all data into Node.js memory to loop and calculate. This kills performance. |
| 63 | + |
| 64 | +**The ObjectStack Pattern:** |
| 65 | +We use **ObjectQL Virtual Columns** to compile logic down to the database layer. |
| 66 | + |
| 67 | +```yaml |
| 68 | +# objects/invoice.object.yaml |
| 69 | +name: invoice |
| 70 | +fields: |
| 71 | + lines: |
| 72 | + type: master_detail |
| 73 | + reference_to: invoice_line |
| 74 | + |
| 75 | + # A summary field that compiles to a SQL subquery or aggregation |
| 76 | + total_amount: |
| 77 | + type: summary |
| 78 | + reference_to: lines |
| 79 | + summary_type: sum |
| 80 | + summary_field: amount |
| 81 | + |
| 82 | + # A formula field that compiles to a SQL expression |
| 83 | + margin_percent: |
| 84 | + type: formula |
| 85 | + formula: "(${total_amount} - ${cost}) / ${total_amount}" |
| 86 | + precision: 18 |
| 87 | + scale: 2 |
| 88 | + |
| 89 | +``` |
| 90 | + |
| 91 | +* **Performance:** The ObjectQL Compiler translates `total_amount` into a highly optimized SQL `SUM()` or a materialized view. |
| 92 | +* **Consistency:** The calculation is defined once in the Schema, ensuring the API, the UI, and the Reports all show the exact same number. |
| 93 | + |
| 94 | +## 3. Granular Governance (Field-Level Security) |
| 95 | + |
| 96 | +In an HR system, everyone can see an "Employee" record, but only HR Managers can see the "Salary" field. |
| 97 | + |
| 98 | +**The Anti-Pattern:** |
| 99 | +Manually stripping fields in API controllers: `delete user.salary`. This is error-prone; developers often forget one endpoint (e.g., the search API). |
| 100 | + |
| 101 | +**The ObjectStack Pattern:** |
| 102 | +Security is injected into the **Compilation Phase**. |
| 103 | + |
| 104 | +```yaml |
| 105 | +# permissions/hr_manager.permission.yaml |
| 106 | +role: hr_manager |
| 107 | +object: employee |
| 108 | +allow_read: true |
| 109 | +allow_edit: true |
| 110 | +field_permissions: |
| 111 | + salary: |
| 112 | + read: true |
| 113 | + edit: true |
| 114 | + |
| 115 | +# permissions/employee.permission.yaml |
| 116 | +role: employee |
| 117 | +object: employee |
| 118 | +allow_read: true |
| 119 | +field_permissions: |
| 120 | + salary: |
| 121 | + read: false # The compiler physically removes this column from the SELECT statement |
| 122 | + |
| 123 | +``` |
| 124 | + |
| 125 | +* **Safety:** If a user without permission tries to query `salary`, the ObjectQL engine throws a compilation error or returns `null` (depending on config). It never touches the database. |
| 126 | + |
| 127 | +## 4. Master-Detail Interfaces (Compound UI) |
| 128 | + |
| 129 | +Enterprise users require high-density interfaces. They need to edit an Order (Header) and its Items (Lines) on a single screen without page refreshes. |
| 130 | + |
| 131 | +**The ObjectStack Pattern:** |
| 132 | +ObjectUI supports **Compound Layouts** defined via JSON. |
| 133 | + |
| 134 | +```json |
| 135 | +{ |
| 136 | + "type": "layout.master_detail", |
| 137 | + "props": { |
| 138 | + "master_object": "order", |
| 139 | + "detail_object": "order_line", |
| 140 | + "link_field": "order_id" |
| 141 | + }, |
| 142 | + "children": [ |
| 143 | + { |
| 144 | + "region": "header", |
| 145 | + "type": "form", |
| 146 | + "fields": ["customer", "date", "status"] |
| 147 | + }, |
| 148 | + { |
| 149 | + "region": "body", |
| 150 | + "type": "grid.editable", // An Excel-like editable table |
| 151 | + "fields": ["product", "quantity", "price", "subtotal"] |
| 152 | + } |
| 153 | + ] |
| 154 | +} |
| 155 | + |
| 156 | +``` |
| 157 | + |
| 158 | +* **Transaction Awareness:** The ObjectUI engine knows these two datasets are linked. When the user clicks "Save", it constructs a **Transactional Mutation** to save both the Order and Lines atomically. |
| 159 | + |
| 160 | +## 5. Audit Trails & Compliance |
| 161 | + |
| 162 | +For Finance and Healthcare (HIPAA/SOX), "Who changed what" is a legal requirement. |
| 163 | + |
| 164 | +**The ObjectStack Pattern:** |
| 165 | +Because all mutations go through the ObjectQL Protocol, auditing is enabled by a single flag. |
| 166 | + |
| 167 | +* **Protocol:** The engine captures the `before` and `after` state of every field. |
| 168 | +* **Storage:** Changes are written to a localized `audit_log` table (or an immutable ledger). |
| 169 | +* **Visualization:** ObjectUI provides a built-in "History" component that renders this log instantly. |
| 170 | + |
| 171 | +## Summary |
| 172 | + |
| 173 | +ObjectStack handles enterprise complexity by **elevating patterns into protocols**. |
| 174 | + |
| 175 | +| Complexity | Traditional Code | ObjectStack Protocol | |
| 176 | +| --- | --- | --- | |
| 177 | +| **Process** | `if/else` spaghetti | **Finite State Machines (YAML)** | |
| 178 | +| **Math** | Looping in memory | **Virtual Columns (SQL Compilation)** | |
| 179 | +| **Secrecy** | Manual API filtering | **Engine-Level RBAC** | |
| 180 | +| **UX** | Hardcoded React forms | **Master-Detail Layouts (JSON)** | |
| 181 | +| **History** | Custom logging logic | **Native Audit Trail** | |
0 commit comments