This commit is contained in:
javad committed 2026-09-16 14:16:05 +03:30
1 parent 6b841dc5fa
commit 0ed677e5fc
10 files changed
+282 -16

No files matched your search

@@ -19,6 +19,12 @@ from apps.tickets.models import Ticket
logger = logging.getLogger(__name__)
DEFINITIVE_DELIVERY_RETRY_EVENT = "STAFF_TICKET_CREATED"
DEFINITIVE_DELIVERY_RETRY_STATUSES = {
NotificationJob.DeliveryStatus.UNDELIVERED,
NotificationJob.DeliveryStatus.EXPIRED,
}
def _magic_link(job, reason):
token,link = TicketMagicLink.issue_with_record(job.ticket, reason=reason, created_by=job.staff_user or job.ticket.owner or job.ticket.created_by)
return link, f"{settings.PUBLIC_BASE_URL}/t/{token}/"
@@ -158,11 +164,50 @@ def _record_success(job, result):
job.last_error = ""
job.provider_message_id = getattr(result, "provider_id", "") if result is not None else ""
job.provider_status_code = getattr(result, "provider_code", "") if result is not None else ""
job.delivery_is_final = False
if job.channel == NotificationJob.Channel.SMS and job.provider_message_id:
job.delivery_status = NotificationJob.DeliveryStatus.PENDING
job.delivery_next_check_at = timezone.now() + timedelta(seconds=settings.SMS_DELIVERY_CHECK_DELAY_SECONDS)
def _delivery_retry_dedupe_key(job):
suffix = f":definitive-delivery-retry:{job.pk}"
return f"{job.dedupe_key[:200-len(suffix)]}{suffix}"
def _schedule_definitive_delivery_retry(job):
"""Schedule exactly one delayed resend for a definitive individual-ticket failure."""
if (
job.channel != NotificationJob.Channel.SMS
or job.event_type != DEFINITIVE_DELIVERY_RETRY_EVENT
or job.delivery_retry_source_id
or not job.ticket_id
or job.ticket.group_dispatch_id
or not job.delivery_is_final
or job.delivery_status not in DEFINITIVE_DELIVERY_RETRY_STATUSES
):
return None
sent_at = job.sent_at or job.created_at
due = max(
timezone.now(),
sent_at + timedelta(seconds=settings.SMS_DEFINITIVE_DELIVERY_RETRY_AFTER_SECONDS),
)
retry, _ = NotificationJob.objects.get_or_create(
delivery_retry_source=job,
defaults={
"channel": job.channel,
"event_type": job.event_type,
"customer_id": job.customer_id,
"staff_user_id": job.staff_user_id,
"ticket_id": job.ticket_id,
"payload": job.payload,
"next_attempt_at": due,
"dedupe_key": _delivery_retry_dedupe_key(job),
},
)
return retry
def _process_delivery_checks(options):
if options.get("channel") not in (None, NotificationJob.Channel.SMS):
return
@@ -207,11 +252,13 @@ def _process_delivery_checks(options):
job.delivery_status = ""
job.delivery_next_check_at = None
job.delivery_description = "این ارائه‌دهنده از استعلام دلیوری پشتیبانی نمی‌کند."
job.delivery_is_final = False
else:
job.delivery_check_attempts += 1
job.delivery_checked_at = timezone.now()
job.delivery_status_code = result.provider_code[:50]
job.delivery_description = result.description[:500]
job.delivery_is_final = result.is_final
if result.is_final:
job.delivery_status = result.status
job.delivery_next_check_at = None
@@ -225,7 +272,9 @@ def _process_delivery_checks(options):
job.save(update_fields=[
"delivery_status", "delivery_status_code", "delivery_description",
"delivery_checked_at", "delivery_check_attempts", "delivery_next_check_at",
"delivery_is_final",
])
_schedule_definitive_delivery_retry(job)
if job.ticket_id and job.ticket.group_dispatch_id:
from apps.tickets.services import refresh_group_dispatch_status
refresh_group_dispatch_status(job.ticket.group_dispatch_id)