Hi,
You are very close.
The reason only the parent record gets cloned is that your Filters for the child and grand-child tables probably return no rows.
You’re filtering on 'Contract'.'Contract Number' and 'Contract Task'.'Contract Task ID', which are fields on the lookup record. It’s more reliable to filter directly by the lookup column itself (i.e., compare records, not inner fields).
Try this simplified version (same structure, but notice the Filters and lookup assignments):
ForAll(
Self.Selected.AllItems As selContract,
With(
{
clonedContract:
Patch(
'GIND UK Contracts',
Defaults('GIND UK Contracts'),
{
'Notes (cr666_notes)':
selContract.'Notes (cr666_notes)' & " COPY - "
// other Contract fields...
}
)
},
// CHILD: Contract Tasks
ForAll(
Filter(
'GIND UK Contract Tasks',
'Contract' = selContract // <-- use lookup, not Contract Number
) As ct,
With(
{
CreatedChildContractTask:
Patch(
'GIND UK Contract Tasks',
Defaults('GIND UK Contract Tasks'),
{
'Comments ': ct.'Comments ' & " (COPY)",
'Contract ': clonedContract // <-- link to new parent
// other Task fields...
}
)
},
// GRANDCHILD: Task Labour
ForAll(
Filter(
'GIND UK Task Labour',
'Contract Task' = ct // <-- use lookup, not ID field
) As gl,
Patch(
'GIND UK Task Labour',
Defaults('GIND UK Task Labour'),
{
Comments: gl.Comments & " (COPY)",
'Contract Task': CreatedChildContractTask
// other Labour fields...
}
)
)
)
)
)
);
Notify("Contract and child records copied", NotificationType.Success)
Key changes:
Filter child tasks with 'Contract' = selContract.
Filter labour records with 'Contract Task' = ct.
Use the result of Patch (clonedContract, CreatedChildContractTask) when setting the lookup columns on the new records.
If you drop a Label with CountRows(ChildContractTask) / CountRows(GrandChildLabour) while testing, you should see those now return > 0 and the children/grandchildren get created.