Helper Functions Reference
Programmatic helper functions for order management, hierarchy operations, validation, and compensation - reusable across manual operations and pipeline automation.
Helper Functions
Complete set of helper functions for order operations:
- Hierarchy Management - Create children, update ancestors, query descendants
- Lifecycle Validation - Check completion/cancellation eligibility
- Process-Stage Validation - Verify stage transitions and flows
- Compensation Execution - Rollback, cleanup, and recovery
- Utility Functions - Common operations and helpers
- Shared by All - Used by manual routes, pipelines, and custom code
Integration: Import from #lib/order/helpers and #lib/order/descendants
Overview
Helper functions provide the core business logic for the order system. They're framework-agnostic - usable in API routes, pipeline stages, background jobs, or custom applications.
Why Helper Functions?
Consistency:
- Same validation logic everywhere
- Manual operations use same rules as pipelines
- No duplicate code
Reusability:
- Use in routes, pipelines, scripts
- Compose complex operations
- Build on validated primitives
Maintainability:
- Update logic in one place
- All consumers get fixes
- Clear separation of concerns
Hierarchy Management
Located in: #lib/order/helpers and #lib/order/descendants
createChildOrder
Create a child order with full hierarchy and composition metadata.
Function Signature:
async function createChildOrder(
params: CreateChildOrderParams,
db: Db,
context: Context
): Promise<CreateChildOrderResult>Parameters:
interface CreateChildOrderParams {
// Parent info
parentOrder: BaseOrder
parentOrderType: string
// Child info
childOrderType: string
childOrderId: string
childOrderReference: string
lspOrderType: LSPOrderType
processor: Context
carrierTrackingNumber?: string
// Composition metadata
creationReason: 'LIFECYCLE_REQUIREMENT' | 'PIPELINE_STAGE' |
'AUTOMATIC_RULE' | 'CONDITIONAL_TRIGGER' |
'EXCEPTION_HANDLING' | 'MANUAL_REQUEST' |
'COMPENSATION' | 'SPLIT_ORDER'
created: ActionRecord
relationship: {
type: 'MANDATORY' | 'OPTIONAL' | 'CONDITIONAL'
canBlockParent: boolean
sequence?: number
dependencies?: string[]
}
metadata?: {
trigger?: string
notes?: string
tags?: string[]
}
}Returns:
interface CreateChildOrderResult {
hierarchy: OrderHierarchy
tracking: OrderTracking
error?: string
}Example Usage:
import { createChildOrder } from '#lib/order/helpers'
const result = await createChildOrder({
parentOrder: outboundOrder,
parentOrderType: 'OutboundOrder',
childOrderType: 'InternalOrder',
childOrderId: 'task-123',
childOrderReference: 'PICK-001',
lspOrderType: 'InternalOrder',
processor: context,
creationReason: 'PIPELINE_STAGE',
created: {
by: { type: 'PIPELINE', id: 'pipe-001', name: 'Outbound Pipeline' },
at: { timestamp: Date.now(), timezone: 'UTC' }
},
relationship: {
type: 'MANDATORY',
canBlockParent: true
}
}, db, context)
if (result.error) {
console.error(result.error)
// "Invalid order relationship: InternalOrder cannot spawn OutboundOrder"
} else {
// Use result.hierarchy and result.tracking for new child
}What It Does:
- ✅ Validates parent-child relationship
- ✅ Validates hierarchy depth
- ✅ Generates hierarchical tracking number
- ✅ Builds child hierarchy object
- ✅ Adds child to parent's childOrders array
- ✅ Updates all ancestors' descendant lists
- ✅ Returns hierarchy and tracking for child
addChildToParent
Add a child record to parent's childOrders array.
Function Signature:
async function addChildToParent(
db: Db,
context: Context,
parentReference: string,
childRecord: ChildOrderRecord
): Promise<void>Example Usage:
import { addChildToParent } from '#lib/order/descendants'
await addChildToParent(
db,
context,
'OUT-001',
{
orderId: 'task-123',
orderReference: 'PICK-001',
orderType: 'InternalOrder',
lspOrderType: 'InternalOrder',
processor: context,
status: 'PENDING',
created: { by: { type: 'USER', id: 'OPR-123' }, at: {...} },
creationReason: 'MANUAL_REQUEST',
parentStateAtCreation: { process: 'FULFILLMENT', stage: 'ALLOCATION', status: 'IN_PROGRESS' },
relationship: { type: 'MANDATORY', canBlockParent: true }
}
)updateAncestorsDescendants
Update all ancestors with new/removed descendant.
Function Signature:
async function updateAncestorsDescendants(
db: Db,
context: Context,
parentOrder: BaseOrder,
action: 'ADD' | 'REMOVE',
descendantReference: string,
descendantType: string
): Promise<void>Example Usage:
import { updateAncestorsDescendants } from '#lib/order/descendants'
// Add descendant to all ancestors
await updateAncestorsDescendants(
db,
context,
parentOrder,
'ADD',
'PICK-001',
'InternalOrder'
)
// Updates:
// - parent.allDescendantReferences += 'PICK-001'
// - grandparent.allDescendantReferences += 'PICK-001'
// - root.allDescendantReferences += 'PICK-001'
// - All get descendantCount incremented
// - All get descendantsByType.InternalOrder += 'PICK-001'getAllDescendants
Get all descendant references (single query).
Function Signature:
async function getAllDescendants(
db: Db,
context: Context,
orderReference: string
): Promise<string[]>Example Usage:
import { getAllDescendants } from '#lib/order/descendants'
const descendants = await getAllDescendants(db, context, 'OUT-001')
// Returns: ['PICK-001', 'PACK-001', 'SHIP-001']getAllDescendantOrders
Get all descendant orders (bulk fetch).
Function Signature:
async function getAllDescendantOrders(
db: Db,
context: Context,
orderReference: string
): Promise<BaseOrder[]>Example Usage:
import { getAllDescendantOrders } from '#lib/order/descendants'
const orders = await getAllDescendantOrders(db, context, 'OUT-001')
// Returns: Full order objects for all descendantsgetDescendantsByType
Get descendants filtered by order type.
Function Signature:
async function getDescendantsByType(
db: Db,
context: Context,
orderReference: string,
orderType: string
): Promise<string[]>Example Usage:
import { getDescendantsByType } from '#lib/order/descendants'
const tasks = await getDescendantsByType(db, context, 'OUT-001', 'InternalOrder')
// Returns: ['PICK-001', 'PACK-001']
const shipping = await getDescendantsByType(db, context, 'OUT-001', 'ShippingOrder')
// Returns: ['SHIP-001']updateParentChildRecord
Update child record in parent's childOrders array.
Function Signature:
async function updateParentChildRecord(
parentReference: string,
childReference: string,
newStatus: string,
db: Db,
context: Context
): Promise<void>Example Usage:
import { updateParentChildRecord } from '#lib/order/descendants'
// Child completed - update parent's record
await updateParentChildRecord(
'OUT-001', // Parent
'PICK-001', // Child
'COMPLETED', // New status
db,
context
)
// Parent's childOrders array updated:
// { ref: 'PICK-001', status: 'COMPLETED', ... }Lifecycle Validation
Located in: #lib/order/helpers
canCompleteOrder
Check if order can be completed.
Function Signature:
async function canCompleteOrder(
order: BaseOrder,
orderType: string,
database: any,
context: Context
): Promise<OrderCompletionValidation>Returns:
interface OrderCompletionValidation {
allowed: boolean
reason?: string
blockers?: Array<{
reference: string
type: string
currentStatus: string
requiredStatuses?: string[]
}>
}Example Usage:
import { canCompleteOrder } from '#lib/order/helpers'
const validation = await canCompleteOrder(
order,
'OutboundOrder',
db,
context
)
if (!validation.allowed) {
console.error(validation.reason)
console.log('Blockers:', validation.blockers)
// Cannot complete: 2 child orders not in required status
// Blockers: [{ ref: 'PICK-001', status: 'IN_PROGRESS', ... }]
} else {
// Safe to complete
await db.updateOne({ reference }, { $set: { status: 'COMPLETED' } })
}canCancelOrder
Check if order can be cancelled.
Function Signature:
async function canCancelOrder(
order: BaseOrder,
orderType: string,
database: any,
context: Context
): Promise<OrderCancellationValidation>Returns:
interface OrderCancellationValidation {
allowed: boolean
reason?: string
childAction?: 'CASCADE_CANCEL' | 'ORPHAN' | 'COMPLETE_FIRST' | 'SUSPEND'
activeChildren?: Array<{
reference: string
type: string
status: string
}>
}Example Usage:
import { canCancelOrder } from '#lib/order/helpers'
const validation = await canCancelOrder(
order,
'OutboundOrder',
db,
context
)
if (!validation.allowed) {
console.error(validation.reason)
console.log('Child action:', validation.childAction)
// Cannot cancel: 2 active child orders in progress
// Child action: CASCADE_CANCEL
} else {
// Cancel order and execute child action
await db.updateOne({ reference }, { $set: { status: 'CANCELLED' } })
await cascadeCancellation(order, validation.childAction, db, context)
}shouldAutoCompleteParent
Check if child completion should trigger parent auto-completion.
Function Signature:
async function shouldAutoCompleteParent(
childOrder: BaseOrder,
childOrderType: string,
parentOrder: BaseOrder,
parentOrderType: string,
database: any,
context: Context
): Promise<boolean>Example Usage:
import { shouldAutoCompleteParent } from '#lib/order/helpers'
// Child just completed
await db.updateOne({ reference: childRef }, { $set: { status: 'COMPLETED' } })
// Check if parent should auto-complete
const shouldComplete = await shouldAutoCompleteParent(
childOrder,
'InternalOrder',
parentOrder,
'OutboundOrder',
db,
context
)
if (shouldComplete) {
// All siblings complete → auto-complete parent
await db.updateOne(
{ reference: parentOrder.reference },
{ $set: { status: 'COMPLETED' } }
)
}getLifecyclePolicy
Get lifecycle policy for an order type.
Function Signature:
function getLifecyclePolicy(orderType: string): OrderLifecyclePolicy | nullExample Usage:
import { getLifecyclePolicy } from '#lib/order/helpers'
const policy = getLifecyclePolicy('OutboundOrder')
if (policy) {
console.log('Requires all children complete:', policy.parentCompletion.requireAllChildrenComplete)
console.log('Child action on cancel:', policy.parentCancellation.childAction)
}Process-Stage Validation
Located in: #lib/order/helpers
isValidStageForProcess
Check if a stage is valid for a process.
Function Signature:
function isValidStageForProcess(
orderType: string,
process: string,
stage: string
): StageValidationResultReturns:
interface StageValidationResult {
valid: boolean
reason?: string
allowedStages?: string[]
validNextStages?: string[]
}Example Usage:
import { isValidStageForProcess } from '#lib/order/helpers'
const validation = isValidStageForProcess(
'OutboundOrder',
'FULFILLMENT',
'PICKING'
)
if (!validation.valid) {
console.error(validation.reason)
console.log('Allowed stages:', validation.allowedStages)
} else {
// Stage is valid for this process
}isValidStageTransition
Check if a stage transition is allowed.
Function Signature:
function isValidStageTransition(
orderType: string,
process: string,
fromStage: string,
toStage: string
): StageValidationResultExample Usage:
import { isValidStageTransition } from '#lib/order/helpers'
const validation = isValidStageTransition(
'OutboundOrder',
'FULFILLMENT',
'PICKING',
'PACKING'
)
if (!validation.valid) {
console.error(validation.reason)
console.log('Valid next stages:', validation.validNextStages)
// Cannot transition from PICKING to SHIPPING
// Valid next stages: ['PACKING']
} else {
// Transition is valid
await db.updateOne({ reference }, { $set: { 'flow.stage': 'PACKING' } })
}getValidNextStages
Get allowed next stages from current stage.
Function Signature:
function getValidNextStages(
orderType: string,
process: string,
currentStage: string
): string[]Example Usage:
import { getValidNextStages } from '#lib/order/helpers'
const nextStages = getValidNextStages(
'OutboundOrder',
'FULFILLMENT',
'PICKING'
)
console.log('Next stages:', nextStages)
// ['PACKING']
// Use in UI to show operators valid optionsgetAllowedStagesForProcess
Get all valid stages for a process.
Function Signature:
function getAllowedStagesForProcess(
orderType: string,
process: string
): string[]Example Usage:
import { getAllowedStagesForProcess } from '#lib/order/helpers'
const stages = getAllowedStagesForProcess(
'OutboundOrder',
'FULFILLMENT'
)
console.log('Allowed stages:', stages)
// ['ALLOCATION', 'PICKING', 'PACKING', 'SHIPPING', 'DELIVERY']isTerminalStage
Check if a stage is terminal (no outgoing transitions).
Function Signature:
function isTerminalStage(
orderType: string,
process: string,
stage: string
): booleanExample Usage:
import { isTerminalStage } from '#lib/order/helpers'
const isTerminal = isTerminalStage(
'OutboundOrder',
'FULFILLMENT',
'DELIVERY'
)
if (isTerminal) {
// No more stages → auto-complete order
await db.updateOne({ reference }, { $set: { status: 'COMPLETED' } })
}Compensation Functions
Located in: #lib/order/helpers
compensateOnParentFailure
Execute compensation when parent fails.
Function Signature:
async function compensateOnParentFailure(
parentOrder: BaseOrder,
orderType: string,
database: any,
context: Context
): Promise<CompensationResult>Returns:
interface CompensationResult {
success: boolean
compensatedOrders: string[]
failedCompensations: Array<{
orderReference: string
error: string
}>
strategy: CompensationAction
}Example Usage:
import { compensateOnParentFailure } from '#lib/order/helpers'
// Parent failed - execute compensation
const compensation = await compensateOnParentFailure(
order,
'OutboundOrder',
db,
context
)
console.log('Strategy:', compensation.strategy)
console.log('Compensated orders:', compensation.compensatedOrders)
console.log('Failures:', compensation.failedCompensations)
if (!compensation.success) {
// Some compensations failed - alert operators
await alertOperators({ failures: compensation.failedCompensations })
}compensateOnChildFailure
Execute compensation when child fails.
Function Signature:
async function compensateOnChildFailure(
parentOrder: BaseOrder,
failedChild: { reference: string; type: string },
orderType: string,
database: any,
context: Context
): Promise<CompensationResult>Example Usage:
import { compensateOnChildFailure } from '#lib/order/helpers'
// Child failed - compensate parent and siblings
const compensation = await compensateOnChildFailure(
parentOrder,
{ reference: 'PICK-001', type: 'InternalOrder' },
'OutboundOrder',
db,
context
)
console.log('Compensated:', compensation.compensatedOrders)
// ['PACK-001', 'SHIP-001'] - siblings cancelledcascadeCancellation
Execute cascading cancellation.
Function Signature:
async function cascadeCancellation(
parentOrder: BaseOrder,
childAction: 'CASCADE_CANCEL' | 'ORPHAN' | 'COMPLETE_FIRST' | 'SUSPEND',
database: any,
context: Context
): Promise<{ updated: number; errors: any[] }>Example Usage:
import { cascadeCancellation } from '#lib/order/helpers'
// Cancel order with cascade
const result = await cascadeCancellation(
order,
'CASCADE_CANCEL',
db,
context
)
console.log('Children updated:', result.updated)
console.log('Errors:', result.errors)getCompensationStrategy
Get compensation strategy for an order type.
Function Signature:
function getCompensationStrategy(orderType: string): CompensationStrategy | nullExample Usage:
import { getCompensationStrategy } from '#lib/order/helpers'
const strategy = getCompensationStrategy('OutboundOrder')
if (strategy) {
console.log('On child failure:', strategy.onChildFailure.action)
console.log('On parent failure:', strategy.onParentFailure.action)
}Usage Patterns
Manual API Route
import {
canCompleteOrder,
isValidStageTransition,
updateParentChildRecord
} from '#lib/order/helpers'
// Complete order route
app.patch('/:reference/complete', async (req, rep) => {
const order = await db.findOne({ reference: req.params.reference })
// Validate completion
const validation = await canCompleteOrder(order, 'OutboundOrder', db, context)
if (!validation.allowed) {
return rep.status(400).send({
error: true,
reason: validation.reason,
blockers: validation.blockers
})
}
// Complete order
await db.updateOne({ reference }, { $set: { status: 'COMPLETED' } })
// Notify parent
if (order.hierarchy?.parentOrderReference) {
await updateParentChildRecord(
order.hierarchy.parentOrderReference,
reference,
'COMPLETED',
db,
context
)
}
return rep.send({ error: false, message: 'Order completed' })
})Pipeline Stage Handler
import {
isValidStageTransition,
compensateOnParentFailure
} from '#lib/order/helpers'
// Pipeline transition handler
async function handleSuccessTransition(stage, execution) {
if (stage.nextStage) {
// Validate stage transition
const validation = isValidStageTransition(
execution.orderType,
order.flow.process,
order.flow.stage,
stage.nextStage
)
if (!validation.valid) {
// Invalid transition - fail pipeline
stage.status = 'FAILED'
stage.errors.push({ message: validation.reason })
// Execute compensation
const compensation = await compensateOnParentFailure(
order,
execution.orderType,
db,
context
)
return
}
// Valid - update stage
await db.updateOne({ reference }, { $set: { 'flow.stage': stage.nextStage } })
}
}Custom Background Job
import {
getAllDescendants,
canCompleteOrder
} from '#lib/order/helpers'
// Auto-complete stale orders
async function autoCompleteStaleOrders() {
const staleOrders = await db.find({
status: 'IN_PROGRESS',
'updated.at.timestamp': { $lt: Date.now() - 86400000 } // 24h old
}).toArray()
for (const order of staleOrders) {
// Check if can complete
const validation = await canCompleteOrder(order, order.orderType, db, context)
if (validation.allowed) {
// Complete order
await db.updateOne(
{ reference: order.reference },
{ $set: { status: 'COMPLETED', completedBy: 'AUTO_COMPLETE_JOB' } }
)
console.log(`Auto-completed ${order.reference}`)
}
}
}Best Practices
Always Validate
✅ Validate before operations:
const validation = await canCompleteOrder(order, type, db, context)
if (!validation.allowed) {
return { error: true, reason: validation.reason }
}
// Proceed with operation❌ Don't skip validation:
// Dangerous - no validation
await db.updateOne({ ref }, { status: 'COMPLETED' })Handle Errors
✅ Check for errors:
const result = await createChildOrder(params, db, context)
if (result.error) {
console.error(result.error)
return { error: true, message: result.error }
}Use Appropriate Functions
✅ Use specific functions:
// For descendants
const descendants = await getAllDescendants(db, context, ref)
// For validation
const validation = await canCompleteOrder(order, type, db, context)
// For compensation
const result = await compensateOnParentFailure(order, type, db, context)Compose Operations
✅ Build complex flows:
// 1. Create child
const child = await createChildOrder(params, db, context)
// 2. Validate stage transition
const validation = isValidStageTransition(type, process, from, to)
// 3. Check completion eligibility
const canComplete = await canCompleteOrder(order, type, db, context)
// 4. Execute compensation if needed
const compensation = await compensateOnParentFailure(order, type, db, context)Next Steps
Related Documentation:

