Files
deals24togo_be/app/services/message_service.py
belviskhoremk c4d836a0f9 Initial commit
2026-03-06 22:57:58 +00:00

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"}