[SalesForce] FFLIB Unit of work. how to register a relationship on both new and existing record

I have been trying to use the FFLIB enterprise service layer module to both insert a new record and update an existing record while registering relationships between both but I am unable to update the old record, other fields update on the record so I assume its got to do with either the registering of the relationship itself, the order which it is done or the initial setup of the UnitOfWork record. I cant get it to work and would really appreciate some insight into what i need to do to achieve it..

Note: Split_From_Payment__c is updated correctly, the new payment record is created correctly and all fields in oldLPP are updated correctly except for the Merged_From_Payment__c field which is the one that I cant get to update.

code:

//more code above to validate records...
oldLPP.Status__c= 'Cancelled';
oldLPP.Cancelled_Reason__c = 'Rescheduled';
oldLPP.Is_Superseded__c = dueAmt == 0 ? false : true;
oldLPP.Amount__c = dueAmt == 0 ? dueAmt : oldLPP.Amount__c;

Schema.SObjectType[] sobjsList = new Schema.SObjectType[] { Payment__c.SObjectType};
uow = new fflib_SObjectUnitOfWork(sobjsList);

if(oldLPP != null) 
    uow.registerRelationship(newLPP, Payment__c.Split_From_Payment__c, oldLPP);

newLPP.Amount__c = dueAmt;
newLPP.Due_Date__c = newDueDate;

system.debug('### newLPP: ' + newLPP);
uow.registerNew(newLPP);

if(oldLPP != null){
    uow.registerRelationship(oldLPP, Payment__c.Merged_Into_Payment__c, newLPP);
    uow.registerDirty(oldLPP,Payment__c.Merged_Into_Payment__c, newLPP);
}
uow.commitWork();

Best Answer

So, UnitOfWork will do inserts first, then updates, then deletes

I would simplify your code to look like this:

if (oldLPP != null {...} // set oldLPP fields
// set newLPP fields
...
// define scope of UoW
Schema.SObjectType[] sobjsList = new Schema.SObjectType[] { Payment__c.SObjectType};
uow = new fflib_SObjectUnitOfWork(sobjsList);

uow.registerNew(newLPP);

// build xrefs
if (oldLPP != null) {
   // new -> old
  uow.registerRelationship(newLPP,Payment__c.Merged_Into_Payment__c,oldLPP);
  // old -> new
  uow.registerDirty(oldLPP,Payment__c.Merged_Into_Payment__c,newLPP);
}
uow.commitWork();

There is of course, no rule against explicitly setting the relationship fields yourself

newLPP.Merged_Into_Payment__c = oldLPP.Id;