feat(db): P1 Alembic+模型整合 — 唯一总库基线迁移 + 培训/园区 ORM 模型

- 新增 alembic(ini/env async/script.mako/versions/0001_initial)。
- models.py 并入培训表(training_accounts/events/bookings/tests/courses/policy/plan/survey_logs)
  与园区表(park_tenants/companies/kb_docs/screens),与平台同库、命名加域前缀避免撞名。
- baseline 迁移用 create_all(幂等):既有平台表保留,新增培训/园区表被建。
- 验证:对临时库 uv run alembic upgrade head 建出全部新表。
This commit is contained in:
Pine
2026-08-24 19:28:18 +08:00
parent c4fb4fb498
commit 8b0bca36a1
7 changed files with 372 additions and 0 deletions
+185
View File
@@ -579,3 +579,188 @@ class UserIdentity(Base):
status: Mapped[str] = mapped_column(String, default="active") # active | disabled
created_at: Mapped[str] = mapped_column(String, default="")
updated_at: Mapped[str] = mapped_column(String, default="")
# ===========================================================================
# 培训业务子应用(原 app/training 独立 opc.db → 并入唯一总库)
# ===========================================================================
class TrainingAccount(Base):
"""培训站账号(原 accounts,含手机/微信登录)。"""
__tablename__ = "training_accounts"
id: Mapped[str] = mapped_column(String, primary_key=True)
username: Mapped[str] = mapped_column(String, unique=True, nullable=False)
wxid: Mapped[str] = mapped_column(String, default="")
phone: Mapped[str] = mapped_column(String, default="")
contact: Mapped[str] = mapped_column(String, default="")
name: Mapped[str] = mapped_column(String, default="")
avatar: Mapped[str] = mapped_column(String, default="")
password: Mapped[str] = mapped_column(String, default="")
phone_bound: Mapped[int] = mapped_column(Integer, default=0)
identities: Mapped[str] = mapped_column(Text, default="[]")
status_label: Mapped[str] = mapped_column(String, default="")
topics: Mapped[str] = mapped_column(Text, default="")
source: Mapped[str] = mapped_column(String, default="")
created_at: Mapped[str] = mapped_column(String, default="")
class Event(Base):
__tablename__ = "training_events"
id: Mapped[str] = mapped_column(String, primary_key=True)
type: Mapped[str] = mapped_column(String, default="")
mode: Mapped[str] = mapped_column(String, default="offline")
title: Mapped[str] = mapped_column(String, default="")
subtitle: Mapped[str] = mapped_column(String, default="")
desc: Mapped[str] = mapped_column(Text, default="")
location: Mapped[str] = mapped_column(String, default="")
host: Mapped[str] = mapped_column(String, default="")
image: Mapped[str] = mapped_column(String, default="")
link: Mapped[str] = mapped_column(String, default="")
start_at: Mapped[str] = mapped_column(String, default="")
end_at: Mapped[str] = mapped_column(String, default="")
checkin_at: Mapped[str] = mapped_column(String, default="")
duration_min: Mapped[int] = mapped_column(Integer, default=90)
capacity: Mapped[int] = mapped_column(Integer, default=0)
show_capacity: Mapped[int] = mapped_column(Integer, default=0)
audit_mode: Mapped[str] = mapped_column(String, default="auto")
status: Mapped[str] = mapped_column(String, default="open")
class Booking(Base):
__tablename__ = "training_bookings"
id: Mapped[str] = mapped_column(String, primary_key=True)
created_at: Mapped[str] = mapped_column(String, default="")
status: Mapped[str] = mapped_column(String, default="pending")
audit_status: Mapped[str] = mapped_column(String, default="pending")
username: Mapped[str] = mapped_column(String, default="")
name: Mapped[str] = mapped_column(String, default="")
contact: Mapped[str] = mapped_column(String, default="")
status_label: Mapped[str] = mapped_column(String, default="")
want: Mapped[str] = mapped_column(Text, default="")
event_id: Mapped[str] = mapped_column(String, default="")
event_title: Mapped[str] = mapped_column(String, default="")
event_start: Mapped[str] = mapped_column(String, default="")
topics: Mapped[str] = mapped_column(Text, default="")
question: Mapped[str] = mapped_column(Text, default="")
source: Mapped[str] = mapped_column(String, default="")
checkin_at: Mapped[str] = mapped_column(String, default="")
class Test(Base):
__tablename__ = "training_tests"
id: Mapped[str] = mapped_column(String, primary_key=True)
created_at: Mapped[str] = mapped_column(String, default="")
username: Mapped[str] = mapped_column(String, default="")
type_code: Mapped[str] = mapped_column(String, default="")
persona: Mapped[str] = mapped_column(String, default="")
adapt_index: Mapped[int] = mapped_column(Integer, default=0)
adapt_level: Mapped[str] = mapped_column(String, default="")
tracks: Mapped[str] = mapped_column(Text, default="")
version: Mapped[str] = mapped_column(String, default="")
class Course(Base):
__tablename__ = "training_courses"
id: Mapped[str] = mapped_column(String, primary_key=True)
category: Mapped[str] = mapped_column(String, default="")
level: Mapped[str] = mapped_column(String, default="")
title: Mapped[str] = mapped_column(String, default="")
subtitle: Mapped[str] = mapped_column(String, default="")
desc: Mapped[str] = mapped_column(Text, default="")
price: Mapped[float] = mapped_column(Float, default=0.0)
status: Mapped[str] = mapped_column(String, default="draft")
start_at: Mapped[str] = mapped_column(String, default="")
end_at: Mapped[str] = mapped_column(String, default="")
venue: Mapped[str] = mapped_column(String, default="")
quota: Mapped[int] = mapped_column(Integer, default=0)
image: Mapped[str] = mapped_column(String, default="")
host: Mapped[str] = mapped_column(String, default="")
created_at: Mapped[str] = mapped_column(String, default="")
class PolicyLog(Base):
__tablename__ = "training_policy_logs"
id: Mapped[str] = mapped_column(String, primary_key=True)
created_at: Mapped[str] = mapped_column(String, default="")
username: Mapped[str] = mapped_column(String, default="")
answers: Mapped[str] = mapped_column(Text, default="")
policies_count: Mapped[int] = mapped_column(Integer, default=0)
subsidies_count: Mapped[int] = mapped_column(Integer, default=0)
loans_count: Mapped[int] = mapped_column(Integer, default=0)
summary: Mapped[str] = mapped_column(Text, default="")
class PlanLog(Base):
__tablename__ = "training_plan_logs"
id: Mapped[str] = mapped_column(String, primary_key=True)
created_at: Mapped[str] = mapped_column(String, default="")
username: Mapped[str] = mapped_column(String, default="")
region: Mapped[str] = mapped_column(String, default="")
status: Mapped[str] = mapped_column(String, default="")
need_park: Mapped[int] = mapped_column(Integer, default=0)
has_staff: Mapped[int] = mapped_column(Integer, default=0)
steps_count: Mapped[int] = mapped_column(Integer, default=0)
class SurveyLog(Base):
__tablename__ = "training_survey_logs"
id: Mapped[str] = mapped_column(String, primary_key=True)
created_at: Mapped[str] = mapped_column(String, default="")
username: Mapped[str] = mapped_column(String, default="")
source: Mapped[str] = mapped_column(String, default="")
answers: Mapped[str] = mapped_column(Text, default="")
# ===========================================================================
# 园区子应用(原 app/park 独立 park.db → 并入唯一总库)
# ===========================================================================
class ParkTenant(Base):
__tablename__ = "park_tenants"
id: Mapped[str] = mapped_column(String, primary_key=True)
name: Mapped[str] = mapped_column(String, default="")
intro_json: Mapped[str] = mapped_column(Text, default="[]")
username: Mapped[str] = mapped_column(String, default="")
salt: Mapped[str] = mapped_column(String, default="")
password_hash: Mapped[str] = mapped_column(String, default="")
admin_username: Mapped[str] = mapped_column(String, default="")
status: Mapped[str] = mapped_column(String, default="active")
data_json: Mapped[str] = mapped_column(Text, default="{}")
agent_json: Mapped[str] = mapped_column(Text, default="{}")
created_at: Mapped[str] = mapped_column(String, default="")
class ParkCompany(Base):
__tablename__ = "park_companies"
id: Mapped[str] = mapped_column(String, primary_key=True)
tenant_id: Mapped[str] = mapped_column(ForeignKey("park_tenants.id", ondelete="CASCADE"), nullable=False, index=True)
name: Mapped[str] = mapped_column(String, default="")
zone: Mapped[str] = mapped_column(String, default="")
room: Mapped[str] = mapped_column(String, default="")
industry: Mapped[str] = mapped_column(String, default="")
bio: Mapped[str] = mapped_column(Text, default="")
founder: Mapped[str] = mapped_column(String, default="")
status: Mapped[str] = mapped_column(String, default="applying")
employees: Mapped[int | None] = mapped_column(Integer, nullable=True)
created_at: Mapped[str] = mapped_column(String, default="")
class ParkKbDoc(Base):
__tablename__ = "park_kb_docs"
id: Mapped[str] = mapped_column(String, primary_key=True)
tenant_id: Mapped[str] = mapped_column(ForeignKey("park_tenants.id", ondelete="CASCADE"), nullable=False, index=True)
grp: Mapped[str] = mapped_column(String, default="general")
title: Mapped[str] = mapped_column(String, default="")
content_md: Mapped[str] = mapped_column(Text, default="")
created_at: Mapped[str] = mapped_column(String, default="")
class ParkScreen(Base):
__tablename__ = "park_screens"
id: Mapped[str] = mapped_column(String, primary_key=True)
tenant_id: Mapped[str] = mapped_column(ForeignKey("park_tenants.id", ondelete="CASCADE"), nullable=False, index=True)
device_id: Mapped[str] = mapped_column(String, default="")
name: Mapped[str] = mapped_column(String, default="")
role: Mapped[str] = mapped_column(String, default="main")
location: Mapped[str] = mapped_column(String, default="")
created_at: Mapped[str] = mapped_column(String, default="")