From 48acd6a91e70dfbfde216946d9c2006546c0af29 Mon Sep 17 00:00:00 2001 From: weicw <594098497@qq.com> Date: Tue, 27 Oct 2026 22:15:16 +0800 Subject: [PATCH] =?UTF-8?q?:bug:=20=E6=B4=BE=E5=8D=95=E4=B8=8E=E5=AF=BC?= =?UTF-8?q?=E5=85=A5=E8=A7=A3=E6=9E=90=E4=B8=8D=E5=88=B0=E5=8F=B8=E6=9C=BA?= =?UTF-8?q?=E6=A1=A3=E6=A1=88=E6=97=B6=E7=95=99=E8=84=B1=E6=95=8F=20WARN?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 改派、主单派单、Excel 导入三条写路径在解析不到档案时只落空不阻断,补 log.warn(号码用 DesensitizedUtil.mobilePhone 脱敏)。同时去掉解析结果上多余的 id > 0 归一:解析入口只返回 null 或唯一命中的档案 ID。 --- .../service/impl/MasterOrderServiceImpl.java | 13 +++++++--- .../impl/WaybillImportBatchServiceImpl.java | 4 ++-- .../service/impl/WaybillServiceImpl.java | 12 ++++++---- .../service/impl/MasterOrderDriverIdTest.java | 23 ++++++++++++++++++ .../impl/WaybillImportDriverIdTest.java | 11 --------- .../impl/WaybillReassignDriverIdTest.java | 24 +++++++++++++++++++ 6 files changed, 67 insertions(+), 20 deletions(-) diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/MasterOrderServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/MasterOrderServiceImpl.java index 1f054b21..d459c234 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/MasterOrderServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/MasterOrderServiceImpl.java @@ -4,8 +4,10 @@ */ package org.springblade.transport.service.impl; +import cn.hutool.core.util.DesensitizedUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; +import lombok.extern.slf4j.Slf4j; import org.springblade.core.log.exception.ServiceException; import org.springblade.core.mp.base.BaseServiceImpl; import org.springblade.core.tool.jackson.JsonUtil; @@ -51,6 +53,7 @@ import java.util.Objects; * @author Chill */ @Service +@Slf4j public class MasterOrderServiceImpl extends BaseServiceImpl implements IMasterOrderService { private static final String CARRIER_SELF = "自运"; @@ -266,11 +269,15 @@ public class MasterOrderServiceImpl extends BaseServiceImpl 0 ? resolvedDriverId : null; + driverId = driverService.resolveDriverIdByMobile(waybill.getTenantId(), waybill.getDriverPhone()); + if (driverId == null) { + log.warn("总单 {} 派单的司机手机号未唯一匹配司机档案,driver_id 落空(不阻断派单)。租户={} 手机号={}", + masterOrder.getMasterNo(), waybill.getTenantId(), DesensitizedUtil.mobilePhone(waybill.getDriverPhone())); + } } waybill.setDriverId(driverId); waybill.setCaptainName(string(dispatch, "captainName")); waybill.setCabinNo(string(dispatch, "cabinNo")); waybill.setContainerNo(string(dispatch, "containerNo")); diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/WaybillImportBatchServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/WaybillImportBatchServiceImpl.java index f78533ab..5eabbc36 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/WaybillImportBatchServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/WaybillImportBatchServiceImpl.java @@ -500,12 +500,12 @@ public class WaybillImportBatchServiceImpl extends BaseServiceImpl 0) { return; } + // 解析入口只返回 null 或唯一命中的档案 ID,不需要再按哨兵归一 Long resolvedDriverId = driverService.resolveDriverIdByMobile(waybill.getTenantId(), waybill.getDriverPhone()); - if (resolvedDriverId != null && resolvedDriverId > 0) { + if (resolvedDriverId != null) { waybill.setDriverId(resolvedDriverId); return; } - // driver_id 只有 >0 才算有主,0 / -1 都按无主落空 waybill.setDriverId(null); log.warn("第{}行 运单 {} 的司机手机号未唯一匹配司机档案,driver_id 留空(不阻断导入)", rowNo, waybill.getWaybillNo()); diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/WaybillServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/WaybillServiceImpl.java index aa3d3290..611b4e5f 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/WaybillServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/WaybillServiceImpl.java @@ -22,6 +22,7 @@ */ package org.springblade.transport.service.impl; +import cn.hutool.core.util.DesensitizedUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; @@ -1615,12 +1616,15 @@ public class WaybillServiceImpl extends BaseServiceImpl TransportBusinessSupport.validateRequired(vehicleNo, "车牌号不能为空"); // 归属主键是档案 ID,手机号只是派单时的号码快照:调用方带了档案 ID 就用它, - // 否则按手机号解析;承运商司机、未建档司机解析为空,派单照旧成功,只留 WARN + // 否则按手机号解析;解析入口只返回 null 或唯一命中的档案 ID,承运商司机、未建档司机 + // 解析为空,派单照旧成功,落空时留 WARN Long driverId = request.getDriverId(); if (driverId == null || driverId <= 0) { - Long resolvedDriverId = driverService.resolveDriverIdByMobile(waybill.getTenantId(), driverPhone); - // driver_id 只有 >0 才算有主,0 / -1 都是「无主」的哨兵写法,落库统一为 NULL - driverId = resolvedDriverId != null && resolvedDriverId > 0 ? resolvedDriverId : null; + driverId = driverService.resolveDriverIdByMobile(waybill.getTenantId(), driverPhone); + if (driverId == null) { + log.warn("运单 {} 的司机手机号未唯一匹配司机档案,driver_id 落空(不阻断派单)。租户={} 手机号={}", + waybill.getWaybillNo(), waybill.getTenantId(), DesensitizedUtil.mobilePhone(driverPhone)); + } } waybill.setDriverId(driverId); waybill.setDriverName(driverName); diff --git a/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/MasterOrderDriverIdTest.java b/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/MasterOrderDriverIdTest.java index 8872dd01..c9290709 100644 --- a/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/MasterOrderDriverIdTest.java +++ b/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/MasterOrderDriverIdTest.java @@ -1,5 +1,7 @@ package org.springblade.transport.service.impl; +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.ILoggingEvent; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -11,6 +13,7 @@ import org.springblade.transport.service.IDriverService; import org.springblade.transport.service.IProjectApplyService; import org.springblade.transport.service.ITransportPlanService; import org.springblade.transport.service.IWaybillService; +import org.springblade.transport.support.LogCapture; import java.lang.reflect.Method; import java.util.LinkedHashMap; @@ -18,6 +21,7 @@ import java.util.List; import java.util.Map; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; @@ -84,6 +88,25 @@ class MasterOrderDriverIdTest { verify(waybillService).submit(any(Waybill.class)); } + @Test + @DisplayName("解析不到档案:落空时留一条脱敏 WARN,派单照常成功") + void unresolvedProfileLogsMaskedWarning() throws Exception { + when(driverService.resolveDriverIdByMobile(any(), eq(DRIVER_PHONE))).thenReturn(null); + try (LogCapture logs = LogCapture.open(MasterOrderServiceImpl.class)) { + assertTrue(createWaybill(dispatch())); + + String warning = logs.events().stream() + .filter(event -> event.getLevel() == Level.WARN) + .map(ILoggingEvent::getFormattedMessage) + .filter(message -> message.contains("司机档案")) + .findFirst() + .orElseThrow(() -> new AssertionError("解析失败必须留 WARN,实际日志:" + logs.messages())); + assertTrue(warning.contains("138****8000"), "WARN 里的号码必须脱敏,实际:" + warning); + assertFalse(warning.contains(DRIVER_PHONE), "WARN 里不能出现完整号码,实际:" + warning); + assertTrue(warning.contains("ZD-20261027-001"), "WARN 要带业务标识(总单号),实际:" + warning); + } + } + // ------------------------------------------------------------ 夹具 private boolean createWaybill(Map dispatch) throws Exception { diff --git a/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/WaybillImportDriverIdTest.java b/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/WaybillImportDriverIdTest.java index d9581932..b7bf273b 100644 --- a/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/WaybillImportDriverIdTest.java +++ b/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/WaybillImportDriverIdTest.java @@ -86,17 +86,6 @@ class WaybillImportDriverIdTest { assertNull(waybill.getDriverId()); } - @Test - @DisplayName("解析器返回 0(无主哨兵):按无主落空,不把 0 写进库") - void normalizesSentinelToNull() throws Exception { - when(driverService.resolveDriverIdByMobile(any(), eq(DRIVER_PHONE))).thenReturn(0L); - - Waybill waybill = importedWaybill(0L); - fillDriverOwnership(waybill, 3); - - assertNull(waybill.getDriverId()); - } - // ------------------------------------------------------------ 夹具 private void fillDriverOwnership(Waybill waybill, int rowNo) throws Exception { diff --git a/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/WaybillReassignDriverIdTest.java b/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/WaybillReassignDriverIdTest.java index 6ce47414..8646431a 100644 --- a/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/WaybillReassignDriverIdTest.java +++ b/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/WaybillReassignDriverIdTest.java @@ -1,5 +1,7 @@ package org.springblade.transport.service.impl; +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.ILoggingEvent; import com.baomidou.mybatisplus.core.MybatisConfiguration; import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; import org.apache.ibatis.builder.MapperBuilderAssistant; @@ -12,11 +14,13 @@ import org.springblade.transport.mapper.WaybillMapper; import org.springblade.transport.pojo.entity.Waybill; import org.springblade.transport.service.IDriverService; import org.springblade.transport.service.IProcessConfigService; +import org.springblade.transport.support.LogCapture; import java.lang.reflect.Field; import java.util.Collections; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; @@ -108,6 +112,25 @@ class WaybillReassignDriverIdTest { assertNull(capturedWaybill().getDriverId()); } + @Test + @DisplayName("解析不到档案:落空时留一条脱敏 WARN,派单照常成功") + void unresolvedProfileLogsMaskedWarning() { + when(driverService.resolveDriverIdByMobile(TENANT_ID, DRIVER_PHONE)).thenReturn(null); + try (LogCapture logs = LogCapture.open(WaybillServiceImpl.class)) { + assertTrue(service.reassignWithoutDeptCheck(reassignRequest(null))); + + String warning = logs.events().stream() + .filter(event -> event.getLevel() == Level.WARN) + .map(ILoggingEvent::getFormattedMessage) + .filter(message -> message.contains("司机档案")) + .findFirst() + .orElseThrow(() -> new AssertionError("解析失败必须留 WARN,实际日志:" + logs.messages())); + assertTrue(warning.contains("138****8000"), "WARN 里的号码必须脱敏,实际:" + warning); + assertFalse(warning.contains(DRIVER_PHONE), "WARN 里不能出现完整号码,实际:" + warning); + assertTrue(warning.contains("YD-20261027-001"), "WARN 要带业务标识(运单号),实际:" + warning); + } + } + // ------------------------------------------------------------ 夹具 private void setUpAgain() throws Exception { @@ -131,6 +154,7 @@ class WaybillReassignDriverIdTest { waybill.setId(WAYBILL_ID); waybill.setIsDeleted(0); waybill.setTenantId(TENANT_ID); + waybill.setWaybillNo("YD-20261027-001"); waybill.setBusinessStatus("pending"); waybill.setTransportType("road"); waybill.setDriverName("张三");