| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618 |
- """创建DMS七张核心表。
- Revision ID: 0001_initial_schema
- Revises:
- Create Date: 2026-07-23
- """
- from __future__ import annotations
- from collections.abc import Sequence
- from alembic import op
- import sqlalchemy as sa
- from sqlalchemy.dialects import mysql
- revision: str = "0001_initial_schema"
- down_revision: str | None = None
- branch_labels: str | Sequence[str] | None = None
- depends_on: str | Sequence[str] | None = None
- def _business_columns() -> list[sa.Column]:
- return [
- sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
- sa.Column("created_by", sa.BigInteger(), nullable=True),
- sa.Column("updated_by", sa.BigInteger(), nullable=True),
- sa.Column(
- "created_at",
- mysql.DATETIME(fsp=3),
- server_default=sa.text("CURRENT_TIMESTAMP(3)"),
- nullable=False,
- ),
- sa.Column(
- "updated_at",
- mysql.DATETIME(fsp=3),
- server_default=sa.text("CURRENT_TIMESTAMP(3)"),
- nullable=False,
- ),
- sa.Column("deleted_at", mysql.DATETIME(fsp=3), nullable=True),
- sa.Column(
- "is_deleted",
- sa.Boolean(),
- server_default=sa.text("0"),
- nullable=False,
- ),
- sa.Column(
- "row_version",
- sa.Integer(),
- server_default=sa.text("0"),
- nullable=False,
- ),
- sa.PrimaryKeyConstraint("id"),
- ]
- def upgrade() -> None:
- op.create_table(
- "sys_organization",
- *_business_columns(),
- sa.Column("parent_id", sa.BigInteger(), nullable=True),
- sa.Column("org_code", sa.String(length=64), nullable=False),
- sa.Column("org_name", sa.String(length=128), nullable=False),
- sa.Column("org_path", sa.String(length=1000), nullable=False),
- sa.Column(
- "sort_no",
- sa.Integer(),
- server_default=sa.text("0"),
- nullable=False,
- ),
- sa.Column(
- "status",
- sa.String(length=20),
- server_default=sa.text("'ENABLED'"),
- nullable=False,
- ),
- sa.CheckConstraint(
- "status IN ('ENABLED', 'DISABLED')",
- name="organization_status",
- ),
- sa.ForeignKeyConstraint(
- ["parent_id"],
- ["sys_organization.id"],
- name="fk_sys_organization_parent_id_sys_organization",
- ondelete="RESTRICT",
- ),
- sa.UniqueConstraint("org_code", name="uq_sys_organization_org_code"),
- )
- op.create_index(
- "ix_sys_organization_parent_active_sort",
- "sys_organization",
- ["parent_id", "is_deleted", "sort_no"],
- )
- op.create_index(
- "ix_sys_organization_status_active",
- "sys_organization",
- ["status", "is_deleted"],
- )
- op.create_table(
- "sys_user",
- *_business_columns(),
- sa.Column("username", sa.String(length=64), nullable=False),
- sa.Column("password_hash", sa.String(length=255), nullable=False),
- sa.Column("real_name", sa.String(length=64), nullable=False),
- sa.Column("organization_id", sa.BigInteger(), nullable=True),
- sa.Column("organization_name", sa.String(length=128), nullable=True),
- sa.Column(
- "role_code",
- sa.String(length=32),
- server_default=sa.text("'USER'"),
- nullable=False,
- ),
- sa.Column(
- "security_level",
- sa.String(length=32),
- server_default=sa.text("'INTERNAL'"),
- nullable=False,
- ),
- sa.Column(
- "status",
- sa.String(length=20),
- server_default=sa.text("'ENABLED'"),
- nullable=False,
- ),
- sa.Column(
- "auth_version",
- sa.Integer(),
- server_default=sa.text("0"),
- nullable=False,
- ),
- sa.Column("last_login_at", mysql.DATETIME(fsp=3), nullable=True),
- sa.Column("last_login_ip", sa.String(length=64), nullable=True),
- sa.CheckConstraint(
- "role_code IN ('USER', 'ADMIN', 'AUDITOR')",
- name="user_role_code",
- ),
- sa.CheckConstraint(
- "security_level IN "
- "('PUBLIC', 'INTERNAL', 'SECRET', 'CONFIDENTIAL', 'TOP_SECRET')",
- name="user_security_level",
- ),
- sa.CheckConstraint(
- "status IN ('ENABLED', 'DISABLED')",
- name="user_status",
- ),
- sa.ForeignKeyConstraint(
- ["organization_id"],
- ["sys_organization.id"],
- name="fk_sys_user_organization_id_sys_organization",
- ondelete="RESTRICT",
- ),
- sa.UniqueConstraint("username", name="uq_sys_user_username"),
- )
- op.create_index(
- "ix_sys_user_organization_active_status",
- "sys_user",
- ["organization_id", "is_deleted", "status"],
- )
- op.create_index(
- "ix_sys_user_role_status_active",
- "sys_user",
- ["role_code", "status", "is_deleted"],
- )
- op.create_table(
- "doc_category",
- *_business_columns(),
- sa.Column("parent_id", sa.BigInteger(), nullable=True),
- sa.Column("category_code", sa.String(length=64), nullable=False),
- sa.Column("category_name", sa.String(length=128), nullable=False),
- sa.Column(
- "category_type",
- sa.String(length=32),
- server_default=sa.text("'OTHER'"),
- nullable=False,
- ),
- sa.Column("category_path", sa.String(length=1000), nullable=False),
- sa.Column(
- "sort_no",
- sa.Integer(),
- server_default=sa.text("0"),
- nullable=False,
- ),
- sa.Column(
- "document_count",
- sa.Integer(),
- server_default=sa.text("0"),
- nullable=False,
- ),
- sa.Column(
- "status",
- sa.String(length=20),
- server_default=sa.text("'ENABLED'"),
- nullable=False,
- ),
- sa.CheckConstraint(
- "category_type IN ('SCENE', 'STYLE', 'SITUATION', 'VERSION', 'OTHER')",
- name="category_type",
- ),
- sa.CheckConstraint(
- "status IN ('ENABLED', 'DISABLED')",
- name="category_status",
- ),
- sa.ForeignKeyConstraint(
- ["parent_id"],
- ["doc_category.id"],
- name="fk_doc_category_parent_id_doc_category",
- ondelete="RESTRICT",
- ),
- sa.UniqueConstraint("category_code", name="uq_doc_category_category_code"),
- )
- op.create_index(
- "ix_doc_category_parent_active_sort",
- "doc_category",
- ["parent_id", "is_deleted", "sort_no"],
- )
- op.create_index(
- "ix_doc_category_status_active",
- "doc_category",
- ["status", "is_deleted"],
- )
- op.create_index(
- "ix_doc_category_type_active",
- "doc_category",
- ["category_type", "is_deleted"],
- )
- op.create_table(
- "doc_document",
- *_business_columns(),
- sa.Column("document_name", sa.String(length=255), nullable=False),
- sa.Column("summary", sa.Text(), nullable=True),
- sa.Column("document_type", sa.String(length=32), nullable=False),
- sa.Column(
- "document_status",
- sa.String(length=32),
- server_default=sa.text("'DRAFT'"),
- nullable=False,
- ),
- sa.Column(
- "security_level",
- sa.String(length=32),
- server_default=sa.text("'INTERNAL'"),
- nullable=False,
- ),
- sa.Column(
- "visibility_type",
- sa.String(length=32),
- server_default=sa.text("'CUSTOM'"),
- nullable=False,
- ),
- sa.Column("attachment_type", sa.String(length=32), nullable=True),
- sa.Column("category_id", sa.BigInteger(), nullable=True),
- sa.Column("category_name", sa.String(length=128), nullable=True),
- sa.Column("category_path", sa.String(length=1000), nullable=True),
- sa.Column("parent_document_id", sa.BigInteger(), nullable=True),
- sa.Column("root_document_id", sa.BigInteger(), nullable=True),
- sa.Column("tags", mysql.JSON(), nullable=True),
- sa.Column("original_file_name", sa.String(length=255), nullable=False),
- sa.Column("file_relative_path", sa.String(length=1000), nullable=False),
- sa.Column("file_extension", sa.String(length=20), nullable=False),
- sa.Column("mime_type", sa.String(length=128), nullable=True),
- sa.Column(
- "file_size",
- sa.BigInteger(),
- server_default=sa.text("0"),
- nullable=False,
- ),
- sa.Column("file_hash", sa.String(length=64), nullable=False),
- sa.Column(
- "child_count",
- sa.Integer(),
- server_default=sa.text("0"),
- nullable=False,
- ),
- sa.Column(
- "attachment_count",
- sa.Integer(),
- server_default=sa.text("0"),
- nullable=False,
- ),
- sa.Column(
- "view_count",
- sa.BigInteger(),
- server_default=sa.text("0"),
- nullable=False,
- ),
- sa.Column(
- "download_count",
- sa.BigInteger(),
- server_default=sa.text("0"),
- nullable=False,
- ),
- sa.Column("search_text", sa.Text(), nullable=True),
- sa.Column("created_by_name", sa.String(length=64), nullable=True),
- sa.Column("updated_by_name", sa.String(length=64), nullable=True),
- sa.CheckConstraint(
- "document_type IN ('MAIN', 'SUB_PLAN', 'ATTACHMENT')",
- name="document_type",
- ),
- sa.CheckConstraint(
- "document_status IN ('DRAFT', 'PUBLISHED', 'ARCHIVED')",
- name="document_status",
- ),
- sa.CheckConstraint(
- "security_level IN "
- "('PUBLIC', 'INTERNAL', 'SECRET', 'CONFIDENTIAL', 'TOP_SECRET')",
- name="document_security_level",
- ),
- sa.CheckConstraint(
- "visibility_type IN ('ALL_AUTHENTICATED', 'ORGANIZATION', 'CUSTOM')",
- name="document_visibility_type",
- ),
- sa.CheckConstraint(
- "attachment_type IS NULL OR attachment_type IN "
- "('POLICY', 'WORK_STANDARD', 'TABLE', 'DIAGRAM', 'OTHER')",
- name="document_attachment_type",
- ),
- sa.CheckConstraint(
- "("
- "document_type = 'MAIN' "
- "AND parent_document_id IS NULL "
- "AND category_id IS NOT NULL "
- "AND attachment_type IS NULL"
- ") OR ("
- "document_type = 'SUB_PLAN' "
- "AND parent_document_id IS NOT NULL "
- "AND root_document_id IS NOT NULL "
- "AND category_id IS NOT NULL "
- "AND attachment_type IS NULL"
- ") OR ("
- "document_type = 'ATTACHMENT' "
- "AND parent_document_id IS NULL "
- "AND root_document_id IS NULL "
- "AND category_id IS NULL "
- "AND attachment_type IS NOT NULL "
- "AND security_level = 'PUBLIC' "
- "AND visibility_type = 'ALL_AUTHENTICATED'"
- ")",
- name="document_type_shape",
- ),
- sa.ForeignKeyConstraint(
- ["category_id"],
- ["doc_category.id"],
- name="fk_doc_document_category_id_doc_category",
- ondelete="RESTRICT",
- ),
- sa.ForeignKeyConstraint(
- ["parent_document_id"],
- ["doc_document.id"],
- name="fk_doc_document_parent_document_id_doc_document",
- ondelete="RESTRICT",
- ),
- sa.ForeignKeyConstraint(
- ["root_document_id"],
- ["doc_document.id"],
- name="fk_doc_document_root_document_id_doc_document",
- ondelete="RESTRICT",
- ),
- )
- op.create_index(
- "ix_doc_document_type_active_updated",
- "doc_document",
- ["document_type", "is_deleted", "updated_at"],
- )
- op.create_index(
- "ix_doc_document_parent_type_active",
- "doc_document",
- ["parent_document_id", "document_type", "is_deleted"],
- )
- op.create_index(
- "ix_doc_document_root_active",
- "doc_document",
- ["root_document_id", "is_deleted"],
- )
- op.create_index(
- "ix_doc_document_category_active",
- "doc_document",
- ["category_id", "is_deleted"],
- )
- op.create_index(
- "ix_doc_document_status_active",
- "doc_document",
- ["document_status", "is_deleted"],
- )
- op.create_index(
- "ix_doc_document_security_active",
- "doc_document",
- ["security_level", "is_deleted"],
- )
- op.create_index("ix_doc_document_file_hash", "doc_document", ["file_hash"])
- op.create_index(
- "ix_doc_document_creator_active",
- "doc_document",
- ["created_by", "is_deleted"],
- )
- op.create_index(
- "ix_doc_document_attachment_type_active_updated",
- "doc_document",
- ["attachment_type", "is_deleted", "updated_at"],
- )
- op.create_index(
- "ix_doc_document_file_extension_active_updated",
- "doc_document",
- ["file_extension", "is_deleted", "updated_at"],
- )
- op.create_table(
- "doc_attachment_binding",
- *_business_columns(),
- sa.Column("main_document_id", sa.BigInteger(), nullable=False),
- sa.Column("attachment_document_id", sa.BigInteger(), nullable=False),
- sa.Column(
- "sort_no",
- sa.Integer(),
- server_default=sa.text("0"),
- nullable=False,
- ),
- sa.Column(
- "active_marker",
- sa.Integer(),
- sa.Computed("IF(is_deleted = 0, 1, NULL)", persisted=False),
- nullable=True,
- ),
- sa.ForeignKeyConstraint(
- ["attachment_document_id"],
- ["doc_document.id"],
- name="fk_doc_attachment_binding_attachment_document_id_doc_document",
- ondelete="RESTRICT",
- ),
- sa.ForeignKeyConstraint(
- ["main_document_id"],
- ["doc_document.id"],
- name="fk_doc_attachment_binding_main_document_id_doc_document",
- ondelete="RESTRICT",
- ),
- sa.UniqueConstraint(
- "main_document_id",
- "attachment_document_id",
- "active_marker",
- name="uq_doc_attachment_binding_active",
- ),
- )
- op.create_index(
- "ix_doc_attachment_binding_main_active_sort",
- "doc_attachment_binding",
- ["main_document_id", "is_deleted", "sort_no"],
- )
- op.create_index(
- "ix_doc_attachment_binding_attachment_active",
- "doc_attachment_binding",
- ["attachment_document_id", "is_deleted"],
- )
- op.create_table(
- "doc_permission",
- *_business_columns(),
- sa.Column("document_id", sa.BigInteger(), nullable=False),
- sa.Column("subject_type", sa.String(length=20), nullable=False),
- sa.Column("subject_id", sa.BigInteger(), nullable=False),
- sa.Column("subject_name", sa.String(length=255), nullable=False),
- sa.Column(
- "can_view",
- sa.Boolean(),
- server_default=sa.text("1"),
- nullable=False,
- ),
- sa.Column(
- "can_download",
- sa.Boolean(),
- server_default=sa.text("0"),
- nullable=False,
- ),
- sa.Column(
- "can_edit",
- sa.Boolean(),
- server_default=sa.text("0"),
- nullable=False,
- ),
- sa.Column(
- "can_manage_permission",
- sa.Boolean(),
- server_default=sa.text("0"),
- nullable=False,
- ),
- sa.Column(
- "can_delete",
- sa.Boolean(),
- server_default=sa.text("0"),
- nullable=False,
- ),
- sa.Column(
- "active_marker",
- sa.Integer(),
- sa.Computed("IF(is_deleted = 0, 1, NULL)", persisted=False),
- nullable=True,
- ),
- sa.CheckConstraint(
- "subject_type IN ('ORG', 'USER')",
- name="permission_subject_type",
- ),
- sa.ForeignKeyConstraint(
- ["document_id"],
- ["doc_document.id"],
- name="fk_doc_permission_document_id_doc_document",
- ondelete="RESTRICT",
- ),
- sa.UniqueConstraint(
- "document_id",
- "subject_type",
- "subject_id",
- "active_marker",
- name="uq_doc_permission_active",
- ),
- )
- op.create_index(
- "ix_doc_permission_document_active",
- "doc_permission",
- ["document_id", "is_deleted"],
- )
- op.create_index(
- "ix_doc_permission_subject_active",
- "doc_permission",
- ["subject_type", "subject_id", "is_deleted"],
- )
- op.create_table(
- "sys_audit_log",
- sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
- sa.Column("user_id", sa.BigInteger(), nullable=True),
- sa.Column("username", sa.String(length=64), nullable=True),
- sa.Column("real_name", sa.String(length=64), nullable=True),
- sa.Column("organization_id", sa.BigInteger(), nullable=True),
- sa.Column("organization_name", sa.String(length=128), nullable=True),
- sa.Column("action_type", sa.String(length=32), nullable=False),
- sa.Column("target_type", sa.String(length=32), nullable=True),
- sa.Column("target_id", sa.BigInteger(), nullable=True),
- sa.Column("target_name", sa.String(length=255), nullable=True),
- sa.Column("operation_result", sa.String(length=20), nullable=False),
- sa.Column("failure_reason", sa.String(length=1000), nullable=True),
- sa.Column("client_ip", sa.String(length=64), nullable=True),
- sa.Column("user_agent", sa.String(length=500), nullable=True),
- sa.Column("request_id", sa.String(length=64), nullable=True),
- sa.Column("operation_detail", mysql.JSON(), nullable=True),
- sa.Column(
- "created_at",
- mysql.DATETIME(fsp=3),
- server_default=sa.text("CURRENT_TIMESTAMP(3)"),
- nullable=False,
- ),
- sa.CheckConstraint(
- "action_type IN ("
- "'LOGIN', 'LOGOUT', 'VIEW_DOCUMENT', 'DOWNLOAD_DOCUMENT', "
- "'UPLOAD_DOCUMENT', 'BATCH_IMPORT', 'EDIT_DOCUMENT', "
- "'DELETE_DOCUMENT', 'CREATE_CATEGORY', 'EDIT_CATEGORY', "
- "'DELETE_CATEGORY', 'CHANGE_PERMISSION', 'BIND_ATTACHMENT', "
- "'UNBIND_ATTACHMENT'"
- ")",
- name="audit_action_type",
- ),
- sa.CheckConstraint(
- "target_type IS NULL OR target_type IN ("
- "'AUTH', 'CATEGORY', 'DOCUMENT', 'ATTACHMENT', "
- "'PERMISSION', 'ATTACHMENT_BINDING'"
- ")",
- name="audit_target_type",
- ),
- sa.CheckConstraint(
- "operation_result IN ('SUCCESS', 'FAILURE')",
- name="audit_operation_result",
- ),
- sa.PrimaryKeyConstraint("id"),
- )
- op.create_index(
- "ix_sys_audit_log_created_at",
- "sys_audit_log",
- ["created_at"],
- )
- op.create_index(
- "ix_sys_audit_log_user_created",
- "sys_audit_log",
- ["user_id", "created_at"],
- )
- op.create_index(
- "ix_sys_audit_log_organization_created",
- "sys_audit_log",
- ["organization_id", "created_at"],
- )
- op.create_index(
- "ix_sys_audit_log_action_created",
- "sys_audit_log",
- ["action_type", "created_at"],
- )
- op.create_index(
- "ix_sys_audit_log_target_created",
- "sys_audit_log",
- ["target_type", "target_id", "created_at"],
- )
- op.create_index(
- "ix_sys_audit_log_result_created",
- "sys_audit_log",
- ["operation_result", "created_at"],
- )
- op.create_index(
- "ix_sys_audit_log_request_id",
- "sys_audit_log",
- ["request_id"],
- )
- def downgrade() -> None:
- op.drop_table("sys_audit_log")
- op.drop_table("doc_permission")
- op.drop_table("doc_attachment_binding")
- op.drop_table("doc_document")
- op.drop_table("doc_category")
- op.drop_table("sys_user")
- op.drop_table("sys_organization")
|