From 42c5648a512e2f7410eec17748c96a4d1b2b3f7a Mon Sep 17 00:00:00 2001 From: Sudan Bhandari Date: Wed, 23 Oct 2024 10:59:52 +0545 Subject: [PATCH] Add status in geo area and retriggered when geo area is failed Update migration --- apps/geo/enums.py | 19 +++++++++++ apps/geo/migrations/0044_region_status.py | 18 ++++++++++ apps/geo/models.py | 6 ++++ apps/geo/mutations.py | 40 +++++++++++++++++++++++ apps/geo/schema.py | 5 ++- apps/geo/serializers.py | 1 + apps/geo/tasks.py | 8 ++++- schema.graphql | 16 +++++++++ 8 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 apps/geo/migrations/0044_region_status.py diff --git a/apps/geo/enums.py b/apps/geo/enums.py index 78ca1d46ca..b421ac3610 100644 --- a/apps/geo/enums.py +++ b/apps/geo/enums.py @@ -1,4 +1,10 @@ import graphene +from geo.models import Region + +from utils.graphene.enums import ( + convert_enum_to_graphene_enum, + get_enum_name_from_django_field, +) class GeoAreaOrderingEnum(graphene.Enum): @@ -8,3 +14,16 @@ class GeoAreaOrderingEnum(graphene.Enum): # DESC DESC_ID = f'-{ASC_ID}' DESC_ADMIN_LEVEL = f'-{ASC_ADMIN_LEVEL}' + + +RegionStatusEnum = convert_enum_to_graphene_enum( + Region.Status, name='RegionStatusEnum' +) + + +enum_map = { + get_enum_name_from_django_field(field): enum + for field, enum in ( + (Region.status, RegionStatusEnum), + ) +} diff --git a/apps/geo/migrations/0044_region_status.py b/apps/geo/migrations/0044_region_status.py new file mode 100644 index 0000000000..5ba1d6ddc8 --- /dev/null +++ b/apps/geo/migrations/0044_region_status.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.25 on 2024-12-05 04:25 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('geo', '0043_create-unaccent_extension'), + ] + + operations = [ + migrations.AddField( + model_name='region', + name='status', + field=models.PositiveSmallIntegerField(choices=[(0, 'Initiated'), (1, 'Pending'), (2, 'Completed'), (3, 'Failed')], default=1), + ), + ] diff --git a/apps/geo/models.py b/apps/geo/models.py index d0be464d21..bf45cd3d3e 100644 --- a/apps/geo/models.py +++ b/apps/geo/models.py @@ -14,6 +14,11 @@ class Region(UserResource): + class Status(models.IntegerChoices): + INITIATED = 0, 'Initiated' + PENDING = 1, 'Pending' + COMPLETED = 2, 'Completed' + FAILED = 3, 'Failed' """ Region model @@ -35,6 +40,7 @@ class Region(UserResource): cache_index = models.SmallIntegerField(default=0) # Used to track cache update. centroid = models.PointField(blank=True, null=True) # Admin level 0 centroid geo_options = models.JSONField(default=None, blank=True, null=True) + status = models.PositiveSmallIntegerField(choices=Status.choices, default=Status.PENDING) def __init__(self, *args, **kwargs): self.id: Union[int, None] diff --git a/apps/geo/mutations.py b/apps/geo/mutations.py index e43cf8090a..58538b405a 100644 --- a/apps/geo/mutations.py +++ b/apps/geo/mutations.py @@ -1,3 +1,4 @@ +from geo.tasks import load_geo_areas import graphene from geo.models import Region, AdminLevel @@ -134,6 +135,44 @@ def mutate(root, info, id): return PublishRegion(result=instance, errors=None, ok=True) +class ReTriggeredFailedRegion(graphene.Mutation): + class Arguments: + region_id = graphene.ID(required=True) + model = Region + errors = graphene.List(graphene.NonNull(CustomErrorType)) + ok = graphene.Boolean() + result = graphene.Field(RegionType) + + @staticmethod + def mutate(root, info, region_id): + instance = Region.objects.filter( + id=region_id + ).first() + error_data = [] + if instance is None: + error_data.append('Region does\'t exist') + elif instance.status == Region.Status.COMPLETED: + error_data.append('Geo Area already generated') + elif instance.created_by != info.context.user: + error_data.append('Authorized User only update region') + elif instance.is_published: + error_data.append("Published Region cannot be retiggered") + + if error_data: + return ReTriggeredFailedRegion(errors=[ + dict( + field='nonFieldErrors', + messages=error_data + ) + ], ok=False) + load_geo_areas(region_id) + return ReTriggeredFailedRegion( + result=instance, + error=None, + ok=True + ) + + class Mutation(): create_region = CreateRegion.Field() update_region = UpdateRegion.Field() @@ -141,3 +180,4 @@ class Mutation(): publish_region = PublishRegion.Field() update_admin_level = UpdateAdminLevel.Field() delete_admin_level = DeleteAdminLevel.Field() + retrigger_region = ReTriggeredFailedRegion.Field() diff --git a/apps/geo/schema.py b/apps/geo/schema.py index 0055464d69..c5adc549b9 100644 --- a/apps/geo/schema.py +++ b/apps/geo/schema.py @@ -1,3 +1,4 @@ +from geo.enums import RegionStatusEnum import graphene from graphene_django import DjangoObjectType from graphene_django_extras import DjangoObjectField, PageGraphqlPagination @@ -53,12 +54,14 @@ def get_custom_queryset(queryset, info, **kwargs): class RegionType(DjangoObjectType, ClientIdMixin): + status = graphene.Field(RegionStatusEnum) + class Meta: model = Region only_fields = ( 'id', 'title', 'public', 'regional_groups', 'key_figures', 'population_data', 'media_sources', - 'centroid', 'is_published', + 'centroid', 'is_published', 'status' ) @staticmethod diff --git a/apps/geo/serializers.py b/apps/geo/serializers.py index cf70db9571..b98a843318 100644 --- a/apps/geo/serializers.py +++ b/apps/geo/serializers.py @@ -111,6 +111,7 @@ def create(self, validated_data): admin_level.save() region = admin_level.region + region.status = Region.Status.INITIATED region.modified_by = self.context['request'].user region.save() diff --git a/apps/geo/tasks.py b/apps/geo/tasks.py index 90dab4fc2c..2a5a873b2f 100644 --- a/apps/geo/tasks.py +++ b/apps/geo/tasks.py @@ -210,13 +210,19 @@ def load_geo_areas(region_id): have_lock = lock.acquire(blocking=False) if not have_lock: return False - + region = Region.objects.filter(id=region_id).first() + if not region: + logger.error("Region not found", exc_info=True) + return False try: return_value = _load_geo_areas(region_id) + region.status = Region.Status.COMPLETED except Exception: logger.error('Load Geo Areas', exc_info=True) return_value = False + region.status = Region.Status.FAILED + region.save() lock.release() return return_value diff --git a/schema.graphql b/schema.graphql index c1aecdab70..e1ba512bcd 100644 --- a/schema.graphql +++ b/schema.graphql @@ -5124,6 +5124,7 @@ type Mutation { publishRegion(id: ID!): PublishRegion updateAdminLevel(data: AdminLevelInputType!, id: ID!): UpdateAdminLevel deleteAdminLevel(adminLevelId: ID!): DeleteAdminLevel + retriggerRegion(regionId: ID!): ReTriggeredFailedRegion organizationCreate(data: OrganizationInputType!): OrganizationCreate createAssessmentRegSummaryIssue(data: AssessmentRegistrySummaryIssueCreateInputType!): AssessmentRegistryCreateIssue fileUpload(data: FileUploadInputType!): UploadFile @@ -5970,6 +5971,12 @@ type QuestionType { subSectorDisplay: EnumDescription } +type ReTriggeredFailedRegion { + errors: [GenericScalar!] + ok: Boolean + result: RegionType +} + type RecentActivityType { id: ID! createdAt: DateTime @@ -6004,6 +6011,7 @@ type RegionDetailType { mediaSources: GenericScalar centroid: PointScalar clientId: ID! + status: RegionStatusEnum adminLevels: [AdminLevelType!]! } @@ -6043,6 +6051,13 @@ input RegionProjectFilterData { isTest: Boolean } +enum RegionStatusEnum { + INITIATED + PENDING + COMPLETED + FAILED +} + type RegionType { id: ID! title: String! @@ -6053,6 +6068,7 @@ type RegionType { populationData: GenericScalar mediaSources: GenericScalar centroid: PointScalar + status: RegionStatusEnum clientId: ID! }