2026-10-12 04:22:32 -04:00
|
|
|
|
"""计提参数目录注册表。
|
|
|
|
|
|
|
|
|
|
|
|
注册表是**迁移种子与运行期校验的唯一来源**:编码、默认值、取值域在此定义
|
|
|
|
|
|
一次;新增参数 = 改这里 + 生成迁移种子(两者一致性由测试锁定)。
|
|
|
|
|
|
值一律以 Fraction 可解析字符串表示(如 "4/360",禁 0.011111 —— 见算法红线)。
|
2026-10-23 04:20:05 -04:00
|
|
|
|
|
|
|
|
|
|
`description` 会直接显示在「计提参数」页的参数名下方,**面向业务人员撰写**:
|
|
|
|
|
|
说清这个参数管什么、钱怎么变、什么时候该调它。不写英文枚举名、需求编号、
|
|
|
|
|
|
内部阶段号,也不写实现层面的精度约束(那些留在代码注释与测试里)。
|
2026-10-12 04:22:32 -04:00
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
from dataclasses import dataclass
|
|
|
|
|
|
from fractions import Fraction
|
|
|
|
|
|
|
|
|
|
|
|
from app.core.exceptions import BadRequestError
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass(frozen=True, slots=True)
|
|
|
|
|
|
class ParamSpec:
|
|
|
|
|
|
"""单个参数的元数据(与 param_definitions 表字段一一对应)。"""
|
|
|
|
|
|
|
|
|
|
|
|
code: str
|
|
|
|
|
|
name: str
|
|
|
|
|
|
group: str
|
|
|
|
|
|
value_type: str
|
|
|
|
|
|
unit: str | None
|
|
|
|
|
|
dimension_type: str
|
|
|
|
|
|
options: tuple[str, ...] | None
|
|
|
|
|
|
default_value: str | None
|
|
|
|
|
|
value_min: str | None
|
|
|
|
|
|
value_max: str | None
|
|
|
|
|
|
description: str | None
|
|
|
|
|
|
sort_order: int
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PARAM_REGISTRY: dict[str, ParamSpec] = {
|
|
|
|
|
|
spec.code: spec
|
|
|
|
|
|
for spec in [
|
|
|
|
|
|
ParamSpec(
|
|
|
|
|
|
code="salesperson.rate.start",
|
|
|
|
|
|
name="业务员起始计提比例",
|
|
|
|
|
|
group="业务员个人户",
|
|
|
|
|
|
value_type="DECIMAL",
|
|
|
|
|
|
unit="‰",
|
|
|
|
|
|
dimension_type="BUSINESS_ROLE",
|
|
|
|
|
|
options=None,
|
|
|
|
|
|
default_value="10",
|
|
|
|
|
|
value_min="0",
|
|
|
|
|
|
value_max=None,
|
2026-10-23 04:20:05 -04:00
|
|
|
|
description="回款当天能拿到的最高计提比例。回款每晚一天,按日递减斜率往下走,直到分界天数为止。",
|
2026-10-12 04:22:32 -04:00
|
|
|
|
sort_order=1,
|
|
|
|
|
|
),
|
|
|
|
|
|
ParamSpec(
|
|
|
|
|
|
code="salesperson.rate.slope",
|
|
|
|
|
|
name="业务员日递减斜率",
|
|
|
|
|
|
group="业务员个人户",
|
|
|
|
|
|
value_type="DECIMAL",
|
|
|
|
|
|
unit="‰/天",
|
|
|
|
|
|
dimension_type="BUSINESS_ROLE",
|
|
|
|
|
|
options=None,
|
|
|
|
|
|
default_value="4/360",
|
|
|
|
|
|
value_min="0",
|
|
|
|
|
|
value_max=None,
|
2026-10-23 04:20:05 -04:00
|
|
|
|
description="回款每延后一天,计提比例下降多少。按分数填写(如 4/360)可保持精确,填小数会引入四舍五入误差。",
|
2026-10-12 04:22:32 -04:00
|
|
|
|
sort_order=2,
|
|
|
|
|
|
),
|
|
|
|
|
|
ParamSpec(
|
|
|
|
|
|
code="salesperson.rate.floor",
|
|
|
|
|
|
name="业务员计提下限",
|
|
|
|
|
|
group="业务员个人户",
|
|
|
|
|
|
value_type="DECIMAL",
|
|
|
|
|
|
unit="‰",
|
|
|
|
|
|
dimension_type="BUSINESS_ROLE",
|
|
|
|
|
|
options=None,
|
|
|
|
|
|
default_value="4",
|
|
|
|
|
|
value_min="0",
|
|
|
|
|
|
value_max=None,
|
2026-10-23 04:20:05 -04:00
|
|
|
|
description="回款天数超过分界天数后,计提比例不再下降,固定按这个值计算,即最低计提比例。",
|
2026-10-12 04:22:32 -04:00
|
|
|
|
sort_order=3,
|
|
|
|
|
|
),
|
|
|
|
|
|
ParamSpec(
|
|
|
|
|
|
code="salesperson.days.boundary",
|
|
|
|
|
|
name="线性递减分界天数",
|
|
|
|
|
|
group="业务员个人户",
|
|
|
|
|
|
value_type="INT",
|
|
|
|
|
|
unit="天",
|
|
|
|
|
|
dimension_type="BUSINESS_ROLE",
|
|
|
|
|
|
options=None,
|
|
|
|
|
|
default_value="360",
|
|
|
|
|
|
value_min="0",
|
|
|
|
|
|
value_max=None,
|
2026-10-23 04:20:05 -04:00
|
|
|
|
description="回款天数在这个范围内按日递减;超过这个天数就固定按下限计提。默认 360 天。",
|
2026-10-12 04:22:32 -04:00
|
|
|
|
sort_order=4,
|
|
|
|
|
|
),
|
|
|
|
|
|
ParamSpec(
|
|
|
|
|
|
code="manager.share.team",
|
|
|
|
|
|
name="经理本团队分成比例",
|
|
|
|
|
|
group="经理分成",
|
|
|
|
|
|
value_type="DECIMAL",
|
|
|
|
|
|
unit="%",
|
|
|
|
|
|
dimension_type="BUSINESS_ROLE",
|
|
|
|
|
|
options=None,
|
|
|
|
|
|
default_value="12.5",
|
|
|
|
|
|
value_min="0",
|
|
|
|
|
|
value_max="100",
|
2026-10-23 04:20:05 -04:00
|
|
|
|
description="经理按本团队业务员的绩效总额提取的分成比例,只统计自己带的业务员。",
|
2026-10-12 04:22:32 -04:00
|
|
|
|
sort_order=5,
|
|
|
|
|
|
),
|
|
|
|
|
|
ParamSpec(
|
|
|
|
|
|
code="manager.share.company",
|
|
|
|
|
|
name="经理全公司分成比例",
|
|
|
|
|
|
group="经理分成",
|
|
|
|
|
|
value_type="DECIMAL",
|
|
|
|
|
|
unit="%",
|
|
|
|
|
|
dimension_type="BUSINESS_ROLE",
|
|
|
|
|
|
options=None,
|
|
|
|
|
|
default_value="5",
|
|
|
|
|
|
value_min="0",
|
|
|
|
|
|
value_max="100",
|
2026-10-23 04:20:05 -04:00
|
|
|
|
description="经理按全公司业务员的绩效总额提取的分成比例,与本团队分成叠加计算。",
|
2026-10-12 04:22:32 -04:00
|
|
|
|
sort_order=6,
|
|
|
|
|
|
),
|
|
|
|
|
|
ParamSpec(
|
|
|
|
|
|
code="enterprise.rate",
|
|
|
|
|
|
name="企业户计提比例",
|
|
|
|
|
|
group="企业户",
|
|
|
|
|
|
value_type="DECIMAL",
|
|
|
|
|
|
unit="‰",
|
|
|
|
|
|
dimension_type="PRODUCT_CATEGORY",
|
|
|
|
|
|
options=None,
|
|
|
|
|
|
default_value="3",
|
|
|
|
|
|
value_min="0",
|
|
|
|
|
|
value_max=None,
|
2026-10-23 04:20:05 -04:00
|
|
|
|
description="企业户客户的回款统一按这个比例计提,不看回款天数。2026-08-13 起由 2‰ 调整为 3‰。",
|
2026-10-12 04:22:32 -04:00
|
|
|
|
sort_order=7,
|
|
|
|
|
|
),
|
|
|
|
|
|
ParamSpec(
|
|
|
|
|
|
code="info.rate",
|
|
|
|
|
|
name="信息员计提比例",
|
|
|
|
|
|
group="信息员",
|
|
|
|
|
|
value_type="DECIMAL",
|
|
|
|
|
|
unit="‰",
|
|
|
|
|
|
dimension_type="BUSINESS_ROLE",
|
|
|
|
|
|
options=None,
|
|
|
|
|
|
default_value="1",
|
|
|
|
|
|
value_min="0",
|
|
|
|
|
|
value_max=None,
|
2026-10-23 04:20:05 -04:00
|
|
|
|
description="信息员的绩效按本人销售额乘这个比例计算,不随回款天数递减。",
|
2026-10-12 04:22:32 -04:00
|
|
|
|
sort_order=8,
|
|
|
|
|
|
),
|
|
|
|
|
|
ParamSpec(
|
|
|
|
|
|
code="prepay.rate",
|
|
|
|
|
|
name="预付款计提比例",
|
|
|
|
|
|
group="支付环节",
|
|
|
|
|
|
value_type="DECIMAL",
|
|
|
|
|
|
unit="‰",
|
|
|
|
|
|
dimension_type="NONE",
|
|
|
|
|
|
options=None,
|
|
|
|
|
|
default_value="10",
|
|
|
|
|
|
value_min="0",
|
|
|
|
|
|
value_max=None,
|
2026-10-23 04:20:05 -04:00
|
|
|
|
description="预付款到账即按这个比例计提绩效,不必等到全额回款。",
|
2026-10-12 04:22:32 -04:00
|
|
|
|
sort_order=9,
|
|
|
|
|
|
),
|
|
|
|
|
|
ParamSpec(
|
|
|
|
|
|
code="barter.discount",
|
|
|
|
|
|
name="以物抵顶折算比例",
|
|
|
|
|
|
group="支付环节",
|
|
|
|
|
|
value_type="DECIMAL",
|
|
|
|
|
|
unit="%",
|
|
|
|
|
|
dimension_type="NONE",
|
|
|
|
|
|
options=None,
|
|
|
|
|
|
default_value="80",
|
|
|
|
|
|
value_min="0",
|
|
|
|
|
|
value_max="100",
|
2026-10-23 04:20:05 -04:00
|
|
|
|
description="以物抵顶的回款,按应发绩效的这个比例折算,即打折后的金额参与绩效。",
|
2026-10-12 04:22:32 -04:00
|
|
|
|
sort_order=10,
|
|
|
|
|
|
),
|
|
|
|
|
|
ParamSpec(
|
|
|
|
|
|
code="payment.start.ratio",
|
|
|
|
|
|
name="支付起付比例",
|
|
|
|
|
|
group="支付环节",
|
|
|
|
|
|
value_type="DECIMAL",
|
|
|
|
|
|
unit="%",
|
|
|
|
|
|
dimension_type="NONE",
|
|
|
|
|
|
options=None,
|
|
|
|
|
|
default_value="60",
|
|
|
|
|
|
value_min="0",
|
|
|
|
|
|
value_max="100",
|
2026-10-23 04:20:05 -04:00
|
|
|
|
description="单项业务的回款累计达到销售额(不含运费)的这个比例后才开始发放绩效;达标之前只累计、不发放。",
|
2026-10-12 04:22:32 -04:00
|
|
|
|
sort_order=11,
|
|
|
|
|
|
),
|
|
|
|
|
|
ParamSpec(
|
|
|
|
|
|
code="payment.weight.mode",
|
|
|
|
|
|
name="支付权重应用方式",
|
|
|
|
|
|
group="支付环节",
|
|
|
|
|
|
value_type="ENUM",
|
|
|
|
|
|
unit=None,
|
|
|
|
|
|
dimension_type="NONE",
|
|
|
|
|
|
options=("FULL", "BALANCE"),
|
|
|
|
|
|
default_value="FULL",
|
|
|
|
|
|
value_min=None,
|
|
|
|
|
|
value_max=None,
|
2026-10-23 04:20:05 -04:00
|
|
|
|
description="选择支付权重乘在哪个基数上:当月全额 = 乘本月全部应发绩效;余额 = 只乘尚未发放的部分。",
|
2026-10-12 04:22:32 -04:00
|
|
|
|
sort_order=12,
|
|
|
|
|
|
),
|
|
|
|
|
|
ParamSpec(
|
|
|
|
|
|
code="product.threshold",
|
|
|
|
|
|
name="折算毛利润额阈值",
|
|
|
|
|
|
group="产品阈值",
|
|
|
|
|
|
value_type="DECIMAL",
|
|
|
|
|
|
unit="%",
|
|
|
|
|
|
dimension_type="PRODUCT_CATEGORY",
|
|
|
|
|
|
options=None,
|
|
|
|
|
|
default_value="30",
|
|
|
|
|
|
value_min="0",
|
|
|
|
|
|
value_max="100",
|
2026-10-23 04:20:05 -04:00
|
|
|
|
description="折算毛利润额 = 销售额 ×(毛利润率 − 阈值),低于阈值的部分不参与绩效。市政水利默认 30%,轨道交通默认 20%。",
|
2026-10-12 04:22:32 -04:00
|
|
|
|
sort_order=13,
|
|
|
|
|
|
),
|
|
|
|
|
|
ParamSpec(
|
|
|
|
|
|
code="salary.basic.mode",
|
|
|
|
|
|
name="月工资基本工资口径",
|
|
|
|
|
|
group="月工资口径",
|
|
|
|
|
|
value_type="ENUM",
|
|
|
|
|
|
unit=None,
|
|
|
|
|
|
dimension_type="BUSINESS_ROLE",
|
|
|
|
|
|
options=("INCLUDE", "DEDUCT", "EXCLUDE"),
|
|
|
|
|
|
default_value="INCLUDE",
|
|
|
|
|
|
value_min=None,
|
|
|
|
|
|
value_max=None,
|
2026-10-23 04:20:05 -04:00
|
|
|
|
description="算月工资时怎么处理基本工资:含基本工资 = 与绩效一起发;扣除基本工资 = 从绩效里扣掉已发的基本工资;不计 = 月工资只发绩效。",
|
2026-10-12 04:22:32 -04:00
|
|
|
|
sort_order=14,
|
|
|
|
|
|
),
|
|
|
|
|
|
ParamSpec(
|
|
|
|
|
|
code="probation.annual.threshold",
|
|
|
|
|
|
name="试用期年累计结算阈值",
|
|
|
|
|
|
group="月工资口径",
|
|
|
|
|
|
value_type="DECIMAL",
|
|
|
|
|
|
unit="元",
|
|
|
|
|
|
dimension_type="NONE",
|
|
|
|
|
|
options=None,
|
|
|
|
|
|
default_value="18000",
|
|
|
|
|
|
value_min="0",
|
|
|
|
|
|
value_max=None,
|
2026-10-23 04:20:05 -04:00
|
|
|
|
description="试用期绩效先不发放;年内累计超过这个金额的部分,年底一次性结算。",
|
2026-10-12 04:22:32 -04:00
|
|
|
|
sort_order=15,
|
|
|
|
|
|
),
|
2026-10-15 05:25:23 -04:00
|
|
|
|
ParamSpec(
|
|
|
|
|
|
code="approval.secondary_allocation.enabled",
|
|
|
|
|
|
name="二次分配审批开关",
|
|
|
|
|
|
group="审批开关",
|
|
|
|
|
|
value_type="BOOL",
|
|
|
|
|
|
unit=None,
|
|
|
|
|
|
dimension_type="NONE",
|
|
|
|
|
|
options=None,
|
2026-10-18 23:09:05 -04:00
|
|
|
|
default_value="1",
|
2026-10-15 05:25:23 -04:00
|
|
|
|
value_min=None,
|
|
|
|
|
|
value_max=None,
|
2026-10-23 04:20:05 -04:00
|
|
|
|
description="二次分配方案提交后是否要审批:开启 = 先经财务复核、再经领导审核,通过后才生效;关闭 = 提交即生效,系统自动记录各节点留痕。",
|
2026-10-15 05:25:23 -04:00
|
|
|
|
sort_order=17,
|
|
|
|
|
|
),
|
|
|
|
|
|
ParamSpec(
|
|
|
|
|
|
code="approval.monthly_settlement.enabled",
|
|
|
|
|
|
name="月度结算审批开关",
|
|
|
|
|
|
group="审批开关",
|
|
|
|
|
|
value_type="BOOL",
|
|
|
|
|
|
unit=None,
|
|
|
|
|
|
dimension_type="NONE",
|
|
|
|
|
|
options=None,
|
2026-10-18 23:09:05 -04:00
|
|
|
|
default_value="1",
|
2026-10-15 05:25:23 -04:00
|
|
|
|
value_min=None,
|
|
|
|
|
|
value_max=None,
|
2026-10-23 04:20:05 -04:00
|
|
|
|
description="月度结算提交后是否要审批:开启 = 先经财务复核、再经领导审核;关闭 = 生成即生效。月结涉及工资发放,默认开启。",
|
2026-10-15 05:25:23 -04:00
|
|
|
|
sort_order=18,
|
|
|
|
|
|
),
|
2026-10-16 04:31:25 -04:00
|
|
|
|
ParamSpec(
|
|
|
|
|
|
code="approval.adjustment.enabled",
|
|
|
|
|
|
name="调整单审批开关",
|
|
|
|
|
|
group="审批开关",
|
|
|
|
|
|
value_type="BOOL",
|
|
|
|
|
|
unit=None,
|
|
|
|
|
|
dimension_type="NONE",
|
|
|
|
|
|
options=None,
|
|
|
|
|
|
default_value="0",
|
|
|
|
|
|
value_min=None,
|
|
|
|
|
|
value_max=None,
|
2026-10-23 04:20:05 -04:00
|
|
|
|
description="调整单提交后是否要审批:开启 = 先经财务复核、再经领导审核;关闭 = 提交即生效。调整单是已锁定月份补发或扣减的唯一通道。",
|
2026-10-16 04:31:25 -04:00
|
|
|
|
sort_order=19,
|
|
|
|
|
|
),
|
2026-10-18 23:09:05 -04:00
|
|
|
|
ParamSpec(
|
|
|
|
|
|
code="manager.personal.included",
|
|
|
|
|
|
name="经理个人户计入聚合基数",
|
|
|
|
|
|
group="经理分成",
|
|
|
|
|
|
value_type="BOOL",
|
|
|
|
|
|
unit=None,
|
|
|
|
|
|
dimension_type="NONE",
|
|
|
|
|
|
options=None,
|
|
|
|
|
|
default_value="0",
|
|
|
|
|
|
value_min=None,
|
|
|
|
|
|
value_max=None,
|
2026-10-23 04:20:05 -04:00
|
|
|
|
description="经理提取团队分成时,是否把经理本人名下的业绩(经理个人户)也算进分成基数。默认不计入。",
|
2026-10-18 23:09:05 -04:00
|
|
|
|
sort_order=20,
|
|
|
|
|
|
),
|
2026-10-19 06:44:15 -04:00
|
|
|
|
# ===== 预警规则(M4 ⑧ 工作台,澄清 #10「做成参数化规则便于调整」)=====
|
|
|
|
|
|
# 首批三条中「同步连续失败」依赖 ⑥ T+ 同步,模块未建前不设参数、不产生条目
|
|
|
|
|
|
ParamSpec(
|
|
|
|
|
|
code="warning.enabled",
|
|
|
|
|
|
name="风险预警总开关",
|
|
|
|
|
|
group="预警规则",
|
|
|
|
|
|
value_type="BOOL",
|
|
|
|
|
|
unit=None,
|
|
|
|
|
|
dimension_type="NONE",
|
|
|
|
|
|
options=None,
|
|
|
|
|
|
default_value="1",
|
|
|
|
|
|
value_min=None,
|
|
|
|
|
|
value_max=None,
|
2026-10-23 04:20:05 -04:00
|
|
|
|
description="工作台风险预警区块的总开关:关闭后不再扫描、也不展示预警条目。默认开启。",
|
2026-10-19 06:44:15 -04:00
|
|
|
|
sort_order=21,
|
|
|
|
|
|
),
|
|
|
|
|
|
ParamSpec(
|
|
|
|
|
|
code="warning.receipt.overdue.days",
|
|
|
|
|
|
name="回款逾期天数阈值",
|
|
|
|
|
|
group="预警规则",
|
|
|
|
|
|
value_type="INT",
|
|
|
|
|
|
unit="天",
|
|
|
|
|
|
dimension_type="NONE",
|
|
|
|
|
|
options=None,
|
|
|
|
|
|
default_value="90",
|
|
|
|
|
|
value_min="1",
|
|
|
|
|
|
value_max=None,
|
2026-10-23 04:20:05 -04:00
|
|
|
|
description="发货后超过这么多天仍未收到回款的发货批次,会出现在工作台的预警列表里。默认 90 天。",
|
2026-10-19 06:44:15 -04:00
|
|
|
|
sort_order=22,
|
|
|
|
|
|
),
|
|
|
|
|
|
ParamSpec(
|
|
|
|
|
|
code="warning.approval.timeout.days",
|
|
|
|
|
|
name="审批超时天数阈值",
|
|
|
|
|
|
group="预警规则",
|
|
|
|
|
|
value_type="INT",
|
|
|
|
|
|
unit="天",
|
|
|
|
|
|
dimension_type="NONE",
|
|
|
|
|
|
options=None,
|
|
|
|
|
|
default_value="3",
|
|
|
|
|
|
value_min="1",
|
|
|
|
|
|
value_max=None,
|
2026-10-23 04:20:05 -04:00
|
|
|
|
description="审批单提交后超过这么多天还没处理,会出现在工作台的预警列表里。默认 3 天。",
|
2026-10-19 06:44:15 -04:00
|
|
|
|
sort_order=23,
|
|
|
|
|
|
),
|
2026-10-12 04:22:32 -04:00
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_spec(code: str) -> ParamSpec:
|
|
|
|
|
|
"""取参数元数据。未注册编码属代码缺陷(500),不是用户错误。"""
|
|
|
|
|
|
spec = PARAM_REGISTRY.get(code)
|
|
|
|
|
|
if spec is None:
|
|
|
|
|
|
raise ValueError(f"参数编码未注册:{code}")
|
|
|
|
|
|
return spec
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def parse_fraction(text: str) -> Fraction:
|
|
|
|
|
|
"""Fraction 精确解析("4/360" → 1/90,不经 float)。非法输入抛 400。"""
|
|
|
|
|
|
try:
|
|
|
|
|
|
return Fraction(text.strip())
|
|
|
|
|
|
except (ValueError, ZeroDivisionError) as exc:
|
|
|
|
|
|
raise BadRequestError(f"参数值无法解析为数值:{text}") from exc
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def validate_and_normalize(spec: ParamSpec, raw: str) -> str:
|
|
|
|
|
|
"""按元数据校验并规范化参数值,返回可入库字符串。
|
|
|
|
|
|
|
|
|
|
|
|
DECIMAL:Fraction 解析 + 取值域校验,分数式原样保留("4/360" 不截断);
|
|
|
|
|
|
INT:必须整数;BOOL:仅 0/1;ENUM:必须命中 options;TEXT:原样返回。
|
|
|
|
|
|
"""
|
|
|
|
|
|
value = raw.strip()
|
|
|
|
|
|
if spec.value_type in {"DECIMAL", "INT"}:
|
|
|
|
|
|
fraction = parse_fraction(value)
|
|
|
|
|
|
if spec.value_type == "INT" and fraction.denominator != 1:
|
|
|
|
|
|
raise BadRequestError(f"参数 {spec.code} 必须为整数:{raw}")
|
|
|
|
|
|
if spec.value_min is not None and fraction < parse_fraction(spec.value_min):
|
|
|
|
|
|
raise BadRequestError(f"参数 {spec.code} 低于取值下限 {spec.value_min}:{raw}")
|
|
|
|
|
|
if spec.value_max is not None and fraction > parse_fraction(spec.value_max):
|
|
|
|
|
|
raise BadRequestError(f"参数 {spec.code} 高于取值上限 {spec.value_max}:{raw}")
|
|
|
|
|
|
return value
|
|
|
|
|
|
if spec.value_type == "BOOL":
|
|
|
|
|
|
if value not in {"0", "1"}:
|
|
|
|
|
|
raise BadRequestError(f"参数 {spec.code} 仅接受 0/1:{raw}")
|
|
|
|
|
|
return value
|
|
|
|
|
|
if spec.value_type == "ENUM":
|
|
|
|
|
|
if not spec.options or value not in spec.options:
|
|
|
|
|
|
allowed = "/".join(spec.options or ())
|
|
|
|
|
|
raise BadRequestError(f"参数 {spec.code} 取值须为 {allowed}:{raw}")
|
|
|
|
|
|
return value
|
|
|
|
|
|
return value
|