When the price of one product depends on the price of another product within the same price list (or LPG) then you need to calculate the price list in several rounds (= passes).

From the technical perspective:

The calculation of the price list line items will then run in several passes:

(info) The current item is only dirty-recalculated when it is the only dirty item. If there are more dirty items resulting from the initial calculation, all dirty items including the initial item are calculated in the same background process. 


def resultPrice

if (isLeader()) {

    /* result price doesn't have dependency on another product => calculate the price right away */
    resultPrice = calculateLeaderPrice()

} else {

    /* result price is derived from the price of the other (= leading) product */
    if (api.getIterationNumber() == 0) {

        /* in the 1st pass the leader product is not yet calculated, so mark this item to be calculated in the next pass */
        api.markItemDirty()

        /* do not calculate remaining elements for a better performance */
        api.abortCalculation()

    } else {

        /* in the 2nd pass, the leader product is calculated already */
        def leaderPrice = api.currentContext(leaderSku)?.ResultPrice

        resultPrice = calculateFollowerPrice(leaderPrice)

    }
}

return resultPrice

Useful Functions and Properties

You can also suppress autoApprove when an item is dirty by setting an advanced config property on a partition:

skipAutoApproveOnDirtyPGI = true


See also How can I trigger the 2nd pass on a dependent line item?