422 lines
14 KiB
Python
422 lines
14 KiB
Python
import os
|
|
import math
|
|
from django.conf import settings
|
|
from rest_framework import serializers
|
|
from django.utils import timezone
|
|
from datetime import datetime
|
|
from module_iam.models import IAmPrincipal
|
|
from ..models import (
|
|
PrincipalHealthData,
|
|
Intolerance,
|
|
Symptoms,
|
|
PastTreatment,
|
|
ChronicCondition,
|
|
Medicine,
|
|
Medication,
|
|
Bowel,
|
|
SymptomTypeAfterMeal,
|
|
SymptomTypeBeforeMeal,
|
|
MealSymptomRecord,
|
|
FoodIngredientRecord,
|
|
FoodRecord,
|
|
BeverageRecord,
|
|
MealRecord,
|
|
)
|
|
|
|
|
|
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
|