Developer Documentation

Data Principles & Vocabulary

Torro's data model is built on three simple concepts borrowed from language — nouns, adjectives, and verbs. Understanding this vocabulary is the foundation for everything else.

Nouns — The Building Blocks

Nouns represent the things that a business has — people, jobs, inventory, suppliers. They form the foundation of every system built on Torro. Every significant entity in the business is a noun.

Type 01

Primary Nouns

The first objects you see when logging in. Accessed from the home screen for daily work — customers, jobs, inventory items. They grow continuously as the business expands and progress through states across their lifecycle.

Type 02

Managed Nouns

Can be added, but the process is controlled. Standard managed allows general staff to add items (e.g. new inventory). Admin managed requires elevated permissions (e.g. adding branches).

Type 03

Growing Nouns

Similar to primary nouns but not on the home screen. Low volume (10–40 items) displays all options. High volume (100,000+) uses search and filter. The treatment evolves naturally as the noun grows.

Adjectives — Descriptive Information

Adjectives describe nouns and add information around them — just as in English. Big or small, male or female, good customer or at-risk customer, buying group membership, vehicle type.

In Torro's definition, adjectives also include what would traditionally be called adverbs — things that describe activities or verbs — because they behave identically in the data model.

Adjectives come in basic forms: some with just a description, others with a code and description (for example M for Male, F for Female). The choice depends on how the data will be filtered and used in code.

Design Note

Adjectives are typically small, stable lists. When a list starts growing significantly or items need their own lifecycle, consider whether it should be promoted to a noun instead.

Properties & References

Classes have two categories of members: properties — data that sits directly on the object such as a name, phone number or date — and references — links to other objects such as a customer's buying group, or a sale line's item.

In Jade, class references can point to collections. A sale order can have a collection of sale order lines. Typically the child manages the relationship by declaring its parent, and Jade automatically maintains the parent's collection.

One-to-many relationships are significantly easier to manage than many-to-many. When possible, engineer your design as one-to-many using an intersection object rather than a direct many-to-many link.

Relationship Types

Type Description Example
Parent–Child The child has no meaning without the parent. Lifecycle is tied — deleting the parent removes the children. SaleOrder_LineSaleOrder
Required One-to-Many The object must have this reference. Many objects can share the same referenced object. Customer must have a buying group
Optional One-to-Many The reference may or may not be set. The object is valid either way. Customer may or may not have a buying group
One-to-One Required This side must have the reference, but the other side may not have a back-reference. BankAccount must have a GL Account
One-to-One Optional This side may or may not have the reference. GL Account may or may not have a BankAccount
Intersection (Many-to-Many) Direct many-to-many is avoided. An intersection object creates two one-to-many relationships instead, with its own properties and lifecycle. CustomerPricingGroup between Customer and PricingGroup

Property Prefix System

Every property and reference in Torro is prefixed with one or two characters that encode its nature. By reading the prefix, a developer immediately knows where the value comes from, whether it can be set, how it relates to other objects, and what validation applies — without reading any documentation.

Reference Prefixes

s
Parent Reference

Reference to a parent object. Implies ownership and lifecycle. Set once on creation, never changed. e.g. sSaleOrder on SaleOrder_Line

r
Required Reference

Must be set. The object is invalid without it. e.g. rItem

o
Optional Reference

May or may not be set. The object is valid either way. e.g. oDiscount

n
Collection (Inverse)

A collection of related objects. Always the inverse side of another reference. e.g. nrSaleOrder_Line on Item

j
Junction Reference

Reference used in an intersection object to manage a many-to-many relationship.

Relationship Modifiers — Combining Prefixes

rn
Required with Inverse

Required reference that has a collection on the other side. e.g. rnItem on SaleOrder_Line

nr
Inverse of Required

The collection side of an rn relationship. e.g. nrSaleOrder_Line on Item

on
Optional with Inverse

Optional reference that has a collection on the other side.

ro
Required / Optional One-to-One

This side is required, the other side is optional. e.g. roGLAccount on BankAccount

or
Optional / Required One-to-One

This side is optional, the other side is required. e.g. orBankAccount on GLAccount

fn
Function with Inverse

System-calculated reference with a collection on the other side. e.g. fnState on SaleOrder

Attribute Prefixes

a
Required Attribute

Must have a meaningful value. Not null, not zero, not blank.

b
Optional Attribute

May be null, zero, or blank. The object is valid without it.

d
Defaulted Attribute

The system provides a default value. Can be overridden by the user. e.g. dOrderDate defaults to today.

u
Unique Attribute

Must be unique within a defined context (not necessarily globally). e.g. invoice number unique per Supplier.

k
Locked Once Set

Can be set on creation but cannot be changed thereafter.

h
Owner Only

Only the person who created the record can change this value. e.g. hNote

g
Governed

There are ristrictions as to who can do what with this property ie Approving a Price Increase.

y
Binary Flag

A bitmask flag used for relationship identification. Multiple flags combine into a single value.

Behavioural Prefixes

i
Inference

Value populated automatically through a relationship. Not settable externally. e.g. iSellPrice populated when Item is set.

e
Editable Inference

Inferred automatically but can be overridden by the user. e.g. eSellPrice

f
Function / Calculated

The system calculates this value. Can be a number, a state, or any type. Not settable externally.

x
Derived Value

Lazily calculated and cached. The system marks it expired when dependencies change, and recalculates only when requested.

Method & Code Prefixes

m
Method

A standard method on a class.

t
Type Method

A method defined at the class type level.

p
Method Parameter

A parameter passed into a method.

l
Local Variable

A variable scoped to the current method.

c
Constant

A system or method-level constant. Fixed value, never changes.

v
Virtual Property

Used on JU objects for data transformation — maps external inputs to internal representations.

Inferences

Inferences explain how data is automatically populated through relationships. When a user selects an Item on a Sale Order Line, a chain of values is inferred from that Item automatically.

Example — Selecting an Item on SaleOrder_Line

rnItem iSellPrice inferred, not editable
rnItem eSellPrice inferred, user can override
rnItem iCostPrice inferred, locked
rnItem eDiscount inferred, user can override
rnItem iDescription inferred, not editable

When the selected item changes, inferences generally update to match the new item. However, there are cases — such as quoting with a generic item before converting to a specific one — where you may not want prices to reset. Every situation has unique requirements, and inference update behaviour is configurable.

Calculations

Calculations produce values that the system computes at the time of update — before the database commit, all related calculations are resolved. There are two types.

Local Calculations

All the information needed is on the object itself or a directly related object. For example: net total = sell price × quantity, optionally adjusted by a discount. Simple, fast, and executed as part of the standard update cycle.

Summation Calculations

The parent object holds a total that is the sum of its children. When a child is added, edited or removed, the parent's total must update. For example, a Sale Order total is the sum of all its Sale Order Line totals.

In Torro, this cascade is automatic. mUpdateCalculations on SaleOrder_Line calls mUpdateCalculations on SaleOrder. The developer updates the calculation logic in one place — not in every event handler that might touch a contributing value.

Key Principle

If you add a discount field to SaleOrder_Line, you update the maths in one place. You do not touch qty-change handlers, price-change handlers, or discount-change handlers separately. The single mUpdateCalculations method is called for any property change.

Derived Values

Derived values differ from calculations in when they are computed. Rather than updating immediately on every change, derived values use a lazy evaluation and caching mechanism — marked with the x prefix.

1
Data changes

When contributing data changes, the cached derived value is marked as expired — but not recalculated.

2
Value is requested

When something asks for the derived value, the system checks whether its cached version is still valid.

3
Cache hit

If the edition number matches, the cached value is returned immediately — no calculation required.

4
Cache miss

If expired or unknown, the system calculates, stores the result with the current edition number, and returns it.

Edition Tracking

Jade automatically manages edition numbers for all objects. Every object begins at edition 1. Each edit increments the edition. When contributing data changes, the derived value object's edition is incremented — expiring its cache automatically.

Significantly, if you change the calculation method itself, Jade increments the edition — automatically expiring all cached values and preventing stale results from persisting.

Example

"Total iPhones sold" — if 1,000 iPhones are sold but nobody requests this total, the calculation never runs. Only when requested does the system compute, cache, and return the result. This minimises database activity, especially for complex queries that may never actually be needed.