feat: add software subscription orders
This commit is contained in:
@@ -219,6 +219,110 @@ class SoftwareEntitlement(models.Model):
|
||||
return self.status == self.Status.ACTIVE and self.grace_expires_at > now
|
||||
|
||||
|
||||
class SoftwareOrder(models.Model):
|
||||
class PayMethod(models.TextChoices):
|
||||
WEIXIN = "weixin", "微信"
|
||||
|
||||
class Status(models.TextChoices):
|
||||
PENDING = "pending", "待支付"
|
||||
PAID = "paid", "已支付"
|
||||
FAILED = "failed", "下单失败"
|
||||
EXPIRED = "expired", "已过期"
|
||||
|
||||
user = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL,
|
||||
verbose_name="用户",
|
||||
on_delete=models.PROTECT,
|
||||
related_name="software_orders",
|
||||
)
|
||||
source_plan = models.ForeignKey(
|
||||
SoftwarePlan,
|
||||
verbose_name="来源套餐",
|
||||
null=True,
|
||||
blank=True,
|
||||
on_delete=models.SET_NULL,
|
||||
related_name="software_orders",
|
||||
)
|
||||
entitlement = models.ForeignKey(
|
||||
SoftwareEntitlement,
|
||||
verbose_name="发放权益",
|
||||
null=True,
|
||||
blank=True,
|
||||
on_delete=models.PROTECT,
|
||||
related_name="software_orders",
|
||||
)
|
||||
fulfillment_event = models.OneToOneField(
|
||||
"LicenseEvent",
|
||||
verbose_name="权益发放事件",
|
||||
null=True,
|
||||
blank=True,
|
||||
on_delete=models.PROTECT,
|
||||
related_name="software_order",
|
||||
)
|
||||
order_no = models.CharField("软件订单号", max_length=64, unique=True, editable=False)
|
||||
product_code = models.CharField(
|
||||
"产品代码",
|
||||
max_length=32,
|
||||
choices=ClientDevice.ProductCode.choices,
|
||||
)
|
||||
plan_name = models.CharField("套餐名称快照", max_length=120)
|
||||
plan_duration_days = models.PositiveIntegerField("套餐有效天数快照")
|
||||
plan_price = models.DecimalField("套餐价格快照", max_digits=12, decimal_places=2)
|
||||
plan_device_limit = models.PositiveSmallIntegerField("设备数量快照")
|
||||
plan_grace_days = models.PositiveSmallIntegerField("宽限天数快照", default=0)
|
||||
amount_money = models.DecimalField("支付金额", max_digits=12, decimal_places=2)
|
||||
currency = models.CharField("币种", max_length=8, default="CNY")
|
||||
pay_method = models.CharField("支付方式", max_length=20, choices=PayMethod.choices)
|
||||
status = models.CharField(
|
||||
"订单状态",
|
||||
max_length=20,
|
||||
choices=Status.choices,
|
||||
default=Status.PENDING,
|
||||
)
|
||||
code_url = models.TextField("二维码票据", blank=True)
|
||||
expires_at = models.DateTimeField("支付票据过期时间", null=True, blank=True)
|
||||
payment_txn_no = models.CharField("支付交易号", max_length=128, null=True, blank=True)
|
||||
paid_at = models.DateTimeField("支付时间", null=True, blank=True)
|
||||
fulfilled_at = models.DateTimeField("权益发放时间", null=True, blank=True)
|
||||
created_at = models.DateTimeField("创建时间", auto_now_add=True)
|
||||
updated_at = models.DateTimeField("更新时间", auto_now=True)
|
||||
|
||||
class Meta:
|
||||
db_table = "software_order"
|
||||
verbose_name = "软件套餐订单"
|
||||
verbose_name_plural = "软件套餐订单"
|
||||
ordering = ("-created_at", "-id")
|
||||
constraints = [
|
||||
models.UniqueConstraint(
|
||||
fields=("pay_method", "payment_txn_no"),
|
||||
name="software_order_pay_method_txn_unique",
|
||||
),
|
||||
models.CheckConstraint(
|
||||
condition=Q(plan_duration_days__gt=0),
|
||||
name="software_order_duration_positive",
|
||||
),
|
||||
models.CheckConstraint(
|
||||
condition=Q(plan_price__gt=0),
|
||||
name="software_order_plan_price_positive",
|
||||
),
|
||||
models.CheckConstraint(
|
||||
condition=Q(plan_device_limit__gt=0),
|
||||
name="software_order_device_limit_positive",
|
||||
),
|
||||
models.CheckConstraint(
|
||||
condition=Q(amount_money__gt=0),
|
||||
name="software_order_amount_positive",
|
||||
),
|
||||
]
|
||||
indexes = [
|
||||
models.Index(fields=("user", "product_code", "status")),
|
||||
models.Index(fields=("status", "expires_at")),
|
||||
]
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"{self.order_no} {self.user} {self.plan_name}"
|
||||
|
||||
|
||||
class LicenseSeat(models.Model):
|
||||
entitlement = models.ForeignKey(
|
||||
SoftwareEntitlement,
|
||||
@@ -273,6 +377,7 @@ class LicenseEvent(models.Model):
|
||||
MIGRATION_GRANTED = "migration_granted", "迁移资格授予"
|
||||
CREDENTIAL_ISSUED = "credential_issued", "设备凭证签发"
|
||||
CREDENTIAL_REVOKED = "credential_revoked", "设备凭证吊销"
|
||||
ORDER_FULFILLED = "order_fulfilled", "套餐订单权益发放"
|
||||
|
||||
entitlement = models.ForeignKey(
|
||||
SoftwareEntitlement,
|
||||
|
||||
Reference in New Issue
Block a user