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("张三");