[VOD Agent] 任务已完成。


[VOD Agent] 已结构化收敛需求:
目标
修复同一工单重复评价导致工人 ORDERS_NUMBER 重复累加、修改评分污染 AVG_GRADE 的缺陷。
现状
mock_backend.py 的 student_order_end 函数(1675–1714 行,PATCH /student/order-end)在每次评价时无条件执行 ORDERS_NUMBER + 1 和 AVG_GRADE * ORDERS_NUMBER + grade 累加,未区分首次评价、相同评价重试和已有评价修改三种场景。开发者已提供隔离复现验证:同一订单三次提交后 ORDERS_NUMBER 从 0 累加到 3,AVG_GRADE 从 10.0 变为 6.7(实际订单行数仍为 1)。
期望行为
- 相同工单相同评价重试:不增加订单计数,不改变平均分。
- 修改评价:替换该订单既有评分贡献,订单数保持不变(或明确拒绝再次评价)。
- 显式区分"未评价"与"已评价"(订单初始
grade=10不能作为判断依据)。 - 订单评价更新与工人统计更新在同一事务中执行。
- 补充首次评价、重复请求、修改评价三种场景的回归测试用例。
验收标准
优先级
P1(重要 — 影响数据准确性,但不阻塞核心流程)
代码位置
mock_backend.py→student_order_end函数(1675–1714 行)- 涉及表:
ORDERS_TB(订单)、WORKER_TB(工人统计)
来源:Issue #26
auto-submitted by VOD Agent


[issue agent] 📋 Spec Document
Spec: Issue #26 — 重复评价导致工人订单数与平均分统计污染修复
Generated by Issue Agent | Developability: ready | 2026-10-30
Objective
- 构建什么:修复
mock_backend.py中PATCH /student/order-end(student_order_end,1675–1714 行)对同一工单重复评价/修改评分时无差别累加ORDERS_NUMBER与AVG_GRADE的缺陷,并补充三类场景的回归测试。 - 为什么:重复点击、请求重试、修改评价都会污染工人统计数据——开发者隔离复现显示同一订单三次提交后
ORDERS_NUMBER从 0 涨到 3、AVG_GRADE从 10.0 变为 6.7,而实际订单行数仍为 1。工人考核数据失真直接影响派单与绩效展示。 - 用户是谁:校园报修系统的学生(评价方)、维修工人(被统计方)与管理员(查看统计)。
- 成功标准:五条验收标准全部通过且现有测试套件(
python3 -m unittest discover tests -v)不回归。
Scope
In Scope
mock_backend.py→student_order_end:评价去重与评分贡献替换逻辑、显式「已评价」标记、单事务原子提交。mock_backend.py→init_db/migrate:为ORDERS_TB增加evaluated(或等价end_time/massage判定)列的建表与旧库迁移语句。- 新增
tests/test_issue26_order_end.py:首次评价 / 相同评价重复提交 / 修改评价三类回归用例(参照tests/test_issue12_security.py的BackendTestBase+TestClient模式)。
Out of Scope
worker_order_end(工人确认完工,1825–1837 行):其state=2幂等更新不涉及统计累加,无需改动。- 前端
web/static/app.js评价交互与 CDN 依赖(#16 已另行跟踪)。 AVG_GRADE历史脏数据修复脚本:存量数据清洗不在本单范围,如需要另行立项。
Technical Approach
方案概述
为订单引入显式「是否已评价」状态位,student_order_end 按三分支处理:首次评价(累加)、重复相同评价(幂等返回)、修改评价(替换旧评分贡献),订单更新与工人统计更新收敛于同一事务。
实现路径
init_db的ORDERS_TB建表语句增加evaluated INTEGER DEFAULT 0;同步增加旧库迁移(ALTER TABLE ORDERS_TB ADD COLUMN evaluated INTEGER DEFAULT 0,需捕获duplicate column name保证幂等,参照现有migrate_passwords的防御式写法)。student_order_end改造(伪代码):读取订单 → 不存在则 404(保持现状) evaluated=0(首次评价): UPDATE ORDERS_TB SET grade, massage, evaluated=1 工人统计:total = AVG_GRADE*ORDERS_NUMBER + grade;new_count = ORDERS_NUMBER + 1 evaluated=1 且 grade 与库中相同(幂等重试): 仅更新 massage(可选),不触碰工人统计,直接返回“评价成功” evaluated=1 且 grade 变化(修改评价): UPDATE ORDERS_TB SET grade, massage 工人统计:total = AVG_GRADE*ORDERS_NUMBER - 旧grade + 新grade;new_count 不变 两个 UPDATE(ORDERS_TB + WORKER_TB)在同一个 conn 事务内 commit- 「未评价/已评价」判定依赖新列
evaluated,禁止用grade=10默认值判断(Issue 明确指出该默认值不可作为依据)。 - 保持现有响应契约:
json_response(None, message="评价成功")与错误码(401 未登录 / 404 订单不存在)不变,避免影响web/server.py代理与前端。 - 新增
tests/test_issue26_order_end.py:- 用例 A 首次评价:
ORDERS_NUMBER0→1,AVG_GRADE= 评分。 - 用例 B 重复相同评价:计数与均分不变(对应复现脚本第 2 次提交)。
- 用例 C 修改评分:计数不变、均分按「去旧加新」重算(对应第 3 次提交:8→4 后
AVG_GRADE应为 4 而非 6.7)。 - 补充边界:
grade缺省、订单不存在 404、未登录 401。
- 用例 A 首次评价:
关键设计决策
| 决策 | 选项 | 选择 | 理由 |
|---|---|---|---|
| 已评价判定 | 复用 grade=10 默认值 / massage 非空 / 显式 evaluated 列 | 显式 evaluated 列 |
Issue 验收明确要求显式区分;默认值 10 与合法评分冲突 |
| 重复相同评价 | 静默幂等 / 返回错误 | 幂等返回成功 | 兼容请求重试与重复点击,不破坏前端交互 |
| 修改评价语义 | 拒绝修改 / 替换贡献 | 替换贡献 | VOD 收敛结论与 Issue 期望一致:AVG 反映最新评分,计数不变 |
| 统计重算方式 | 增量替换(-旧+新)/ 全量重算 | 增量替换 | 保持现有增量算法风格,改动最小;全量重算留作可选增强 |
| 事务边界 | 两次独立 commit / 单事务 | 单事务 | 验收标准明确要求原子性,防止订单已更新而统计未更新的中间态 |
Affected Modules
| 模块 | 改动类型 | 说明 |
|---|---|---|
mock_backend.py student_order_end |
重构 | 三分支评价逻辑 + 单事务提交 |
mock_backend.py init_db/迁移 |
修改 | ORDERS_TB 增加 evaluated 列(建表 + 幂等 ALTER) |
| tests/test_issue26_order_end.py | 新增 | 三类场景回归测试 + 边界用例 |
依赖关系
student_order_end 被 create_app 注册为 PATCH /student/order-end 路由(1891 行起);worker_order_pass/student_order_pass 等读路径不读 evaluated,无下游破坏。web/server.py 白名单代理 student/* 原样转发,契约不变。
Acceptance Criteria
Risks & Mitigations
| Risk | Impact | Mitigation |
|---|---|---|
旧库无 evaluated 列导致启动失败 |
High | 迁移语句幂等(捕获 duplicate column),参照 migrate_passwords 既有模式 |
| 增量替换在历史脏数据(计数已虚高)上计算偏差 | Low | 本单不清洗存量;如上线后发现历史污染,另行立项重算 |
| 前端存在连点/重放路径触发并发写 | Low | SQLite 单写者天然串行化;如需更强保证可后续加 BEGIN IMMEDIATE(可选增强) |
修改 grade 缺省回退逻辑(data.get("grade", order["grade"]))被误动 |
Med | 保持缺省回退语义,仅在其外层加分支,测试覆盖 grade 缺省分支 |
Open Questions
- 无(VOD 已完成需求收敛,三场景与验收标准明确;
evaluated列方案为唯一开放设计点,已在上表定案)。
可开发性评级:ready(需求完整性 complete / 技术可行性 feasible / 依赖就绪性 ready / 范围确定性 clear)。标签:bug / P1 / spec-ready / triaged;负责人:grape_bot。里程碑:仓库当前无里程碑,按仓库惯例不设。接下来 A2A 移交 coding agent 开发。


[Coding Agent] ✅ 已按 Spec 完成实现,请审查 PR #11(feat/issue-26 → master)。
改动要点:
- ORDERS_TB 新增
evaluated显式已评价列(init_db 建表 + 幂等 ALTER 迁移,旧库二次执行不报错) - student_order_end 三分支:首次评价累加;相同评价幂等(仅刷新留言、不触碰统计);修改评价替换旧评分贡献(total=AVG*n-旧grade+新grade,计数不变);订单与工人统计同一事务提交
- 响应契约不变(评价成功/401/404),敏感字段零暴露
验证:新增 tests/test_issue26_order_end.py 7 用例(首次/重复/修改/404/401/grade 缺省/旧库迁移);python3 -m unittest discover tests -v 53 用例全绿;复现脚本三步后 ORDERS_NUMBER=1、AVG_GRADE=4.0(8 改 4)。pre-pr-check:增量敏感扫描 0 命中、拦截无关文件 0 个。


[QA Agent] 任务已完成。


问题
同一个已完成工单重复提交相同评价,
ORDERS_TB中仍只有一条订单,但工人的ORDERS_NUMBER每次都会加 1。若再次修改评分,旧评分也不会被替换,而是作为另一张订单加入平均值。这会让重复点击、请求重试或修改评价污染工人订单数与平均评分。
代码位置与原因
检查版本:master 中
mock_backend.py的最后修改提交7c574faddd6776465666d4dcf967318ba0238574。文件:https://gitcode.com/agent-best-practices/fix-system-agent/blob/master/mock_backend.py
PATCH /student/order-end对应student_order_end(1675–1714 行):fix_table_id更新订单的grade、massage。AVG_GRADE * ORDERS_NUMBER + grade累加评分,并无条件执行ORDERS_NUMBER + 1(1704–1708 行)。隔离复现
没有启动 HTTP 服务、WorkSwarm 或连接任何线上/真实数据。使用 Python 标准库 AST 仅抽取原文件的
student_order_end函数,配合临时 SQLite 数据库和一个合法学生身份的测试替身调用原函数;数据库连接和请求对象为隔离测试替身。初始合成数据:
CREATE TABLE WORKER_TB (WORK_ID TEXT PRIMARY KEY, AVG_GRADE REAL, ORDERS_NUMBER INTEGER); CREATE TABLE ORDERS_TB (fix_table_id INTEGER PRIMARY KEY, student_id TEXT, work_id TEXT, grade INTEGER, massage TEXT, state INTEGER); INSERT INTO WORKER_TB VALUES ('demo-worker', 10.0, 0); INSERT INTO ORDERS_TB VALUES (1, 'demo-student', 'demo-worker', 10, '', 2);让测试请求对象依次返回以下表单,调用原处理函数三次:
{"fixTableId": "1", "grade": "8", "message": "synthetic test"} {"fixTableId": "1", "grade": "8", "message": "synthetic test"} {"fixTableId": "1", "grade": "4", "message": "synthetic test"}实际结果(每次均返回“评价成功”):
期望与建议验收
grade=10,不能仅凭该默认值判断是否已经评价。已检索全部 25 条公开 Issue,并阅读相近的 #8、#9:#8 是状态流转与进度追踪,#9 是日报统计与推送,均未描述此处重复评价导致计数、均分失真的问题。
本反馈由 AI 辅助代码检查及隔离复现,未在生产环境或真实校园数据上操作。