Skip to content

Commit

Permalink
Add "none" option to gas_utility param; validate param (#620)
Browse files Browse the repository at this point in the history
## Description

While implementing the Mass Save logic I realized that there's a
crucial distinction between a user _not having gas service_, and a
user _not specifying who their gas utility is_. (The former case
allows us to show more non-Mass Save utility incentives.)

My solution is to allow passing a special value of `none` to the
`gas_utility` param, meaning you affirmatively do not have gas
service. I'm anticipating that the calculator UI will offer options
like:

- National Grid
- Eversource
- Other
- I don't have gas service

"I don't have gas service" will result in the calculator sending the
special `none` value of the `gas_utility` param, while "Other" will
result in the param being absent.

This also adds logic to validate the parameter.

## Test Plan

`yarn test` with new tests.

Test coverage of this isn't going to be quite comprehensive until we
have the actual Mass Save data in here, which requires a couple more
changes first.
  • Loading branch information
oyamauchi authored Dec 17, 2024
1 parent 30e084a commit c4c023b
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 6 deletions.
7 changes: 7 additions & 0 deletions src/data/authorities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,10 @@ export const AUTHORITIES_BY_STATE: AuthoritiesByState = (() => {
}
return result;
})();

/**
* A special value for the API to allow positively indicating "I don't have gas
* service" (as opposed to your gas utility being unknown or unspecified). This
* matters for some eligibility decisions, such as with MA's Mass Save program.
*/
export const NO_GAS_UTILITY = 'none';
28 changes: 28 additions & 0 deletions src/lib/incentives-calculation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
AUTHORITIES_BY_STATE,
AuthoritiesById,
AuthorityType,
NO_GAS_UTILITY,
} from '../data/authorities';
import { DataPartnersType } from '../data/data_partners';
import { IRAIncentive, IRA_INCENTIVES } from '../data/ira_incentives';
Expand Down Expand Up @@ -264,6 +265,18 @@ export default function calculateIncentives(
);
}

if (
authority_types &&
authority_types.includes(AuthorityType.GasUtility) &&
(!request.gas_utility || request.gas_utility === NO_GAS_UTILITY)
) {
throw new InvalidInputError(
`Must include the "gas_utility" field, with a value other than \
"${NO_GAS_UTILITY}", when requesting gas utility incentives.`,
'gas_utility',
);
}

const stateAuthorities = AUTHORITIES_BY_STATE[state_id];
if (request.utility) {
if (!stateAuthorities) {
Expand All @@ -281,6 +294,21 @@ export default function calculateIncentives(
}
}

if (request.gas_utility && request.gas_utility !== NO_GAS_UTILITY) {
if (!stateAuthorities.gas_utility) {
throw new InvalidInputError(
`We do not yet have information about gas utilities in ${state_id}.`,
'gas_utility',
);
}
if (!stateAuthorities.gas_utility[request.gas_utility]) {
throw new InvalidInputError(
`Invalid gas utility: "${request.gas_utility}.`,
'gas_utility',
);
}
}

const isUnder80Ami =
household_income < amiAndEvCreditEligibility.computedAMI80;
const isUnder150Ami =
Expand Down
19 changes: 13 additions & 6 deletions src/schemas/v1/calculator-endpoint.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { FromSchema } from 'json-schema-to-ts';
import { API_AUTHORITY_SCHEMA, AuthorityType } from '../../data/authorities';
import {
API_AUTHORITY_SCHEMA,
AuthorityType,
NO_GAS_UTILITY,
} from '../../data/authorities';
import { API_DATA_PARTNER_SCHEMA } from '../../data/data_partners';
import { FilingStatus } from '../../data/tax_brackets';
import { API_COVERAGE_SCHEMA } from '../../data/types/coverage';
Expand Down Expand Up @@ -44,11 +48,14 @@ absent, no incentives offered by electric utilities will be returned.`,
gas_utility: {
type: 'string',
description: `The ID of your gas utility company, as returned from \
\`/api/v1/utilities\`. Required if authority_types includes "gas_utility". If \
absent, no incentives offered by gas utilities will be returned. In some \
jurisdictions, your gas utility can affect your eligibility for incentives \
offered by other authorities; in such cases, if this parameter is absent, \
incentives with gas-utility-dependent eligibility will _not_ be returned.`,
\`/api/v1/utilities\`, or the special string \`${NO_GAS_UTILITY}\` indicating \
that you do not have gas service. A value other than \`${NO_GAS_UTILITY}\` is \
required if authority_types includes "gas_utility". If this parameter is \
absent or \`${NO_GAS_UTILITY}\`, no incentives offered by gas utilities will \
be returned. In some jurisdictions, your gas utility can affect your \
eligibility for incentives offered by other authorities; in such cases, if \
this parameter is absent, incentives with gas-utility-dependent eligibility \
will _not_ be returned.`,
},
items: {
type: 'array',
Expand Down
28 changes: 28 additions & 0 deletions test/routes/v1.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,34 @@ const BAD_QUERIES = [
// We don't have coverage in 84106 (Utah)
utility: 'ri-rhode-island-energy',
},
{
zip: '02130',
owner_status: 'homeowner',
household_income: 80000,
tax_filing: 'joint',
household_size: 4,
// Must pass gas_utility param if you pass this
authority_types: ['gas_utility'],
},
{
zip: '02130',
owner_status: 'homeowner',
household_income: 80000,
tax_filing: 'joint',
household_size: 4,
authority_types: ['gas_utility'],
// Must pass a real gas_utility param
gas_utility: 'none',
},
{
zip: '02130',
owner_status: 'homeowner',
household_income: 80000,
tax_filing: 'joint',
household_size: 4,
// Must be a valid authority ID or "none"
gas_utility: 'nonexistent-utility',
},
];

test('bad queries', async t => {
Expand Down

0 comments on commit c4c023b

Please sign in to comment.