Surface AER eligibility requirements in plan comparisons
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 17s
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:
parent
e4c41c3eb9
commit
8cbcd0155f
2 changed files with 18 additions and 0 deletions
|
|
@ -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.")
|
||||||
|
|
|
||||||
|
|
@ -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 = '—';
|
let savingsCell = '—';
|
||||||
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) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue