Question

We mark nearly all items as "dirty" since we need all products from one product family calculated first before setting a family price for all of them. But the first and second pass calculate different fields. Yet I need the results from the first pass in the second pass. My question is: is there a way not to calculate those again but refer to their results from the first pass without using api.global?

This topic Multi-pass Calculation of a Price List or LPG does not fully cover this case.

Answer

It's not so pretty, but we've used this:

Boolean isSecondPass(){
  return ((String)api.currentContext()).contains("update")
}
Object getFirstPassResult(String elementName){
  api.currentItem().calculationResults.find { it.resultName == elementName }.result
}
if(isSecondPass()){
  return getFirstPassResult("ThisElementName")
}

Doesn't api.currentItem do the trick? I got the understanding that results from the 1st pass are persisted.

The results from the 1st pass are persisted to a PGI. A PGI item access is the best way when accessing another SKU from the first pass.

api.currentItem() stores only elements which are marked as output (so this means max 100 elements). We use a lookup from PGI:

def getCurrentCalculationResultsPGI(sku) {
  def PGI = api.find("PGI", 0, 1, null, Filter.equal("sku", sku))
  if (PGI) {
    def results = PGI[0].allCalculationResults
    return getCalculationResults(results)
  }
  return [:]
}
def getCalculationResults(calculationResults) {
  if (calculationResults) {
    return calculationResults.collectEntries{ [(it.resultName) : it.result] }
  }
  return [:]
}

Note: Use collectEntries only when it is needed – it has serious performance impact. It is handy to use when you can load only some attributes which ideally have fixed attribute allocation.