Transition Condition for Checking a Hard Point of No Return
The following XQuery can be used to check whether a hard point of no return has been reached, so that an amendment can be rejected if it is received after a hard point of no return. This XQuery checks to see whether there have been any revisions to significant data for order items that have reached a hard point of no return. Business considerations will determine what state/transition combinations will need to check for the point of no return, but at a minimum it should be defined in the In Progress state for the Submit Amendment transition.
To use this XQuery, follow the standard procedure for updating the lifecycle policy, creating a new transition condition and using the XQuery below in the Expression box for that condition. See "Configuring Order Lifecycle Policies" for more information about updating the lifecycle policy.
declare variable $PONR_NOT_YET := "NOT YET"; (: Checks for Hard Point Of No Return, return = true means no PONR has been reached. Raise an error if PONR has been reached. :) declare function local:allowRevision( $taskData as element()) as xs:boolean { let $rootData := $taskData/_root let $changes := $taskData/RevisionPerspective/Changes return if (fn:exists($rootData) and fn:exists($changes)) then ( let $changedOrderItems as element()* := local:getChangedOrderItems($rootData, $changes) let $revisionOrderItemsPastHardPONR as xs:string* := for $orderItem in $changedOrderItems return local:getOrderItemsPastHardPONR($orderItem) return fn:not(fn:exists($revisionOrderItemsPastHardPONR))) else fn:true() }; declare function local:getChangedOrderItems( $root as element(), $changes as element()) as element()* { let $indices := local:getOrderItemIndicesForChecking($changes) let $distinctIndicies := fn:distinct-values($indices) for $index in $distinctIndicies return local:getOrderItem($root, $index) }; declare function local:getOrderItemIndicesForChecking( $changes as element()) as xs:string* { for $change in $changes/*[@significant = "true"] return local:getOrderItemIndex($change) }; declare function local:getOrderItemIndex( $changeNode as element()) as xs:string* { let $changeType := local-name($changeNode) let $tokens := fn:tokenize($changeNode/@path, "/") let $t1 := $tokens[position() = 2] let $t2 := $tokens[position() = 3] let $t3 := $tokens[position() = 4] let $t4 := $tokens[position() = 5] return if (fn:starts-with($t1, "ControlData") and fn:starts-with($t2, "Functions")) then (: /ControlData/Functions/*Function/orderItem/... :) local:getOrderItemIndexInFunction( fn:root($changeNode)/GetOrder.Response/_root, (: Functions/@index, if exists :) fn:substring-before(fn:substring-after($t2,"'"), "'"), (: e.g. SyncCustomerFunction/@index :) fn:substring-before(fn:substring-after($t3,"'"), "'"), (: e.g. orderItem/@index :) fn:substring-before(fn:substring-after($t4,"'"), "'")) else "" }; declare function local:getOrderItemIndexInFunction( $root as element(), $functionsIndex as xs:string, $functionIndex as xs:string, $orderItemIndex as xs:string) as xs:string* { if (fn:boolean($functionsIndex)) then $root/ControlData/Functions[@index = $functionsIndex]/*[@index = $functionIndex]/orderItem[@index = $orderItemIndex]/orderItemRef/@referencedIndex else $root/ControlData/Functions/*[@index = $functionIndex]/orderItem[@index = $orderItemIndex]/orderItemRef/@referencedIndex }; declare function local:getOrderItem( $root as element(), $orderItemIndex as xs:string) as element()* { $root/ControlData/OrderItem[@index = $orderItemIndex] }; declare function local:getOrderItemsPastHardPONR( $orderItem as element()) as xs:string* { let $lineId as xs:string := local:getLineId($orderItem) let $pointOfNoReturn as xs:string := local:getPointOfNoReturn($orderItem) let $isHardPONRReached := if ($pointOfNoReturn = "HARD") then true() else false() return if ($isHardPONRReached) then $lineId else () }; declare function local:getLineId( $orderItem as element()) as xs:string { fn:normalize-space($orderItem/LineID/text()) }; declare function local:getPointOfNoReturn( $orderItem as element()) as xs:string { let $ponrData := fn:normalize-space($orderItem/PoNR/text()) let $ponrCode := if (fn:empty($ponrData)) then $PONR_NOT_YET else ( let $lastPonrValue := fn:normalize-space($orderItem/PoNR[last()]/text()) return (: We are looking for strings with either [xxxx]xxxx or xxxx format. Return what is in the [] or the whole string if no brackets. :) let $hard1 := fn:tokenize($lastPonrValue, "\[|\]") return fn:concat( $hard1[1] , $hard1[2] ) ) return $ponrCode }; (: Detect false revision order. return = true means there are significant data changes in the revision order :) declare function local:doSignificantChangesExist( $taskData as element()) as xs:boolean { let $dataChanges := $taskData/RevisionPerspective/Changes/*[@significant='true'] return if (fn:exists($dataChanges)) then true() else false() }; (: Only do the complex calculation for a valid revision.:) let $taskData := fn:root(.)/GetOrder.Response let $isValidRevision := local:doSignificantChangesExist($taskData) return if ($isValidRevision) then local:allowRevision($taskData) else fn:true()