Files
digest_app/module_activity/api/serializers.py

413 lines
14 KiB
Python

import math
import os
from datetime import datetime
from django.conf import settings
from django.utils import timezone
from rest_framework import serializers
from module_iam.models import IAmPrincipal
from ..models import (BeverageRecord, Bowel, ChronicCondition,
FoodIngredientRecord, FoodRecord, Intolerance,
MealRecord, MealSymptomRecord, Medication, Medicine,
PastTreatment, PrincipalHealthData, Symptoms,
SymptomTypeAfterMeal, SymptomTypeBeforeMeal)
class IAmPrincipalSerializer(serializers.ModelSerializer):
class Meta:
model = IAmPrincipal
fields = [
"profile_photo",
"first_name",
"date_of_birth",
"gender",
"phone_no",
]
class PrincipalHealthDataSerializer(serializers.ModelSerializer):
class Meta:
model = PrincipalHealthData
fields = [
"ethenicity",
"weight",
"height",
"gastrointestinal_health",
"exercise_frequency",
"sleep_duration",
"eat_frequency",
]
class PrincipalAndHealthSerializer(serializers.ModelSerializer):
ethenicity = serializers.CharField(read_only=True)
weight = serializers.DecimalField(max_digits=5, decimal_places=2, read_only=True)
height = serializers.DecimalField(max_digits=6, decimal_places=2, read_only=True)
gastrointestinal_health = serializers.CharField(read_only=True)
exercise_frequency = serializers.CharField(read_only=True)
sleep_duration = serializers.CharField(read_only=True)
eat_frequency = serializers.CharField(read_only=True)
profile_complete = serializers.IntegerField(read_only=True)
class Meta:
model = IAmPrincipal
fields = [
"profile_photo",
"first_name",
"email",
"date_of_birth",
"gender",
"phone_no",
# "phone_verified",
# "email_verified",
"ethenicity",
"weight",
"height",
"gastrointestinal_health",
"exercise_frequency",
"sleep_duration",
"eat_frequency",
"profile_complete"
]
def calculate_profile_completion(self, user):
"""
Calculates the profile completion percentage for a user based on the required fields.
"""
fields = self.fields
try:
# Retrieve the user profile from the database
profile = IAmPrincipal.objects.get(id=user)
try:
# Retrieve the user's health data from the database
health_data = PrincipalHealthData.objects.get(principal=profile)
except PrincipalHealthData.DoesNotExist:
# If health data doesn't exist, set health_data to None
health_data = None
# Initialize a counter for completed fields
completed_fields = sum(
1
for field in fields
if (
# If the field is in the user profile and the field value is not None, not an empty string, and not an instance of datetime.date
(field in vars(profile) and vars(profile).get(field, '') and vars(profile).get(field) != datetime.date) or
# If health data exists, the field is in the user's health data, and the field value is not None, not an empty string, and not an instance of datetime.date
(health_data and field in vars(health_data) and vars(health_data).get(field, '') and vars(health_data).get(field) != datetime.date)
)
)
except IAmPrincipal.DoesNotExist:
# If the user profile doesn't exist, return 0
return 0
# Calculate the total number of fields
total_fields = len(fields) - 1 # Exclude profile_complete field
# Calculate the profile completion percentage
completion_percentage = math.floor((completed_fields / total_fields) * 100)
# Return the profile completion percentage
return completion_percentage
def get_image_url(self, obj, field_name, request):
image_field = getattr(obj, field_name)
if image_field:
return request.build_absolute_uri(image_field.url)
else:
# Return the URL of the default image from the static path
default_image_path = os.path.join(
settings.STATIC_URL, "img/default_profile.jpg"
)
return request.build_absolute_uri(default_image_path)
def to_representation(self, instance):
data = super().to_representation(instance)
request = self.context.get("request")
data["profile_photo"] = self.get_image_url(instance, "profile_photo", request)
data["profile_complete"] = self.calculate_profile_completion(request.user.id)
if (
hasattr(instance, "health_data_principal")
and instance.health_data_principal
):
health_data = instance.health_data_principal
data["ethenicity"] = health_data.ethenicity
data["weight"] = health_data.weight
data["height"] = health_data.height
data["gastrointestinal_health"] = health_data.gastrointestinal_health
data["exercise_frequency"] = health_data.exercise_frequency
data["sleep_duration"] = health_data.sleep_duration
data["eat_frequency"] = health_data.eat_frequency
else:
# If health_data_principal doesn't exist or is empty, set empty strings for all attributes
data["ethenicity"] = ""
data["weight"] = 0.00
data["height"] = 0.00
data["gastrointestinal_health"] = ""
data["exercise_frequency"] = ""
data["sleep_duration"] = ""
data["eat_frequency"] = ""
return data
class IntoleranceSerializer(serializers.ModelSerializer):
class Meta:
model = Intolerance
fields = ["id", "name", "duration"]
class SymptomsSerializer(serializers.ModelSerializer):
class Meta:
model = Symptoms
fields = ["id", "name", "duration"]
class PastTreatmentSerializer(serializers.ModelSerializer):
class Meta:
model = PastTreatment
fields = ["id", "name", "duration"]
class ChronicConditionSerializer(serializers.ModelSerializer):
class Meta:
model = ChronicCondition
fields = ["id", "name", "duration"]
class FoodIngredientRecordSerializer(serializers.ModelSerializer):
class Meta:
model = FoodIngredientRecord
fields = ["name"]
class FoodRecordSerializer(serializers.ModelSerializer):
class Meta:
model = FoodRecord
fields = ["name", "quantity"]
class BeverageRecordSerializer(serializers.ModelSerializer):
class Meta:
model = BeverageRecord
fields = [
"beverage_type",
"glass_type",
"glass_count",
"quantity",
"quantity_measure",
]
class MealRecordSerializer(serializers.ModelSerializer):
food_records = FoodRecordSerializer(many=True)
beverage_records = BeverageRecordSerializer(many=True)
food_ingredient_records = FoodIngredientRecordSerializer(many=True)
class Meta:
model = MealRecord
fields = [
"id",
"date",
"time",
"meal_type",
"food_records",
"food_ingredient_records",
"beverage_records",
]
def create(self, validated_data):
food_record_data = validated_data.pop("food_records", [])
beverage_record_data = validated_data.pop("beverage_records", [])
food_ingredient_record_data = validated_data.pop("food_ingredient_records", [])
meal_record = self.Meta.model.objects.create(**validated_data)
food_record_list = []
for data in food_record_data:
obj, _ = FoodRecord.objects.get_or_create(**data)
food_record_list.append(obj)
food_ingredient_list = []
for data in food_ingredient_record_data:
obj, _ = FoodIngredientRecord.objects.get_or_create(**data)
food_ingredient_list.append(obj)
beverage_record_list = []
for data in beverage_record_data:
obj, _ = BeverageRecord.objects.get_or_create(**data)
beverage_record_list.append(obj)
meal_record.food_records.set(food_record_list)
meal_record.food_ingredient_records.set(food_ingredient_list)
meal_record.beverage_records.set(beverage_record_list)
return meal_record
def update(self, instance, validated_data):
instance.date = validated_data.get("date", instance.date)
instance.time = validated_data.get("time", instance.time)
instance.meal_type = validated_data.get("meal_type", instance.meal_type)
instance.save()
food_record_data = validated_data.pop("food_records", [])
beverage_record_data = validated_data.pop("beverage_records", [])
food_ingredient_record_data = validated_data.pop("food_ingredient_records", [])
food_record_list = []
for data in food_record_data:
obj, _ = FoodRecord.objects.get_or_create(**data)
food_record_list.append(obj)
food_ingredient_list = []
for data in food_ingredient_record_data:
obj, _ = FoodIngredientRecord.objects.get_or_create(**data)
food_ingredient_list.append(obj)
beverage_record_list = []
for data in beverage_record_data:
obj, _ = BeverageRecord.objects.get_or_create(**data)
beverage_record_list.append(obj)
instance.food_records.set(food_record_list)
instance.food_ingredient_records.set(food_ingredient_list)
instance.beverage_records.set(beverage_record_list)
instance.save()
return instance
class MedicineSerializer(serializers.ModelSerializer):
class Meta:
model = Medicine
fields = ["name", "quantity", "type"]
class MedicationSerializer(serializers.ModelSerializer):
medicines = MedicineSerializer(many=True)
class Meta:
model = Medication
fields = ["id", "date", "time", "medicines"]
def create(self, validated_data):
medicines_data = validated_data.pop("medicines")
medication = self.Meta.model.objects.create(**validated_data)
for medicine_data in medicines_data:
medicine = Medicine.objects.create(**medicine_data)
medication.medicines.add(medicine)
return medication
def update(self, instance, validated_data):
instance.date = validated_data.get("date", instance.date)
instance.time = validated_data.get("time", instance.time)
instance.save()
medicines_data = validated_data.get("medicines", [])
instance.medicines.clear()
for medicine_data in medicines_data:
medicine = Medicine.objects.create(**medicine_data)
instance.medicines.add(medicine)
return instance
class BowelSerializer(serializers.ModelSerializer):
class Meta:
model = Bowel
fields = [
"id",
"date",
"time",
"stool_type",
"stool_name",
"duration",
"completeness_of_evacuation",
"urgency",
"smellness",
"pain_level",
"volume",
"color",
"excessive_flatulence",
]
class SymptomTypeBeforeMealSerializer(serializers.ModelSerializer):
class Meta:
model = SymptomTypeBeforeMeal
fields = ["name"]
class SymptomTypeAfterMealSerializer(serializers.ModelSerializer):
class Meta:
model = SymptomTypeAfterMeal
fields = ["name"]
class MealSymptomRecordSerializer(serializers.ModelSerializer):
symptoms_before_meal = SymptomTypeBeforeMealSerializer(many=True)
symptoms_after_meal = SymptomTypeAfterMealSerializer(many=True)
class Meta:
model = MealSymptomRecord
fields = [
"id",
"date",
"time",
"symptoms_description",
"interval",
"symptoms_before_meal",
"symptoms_after_meal",
]
def create(self, validated_data):
before_meal_data = validated_data.pop("symptoms_before_meal")
after_meal_data = validated_data.pop("symptoms_after_meal")
meal_symptom_record = MealSymptomRecord.objects.create(**validated_data)
before_meal_list = []
for data in before_meal_data:
obj, _ = SymptomTypeBeforeMeal.objects.get_or_create(**data)
before_meal_list.append(obj)
after_meal_list = []
for data in after_meal_data:
obj, _ = SymptomTypeAfterMeal.objects.get_or_create(**data)
after_meal_list.append(obj)
meal_symptom_record.symptoms_before_meal.set(before_meal_list)
meal_symptom_record.symptoms_after_meal.set(after_meal_list)
return meal_symptom_record
def update(self, instance, validated_data):
instance.date = validated_data.get("date", instance.date)
instance.time = validated_data.get("time", instance.time)
instance.symptoms_description = validated_data.get(
"symptoms_description", instance.symptoms_description
)
instance.interval = validated_data.get("interval", instance.interval)
before_meal_data = validated_data.pop("symptoms_before_meal", [])
after_meal_data = validated_data.pop("symptoms_after_meal", [])
before_meal_instances = []
for data in before_meal_data:
obj, _ = SymptomTypeBeforeMeal.objects.get_or_create(**data)
before_meal_instances.append(obj)
after_meal_instances = []
for data in after_meal_data:
obj, _ = SymptomTypeAfterMeal.objects.get_or_create(**data)
after_meal_instances.append(obj)
instance.symptoms_before_meal.set(before_meal_instances)
instance.symptoms_after_meal.set(after_meal_instances)
instance.save()
return instance