Selegic CRM Docs
ServerDynamic Objects

Schema Runtime

Entity discovery, validation caching, formula computation, and schema versioning.

Entity Discovery

When a request targets a dynamic object, the system determines if it's a "Static" (Prisma) or "Dynamic" model:

// Discovery flow
const isDynamic = !prisma[modelName];  // Check if not static Prisma model
if (isDynamic) {
  const fields = await EntityMetadataService.getFields(entity, tenantId);
  // Return dynamic field definitions
}

Field Metadata

Each dynamic entity has associated Field records containing:

  • name: Field API name
  • type: Field type (TEXT, NUMBER, LOOKUP, etc.)
  • label: UI label
  • required: Whether field is mandatory
  • defaultValue: Default value expression
  • options: Picklist options array

Validation Caching

Generating validation schemas is expensive. The ValidationService caches generated AJV validators:

// Double-key cache: (tenantId, entityName)
const cacheKey = `${tenantId}:${entityName}`;
const validator = cache.get(cacheKey) ?? generateValidator(fields);

Cache Invalidation

Caches must be invalidated when:

  • An Entity definition is modified
  • A Field is added, removed, or updated
  • A tenant's metadata is reset

This is handled automatically via afterSuccess hooks on Entity and Field CRUD models.

Verification Endpoint

To debug validation issues:

# Get current schema as seen by server
GET /api/v1/metadata/fields?entity=Invoice

Formula Runtime

Formula fields are computed at runtime during the execution phase:

// Formula evaluation
for (const field of formulaFields) {
  const computed = evaluateFormula(field.formula, recordData);
  recordData[field.name] = computed;
}

Supported Formula Functions

  • Mathematical: SUM, AVG, MIN, MAX, ROUND
  • Logical: IF, AND, OR, NOT
  • Text: CONCAT, LEFT, RIGHT, LEN
  • Date: TODAY, NOW, DATEADD
  • Lookup: LOOKUP

Formula Context

Formulas have access to:

  • Current record fields
  • Related record fields (via LOOKUP)
  • System values ($USER, $TODAY)

Schema Versioning

Each dynamic entity maintains a schema version that increments on field changes:

-- Entity table has version column
SELECT version FROM entity WHERE name = 'Invoice'; -- 42

-- Field changes increment version
UPDATE entity SET version = version + 1 WHERE name = 'Invoice';

The client uses this version for cache invalidation and schema comparison.

On this page