Files
RasadDam_Backend/apps/authentication/api/v1/serializers/serializer.py

369 lines
13 KiB
Python

import typing
from django.contrib.auth.hashers import make_password
from django.db.models import Q
from rest_framework import serializers
from apps.authentication.exceptions import UserExistException, OrganizationNationalUniqueIDException, \
OrganizationTypeRepeatableException, BankAccountExistException, BankAccountNumberAccountException, \
BankAccountCardException, BankAccountShebaException
from apps.authentication.models import (
User,
City,
Province,
Organization,
OrganizationType,
OrganizationStats,
BankAccountInformation
)
from apps.authorization import models as authorize_models
from apps.authorization.api.v1.serializers import (
UserRelationSerializer
)
class CitySerializer(serializers.ModelSerializer):
""" Serialize city data """
class Meta:
model = City
fields = [
'id',
'name',
'province'
]
class ProvinceSerializer(serializers.ModelSerializer):
""" Serialize province data """
class Meta:
model = Province
fields = [
'id',
'name',
]
class BankAccountSerializer(serializers.ModelSerializer):
""" Serialize bank account data """
class Meta:
model = BankAccountInformation
fields = '__all__'
def validate(self, attrs):
account = attrs['account']
card = attrs['card']
sheba = attrs['sheba']
if not self.instance:
if self.Meta.model.objects.filter(Q(account=account) | Q(card=card) | Q(sheba=sheba)).exists():
raise BankAccountExistException()
elif self.instance:
if self.instance.account != account:
if self.Meta.model.objects.filter(Q(account=account)).exists():
raise BankAccountNumberAccountException()
elif self.instance.card != card:
if self.Meta.model.objects.filter(Q(card=card)).exists():
raise BankAccountCardException()
elif self.instance.sheba != sheba:
if self.Meta.model.objects.filter(Q(sheba=sheba)).exists():
raise BankAccountShebaException()
return attrs
def update(self, instance, validated_data):
""" update user bank account information """
instance.name = validated_data.get('name', instance.name)
instance.account = validated_data.get('account', instance.account)
instance.organization = validated_data.get('organization', instance.organization)
instance.account_type = validated_data.get('account_type', instance.account_type)
instance.card = validated_data.get('card', instance.card)
instance.sheba = validated_data.get('sheba', instance.sheba)
instance.save()
return instance
class UserSerializer(serializers.ModelSerializer):
""" Serialize user data """
class Meta:
model = User
fields = [
'id',
'username',
'password',
'first_name',
'last_name',
'is_active',
'mobile',
'phone',
'national_code',
'birthdate',
'nationality',
'ownership',
'address',
'unit_name',
'unit_national_id',
'photo',
'province',
'city',
'otp_status',
'is_herd_owner',
]
extra_kwargs = {
'password': {
'required': False
},
'username': {
'required': False
},
"national_code": {
'required': False
},
"unit_name": {
'required': False
},
"unit_national_id": {
'required': False
}
}
def validate(self, attrs):
mobile = attrs['mobile']
if not self.instance:
if self.Meta.model.objects.filter(
Q(mobile=mobile) | Q(username=attrs['username']),
trash=False
).exists():
raise UserExistException()
elif self.instance:
if self.instance.mobile != mobile:
if self.Meta.model.objects.filter(trash=False, mobile=mobile).exists():
raise UserExistException()
if 'username' in attrs.keys():
if self.instance.username != attrs['username']:
if self.Meta.model.objects.filter(trash=False, username=attrs['username']).exists():
raise UserExistException()
return attrs
def to_representation(self, instance):
""" Custom output """
representation = super().to_representation(instance)
if isinstance(instance, User):
if instance.bank_information.filter().exists():
representation['bank_account'] = BankAccountSerializer(
instance.bank_information.all(), many=True
).data
if instance.city:
representation['city_name'] = instance.city.name
if instance.province:
representation['province_name'] = instance.province.name
return representation
def update(self, instance, validated_data):
""" update user instance """
instance.username = validated_data.get('username', instance.username)
# control password
if validated_data.get('password'):
instance.password = make_password(validated_data.get('password', instance.password))
instance.first_name = validated_data.get('first_name')
instance.last_name = validated_data.get('last_name')
instance.is_active = validated_data.get('is_active')
instance.mobile = validated_data.get('mobile')
instance.phone = validated_data.get('phone')
instance.national_code = validated_data.get('national_code')
instance.birthdate = validated_data.get('birthdate')
instance.nationality = validated_data.get('nationality')
instance.ownership = validated_data.get('ownership')
instance.address = validated_data.get('address')
instance.unit_name = validated_data.get('unit_name')
instance.unit_national_id = validated_data.get('unit_national_id')
instance.photo = validated_data.get('photo')
instance.province = validated_data.get('province', instance.province)
instance.city = validated_data.get('city', instance.city)
instance.otp_status = validated_data.get('otp_status')
instance.save()
return instance
@staticmethod
def update_relations(user: object, relation_data: dict, bank_data: dict) -> typing.Any:
"""
update user relations & bank account for user
"""
user_relation = UserRelationSerializer(data=relation_data) # Create user relation
if user_relation.is_valid(raise_exception=True):
user_relation_obj = user_relation.update(
authorize_models.UserRelations.objects.get(user=user),
validated_data=relation_data
)
bank_info = BankAccountSerializer(data=bank_data) # Create user bank information
if bank_info.is_valid(raise_exception=True):
bank_obj = bank_info.update(
BankAccountInformation.objects.get(id=bank_data['id']),
validated_data=bank_data
)
return user_relation_obj, bank_obj # noqa
class OrganizationTypeSerializer(serializers.ModelSerializer):
""" Serialize organization type data """
class Meta:
model = OrganizationType
fields = [
'id',
'parent',
'key',
'name',
'org_type_field',
'is_repeatable'
]
def to_representation(self, instance):
representation = super().to_representation(instance)
if instance.parent:
representation['parent'] = {
'name': instance.parent.name,
'id': instance.parent.id
}
return representation
class OrganizationSerializer(serializers.ModelSerializer):
""" Serialize organization data """
class Meta:
model = Organization
fields = [
'id',
'name',
'type',
'province',
'city',
'address',
'parent_organization',
'national_unique_id',
'company_code',
'field_of_activity',
'free_visibility_by_scope'
]
extra_kwargs = {}
def validate(self, attrs):
"""
@ validate national_unique_code to be unique
@ validate to organization type field
"""
# check national_unique_id
national_unique_id = attrs['national_unique_id']
if not self.instance:
if self.Meta.model.objects.filter(national_unique_id=national_unique_id).exists():
raise OrganizationNationalUniqueIDException()
if self.instance:
if self.instance.national_unique_id != national_unique_id:
if self.Meta.model.objects.filter(national_unique_id=national_unique_id).exists():
raise OrganizationNationalUniqueIDException()
# check organization type field
# if is repeatable of type, organization will not be recreating
org_type = attrs['type']
if not self.instance:
if not org_type.is_repeatable:
if org_type.org_type_field == 'PR' and self.Meta.model.objects.filter(
type=org_type,
province=attrs['province']
).exists():
raise OrganizationTypeRepeatableException()
if org_type.org_type_field == 'CI' and self.Meta.model.objects.filter(
type=org_type,
city=attrs['city']
).exists():
raise OrganizationTypeRepeatableException()
if org_type.org_type_field == 'CO' and self.Meta.model.objects.filter(
type=org_type,
province=attrs['province'],
).exists():
raise OrganizationTypeRepeatableException()
# check organization type field when updating
elif self.instance:
if not org_type.is_repeatable:
if org_type.org_type_field == 'PR' and self.instance.province != attrs[
'province'] and self.Meta.model.objects.filter(
type=org_type,
province=attrs['province'],
).exists():
raise OrganizationTypeRepeatableException()
if org_type.org_type_field == 'CI' and self.instance.city != attrs[
'city'] and self.Meta.model.objects.filter(
type=org_type,
city=attrs['city'],
).exists():
raise OrganizationTypeRepeatableException()
if org_type.org_type_field == 'CO' and self.instance.province != attrs[
'province'] and self.Meta.model.objects.filter(
type=org_type,
province=attrs['province'],
).exists():
raise OrganizationTypeRepeatableException()
return attrs
def to_representation(self, instance):
""" Custom output """
representation = super().to_representation(instance)
if isinstance(instance, Organization):
representation['province'] = ProvinceSerializer(instance.province).data
representation['city'] = CitySerializer(instance.city).data
representation['type'] = OrganizationTypeSerializer(instance.type).data
if instance.parent_organization:
representation['parent_organization'] = OrganizationSerializer(
instance.parent_organization
).data
if instance.bank_information.exists():
representation['bank_account'] = BankAccountSerializer(
instance.bank_information.all(), many=True
).data
return representation
def update(self, instance, validated_data):
""" update user organization information """ # noqa
instance.name = validated_data.get('name', instance.name)
instance.type = validated_data.get('type', instance.type)
instance.province = validated_data.get('province', instance.province)
instance.city = validated_data.get('city', instance.city)
instance.address = validated_data.get('address', instance.address)
instance.parent_organization = validated_data.get('parent_organization', instance.parent_organization)
instance.national_unique_id = validated_data.get('national_unique_id', instance.national_unique_id)
instance.save()
return instance
class OrganizationStatsSerializer(serializers.ModelSerializer):
class Meta:
model = OrganizationStats
fields = '__all__'