certflow.services.output_guard module

统一输出护栏管道(print/scan 共用,配置驱动,与 UI 解耦)。

设计原则(docs/PRINT_BLUEPRINT.md §11.5 / §11.8 阶段1): - 本模块为**纯逻辑层**,不依赖 PySide6 / 任何 UI 框架,便于 pytest 无头测试。 - 所有「用户交互」(弹输入框补录、确认闸口)通过 GuardPrompt 协议注入,

view 层负责提供 PyQt 实现(如 print_view._QtGuardPrompt),scan 可注入非交互实现。

  • 历史差异比对(④ reconfirm_on_diff)依赖调用方传入 history_last``(由 :class:`~certflow.services.print_history_service.HistoryBackfillService` 提供, ``PrintLog 聚合的「同型号上次实际值」);历史源缺失时该字段自动跳过差异闸。

管道顺序(与旧 print_view._guard_before_print 等价并补 ④):

② 必填补录 / ③ reconfirm(即使有值也确认) ④ 与历史差异确认(reconfirm_on_diff) ⑤ 确认闸口(confirmation.summary_fields 预览)

任一环节用户取消 → 返回 (False, data),调用方应中止本批(及多计划剩余批)。

certflow.services.output_guard.field_label(key)[源代码]

字段 key → 中文标签(取不到回退 key 本身)。

参数:

key (str)

返回类型:

str

class certflow.services.output_guard.GuardPrompt(*args, **kwargs)[源代码]

基类:Protocol

护栏与用户交互的抽象接口。

  • prompt_field:请求用户补全/确认某字段,返回字符串或 ``None``(用户取消)。

  • confirm:确认闸口,返回是否继续。

prompt_field(*, key, label, current, suggestion)[源代码]
参数:
返回类型:

str | None

confirm(*, message)[源代码]
参数:

message (str)

返回类型:

bool

certflow.services.output_guard.collect_incomplete(data, fields)[源代码]

非交互完整性闸门:返回 fields 中值为空的字段 key 列表。

供 scan 视图在生成前检查合格证必填信息是否齐全(缺失即中止,不弹输入框)。

参数:
返回类型:

list[str]

certflow.services.output_guard.family_requires_pn_unit(family)[源代码]

中文合格证底版已预印压力单位 → 不要求填单位;中英文/全英文/俄英文必须带单位。

参数:

family (str) -- 语言族(全中文/中英文/全英文/俄英文,来自 family_of)。

返回类型:

bool

certflow.services.output_guard.scan_required_fields_for(family, base)[源代码]

按模板语言族计算扫描件必填字段(配置 base + 压力字段门限)。

  • 公称压力数值(pn_value)任何族都必填;

  • 中文族:底版预印单位,不要求 pn_unit;其余族必须带 pn_unit

参数:
返回类型:

list[str]

certflow.services.output_guard.validate_pn_text(family, raw)[源代码]

校验压力文本是否符合模板族的单位要求,返回错误提示(空串表示通过)。

pn_display 为权威输入串(任意格式),本函数只做「门限」把关,不做改写:

  • 中文族:底板预印单位,放行不设置门限。用户输入数值(如 25.0)保存时 默认补 MPa;若输入带单位(32.0MPa 或英制 1500Lb),渲染层按族处理 (MPa 剥离、非 MPa 的 Lb 保留,见 format_pn),本函数不拦截;

  • 其余族(中英文/全英文/俄英文):**必须带单位**(如 2.5MPa / 150Lb), 缺单位返回错误提示,阻断保存/入队以强制补齐(避免打印出无单位的压力文本)。

参数:
返回类型:

str

certflow.services.output_guard.diff_fields(data, history_last, diff_keys)[源代码]

计算与历史差异的项,返回 (key, current, history) 列表。

仅当历史有值、当前有值、且两者不同才计入(空历史/空当前不触发差异闸)。

参数:
返回类型:

list[tuple[str, str, str]]

certflow.services.output_guard.run_guard(data, *, guard, prompt, history_last=None, multi=False)[源代码]

统一护栏管道。返回 (ok, updated_data)

顺序:② 必填补录 / ③ reconfirm → ④ 差异确认 → ⑤ 确认闸口。 任一环节用户取消 → 返回 (False, data),调用方应中止本批(及多计划剩余批)。

参数:
  • data (dict[str, Any]) -- 当前合格证字段字典(不会被原地修改,返回副本)。

  • guard (dict[str, Any]) -- print.guard 段(来自 cfg("print.guard"),dict 结构)。

  • prompt (GuardPrompt) -- 交互实现(PyQt 或非交互)。

  • history_last (dict[str, str] | None) -- 同型号上次实际值(Certificate 字段名 → 值),缺省跳过差异闸。

  • multi (bool) -- 是否多计划批量(影响确认闸口的 single/multi_batch 开关)。

返回类型:

tuple[bool, dict[str, Any]]