fix: allow expired members to buy new plans

This commit is contained in:
QiuSW
2026-07-23 17:42:08 +08:00
parent e12659faa0
commit 976b55c374
6 changed files with 207 additions and 21 deletions
+40 -13
View File
@@ -783,17 +783,41 @@ def _generate_software_order_no() -> str:
raise SoftwareOrderError("order_number_failed", "无法生成软件订单号")
def _active_entitlement_for_software_order(*, user, product_code):
return (
def _usable_entitlement_for_software_order(
*,
user,
product_code,
now=None,
for_update=False,
):
now = now or timezone.now()
queryset = SoftwareEntitlement.objects.filter(
user=user,
product_code=product_code,
status=SoftwareEntitlement.Status.ACTIVE,
grace_expires_at__gt=now,
)
if for_update:
queryset = queryset.select_for_update()
return queryset.order_by("-expires_at", "-id").first()
def _expire_elapsed_entitlements_for_software_order(*, user, product_code, now):
entitlement_ids = list(
SoftwareEntitlement.objects.select_for_update()
.filter(
user=user,
product_code=product_code,
status=SoftwareEntitlement.Status.ACTIVE,
grace_expires_at__lte=now,
)
.order_by("-expires_at", "-id")
.first()
.values_list("id", flat=True)
)
if entitlement_ids:
SoftwareEntitlement.objects.filter(id__in=entitlement_ids).update(
status=SoftwareEntitlement.Status.EXPIRED,
updated_at=now,
)
def create_software_order(*, user, plan: SoftwarePlan, pay_method: str, payment_order_func=None):
@@ -801,14 +825,9 @@ def create_software_order(*, user, plan: SoftwarePlan, pay_method: str, payment_
raise SoftwareOrderError("plan_inactive", "套餐已停用,无法购买")
if pay_method != SoftwareOrder.PayMethod.WEIXIN:
raise SoftwareOrderError("bad_request", "当前软件订阅仅支持微信支付")
existing_entitlement = (
SoftwareEntitlement.objects.filter(
user=user,
product_code=plan.product_code,
status=SoftwareEntitlement.Status.ACTIVE,
)
.order_by("-expires_at", "-id")
.first()
existing_entitlement = _usable_entitlement_for_software_order(
user=user,
product_code=plan.product_code,
)
if existing_entitlement is not None and existing_entitlement.source_plan_id != plan.id:
raise SoftwareOrderError("plan_change_not_supported", "当前套餐变更请联系运营处理")
@@ -917,9 +936,17 @@ def apply_software_payment(payment) -> SoftwarePaymentResult:
).exclude(pk=order.pk).exists():
raise SoftwareOrderTransactionMismatchError()
entitlement = _active_entitlement_for_software_order(
fulfillment_now = timezone.now()
_expire_elapsed_entitlements_for_software_order(
user=order.user,
product_code=order.product_code,
now=fulfillment_now,
)
entitlement = _usable_entitlement_for_software_order(
user=order.user,
product_code=order.product_code,
now=fulfillment_now,
for_update=True,
)
if entitlement is None:
entitlement = _grant_software_order_entitlement(order=order, now=paid_at)