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()