"""Isolated worker handler; existing events keep their delivery flow.""" from django.core.exceptions import ValidationError from apps.tickets.models import DispatchResponseControl DEFAULT_OPENING_SMS = ( "لوله گستر گلپایگان با سلام؛ پاسخ استعلام شما بازگشایی شد. جهت صیانت از رقابت عادلانه، تمامی پیشنهادات تا این لحظه کاملاً محرمانه بوده و هیچ‌کس دسترسی به مشاهده آن‌ها نداشته است. اکنون تمامی پاسخ‌ها به‌صورت هم‌زمان بازگشایی شدند تا سلامت فرآیند تضمین گردد.\n" "از همراهی و اعتماد شما سپاسگزاریم. واحد فناوری اطلاعات لوله گستر گلپایگان" ) def ensure_opening_template(): """Legacy seed bundles may predate this event; never replace an existing body.""" from .models import SMSTemplate return SMSTemplate.objects.get_or_create(unit=None, event_type="DISPATCH_RESPONSES_OPENED", defaults={ "title": "بازگشایی پاسخ‌های ارسال گروهی", "body": DEFAULT_OPENING_SMS, "allowed_tags": [], "is_active": True, })[0] def send_opening_sms(job, provider_factory): control = DispatchResponseControl.objects.get(dispatch_id=job.payload.get("dispatch_id")) permitted = (control.mode == "SEALED" and control.notify_sms and control.recipient_count_snapshot <= 15 and control.opened_at and job.ticket_id and job.ticket.group_dispatch_id == control.dispatch_id and job.customer_id == job.ticket.customer_id and str(job.customer.public_id) in control.respondents_snapshot) if not permitted or job.payload.get("body") != control.sms_body_snapshot: raise ValidationError("Opening notification does not match its authorized snapshot.") return provider_factory().send_message(job.customer.mobile, control.sms_body_snapshot) def send_dispatch_reply_bale(job, text, provider_factory): """Dispatch metadata goes to its creator's private destination, never a unit room.""" from apps.tickets.policies import DispatchPolicy dispatch = job.ticket.group_dispatch owner = dispatch.created_by profile = getattr(owner, "staff_profile", None) if not owner.is_active or not profile or not profile.is_active or not profile.bale_notifications_enabled: return None if not profile.bale_chat_id.strip() or not DispatchPolicy.can_view(owner, dispatch): return None return provider_factory().send_message(profile.bale_chat_id.strip(), text)