Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: EligibilityType model fields for expiration - validation on model #1957

Merged
merged 4 commits into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions benefits/core/migrations/0003_eligibilitytype_expiration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Generated by Django 5.0.2 on 2024-03-14 20:48

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("core", "0002_paymentprocessor_backoffice_api"),
]

operations = [
migrations.AddField(
model_name="eligibilitytype",
name="expiration_days",
field=models.PositiveSmallIntegerField(blank=True, null=True),
),
migrations.AddField(
model_name="eligibilitytype",
name="expiration_reenrollment_days",
field=models.PositiveSmallIntegerField(blank=True, null=True),
),
migrations.AddField(
model_name="eligibilitytype",
name="supports_expiration",
field=models.BooleanField(default=False),
),
]
20 changes: 20 additions & 0 deletions benefits/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import logging

from django.conf import settings
from django.core.exceptions import ValidationError
from django.db import models
from django.urls import reverse

Expand Down Expand Up @@ -109,6 +110,9 @@ class EligibilityType(models.Model):
name = models.TextField()
label = models.TextField()
group_id = models.TextField()
supports_expiration = models.BooleanField(default=False)
expiration_days = models.PositiveSmallIntegerField(null=True, blank=True)
expiration_reenrollment_days = models.PositiveSmallIntegerField(null=True, blank=True)

def __str__(self):
return self.label
Expand All @@ -132,6 +136,22 @@ def get_names(eligibility_types):
eligibility_types = [eligibility_types]
return [t.name for t in eligibility_types if isinstance(t, EligibilityType)]

def clean(self):
supports_expiration = self.supports_expiration
expiration_days = self.expiration_days
expiration_reenrollment_days = self.expiration_reenrollment_days

if supports_expiration:
errors = {}
message = "When support_expiration is True, this value must be greater than 0."
if expiration_days is None or expiration_days <= 0:
errors.update(expiration_days=ValidationError(message))
if expiration_reenrollment_days is None or expiration_reenrollment_days <= 0:
errors.update(expiration_reenrollment_days=ValidationError(message))

if errors:
raise ValidationError(errors)


class EligibilityVerifier(models.Model):
"""An entity that verifies eligibility."""
Expand Down
75 changes: 75 additions & 0 deletions tests/pytest/core/test_models.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from django.conf import settings
from django.core.exceptions import ValidationError

import pytest

Expand All @@ -12,6 +13,45 @@ def mock_requests_get_pem_data(mocker):
return mocker.patch("benefits.core.models.requests.get", return_value=mocker.Mock(text="PEM text"))


@pytest.fixture
def model_EligibilityType_does_not_support_expiration(model_EligibilityType):
model_EligibilityType.supports_expiration = False
model_EligibilityType.expiration_days = 0
model_EligibilityType.save()

return model_EligibilityType


@pytest.fixture
def model_EligibilityType_zero_expiration_days(model_EligibilityType):
model_EligibilityType.supports_expiration = True
model_EligibilityType.expiration_days = 0
model_EligibilityType.expiration_reenrollment_days = 14
model_EligibilityType.save()

return model_EligibilityType


@pytest.fixture
def model_EligibilityType_zero_expiration_reenrollment_days(model_EligibilityType):
model_EligibilityType.supports_expiration = True
model_EligibilityType.expiration_days = 14
model_EligibilityType.expiration_reenrollment_days = 0
model_EligibilityType.save()

return model_EligibilityType


@pytest.fixture
def model_EligibilityType_supports_expiration(model_EligibilityType):
model_EligibilityType.supports_expiration = True
model_EligibilityType.expiration_days = 365
model_EligibilityType.expiration_reenrollment_days = 14
model_EligibilityType.save()

return model_EligibilityType


def test_SecretNameField_init():
field = SecretNameField()

Expand Down Expand Up @@ -180,6 +220,41 @@ def test_EligibilityVerifier_str(model_EligibilityVerifier):
assert str(model_EligibilityVerifier) == model_EligibilityVerifier.name


@pytest.mark.django_db
def test_EligibilityType_supports_expiration_False(model_EligibilityType_does_not_support_expiration):
# test will fail if any error is raised
model_EligibilityType_does_not_support_expiration.full_clean()


@pytest.mark.django_db
def test_EligibilityType_zero_expiration_days(model_EligibilityType_zero_expiration_days):
with pytest.raises(ValidationError) as exception_info:
model_EligibilityType_zero_expiration_days.full_clean()

error_dict = exception_info.value.error_dict
assert len(error_dict["expiration_days"]) == 1
assert error_dict["expiration_days"][0].message == "When support_expiration is True, this value must be greater than 0."


@pytest.mark.django_db
def test_EligibilityType_zero_expiration_reenrollment_days(model_EligibilityType_zero_expiration_reenrollment_days):
with pytest.raises(ValidationError) as exception_info:
model_EligibilityType_zero_expiration_reenrollment_days.full_clean()

error_dict = exception_info.value.error_dict
assert len(error_dict["expiration_reenrollment_days"]) == 1
assert (
error_dict["expiration_reenrollment_days"][0].message
== "When support_expiration is True, this value must be greater than 0."
)


@pytest.mark.django_db
def test_EligibilityType_supports_expiration(model_EligibilityType_supports_expiration):
# test will fail if any error is raised
model_EligibilityType_supports_expiration.full_clean()


class SampleFormClass:
"""A class for testing EligibilityVerifier form references."""

Expand Down
Loading