Skip to content

Commit

Permalink
DCT limit_to > available_for
Browse files Browse the repository at this point in the history
  • Loading branch information
pavlo-mk committed Mar 5, 2024
1 parent b3b9d56 commit b10c0a4
Show file tree
Hide file tree
Showing 21 changed files with 70 additions and 38 deletions.
4 changes: 2 additions & 2 deletions backend/hct_mis_api/apps/core/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -730,10 +730,10 @@ class DataCollectingTypeAdmin(AdminFiltersMixin, admin.ModelAdmin):
"recalculate_composition",
)
list_filter = (
("limit_to", AutoCompleteFilter),
("available_for", AutoCompleteFilter),
"active",
"individual_filters_available",
"household_filters_available",
"recalculate_composition",
)
filter_horizontal = ("compatible_types", "limit_to")
filter_horizontal = ("compatible_types", "available_for")
2 changes: 1 addition & 1 deletion backend/hct_mis_api/apps/core/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,4 @@ def business_areas(self, create: Any, extracted: List[Any], **kwargs: Any) -> No

if extracted:
for business_area in extracted:
self.limit_to.add(business_area)
self.available_for.add(business_area)
14 changes: 7 additions & 7 deletions backend/hct_mis_api/apps/core/fixtures/data.json
Original file line number Diff line number Diff line change
Expand Up @@ -6667,7 +6667,7 @@
"individual_filters_available": true,
"household_filters_available": true,
"compatible_types": [1, 2, 3],
"limit_to": ["c259b1a0-ae3a-494e-b343-f7c8eb060c68", "3e269a73-123b-43e1-86af-ced1b30d8e80"]
"available_for": ["c259b1a0-ae3a-494e-b343-f7c8eb060c68", "3e269a73-123b-43e1-86af-ced1b30d8e80"]
}
},
{
Expand All @@ -6684,7 +6684,7 @@
"individual_filters_available": false,
"household_filters_available": true,
"compatible_types": [2, 3],
"limit_to": ["c259b1a0-ae3a-494e-b343-f7c8eb060c68", "3e269a73-123b-43e1-86af-ced1b30d8e80"]
"available_for": ["c259b1a0-ae3a-494e-b343-f7c8eb060c68", "3e269a73-123b-43e1-86af-ced1b30d8e80"]
}
},
{
Expand All @@ -6701,7 +6701,7 @@
"individual_filters_available": true,
"household_filters_available": true,
"compatible_types": [3],
"limit_to": ["c259b1a0-ae3a-494e-b343-f7c8eb060c68", "3e269a73-123b-43e1-86af-ced1b30d8e80"]
"available_for": ["c259b1a0-ae3a-494e-b343-f7c8eb060c68", "3e269a73-123b-43e1-86af-ced1b30d8e80"]
}
},
{
Expand All @@ -6717,7 +6717,7 @@
"individual_filters_available": false,
"household_filters_available": true,
"compatible_types": [4],
"limit_to": ["c259b1a0-ae3a-494e-b343-f7c8eb060c68", "3e269a73-123b-43e1-86af-ced1b30d8e80"]
"available_for": ["c259b1a0-ae3a-494e-b343-f7c8eb060c68", "3e269a73-123b-43e1-86af-ced1b30d8e80"]
}
},
{
Expand All @@ -6733,7 +6733,7 @@
"individual_filters_available": false,
"household_filters_available": false,
"compatible_types": [5],
"limit_to": ["c259b1a0-ae3a-494e-b343-f7c8eb060c68", "3e269a73-123b-43e1-86af-ced1b30d8e80"]
"available_for": ["c259b1a0-ae3a-494e-b343-f7c8eb060c68", "3e269a73-123b-43e1-86af-ced1b30d8e80"]
}
},
{
Expand All @@ -6748,7 +6748,7 @@
"active": false,
"individual_filters_available": true,
"compatible_types": [],
"limit_to": ["c259b1a0-ae3a-494e-b343-f7c8eb060c68", "3e269a73-123b-43e1-86af-ced1b30d8e80"]
"available_for": ["c259b1a0-ae3a-494e-b343-f7c8eb060c68", "3e269a73-123b-43e1-86af-ced1b30d8e80"]
}
},
{
Expand All @@ -6764,7 +6764,7 @@
"deprecated": true,
"individual_filters_available": true,
"compatible_types": [],
"limit_to": ["c259b1a0-ae3a-494e-b343-f7c8eb060c68", "3e269a73-123b-43e1-86af-ced1b30d8e80"]
"available_for": ["c259b1a0-ae3a-494e-b343-f7c8eb060c68", "3e269a73-123b-43e1-86af-ced1b30d8e80"]
}
},
{
Expand Down
18 changes: 18 additions & 0 deletions backend/hct_mis_api/apps/core/migrations/0078_migration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.2.24 on 2024-03-05 14:11

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('core', '0077_migration'),
]

operations = [
migrations.RenameField(
model_name='datacollectingtype',
old_name='limit_to',
new_name='available_for',
),
]
2 changes: 1 addition & 1 deletion backend/hct_mis_api/apps/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ class Type(models.TextChoices):
type = models.CharField(choices=Type.choices, null=True, blank=True, max_length=32)
description = models.TextField(blank=True)
compatible_types = models.ManyToManyField("self", blank=True, symmetrical=False)
limit_to = models.ManyToManyField(to="BusinessArea", related_name="data_collecting_types", blank=True)
available_for = models.ManyToManyField(to="BusinessArea", related_name="data_collecting_types", blank=True)
active = models.BooleanField(default=True)
deprecated = models.BooleanField(
default=False, help_text="Cannot be used in new programs, totally hidden in UI, only admin have access"
Expand Down
6 changes: 5 additions & 1 deletion backend/hct_mis_api/apps/core/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

from django.core.exceptions import ObjectDoesNotExist
from django.db import models
from django.db.models import Q

import graphene
from constance import config
Expand Down Expand Up @@ -407,9 +408,12 @@ def resolve_all_languages(self, info: Any, code: str, **kwargs: Any) -> List[Lan
def resolve_data_collection_type_choices(self, info: Any, **kwargs: Any) -> List[Dict[str, Any]]:
data_collecting_types = (
DataCollectingType.objects.filter(
Q(
Q(available_for__slug=info.context.headers.get("Business-Area").lower())
| Q(available_for__isnull=True)
),
active=True,
deprecated=False,
limit_to__slug=info.context.headers.get("Business-Area").lower(),
)
.exclude(code__iexact="unknown")
.only("code", "label", "description")
Expand Down
6 changes: 3 additions & 3 deletions backend/hct_mis_api/apps/core/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,9 +329,9 @@ def validate_data_collecting_type(cls, *args: Any, **kwargs: Any) -> Optional[No
program = kwargs.get("program")
business_area = kwargs.get("business_area") or getattr(program, "business_area", None)

# validate program BA and DCT.limit_to
if data_collecting_type and business_area:
if business_area not in data_collecting_type.limit_to.all():
# validate program BA and DCT.available_for
if data_collecting_type and business_area and data_collecting_type.available_for.all().count() > 0:
if business_area not in data_collecting_type.available_for.all():
raise ValidationError("This Data Collection Type is not assigned to the Program's Business Area")

# user can update the program and don't update data collecting type
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ def setUpTestData(cls) -> None:
cls.data_collecting_type = DataCollectingType.objects.create(
code="full", description="Full individual collected", active=True
)
cls.data_collecting_type.limit_to.add(cls.business_area)
cls.data_collecting_type.available_for.add(cls.business_area)

@patch("hct_mis_api.apps.payment.models.PaymentPlan.get_exchange_rate", return_value=2.0)
def test_receiving_reconciliations_from_fsp(self, mock_get_exchange_rate: Any) -> None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def setUpTestData(cls) -> None:
cls.data_collecting_type = DataCollectingType.objects.create(
code="full", description="Full individual collected", active=True
)
cls.data_collecting_type.limit_to.add(cls.business_area)
cls.data_collecting_type.available_for.add(cls.business_area)

cls.create_program_mutation_variables = {
"programData": {
Expand Down
7 changes: 6 additions & 1 deletion backend/hct_mis_api/apps/program/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,9 +236,14 @@ def resolve_cash_plan_status_choices(self, info: Any, **kwargs: Any) -> List[Dic
def resolve_data_collecting_type_choices(self, info: Any, **kwargs: Any) -> List[Dict[str, Any]]:
return list(
DataCollectingType.objects.filter(
Q(
Q(
available_for__slug=info.context.headers.get("Business-Area").lower(),
)
| Q(available_for__isnull=True)
),
active=True,
deprecated=False,
limit_to__slug=info.context.headers.get("Business-Area").lower(),
)
.exclude(code__iexact="unknown")
.annotate(name=F("label"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def test_status_change(
data_collecting_type, _ = DataCollectingType.objects.update_or_create(
**{"label": "Full", "code": "full_collection", "description": "Full"}
)
data_collecting_type.limit_to.add(self.business_area)
data_collecting_type.available_for.add(self.business_area)
program = ProgramFactory.create(
status=initial_status,
business_area=self.business_area,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def setUpTestData(cls) -> None:
active=True,
individual_filters_available=True,
)
cls.data_collecting_type.limit_to.add(cls.business_area)
cls.data_collecting_type.available_for.add(cls.business_area)
cls.program_data = {
"programData": {
"name": "Test",
Expand Down Expand Up @@ -112,7 +112,6 @@ def test_create_program_with_deprecated_dct(self) -> None:
dct, _ = DataCollectingType.objects.update_or_create(
**{"label": "Deprecated", "code": "deprecated", "description": "Deprecated", "deprecated": True}
)
dct.limit_to.add(self.business_area)
self.create_user_role_with_permissions(self.user, [Permissions.PROGRAMME_CREATE], self.business_area)

program_data = self.program_data
Expand All @@ -126,7 +125,6 @@ def test_create_program_with_inactive_dct(self) -> None:
dct, _ = DataCollectingType.objects.update_or_create(
**{"label": "Inactive", "code": "inactive", "description": "Inactive", "active": False}
)
dct.limit_to.add(self.business_area)
self.create_user_role_with_permissions(self.user, [Permissions.PROGRAMME_CREATE], self.business_area)

program_data = self.program_data
Expand Down
8 changes: 4 additions & 4 deletions backend/hct_mis_api/apps/program/tests/test_update_program.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def test_update_program_authenticated(
def test_update_active_program_with_dct(self) -> None:
self.create_user_role_with_permissions(self.user, [Permissions.PROGRAMME_UPDATE], self.business_area)
data_collecting_type = DataCollectingType.objects.get(code="full_collection")
data_collecting_type.limit_to.add(self.business_area)
data_collecting_type.available_for.add(self.business_area)
Program.objects.filter(id=self.program.id).update(
status=Program.ACTIVE, data_collecting_type=data_collecting_type
)
Expand All @@ -137,7 +137,7 @@ def test_update_active_program_with_dct(self) -> None:
def test_update_draft_not_empty_program_with_dct(self) -> None:
self.create_user_role_with_permissions(self.user, [Permissions.PROGRAMME_UPDATE], self.business_area)
data_collecting_type = DataCollectingType.objects.get(code="full_collection")
data_collecting_type.limit_to.add(self.business_area)
data_collecting_type.available_for.add(self.business_area)
create_household(household_args={"program": self.program})

self.snapshot_graphql_request(
Expand All @@ -158,7 +158,7 @@ def test_update_program_with_deprecated_dct(self) -> None:
dct, _ = DataCollectingType.objects.update_or_create(
**{"label": "Deprecated", "code": "deprecated", "description": "Deprecated", "deprecated": True}
)
dct.limit_to.add(self.business_area)
dct.available_for.add(self.business_area)

self.create_user_role_with_permissions(self.user, [Permissions.PROGRAMME_UPDATE], self.business_area)

Expand All @@ -179,7 +179,7 @@ def test_update_program_with_inactive_dct(self) -> None:
dct, _ = DataCollectingType.objects.update_or_create(
**{"label": "Inactive", "code": "inactive", "description": "Inactive", "active": False}
)
dct.limit_to.add(self.business_area)
dct.available_for.add(self.business_area)

self.create_user_role_with_permissions(self.user, [Permissions.PROGRAMME_UPDATE], self.business_area)

Expand Down
6 changes: 5 additions & 1 deletion backend/hct_mis_api/apps/program/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,12 @@ def validate_data_collecting_type(
original_program_data_collecting_type: Optional["DataCollectingType"] = None,
data_collecting_type: Optional["DataCollectingType"] = None,
) -> None:
if business_area not in data_collecting_type.limit_to.all():
if (
data_collecting_type.available_for.all().count() > 0
and business_area not in data_collecting_type.available_for.all()
):
raise ValidationError("This Data Collection Type is not assigned to the Program's Business Area")

if not original_program_data_collecting_type:
raise ValidationError("The original Programme must have a Data Collection Type.")
elif (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def setUp(cls) -> None:
cls.business_area = BusinessAreaFactory(slug="some-czech-slug")

cls.data_collecting_type = DataCollectingType.objects.create(label="someLabel", code="some_label")
cls.data_collecting_type.limit_to.add(cls.business_area)
cls.data_collecting_type.available_for.add(cls.business_area)

cls.program = ProgramFactory(status="ACTIVE", data_collecting_type=cls.data_collecting_type)
cls.organization = OrganizationFactory(business_area=cls.business_area, slug=cls.business_area.slug)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def setUp(cls) -> None:
cls.business_area = BusinessAreaFactory(slug="generic-slug")

cls.data_collecting_type = DataCollectingType.objects.create(label="SomeFull", code="some_full")
cls.data_collecting_type.limit_to.add(cls.business_area)
cls.data_collecting_type.available_for.add(cls.business_area)

cls.program = ProgramFactory(status="ACTIVE", data_collecting_type=cls.data_collecting_type)
cls.organization = OrganizationFactory(business_area=cls.business_area, slug=cls.business_area.slug)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def setUp(cls) -> None:

cls.business_area = BusinessAreaFactory(slug="sri-lanka2")
cls.data_collecting_type = DataCollectingType.objects.create(label="SizeOnlyXYZ", code="size_onlyXYZ")
cls.data_collecting_type.limit_to.add(cls.business_area)
cls.data_collecting_type.available_for.add(cls.business_area)

cls.program = ProgramFactory(status="ACTIVE", data_collecting_type=cls.data_collecting_type)
cls.organization = OrganizationFactory(business_area=cls.business_area, slug=cls.business_area.slug)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def setUpTestData(cls) -> None:
cls.business_area = BusinessAreaFactory(slug="some-ukraine-slug")

cls.data_collecting_type = DataCollectingType.objects.create(label="SomeFull", code="some_full")
cls.data_collecting_type.limit_to.add(cls.business_area)
cls.data_collecting_type.available_for.add(cls.business_area)

cls.program = ProgramFactory(status="ACTIVE", data_collecting_type=cls.data_collecting_type)
cls.organization = OrganizationFactory(business_area=cls.business_area, slug=cls.business_area.slug)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,10 @@ def validate_data_collection_type(self) -> None:
if data_collecting_type.deprecated:
raise ValidationError("Data Collecting Type of program is deprecated")

if business_area not in data_collecting_type.limit_to.all():
if (
data_collecting_type.available_for.all().count() > 0
and business_area not in data_collecting_type.available_for.all()
):
raise ValidationError(
f"{business_area.slug.capitalize()} is not limited for DataCollectingType: {data_collecting_type.code}"
)
Expand Down
2 changes: 1 addition & 1 deletion backend/selenium_tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ def create_super_user() -> User:
data_collecting_type = DataCollectingType.objects.create(
label=dct["label"], code=dct["code"], description=dct["description"], active=dct["active"]
)
data_collecting_type.limit_to.add(business_area)
data_collecting_type.available_for.add(business_area)
data_collecting_type.save()

partner.permissions = {
Expand Down
10 changes: 5 additions & 5 deletions backend/specific.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"active": true,
"individual_filters_available": false,
"compatible_types": [],
"limit_to": []
"available_for": []
}
},
{
Expand All @@ -24,7 +24,7 @@
"active": true,
"individual_filters_available": false,
"compatible_types": [],
"limit_to": []
"available_for": []
}
},
{
Expand All @@ -38,7 +38,7 @@
"active": true,
"individual_filters_available": false,
"compatible_types": [],
"limit_to": []
"available_for": []
}
},
{
Expand All @@ -52,7 +52,7 @@
"active": true,
"individual_filters_available": false,
"compatible_types": [],
"limit_to": []
"available_for": []
}
},
{
Expand All @@ -66,7 +66,7 @@
"active": true,
"individual_filters_available": false,
"compatible_types": [],
"limit_to": []
"available_for": []
}
}
]

0 comments on commit b10c0a4

Please sign in to comment.