feat: 数据治理 — 入库约束+元数据卡片+编码清洗+审计看板
This commit is contained in:
@@ -406,12 +406,43 @@ def get_kpi(kpi_id: int, db: Session = Depends(get_db)):
|
||||
return kpi_to_dict(kpi)
|
||||
|
||||
|
||||
def _validate_kpi_data(data: dict, is_update: bool = False):
|
||||
"""数据治理:入库必检 + 元数据校验"""
|
||||
errors = []
|
||||
|
||||
# 规则1: target_value 必填
|
||||
tv = data.get("target_value")
|
||||
if tv is None or (isinstance(tv, (int, float)) and tv < 0 and not is_update):
|
||||
if not is_update or "target_value" in data:
|
||||
if tv is None:
|
||||
errors.append("目标值(target_value)不能为空")
|
||||
|
||||
# 规则1: unit 必填
|
||||
unit = data.get("unit")
|
||||
if not unit or (isinstance(unit, str) and unit.strip() == ""):
|
||||
if not is_update or "unit" in data:
|
||||
errors.append("单位(unit)不能为空")
|
||||
|
||||
# 规则2: 元数据必填 — formula/data_source/data_owner
|
||||
for field, label in [("formula", "计算公式"), ("data_source", "数据来源"), ("data_owner", "数据责任人")]:
|
||||
val = data.get(field)
|
||||
if not val or (isinstance(val, str) and val.strip() == ""):
|
||||
if not is_update or field in data:
|
||||
errors.append(f"元数据字段'{label}'({field})不能为空")
|
||||
|
||||
return errors
|
||||
|
||||
|
||||
@router.post("")
|
||||
def create_kpi(data: dict, db: Session = Depends(get_db), user=WRITE_ROLES):
|
||||
# 检查编码唯一性
|
||||
existing = db.query(KPIDefinition).filter(KPIDefinition.kpi_code == data.get("kpi_code", "")).first()
|
||||
if existing:
|
||||
raise HTTPException(400, f"KPI编码 {data['kpi_code']} 已存在")
|
||||
# 数据治理校验
|
||||
errs = _validate_kpi_data(data, is_update=False)
|
||||
if errs:
|
||||
raise HTTPException(422, detail={"message": "数据校验不通过", "errors": errs})
|
||||
kpi = KPIDefinition(**data)
|
||||
db.add(kpi)
|
||||
db.commit()
|
||||
@@ -425,6 +456,10 @@ def update_kpi(kpi_id: int, data: dict, db: Session = Depends(get_db), user=WRIT
|
||||
kpi = db.query(KPIDefinition).filter(KPIDefinition.id == kpi_id).first()
|
||||
if not kpi:
|
||||
raise HTTPException(404, "KPI不存在")
|
||||
# 数据治理校验(更新时只检查传了但为空的字段)
|
||||
errs = _validate_kpi_data(data, is_update=True)
|
||||
if errs:
|
||||
raise HTTPException(422, detail={"message": "数据校验不通过", "errors": errs})
|
||||
for k, v in data.items():
|
||||
if hasattr(kpi, k) and v is not None:
|
||||
setattr(kpi, k, v)
|
||||
|
||||
Reference in New Issue
Block a user