fix payment
This commit is contained in:
1 parent
4f7486152c
commit
bb3ddd1610
47 files changed
+2137
-51
No files matched your search
@@ -0,0 +1,102 @@
|
||||
"""Receipt-only outbox handlers. No network operation runs during receipt registration."""
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import transaction
|
||||
from django.urls import reverse
|
||||
|
||||
from apps.core.templatetags.jalali import jalali_date, jalali_datetime
|
||||
from apps.integrations.sms.base import SMSResult
|
||||
from apps.notifications.services import enqueue
|
||||
from .alert_templates import validate_alert_template
|
||||
from .models import PaymentReceiptAlert, PaymentReceiptAlertConfiguration
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
RECEIPT_ALERT_EVENT = 'PAYMENT_RECEIPT_RECEIVED'
|
||||
|
||||
|
||||
def receipt_alert_context(revision):
|
||||
customer = revision.receipt.customer
|
||||
profile = getattr(customer, 'customer_profile', None)
|
||||
name = f'{profile.first_name} {profile.last_name}'.strip() if profile else ''
|
||||
return {'customer_name': name or customer.get_full_name() or 'نام ثبت نشده',
|
||||
'customer_mobile': customer.local_mobile, 'amount_rial': f'{revision.amount:,}',
|
||||
'received_at': jalali_datetime(revision.created_at), 'paid_date': jalali_date(revision.paid_date),
|
||||
'receipt_number': revision.receipt.number, 'revision_version': str(revision.version), 'manager_name': '',
|
||||
'receipt_link': settings.PUBLIC_BASE_URL.rstrip('/') + reverse('staff_payments:receipt_detail', args=[revision.receipt.public_id])}
|
||||
|
||||
|
||||
def queue_receipt_alerts(revision, actor):
|
||||
if actor.account_type != 'CUSTOMER' or actor.pk != revision.receipt.customer_id:
|
||||
return
|
||||
configuration = PaymentReceiptAlertConfiguration.objects.filter(pk=1).first()
|
||||
if not configuration or not (configuration.bale_enabled or configuration.sms_enabled) or (revision.version > 1 and not configuration.notify_revisions):
|
||||
return
|
||||
context = receipt_alert_context(revision)
|
||||
destinations = []
|
||||
if configuration.bale_enabled:
|
||||
destinations.append(('BALE', None, configuration.bale_caption))
|
||||
if configuration.sms_enabled:
|
||||
destinations.extend(('SMS', recipient, configuration.sms_template) for recipient in configuration.recipients.filter(is_active=True))
|
||||
for channel, recipient, template in destinations:
|
||||
try:
|
||||
with transaction.atomic():
|
||||
job = enqueue(channel, RECEIPT_ALERT_EVENT, None,
|
||||
f'receipt-alert:{revision.pk}:{channel}:{recipient.pk if recipient else "group"}', customer=revision.receipt.customer)
|
||||
PaymentReceiptAlert.objects.get_or_create(job=job, defaults={'revision': revision, 'recipient': recipient,
|
||||
'recipient_name': recipient.name if recipient else '', 'recipient_mobile': recipient.mobile if recipient else '',
|
||||
'bale_chat_id': configuration.bale_chat_id if channel == 'BALE' else '', 'message_template': template,
|
||||
'context': {**context, 'manager_name': recipient.name if recipient else ''}})
|
||||
except Exception as error:
|
||||
logger.error('Receipt alert destination queue failed revision=%s channel=%s type=%s', revision.pk, channel, type(error).__name__)
|
||||
|
||||
|
||||
def safe_queue_receipt_alerts(revision, actor):
|
||||
# A failed configuration lookup/queue write rolls back only this savepoint.
|
||||
try:
|
||||
with transaction.atomic():
|
||||
queue_receipt_alerts(revision, actor)
|
||||
except Exception as error:
|
||||
logger.error('Receipt alert queue failed revision=%s type=%s', revision.pk, type(error).__name__)
|
||||
|
||||
|
||||
def prepare_receipt_alert(job):
|
||||
configuration = PaymentReceiptAlertConfiguration.objects.filter(pk=1).first()
|
||||
alert = PaymentReceiptAlert.objects.select_related('recipient').get(job=job)
|
||||
if job.channel == 'BALE':
|
||||
enabled = configuration and configuration.bale_enabled and configuration.bale_chat_id == alert.bale_chat_id
|
||||
else:
|
||||
enabled = configuration and configuration.sms_enabled and alert.recipient and alert.recipient.is_active and alert.recipient.mobile == alert.recipient_mobile
|
||||
if enabled:
|
||||
return True
|
||||
job.status = 'CANCELLED'
|
||||
job.last_error = 'اطلاعرسانی این کانال یا گیرنده غیرفعال شده یا مقصد تغییر کرده است.'
|
||||
job.save(update_fields=['status', 'last_error'])
|
||||
return False
|
||||
|
||||
|
||||
def send_receipt_alert(job, sms_provider_factory=None):
|
||||
"""A destination failure is returned to the worker's existing bounded retry policy."""
|
||||
try:
|
||||
alert = PaymentReceiptAlert.objects.select_related('revision').get(job=job)
|
||||
if not alert.rendered_body:
|
||||
validate_alert_template(alert.message_template)
|
||||
alert.rendered_body = alert.message_template.format(**alert.context)
|
||||
alert.save(update_fields=['rendered_body'])
|
||||
if job.channel == 'SMS':
|
||||
from apps.integrations.sms.providers import get_sms_provider
|
||||
return (sms_provider_factory or get_sms_provider)().send_message(alert.recipient_mobile, alert.rendered_body)
|
||||
from apps.integrations.bale.providers import BaleBotProvider
|
||||
configuration = PaymentReceiptAlertConfiguration.objects.get(pk=1)
|
||||
if not configuration.bale_token:
|
||||
return SMSResult(False, error='توکن ربات بله پرداخت تنظیم نشده است.')
|
||||
if len(alert.rendered_body) > 4096:
|
||||
return SMSResult(False, error='متن همراه تصویر بله بیش از ۴۰۹۶ کاراکتر است.')
|
||||
with alert.revision.image.open('rb') as image:
|
||||
return BaleBotProvider().send_photo(alert.bale_chat_id, image, alert.rendered_body,
|
||||
token=configuration.bale_token, filename=f'receipt-{alert.revision.pk}{Path(alert.revision.image.name).suffix}',
|
||||
mime_type=alert.revision.mime_type)
|
||||
except Exception as error:
|
||||
# HTTP exception strings can contain credentials in the request URL. Never persist them.
|
||||
return SMSResult(False, error=f'خطا در ارسال اعلان فیش ({type(error).__name__})')
|
||||
Reference in new issue
Block a user