Repository navigation
feat(clues): add scoped timeline API - #123
Conversation
📝 WalkthroughWalkthrough新增 Changes线索时间轴查询
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Client
participant ListClues
participant CaseService
participant Database
Client->>ListClues: 请求案件线索时间轴
ListClues->>CaseService: 传递认证信息和查询参数
CaseService->>Database: 加载案件角色与线索
CaseService->>Database: 批量加载线索归属
CaseService-->>ListClues: 返回分页线索响应
ListClues-->>Client: 返回 200 JSON
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Preview readyThe preview for this build is available at https://pr-123-f4060549e85d.angui.cg8.site. Temporary demo accounts (all use the password
|
There was a problem hiding this comment.
🧹 Nitpick comments (5)
tests/api/case_clues_get.rs (1)
71-85: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win排序行为未被断言。
请求带了
sort=created_at&order=asc,但只校验了条数与分页字段,没有校验返回顺序;sort=occurred_at(含二级created_at/id兜底)这条分支完全没有覆盖。建议断言首末项顺序,并补一个sort=occurred_at&order=desc的用例;顺带对成功响应断言StatusCode::OK,避免错误响应体被静默反序列化成Value后仅在字段断言处才失败。如需,我可以补齐排序断言与
occurred_at用例。As per path instructions, "Check that changed behavior has meaningful positive, negative, and boundary-case coverage."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/api/case_clues_get.rs` around lines 71 - 85, 增强 case clues 分页测试:在现有 sort=created_at&order=asc 请求中断言响应状态为 StatusCode::OK,并校验首末返回项的排序顺序;新增 sort=occurred_at&order=desc 的成功响应用例,覆盖其 occurred_at 及 created_at/id 兜底排序,并同样断言状态和结果顺序。Source: Path instructions
src/services/case_service.rs (1)
290-309: 🚀 Performance & Scalability | 🔵 Trivial | 🏗️ Heavy lift分页在内存中完成,会全量加载案件线索。
clue_query.all(db)未加LIMIT/OFFSET,每次请求都会拉取该案件的全部线索及其归属记录,再在内存里裁剪可见性并分页。由于total需要反映可见条数,当前实现语义正确,但线索量增长后内存与 IO 开销会线性上升。可考虑将可见性条件下推到 SQL(例如status = 'confirmed' OR submitted_by_user_id = :user,Commander 不加条件),用paginate/count取代内存切片。如需,我可以给出下推可见性条件后的查询实现草案。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/services/case_service.rs` around lines 290 - 309, 将案件线索的可见性筛选和分页下推到数据库查询:在 clue_query 中复用 status、submitted_by_user_id 及 Commander 角色对应的条件,使用查询层的 count 和 paginate/limit/offset 获取 total 与当前页,避免 clue_query.all(db) 加载全部线索及归属记录。保留现有响应映射和可见性语义,确保 total 仍仅统计可见线索。tests/api/openapi_intake_contract.rs (1)
146-152: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value契约断言依赖 YAML 中 GET 必须写在 POST 之前。
纯文本切片让测试与文档书写顺序耦合,单纯调整
openapi.yaml里操作顺序就会红。若愿意引入serde_yaml(或按缩进定位get:块而不要求它在post:之前),断言会稳健得多。当前写法与本文件既有风格一致,属可选改进。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/api/openapi_intake_contract.rs` around lines 146 - 152, 改进 openapi_intake_contract.rs 中围绕 OPENAPI 的 GET/POST 提取逻辑,避免通过 split_once 要求 get: 必须出现在 post: 之前。可改用 serde_yaml 解析操作,或按缩进独立定位 get: 块,使断言仅验证对应路径的 GET 契约而不依赖文档中的操作顺序。tests/api/case_clues_post.rs (1)
32-37: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
body["id"].as_str()传Option会让缺失 id 退化为IS NULL查询。显式解包更能定位失败原因。
♻️ 建议改动
+ let clue_id = body["id"].as_str().expect("clue id should be text"); let audit = angui::entities::audit_events::Entity::find() - .filter(angui::entities::audit_events::Column::EntityId.eq(body["id"].as_str())) + .filter(angui::entities::audit_events::Column::EntityId.eq(clue_id)) .one(&context.database)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/api/case_clues_post.rs` around lines 32 - 37, 在审计查询中先对 body["id"].as_str() 显式解包并在缺失时立即失败,再将实际字符串传给 audit_events::Column::EntityId.eq;不要把 Option 直接传入查询,保留现有的审计记录查找与断言流程。tests/api/clue_review_patch.rs (1)
81-139: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win审计断言再精确一点
当前只检查metadata_json是否包含状态字符串,无法区分每条审计的from/to;建议解析成 JSON 后,逐条断言两次状态变更的组合。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/api/clue_review_patch.rs` around lines 81 - 139, Update the audit assertions in patch_clue_review_rejects_volunteers_and_records_each_review_transition to parse each audit’s metadata_json as JSON and assert the exact from/to transition for both records, rather than only checking that each status string appears. Preserve the existing audit count and verify the two expected transition combinations individually.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/services/case_service.rs`:
- Around line 290-309: 将案件线索的可见性筛选和分页下推到数据库查询:在 clue_query 中复用
status、submitted_by_user_id 及 Commander 角色对应的条件,使用查询层的 count 和
paginate/limit/offset 获取 total 与当前页,避免 clue_query.all(db)
加载全部线索及归属记录。保留现有响应映射和可见性语义,确保 total 仍仅统计可见线索。
In `@tests/api/case_clues_get.rs`:
- Around line 71-85: 增强 case clues 分页测试:在现有 sort=created_at&order=asc 请求中断言响应状态为
StatusCode::OK,并校验首末返回项的排序顺序;新增 sort=occurred_at&order=desc 的成功响应用例,覆盖其
occurred_at 及 created_at/id 兜底排序,并同样断言状态和结果顺序。
In `@tests/api/case_clues_post.rs`:
- Around line 32-37: 在审计查询中先对 body["id"].as_str() 显式解包并在缺失时立即失败,再将实际字符串传给
audit_events::Column::EntityId.eq;不要把 Option 直接传入查询,保留现有的审计记录查找与断言流程。
In `@tests/api/clue_review_patch.rs`:
- Around line 81-139: Update the audit assertions in
patch_clue_review_rejects_volunteers_and_records_each_review_transition to parse
each audit’s metadata_json as JSON and assert the exact from/to transition for
both records, rather than only checking that each status string appears.
Preserve the existing audit count and verify the two expected transition
combinations individually.
In `@tests/api/openapi_intake_contract.rs`:
- Around line 146-152: 改进 openapi_intake_contract.rs 中围绕 OPENAPI 的 GET/POST
提取逻辑,避免通过 split_once 要求 get: 必须出现在 post: 之前。可改用 serde_yaml 解析操作,或按缩进独立定位 get:
块,使断言仅验证对应路径的 GET 契约而不依赖文档中的操作顺序。
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: fea64306-8fd1-4c9d-a51f-f933adc0871f
📒 Files selected for processing (12)
docs/API.mddocs/openapi.yamlsrc/models.rssrc/routes/cases.rssrc/routes/mod.rssrc/services/case_service.rstests/api/authentication_guards.rstests/api/case_clues_get.rstests/api/case_clues_post.rstests/api/clue_review_patch.rstests/api/mod.rstests/api/openapi_intake_contract.rs
f406054 to
cd87fe0
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
tests/api/case_clues_post.rs (1)
32-48: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win将审计事件断言限定为创建操作并解析结构化元数据。
当前查询只按
entity_id取任意记录,且contains可能匹配错误事件或错误字段,导致审计状态/隐私回归仍然通过。请筛选预期的创建审计操作,并反序列化metadata_json后断言状态字段及不存在内容字段。As per path instructions,
tests/**要求变更行为具有有意义的覆盖。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/api/case_clues_post.rs` around lines 32 - 48, Update the audit lookup in the case clue submission test to filter by both entity ID and the expected create operation, rather than selecting any audit event. Deserialize audit.metadata_json into its structured representation, then assert the status field is pending_review and the content field is absent instead of using string contains checks.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@tests/api/case_clues_post.rs`:
- Around line 32-48: Update the audit lookup in the case clue submission test to
filter by both entity ID and the expected create operation, rather than
selecting any audit event. Deserialize audit.metadata_json into its structured
representation, then assert the status field is pending_review and the content
field is absent instead of using string contains checks.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 1ff54d67-a61b-4f2e-862e-65539c4477d9
📒 Files selected for processing (12)
docs/API.mddocs/openapi.yamlsrc/models.rssrc/routes/cases.rssrc/routes/mod.rssrc/services/case_service.rstests/api/authentication_guards.rstests/api/case_clues_get.rstests/api/case_clues_post.rstests/api/clue_review_patch.rstests/api/mod.rstests/api/openapi_intake_contract.rs
🚧 Files skipped from review as they are similar to previous changes (10)
- tests/api/authentication_guards.rs
- tests/api/openapi_intake_contract.rs
- tests/api/mod.rs
- docs/openapi.yaml
- src/routes/cases.rs
- tests/api/clue_review_patch.rs
- tests/api/case_clues_get.rs
- docs/API.md
- src/routes/mod.rs
- src/services/case_service.rs
Preview readyThe preview for this build is available at https://pr-123-cd87fe0aee68.angui.cg8.site. Temporary demo accounts (all use the password
|
Summary by CodeRabbit
GET /api/cases/{case_id}/clues,支持分页(page/page_size)、状态筛选、排序(sort/ order)。items/page/page_size/total。404。400,并返回结构化validation_error(如分页/枚举白名单不通过)。ClueTimelinePage等响应结构。