From 8e704c6474b8a9df9652191112f6dc280992ba52 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期二, 13 十月 2026 17:15:45 +0800
Subject: [PATCH] fix(crm): 修复客户公海数据显示问题

---
 sql/mysql/mes_wm_misc_receipt_source_fields.sql                                                                            |    7 ++
 yudao-module-crm/src/test/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerAutoPoolTest.java                   |   33 ++++++++++
 scripts/operate-log-time-20261013/read_customer_pool.py                                                                    |   15 +++++
 yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java                       |    6 -
 yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerPageReqVO.java |    4 
 scripts/operate-log-time-20261013/fix_misc_receipt_schema.py                                                               |   50 ++++++++++++++++
 scripts/operate-log-time-20261013/read_misc_receipt_schema.py                                                              |   16 +++++
 yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java          |    5 +
 8 files changed, 129 insertions(+), 7 deletions(-)

diff --git a/scripts/operate-log-time-20261013/fix_misc_receipt_schema.py b/scripts/operate-log-time-20261013/fix_misc_receipt_schema.py
new file mode 100644
index 0000000..ac85441
--- /dev/null
+++ b/scripts/operate-log-time-20261013/fix_misc_receipt_schema.py
@@ -0,0 +1,50 @@
+from read_log_times import connect
+from pathlib import Path
+import json
+import re
+
+HERE = Path(__file__).resolve().parent
+ROOT = HERE.parents[1]
+ADDITIONS = {
+    'type': "int DEFAULT 1 COMMENT '鏉傞」绫诲瀷锛歮es_wm_misc_receipt_type' AFTER `name`",
+    'source_doc_type': "varchar(64) DEFAULT NULL COMMENT '鏉ユ簮鍗曟嵁绫诲瀷' AFTER `type`",
+    'source_doc_id': "bigint DEFAULT NULL COMMENT '鏉ユ簮鍗曟嵁ID' AFTER `source_doc_type`",
+    'source_doc_code': "varchar(100) DEFAULT NULL COMMENT '鏉ユ簮鍗曟嵁缂栫爜' AFTER `source_doc_id`",
+}
+
+with connect() as c:
+    with c.cursor() as q:
+        q.execute('SHOW CREATE TABLE mes_wm_misc_receipt')
+        old_schema = q.fetchall()
+        q.execute('SHOW COLUMNS FROM mes_wm_misc_receipt')
+        columns = {r['Field'] for r in q.fetchall()}
+        q.execute('SELECT * FROM mes_wm_misc_receipt ORDER BY id')
+        before = q.fetchall()
+        missing = [name for name in ADDITIONS if name not in columns]
+        backup = HERE/'misc-receipt-schema-before.json'
+        if missing:
+            with backup.open('x', encoding='utf-8') as f:
+                json.dump(dict(target='36.213.150.237:10000/mom-hm', schema=old_schema,
+                               rows=before, missing=missing), f, ensure_ascii=False, indent=2, default=str)
+            sql = 'ALTER TABLE mes_wm_misc_receipt '+', '.join(
+                'ADD COLUMN `'+name+'` '+ADDITIONS[name] for name in missing)
+            q.execute(sql)
+        # 楠岃瘉涓変釜鏁版嵁瀵硅薄鐨勫叏閮ㄦ槧灏勫瓧娈甸兘鑳芥煡璇€��
+        counts = {}
+        for suffix, class_name in [('', 'MesWmMiscReceiptDO'), ('_line', 'MesWmMiscReceiptLineDO'),
+                                   ('_detail', 'MesWmMiscReceiptDetailDO')]:
+            source = (ROOT / ('yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscreceipt/'+class_name+'.java')).read_text(encoding='utf-8')
+            fields = re.findall(r'private\s+\w+\s+(\w+);', source)
+            mapped = [re.sub(r'(?<!^)([A-Z])', r'_\1', name).lower() for name in fields]
+            mapped += ['create_time', 'update_time', 'creator', 'updater', 'deleted']
+            table = 'mes_wm_misc_receipt'+suffix
+            q.execute('SELECT '+','.join('`'+field+'`' for field in mapped)+
+                      ' FROM '+table+' WHERE deleted=0 ORDER BY id DESC LIMIT 10')
+            counts[table] = len(q.fetchall())
+        q.execute('SELECT * FROM mes_wm_misc_receipt ORDER BY id')
+        after = q.fetchall()
+        assert [{k: row[k] for k in columns} for row in after] == before, 'Existing data changed'
+        result = dict(target='36.213.150.237:10000/mom-hm', added_columns=missing,
+                      original_data_unchanged=True, query_verified=counts, backup=str(backup))
+        (HERE/'misc-receipt-schema-result.json').write_text(json.dumps(result, ensure_ascii=False, indent=2), encoding='utf-8')
+        print(json.dumps(result, ensure_ascii=False))
diff --git a/scripts/operate-log-time-20261013/read_customer_pool.py b/scripts/operate-log-time-20261013/read_customer_pool.py
new file mode 100644
index 0000000..4f344a9
--- /dev/null
+++ b/scripts/operate-log-time-20261013/read_customer_pool.py
@@ -0,0 +1,15 @@
+from read_log_times import connect
+import json
+
+with connect() as c:
+    with c.cursor() as q:
+        queries = [
+            "SHOW COLUMNS FROM crm_customer LIKE 'auto_pool_enabled'",
+            "SELECT COUNT(*) total, SUM(owner_user_id IS NULL) no_owner, SUM(owner_user_id=0) zero_owner, SUM(auto_pool_enabled=1) enabled, SUM(auto_pool_enabled=0) disabled, SUM(auto_pool_enabled IS NULL) unset FROM crm_customer WHERE deleted=0",
+            "SELECT owner_user_id IS NULL no_owner, auto_pool_enabled+0 enabled, COUNT(*) count FROM crm_customer WHERE deleted=0 GROUP BY owner_user_id IS NULL, auto_pool_enabled",
+            "SELECT id,code,status FROM system_role WHERE code IN ('super_admin','crm_admin') AND deleted=0",
+        ]
+        for sql in queries:
+            q.execute(sql)
+            print(json.dumps({'sql': sql, 'rows': q.fetchall()}, ensure_ascii=False, default=str))
+
diff --git a/scripts/operate-log-time-20261013/read_misc_receipt_schema.py b/scripts/operate-log-time-20261013/read_misc_receipt_schema.py
new file mode 100644
index 0000000..f486276
--- /dev/null
+++ b/scripts/operate-log-time-20261013/read_misc_receipt_schema.py
@@ -0,0 +1,16 @@
+from read_log_times import connect
+import json
+
+with connect() as c:
+    with c.cursor() as q:
+        for sql in [
+            "SHOW CREATE TABLE mes_wm_misc_receipt_line",
+            "SHOW CREATE TABLE mes_wm_misc_receipt_detail",
+            "SHOW CREATE TABLE mes_wm_misc_receipt",
+            "SHOW TABLES LIKE 'mes_wm_misc_receipt%'",
+            "SELECT COUNT(*) count FROM mes_wm_misc_receipt",
+            "SELECT id,code,name,status FROM mes_wm_misc_receipt ORDER BY id DESC LIMIT 3",
+            "SELECT label,value,status FROM system_dict_data WHERE dict_type='mes_wm_misc_receipt_type' AND deleted=0",
+        ]:
+            q.execute(sql)
+            print(json.dumps({'sql': sql, 'rows': q.fetchall()}, ensure_ascii=False, default=str))
diff --git a/sql/mysql/mes_wm_misc_receipt_source_fields.sql b/sql/mysql/mes_wm_misc_receipt_source_fields.sql
new file mode 100644
index 0000000..abe24f1
--- /dev/null
+++ b/sql/mysql/mes_wm_misc_receipt_source_fields.sql
@@ -0,0 +1,7 @@
+-- 淇鏉傞」鍏ュ簱涓昏〃涓� MesWmMiscReceiptDO 鐨勫瓧娈靛樊寮傘��
+-- 瀛橀噺搴撳瓨琛ュ厖鍗曞搴旂被鍨嬪瓧鍏革細1 = 搴撳瓨璋冩暣锛涙潵婧愬崟鎹瓧娈典繚鎸佸彲绌恒��
+ALTER TABLE `mes_wm_misc_receipt`
+    ADD COLUMN `type` int DEFAULT 1 COMMENT '鏉傞」绫诲瀷锛歮es_wm_misc_receipt_type' AFTER `name`,
+    ADD COLUMN `source_doc_type` varchar(64) DEFAULT NULL COMMENT '鏉ユ簮鍗曟嵁绫诲瀷' AFTER `type`,
+    ADD COLUMN `source_doc_id` bigint DEFAULT NULL COMMENT '鏉ユ簮鍗曟嵁ID' AFTER `source_doc_type`,
+    ADD COLUMN `source_doc_code` varchar(100) DEFAULT NULL COMMENT '鏉ユ簮鍗曟嵁缂栫爜' AFTER `source_doc_id`;
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerPageReqVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerPageReqVO.java
index 796dd1d..2c4d932 100644
--- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerPageReqVO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerPageReqVO.java
@@ -46,8 +46,8 @@
     @InEnum(CrmSceneTypeEnum.class)
     private Integer sceneType; // 鍦烘櫙绫诲瀷锛屼负 null 鏃跺垯琛ㄧず鍏ㄩ儴
 
-    @Schema(description = "鏄惁涓哄叕娴锋暟鎹�", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
-    private Boolean pool; // null 鍒欒〃绀轰负涓嶆槸鍏捣鏁版嵁
+    @Schema(description = "鏄惁鏌ヨ鍏捣鍙瀹㈡埛锛堝寘鍚凡鏈夎礋璐d汉鐨勫鎴凤級", example = "false")
+    private Boolean pool;
 
     @Schema(description = "鑱旂郴鐘舵��", example = "1")
     private Integer contactStatus; // backlog 鏌ヨ鏉′欢
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java
index 9e3935b..5c277a4 100644
--- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java
@@ -56,10 +56,9 @@
     default PageResult<CrmCustomerDO> selectPage(CrmCustomerPageReqVO pageReqVO, Long ownerUserId,
                                                boolean superAdmin) {
         MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>();
-        // 鍏捣鏌ヨ蹇呴』浼樺厛杩囨护锛屼笉鑳借鈥滃叏閮ㄦ暟鎹�濆満鏅粫杩囥��
+        // 鍏捣灞曠ず鍏佽鍏变韩鐨勫鎴凤紙鍖呭惈宸叉湁璐熻矗浜猴級锛屼笌瀹㈡埛绠$悊浣跨敤鍚屼竴浠芥暟鎹��
         if (Boolean.TRUE.equals(pageReqVO.getPool())) {
-            query.isNull(CrmCustomerDO::getOwnerUserId)
-                    .eq(!superAdmin, CrmCustomerDO::getAutoPoolEnabled, true);
+            query.eq(!superAdmin, CrmCustomerDO::getAutoPoolEnabled, true);
         } else if (CrmSceneTypeEnum.isAll(pageReqVO.getSceneType())) {
             // 鍦烘櫙鍥涳細鍏ㄩ儴鏁版嵁锛屼笉鍖哄垎鍏捣/闈炲叕娴凤紝鐢� appendPermissionCondition 缁熶竴澶勭悊
             CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(),
@@ -213,7 +212,6 @@
 
     default Long selectPoolCount() {
         return selectCount(new LambdaQueryWrapperX<CrmCustomerDO>()
-                .isNull(CrmCustomerDO::getOwnerUserId)
                 .eq(!CrmPermissionUtils.isSuperAdmin(), CrmCustomerDO::getAutoPoolEnabled, true));
     }
 
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java
index 417e5f8..9658e37 100644
--- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java
@@ -83,6 +83,11 @@
         if (CrmPermissionUtils.isCrmAdmin()) {
             return;
         }
+        // 鍏捣鍏佽鏌ョ湅鏈夎礋璐d汉鐨勫鎴凤紱鍙巿浜堣鍙栨潈闄愶紝涓嶅奖鍝嶅啓鍏ャ�佽浆绉绘垨棰嗗彇鏉冮檺銆�
+        if (CrmBizTypeEnum.CRM_CUSTOMER.getType().equals(bizType)
+                && CrmPermissionLevelEnum.isRead(permissionLevel) && isPublicPoolVisible(bizType, bizId)) {
+            return;
+        }
         // 鐗规畩锛氭病鏈夋暟鎹潈闄愮殑鎯呭喌锛岄拡瀵� READ 鐨勭壒娈婂鐞�
         if (CollUtil.isEmpty(bizPermissions)) {
             // 1.1 鍏捣鏁版嵁锛屽鏋滄病鏈夊洟闃熸垚鍛橈紝澶у涔熷簲璇ユ湁 READ 鏉冮檺鎵嶅
diff --git a/yudao-module-crm/src/test/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerAutoPoolTest.java b/yudao-module-crm/src/test/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerAutoPoolTest.java
index 6507321..4111aad 100644
--- a/yudao-module-crm/src/test/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerAutoPoolTest.java
+++ b/yudao-module-crm/src/test/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerAutoPoolTest.java
@@ -10,6 +10,11 @@
 import cn.iocoder.yudao.module.crm.framework.permission.core.aop.CrmPermissionAspect;
 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
 import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum;
+import cn.iocoder.yudao.module.crm.controller.admin.customer.CrmCustomerController;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
+import cn.iocoder.yudao.module.system.api.dept.DeptApi;
+import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
 import cn.idev.excel.metadata.data.ReadCellData;
 import com.baomidou.mybatisplus.core.MybatisConfiguration;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -21,6 +26,7 @@
 import java.lang.reflect.Proxy;
 import java.math.BigDecimal;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.atomic.AtomicReference;
 
 import static org.junit.jupiter.api.Assertions.*;
@@ -70,6 +76,31 @@
         assertPoolListFilter(true);
     }
 
+    @Test
+    void poolCustomersUseSameOwnerAndDepartmentAsCustomerManagement() {
+        var controller = new CrmCustomerController();
+        var users = AdminUserApi.class.cast(Proxy.newProxyInstance(getClass().getClassLoader(),
+                new Class<?>[]{AdminUserApi.class}, (proxy, method, args) -> {
+                    assertEquals("getUserMap", method.getName());
+                    return Map.of(10L, new AdminUserRespDTO().setId(10L).setNickname("閿�鍞礋璐d汉").setDeptId(20L));
+                }));
+        var departments = DeptApi.class.cast(Proxy.newProxyInstance(getClass().getClassLoader(),
+                new Class<?>[]{DeptApi.class}, (proxy, method, args) -> {
+                    assertEquals("getDeptMap", method.getName());
+                    return Map.of(20L, new DeptRespDTO().setId(20L).setName("閿�鍞儴"));
+                }));
+        var config = CrmCustomerPoolConfigService.class.cast(Proxy.newProxyInstance(getClass().getClassLoader(),
+                new Class<?>[]{CrmCustomerPoolConfigService.class}, (proxy, method, args) -> null));
+        ReflectionTestUtils.setField(controller, "adminUserApi", users);
+        ReflectionTestUtils.setField(controller, "deptApi", departments);
+        ReflectionTestUtils.setField(controller, "customerPoolConfigService", config);
+        var customer = controller.buildCustomerDetailList(List.of(new CrmCustomerDO().setId(1L)
+                .setOwnerUserId(10L).setAutoPoolEnabled(true))).getFirst();
+        assertEquals(10L, customer.getOwnerUserId());
+        assertEquals("閿�鍞礋璐d汉", customer.getOwnerUserName());
+        assertEquals("閿�鍞儴", customer.getOwnerUserDeptName());
+    }
+
     private void assertPoolListFilter(boolean superAdmin) {
         TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(), "test"), CrmCustomerDO.class);
         var mapper = CrmCustomerMapper.class.cast(Proxy.newProxyInstance(getClass().getClassLoader(),
@@ -77,7 +108,7 @@
                     if (method.getName().equals("selectJoinPage")) {
                         var query = (com.github.yulichang.wrapper.MPJLambdaWrapper<?>) args[2];
                         String sql = query.getSqlSegment();
-                        assertTrue(sql.contains("owner_user_id IS NULL"), sql);
+                        assertFalse(sql.contains("owner_user_id IS NULL"), sql);
                         assertEquals(!superAdmin, sql.contains("auto_pool_enabled ="), sql);
                         return new cn.iocoder.yudao.framework.common.pojo.PageResult<>(List.of(), 0L);
                     }

--
Gitblit v1.9.3