Skip to main content

Custom Values

Custom values allow you to extend entities with organization-specific properties without schema changes. They are the primary extensibility mechanism in CXTMS — use them to store data that doesn't fit the built-in entity fields.

CXTMS provides two complementary systems:

SystemPurposeScope
customValuesRuntime key-value dictionary on entitiesPer-entity instance — stores actual data
CustomFieldField metadata definitionsPer-organization — defines field names, types, and UI behavior

customValues is the storage layer — a flexible Dictionary<string, object?> persisted as JSONB in PostgreSQL. CustomField is the definition layer — it tells the UI what fields exist, their types, labels, and display rules.

Supported Entities

The following entities include a customValues property:

  • Order — customer references, project codes, service levels, incoterms
  • Job — consolidation data, vessel info, container types, ETD/ETA
  • Commodity — SKUs, lot numbers, serial numbers, hazmat flags
  • Contact — DOT numbers, industry codes, account managers, departments
  • Charge — rate workflow responses, billing metadata
  • OrderCommodity — sequence numbers, handling instructions
  • OrderEntity — extended contact details per order role

Working with Custom Values in Workflows

Reading custom values

Access custom values using dot notation in workflow expressions:

- task: Order/Get@1
name: getOrder
inputs:
organizationId: ${organizationId}
orderId: ${orderId}

# Access in subsequent steps:
# ${getOrder.result.customValues.customerPO}
# ${getOrder.result.customValues.projectCode}

Writing custom values

Use entity update tasks to set custom values. Values are merged with existing custom values — you only need to specify the keys you want to add or change.

- task: Order/Update@1
name: updateCustomValues
inputs:
organizationId: ${organizationId}
orderId: ${orderId}
order:
customValues:
customerPO: "PO-2025-ABC"
projectCode: "PROJ-789"
specialHandling: true
requiredDeliveryDate: "2025-02-15"
insuranceValue: 50000

Setting a value to null removes the key from the dictionary.

Creating entities with custom values

Custom values can be set at creation time:

- task: Order/Create@1
name: createOrder
inputs:
organizationId: ${organizationId}
order:
orderNumber: "ORD-2025-001"
customValues:
customerReference: "PO-98765"
specialInstructions: "Temperature controlled"
incoterms: "FOB"
serviceLevel: "Express"

Single value updates

Some entities support updating a single key without reading the entire dictionary:

# Job entity supports ChangeCustomValue for single-key updates
- task: Job/ChangeCustomValue@1
inputs:
organizationId: ${organizationId}
jobId: ${jobId}
key: "masterBL"
value: "MAEU1234567890"

Defining Custom Fields in App Modules

To give custom values structure in the UI, define them as fields in your App Module's entities section. This registers the fields with the platform so they appear in grids, forms, and filters.

entities:
- name: "ParcelShipment"
entityKind: Order
extension: true
displayName:
en-US: "Parcel Shipment"
fields:
- name: "trackingNumber"
displayName:
en-US: "Tracking Number"
fieldType: "text"
isCustomField: true
- name: "originCountry"
displayName:
en-US: "Origin Country"
fieldType: "Country"
isCustomField: true
props:
filterComponent: Countries/Select
allowOrderBy: false
allowFilter: false

Field types

Field TypeDescriptionExample Use
textString dataNames, descriptions, reference numbers
numberNumeric valuesQuantities, measurements, monetary amounts
dateDate/time valuesShip dates, deadlines, ETAs
booleanTrue/false valuesActive flags, hazmat indicators
listOptions/dropdownsStatus codes, categories
entityNameEntity referencesLinks to contacts, locations

Field props

PropDefaultDescription
showAsDisplay component for grid and form rendering
allowOrderBytrueWhether the field can be used for sorting
orderByPropertyAlternative property name for sorting
allowFiltertrueWhether the field can be used for filtering
filterByPropertyAlternative property name for filtering
filterFilter component definition (component, fieldName)
isInactivefalseDeactivate the field without removing it

Displaying Custom Values in DataGrids

Custom values can be displayed as columns in datagrid components using dot notation. Columns support inline editing with automatic persistence.

Basic column with formatting

columns:
- name: customValues.ETA
label:
en-US: ETA
showAs:
component: text
props:
value: "{{ format customValues.ETA L }}"

Inline-editable column

columns:
- name: customValues.ETA
label:
en-US: ETA
enableEdit: true
editor:
component: field
props:
type: datetime
onEdit:
- task: Order/Update@1
inputs:
organizationId: "{{number organizationId }}"
orderId: "{{number orderId }}"
values:
customValues:
ETA: "{{ changedValues }}"
onSuccess:
- notification:
message:
en-US: "ETA has been updated to {{ changedValues }}"
showAs:
component: text
props:
value: "{{ format customValues.ETA L }}"

Custom component editor

columns:
- name: customValues.returnLocation
label:
en-US: Return Location
enableEdit: true
editor:
component: TRTImport/Terminals/Select
onEdit:
- task: Order/Update@1
inputs:
organizationId: "{{number organizationId }}"
orderId: "{{number orderId }}"
values:
customValues:
returnLocation: "{{ changedValues }}"

Filtering Custom Values

Custom values support Lucene-style filtering in GraphQL queries.

Text matching

customValues.serviceLevel: Express
customValues.origin: "Shanghai*"
customValues.projectCode: PROJ-*

Existence check

customValues.insuranceValue: *

Numeric range

customValues.weight: [100 TO 500]
customValues.price: {0 TO *}

Date range

customValues.ETA: [2026-01-01 TO 2026-03-31]
customValues.pickupDate: {* TO 2026-03-23}

Range filters on JSONB fields use PostgreSQL casting for correct comparison semantics (numeric or timestamp), not string comparison.

For full filter syntax, see Filtering.

Sorting by Custom Values

Sort by custom values using dot notation in the orderBy parameter:

query {
orders(organizationId: 1, orderBy: "customValues.priority") {
items {
orderNumber
customValues
}
}
}

Prefix with - for descending order: orderBy: "-customValues.priority"

For full sorting syntax, see Sorting.

Best Practices

  • Use custom values for variable, non-critical properties — customer-specific references, project codes, industry-specific fields (DOT numbers, NAICS codes, SKUs, lot numbers)
  • Use CustomField definitions for UI structure — register fields in App Module entities so they appear in grids and forms with proper labels and types
  • Avoid custom values for data requiring complex queries — if you need indexing, joins, or frequent aggregation, consider a dedicated entity field instead
  • Use ChangeCustomValue for single-key updates where available (Job entity) to avoid reading the entire dictionary
  • Setting a value to null removes the key — use this to clean up stale properties
  • Custom values support complex types — arrays (["SN001", "SN002"]), nested objects, and mixed types are all valid