💡 清理本次改动注释中的票据引用与设计叙述
注释只写从代码看不出来的事实:删除票号引用、设计权衡与取证经过, 保留业务约束(id_card_no 为 NULL 表示未采集、唯一索引覆盖软删除行、 driving_vehicle 为 ALWAYS 策略等)。
This commit is contained in:
+2
-2
@@ -83,12 +83,12 @@
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-resource-api</artifactId>
|
||||
</dependency>
|
||||
<!-- 登录编排需要在认证侧直接调司机档案的 ensureProfile -->
|
||||
<!-- 登录编排调用司机档案的 ensureProfile -->
|
||||
<dependency>
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-transport-api</artifactId>
|
||||
</dependency>
|
||||
<!-- 登录编排的失败语义(建档/绑 openid 失败必须放行)只能靠 mock feign 返回值守住 -->
|
||||
<!-- 登录编排测试:mock feign 返回值 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
|
||||
@@ -34,9 +34,9 @@ import static org.springblade.core.oauth2.constant.OAuth2TokenConstant.USER_PHON
|
||||
/**
|
||||
* 发码端点的端分流测试。
|
||||
* <p>
|
||||
* 守住票 13 的口径:小程序端(User-Type: mp)对未注册手机号也要发码,
|
||||
* 否则新号走不到「验证码校验通过后自动建号」;Web 端保持拒绝。
|
||||
* 同时守住「发码不建号」:mp 分支根本不查账号。
|
||||
* 保住发码端点的分流口径:小程序端(User-Type: mp)对未注册手机号也发码,
|
||||
* Web 端仍拒绝。
|
||||
* 同时保住「发码不建号」:mp 分支根本不查账号。
|
||||
*/
|
||||
class Oauth2SmsEndpointTest {
|
||||
|
||||
|
||||
+5
-7
@@ -349,9 +349,8 @@ public class CertAuditServiceImpl implements ICertAuditService {
|
||||
if (Func.isEmpty(snapshot.getIdCardNo()) && Func.isEmpty(snapshot.getDriverFileNo())) {
|
||||
return;
|
||||
}
|
||||
// 身份证号要落到档案上,先确认它没有落在别人名下:该列在基线建表脚本与本地库上
|
||||
// 有唯一索引 uk_transport_driver_id_card,但迁移历史里没有任何一次添加它的记录,
|
||||
// 生产库是否已建未核实;应用层查重不能省,否则重复证件号会静默落库
|
||||
// 身份证号要落到档案上,先确认它没有落在别人名下:重复证件号一旦落库,
|
||||
// 建档查重与按证件号识别同一人都会失效
|
||||
requireIdCardNotTaken(snapshot.getIdCardNo(), driver.getId());
|
||||
driver.setDriverName(snapshot.getRealName());
|
||||
driver.setIdCardNo(snapshot.getIdCardNo());
|
||||
@@ -384,10 +383,9 @@ public class CertAuditServiceImpl implements ICertAuditService {
|
||||
* 身份证号不得落在另一名司机名下
|
||||
* <p>
|
||||
* 司机申报的实名内容会写回档案,其中身份证号是管理端建档时的查重判据。
|
||||
* 该列在基线建表脚本与本地库上有唯一索引 {@code uk_transport_driver_id_card},
|
||||
* 但迁移历史里没有任何一次添加它的记录,生产库是否已建未核实;
|
||||
* 应用层查重仍不能省:重复证件号一旦落库,后续建档查重、
|
||||
* 按证件号识别同一人都将失效。此处阻断审核并整体回滚,交由管理端先处理档案归属。
|
||||
* {@code blade_transport_driver.id_card_no} 上有唯一索引
|
||||
* {@code uk_transport_driver_id_card};证件号已属于另一条档案时,
|
||||
* 此处阻断审核并整体回滚,交由管理端先处理档案归属。
|
||||
* <p>
|
||||
* 证件号与当前档案相同(绝大多数情况)、或库里尚无该号时不阻断;
|
||||
* 快照没带证件号时无从判断,同样不阻断(历史快照就是这种)。
|
||||
|
||||
+7
-7
@@ -122,8 +122,8 @@ public class DriverServiceImpl extends BaseServiceImpl<DriverMapper, Driver> imp
|
||||
if (resolvedTenantId == null) {
|
||||
resolvedTenantId = trimToNull(AuthUtil.getTenantId());
|
||||
}
|
||||
// 租户是档案归属与手机号查重的范围,宁可让本次建档失败(登录层只记 WARN),
|
||||
// 也不能写出 tenant_id 为空的档案——那会让下一条同号档案无法被查到
|
||||
// 租户是档案归属与手机号查重的范围,tenant_id 为空的档案不能被后续同号查询命中,
|
||||
// 故此处拒绝写库(登录层只记 WARN)
|
||||
if (resolvedTenantId == null) {
|
||||
throw new ServiceException("租户信息为空,无法创建司机档案");
|
||||
}
|
||||
@@ -134,8 +134,8 @@ public class DriverServiceImpl extends BaseServiceImpl<DriverMapper, Driver> imp
|
||||
if (mobile == null) {
|
||||
throw new ServiceException("手机号不能为空");
|
||||
}
|
||||
// 查找顺序固定为 user_id → phone:user_id 是稳定标识;
|
||||
// phone 会被运营商二次放号,拿它优先会把别人档案绑给新持卡人
|
||||
// 查找顺序固定为 user_id → phone:user_id 是账号的稳定标识,
|
||||
// phone 会被运营商二次放号
|
||||
Driver bound = findDriverByUserId(mpUserId);
|
||||
if (bound != null) {
|
||||
return ensureResult(bound.getId(), false, false, null);
|
||||
@@ -169,10 +169,10 @@ public class DriverServiceImpl extends BaseServiceImpl<DriverMapper, Driver> imp
|
||||
}
|
||||
|
||||
/**
|
||||
* 新建占位档案(票 01 定值)
|
||||
* 新建占位档案
|
||||
* <p>
|
||||
* 不走 {@link #submit}:那条路径要求 15 项必填,自动建档必然被拦。这里只满足表约束——
|
||||
* id_card_no 留 NULL(唯一索引对 NULL 不去重,且 NULL 是「未采集」的判据),
|
||||
* 不走 {@link #submit}:那条路径要求 15 项必填。这里只满足表约束——
|
||||
* id_card_no 留 NULL(唯一索引对 NULL 不去重,NULL 同时是「未采集」的判据),
|
||||
* 其余 NOT NULL 列写空串或可读占位。
|
||||
*/
|
||||
private DriverEnsureProfileVO createPlaceholderProfile(String tenantId, Long mpUserId, String mobile) {
|
||||
|
||||
+1
-1
@@ -76,7 +76,7 @@ class DriverEnsureProfileTest {
|
||||
// ------------------------------------------------------------ 新建占位档案
|
||||
|
||||
@Test
|
||||
@DisplayName("无账号档案、无同号档案:按票 01 的占位值新建,created=true")
|
||||
@DisplayName("无账号档案、无同号档案:按占位值新建,created=true")
|
||||
void createsPlaceholderProfile() {
|
||||
// 第一次按 user_id 查、第二次按手机号查,都没有
|
||||
when(driverMapper.selectList(any())).thenReturn(Collections.emptyList(), Collections.emptyList());
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
-- ----------------------------
|
||||
-- 司机档案与登录账号打通(2026-10-23)
|
||||
-- ----------------------------
|
||||
-- 三处结构变更,均在单据「07 数据模型迁移」内:
|
||||
-- 三处结构变更:
|
||||
-- ① user_id 加唯一索引 uk_transport_driver_user —— 一个账号只能对应一条司机档案。
|
||||
-- ② id_card_no 放宽为可空 —— NULL 表示「身份证号尚未采集」,是判断档案是否完善的口径。
|
||||
-- uk_transport_driver_id_card 保留:MySQL 唯一索引对多行 NULL 不去重,
|
||||
@@ -11,7 +11,7 @@
|
||||
-- NULL 表示改造前存量(来源未知,不臆造);account_bound_time 是档案与账号建立关联的时点。
|
||||
--
|
||||
-- 只做结构变更,不回填数据:存量档案的 profile_source / account_bound_time 一律保持 NULL。
|
||||
-- 判定「档案是否采集」用 id_card_no IS NULL,不另加标记列(见票 01)。
|
||||
-- 判定「档案是否采集」用 id_card_no IS NULL,不另加标记列。
|
||||
--
|
||||
-- 幂等:每段先查 information_schema,条件已满足即跳过,重复执行不报错;
|
||||
-- 全部用 PREPARE 动态语句而非存储过程,因此不需要 DELIMITER——按分号逐句切分的客户端
|
||||
@@ -20,7 +20,7 @@
|
||||
-- 前置检查(user_id 有重复时,第 1 节会以
|
||||
-- Duplicate entry '<值>' for key 'blade_transport_driver.uk_transport_driver_user'
|
||||
-- 失败并终止;此时本脚本对表零修改,先修数据再重跑):
|
||||
-- 唯一索引统计**全表**行,含 is_deleted = 1 的软删除档案。票面给的 is_deleted = 0 口径
|
||||
-- 唯一索引统计**全表**行,含 is_deleted = 1 的软删除档案:只按 is_deleted = 0
|
||||
-- 只能发现活跃重复,软删除行之间的重复同样会让第 1 节失败:
|
||||
-- SELECT user_id, COUNT(*) AS dup_count FROM `blade_transport_driver`
|
||||
-- WHERE user_id IS NOT NULL
|
||||
|
||||
Reference in New Issue
Block a user