Units and display
Overview
Section titled “Overview”Behind every size and every rent in Formation are two decisions: what basis to display (net or gross), and what unit to display it in (square metres vs square feet, per-foot vs per-metre, monthly vs annual rent). Both are driven by the user’s preferences under Settings, not by anything on the record itself — which means the same scheme renders different sizes for two users with different preferences, while the underlying data is identical.
This page describes how those decisions are made and what falls back to what when the preferred value isn’t available.
Area basis: net vs gross
Section titled “Area basis: net vs gross”Every size on the system is stored in two versions: a Net value (lettable / usable area) and a Gross value (including circulation, plant, and other non-lettable space). Gross is always the larger figure for any given physical building.
Your Settings → Format → Area Calculation preference determines which one shows by default:
- Net — Net values appear first; Gross values are still available as a secondary column.
- Gross — Gross values appear first; Net is the secondary column.
This affects every list page (the Total Size column on Schemes, on Developments, on Investment Events) and every detail page.
The basis fallback
Section titled “The basis fallback”When a record’s preferred basis is missing for some reason, the display falls back through a 3-step chain:
- The preferred basis (Net or Gross).
- The other basis.
- The local value — the raw size as entered, in the unit the user typed it in.
So a development with only a local size and no net/gross still shows a number; it just shows whichever it has. This typically only happens during the create flow before the SizeTriplet interceptor has filled in the other two.
Measurement system: metric vs imperial
Section titled “Measurement system: metric vs imperial”Your Settings → Format → Measurement System preference picks between metric (square metres, sqm) and imperial (square feet, sqft). The system stores every size in canonical square metres regardless of preference; the conversion to imperial happens at display time.
The conversion ratio comes from the SizeUnit table itself (each unit row carries a RatioToMetric and RatioToImperial field). If the unit table hasn’t loaded yet — say, on the very first render after a hard reload — the system falls back to a hard-coded 10.7639 (the standard sqm-to-sqft conversion) so the UI doesn’t show a wrong-looking number.
Default unit selection
Section titled “Default unit selection”When a field needs a unit and you haven’t picked one, the system picks a default based on your preferences:
- Imperial + Net → Sqft Net.
- Imperial + Gross → Sqft Gross.
- Metric + Net → Sqm Net.
- Metric + Gross → Sqm Gross.
If no exact match is found in the SizeUnit table for your combination, the system falls back through three further steps:
- Any unit with the right system (sqft / sqm) and the right basis (net / gross).
- Any unit with the right system, ignoring basis.
- Empty — no default selected, you’ll have to pick one yourself.
Rent display format
Section titled “Rent display format”Rent isn’t just a number — it’s a number with a currency, a per-unit qualifier (per-foot, per-metre, per-month), and a period (per annum, per month). The format is driven by a DisplayFormat template on the SizeUnit row.
A unit’s template looks like £{value} psf pa. The system replaces {value} with the rent figure formatted by Intl.NumberFormat using the user’s locale, then renders the result.
When the user’s currency preference differs from the unit’s template currency, the system substitutes the currency symbol at display time — so a unit defined as £{value} psf pa renders to $1,234 psf pa for a USD-preference user.
Time period suffix on column headers
Section titled “Time period suffix on column headers”Column headers that show rent (e.g. the Rent column on Occupier Events lists) include the time period as a suffix:
- Annual (the default) →
pa(per annum). Header reads e.g.Rent (£ psqm pa). - Monthly →
pm. Header reads e.g.Rent (£ psqm pm).
The time-period preference also lives under Settings → Format. Changing it rewrites the column header silently — the underlying values aren’t converted (annual rent stays annual rent in the data), but the display of those values updates.
Scaler precedence
Section titled “Scaler precedence”When a value needs converting between bases (e.g. to compute Net from Local for a hotel use), the system looks up a scaler that says “how many sqm of net floor does a sqm of local-as-typed produce?” The scaler lookup goes through a precedence chain:
- Unit + Building Type + Country — the most specific scaler.
- Unit + Country — drop the building type.
- Unit + Building Type — drop the country.
- Unit only — drop both.
- Global — fall back to a default 1:1.
The first match in this chain wins. This lets us encode “in France, hotel net floor is 0.85 of gross” without affecting every other country.
Unknown markers on size and rent
Section titled “Unknown markers on size and rent”A size or rent field that’s been deliberately set to unknown (via the Unknown checkbox where available) displays as “Unknown” in detail and list views rather than as a missing value. See Unknown and optional fields.
Related rules
Section titled “Related rules”- Currency — how currency is converted and how the symbol substitutes into rent templates.
- Developments, Schemes, Occupier Events — entities where the basis preference visibly affects what’s displayed.
Where this lives
Section titled “Where this lives”- Frontend units module:
src/services/web/src/lib/units.ts - Display components:
src/services/web/src/lib/components/displays/(AreaValue.svelte,AreaLabel.svelte,RentValue.svelte) - Preferences:
src/services/web/src/lib/preferences/ - Server-side scaler precedence:
src/services/api/app/app.api/Services/Conversion/SizeTripletConversionService.cs - DisplayFormat templates: stored on the
SizeUnittable; surfaced through the EnumService cache