document.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. """主案、子方案和共享附件统一文档模型。"""
  2. from __future__ import annotations
  3. from sqlalchemy import (
  4. BigInteger,
  5. CheckConstraint,
  6. ForeignKey,
  7. Index,
  8. Integer,
  9. JSON,
  10. String,
  11. Text,
  12. text,
  13. )
  14. from sqlalchemy.orm import Mapped, mapped_column
  15. from dms.database.base import BusinessTableMixin
  16. from dms.extensions import db
  17. class Document(BusinessTableMixin, db.Model):
  18. __tablename__ = "doc_document"
  19. __table_args__ = (
  20. CheckConstraint(
  21. "document_type IN ('MAIN', 'SUB_PLAN', 'ATTACHMENT')",
  22. name="document_type",
  23. ),
  24. CheckConstraint(
  25. "document_status IN ('DRAFT', 'PUBLISHED', 'ARCHIVED')",
  26. name="document_status",
  27. ),
  28. CheckConstraint(
  29. "security_level IN "
  30. "('PUBLIC', 'INTERNAL', 'SECRET', 'CONFIDENTIAL', 'TOP_SECRET')",
  31. name="document_security_level",
  32. ),
  33. CheckConstraint(
  34. "visibility_type IN ('ALL_AUTHENTICATED', 'ORGANIZATION', 'CUSTOM')",
  35. name="document_visibility_type",
  36. ),
  37. CheckConstraint(
  38. "attachment_type IS NULL OR attachment_type IN "
  39. "('POLICY', 'WORK_STANDARD', 'TABLE', 'DIAGRAM', 'OTHER')",
  40. name="document_attachment_type",
  41. ),
  42. CheckConstraint(
  43. "("
  44. "document_type = 'MAIN' "
  45. "AND parent_document_id IS NULL "
  46. "AND category_id IS NOT NULL "
  47. "AND attachment_type IS NULL"
  48. ") OR ("
  49. "document_type = 'SUB_PLAN' "
  50. "AND parent_document_id IS NOT NULL "
  51. "AND root_document_id IS NOT NULL "
  52. "AND category_id IS NOT NULL "
  53. "AND attachment_type IS NULL"
  54. ") OR ("
  55. "document_type = 'ATTACHMENT' "
  56. "AND parent_document_id IS NULL "
  57. "AND root_document_id IS NULL "
  58. "AND category_id IS NULL "
  59. "AND attachment_type IS NOT NULL "
  60. "AND security_level = 'PUBLIC' "
  61. "AND visibility_type = 'ALL_AUTHENTICATED'"
  62. ")",
  63. name="document_type_shape",
  64. ),
  65. Index(
  66. "ix_doc_document_type_active_updated",
  67. "document_type",
  68. "is_deleted",
  69. "updated_at",
  70. ),
  71. Index(
  72. "ix_doc_document_parent_type_active",
  73. "parent_document_id",
  74. "document_type",
  75. "is_deleted",
  76. ),
  77. Index(
  78. "ix_doc_document_root_active",
  79. "root_document_id",
  80. "is_deleted",
  81. ),
  82. Index(
  83. "ix_doc_document_category_active",
  84. "category_id",
  85. "is_deleted",
  86. ),
  87. Index(
  88. "ix_doc_document_status_active",
  89. "document_status",
  90. "is_deleted",
  91. ),
  92. Index(
  93. "ix_doc_document_security_active",
  94. "security_level",
  95. "is_deleted",
  96. ),
  97. Index("ix_doc_document_file_hash", "file_hash"),
  98. Index(
  99. "ix_doc_document_creator_active",
  100. "created_by",
  101. "is_deleted",
  102. ),
  103. Index(
  104. "ix_doc_document_attachment_type_active_updated",
  105. "attachment_type",
  106. "is_deleted",
  107. "updated_at",
  108. ),
  109. Index(
  110. "ix_doc_document_file_extension_active_updated",
  111. "file_extension",
  112. "is_deleted",
  113. "updated_at",
  114. ),
  115. Index(
  116. "ix_doc_document_recycle_deleted",
  117. "is_deleted",
  118. "deleted_at",
  119. "id",
  120. ),
  121. )
  122. document_name: Mapped[str] = mapped_column(String(255), nullable=False)
  123. summary: Mapped[str | None] = mapped_column(Text, nullable=True)
  124. document_type: Mapped[str] = mapped_column(String(32), nullable=False)
  125. document_status: Mapped[str] = mapped_column(
  126. String(32),
  127. nullable=False,
  128. server_default=text("'DRAFT'"),
  129. )
  130. security_level: Mapped[str] = mapped_column(
  131. String(32),
  132. nullable=False,
  133. server_default=text("'INTERNAL'"),
  134. )
  135. visibility_type: Mapped[str] = mapped_column(
  136. String(32),
  137. nullable=False,
  138. server_default=text("'CUSTOM'"),
  139. )
  140. attachment_type: Mapped[str | None] = mapped_column(String(32), nullable=True)
  141. category_id: Mapped[int | None] = mapped_column(
  142. BigInteger,
  143. ForeignKey("doc_category.id", ondelete="RESTRICT"),
  144. nullable=True,
  145. )
  146. category_name: Mapped[str | None] = mapped_column(String(128), nullable=True)
  147. category_path: Mapped[str | None] = mapped_column(String(1000), nullable=True)
  148. parent_document_id: Mapped[int | None] = mapped_column(
  149. BigInteger,
  150. ForeignKey("doc_document.id", ondelete="RESTRICT"),
  151. nullable=True,
  152. )
  153. root_document_id: Mapped[int | None] = mapped_column(
  154. BigInteger,
  155. ForeignKey("doc_document.id", ondelete="RESTRICT"),
  156. nullable=True,
  157. )
  158. tags: Mapped[list[str] | None] = mapped_column(JSON, nullable=True)
  159. original_file_name: Mapped[str] = mapped_column(String(255), nullable=False)
  160. file_relative_path: Mapped[str] = mapped_column(String(1000), nullable=False)
  161. file_extension: Mapped[str] = mapped_column(String(20), nullable=False)
  162. mime_type: Mapped[str | None] = mapped_column(String(128), nullable=True)
  163. file_size: Mapped[int] = mapped_column(
  164. BigInteger,
  165. nullable=False,
  166. server_default=text("0"),
  167. )
  168. file_hash: Mapped[str] = mapped_column(String(64), nullable=False)
  169. child_count: Mapped[int] = mapped_column(
  170. Integer,
  171. nullable=False,
  172. server_default=text("0"),
  173. )
  174. attachment_count: Mapped[int] = mapped_column(
  175. Integer,
  176. nullable=False,
  177. server_default=text("0"),
  178. )
  179. view_count: Mapped[int] = mapped_column(
  180. BigInteger,
  181. nullable=False,
  182. server_default=text("0"),
  183. )
  184. download_count: Mapped[int] = mapped_column(
  185. BigInteger,
  186. nullable=False,
  187. server_default=text("0"),
  188. )
  189. search_text: Mapped[str | None] = mapped_column(Text, nullable=True)
  190. created_by_name: Mapped[str | None] = mapped_column(String(64), nullable=True)
  191. updated_by_name: Mapped[str | None] = mapped_column(String(64), nullable=True)