| name | generate-domain-model |
| description | Creating Mendix Domain Model MDL Scripts — entities, associations, enumerations, view entities, indexes, generalization, event handlers, ALTER ENTITY, positioning, and documentation |
| compatibility | opencode |
MDL domain model author — generate well-documented, correctly positioned entity structures with associations, enumerations, and view entities.
> Full reference for generating Mendix domain model scripts. Covers modules, enumerations, persistent/non-persistent/view entities, indexes, generalization, auditing attributes, event handlers, associations, calculated attributes, ALTER ENTITY, and positioning guidelines.
Load when:
- User asks to create a domain model for a specific use case
- User wants to generate entities, associations, and enumerations
- User requests a complete e-commerce, HR, CRM, or other business domain model
- Needing ALTER ENTITY for incremental modifications
<critical_rules>
- All CREATE statements MUST have JavaDoc-style documentation (
/** ... */)
- All entities MUST have
@position(x, y) annotation
- EXTENDS goes BEFORE the opening parenthesis —
create persistent entity Module.Photo extends System.Image (...)
- INDEX syntax goes AFTER the closing parenthesis, with NO comma before
- Non-persistent entities cannot have validation rules (
not null error, unique error) — only default values
- Large files (300+ lines) MUST use
-- MARK: Section Name comments (at least 3 for 300+ lines)
- Always quote all identifiers with double quotes to avoid reserved keyword conflicts
</critical_rules>
<module_creation>
create module Finance;
</module_creation>
<mark_comments>
Use -- MARK: Section Name comments for navigation in large files:
</mark_comments>
create enumeration Module.TransactionType (
INCOME 'Income',
EXPENSE 'Expense'
);
Persistent Entity
@position(100, 100)
create persistent entity Module.EntityName (
Id: long not null error 'ID is required' unique error 'ID must be unique',
attributename: string(200) not null error 'Attribute name is required',
Amount: decimal,
CreationDate: date,
IsActive: boolean not null error 'IsActive flag is required' default true,
status: enumeration(Module.StatusEnum) not null error 'Status is required'
);
Entity Indexes
INDEX syntax goes AFTER closing parenthesis, NO comma before first INDEX:
create persistent entity Module.Transaction (
TransactionDate: datetime not null,
status: enumeration(Module.Status) not null,
Amount: decimal not null,
IsRecurring: boolean default false
)
index (TransactionDate desc)
index (status, TransactionDate)
index (IsRecurring);
Entity Generalization (EXTENDS)
create persistent entity Module.ProductPhoto extends System.Image (
PhotoCaption: string(200),
SortOrder: integer default 0
);
create persistent entity Module.Attachment extends System.FileDocument (
AttachmentDescription: string(500)
);
create persistent entity Module.Photo (PhotoCaption: string(200)) extends System.Image;
System Attributes (Auditing)
create persistent entity Sales.Order (
OrderNumber: autonumber,
TotalAmount: decimal not null,
status: enumeration(Sales.OrderStatus) not null,
owner: autoowner,
ChangedBy: autochangedby,
CreatedDate: autocreateddate,
ChangedDate: autochangeddate
);
| Pseudo-Type | System Attribute | Set When |
|---|
autoowner | System.owner (→ System.User) | Object created |
autochangedby | System.changedBy (→ System.User) | Every commit |
autocreateddate | CreatedDate (DateTime) | Object created |
autochangeddate | ChangedDate (DateTime) | Every commit |
Non-Persistent Entity
Cannot have validation rules (not null error, unique error):
@position(200, 100)
create non-persistent entity Module.TemporaryData (
SessionId: string(100),
data: string(1000),
IsActive: boolean default false
);
View Entity (with OQL)
@position(300, 500)
create view entity Module.ViewName (
Attribute1: type,
Attribute2: type
) as (
select
e.Id as Id,
e.Name as Name,
e.Amount as Amount
from Module.Entity as e
where e.IsActive = true
);
Enumeration Comparisons in OQL: Use the enumeration value (identifier), not the caption:
where e.Status != 'CANCELLED'
where e.Status != 'Cancelled'
Entity Event Handlers
create persistent entity Sales.Order (
Total: decimal,
status: string(50)
)
on before commit call Sales.ACT_ValidateOrder raise error
on after create call Sales.ACT_InitDefaults;
alter entity Sales.Order
add event handler on before delete call Sales.ACT_CheckCanDelete raise error;
alter entity Sales.Order
drop event handler on before commit;
Calculated Attributes
Only supported on persistent entities:
@position(100, 100)
create persistent entity Module.OrderLine (
UnitPrice: decimal not null,
Quantity: integer not null,
TotalPrice: decimal calculated by Module.CalcTotalPrice
);
<data_types>
| Type | Example | Description |
|---|
string(length) | string(200) | Text field with max length |
integer | integer | 32-bit integer |
long | long | 64-bit integer (use for IDs) |
decimal | decimal | Decimal number |
boolean | boolean | True/false (auto-defaults to false) |
datetime | datetime | Date and time |
date | date | Date only |
binary | binary | Binary data |
autonumber | autonumber default 1 | Auto-incrementing number |
enumeration(Module.Enum) | enumeration(Shop.Status) | Enumeration reference |
</data_types>
CRITICAL: Association Directionality
Associations are defined FROM the entity that contains the foreign key TO the entity that is referenced.
create association Finance.Transaction_Account
from Finance.Transaction to Finance.Account
type reference;
create association Sales.Order_Customer
from Sales.Order to Sales.Customer
type reference;
create association Sales.Order_Products
from Sales.Order to Sales.Product
type ReferenceSet
owner both;
create association Module.Category_ParentCategory
from Module.Category to Module.Category
type reference
owner default;
Full Syntax:
create association Module.EntityWithFK_ReferencedEntity
from Module.EntityWithFK to Module.ReferencedEntity
type reference
owner default
delete_behavior DELETE_BUT_KEEP_REFERENCES
comment 'Additional documentation';
Delete Behaviors: DELETE_AND_REFERENCES, DELETE_BUT_KEEP_REFERENCES, DELETE_IF_NO_REFERENCES, cascade, prevent
Naming Convention: {FromEntity}_{ToEntity} (e.g., Order_Customer, Transaction_Account)
<alter_entity>
alter entity Module.Customer
add attribute PhoneNumber: string(20);
alter entity Module.Order
add attribute VATRate: decimal
add attribute VATAmount: decimal;
alter entity Module.Order
rename attribute CreatedDate to OrderDate;
alter entity Module.Product
drop attribute LegacyCode;
alter entity Module.Customer
modify attribute Address: string(500);
alter entity Module.Customer
add index idx_email (Email asc);
alter entity Module.Customer
set position (100, 200);
Supported operations: ADD ATTRIBUTE, RENAME ATTRIBUTE, MODIFY ATTRIBUTE, DROP ATTRIBUTE, SET DOCUMENTATION, SET COMMENT, ADD INDEX, DROP INDEX, SET POSITION.
</alter_entity>
<entity_positioning>
Layout rules for readable domain models:
- Horizontal spacing: 350px between columns (x = 50, 400, 750, 1100, ...)
- Vertical spacing: calculate per-column:
y = previous_y + 50 + (previous_entity_attribute_count * 20)
- Entity header is ~40px, each attribute adds ~20px of height, plus ~50px padding
- Place related entities in the same column or adjacent columns so associations are short
@position(50, 50)
create persistent entity Module.Customer (...);
@position(400, 50)
create persistent entity Module.Address (...);
@position(50, 250)
create persistent entity Module.Order (...);
</entity_positioning>
<script_structure>
create enumeration Module.Enum1 (...);
create persistent entity Module.Entity1 (...);
create view entity Module.View1 as ...;
create association Module.Assoc1 ...;
</script_structure>
<output_rules>Output MDL code only in code blocks. Keep explanations concise.</output_rules>