feat(fusion_portal): Phase 2a - mobility scooter ADP type + power-mobility home-access rule

Adds 'scooter' as a 4th ADP equipment type with a lean Express-form section
(scooter type + max range) and the power-mobility home-accessibility hard rule
(scooter + powerchair): "is the home usable inside and outside, no lifting?" - if No,
prompts adding an accessibility item (ramp / porch lift). Captures
x_fc_power_home_accessible + notes; the section toggles via the existing
equipment-select JS; controller parses the new fields.

NOT YET: ADP multi-device + combination rules (the bigger restructure).
Untested locally (Enterprise dep) - to be verified on a westin-v19 clone.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-06-02 02:22:47 -04:00
parent b17bd615bf
commit e0ddd9ef40
3 changed files with 96 additions and 3 deletions

View File

@@ -815,6 +815,14 @@ class AssessmentPortal(CustomerPortal):
vals['wheelchair_type'] = kw.get('wheelchair_type') vals['wheelchair_type'] = kw.get('wheelchair_type')
if kw.get('powerchair_type'): if kw.get('powerchair_type'):
vals['powerchair_type'] = kw.get('powerchair_type') vals['powerchair_type'] = kw.get('powerchair_type')
if kw.get('scooter_type'):
vals['scooter_type'] = kw.get('scooter_type')
if kw.get('scooter_max_range'):
vals['scooter_max_range'] = float(kw.get('scooter_max_range') or 0)
if kw.get('x_fc_power_home_accessible'):
vals['x_fc_power_home_accessible'] = kw.get('x_fc_power_home_accessible')
if kw.get('x_fc_power_home_access_notes'):
vals['x_fc_power_home_access_notes'] = kw.get('x_fc_power_home_access_notes')
# Float measurements # Float measurements
float_fields = [ float_fields = [

View File

@@ -45,6 +45,7 @@ class FusionAssessment(models.Model):
('rollator', 'Rollator'), ('rollator', 'Rollator'),
('wheelchair', 'Wheelchair'), ('wheelchair', 'Wheelchair'),
('powerchair', 'Powerchair'), ('powerchair', 'Powerchair'),
('scooter', 'Mobility Scooter'),
], string='Equipment Type', tracking=True, index=True) ], string='Equipment Type', tracking=True, index=True)
# Rollator Types # Rollator Types
@@ -70,6 +71,31 @@ class FusionAssessment(models.Model):
('type_3', 'Adult Power Base Type 3'), ('type_3', 'Adult Power Base Type 3'),
], string='Powerchair Type') ], string='Powerchair Type')
# ===== MOBILITY SCOOTER (ADP) — 2026-06 Phase 2 =====
scooter_type = fields.Selection([
('travel_3', '3-Wheel Travel/Portable'),
('travel_4', '4-Wheel Travel/Portable'),
('standard_3', '3-Wheel Standard'),
('standard_4', '4-Wheel Standard'),
('heavy_duty', 'Heavy-Duty / Bariatric'),
], string='Scooter Type')
scooter_max_range = fields.Float(
string='Maximum Range Needed (km)', digits=(10, 1),
help='Maximum distance the client needs the scooter to travel on a charge.',
)
# ===== POWER-MOBILITY HOME ACCESSIBILITY (ADP hard rule) =====
# Applies to scooter + power wheelchair: ADP funds power mobility only if the
# device can enter and be used at the residence independently, without lifting.
x_fc_power_home_accessible = fields.Selection([
('yes', 'Yes — usable inside and outside independently'),
('no', 'No — home needs accessibility work'),
], string='Home accessible for power-mobility device?',
help='ADP will not fund a scooter / power wheelchair if the home cannot '
'take it (device left outside or in the garage). If No, the home '
'needs an accessibility product (ramp / porch lift).')
x_fc_power_home_access_notes = fields.Text(string='Home Access Notes')
# ===== EXPRESS FORM: ROLLATOR MEASUREMENTS ===== # ===== EXPRESS FORM: ROLLATOR MEASUREMENTS =====
rollator_handle_height = fields.Float(string='Handle Height (inches)', digits=(10, 2)) rollator_handle_height = fields.Float(string='Handle Height (inches)', digits=(10, 2))
rollator_seat_height = fields.Float(string='Seat Height (inches)', digits=(10, 2)) rollator_seat_height = fields.Float(string='Seat Height (inches)', digits=(10, 2))

View File

@@ -98,6 +98,7 @@
<option value="rollator" t-att-selected="assessment.equipment_type == 'rollator' if assessment else False">Rollator</option> <option value="rollator" t-att-selected="assessment.equipment_type == 'rollator' if assessment else False">Rollator</option>
<option value="wheelchair" t-att-selected="assessment.equipment_type == 'wheelchair' if assessment else False">Wheelchair</option> <option value="wheelchair" t-att-selected="assessment.equipment_type == 'wheelchair' if assessment else False">Wheelchair</option>
<option value="powerchair" t-att-selected="assessment.equipment_type == 'powerchair' if assessment else False">Powerchair</option> <option value="powerchair" t-att-selected="assessment.equipment_type == 'powerchair' if assessment else False">Powerchair</option>
<option value="scooter" t-att-selected="assessment.equipment_type == 'scooter' if assessment else False">Mobility Scooter</option>
</select> </select>
</div> </div>
@@ -688,6 +689,60 @@
<label class="form-label fw-bold">Additional Information/Customization</label> <label class="form-label fw-bold">Additional Information/Customization</label>
<textarea name="additional_customization" class="form-control powerchair-field" rows="4" placeholder="Enter any additional requirements or customization notes..."><t t-esc="assessment.additional_customization if assessment else ''"/></textarea> <textarea name="additional_customization" class="form-control powerchair-field" rows="4" placeholder="Enter any additional requirements or customization notes..."><t t-esc="assessment.additional_customization if assessment else ''"/></textarea>
</div> </div>
<!-- Power-mobility home-accessibility — ADP hard rule -->
<div class="mb-4 p-3 border rounded bg-light">
<label class="form-label fw-bold">Home accessible for the device — inside &amp; outside?</label>
<select name="x_fc_power_home_accessible" class="form-control">
<option value="">-- Select --</option>
<option value="yes" t-att-selected="assessment.x_fc_power_home_accessible == 'yes' if assessment else False">Yes — usable inside and outside independently</option>
<option value="no" t-att-selected="assessment.x_fc_power_home_accessible == 'no' if assessment else False">No — home needs accessibility work</option>
</select>
<div class="alert alert-warning mt-2 mb-0">
<i class="fa fa-exclamation-triangle"/> ADP funds power mobility only if the device can enter and be used at the residence <strong>independently, without lifting</strong> (not left outside / in the garage). If <strong>No</strong>, add an accessibility assessment (ramp / porch lift) for the home.
</div>
<textarea name="x_fc_power_home_access_notes" class="form-control mt-2" rows="2" placeholder="Access notes (entry steps, garage, thresholds, turning space...)"><t t-esc="assessment.x_fc_power_home_access_notes if assessment else ''"/></textarea>
</div>
</div>
<!-- ===== MOBILITY SCOOTER ===== -->
<div id="scooter_form" class="equipment-form" style="display: none;">
<h2 class="text-center fw-bold text-uppercase mb-4">Mobility Scooter Assessment</h2>
<div class="mb-4">
<label class="form-label fw-bold">Scooter Type</label>
<select name="scooter_type" class="form-select">
<option value="">-- Select Type --</option>
<option value="travel_3" t-att-selected="assessment.scooter_type == 'travel_3' if assessment else False">3-Wheel Travel/Portable</option>
<option value="travel_4" t-att-selected="assessment.scooter_type == 'travel_4' if assessment else False">4-Wheel Travel/Portable</option>
<option value="standard_3" t-att-selected="assessment.scooter_type == 'standard_3' if assessment else False">3-Wheel Standard</option>
<option value="standard_4" t-att-selected="assessment.scooter_type == 'standard_4' if assessment else False">4-Wheel Standard</option>
<option value="heavy_duty" t-att-selected="assessment.scooter_type == 'heavy_duty' if assessment else False">Heavy-Duty / Bariatric</option>
</select>
</div>
<div class="row mb-3">
<div class="col-12 col-md-6 mb-3">
<label class="form-label fw-bold">Maximum Range Needed (km)</label>
<div class="input-group">
<input type="number" step="1" name="scooter_max_range" class="form-control"
t-att-value="assessment.scooter_max_range if assessment else ''"/>
<span class="input-group-text">km</span>
</div>
</div>
</div>
<!-- Power-mobility home-accessibility — ADP hard rule -->
<div class="mb-4 p-3 border rounded bg-light">
<label class="form-label fw-bold">Home accessible for the device — inside &amp; outside?</label>
<select name="x_fc_power_home_accessible" class="form-control">
<option value="">-- Select --</option>
<option value="yes" t-att-selected="assessment.x_fc_power_home_accessible == 'yes' if assessment else False">Yes — usable inside and outside independently</option>
<option value="no" t-att-selected="assessment.x_fc_power_home_accessible == 'no' if assessment else False">No — home needs accessibility work</option>
</select>
<div class="alert alert-warning mt-2 mb-0">
<i class="fa fa-exclamation-triangle"/> ADP funds power mobility only if the device can enter and be used at the residence <strong>independently, without lifting</strong> (not left outside / in the garage). If <strong>No</strong>, add an accessibility assessment (ramp / porch lift) for the home.
</div>
<textarea name="x_fc_power_home_access_notes" class="form-control mt-2" rows="2" placeholder="Access notes (entry steps, garage, thresholds, turning space...)"><t t-esc="assessment.x_fc_power_home_access_notes if assessment else ''"/></textarea>
</div>
</div> </div>
</div> </div>
@@ -1278,6 +1333,7 @@
var rollatorForm = document.getElementById('rollator_form'); var rollatorForm = document.getElementById('rollator_form');
var wheelchairForm = document.getElementById('wheelchair_form'); var wheelchairForm = document.getElementById('wheelchair_form');
var powerchairForm = document.getElementById('powerchair_form'); var powerchairForm = document.getElementById('powerchair_form');
var scooterForm = document.getElementById('scooter_form');
var wheelchairTypeSelect = document.querySelector('select[name="wheelchair_type"]'); var wheelchairTypeSelect = document.querySelector('select[name="wheelchair_type"]');
var reasonSelect = document.getElementById('reason_for_application'); var reasonSelect = document.getElementById('reason_for_application');
var previousFundingContainer = document.getElementById('previous_funding_date_container'); var previousFundingContainer = document.getElementById('previous_funding_date_container');
@@ -1339,6 +1395,7 @@
disableFormInputs(rollatorForm); disableFormInputs(rollatorForm);
disableFormInputs(wheelchairForm); disableFormInputs(wheelchairForm);
disableFormInputs(powerchairForm); disableFormInputs(powerchairForm);
disableFormInputs(scooterForm);
if (value === 'rollator') { if (value === 'rollator') {
enableFormInputs(rollatorForm); enableFormInputs(rollatorForm);
@@ -1346,6 +1403,8 @@
enableFormInputs(wheelchairForm); enableFormInputs(wheelchairForm);
} else if (value === 'powerchair') { } else if (value === 'powerchair') {
enableFormInputs(powerchairForm); enableFormInputs(powerchairForm);
} else if (value === 'scooter') {
enableFormInputs(scooterForm);
} }
} }