Skip to content

Commit

Permalink
Merge pull request #603 from Gary-Community-Ventures/dev
Browse files Browse the repository at this point in the history
Release 10/25/2024
  • Loading branch information
CalebPena authored Nov 1, 2024
2 parents f86ea62 + fda4302 commit 4f1f70d
Show file tree
Hide file tree
Showing 24 changed files with 181 additions and 110 deletions.
8 changes: 4 additions & 4 deletions configuration/management/commands/add_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,23 +120,23 @@ class Command(BaseCommand):
"cch": "Colorado Coalition for the Homeless",
"frca": "Family Resource Center Association",
"jeffcoHS": "Jeffco Human Services",
"dhs": "Denver Human Services",
"gac": "Get Ahead Colorado",
"bia": "Benefits in Action",
"arapahoectypublichealth": "Arapahoe County Public Health",
"fircsummitresourcecenter": {
"_label": "referralOptions.fircsummitresourcecenter",
"_default_message": "FIRC Summit Resource Center",
},
"dhs": "Denver Human Services",
"ccig": "Colorado Community 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"},
"testOrProspect": {
"_label": "referralOptions.testOrProspect",
"_default_message": "Test / Prospective Partner",
},
"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"},
}

language_options = {
Expand Down
3 changes: 0 additions & 3 deletions programs/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ def action_buttons(self, obj):
description_short = obj.description_short
learn_more_link = obj.learn_more_link
apply_button_link = obj.apply_button_link
category = obj.category
estimated_delivery_time = obj.estimated_delivery_time
estimated_application_time = obj.estimated_application_time
value_type = obj.value_type
Expand All @@ -56,7 +55,6 @@ def action_buttons(self, obj):
<a href="{}">Name</a>
<a href="{}">Description</a>
<a href="{}">Short Description</a>
<a href="{}">Category</a>
<a href="{}">Learn More Link</a>
<a href="{}">Apply Button Link</a>
<a href="{}">Estimated Delivery Time</a>
Expand All @@ -70,7 +68,6 @@ def action_buttons(self, obj):
reverse("translation_admin_url", args=[name.id]),
reverse("translation_admin_url", args=[description.id]),
reverse("translation_admin_url", args=[description_short.id]),
reverse("translation_admin_url", args=[category.id]),
reverse("translation_admin_url", args=[learn_more_link.id]),
reverse("translation_admin_url", args=[apply_button_link.id]),
reverse("translation_admin_url", args=[estimated_delivery_time.id]),
Expand Down
1 change: 0 additions & 1 deletion programs/management/commands/remove_programs.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ def handle(self, *args, **options):
"value_type",
"estimated_delivery_time",
"estimated_application_time",
"category",
"warning",
)

Expand Down
17 changes: 17 additions & 0 deletions programs/migrations/0093_remove_program_category.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 4.2.15 on 2024-10-14 18:13

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
("programs", "0092_programcategory_icon"),
]

operations = [
migrations.RemoveField(
model_name="program",
name="category",
),
]
18 changes: 18 additions & 0 deletions programs/migrations/0094_rename_category_v2_program_category.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 4.2.15 on 2024-10-15 19:32

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
("programs", "0093_remove_program_category"),
]

operations = [
migrations.RenameField(
model_name="program",
old_name="category_v2",
new_name="category",
),
]
16 changes: 7 additions & 9 deletions programs/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,6 @@ class ProgramManager(models.Manager):
"value_type",
"estimated_delivery_time",
"estimated_application_time",
"category",
"estimated_value",
"website_description",
)
Expand Down Expand Up @@ -251,7 +250,7 @@ class ProgramDataController(ModelDataController["Program"]):
"active": bool,
"low_confidence": bool,
"documents": list[str],
"category": str,
"category": Optional[str],
},
)

Expand All @@ -272,7 +271,7 @@ def to_model_data(self) -> DataType:
"low_confidence": program.low_confidence,
"name_abbreviated": program.name_abbreviated,
"documents": [d.external_name for d in program.documents.all()],
"category": program.category_v2.external_name,
"category": program.category.external_name if program.category is not None else None,
}

def from_model_data(self, data: DataType):
Expand Down Expand Up @@ -315,8 +314,10 @@ def from_model_data(self, data: DataType):
program.documents.set(documents)

# get program category
program_category = ProgramCategory.objects.get(external_name=data["category"])
program.category_v2 = program_category
program_category = None
if data["category"] is not None:
program_category = ProgramCategory.objects.get(external_name=data["category"])
program.category = program_category

program.save()

Expand All @@ -336,7 +337,7 @@ class Program(models.Model):
active = models.BooleanField(blank=True, default=True)
low_confidence = models.BooleanField(blank=True, null=False, default=False)
fpl = models.ForeignKey(FederalPoveryLimit, related_name="fpl", blank=True, null=True, on_delete=models.SET_NULL)
category_v2 = models.ForeignKey(
category = models.ForeignKey(
ProgramCategory, related_name="programs", blank=True, null=True, on_delete=models.SET_NULL
)

Expand Down Expand Up @@ -368,9 +369,6 @@ class Program(models.Model):
null=False,
on_delete=models.PROTECT,
)
category = models.ForeignKey(
Translation, related_name="program_category", blank=False, null=False, on_delete=models.PROTECT
)
estimated_value = models.ForeignKey(
Translation,
related_name="program_estimated_value",
Expand Down
7 changes: 6 additions & 1 deletion programs/programs/categories/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,12 @@ def calc_max_cap(self, cap: CategoryCap, values: list[int]):
return max(*values)

def calc_average_cap(self, cap: CategoryCap, values: list[int]):
return sum(values) / len(values)
non_0_values = [v for v in values if v > 0]

if len(non_0_values) == 0:
return 0

return sum(non_0_values) / len(non_0_values)

def _handle_caps(self, caps: list[CategoryCap], func: Callable[[CategoryCap, list[int]], int]) -> list[CategoryCap]:
"""
Expand Down
7 changes: 5 additions & 2 deletions programs/programs/categories/co/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
from programs.programs.categories.co.preschool import PreschoolCategoryCap
from programs.programs.categories.co.caps import HealthCareCategoryCap, PreschoolCategoryCap
from ..base import ProgramCategoryCapCalculator

co_category_cap_calculators: dict[str, type[ProgramCategoryCapCalculator]] = {"co_preschool": PreschoolCategoryCap}
co_category_cap_calculators: dict[str, type[ProgramCategoryCapCalculator]] = {
"co_preschool": PreschoolCategoryCap,
"co_health_care": HealthCareCategoryCap,
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,7 @@

class PreschoolCategoryCap(ProgramCategoryCapCalculator):
static_caps = [CategoryCap(["dpp", "upk", "chs"], cap=8_640, member_cap=True)]


class HealthCareCategoryCap(ProgramCategoryCapCalculator):
max_caps = [CategoryCap(["cfhc", "awd_medicaid", "cwd_medicaid"], member_cap=True)]
1 change: 1 addition & 0 deletions programs/programs/co/pe/member.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class Chp(PolicyEngineMembersCalculator):
pe_inputs = [
dependency.member.AgeDependency,
dependency.member.PregnancyDependency,
dependency.member.ExpectedChildrenPregnancyDependency,
dependency.household.CoStateCode,
*dependency.irs_gross_income,
]
Expand Down
24 changes: 5 additions & 19 deletions programs/programs/co/utility_bill_pay/calculator.py
Original file line number Diff line number Diff line change
@@ -1,34 +1,20 @@
from programs.programs.calc import Eligibility, ProgramCalculator
import programs.programs.messages as messages


class UtilityBillPay(ProgramCalculator):
income_limits = (
36_983,
48_362,
59_742,
71_122,
82_501,
93_881,
96_014,
101_120,
)
presumptive_eligibility = ("snap", "ssi", "andcs", "tanf", "wic")
amount = 350
dependencies = ["household_size", "income_amount", "income_frequency"]
presumptive_eligibility = ("snap", "ssi", "andcs", "tanf", "wic", "co_medicaid", "emergency_medicaid", "chp")
amount = 400

def household_eligible(self, e: Eligibility):
# has other programs
presumptive_eligible = False
for benefit in UtilityBillPay.presumptive_eligibility:
if self.screen.has_benefit(benefit):
presumptive_eligible = True
elif benefit in self.data and self.data[benefit].eligible:
presumptive_eligible = True

# income
income = int(self.screen.calc_gross_income("yearly", ["all"]))
income_limit = UtilityBillPay.income_limits[self.screen.household_size - 1]

e.condition(income < income_limit or presumptive_eligible, messages.income(income, income_limit))
e.condition(presumptive_eligible)

# has rent or mortgage expense
has_rent_or_mortgage = self.screen.has_expense(["rent", "mortgage"])
Expand Down
1 change: 1 addition & 0 deletions programs/programs/federal/pe/member.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class Wic(PolicyEngineMembersCalculator):
pe_name = "wic"
pe_inputs = [
dependency.member.PregnancyDependency,
dependency.member.ExpectedChildrenPregnancyDependency,
dependency.member.AgeDependency,
dependency.spm.SchoolMealCountableIncomeDependency,
]
Expand Down
2 changes: 2 additions & 0 deletions programs/programs/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ def medicaid_eligible(data: dict[str, Eligibility]):
if name in data:
return data[name].eligible

return False


def snap_ineligible_student(screen: Screen, member: HouseholdMember):
if not member.student:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ def value(self):
return self.member.pregnant or False


class ExpectedChildrenPregnancyDependency(Member):
field = "current_pregnancies"

def value(self):
return 1 if self.member.pregnant else 0


class FullTimeCollegeStudentDependency(Member):
field = "is_full_time_college_student"

Expand Down
2 changes: 1 addition & 1 deletion programs/programs/urgent_needs/urgent_need_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ def eligible(self):
class EocIncomeLimitCache(GoogleSheetsCache):
default = {}
sheet_id = "1T4RSc9jXRV5kzdhbK5uCQXqgtLDWt-wdh2R4JVsK33o"
range_name = "'2023'!A2:I65"
range_name = "'current'!A2:I65"

def update(self):
data = super().update()
Expand Down
30 changes: 26 additions & 4 deletions programs/serializers.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from programs.models import Program, UrgentNeed, Navigator
from programs.models import Program, ProgramCategory, UrgentNeed, Navigator
from rest_framework import serializers
from translations.serializers import ModelTranslationSerializer

Expand All @@ -9,16 +9,38 @@ class Meta:
fields = "__all__"


class ProgramSerializerMeta:
model = Program
fields = ("id", "name", "website_description")


class ProgramSerializer(serializers.ModelSerializer):
name = ModelTranslationSerializer()
website_description = ModelTranslationSerializer()
category = ModelTranslationSerializer()

class Meta:
model = Program
class Meta(ProgramSerializerMeta):
pass


class ProgramSerializerWithCategory(ProgramSerializer):
category = ModelTranslationSerializer(source="category.name")

class Meta(ProgramSerializerMeta):
fields = ("id", "name", "website_description", "category")


class ProgramCategorySerializer(serializers.ModelSerializer):
programs = serializers.SerializerMethodField()
name = ModelTranslationSerializer()

class Meta:
model = ProgramCategory
fields = ("id", "name", "icon", "programs")

def get_programs(self, obj: ProgramCategory):
return ProgramSerializer(obj.programs.filter(active=True), many=True).data


class UrgentNeedAPISerializer(serializers.ModelSerializer):
name = ModelTranslationSerializer()
website_description = ModelTranslationSerializer()
Expand Down
1 change: 1 addition & 0 deletions programs/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

router = routers.DefaultRouter()
router.register(r"programs", views.ProgramViewSet)
router.register(r"program_categories", views.ProgramCategoryViewSet)
router.register(r"navigators", views.NavigatorViewSet)
router.register(r"urgent-needs", views.UrgentNeedViewSet)

Expand Down
29 changes: 14 additions & 15 deletions programs/views.py
Original file line number Diff line number Diff line change
@@ -1,34 +1,33 @@
from programs.models import Program, Navigator, UrgentNeed
from programs.models import Program, Navigator, ProgramCategory, UrgentNeed
from rest_framework import viewsets, mixins
from rest_framework import permissions
from programs.serializers import ProgramSerializer, NavigatorAPISerializer, UrgentNeedAPISerializer
from programs.serializers import (
ProgramCategorySerializer,
NavigatorAPISerializer,
ProgramSerializerWithCategory,
UrgentNeedAPISerializer,
)


class ProgramViewSet(mixins.RetrieveModelMixin, mixins.ListModelMixin, viewsets.GenericViewSet):
"""
API endpoint that allows programs to be viewed or edited.
"""
queryset = Program.objects.filter(active=True, category__isnull=False)
serializer_class = ProgramSerializerWithCategory
permission_classes = [permissions.IsAuthenticated]


queryset = Program.objects.filter(active=True)
serializer_class = ProgramSerializer
class ProgramCategoryViewSet(mixins.RetrieveModelMixin, mixins.ListModelMixin, viewsets.GenericViewSet):
queryset = ProgramCategory.objects.filter(programs__isnull=False, programs__active=True).distinct()
serializer_class = ProgramCategorySerializer
permission_classes = [permissions.IsAuthenticated]


class NavigatorViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
"""
API endpoint that allows programs to be viewed or edited.
"""

queryset = Navigator.objects.all()
serializer_class = NavigatorAPISerializer
permission_classes = [permissions.IsAuthenticated]


class UrgentNeedViewSet(mixins.RetrieveModelMixin, mixins.ListModelMixin, viewsets.GenericViewSet):
"""
API endpoint that allows programs to be viewed or edited.
"""

queryset = UrgentNeed.objects.filter(active=True)
serializer_class = UrgentNeedAPISerializer
permission_classes = [permissions.IsAuthenticated]
2 changes: 1 addition & 1 deletion runtime.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
python-3.9.13
python-3.9.20
Loading

0 comments on commit 4f1f70d

Please sign in to comment.