feat(task): 规则模板 FORM 真正可套用 + 已归档任务可删(客户确认的两项)
一、规则模板的 FORM 部分(F-57/F-64)—— 此前只能「跳过并说明」,等于装饰
· FormSchemaService.saveRawVersion:用已存在的 schemaJson 存为新版本。
与手工保存的区别:内容不再校验/归一化(它当初就是按本服务规则存出来的,
再走一遍解析→序列化只会丢未建模字段);状态检查与版本管理保留 —— 版本化
逻辑只有一份
· RuleTemplateService 的 FORM 分支接上它(不再 skipped)
· 顺带补上另一半:saveAsTemplate 此前不存表单(存模板不存、套模板用不上,
两头各缺一半)—— 现在把源任务的当前表单一并带走;没存过 = null =
套用时按「用系统默认,不覆盖」跳过
二、已归档任务可删(F-14 / §17.2 D-9)—— 此前「已发布即删不掉」,
演示/测试任务只能改名挪开,库只增不减
· DELETE /tasks/{id} 支持 status=3:收集中/已截止仍拒(归档是最后的后悔药),
拒绝的话说清「先归档」
· 子表级联物理删 14 张表(TaskCascadeMapper 集中放置,表清单来自
information_schema 的事实核对)—— 大头是名册(证件号密文)、材料、审核记录
· ★ 任务行本身**软删**:它必须占住 task_code —— maxSeqByCodePrefix 靠
「含软删行的最大序号」保证编码永不复用(编码同时是文件目录名,重号会把
两批任务的文件混进同一目录)。第一版做成了物理删,e2e-m1-task 的
「编码递增」断言当场抓到重号 —— 这条回归现在被 e2e-m1-task-delete
的「删除后新建不重号」断言守住
· 物理文件尽力删(先取路径再删行,顺序反了文件就永远留在磁盘上;
删不掉只记日志不阻断);全程留痕(sys_operation_log 记 DELETE_TASK +
行数/文件数)
验证:e2e-m7-taskconfig → 75/75(新增 FORM 完整链路 7 条断言)
e2e-m1-task-delete(新增)→ 20/20(拒删/删净/占号软删/留痕/再删报错/草稿直删)
e2e-m1-task → 71/71(旧口径断言更新为新口径)
This commit is contained in:
@@ -262,12 +262,52 @@ def main():
|
||||
check("⭐ 模板的 useCount 被 +1(用户能看出哪个模板常用)",
|
||||
use_after == use_before + 1, "前 %d → 后 %d" % (use_before, use_after))
|
||||
|
||||
# 只应用 FORM:应该 skipped 且说明原因
|
||||
# 只应用 FORM(公共模板没带表单定义):应该明确 skipped 且说明原因
|
||||
ap2 = body_of("POST", "/api/v1/rule-templates/%d/apply" % tpl_id, at,
|
||||
{"targetTaskId": tgt, "parts": ["FORM"]})
|
||||
check("⭐ 只应用 FORM 时明确 skipped + 原因(公共模板的 form_schema 为空)",
|
||||
len((ap2.get("data") or {}).get("skipped") or []) >= 1,
|
||||
json.dumps(ap2.get("data"), ensure_ascii=False)[:300])
|
||||
|
||||
# ── FORM 的完整链路(2026-09-30 接上,F-64:此前只能"跳过并说明",模板的 FORM 部分是装饰)──
|
||||
print(" FORM 完整链路:存表单 → 存模板(带表单)→ 套用到另一个草稿")
|
||||
fs = body_of("GET", "/api/v1/tasks/%d/form-schema" % tgt, at).get("data") or {}
|
||||
save_fs = body_of("PUT", "/api/v1/tasks/%d/form-schema" % tgt, at, {
|
||||
"baseVersion": fs.get("version"),
|
||||
"fields": fs.get("fields") or [],
|
||||
# ⚠️ 扩展字段的 key 必须以 extra_ 开头(服务端规则,写错会 40001)
|
||||
"extras": [{"key": "extra_e2e", "label": "E2E扩展字段", "type": "text"}],
|
||||
})
|
||||
check("⭐ 给草稿任务存一份表单(v1,带一个扩展字段)",
|
||||
save_fs.get("code") == 0 and (save_fs.get("data") or {}).get("version") == 1,
|
||||
json.dumps(save_fs, ensure_ascii=False)[:200])
|
||||
tpl2 = body_of("POST", "/api/v1/tasks/%d/save-as-template" % tgt, at,
|
||||
{"templateName": "E2E表单模板" + suffix})
|
||||
check("存为模板成功", tpl2.get("code") == 0, json.dumps(tpl2, ensure_ascii=False)[:160])
|
||||
tpl2_id = ((tpl2.get("data") or {}).get("templateId"))
|
||||
has_fs = sql("select (form_schema is not null)::text from collect_rule_template where id=%s;"
|
||||
% tpl2_id).strip()
|
||||
check("⭐ 模板把表单定义也存进去了(此前存模板不存表单,F-64 的前一半)",
|
||||
has_fs == "true", "form_schema is not null = %s" % has_fs)
|
||||
_, b3 = R.call("POST", BASE + "/api/v1/tasks", at, {
|
||||
"taskName": "E2E套表单 " + suffix, "batchNo": "202609", "majorName": "数控加工",
|
||||
"collectMode": 1, "certType": 1, "startTime": "2026-01-01", "endTime": "2026-12-31"
|
||||
})
|
||||
tgt2 = b3["data"]["id"]
|
||||
CREATED_TASK_IDS.append(tgt2)
|
||||
apf = body_of("POST", "/api/v1/rule-templates/%s/apply" % tpl2_id, at,
|
||||
{"targetTaskId": tgt2, "parts": ["FORM"]})
|
||||
check("⭐ FORM 部分真的应用了(不再「跳过并说明」)",
|
||||
"FORM" in ((apf.get("data") or {}).get("applied") or []),
|
||||
json.dumps(apf.get("data"), ensure_ascii=False)[:200])
|
||||
rows2 = sql("select count(*) from collect_form_schema where task_id=%d;" % tgt2).strip()
|
||||
check("⭐ 目标任务有了版本化的表单行(套用走 FormSchemaService 的版本化保存)",
|
||||
rows2 >= "1", "collect_form_schema 行数=%s" % rows2)
|
||||
# schema_json 是 jsonb:LIKE 之前要 ::text
|
||||
got_extra = sql("select (schema_json::text like '%%extra_e2e%%')::text "
|
||||
"from collect_form_schema where task_id=%d "
|
||||
"order by version desc limit 1;" % tgt2).strip()
|
||||
check("套过去的就是源任务那份定义(含 extra_e2e 扩展字段)", got_extra == "true", got_extra)
|
||||
bad_parts = body_of("POST", "/api/v1/rule-templates/%d/apply" % tpl_id, at,
|
||||
{"targetTaskId": tgt, "parts": ["NOPE"]})
|
||||
check("parts 写错 → 明确报错并列出合法值",
|
||||
@@ -568,9 +608,10 @@ def cleanup():
|
||||
R.sql("delete from collect_roster where task_id=%d;" % tid)
|
||||
R.sql("delete from collect_task_org where task_id=%d;" % tid)
|
||||
R.sql("delete from collect_material_def where task_id=%d;" % tid)
|
||||
R.sql("delete from collect_form_schema where task_id=%d;" % tid)
|
||||
R.sql("delete from collect_task where id=%d;" % tid)
|
||||
R.sql("delete from collect_rule_template where template_name like 'E2E自建模板%' "
|
||||
"or template_name like 'E2E公共尝试%';")
|
||||
"or template_name like 'E2E公共尝试%' or template_name like 'E2E表单模板%';")
|
||||
R.sql("update collect_rule_template set use_count=0 where id in (1,2);")
|
||||
R.sql("delete from collect_message where user_id in (995111, 995112);")
|
||||
R.sql("delete from sys_user_role where user_id = 995101;")
|
||||
|
||||
Reference in New Issue
Block a user