Surface AER eligibility requirements in plan comparisons
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 17s

Cost modeling can't tell you whether you actually qualify for a plan --
several top-ranked results turned out to require things like buying
solar equipment through a specific installer partner, or being a new
customer only. AER's data states these restrictions explicitly in most
cases; surface them as modeling notes (and a badge in the comparison
table) so they're visible before considering a switch, rather than
only showing up when someone tries to sign up.

Doesn't catch every restriction -- some plans (e.g. concession/seniors
offers) carry no eligibility block in AER's data at all despite an
implied real-world restriction, so absence of the badge isn't a
guarantee of eligibility.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
dlawler489 2026-09-11 15:23:50 +10:00
parent e4c41c3eb9
commit 8cbcd0155f
2 changed files with 18 additions and 0 deletions

View file

@ -216,6 +216,21 @@ def map_aer_plan(list_entry: dict, detail: dict) -> TariffPlan:
label = incentive.get("displayName") or incentive.get("description", "") label = incentive.get("displayName") or incentive.get("description", "")
notes.append(f"One-off sign-up incentive not included in the cost estimate: {label}") notes.append(f"One-off sign-up incentive not included in the cost estimate: {label}")
# Cost modeling can't tell you whether you actually qualify for a plan --
# AER's data sometimes states this explicitly (e.g. "must purchase an
# eligible solar PV system from an Origin approved solar installer",
# "new residential customers only"), and a plan ranking well on price
# alone is useless if you don't meet its eligibility criteria. Surface
# whatever AER provides so at least the stated restrictions are visible
# in the comparison -- this can't catch requirements AER leaves
# unstated (e.g. concession/seniors card plans with no eligibility
# block at all), so a plan showing no note here isn't a guarantee of
# eligibility, just that AER didn't document a restriction.
for elig in ec.get("eligibility", []):
description = elig.get("description") or elig.get("information")
if description:
notes.append(f"Eligibility requirement: {description}")
supply_charge_c_per_day = supply_charges_c[0] if supply_charges_c else 0.0 supply_charge_c_per_day = supply_charges_c[0] if supply_charges_c else 0.0
if len(set(supply_charges_c)) > 1: if len(set(supply_charges_c)) > 1:
notes.append("Supply charge varies by season in the source data; using the first season's rate.") notes.append("Supply charge varies by season in the source data; using the first season's rate.")

View file

@ -68,6 +68,9 @@ async function loadPlans(days) {
const badges = []; const badges = [];
if (row.is_current) badges.push('<span class="badge current">Current plan</span>'); if (row.is_current) badges.push('<span class="badge current">Current plan</span>');
if (!row.modelable) badges.push('<span class="badge not-modelable">Not fully modeled</span>'); if (!row.modelable) badges.push('<span class="badge not-modelable">Not fully modeled</span>');
if (row.modeling_notes.some(n => n.startsWith('Eligibility requirement:'))) {
badges.push('<span class="badge not-modelable">Eligibility restricted</span>');
}
let savingsCell = '&mdash;'; let savingsCell = '&mdash;';
if (row.savings_vs_current_dollars !== null && row.savings_vs_current_dollars !== undefined && !row.is_current) { if (row.savings_vs_current_dollars !== null && row.savings_vs_current_dollars !== undefined && !row.is_current) {