2024-03-11 14:48:48 +05:30
import math
2024-03-21 13:09:14 +05:30
import os
from datetime import datetime
2024-03-11 14:48:48 +05:30
from django . conf import settings
2024-02-26 13:28:32 +05:30
from django . utils import timezone
2024-03-21 13:09:14 +05:30
from rest_framework import serializers
2024-02-26 13:28:32 +05:30
from module_iam . models import IAmPrincipal
2024-03-21 13:09:14 +05:30
2024-03-29 00:45:21 +05:30
from . . models import (
BeverageRecord ,
Bowel ,
ChronicCondition ,
FoodIngredientRecord ,
FoodIngredintDataset ,
FoodRecord ,
Intolerance ,
MealRecord ,
MealSymptomRecord ,
Medication ,
Medicine ,
PastTreatment ,
PrincipalHealthData ,
Symptoms ,
SymptomTypeAfterMeal ,
SymptomTypeBeforeMeal ,
)
class FoodDatasetSerializer ( serializers . ModelSerializer ) :
class Meta :
model = FoodIngredintDataset
fields = [ " id " , " food_name " ]
class FoodIngredientDatasetSerializer ( serializers . ModelSerializer ) :
class Meta :
model = FoodIngredintDataset
fields = [ ' id ' , ' food_name ' , ' ingredients ' ]
2024-02-26 13:28:32 +05:30
2024-03-11 14:48:48 +05:30
2024-02-26 13:28:32 +05:30
class IAmPrincipalSerializer ( serializers . ModelSerializer ) :
class Meta :
model = IAmPrincipal
fields = [
2024-03-11 14:48:48 +05:30
" profile_photo " ,
2024-02-26 13:28:32 +05:30
" first_name " ,
" date_of_birth " ,
" gender " ,
" phone_no " ,
]
2024-03-11 14:48:48 +05:30
2024-02-26 13:28:32 +05:30
class PrincipalHealthDataSerializer ( serializers . ModelSerializer ) :
2024-03-29 00:45:21 +05:30
weight = serializers . DecimalField ( max_digits = 5 , decimal_places = 2 , read_only = True )
height = serializers . DecimalField ( max_digits = 6 , decimal_places = 2 , read_only = True )
2024-02-26 13:28:32 +05:30
class Meta :
model = PrincipalHealthData
fields = [
" ethenicity " ,
" weight " ,
2024-03-29 00:45:21 +05:30
" weight_unit " ,
2024-02-26 13:28:32 +05:30
" height " ,
2024-03-29 00:45:21 +05:30
" height_unit " ,
2024-02-26 13:28:32 +05:30
" gastrointestinal_health " ,
" exercise_frequency " ,
" sleep_duration " ,
" eat_frequency " ,
]
2024-03-11 14:48:48 +05:30
2024-02-26 13:28:32 +05:30
class PrincipalAndHealthSerializer ( serializers . ModelSerializer ) :
ethenicity = serializers . CharField ( read_only = True )
weight = serializers . DecimalField ( max_digits = 5 , decimal_places = 2 , read_only = True )
2024-03-29 00:45:21 +05:30
weight_unit = serializers . CharField ( max_length = 10 , read_only = True )
2024-02-26 13:28:32 +05:30
height = serializers . DecimalField ( max_digits = 6 , decimal_places = 2 , read_only = True )
2024-03-29 00:45:21 +05:30
height_unit = serializers . CharField ( max_length = 10 , read_only = True )
2024-02-26 13:28:32 +05:30
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 )
2024-03-11 14:48:48 +05:30
profile_complete = serializers . IntegerField ( read_only = True )
2024-02-26 13:28:32 +05:30
class Meta :
model = IAmPrincipal
fields = [
" profile_photo " ,
" first_name " ,
" email " ,
" date_of_birth " ,
" gender " ,
" phone_no " ,
2024-03-11 14:48:48 +05:30
# "phone_verified",
# "email_verified",
2024-02-26 13:28:32 +05:30
" ethenicity " ,
" weight " ,
2024-03-29 00:45:21 +05:30
" weight_unit " ,
2024-02-26 13:28:32 +05:30
" height " ,
2024-03-29 00:45:21 +05:30
" height_unit " ,
2024-02-26 13:28:32 +05:30
" gastrointestinal_health " ,
" exercise_frequency " ,
" sleep_duration " ,
" eat_frequency " ,
2024-03-29 00:45:21 +05:30
" profile_complete " ,
2024-02-26 13:28:32 +05:30
]
2024-03-11 14:48:48 +05:30
def calculate_profile_completion ( self , user ) :
"""
Calculates the profile completion percentage for a user based on the required fields .
"""
2024-03-29 00:45:21 +05:30
fields = [
" profile_photo " ,
" first_name " ,
" email " ,
" date_of_birth " ,
" gender " ,
" phone_no " ,
" ethenicity " ,
" weight " ,
" height " ,
" gastrointestinal_health " ,
" exercise_frequency " ,
" sleep_duration " ,
" eat_frequency " ,
]
2024-03-11 14:48:48 +05:30
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
2024-03-29 00:45:21 +05:30
(
field in vars ( profile )
and vars ( profile ) . get ( field , " " )
and vars ( profile ) . get ( field ) != datetime . date
)
or
2024-03-11 14:48:48 +05:30
# 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
2024-03-29 00:45:21 +05:30
(
health_data
and field in vars ( health_data )
and vars ( health_data ) . get ( field , " " )
and vars ( health_data ) . get ( field ) != datetime . date
)
2024-03-11 14:48:48 +05:30
)
)
except IAmPrincipal . DoesNotExist :
# If the user profile doesn't exist, return 0
return 0
# Calculate the total number of fields
2024-03-29 00:45:21 +05:30
total_fields = len ( fields )
2024-03-11 14:48:48 +05:30
# Calculate the profile completion percentage
completion_percentage = math . floor ( ( completed_fields / total_fields ) * 100 )
# Return the profile completion percentage
return completion_percentage
2024-02-26 13:28:32 +05:30
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 )
2024-03-11 14:48:48 +05:30
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 )
2024-02-26 13:28:32 +05:30
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 )
2024-03-11 14:48:48 +05:30
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
2024-03-29 00:45:21 +05:30
data [ " weight_unit " ] = health_data . weight_unit
2024-03-11 14:48:48 +05:30
data [ " height " ] = health_data . height
2024-03-29 00:45:21 +05:30
data [ " height_unit " ] = health_data . height_unit
2024-03-11 14:48:48 +05:30
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
2024-03-29 00:45:21 +05:30
data [ " weight_unit " ] = " kg "
2024-03-11 14:48:48 +05:30
data [ " height " ] = 0.00
2024-03-29 00:45:21 +05:30
data [ " height_unit " ] = " cm "
2024-03-11 14:48:48 +05:30
data [ " gastrointestinal_health " ] = " "
data [ " exercise_frequency " ] = " "
data [ " sleep_duration " ] = " "
data [ " eat_frequency " ] = " "
2024-02-26 13:28:32 +05:30
return data
class IntoleranceSerializer ( serializers . ModelSerializer ) :
class Meta :
model = Intolerance
fields = [ " id " , " name " , " duration " ]
2024-03-11 14:48:48 +05:30
2024-02-26 13:28:32 +05:30
class SymptomsSerializer ( serializers . ModelSerializer ) :
class Meta :
model = Symptoms
fields = [ " id " , " name " , " duration " ]
class PastTreatmentSerializer ( serializers . ModelSerializer ) :
class Meta :
model = PastTreatment
2024-03-29 00:45:21 +05:30
fields = [ " id " , " name " , " duration " , " is_recurring " , " treatment_frequency " ]
2024-02-26 13:28:32 +05:30
class ChronicConditionSerializer ( serializers . ModelSerializer ) :
class Meta :
model = ChronicCondition
fields = [ " id " , " name " , " duration " ]
class FoodIngredientRecordSerializer ( serializers . ModelSerializer ) :
class Meta :
model = FoodIngredientRecord
2024-03-29 00:45:21 +05:30
fields = [ " name " , " from_dataset " ]
2024-02-26 13:28:32 +05:30
class FoodRecordSerializer ( serializers . ModelSerializer ) :
class Meta :
model = FoodRecord
fields = [ " name " , " quantity " ]
class BeverageRecordSerializer ( serializers . ModelSerializer ) :
class Meta :
model = BeverageRecord
fields = [
" beverage_type " ,
" quantity " ,
" quantity_measure " ,
]
2024-03-11 14:48:48 +05:30
2024-02-26 13:28:32 +05:30
class MealRecordSerializer ( serializers . ModelSerializer ) :
food_records = FoodRecordSerializer ( many = True )
beverage_records = BeverageRecordSerializer ( many = True )
food_ingredient_records = FoodIngredientRecordSerializer ( many = True )
class Meta :
model = MealRecord
2024-03-11 14:48:48 +05:30
fields = [
" id " ,
" date " ,
" time " ,
" meal_type " ,
" food_records " ,
" food_ingredient_records " ,
" beverage_records " ,
]
2024-02-26 13:28:32 +05:30
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 )
2024-04-04 16:27:43 +05:30
print ( f " meal recordd id in serializer { meal_record . id } " )
2024-02-26 13:28:32 +05:30
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 ( )
2024-04-04 16:27:43 +05:30
print ( f " meal record id in update 1 method { instance . id } " )
2024-02-26 13:28:32 +05:30
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 ( )
2024-04-04 16:27:43 +05:30
print ( f " meal record id in update 2 method { instance . id } " )
2024-02-26 13:28:32 +05:30
return instance
2024-03-11 14:48:48 +05:30
2024-02-26 13:28:32 +05:30
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 " ,
2024-03-11 14:48:48 +05:30
" stool_name " ,
2024-02-26 13:28:32 +05:30
" duration " ,
" completeness_of_evacuation " ,
" urgency " ,
" smellness " ,
" pain_level " ,
" volume " ,
" color " ,
" excessive_flatulence " ,
]
2024-03-29 00:45:21 +05:30
class MealRecordSymptomsSerializer ( serializers . ModelSerializer ) :
class Meta :
model = MealRecord
fields = [
" id " ,
" date " ,
" time " ,
" meal_type " ,
]
2024-02-26 13:28:32 +05:30
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 )
2024-03-29 00:45:21 +05:30
related_meal_id = serializers . PrimaryKeyRelatedField (
queryset = MealRecord . objects . all ( ) , write_only = True
) # Added field to accept meal ID
related_meal = MealRecordSymptomsSerializer ( read_only = True )
2024-02-26 13:28:32 +05:30
class Meta :
model = MealSymptomRecord
fields = [
" id " ,
" date " ,
" time " ,
" symptoms_description " ,
" interval " ,
" symptoms_before_meal " ,
" symptoms_after_meal " ,
2024-03-29 00:45:21 +05:30
" related_meal_id " ,
" related_meal "
2024-02-26 13:28:32 +05:30
]
def create ( self , validated_data ) :
before_meal_data = validated_data . pop ( " symptoms_before_meal " )
after_meal_data = validated_data . pop ( " symptoms_after_meal " )
2024-03-29 00:45:21 +05:30
related_meal_id = validated_data . pop ( " related_meal_id " )
2024-02-26 13:28:32 +05:30
2024-03-29 00:45:21 +05:30
meal_symptom_record = MealSymptomRecord . objects . create (
related_meal = related_meal_id , * * validated_data
)
2024-02-26 13:28:32 +05:30
2024-04-04 16:27:43 +05:30
print ( f " symptoms meal record in create { meal_symptom_record . id , meal_symptom_record . related_meal . id } " )
2024-02-26 13:28:32 +05:30
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 ) :
2024-03-11 14:48:48 +05:30
instance . date = validated_data . get ( " date " , instance . date )
instance . time = validated_data . get ( " time " , instance . time )
2024-02-26 13:28:32 +05:30
instance . symptoms_description = validated_data . get (
" symptoms_description " , instance . symptoms_description
)
instance . interval = validated_data . get ( " interval " , instance . interval )
2024-03-29 00:45:21 +05:30
related_meal_id = validated_data . pop ( " related_meal_id " , None ) # Extract meal ID
if related_meal_id is not None :
instance . related_meal = related_meal_id
2024-02-26 13:28:32 +05:30
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 ( )
2024-04-04 16:27:43 +05:30
print ( f " symptoms meal record in update { instance . id , instance . related_meal . id } " )
2024-02-26 13:28:32 +05:30
2024-03-11 14:48:48 +05:30
return instance