File size: 6,782 Bytes
b407a42
 
91dc3b5
8ee3f02
fe2f3e5
 
 
b407a42
 
8ee3f02
b407a42
 
 
df8187a
fe2f3e5
 
 
df8187a
fe2f3e5
df8187a
fe2f3e5
 
 
 
b407a42
 
91dc3b5
df8187a
fe2f3e5
91dc3b5
fe2f3e5
df8187a
fe2f3e5
df8187a
fe2f3e5
 
91dc3b5
fe2f3e5
b407a42
91dc3b5
 
 
df8187a
91dc3b5
 
b407a42
 
fe2f3e5
 
 
91dc3b5
 
df8187a
fe2f3e5
91dc3b5
df8187a
fe2f3e5
91dc3b5
df8187a
91dc3b5
fe2f3e5
91dc3b5
 
fe2f3e5
 
 
91dc3b5
fe2f3e5
 
df8187a
fe2f3e5
 
91dc3b5
 
 
fe2f3e5
 
 
 
 
 
b407a42
 
91dc3b5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b407a42
 
8ee3f02
 
 
b407a42
 
 
 
91dc3b5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82a6cc5
 
 
a9ccd3b
 
82a6cc5
 
 
 
 
 
 
a9ccd3b
82a6cc5
 
 
 
 
 
 
 
 
a9ccd3b
82a6cc5
 
 
a9ccd3b
 
82a6cc5
a9ccd3b
82a6cc5
 
a9ccd3b
82a6cc5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
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