AIDA / app /models /user.py
destinyebuka's picture
fyp
ee3d3d4
# ============================================================
# app/models/user.py - User Model
# ============================================================
from datetime import datetime
from typing import Optional
from datetime import datetime
from enum import Enum
class UserRole(str, Enum):
"""User roles"""
RENTER = "renter"
LANDLORD = "landlord"
ADMIN = "admin"
class SubscriptionType(str, Enum):
"""Subscription types"""
FREE = "free"
PREMIUM = "premium"
class User:
"""User model for MongoDB"""
@staticmethod
def create_document(
first_name: str,
last_name: str,
email: Optional[str],
phone: Optional[str],
hashed_password: str,
role: str,
preferred_language: str = "en",
) -> dict:
"""Create user document for insertion"""
now = datetime.utcnow()
return {
"firstName": first_name,
"lastName": last_name,
"email": email.lower() if email else None,
"phone": phone,
"password": hashed_password,
"role": role,
"subscriptionType": SubscriptionType.FREE.value,
"subscriptionExpiresAt": None,
"isEmailVerified": False if email else None,
"isPhoneVerified": False if phone else None,
"isActive": False, # Inactive until email/phone verified
"totalListings": 0,
"profilePicture": None,
"bio": None,
"location": None,
"languages": [],
"preferredLanguage": preferred_language, # User's preferred language for emails/notifications
"isVerified": False,
"rating": 0.0, # User's average rating from reviews
"reviews_count": 0, # Number of reviews received
"lastLogin": None,
"createdAt": now,
"updatedAt": now,
}
@staticmethod
def format_response(user_doc: dict) -> dict:
"""Format user document for API response"""
if not user_doc:
return None
return {
"id": str(user_doc.get("_id", "")),
"firstName": user_doc.get("firstName"),
"lastName": user_doc.get("lastName"),
"email": user_doc.get("email"),
"phone": user_doc.get("phone"),
"role": user_doc.get("role"),
"subscriptionType": user_doc.get("subscriptionType", "free"),
"subscriptionExpiresAt": user_doc.get("subscriptionExpiresAt"),
"isEmailVerified": user_doc.get("isEmailVerified"),
"isPhoneVerified": user_doc.get("isPhoneVerified"),
"isActive": user_doc.get("isActive"),
"totalListings": user_doc.get("totalListings", 0),
"profilePicture": user_doc.get("profilePicture"),
"bio": user_doc.get("bio"),
"location": user_doc.get("location"),
"languages": user_doc.get("languages", []),
"preferredLanguage": user_doc.get("preferredLanguage", "en"),
"isVerified": user_doc.get("isVerified", False),
"rating": user_doc.get("rating", 0.0), # User's average rating
"reviews_count": user_doc.get("reviews_count", 0),
"lastLogin": user_doc.get("lastLogin"),
"createdAt": user_doc.get("createdAt"),
"updatedAt": user_doc.get("updatedAt"),
}
# ============================================================
# app/models/otp.py - OTP Model
# ============================================================
class OTP:
"""OTP model for MongoDB"""
OTP_PURPOSES = ["signup", "password_reset"]
@staticmethod
def create_document(
identifier: str,
code: str,
purpose: str,
) -> dict:
"""Create OTP document for insertion"""
return {
"identifier": identifier,
"code": code,
"purpose": purpose,
"isVerified": False,
"attempts": 0,
"createdAt": datetime.utcnow(),
}
@staticmethod
def format_response(otp_doc: dict) -> dict:
"""Format OTP document for API response"""
if not otp_doc:
return None
return {
"id": str(otp_doc.get("_id", "")),
"identifier": otp_doc.get("identifier"),
"purpose": otp_doc.get("purpose"),
"isVerified": otp_doc.get("isVerified"),
"attempts": otp_doc.get("attempts"),
"createdAt": otp_doc.get("createdAt"),
}