b79229a5b0
Each nightly profile refresh now also picks FRIEND_SAMPLE_SIZE (5) random
followed users and fetches their rankings, building up a picture of friends'
lists over time. Rows are tagged with friend_beli_user_id/friend_name so the
agent tool can surface attribution ("via Alex").
Requires migration to add friend_beli_user_id/friend_name columns and update
unique_together on beli_restaurants.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
59 lines
2.3 KiB
Python
59 lines
2.3 KiB
Python
import enum
|
|
import uuid
|
|
|
|
from tortoise import fields
|
|
from tortoise.models import Model
|
|
|
|
from blueprints.email.crypto_service import EncryptedTextField
|
|
|
|
|
|
class BeliStatus(str, enum.Enum):
|
|
BEEN = "been"
|
|
WANT_TO_TRY = "want_to_try"
|
|
|
|
|
|
class BeliProfile(Model):
|
|
id = fields.UUIDField(primary_key=True, default=uuid.uuid4)
|
|
user = fields.ForeignKeyField("models.User", related_name="beli_profiles")
|
|
beli_email = fields.CharField(max_length=255)
|
|
beli_password = EncryptedTextField()
|
|
beli_user_id = fields.CharField(max_length=255, null=True)
|
|
# refresh token lasts 7 days; we store it encrypted to avoid re-authenticating each run
|
|
beli_refresh_token = EncryptedTextField(null=True)
|
|
last_refreshed_at = fields.DatetimeField(null=True)
|
|
last_error = fields.TextField(null=True)
|
|
enabled = fields.BooleanField(default=True)
|
|
created_at = fields.DatetimeField(auto_now_add=True)
|
|
updated_at = fields.DatetimeField(auto_now=True)
|
|
|
|
class Meta:
|
|
table = "beli_profiles"
|
|
unique_together = (("user", "beli_email"),)
|
|
|
|
|
|
class BeliRestaurant(Model):
|
|
id = fields.UUIDField(primary_key=True, default=uuid.uuid4)
|
|
profile = fields.ForeignKeyField("models.BeliProfile", related_name="restaurants")
|
|
beli_business_id = fields.CharField(max_length=255)
|
|
# Empty string = profile owner's own ranking; UUID string = a followed user's ranking
|
|
friend_beli_user_id = fields.CharField(max_length=255, default="")
|
|
friend_name = fields.CharField(max_length=255, null=True)
|
|
name = fields.CharField(max_length=500)
|
|
city = fields.CharField(max_length=255, null=True)
|
|
neighborhood = fields.CharField(max_length=255, null=True)
|
|
cuisine = fields.JSONField(default=list)
|
|
price_range = fields.CharField(max_length=10, null=True)
|
|
status = fields.CharEnumField(enum_type=BeliStatus, max_length=20)
|
|
rank_index = fields.IntField(null=True)
|
|
score = fields.DecimalField(max_digits=5, decimal_places=2, null=True)
|
|
notes = fields.TextField(null=True)
|
|
tags = fields.JSONField(default=list)
|
|
fetched_at = fields.DatetimeField(auto_now=True)
|
|
created_at = fields.DatetimeField(auto_now_add=True)
|
|
|
|
class Meta:
|
|
table = "beli_restaurants"
|
|
unique_together = (
|
|
("profile", "beli_business_id", "status", "friend_beli_user_id"),
|
|
)
|