diff --git a/config/settings.py b/config/settings.py index bffc8b7..bfccd07 100644 --- a/config/settings.py +++ b/config/settings.py @@ -47,6 +47,7 @@ INSTALLED_APPS = [ 'django.contrib.staticfiles', 'django.contrib.humanize', 'channels', + 'widget_tweaks', 'expenses', 'payroll', 'procurement', diff --git a/expenses/consumers.py b/expenses/consumers.py index 76805bf..e182c86 100644 --- a/expenses/consumers.py +++ b/expenses/consumers.py @@ -19,11 +19,7 @@ class ExpenseConsumer(AsyncWebsocketConsumer): # Recibir actualización desde el Channel Layer async def expense_update(self, event): - expense_data = event['expense'] - action = event['action'] + html_payload = event['html'] - # Enviar actualización por WebSocket al cliente - await self.send(text_data=json.dumps({ - 'action': action, - 'expense': expense_data - })) + # Enviar actualización por WebSocket al cliente (HTMX espera HTML puro, no JSON) + await self.send(text_data=html_payload) diff --git a/expenses/signals.py b/expenses/signals.py index 26913ae..042143c 100644 --- a/expenses/signals.py +++ b/expenses/signals.py @@ -2,40 +2,42 @@ from django.db.models.signals import post_save, post_delete from django.dispatch import receiver from channels.layers import get_channel_layer from asgiref.sync import async_to_sync +from django.template.loader import render_to_string from .models import Expense @receiver(post_save, sender=Expense) def expense_saved(sender, instance, created, **kwargs): channel_layer = get_channel_layer() - action = 'created' if created else 'updated' - expense_data = { - 'id': instance.id, - 'amount': str(instance.amount_clp), - 'category': instance.category.name if instance.category else None, - 'project': instance.project.name if instance.project else None, - 'user': instance.user.username if instance.user else None, - 'date': instance.date.strftime('%Y-%m-%d'), - 'description': instance.description, - } + # Renderizamos la fila parcial + html = render_to_string('expenses/partials/expense_row.html', {'expense': instance}) + + # Envolvemos el HTML con las directivas OOB (Out-of-Band) de HTMX + if created: + # Si es nuevo, lo insertamos al principio del tbody con id "expenses-tbody" + payload = f'
{html}' + else: + # Si ya existe, HTMX reemplazará automáticamente el tr con el mismo ID si usamos hx-swap-oob="true" + payload = html.replace('