fix: defer expiry reminders for trial and bonus subscriptions

Trial and registration/referral-bonus subscriptions usually last only a
few days, so the multi-day ending-soon reminders fired almost the moment
they were granted and needlessly alarmed newcomers.

Track this with a new subscription flag (suppress_early_expiry_notifications,
migration 0035): trial activation, referral welcome bonus and inviter bonus
grants set it, while a real paid purchase clears it on upsert. While set, the
notification worker skips the day-before stages but still sends the
hours-before reminder and the expiry/after-expiry notices, so users are
warned shortly before access ends. Once they pay for a full subscription the
complete reminder spectrum resumes.
This commit is contained in:
3252a8
2026-06-02 19:53:13 +03:00
parent e15d6559aa
commit 36e0e4f462
7 changed files with 73 additions and 2 deletions
+30 -2
View File
@@ -23,8 +23,11 @@ def _worker(**overrides):
)
def _sub(end_date):
return SimpleNamespace(end_date=end_date)
def _sub(end_date, *, suppress_early_expiry_notifications=False):
return SimpleNamespace(
end_date=end_date,
suppress_early_expiry_notifications=suppress_early_expiry_notifications,
)
def test_stage_prefers_hour_reminder_over_day_backlog():
@@ -58,3 +61,28 @@ def test_stage_sends_yesterday_notice_only_after_first_day():
assert stage.key == "expired_24h_after"
assert stage.message_key == "subscription_expired_yesterday_notification"
def test_promo_subscription_skips_day_before_reminders():
now = datetime(2026, 5, 28, 12, tzinfo=timezone.utc)
sub = _sub(now + timedelta(hours=23), suppress_early_expiry_notifications=True)
assert _worker().stage_for_subscription(sub, now) is None
def test_promo_subscription_still_gets_hours_before_reminder():
now = datetime(2026, 5, 28, 12, tzinfo=timezone.utc)
sub = _sub(now + timedelta(hours=2, minutes=30), suppress_early_expiry_notifications=True)
stage = _worker().stage_for_subscription(sub, now)
assert stage.key == "before_3h"
assert stage.hours_before == 3
def test_promo_subscription_still_gets_expiry_notice():
now = datetime(2026, 5, 28, 12, tzinfo=timezone.utc)
sub = _sub(now - timedelta(hours=1), suppress_early_expiry_notifications=True)
stage = _worker().stage_for_subscription(sub, now)
assert stage.key == "expired"
assert stage.message_key == "subscription_expired_notification"