Skip to content

Commit

Permalink
Merge pull request #1497 from MZaFaRM/dev
Browse files Browse the repository at this point in the history
[FEAT] Org to Org link iteration #1
  • Loading branch information
MZaFaRM authored Nov 1, 2023
2 parents 6ef2d63 + 33a174c commit 9d36539
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 83 deletions.
89 changes: 39 additions & 50 deletions api/dashboard/organisation/organisation_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
AffiliationSerializer,
DepartmentSerializer,
InstitutionCreateUpdateSerializer,
InstitutionSerializer, InstitutionPrefillSerializer,
InstitutionSerializer,
InstitutionPrefillSerializer,
OrganizationMergerSerializer,
)


Expand Down Expand Up @@ -129,19 +131,15 @@ def delete(self, request, org_code):

class InstitutionAPI(APIView):
def get(self, request, org_type, district_id=None):

if district_id:
organisations = Organization.objects.filter(
org_type=org_type,
district_id=district_id
org_type=org_type, district_id=district_id
)
else:
organisations = Organization.objects.filter(
org_type=org_type
)
organisations = Organization.objects.filter(org_type=org_type)

org_queryset = organisations.select_related(
'affiliation',
"affiliation",
# 'district',
# "district__zone__state__country",
# "district__zone__state",
Expand Down Expand Up @@ -197,9 +195,8 @@ class InstitutionCSVAPI(APIView):
@role_required([RoleType.ADMIN.value])
def get(self, request, org_type):
organizations = (
Organization.objects.filter(
org_type=org_type
).select_related(
Organization.objects.filter(org_type=org_type)
.select_related(
"affiliation",
# "district__zone__state__country",
# "district__zone__state",
Expand All @@ -216,15 +213,9 @@ def get(self, request, org_type):
)
)

serializer = InstitutionSerializer(
organizations,
many=True
).data
serializer = InstitutionSerializer(organizations, many=True).data

return CommonUtils.generate_csv(
serializer,
f"{org_type} data"
)
return CommonUtils.generate_csv(serializer, f"{org_type} data")


class InstitutionDetailsAPI(APIView):
Expand Down Expand Up @@ -287,22 +278,13 @@ class AffiliationGetPostUpdateDeleteAPI(APIView):
def get(self, request):
affiliation = OrgAffiliation.objects.all()
paginated_queryset = CommonUtils.get_paginated_queryset(
affiliation,
request,
[
"id",
"title"
]
affiliation, request, ["id", "title"]
)
serializer = AffiliationSerializer(
paginated_queryset.get("queryset"),
many=True
paginated_queryset.get("queryset"), many=True
)
return CustomResponse().paginated_response(
data=serializer.data,
pagination=paginated_queryset.get(
"pagination"
)
data=serializer.data, pagination=paginated_queryset.get("pagination")
)

@role_required([RoleType.ADMIN.value])
Expand All @@ -323,9 +305,7 @@ def post(self, request):
general_message=f"{request.data.get('title')} added successfully"
).get_success_response()

return CustomResponse(
general_message=serializer.errors
).get_failure_response()
return CustomResponse(general_message=serializer.errors).get_failure_response()

@role_required([RoleType.ADMIN.value])
def put(self, request, affiliation_id):
Expand Down Expand Up @@ -432,15 +412,9 @@ def delete(self, request, department_id):
class AffiliationListAPI(APIView):
@role_required([RoleType.ADMIN.value])
def get(self, request):
affiliation = OrgAffiliation.objects.all().values("id", "title")

affiliation = OrgAffiliation.objects.all().values(
'id',
'title'
)

return CustomResponse(
response=affiliation
).get_success_response()
return CustomResponse(response=affiliation).get_success_response()


class InstitutionPrefillAPI(APIView):
Expand All @@ -450,14 +424,29 @@ class InstitutionPrefillAPI(APIView):
]
)
def get(self, request, org_code):

organization = Organization.objects.filter(code=org_code).first()

serializer = InstitutionPrefillSerializer(
organization,
many=False
).data
serializer = InstitutionPrefillSerializer(organization, many=False).data

return CustomResponse(
response=serializer
).get_success_response()
return CustomResponse(response=serializer).get_success_response()


class OrganizationMergerView(APIView):
def patch(self, request, organisation_id):
try:
destination = Organization.objects.get(pk=organisation_id)
serializer = OrganizationMergerSerializer(destination, data=request.data)
if not serializer.is_valid():
return CustomResponse(
general_message=serializer.errors
).get_failure_response()
serializer.save()

return CustomResponse(
general_message=f"Organizations merged successfully into {destination.title}."
).get_success_response()

except Organization.DoesNotExist as e:
return CustomResponse(
general_message="Organisation id that was given to merge into does not exist"
).get_failure_response()
127 changes: 96 additions & 31 deletions api/dashboard/organisation/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,20 @@

from django.db.models import Count
from rest_framework import serializers

from db.organization import Organization, District, Zone, State, OrgAffiliation, Department
from django.db import models

from db.organization import (
Organization,
District,
Zone,
State,
OrgAffiliation,
Department,
)
from utils.permission import JWTUtils
from utils.types import OrganizationType
from django.db import transaction
from django.forms.models import model_to_dict


class InstitutionSerializer(serializers.ModelSerializer):
Expand All @@ -27,15 +37,11 @@ class Meta:
"zone",
"state",
"country",
"user_count"
"user_count",
]

def get_user_count(self, obj):
return obj.user_organization_link_org.annotate(
user_count=Count(
'user'
)
).count()
return obj.user_organization_link_org.annotate(user_count=Count("user")).count()


# class InstitutionSerializer(serializers.ModelSerializer):
Expand Down Expand Up @@ -142,15 +148,12 @@ def validate_affiliation(self, affiliation_id):


class AffiliationSerializer(serializers.ModelSerializer):
label = serializers.ReadOnlyField(source='title')
value = serializers.ReadOnlyField(source='id')
label = serializers.ReadOnlyField(source="title")
value = serializers.ReadOnlyField(source="id")

class Meta:
model = OrgAffiliation
fields = [
"value",
"label"
]
fields = ["value", "label"]


class AffiliationCreateUpdateSerializer(serializers.ModelSerializer):
Expand All @@ -174,14 +177,10 @@ def update(self, instance, validated_data):
return instance

def validate_title(self, title):
org_affiliation = OrgAffiliation.objects.filter(
title=title
).first()
org_affiliation = OrgAffiliation.objects.filter(title=title).first()

if org_affiliation:
raise serializers.ValidationError(
"Affiliation already exist"
)
raise serializers.ValidationError("Affiliation already exist")

return title

Expand Down Expand Up @@ -212,16 +211,20 @@ def update(self, instance, validated_data):


class InstitutionPrefillSerializer(serializers.ModelSerializer):
affiliation_id = serializers.CharField(source='affiliation.id', allow_null=True)
affiliation_name = serializers.CharField(source='affiliation.name', allow_null=True)
district_id = serializers.CharField(source='district.id', allow_null=True)
district_name = serializers.CharField(source='district.name', allow_null=True)
zone_id = serializers.CharField(source='district.zone.id', allow_null=True)
zone_name = serializers.CharField(source='district.zone.name', allow_null=True)
state_id = serializers.CharField(source='district.state.id', allow_null=True)
state_name = serializers.CharField(source='district.state.name', allow_null=True)
country_id = serializers.CharField(source='district.state.country.id', allow_null=True)
country_name = serializers.CharField(source='district.state.country.name', allow_null=True)
affiliation_id = serializers.CharField(source="affiliation.id", allow_null=True)
affiliation_name = serializers.CharField(source="affiliation.name", allow_null=True)
district_id = serializers.CharField(source="district.id", allow_null=True)
district_name = serializers.CharField(source="district.name", allow_null=True)
zone_id = serializers.CharField(source="district.zone.id", allow_null=True)
zone_name = serializers.CharField(source="district.zone.name", allow_null=True)
state_id = serializers.CharField(source="district.state.id", allow_null=True)
state_name = serializers.CharField(source="district.state.name", allow_null=True)
country_id = serializers.CharField(
source="district.state.country.id", allow_null=True
)
country_name = serializers.CharField(
source="district.state.country.name", allow_null=True
)

class Meta:
model = Organization
Expand All @@ -239,4 +242,66 @@ class Meta:
"state_name",
"country_id",
"country_name",
]
]


class OrganizationMergerSerializer(serializers.Serializer):
remove_code = serializers.SlugRelatedField(
slug_field="code", queryset=Organization.objects.all()
)

def validate(self, attrs):
if self.instance.code == attrs.get("remove_code"):
raise serializers.ValidationError(
"Keep code and remove code should not be the same."
)
return super().validate(attrs)

def update(self, instance, validated_data):
with transaction.atomic():
remove_org = validated_data["remove_code"]

# Fetch and iterate over all relations to the Organization model
for relation in Organization._meta.related_objects:
# We're interested in ForeignKey relations only
if isinstance(
relation,
(models.ForeignKey, models.OneToOneField, models.ManyToManyField),
):
related_model = relation.related_model
related_field_name = relation.field.name
elif isinstance(
relation,
(models.ManyToOneRel, models.ManyToManyRel, models.OneToOneRel),
):
related_model = relation.related_model
related_field_name = None
for field in related_model._meta.fields:
if (
isinstance(field, models.ForeignKey)
and field.related_model == Organization
):
related_field_name = field.name
break

if (
not related_field_name
): # If the related field is not found, skip
continue
else:
continue # Skip other types of relations

# Update the ForeignKey in the related model
filter_kwargs = {related_field_name: remove_org}
update_kwargs = {related_field_name: instance}
relation_instance = related_model.objects.filter(**filter_kwargs)
if isinstance(relation, (models.OneToOneField, models.OneToOneRel)):
if existing_college := related_model.objects.filter(
**{related_field_name: instance}
):
existing_college.delete()

relation_instance.update(**update_kwargs)
remove_org.delete()

return instance
1 change: 1 addition & 0 deletions api/dashboard/organisation/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@
path('departments/edit/<str:department_id>/', organisation_views.DepartmentAPI.as_view()),
path('departments/delete/<str:department_id>/', organisation_views.DepartmentAPI.as_view()),
path('affiliation/list/', organisation_views.AffiliationListAPI.as_view()),
path('merge_organizations/<str:organisation_id>/', organisation_views.OrganizationMergerView.as_view())
]
4 changes: 2 additions & 2 deletions db/organization.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ class Meta:
class College(models.Model):
id = models.CharField(primary_key=True, max_length=36)
level = models.IntegerField()
org = models.ForeignKey(Organization, on_delete=models.CASCADE, related_name='college_org')
org = models.OneToOneField(Organization, on_delete=models.CASCADE, related_name='college_org', unique=True)
updated_by = models.ForeignKey(User, on_delete=models.CASCADE, db_column='updated_by', related_name='college_updated_by')
updated_at = models.DateTimeField(auto_now=True)
created_by = models.ForeignKey(User, on_delete=models.CASCADE, db_column='created_by', related_name='college_created_by')
Expand All @@ -132,7 +132,7 @@ class Meta:
class OrgDiscordLink(models.Model):
id = models.CharField(primary_key=True, max_length=36)
discord_id = models.CharField(unique=True, max_length=36)
org = models.ForeignKey(Organization, on_delete=models.CASCADE, related_name='org_discord_link_org_id')
org = models.OneToOneField(Organization, on_delete=models.CASCADE, related_name='org_discord_link_org_id')
updated_by = models.ForeignKey(User, on_delete=models.CASCADE, db_column='updated_by', related_name='org_discord_link_updated_by')
updated_at = models.DateTimeField(auto_now=True)
created_by = models.ForeignKey(User, on_delete=models.CASCADE, db_column='created_by', related_name='org_discord_link_created_by')
Expand Down

0 comments on commit 9d36539

Please sign in to comment.