diff --git a/server/tests/test_orchestrator_service.py b/server/tests/test_orchestrator_service.py index b75e3a5..b187a4a 100644 --- a/server/tests/test_orchestrator_service.py +++ b/server/tests/test_orchestrator_service.py @@ -312,6 +312,87 @@ def test_orchestrator_non_finance_cannot_query_other_users_expense_claims() -> N ] +def test_orchestrator_non_finance_does_not_leak_duplicate_name_claims() -> None: + client, session_factory = build_client() + user_id = "zhangsan1@example.com" + + with session_factory() as db: + employee_a = Employee( + employee_no="E9201", + name="张三", + email=user_id, + ) + employee_b = Employee( + employee_no="E9202", + name="张三", + email="zhangsan2@example.com", + ) + db.add_all([employee_a, employee_b]) + db.flush() + db.add_all( + [ + ExpenseClaim( + claim_no="EXP-DUP-101", + employee_id=employee_a.id, + employee_name="张三", + department_name="市场部", + project_code="PRJ-A", + expense_type="travel", + reason="本人报销", + location="上海", + amount=Decimal("120.00"), + currency="CNY", + invoice_count=1, + occurred_at=datetime(2026, 5, 12, 9, 0, tzinfo=UTC), + submitted_at=datetime(2026, 5, 12, 10, 0, tzinfo=UTC), + status="submitted", + approval_stage="finance_review", + risk_flags_json=[], + ), + ExpenseClaim( + claim_no="EXP-DUP-102", + employee_id=employee_b.id, + employee_name="张三", + department_name="销售部", + project_code="PRJ-B", + expense_type="meal", + reason="他人报销", + location="杭州", + amount=Decimal("300.00"), + currency="CNY", + invoice_count=1, + occurred_at=datetime(2026, 5, 12, 12, 0, tzinfo=UTC), + submitted_at=datetime(2026, 5, 12, 13, 0, tzinfo=UTC), + status="approved", + approval_stage="completed", + risk_flags_json=[], + ), + ] + ) + db.commit() + + response = client.post( + "/api/v1/orchestrator/run", + json={ + "source": "user_message", + "user_id": user_id, + "message": "请查询我的报销单", + "context_json": { + "role_codes": ["manager"], + "name": "张三", + "client_now_iso": "2026-05-13T08:00:00+00:00", + }, + }, + ) + + assert response.status_code == 200 + payload = response.json() + assert payload["result"]["query_payload"]["record_count"] == 1 + assert [item["claim_no"] for item in payload["result"]["query_payload"]["records"]] == [ + "EXP-DUP-101", + ] + + def test_orchestrator_finance_can_query_all_expense_claims() -> None: client, session_factory = build_client() @@ -384,6 +465,13 @@ def test_orchestrator_expense_query_claim_no_bypasses_recent_window() -> None: user_id = "zhaoliu@example.com" with session_factory() as db: + db.add( + Employee( + employee_no="E9301", + name="赵六", + email=user_id, + ) + ) db.add( ExpenseClaim( claim_no="EXP-202604-001",