diff --git a/configuration/white_labels/co.py b/configuration/white_labels/co.py index f246ecf9..c92da844 100644 --- a/configuration/white_labels/co.py +++ b/configuration/white_labels/co.py @@ -136,18 +136,20 @@ def get_white_label(self) -> WhiteLabel: "211co": "2-1-1 Colorado", "cch": "Colorado Coalition for the Homeless", "frca": "Family Resource Center Association", - "jeffcoHS": "Jeffco Human Services", - "dhs": "Denver Human Services", "achs": "Adams County Human Services", + "arapahoectypublichealth": "Arapahoe County Public Health", + "dhs": "Denver Human Services", + "eaglecounty": "Eagle County", + "jeffcoHS": "Jeffco Human Services", + "larimercounty": "Larimer County", + "tellercounty": "Teller County", "gac": "Get Ahead Colorado", "bia": "Benefits in Action", - "arapahoectypublichealth": "Arapahoe County Public Health", "fircsummitresourcecenter": { "_label": "referralOptions.fircsummitresourcecenter", "_default_message": "FIRC Summit Resource Center", }, "ccig": "Colorado Design Insight Group", - "eaglecounty": "Eagle County", "searchEngine": {"_label": "referralOptions.searchEngine", "_default_message": "Google or other search engine"}, "socialMedia": {"_label": "referralOptions.socialMedia", "_default_message": "Social Media"}, "other": {"_label": "referralOptions.other", "_default_message": "Other"}, @@ -202,7 +204,10 @@ def get_white_label(self) -> WhiteLabel: "_label": "incomeOptions.sSDependent", "_default_message": "Social Security Dependent Benefits (retirement, disability, or survivors)", }, - "cashAssistance": {"_label": "incomeOptions.cashAssistance", "_default_message": "Cash Assistance Grant"}, + "cashAssistance": { + "_label": "incomeOptions.cashAssistance", + "_default_message": "Government Cash Assistance (including Colorado Works/TANF)", + }, "gifts": {"_label": "incomeOptions.gifts", "_default_message": "Gifts/Contributions (Received)"}, "investment": { "_label": "incomeOptions.investment", @@ -2011,13 +2016,6 @@ def get_white_label(self) -> WhiteLabel: "_default_message": "Free preschool", }, }, - "pell": { - "name": {"_label": "childCareBenefits.pell", "_default_message": "Pell Grant: "}, - "description": { - "_label": "childCareBenefits.pell_desc", - "_default_message": "Federal grant to help with the cost of college or technical school", - }, - }, }, "category_name": { "_label": "childCareYouthAndEducation", @@ -2180,6 +2178,8 @@ def get_white_label(self) -> WhiteLabel: "ccig": "CCIG_Logo", "eaglecounty": "EC_MFBLogo", "achs": "ACHS_MFBLogo", + "larimercounty": "LC_MFBLogo", + "tellercounty": "TC_MFBLogo", }, "logoAlt": { "default": {"id": "referrerHook.logoAlts.default", "defaultMessage": "MyFriendBen home page button"}, @@ -2222,10 +2222,23 @@ def get_white_label(self) -> WhiteLabel: "id": "referrerHook.logoAlts.adamscountyhumanservices", "defaultMessage": "Adams County and MyFriendBen home page button", }, + "larimercounty": { + "id": "referrerHook.logoAlts.larimercounty", + "defaultMessage": "Larimer County and MyFriendBen home page button", + }, + "tellercounty": { + "id": "referrerHook.logoAlts.tellercounty", + "defaultMessage": "Teller County and MyFriendBen home page button", + }, }, "logoFooterSource": {"default": "MFB_Logo"}, "logoFooterAlt": {"default": {"id": "footer.logo.alt", "defaultMessage": "MFB Logo"}}, - "logoClass": {"default": "logo", "eaglecounty": "eaglecounty-logo-size"}, + "logoClass": { + "default": "logo", + "eaglecounty": "eaglecounty-logo-size", + "larimercounty": "larimercounty-logo-size", + "tellercounty": "tellercounty-logo-size", + }, "twoOneOneLink": { "default": 'https://www.211colorado.org/?utm_source=myfriendben&utm_medium=inlink&utm_campaign=organic&utm_id="211mfb"', "211co": 'https://www.211colorado.org/?utm_source=myfriendben&utm_medium=inlink&utm_campaign=whitelabel&utm_id="211mfb"', diff --git a/programs/programs/co/child_care_assistance/calculator.py b/programs/programs/co/child_care_assistance/calculator.py index b4a9d93d..e1a85bb4 100644 --- a/programs/programs/co/child_care_assistance/calculator.py +++ b/programs/programs/co/child_care_assistance/calculator.py @@ -43,7 +43,7 @@ def household_eligible(self, e: Eligibility): # income frequency = "yearly" - gross_income = self.screen.calc_gross_income(frequency, ["all"]) + gross_income = self.screen.calc_gross_income(frequency, ["all"], ["cashAssistance"]) deductions = self.screen.calc_expenses(frequency, ["childSupport"]) net_income = gross_income - deductions fpl_percent = cccap_county_limits[county_name] / 100 diff --git a/programs/programs/co/connect_for_health/calculator.py b/programs/programs/co/connect_for_health/calculator.py index 0033024b..45b8739c 100644 --- a/programs/programs/co/connect_for_health/calculator.py +++ b/programs/programs/co/connect_for_health/calculator.py @@ -35,7 +35,7 @@ def household_eligible(self, e: Eligibility): # Income fpl = self.program.fpl.as_dict() income_band = int(fpl[self.screen.household_size] * ConnectForHealth.percent_of_fpl) - gross_income = int(self.screen.calc_gross_income("yearly", ("all",))) + gross_income = int(self.screen.calc_gross_income("yearly", ["all"], exclude=["cashAssistance"])) e.condition(gross_income < income_band, messages.income(gross_income, income_band)) def member_eligible(self, e: MemberEligibility): diff --git a/programs/programs/co/medicaid/family_planning_services/calculator.py b/programs/programs/co/medicaid/family_planning_services/calculator.py index bab36999..1d8603da 100644 --- a/programs/programs/co/medicaid/family_planning_services/calculator.py +++ b/programs/programs/co/medicaid/family_planning_services/calculator.py @@ -24,7 +24,7 @@ def household_eligible(self, e: Eligibility): income_limit = int( FamilyPlanningServices.fpl_percent * fpl.get_limit(self.screen.household_size + len(e.eligible_members)) ) - gross_income = int(self.screen.calc_gross_income("yearly", ["all"])) + gross_income = int(self.screen.calc_gross_income("yearly", ["all"], exclude=["cashAssistance"])) e.condition(gross_income < income_limit, messages.income(gross_income, income_limit)) diff --git a/programs/programs/co/weatherization_assistance/calculator.py b/programs/programs/co/weatherization_assistance/calculator.py index 8054eab7..5d6454ec 100644 --- a/programs/programs/co/weatherization_assistance/calculator.py +++ b/programs/programs/co/weatherization_assistance/calculator.py @@ -4,56 +4,38 @@ import programs.programs.messages as messages -class SmiCache(GoogleSheetsCache): - sheet_id = "1KE0fBYqmIcwXO-tLu4RIF47GLFTyxLi4mi3uG-llMDY" - range_name = "current 60% SMI!B2:I2" - default = [0, 0, 0, 0, 0, 0, 0, 0] - - def update(self): - data = super().update() - - return [int(a.replace(",", "")) for a in data[0]] - - -class AmiCache(GoogleSheetsCache): - sheet_id = "1KE0fBYqmIcwXO-tLu4RIF47GLFTyxLi4mi3uG-llMDY" - range_name = "current 80% AMI!A2:I" +class IncomeLimitsCache(GoogleSheetsCache): + sheet_id = "1ZzQYhULtiP61crj0pbPjhX62L1TnyAisLcr_dQXbbFg" + range_name = "A2:K" # WARN: This selects the first tab because the tab name is "(Updated mm/dd/yyyy)" default = {} def update(self): data = super().update() - county_fpls = {r[0].strip() + " County": self._get_income_limits(r[1:]) for r in data} - - return county_fpls - - def _get_income_limits(self, raw_limits: list[str]): - limits = [] + return {self._format_county(r[0]): self._format_amounts(r[1:9]) for r in data} - for limit in raw_limits: - limits.append(int(limit.replace(",", ""))) + @staticmethod + def _format_county(county: str): + return county.strip() + " County" - return limits + @staticmethod + def _format_amounts(amounts: list[str]): + return [float(a.strip().replace("$", "").replace(",", "")) for a in amounts] class WeatherizationAssistance(ProgramCalculator): - smi_cache = SmiCache() - ami_cache = AmiCache() + income_limits = IncomeLimitsCache() presumptive_eligibility = ("andcs", "ssi", "snap", "leap", "tanf") amount = 350 dependencies = ["household_size", "income_amount", "income_frequency"] def household_eligible(self, e: Eligibility): # income condition - income_limit = self.smi_cache.fetch()[self.screen.household_size - 1] - if self.screen.zipcode != None: - counties = counties_from_screen(self.screen) - - for county in counties: - ami_limit = self.ami_cache.fetch()[county][self.screen.household_size - 1] - - if ami_limit > income_limit: - income_limit = ami_limit + counties = counties_from_screen(self.screen) + income_limits = [] + for county in counties: + income_limits.append(self.income_limits.fetch()[county][self.screen.household_size - 1]) + income_limit = min(income_limits) income = int(self.screen.calc_gross_income("yearly", ["all"])) income_eligible = income <= income_limit diff --git a/programs/programs/policyengine/calculators/dependencies/spm.py b/programs/programs/policyengine/calculators/dependencies/spm.py index 5481223d..5bda5b1c 100644 --- a/programs/programs/policyengine/calculators/dependencies/spm.py +++ b/programs/programs/policyengine/calculators/dependencies/spm.py @@ -202,7 +202,7 @@ class CoTanfCountableGrossUnearnedIncomeDependency(SpmUnit): ) def value(self): - return int(self.screen.calc_gross_income("yearly", ["unearned"])) + return int(self.screen.calc_gross_income("yearly", ["unearned"], exclude=["cashAssistance"])) class NcTanfCountableEarnedIncomeDependency(SpmUnit): diff --git a/screener/models.py b/screener/models.py index 99157c93..fdffee91 100644 --- a/screener/models.py +++ b/screener/models.py @@ -105,12 +105,12 @@ class Screen(models.Model): def frozen(self): return self.validations.count() > 0 - def calc_gross_income(self, frequency, types): + def calc_gross_income(self, frequency, types, exclude=[]): household_members = self.household_members.all() gross_income = 0 for household_member in household_members: - gross_income += household_member.calc_gross_income(frequency, types) + gross_income += household_member.calc_gross_income(frequency, types, exclude) return float(gross_income) def calc_expenses(self, frequency, types): @@ -413,12 +413,15 @@ class HouseholdMember(models.Model): has_income = models.BooleanField(blank=True, null=True) has_expenses = models.BooleanField(blank=True, null=True) - def calc_gross_income(self, frequency, types): + def calc_gross_income(self, frequency, types, exclude=[]): gross_income = 0 earned_income_types = ["wages", "selfEmployment"] income_streams = self.income_streams.all() for income_stream in income_streams: + if income_stream.type in exclude: + continue + include_all = "all" in types specific_match = income_stream.type in types earned_income_match = "earned" in types and income_stream.type in earned_income_types