package jnpf.dmsService;
|
|
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
import jnpf.audit.sdk.annotation.AuditLog;
|
import jnpf.base.ActionResult;
|
import jnpf.base.ActionResultCode;
|
import jnpf.base.UserInfo;
|
import jnpf.dmsEntity.DmsWenjianFushenJihuaFenpeiZixiangEntity;
|
import jnpf.dmsEntity.DmsWenjianFushenZhixingEntity;
|
import jnpf.dmsEntity.DmsWenjianFushenZhixingZixiangEntity;
|
import jnpf.dmsEntity.DmsWenjianZiyuanEntity;
|
import jnpf.dmsEntity.form.DmsWenjianFushenZhixingBatchReturnForm;
|
import jnpf.dmsEntity.storage.form.DmsFileExtendValidityForm;
|
import jnpf.dmsMapper.DmsWenjianFushenJihuaFenpeiZixiangMapper;
|
import jnpf.dmsMapper.DmsWenjianFushenZhixingMapper;
|
import jnpf.dmsMapper.DmsWenjianFushenZhixingZixiangMapper;
|
import jnpf.dmsMapper.DmsWenjianZiyuanMapper;
|
import jnpf.dmsPermission.DmsCurrentIdentity;
|
import jnpf.flowable.TaskApi;
|
import jnpf.flowable.WorkFlowApi;
|
import jnpf.flowable.entity.TemplateJsonEntity;
|
import jnpf.flowable.model.task.AuditModel;
|
import jnpf.flowable.model.task.FlowModel;
|
import jnpf.dmsService.impl.DmsWenjianFushenZhixingServiceImpl;
|
import jnpf.exception.DataException;
|
import org.apache.ibatis.builder.MapperBuilderAssistant;
|
import org.apache.ibatis.session.Configuration;
|
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.Test;
|
import org.mockito.ArgumentCaptor;
|
|
import java.lang.reflect.Method;
|
import java.util.Arrays;
|
import java.util.Collections;
|
import java.util.Date;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.UUID;
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.isNull;
|
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.when;
|
|
class DmsWenjianFushenZhixingServiceTest {
|
|
@BeforeEach
|
void setUp() {
|
if (TableInfoHelper.getTableInfo(DmsWenjianFushenJihuaFenpeiZixiangEntity.class) == null) {
|
TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new Configuration(), ""),
|
DmsWenjianFushenJihuaFenpeiZixiangEntity.class);
|
}
|
initTableInfo(DmsWenjianFushenZhixingEntity.class);
|
initTableInfo(DmsWenjianFushenZhixingZixiangEntity.class);
|
initTableInfo(DmsWenjianZiyuanEntity.class);
|
}
|
|
@Test
|
void declaresTheBatchReturnAuditEvent() throws NoSuchMethodException {
|
Method method = DmsWenjianFushenZhixingServiceImpl.class.getMethod("batchReturn", List.class);
|
AuditLog auditLog = method.getAnnotation(AuditLog.class);
|
|
assertNotNull(auditLog);
|
assertEquals("FILE_REVIEW_BATCH_RETURN", auditLog.action());
|
assertEquals("文件复审执行批量退回", auditLog.label());
|
assertEquals("DMS_FILE_REVIEW", auditLog.bizType());
|
assertEquals("wenjian_fushen_jihua_fenpei_zixiang", auditLog.targetTable());
|
assertEquals("#p0[0].fenpeiZixiangId", auditLog.targetIdExpr());
|
assertEquals("#p0.![fenpeiZixiangId]", auditLog.targetIdsExpr());
|
assertTrue(auditLog.diff());
|
assertEquals(DmsWenjianFushenJihuaFenpeiZixiangEntity.class, auditLog.entityClass());
|
}
|
|
@Test
|
void declaresTheExecutionWriteBackAuditEvent() throws NoSuchMethodException {
|
Method method = DmsWenjianFushenZhixingServiceImpl.class.getMethod("writeBack", String.class);
|
AuditLog auditLog = method.getAnnotation(AuditLog.class);
|
|
assertNotNull(auditLog);
|
assertEquals("FILE_REVIEW_EXECUTION_WRITE_BACK", auditLog.action());
|
assertEquals("文件复审执行结果回写", auditLog.label());
|
assertEquals("wenjian_fushen_zhixing", auditLog.targetTable());
|
assertEquals("#p0", auditLog.targetIdExpr());
|
}
|
|
@Test
|
void batchReturnsEveryRequestedDetailWithoutDeletingIt() throws Exception {
|
DmsWenjianFushenJihuaFenpeiZixiangMapper mapper = mock(
|
DmsWenjianFushenJihuaFenpeiZixiangMapper.class);
|
when(mapper.update(isNull(), any())).thenReturn(2);
|
|
service(mapper).batchReturn(Arrays.asList(item("detail-1"), item("detail-2")));
|
|
ArgumentCaptor<Wrapper<DmsWenjianFushenJihuaFenpeiZixiangEntity>> captor = ArgumentCaptor.forClass(
|
Wrapper.class);
|
verify(mapper).update(isNull(), captor.capture());
|
LambdaUpdateWrapper<?> update = (LambdaUpdateWrapper<?>) captor.getValue();
|
String sqlSet = update.getSqlSet();
|
assertTrue(sqlSet.contains("huigu_ren"));
|
assertTrue(sqlSet.contains("fenpei_bumen_id"));
|
assertTrue(sqlSet.contains("fenpei_bumen_fuzeren"));
|
assertTrue(sqlSet.contains("fenpei_riqi"));
|
assertTrue(sqlSet.contains("biz_status"));
|
assertTrue(update.getExpression().getNormal().getSqlSegment().contains("f_id"));
|
assertTrue(update.getExpression().getNormal().getSqlSegment().contains("f_delete_mark"));
|
assertTrue(update.getParamNameValuePairs().containsValue("detail-1"));
|
assertTrue(update.getParamNameValuePairs().containsValue("detail-2"));
|
assertTrue(update.getParamNameValuePairs().containsValue("daifenpei"));
|
}
|
|
@Test
|
void rejectsDuplicateDetailIdsBeforeUpdating() {
|
DmsWenjianFushenJihuaFenpeiZixiangMapper mapper = mock(
|
DmsWenjianFushenJihuaFenpeiZixiangMapper.class);
|
|
DataException error = assertThrows(DataException.class,
|
() -> service(mapper).batchReturn(Arrays.asList(item("detail-1"), item("detail-1"))));
|
|
assertEquals("文件复审执行批量退回参数中不能包含重复fenpei_zixiang_id", error.getMessage());
|
verify(mapper, never()).update(any(), any());
|
}
|
|
@Test
|
void rejectsPartialUpdatesToKeepTheBatchAtomic() {
|
DmsWenjianFushenJihuaFenpeiZixiangMapper mapper = mock(
|
DmsWenjianFushenJihuaFenpeiZixiangMapper.class);
|
when(mapper.update(isNull(), any())).thenReturn(1);
|
|
DataException error = assertThrows(DataException.class,
|
() -> service(mapper).batchReturn(Arrays.asList(item("detail-1"), item("detail-2"))));
|
|
assertEquals("存在未找到或已退回的文件复审计划分配子项,无法批量退回", error.getMessage());
|
}
|
|
@Test
|
void writesBackTheExecutionDateAndEachDetailResultToItsAssignedDetail() throws Exception {
|
DmsWenjianFushenJihuaFenpeiZixiangMapper fenpeiMapper = mock(
|
DmsWenjianFushenJihuaFenpeiZixiangMapper.class);
|
DmsWenjianFushenZhixingMapper zhixingMapper = mock(DmsWenjianFushenZhixingMapper.class);
|
DmsWenjianFushenZhixingZixiangMapper zhixingZixiangMapper = mock(
|
DmsWenjianFushenZhixingZixiangMapper.class);
|
Date huiguRiqi = new Date();
|
when(zhixingMapper.selectOne(any())).thenReturn(zhixing("execution-1", huiguRiqi));
|
when(zhixingZixiangMapper.selectList(any())).thenReturn(Arrays.asList(
|
zhixingZixiangWithResult("execution-detail-1", "assigned-detail-1", "总结一", "结论一"),
|
zhixingZixiangWithResult("execution-detail-2", "assigned-detail-2", "总结二", "结论二")));
|
when(fenpeiMapper.update(isNull(), any())).thenReturn(1);
|
|
service(fenpeiMapper, zhixingMapper, zhixingZixiangMapper)
|
.writeBack("execution-1");
|
|
ArgumentCaptor<Wrapper<DmsWenjianFushenJihuaFenpeiZixiangEntity>> captor = ArgumentCaptor.forClass(
|
Wrapper.class);
|
verify(fenpeiMapper, org.mockito.Mockito.times(2)).update(isNull(), captor.capture());
|
List<Wrapper<DmsWenjianFushenJihuaFenpeiZixiangEntity>> updates = captor.getAllValues();
|
LambdaUpdateWrapper<?> first = (LambdaUpdateWrapper<?>) updates.get(0);
|
LambdaUpdateWrapper<?> second = (LambdaUpdateWrapper<?>) updates.get(1);
|
assertWriteBackUpdate(first, "assigned-detail-1", huiguRiqi, "总结一", "结论一");
|
assertWriteBackUpdate(second, "assigned-detail-2", huiguRiqi, "总结二", "结论二");
|
}
|
|
@Test
|
void rejectsAnExecutionDetailWithoutAnAssignedDetailId() {
|
DmsWenjianFushenJihuaFenpeiZixiangMapper fenpeiMapper = mock(
|
DmsWenjianFushenJihuaFenpeiZixiangMapper.class);
|
DmsWenjianFushenZhixingMapper zhixingMapper = mock(DmsWenjianFushenZhixingMapper.class);
|
DmsWenjianFushenZhixingZixiangMapper zhixingZixiangMapper = mock(
|
DmsWenjianFushenZhixingZixiangMapper.class);
|
when(zhixingMapper.selectOne(any())).thenReturn(zhixing("execution-1", new Date()));
|
when(zhixingZixiangMapper.selectList(any())).thenReturn(Arrays.asList(
|
zhixingZixiangWithResult("execution-detail-1", " ", "总结", "结论")));
|
|
DataException error = assertThrows(DataException.class,
|
() -> service(fenpeiMapper, zhixingMapper, zhixingZixiangMapper)
|
.writeBack("execution-1"));
|
|
assertEquals("文件复审执行子项fenpei_zixiang_id不能为空", error.getMessage());
|
verify(fenpeiMapper, never()).update(any(), any());
|
}
|
|
@Test
|
void rejectsWhenAnAssignedDetailCannotBeUpdated() {
|
DmsWenjianFushenJihuaFenpeiZixiangMapper fenpeiMapper = mock(
|
DmsWenjianFushenJihuaFenpeiZixiangMapper.class);
|
DmsWenjianFushenZhixingMapper zhixingMapper = mock(DmsWenjianFushenZhixingMapper.class);
|
DmsWenjianFushenZhixingZixiangMapper zhixingZixiangMapper = mock(
|
DmsWenjianFushenZhixingZixiangMapper.class);
|
when(zhixingMapper.selectOne(any())).thenReturn(zhixing("execution-1", new Date()));
|
when(zhixingZixiangMapper.selectList(any())).thenReturn(Arrays.asList(
|
zhixingZixiangWithResult("execution-detail-1", "assigned-detail-1", "总结", "结论")));
|
when(fenpeiMapper.update(isNull(), any())).thenReturn(0);
|
|
DataException error = assertThrows(DataException.class,
|
() -> service(fenpeiMapper, zhixingMapper, zhixingZixiangMapper)
|
.writeBack("execution-1"));
|
|
assertEquals("未找到可回写的文件复审计划分配子项:f_id=assigned-detail-1", error.getMessage());
|
}
|
|
@Test
|
void processesEverySupportedConclusionGroupAfterWritingBack() throws Exception {
|
DmsWenjianFushenJihuaFenpeiZixiangMapper fenpeiMapper = mock(
|
DmsWenjianFushenJihuaFenpeiZixiangMapper.class);
|
DmsWenjianFushenZhixingMapper zhixingMapper = mock(DmsWenjianFushenZhixingMapper.class);
|
DmsWenjianFushenZhixingZixiangMapper zhixingZixiangMapper = mock(
|
DmsWenjianFushenZhixingZixiangMapper.class);
|
DmsWenjianZiyuanMapper ziyuanMapper = mock(DmsWenjianZiyuanMapper.class);
|
DmsFileValidityService validityService = mock(DmsFileValidityService.class);
|
DmsCurrentIdentity identity = mock(DmsCurrentIdentity.class);
|
TaskApi taskApi = mock(TaskApi.class);
|
WorkFlowApi workFlowApi = mock(WorkFlowApi.class);
|
UserInfo user = new UserInfo();
|
user.setUserId("user-1");
|
user.setTenantId("tenant-1");
|
user.setOrganizeId("organization-1");
|
Date currentExpiry = new Date();
|
|
when(zhixingMapper.selectOne(any())).thenReturn(zhixing("execution-1", new Date()));
|
when(zhixingZixiangMapper.selectList(any())).thenReturn(Arrays.asList(
|
zhixingZixiang("execution-detail-1", "assigned-detail-1", "file-1", "keyanyong"),
|
zhixingZixiang("execution-detail-2", "assigned-detail-2", "file-2", "xuxiuding"),
|
zhixingZixiang("execution-detail-3", "assigned-detail-3", "file-3", "xuchexiao")));
|
when(fenpeiMapper.update(isNull(), any())).thenReturn(1);
|
when(ziyuanMapper.selectByTenantAndId("tenant-1", "file-1"))
|
.thenReturn(resource("file-1", currentExpiry, "018f0000-0000-7000-8000-000000000801"));
|
when(ziyuanMapper.selectByTenantAndId("tenant-1", "file-2"))
|
.thenReturn(resource("file-2", currentExpiry, "018f0000-0000-7000-8000-000000000802"));
|
when(ziyuanMapper.selectByTenantAndId("tenant-1", "file-3"))
|
.thenReturn(resource("file-3", currentExpiry, "018f0000-0000-7000-8000-000000000803"));
|
when(ziyuanMapper.updateReviewExecutionExtension(any(), any(), any(), any(), any())).thenReturn(1);
|
when(identity.requireUser()).thenReturn(user);
|
when(identity.tenantId(user)).thenReturn("tenant-1");
|
when(workFlowApi.getFlowIdsByTemplate(any())).thenReturn(Arrays.asList(activeVersion("flow-version-1")));
|
ActionResult<AuditModel> draftSuccess = mock(ActionResult.class);
|
when(draftSuccess.getCode()).thenReturn(ActionResultCode.SUCCESS.getCode());
|
when(taskApi.saveDraft(any())).thenReturn(draftSuccess);
|
|
service(fenpeiMapper, zhixingMapper, zhixingZixiangMapper, ziyuanMapper, validityService,
|
identity, taskApi, workFlowApi).writeBack("execution-1");
|
|
ArgumentCaptor<DmsFileExtendValidityForm> validityCaptor = ArgumentCaptor.forClass(
|
DmsFileExtendValidityForm.class);
|
verify(validityService).extendValidity(validityCaptor.capture());
|
DmsFileExtendValidityForm validityForm = validityCaptor.getValue();
|
assertEquals("", validityForm.getSourceId());
|
assertEquals("", validityForm.getTaskId());
|
assertEquals(1, validityForm.getFiles().size());
|
assertEquals(UUID.fromString("018f0000-0000-7000-8000-000000000801"),
|
validityForm.getFiles().get(0).getFileVersionId());
|
verify(ziyuanMapper).updateReviewExecutionExtension(
|
org.mockito.Mockito.eq("tenant-1"), org.mockito.Mockito.eq("file-1"), any(Date.class),
|
org.mockito.Mockito.eq("execution-1"), any(String.class));
|
|
ArgumentCaptor<FlowModel> draftCaptor = ArgumentCaptor.forClass(FlowModel.class);
|
verify(taskApi, org.mockito.Mockito.times(2)).saveDraft(draftCaptor.capture());
|
List<FlowModel> drafts = draftCaptor.getAllValues();
|
assertEquals(0, drafts.get(0).getStatus().intValue());
|
assertEquals(1, drafts.get(0).getIsFlow().intValue());
|
assertEquals("flow-version-1", drafts.get(0).getFlowId());
|
List<Map<String, Object>> revisionDetails = (List<Map<String, Object>>) drafts.get(0).getFormData()
|
.get("xiuding_shenqing_zixiang");
|
assertEquals(1, revisionDetails.size());
|
assertEquals(Collections.singletonList("wenjian"), revisionDetails.get(0).get("biangeng_neirong"));
|
List<?> revokeDetails=(List<?>) drafts.get(1).getFormData().get("chexiao_wenjian_mingxi");
|
assertEquals(1,revokeDetails.size());
|
Map<?,?> revoke=(Map<?,?>)revokeDetails.get(0);
|
assertEquals("file-3",revoke.get("wenjian_id"));
|
assertEquals("business-version-file-3",revoke.get("wenjian_banben_id"));
|
assertEquals("current-version",revoke.get("banben_hao"));
|
}
|
|
private DmsWenjianFushenZhixingService service(DmsWenjianFushenJihuaFenpeiZixiangMapper mapper) {
|
return service(mapper, mock(DmsWenjianFushenZhixingMapper.class),
|
mock(DmsWenjianFushenZhixingZixiangMapper.class));
|
}
|
|
private DmsWenjianFushenZhixingService service(DmsWenjianFushenJihuaFenpeiZixiangMapper fenpeiMapper,
|
DmsWenjianFushenZhixingMapper zhixingMapper,
|
DmsWenjianFushenZhixingZixiangMapper zhixingZixiangMapper) {
|
return service(fenpeiMapper, zhixingMapper, zhixingZixiangMapper,
|
mock(DmsWenjianZiyuanMapper.class), mock(DmsFileValidityService.class),
|
mock(DmsCurrentIdentity.class), mock(TaskApi.class), mock(WorkFlowApi.class));
|
}
|
|
private DmsWenjianFushenZhixingService service(DmsWenjianFushenJihuaFenpeiZixiangMapper fenpeiMapper,
|
DmsWenjianFushenZhixingMapper zhixingMapper,
|
DmsWenjianFushenZhixingZixiangMapper zhixingZixiangMapper,
|
DmsWenjianZiyuanMapper ziyuanMapper, DmsFileValidityService validityService,
|
DmsCurrentIdentity identity, TaskApi taskApi, WorkFlowApi workFlowApi) {
|
return new DmsWenjianFushenZhixingServiceImpl(fenpeiMapper, zhixingMapper, zhixingZixiangMapper,
|
ziyuanMapper, validityService, identity, taskApi, workFlowApi);
|
}
|
|
private DmsWenjianFushenZhixingBatchReturnForm item(String id) {
|
DmsWenjianFushenZhixingBatchReturnForm form = new DmsWenjianFushenZhixingBatchReturnForm();
|
form.setFenpeiZixiangId(id);
|
return form;
|
}
|
|
private DmsWenjianFushenZhixingEntity zhixing(String id, Date huiguRiqi) {
|
DmsWenjianFushenZhixingEntity result = new DmsWenjianFushenZhixingEntity();
|
result.setId(id);
|
result.setHuiguRiqi(huiguRiqi);
|
return result;
|
}
|
|
private DmsWenjianFushenZhixingZixiangEntity zhixingZixiangWithResult(String id, String fenpeiZixiangId,
|
String huiguNeirongZongjie, String zuizhongJielun) {
|
DmsWenjianFushenZhixingZixiangEntity result = new DmsWenjianFushenZhixingZixiangEntity();
|
result.setId(id);
|
result.setFenpeiZixiangId(fenpeiZixiangId);
|
result.setHuiguNeirongZongjie(huiguNeirongZongjie);
|
result.setZuizhongJielun(zuizhongJielun);
|
return result;
|
}
|
|
private DmsWenjianFushenZhixingZixiangEntity zhixingZixiang(String id, String fenpeiZixiangId,
|
String wenjianId, String conclusion) {
|
DmsWenjianFushenZhixingZixiangEntity result = zhixingZixiangWithResult(
|
id, fenpeiZixiangId, "总结", conclusion);
|
result.setWenjianId(wenjianId);
|
result.setWenjianBianhao("编号-" + wenjianId);
|
result.setWenjianMingcheng("名称-" + wenjianId);
|
result.setBanbenhao("D(01)");
|
return result;
|
}
|
|
private DmsWenjianZiyuanEntity resource(String id, Date expiry, String fileVersionId) {
|
DmsWenjianZiyuanEntity result = new DmsWenjianZiyuanEntity();
|
result.setId(id);
|
result.setYouxiaoQiZhi(expiry);
|
result.setWenjianZhongxinBanbenId(fileVersionId);
|
result.setWenjianBianhao("编号-" + id);
|
result.setWenjianMingcheng("名称-" + id);
|
result.setDangqianBanbenId("business-version-" + id);
|
result.setDangqianBanbenhao("current-version");
|
return result;
|
}
|
|
private TemplateJsonEntity activeVersion(String id) {
|
TemplateJsonEntity result = new TemplateJsonEntity();
|
result.setId(id);
|
result.setState(1);
|
return result;
|
}
|
|
private void assertWriteBackUpdate(LambdaUpdateWrapper<?> update, String fenpeiZixiangId,
|
Date huiguRiqi, String huiguNeirongZongjie, String zuizhongJielun) {
|
String sqlSet = update.getSqlSet();
|
assertTrue(sqlSet.contains("huigu_riqi"));
|
assertTrue(sqlSet.contains("huigu_neirong_zongjie"));
|
assertTrue(sqlSet.contains("zuizhong_jielun"));
|
assertTrue(sqlSet.contains("biz_status"));
|
assertTrue(update.getExpression().getNormal().getSqlSegment().contains("f_id"));
|
assertTrue(update.getExpression().getNormal().getSqlSegment().contains("f_delete_mark"));
|
assertTrue(update.getParamNameValuePairs().containsValue(fenpeiZixiangId));
|
assertTrue(update.getParamNameValuePairs().containsValue(huiguRiqi));
|
assertTrue(update.getParamNameValuePairs().containsValue(huiguNeirongZongjie));
|
assertTrue(update.getParamNameValuePairs().containsValue(zuizhongJielun));
|
assertTrue(update.getParamNameValuePairs().containsValue("yiwancheng"));
|
}
|
|
private void initTableInfo(Class<?> entityClass) {
|
if (TableInfoHelper.getTableInfo(entityClass) == null) {
|
TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new Configuration(), ""), entityClass);
|
}
|
}
|
}
|