"""Serializer file for junior""" # third party imports import pytz # django imports from rest_framework import serializers from django.contrib.auth.models import User from django.db import transaction from datetime import datetime from django.utils import timezone from rest_framework_simplejwt.tokens import RefreshToken # local imports from account.utils import send_otp_email, generate_code, make_special_password from junior.models import Junior, JuniorPoints, JuniorGuardianRelationship, JuniorArticlePoints, FAQ from guardian.tasks import generate_otp from base.messages import ERROR_CODE, SUCCESS_CODE from base.constants import (PENDING, IN_PROGRESS, REJECTED, REQUESTED, COMPLETED, NUMBER, JUN, ZOD, EXPIRED, GUARDIAN_CODE_STATUS, JUNIOR) from guardian.models import Guardian, JuniorTask from account.models import UserEmailOtp, UserNotification from junior.utils import junior_notification_email, junior_approval_mail, get_junior_leaderboard_rank from guardian.utils import real_time, update_referral_points, convert_timedelta_into_datetime from notifications.utils import send_notification from notifications.constants import (ASSOCIATE_REQUEST, ASSOCIATE_JUNIOR, TASK_ACTION, ) from web_admin.models import ArticleCard class ListCharField(serializers.ListField): """Serializer for Array field""" child = serializers.CharField() def to_representation(self, data): """to represent the data""" return data def to_internal_value(self, data): """internal value""" if isinstance(data, list): return data raise serializers.ValidationError({"details":ERROR_CODE['2025']}) class CreateJuniorSerializer(serializers.ModelSerializer): """Create junior serializer""" first_name = serializers.SerializerMethodField('get_first_name') last_name = serializers.SerializerMethodField('get_last_name') email = serializers.SerializerMethodField('get_email') phone = serializers.CharField(max_length=20, required=False) country_code = serializers.IntegerField(required=False) dob = serializers.DateField(required=False) referral_code = serializers.CharField(max_length=100, required=False) guardian_code = ListCharField(required=False) image = serializers.URLField(required=False) class Meta(object): """Meta info""" model = Junior fields = ['id', 'first_name', 'last_name', 'email', 'phone', 'gender', 'country_code', 'dob', 'referral_code', 'passcode', 'is_complete_profile', 'guardian_code', 'referral_code_used', 'country_name', 'image', 'is_invited'] def get_first_name(self,obj): """first name of junior""" return obj.auth.first_name def get_last_name(self,obj): """last name of junior""" return obj.auth.last_name def get_email(self,obj): """email of junior""" return obj.auth.email def create(self, validated_data): """Create junior profile""" guardian_code = validated_data.get('guardian_code',None) user = User.objects.filter(username=self.context['user']).last() if user: """Save first and last name of junior""" if self.context.get('first_name') != '' and self.context.get('first_name') is not None: user.first_name = self.context.get('first_name') if self.context.get('last_name') != '' and self.context.get('last_name') is not None: user.last_name = self.context.get('last_name') user.save() """Create junior data""" junior = Junior.objects.filter(auth=self.context['user']).last() if junior: """update details according to the data get from request""" junior.gender = validated_data.get('gender',junior.gender) # Update guardian code""" # condition for guardian code if guardian_code: if junior.guardian_code and guardian_code: if guardian_code[0] in junior.guardian_code: raise serializers.ValidationError({"error":ERROR_CODE['2076'],"code":"400", "status":"failed"}) if not junior.guardian_code: junior.guardian_code = [] junior.guardian_code_status = [] junior.guardian_code.extend(guardian_code) junior.guardian_code_status.extend(str(NUMBER['three'])) elif len(junior.guardian_code) < 3 and len(guardian_code) < 3: junior.guardian_code.extend(guardian_code) junior.guardian_code_status.extend(str(NUMBER['three'])) else: raise serializers.ValidationError({"error":ERROR_CODE['2081'],"code":"400", "status":"failed"}) guardian_data = Guardian.objects.filter(guardian_code=guardian_code[0]).last() if guardian_data: JuniorGuardianRelationship.objects.get_or_create(guardian=guardian_data, junior=junior) send_notification.delay(ASSOCIATE_REQUEST, junior.auth_id, JUNIOR, guardian_data.user_id, {}) # junior_approval_mail.delay(user.email, user.first_name) removed as per changes junior.dob = validated_data.get('dob', junior.dob) junior.passcode = validated_data.get('passcode', junior.passcode) junior.country_name = validated_data.get('country_name', junior.country_name) """Update country code and phone number""" junior.phone = validated_data.get('phone', junior.phone) junior.country_code = validated_data.get('country_code', junior.country_code) junior.image = validated_data.get('image', junior.image) """Complete profile of the junior if below all data are filled""" complete_profile_field = all([junior.gender, junior.country_name, junior.image, junior.dob, user.first_name]) junior.is_complete_profile = False if complete_profile_field: junior.is_complete_profile = True referral_code_used = validated_data.get('referral_code_used') update_referral_points(junior.referral_code, referral_code_used) junior.referral_code_used = validated_data.get('referral_code_used', junior.referral_code_used) junior.save() return junior def save(self, **kwargs): """Save the data into junior table""" with transaction.atomic(): instance = super().save(**kwargs) return instance class JuniorDetailSerializer(serializers.ModelSerializer): """junior serializer""" email = serializers.SerializerMethodField('get_auth') first_name = serializers.SerializerMethodField('get_first_name') last_name = serializers.SerializerMethodField('get_last_name') def get_auth(self, obj): """user email address""" return obj.auth.username def get_first_name(self, obj): """user first name""" return obj.auth.first_name def get_last_name(self, obj): """user last name""" return obj.auth.last_name class Meta(object): """Meta info""" model = Junior fields = ['id', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'gender', 'dob', 'guardian_code', 'image', 'is_invited', 'referral_code','is_active', 'is_complete_profile', 'created_at', 'image', 'is_deleted', 'updated_at'] class JuniorDetailListSerializer(serializers.ModelSerializer): """junior serializer""" email = serializers.SerializerMethodField('get_auth') first_name = serializers.SerializerMethodField('get_first_name') last_name = serializers.SerializerMethodField('get_last_name') assigned_task = serializers.SerializerMethodField('get_assigned_task') points = serializers.SerializerMethodField('get_points') in_progress_task = serializers.SerializerMethodField('get_in_progress_task') completed_task = serializers.SerializerMethodField('get_completed_task') requested_task = serializers.SerializerMethodField('get_requested_task') rejected_task = serializers.SerializerMethodField('get_rejected_task') pending_task = serializers.SerializerMethodField('get_pending_task') position = serializers.SerializerMethodField('get_position') guardian_code_status = serializers.SerializerMethodField('get_guardian_code_status') def get_auth(self, obj): return obj.auth.username def get_first_name(self, obj): return obj.auth.first_name def get_last_name(self, obj): return obj.auth.last_name def get_assigned_task(self, obj): data = JuniorTask.objects.filter(junior=obj).count() return data def get_position(self, obj): return get_junior_leaderboard_rank(obj) def get_points(self, obj): data = JuniorPoints.objects.filter(junior=obj).last() if data: return data.total_points return NUMBER['zero'] def get_in_progress_task(self, obj): data = JuniorTask.objects.filter(junior=obj, task_status=IN_PROGRESS).count() return data def get_completed_task(self, obj): data = JuniorTask.objects.filter(junior=obj, task_status=COMPLETED).count() return data def get_requested_task(self, obj): data = JuniorTask.objects.filter(junior=obj, task_status=REQUESTED).count() return data def get_rejected_task(self, obj): data = JuniorTask.objects.filter(junior=obj, task_status=REJECTED).count() return data def get_pending_task(self, obj): data = JuniorTask.objects.filter(junior=obj, task_status=PENDING).count() return data def get_guardian_code_status(self, obj): if self.context['guardian_code'] in obj.guardian_code: index = obj.guardian_code.index(self.context['guardian_code']) if obj.guardian_code_status: data = obj.guardian_code_status[index] return data class Meta(object): """Meta info""" model = Junior fields = ['id', 'email', 'first_name', 'last_name', 'country_code', 'country_name', 'phone', 'gender', 'dob', 'guardian_code', 'referral_code','is_active', 'is_complete_profile', 'created_at', 'image', 'updated_at', 'assigned_task','points', 'pending_task', 'in_progress_task', 'completed_task', 'requested_task', 'rejected_task', 'position', 'is_invited', 'guardian_code_status', 'is_deleted'] class JuniorProfileSerializer(serializers.ModelSerializer): """junior serializer""" email = serializers.SerializerMethodField('get_auth') first_name = serializers.SerializerMethodField('get_first_name') last_name = serializers.SerializerMethodField('get_last_name') notification_count = serializers.SerializerMethodField('get_notification_count') total_count = serializers.SerializerMethodField('get_total_count') complete_field_count = serializers.SerializerMethodField('get_complete_field_count') def get_auth(self, obj): """user email address""" return obj.auth.username def get_first_name(self, obj): """user first name""" return obj.auth.first_name def get_last_name(self, obj): """user last name""" return obj.auth.last_name def get_notification_count(self, obj): """total notification count""" return 0 def get_total_count(self, obj): """total fields count""" return NUMBER['five'] def get_complete_field_count(self, obj): """total filled fields count""" field_list = [obj.auth.first_name, obj.country_name, obj.gender, obj.dob, obj.image] complete_field = [data for data in field_list if data is not None and data != ''] return len(complete_field) class Meta(object): """Meta info""" model = Junior fields = ['id', 'email', 'first_name', 'last_name', 'country_name', 'country_code', 'phone', 'gender', 'dob', 'guardian_code', 'referral_code','is_active', 'is_complete_profile', 'created_at', 'image', 'updated_at', 'notification_count', 'total_count', 'complete_field_count', 'signup_method', 'is_invited', 'passcode', 'guardian_code_approved', 'is_deleted'] class AddJuniorSerializer(serializers.ModelSerializer): """Add junior serializer""" class Meta(object): """Meta info""" model = Junior fields = ['id', 'gender', 'dob', 'is_invited'] def create(self, validated_data): """ create junior""" with transaction.atomic(): email = self.context['email'] guardian = self.context['user'] relationship = self.context['relationship'] profile_image = self.context['image'] full_name = self.context['first_name'] + ' ' + self.context['last_name'] guardian_data = Guardian.objects.filter(user__username=guardian).last() user_data = User.objects.create(username=email, email=email, first_name=self.context['first_name'], last_name=self.context['last_name']) special_password = make_special_password() user_data.set_password(special_password) user_data.save() junior_data = Junior.objects.create(auth=user_data, gender=validated_data.get('gender'), image=profile_image, dob=validated_data.get('dob'), is_invited=True, guardian_code=[guardian_data.guardian_code], junior_code=generate_code(JUN, user_data.id), referral_code=generate_code(ZOD, user_data.id), referral_code_used=guardian_data.referral_code, is_password_set=False, is_verified=True, guardian_code_status=[str(NUMBER['two'])]) JuniorGuardianRelationship.objects.create(guardian=guardian_data, junior=junior_data, relationship=relationship) total_junior = Junior.objects.all().count() JuniorPoints.objects.create(junior=junior_data, position=total_junior) """Generate otp""" otp_value = generate_otp() expiry_time = timezone.now() + timezone.timedelta(days=1) UserEmailOtp.objects.create(email=email, otp=otp_value, user_type='1', expired_at=expiry_time, is_verified=True) # add push notification UserNotification.objects.get_or_create(user=user_data) """Notification email""" junior_notification_email.delay(email, full_name, email, special_password) # push notification send_notification.delay(ASSOCIATE_JUNIOR, None, None, junior_data.auth_id, {}) return junior_data class RemoveJuniorSerializer(serializers.ModelSerializer): """User Update Serializer""" class Meta(object): """Meta class""" model = Junior fields = ('id', 'is_invited') def update(self, instance, validated_data): if instance: guardian_code = self.context['guardian_code'] instance.is_invited = False if instance.guardian_code and ('-' in instance.guardian_code): instance.guardian_code.remove('-') index = instance.guardian_code.index(guardian_code) instance.guardian_code.remove(guardian_code) instance.guardian_code_status.pop(index) instance.save() return instance class CompleteTaskSerializer(serializers.ModelSerializer): """User task Serializer""" class Meta(object): """Meta class""" model = JuniorTask fields = ('id', 'image') def update(self, instance, validated_data): instance.image = validated_data.get('image', instance.image) instance.requested_on = timezone.now().astimezone(pytz.utc) instance.task_status = str(NUMBER['four']) instance.is_approved = False instance.save() send_notification.delay(TASK_ACTION, instance.junior.auth_id, JUNIOR, instance.guardian.user_id, {'task_id': instance.id}) return instance class JuniorPointsSerializer(serializers.ModelSerializer): """Junior points serializer""" junior_id = serializers.SerializerMethodField('get_junior_id') total_points = serializers.SerializerMethodField('get_points') in_progress_task = serializers.SerializerMethodField('get_in_progress_task') completed_task = serializers.SerializerMethodField('get_completed_task') requested_task = serializers.SerializerMethodField('get_requested_task') rejected_task = serializers.SerializerMethodField('get_rejected_task') pending_task = serializers.SerializerMethodField('get_pending_task') expired_task = serializers.SerializerMethodField('get_expired_task') position = serializers.SerializerMethodField('get_position') def get_junior_id(self, obj): """junior id""" return obj.junior.id def get_position(self, obj): return get_junior_leaderboard_rank(obj.junior) def get_points(self, obj): """total points""" points = JuniorPoints.objects.filter(junior=obj.junior).last() if points: return points.total_points def get_in_progress_task(self, obj): return JuniorTask.objects.filter(junior=obj.junior, task_status=IN_PROGRESS).count() def get_completed_task(self, obj): return JuniorTask.objects.filter(junior=obj.junior, task_status=COMPLETED).count() def get_requested_task(self, obj): return JuniorTask.objects.filter(junior=obj.junior, task_status=REQUESTED).count() def get_rejected_task(self, obj): return JuniorTask.objects.filter(junior=obj.junior, task_status=REJECTED).count() def get_pending_task(self, obj): return JuniorTask.objects.filter(junior=obj.junior, task_status=PENDING).count() def get_expired_task(self, obj): return JuniorTask.objects.filter(junior=obj.junior, task_status=EXPIRED).count() class Meta(object): """Meta info""" model = Junior fields = ['junior_id', 'total_points', 'position', 'pending_task', 'in_progress_task', 'completed_task', 'requested_task', 'rejected_task', 'expired_task', 'is_deleted'] class AddGuardianSerializer(serializers.ModelSerializer): """Add guardian serializer""" class Meta(object): """Meta info""" model = Guardian fields = ['id'] def create(self, validated_data): """ invite and create guardian""" with transaction.atomic(): email = self.context['email'] junior = self.context['user'] relationship = self.context['relationship'] full_name = self.context['first_name'] + ' ' + self.context['last_name'] junior_data = Junior.objects.filter(auth__username=junior).last() junior_data.guardian_code_status = GUARDIAN_CODE_STATUS[2][0] junior_data.save() instance = User.objects.filter(username=email).last() if instance: guardian_data = Guardian.objects.filter(user=instance).update(is_invited=True, referral_code=generate_code(ZOD, instance.id), referral_code_used=junior_data.referral_code, is_verified=True) UserNotification.objects.get_or_create(user=instance) return guardian_data else: user = User.objects.create(username=email, email=email, first_name=self.context['first_name'], last_name=self.context['last_name']) password = User.objects.make_random_password() user.set_password(password) user.save() guardian_data = Guardian.objects.create(user=user, is_invited=True, referral_code=generate_code(ZOD, user.id), referral_code_used=junior_data.referral_code, is_password_set=False, is_verified=True) """Generate otp""" otp_value = generate_otp() expiry_time = timezone.now() + timezone.timedelta(days=1) UserEmailOtp.objects.create(email=email, otp=otp_value, user_type=str(NUMBER['two']), expired_at=expiry_time, is_verified=True) UserNotification.objects.get_or_create(user=user) JuniorGuardianRelationship.objects.create(guardian=guardian_data, junior=junior_data, relationship=relationship) """Notification email""" junior_notification_email(email, full_name, email, password) # junior_approval_mail.delay(email, full_name) removed as per changes send_notification.delay(ASSOCIATE_REQUEST, junior_data.auth_id, JUNIOR, guardian_data.user_id, {}) return guardian_data class StartTaskSerializer(serializers.ModelSerializer): """User task Serializer""" task_duration = serializers.SerializerMethodField('get_task_duration') def get_task_duration(self, obj): """ remaining time to complete task""" due_date = datetime.combine(obj.due_date, datetime.max.time()) # fetch real time # real_datetime = real_time() # new code due_date = due_date.astimezone(pytz.utc) real_datetime = timezone.now().astimezone(pytz.utc) # Perform the subtraction if due_date > real_datetime: time_difference = due_date - real_datetime time_only = convert_timedelta_into_datetime(time_difference) return str(time_difference.days) + ' days ' + str(time_only) return str(NUMBER['zero']) + ' days ' + '00:00:00:00000' class Meta(object): """Meta class""" model = JuniorTask fields = ('id', 'task_duration') def update(self, instance, validated_data): instance.task_status = str(NUMBER['two']) instance.save() return instance class ReAssignTaskSerializer(serializers.ModelSerializer): """User task Serializer""" class Meta(object): """Meta class""" model = JuniorTask fields = ('id', 'due_date') def update(self, instance, validated_data): instance.task_status = str(NUMBER['one']) instance.due_date = validated_data.get('due_date') instance.is_approved = False instance.requested_on = None instance.save() return instance class RemoveGuardianCodeSerializer(serializers.ModelSerializer): """User task Serializer""" class Meta(object): """Meta class""" model = Junior fields = ('id', ) def update(self, instance, validated_data): guardian_code = self.context['guardian_code'] if guardian_code in instance.guardian_code: if instance.guardian_code and ('-' in instance.guardian_code): instance.guardian_code.remove('-') if instance.guardian_code_status and ('-' in instance.guardian_code_status): instance.guardian_code_status.remove('-') index = instance.guardian_code.index(guardian_code) instance.guardian_code.remove(guardian_code) instance.guardian_code_status.pop(index) else: raise serializers.ValidationError({"error":ERROR_CODE['2082'],"code":"400", "status":"failed"}) instance.save() return instance class FAQSerializer(serializers.ModelSerializer): """FAQ Serializer""" class Meta(object): """meta info""" model = FAQ fields = ('id', 'question', 'description') class CreateArticleCardSerializer(serializers.ModelSerializer): """Article card Serializer""" class Meta(object): """meta info""" model = ArticleCard fields = ('id', 'article')