62 lines
2.1 KiB
Python
62 lines
2.1 KiB
Python
"""Сервисный слой для онбординга."""
|
||
|
||
from __future__ import annotations
|
||
|
||
from sqlalchemy.orm import Session
|
||
|
||
from app.models.onboarding import OnboardingSlide, OnboardingState
|
||
from app.models.user import User
|
||
|
||
|
||
def _ensure_state(db: Session, user: User) -> OnboardingState:
|
||
"""Гарантируем наличие записи о прогрессе."""
|
||
|
||
if user.onboarding_state:
|
||
return user.onboarding_state
|
||
|
||
state = OnboardingState(user_id=user.id, last_completed_order=0, is_completed=False)
|
||
db.add(state)
|
||
db.flush()
|
||
db.refresh(state)
|
||
return state
|
||
|
||
|
||
def get_overview(db: Session, user: User) -> tuple[list[OnboardingSlide], OnboardingState, int | None]:
|
||
"""Возвращаем все слайды и текущий прогресс."""
|
||
|
||
slides = db.query(OnboardingSlide).order_by(OnboardingSlide.order).all()
|
||
state = _ensure_state(db, user)
|
||
|
||
next_slide = next((slide for slide in slides if slide.order > state.last_completed_order), None)
|
||
next_order: int | None = next_slide.order if next_slide else None
|
||
return slides, state, next_order
|
||
|
||
|
||
def complete_slide(db: Session, user: User, order: int) -> OnboardingState:
|
||
"""Фиксируем завершение шага, если это корректный порядок."""
|
||
|
||
slides = db.query(OnboardingSlide).order_by(OnboardingSlide.order).all()
|
||
if not slides:
|
||
raise ValueError("Онбординг ещё не настроен")
|
||
|
||
state = _ensure_state(db, user)
|
||
|
||
allowed_orders = [slide.order for slide in slides]
|
||
if order not in allowed_orders:
|
||
raise ValueError("Неизвестный шаг онбординга")
|
||
|
||
if order <= state.last_completed_order:
|
||
return state
|
||
|
||
expected_order = next((value for value in allowed_orders if value > state.last_completed_order), None)
|
||
if expected_order is None or order != expected_order:
|
||
raise ValueError("Сначала завершите предыдущие шаги")
|
||
|
||
state.last_completed_order = order
|
||
state.is_completed = order == allowed_orders[-1]
|
||
db.add(state)
|
||
db.commit()
|
||
db.refresh(state)
|
||
return state
|
||
|