# Исправление: WebSocket события для опросов ## 🐛 Проблемы ### 1. Новые опросы не встраивались в DOM - **Причина**: `create_poll` отправлял неправильную структуру WebSocket события - **Симптом**: После создания опроса он не появлялся, нужна была перезагрузка ### 2. Информация о проголосовавших не обновлялась - **Причина**: `user_consumer.py` не передавал полные данные `results` на фронтенд - **Симптом**: После голосования проценты/счётчики не обновлялись в реальном времени --- ## ✅ Исправления ### 1. Backend: `poll_views.py` - Создание опроса **БЫЛО (неправильная структура):** ```python ws_message = { 'type': 'chat_message', # ← неправильный тип 'payload': { 'message': { # ← лишняя вложенность 'id': message.id, 'content': message.content, 'poll': poll_data # ← poll не сериализован через serialize_message } } } ``` **СТАЛО (правильная структура):** ```python from communications.consumers import serialize_message # Перезагружаем сообщение со всеми связанными объектами message = Message.objects.select_related( 'author', 'reply_to', 'reply_to__author', 'forwarded_from_author', 'poll' ).prefetch_related( 'attachments', 'reactions', 'reactions__user', 'poll__options' ).get(pk=message.id) payload = serialize_message(message) # ← правильная сериализация! async_to_sync(channel_layer.group_send)( f'chat_{chat.id}', { 'type': 'chat.message', # ← правильный тип для consumer 'chat_id': chat.id, 'payload': payload # ← полный payload с poll } ) ``` ### 2. Backend: `poll_views.py` - Голосование (vote_poll) **БЫЛО (отсутствовал chat_id):** ```python ws_message = { 'type': 'poll_update', # chat_id отсутствовал! ← 'payload': { 'poll_id': poll.id, 'message_id': poll.message.id, 'results': results } } ``` **СТАЛО:** ```python ws_message = { 'type': 'poll_update', 'chat_id': chat.id, # ← добавлено! 'payload': { 'poll_id': poll.id, 'message_id': poll.message.id, 'results': results # ← полные результаты } } ``` ### 3. Backend: `poll_views.py` - Закрытие опроса (close_poll) **Та же проблема - добавлен `chat_id`:** ```python ws_message = { 'type': 'poll_update', 'chat_id': poll.message.chat.id, # ← добавлено! 'payload': { 'poll_id': poll.id, 'message_id': poll.message.id, 'results': poll.get_results() } } ``` ### 4. Backend: `user_consumer.py` - Обработка poll_update **БЫЛО (неполные данные):** ```python async def chat_poll_update(self, event): chat_id = event.get("chat_id") if chat_id == self.active_chat_id: await self.send_json({ "type": "poll_vote", # ← старое название "chat_id": chat_id, "poll_id": event.get("poll_id"), # ← берёт из корня, а не из payload "option_id": event.get("option_id"), # ← этого нет в event! "vote_count": event.get("vote_count"), # ← этого тоже нет! "total_voters": event.get("total_voters") # ← и этого нет! }) ``` **СТАЛО (полные данные из payload):** ```python async def chat_poll_update(self, event): chat_id = event.get("chat_id") payload = event.get("payload", {}) # ← извлекаем payload! if chat_id == self.active_chat_id: await self.send_json({ "type": "poll_update", # ← правильное название "chat_id": chat_id, "poll_id": payload.get("poll_id"), # ← из payload "message_id": payload.get("message_id"), # ← добавлено "results": payload.get("results") # ← полные результаты! }) ``` ### 5. Frontend: `userWebSocket.js` - Добавлен обработчик **БЫЛО (только poll_vote):** ```javascript case 'poll_vote': handlePollVote(data); break; ``` **СТАЛО (поддержка обоих типов):** ```javascript case 'poll_vote': case 'poll_update': // ← добавлено! handlePollUpdate(data); break; ``` **Новая функция handlePollUpdate:** ```javascript function handlePollUpdate(data) { console.log('[UserWebSocket] Poll update received:', data); window.dispatchEvent(new CustomEvent('chat:poll-update', { detail: { poll_id: data.poll_id, message_id: data.message_id, results: data.results // ← передаём полные результаты! } })); } ``` --- ## 🔄 Процесс обновления опросов ### Создание нового опроса: ``` User создаёт опрос ↓ POST /api/v1/communications/polls/create/ ↓ Backend: create_poll() ├─ Message.objects.create(content="📊 Вопрос") ├─ Poll.objects.create(message=message) ├─ PollOption.objects.create(poll=poll, text="Вариант 1") ├─ serialize_message(message) → полный payload с poll └─ WebSocket: type='chat.message', payload={id, content, poll: {...}} ↓ user_consumer.py: chat_message() └─ send_json(type='new_message', message=payload) ↓ userWebSocket.js: handleNewMessage() └─ dispatchEvent('new_message', payload) ↓ chatScroll добавляет сообщение в DOM ↓ MessageRenderer.buildMessageHtml() ├─ buildPollHtml(msg.poll) → генерирует HTML └─ вставляет