🐛 修复配载承运商乙方交集在缺客户合同与无可用合同时的报错

子运单全都没有客户合同时,甲方映射是空表,按 null 键取甲方抛 NPE,配载提交 500;
项目下没有可用承运商合同时乙方交集必然为空,被当成「无共同乙方」拦截,自运的多张子运单因此配不进去。
金蝶客商同步测试补 HCS 占位地址:本地未配置 thirdParty.hcs.baseUrl 时 Feign 客户端会让整个上下文起不来。
This commit is contained in:
2026-10-27 23:53:32 +08:00
parent 43525df87c
commit 6ac6cf9bff
3 changed files with 37 additions and 2 deletions
@@ -952,6 +952,10 @@ public class LoadingManageServiceImpl extends BaseServiceImpl<LoadingManageMappe
return;
}
List<ContractManage> contracts = availableCarrierContracts(projectIdsOf(waybills));
// 项目下没有任何可用承运商合同时不存在乙方交集约束;承运类型为「承运商」由 validateCarrierContract 要求选择合同
if (Func.isEmpty(contracts)) {
return;
}
Set<String> allowedPartyBs = intersectCarrierPartyBs(waybills, contracts);
if (allowedPartyBs.isEmpty()) {
throw new ServiceException("所选运单在同一项目下没有共同的承运商合同乙方,不能配载到同一配载单");
@@ -1071,7 +1075,9 @@ public class LoadingManageServiceImpl extends BaseServiceImpl<LoadingManageMappe
if (waybill == null || Func.isEmpty(projectContracts)) {
return Set.of();
}
String partyA = customerPartyAMap.get(waybill.getContractId());
Long contractId = waybill.getContractId();
// 运单没有客户合同时不按甲方过滤,取空串而不是去空表里取 null 键
String partyA = contractId == null ? "" : customerPartyAMap.get(contractId);
return projectContracts.stream()
.filter(contract -> Objects.equals(contract.getProjectId(), waybill.getProjectId()))
.filter(contract -> Func.isEmpty(partyA) || Objects.equals(normalizePartyName(contract.getPartyA()), partyA))
@@ -40,7 +40,9 @@ import org.springframework.boot.test.context.SpringBootTest;
*/
@SpringBootTest(classes = TransportApplication.class, properties = {
"spring.profiles.active=dev",
"spring.main.allow-bean-definition-overriding=true"
"spring.main.allow-bean-definition-overriding=true",
// HCS 是可选外部集成,本地 Nacos 未配置该地址时 Feign 客户端会让整个上下文起不来;本测试不调用 HCS
"thirdParty.hcs.baseUrl=http://localhost:9"
})
class CustomerArchiveSyncKingdeeDataTest {
@@ -294,6 +294,33 @@ class LoadingManageAdmissionTest {
assertEquals("所选承运商合同不存在、未审核通过或已失效", exception.getMessage());
}
@Test
@DisplayName("子运单的客户合同快照为空时不按甲方过滤,取不到甲方也不空指针")
void missingCustomerContractDoesNotFilterByPartyA() {
Waybill withSnapshot = waybill(1L, WAYBILL_NO_A, "road", "pending", null, PROJECT_A);
withSnapshot.setContractId(OTHER_CONTRACT_ID);
stubWaybills(withSnapshot, waybill(2L, WAYBILL_NO_B, "road", "pending", null, PROJECT_A));
stubContract(CONTRACT_ID, PROJECT_A);
assertDoesNotThrow(() -> service.submit(submitPayload(List.of(1L, 2L))));
}
@Test
@DisplayName("项目下没有可用承运商合同时不按乙方交集拦截:自运的多张子运单照常提交")
void noAvailableCarrierContractSkipsPartyBCheck() {
stubWaybills(
waybill(1L, WAYBILL_NO_A, "road", "pending", null, PROJECT_A),
waybill(2L, WAYBILL_NO_B, "road", "pending", null, PROJECT_A));
when(contractManageService.list(anyContractWrapper())).thenReturn(List.of());
LoadingManage payload = submitPayload(List.of(1L, 2L));
payload.setCarrierType("自运");
payload.setCarrierContractId(null);
payload.setDriverName("张三");
payload.setDriverPhone("13800008000");
assertDoesNotThrow(() -> service.submit(payload));
}
// ------------------------------------------------------------ 放行
@Test