1. 去除部门编码为空时,默认使用 id 作为 code 进行映射的逻辑
This commit is contained in:
@@ -513,7 +513,7 @@ public class IWorkSyncProcessorImpl implements IWorkSyncProcessor {
|
|||||||
req.setIsGroup(Boolean.FALSE);
|
req.setIsGroup(Boolean.FALSE);
|
||||||
req.setDeptSource(DeptSourceEnum.IWORK.getSource());
|
req.setDeptSource(DeptSourceEnum.IWORK.getSource());
|
||||||
req.setExternalSystemCode(ExternalPlatformEnum.IWORK.getCode());
|
req.setExternalSystemCode(ExternalPlatformEnum.IWORK.getCode());
|
||||||
req.setExternalDeptCode(StrUtil.blankToDefault(trimToNull(data.getSubcompanycode()), String.valueOf(data.getId())));
|
req.setExternalDeptCode(trimToNull(data.getSubcompanycode()));
|
||||||
req.setExternalDeptName(data.getSubcompanyname());
|
req.setExternalDeptName(data.getSubcompanyname());
|
||||||
return req;
|
return req;
|
||||||
}
|
}
|
||||||
@@ -533,7 +533,7 @@ public class IWorkSyncProcessorImpl implements IWorkSyncProcessor {
|
|||||||
req.setIsGroup(Boolean.FALSE);
|
req.setIsGroup(Boolean.FALSE);
|
||||||
req.setDeptSource(DeptSourceEnum.IWORK.getSource());
|
req.setDeptSource(DeptSourceEnum.IWORK.getSource());
|
||||||
req.setExternalSystemCode(ExternalPlatformEnum.IWORK.getCode());
|
req.setExternalSystemCode(ExternalPlatformEnum.IWORK.getCode());
|
||||||
req.setExternalDeptCode(StrUtil.blankToDefault(trimToNull(data.getDepartmentcode()), String.valueOf(data.getId())));
|
req.setExternalDeptCode(trimToNull(data.getDepartmentcode()));
|
||||||
req.setExternalDeptName(data.getDepartmentname());
|
req.setExternalDeptName(data.getDepartmentname());
|
||||||
return req;
|
return req;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,141 @@
|
|||||||
|
package com.zt.plat.module.system.service.integration.iwork.impl;
|
||||||
|
|
||||||
|
import com.zt.plat.framework.test.core.ut.BaseMockitoUnitTest;
|
||||||
|
import com.zt.plat.module.system.controller.admin.dept.vo.dept.DeptSaveReqVO;
|
||||||
|
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkHrDepartmentPageRespVO;
|
||||||
|
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkHrSubcompanyPageRespVO;
|
||||||
|
import com.zt.plat.module.system.dal.mysql.dept.PostMapper;
|
||||||
|
import com.zt.plat.module.system.dal.mysql.user.AdminUserMapper;
|
||||||
|
import com.zt.plat.module.system.service.dept.DeptService;
|
||||||
|
import com.zt.plat.module.system.service.dept.PostService;
|
||||||
|
import com.zt.plat.module.system.service.integration.iwork.IWorkSyncProcessor;
|
||||||
|
import com.zt.plat.module.system.service.user.AdminUserService;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.mockito.InjectMocks;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for cross-page pending handling and placeholder backfill in IWorkSyncProcessorImpl.
|
||||||
|
*/
|
||||||
|
class IWorkSyncProcessorImplTest extends BaseMockitoUnitTest {
|
||||||
|
|
||||||
|
@InjectMocks
|
||||||
|
private IWorkSyncProcessorImpl processor;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private DeptService deptService;
|
||||||
|
@Mock
|
||||||
|
private PostService postService;
|
||||||
|
@Mock
|
||||||
|
private PostMapper postMapper;
|
||||||
|
@Mock
|
||||||
|
private AdminUserService adminUserService;
|
||||||
|
@Mock
|
||||||
|
private AdminUserMapper adminUserMapper;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldProcessPendingChildWhenParentArrivesInLaterPage() {
|
||||||
|
IWorkSyncProcessor.DeptSyncContext context = new IWorkSyncProcessor.DeptSyncContext();
|
||||||
|
IWorkSyncProcessor.SyncOptions options = IWorkSyncProcessor.SyncOptions.custom(true, true, true);
|
||||||
|
|
||||||
|
IWorkHrDepartmentPageRespVO.Department child = new IWorkHrDepartmentPageRespVO.Department();
|
||||||
|
child.setId(200);
|
||||||
|
child.setDepartmentname("child");
|
||||||
|
child.setSupdepid(100); // parent comes later
|
||||||
|
|
||||||
|
IWorkHrDepartmentPageRespVO.Department parent = new IWorkHrDepartmentPageRespVO.Department();
|
||||||
|
parent.setId(100);
|
||||||
|
parent.setDepartmentname("parent");
|
||||||
|
parent.setSupdepid(0); // root
|
||||||
|
|
||||||
|
when(deptService.getDept(anyLong())).thenReturn(null);
|
||||||
|
when(deptService.createDept(any(DeptSaveReqVO.class))).thenReturn(100L, 200L);
|
||||||
|
|
||||||
|
processor.syncDepartments(List.of(child), options, context);
|
||||||
|
|
||||||
|
verify(deptService, never()).createDept(any());
|
||||||
|
assertEquals(1, context.getPendingDepartments().size());
|
||||||
|
|
||||||
|
processor.syncDepartments(List.of(parent), options, context);
|
||||||
|
|
||||||
|
verify(deptService, times(2)).createDept(any());
|
||||||
|
assertTrue(context.getPendingDepartments().isEmpty(), "pending should be cleared after parent processed");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldInsertPlaceholderWhenParentMissingAfterFlush() {
|
||||||
|
IWorkSyncProcessor.DeptSyncContext context = new IWorkSyncProcessor.DeptSyncContext();
|
||||||
|
IWorkSyncProcessor.SyncOptions options = IWorkSyncProcessor.SyncOptions.custom(true, true, true);
|
||||||
|
|
||||||
|
IWorkHrDepartmentPageRespVO.Department child = new IWorkHrDepartmentPageRespVO.Department();
|
||||||
|
child.setId(300);
|
||||||
|
child.setDepartmentname("orphan");
|
||||||
|
child.setSupdepid(9999); // never provided
|
||||||
|
|
||||||
|
when(deptService.getDept(anyLong())).thenReturn(null);
|
||||||
|
when(deptService.createDept(any(DeptSaveReqVO.class))).thenReturn(300L);
|
||||||
|
|
||||||
|
processor.syncDepartments(List.of(child), options, context);
|
||||||
|
assertEquals(1, context.getPendingDepartments().size());
|
||||||
|
|
||||||
|
IWorkSyncProcessor.BatchResult flushResult = processor.flushDeptPending(context, options);
|
||||||
|
assertNotNull(flushResult);
|
||||||
|
|
||||||
|
ArgumentCaptor<DeptSaveReqVO> captor = ArgumentCaptor.forClass(DeptSaveReqVO.class);
|
||||||
|
verify(deptService, times(1)).createDept(captor.capture());
|
||||||
|
DeptSaveReqVO placeholderReq = captor.getValue();
|
||||||
|
assertTrue(Boolean.TRUE.equals(placeholderReq.getDelayCodeGeneration()));
|
||||||
|
assertNull(placeholderReq.getCode());
|
||||||
|
|
||||||
|
assertTrue(context.getPendingDepartments().isEmpty(), "pending should be cleared after placeholder insert");
|
||||||
|
assertTrue(context.getPlaceholderDeptIds().contains(300L));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldKeepExternalCodeNullWhenDepartmentCodeBlank() {
|
||||||
|
IWorkSyncProcessor.SyncOptions options = IWorkSyncProcessor.SyncOptions.custom(true, true, true);
|
||||||
|
|
||||||
|
IWorkHrDepartmentPageRespVO.Department dept = new IWorkHrDepartmentPageRespVO.Department();
|
||||||
|
dept.setId(500);
|
||||||
|
dept.setDepartmentname("blank-code-dept");
|
||||||
|
dept.setDepartmentcode(" ");
|
||||||
|
dept.setSupdepid(0);
|
||||||
|
|
||||||
|
when(deptService.getDept(anyLong())).thenReturn(null);
|
||||||
|
when(deptService.createDept(any(DeptSaveReqVO.class))).thenReturn(500L);
|
||||||
|
|
||||||
|
processor.syncDepartments(List.of(dept), options, null);
|
||||||
|
|
||||||
|
ArgumentCaptor<DeptSaveReqVO> captor = ArgumentCaptor.forClass(DeptSaveReqVO.class);
|
||||||
|
verify(deptService, times(1)).createDept(captor.capture());
|
||||||
|
DeptSaveReqVO req = captor.getValue();
|
||||||
|
assertNull(req.getExternalDeptCode(), "externalDeptCode should remain null when source code is blank");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldKeepExternalCodeNullWhenSubcompanyCodeBlank() {
|
||||||
|
IWorkSyncProcessor.SyncOptions options = IWorkSyncProcessor.SyncOptions.custom(true, true, true);
|
||||||
|
|
||||||
|
IWorkHrSubcompanyPageRespVO.Subcompany subcompany = new IWorkHrSubcompanyPageRespVO.Subcompany();
|
||||||
|
subcompany.setId(600);
|
||||||
|
subcompany.setSubcompanyname("blank-code-sub");
|
||||||
|
subcompany.setSubcompanycode(null);
|
||||||
|
subcompany.setSupsubcomid(0);
|
||||||
|
|
||||||
|
when(deptService.getDept(anyLong())).thenReturn(null);
|
||||||
|
when(deptService.createDept(any(DeptSaveReqVO.class))).thenReturn(600L);
|
||||||
|
|
||||||
|
processor.syncSubcompanies(List.of(subcompany), options, null);
|
||||||
|
|
||||||
|
ArgumentCaptor<DeptSaveReqVO> captor = ArgumentCaptor.forClass(DeptSaveReqVO.class);
|
||||||
|
verify(deptService, times(1)).createDept(captor.capture());
|
||||||
|
DeptSaveReqVO req = captor.getValue();
|
||||||
|
assertNull(req.getExternalDeptCode(), "externalDeptCode should remain null when source code is null or blank");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package com.zt.plat.module.system.service.integration.iwork.impl;
|
||||||
|
|
||||||
|
import com.zt.plat.framework.test.core.ut.BaseMockitoUnitTest;
|
||||||
|
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkFullSyncReqVO;
|
||||||
|
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkHrDepartmentPageRespVO;
|
||||||
|
import com.zt.plat.module.system.enums.integration.IWorkSyncEntityTypeEnum;
|
||||||
|
import com.zt.plat.module.system.service.dept.DeptService;
|
||||||
|
import com.zt.plat.module.system.service.integration.iwork.IWorkOrgRestService;
|
||||||
|
import com.zt.plat.module.system.service.integration.iwork.IWorkSyncProcessor;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.InjectMocks;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.stubbing.Answer;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
|
class IWorkSyncServiceImplTest extends BaseMockitoUnitTest {
|
||||||
|
|
||||||
|
@InjectMocks
|
||||||
|
private IWorkSyncServiceImpl syncService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private IWorkOrgRestService orgRestService;
|
||||||
|
@Mock
|
||||||
|
private IWorkSyncProcessor syncProcessor;
|
||||||
|
@Mock
|
||||||
|
private DeptService deptService;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldBackfillCodesWhenPlaceholdersExistAfterFullSync() {
|
||||||
|
IWorkFullSyncReqVO reqVO = new IWorkFullSyncReqVO();
|
||||||
|
reqVO.setPageSize(1);
|
||||||
|
reqVO.setMaxPages(1);
|
||||||
|
|
||||||
|
IWorkHrDepartmentPageRespVO pageResp = new IWorkHrDepartmentPageRespVO();
|
||||||
|
pageResp.setSuccess(true);
|
||||||
|
IWorkHrDepartmentPageRespVO.Department dept = new IWorkHrDepartmentPageRespVO.Department();
|
||||||
|
dept.setId(1);
|
||||||
|
pageResp.setDataList(List.of(dept));
|
||||||
|
when(orgRestService.listDepartments(any())).thenReturn(pageResp);
|
||||||
|
|
||||||
|
// 在部门同步时标记占位 ID
|
||||||
|
doAnswer((Answer<IWorkSyncProcessor.BatchResult>) invocation -> {
|
||||||
|
IWorkSyncProcessor.DeptSyncContext context = invocation.getArgument(2);
|
||||||
|
if (context != null) {
|
||||||
|
context.getPlaceholderDeptIds().add(500L);
|
||||||
|
}
|
||||||
|
return IWorkSyncProcessor.BatchResult.empty();
|
||||||
|
}).when(syncProcessor).syncDepartments(any(), any(), any(IWorkSyncProcessor.DeptSyncContext.class));
|
||||||
|
|
||||||
|
when(syncProcessor.flushDeptPending(any(), any())).thenReturn(IWorkSyncProcessor.BatchResult.empty());
|
||||||
|
|
||||||
|
syncService.fullSyncDepartments(reqVO);
|
||||||
|
|
||||||
|
verify(deptService, times(1)).backfillMissingCodesWithoutEvent(argThat(set -> set.contains(500L)));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user