bookmyservice-ums / app /models /user_model.py
MukeshKapoor25's picture
refactor(logging): change debug to info level for operational logs
df8187a
from fastapi import HTTPException
from app.core.nosql_client import db
from app.utils.common_utils import is_email, is_phone, validate_identifier # Updated imports
from app.schemas.user_schema import UserRegisterRequest
import logging
logger = logging.getLogger("user_model")
class BookMyServiceUserModel:
collection = db["customers"]
@staticmethod
async def find_by_email(email: str):
logger.info(f"Searching for user by email: {email}")
try:
user = await BookMyServiceUserModel.collection.find_one({"email": email})
if user:
logger.info(f"User found by email: {email}")
else:
logger.info(f"No user found with email: {email}")
return user
except Exception as e:
logger.error(f"Error finding user by email {email}: {str(e)}", exc_info=True)
return None
@staticmethod
async def find_by_phone(phone: str):
logger.info(f"Searching for user by phone: {phone}")
try:
user = await BookMyServiceUserModel.collection.find_one({"phone": phone})
if user:
logger.info(f"User found by phone: {phone}")
else:
logger.info(f"No user found with phone: {phone}")
return user
except Exception as e:
logger.error(f"Error finding user by phone {phone}: {str(e)}", exc_info=True)
return None
@staticmethod
async def find_by_mobile(mobile: str):
"""Legacy method for backward compatibility - redirects to find_by_phone"""
logger.info(f"Legacy find_by_mobile called, redirecting to find_by_phone for: {mobile}")
return await BookMyServiceUserModel.find_by_phone(mobile)
@staticmethod
async def find_by_identifier(identifier: str):
logger.info(f"Finding user by identifier: {identifier}")
try:
# Validate and determine identifier type
identifier_type = validate_identifier(identifier)
logger.info(f"Identifier type determined: {identifier_type}")
if identifier_type == "email":
logger.info(f"Searching by email for identifier: {identifier}")
user = await BookMyServiceUserModel.find_by_email(identifier)
elif identifier_type == "phone":
logger.info(f"Searching by phone for identifier: {identifier}")
user = await BookMyServiceUserModel.find_by_phone(identifier)
else:
logger.error(f"Invalid identifier type: {identifier_type}")
raise HTTPException(status_code=400, detail="Invalid identifier format")
if not user:
logger.warning(f"User not found with identifier: {identifier}")
raise HTTPException(status_code=404, detail="User not found with this email or phone")
logger.info(f"User found successfully for identifier: {identifier}")
logger.info(f"User data keys: {list(user.keys()) if user else 'None'}")
return user
except ValueError as ve:
logger.error(f"Validation error for identifier {identifier}: {str(ve)}")
raise HTTPException(status_code=400, detail=str(ve))
except HTTPException as e:
logger.error(f"HTTP error finding user by identifier {identifier}: {e.status_code} - {e.detail}")
raise e
except Exception as e:
logger.error(f"Unexpected error finding user by identifier {identifier}: {str(e)}", exc_info=True)
raise HTTPException(status_code=500, detail="Failed to find user")
@staticmethod
async def exists_by_email_or_phone(email: str = None, phone: str = None) -> bool:
"""Check if user exists by email or phone"""
query_conditions = []
if email:
query_conditions.append({"email": email})
if phone:
query_conditions.append({"phone": phone})
if not query_conditions:
return False
query = {"$or": query_conditions} if len(query_conditions) > 1 else query_conditions[0]
result = await BookMyServiceUserModel.collection.find_one(query)
return result is not None
@staticmethod
async def create(user_data: UserRegisterRequest):
user_dict = user_data.dict()
result = await BookMyServiceUserModel.collection.insert_one(user_dict)
return result.inserted_id
@staticmethod
async def update_by_identifier(identifier: str, update_fields: dict):
try:
identifier_type = validate_identifier(identifier)
if identifier_type == "email":
query = {"email": identifier}
elif identifier_type == "phone":
query = {"phone": identifier}
else:
raise HTTPException(status_code=400, detail="Invalid identifier format")
result = await BookMyServiceUserModel.collection.update_one(query, {"$set": update_fields})
if result.matched_count == 0:
raise HTTPException(status_code=404, detail="User not found")
return result.modified_count > 0
except ValueError as ve:
logger.error(f"Validation error for identifier {identifier}: {str(ve)}")
raise HTTPException(status_code=400, detail=str(ve))
@staticmethod
async def update_profile(customer_id: str, update_fields: dict):
"""Update user profile by customer_id"""
try:
from datetime import datetime
# Add updated_at timestamp
update_fields["updated_at"] = datetime.utcnow()
result = await BookMyServiceUserModel.collection.update_one(
{"customer_id": customer_id},
{"$set": update_fields}
)
if result.matched_count == 0:
raise HTTPException(status_code=404, detail="User not found")
return result.modified_count > 0
except Exception as e:
logger.error(f"Error updating profile for user {customer_id}: {str(e)}")
raise HTTPException(status_code=500, detail="Failed to update profile")
@staticmethod
async def find_by_id(customer_id: str):
"""Find user by customer_id"""
try:
user = await BookMyServiceUserModel.collection.find_one({"customer_id": customer_id})
return user
except Exception as e:
logger.error(f"Error finding user by ID {customer_id}: {str(e)}")
return None