estelam ticket, varizha , others

This commit is contained in:
javad committed 2026-10-13 15:48:24 +03:30
1 parent 35a1ec1794
commit 6b546aad76
71 files changed
+2865 -191

No files matched your search

+22 -1
View File
@@ -63,6 +63,7 @@ def dispatch_group_tickets(*, user, unit, contact_group, category, subject, body
)
if not contacts:
raise ValidationError("گروه انتخاب‌شده مخاطب فعال دارای شماره همراه ندارد.")
from .models import DispatchResponseControl
dispatch = GroupDispatch.objects.create(
unit=unit,
operation_type=operation_type,
@@ -74,6 +75,9 @@ def dispatch_group_tickets(*, user, unit, contact_group, category, subject, body
status=GroupDispatch.Status.QUEUED,
recipient_count=len(contacts),
)
DispatchResponseControl.objects.create(dispatch=dispatch, mode="SEALED",
notify_sms=len(contacts) <= 15,
recipient_count_snapshot=len(contacts))
tickets=[]
for contact in contacts:
for uploaded in files:
@@ -97,6 +101,20 @@ def dispatch_group_tickets(*, user, unit, contact_group, category, subject, body
return dispatch, tickets
@transaction.atomic
def create_group_dispatch(*, response_mode="SEALED", notify_opening_sms=True, **dispatch_fields):
"""Configure responses without changing the existing creation API."""
from .models import DispatchResponseControl
if response_mode not in DispatchResponseControl.Mode.values:
raise ValidationError("روش مشاهده پاسخ‌ها معتبر نیست.")
dispatch, tickets = dispatch_group_tickets(**dispatch_fields)
control = DispatchResponseControl.objects.get(dispatch=dispatch)
control.mode = response_mode
control.notify_sms = bool(notify_opening_sms and response_mode == "SEALED" and control.recipient_count_snapshot <= 15)
control.save(update_fields=["mode", "notify_sms"])
return dispatch, tickets
def refresh_group_dispatch_status(dispatch_id):
"""Persist delivery state independently of whether a report page is opened."""
dispatch=GroupDispatch.objects.filter(pk=dispatch_id).first()
@@ -194,6 +212,8 @@ def revoke_access(ticket,user,target):
@transaction.atomic
def reply_ticket(*,ticket_id,user,body="",files=(),internal=False,mentioned_users=()):
from .dispatch_responses import lock_dispatch_for_ticket
control = lock_dispatch_for_ticket(ticket_id)
ticket=Ticket.objects.select_for_update().get(pk=ticket_id)
if not TicketPolicy.can_reply(user,ticket): raise PermissionDenied
if internal and (TicketPolicy.is_customer(user) or not user.has_perm("messaging.add_internal_note")): raise PermissionDenied
@@ -204,7 +224,8 @@ def reply_ticket(*,ticket_id,user,body="",files=(),internal=False,mentioned_user
if not TicketPolicy.can_view(target,ticket):
if TicketPolicy.can_share(user,ticket): share_ticket(ticket,user,target)
else: raise PermissionDenied("کارشناس Mention‌شده به تیکت دسترسی ندارد.")
MessageMention.objects.get_or_create(message=msg,mentioned_user=target); enqueue(NotificationJob.Channel.BALE,"MENTION",ticket,f"message:{msg.pk}:mention:{target.pk}",staff_user=target,payload={"excerpt":body[:150]})
excerpt = "پاسخ محرمانه ثبت شد." if control and control.mode == "SEALED" and not control.opened_at and user.pk == ticket.customer_id else body[:150]
MessageMention.objects.get_or_create(message=msg,mentioned_user=target); enqueue(NotificationJob.Channel.BALE,"MENTION",ticket,f"message:{msg.pk}:mention:{target.pk}",staff_user=target,payload={"excerpt":excerpt})
now=timezone.now(); ticket.last_activity_at=now
if not internal:
if TicketPolicy.is_customer(user):