Merge branch 'test' of http://git.lionquexpress.com/wuweihua/BMS into test
This commit is contained in:
+10
-6
@@ -7,9 +7,9 @@ import java.util.Date;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import lombok.ToString;
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
|
||||||
import com.bms.common.annotation.Excel;
|
import com.bms.common.annotation.Excel;
|
||||||
import com.bms.common.core.domain.BaseEntity;
|
import com.bms.common.core.domain.BaseEntity;
|
||||||
|
|
||||||
@@ -52,16 +52,20 @@ public class BmsCustomer extends BaseEntity
|
|||||||
private String isEnable;
|
private String isEnable;
|
||||||
|
|
||||||
/** 业务员用户ID */
|
/** 业务员用户ID */
|
||||||
@Excel(name = "业务员用户ID")
|
|
||||||
private String salesUserId;
|
private String salesUserId;
|
||||||
|
|
||||||
/** 业务员姓名 */
|
/** 业务员姓名(查询结果只回填已关联系统用户的姓名) */
|
||||||
@Excel(name = "业务员姓名")
|
|
||||||
private String salesUser;
|
private String salesUser;
|
||||||
|
|
||||||
/** 业务员昵称(join sys_user.nick_name,sales_user_id 存工号=sys_user.user_name) */
|
/** 业务员昵称(关联 sys_user.nick_name) */
|
||||||
|
@Excel(name = "业务员")
|
||||||
private String salesUserNickName;
|
private String salesUserNickName;
|
||||||
|
|
||||||
|
/** 客户同步源中的原始业务员工号,仅供内部同步和迁移使用。 */
|
||||||
|
@JsonIgnore
|
||||||
|
@ToString.Exclude
|
||||||
|
private String sourceSalesCode;
|
||||||
|
|
||||||
/** 资金额度(元) */
|
/** 资金额度(元) */
|
||||||
@Excel(name = "资金额度", readConverterExp = "元=")
|
@Excel(name = "资金额度", readConverterExp = "元=")
|
||||||
private BigDecimal ed;
|
private BigDecimal ed;
|
||||||
|
|||||||
+3
@@ -34,6 +34,9 @@ public interface BmsCustomerMapper
|
|||||||
*/
|
*/
|
||||||
public List<BmsCustomer> selectBmsCustomerList(BmsCustomer bmsCustomer);
|
public List<BmsCustomer> selectBmsCustomerList(BmsCustomer bmsCustomer);
|
||||||
|
|
||||||
|
/** 校验业务员用户ID仍对应未删除的系统用户。 */
|
||||||
|
public int countValidSalesUserId(@org.apache.ibatis.annotations.Param("salesUserId") String salesUserId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新增客户主
|
* 新增客户主
|
||||||
*
|
*
|
||||||
|
|||||||
+5
-6
@@ -11,16 +11,15 @@ import com.bms.customer.customerinfo.domain.BmsCustomer;
|
|||||||
*/
|
*/
|
||||||
public interface CustomerSyncMapper
|
public interface CustomerSyncMapper
|
||||||
{
|
{
|
||||||
/**
|
/** 库中未删除的全部客户编码,用于判定新增/更新。 */
|
||||||
* 库中未删除的全部客户编码,用于判定新增/更新
|
|
||||||
*/
|
|
||||||
List<String> selectExistingCodes();
|
List<String> selectExistingCodes();
|
||||||
|
|
||||||
/**
|
/** 未删除用户映射,用于唯一工号匹配。 */
|
||||||
* 未删除用户的 工号(user_name)->用户ID(user_id) 映射,用于 TMS BELONG_SALER 工号转换
|
|
||||||
*/
|
|
||||||
List<SysUser> selectUserLoginMap();
|
List<SysUser> selectUserLoginMap();
|
||||||
|
|
||||||
|
/** 读取存量客户的人工业务员选择和上次同步的源工号。 */
|
||||||
|
List<BmsCustomer> selectExistingSalesAssignments();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新增客户(同步专用,字段集与老系统导入脚本一致)
|
* 新增客户(同步专用,字段集与老系统导入脚本一致)
|
||||||
*/
|
*/
|
||||||
|
|||||||
+1
-1
@@ -587,7 +587,7 @@ public class BmsCustomerLogServiceImpl implements IBmsCustomerLogService
|
|||||||
return s == null ? "" : s;
|
return s == null ? "" : s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 人员字段展示:姓名(工号),缺姓名时只显示工号 */
|
/** 人员字段展示:姓名(系统用户ID),缺姓名时只显示系统用户ID。 */
|
||||||
private static String userDisplay(String code, String name)
|
private static String userDisplay(String code, String name)
|
||||||
{
|
{
|
||||||
String c = trimToNull(code);
|
String c = trimToNull(code);
|
||||||
|
|||||||
+20
-1
@@ -82,7 +82,7 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
|
|||||||
* @return 客户主
|
* @return 客户主
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
// sales_user_id 存的是员工工号(=sys_user.user_name),仅本人/本部门均通过 sys_user 别名 su 关联匹配
|
// sales_user_id 只存系统 user_id;数据权限通过该用户的部门和用户范围判断。
|
||||||
@DataScope(deptAlias = "su", deptField = "dept_id", userAlias = "su", userField = "user_id")
|
@DataScope(deptAlias = "su", deptField = "dept_id", userAlias = "su", userField = "user_id")
|
||||||
public List<BmsCustomer> selectBmsCustomerList(BmsCustomer bmsCustomer)
|
public List<BmsCustomer> selectBmsCustomerList(BmsCustomer bmsCustomer)
|
||||||
{
|
{
|
||||||
@@ -275,6 +275,7 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
|
|||||||
public int insertBmsCustomer(BmsCustomer bmsCustomer)
|
public int insertBmsCustomer(BmsCustomer bmsCustomer)
|
||||||
{
|
{
|
||||||
checkContractDate(bmsCustomer.getContractStartDate(), bmsCustomer.getContractEndDate());
|
checkContractDate(bmsCustomer.getContractStartDate(), bmsCustomer.getContractEndDate());
|
||||||
|
normalizeAndValidateSalesUserId(bmsCustomer);
|
||||||
SysUser user = SecurityUtils.getLoginUser().getUser();
|
SysUser user = SecurityUtils.getLoginUser().getUser();
|
||||||
bmsCustomer.setCreateTime(DateUtils.getNowDate());
|
bmsCustomer.setCreateTime(DateUtils.getNowDate());
|
||||||
bmsCustomer.setCreateBy(user.getUserName());
|
bmsCustomer.setCreateBy(user.getUserName());
|
||||||
@@ -303,6 +304,7 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
|
|||||||
public int updateBmsCustomer(BmsCustomer bmsCustomer)
|
public int updateBmsCustomer(BmsCustomer bmsCustomer)
|
||||||
{
|
{
|
||||||
checkContractDate(bmsCustomer.getContractStartDate(), bmsCustomer.getContractEndDate());
|
checkContractDate(bmsCustomer.getContractStartDate(), bmsCustomer.getContractEndDate());
|
||||||
|
normalizeAndValidateSalesUserId(bmsCustomer);
|
||||||
SysUser user = SecurityUtils.getLoginUser().getUser();
|
SysUser user = SecurityUtils.getLoginUser().getUser();
|
||||||
bmsCustomer.setUpdateTime(DateUtils.getNowDate());
|
bmsCustomer.setUpdateTime(DateUtils.getNowDate());
|
||||||
bmsCustomer.setUpdateBy(user.getUserName());
|
bmsCustomer.setUpdateBy(user.getUserName());
|
||||||
@@ -518,4 +520,21 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
|
|||||||
throw new ServiceException("合同结束时间不能早于开始时间");
|
throw new ServiceException("合同结束时间不能早于开始时间");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 客户编辑仅允许写入真实存在的系统用户ID,不接受工号作为兼容值。 */
|
||||||
|
private void normalizeAndValidateSalesUserId(BmsCustomer customer)
|
||||||
|
{
|
||||||
|
String salesUserId = customer.getSalesUserId();
|
||||||
|
if (salesUserId == null || salesUserId.trim().isEmpty())
|
||||||
|
{
|
||||||
|
customer.setSalesUserId(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
salesUserId = salesUserId.trim();
|
||||||
|
if (bmsCustomerMapper.countValidSalesUserId(salesUserId) == 0)
|
||||||
|
{
|
||||||
|
throw new ServiceException("业务员不存在或已删除,请从业务员选择器中重新选择");
|
||||||
|
}
|
||||||
|
customer.setSalesUserId(salesUserId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+52
-24
@@ -9,6 +9,7 @@ import java.util.HashSet;
|
|||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -23,7 +24,7 @@ import com.bms.customer.customerinfo.mapper.CustomerSyncMapper;
|
|||||||
* 老系统 Oracle TAB_CUSTOMER -> ctr_customer 每日同步。
|
* 老系统 Oracle TAB_CUSTOMER -> ctr_customer 每日同步。
|
||||||
*
|
*
|
||||||
* 字段映射、字典转换与 D:\\生产客户数据\\scripts\\import_customers.py 完全一致:
|
* 字段映射、字典转换与 D:\\生产客户数据\\scripts\\import_customers.py 完全一致:
|
||||||
* 按 customer_code 判定新增/更新;源为空的字段不写(走默认值/保留原值)。
|
* 按 customer_code 判定新增/更新;普通资料的源空字段不写,业务员归属则按匹配结果明确写入ID或NULL。
|
||||||
*
|
*
|
||||||
* @author bms
|
* @author bms
|
||||||
*/
|
*/
|
||||||
@@ -59,7 +60,6 @@ public class CustomerSyncService
|
|||||||
private static final int LEN_CODE = 50;
|
private static final int LEN_CODE = 50;
|
||||||
private static final int LEN_NAME = 100;
|
private static final int LEN_NAME = 100;
|
||||||
private static final int LEN_CODE_DW = 50;
|
private static final int LEN_CODE_DW = 50;
|
||||||
private static final int LEN_USER_ID = 64;
|
|
||||||
private static final int LEN_USER = 50;
|
private static final int LEN_USER = 50;
|
||||||
private static final int LEN_REMARK = 500;
|
private static final int LEN_REMARK = 500;
|
||||||
/** 告警明细最多打印条数 */
|
/** 告警明细最多打印条数 */
|
||||||
@@ -86,8 +86,15 @@ public class CustomerSyncService
|
|||||||
|
|
||||||
Set<String> existingCodes = new HashSet<>(customerSyncMapper.selectExistingCodes());
|
Set<String> existingCodes = new HashSet<>(customerSyncMapper.selectExistingCodes());
|
||||||
|
|
||||||
// 业务员归属转本系统用户ID:数据权限按 user_id 控制,工号后续修改不影响归属
|
// 源工号只用于匹配;归属字段始终保存系统 user_id。
|
||||||
Map<String, String> userIdByLogin = loadUserIdByLogin();
|
Map<String, List<String>> userIdsByLogin = loadUserIdsByLogin();
|
||||||
|
Set<String> validUserIds = new HashSet<>();
|
||||||
|
userIdsByLogin.values().forEach(validUserIds::addAll);
|
||||||
|
Map<String, BmsCustomer> existingSalesAssignments = new HashMap<>();
|
||||||
|
for (BmsCustomer existing : customerSyncMapper.selectExistingSalesAssignments())
|
||||||
|
{
|
||||||
|
existingSalesAssignments.put(existing.getCustomerCode(), existing);
|
||||||
|
}
|
||||||
|
|
||||||
List<BmsCustomer> inserts = new ArrayList<>();
|
List<BmsCustomer> inserts = new ArrayList<>();
|
||||||
List<BmsCustomer> updates = new ArrayList<>();
|
List<BmsCustomer> updates = new ArrayList<>();
|
||||||
@@ -123,7 +130,8 @@ public class CustomerSyncService
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
BmsCustomer c = mapRow(row, code, name, userIdByLogin, warnings);
|
BmsCustomer c = mapRow(row, code, name, userIdsByLogin,
|
||||||
|
validUserIds, existingSalesAssignments.get(code), warnings);
|
||||||
if (existingCodes.contains(code))
|
if (existingCodes.contains(code))
|
||||||
{
|
{
|
||||||
c.setUpdateBy(SYNC_MARKER);
|
c.setUpdateBy(SYNC_MARKER);
|
||||||
@@ -161,7 +169,8 @@ public class CustomerSyncService
|
|||||||
* 单行映射(逻辑对齐 import_customers.py 的 build_row)
|
* 单行映射(逻辑对齐 import_customers.py 的 build_row)
|
||||||
*/
|
*/
|
||||||
private BmsCustomer mapRow(Map<String, Object> row, String code, String name,
|
private BmsCustomer mapRow(Map<String, Object> row, String code, String name,
|
||||||
Map<String, String> userIdByLogin, List<String> warnings)
|
Map<String, List<String>> userIdsByLogin, Set<String> validUserIds,
|
||||||
|
BmsCustomer existingAssignment, List<String> warnings)
|
||||||
{
|
{
|
||||||
BmsCustomer c = new BmsCustomer();
|
BmsCustomer c = new BmsCustomer();
|
||||||
c.setCustomerCode(truncate(code, LEN_CODE, code, "customer_code", warnings));
|
c.setCustomerCode(truncate(code, LEN_CODE, code, "customer_code", warnings));
|
||||||
@@ -169,7 +178,10 @@ public class CustomerSyncService
|
|||||||
c.setDelFlag("0");
|
c.setDelFlag("0");
|
||||||
|
|
||||||
c.setCustomerCodeDw(truncate(getStr(row, "CUSTOMER_OUTER_CODE"), LEN_CODE_DW, code, "customer_code_dw", warnings));
|
c.setCustomerCodeDw(truncate(getStr(row, "CUSTOMER_OUTER_CODE"), LEN_CODE_DW, code, "customer_code_dw", warnings));
|
||||||
c.setSalesUserId(resolveSalesUserId(clean(getStr(row, "BELONG_SALER")), userIdByLogin, code, warnings));
|
String sourceSalesCode = clean(getStr(row, "BELONG_SALER"));
|
||||||
|
c.setSourceSalesCode(sourceSalesCode);
|
||||||
|
c.setSalesUserId(resolveSalesUserId(sourceSalesCode, userIdsByLogin,
|
||||||
|
validUserIds, existingAssignment, code, warnings));
|
||||||
c.setSalesUser(truncate(getStr(row, "BELONG_SALER_NAME"), LEN_USER, code, "sales_user", warnings));
|
c.setSalesUser(truncate(getStr(row, "BELONG_SALER_NAME"), LEN_USER, code, "sales_user", warnings));
|
||||||
c.setSettlementUser(truncate(getStr(row, "SETTLEMENT_MAN"), LEN_USER, code, "settlement_user", warnings));
|
c.setSettlementUser(truncate(getStr(row, "SETTLEMENT_MAN"), LEN_USER, code, "settlement_user", warnings));
|
||||||
c.setServiceUser(truncate(getStr(row, "SERVICE_MAN"), LEN_USER, code, "service_user", warnings));
|
c.setServiceUser(truncate(getStr(row, "SERVICE_MAN"), LEN_USER, code, "service_user", warnings));
|
||||||
@@ -231,40 +243,56 @@ public class CustomerSyncService
|
|||||||
return ("1".equals(s) || "1.0".equals(s)) ? "0" : "1";
|
return ("1".equals(s) || "1.0".equals(s)) ? "0" : "1";
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 加载未删除用户的 工号(user_name)->用户ID(user_id) 映射 */
|
/** 加载未删除用户的工号映射;保留重复项以便将歧义匹配按未关联处理。 */
|
||||||
private Map<String, String> loadUserIdByLogin()
|
private Map<String, List<String>> loadUserIdsByLogin()
|
||||||
{
|
{
|
||||||
Map<String, String> map = new HashMap<>();
|
Map<String, List<String>> map = new HashMap<>();
|
||||||
for (SysUser u : customerSyncMapper.selectUserLoginMap())
|
for (SysUser u : customerSyncMapper.selectUserLoginMap())
|
||||||
{
|
{
|
||||||
if (u != null && u.getUserName() != null && u.getUserId() != null
|
if (u != null && clean(u.getUserName()) != null && u.getUserId() != null)
|
||||||
&& !map.containsKey(u.getUserName()))
|
|
||||||
{
|
{
|
||||||
map.put(u.getUserName(), String.valueOf(u.getUserId()));
|
map.computeIfAbsent(u.getUserName().trim(), key -> new ArrayList<>())
|
||||||
|
.add(String.valueOf(u.getUserId()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 业务员工号 -> 本系统 sys_user.user_id 转换(数据权限按 user_id 控制,工号修改不影响归属)。
|
* 只在唯一匹配时关联系统用户。
|
||||||
* 工号在系统用户中不存在时保留原工号并告警(常见于该用户尚未同步),避免归属信息丢失。
|
* 源工号不变时保留客户页面人工选择的有效业务员;工号为空时也保留有效业务员。
|
||||||
*/
|
*/
|
||||||
private String resolveSalesUserId(String salerCode, Map<String, String> userIdByLogin,
|
private String resolveSalesUserId(String salerCode, Map<String, List<String>> userIdsByLogin,
|
||||||
|
Set<String> validUserIds, BmsCustomer existingAssignment,
|
||||||
String code, List<String> warnings)
|
String code, List<String> warnings)
|
||||||
{
|
{
|
||||||
String s = truncate(salerCode, LEN_USER_ID, code, "sales_user_id", warnings);
|
String existingUserId = existingAssignment == null ? null : clean(existingAssignment.getSalesUserId());
|
||||||
if (s == null)
|
boolean existingUserValid = existingUserId != null && validUserIds.contains(existingUserId);
|
||||||
|
if (salerCode == null)
|
||||||
{
|
{
|
||||||
return null;
|
return existingUserValid ? existingUserId : null;
|
||||||
}
|
}
|
||||||
String userId = userIdByLogin.get(s);
|
|
||||||
if (userId != null)
|
boolean sourceCodeUnchanged = existingAssignment != null
|
||||||
|
&& Objects.equals(salerCode, clean(existingAssignment.getSourceSalesCode()));
|
||||||
|
boolean sourceCodeUnknown = existingAssignment != null
|
||||||
|
&& clean(existingAssignment.getSourceSalesCode()) == null;
|
||||||
|
if (existingUserValid && (sourceCodeUnchanged || sourceCodeUnknown))
|
||||||
{
|
{
|
||||||
return userId;
|
// 历史有效用户ID可能尚无可恢复的源工号;首次同步建立源工号基线时不覆盖已有人工归属。
|
||||||
|
return existingUserId;
|
||||||
}
|
}
|
||||||
warnings.add(code + ": 业务员工号 " + s + " 在系统用户中不存在,sales_user_id 保留原工号");
|
|
||||||
return s;
|
List<String> matchedUserIds = userIdsByLogin.get(salerCode);
|
||||||
|
if (matchedUserIds != null && matchedUserIds.size() == 1)
|
||||||
|
{
|
||||||
|
return matchedUserIds.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
warnings.add(code + (matchedUserIds == null || matchedUserIds.isEmpty()
|
||||||
|
? ": 业务员工号未匹配到系统用户,客户保持未关联"
|
||||||
|
: ": 业务员工号匹配到多个系统用户,客户保持未关联"));
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String clean(String v)
|
private static String clean(String v)
|
||||||
|
|||||||
@@ -45,7 +45,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
<!-- 信用额度=总额度+额外额度-已用额度-->
|
<!-- 信用额度=总额度+额外额度-已用额度-->
|
||||||
<sql id="selectBmsCustomerVo">
|
<sql id="selectBmsCustomerVo">
|
||||||
select c.customer_id, c.customer_code, c.customer_name, c.customer_code_dw, c.credit_code, c.customer_type,
|
select c.customer_id, c.customer_code, c.customer_name, c.customer_code_dw, c.credit_code, c.customer_type,
|
||||||
c.is_enable, c.sales_user_id, c.sales_user, c.ed, c.zq, c.settlement_user_id, c.settlement_user,
|
c.is_enable,
|
||||||
|
case when su.user_id is not null then cast(su.user_id as char) else null end as sales_user_id,
|
||||||
|
su.nick_name as sales_user, c.ed, c.zq, c.settlement_user_id, c.settlement_user,
|
||||||
c.service_user_id, c.service_user, c.settlement_type, c.temp_ed,
|
c.service_user_id, c.service_user, c.settlement_type, c.temp_ed,
|
||||||
(select coalesce(sum(ca.balance), 0) from ctr_customer_account ca
|
(select coalesce(sum(ca.balance), 0) from ctr_customer_account ca
|
||||||
where ca.customer_id = c.customer_id and ca.currency = 'CNY' and ca.del_flag = '0') as account_balance,
|
where ca.customer_id = c.customer_id and ca.currency = 'CNY' and ca.del_flag = '0') as account_balance,
|
||||||
@@ -61,11 +63,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
su.nick_name as sales_user_nick_name,
|
su.nick_name as sales_user_nick_name,
|
||||||
cps.price_set_id, ps.price_set_name
|
cps.price_set_id, ps.price_set_name
|
||||||
from ctr_customer c
|
from ctr_customer c
|
||||||
<!-- sales_user_id 统一存本系统 user_id(同步时由工号转换、手工录入选人即存ID),
|
<!-- sales_user_id 只保存 sys_user.user_id;源工号不参与客户查询和权限匹配。 -->
|
||||||
数据权限按 su.user_id / su.dept_id 控制;保留 user_name 匹配仅作历史未转换工号兜底 -->
|
|
||||||
left join sys_user su
|
left join sys_user su
|
||||||
on su.del_flag = '0'
|
on su.del_flag = '0'
|
||||||
and (su.user_id = c.sales_user_id + 0 or su.user_name = c.sales_user_id)
|
and cast(su.user_id as char) = c.sales_user_id
|
||||||
<!-- 客户套餐绑定:uk_customer_one_set 保证一客户至多一条,不会放大行数 -->
|
<!-- 客户套餐绑定:uk_customer_one_set 保证一客户至多一条,不会放大行数 -->
|
||||||
left join prc_customer_price_set cps on cps.customer_id = c.customer_id
|
left join prc_customer_price_set cps on cps.customer_id = c.customer_id
|
||||||
left join prc_price_set ps on ps.price_set_id = cps.price_set_id
|
left join prc_price_set ps on ps.price_set_id = cps.price_set_id
|
||||||
@@ -92,7 +93,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
<if test="customerType != null and customerType != ''"> and c.customer_type = #{customerType}</if>
|
<if test="customerType != null and customerType != ''"> and c.customer_type = #{customerType}</if>
|
||||||
<if test="isEnable != null and isEnable != ''"> and c.is_enable = #{isEnable}</if>
|
<if test="isEnable != null and isEnable != ''"> and c.is_enable = #{isEnable}</if>
|
||||||
<if test="salesUserId != null and salesUserId != ''"> and c.sales_user_id = #{salesUserId}</if>
|
<if test="salesUserId != null and salesUserId != ''"> and c.sales_user_id = #{salesUserId}</if>
|
||||||
<if test="salesUser != null and salesUser != ''"> and c.sales_user = #{salesUser}</if>
|
<if test="salesUser != null and salesUser != ''"> and su.nick_name = #{salesUser}</if>
|
||||||
<if test="ed != null "> and c.ed = #{ed}</if>
|
<if test="ed != null "> and c.ed = #{ed}</if>
|
||||||
<if test="zq != null "> and c.zq = #{zq}</if>
|
<if test="zq != null "> and c.zq = #{zq}</if>
|
||||||
<if test="settlementUserId != null and settlementUserId != ''"> and c.settlement_user_id = #{settlementUserId}</if>
|
<if test="settlementUserId != null and settlementUserId != ''"> and c.settlement_user_id = #{settlementUserId}</if>
|
||||||
@@ -111,6 +112,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
order by c.customer_id desc
|
order by c.customer_id desc
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="countValidSalesUserId" resultType="int">
|
||||||
|
select count(1)
|
||||||
|
from sys_user
|
||||||
|
where user_id = #{salesUserId}
|
||||||
|
and del_flag = '0'
|
||||||
|
</select>
|
||||||
|
|
||||||
<select id="selectBmsCustomerByCustomerId" parameterType="Long" resultMap="BmsCustomerResult">
|
<select id="selectBmsCustomerByCustomerId" parameterType="Long" resultMap="BmsCustomerResult">
|
||||||
<include refid="selectBmsCustomerVo"/>
|
<include refid="selectBmsCustomerVo"/>
|
||||||
where c.customer_id = #{customerId} and c.del_flag = '0'
|
where c.customer_id = #{customerId} and c.del_flag = '0'
|
||||||
|
|||||||
@@ -8,22 +8,28 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
SELECT customer_code FROM ctr_customer WHERE del_flag = '0'
|
SELECT customer_code FROM ctr_customer WHERE del_flag = '0'
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<!-- 工号->用户ID 映射(列别名显式映射,项目未开下划线转驼峰) -->
|
<!-- 工号->用户ID 候选;Java 层检测重复工号,不任意取一条。 -->
|
||||||
<select id="selectUserLoginMap" resultType="com.bms.common.core.domain.entity.SysUser">
|
<select id="selectUserLoginMap" resultType="com.bms.common.core.domain.entity.SysUser">
|
||||||
SELECT user_id AS userId, user_name AS userName
|
SELECT user_id AS userId, user_name AS userName
|
||||||
FROM sys_user
|
FROM sys_user
|
||||||
WHERE del_flag = '0'
|
WHERE del_flag = '0'
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<!-- 字段集与 scripts/import_customers.py 的 MAP_COLUMNS 保持一致;
|
<select id="selectExistingSalesAssignments" resultType="com.bms.customer.customerinfo.domain.BmsCustomer">
|
||||||
源行为空的字段不写,走数据库默认值 -->
|
SELECT customer_code AS customerCode,
|
||||||
|
sales_user_id AS salesUserId,
|
||||||
|
source_sales_code AS sourceSalesCode
|
||||||
|
FROM ctr_customer
|
||||||
|
WHERE del_flag = '0'
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 普通客户资料沿用源空值不覆盖;业务员ID和源工号始终按本次匹配结果写入,允许明确清空。 -->
|
||||||
<insert id="insertSyncCustomer" parameterType="com.bms.customer.customerinfo.domain.BmsCustomer">
|
<insert id="insertSyncCustomer" parameterType="com.bms.customer.customerinfo.domain.BmsCustomer">
|
||||||
INSERT INTO ctr_customer (
|
INSERT INTO ctr_customer (
|
||||||
customer_code, customer_name, is_enable,
|
customer_code, customer_name, is_enable,
|
||||||
del_flag, create_by
|
del_flag, create_by, sales_user_id, source_sales_code
|
||||||
<if test="customerCodeDw != null">, customer_code_dw</if>
|
<if test="customerCodeDw != null">, customer_code_dw</if>
|
||||||
<if test="customerType != null">, customer_type</if>
|
<if test="customerType != null">, customer_type</if>
|
||||||
<if test="salesUserId != null">, sales_user_id</if>
|
|
||||||
<if test="salesUser != null">, sales_user</if>
|
<if test="salesUser != null">, sales_user</if>
|
||||||
<if test="settlementUser != null">, settlement_user</if>
|
<if test="settlementUser != null">, settlement_user</if>
|
||||||
<if test="serviceUser != null">, service_user</if>
|
<if test="serviceUser != null">, service_user</if>
|
||||||
@@ -37,10 +43,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
<if test="createTime != null">, create_time</if>
|
<if test="createTime != null">, create_time</if>
|
||||||
) VALUES (
|
) VALUES (
|
||||||
#{customerCode}, #{customerName}, #{isEnable},
|
#{customerCode}, #{customerName}, #{isEnable},
|
||||||
'0', #{createBy}
|
'0', #{createBy}, #{salesUserId}, #{sourceSalesCode}
|
||||||
<if test="customerCodeDw != null">, #{customerCodeDw}</if>
|
<if test="customerCodeDw != null">, #{customerCodeDw}</if>
|
||||||
<if test="customerType != null">, #{customerType}</if>
|
<if test="customerType != null">, #{customerType}</if>
|
||||||
<if test="salesUserId != null">, #{salesUserId}</if>
|
|
||||||
<if test="salesUser != null">, #{salesUser}</if>
|
<if test="salesUser != null">, #{salesUser}</if>
|
||||||
<if test="settlementUser != null">, #{settlementUser}</if>
|
<if test="settlementUser != null">, #{settlementUser}</if>
|
||||||
<if test="serviceUser != null">, #{serviceUser}</if>
|
<if test="serviceUser != null">, #{serviceUser}</if>
|
||||||
@@ -61,7 +66,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
<if test="customerName != null">, customer_name = #{customerName}</if>
|
<if test="customerName != null">, customer_name = #{customerName}</if>
|
||||||
<if test="customerCodeDw != null">, customer_code_dw = #{customerCodeDw}</if>
|
<if test="customerCodeDw != null">, customer_code_dw = #{customerCodeDw}</if>
|
||||||
<if test="customerType != null">, customer_type = #{customerType}</if>
|
<if test="customerType != null">, customer_type = #{customerType}</if>
|
||||||
<if test="salesUserId != null">, sales_user_id = #{salesUserId}</if>
|
, sales_user_id = #{salesUserId}
|
||||||
|
, source_sales_code = #{sourceSalesCode}
|
||||||
<if test="salesUser != null">, sales_user = #{salesUser}</if>
|
<if test="salesUser != null">, sales_user = #{salesUser}</if>
|
||||||
<if test="settlementUser != null">, settlement_user = #{settlementUser}</if>
|
<if test="settlementUser != null">, settlement_user = #{settlementUser}</if>
|
||||||
<if test="serviceUser != null">, service_user = #{serviceUser}</if>
|
<if test="serviceUser != null">, service_user = #{serviceUser}</if>
|
||||||
|
|||||||
@@ -93,8 +93,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
AND ifnull(c.del_flag, '0') = '0'
|
AND ifnull(c.del_flag, '0') = '0'
|
||||||
INNER JOIN sys_user su
|
INNER JOIN sys_user su
|
||||||
ON su.del_flag = '0'
|
ON su.del_flag = '0'
|
||||||
AND (su.user_name = c.sales_user_id COLLATE utf8mb4_general_ci
|
AND cast(su.user_id as char) = c.sales_user_id
|
||||||
OR su.user_id = c.sales_user_id + 0)
|
|
||||||
WHERE cps.price_set_id = s.price_set_id
|
WHERE cps.price_set_id = s.price_set_id
|
||||||
${params.dataScope}
|
${params.dataScope}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,10 +1,4 @@
|
|||||||
-- 客户归属销售员由"工号"改存本系统用户ID(数据权限按 user_id 控制,工号后续修改不影响归属)
|
-- DEPRECATED: 不要执行本文件。
|
||||||
-- 同步链路已在 CustomerSyncService.resolveSalesUserId 做同样转换,本脚本只处理存量数据。
|
-- 旧版脚本仅按非数字判断工号并直接 UPDATE,无法安全处理重复工号和数字工号/user_id 冲突。
|
||||||
-- 仅转换"含非数字字符"的工号值(工号形如 WS0052/WSC0184/wsadmin);
|
-- 请先执行 customer+supplier/20261028_customer_sales_user_classification.sql 查看清单,
|
||||||
-- 已是数字(user_id)的行不触碰,脚本可重复执行。
|
-- 再按上线顺序执行 customer+supplier/20261028_customer_sales_user_migration.sql。
|
||||||
UPDATE ctr_customer c
|
|
||||||
JOIN sys_user u ON u.del_flag = '0' AND u.user_name = c.sales_user_id
|
|
||||||
SET c.sales_user_id = CONVERT(u.user_id, CHAR)
|
|
||||||
WHERE c.del_flag = '0'
|
|
||||||
AND c.sales_user_id IS NOT NULL
|
|
||||||
AND c.sales_user_id REGEXP '[^0-9]';
|
|
||||||
|
|||||||
@@ -356,7 +356,8 @@ CREATE TABLE `ctr_customer` (
|
|||||||
`credit_code` varchar(18) DEFAULT '' COMMENT '统一社会信用代码',
|
`credit_code` varchar(18) DEFAULT '' COMMENT '统一社会信用代码',
|
||||||
`customer_type` char(1) DEFAULT '0' COMMENT '业务类型(0直客 1同行 2集运)',
|
`customer_type` char(1) DEFAULT '0' COMMENT '业务类型(0直客 1同行 2集运)',
|
||||||
`is_enable` char(1) DEFAULT '0' COMMENT '启用状态(0正常 1停用)',
|
`is_enable` char(1) DEFAULT '0' COMMENT '启用状态(0正常 1停用)',
|
||||||
`sales_user_id` varchar(64) DEFAULT '' COMMENT '业务员用户ID',
|
`sales_user_id` varchar(64) DEFAULT NULL COMMENT '业务员系统用户ID(sys_user.user_id)',
|
||||||
|
`source_sales_code` varchar(255) DEFAULT NULL COMMENT '客户同步源业务员工号(内部字段)',
|
||||||
`sales_user` varchar(50) DEFAULT '' COMMENT '业务员姓名',
|
`sales_user` varchar(50) DEFAULT '' COMMENT '业务员姓名',
|
||||||
`ed` decimal(15,2) DEFAULT '0.00' COMMENT '资金额度(元)',
|
`ed` decimal(15,2) DEFAULT '0.00' COMMENT '资金额度(元)',
|
||||||
`zq` int(11) DEFAULT '0' COMMENT '回款账期(天)',
|
`zq` int(11) DEFAULT '0' COMMENT '回款账期(天)',
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
-- MySQL 5.7
|
||||||
|
-- 客户业务员存量迁移前分类清单(只读,不修改数据)。
|
||||||
|
-- 请先执行本文件,检查 ID/工号冲突,再执行 20261028_customer_sales_user_migration.sql。
|
||||||
|
-- 分类依据:精确匹配 sys_user.user_id;或按区分大小写的 sys_user.user_name 唯一匹配。
|
||||||
|
|
||||||
|
-- 分类汇总:VALID_USER_ID 保留;UNIQUE_USERNAME 可安全转换;其余分类写入冲突/未匹配清单。
|
||||||
|
SELECT classified.classification, COUNT(*) AS customer_count
|
||||||
|
FROM (
|
||||||
|
SELECT c.customer_id,
|
||||||
|
CASE
|
||||||
|
WHEN c.sales_user_id IS NULL OR TRIM(c.sales_user_id) = '' THEN 'EMPTY'
|
||||||
|
WHEN id_match.match_count > 0 AND name_match.match_count > 0 THEN 'ID_USERNAME_COLLISION'
|
||||||
|
WHEN id_match.match_count > 0 THEN 'VALID_USER_ID'
|
||||||
|
WHEN name_match.match_count = 1 THEN 'UNIQUE_USERNAME'
|
||||||
|
WHEN name_match.match_count > 1 THEN 'AMBIGUOUS_USERNAME'
|
||||||
|
ELSE 'NO_MATCH'
|
||||||
|
END AS classification
|
||||||
|
FROM ctr_customer c
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT CAST(user_id AS CHAR) AS lookup_value, COUNT(*) AS match_count
|
||||||
|
FROM sys_user
|
||||||
|
WHERE del_flag = '0'
|
||||||
|
GROUP BY CAST(user_id AS CHAR)
|
||||||
|
) id_match ON BINARY id_match.lookup_value = BINARY TRIM(c.sales_user_id)
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT BINARY TRIM(user_name) AS lookup_value, COUNT(*) AS match_count
|
||||||
|
FROM sys_user
|
||||||
|
WHERE del_flag = '0'
|
||||||
|
AND user_name IS NOT NULL
|
||||||
|
AND user_name != ''
|
||||||
|
GROUP BY BINARY TRIM(user_name)
|
||||||
|
) name_match ON name_match.lookup_value = BINARY TRIM(c.sales_user_id)
|
||||||
|
WHERE c.del_flag = '0'
|
||||||
|
) classified
|
||||||
|
GROUP BY classified.classification
|
||||||
|
ORDER BY classified.classification;
|
||||||
|
|
||||||
|
-- 逐条分类。冲突项会列出原值、user_id 候选和 user_name 候选,供管理员人工核实。
|
||||||
|
SELECT c.customer_id,
|
||||||
|
c.customer_code,
|
||||||
|
c.customer_name,
|
||||||
|
c.sales_user_id AS original_sales_user_id,
|
||||||
|
CASE
|
||||||
|
WHEN c.sales_user_id IS NULL OR TRIM(c.sales_user_id) = '' THEN 'EMPTY'
|
||||||
|
WHEN id_match.match_count > 0 AND name_match.match_count > 0 THEN 'ID_USERNAME_COLLISION'
|
||||||
|
WHEN id_match.match_count > 0 THEN 'VALID_USER_ID'
|
||||||
|
WHEN name_match.match_count = 1 THEN 'UNIQUE_USERNAME'
|
||||||
|
WHEN name_match.match_count > 1 THEN 'AMBIGUOUS_USERNAME'
|
||||||
|
ELSE 'NO_MATCH'
|
||||||
|
END AS classification,
|
||||||
|
COALESCE(id_match.match_count, 0) AS user_id_match_count,
|
||||||
|
COALESCE(name_match.match_count, 0) AS user_name_match_count,
|
||||||
|
id_match.candidate_user_ids AS user_id_candidates,
|
||||||
|
name_match.candidate_user_ids AS user_name_candidates
|
||||||
|
FROM ctr_customer c
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT CAST(user_id AS CHAR) AS lookup_value,
|
||||||
|
COUNT(*) AS match_count,
|
||||||
|
GROUP_CONCAT(CAST(user_id AS CHAR) ORDER BY user_id SEPARATOR ',') AS candidate_user_ids
|
||||||
|
FROM sys_user
|
||||||
|
WHERE del_flag = '0'
|
||||||
|
GROUP BY CAST(user_id AS CHAR)
|
||||||
|
) id_match ON BINARY id_match.lookup_value = BINARY TRIM(c.sales_user_id)
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT BINARY TRIM(user_name) AS lookup_value,
|
||||||
|
COUNT(*) AS match_count,
|
||||||
|
GROUP_CONCAT(CAST(user_id AS CHAR) ORDER BY user_id SEPARATOR ',') AS candidate_user_ids
|
||||||
|
FROM sys_user
|
||||||
|
WHERE del_flag = '0'
|
||||||
|
AND user_name IS NOT NULL
|
||||||
|
AND user_name != ''
|
||||||
|
GROUP BY BINARY TRIM(user_name)
|
||||||
|
) name_match ON name_match.lookup_value = BINARY TRIM(c.sales_user_id)
|
||||||
|
WHERE c.del_flag = '0'
|
||||||
|
ORDER BY classification, c.customer_id;
|
||||||
@@ -0,0 +1,142 @@
|
|||||||
|
-- MySQL 5.7
|
||||||
|
-- 客户业务员工号 -> 系统用户ID 存量迁移。
|
||||||
|
-- 上线前先执行 20261028_customer_sales_user_classification.sql 并核对 ID_USERNAME_COLLISION。
|
||||||
|
-- 自动转换仅处理唯一 user_name 匹配;未匹配、重复匹配和 ID/工号冲突会备份原值、清空 sales_user_id,留给管理员在客户编辑页处理。
|
||||||
|
-- 本脚本不连接数据库执行;可重复运行。完成标记写入后,重复运行不会再次处理存量或改写备份。
|
||||||
|
|
||||||
|
-- 新增内部源工号列(兼容 MySQL 5.7,不依赖 ADD COLUMN IF NOT EXISTS)。
|
||||||
|
SET @add_source_sales_code_sql = (
|
||||||
|
SELECT IF(COUNT(*) = 0,
|
||||||
|
'ALTER TABLE ctr_customer ADD COLUMN source_sales_code varchar(255) DEFAULT NULL COMMENT ''客户同步源业务员工号(内部字段)'' AFTER sales_user_id',
|
||||||
|
'SELECT 1')
|
||||||
|
FROM information_schema.columns
|
||||||
|
WHERE table_schema = DATABASE()
|
||||||
|
AND table_name = 'ctr_customer'
|
||||||
|
AND column_name = 'source_sales_code'
|
||||||
|
);
|
||||||
|
PREPARE add_source_sales_code_stmt FROM @add_source_sales_code_sql;
|
||||||
|
EXECUTE add_source_sales_code_stmt;
|
||||||
|
DEALLOCATE PREPARE add_source_sales_code_stmt;
|
||||||
|
|
||||||
|
-- 未匹配时使用 NULL,避免空字符串伪装成用户ID。
|
||||||
|
ALTER TABLE ctr_customer
|
||||||
|
MODIFY COLUMN sales_user_id varchar(64) DEFAULT NULL COMMENT '业务员系统用户ID(sys_user.user_id)';
|
||||||
|
|
||||||
|
-- 备份表同时保留分类结果和候选ID;PRIMARY KEY + INSERT IGNORE 保证原始值不会被后续重跑覆盖。
|
||||||
|
CREATE TABLE IF NOT EXISTS ctr_customer_sales_user_migration_backup (
|
||||||
|
customer_id bigint(20) NOT NULL COMMENT '客户ID',
|
||||||
|
customer_code varchar(50) NOT NULL COMMENT '客户编码',
|
||||||
|
original_sales_user_id varchar(64) DEFAULT NULL COMMENT '迁移前 sales_user_id 原值',
|
||||||
|
classification varchar(40) NOT NULL COMMENT '迁移前分类',
|
||||||
|
user_id_match_count int NOT NULL DEFAULT 0 COMMENT '精确 user_id 匹配数',
|
||||||
|
user_name_match_count int NOT NULL DEFAULT 0 COMMENT '精确 user_name 匹配数',
|
||||||
|
user_id_candidates text COMMENT 'user_id 匹配候选',
|
||||||
|
user_name_candidates text COMMENT 'user_name 匹配候选',
|
||||||
|
backup_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '备份时间',
|
||||||
|
PRIMARY KEY (customer_id),
|
||||||
|
KEY idx_customer_sales_user_backup_classification (classification)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客户业务员ID迁移原值及分类备份';
|
||||||
|
|
||||||
|
-- 防止成功执行后重跑时把后来新建/人工维护的客户重新当作存量数据处理。
|
||||||
|
CREATE TABLE IF NOT EXISTS ctr_customer_sales_user_migration_control (
|
||||||
|
migration_key varchar(64) NOT NULL,
|
||||||
|
status varchar(16) NOT NULL DEFAULT 'PENDING',
|
||||||
|
completed_at datetime DEFAULT NULL,
|
||||||
|
PRIMARY KEY (migration_key)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客户业务员ID迁移执行状态';
|
||||||
|
|
||||||
|
INSERT IGNORE INTO ctr_customer_sales_user_migration_control (migration_key, status)
|
||||||
|
VALUES ('20261028_customer_sales_user', 'PENDING');
|
||||||
|
|
||||||
|
START TRANSACTION;
|
||||||
|
|
||||||
|
-- 首次运行时先保留旧值和候选;后续事务失败可安全重跑,成功后由 control 表阻止再次处理。
|
||||||
|
INSERT IGNORE INTO ctr_customer_sales_user_migration_backup (
|
||||||
|
customer_id, customer_code, original_sales_user_id, classification,
|
||||||
|
user_id_match_count, user_name_match_count, user_id_candidates, user_name_candidates
|
||||||
|
)
|
||||||
|
SELECT c.customer_id,
|
||||||
|
c.customer_code,
|
||||||
|
c.sales_user_id,
|
||||||
|
CASE
|
||||||
|
WHEN c.sales_user_id IS NULL OR TRIM(c.sales_user_id) = '' THEN 'EMPTY'
|
||||||
|
WHEN id_match.match_count > 0 AND name_match.match_count > 0 THEN 'ID_USERNAME_COLLISION'
|
||||||
|
WHEN id_match.match_count > 0 THEN 'VALID_USER_ID'
|
||||||
|
WHEN name_match.match_count = 1 THEN 'UNIQUE_USERNAME'
|
||||||
|
WHEN name_match.match_count > 1 THEN 'AMBIGUOUS_USERNAME'
|
||||||
|
ELSE 'NO_MATCH'
|
||||||
|
END,
|
||||||
|
COALESCE(id_match.match_count, 0),
|
||||||
|
COALESCE(name_match.match_count, 0),
|
||||||
|
id_match.candidate_user_ids,
|
||||||
|
name_match.candidate_user_ids
|
||||||
|
FROM ctr_customer c
|
||||||
|
JOIN ctr_customer_sales_user_migration_control migration
|
||||||
|
ON migration.migration_key = '20261028_customer_sales_user'
|
||||||
|
AND migration.status = 'PENDING'
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT CAST(user_id AS CHAR) AS lookup_value,
|
||||||
|
COUNT(*) AS match_count,
|
||||||
|
GROUP_CONCAT(CAST(user_id AS CHAR) ORDER BY user_id SEPARATOR ',') AS candidate_user_ids
|
||||||
|
FROM sys_user
|
||||||
|
WHERE del_flag = '0'
|
||||||
|
GROUP BY CAST(user_id AS CHAR)
|
||||||
|
) id_match ON BINARY id_match.lookup_value = BINARY TRIM(c.sales_user_id)
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT BINARY TRIM(user_name) AS lookup_value,
|
||||||
|
COUNT(*) AS match_count,
|
||||||
|
GROUP_CONCAT(CAST(user_id AS CHAR) ORDER BY user_id SEPARATOR ',') AS candidate_user_ids
|
||||||
|
FROM sys_user
|
||||||
|
WHERE del_flag = '0'
|
||||||
|
AND user_name IS NOT NULL
|
||||||
|
AND user_name != ''
|
||||||
|
GROUP BY BINARY TRIM(user_name)
|
||||||
|
) name_match ON name_match.lookup_value = BINARY TRIM(c.sales_user_id)
|
||||||
|
WHERE c.del_flag = '0'
|
||||||
|
AND c.source_sales_code IS NULL;
|
||||||
|
|
||||||
|
-- 唯一工号映射到系统用户ID;不唯一、不匹配或存在ID/工号冲突的项不猜测,清空关联并保留源值。
|
||||||
|
UPDATE ctr_customer c
|
||||||
|
JOIN ctr_customer_sales_user_migration_backup b
|
||||||
|
ON b.customer_id = c.customer_id
|
||||||
|
JOIN ctr_customer_sales_user_migration_control migration
|
||||||
|
ON migration.migration_key = '20261028_customer_sales_user'
|
||||||
|
AND migration.status = 'PENDING'
|
||||||
|
SET c.source_sales_code = b.original_sales_user_id,
|
||||||
|
c.sales_user_id = CASE
|
||||||
|
WHEN b.classification = 'UNIQUE_USERNAME'
|
||||||
|
THEN b.user_name_candidates
|
||||||
|
ELSE NULL
|
||||||
|
END
|
||||||
|
WHERE c.del_flag = '0'
|
||||||
|
AND c.source_sales_code IS NULL
|
||||||
|
AND b.classification IN (
|
||||||
|
'UNIQUE_USERNAME',
|
||||||
|
'AMBIGUOUS_USERNAME',
|
||||||
|
'NO_MATCH',
|
||||||
|
'ID_USERNAME_COLLISION'
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 将旧空字符串归一为 NULL,已确认是系统用户ID的行保持不变。
|
||||||
|
UPDATE ctr_customer c
|
||||||
|
JOIN ctr_customer_sales_user_migration_control migration
|
||||||
|
ON migration.migration_key = '20261028_customer_sales_user'
|
||||||
|
AND migration.status = 'PENDING'
|
||||||
|
SET c.sales_user_id = NULL
|
||||||
|
WHERE c.del_flag = '0'
|
||||||
|
AND c.sales_user_id IS NOT NULL
|
||||||
|
AND TRIM(c.sales_user_id) = '';
|
||||||
|
|
||||||
|
UPDATE ctr_customer_sales_user_migration_control
|
||||||
|
SET status = 'DONE', completed_at = NOW()
|
||||||
|
WHERE migration_key = '20261028_customer_sales_user'
|
||||||
|
AND status = 'PENDING';
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
-- 执行后核对人工处理清单;原值和候选均保存在备份表中。
|
||||||
|
SELECT customer_id, customer_code, original_sales_user_id, classification,
|
||||||
|
user_id_candidates, user_name_candidates
|
||||||
|
FROM ctr_customer_sales_user_migration_backup
|
||||||
|
WHERE classification IN ('ID_USERNAME_COLLISION', 'AMBIGUOUS_USERNAME', 'NO_MATCH')
|
||||||
|
ORDER BY classification, customer_id;
|
||||||
@@ -148,7 +148,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column v-if="isColVisible('salesUserId')" label="业务员" align="center" prop="salesUserId">
|
<el-table-column v-if="isColVisible('salesUserId')" label="业务员" align="center" prop="salesUserId">
|
||||||
<template #default="scope">{{ scope.row.salesUserNickName || scope.row.salesUser || scope.row.salesUserId }}</template>
|
<template #default="scope">{{ scope.row.salesUserNickName || '' }}</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<!-- <el-table-column v-if="isColVisible('ed')" label="资金额度" align="center" prop="ed" />-->
|
<!-- <el-table-column v-if="isColVisible('ed')" label="资金额度" align="center" prop="ed" />-->
|
||||||
@@ -393,7 +393,7 @@ const copyColumns = computed(() => [
|
|||||||
{ key: 'creditCode', label: '统一社会信用代码', get: r => r.creditCode || '' },
|
{ key: 'creditCode', label: '统一社会信用代码', get: r => r.creditCode || '' },
|
||||||
{ key: 'customerType', label: '业务类型', get: r => proxy.selectDictLabel(customer_type.value, r.customerType) },
|
{ key: 'customerType', label: '业务类型', get: r => proxy.selectDictLabel(customer_type.value, r.customerType) },
|
||||||
{ key: 'isEnable', label: '启用状态', get: r => proxy.selectDictLabel(sys_normal_disable.value, r.isEnable) },
|
{ key: 'isEnable', label: '启用状态', get: r => proxy.selectDictLabel(sys_normal_disable.value, r.isEnable) },
|
||||||
{ key: 'salesUserId', label: '业务员', get: r => r.salesUserNickName || r.salesUser || r.salesUserId || '' },
|
{ key: 'salesUserId', label: '业务员', get: r => r.salesUserNickName || '' },
|
||||||
{ key: 'zq', label: '回款账期', get: r => (r.zq === null || r.zq === undefined ? '' : r.zq) },
|
{ key: 'zq', label: '回款账期', get: r => (r.zq === null || r.zq === undefined ? '' : r.zq) },
|
||||||
{ key: 'settlementUserId', label: '结算员', get: r => getUserName(r.settlementUserId) },
|
{ key: 'settlementUserId', label: '结算员', get: r => getUserName(r.settlementUserId) },
|
||||||
{ key: 'serviceUserId', label: '客服', get: r => getUserName(r.serviceUserId) },
|
{ key: 'serviceUserId', label: '客服', get: r => getUserName(r.serviceUserId) },
|
||||||
|
|||||||
Reference in New Issue
Block a user