Extending QuoteX Cloning Logic
Extending QuoteX Cloning Logic
|
Technical Design
|
OBJECTIVE
|
| To enable the cloning of custom (out-of-namespace) fields during the QuoteX cloning process for both Parent Quotes and Timeline (Child) records. |
⚠️ Scope This approach applies only to custom fields you have added to the PSC Quote object. Native managed-package fields are handled internally by QuoteX and are outside scope. |
The QuoteX managed package cloning functionality only recognizes fields within its own namespace. Custom fields added to the PSC Quote object are ignored during the native clone operation. Additionally, the native process does not provide a direct hook to map these fields, requiring a workaround to identify the Source Record ID during the before insert execution context.
Logic & Workaround Strategy
|
To map custom fields, we must capture the Source Record ID, retrieve its custom field values, and inject them into the new record. We will utilize two existing fields as temporary "pass-through" containers for the Source ID:
- For Parent Quotes: The deprecated
Version Notes field. - For Timelines (Child Quotes): The standard
Name field (pre-populated by the package as "Only for Timeline").
Record Identification Criteria
|
| Record Type | psce__Is_Specific_To_Timeline__c | psce__Parent_Estimate__c | Identity Container |
| Parent Quote | False | null | Version_Notes__c |
| Timeline (Child) | True | NOT null | Name |
Execution Logic (Apex Trigger / Flow)
|
| ▶ Phase A: Before Insert (Data Mapping) |
- Parent Quotes:
- Check if
Version_Notes__c contains a valid Salesforce 18-digit ID. - If valid, query the Source Quote record for all relevant custom field values.
- Map these values to the current record instance (
Trigger.new). - Timeline Records:
- Check if the
Name field contains a valid Salesforce 18-digit ID. - If valid, query the Source Timeline record for all relevant custom field values.
- Map these values to the current record instance (
Trigger.new).
| ▶ Phase B: After Insert (Field Cleanup) |
To ensure data integrity and prevent the "pass-through" IDs from remaining in the system:
- Parent Quotes: Update
Version_Notes__c with the ID of the newly created record (or nullify if preferred). - Timeline Records: Update the
Name field with the ID of the newly created record to overwrite the source ID reference.
Implementation Notes & Constraints
|
- Namespace Awareness: Ensure the query for custom fields dynamically handles fields outside the
psce__ namespace. - SOQL Optimization: When bulk cloning, ensure the "Source Record" queries are bulkified (Collection-based) to avoid Governor Limits.
- Field Deprecation: Note that
Version_Notes__c is deprecated as of v1.85 and is safe for re-purposing as a temporary ID container for Parent Quotes. - Timeline Hard-coding: The native package hard-codes the
Name field for Timelines; our logic must override this in the After Insert phase to maintain record naming conventions.
| Trigger Event | Condition | Action |
| Before Insert | Version_Notes__c contains valid record ID | Fetch source Quote, copy custom field values to new record |
| Before Insert | Name = valid record ID & Timeline condition met | Fetch source Timeline, copy custom field values to new record |
| After Insert | psce__Is_Specific_To_Timeline__c = false | Set Version_Notes__c = new record ID (via DML update) |
| After Insert | psce__Is_Specific_To_Timeline__c = true | Set Name = new record ID (via DML update) |
Potential Risks & Enhancements
|
While the logic is solid, you should consider these technical nuances to ensure it is "100% correct":
- The "Recursion" Trap: Since you are doing an
After Insert update on the same object, ensure your trigger framework has Static Variable recursion control. Don't use Trigger.new rather create a new instance of object and update. - Governor Limits (Bulkification):
- In the
Before Insert, you must collect all IDs from the Version Notes/Name fields first. - Run one single SOQL query to get all custom field values for those Source IDs.
- Map them using a
Map<Id, PSC_Quote__c>. - Never query inside the loop.
- The "Name" Field Sensitivity: Since you are using the Standard
Name field for Timelines, ensure that any other automation (like Auto-numbering or other Flows) doesn't overwrite your Source ID before your Before Insert logic has a chance to read it. And it has to happen only for timelines and not for parent Quote because parent quote Name field is in use and populated by users.