narendrasinghd commited on
Commit
21eb4e3
·
verified ·
1 Parent(s): fd39d85

Upload 6 files

Browse files
Files changed (5) hide show
  1. app/crud.py +42 -36
  2. app/models.py +6 -5
  3. app/router.py +100 -51
  4. app/services/agent.py +8 -0
  5. app/services/properties.py +51 -0
app/crud.py CHANGED
@@ -5,10 +5,10 @@ from utils.log_utils import setup_logger
5
 
6
  logger = setup_logger("crud")
7
 
8
- def get_property_by_mls_and_buyer_phone(db: Session, mls_number: str, buyer_agent_phone_number: str):
9
- return db.query(models.Property).filter(
10
- models.Property.mls_number == mls_number,
11
- models.Property.buyer_agent_phone_number == buyer_agent_phone_number
12
  ).first()
13
 
14
  def get_user_by_phone_number(db: Session, phone_number: str):
@@ -22,11 +22,12 @@ def create_user(db: Session, full_name: str, phone_number: str, type: str, agent
22
  user = db.query(models.User).filter(models.User.phone_number == phone_number).first()
23
  if user:
24
  if user.active_session_id:
25
- logger.info(f"User Already exist, with phone_number: {phone_number}")
 
 
26
  else:
27
- logger.info(f"User Already exist, with phone_number: {phone_number}")
28
  user.active_session_id = new_session_id
29
- user.all_session_ids = user.all_session_ids + [new_session_id]
30
  db.commit()
31
  db.refresh(user)
32
  return user
@@ -44,26 +45,31 @@ def create_user(db: Session, full_name: str, phone_number: str, type: str, agent
44
  db.refresh(new_user)
45
  return new_user
46
  else:
47
- logger.info(f"Buyer Agent Found: Creating buyer agent with phone number: {phone_number}")
48
- new_user = models.User(full_name=full_name,
49
- phone_number=phone_number,
50
- type="buyer",
51
- agent_id=agent_id,
52
- broker_name=broker_name)
53
- db.add(new_user)
54
- db.commit()
55
- db.refresh(new_user)
56
- return new_user
 
 
 
 
 
57
  except Exception as e:
58
  db.rollback()
59
- print(f"Error creating user: {e}")
60
- return None
61
 
62
- def get_property_by_session_id(db: Session, session_id: str):
63
- return db.query(models.Property).filter(models.Property.listing_agent_session_id == session_id).first()
64
 
65
 
66
- def create_property(db: Session,
67
  buyer_agent_phone_number: str,
68
  address: str, mls_number: str,
69
  buyer_selected_date: str,
@@ -74,18 +80,18 @@ def create_property(db: Session,
74
  listing_agent_session_id: str = None,
75
  status: str = None):
76
  try:
77
- property = db.query(models.Property).filter(models.Property.mls_number == mls_number,
78
- models.Property.buyer_agent_phone_number == buyer_agent_phone_number).first()
79
- if property:
80
- logger.info(f"Property already exist: Updating property with mls_number: {mls_number}")
81
- property.buyer_selected_date = buyer_selected_date
82
- property.buyer_selected_time = buyer_selected_time
83
  db.commit()
84
- db.refresh(property)
85
- return property
86
  else:
87
- logger.info(f"Creating new property with mls_number: {mls_number}")
88
- new_property = models.Property(buyer_agent_phone_number=buyer_agent_phone_number,
89
  address=address,
90
  mls_number=mls_number,
91
  buyer_selected_date=buyer_selected_date,
@@ -95,11 +101,11 @@ def create_property(db: Session,
95
  listing_agent_phone_number=listing_agent_phone_number,
96
  listing_agent_session_id=listing_agent_session_id,
97
  status=status)
98
- db.add(new_property)
99
  db.commit()
100
- db.refresh(new_property)
101
- return new_property
102
  except Exception as e:
103
  db.rollback()
104
- print(f"Error creating property: {e}")
105
  return None
 
5
 
6
  logger = setup_logger("crud")
7
 
8
+ def get_booking_by_mls_and_buyer_phone(db: Session, mls_number: str, buyer_agent_phone_number: str):
9
+ return db.query(models.booking).filter(
10
+ models.booking.mls_number == mls_number,
11
+ models.booking.buyer_agent_phone_number == buyer_agent_phone_number
12
  ).first()
13
 
14
  def get_user_by_phone_number(db: Session, phone_number: str):
 
22
  user = db.query(models.User).filter(models.User.phone_number == phone_number).first()
23
  if user:
24
  if user.active_session_id:
25
+ user.queued_session_ids = user.queued_session_ids + [new_session_id]
26
+ logger.info(f"The user already exists with the provided phone number and has an active session. Therefore, the task is being added to the queue: {phone_number}")
27
+ return None
28
  else:
29
+ logger.info(f"The user already exists with the provided phone number : {phone_number}")
30
  user.active_session_id = new_session_id
 
31
  db.commit()
32
  db.refresh(user)
33
  return user
 
45
  db.refresh(new_user)
46
  return new_user
47
  else:
48
+ user = db.query(models.User).filter(models.User.phone_number == phone_number).first()
49
+ if user:
50
+ logger.info(f"Buyer Agent Found: User already exist with phone number: {phone_number}")
51
+ return {"status": "exists", "message": "User already exists"}
52
+ else:
53
+ logger.info(f"Buyer Agent Found: Creating buyer agent with phone number: {phone_number}")
54
+ new_user = models.User(full_name=full_name,
55
+ phone_number=phone_number,
56
+ type="buyer",
57
+ agent_id=agent_id,
58
+ broker_name=broker_name)
59
+ db.add(new_user)
60
+ db.commit()
61
+ db.refresh(new_user)
62
+ return new_user
63
  except Exception as e:
64
  db.rollback()
65
+ logger.error(f"Error creating user: {e}")
66
+ return {"status": "error", "message": f"Error: {str(e)}"}
67
 
68
+ def get_booking_by_session_id(db: Session, session_id: str):
69
+ return db.query(models.booking).filter(models.booking.listing_agent_session_id == session_id).first()
70
 
71
 
72
+ def create_booking(db: Session,
73
  buyer_agent_phone_number: str,
74
  address: str, mls_number: str,
75
  buyer_selected_date: str,
 
80
  listing_agent_session_id: str = None,
81
  status: str = None):
82
  try:
83
+ booking = db.query(models.booking).filter(models.booking.mls_number == mls_number,
84
+ models.booking.buyer_agent_phone_number == buyer_agent_phone_number).first()
85
+ if booking:
86
+ logger.info(f"booking already exist: Updating booking with mls_number: {mls_number}")
87
+ booking.buyer_selected_date = buyer_selected_date
88
+ booking.buyer_selected_time = buyer_selected_time
89
  db.commit()
90
+ db.refresh(booking)
91
+ return booking
92
  else:
93
+ logger.info(f"Creating new booking with mls_number: {mls_number}")
94
+ new_booking = models.booking(buyer_agent_phone_number=buyer_agent_phone_number,
95
  address=address,
96
  mls_number=mls_number,
97
  buyer_selected_date=buyer_selected_date,
 
101
  listing_agent_phone_number=listing_agent_phone_number,
102
  listing_agent_session_id=listing_agent_session_id,
103
  status=status)
104
+ db.add(new_booking)
105
  db.commit()
106
+ db.refresh(new_booking)
107
+ return new_booking
108
  except Exception as e:
109
  db.rollback()
110
+ print(f"Error creating booking: {e}")
111
  return None
app/models.py CHANGED
@@ -12,13 +12,14 @@ class User(Base):
12
  type = Column(String, default="buyer")
13
  broker_name = Column(String, default="")
14
  active_session_id = Column(String, default="")
15
- all_session_ids = Column(ARRAY(String), default=[])
 
16
  created_at = Column(DateTime(timezone=True), server_default=func.now())
17
 
18
- properties = relationship("Property", back_populates="buyer_agent")
19
 
20
- class Property(Base):
21
- __tablename__ = "properties"
22
 
23
  id = Column(Integer, primary_key=True, index=True)
24
  buyer_agent_phone_number = Column(String, ForeignKey("users.phone_number"), nullable=False)
@@ -33,4 +34,4 @@ class Property(Base):
33
  status = Column(String, default="pending")
34
  created_at = Column(DateTime(timezone=True), server_default=func.now())
35
 
36
- buyer_agent = relationship("User", back_populates="properties")
 
12
  type = Column(String, default="buyer")
13
  broker_name = Column(String, default="")
14
  active_session_id = Column(String, default="")
15
+ queued_session_ids = Column(ARRAY(String), default=[])
16
+ completed_session_ids = Column(ARRAY(String), default=[])
17
  created_at = Column(DateTime(timezone=True), server_default=func.now())
18
 
19
+ bookings = relationship("booking", back_populates="buyer_agent")
20
 
21
+ class booking(Base):
22
+ __tablename__ = "bookings"
23
 
24
  id = Column(Integer, primary_key=True, index=True)
25
  buyer_agent_phone_number = Column(String, ForeignKey("users.phone_number"), nullable=False)
 
34
  status = Column(String, default="pending")
35
  created_at = Column(DateTime(timezone=True), server_default=func.now())
36
 
37
+ buyer_agent = relationship("User", back_populates="bookings")
app/router.py CHANGED
@@ -1,12 +1,13 @@
1
-
2
  from app import models, crud
3
- from app.database import SessionLocal, engine
4
- from utils.log_utils import setup_logger
5
- from fastapi import Request, Depends, APIRouter, HTTPException
6
  import os, json, random, requests
7
  from sqlalchemy.orm import Session
8
  from fastapi.responses import JSONResponse
 
 
 
9
  from twilio.twiml.messaging_response import MessagingResponse
 
 
10
  from fastapi.responses import Response
11
  from pydantic import BaseModel, Field
12
  from twilio.rest import Client
@@ -32,6 +33,19 @@ def get_db():
32
  finally:
33
  db.close()
34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  class MessageRequestSignUP(BaseModel):
36
  phone_number: str = Field(default="+917389058485")
37
  agent_id: str = Field(default="")
@@ -72,9 +86,9 @@ def create_payload_for_whatsapp_message(from_number, to_number, body):
72
  return payload
73
 
74
 
75
- class CreatePropertyRequest(BaseModel):
76
  buyer_agent_phone_number: str = Field(default="+917389058485")
77
- address: str = Field(default="property_address_test")
78
  mls_number: str = Field(default="mls_number_test")
79
  buyer_selected_date: str = Field(default="date_test")
80
  buyer_selected_time: str = Field(default="time_test")
@@ -82,9 +96,9 @@ class CreatePropertyRequest(BaseModel):
82
  listing_agent_session_id: str = Field(default="")
83
  status: str = Field(default="pending")
84
 
85
- @router.post('/realtor/create_property')
86
- async def create_property(request: CreatePropertyRequest, db: Session = Depends(get_db)):
87
- logger.warning(f"Create property request: {request}")
88
 
89
  buyer_agent_phone_number = request.buyer_agent_phone_number
90
  address = request.address
@@ -96,19 +110,53 @@ async def create_property(request: CreatePropertyRequest, db: Session = Depends(
96
  status = request.status
97
 
98
  try:
99
- property = crud.create_property(db, buyer_agent_phone_number=buyer_agent_phone_number,
100
  address=address, mls_number=mls_number, buyer_selected_date=buyer_selected_date,
101
  buyer_selected_time=buyer_selected_time, listing_agent_phone_number=listing_agent_phone_number,
102
  listing_agent_session_id=listing_agent_session_id, status=status)
103
  except Exception as e:
104
  db.rollback()
105
- logger.error(f"Error in creating property: {e}")
106
- raise HTTPException(status_code=400, detail="Property creation failed")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
 
108
- return JSONResponse(content="Property is created successfully.")
109
 
110
  class ListingRealtorSignUP(BaseModel):
111
- property_address: str = Field(default="property_address_test")
112
  mls_number: str = Field(default="mls_number_test")
113
  date: str = Field(default="date_test")
114
  time: str = Field(default="time_test")
@@ -118,39 +166,39 @@ class ListingRealtorSignUP(BaseModel):
118
  async def listing_realtor_sign_up(request: ListingRealtorSignUP, db: Session = Depends(get_db)):
119
  logger.warning(f"Listing realtor singup request: {request}")
120
 
121
- property_address = request.property_address
122
  mls_number = request.mls_number
123
  buyer_selected_date = request.date
124
  buyer_selected_time = request.time
125
  buyer_agent_phone_number = request.buyer_agent_phone_number
126
 
127
- logger.warning(f"Listing realtore - property_address: {property_address}, mls_number: {mls_number}, date: {buyer_selected_date}, time: {buyer_selected_time}, buyer_agent_phone_number: {buyer_agent_phone_number}")
128
- #TODO: Add logic to get property details from mls_number
129
- listing_agent_full_name = "Bob"
130
- listing_agent_phone_number = "+917347256305"
 
 
 
131
  type = "listing"
132
- property_address = "123 Main Street"
133
  try:
134
  buyer_user = crud.get_user_by_phone_number(db, phone_number=buyer_agent_phone_number)
135
  if not buyer_user:
136
  raise HTTPException(status_code=400, detail="Buyer agent not found")
137
  listing_user = crud.create_user(db, full_name=listing_agent_full_name, phone_number=listing_agent_phone_number, type=type)
138
- except Exception as e:
139
- db.rollback()
140
- logger.error(f"Error in creating user: {e}")
141
- raise HTTPException(status_code=400, detail="User creation failed")
142
-
143
- try:
144
- property = crud.create_property(db, buyer_agent_phone_number=buyer_agent_phone_number,
145
- address=property_address, mls_number=mls_number, buyer_selected_date=buyer_selected_date,
146
  buyer_selected_time=buyer_selected_time, listing_agent_phone_number=listing_agent_phone_number,
147
  listing_agent_session_id=listing_user.active_session_id)
148
  except Exception as e:
149
  db.rollback()
150
- logger.error(f"Error in creating property: {e}")
151
- raise HTTPException(status_code=400, detail="Property creation failed")
152
 
153
- listing_agent_body = f"Hello {listing_agent_full_name}, this is Alice assistant of {buyer_user.full_name}. We would like to schedule a showing for {property_address} (MLS # {mls_number}) at {buyer_selected_time} on {buyer_selected_date}. Can you make that work?"
154
 
155
  try:
156
  logger.info(f"Sending message to listing agent from: {ai_agnet_number}, body: {listing_agent_body}, to: {listing_agent_phone_number}")
@@ -164,7 +212,8 @@ async def listing_realtor_sign_up(request: ListingRealtorSignUP, db: Session = D
164
  logger.error(f"Error in sending message to listing agent: {e}")
165
  raise HTTPException(status_code=400, detail=f"Error in sending message to listing agent: {e}")
166
 
167
- return JSONResponse(content="I will inform you as soon as the listing agent confirms the property showing. The notification has been sent to them successfully.")
 
168
 
169
 
170
  class ListingRealtorConfirmation(BaseModel):
@@ -183,37 +232,37 @@ async def listing_realtor_sign_up(request: ListingRealtorConfirmation, db: Sessi
183
 
184
  logger.warning(f"Listing realtore - listing_selected_date: {listing_selected_date}, listing_selected_time: {listing_selected_time}, session_id: {session_id}, confirmation: {confirmation}.")
185
  try:
186
- property = crud.get_property_by_session_id(db, session_id=session_id)
187
- listing_user = crud.get_user_by_phone_number(db, phone_number=property.listing_agent_phone_number)
188
  except Exception as e:
189
  logger.error(f"Error in creating user: {e}")
190
- raise HTTPException(status_code=400, detail=f"property not found with this session id, Error: {str(e)}")
191
- if not property:
192
- raise HTTPException(status_code=400, detail="property not found with this session id")
193
- property.listing_selected_date = listing_selected_date
194
- property.listing_selected_time = listing_selected_time
195
  if confirmation == "confirmed":
196
- logger.warning(f"Property Schudule is confirmed by listing agent.")
197
- property.status = "confirmed"
198
- listing_agent_body = f"Your showing at {property.address} (MLS # {property.mls_number}) is confirmed on {listing_selected_date} at {listing_selected_time}. I'll send you a reminder the day before to ensure you're prepared."
199
- buyer_agent_body = f"Your showing at {property.address} (MLS # {property.mls_number}) is confirmed by {listing_user.full_name} on {listing_selected_date} at {listing_selected_time}. I'll send you a reminder the day before to ensure you're prepared."
200
  elif confirmation == "cancelled":
201
- logger.warning(f"Property Schudule is cancelled by listing agent.")
202
- property.status = "cancelled"
203
  listing_agent_body = f"Thank you for letting us know. We will inform the buyer that the showing has been cancelled."
204
  buyer_agent_body = f"Unfortunately, the listing agent has cancelled the showing. We apologize for any inconvenience caused."
205
  elif confirmation == "reschedule":
206
- logger.warning(f"Property Schudule is rescheduled by listing agent. because of listing_selected_date: {listing_selected_date}, listing_selected_time: {listing_selected_time} and buyer_selected_date: {property.buyer_selected_date}, buyer_selected_time: {property.buyer_selected_time}")
207
- property.status = "rescheduled"
208
  listing_agent_body = f"Thank you for letting us know. I will inform the buyer agent that you have rescheduled the showing on {listing_selected_date} at {listing_selected_time}."
209
- buyer_agent_body = f"The listing agent for the property at {property.address} (MLS # {property.mls_number}) has rescheduled the showing on {listing_selected_date} at {listing_selected_time}. Please confirm if this new time works for you."
210
  else:
211
  raise HTTPException(status_code=400, detail="Invalid confirmation status")
212
 
213
- logger.warning(f"Property Schudule is {confirmation} by listing agent. listing_agent_body: {listing_agent_body}, buyer_agent_body: {buyer_agent_body}")
214
  try:
215
- logger.info(f"Sending message to listing agent from: {ai_agnet_number}, body: {listing_agent_body}, to: {property.buyer_agent_phone_number}")
216
- payload = create_payload_for_whatsapp_message(from_number=property.buyer_agent_phone_number, to_number=ai_agnet_number, body=buyer_agent_body)
217
  headers = {"Content-Type": "application/json"}
218
  response = requests.post(n8n_webhook_url, headers=headers, data=json.dumps(payload))
219
  logger.info(f"Response for whatsapp webhook: {response.text}")
 
 
1
  from app import models, crud
 
 
 
2
  import os, json, random, requests
3
  from sqlalchemy.orm import Session
4
  from fastapi.responses import JSONResponse
5
+ from app.database import SessionLocal, engine
6
+ from utils.log_utils import setup_logger
7
+ from fastapi import Request, Depends, APIRouter, HTTPException
8
  from twilio.twiml.messaging_response import MessagingResponse
9
+ from app.services.properties import get_property_by_address_or_mls_number
10
+ from app.services.agent import verify_agent_by_agent_id_and_broker_name
11
  from fastapi.responses import Response
12
  from pydantic import BaseModel, Field
13
  from twilio.rest import Client
 
33
  finally:
34
  db.close()
35
 
36
+
37
+ @router.post('/realtor/get_properties')
38
+ async def get_properties(address: str=None, mls_number: str=None, db: Session = Depends(get_db)):
39
+ logger.warning(f"get_properties request: address: {address}, mls_number: {mls_number}")
40
+ response = get_property_by_address_or_mls_number(mls_number=mls_number, address=address)
41
+ return JSONResponse(content=response)
42
+
43
+ @router.post('/realtor/verify_agent')
44
+ async def verify_agent(agent_id: str, broker_name: str, db: Session = Depends(get_db)):
45
+ logger.warning(f"verify_agent request: agent_id: {agent_id}, broker_name: {broker_name}")
46
+ return verify_agent_by_agent_id_and_broker_name(agent_id=agent_id, broker_name=broker_name)
47
+
48
+
49
  class MessageRequestSignUP(BaseModel):
50
  phone_number: str = Field(default="+917389058485")
51
  agent_id: str = Field(default="")
 
86
  return payload
87
 
88
 
89
+ class CreatebookingRequest(BaseModel):
90
  buyer_agent_phone_number: str = Field(default="+917389058485")
91
+ address: str = Field(default="booking_address_test")
92
  mls_number: str = Field(default="mls_number_test")
93
  buyer_selected_date: str = Field(default="date_test")
94
  buyer_selected_time: str = Field(default="time_test")
 
96
  listing_agent_session_id: str = Field(default="")
97
  status: str = Field(default="pending")
98
 
99
+ @router.post('/realtor/create_booking')
100
+ async def create_booking(request: CreatebookingRequest, db: Session = Depends(get_db)):
101
+ logger.warning(f"Create booking request: {request}")
102
 
103
  buyer_agent_phone_number = request.buyer_agent_phone_number
104
  address = request.address
 
110
  status = request.status
111
 
112
  try:
113
+ booking = crud.create_booking(db, buyer_agent_phone_number=buyer_agent_phone_number,
114
  address=address, mls_number=mls_number, buyer_selected_date=buyer_selected_date,
115
  buyer_selected_time=buyer_selected_time, listing_agent_phone_number=listing_agent_phone_number,
116
  listing_agent_session_id=listing_agent_session_id, status=status)
117
  except Exception as e:
118
  db.rollback()
119
+ logger.error(f"Error in creating booking: {e}")
120
+ raise HTTPException(status_code=400, detail="booking creation failed")
121
+
122
+ return JSONResponse(content="booking is created successfully.")
123
+
124
+
125
+ class BuyerRealtorSignUP(BaseModel):
126
+ full_name: str = Field(default="full_name_test")
127
+ agent_id: str = Field(default="agent_id_test")
128
+ broker_name: str = Field(default="broker_name_test")
129
+ phone_number: str = Field(default="")
130
+ type: str = Field(default="buyer")
131
+
132
+ @router.post('/buyer_realtor/signup')
133
+ async def buyer_realtor_sign_up(request: BuyerRealtorSignUP, db: Session = Depends(get_db)):
134
+ logger.warning(f"Buyer realtor singup request: {request}")
135
+ full_name = request.full_name
136
+ agent_id = request.agent_id
137
+ broker_name = request.broker_name
138
+ phone_number = request.phone_number
139
+ type = request.type
140
+ #TODO: Add logic to verify agent_id and broker_name
141
+ if not verify_agent_by_agent_id_and_broker_name(agent_id=agent_id, broker_name=broker_name):
142
+ raise HTTPException(status_code=400, detail="Invalid agent_id or broker_name")
143
+ user = crud.create_user(db, full_name=full_name, phone_number=phone_number, type=type, agent_id=agent_id, broker_name=broker_name)
144
+ logger.warning(f"User: {user}")
145
+ if isinstance(user, dict) and "status" in user:
146
+ logger.warning(f"User status: {user['status']}")
147
+ if user["status"] == "exists":
148
+ logger.info(f"User already exist with this phone number.")
149
+ raise HTTPException(status_code=400, detail="User already exist with this phone number.")
150
+ if user["status"] == "failed":
151
+ logger.error(f"Error in creating user.")
152
+ raise HTTPException(status_code=400, detail=str(user["message"]))
153
+ if not user:
154
+ raise HTTPException(status_code=400, detail="User creation failed")
155
+ return JSONResponse(content="user is signed up sucessfully.")
156
 
 
157
 
158
  class ListingRealtorSignUP(BaseModel):
159
+ booking_address: str = Field(default="booking_address_test")
160
  mls_number: str = Field(default="mls_number_test")
161
  date: str = Field(default="date_test")
162
  time: str = Field(default="time_test")
 
166
  async def listing_realtor_sign_up(request: ListingRealtorSignUP, db: Session = Depends(get_db)):
167
  logger.warning(f"Listing realtor singup request: {request}")
168
 
169
+ booking_address = request.booking_address
170
  mls_number = request.mls_number
171
  buyer_selected_date = request.date
172
  buyer_selected_time = request.time
173
  buyer_agent_phone_number = request.buyer_agent_phone_number
174
 
175
+ logger.warning(f"Listing realtore - booking_address: {booking_address}, mls_number: {mls_number}, date: {buyer_selected_date}, time: {buyer_selected_time}, buyer_agent_phone_number: {buyer_agent_phone_number}")
176
+ #TODO: Add logic to get booking details from mls_number
177
+ response = get_property_by_address_or_mls_number(mls_number=mls_number, address=booking_address)
178
+ if response["address"] != booking_address or response["mls_number"] != mls_number:
179
+ raise HTTPException(status_code=400, detail="Invalid mls_number or address")
180
+ listing_agent_full_name = response["agent_name"]
181
+ listing_agent_phone_number = response["agent_phone"]
182
  type = "listing"
183
+ booking_address = response["address"]
184
  try:
185
  buyer_user = crud.get_user_by_phone_number(db, phone_number=buyer_agent_phone_number)
186
  if not buyer_user:
187
  raise HTTPException(status_code=400, detail="Buyer agent not found")
188
  listing_user = crud.create_user(db, full_name=listing_agent_full_name, phone_number=listing_agent_phone_number, type=type)
189
+ if not listing_user:
190
+ logger.info(f"Listing agent have already active session so putting the task in queue.")
191
+ return JSONResponse(content="I will let you know once the listing agent confirms the showing appointment.")
192
+ booking = crud.create_booking(db, buyer_agent_phone_number=buyer_agent_phone_number,
193
+ address=booking_address, mls_number=mls_number, buyer_selected_date=buyer_selected_date,
 
 
 
194
  buyer_selected_time=buyer_selected_time, listing_agent_phone_number=listing_agent_phone_number,
195
  listing_agent_session_id=listing_user.active_session_id)
196
  except Exception as e:
197
  db.rollback()
198
+ logger.error(f"Error in creating booking: {e}")
199
+ raise HTTPException(status_code=400, detail="booking creation failed")
200
 
201
+ listing_agent_body = f"Hello {listing_agent_full_name}, this is Alice assistant of {buyer_user.full_name}. We would like to schedule a showing for {booking_address} (MLS # {mls_number}) at {buyer_selected_time} on {buyer_selected_date}. Can you make that work?"
202
 
203
  try:
204
  logger.info(f"Sending message to listing agent from: {ai_agnet_number}, body: {listing_agent_body}, to: {listing_agent_phone_number}")
 
212
  logger.error(f"Error in sending message to listing agent: {e}")
213
  raise HTTPException(status_code=400, detail=f"Error in sending message to listing agent: {e}")
214
 
215
+ return JSONResponse(content="I will let you know once the listing agent confirms the showing appointment.")
216
+
217
 
218
 
219
  class ListingRealtorConfirmation(BaseModel):
 
232
 
233
  logger.warning(f"Listing realtore - listing_selected_date: {listing_selected_date}, listing_selected_time: {listing_selected_time}, session_id: {session_id}, confirmation: {confirmation}.")
234
  try:
235
+ booking = crud.get_booking_by_session_id(db, session_id=session_id)
236
+ listing_user = crud.get_user_by_phone_number(db, phone_number=booking.listing_agent_phone_number)
237
  except Exception as e:
238
  logger.error(f"Error in creating user: {e}")
239
+ raise HTTPException(status_code=400, detail=f"booking not found with this session id, Error: {str(e)}")
240
+ if not booking:
241
+ raise HTTPException(status_code=400, detail="booking not found with this session id")
242
+ booking.listing_selected_date = listing_selected_date
243
+ booking.listing_selected_time = listing_selected_time
244
  if confirmation == "confirmed":
245
+ logger.warning(f"booking Schudule is confirmed by listing agent.")
246
+ booking.status = "confirmed"
247
+ listing_agent_body = f"Your showing at {booking.address} (MLS # {booking.mls_number}) is confirmed on {listing_selected_date} at {listing_selected_time}. I'll send you a reminder the day before to ensure you're prepared."
248
+ buyer_agent_body = f"Your showing at {booking.address} (MLS # {booking.mls_number}) is confirmed by {listing_user.full_name} on {listing_selected_date} at {listing_selected_time}. I'll send you a reminder the day before to ensure you're prepared."
249
  elif confirmation == "cancelled":
250
+ logger.warning(f"booking Schudule is cancelled by listing agent.")
251
+ booking.status = "cancelled"
252
  listing_agent_body = f"Thank you for letting us know. We will inform the buyer that the showing has been cancelled."
253
  buyer_agent_body = f"Unfortunately, the listing agent has cancelled the showing. We apologize for any inconvenience caused."
254
  elif confirmation == "reschedule":
255
+ logger.warning(f"booking Schudule is rescheduled by listing agent. because of listing_selected_date: {listing_selected_date}, listing_selected_time: {listing_selected_time} and buyer_selected_date: {booking.buyer_selected_date}, buyer_selected_time: {booking.buyer_selected_time}")
256
+ booking.status = "rescheduled"
257
  listing_agent_body = f"Thank you for letting us know. I will inform the buyer agent that you have rescheduled the showing on {listing_selected_date} at {listing_selected_time}."
258
+ buyer_agent_body = f"The listing agent for the booking at {booking.address} (MLS # {booking.mls_number}) has rescheduled the showing on {listing_selected_date} at {listing_selected_time}. Please confirm if this new time works for you."
259
  else:
260
  raise HTTPException(status_code=400, detail="Invalid confirmation status")
261
 
262
+ logger.warning(f"booking Schudule is {confirmation} by listing agent. listing_agent_body: {listing_agent_body}, buyer_agent_body: {buyer_agent_body}")
263
  try:
264
+ logger.info(f"Sending message to listing agent from: {ai_agnet_number}, body: {listing_agent_body}, to: {booking.buyer_agent_phone_number}")
265
+ payload = create_payload_for_whatsapp_message(from_number=booking.buyer_agent_phone_number, to_number=ai_agnet_number, body=buyer_agent_body)
266
  headers = {"Content-Type": "application/json"}
267
  response = requests.post(n8n_webhook_url, headers=headers, data=json.dumps(payload))
268
  logger.info(f"Response for whatsapp webhook: {response.text}")
app/services/agent.py ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ def verify_agent_by_agent_id_and_broker_name(agent_id, broker_name):
4
+ if agent_id == "agent_id_test" and broker_name == "broker_name_test":
5
+ return True
6
+ elif agent_id == "king_agent" and broker_name == "king_broker":
7
+ return True
8
+ return False
app/services/properties.py ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from utils.log_utils import setup_logger
2
+
3
+ logger = setup_logger("properties_service")
4
+
5
+ def get_property_by_address_or_mls_number(mls_number, address):
6
+ if mls_number == "123456":
7
+ response = {
8
+ "address": "123 Main St, San Francisco, CA 94105",
9
+ "mls_number": mls_number,
10
+ "price": "$1,000,000",
11
+ "bedrooms": "3",
12
+ "bathrooms": "2",
13
+ "sqft": "1,500",
14
+ "lot_size": "0.25",
15
+ "year_built": "2000",
16
+ "description": "This is a beautiful 3 bedroom, 2 bathroom home with 1,500 sqft of living space on a 0.25 acre lot. The home was built in 2000 and is listed for $1,000,000.",
17
+ "agent_name": "Alice",
18
+ "agent_phone": "+917347256305"
19
+ }
20
+ elif mls_number == "654321":
21
+ response = {
22
+ "address": "456 Elm St, San Francisco, CA 94105",
23
+ "mls_number": mls_number,
24
+ "price": "$1,500,000",
25
+ "bedrooms": "4",
26
+ "bathrooms": "3",
27
+ "sqft": "2,000",
28
+ "lot_size": "0.5",
29
+ "year_built": "2010",
30
+ "description": "This is a beautiful 4 bedroom, 3 bathroom home with 2,000 sqft of living space on a 0.5 acre lot. The home was built in 2010 and is listed for $1,500,000.",
31
+ "agent_name": "Alice2",
32
+ "agent_phone": "+917347256302"
33
+ }
34
+ elif address == "321 Oak St, San Francisco, CA 94105":
35
+ response = {
36
+ "address": address,
37
+ "mls_number": "789012",
38
+ "price": "$2,000,000",
39
+ "bedrooms": "5",
40
+ "bathrooms": "4",
41
+ "sqft": "2,500",
42
+ "lot_size": "0.75",
43
+ "year_built": "2020",
44
+ "description": "This is a beautiful 5 bedroom, 4 bathroom home with 2,500 sqft of living space on a 0.75 acre lot. The home was built in 2020 and is listed for $2,000,000.",
45
+ "agent_name": "Alice3",
46
+ "agent_phone": "+917347256303"
47
+ }
48
+ else:
49
+ logger.warning(f"Property not found for address: {address}, mls_number: {mls_number}")
50
+ response = {}
51
+ return response