From e36aaab306a29ddc16624b58a144afb35bc3f985 Mon Sep 17 00:00:00 2001 From: gsinghpal Date: Tue, 2 Jun 2026 01:38:42 -0400 Subject: [PATCH] fix(fusion_portal): validate funding_source in accessibility save (parity with booking) Coerce an unexpected/tampered funding_source to direct_private instead of passing it raw into create() (which would raise on the Selection field). Mirrors the /book-assessment controller; the whitelist is derived from the model selection so it auto-covers hardship and any future values. Co-Authored-By: Claude Opus 4.8 (1M context) --- fusion_portal/controllers/portal_main.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/fusion_portal/controllers/portal_main.py b/fusion_portal/controllers/portal_main.py index b5f65b51..0563e099 100644 --- a/fusion_portal/controllers/portal_main.py +++ b/fusion_portal/controllers/portal_main.py @@ -2493,7 +2493,14 @@ class AuthorizerPortal(CustomerPortal): assessment_type = post.get('assessment_type') if not assessment_type: return {'success': False, 'error': 'Assessment type is required'} - + + # Funding source drives the downstream sale-order workflow; coerce + # anything unexpected to private pay (mirrors /book-assessment). + _funding_keys = dict(Assessment._fields['x_fc_funding_source'].selection) + funding_source = post.get('funding_source') or 'direct_private' + if funding_source not in _funding_keys: + funding_source = 'direct_private' + # Build assessment values vals = { 'assessment_type': assessment_type, @@ -2507,7 +2514,7 @@ class AuthorizerPortal(CustomerPortal): 'client_address_postal': post.get('client_address_postal', '').strip(), 'client_phone': post.get('client_phone', '').strip(), 'client_email': post.get('client_email', '').strip(), - 'x_fc_funding_source': post.get('funding_source') or 'direct_private', + 'x_fc_funding_source': funding_source, 'notes': post.get('notes', '').strip(), }