Skip to main content

Related Orders

CXTMS tracks relationships between orders through shared commodities. Two orders are related when they share any commodity on the same root-to-leaf path of the container tree — meaning one order's commodity is an ancestor, equal to, or descendant of a commodity owned by another order.

All related-order fields are available on the Order type and support optional filtering and sorting.

Fields

FieldReturnsDataLoader
allRelatedOrders[Order]vw_order_related_orders_v3 (organization-scoped)
relatedOrders[Order]Alias of allRelatedOrders
relatedOrderOrderFirst result only
relatedOrdersV3[Order]Compatibility alias of relatedOrders
relatedOrderV3OrderCompatibility alias of relatedOrder
Removed experimental fields

The temporary relatedOrdersV2 and relatedOrderV2 fields have been removed. The V3 aliases remain for production modules created during the rollout, but new configuration should use allRelatedOrders, relatedOrders, or relatedOrder.

Arguments

All five fields accept the same arguments:

ArgumentTypeRequiredDescription
filterStringNoLucene filter applied to the related orders at the database level
orderByStringNoSort expression (e.g. orderNumber asc, created desc). Defaults to orderNumber

relatedOrders and allRelatedOrders

Both fields return all orders related to the parent order. They use the same AllRelatedOrdersDataLoader and the same organization-scoped vw_order_related_orders_v3 relation used by property-path filtering and sorting. allRelatedOrders is also the preferred navigation name in new filterByProperty and orderByProperty configuration.

query {
getOrders(organizationId: 1, take: 5) {
items {
orderId
orderNumber
relatedOrders(filter: "orderType:Shipment", orderBy: "created desc") {
orderId
orderNumber
orderType
}
}
}
}

relatedOrder

Returns only the first related order matching the filter and sort criteria. Backed by the same DataLoader as relatedOrders; identical performance characteristics.

query {
getOrders(organizationId: 1, take: 10) {
items {
orderId
orderNumber
relatedOrder(orderBy: "created desc") {
orderId
orderNumber
created
}
}
}
}

relatedOrdersV3 and relatedOrderV3

These are compatibility aliases for relatedOrders and relatedOrder. All names now resolve pairs through vw_order_related_orders_v3. The view reads a trigger-maintained commodity-kinship table, so it does not walk the container tree for each request. Pair discovery and the final Order query are organization-scoped, preventing a commodity link that crosses organization boundaries from exposing another organization's orders.

The GraphQL resolver, filtering, and sorting all use this same view and therefore share one definition of "related." This also makes V3 paths usable before paging:

relatedOrdersV3[relatedOrder.orderType:BookingOrder].relatedOrder.trackingNumber

The view excludes draft related orders and has no container-depth limit. Commodity-tree changes maintain the kinship table through database triggers, and PostgreSQL can push the caller's filter or sort predicate into the view. This avoids the full-table recursive work performed by the legacy view while keeping list, filter, and sort results aligned.

relatedOrdersV3 returns every matching order. relatedOrderV3 returns the first result after applying filter and orderBy.

query {
getOrders(organizationId: 1, take: 5) {
items {
orderId
orderNumber
relatedOrdersV3(filter: "orderType:Shipment", orderBy: "created desc") {
orderId
orderNumber
orderType
}
}
}
}

DataLoader batching

All five fields share the same batching strategy. Requests within a single GraphQL operation that have identical (organizationId, filter, orderBy) arguments are grouped. Pair resolution reads the organization-scoped view for the whole batch in one query:

  1. Resolve (OrderId, RelatedOrderId) pairs for all batched orders.
  2. Group the pair-resolution results by (organizationId, filter, orderBy) and fetch the matching Order rows once per unique combination.
  3. Project Order → OrderGqlDto using AutoMapper and return the results to each caller.

This means fetching related orders for 50 orders in a list view costs the same as fetching them for 1 — as long as the filter and sort arguments are consistent.

Property-path filtering and sorting

The Order entity exposes both allRelatedOrders and relatedOrdersV3 navigations over the same view so existing module paths continue to work. Prefer the unversioned form:

allRelatedOrders[relatedOrder.orderType:BookingOrder].relatedOrder.trackingNumber