diff --git a/DOMAIN.md b/DOMAIN.md new file mode 100644 index 0000000..96307fd --- /dev/null +++ b/DOMAIN.md @@ -0,0 +1,178 @@ +# Domain — Terminology & Ontology + +This document defines key terms, naming conventions, entity relationships, and business concepts used throughout the Business Data Platform (BDP). It reduces ambiguity for AI agents and developers working with the codebase. For exhaustive field-level specifications, see `requirements.md`. + +## Core Terminology + +| Term | Meaning | +|---|---| +| **Object ID** | A reference identifier pointing to another entity record in the database. Used extensively across entities as foreign-key-like references (e.g., `customer._id` on an Order). | +| **_underscore fields** | System-managed metadata prefixed with underscore. Never set by agents directly — computed or managed by the platform internally. Examples: `_id`, `_entered.by`, `_modified.ts`, `_total`, `_active`. | +| **SKU** | Unique product identifier starting at 100000 by default. Must be unique across all products. | +| **MPN** | Manufacturer Part Number — identifies a specific part from a manufacturer. | +| **EAN** | European Article Number barcode identifier for products. | + +## Naming Conventions + +### Field naming rules + +- Regular data fields use **snake_case**: `product_id`, `price_as_cents`, `invoice_date` +- System metadata uses underscore prefix + snake_case: `_id`, `_entered.by`, `_modified.ts`, `_total`, `_active` +- GraphQL output types (structs/enums) use **PascalCase** in Rust code but expose as camelCase/snake_case via Juniper field name annotations + +### Reference patterns + +All entity references follow a consistent pattern: + +``` +reference._id → object ID pointing to the referenced entity +reference.name → human-readable label of the reference +``` + +Examples: +- `customer._id` on an Order — points to the Customer record +- `supplier._id` on an Invoice — points to the Supplier record +- `category._id` on a Product — points to the Category record + +## Entity Relationship Map + +### Primary relationships + +| Source entity | Points to | Purpose | +|---|---|---| +| **Order** → Customer | Embedded customer data on every order | Links transaction to buyer | +| **Order** → Address (invoice_address, shipping_address) | Invoice address and shipping address blocks | Delivery logistics | +| **Order** → Product(s) | Nested product data in each order item | Transaction contents | +| **Invoice** → Supplier | Required reference on every invoice | Purchasing source | +| **Invoice** → Account | GL account reference | Accounting classification | +| **Invoice** → Order / Project | Optional attachment via `_attached.to` | Invoice linkage to transaction | +| **Product** → Category | Required reference — every product belongs to a category | Classification | +| **Product** → Manufacturer | Supplier identification for products | Sourcing traceability | +| **Customer** → Business Unit | Required assignment on save | Organizational scope | +| **Employee** → Business Unit / Location | Organizational placement | Work location and unit | +| **Inventory** → Product | Each stock unit references a product SKU | Physical-to-logical mapping | +| **Inventory** → Invoice | Supplier invoice the inventory was received against | Procurement traceability | +| **Business Unit** → Locations | Locations attached to business units | Physical site management | + +### Secondary / derived relationships + +| Chain | Description | +|---|---| +| **Pipeline → Sales Quote → Order** | Quotes are proposals; converting a quote creates an order | +| **Sales Quote → Customer** | Every quote is presented to a customer | +| **Inventory → RMA** | Returned inventory units reference the RMA record | +| **Service Job → Employee** | Service jobs assigned to employees/teams for execution | +| **Task → Employee / User** | Tasks assigned to individuals or teams | +| **Product → Supplier Part Numbers** | Products track supplier part numbers for procurement | + +## Common Enums Across Entities + +### Status enums (reused across many entities) + +- `Current`, `Deleted`, `Internal`, `Hidden`, `Discontinued` — product/customer/status lifecycle states +- `Active`, `Closed` — business unit/location/financial account states +- `Primary`, `Secondary`, `Tertiary` — supplier priority levels +- `Stock`, `Courier`, `Expense`, `Contractor` — supplier type classification + +### Order-specific enums + +- **Classification**: `SalesOrder`, `Project`, `Job`, `AssetBooking`, `SupportTicket` +- **Order Type**: `Standard`, `Master`, `Suborder` — Master orders aggregate Suborders +- **Source**: `API`, `SAPI`, `WAPI` — origin of order creation + +### Product-specific enums + +- **Product Type**: `Product`, `Service`, `Discount`, `Virtual`, `Property`, `Labour` +- **Unit of Measure**: `Each`, `Mitre`, `Roll`, `LinearMetre`, `Pack` +- **Stock Priority**: `AlwaysInStock`, `LowStockQty`, `OrderInOnly`, `SpecialOrder` +- **Product Status**: `Current`, `Internal`, `Hidden`, `Discontinued` + +### Invoice-specific enums + +- **Invoice Type**: `SalesInvoice`, `ReturnMerchandiseAuthorization`, `EmployeeInvoice` +- **Tax Classification**: `G3`, `G4`, `G5`, `G6`, `G11`, `G13` — Australian GST grouping codes + +### Currency enums + +- `AUD`, `USD`, `EUR`, `NZD`, `GBP`, `HKD`, `SGD`, `RMB`, `CAD`, `AED`, `INR`, `PHP` +- Default currency is **AUD** (Australian Dollar) across the platform. + +## Business Concept Explanations + +### MASTER / SUBORDER Aggregation + +Orders can be grouped hierarchically: a **Master** order aggregates totals (`_total`, `_exTotal`, `_payments`, `_owing`) from all its linked **Suborders**. This is used for complex transactions where multiple line items need to be tracked individually but reported as one consolidated transaction. + +### Classification / Profile Pattern + +Both Customers and Products use a **classification + category** structure with optional profile attributes: +- `classification.name` — default name (e.g., "Standard") +- `classification.profile._id`, `classification.profile.fields` — custom classification attributes via FieldSchema +- Same pattern applies to `category` + +This allows extendable, schema-driven classification without hard-coding every possible attribute into the base entity. + +### Credit Terms + +Customers and Suppliers both have credit terms: +- `credit.terms` (number) — period in days/weeks/months +- `credit.amount` (number) — credit limit amount +- `credit.duration/type` — unit of time (`days`, `weeks`, `months`) + +### Tax Structure + +The platform uses Australian GST tax classification codes: +- **Product taxes**: configured per product, applied to order items and quotes +- **Invoice tax classifiction**: enum-based grouping (`G3`, `G4`, etc.) for accounting +- Order totals include `_total` (with taxes) and `_exTotal` (excluding taxes), with a breakdown in the `taxes` array + +### Audit Fields + +Every entity tracks creation and modification: +- `_entered.by` — who created the record (object ID ref to User/Employee) +- `_entered.ts` — timestamp of creation +- `_modified.by` — last modifier (object ID ref) +- `_modified.ts` — timestamp of modification +- Some entities also have `_undo` for undo references + +### Business Unit & Location Allocation + +Every entity that participates in business operations must be assigned to a **Business Unit** and often a **Location**: +- Customer → `_businessUnit`, `_location` (required on save) +- Employee → `businessUnit`, `location` +- Order → `_businessUnit`, `_location` (required) +- Invoice → `businessUnit`, `location` +- Business Unit itself defines currency, locale (`en-AU` default), tax settings (`GST` or `No GST`) + +### Sequences + +Shared counters auto-generate unique identifiers across entities: +- Each Sequence belongs to a **model** (e.g., `Order`, `Invoice`) and increments the corresponding field (e.g., `orderNo`, `no`) +- Default starting count is 200000 + +### RMA (Return Merchandise Authorization) + +Returns track fault reporting, replacements, and resolution: +- Customer returns → customer replacement items +- Supplier returns → supplier replacement items +- Each inventory unit can reference an RMA via `_rma.rma` +- Status tracking includes both `customerCompleted` and `supplierCompleted` dates + +### Templates + +Templates are reusable blueprints for generating entities without starting from scratch: +- **Order Template** — pre-filled order structure with default items, addresses, customer +- **Sales Quote Template** — reusable quote content blueprint +- **Email Template** — branded email content (header/body/footer text) +- **Ticket Template** — support ticket structure with status/priority defaults +- Templates can be scoped: global or personal/owned by a specific Customer + +## Reference Resolution Guide + +When an agent encounters a reference field, follow this pattern: + +1. **Read the `_id`** — extract the object ID value (e.g., `customer._id = "abc123"`) +2. **Query for the referenced entity** — use GraphQL to fetch the record with that ID +3. **The referenced entity may have its own nested references** — recurse as needed + +Example: an Order's item contains `product._id` → query Product by that ID → Product has `category._id` → query Category → Category has `master._id` → query MasterCategory.