feat: add recharge callback processing
This commit is contained in:
@@ -154,6 +154,80 @@ class ExchangeRate(models.Model):
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
|
||||
class RechargeOrder(models.Model):
|
||||
class PayMethod(models.TextChoices):
|
||||
WEIXIN = "weixin", "Weixin"
|
||||
ALIPAY = "alipay", "Alipay"
|
||||
|
||||
class Status(models.TextChoices):
|
||||
PENDING = "pending", "Pending"
|
||||
PAID = "paid", "Paid"
|
||||
FAILED = "failed", "Failed"
|
||||
EXPIRED = "expired", "Expired"
|
||||
|
||||
order_no = models.CharField(max_length=64, unique=True)
|
||||
user = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL,
|
||||
on_delete=models.PROTECT,
|
||||
related_name="recharge_orders",
|
||||
)
|
||||
amount_money = models.DecimalField(max_digits=12, decimal_places=2)
|
||||
currency = models.CharField(max_length=10, default="CNY")
|
||||
pay_method = models.CharField(max_length=20, choices=PayMethod.choices)
|
||||
exchange_rate = models.DecimalField(max_digits=12, decimal_places=4)
|
||||
points_granted = models.BigIntegerField()
|
||||
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, blank=True)
|
||||
paid_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 = "recharge_order"
|
||||
ordering = ("-created_at", "-id")
|
||||
constraints = [
|
||||
models.CheckConstraint(
|
||||
condition=Q(amount_money__gt=0),
|
||||
name="recharge_order_amount_money_positive",
|
||||
),
|
||||
models.CheckConstraint(
|
||||
condition=Q(exchange_rate__gt=0),
|
||||
name="recharge_order_exchange_rate_positive",
|
||||
),
|
||||
models.CheckConstraint(
|
||||
condition=Q(points_granted__gt=0),
|
||||
name="recharge_order_points_granted_positive",
|
||||
),
|
||||
]
|
||||
indexes = [
|
||||
models.Index(fields=("user", "created_at")),
|
||||
models.Index(fields=("status", "created_at")),
|
||||
models.Index(fields=("pay_method", "status")),
|
||||
]
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"{self.order_no} {self.status}"
|
||||
|
||||
def clean(self) -> None:
|
||||
super().clean()
|
||||
self.order_no = str(self.order_no or "").strip()
|
||||
self.currency = str(self.currency or "").strip().upper()
|
||||
if not self.order_no:
|
||||
raise ValidationError({"order_no": "Order number is required."})
|
||||
if not self.currency:
|
||||
raise ValidationError({"currency": "Currency is required."})
|
||||
|
||||
def save(self, *args, **kwargs) -> None:
|
||||
self.full_clean()
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
|
||||
class PointsLedger(models.Model):
|
||||
class ChangeType(models.TextChoices):
|
||||
RECHARGE = "recharge", "Recharge"
|
||||
@@ -196,6 +270,10 @@ class PointsLedger(models.Model):
|
||||
fields=("ref_call", "change_type"),
|
||||
name="unique_ledger_change_type_per_call",
|
||||
),
|
||||
models.UniqueConstraint(
|
||||
fields=("ref_order_id", "change_type"),
|
||||
name="unique_ledger_change_type_per_order",
|
||||
),
|
||||
]
|
||||
indexes = [
|
||||
models.Index(fields=("user", "created_at")),
|
||||
|
||||
Reference in New Issue
Block a user