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