From d363a09f364a5b4a53f603b5c1357eeb27d64a3d Mon Sep 17 00:00:00 2001 From: MatheusAlves96 Date: Wed, 22 Apr 2026 23:57:28 -0300 Subject: [PATCH] feat(backend): add video_url and video_position to properties - Model: video_url VARCHAR(512) nullable, video_position VARCHAR(20) default 'section' - Migration: k3l4m5n6o7p8_add_video_to_properties - Admin route: expose/accept video_url (sanitize empty->NULL) and video_position - Public schema: PropertyDetailOut exposes both fields --- backend/app/models/property.py | 2 ++ backend/app/routes/admin.py | 11 +++++++- backend/app/schemas/property.py | 2 ++ .../k3l4m5n6o7p8_add_video_to_properties.py | 26 +++++++++++++++++++ 4 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 backend/migrations/versions/k3l4m5n6o7p8_add_video_to_properties.py diff --git a/backend/app/models/property.py b/backend/app/models/property.py index ac8f48b..55c1732 100644 --- a/backend/app/models/property.py +++ b/backend/app/models/property.py @@ -51,6 +51,8 @@ class Property(db.Model): index=True, ) created_at = db.Column(db.DateTime, nullable=False, server_default=db.func.now()) + video_url = db.Column(db.String(512), nullable=True) + video_position = db.Column(db.String(20), nullable=False, server_default='section') photos = db.relationship( "PropertyPhoto", diff --git a/backend/app/routes/admin.py b/backend/app/routes/admin.py index 86406ed..d01cd62 100644 --- a/backend/app/routes/admin.py +++ b/backend/app/routes/admin.py @@ -4,7 +4,7 @@ import re import bcrypt from datetime import datetime, date from decimal import Decimal -from typing import Optional +from typing import Optional, Literal from flask import Blueprint, request, jsonify, current_app, send_from_directory from werkzeug.utils import secure_filename from pydantic import BaseModel, ValidationError @@ -168,6 +168,8 @@ class PropertyAdminOut(BaseModel): is_featured: bool photos: list[PhotoAdminOut] = [] amenity_ids: list[int] = [] + video_url: Optional[str] = None + video_position: Literal['carousel', 'section'] = 'section' @classmethod def from_prop(cls, p: Property) -> "PropertyAdminOut": @@ -203,6 +205,8 @@ class PropertyAdminOut(BaseModel): for ph in p.photos ], amenity_ids=[a.id for a in p.amenities], + video_url=p.video_url, + video_position=p.video_position, ) @@ -348,10 +352,15 @@ def admin_update_property(property_id: str): "area_m2", "city_id", "neighborhood_id", + "video_position", ) for field in _SCALAR_FIELDS: if field in body: setattr(prop, field, body[field]) + # video_url: sanitizar e tratar string vazia como NULL + if 'video_url' in body: + raw = body['video_url'] + prop.video_url = raw.strip() if raw and raw.strip() else None # code: tratar string vazia como NULL if "code" in body: prop.code = body["code"] if body["code"] else None diff --git a/backend/app/schemas/property.py b/backend/app/schemas/property.py index 967bc46..7b6c2ba 100644 --- a/backend/app/schemas/property.py +++ b/backend/app/schemas/property.py @@ -61,3 +61,5 @@ class PropertyDetailOut(PropertyOut): address: str | None = None code: str | None = None description: str | None = None + video_url: str | None = None + video_position: Literal['carousel', 'section'] = 'section' diff --git a/backend/migrations/versions/k3l4m5n6o7p8_add_video_to_properties.py b/backend/migrations/versions/k3l4m5n6o7p8_add_video_to_properties.py new file mode 100644 index 0000000..8ede227 --- /dev/null +++ b/backend/migrations/versions/k3l4m5n6o7p8_add_video_to_properties.py @@ -0,0 +1,26 @@ +"""add video to properties + +Revision ID: k3l4m5n6o7p8 +Revises: j2k3l4m5n6o7 +Create Date: 2026-04-22 +""" +import sqlalchemy as sa +from alembic import op + +revision = 'k3l4m5n6o7p8' +down_revision = 'j2k3l4m5n6o7' +branch_labels = None +depends_on = None + + +def upgrade() -> None: + 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')) + + +def downgrade() -> None: + op.drop_column('properties', 'video_position') + op.drop_column('properties', 'video_url')