feat(kpi,review): KPI direction 列 + KPITarget 模型 + 复盘产出方入库(R1 收口)
ci/woodpecker/push/main Pipeline failed
ci/woodpecker/push/main Pipeline failed
R1 收口批次(A 侧裁定 p12-ruling-input-r1-batch.RULING.md 主路径)· 单个快进提交: - backend/app/models/__init__.py(+42/−2):CMA-KPI-20261003 阶段1 `direction`(KPIDefinition/KPITemplate) + ② KPITarget(kpi_targets,11 列 + uk_entity_kpi_period_type + 2 索引) - 复盘产出方三件(review_builder 含 getattr(direction) 硬化 / review_run / 测试件),原始提交件 26dc242 的重铸件 收口边界申报:本提交**不含** D-1 批次(VoucherDetail.row_uid / ImportLog uq_import_logs_entity_batch_type)—— 只读补证显示 prod `cma` 无该列/该唯一键(证据 out/r1-t1-batches.json + out/r1-t1-d1-placement.json), 携行会导致 deploy 后 voucher_details 整实体 SELECT/INSERT 报 1054;D-1 另单(先 DDL 后 ORM)。
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
"""管理会计OS 数据模型"""
|
||||
from sqlalchemy import Column, Integer, String, Text, Float, DateTime, ForeignKey, Boolean, JSON, func, UniqueConstraint, Numeric, Date
|
||||
from sqlalchemy import Column, Integer, String, Text, Float, DateTime, ForeignKey, Boolean, JSON, func, text, UniqueConstraint, Index, Numeric, Date
|
||||
from app.database import Base
|
||||
|
||||
from app.models.budget_plan import BudgetPlan
|
||||
@@ -93,7 +93,13 @@ class KPIDefinition(Base):
|
||||
data_owner = Column(String(100), default="待指定", comment="数据责任人")
|
||||
frequency = Column(String(20), default="monthly", comment="daily/weekly/monthly/quarterly/yearly")
|
||||
unit = Column(String(50), default="%", comment="单位")
|
||||
target_value = Column(Float, nullable=True, comment="目标值(兼容旧字段)")
|
||||
# 2026-10-03 KPI字典分层治理(任务 CMA-KPI-20261003)阶段1:direction 结构列。
|
||||
# 枚举 higher_better(越大越好)/lower_better(越小越好),NULL=未定。
|
||||
# 既有行由 migrate_kpi_direction_20261003.py 按 threshold_green 比较符**结构推定**回填
|
||||
# (非口径裁定);口径/阈值语义仍属 finance/DAMA 在途批次。
|
||||
direction = Column(String(16), nullable=True,
|
||||
comment="指标方向: higher_better越大越好/lower_better越小越好/NULL未定")
|
||||
target_value = Column(Float, nullable=True, comment="目标值(NULL=未设目标;0=真零目标;兼容旧字段)")
|
||||
target_monthly = Column(Float, nullable=True, comment="月度目标值")
|
||||
target_quarterly = Column(Float, nullable=True, comment="季度目标值")
|
||||
target_yearly = Column(Float, nullable=True, comment="年度目标值")
|
||||
@@ -491,6 +497,10 @@ class KPITemplate(Base):
|
||||
formula = Column(Text)
|
||||
formula_desc = Column(String(500))
|
||||
unit = Column(String(50))
|
||||
# 2026-10-03 KPI字典分层治理(任务 CMA-KPI-20261003)阶段1:字典层同加 direction;
|
||||
# 回填规则 = 继承同 kpi_code 实例的已定方向(见 docs/kpi-dictionary-layering-design.md §2.2)。
|
||||
direction = Column(String(16), nullable=True,
|
||||
comment="指标方向: higher_better越大越好/lower_better越小越好/NULL未定")
|
||||
target_value = Column(Float)
|
||||
description = Column(Text)
|
||||
is_system = Column(Integer, default=0)
|
||||
@@ -864,6 +874,36 @@ class ObjectiveKPI(Base):
|
||||
__table_args__ = (UniqueConstraint("objective_id", "kpi_id", name="uk_obj_kpi"),)
|
||||
|
||||
|
||||
class KPITarget(Base):
|
||||
"""KPI 期间目标(考核型·方案 A)—— ③ 读点收敛 CMA-KPI-20261003
|
||||
|
||||
唯一真源(考核型):`(entity_id, kpi_id, period, target_type)` 唯一;
|
||||
承诺型目标只写 `krs`(裁定 §二 边界声明:同一 KPI 不得两处均有 target)。
|
||||
|
||||
**列定义与 ② DDL 出件包 `up.sql` 逐字一致**(11 列 + uk_entity_kpi_period_type + 2 索引);
|
||||
`entity_id` 无 DDL DEFAULT(写入口必须显式传值,防静默默认把实体隔离降级为约定);
|
||||
`updated_at` 无 `ON UPDATE CURRENT_TIMESTAMP`(由 ORM/写入口维护,与现网 kpi_definitions 同风格)。
|
||||
"""
|
||||
__tablename__ = "kpi_targets"
|
||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||
entity_id = Column(Integer, nullable=False, comment="账套(企业ID);写入口必须显式传值(实体隔离)")
|
||||
kpi_id = Column(Integer, nullable=False, comment="指标实例 → kpi_definitions.id")
|
||||
period = Column(String(20), nullable=False, comment="期间: 2026-08(月)/2026Q3(季)/2026(年)")
|
||||
target_type = Column(String(16), nullable=False, comment="目标粒度: monthly/quarterly/yearly")
|
||||
target_value = Column(Numeric(15, 2), nullable=True, comment="NULL=该期未设;0=真零")
|
||||
source = Column(String(20), nullable=False, server_default=text("'manual'"),
|
||||
comment="manual/okr/budget/import")
|
||||
note = Column(String(255), nullable=True, comment="备注")
|
||||
created_by = Column(String(64), nullable=True, comment="写入者(用户/Bot标识)")
|
||||
created_at = Column(DateTime, nullable=False, server_default=func.now())
|
||||
updated_at = Column(DateTime, nullable=False, server_default=func.now())
|
||||
__table_args__ = (
|
||||
UniqueConstraint("entity_id", "kpi_id", "period", "target_type", name="uk_entity_kpi_period_type"),
|
||||
Index("ix_kpi_targets_entity_period", "entity_id", "period"),
|
||||
Index("ix_kpi_targets_kpi", "kpi_id"),
|
||||
)
|
||||
|
||||
|
||||
class KR(Base):
|
||||
"""关键结果KR — OKR完整化 (O→KR→KPI)"""
|
||||
__tablename__ = "krs"
|
||||
|
||||
Reference in New Issue
Block a user