feat(后端): 添加授权体系、系统监控与试用期计提
按 2026-11-02 需求补齐计划交付后端能力: - 角色授权:权限目录化,接口统一准入校验,未登记默认拒绝; 管理员判断改为按数据库角色重新判定,防止权限码持有者绕过 - 系统监控:单进程采集资源、请求与异常指标,分钟级聚合, 阈值配置化;敏感配置增加 repr 保护,Redis 密码 URL 转义 - 试用期计提:按回款日判定并写入快照,年度结清与调整单联动; 人员模型补试用期、离职日期与工资版本历史字段 - 计提模板:公式骨架受控,页面维护名称与参数绑定 - T+ 采集:自动化配置表与进度查询 内置角色禁停用保护对齐模块注释;核算规则版本提为常量并 补充批量核算失败堆栈日志。 影响范围:后端全部模块、数据库迁移 V22-V28 验证:uv run ruff check 通过;922 个单元测试全部通过; 集成测试因本机 MySQL 数据卷被其他容器锁定暂未运行
这个提交包含在:
1 父节点
02fb06e0af
当前提交
1461a8d113
149 个文件已更改
+8736
-368
没有与搜索条件相匹配的文件
@@ -10,16 +10,20 @@
|
||||
"""
|
||||
|
||||
from app.models.approval import ApprovalOrder, ApprovalStep
|
||||
from app.models.authorization import AuthorizationSetting, UserPermissionOverride
|
||||
from app.models.base import Base, TimestampMixin
|
||||
from app.models.business import Business, BusinessItem, BusinessStatusLog, SecondaryAllocation
|
||||
from app.models.business_role import BusinessRole
|
||||
from app.models.calc_template import CalcTemplateDefinition
|
||||
from app.models.customer import Customer, OwnershipChangeLog
|
||||
from app.models.login_log import LoginLog
|
||||
from app.models.monitor import MonitorEvent, MonitorRequestMinute, MonitorSnapshot
|
||||
from app.models.operation_log import OperationLog
|
||||
from app.models.param import ParamChangeBatch, ParamDefinition, ParamValue
|
||||
from app.models.payroll import PayrollAllocation, PayrollInput, PayrollMonth
|
||||
from app.models.performance_ledger import PerformanceLedger
|
||||
from app.models.personnel import Personnel, PersonnelPlan, PersonnelRegion
|
||||
from app.models.probation import ProbationDeferral, ProbationPayment
|
||||
from app.models.product import Product
|
||||
from app.models.rating import CustomerRatingGrade
|
||||
from app.models.receipt import Receipt
|
||||
@@ -27,7 +31,7 @@ from app.models.role import Permission, Role, RolePermission
|
||||
from app.models.settlement import AdjustmentOrder, MonthlySettlement, SettlementItem
|
||||
from app.models.shipment import Shipment, ShipmentItem
|
||||
from app.models.system_setting import SystemSetting
|
||||
from app.models.tplus_automation import TPlusAutomationState
|
||||
from app.models.tplus_automation import TPlusAutomationConfig, TPlusAutomationState
|
||||
from app.models.tplus_sync import (
|
||||
TPlusSyncBatch,
|
||||
TPlusSyncError,
|
||||
@@ -47,14 +51,19 @@ __all__ = [
|
||||
"AdjustmentOrder",
|
||||
"ApprovalOrder",
|
||||
"ApprovalStep",
|
||||
"AuthorizationSetting",
|
||||
"Base",
|
||||
"Business",
|
||||
"BusinessItem",
|
||||
"BusinessRole",
|
||||
"BusinessStatusLog",
|
||||
"CalcTemplateDefinition",
|
||||
"Customer",
|
||||
"CustomerRatingGrade",
|
||||
"LoginLog",
|
||||
"MonitorEvent",
|
||||
"MonitorRequestMinute",
|
||||
"MonitorSnapshot",
|
||||
"MonthlySettlement",
|
||||
"OperationLog",
|
||||
"OwnershipChangeLog",
|
||||
@@ -69,6 +78,8 @@ __all__ = [
|
||||
"Personnel",
|
||||
"PersonnelPlan",
|
||||
"PersonnelRegion",
|
||||
"ProbationDeferral",
|
||||
"ProbationPayment",
|
||||
"Product",
|
||||
"Receipt",
|
||||
"Role",
|
||||
@@ -78,6 +89,7 @@ __all__ = [
|
||||
"Shipment",
|
||||
"ShipmentItem",
|
||||
"SystemSetting",
|
||||
"TPlusAutomationConfig",
|
||||
"TPlusAutomationState",
|
||||
"TPlusFact",
|
||||
"TPlusSourceHead",
|
||||
@@ -90,5 +102,6 @@ __all__ = [
|
||||
"TPlusWorkRun",
|
||||
"TimestampMixin",
|
||||
"User",
|
||||
"UserPermissionOverride",
|
||||
"UserRole",
|
||||
]
|
||||
@@ -0,0 +1,28 @@
|
||||
"""授权版本锁及旧版授权结构;V26 后不再使用个人覆盖或全局制作人绑定。"""
|
||||
|
||||
from sqlalchemy import ForeignKey, Index, Integer, String, UniqueConstraint
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from app.models.base import BIGINT_UNSIGNED, Base, TimestampMixin, mysql_table_args
|
||||
|
||||
|
||||
class UserPermissionOverride(Base, TimestampMixin):
|
||||
__tablename__ = "user_permission_overrides"
|
||||
__table_args__ = mysql_table_args(
|
||||
"用户权限覆盖表(个人禁止优先)",
|
||||
UniqueConstraint("user_id", "permission_id", name="uk_user_permission_overrides_user_permission"),
|
||||
Index("idx_user_permission_overrides_permission_id", "permission_id"),
|
||||
)
|
||||
id: Mapped[int] = mapped_column(BIGINT_UNSIGNED, primary_key=True, autoincrement=True, comment="主键ID")
|
||||
user_id: Mapped[int] = mapped_column(BIGINT_UNSIGNED, ForeignKey("users.id", ondelete="CASCADE"), comment="系统用户ID")
|
||||
permission_id: Mapped[int] = mapped_column(BIGINT_UNSIGNED, ForeignKey("permissions.id", ondelete="RESTRICT"), comment="权限ID")
|
||||
effect: Mapped[str] = mapped_column(String(8), comment="个人覆盖:ALLOW允许 DENY禁止")
|
||||
|
||||
|
||||
class AuthorizationSetting(Base, TimestampMixin):
|
||||
__tablename__ = "authorization_settings"
|
||||
__table_args__ = mysql_table_args("授权设置表(单例与并发修改锁)")
|
||||
id: Mapped[int] = mapped_column(BIGINT_UNSIGNED, primary_key=True, autoincrement=True, comment="单例主键ID")
|
||||
maker_user_id: Mapped[int | None] = mapped_column(BIGINT_UNSIGNED, ForeignKey("users.id", ondelete="RESTRICT"), comment="现任工资制作人账号ID")
|
||||
revision: Mapped[int] = mapped_column(Integer, nullable=False, server_default="1", comment="全局授权版本")
|
||||
updated_by: Mapped[int | None] = mapped_column(BIGINT_UNSIGNED, ForeignKey("users.id", ondelete="SET NULL"), comment="最近修改人ID")
|
||||
@@ -0,0 +1,52 @@
|
||||
"""计提公式模板定义模型。
|
||||
|
||||
把一期代码内注册表升级为数据库配置:模板名称、说明、参数绑定可在页面维护,
|
||||
公式执行骨架仍是受控枚举(formula_type),不允许自由表达式,避免注入与算错。
|
||||
岗位角色 `business_roles.calc_template` 绑定模板编码,编码创建后不可修改。
|
||||
"""
|
||||
|
||||
from sqlalchemy import JSON, Integer, String
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from app.models.base import BIGINT_UNSIGNED, TINYINT_TYPE, Base, TimestampMixin, mysql_table_args
|
||||
|
||||
|
||||
class CalcTemplateDefinition(Base, TimestampMixin):
|
||||
"""计提公式模板定义表。内置模板随迁移初始化,页面可新增自定义模板。"""
|
||||
|
||||
__tablename__ = "calc_template_definitions"
|
||||
__table_args__ = mysql_table_args("计提公式模板定义表(页面可维护,骨架受控)")
|
||||
|
||||
id: Mapped[int] = mapped_column(
|
||||
BIGINT_UNSIGNED, primary_key=True, autoincrement=True, comment="主键ID"
|
||||
)
|
||||
template_code: Mapped[str] = mapped_column(
|
||||
String(32),
|
||||
nullable=False,
|
||||
unique=True,
|
||||
comment="模板编码,创建后不可修改;岗位表 business_roles.calc_template 引用",
|
||||
)
|
||||
template_name: Mapped[str] = mapped_column(String(64), nullable=False, comment="模板名称")
|
||||
formula_type: Mapped[str] = mapped_column(
|
||||
String(32),
|
||||
nullable=False,
|
||||
comment="公式骨架类型:linear_decay/fixed_profit/fixed_sales/manager_share/prepay_fixed,创建后不可修改",
|
||||
)
|
||||
params_json: Mapped[dict] = mapped_column(
|
||||
JSON,
|
||||
nullable=False,
|
||||
comment="骨架参数角色到参数编码的 JSON 映射,如 {start:..., slope:...}",
|
||||
)
|
||||
description: Mapped[str | None] = mapped_column(String(255), comment="模板说明")
|
||||
sort_order: Mapped[int] = mapped_column(
|
||||
Integer, nullable=False, server_default="0", comment="显示排序"
|
||||
)
|
||||
status: Mapped[int] = mapped_column(
|
||||
TINYINT_TYPE, nullable=False, server_default="1", comment="状态:1启用 0停用"
|
||||
)
|
||||
is_system: Mapped[int] = mapped_column(
|
||||
TINYINT_TYPE,
|
||||
nullable=False,
|
||||
server_default="0",
|
||||
comment="是否系统模板:1内置(禁删、骨架与编码锁定) 0自定义",
|
||||
)
|
||||
@@ -0,0 +1,79 @@
|
||||
"""监控数据独立保存,不关联工资或审计表;仅这些新表按七天保留。"""
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import JSON, DateTime, Float, Index, Integer, String, UniqueConstraint
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from app.models.base import BIGINT_UNSIGNED, Base, mysql_table_args
|
||||
|
||||
|
||||
class MonitorSnapshot(Base):
|
||||
__tablename__ = "monitor_snapshots"
|
||||
__table_args__ = mysql_table_args(
|
||||
"分钟级运行监控快照",
|
||||
UniqueConstraint("instance_id", "minute", name="uk_monitor_snapshots_instance_minute"),
|
||||
Index("idx_monitor_snapshots_minute", "minute"),
|
||||
)
|
||||
|
||||
id: Mapped[int] = mapped_column(
|
||||
BIGINT_UNSIGNED, primary_key=True, autoincrement=True, comment="主键ID"
|
||||
)
|
||||
instance_id: Mapped[str] = mapped_column(String(32), comment="应用实例标识")
|
||||
minute: Mapped[datetime] = mapped_column(DateTime, comment="采集分钟,北京时间")
|
||||
sample_count: Mapped[int] = mapped_column(Integer, comment="实际采样次数")
|
||||
resources: Mapped[dict] = mapped_column(JSON, comment="资源均值与采集范围,不含配置")
|
||||
requests: Mapped[dict] = mapped_column(JSON, comment="请求汇总与固定耗时直方图")
|
||||
|
||||
|
||||
class MonitorRequestMinute(Base):
|
||||
__tablename__ = "monitor_request_minutes"
|
||||
__table_args__ = mysql_table_args(
|
||||
"接口分钟级运行统计",
|
||||
UniqueConstraint(
|
||||
"instance_id", "minute", "method", "route", name="uk_monitor_request_minutes_endpoint"
|
||||
),
|
||||
Index("idx_monitor_request_minutes_minute", "minute"),
|
||||
)
|
||||
|
||||
id: Mapped[int] = mapped_column(
|
||||
BIGINT_UNSIGNED, primary_key=True, autoincrement=True, comment="主键ID"
|
||||
)
|
||||
instance_id: Mapped[str] = mapped_column(String(32), comment="应用实例标识")
|
||||
minute: Mapped[datetime] = mapped_column(DateTime, comment="请求分钟,北京时间")
|
||||
method: Mapped[str] = mapped_column(String(8), comment="HTTP方法,固定集合")
|
||||
route: Mapped[str] = mapped_column(String(256), comment="路由模板,不含原始地址及参数")
|
||||
metrics: Mapped[dict] = mapped_column(JSON, comment="请求数、状态分类与固定直方图")
|
||||
|
||||
|
||||
class MonitorEvent(Base):
|
||||
__tablename__ = "monitor_events"
|
||||
__table_args__ = mysql_table_args(
|
||||
"脱敏诊断事件与异常恢复记录",
|
||||
Index("idx_monitor_events_last_seen", "last_seen"),
|
||||
Index("idx_monitor_events_request_id", "request_id"),
|
||||
Index("idx_monitor_events_fingerprint", "fingerprint", "resolved_at"),
|
||||
)
|
||||
|
||||
id: Mapped[int] = mapped_column(
|
||||
BIGINT_UNSIGNED, primary_key=True, autoincrement=True, comment="主键ID"
|
||||
)
|
||||
instance_id: Mapped[str] = mapped_column(String(32), comment="应用实例标识")
|
||||
kind: Mapped[str] = mapped_column(String(24), comment="事件类型,固定集合")
|
||||
code: Mapped[str] = mapped_column(String(64), comment="稳定错误码")
|
||||
component: Mapped[str] = mapped_column(String(128), comment="所属组件或日志模块")
|
||||
level: Mapped[str] = mapped_column(String(16), comment="异常级别")
|
||||
message: Mapped[str] = mapped_column(String(256), comment="通用说明,不保存内部异常文本")
|
||||
fingerprint: Mapped[str | None] = mapped_column(String(64), comment="同类健康异常合并键")
|
||||
request_id: Mapped[str | None] = mapped_column(String(32), comment="请求关联编号")
|
||||
method: Mapped[str | None] = mapped_column(String(8), comment="HTTP方法")
|
||||
route: Mapped[str | None] = mapped_column(String(256), comment="路由模板")
|
||||
status_code: Mapped[int | None] = mapped_column(Integer, comment="HTTP状态码")
|
||||
duration_ms: Mapped[float | None] = mapped_column(Float, comment="请求耗时,毫秒")
|
||||
batch_no: Mapped[str | None] = mapped_column(String(32), comment="相关同步批次编号")
|
||||
first_seen: Mapped[datetime] = mapped_column(DateTime, comment="首次发生时间")
|
||||
last_seen: Mapped[datetime] = mapped_column(DateTime, comment="最近发生时间")
|
||||
occurrences: Mapped[int] = mapped_column(Integer, comment="发生或持续采样次数")
|
||||
resolved_at: Mapped[datetime | None] = mapped_column(
|
||||
DateTime, comment="恢复时间,仅用于健康异常"
|
||||
)
|
||||
@@ -10,7 +10,7 @@
|
||||
from datetime import date
|
||||
from decimal import Decimal
|
||||
|
||||
from sqlalchemy import Date, ForeignKey, Numeric, String
|
||||
from sqlalchemy import JSON, Date, ForeignKey, Numeric, String
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from app.models.base import (
|
||||
@@ -62,9 +62,22 @@ class Personnel(Base, TimestampMixin, TPlusSyncMixin):
|
||||
server_default="0",
|
||||
comment="是否试用期:1是 0否(试用期绩效照算不发放)",
|
||||
)
|
||||
probation_start_date: Mapped[date | None] = mapped_column(
|
||||
Date, comment="试用期开始日(含当日)"
|
||||
)
|
||||
regularization_date: Mapped[date | None] = mapped_column(
|
||||
Date, comment="转正生效日(当日不再属于试用期)"
|
||||
)
|
||||
resignation_date: Mapped[date | None] = mapped_column(
|
||||
Date, comment="离职生效日(当日起不计基本工资)"
|
||||
)
|
||||
salary_standard: Mapped[Decimal | None] = mapped_column(
|
||||
Numeric(12, 2), comment="月工资标准(元;T+同步不覆盖)"
|
||||
)
|
||||
salary_history_json: Mapped[list | None] = mapped_column(
|
||||
JSON,
|
||||
comment="工资标准、岗位及任职资料生效版本",
|
||||
)
|
||||
status: Mapped[int] = mapped_column(
|
||||
TINYINT_TYPE,
|
||||
nullable=False,
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
"""试用期缓发与结清记录,引用固化台账,不使用人员当前开关重写历史。"""
|
||||
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
|
||||
from sqlalchemy import JSON, DateTime, ForeignKey, Index, Numeric, String, UniqueConstraint, text
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from app.models.base import BIGINT_UNSIGNED, Base, mysql_table_args
|
||||
|
||||
|
||||
class ProbationDeferral(Base):
|
||||
__tablename__ = "probation_deferrals"
|
||||
__table_args__ = mysql_table_args(
|
||||
"试用期缓发台账(每个正式台账版本一条)",
|
||||
UniqueConstraint("ledger_id", name="uk_probation_deferrals_ledger_id"),
|
||||
Index("idx_probation_deferrals_personnel_id_year", "personnel_id", "year"),
|
||||
)
|
||||
id: Mapped[int] = mapped_column(
|
||||
BIGINT_UNSIGNED, primary_key=True, autoincrement=True, comment="主键ID"
|
||||
)
|
||||
ledger_id: Mapped[int] = mapped_column(
|
||||
BIGINT_UNSIGNED,
|
||||
ForeignKey("performance_ledgers.id", ondelete="RESTRICT"),
|
||||
nullable=False,
|
||||
comment="原核算台账版本ID",
|
||||
)
|
||||
personnel_id: Mapped[int] = mapped_column(BIGINT_UNSIGNED, nullable=False, comment="归属人员ID")
|
||||
year: Mapped[str] = mapped_column(String(4), nullable=False, comment="原计提年度")
|
||||
month: Mapped[str] = mapped_column(String(7), nullable=False, comment="本次计提或应付变化月份")
|
||||
accrued: Mapped[Decimal] = mapped_column(
|
||||
Numeric(14, 2), nullable=False, comment="本次试用期计提额,可负"
|
||||
)
|
||||
eligible: Mapped[Decimal] = mapped_column(
|
||||
Numeric(14, 2), nullable=False, comment="满足起付及权重的本次应付差额,可负"
|
||||
)
|
||||
create_time: Mapped[datetime] = mapped_column(
|
||||
DateTime, server_default=text("CURRENT_TIMESTAMP"), nullable=False, comment="创建时间"
|
||||
)
|
||||
|
||||
|
||||
class ProbationPayment(Base):
|
||||
__tablename__ = "probation_payments"
|
||||
__table_args__ = mysql_table_args(
|
||||
"试用期年终及后续结清记录(工资生成事务内固化)",
|
||||
UniqueConstraint(
|
||||
"settlement_id",
|
||||
"personnel_id",
|
||||
"year",
|
||||
name="uk_probation_payments_settlement_person_year",
|
||||
),
|
||||
UniqueConstraint("adjustment_order_id", name="uk_probation_payments_adjustment_order_id"),
|
||||
Index("idx_probation_payments_personnel_id_year", "personnel_id", "year"),
|
||||
)
|
||||
id: Mapped[int] = mapped_column(
|
||||
BIGINT_UNSIGNED, primary_key=True, autoincrement=True, comment="主键ID"
|
||||
)
|
||||
settlement_id: Mapped[int | None] = mapped_column(
|
||||
BIGINT_UNSIGNED,
|
||||
ForeignKey("monthly_settlements.id", ondelete="CASCADE"),
|
||||
nullable=True,
|
||||
comment="月结ID(当月调整单结清时为空)",
|
||||
)
|
||||
adjustment_order_id: Mapped[int | None] = mapped_column(
|
||||
BIGINT_UNSIGNED,
|
||||
ForeignKey("adjustment_orders.id", ondelete="RESTRICT"),
|
||||
nullable=True,
|
||||
comment="已生成工资后的结清调整单ID",
|
||||
)
|
||||
personnel_id: Mapped[int] = mapped_column(BIGINT_UNSIGNED, nullable=False, comment="归属人员ID")
|
||||
year: Mapped[str] = mapped_column(String(4), nullable=False, comment="原累计年度")
|
||||
month: Mapped[str] = mapped_column(String(7), nullable=False, comment="本次实际支付月份")
|
||||
amount: Mapped[Decimal] = mapped_column(
|
||||
Numeric(14, 2), nullable=False, comment="本次补发或扣回金额"
|
||||
)
|
||||
snapshot_json: Mapped[dict] = mapped_column(
|
||||
JSON, nullable=False, comment="计提、起付权重、门槛及历史补发依据"
|
||||
)
|
||||
create_time: Mapped[datetime] = mapped_column(
|
||||
DateTime, server_default=text("CURRENT_TIMESTAMP"), nullable=False, comment="创建时间"
|
||||
)
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
from decimal import Decimal
|
||||
|
||||
from sqlalchemy import Numeric, String, UniqueConstraint
|
||||
from sqlalchemy import JSON, Numeric, String, UniqueConstraint
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from app.models.base import (
|
||||
@@ -56,3 +56,5 @@ class Product(Base, TimestampMixin, TPlusSyncMixin):
|
||||
TINYINT_TYPE, nullable=False, server_default="1", comment="状态:1启用 0停用"
|
||||
)
|
||||
remark: Mapped[str | None] = mapped_column(String(255), comment="备注")
|
||||
source_trade_json: Mapped[dict | None] = mapped_column(JSON, comment="最近有效发货数量、含税成交价及源单据快照")
|
||||
quantity_price_manual: Mapped[int] = mapped_column(TINYINT_TYPE, nullable=False, server_default="0", comment="数量单价人工保护:1人工维护 0随源更新")
|
||||
@@ -131,17 +131,27 @@ class SettlementItem(Base):
|
||||
String(16), comment="月工资口径快照:INCLUDE/DEDUCT/EXCLUDE"
|
||||
)
|
||||
net_amount: Mapped[Decimal | None] = mapped_column(
|
||||
Numeric(14, 2), comment="净工资 = 绩效±基本工资(按口径;试用期 0)"
|
||||
Numeric(14, 2),
|
||||
comment="净工资 = 绩效±基本工资(按口径;试用期为基本工资+正常应付+年度差额,缓发部分不发)"
|
||||
)
|
||||
is_probation: Mapped[int] = mapped_column(
|
||||
TINYINT_TYPE,
|
||||
nullable=False,
|
||||
server_default="0",
|
||||
comment="试用期:1绩效照算不发放(net=0,超年累计记 note)0否",
|
||||
comment="试用期:1缓发绩效不发(基本工资正常发,超年累计记 note)0否",
|
||||
)
|
||||
probation_note: Mapped[str | None] = mapped_column(
|
||||
String(255), comment="试用期说明(年累计超阈值部分年底一次性结算)"
|
||||
)
|
||||
normal_payable_sum: Mapped[Decimal] = mapped_column(
|
||||
Numeric(14, 2), nullable=False, server_default="0", comment="当月正常实付绩效"
|
||||
)
|
||||
deferred_sum: Mapped[Decimal] = mapped_column(
|
||||
Numeric(14, 2), nullable=False, server_default="0", comment="当月试用期缓发变化"
|
||||
)
|
||||
probation_payment_sum: Mapped[Decimal] = mapped_column(
|
||||
Numeric(14, 2), nullable=False, server_default="0", comment="本月年度补发或扣回"
|
||||
)
|
||||
snapshot_json: Mapped[dict | None] = mapped_column(
|
||||
JSON, comment="个人明细快照(台账行引用列表)"
|
||||
)
|
||||
|
||||
@@ -2,10 +2,26 @@
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import DateTime, Integer, String
|
||||
from sqlalchemy import DateTime, Integer, String, UniqueConstraint
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from app.models.base import BIGINT_UNSIGNED, Base, TimestampMixin, mysql_table_args
|
||||
from app.models.base import BIGINT_UNSIGNED, TINYINT_TYPE, Base, TimestampMixin, mysql_table_args
|
||||
|
||||
|
||||
class TPlusAutomationConfig(Base, TimestampMixin):
|
||||
"""页面保存的源级开关,与长任务心跳表分开,切换不争用采集状态行。"""
|
||||
|
||||
__tablename__ = "tplus_automation_configs"
|
||||
__table_args__ = mysql_table_args(
|
||||
"T+自动采集设置(不含连接凭据)",
|
||||
UniqueConstraint("source_key", name="uk_tplus_automation_configs_source_key"),
|
||||
)
|
||||
id: Mapped[int] = mapped_column(BIGINT_UNSIGNED, primary_key=True, autoincrement=True, comment="主键ID")
|
||||
source_key: Mapped[str] = mapped_column(String(64), comment="源连接身份摘要")
|
||||
source_database: Mapped[str] = mapped_column(String(128), comment="源账套")
|
||||
enabled: Mapped[int] = mapped_column(TINYINT_TYPE, comment="自动采集是否开启:1开启0关闭")
|
||||
version: Mapped[int] = mapped_column(Integer, comment="设置版本号,防止并发覆盖")
|
||||
updated_by: Mapped[int] = mapped_column(BIGINT_UNSIGNED, comment="最近修改账号ID")
|
||||
|
||||
|
||||
class TPlusAutomationState(Base, TimestampMixin):
|
||||
|
||||
在新工单中引用
屏蔽一个用户