Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
ff5f315
feat: ajustando script sql
luisaferreirass Mar 23, 2026
eab133a
feat: criação dos models
luisaferreirass Mar 23, 2026
2861d21
feat: adicionando decorator para analisar sinais quando um imóvel é d…
luisaferreirass Mar 23, 2026
179e6b3
feat: implementando serializers e validators
luisaferreirass Mar 23, 2026
6843515
feat: implementação das views de imóveis
luisaferreirass Mar 24, 2026
0bef916
feat: adição das urls
luisaferreirass Mar 24, 2026
a30f776
fix: alterando tipos de variáveis
luisaferreirass Mar 25, 2026
b8a61c8
feat: implementando filtros objetivos de imóveis
luisaferreirass Mar 25, 2026
c74c833
config: adicionando configuração de filtros
luisaferreirass Mar 25, 2026
6979e17
feat: adicionando filtro na view
luisaferreirass Mar 25, 2026
8b81c29
feat: ajustando modelagem do db
luisaferreirass Mar 25, 2026
039a918
fix: ajustando variaveis
luisaferreirass Mar 25, 2026
1564c64
feat: adicionando conexão com api da cloud para upload/delete de fotos
luisaferreirass Mar 26, 2026
590ce1d
config: adicionando variáveis de configuração da cloud
luisaferreirass Mar 26, 2026
6d6c353
fix: ajustndo nomes de atributos
luisaferreirass Mar 26, 2026
1e1b7f9
feat: implementando novos serializers de imagens, separando serialize…
luisaferreirass Mar 26, 2026
47adb54
feat: ajustando views para os novos serializers
luisaferreirass Mar 26, 2026
8e21ef2
feat: criando novas urls e ajustando erros
luisaferreirass Mar 26, 2026
224bfbb
config: add migrations
luisaferreirass Mar 26, 2026
7357994
fix: ajustando erros
luisaferreirass Mar 26, 2026
1f52e69
feat: separação de views e serializers e implementação de UpdatePhoto…
luisaferreirass Mar 26, 2026
d121955
feat: junção e refatoração de views
luisaferreirass Mar 28, 2026
5aeb13c
fix: junção de urls
luisaferreirass Mar 28, 2026
ac9d561
fix: correção de erros
luisaferreirass Mar 28, 2026
70bc657
fix logic errors
luisaferreirass Mar 31, 2026
c72db65
feat: implementing isAdvertiser permission and refactoring code
luisaferreirass Mar 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions apps/properties/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@
class PropertiesConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "apps.properties"
def ready(self):
import apps.properties.signals # importa o arquivo de signals
53 changes: 53 additions & 0 deletions apps/properties/filters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import django_filters
from .models import Properties

class PropertiesFilters(django_filters.FilterSet):
# price
min_price = django_filters.NumberFilter(field_name="price", lookup_expr="gte")
max_price = django_filters.NumberFilter(field_name="price", lookup_expr="lte")

# Size
min_area = django_filters.NumberFilter(field_name="area", lookup_expr="gte")
max_area = django_filters.NumberFilter(field_name="area", lookup_expr="lte")


# Localization
neighborhood = django_filters.CharFilter(lookup_expr="icontains")
city = django_filters.CharFilter(lookup_expr="icontains")

#Rooms
bedrooms = django_filters.BaseInFilter(field_name="rooms__bedrooms", lookup_expr="in")
bathrooms = django_filters.BaseInFilter(field_name="rooms__bathrooms", lookup_expr="in")
parking_spots = django_filters.BaseInFilter(field_name="rooms__parking_spots", lookup_expr="in")


# Rooms Extras
living_room = django_filters.BooleanFilter(field_name="rooms_extras__living_room")
garden = django_filters.BooleanFilter(field_name="rooms_extras__garden")
kitchen = django_filters.BooleanFilter(field_name="rooms_extras__kitchen")
laundry_room = django_filters.BooleanFilter(field_name="rooms_extras__laundry_room")
pool = django_filters.BooleanFilter(field_name="rooms_extras__pool")
office = django_filters.BooleanFilter(field_name="rooms_extras__office")

# Type
type = django_filters.MultipleChoiceFilter(choices=Properties.TYPE_CHOICES)

# Purpose
property_purpose = django_filters.MultipleChoiceFilter(choices=Properties.PURPOSE_CHOICES)

# Condo
condo_name = django_filters.CharFilter(field_name="condo__name", lookup_expr="icontains")
condo_gym = django_filters.BooleanFilter(field_name="condo__gym")
condo_pool = django_filters.BooleanFilter(field_name="condo__pool")
condo_court = django_filters.BooleanFilter(field_name="condo__court")
condo_parks = django_filters.BooleanFilter(field_name="condo__parks")
condo_party_spaces = django_filters.BooleanFilter(field_name="condo__party_spaces")
condo_concierge = django_filters.BooleanFilter(field_name="condo__concierge")

# Floors
floors = django_filters.BaseInFilter(lookup_expr="in")
floor_number = django_filters.BaseInFilter(lookup_expr="in")

class Meta:
model = Properties
fields = []
93 changes: 93 additions & 0 deletions apps/properties/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# Generated by Django 5.2 on 2026-03-26 13:34

import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):

initial = True

dependencies = [
]

operations = [
migrations.CreateModel(
name='Condo',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
('address', models.TextField(max_length=200)),
('gym', models.BooleanField(default=False)),
('pool', models.BooleanField(default=False)),
('court', models.BooleanField(default=False)),
('parks', models.BooleanField(default=False)),
('party_spaces', models.BooleanField(default=False)),
('concierge', models.BooleanField(default=False)),
],
),
migrations.CreateModel(
name='RoomsExtras',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('living_room', models.BooleanField(default=True)),
('garden', models.BooleanField(default=False)),
('kitchen', models.BooleanField(default=True)),
('laundry_room', models.BooleanField(default=False)),
('pool', models.BooleanField(default=False)),
('office', models.BooleanField(default=False)),
],
),
migrations.CreateModel(
name='Properties',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('property_purpose', models.CharField(choices=[('S', 'Sale'), ('R', 'Rent'), ('B', 'Both')], max_length=1)),
('type', models.CharField(choices=[('A', 'Apartment'), ('H', 'House')], max_length=1)),
('area', models.FloatField()),
('floors', models.IntegerField()),
('floor_number', models.IntegerField(blank=True, null=True)),
('price', models.DecimalField(decimal_places=2, max_digits=15)),
('address', models.TextField(max_length=200)),
('neighborhood', models.CharField(max_length=100)),
('city', models.CharField(max_length=100)),
('has_mobilia', models.BooleanField(default=False)),
('status', models.BooleanField(default=True)),
('description', models.TextField()),
('embedding', models.TextField()),
('created_at', models.DateTimeField(auto_now_add=True)),
('condo', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='properties', to='properties.condo')),
],
),
migrations.CreateModel(
name='PropertiesPhotos',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('r2_key', models.TextField()),
('order', models.IntegerField()),
('property_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='photos', to='properties.properties')),
],
),
migrations.CreateModel(
name='Rooms',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('bedrooms', models.IntegerField()),
('bathrooms', models.IntegerField()),
('parking_spots', models.IntegerField()),
],
options={
'constraints': [models.UniqueConstraint(fields=('bedrooms', 'bathrooms', 'parking_spots'), name='rooms_unique')],
},
),
migrations.AddField(
model_name='properties',
name='rooms',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='properties', to='properties.rooms'),
),
migrations.AddField(
model_name='properties',
name='rooms_extras',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='properties', to='properties.roomsextras'),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 5.2 on 2026-03-28 17:43

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('properties', '0001_initial'),
]

operations = [
migrations.RenameField(
model_name='propertiesphotos',
old_name='property_id',
new_name='property',
),
]
76 changes: 75 additions & 1 deletion apps/properties/models.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,77 @@
from django.db import models

# Create your models here.
class Rooms(models.Model):
bedrooms = models.IntegerField()
bathrooms = models.IntegerField()
parking_spots = models.IntegerField()

class Meta:
constraints = [
models.UniqueConstraint(
fields=["bedrooms", "bathrooms", "parking_spots"],
name="rooms_unique"
)
]

class RoomsExtras(models.Model):
living_room = models.BooleanField(default=True)
garden = models.BooleanField(default=False)
kitchen = models.BooleanField(default=True)
laundry_room = models.BooleanField(default=False)
pool = models.BooleanField(default=False)
office = models.BooleanField(default=False)

class Condo(models.Model):
name = models.CharField(max_length=100, null=False)
address = models.TextField(max_length=200)
gym = models.BooleanField(default=False)
pool = models.BooleanField(default=False)
court = models.BooleanField(default=False)
parks = models.BooleanField(default=False)
party_spaces = models.BooleanField(default=False)
concierge = models.BooleanField(default=False)

class Properties(models.Model):
PURPOSE_CHOICES = [("S", "Sale"), ("R", "Rent"), ("B", "Both")]
TYPE_CHOICES = [("A", "Apartment"), ("H", "House")]

rooms = models.ForeignKey(
Rooms,
on_delete=models.PROTECT,
related_name="properties"
)
rooms_extras = models.ForeignKey(
RoomsExtras,
on_delete=models.PROTECT,
related_name="properties"
)
condo = models.ForeignKey(
Condo,
on_delete=models.PROTECT,
related_name="properties",
null=True,
blank=True)
property_purpose = models.CharField(max_length=1, choices=PURPOSE_CHOICES)
type = models.CharField(max_length=1, choices=TYPE_CHOICES)
area = models.FloatField(null=False)
floors = models.IntegerField()
floor_number = models.IntegerField(null=True, blank=True)
price = models.DecimalField(max_digits=15, decimal_places=2)
address = models.TextField(max_length=200, null=False)
neighborhood = models.CharField(max_length=100, null=False)
city = models.CharField(max_length=100, null=False)
has_mobilia = models.BooleanField(default=False)
status = models.BooleanField(default=True)
description = models.TextField()
embedding = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)


class PropertiesPhotos(models.Model):
property = models.ForeignKey(
Properties,
on_delete=models.CASCADE,
related_name="photos"
)
r2_key = models.TextField(null=False, blank=False)
order = models.IntegerField()
38 changes: 38 additions & 0 deletions apps/properties/serializers/photo_serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from rest_framework import serializers
from apps.properties.models import PropertiesPhotos
from apps.properties.services import upload_to_cloud, delete_from_cloud, generate_url

class PropertiesUploadPhotosSerializer(serializers.ModelSerializer):
image = serializers.ImageField(write_only=True)

def create(self, validated_data):
image = validated_data.pop('image')

r2_key = upload_to_cloud(image)
return PropertiesPhotos.objects.create(r2_key=r2_key, **validated_data)

def update(self, instance, validated_data):
new_image = validated_data.pop('image', None)

if new_image:
delete_from_cloud(instance.r2_key)
instance.r2_key = upload_to_cloud(new_image)
instance.save()

return instance


class Meta:
model = PropertiesPhotos
fields = ['id', 'image', 'order']

class PropertiesPhotosSerializer(serializers.ModelSerializer):
url = serializers.SerializerMethodField()

def get_url(self, obj):
return generate_url(obj.r2_key)


class Meta:
model = PropertiesPhotos
fields = ['id', 'url']
Loading
Loading