Files
QTImport/README.md
T
chenshoulin 58850314cf 初始提交:QuickTeam 工单接口导入工具
用「WCF + 通用存储过程网关」接口替代 Selenium(D://Learning//Python//工单自动化)导入工单:
单 Sprint 12 个项目 175s 跑完(旧方案 25~35 分钟),失败可断点续跑且不重复建单。

- 分层:transport(HTTP/协议)/ api(存储过程语义)/ domain(纯规则)/
  workflow(阶段编排)/ store(SQLite 台账)/ report / CLI
- 幂等:台账驱动断点续跑;dry-run 与跳过行不污染进度;--rollback-on-fail 清理半成品
- 命令:plan / apply / report / status,真实写入需 --yes
- tools:只读探针、存储过程源码导出(sp_helptext)、导入诊断
- docs:调研与设计文档(含联调踩到的 5 个坑)+ 6 个关键存储过程源码

实测:Sprint 2026 Sprint 10 的 12 个项目全部完成建单→导入→确认→推送 TFS,
工单 225134–225145,35 个功能模块,重跑 plan 全部 skip-pushed。69 个单测通过。
2026-11-05 19:14:25 +08:00

5.9 KiB
Raw Blame History

QTImport

通过接口(而非浏览器自动化)把工单数据批量导入 QuickTeam 的项目。

替代 D:\Learning\Python\工单自动化\auto_quickteam.py(Selenium 版):单项目 2~3 分钟、依赖 DOM、易随前端改版失效,失败重跑还可能重复建单。

状态

阶段 内容 状态
M0 接口调研 + 只读探针 ✅ 完成
M1 读链路(登录/项目/工单/上传/TFS 上下文) ✅ 完成,已在生产实测
M2 写入链路(建单/填单/导入/确认/推送) ✅ 完成,单项目已真实写入并核对落库
M3 幂等台账、断点续跑、回滚、报告 ✅ 完成,69 个单测通过
M4 真实项目联调 + 灰度 ✅ 12 个项目已真实执行(工单 225134–225145)

全量实测:Sprint 2026 Sprint 10 的 12 个项目全部建单 → 导入明细(33 个功能模块,逐文件与 Excel 核对一致) → 确认 → 推送 TFS,整轮 175 s(旧方案同流程约 25~35 分钟),重跑 plan 全部 skip-pushed。设计文档与联调踩坑记录: docs/QuickTeam-API导入-调研与设计.md §8。

为什么可行

QuickTeam 前端是 Vue SPA,业务数据全部经一层「WCF + 通用存储过程网关」读写:

POST /Services/CommonService.svc/ExecTable
{ "connectionName": "QuickTeam", "param": "<encodeURIComponent(SPName+SQLParams)>" }

前端本身就是这套接口的客户端,复刻调用序列即可绕开浏览器与 DOM。实测:登录 0.5s、215 个项目 1.7s、 单项目工单查询 1.05s、文件上传 0.19s;12 个项目的完整演练 19s(旧方案约 25~35 分钟)。

快速开始

cp config/config.example.json config/config.json    # 填账号、Sprint、目录、起止日期

凭据可用环境变量覆盖,避免落盘:export QT_PASSWORD=***。

# 1. 只读预演:能做什么、为什么跳过
python -m qtimport plan --config config/config.json

# 2. 演练完整链路(不发任何写请求,打印每一步的真实参数)
python -m qtimport apply --config config/config.json --dry-run

# 3. 真实执行(必须显式 --yes)
python -m qtimport apply --config config/config.json --yes

# 4. 看状态与报告
python -m qtimport status --config config/config.json
python -m qtimport report --config config/config.json

plan 输出:

项目                       动作          说明
信托 - 上海信托                create      本项目该 Sprint 无工单
资管 - 华泰保险资管             create      本项目该 Sprint 无工单
资管 - 华泰资管                create      本项目该 Sprint 无工单

幂等与续跑

  • 业务唯一键 (ProjectId, SystemName):同一项目同一 Sprint 只建一张工单。
  • 台账在 state/qtimport.db(SQLite),每推进一个阶段落一次,中断后重跑自动从断点继续。
  • 已存在但无台账记录的工单默认跳过(不接管别人的单);确认要接管加 --adopt。
  • 已推送 TFS 的不再推;失败时可用 --rollback-on-fail 删掉本次新建的半成品(已推送的绝不删)。

常用参数:

参数 用途
--project "资管 - 粤海资本" 只处理指定项目(可多次)
--limit 1 只跑前 1 个,联调用
--skip-tfs 只建单+导入+确认,不推送
--adopt 接管无台账记录的既有工单
--rollback-on-fail 失败时回滚本次新建的半成品
--workers 3 并发数(默认取配置,写路径建议 ≤4)
--force 跳过 Excel 模板预检

联调(唯一剩余的验证)

第一次真实写入建议这样跑,只影响一个项目:

python -m qtimport apply --config config/config.json \
  --project "资管 - 粤海资本" --limit 1 --skip-tfs --rollback-on-fail --yes

预期:建单 → 填 17 个字段 → 上传 xlsx → 服务器解析明细 → 确认工单(技术责任人确认版 → 客户责任人确认版)。 然后到 QuickTeam 页面上核对:工单数、明细行数、三个责任人、起止日期、状态。 核对无误后再去掉 --skip-tfs 验证推送,最后 --limit 1 换成全量。

注意:config.start_time / end_time 会原样写进工单,执行前务必确认为该 Sprint 的真实区间。

目录

QTImport/
├── config/
│   ├── config.example.json     # 模板
│   └── config.json             # 含凭据,已 gitignore
├── docs/
│   └── QuickTeam-API导入-调研与设计.md
├── qtimport/
│   ├── transport.py            # WCF 网关:双层 JSON、错误解析、裸字节上传
│   ├── api.py                  # 存储过程语义封装
│   ├── domain.py               # 项目匹配、动作判定、版本推进、Excel 预检
│   ├── workflow.py             # 阶段编排、并发、回滚
│   ├── store.py                # SQLite 台账
│   ├── report.py               # summary.md / detail.csv / JSONL
│   └── __main__.py             # CLI
├── tools/
│   └── api_probe.py            # 只读探针(零依赖,可独立交付)
└── tests/                      # 69 个用例,无需网络

测试

python -m unittest discover -s tests -t .

覆盖:双层 JSON 解码、WCF 错误分类、项目名精确匹配(避免 contains 误命中)、 动作判定全分支、版本推进、Excel 预检、17 个参数构造、Column1 判定、TFS 路径解析、 dry-run 隔离、断点续跑、失败归属与回滚。

环境

Python 3.12+,零第三方依赖,不需要浏览器。需能访问 http://192.168.1.213。

注意

  • ExecTable 网关无身份校验,本工具只在内网执行;请使用个人账号(Operator 会写入真实姓名,便于审计)。
  • 凭据不要提交:config/config.json、state/、reports/、logs/ 均在 .gitignore 中。