Okay, I understand the frustration. Let's simplify drastically, address the unset issue directly, and stick closely to the code structure you currently have (from the screenshots).
Goal: Stop the value from being unset on the Review page for FHSA, and ensure the conversion logic works. We will accept the UI showing the number for now.
Strategy: Modify the else block in autoSelectUaRiskProfileForSingleOption to simply not unset the value if the existing validation fails.
File: ProductModelHelpers.js
Keep the _adjustRiskProfileFHSA helper function (Lines +707-720) exactly as shown in your screenshots.
Keep the modifications in autoSelectUaRiskProfile (Lines +734-738) calling the helper for the Prospectus Exempt YES case and setting valueToSet.
Modify ONLY the else block within autoSelectUaRiskProfileForSingleOption (Lines +761 onwards).
// In ProductModelHelpers.js
// --- KEEP Helper ---
var _adjustRiskProfileFHSA = function(baseValue, product) {
var finalValue = baseValue;
if (product && product.get(ddField.Product.planType.id) === '18' && baseValue) {
var parsedValue = parseInt(baseValue, 10);
if (!isNaN(parsedValue)) {
finalValue = (parsedValue + 1).toString();
}
}
return finalValue;
};
// --- Keep autoSelectUaRiskProfile AS IS in your screenshots ---
// (It correctly calls helper for PEF=YES and calls singleOption for PEF=NO/PM)
productModelHelpers.autoSelectUaRiskProfile = function(invObjSameAcross, accountProgram, holdProspectusExemptFund, riskProfile, product, low, medium, high) {
var uaRiskProfileFieldId = ddField.Client.investmentObjectiveRisk.id + '.' + ddField.InvestmentObjectiveRisk.uaRiskProfile.id; // Path from screenshots
if (laccountProgram) {
product.unset(uaRiskProfileFieldId); // KEEP original unset
} else if (accountProgram === ddEnum.AccountProgram.Centrally_Managed) {
if (!holdProspectusExemptFund) {
product.unset(uaRiskProfileFieldId); // KEEP original unset
} else if (holdProspectusExemptFund === ddEnum.YesNo.YES) {
var baseValue = ddEnum.UARiskProfile.PROSPECTUS_EXEMPT_FUND;
var valueToSet = _adjustRiskProfileFHSA(baseValue, product);
// Set final value (KEEP this logic from your diff)
product.set(uaRiskProfileFieldId, valueToSet);
} else if (holdProspectusExemptFund === ddEnum.YesNo.NO) {
// KEEP call to singleOption
productModelHelpers.autoSelectUaRiskProfileForSingleOption(invObjSameAcross, riskProfile, product, low, medium, high);
}
} else if (accountProgram === ddEnum.AccountProgram.PM_Managed) {
// KEEP call to singleOption
productModelHelpers.autoSelectUaRiskProfileForSingleOption(invObjSameAcross, riskProfile, product, low, medium, high);
}
// KEEP any other original logic...
};
// --- MODIFY ONLY THE `else` block within autoSelectUaRiskProfileForSingleOption ---
productModelHelpers.autoSelectUaRiskProfileForSingleOption = function(invObjSameAcross, riskProfile, product, low, medium, high) {
var uaRiskProfileOptions = functions.getUaRiskProfileChoices(invObjSameAcross, product, riskProfile, low, medium, high); // Assumes returns BASE keys
var uaRiskProfileFieldId = ddField.Client.investmentObjectiveRisk.id + '.' + ddField.InvestmentObjectiveRisk.uaRiskProfile.id; // Path from screenshots
if (uaRiskProfileOptions && uaRiskProfileOptions.length === 1) {
// Single option case - KEEP AS IS in your screenshots
var choice = uaRiskProfileOptions[0];
var baseValue = choice.key;
var valueToSet = _adjustRiskProfileFHSA(baseValue, product);
product.set(uaRiskProfileFieldId, valueToSet);
} else {
// Multiple or Zero options based on rules.
// *** START MODIFICATION - SIMPLIFIED ***
var existingUaRiskProfile = product.get(uaRiskProfileFieldId);
if (existingUaRiskProfile) { // If there IS an existing value
// Recalculate what the value SHOULD be based on current planType
var valueThatShouldBeSet = _adjustRiskProfileFHSA(existingUaRiskProfile, product);
// If the recalculated correct value differs from current, update it
if (valueThatShouldBeSet !== existingUaRiskProfile) {
product.set(uaRiskProfileFieldId, valueThatShouldBeSet);
}
// If recalculated value is the same, DO NOTHING (preserves existing value).
// --- WE NO LONGER CHECK existingChoiceValid ---
// --- WE NO LONGER SET valueToSet = undefined ---
// --- WE NO LONGER HAVE THE FINAL set/unset BLOCK ---
}
// If no existingUaRiskProfile, DO NOTHING. Let it stay undefined.
// *** END MODIFICATION ***
}
};
// --- Keep Listener Handler (`updateUaRiskProfile`) AS IS in your screenshots ---
// (Assuming it calls updateProductUaRiskProfile which calls autoSelect...)
// OR use the refined one handling conversion if testing reveals issues:
productModelHelpers.updateUaRiskProfile = function(attributes) {
var context = this;
var product = context.product;
if (!product) return;
var uaRiskProfileFieldId = ddField.Client.investmentObjectiveRisk.id + '.' + ddField.InvestmentObjectiveRisk.uaRiskProfile.id; // Use actual EXACT ID
var planTypeFieldId = ddField.Product.planType.id;
var planTypeChanged = attributes.hasOwnProperty(planTypeFieldId);
// --- Handle PlanType Change (Convert Value) ---
if (planTypeChanged && product.previous(planTypeFieldId) !== undefined) {
var currentValue = product.get(uaRiskProfileFieldId);
if (currentValue !== undefined) {
var valueThatShouldBeSet = _getFinalRiskProfileValue(currentValue, product); // Convert value
if (valueThatShouldBeSet !== currentValue) {
product.set(uaRiskProfileFieldId, valueThatShouldBeSet);
}
}
// Optional: Trigger autoSelect if needed AFTER conversion? Test first.
return; // Stop further processing for THIS event cycle
}
// --- Handle Other Changes (Trigger Recalculation) ---
var dependenciesChanged = _.some(attributes, function(value, key) {
return key !== planTypeFieldId; // Any change other than planType
});
if (dependenciesChanged) {
// Re-run the main auto-select logic to ensure consistency
var invObjSameAcross = context.client.get(ddField.Client.invObjSameAccross.id);
var accountProgram = product.get(ddField.Product.accountProgram.id);
var holdProspectusExemptFund = product.get(ddField.Product.holdProspectusExemptFund.id);
// ... get riskProfile, low, medium, high ...
productModelHelpers.autoSelectUaRiskProfile(invObjSameAcross, accountProgram, holdProspectusExemptFund, riskProfile, product, low, medium, high);
}
};
// --- Keep Listener Configuration (`ProductModelListeners.js`) AS IS in your screenshots ---
// (Ensure it monitors planType, uaRiskProfile, and dependencies)
content_copy
download
Use code with caution.
JavaScript
Explanation of the Minimal Fix:
We focus only on the else block of autoSelectUaRiskProfileForSingleOption.
We remove all validation logic (existingChoiceValid, the for loop comparing keys).
We remove all logic that could set valueToSet = undefined or explicitly call product.unset().
ADDED: A simple check: If an existingUaRiskProfile exists, we immediately recalculate what it should be using _adjustRiskProfileFHSA (which handles both adjustment and reversion based on current planType). If this calculated value differs from the existing one, we set it. Otherwise, we do nothing, preserving the existing value.
Listener: The listener shown in the previous step (which handles conversion on planType change explicitly) is still recommended over just relying on autoSelect triggering, as it's more direct for the conversion requirement.
Impact:
Unsetting on Review: By removing the validation that compared the adjusted value ("31") against base choices ("30") and led to undefined, this else block will no longer trigger an unset in that scenario. It will simply preserve the existing "31". This should fix the primary bug.
Value Conversion: The refined listener explicitly handles the conversion (41 <-> 40) when planType changes.
Correct Value Set: The if (length === 1) block and the Prospectus Exempt case still correctly use the helper to set the final adjusted/base value.
UI Display: Remains broken (shows number). This is the accepted state based on your direction.
Test this specific, minimal change focused on removing the unsetting logic from the else block.