calendar events
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2025-09-26 15:57:50 +09:00
parent 64171196b6
commit 76d0d86211
16 changed files with 1657 additions and 22 deletions

View File

@@ -13,6 +13,7 @@ from services.calendar_service.schemas import (CalendarEntryCreate, CalendarEntr
CycleDataResponse, CycleOverview, EntryType,
FlowIntensity, HealthInsightResponse, MoodType,
CalendarEventCreate)
from services.calendar_service.mobile_endpoint import MobileCalendarEntryCreate, mobile_create_calendar_entry
from shared.auth import get_current_user_from_token as get_current_user
from shared.config import settings
from shared.database import get_db
@@ -415,6 +416,160 @@ async def create_calendar_entry(
return CalendarEntryResponse.model_validate(new_entry)
# Мобильный эндпоинт для создания записей календаря
@app.post("/api/v1/calendar/entries/mobile", response_model=CalendarEntryResponse, status_code=201)
async def create_mobile_calendar_entry_endpoint(
mobile_entry: MobileCalendarEntryCreate,
current_user: Dict = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
"""Создать новую запись календаря из мобильного приложения"""
import logging
logging.info(f"Получены данные мобильного приложения: {mobile_entry.model_dump()}")
try:
# Преобразуем симптомы из списка в строку
symptoms_str = ""
if mobile_entry.symptoms:
symptoms_str = ", ".join(mobile_entry.symptoms)
logging.info(f"Преобразованы симптомы в строку: {symptoms_str}")
# Преобразуем данные из мобильного формата в формат сервера
server_entry = CalendarEntryCreate(
entry_date=mobile_entry.date,
entry_type=EntryType.PERIOD if mobile_entry.type == "MENSTRUATION" else
EntryType.OVULATION if mobile_entry.type == "OVULATION" else
EntryType.SYMPTOMS,
flow_intensity=FlowIntensity.from_int(mobile_entry.flow_intensity) if mobile_entry.flow_intensity else None,
mood=MoodType.from_mobile_mood(mobile_entry.mood) if mobile_entry.mood else None,
symptoms=symptoms_str,
notes=mobile_entry.notes,
# Значения по умолчанию для обязательных полей сервера
period_symptoms="",
energy_level=1, # Минимальное значение должно быть 1
sleep_hours=0,
medications="",
)
logging.info(f"Преобразовано в серверный формат: {server_entry}")
# Проверяем существование записи
existing = await db.execute(
select(CalendarEntry).filter(
and_(
CalendarEntry.user_id == current_user["user_id"],
CalendarEntry.entry_date == server_entry.entry_date,
CalendarEntry.entry_type == server_entry.entry_type.value,
)
)
)
existing_entry = existing.scalars().first()
if existing_entry:
logging.info(f"Найдена существующая запись с ID: {existing_entry.id}")
# Если запись существует, обновляем её
if server_entry.flow_intensity is not None:
setattr(existing_entry, 'flow_intensity', server_entry.flow_intensity.value if server_entry.flow_intensity else None)
if server_entry.symptoms is not None:
setattr(existing_entry, 'symptoms', server_entry.symptoms)
if server_entry.mood is not None:
setattr(existing_entry, 'mood', server_entry.mood.value if server_entry.mood else None)
if server_entry.notes is not None:
setattr(existing_entry, 'notes', server_entry.notes)
await db.commit()
await db.refresh(existing_entry)
logging.info("Существующая запись обновлена")
return CalendarEntryResponse.model_validate(existing_entry)
# Создаем новую запись в календаре
new_entry = CalendarEntry(
user_id=current_user["user_id"],
entry_date=server_entry.entry_date,
entry_type=server_entry.entry_type.value,
flow_intensity=server_entry.flow_intensity.value if server_entry.flow_intensity else None,
period_symptoms=server_entry.period_symptoms,
mood=server_entry.mood.value if server_entry.mood else None,
energy_level=server_entry.energy_level,
sleep_hours=server_entry.sleep_hours,
symptoms=server_entry.symptoms,
medications=server_entry.medications,
notes=server_entry.notes,
)
db.add(new_entry)
await db.commit()
await db.refresh(new_entry)
logging.info(f"Создана новая запись с ID: {new_entry.id}")
# Если это запись о менструации, обновляем данные цикла
if server_entry.entry_type == EntryType.PERIOD:
await update_cycle_data(current_user["user_id"], server_entry.entry_date, db)
logging.info("Данные цикла обновлены")
return CalendarEntryResponse.model_validate(new_entry)
except Exception as e:
logging.error(f"Ошибка при создании записи календаря: {str(e)}")
await db.rollback() # Откатываем транзакцию при ошибке
raise HTTPException(status_code=500, detail=f"Ошибка сервера: {str(e)}")
@app.post("/debug/mobile-entry", status_code=200)
async def debug_mobile_calendar_entry(
mobile_entry: MobileCalendarEntryCreate,
db: AsyncSession = Depends(get_db),
):
"""Тестовый эндпоинт для проверки преобразования данных из мобильного формата (без создания записи)"""
# Используем фиктивного пользователя для тестирования
mock_user = {"user_id": 1, "username": "test_user"}
# Преобразуем симптомы из списка в строку
symptoms_str = ""
if mobile_entry.symptoms:
symptoms_str = ", ".join(mobile_entry.symptoms)
# Преобразуем данные из мобильного формата в формат сервера
server_entry = CalendarEntryCreate(
entry_date=mobile_entry.date,
entry_type=EntryType.PERIOD if mobile_entry.type == "MENSTRUATION" else
EntryType.OVULATION if mobile_entry.type == "OVULATION" else
EntryType.SYMPTOMS,
flow_intensity=FlowIntensity.from_int(mobile_entry.flow_intensity) if mobile_entry.flow_intensity else None,
mood=MoodType.from_mobile_mood(mobile_entry.mood) if mobile_entry.mood else None,
symptoms=symptoms_str,
notes=mobile_entry.notes,
# Значения по умолчанию для обязательных полей сервера
period_symptoms="",
energy_level=1, # Минимальное значение должно быть 1
sleep_hours=0,
medications="",
)
# Создаем ответ без сохранения в БД
response_data = {
"id": 0, # Фиктивный ID
"user_id": mock_user["user_id"],
"entry_date": server_entry.entry_date.isoformat(),
"entry_type": server_entry.entry_type.value,
"flow_intensity": server_entry.flow_intensity.value if server_entry.flow_intensity else None,
"period_symptoms": server_entry.period_symptoms,
"mood": server_entry.mood.value if server_entry.mood else None,
"energy_level": server_entry.energy_level,
"sleep_hours": server_entry.sleep_hours,
"symptoms": server_entry.symptoms,
"medications": server_entry.medications,
"notes": server_entry.notes,
"created_at": date.today().isoformat(),
"updated_at": date.today().isoformat(),
"is_active": True
}
return {
"message": "Данные успешно преобразованы из мобильного формата (без сохранения в БД)",
"original_data": mobile_entry.model_dump(),
"transformed_data": response_data
}
@app.delete("/api/v1/entries/{entry_id}")
async def delete_calendar_entry(
@@ -476,14 +631,14 @@ async def create_mobile_calendar_entry(
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
if server_entry_data.flow_intensity is not None:
setattr(existing_entry, 'flow_intensity', server_entry_data.flow_intensity.value if server_entry_data.flow_intensity else None)
if server_entry_data.symptoms is not None:
setattr(existing_entry, 'symptoms', server_entry_data.symptoms)
if server_entry_data.mood is not None:
setattr(existing_entry, 'mood', server_entry_data.mood.value if server_entry_data.mood else None)
if server_entry_data.notes is not None:
setattr(existing_entry, 'notes', server_entry_data.notes)
await db.commit()
await db.refresh(existing_entry)