From 10982f24a30e033594f19cb2a6e21a31a698f1df Mon Sep 17 00:00:00 2001 From: xiaoqu-ai Date: Tue, 20 Oct 2026 18:40:44 +0800 Subject: [PATCH] =?UTF-8?q?fix(mcp):=20=E4=BF=AE=E6=AD=A3=E7=89=A9?= =?UTF-8?q?=E4=B8=9A=E6=89=80=E5=B1=9E=E9=94=80=E5=94=AE=E5=AF=8C=E5=8C=96?= =?UTF-8?q?=E6=B0=B8=E8=BF=9C=E4=B8=BA=E7=A9=BA=EF=BC=88Map=20key=20?= =?UTF-8?q?=E8=A2=AB=E9=A9=BC=E5=B3=B0=E5=8C=96=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因:SQL 别名用 property_id/user_id/user_name,而 MyBatis 的 mapUnderscoreToCamelCase=true 会把结果 Map 的 key 转成 propertyId/userId/userName, 代码按 "property_id" 取值永远 null → 富化静默跳过,sale_user_id 恒为空。 修复: - 别名改为无下划线的 pid/uid/uname,绕开驼峰转换 - 单测补两条并锁住:取到 userId → sale_user_id;缺失时回落 create_id (此前构造器新增 AgentMapper 参数,测试未同步,已一并修正) 验证:SyncEntitiesTest 26 例全过。 --- .../iiv/agent/mapper/m0/ProperytMapper.java | 4 +- .../agent/mcp/sync/PropertiesSyncEntity.java | 6 +-- .../iiv/agent/mcp/sync/SyncEntitiesTest.java | 45 ++++++++++++++++++- 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/xiaoqu-agent-service/src/main/java/me/iiv/agent/mapper/m0/ProperytMapper.java b/xiaoqu-agent-service/src/main/java/me/iiv/agent/mapper/m0/ProperytMapper.java index 224c8f7..b1025d2 100644 --- a/xiaoqu-agent-service/src/main/java/me/iiv/agent/mapper/m0/ProperytMapper.java +++ b/xiaoqu-agent-service/src/main/java/me/iiv/agent/mapper/m0/ProperytMapper.java @@ -24,7 +24,9 @@ public interface ProperytMapper extends BaseMapper { *

来源是物业表的 userId / userName 两列(实体未映射,故用显式 SQL)。 * 独立查询 + 调用方容错:列名或数据异常只丢归属,不影响 properties 变更流。

*/ - @Select("") diff --git a/xiaoqu-agent-service/src/main/java/me/iiv/agent/mcp/sync/PropertiesSyncEntity.java b/xiaoqu-agent-service/src/main/java/me/iiv/agent/mcp/sync/PropertiesSyncEntity.java index a7a0491..744416d 100644 --- a/xiaoqu-agent-service/src/main/java/me/iiv/agent/mcp/sync/PropertiesSyncEntity.java +++ b/xiaoqu-agent-service/src/main/java/me/iiv/agent/mcp/sync/PropertiesSyncEntity.java @@ -76,13 +76,13 @@ public class PropertiesSyncEntity extends AbstractSyncEntity implements SyncEnti } if (!ids.isEmpty()) { for (Map owner : properytMapper.selectPropertyOwners(ids)) { - Object pid = owner.get("property_id"); + Object pid = owner.get("pid"); if (pid == null) { continue; } Long propertyId = Long.valueOf(String.valueOf(pid)); - Object uid = owner.get("user_id"); - Object uname = owner.get("user_name"); + Object uid = owner.get("uid"); + Object uname = owner.get("uname"); if (uid != null) { ownerIds.put(propertyId, String.valueOf(uid)); } diff --git a/xiaoqu-agent-service/src/test/java/me/iiv/agent/mcp/sync/SyncEntitiesTest.java b/xiaoqu-agent-service/src/test/java/me/iiv/agent/mcp/sync/SyncEntitiesTest.java index f00d921..cc48881 100644 --- a/xiaoqu-agent-service/src/test/java/me/iiv/agent/mcp/sync/SyncEntitiesTest.java +++ b/xiaoqu-agent-service/src/test/java/me/iiv/agent/mcp/sync/SyncEntitiesTest.java @@ -18,6 +18,7 @@ import me.iiv.agent.entity.m2.WithdrawOrder; import me.iiv.agent.mapper.m0.BatteryFaultLogMapper; import me.iiv.agent.mapper.m0.DeviceLifeCycleMapper; import me.iiv.agent.mapper.m0.HardwareViewMapper; +import me.iiv.agent.mapper.m0.AgentMapper; import me.iiv.agent.mapper.m0.ProperytMapper; import me.iiv.agent.mapper.m0.UserMapper; import me.iiv.agent.mapper.m1.MallGoodsOrderMapper; @@ -67,6 +68,8 @@ class SyncEntitiesTest { @Mock ProperytMapper properytMapper; @Mock + AgentMapper agentMapper; + @Mock ContractNewMapper contractNewMapper; @Mock SalerRepaymentMapper salerRepaymentMapper; @@ -166,7 +169,7 @@ class SyncEntitiesTest { @Test void propertiesAppliesRowFilterForUserAndMapsFields() { - PropertiesSyncEntity entity = new PropertiesSyncEntity(properytMapper, permissionService); + PropertiesSyncEntity entity = new PropertiesSyncEntity(properytMapper, permissionService, agentMapper); Properyt property = new Properyt(); property.setId(9L); property.setName("望京SOHO"); @@ -192,9 +195,47 @@ class SyncEntitiesTest { assertEquals("ACTIVE", rows.get(0).item().get("status")); } + @Test + void propertiesExportsSaleOwnerFromUserIdColumns() { + PropertiesSyncEntity entity = new PropertiesSyncEntity(properytMapper, permissionService, agentMapper); + Properyt property = new Properyt(); + property.setId(9L); + property.setName("望京SOHO"); + property.setAgentId(33L); + property.setCreateId(11L); + property.setSoftDelete(0); + property.setModifyTime(Timestamp.valueOf("2026-09-01 10:00:00")); + when(properytMapper.selectList(any())).thenReturn(List.of(property)); + // 别名刻意无下划线:MyBatis 会把 property_id 转成 propertyId + when(properytMapper.selectPropertyOwners(any())) + .thenReturn(List.of(Map.of("pid", 9L, "uid", 77L, "uname", "张三"))); + + List rows = entity.fetchPage(null, 2000L, null, null, 3, null); + + assertEquals("77", rows.get(0).item().get("sale_user_id"), "物业所属销售取 userId 列"); + assertEquals("张三", rows.get(0).item().get("sale_user_name")); + } + + @Test + void propertiesFallsBackToCreateIdWhenOwnerMissing() { + PropertiesSyncEntity entity = new PropertiesSyncEntity(properytMapper, permissionService, agentMapper); + Properyt property = new Properyt(); + property.setId(9L); + property.setName("望京SOHO"); + property.setCreateId(11L); + property.setSoftDelete(0); + property.setModifyTime(Timestamp.valueOf("2026-09-01 10:00:00")); + when(properytMapper.selectList(any())).thenReturn(List.of(property)); + when(properytMapper.selectPropertyOwners(any())).thenReturn(List.of()); + + List rows = entity.fetchPage(null, 2000L, null, null, 3, null); + + assertEquals("11", rows.get(0).item().get("sale_user_id"), "缺 userId 时回落到创建人"); + } + @Test void propertiesSkipsRowFilterForServiceToken() { - PropertiesSyncEntity entity = new PropertiesSyncEntity(properytMapper, permissionService); + PropertiesSyncEntity entity = new PropertiesSyncEntity(properytMapper, permissionService, agentMapper); when(properytMapper.selectList(any())).thenReturn(List.of()); entity.fetchPage(null, 2000L, null, null, 3, null);