| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354 |
- """站内通知模型(追加型,类似审计日志,不用业务表 mixin)。"""
- from __future__ import annotations
- from datetime import datetime, timezone
- from sqlalchemy import BigInteger, CheckConstraint, Index, String, text
- from sqlalchemy.dialects.mysql import DATETIME
- from sqlalchemy.orm import Mapped, mapped_column
- from dms.extensions import db
- class Notification(db.Model):
- """用户站内通知:审批流等待处理等需用户关注的信息。
- 通知只追加与状态流转(未读→已读、待处理→已同意/已拒绝),
- 不做软删与乐观锁,故不使用 BusinessTableMixin。
- """
- __tablename__ = "sys_notification"
- __table_args__ = (
- CheckConstraint(
- "notify_type IN ('APPROVAL')",
- name="notification_notify_type",
- ),
- CheckConstraint(
- "action IN ('NONE', 'PENDING', 'AGREE', 'REJECT')",
- name="notification_action",
- ),
- CheckConstraint(
- "status IN ('UNREAD', 'READ')",
- name="notification_status",
- ),
- Index("ix_sys_notification_user_id", "user_id", "id"),
- )
- id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
- user_id: Mapped[int] = mapped_column(BigInteger, nullable=False)
- title: Mapped[str] = mapped_column(String(200), nullable=False)
- content: Mapped[str | None] = mapped_column(String(1000), nullable=True)
- # 通知类别:APPROVAL 审批待办(后续审批流写入,预留扩展)
- notify_type: Mapped[str] = mapped_column(String(32), nullable=False)
- # 待办操作:NONE 无需操作 / PENDING 待处理 / AGREE 已同意 / REJECT 已拒绝
- action: Mapped[str] = mapped_column(String(16), nullable=False)
- status: Mapped[str] = mapped_column(String(16), nullable=False)
- created_at: Mapped[datetime] = mapped_column(
- DATETIME(fsp=3),
- nullable=False,
- # 应用侧 UTC 落库(与 sys_audit_log 同口径,序列化追加 Z)
- default=lambda: datetime.now(timezone.utc).replace(tzinfo=None),
- server_default=text("CURRENT_TIMESTAMP(3)"),
- )
- handled_at: Mapped[datetime | None] = mapped_column(DATETIME(fsp=3), nullable=True)
|