baseline: 批次A-D 成果 + membership 半成品(测试红)
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
"""订阅到期处理(Dramatiq actor + cron 每日调用)。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import date, timedelta
|
||||
|
||||
import dramatiq
|
||||
from django.utils import timezone
|
||||
|
||||
from .models import Plan, Subscription
|
||||
|
||||
|
||||
def expire_trials() -> dict:
|
||||
"""扫描到期试用 → 降级 free 并把状态置为 expired,同时发通知。"""
|
||||
from django.db.models import Q
|
||||
|
||||
from apps.notify.services import send_notification
|
||||
|
||||
now = timezone.now()
|
||||
qs = Subscription.objects.filter(
|
||||
status=Subscription.STATUS_TRIAL,
|
||||
trial_ends_at__isnull=False,
|
||||
trial_ends_at__lt=now,
|
||||
).select_related("tenant", "plan")
|
||||
|
||||
free = Plan.objects.filter(code="free", is_active=True).first()
|
||||
downgraded = 0
|
||||
for sub in qs:
|
||||
sub.status = Subscription.STATUS_EXPIRED
|
||||
if free is not None:
|
||||
sub.plan = free
|
||||
sub.save(update_fields=["status", "plan", "updated_at"])
|
||||
try:
|
||||
send_notification(
|
||||
tenant=sub.tenant,
|
||||
title="【套餐】免费试用已到期",
|
||||
content=(
|
||||
"30 天全功能试用已结束,当前已回落至免费版配额"
|
||||
"(1 用户 / 100 商品 / 50 单据每月)。"
|
||||
"升级基础版 ¥998/月 可解除限制,历史数据全部保留。"
|
||||
),
|
||||
category="warning",
|
||||
link="/#/pricing",
|
||||
extra_data={"kind": "trial_expired"},
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
downgraded += 1
|
||||
|
||||
# 付费到期(未续费)→ 同样降级
|
||||
today = date.today()
|
||||
paid_expired = Subscription.objects.filter(
|
||||
status=Subscription.STATUS_ACTIVE,
|
||||
period_end__isnull=False,
|
||||
period_end__lt=today,
|
||||
).select_related("tenant", "plan")
|
||||
for sub in paid_expired:
|
||||
sub.status = Subscription.STATUS_EXPIRED
|
||||
if free is not None:
|
||||
sub.plan = free
|
||||
sub.save(update_fields=["status", "plan", "updated_at"])
|
||||
try:
|
||||
send_notification(
|
||||
tenant=sub.tenant,
|
||||
title="【套餐】订阅已到期",
|
||||
content=f"套餐已于 {sub.period_end} 到期,当前回落至免费版配额,请及时续费。",
|
||||
category="warning",
|
||||
link="/#/pricing",
|
||||
extra_data={"kind": "subscription_expired"},
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
downgraded += 1
|
||||
|
||||
return {"expired_count": downgraded, "checked_at": now.isoformat()}
|
||||
|
||||
|
||||
@dramatiq.actor(max_retries=2, time_limit=300_000)
|
||||
def expire_trials_and_notify():
|
||||
"""Dramatiq actor 包装(供 config/dramatiq.py 的 cron 调用/手动 send)。"""
|
||||
return expire_trials()
|
||||
Reference in New Issue
Block a user