sass-imobiliaria/specs/033-video-apresentacao-imovel/data-model.md
MatheusAlves96 e1a1f71fbd
Some checks failed
CI/CD → Deploy via SSH / Build & Push Docker Images (push) Successful in 1m6s
CI/CD → Deploy via SSH / Deploy via SSH (push) Successful in 4m18s
CI/CD → Deploy via SSH / Validate HTTPS & Endpoints (push) Has been cancelled
chore: seed sample video data, add spec 033 and update instructions
2026-04-22 23:57:50 -03:00

2.9 KiB

Data Model: Vídeo de Apresentação do Imóvel (033)

Gerado por: /speckit.plan
Data: 2026-04-22


Entidade Afetada: Property (tabela properties)

Novos Campos

Coluna Tipo SQL Nullable Default Restrições
video_url VARCHAR(512) NULL NULL
video_position VARCHAR(20) NOT NULL 'section' valores válidos: 'carousel' | 'section' (enforced no Pydantic)

Justificativa de tipos

  • VARCHAR(512) para video_url: URLs YouTube/Vimeo raramente ultrapassam 100 chars, mas URLs diretas de CDN podem ser longas; 512 é conservador sem overhead relevante.
  • VARCHAR(20) para video_position: valores 'carousel' (8 chars) e 'section' (7 chars) cabem confortavelmente; sem ENUM SQL para simplificar migrations.

Migration Alembic

Arquivo: backend/migrations/versions/k3l4m5n6o7p8_add_video_to_properties.py
Antecessora: j2k3l4m5n6o7_add_homepage_hero_theme_images.py

# upgrade
op.add_column('properties', sa.Column('video_url', sa.String(512), nullable=True))
op.add_column('properties', sa.Column('video_position', sa.String(20), nullable=False, server_default='section'))

# downgrade
op.drop_column('properties', 'video_position')
op.drop_column('properties', 'video_url')

Schema Pydantic — Campos Adicionados

PropertyDetailOut (backend/app/schemas/property.py)

video_url: str | None = None
video_position: Literal['carousel', 'section'] = 'section'

PropertyAdminOut (backend/app/routes/admin.py)

video_url: str | None = None
video_position: Literal['carousel', 'section'] = 'section'

_SCALAR_FIELDS no admin_update_property

Adicionar 'video_url' e 'video_position' à tupla _SCALAR_FIELDS.
Sanitização: se 'video_url' estiver presente no body, aplicar .strip() e tratar string vazia como None.


Tipos TypeScript

PropertyDetail (frontend/src/types/property.ts)

video_url: string | null
video_position: 'carousel' | 'section'

Validação de Regras

Regra Onde Validado
video_position só aceita 'carousel' ou 'section' Pydantic Literal (backend)
video_url string vazia → None handler admin_update_property (backend)
video_url sem espaços .strip() antes de persistir (backend)
URL inválida (domínio não suportado) → sem exibição getEmbedUrl retorna type: 'unknown' (frontend)

Estado de Transição

Property sem vídeo (video_url = NULL)
  → Nenhuma alteração visual na página de detalhe

Property com video_position = 'section'
  → Seção "Vídeo de Apresentação" renderizada após carrossel

Property com video_position = 'carousel'
  → VideoPlayer como índice 0 no PhotoCarousel

Remover vídeo (admin)
  → video_url = NULL, video_position retorna ao default 'section'