feat: add avatar payments and finance management

This commit is contained in:
stefanfeng
2026-09-08 18:47:29 +08:00
parent 62eb9578fd
commit 8585d101d5
36 changed files with 10228 additions and 43 deletions
+114
View File
@@ -344,6 +344,7 @@ class TokenPlan(Base):
price = Column(Float, default=0)
badge = Column(String, default="")
desc = Column(String, default="")
virtual_product_id = Column(String, default="")
def to_dict(self):
return {
@@ -353,6 +354,7 @@ class TokenPlan(Base):
"price": self.price,
"badge": self.badge,
"desc": self.desc,
"virtualProductId": self.virtual_product_id,
}
@@ -369,14 +371,17 @@ class TokenPaymentOrder(Base):
points_amount = Column(BigInteger, nullable=False)
price_cents = Column(Integer, nullable=False)
status = Column(String, nullable=False, default="pending", index=True)
provider = Column(String, nullable=False, default="huihui", index=True)
provider_order_id = Column(String, default="")
provider_order_no = Column(String, default="")
provider_status = Column(String, default="")
pay_message = Column(Text, default="")
failure_reason = Column(String, default="")
refund_status = Column(String, nullable=False, default="none", index=True)
created_at = Column(DateTime, server_default=func.now())
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())
paid_at = Column(DateTime)
refunded_at = Column(DateTime)
def to_dict(self):
return {
@@ -389,11 +394,117 @@ class TokenPaymentOrder(Base):
"pointsAmount": self.points_amount,
"price": self.price_cents / 100,
"status": self.status,
"provider": self.provider,
"providerStatus": self.provider_status,
"payMessage": self.pay_message,
"failureReason": self.failure_reason,
"refundStatus": self.refund_status,
"createdAt": _iso(self.created_at),
"paidAt": _iso(self.paid_at),
"refundedAt": _iso(self.refunded_at),
}
class PaymentTransaction(Base):
"""Auditable provider event for one Token purchase order."""
__tablename__ = "payment_transactions"
__table_args__ = (
Index("ix_payment_transactions_order_created", "order_no", "created_at"),
)
id = Column(String, primary_key=True, default=lambda: uuid.uuid4().hex)
order_no = Column(String, nullable=False, index=True)
provider = Column(String, nullable=False, default="huihui")
transaction_no = Column(String, nullable=False, default="")
event_type = Column(String, nullable=False, default="payment")
status = Column(String, nullable=False, default="pending")
amount_cents = Column(Integer, nullable=False, default=0)
raw_summary = Column(Text, default="")
created_at = Column(DateTime, server_default=func.now())
def to_dict(self):
return {
"id": self.id,
"orderNo": self.order_no,
"provider": self.provider,
"transactionNo": self.transaction_no,
"eventType": self.event_type,
"status": self.status,
"amount": self.amount_cents / 100,
"createdAt": _iso(self.created_at),
}
class PaymentRefund(Base):
__tablename__ = "payment_refunds"
id = Column(String, primary_key=True, default=lambda: uuid.uuid4().hex)
refund_no = Column(String, nullable=False, unique=True, index=True)
order_no = Column(String, nullable=False, index=True)
amount_cents = Column(Integer, nullable=False)
points_amount = Column(BigInteger, nullable=False)
reason = Column(String, default="")
status = Column(String, nullable=False, default="pending", index=True)
provider_refund_no = Column(String, default="")
requested_by = Column(String, default="admin")
failure_reason = Column(String, default="")
created_at = Column(DateTime, server_default=func.now())
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())
completed_at = Column(DateTime)
def to_dict(self):
return {
"id": self.id,
"refundNo": self.refund_no,
"orderNo": self.order_no,
"amount": self.amount_cents / 100,
"pointsAmount": self.points_amount,
"reason": self.reason,
"status": self.status,
"providerRefundNo": self.provider_refund_no,
"requestedBy": self.requested_by,
"failureReason": self.failure_reason,
"createdAt": _iso(self.created_at),
"completedAt": _iso(self.completed_at),
}
class InvoiceApplication(Base):
__tablename__ = "invoice_applications"
id = Column(String, primary_key=True, default=lambda: uuid.uuid4().hex)
order_no = Column(String, nullable=False, unique=True, index=True)
user_id = Column(String, nullable=False, index=True)
amount_cents = Column(Integer, nullable=False)
title = Column(String, nullable=False)
invoice_type = Column(String, nullable=False, default="personal")
tax_number = Column(String, default="")
email = Column(String, default="")
status = Column(String, nullable=False, default="pending", index=True)
invoice_no = Column(String, default="")
invoice_url = Column(String, default="")
remark = Column(String, default="")
created_at = Column(DateTime, server_default=func.now())
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())
issued_at = Column(DateTime)
def to_dict(self):
return {
"id": self.id,
"orderNo": self.order_no,
"userId": self.user_id,
"amount": self.amount_cents / 100,
"title": self.title,
"invoiceType": self.invoice_type,
"taxNumber": self.tax_number,
"email": self.email,
"status": self.status,
"invoiceNo": self.invoice_no,
"invoiceUrl": self.invoice_url,
"remark": self.remark,
"createdAt": _iso(self.created_at),
"issuedAt": _iso(self.issued_at),
}
@@ -408,6 +519,9 @@ class User(Base):
avatar_url = Column(String, default="")
huihui_token = Column(String, default="") # 会会 access_token
app_token = Column(String, default="") # 本系统会话 token
wechat_mp_openid = Column(String, default="", index=True)
# 微信 session_key 仅保存在服务端,用于虚拟支付用户态签名,绝不下发客户端。
wechat_mp_session_key = Column(String, default="")
last_login_at = Column(DateTime)
created_at = Column(DateTime, server_default=func.now())
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())