first
This commit is contained in:
commit
fa9d154db9
260 files changed
+17643
No files matched your search
@@ -0,0 +1,53 @@
|
||||
from datetime import timedelta
|
||||
from uuid import uuid4
|
||||
from django.utils import timezone
|
||||
from .models import NotificationJob,NotificationPolicy
|
||||
def enqueue(channel,event_type,ticket,dedupe_key,payload=None,customer=None,staff_user=None):
|
||||
return NotificationJob.objects.get_or_create(dedupe_key=dedupe_key,defaults={"channel":channel,"event_type":event_type,"ticket":ticket,"payload":payload or {},"customer":customer,"staff_user":staff_user,"next_attempt_at":timezone.now()})[0]
|
||||
|
||||
def staff_reply_policy():
|
||||
return NotificationPolicy.objects.get_or_create(key=NotificationPolicy.Key.STAFF_REPLY_SMS,defaults={"quiet_period_seconds":300})[0]
|
||||
|
||||
def customer_reply_bale_policy():
|
||||
return NotificationPolicy.objects.get_or_create(key=NotificationPolicy.Key.CUSTOMER_REPLY_BALE,defaults={"quiet_period_seconds":600})[0]
|
||||
|
||||
def cancel_staff_reply_sms(ticket,reason):
|
||||
return NotificationJob.objects.filter(ticket=ticket,channel=NotificationJob.Channel.SMS,event_type="STAFF_REPLY",status__in=[NotificationJob.Status.PENDING,NotificationJob.Status.FAILED]).update(status=NotificationJob.Status.CANCELLED,last_error=reason)
|
||||
|
||||
def schedule_staff_reply_sms(ticket,message):
|
||||
"""Debounce a chat burst into one SMS; caller already locks the ticket."""
|
||||
policy=staff_reply_policy()
|
||||
if not policy.is_active:
|
||||
cancel_staff_reply_sms(ticket,"policy_disabled")
|
||||
return None,False
|
||||
due=timezone.now()+timedelta(seconds=policy.quiet_period_seconds)
|
||||
job=NotificationJob.objects.filter(ticket=ticket,customer=ticket.customer,channel=NotificationJob.Channel.SMS,event_type="STAFF_REPLY",status__in=[NotificationJob.Status.PENDING,NotificationJob.Status.FAILED]).order_by("-created_at").first()
|
||||
payload={"latest_message_id":message.pk}
|
||||
if job:
|
||||
job.payload=payload; job.next_attempt_at=due; job.status=NotificationJob.Status.PENDING; job.attempts=0; job.last_error=""
|
||||
job.save(update_fields=["payload","next_attempt_at","status","attempts","last_error"])
|
||||
return job,False
|
||||
return NotificationJob.objects.create(channel=NotificationJob.Channel.SMS,event_type="STAFF_REPLY",ticket=ticket,customer=ticket.customer,payload=payload,next_attempt_at=due,dedupe_key=f"ticket:{ticket.pk}:staff-reply:{uuid4().hex}"),True
|
||||
|
||||
def cancel_staff_reply_sms_if_read(ticket,customer):
|
||||
jobs=NotificationJob.objects.filter(ticket=ticket,customer=customer,channel=NotificationJob.Channel.SMS,event_type="STAFF_REPLY",status__in=[NotificationJob.Status.PENDING,NotificationJob.Status.FAILED])
|
||||
cancelled=0
|
||||
for job in jobs:
|
||||
message_id=job.payload.get("latest_message_id")
|
||||
if message_id and customer.message_read_receipts.filter(message_id=message_id).exists():
|
||||
job.status=NotificationJob.Status.CANCELLED; job.last_error="customer_read"; job.save(update_fields=["status","last_error"]); cancelled+=1
|
||||
return cancelled
|
||||
|
||||
def schedule_customer_reply_bale(ticket,message):
|
||||
"""Debounce consecutive customer chat messages into one Bale group alert."""
|
||||
policy=customer_reply_bale_policy()
|
||||
if not policy.is_active: return None,False
|
||||
due=timezone.now()+timedelta(seconds=policy.quiet_period_seconds)
|
||||
job=NotificationJob.objects.filter(ticket=ticket,channel=NotificationJob.Channel.BALE,event_type="CUSTOMER_TICKET_REPLY",status__in=[NotificationJob.Status.PENDING,NotificationJob.Status.FAILED]).order_by("-created_at").first()
|
||||
count=int((job.payload if job else {}).get("message_count",0))+1
|
||||
payload={"message_id":message.pk,"message_count":count}
|
||||
if job:
|
||||
job.payload=payload; job.next_attempt_at=due; job.status=NotificationJob.Status.PENDING; job.attempts=0; job.last_error=""
|
||||
job.save(update_fields=["payload","next_attempt_at","status","attempts","last_error"])
|
||||
return job,False
|
||||
return NotificationJob.objects.create(channel=NotificationJob.Channel.BALE,event_type="CUSTOMER_TICKET_REPLY",ticket=ticket,customer=ticket.customer,payload=payload,next_attempt_at=due,dedupe_key=f"ticket:{ticket.pk}:customer-reply-bale:{uuid4().hex}"),True
|
||||
Reference in new issue
Block a user