Files
chat/services/calendar_service/schemas_mobile.py
Andrew K. Choi b98034b616
All checks were successful
continuous-integration/drone/push Build is passing
calendar
2025-09-26 14:12:49 +09:00

197 lines
6.6 KiB
Python

from datetime import date
from enum import Enum
from typing import Optional, Dict, Any, List
from pydantic import BaseModel, Field
from .schemas import (
EntryType, FlowIntensity, MoodType, CalendarEntryCreate, CalendarEntryResponse
)
class MobileFlowIntensity(int, Enum):
"""Flow intensity values used in the mobile app (1-5)"""
SPOTTING = 1
LIGHT = 2
MEDIUM = 3
HEAVY = 4
VERY_HEAVY = 5
@classmethod
def to_server_intensity(cls, value: int) -> Optional[str]:
"""Convert mobile app intensity value to server format"""
if value is None:
return None
mapping = {
cls.SPOTTING.value: FlowIntensity.SPOTTING.value,
cls.LIGHT.value: FlowIntensity.LIGHT.value,
cls.MEDIUM.value: FlowIntensity.MEDIUM.value,
cls.HEAVY.value: FlowIntensity.HEAVY.value,
cls.VERY_HEAVY.value: FlowIntensity.HEAVY.value, # Server has no "very heavy"
}
return mapping.get(value)
@classmethod
def from_server_intensity(cls, value: Optional[str]) -> Optional[int]:
"""Convert server intensity value to mobile app format"""
if value is None:
return None
mapping = {
FlowIntensity.SPOTTING.value: cls.SPOTTING.value,
FlowIntensity.LIGHT.value: cls.LIGHT.value,
FlowIntensity.MEDIUM.value: cls.MEDIUM.value,
FlowIntensity.HEAVY.value: cls.HEAVY.value,
}
return mapping.get(value)
class MobileMood(str, Enum):
"""Mood values used in the mobile app"""
HAPPY = "HAPPY"
SAD = "SAD"
ANXIOUS = "ANXIOUS"
IRRITABLE = "IRRITABLE"
ENERGETIC = "ENERGETIC"
TIRED = "TIRED"
@classmethod
def to_server_mood(cls, value: str) -> Optional[MoodType]:
"""Convert mobile app mood value to server format"""
if value is None:
return None
mapping = {
cls.HAPPY: MoodType.HAPPY,
cls.SAD: MoodType.SAD,
cls.ANXIOUS: MoodType.ANXIOUS,
cls.IRRITABLE: MoodType.IRRITATED, # Different spelling
cls.ENERGETIC: MoodType.ENERGETIC,
cls.TIRED: MoodType.TIRED,
}
return mapping.get(MobileMood(value))
@classmethod
def from_server_mood(cls, value: Optional[str]) -> Optional[str]:
"""Convert server mood value to mobile app format"""
if value is None:
return None
# Convert string value to MoodType enum
try:
mood_type = MoodType(value)
except ValueError:
return None
mapping = {
MoodType.HAPPY: cls.HAPPY,
MoodType.SAD: cls.SAD,
MoodType.ANXIOUS: cls.ANXIOUS,
MoodType.IRRITATED: cls.IRRITABLE, # Different spelling
MoodType.ENERGETIC: cls.ENERGETIC,
MoodType.TIRED: cls.TIRED,
}
return mapping.get(mood_type)
class MobileAppCalendarEntryCreate(BaseModel):
"""Schema for creating calendar entries from mobile app"""
entry_date: date
entry_type: str # Will be mapped to EntryType
flow_intensity: Optional[int] = None # 1-5 scale
symptoms: Optional[str] = None
mood: Optional[str] = None # Mobile mood enum as string
notes: Optional[str] = None
class MobileAppCalendarEntryResponse(BaseModel):
"""Schema for calendar entry responses to mobile app"""
id: int
user_id: int
entry_date: date
entry_type: str
flow_intensity: Optional[int] = None
symptoms: Optional[str] = None
mood: Optional[str] = None
notes: Optional[str] = None
created_at: date
updated_at: date
def convert_mobile_app_format_to_server(mobile_entry: MobileAppCalendarEntryCreate) -> CalendarEntryCreate:
"""Convert mobile app format to server format"""
# Map entry type
try:
entry_type = EntryType(mobile_entry.entry_type.lower())
except ValueError:
# Handle case where entry type doesn't match directly
if mobile_entry.entry_type == "MENSTRUATION":
entry_type = EntryType.PERIOD
elif mobile_entry.entry_type == "SPOTTING":
entry_type = EntryType.PERIOD
else:
# Default to symptoms if no direct mapping
entry_type = EntryType.SYMPTOMS
# Map flow intensity (1-5 scale to text values)
flow_intensity_str = None
if mobile_entry.flow_intensity is not None:
flow_intensity_str = MobileFlowIntensity.to_server_intensity(mobile_entry.flow_intensity)
# Map mood
mood_str = None
if mobile_entry.mood is not None:
try:
mobile_mood = MobileMood(mobile_entry.mood)
mood_type = MobileMood.to_server_mood(mobile_entry.mood)
if mood_type:
mood_str = mood_type.value
except ValueError:
# If mood doesn't match any enum value, leave it as None
pass
return CalendarEntryCreate(
entry_date=mobile_entry.entry_date,
entry_type=entry_type,
flow_intensity=flow_intensity_str,
symptoms=mobile_entry.symptoms or "",
mood=mood_str,
notes=mobile_entry.notes or "",
# Default values for server required fields that mobile app doesn't provide
period_symptoms="",
energy_level=0,
sleep_hours=0,
medications="",
)
def convert_server_response_to_mobile_app(
server_response: CalendarEntryResponse
) -> MobileAppCalendarEntryResponse:
"""Convert server response to mobile app format"""
# Map flow intensity back to 1-5 scale
flow_intensity = None
if server_response.flow_intensity is not None:
flow_intensity = MobileFlowIntensity.from_server_intensity(server_response.flow_intensity)
# Map mood back to mobile format
mood = None
if server_response.mood is not None:
mood = MobileMood.from_server_mood(server_response.mood)
# Upper case the entry type
entry_type = server_response.entry_type.upper() if server_response.entry_type else ""
return MobileAppCalendarEntryResponse(
id=server_response.id,
user_id=getattr(server_response, "user_id", 0), # Handle if field doesn't exist
entry_date=server_response.entry_date,
entry_type=entry_type,
flow_intensity=flow_intensity,
symptoms=server_response.symptoms,
mood=mood,
notes=server_response.notes,
created_at=getattr(server_response, "created_at", date.today()),
updated_at=getattr(server_response, "created_at", date.today()), # Fallback to created_at
)