mirror of
http://88.130.71.182:3000/BlitTech/deals24togo_be.git
synced 2026-06-12 23:33:21 +00:00
160 lines
5.2 KiB
Python
160 lines
5.2 KiB
Python
"""Message / contact service."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime, timezone
|
|
from typing import Optional
|
|
|
|
from app.core.config import get_settings
|
|
from app.core.exceptions import ForbiddenException, NotFoundException
|
|
from app.core.supabase import get_supabase_admin
|
|
from app.services.email_service import EmailService
|
|
|
|
|
|
class MessageService:
|
|
def __init__(self):
|
|
self.db = get_supabase_admin()
|
|
|
|
def send_message(self, data: dict) -> dict:
|
|
# Resolve agency_id and listing title
|
|
listing_row = (
|
|
self.db.table("listings")
|
|
.select("agency_id, title")
|
|
.eq("id", data["listing_id"])
|
|
.execute()
|
|
)
|
|
if not listing_row.data:
|
|
raise NotFoundException("Listing not found")
|
|
|
|
agency_id = listing_row.data[0]["agency_id"]
|
|
listing_title = listing_row.data[0].get("title", "")
|
|
|
|
now = datetime.now(timezone.utc).isoformat()
|
|
msg_data = {
|
|
**data,
|
|
"agency_id": agency_id,
|
|
"read": False,
|
|
"created_at": now,
|
|
}
|
|
result = self.db.table("messages").insert(msg_data).execute()
|
|
if not result.data:
|
|
raise Exception("Failed to send message")
|
|
|
|
# Notify agency via email (non-blocking)
|
|
try:
|
|
agency_row = (
|
|
self.db.table("agencies")
|
|
.select("name, email")
|
|
.eq("id", agency_id)
|
|
.execute()
|
|
)
|
|
if agency_row.data:
|
|
agency = agency_row.data[0]
|
|
settings = get_settings()
|
|
dashboard_url = f"{settings.FRONTEND_URL}/agency/dashboard"
|
|
EmailService().send_new_message_notification(
|
|
to_email=agency["email"],
|
|
agency_name=agency["name"],
|
|
sender_name=data.get("name", "Someone"),
|
|
listing_title=listing_title,
|
|
dashboard_url=dashboard_url,
|
|
)
|
|
except Exception:
|
|
pass
|
|
|
|
return result.data[0]
|
|
|
|
def list_messages(
|
|
self,
|
|
agency_id: str,
|
|
user_id: str,
|
|
user_role: str,
|
|
read_filter: Optional[bool] = None,
|
|
page: int = 1,
|
|
page_size: int = 20,
|
|
) -> dict:
|
|
# Verify ownership
|
|
if user_role != "admin":
|
|
agency = (
|
|
self.db.table("agencies")
|
|
.select("user_id")
|
|
.eq("id", agency_id)
|
|
.execute()
|
|
)
|
|
if not agency.data or agency.data[0]["user_id"] != user_id:
|
|
raise ForbiddenException("Not authorized")
|
|
|
|
query = (
|
|
self.db.table("messages")
|
|
.select("*, listings(title)", count="exact")
|
|
.eq("agency_id", agency_id)
|
|
)
|
|
if read_filter is not None:
|
|
query = query.eq("read", read_filter)
|
|
|
|
offset = (page - 1) * page_size
|
|
result = (
|
|
query.order("created_at", desc=True)
|
|
.range(offset, offset + page_size - 1)
|
|
.execute()
|
|
)
|
|
|
|
messages = []
|
|
for m in result.data:
|
|
listings_data = m.pop("listings", None)
|
|
if listings_data and isinstance(listings_data, dict):
|
|
m["listing_title"] = listings_data.get("title")
|
|
messages.append(m)
|
|
|
|
return {
|
|
"messages": messages,
|
|
"total": result.count or 0,
|
|
"page": page,
|
|
"page_size": page_size,
|
|
}
|
|
|
|
def mark_read(self, message_id: str, user_id: str, user_role: str, read: bool = True) -> dict:
|
|
msg = self.db.table("messages").select("*, agencies(user_id)").eq("id", message_id).execute()
|
|
if not msg.data:
|
|
raise NotFoundException("Message not found")
|
|
|
|
message = msg.data[0]
|
|
agencies_data = message.get("agencies")
|
|
if user_role != "admin":
|
|
if not agencies_data or agencies_data.get("user_id") != user_id:
|
|
raise ForbiddenException("Not authorized")
|
|
|
|
result = (
|
|
self.db.table("messages")
|
|
.update({"read": read})
|
|
.eq("id", message_id)
|
|
.execute()
|
|
)
|
|
if not result.data:
|
|
raise NotFoundException("Message not found")
|
|
return result.data[0]
|
|
|
|
def get_unread_count(self, agency_id: str) -> int:
|
|
result = (
|
|
self.db.table("messages")
|
|
.select("id", count="exact")
|
|
.eq("agency_id", agency_id)
|
|
.eq("read", False)
|
|
.execute()
|
|
)
|
|
return result.count or 0
|
|
|
|
def delete_message(self, message_id: str, user_id: str, user_role: str) -> dict:
|
|
msg = self.db.table("messages").select("*, agencies(user_id)").eq("id", message_id).execute()
|
|
if not msg.data:
|
|
raise NotFoundException("Message not found")
|
|
|
|
message = msg.data[0]
|
|
agencies_data = message.get("agencies")
|
|
if user_role != "admin":
|
|
if not agencies_data or agencies_data.get("user_id") != user_id:
|
|
raise ForbiddenException("Not authorized")
|
|
|
|
self.db.table("messages").delete().eq("id", message_id).execute()
|
|
return {"message": "Message deleted"}
|