from __future__ import annotations from types import SimpleNamespace from app.services.expense_claim_platform_context_tools import ( collect_context_cities, collect_context_item_ids, extract_first_known_city_from_text, unique_text_values, ) from app.services.expense_rule_runtime_models import build_default_expense_rule_catalog def test_unique_text_values_trims_and_preserves_order() -> None: assert unique_text_values([" 上海 ", "", "上海", "北京", None, "北京"]) == [ "上海", "北京", ] def test_collect_context_item_ids_skips_empty_and_dedupes() -> None: contexts = [ {"item": SimpleNamespace(id="item-1")}, {"item": SimpleNamespace(id="item-1")}, {"item": SimpleNamespace(id=" item-2 ")}, {"item": SimpleNamespace(id="")}, {}, ] assert collect_context_item_ids(contexts) == ["item-1", "item-2"] def test_collect_context_cities_can_include_item_reason() -> None: policy = build_default_expense_rule_catalog().travel_policy assert policy is not None context = { "ocr_summary": "火车票;武汉-上海", "ocr_text": "", "document_info": { "fields": [ {"key": "route", "label": "路线", "value": "上海-深圳"}, ] }, "item": SimpleNamespace(item_location="", item_reason="深圳-上海"), } assert set(collect_context_cities(context, policy, include_item_reason=True)) == { "武汉", "上海", "深圳", } assert extract_first_known_city_from_text("预计前往北京客户现场", policy) == "北京"