diff --git a/yunke-server/app/api/routers/customer.py b/yunke-server/app/api/routers/customer.py index 0f5716f..f8cfea1 100644 --- a/yunke-server/app/api/routers/customer.py +++ b/yunke-server/app/api/routers/customer.py @@ -108,9 +108,14 @@ async def _list_owner_links( .where(*conditions) ) ).scalar_one() + # LEFT JOIN 档案带 raw_json(2026-09-09):WA 客户列表大量列只存在于 + # raw_json(userName/salePhone/createTime 等员工侧字段),link 快照没存; + # raw_json 按 friend_id 全局一份,挂谁名下内容相同。注:共享客户的员工 + # 侧字段是「最后写入员工」的记录,可能非本员工(客户自身字段不受影响)。 rows = ( await session.execute( - sa.select(CustomerAccountLink) + sa.select(CustomerAccountLink, Customer.raw_json, Customer.version) + .outerjoin(Customer, Customer.friend_id == CustomerAccountLink.friend_id) .where(*conditions) .order_by( sa.nullslast(CustomerAccountLink.last_chat_time.desc()), @@ -119,8 +124,14 @@ async def _list_owner_links( .limit(page_size) .offset((page - 1) * page_size) ) - ).scalars().all() - items = [CustomerOut.model_validate(r) for r in rows] + ).all() + items = [] + for link, raw_json, version in rows: + out = CustomerOut.model_validate(link) + out.raw_json = raw_json + if version is not None: + out.version = version + items.append(out) return Page(items=items, total=total, page=page, page_size=page_size) diff --git a/yunke-server/tests/test_api_customers.py b/yunke-server/tests/test_api_customers.py index cd6ce6f..4d3b93b 100644 --- a/yunke-server/tests/test_api_customers.py +++ b/yunke-server/tests/test_api_customers.py @@ -226,3 +226,35 @@ async def test_owner_filter_with_dept_falls_back_to_archive(make_client): body = r.json() # 档案路径:只命中 user_id 属于 d1 的档案行(link 行不带 user_id) assert [it["friend_id"] for it in body["items"]] == ["f_archived"] + + +async def test_owner_link_path_carries_archive_raw_json(make_client): + """link 路径按 friend_id 带出档案 raw_json(2026-09-09 WA 列表修复)。 + + WA 客户列表大量列只存在于 raw_json(userName/salePhone/createTime 等), + link 快照没存——不带 raw_json 时整表列空白。 + """ + from app.db.models import Customer as C, CustomerAccountLink as L + + async def seed(session): + session.add_all([ + # 档案行挂在别的员工名下(共享),raw_json 里带员工侧 camelCase 字段 + C(channel="whatsapp", friend_id="f1@s.whatsapp.net", + owner_account_id="wx_other", friend_nickname="Nick", + raw_json={"userName": "员工WA名", "salePhone": "13800000000", + "uid": "15600000000@s.whatsapp.net", "createTime": 1700000000000}), + L(channel="whatsapp", owner_account_id="wa_me", + friend_id="f1@s.whatsapp.net", friend_nickname="Nick", last_chat_time=100), + ]) + await session.commit() + + client = await make_client(seed) + r = await client.get("/api/customers", params={ + "channel": "whatsapp", "owner_account_id": "wa_me"}) + assert r.status_code == 200 + body = r.json() + assert body["total"] == 1 + it = body["items"][0] + assert it["friend_nickname"] == "Nick" # link 快照 + assert it["raw_json"]["userName"] == "员工WA名" # 档案 raw_json 带出 + assert it["raw_json"]["salePhone"] == "13800000000"