changes
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -59,8 +59,10 @@ class DataConsumer(AsyncJsonWebsocketConsumer):
|
|||||||
from .views import get_serializer
|
from .views import get_serializer
|
||||||
|
|
||||||
payload = event["payload"]
|
payload = event["payload"]
|
||||||
|
change_type = payload.get("change_type")
|
||||||
record_id = payload["record"].get("id")
|
record_id = payload["record"].get("id")
|
||||||
if not record_id:
|
|
||||||
|
if not record_id or not change_type:
|
||||||
return
|
return
|
||||||
|
|
||||||
model_name_lower = payload["name"]
|
model_name_lower = payload["name"]
|
||||||
@@ -71,7 +73,19 @@ class DataConsumer(AsyncJsonWebsocketConsumer):
|
|||||||
if not client_params:
|
if not client_params:
|
||||||
return # This client is not subscribed to this model.
|
return # This client is not subscribed to this model.
|
||||||
|
|
||||||
# 2. Check if the updated record ID could possibly match the client's filter
|
# 2. Handle DELETION event
|
||||||
|
if change_type == 'deleted':
|
||||||
|
await self.send_json({
|
||||||
|
"type": "realtime_update",
|
||||||
|
"payload": {
|
||||||
|
"name": model_name_lower,
|
||||||
|
"change_type": "deleted",
|
||||||
|
"record": {"id": record_id}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return
|
||||||
|
|
||||||
|
# 3. Handle CREATION and UPDATE events
|
||||||
Model, _ = get_serializer(model_name_lower)
|
Model, _ = get_serializer(model_name_lower)
|
||||||
if not Model:
|
if not Model:
|
||||||
return
|
return
|
||||||
@@ -80,36 +94,37 @@ class DataConsumer(AsyncJsonWebsocketConsumer):
|
|||||||
filter_q = Q()
|
filter_q = Q()
|
||||||
filter_dict = client_params.get('filter')
|
filter_dict = client_params.get('filter')
|
||||||
if isinstance(filter_dict, dict):
|
if isinstance(filter_dict, dict):
|
||||||
for key, value in filter_dict.items():
|
filter_q = Q(**filter_dict)
|
||||||
filter_q.add(Q(**{key: value}), Q.AND)
|
|
||||||
|
|
||||||
# Combine the client's filter with the specific record's ID
|
|
||||||
combined_filter = Q(pk=record_id) & filter_q
|
|
||||||
|
|
||||||
# Check if the object actually exists with the combined filter
|
# Check if the object actually exists with the combined filter
|
||||||
record_exists = await database_sync_to_async(Model.objects.filter(combined_filter).exists)()
|
record_exists = await database_sync_to_async(
|
||||||
if not record_exists:
|
Model.objects.filter(Q(pk=record_id) & filter_q).exists
|
||||||
return # The record does not match the client's filter, so don't send.
|
)()
|
||||||
|
|
||||||
# 3. Re-run the original query for just this single object.
|
if record_exists:
|
||||||
# This correctly applies 'values', 'distinct_values', 'summary', etc.
|
# If record matches filter, re-run the query to get the correctly shaped data
|
||||||
single_record_params = client_params.copy()
|
single_record_params = client_params.copy()
|
||||||
single_record_params['filter'] = {'pk': record_id}
|
single_record_params['filter'] = {'pk': record_id}
|
||||||
|
|
||||||
data = await database_sync_to_async(execute_data_query)(model_name_capitalized, single_record_params)
|
data = await database_sync_to_async(execute_data_query)(model_name_capitalized, single_record_params)
|
||||||
|
|
||||||
# If the query returns no data (e.g., record was deleted or no longer matches), do nothing.
|
if data and data.get('rows'):
|
||||||
if not data or not data.get('rows'):
|
|
||||||
return
|
|
||||||
|
|
||||||
# 4. Build the final payload with the correctly-shaped record
|
|
||||||
payload_for_client = {
|
payload_for_client = {
|
||||||
"name": model_name_lower,
|
"name": model_name_lower,
|
||||||
|
"change_type": change_type,
|
||||||
"record": data['rows'][0]
|
"record": data['rows'][0]
|
||||||
}
|
}
|
||||||
|
|
||||||
# 5. Send the final, tailored payload to the client
|
|
||||||
await self.send_json({
|
await self.send_json({
|
||||||
"type": "realtime_update",
|
"type": "realtime_update",
|
||||||
"payload": payload_for_client
|
"payload": payload_for_client
|
||||||
})
|
})
|
||||||
|
else:
|
||||||
|
# If the record exists but no longer matches the filter, treat as a deletion for this client
|
||||||
|
await self.send_json({
|
||||||
|
"type": "realtime_update",
|
||||||
|
"payload": {
|
||||||
|
"name": model_name_lower,
|
||||||
|
"change_type": "deleted",
|
||||||
|
"record": {"id": record_id}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
# Generated by Django 5.1.7 on 2025-12-31 09:43
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('app', '0340_file_hashtag_co_ownership'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name='people',
|
||||||
|
old_name='facebook',
|
||||||
|
new_name='taxcode',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='people',
|
||||||
|
name='zalo',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='transaction_detail',
|
||||||
|
name='amount_received',
|
||||||
|
field=models.DecimalField(decimal_places=2, max_digits=15, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='transaction_detail',
|
||||||
|
name='amount_remaining',
|
||||||
|
field=models.DecimalField(decimal_places=2, max_digits=15, null=True),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -1200,8 +1200,7 @@ class People(models.Model):
|
|||||||
issued_date = models.DateField(null=True)
|
issued_date = models.DateField(null=True)
|
||||||
address = models.CharField(max_length=200, null=True)
|
address = models.CharField(max_length=200, null=True)
|
||||||
contact_address = models.CharField(max_length=200, null=True)
|
contact_address = models.CharField(max_length=200, null=True)
|
||||||
zalo = models.CharField(max_length=20, null=True)
|
taxcode = models.CharField(max_length=100, null=True)
|
||||||
facebook = models.CharField(max_length=100, null=True)
|
|
||||||
note = models.TextField(null=True)
|
note = models.TextField(null=True)
|
||||||
country = models.ForeignKey(Country, null=True, related_name='+', on_delete=models.PROTECT, default=1)
|
country = models.ForeignKey(Country, null=True, related_name='+', on_delete=models.PROTECT, default=1)
|
||||||
company = models.ForeignKey(Company, null=True, related_name='+', on_delete=models.PROTECT)
|
company = models.ForeignKey(Company, null=True, related_name='+', on_delete=models.PROTECT)
|
||||||
@@ -1371,6 +1370,8 @@ class Transaction_Detail(AutoCodeModel):
|
|||||||
code = models.CharField(max_length=30, null=True, unique=True)
|
code = models.CharField(max_length=30, null=True, unique=True)
|
||||||
date = models.DateField()
|
date = models.DateField()
|
||||||
amount = models.DecimalField(max_digits=15, decimal_places=2, null=True)
|
amount = models.DecimalField(max_digits=15, decimal_places=2, null=True)
|
||||||
|
amount_remaining = models.DecimalField(max_digits=15, decimal_places=2, null=True)
|
||||||
|
amount_received = models.DecimalField(max_digits=15, decimal_places=2, null=True)
|
||||||
due_date = models.DateField(null=True)
|
due_date = models.DateField(null=True)
|
||||||
transaction = models.ForeignKey(Transaction, null=False, related_name='resvtxn', on_delete=models.PROTECT)
|
transaction = models.ForeignKey(Transaction, null=False, related_name='resvtxn', on_delete=models.PROTECT)
|
||||||
phase = models.ForeignKey(Transaction_Phase, null=False, related_name='+', on_delete=models.PROTECT)
|
phase = models.ForeignKey(Transaction_Phase, null=False, related_name='+', on_delete=models.PROTECT)
|
||||||
|
|||||||
Reference in New Issue
Block a user