This commit is contained in:
Redsandy
2026-03-14 18:48:57 +03:00
parent 1d1350fc13
commit 3ea4fb4771
40 changed files with 2150 additions and 0 deletions

17
app/models/__init__.py Normal file
View File

@@ -0,0 +1,17 @@
from app.models.user import User
from app.models.activity import Activity
from app.models.zone import Zone
from app.models.zone_history import ZoneHistory
from app.models.friendship import Friendship
from app.models.score import Score
from app.models.notification import Notification
__all__ = [
"User",
"Activity",
"Zone",
"ZoneHistory",
"Friendship",
"Score",
"Notification",
]

19
app/models/activity.py Normal file
View File

@@ -0,0 +1,19 @@
import uuid
from datetime import datetime, timezone
from sqlmodel import SQLModel, Field
class Activity(SQLModel, table=True):
__tablename__ = "activities"
id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
user_id: uuid.UUID = Field(foreign_key="users.id", index=True)
type: str = Field(max_length=16) # run | cycle | walk | hike
started_at: datetime | None = None
ended_at: datetime | None = None
distance_m: float | None = None
raw_gpx: str | None = None # deleted after 30 days (privacy)
status: str = Field(
default="pending", max_length=16
) # pending | completed | failed
created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))

11
app/models/friendship.py Normal file
View File

@@ -0,0 +1,11 @@
import uuid
from datetime import datetime, timezone
from sqlmodel import SQLModel, Field
class Friendship(SQLModel, table=True):
__tablename__ = "friendships"
user_id: uuid.UUID = Field(foreign_key="users.id", primary_key=True)
friend_id: uuid.UUID = Field(foreign_key="users.id", primary_key=True)
created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))

View File

@@ -0,0 +1,17 @@
import uuid
from datetime import datetime, timezone
from sqlmodel import SQLModel, Field, Column
from sqlalchemy import JSON
class Notification(SQLModel, table=True):
__tablename__ = "notifications"
id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
user_id: uuid.UUID = Field(foreign_key="users.id", index=True)
type: str = Field(
max_length=32
) # zone_captured | leaderboard_change | streak_risk | friend_joined | raid_weekend
payload: dict = Field(default_factory=dict, sa_column=Column(JSON))
sent_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
read_at: datetime | None = None

15
app/models/score.py Normal file
View File

@@ -0,0 +1,15 @@
import uuid
from datetime import date, datetime, timezone
from sqlmodel import SQLModel, Field
class Score(SQLModel, table=True):
__tablename__ = "scores"
id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
user_id: uuid.UUID = Field(foreign_key="users.id", index=True)
date: date
base_pts: int = 0
bonus_pts: int = 0
total_pts: int = 0
streak_days: int = 0

15
app/models/user.py Normal file
View File

@@ -0,0 +1,15 @@
import uuid
from datetime import datetime, timezone
from sqlmodel import SQLModel, Field
class User(SQLModel, table=True):
__tablename__ = "users"
id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
username: str = Field(max_length=32, unique=True, index=True)
email: str = Field(unique=True, index=True)
password_hash: str
avatar_url: str | None = None
fcm_token: str | None = None
created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))

19
app/models/zone.py Normal file
View File

@@ -0,0 +1,19 @@
import uuid
from datetime import datetime, timezone
from sqlmodel import SQLModel, Field
class Zone(SQLModel, table=True):
__tablename__ = "zones"
id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
owner_id: uuid.UUID = Field(foreign_key="users.id", index=True)
activity_id: uuid.UUID = Field(foreign_key="activities.id")
# Polygon stored as WKT text for SQLite compatibility.
# For PostgreSQL/PostGIS, a migration can add a GEOMETRY column.
polygon_wkt: str # e.g. "POLYGON((lon lat, lon lat, ...))"
area_m2: float
defense_level: int = Field(default=1)
defense_runs: int = Field(default=0)
created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
last_reinforced_at: datetime | None = None

View File

@@ -0,0 +1,14 @@
import uuid
from datetime import datetime, timezone
from sqlmodel import SQLModel, Field
class ZoneHistory(SQLModel, table=True):
__tablename__ = "zone_history"
id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
zone_id: uuid.UUID = Field(foreign_key="zones.id", index=True)
from_owner_id: uuid.UUID = Field(foreign_key="users.id")
to_owner_id: uuid.UUID = Field(foreign_key="users.id")
changed_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
cause: str = Field(max_length=16) # capture | merge