feat(services): assignment 6 full - form/business key mapping and stream write-back
- fields_registry: FORM_TO_BUSINESS_KEY bidirectional mapping between the graph's six form keys (has_injury...) and the acd business keys (ywrysw...); bjrjs/ywmtc have no form source (set_info only); business_patch_from_form maps graph diffs to whitelisted business keys and filters internal/unknown keys - app_service: chat injection now maps repository business keys back to form keys; both complete() and stream() write back field diffs (FormUpdate events captured in stream, closing the skeleton gap); form keys never leak into the business repository - docs/assignment6-compat.md: mapping table documented, stream write-back backlog item resolved - tests: mapping coverage, write-back mapping end-to-end, reverse mapping injection (bjrjs/ywmtc excluded), stream FormUpdate write-back Verified: 205 unit tests
This commit is contained in:
@@ -128,6 +128,33 @@ async def test_chat_sees_set_info_values_and_writes_back_patch():
|
||||
assert json.loads(service.get_info("s1", "hphm1")) == "苏B12345"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_chat_form_patch_mapped_to_business_keys():
|
||||
"""图表单键差量经映射写回业务键(作业 6 映射的端到端)。"""
|
||||
service, backend = make_service(form_update={
|
||||
"has_injury": False, "vehicle_count": 2, "accident_cause": "追尾",
|
||||
})
|
||||
await service.chat(_input("s1", "两辆汽车追尾,没有人受伤"))
|
||||
acd = json.loads(service.get_info("s1", "acdinfo"))
|
||||
assert acd["ywrysw"] == "0"
|
||||
assert acd["jdcsl"] == "2"
|
||||
assert acd["sgyy"] == "追尾"
|
||||
# 表单键本身不落 repository(未知业务键 -> JSON 空串)
|
||||
assert json.loads(service.get_info("s1", "has_injury")) == ""
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_set_info_acd_value_mapped_into_form_injection():
|
||||
"""set_info 写业务键 -> chat 注入为图表单键(反向映射)。"""
|
||||
service, backend = make_service()
|
||||
service.set_info("s1", "ywrysw", "0")
|
||||
service.set_info("s1", "jdcsl", "2")
|
||||
service.set_info("s1", "bjrjs", "1") # 无表单来源,不注入
|
||||
await service.chat(_input("s1", "继续办理"))
|
||||
injected = backend.calls[0].injected_fields
|
||||
assert injected["accident_fields"] == {"has_injury": False, "vehicle_count": 2}
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_chat_without_business_state_passes_no_injection():
|
||||
service, backend = make_service()
|
||||
@@ -136,8 +163,9 @@ async def test_chat_without_business_state_passes_no_injection():
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_stream_injects_fields_and_passthrough_events():
|
||||
service, backend = make_service(form_update={"ywrysw": False})
|
||||
async def test_stream_injects_fields_writes_back_form_update():
|
||||
"""流式:注入同 chat;FormUpdate 事件差量捕获写回后透传。"""
|
||||
service, backend = make_service(form_update={"has_injury": False})
|
||||
service.set_info("s1", "xm1", "王五")
|
||||
events = [
|
||||
event async for event in service.stream(_input("s1", "继续办理"))
|
||||
@@ -145,6 +173,8 @@ async def test_stream_injects_fields_and_passthrough_events():
|
||||
kinds = [type(event).__name__ for event in events]
|
||||
assert kinds == ["TextDelta", "FormUpdate", "TextDelta"]
|
||||
assert backend.stream_calls[0].injected_fields["person_fields"]["xm1"] == "王五"
|
||||
# FormUpdate 差量已写回 repository(表单键 -> 业务键)
|
||||
assert json.loads(service.get_info("s1", "acdinfo"))["ywrysw"] == "0"
|
||||
|
||||
|
||||
# ---- delete:清理 + 幂等 ----
|
||||
|
||||
Reference in New Issue
Block a user