Skip to content

Commit a287a15

Browse files
committed
Add coords to sublet model
1 parent bcf14e6 commit a287a15

3 files changed

Lines changed: 101 additions & 1 deletion

File tree

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Generated by Django 5.0.2 on 2026-02-13 23:08
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("market", "0004_rename_address_sublet_street_address_and_more"),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name="sublet",
15+
name="true_latitude",
16+
field=models.DecimalField(
17+
blank=True, decimal_places=6, max_digits=9, null=True
18+
),
19+
),
20+
migrations.AddField(
21+
model_name="sublet",
22+
name="true_longitude",
23+
field=models.DecimalField(
24+
blank=True, decimal_places=6, max_digits=9, null=True
25+
),
26+
),
27+
]

backend/market/models.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,10 +131,52 @@ class Sublet(Listing):
131131
start_date = models.DateField()
132132
end_date = models.DateField()
133133

134+
true_latitude = models.DecimalField(max_digits=9, decimal_places=6, null=True, blank=True)
135+
true_longitude = models.DecimalField(max_digits=9, decimal_places=6, null=True, blank=True)
136+
137+
134138
def clean(self):
135139
super().clean()
136140
if self.start_date and self.end_date and self.start_date >= self.end_date:
137141
raise ValidationError({"end_date": "End date must be after start date"})
142+
143+
def _calculate_fake_location(self, true_latitude, true_longitude):
144+
import math
145+
import hashlib
146+
from decimal import Decimal
147+
148+
if true_latitude is None or true_longitude is None:
149+
return None, None
150+
151+
lat_str = f"{float(true_latitude):.6f}"
152+
lon_str = f"{float(true_longitude):.6f}"
153+
seed = hashlib.md5(f"{lat_str}{lon_str}".encode()).hexdigest()
154+
155+
offset_factor = int(seed[:8], 16) / 0xFFFFFFFF
156+
157+
offset_distance = 0.0005 + (offset_factor * 0.0013)
158+
angle = offset_factor * 2 * math.pi
159+
160+
lat_offset = offset_distance * math.sin(angle)
161+
lon_offset = offset_distance * math.cos(angle)
162+
163+
approx_lat = Decimal(str(float(true_latitude) + lat_offset))
164+
approx_lon = Decimal(str(float(true_longitude) + lon_offset))
165+
return approx_lat, approx_lon
166+
167+
@property
168+
def fake_latitude(self):
169+
if self.true_latitude and self.true_longitude:
170+
fake_lat, _ = self._calculate_fake_location(self.true_latitude, self.true_longitude)
171+
return fake_lat
172+
return None
173+
174+
@property
175+
def fake_longitude(self):
176+
if self.true_latitude and self.true_longitude:
177+
_, fake_lon = self._calculate_fake_location(self.true_latitude, self.true_longitude)
178+
return fake_lon
179+
return None
138180

139181
def save(self, *args, **kwargs):
140182
self.full_clean()

backend/market/serializers.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,25 @@ def get_condition(self, obj):
9898

9999

100100
class SubletDataSerializer(ModelSerializer):
101+
latitude = SerializerMethodField()
102+
longitude = SerializerMethodField()
103+
101104
class Meta:
102105
model = Sublet
103-
fields = ["street_address", "beds", "baths", "start_date", "end_date"]
106+
fields = ["street_address", "beds", "baths", "start_date", "end_date", "latitude", "longitude"]
107+
108+
def get_latitude(self, obj):
109+
if obj.true_latitude and obj.true_longitude:
110+
fake_lat, _ = obj._calculate_fake_location(obj.true_latitude, obj.true_longitude)
111+
return float(fake_lat) if fake_lat else None
112+
return None
113+
114+
def get_longitude(self, obj):
115+
if obj.true_latitude and obj.true_longitude:
116+
_, fake_lon = obj._calculate_fake_location(obj.true_latitude, obj.true_longitude)
117+
return float(fake_lon) if fake_lon else None
118+
return None
119+
104120

105121

106122
# Unified serializer for all listing types (Items and Sublets); used for CRUD operations
@@ -255,14 +271,25 @@ def _create_item(self, validated_data, additional_data):
255271
return item
256272

257273
def _create_sublet(self, validated_data, additional_data):
274+
from decimal import Decimal, ROUND_DOWN
258275
tags = validated_data.pop("tags", None)
259276

277+
latitude = additional_data.get("latitude")
278+
longitude = additional_data.get("longitude")
279+
280+
if latitude is not None:
281+
latitude = Decimal(str(latitude)).quantize(Decimal("1.000000"), rounding=ROUND_DOWN)
282+
if longitude is not None:
283+
longitude = Decimal(str(longitude)).quantize(Decimal("1.000000"), rounding=ROUND_DOWN)
284+
260285
sublet = Sublet.objects.create(
261286
street_address=additional_data.get("street_address"),
262287
beds=additional_data.get("beds"),
263288
baths=additional_data.get("baths"),
264289
start_date=additional_data.get("start_date"),
265290
end_date=additional_data.get("end_date"),
291+
true_latitude=latitude,
292+
true_longitude=longitude,
266293
**validated_data,
267294
)
268295

@@ -319,6 +346,10 @@ def _update_sublet(self, instance, additional_data):
319346
for field in sublet_fields:
320347
if field in additional_data:
321348
setattr(sublet, field, additional_data[field])
349+
if "latitude" in additional_data:
350+
sublet.true_latitude = additional_data["latitude"]
351+
if "longitude" in additional_data:
352+
sublet.true_longitude = additional_data["longitude"]
322353
sublet.full_clean()
323354
sublet.save()
324355

0 commit comments

Comments
 (0)