🔀 合并编辑保存以库为准
This commit is contained in:
+14
-2
@@ -1068,10 +1068,11 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
|
||||
waybill.setMasterNo(null);
|
||||
waybill.setMileageRemark(null);
|
||||
}
|
||||
// 新建若已带业务状态(如复制提交已完成)则在过程校正后回写,保证与原运单一致
|
||||
// 新建若已带业务状态(如复制提交已完成)则在过程校正后回写,保证与原运单一致;
|
||||
// 编辑保存只改资料,business_status 以库里的值为准,请求体里的值不回写
|
||||
String preservedBusinessStatus = created
|
||||
? TransportBusinessSupport.trimToNull(waybill.getBusinessStatus())
|
||||
: null;
|
||||
: editPreservedBusinessStatus(oldRecord);
|
||||
if (isCompletedBusinessStatus(preservedBusinessStatus)) {
|
||||
preservedBusinessStatus = "completed";
|
||||
}
|
||||
@@ -1093,6 +1094,17 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑保存要回写的业务状态:取库里的值。
|
||||
* 草稿返回 null —— submit 即正式提交,草稿须由过程校正提升为待执行 / 进行中。
|
||||
*/
|
||||
private String editPreservedBusinessStatus(Waybill oldRecord) {
|
||||
String currentStatus = oldRecord == null
|
||||
? null
|
||||
: TransportBusinessSupport.trimToNull(oldRecord.getBusinessStatus());
|
||||
return STATUS_DRAFT.equals(currentStatus) ? null : currentStatus;
|
||||
}
|
||||
|
||||
private void fillCustomerName(Waybill waybill) {
|
||||
if (Func.isNotEmpty(waybill.getContractId())) {
|
||||
ContractManage contract = contractManageService.getById(waybill.getContractId());
|
||||
|
||||
+198
@@ -0,0 +1,198 @@
|
||||
package org.springblade.transport.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.MybatisConfiguration;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
||||
import org.apache.ibatis.builder.MapperBuilderAssistant;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.springblade.core.secure.utils.AuthUtil;
|
||||
import org.springblade.transport.mapper.WaybillMapper;
|
||||
import org.springblade.transport.pojo.entity.Waybill;
|
||||
import org.springblade.transport.support.WaybillProcessSupport;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* 运单编辑保存的业务状态来源测试。
|
||||
* <p>
|
||||
* 编辑保存只改运单资料,business_status 一律以库里的值为准:请求体不回传(null / 空串)
|
||||
* 不得把库里的待执行、进行中、已完成改写成别的状态,回传陈旧值也不得覆盖。
|
||||
* 唯一例外是草稿——submit 即正式提交,草稿须按过程配置提升为待执行 / 进行中。
|
||||
* <p>
|
||||
* 过程配置用「无需确认接单」的快照({@code []}):无过程校正时待执行会被提升为进行中,
|
||||
* 正是编辑保存最容易把库里状态写坏的场景。
|
||||
*/
|
||||
class WaybillEditSaveBusinessStatusTest {
|
||||
|
||||
private static final Long WAYBILL_ID = 7001L;
|
||||
private static final Long DEPT_ID = 100L;
|
||||
/** 无接单节点的过程配置:normalizeBusinessStatus 会把空 / pending 提升为 running */
|
||||
private static final String PROCESS_JSON_NO_ACCEPT = "[]";
|
||||
|
||||
private WaybillMapper waybillMapper;
|
||||
private WaybillServiceImpl service;
|
||||
|
||||
@BeforeAll
|
||||
static void initTableInfo() {
|
||||
// saveOrUpdate 判主键需要 MyBatis-Plus 的实体元数据缓存
|
||||
MybatisConfiguration configuration = new MybatisConfiguration();
|
||||
MapperBuilderAssistant assistant = new MapperBuilderAssistant(configuration, "");
|
||||
assistant.setCurrentNamespace("test");
|
||||
TableInfoHelper.initTableInfo(assistant, Waybill.class);
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void setUp() throws Exception {
|
||||
waybillMapper = mock(WaybillMapper.class);
|
||||
service = new WaybillServiceImpl();
|
||||
inject("baseMapper", waybillMapper);
|
||||
when(waybillMapper.updateById(any(Waybill.class))).thenReturn(1);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------ 编辑保存:以库里的状态为准
|
||||
|
||||
@Test
|
||||
@DisplayName("编辑保存:请求体不回传业务状态,库里的待执行不得被提升为进行中")
|
||||
void editSaveKeepsPendingWhenRequestBodyOmitsStatus() {
|
||||
Waybill request = editableRequest();
|
||||
|
||||
submit(request, "pending");
|
||||
|
||||
assertEquals("pending", request.getBusinessStatus(),
|
||||
"编辑保存时请求体没有 business_status,不得按过程配置把库里的待执行改写成进行中");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("编辑保存:请求体不回传业务状态,库里的进行中不得被改写")
|
||||
void editSaveKeepsRunningWhenRequestBodyOmitsStatus() {
|
||||
Waybill request = editableRequest();
|
||||
|
||||
submit(request, "running");
|
||||
|
||||
assertEquals("running", request.getBusinessStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("编辑保存:请求体不回传业务状态,库里的已完成不得被改写")
|
||||
void editSaveKeepsCompletedWhenRequestBodyOmitsStatus() {
|
||||
Waybill request = editableRequest();
|
||||
|
||||
submit(request, "completed");
|
||||
|
||||
assertEquals("completed", request.getBusinessStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("编辑保存:请求体回传陈旧状态,仍以库里的值为准")
|
||||
void editSaveKeepsDatabaseStatusWhenRequestBodyCarriesStaleValue() {
|
||||
Waybill request = editableRequest();
|
||||
request.setBusinessStatus("running");
|
||||
|
||||
submit(request, "completed");
|
||||
|
||||
assertEquals("completed", request.getBusinessStatus(),
|
||||
"库里已完成,请求体带的是打开表单时的旧值,不得据此回退状态");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("编辑保存:请求体回传空串,库里的状态不得被清空")
|
||||
void editSaveKeepsDatabaseStatusWhenRequestBodyIsBlank() {
|
||||
Waybill request = editableRequest();
|
||||
request.setBusinessStatus("");
|
||||
|
||||
submit(request, "running");
|
||||
|
||||
assertEquals("running", request.getBusinessStatus());
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------ 新增状态
|
||||
|
||||
@Test
|
||||
@DisplayName("编辑保存:待回单确认的运单不得被编辑保存改成进行中")
|
||||
void editSaveKeepsPendingReturnConfirm() {
|
||||
Waybill request = editableRequest();
|
||||
|
||||
submit(request, WaybillProcessSupport.STATUS_PENDING_RETURN_CONFIRM);
|
||||
|
||||
assertEquals(WaybillProcessSupport.STATUS_PENDING_RETURN_CONFIRM, request.getBusinessStatus(),
|
||||
"司机已打完末位卡,编辑一次运单资料不得把它退回进行中");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------ 草稿例外
|
||||
|
||||
@Test
|
||||
@DisplayName("提交草稿:草稿仍按过程配置提升为进行中")
|
||||
void submitDraftStillPromotesToRunning() {
|
||||
Waybill request = editableRequest();
|
||||
|
||||
submit(request, "draft");
|
||||
|
||||
assertEquals("running", request.getBusinessStatus(),
|
||||
"submit 即正式提交,草稿必须脱离 draft,不能被「以库里的值为准」锁死");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------ 夹具
|
||||
|
||||
private Waybill editableRequest() {
|
||||
Waybill waybill = new Waybill();
|
||||
waybill.setId(WAYBILL_ID);
|
||||
waybill.setProjectName("项目A");
|
||||
waybill.setContractName("客户合同A");
|
||||
waybill.setCustomerName("客户A");
|
||||
waybill.setTransportType("公路运输");
|
||||
waybill.setCargoName("钢材");
|
||||
waybill.setCargoType("普货");
|
||||
waybill.setQuantityUnit("吨");
|
||||
waybill.setCarrierType("自运");
|
||||
waybill.setVehicleNo("桂A12345");
|
||||
waybill.setDriverName("张三");
|
||||
waybill.setCarrierJson("{}");
|
||||
waybill.setQuantity(BigDecimal.TEN);
|
||||
waybill.setProcessJson(PROCESS_JSON_NO_ACCEPT);
|
||||
return waybill;
|
||||
}
|
||||
|
||||
/**
|
||||
* 让库里的同一条运单处于 {@code databaseStatus},再走一次编辑保存(submit)。
|
||||
* 司机与车牌保持一致,避免接单记录被判定为「换了司机」而清空。
|
||||
*/
|
||||
private void submit(Waybill request, String databaseStatus) {
|
||||
Waybill oldRecord = editableRequest();
|
||||
oldRecord.setBusinessStatus(databaseStatus);
|
||||
oldRecord.setDeptId(DEPT_ID);
|
||||
oldRecord.setDeptName("测试组织");
|
||||
when(waybillMapper.selectById(WAYBILL_ID)).thenReturn(oldRecord);
|
||||
|
||||
try (MockedStatic<AuthUtil> authUtil = mockStatic(AuthUtil.class)) {
|
||||
authUtil.when(AuthUtil::getDeptId).thenReturn(DEPT_ID);
|
||||
assertTrue(service.submit(request));
|
||||
}
|
||||
}
|
||||
|
||||
private void inject(String field, Object value) throws Exception {
|
||||
Class<?> type = service.getClass();
|
||||
while (type != null) {
|
||||
try {
|
||||
Field declared = type.getDeclaredField(field);
|
||||
declared.setAccessible(true);
|
||||
declared.set(service, value);
|
||||
return;
|
||||
} catch (NoSuchFieldException ignored) {
|
||||
type = type.getSuperclass();
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("未找到字段:" + field);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user