fix: allow expired members to buy new plans
This commit is contained in:
+40
-13
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user