goon/app/models/survey_response.py
goon-foss 88f8729840 feat(survey): jednorazowa ankieta in-app (6 pytan), endpointy i podsumowanie
- backend: tabela survey_responses (0055), GET /survey/current z bramka po obejrzanych
  scenach, POST /survey/{id} (upsert per urzadzenie), GET /survey/{id}/summary
- apka: SurveyModal po tutorialu i po "What's new" (popupBus), raz na urzadzenie,
  pomijalna, flaga w SecureStore; wpis w changelogu
2026-10-12 17:34:19 +02:00

37 lines
1.6 KiB
Python

"""Odpowiedzi na jednorazowa ankiete in-app (pytania sa w apce, patrz app/api/survey.py).
Jedna odpowiedz na urzadzenie i ankiete (UNIQUE survey_id + device_id, ponowne wyslanie
nadpisuje). `answers` to JSON {klucz_pytania: wartosc | [wartosci]}, bez danych osobowych.
"""
from __future__ import annotations
import uuid
from datetime import datetime
from typing import Any
from sqlalchemy import DateTime, Index, String, Text, UniqueConstraint, func
from sqlalchemy.dialects.postgresql import JSONB, UUID
from sqlalchemy.orm import Mapped, mapped_column
from app.models.base import Base
class SurveyResponse(Base):
__tablename__ = "survey_responses"
__table_args__ = (
UniqueConstraint("survey_id", "device_id", name="uq_survey_responses_survey_device"),
Index("ix_survey_responses_survey_created", "survey_id", "created_at"),
)
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
survey_id: Mapped[str] = mapped_column(String(32), nullable=False)
device_id: Mapped[str] = mapped_column(String(64), nullable=False)
answers: Mapped[dict[str, Any]] = mapped_column(JSONB, nullable=False)
free_text: Mapped[str | None] = mapped_column(Text, nullable=True)
app_version: Mapped[str | None] = mapped_column(String(32), nullable=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), server_default=func.now(), nullable=False
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False
)