fix: 金额/算力/信用额度列 int→bigint,修复充值 Out of range 500(compute_quota 等 43 列)+ alembic 0077
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
"""0077 金额/算力/信用额度列 int → bigint(杜绝 Out of range 溢出)
|
||||
|
||||
覆盖全部金额、算力额度、信用积分列(含 raw SQL 表,无 ORM 模型者一并处理)。
|
||||
Revision ID: 0077
|
||||
Revises: 0076
|
||||
Create Date: 2026-09-10
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
revision = "0077"
|
||||
down_revision = "0076"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
# (表, 列):opc 库中所有金额/算力/信用积分列
|
||||
COLUMNS = [
|
||||
("users", "compute_quota"),
|
||||
("users", "compute_used_quota"),
|
||||
("users", "compute_personal_balance"),
|
||||
("park_companies", "compute_quota"),
|
||||
("park_companies", "compute_quota_used"),
|
||||
("park_companies", "compute_balance"),
|
||||
("park_companies", "compute_balance_used"),
|
||||
("company_members", "compute_balance"),
|
||||
("company_members", "compute_balance_used"),
|
||||
("compute_recharges", "amount"),
|
||||
("compute_recharges", "compute_amount"),
|
||||
("compute_balance_allocations", "amount"),
|
||||
("compute_usage_records", "standard_price"),
|
||||
("compute_usage_records", "actual_amount"),
|
||||
("compute_recharge_orders", "amount_fen"),
|
||||
("compute_recharge_orders", "quota_micro"),
|
||||
("compute_recharge_orders", "bonus_quota_micro"),
|
||||
("market_items", "price_fen"),
|
||||
("market_purchase_orders", "amount_fen"),
|
||||
("market_purchases", "amount_fen"),
|
||||
("event_orders", "amount_fen"),
|
||||
("events", "price_fen"),
|
||||
("opc_services", "price"),
|
||||
("service_orders", "price"),
|
||||
("service_orders", "amount_cents"),
|
||||
("service_orders", "platform_fee_cents"),
|
||||
("service_orders", "refund_amount_cents"),
|
||||
("service_orders", "seller_income_cents"),
|
||||
("settlement_logs", "amount"),
|
||||
("certification_types", "fee"),
|
||||
("certification_types", "credit_points"),
|
||||
("certifications", "fee_amount"),
|
||||
("certifications", "credit_points"),
|
||||
("training_courses", "price"),
|
||||
("training_course_enrollments", "price_paid"),
|
||||
("subsidy_applications", "amount"),
|
||||
("escrows", "amount"),
|
||||
("invoices", "amount"),
|
||||
("finance_records", "amount"),
|
||||
("investor_preferences", "amount_min"),
|
||||
("investor_preferences", "amount_max"),
|
||||
("badges", "credit_bonus"),
|
||||
("credit_ledger", "balance"),
|
||||
]
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
conn = op.get_bind()
|
||||
for table, col in COLUMNS:
|
||||
# 幂等:仅当列存在且为 int 时才改
|
||||
row = conn.execute(sa.text(
|
||||
"SELECT COLUMN_TYPE, IS_NULLABLE, IFNULL(COLUMN_DEFAULT,'') FROM information_schema.COLUMNS "
|
||||
"WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=:t AND COLUMN_NAME=:c"
|
||||
), {"t": table, "c": col}).fetchone()
|
||||
if not row:
|
||||
continue
|
||||
col_type, nullable, default = row
|
||||
if col_type.lower().startswith("bigint"):
|
||||
continue
|
||||
nn = "" if nullable == "YES" else " NOT NULL"
|
||||
dflt = ""
|
||||
if default == "0":
|
||||
dflt = " DEFAULT 0"
|
||||
conn.execute(sa.text(
|
||||
f"ALTER TABLE `{table}` MODIFY COLUMN `{col}` BIGINT{nn}{dflt}"
|
||||
))
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
# 金额列不降级回 int(历史溢出风险,且不可逆恢复成本高)
|
||||
pass
|
||||
@@ -10,6 +10,7 @@ from __future__ import annotations
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
from sqlalchemy import (
|
||||
BigInteger,
|
||||
Boolean,
|
||||
Float,
|
||||
ForeignKey,
|
||||
@@ -74,10 +75,10 @@ class User(Base):
|
||||
# ── 算力(引擎用户镜像,全局一致) ──
|
||||
compute_provisioned: Mapped[bool] = mapped_column(Boolean, default=False) # 是否已在算力引擎建号
|
||||
compute_username: Mapped[str] = mapped_column(String, default="") # 引擎用户名(= username)
|
||||
compute_quota: Mapped[int] = mapped_column(Integer, default=0) # 缓存引擎可用额度
|
||||
compute_used_quota: Mapped[int] = mapped_column(Integer, default=0) # 缓存引擎已用额度
|
||||
compute_quota: Mapped[int] = mapped_column(BigInteger, default=0) # 缓存引擎可用额度
|
||||
compute_used_quota: Mapped[int] = mapped_column(BigInteger, default=0) # 缓存引擎已用额度
|
||||
# ── 个人算力余额(分;个人充值/企业转入,与 company_members.compute_balance 企业分配分离) ──
|
||||
compute_personal_balance: Mapped[int] = mapped_column(Integer, default=0) # 个人充值/转入余额(分)
|
||||
compute_personal_balance: Mapped[int] = mapped_column(BigInteger, default=0) # 个人充值/转入余额(分)
|
||||
# ── 状态与身份分类 ──
|
||||
certification_status: Mapped[str] = mapped_column(String, default="uncertified") # uncertified|pending|certified|rejected
|
||||
certification_time: Mapped[str] = mapped_column(String, default="")
|
||||
@@ -542,8 +543,8 @@ class InvestorPreference(Base):
|
||||
)
|
||||
industries: Mapped[str] = mapped_column(String, default="[]") # JSON list
|
||||
stage: Mapped[str] = mapped_column(String, default="") # seed/angel/series_a/...
|
||||
amount_min: Mapped[int] = mapped_column(Integer, default=0)
|
||||
amount_max: Mapped[int] = mapped_column(Integer, default=0)
|
||||
amount_min: Mapped[int] = mapped_column(BigInteger, default=0)
|
||||
amount_max: Mapped[int] = mapped_column(BigInteger, default=0)
|
||||
region_id: Mapped[str | None] = mapped_column(ForeignKey("regions.id"), nullable=True)
|
||||
updated_at: Mapped[str] = mapped_column(String, default="")
|
||||
|
||||
@@ -645,7 +646,7 @@ class SubsidyApplication(Base):
|
||||
opc_id: Mapped[str] = mapped_column(String, default="")
|
||||
opc_name: Mapped[str] = mapped_column(String, default="")
|
||||
title: Mapped[str] = mapped_column(String, default="")
|
||||
amount: Mapped[int] = mapped_column(Integer, default=0)
|
||||
amount: Mapped[int] = mapped_column(BigInteger, default=0)
|
||||
region_id: Mapped[str | None] = mapped_column(ForeignKey("regions.id"), nullable=True)
|
||||
status: Mapped[str] = mapped_column(String, default="applying") # applying/district_review/city_review/province_review/approved/paid/rejected
|
||||
comment: Mapped[str] = mapped_column(String, default="")
|
||||
@@ -714,7 +715,7 @@ class Escrow(Base):
|
||||
ForeignKey("tasks.id", ondelete="CASCADE"), nullable=False,
|
||||
)
|
||||
task_title: Mapped[str] = mapped_column(String, default="")
|
||||
amount: Mapped[int] = mapped_column(Integer, default=0)
|
||||
amount: Mapped[int] = mapped_column(BigInteger, default=0)
|
||||
commission: Mapped[int] = mapped_column(Integer, default=0) # 平台佣金
|
||||
status: Mapped[str] = mapped_column(String, default="deposited") # deposited/frozen/released/refunded
|
||||
# ── 微信服务商分账(资金托管)字段 ──
|
||||
@@ -854,7 +855,7 @@ class Invoice(Base):
|
||||
issuer_id: Mapped[str] = mapped_column(String, default="") # 开票方(接单人)
|
||||
issuer_name: Mapped[str] = mapped_column(String, default="")
|
||||
payer_name: Mapped[str] = mapped_column(String, default="") # 抬头(发包方)
|
||||
amount: Mapped[int] = mapped_column(Integer, default=0)
|
||||
amount: Mapped[int] = mapped_column(BigInteger, default=0)
|
||||
tax_rate: Mapped[float] = mapped_column(Float, default=0.01)
|
||||
invoice_type: Mapped[str] = mapped_column(String, default="personal") # personal/vat
|
||||
status: Mapped[str] = mapped_column(String, default="applied") # applied/issued/rejected
|
||||
@@ -927,7 +928,7 @@ class FinanceRecord(Base):
|
||||
ForeignKey("users.id", ondelete="CASCADE"), nullable=False,
|
||||
)
|
||||
category: Mapped[str] = mapped_column(String, default="income") # income | expense
|
||||
amount: Mapped[int] = mapped_column(Integer, default=0)
|
||||
amount: Mapped[int] = mapped_column(BigInteger, default=0)
|
||||
date: Mapped[str] = mapped_column(String, default="") # YYYY-MM-DD
|
||||
note: Mapped[str] = mapped_column(String, default="")
|
||||
created_at: Mapped[str] = mapped_column(String, default="")
|
||||
@@ -1189,13 +1190,13 @@ class ParkCompany(Base):
|
||||
emp_migrant: Mapped[int | None] = mapped_column(Integer, nullable=True) # 返乡农民工
|
||||
# 企业算力(只增不减):折扣% off 模型价;配额为发放给成员的算力额度
|
||||
compute_discount: Mapped[int] = mapped_column(Integer, default=0) # 折扣%(0-100,单调非降)
|
||||
compute_quota: Mapped[int] = mapped_column(Integer, default=0) # 企业算力配额(单调非降/增量)
|
||||
compute_quota_used: Mapped[int] = mapped_column(Integer, default=0) # 已分配/已用配额(统计)
|
||||
compute_quota: Mapped[int] = mapped_column(BigInteger, default=0) # 企业算力配额(单调非降/增量)
|
||||
compute_quota_used: Mapped[int] = mapped_column(BigInteger, default=0) # 已分配/已用配额(统计)
|
||||
engine_group: Mapped[str] = mapped_column(String, default="") # 引擎用户组名(折扣倍率载体)
|
||||
owner_user_id: Mapped[str] = mapped_column(String, default="") # 负责人/管理员账号id(必填)
|
||||
# ── 企业算力余额(企业管理员充值后分配给成员,0056) ──
|
||||
compute_balance: Mapped[int] = mapped_column(Integer, default=0) # 企业算力余额(分)
|
||||
compute_balance_used: Mapped[int] = mapped_column(Integer, default=0) # 已分配给成员的余额(分)
|
||||
compute_balance: Mapped[int] = mapped_column(BigInteger, default=0) # 企业算力余额(分)
|
||||
compute_balance_used: Mapped[int] = mapped_column(BigInteger, default=0) # 已分配给成员的余额(分)
|
||||
created_at: Mapped[str] = mapped_column(String, default="")
|
||||
|
||||
|
||||
@@ -1344,8 +1345,8 @@ class CompanyMember(Base):
|
||||
role: Mapped[str] = mapped_column(String, default="staff") # 企业内角色(admin/finance/hr/staff,0056)
|
||||
status: Mapped[str] = mapped_column(String, default="active") # active/left
|
||||
# ── 成员算力余额(从企业分配,0056) ──
|
||||
compute_balance: Mapped[int] = mapped_column(Integer, default=0) # 成员个人余额(分)
|
||||
compute_balance_used: Mapped[int] = mapped_column(Integer, default=0) # 已使用余额(分)
|
||||
compute_balance: Mapped[int] = mapped_column(BigInteger, default=0) # 成员个人余额(分)
|
||||
compute_balance_used: Mapped[int] = mapped_column(BigInteger, default=0) # 已使用余额(分)
|
||||
# ── 退出企业(0056) ──
|
||||
left_at: Mapped[str] = mapped_column(String, default="") # 退出时间
|
||||
left_reason: Mapped[str] = mapped_column(String, default="") # 退出原因
|
||||
@@ -1393,8 +1394,8 @@ class ComputeRecharge(Base):
|
||||
id: Mapped[str] = mapped_column(String, primary_key=True)
|
||||
company_id: Mapped[str] = mapped_column(String, default="", index=True) # 企业充值时填写
|
||||
user_id: Mapped[str] = mapped_column(String, default="", index=True) # 个人充值时填写
|
||||
amount: Mapped[int] = mapped_column(Integer, default=0) # 充值金额(分)
|
||||
compute_amount: Mapped[int] = mapped_column(Integer, default=0) # 到账算力(分)
|
||||
amount: Mapped[int] = mapped_column(BigInteger, default=0) # 充值金额(分)
|
||||
compute_amount: Mapped[int] = mapped_column(BigInteger, default=0) # 到账算力(分)
|
||||
payment_method: Mapped[str] = mapped_column(String, default="")
|
||||
payment_status: Mapped[str] = mapped_column(String, default="pending") # pending/paid/failed
|
||||
transaction_id: Mapped[str] = mapped_column(String, default="")
|
||||
@@ -1410,7 +1411,7 @@ class ComputeBalanceAllocation(Base):
|
||||
company_id: Mapped[str] = mapped_column(String, index=True)
|
||||
from_user_id: Mapped[str] = mapped_column(String, default="") # 分配人(企业管理员)
|
||||
to_user_id: Mapped[str] = mapped_column(String, index=True) # 接收成员
|
||||
amount: Mapped[int] = mapped_column(Integer, default=0) # 分配金额(分)
|
||||
amount: Mapped[int] = mapped_column(BigInteger, default=0) # 分配金额(分)
|
||||
type: Mapped[str] = mapped_column(String, default="allocate") # allocate/reclaim(分配/回收)
|
||||
reason: Mapped[str] = mapped_column(Text, default="")
|
||||
created_at: Mapped[str] = mapped_column(String, default="")
|
||||
@@ -1424,10 +1425,10 @@ class ComputeUsageRecord(Base):
|
||||
company_id: Mapped[str] = mapped_column(String, default="", index=True) # 从企业余额扣费时填写
|
||||
model: Mapped[str] = mapped_column(String, default="")
|
||||
token_count: Mapped[int] = mapped_column(Integer, default=0)
|
||||
standard_price: Mapped[int] = mapped_column(Integer, default=0) # 标准价(分)
|
||||
standard_price: Mapped[int] = mapped_column(BigInteger, default=0) # 标准价(分)
|
||||
discount: Mapped[int] = mapped_column(Integer, default=0) # 实际折扣(0-100)
|
||||
discount_source: Mapped[str] = mapped_column(String, default="standard") # standard/tenant/company/tenant_user
|
||||
actual_amount: Mapped[int] = mapped_column(Integer, default=0) # 实际扣费(分)
|
||||
actual_amount: Mapped[int] = mapped_column(BigInteger, default=0) # 实际扣费(分)
|
||||
balance_source: Mapped[str] = mapped_column(String, default="personal") # company/personal
|
||||
created_at: Mapped[str] = mapped_column(String, default="")
|
||||
|
||||
@@ -1484,7 +1485,7 @@ class OpcService(Base):
|
||||
description: Mapped[str] = mapped_column(Text, default="")
|
||||
cover: Mapped[str] = mapped_column(String, default="")
|
||||
gallery_json: Mapped[str] = mapped_column(Text, default="[]") # 作品集 URL 数组
|
||||
price: Mapped[int] = mapped_column(Integer, default=0) # 定价(元,0=面议)
|
||||
price: Mapped[int] = mapped_column(BigInteger, default=0) # 定价(元,0=面议)
|
||||
delivery_days: Mapped[int] = mapped_column(Integer, default=0) # 交付时限(天)
|
||||
tags: Mapped[str] = mapped_column(String, default="")
|
||||
status: Mapped[str] = mapped_column(String, default="pending") # pending/published/offline/hidden
|
||||
@@ -1618,7 +1619,7 @@ class MarketItem(Base):
|
||||
bundle_json: Mapped[str] = mapped_column(Text, default="{}") # 安装包元数据(skill 内嵌完整 SKILL.md;MySQL 已 ALTER 为 MEDIUMTEXT)
|
||||
bundle_url: Mapped[str] = mapped_column(String, default="") # OSS 对象路径(plugin/app zip)
|
||||
bundle_sha256: Mapped[str] = mapped_column(String, default="")
|
||||
price_fen: Mapped[int] = mapped_column(Integer, default=0) # 定价(分);0=免费(skill 恒 0)
|
||||
price_fen: Mapped[int] = mapped_column(BigInteger, default=0) # 定价(分);0=免费(skill 恒 0)
|
||||
stats_json: Mapped[str] = mapped_column(Text, default="{}") # {"downloads":0,"views":0,"likes":0}
|
||||
is_featured: Mapped[int] = mapped_column(Integer, default=0)
|
||||
status: Mapped[str] = mapped_column(String, default="draft", index=True) # draft|pending|published|rejected|offline
|
||||
@@ -1663,7 +1664,7 @@ class MarketPurchaseOrder(Base):
|
||||
item_name: Mapped[str] = mapped_column(String, default="")
|
||||
user_id: Mapped[str] = mapped_column(String, default="", index=True)
|
||||
username: Mapped[str] = mapped_column(String, default="")
|
||||
amount_fen: Mapped[int] = mapped_column(Integer, default=0) # 实付金额(分)
|
||||
amount_fen: Mapped[int] = mapped_column(BigInteger, default=0) # 实付金额(分)
|
||||
client_type: Mapped[str] = mapped_column(String, default="mp") # mp(小程序码) | jsapi | native
|
||||
appid: Mapped[str] = mapped_column(String, default="")
|
||||
status: Mapped[str] = mapped_column(String, default="pending", index=True)
|
||||
@@ -1689,7 +1690,7 @@ class MarketPurchase(Base):
|
||||
user_id: Mapped[str] = mapped_column(String, default="", index=True)
|
||||
item_id: Mapped[str] = mapped_column(String, default="", index=True)
|
||||
item_type: Mapped[str] = mapped_column(String, default="plugin")
|
||||
amount_fen: Mapped[int] = mapped_column(Integer, default=0)
|
||||
amount_fen: Mapped[int] = mapped_column(BigInteger, default=0)
|
||||
order_no: Mapped[str] = mapped_column(String, default="")
|
||||
created_at: Mapped[str] = mapped_column(String, default="")
|
||||
|
||||
@@ -1709,7 +1710,7 @@ class ServiceOrder(Base):
|
||||
buyer_name: Mapped[str] = mapped_column(String, default="")
|
||||
contact: Mapped[str] = mapped_column(String, default="")
|
||||
schedule_at: Mapped[str] = mapped_column(String, default="") # 预约时间
|
||||
price: Mapped[int] = mapped_column(Integer, default=0) # 成交价(元,0=按服务定价)
|
||||
price: Mapped[int] = mapped_column(BigInteger, default=0) # 成交价(元,0=按服务定价)
|
||||
note: Mapped[str] = mapped_column(Text, default="")
|
||||
status: Mapped[str] = mapped_column(String, default="pending")
|
||||
accept_at: Mapped[str] = mapped_column(String, default="")
|
||||
@@ -1918,9 +1919,9 @@ class CertificationType(Base):
|
||||
category: Mapped[str] = mapped_column(String, default="personal") # personal/enterprise/opc_talent/skill
|
||||
name: Mapped[str] = mapped_column(String, default="")
|
||||
description: Mapped[str] = mapped_column(Text, default="")
|
||||
fee: Mapped[int] = mapped_column(Integer, default=0) # 分,0=免费
|
||||
fee: Mapped[int] = mapped_column(BigInteger, default=0) # 分,0=免费
|
||||
validity_days: Mapped[int] = mapped_column(Integer, default=0) # 0=永久
|
||||
credit_points: Mapped[int] = mapped_column(Integer, default=0)
|
||||
credit_points: Mapped[int] = mapped_column(BigInteger, default=0)
|
||||
levels_json: Mapped[str] = mapped_column(Text, default="[]") # 等级配置JSON
|
||||
materials_schema: Mapped[str] = mapped_column(Text, default="{}") # 表单JSON Schema
|
||||
review_mode: Mapped[str] = mapped_column(String, default="manual") # auto/manual/hybrid
|
||||
@@ -1948,8 +1949,8 @@ class Certification(Base):
|
||||
# not_started/pending/approved/rejected/active/expiring/expired/revoked
|
||||
materials_json: Mapped[str] = mapped_column(Text, default="{}") # 提交材料(脱敏)
|
||||
score: Mapped[int] = mapped_column(Integer, default=0) # 认证分数(技能测试用)
|
||||
credit_points: Mapped[int] = mapped_column(Integer, default=0) # 获得的信用加分
|
||||
fee_amount: Mapped[int] = mapped_column(Integer, default=0) # 费用(分)
|
||||
credit_points: Mapped[int] = mapped_column(BigInteger, default=0) # 获得的信用加分
|
||||
fee_amount: Mapped[int] = mapped_column(BigInteger, default=0) # 费用(分)
|
||||
payment_id: Mapped[str] = mapped_column(String, default="")
|
||||
submitted_at: Mapped[str] = mapped_column(String, default="")
|
||||
approved_at: Mapped[str] = mapped_column(String, default="")
|
||||
@@ -2002,7 +2003,7 @@ class TrainingCourse(Base):
|
||||
# ui_design/graphic_design/frontend_dev/backend_dev/copywriting/translation/data_analysis/project_management
|
||||
level: Mapped[str] = mapped_column(String, default="beginner")
|
||||
# beginner/intermediate/advanced/expert
|
||||
price: Mapped[int] = mapped_column(Integer, default=0) # 分,0=免费
|
||||
price: Mapped[int] = mapped_column(BigInteger, default=0) # 分,0=免费
|
||||
duration_minutes: Mapped[int] = mapped_column(Integer, default=0)
|
||||
lesson_count: Mapped[int] = mapped_column(Integer, default=0)
|
||||
chapter_count: Mapped[int] = mapped_column(Integer, default=0)
|
||||
@@ -2069,7 +2070,7 @@ class TrainingCourseEnrollment(Base):
|
||||
total_watch_seconds: Mapped[int] = mapped_column(Integer, default=0)
|
||||
enrolled_at: Mapped[str] = mapped_column(String, default="")
|
||||
completed_at: Mapped[str] = mapped_column(String, default="")
|
||||
price_paid: Mapped[int] = mapped_column(Integer, default=0)
|
||||
price_paid: Mapped[int] = mapped_column(BigInteger, default=0)
|
||||
created_at: Mapped[str] = mapped_column(String, default="")
|
||||
|
||||
|
||||
@@ -2249,7 +2250,7 @@ class CreditLedger(Base):
|
||||
event_code: Mapped[str] = mapped_column(String, default="", index=True)
|
||||
dimension: Mapped[str] = mapped_column(String, default="system")
|
||||
delta: Mapped[int] = mapped_column(Integer, default=0)
|
||||
balance: Mapped[int] = mapped_column(Integer, default=0)
|
||||
balance: Mapped[int] = mapped_column(BigInteger, default=0)
|
||||
reason: Mapped[str] = mapped_column(String, default="")
|
||||
ref_type: Mapped[str] = mapped_column(String, default="")
|
||||
ref_id: Mapped[str] = mapped_column(String, default="")
|
||||
@@ -2288,7 +2289,7 @@ class Badge(Base):
|
||||
description: Mapped[str] = mapped_column(String, default="")
|
||||
condition: Mapped[str] = mapped_column(String, default="")
|
||||
grant_rule_json: Mapped[str] = mapped_column(Text, default="{}")
|
||||
credit_bonus: Mapped[int] = mapped_column(Integer, default=0)
|
||||
credit_bonus: Mapped[int] = mapped_column(BigInteger, default=0)
|
||||
lifetime: Mapped[int] = mapped_column(Integer, default=1)
|
||||
revocable: Mapped[int] = mapped_column(Integer, default=1)
|
||||
expiry_days: Mapped[int] = mapped_column(Integer, default=0)
|
||||
@@ -2492,4 +2493,4 @@ class TeamMember(Base):
|
||||
role: Mapped[str] = mapped_column(String, default="member") # owner/admin/member
|
||||
status: Mapped[str] = mapped_column(String, default="active") # active/left
|
||||
created_at: Mapped[str] = mapped_column(String, default="")
|
||||
left_at: Mapped[str] = mapped_column(String, default="")
|
||||
left_at: Mapped[str] = mapped_column(String, default="")
|
||||
Reference in New Issue
Block a user