import json from channels.generic.websocket import AsyncWebsocketConsumer from channels.db import database_sync_to_async from helpdesk.services.ticket_service import TicketService # ตรวจสอบ Ticket class ChatConsumer(AsyncWebsocketConsumer): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.ticket_id = None self.ticket_group_name = None @database_sync_to_async def check_ticket_and_auth(self, ticket_id, user): """ตรวจสอบสิทธิ์และสถานะของ Ticket ใน DB""" if not user.is_authenticated: return False # Business Logic Authorization: # ใช้ TicketService เพื่อตรวจสอบว่าผู้ใช้มีสิทธิ์เข้าถึง Ticket นี้หรือไม่ if not TicketService().is_user_authorized(ticket_id, user): return False # สำหรับตัวอย่างนี้ให้แค่ตรวจสอบว่า Ticket มีอยู่จริงหรือไม่ from helpdesk.models import Ticket return Ticket.objects.filter(pk=ticket_id).exists() async def connect(self): self.ticket_id = self.scope['url_route']['kwargs']['ticket_id'] self.ticket_group_name = f'ticket_{self.ticket_id}' user = self.scope['user'] # 1. ตรวจสอบสิทธิ์ก่อนเชื่อมต่อ is_allowed = await self.check_ticket_and_auth(self.ticket_id, user) if is_allowed: # Join room group await self.channel_layer.group_add( self.ticket_group_name, self.channel_name ) await self.accept() else: await self.close() async def disconnect(self, close_code): if self.ticket_group_name: # Leave room group await self.channel_layer.group_discard( self.ticket_group_name, self.channel_name ) # Receive message from WebSocket (ไคลเอนต์ส่งข้อความมา) async def receive(self, text_data=None, bytes_data=None): # Consumer ไม่ควรมี Business Logic # ข้อมูลขาเข้าควรถูกส่งไปให้ Service Layer ประมวลผล text_data_json = json.loads(text_data) content = text_data_json.get('content') # เรียก Service เพื่อสร้างและส่งข้อความ (ต้องทำแบบ sync) # เนื่องจาก Consumer เป็น async, เราจะส่งไปให้ Service แบบ sync/async await self.save_message_and_broadcast(self.ticket_id, self.scope['user'], content) # เมธอดที่ Service Layer เรียกผ่าน Channel Layer (group_send) async def chat_message(self, event): """ส่งข้อความที่ถูก broadcast กลับไปยัง WebSocket Client""" message = event['message'] # Send message to WebSocket await self.send(text_data=json.dumps({ 'type': 'new_message', 'message': message })) @database_sync_to_async def save_message_and_broadcast(self, ticket_id, user, content): """ เมธอด sync ที่เรียก Service Layer เพื่อทำ Business Logic และส่ง broadcast กลับมา (ผ่าน _send_realtime_update ใน Service) """ from chat.services.message_service import chat_svc # ต้องแน่ใจว่า import ถูกต้อง if not content: return # Service จะสร้างข้อความใน DB, อัปเดต Ticket, และส่ง broadcast chat_svc.create_and_send_message( ticket_id=ticket_id, sender=user, content=content, message_type='T' )