This commit is contained in:
@@ -8,9 +8,11 @@ from sqlalchemy import and_, desc, select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from services.calendar_service.models import CalendarEntry, CycleData, HealthInsights
|
||||
import services.calendar_service.schemas as schemas
|
||||
from services.calendar_service.schemas import (CalendarEntryCreate, CalendarEntryResponse,
|
||||
CycleDataResponse, CycleOverview, EntryType,
|
||||
FlowIntensity, HealthInsightResponse, MoodType)
|
||||
FlowIntensity, HealthInsightResponse, MoodType,
|
||||
CalendarEventCreate)
|
||||
from shared.auth import get_current_user_from_token as get_current_user
|
||||
from shared.config import settings
|
||||
from shared.database import get_db
|
||||
@@ -33,42 +35,7 @@ async def health_check():
|
||||
return {"status": "healthy", "service": "calendar_service"}
|
||||
|
||||
|
||||
class CycleDataResponse(BaseModel):
|
||||
id: int
|
||||
cycle_start_date: date
|
||||
cycle_length: Optional[int]
|
||||
period_length: Optional[int]
|
||||
ovulation_date: Optional[date]
|
||||
fertile_window_start: Optional[date]
|
||||
fertile_window_end: Optional[date]
|
||||
next_period_predicted: Optional[date]
|
||||
avg_cycle_length: Optional[int]
|
||||
avg_period_length: Optional[int]
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class HealthInsightResponse(BaseModel):
|
||||
id: int
|
||||
insight_type: str
|
||||
title: str
|
||||
description: str
|
||||
recommendation: Optional[str]
|
||||
confidence_level: str
|
||||
created_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class CycleOverview(BaseModel):
|
||||
current_cycle_day: Optional[int]
|
||||
current_phase: str # menstrual, follicular, ovulation, luteal
|
||||
next_period_date: Optional[date]
|
||||
days_until_period: Optional[int]
|
||||
cycle_regularity: str # very_regular, regular, irregular, very_irregular
|
||||
avg_cycle_length: Optional[int]
|
||||
# Используем классы из schemas
|
||||
|
||||
|
||||
def calculate_cycle_phase(
|
||||
@@ -124,62 +91,28 @@ async def calculate_predictions(user_id: int, db: AsyncSession):
|
||||
}
|
||||
|
||||
|
||||
@app.post("/api/v1/entries", response_model=CalendarEntryResponse)
|
||||
async def create_calendar_entry(
|
||||
@app.post("/api/v1/entries", response_model=CalendarEntryResponse, status_code=201)
|
||||
@app.post("/api/v1/entry", response_model=CalendarEntryResponse, status_code=201)
|
||||
async def create_calendar_entry_legacy(
|
||||
entry_data: CalendarEntryCreate,
|
||||
current_user: Dict = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
"""Create new calendar entry"""
|
||||
"""Create a new calendar entry via legacy endpoint"""
|
||||
return await create_calendar_entry(entry_data, current_user, db)
|
||||
|
||||
# Check if entry already exists for this date and type
|
||||
existing = await db.execute(
|
||||
select(CalendarEntry).filter(
|
||||
and_(
|
||||
CalendarEntry.user_id == current_user["user_id"],
|
||||
CalendarEntry.entry_date == entry_data.entry_date,
|
||||
CalendarEntry.entry_type == entry_data.entry_type.value,
|
||||
)
|
||||
)
|
||||
)
|
||||
if existing.scalars().first():
|
||||
raise HTTPException(
|
||||
status_code=400, detail="Entry already exists for this date and type"
|
||||
)
|
||||
|
||||
try:
|
||||
db_entry = CalendarEntry(
|
||||
user_id=current_user["user_id"],
|
||||
entry_date=entry_data.entry_date,
|
||||
entry_type=entry_data.entry_type.value,
|
||||
flow_intensity=entry_data.flow_intensity.value
|
||||
if entry_data.flow_intensity
|
||||
else None,
|
||||
period_symptoms=entry_data.period_symptoms,
|
||||
mood=entry_data.mood.value if entry_data.mood else None,
|
||||
energy_level=entry_data.energy_level,
|
||||
sleep_hours=entry_data.sleep_hours,
|
||||
symptoms=entry_data.symptoms,
|
||||
medications=entry_data.medications,
|
||||
notes=entry_data.notes,
|
||||
)
|
||||
|
||||
db.add(db_entry)
|
||||
await db.commit()
|
||||
await db.refresh(db_entry)
|
||||
|
||||
import logging
|
||||
logging.info(f"Created calendar entry: {db_entry.id}")
|
||||
except Exception as e:
|
||||
import logging
|
||||
logging.error(f"Error creating calendar entry: {str(e)}")
|
||||
raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
|
||||
|
||||
# If this is a period entry, update cycle data
|
||||
if entry_data.entry_type == EntryType.PERIOD:
|
||||
await update_cycle_data(current_user["user_id"], entry_data.entry_date, db)
|
||||
|
||||
return CalendarEntryResponse.model_validate(db_entry)
|
||||
@app.post("/api/v1/calendar/entry", response_model=CalendarEntryResponse, status_code=201)
|
||||
async def create_calendar_entry_mobile_app(
|
||||
entry_data: CalendarEventCreate,
|
||||
current_user: Dict = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
"""Create a new calendar entry via mobile app format endpoint"""
|
||||
# Convert mobile app format to server format
|
||||
server_entry_data = entry_data.to_server_format()
|
||||
response = await create_calendar_entry(server_entry_data, current_user, db)
|
||||
return response
|
||||
|
||||
|
||||
async def update_cycle_data(user_id: int, period_date: date, db: AsyncSession):
|
||||
@@ -455,6 +388,84 @@ async def health_check():
|
||||
return {"status": "healthy", "service": "calendar-service"}
|
||||
|
||||
|
||||
# Новый эндпоинт для мобильного приложения
|
||||
@app.post("/api/v1/calendar/entry", response_model=schemas.CalendarEvent, status_code=201)
|
||||
async def create_mobile_calendar_entry(
|
||||
entry_data: schemas.CalendarEventCreate,
|
||||
current_user: Dict = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
"""Create a new calendar entry from mobile app"""
|
||||
import logging
|
||||
logging.info(f"Received mobile entry data: {entry_data}")
|
||||
|
||||
# Преобразуем в серверный формат
|
||||
server_entry_data = entry_data.to_server_format()
|
||||
logging.info(f"Converted to server format: {server_entry_data}")
|
||||
|
||||
# Проверяем существование записи
|
||||
try:
|
||||
existing = await db.execute(
|
||||
select(CalendarEntry).filter(
|
||||
and_(
|
||||
CalendarEntry.user_id == current_user["user_id"],
|
||||
CalendarEntry.entry_date == server_entry_data.entry_date,
|
||||
CalendarEntry.entry_type == server_entry_data.entry_type.value,
|
||||
)
|
||||
)
|
||||
)
|
||||
existing_entry = existing.scalars().first()
|
||||
|
||||
if existing_entry:
|
||||
# Если запись существует, обновляем её
|
||||
if server_entry_data.flow_intensity:
|
||||
existing_entry.flow_intensity = server_entry_data.flow_intensity.value
|
||||
if server_entry_data.symptoms:
|
||||
existing_entry.symptoms = server_entry_data.symptoms
|
||||
if server_entry_data.mood:
|
||||
existing_entry.mood = server_entry_data.mood.value
|
||||
if server_entry_data.notes:
|
||||
existing_entry.notes = server_entry_data.notes
|
||||
|
||||
await db.commit()
|
||||
await db.refresh(existing_entry)
|
||||
|
||||
# Возвращаем обновлённую запись
|
||||
response = schemas.CalendarEntryResponse.model_validate(existing_entry)
|
||||
return schemas.CalendarEvent.from_server_response(response)
|
||||
|
||||
# Создаем новую запись
|
||||
db_entry = CalendarEntry(
|
||||
user_id=current_user["user_id"],
|
||||
entry_date=server_entry_data.entry_date,
|
||||
entry_type=server_entry_data.entry_type.value,
|
||||
flow_intensity=server_entry_data.flow_intensity.value if server_entry_data.flow_intensity else None,
|
||||
period_symptoms=server_entry_data.period_symptoms,
|
||||
mood=server_entry_data.mood.value if server_entry_data.mood else None,
|
||||
energy_level=server_entry_data.energy_level,
|
||||
sleep_hours=server_entry_data.sleep_hours,
|
||||
symptoms=server_entry_data.symptoms,
|
||||
medications=server_entry_data.medications,
|
||||
notes=server_entry_data.notes,
|
||||
)
|
||||
|
||||
db.add(db_entry)
|
||||
await db.commit()
|
||||
await db.refresh(db_entry)
|
||||
|
||||
# Если это запись о периоде, обновляем данные цикла
|
||||
if server_entry_data.entry_type == schemas.EntryType.PERIOD:
|
||||
await update_cycle_data(current_user["user_id"], server_entry_data.entry_date, db)
|
||||
|
||||
# Преобразуем в формат для мобильного приложения
|
||||
response = schemas.CalendarEntryResponse.model_validate(db_entry)
|
||||
return schemas.CalendarEvent.from_server_response(response)
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"Error creating calendar entry: {str(e)}")
|
||||
raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
|
||||
|
||||
Reference in New Issue
Block a user