diff --git a/apps/push_notifications/management/__init__.py b/apps/push_notifications/management/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/push_notifications/management/commands/__init__.py b/apps/push_notifications/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/push_notifications/management/commands/seed_notification_links.py b/apps/push_notifications/management/commands/seed_notification_links.py new file mode 100644 index 0000000..fc93286 --- /dev/null +++ b/apps/push_notifications/management/commands/seed_notification_links.py @@ -0,0 +1,103 @@ +from django.core.management.base import BaseCommand + +from apps.push_notifications.models import NotificationLink + +# The full action_code catalog documented in +# docs/frontend-notification-click-actions.md. Each entry: +# action_code, description, url_template +# url_template uses {object_id} as a placeholder, filled in at send time +# with PushMessage.click_object_id_value (see NotificationLink.resolve()). +# +# These URLs are sample/placeholder destinations — rows are seeded +# `is_active=True` so notifications of these types are clickable end to +# end today, but the actual routes still need confirming with whoever owns +# the frontend before going live for real. Update via the Django admin +# (NotificationLink) at any time; this command won't clobber a row that +# already exists unless --force is passed. + +BILLBOARD_URL_TEMPLATE = "https://app.gooyal.ir/ads/{object_id}" +ESCROW_URL_TEMPLATE = "https://app.gooyal.ir/escrow/{object_id}" + +NOTIFICATION_LINKS = [ + # Billboards & content — all resolve to the ad detail screen today. + ("billboard.viewed", "شخصی شروع به مشاهده بیلبورد شما کرد.", BILLBOARD_URL_TEMPLATE), + ("billboard.created", "بیلبورد شما با موفقیت ساخته شد.", BILLBOARD_URL_TEMPLATE), + ("billboard.approved", "بیلبورد شما تایید شد.", BILLBOARD_URL_TEMPLATE), + ("billboard.rejected", "بیلبورد شما رد شد.", BILLBOARD_URL_TEMPLATE), + ("billboard.commented", "یک نفر برای بیلبورد شما نظر گذاشت!", BILLBOARD_URL_TEMPLATE), + ("billboard.replied", "یک نفر به نظر شما پاسخ داد!", BILLBOARD_URL_TEMPLATE), + ("billboard.content_bought", "درآمد جدید دارید! یک نفر محتوای شما را خرید.", BILLBOARD_URL_TEMPLATE), + ("billboard.content_supported", "یک نفر از محتوای شما حمایت کرد!", BILLBOARD_URL_TEMPLATE), + ("billboard.pin_expiring", "زمان پین رو به اتمامه!", BILLBOARD_URL_TEMPLATE), + ("billboard.pin_expired", "پین شما منقضی شد!", BILLBOARD_URL_TEMPLATE), + ("billboard.credit_low", "اعتبار پین رو به اتمامه!", BILLBOARD_URL_TEMPLATE), + ("billboard.credit_exhausted", "اعتبار پین شما به پایان رسید!", BILLBOARD_URL_TEMPLATE), + + # Escrow deals — all resolve to the escrow deal detail screen today. + ("escrow.request_deal", "Buyer paid, seller needs to review", ESCROW_URL_TEMPLATE), + ("escrow.cancel_deal", "Buyer canceled before seller responded", ESCROW_URL_TEMPLATE), + ("escrow.reject_deal", "Seller declined the deal", ESCROW_URL_TEMPLATE), + ("escrow.approve_deal", "Seller confirmed the deal", ESCROW_URL_TEMPLATE), + ("escrow.cancel_deal_by_seller", "Seller canceled an active deal", ESCROW_URL_TEMPLATE), + ("escrow.request_cancel", "Buyer requested cancellation", ESCROW_URL_TEMPLATE), + ("escrow.approve_cancel", "Seller accepted the cancellation", ESCROW_URL_TEMPLATE), + ("escrow.reject_cancel", "Seller declined the cancellation", ESCROW_URL_TEMPLATE), + ("escrow.confirm_by_seller", "Seller marked it delivered", ESCROW_URL_TEMPLATE), + ("escrow.confirm_by_buyer", "Buyer confirmed receipt — deal completed", ESCROW_URL_TEMPLATE), + ("escrow.request_judge", "A dispute was opened", ESCROW_URL_TEMPLATE), + ("escrow.cancel_judge", "Buyer withdrew their dispute", ESCROW_URL_TEMPLATE), + ("escrow.approve_judge", "Dispute resolved for the buyer", ESCROW_URL_TEMPLATE), + ("escrow.reject_judge", "Dispute resolved for the seller", ESCROW_URL_TEMPLATE), + ("escrow.timeout", "Deal expired without a response", ESCROW_URL_TEMPLATE), +] + + +class Command(BaseCommand): + help = ( + "Seed the admin-managed NotificationLink table with one row per " + "action_code currently sent by producer services (see " + "docs/frontend-notification-click-actions.md), so their " + "notifications resolve a click_url end to end. Existing rows are " + "left untouched unless --force is passed." + ) + + def add_arguments(self, parser): + parser.add_argument( + "--force", + action="store_true", + help="Overwrite url_template/description/is_active on rows that already exist.", + ) + + def handle(self, *args, **options): + force = options["force"] + created_count = 0 + updated_count = 0 + skipped_count = 0 + + for action_code, description, url_template in NOTIFICATION_LINKS: + link, created = NotificationLink.objects.get_or_create( + action_code=action_code, + defaults={ + "description": description, + "url_template": url_template, + "is_active": True, + }, + ) + if created: + created_count += 1 + self.stdout.write(self.style.SUCCESS(f"created {action_code}")) + elif force: + link.description = description + link.url_template = url_template + link.is_active = True + link.save(update_fields=["description", "url_template", "is_active"]) + updated_count += 1 + self.stdout.write(self.style.WARNING(f"updated {action_code}")) + else: + skipped_count += 1 + self.stdout.write(f"skipped {action_code} (already exists, use --force to overwrite)") + + self.stdout.write(self.style.SUCCESS( + f"\nDone. {created_count} created, {updated_count} updated, {skipped_count} skipped " + f"({len(NOTIFICATION_LINKS)} total action_codes)." + )) diff --git a/main/settings.py b/main/settings.py index dcc70b3..9744e35 100644 --- a/main/settings.py +++ b/main/settings.py @@ -226,7 +226,9 @@ CORS_ORIGIN_ALLOW_ALL = True CORS_ALLOW_ALL_ORIGINS = True CSRF_TRUSTED_ORIGINS = ['http://*', 'https://*', 'http://*.gooyal.com', 'https://*.gooyal.com', - 'http://*.gooyal.ir', 'https://*.gooyal.ir'] + 'http://*.gooyal.ir', 'https://*.gooyal.ir', + 'http://*.winsoo.com', 'https://*.winsoo.com', + 'http://*.winsoo.ir', 'https://*.winsoo.ir',] JALALI_DATE_DEFAULTS = { 'Strftime': {