Models
Complete P9 model definition syntax — objects, applications, fields, selects, lookups, and layouts.
Model Definition
A P9 model defines a business object — its fields, relationships, and user interface. Every object in Tuli is defined using this declarative syntax in .model files.
Object Declaration
Every model starts with object metadata:
@object Contract
@application Leasing
@icon "file-text-icon"
@group "Lease Management"
@order 1, 5
| Directive | Required | Description |
|---|---|---|
@object |
Yes | Unique object name (PascalCase, no spaces) |
@application |
Yes | Module this object belongs to |
@icon |
No | Icon identifier for UI |
@group |
No | Navigation group within the module |
@order |
No | Display order (position, subposition) |
Field Definitions
Fields use inline attribute syntax with colon-separated key-value pairs:
field TenantName type:Lookup label:"Tenant" required:true
field MonthlyRent type:Money label:"Monthly Rent" required:true
field StartDate type:Date label:"Lease Start Date" required:true default:[now()]
field Notes type:Text label:"Notes" optional:true multi-line:true placeholder:"Enter any additional notes..."
field ContractNumber type:Autonumber label:"Contract #" format:"CON-{yy}-#" readonly:true
Select Blocks
Define dropdown options for Select fields using curly braces:
field LeaseType type:Select label:"Lease Type" required:true
select LeaseType {
label:"New" value:"New" default:true
label:"Renewal" value:"Renewal"
label:"Amendment" value:"Amendment"
label:"Sublease" value:"Sublease"
}
Select options support visual indicators:
select Status {
label:"Active" value:"Active" sentiment:Positive default:true
label:"Pending" value:"Pending" sentiment:Neutral
label:"Expired" value:"Expired" sentiment:Negative
}
select Priority {
label:"Critical" value:"Critical" stars:5
label:"High" value:"High" stars:4
label:"Normal" value:"Normal" stars:3 default:true
label:"Low" value:"Low" stars:2
}
Lookup Blocks
Define relationships to other objects:
field Tenant type:Lookup label:"Tenant" required:true
lookup Tenant {
lookupobjectname:"Tenant"
displayfield {
"Name"
"Number"
}
filter {
Status="Active"
}
}
Cascading lookups with parent relationships:
field Building type:Lookup label:"Building" required:true
field Unit type:Lookup label:"Unit" required:true parent:Building
lookup Unit {
lookupobjectname:"Unit"
displayfield {
"Number"
"Floor"
}
parents {
Building {
parentobjectfield: "Building"
}
}
filter {
Status="Available"
}
}
Layout Definition
Control the form layout using a 12-column grid:
@layout
form {
create {
title:"Create Contract"
savebuttontext:"Save"
cancelbuttontext:"Cancel"
section {
title:"Contract Details"
subtitle:"Basic contract information"
row {
layout:6,6
fields ContractNumber,LeaseType
}
row {
layout:12
fields Tenant
}
row {
layout:6,6
fields Building,Unit
}
}
section {
title:"Term"
subtitle:"Contract duration"
row {
layout:6,6
fields StartDate,EndDate
}
row {
layout:6
fields Duration
}
}
section {
title:"Financial"
subtitle:"Payment terms"
row {
layout:6,6
fields MonthlyRent,AnnualRent
}
row {
layout:6
fields SecurityDeposit
}
}
}
list {
mobile {
fields ContractNumber,Tenant,MonthlyRent
}
desktop {
fields ContractNumber,Tenant,Building,Unit,StartDate,EndDate,MonthlyRent,Status
}
}
}
Layout Columns:
layout:12= one field, full widthlayout:6,6= two fields, 50% width eachlayout:4,4,4= three fields, 33% width eachlayout:3,3,3,3= four fields, 25% width each
Conditional Sections
Sections can have conditional visibility:
section show:[{Type}='Commercial'] {
title:"Commercial Terms"
row {
layout:6,6
fields CAMCharges,EscalationRate
}
}
section show:[$RecordId != null] {
title:"Status"
row {
layout:6
fields Status
}
}
Complete Contract Example
@object Contract
@application Leasing
@icon "file-text-icon"
@group "Lease Management"
@order 1, 1
field ContractNumber type:Autonumber label:"Contract #" format:"CON-{yy}-#" readonly:true search-field:true filter-order:"1"
field LeaseType type:Select label:"Lease Type" required:true
select LeaseType {
label:"New" value:"New" default:true
label:"Renewal" value:"Renewal"
label:"Amendment" value:"Amendment"
}
field Tenant type:Lookup label:"Tenant" required:true linked-view:true advance-search:true
lookup Tenant {
lookupobjectname:"Tenant"
displayfield {
"Name"
"Number"
}
filter {
Status="Active"
}
}
field Building type:Lookup label:"Building" required:true linked-view:true advance-search:true
lookup Building {
lookupobjectname:"Building"
displayfield {
"Name"
"Number"
}
}
field Unit type:Lookup label:"Unit" required:true parent:Building
lookup Unit {
lookupobjectname:"Unit"
displayfield {
"Number"
"Floor"
}
parents {
Building {
parentobjectfield: "Building"
}
}
}
field StartDate type:Date label:"Start Date" required:true
field EndDate type:Date label:"End Date" required:true
field Duration type:Number label:"Duration (Months)" required:true default:"12"
field MonthlyRent type:Money label:"Monthly Rent" required:true
field SecurityDeposit type:Money label:"Security Deposit" optional:true
field AnnualRent type:Calculated label:"Annual Rent" expression:"{MonthlyRent} * 12" readonly:true
field Status type:Select label:"Status" readonly:true
select Status {
label:"Draft" value:"Draft" default:true
label:"Pending Approval" value:"PendingApproval"
label:"Active" value:"Active" sentiment:Positive
label:"Expired" value:"Expired" sentiment:Negative
label:"Terminated" value:"Terminated" sentiment:Negative
}
@layout
form {
create {
title:"Create Contract"
savebuttontext:"Save"
cancelbuttontext:"Cancel"
section {
title:"Contract Details"
subtitle:"Basic contract information"
row {
layout:6,6
fields ContractNumber,LeaseType
}
row {
layout:12
fields Tenant
}
row {
layout:6,6
fields Building,Unit
}
}
section {
title:"Term"
subtitle:"Contract duration"
row {
layout:6,6
fields StartDate,EndDate
}
row {
layout:6
fields Duration
}
}
section {
title:"Financial"
subtitle:"Payment terms"
row {
layout:6,6
fields MonthlyRent,AnnualRent
}
row {
layout:6
fields SecurityDeposit
}
}
section show:[$RecordId != null] {
title:"Status"
row {
layout:6
fields Status
}
}
}
list {
mobile {
fields ContractNumber,Tenant,MonthlyRent
}
desktop {
fields ContractNumber,Tenant,Building,Unit,StartDate,EndDate,MonthlyRent,Status
}
}
}