Skip to content

Commit f85ebab

Browse files
committed
refactor: Mejora de funciones de chat y optimizado la carga de mensajes, para que ahora sea bajo demanda y no cargen todos los mensajes al entrar al panel de administración.
1 parent c599a5f commit f85ebab

4 files changed

Lines changed: 106 additions & 14 deletions

File tree

codigo/chat/_utils.py

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
# Autor: Alejandro Gasca Mediel
33
# ==========================================
44
"""
5-
Funciones de utilidad interna para la aplicación de chat."""
5+
Utilidades para la aplicación de chat.
6+
"""
67
from django.contrib.auth.models import User
78
from django.utils import timezone
89
from .models import Message, Chat
@@ -24,12 +25,30 @@ def format_message_for_api(message: Message) -> dict:
2425
'date': message.created_at.strftime('%Y-%m-%d')
2526
}
2627

27-
def get_messages_for_chat(chat: Chat) -> list:
28+
def get_messages_for_chat(chat):
2829
"""
29-
Obtiene todos los mensajes de un chat formateados para la API.
30+
Obtiene los mensajes de un chat formateados para la API.
31+
Solo se llama cuando se visualiza un chat específico.
3032
"""
31-
messages = chat.messages.all().order_by('created_at')
32-
return [format_message_for_api(msg) for msg in messages]
33+
messages = Message.objects.filter(chat=chat).order_by('created_at')
34+
messages_data = []
35+
36+
for message in messages:
37+
# Format date as day/month/year
38+
date_str = message.created_at.strftime('%d/%m/%Y')
39+
# Format time as hour:minute
40+
time_str = message.created_at.strftime('%H:%M')
41+
42+
messages_data.append({
43+
'id': message.id,
44+
'sender': message.sender.username,
45+
'content': message.content,
46+
'timestamp': time_str,
47+
'date': date_str,
48+
'is_read': message.is_read,
49+
})
50+
51+
return messages_data
3352

3453
def can_send_message(chat: Chat) -> bool:
3554
"""

codigo/chat/public.py

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
2-
3-
1+
# ==========================================
2+
# Autor: Alejandro Gasca Mediel
3+
# ==========================================
44
"""
55
API pública para la aplicación de chat.
66
"""
77
from django.contrib.auth.models import User
88
from django.utils import timezone
99
from django.db.models import Q, Count
10+
from django.db.models import Count, Max, Subquery, OuterRef, F
1011

1112
from .models import Chat, Message
1213
from accounts.public import update_last_activity
@@ -159,6 +160,67 @@ def filter_chats_by_criteria(search=None, chat_type=None, from_date=None, to_dat
159160
key=lambda x: x['last_message'].created_at if x['last_message'] else chat.created_at,
160161
reverse=True)
161162

163+
def filter_chats_by_criteria_optimized(search=None, chat_type=None, from_date=None, to_date=None):
164+
"""
165+
Versión optimizada de filter_chats_by_criteria que no carga todos los mensajes
166+
sino solo datos esenciales para mostrar en la lista.
167+
"""
168+
169+
chats_query = Chat.objects.all()
170+
171+
172+
if search:
173+
matching_users = User.objects.filter(username__icontains=search)
174+
chats_query = chats_query.filter(participants__in=matching_users).distinct()
175+
176+
177+
if chat_type == 'ride':
178+
chats_query = chats_query.filter(ride__isnull=False)
179+
elif chat_type == 'direct':
180+
chats_query = chats_query.filter(ride__isnull=True)
181+
182+
183+
if from_date:
184+
chats_query = chats_query.filter(created_at__gte=from_date)
185+
if to_date:
186+
chats_query = chats_query.filter(created_at__lte=to_date)
187+
188+
189+
chats_query = chats_query.annotate(
190+
messages_count=Count('messages', distinct=True),
191+
has_ride=Count('ride', distinct=True)
192+
)
193+
194+
195+
last_message_subquery = Message.objects.filter(
196+
chat=OuterRef('pk')
197+
).order_by('-created_at').values('id', 'created_at')[:1]
198+
199+
chats_query = chats_query.annotate(
200+
last_message_id=Subquery(last_message_subquery.values('id')),
201+
last_message_date=Subquery(last_message_subquery.values('created_at'))
202+
)
203+
204+
205+
chats_query = chats_query.order_by('-last_message_date', '-created_at')
206+
207+
208+
result = []
209+
for chat in chats_query:
210+
211+
last_message = None
212+
if chat.last_message_id:
213+
last_message = Message.objects.get(id=chat.last_message_id)
214+
215+
result.append({
216+
'chat': chat,
217+
'messages_count': chat.messages_count,
218+
'last_message': last_message,
219+
'is_ride_chat': chat.has_ride > 0
220+
})
221+
222+
return result
223+
162224
def get_chat_stats():
163225
"""
164226
Obtiene estadísticas generales sobre los chats para el panel de administración.

codigo/dashboard/_utils.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# ==========================================
22
# Autor: Alejandro Gasca Mediel
33
# ==========================================
4+
5+
46
"""
57
Utilidades para la aplicación de dashboard
68
"""
@@ -11,16 +13,14 @@
1113
from django.db.models.functions import TruncDate, TruncMonth, ExtractHour
1214
from django.utils import timezone
1315

14-
16+
1517
from rides.public import get_rides_in_period, get_ride_stats_for_dashboard, get_recently_published_rides
1618
from chat.public import get_messages_in_period
1719
from reports.public import get_reports_in_period
1820
from accounts.public import get_users_in_period, get_active_users
1921
from payments.public import get_payments_in_period
20-
from chat.public import filter_chats_by_criteria, get_chat_stats
22+
from chat.public import filter_chats_by_criteria_optimized, get_chat_stats
2123
from django.core.paginator import Paginator
22-
import json
23-
from django.core.serializers.json import DjangoJSONEncoder
2424
from reports.public import (
2525
get_hourly_report_counts,
2626
get_daily_report_counts,
@@ -296,7 +296,7 @@ def get_messages_data(period=DEFAULT_PERIOD):
296296
'total': total_messages,
297297
'labels': labels,
298298
'data': data,
299-
'avg_per_day': round(total_messages / max(1, days_in_period)), # Redondear a entero, sin el segundo parámetro
299+
'avg_per_day': round(total_messages / max(1, days_in_period)),
300300
'period': period,
301301
'period_text': period_text
302302
}
@@ -1027,7 +1027,8 @@ def get_chat_management_context(request):
10271027
'to_date': request.GET.get('to_date', ''),
10281028
}
10291029

1030-
chats_data = filter_chats_by_criteria(
1030+
1031+
chats_data = filter_chats_by_criteria_optimized(
10311032
search=filters['search'],
10321033
chat_type=filters['chat_type'],
10331034
from_date=filters['from_date'],
@@ -1044,10 +1045,20 @@ def get_chat_management_context(request):
10441045

10451046
stats = get_chat_stats()
10461047

1048+
1049+
chart_data = {
1050+
'daily_messages': json.dumps(stats['daily_messages'], cls=DjangoJSONEncoder),
1051+
'chat_distribution': json.dumps([
1052+
{'type': 'Chats de viaje', 'count': stats['ride_chats']},
1053+
{'type': 'Chats directos', 'count': stats['direct_chats']}
1054+
], cls=DjangoJSONEncoder)
1055+
}
1056+
10471057
return {
10481058
'chats': chats,
10491059
'filters': filters,
10501060
'stats': stats,
1061+
'chart_data': chart_data,
10511062
'active_section': 'chats',
10521063
'now': timezone.now()
10531064
}

requirements.txt

1.67 KB
Binary file not shown.

0 commit comments

Comments
 (0)