| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605 |
- package com.malk.service.workhours;
- import com.malk.server.aliwork.YDConf;
- import com.malk.server.aliwork.YDParam;
- import com.malk.server.common.McException;
- import com.malk.server.dingtalk.DDR_New;
- import com.malk.server.workhours.TimeCardApprovalStartRequest;
- import com.malk.server.workhours.WHConf;
- import com.malk.service.aliwork.YDClient;
- import com.malk.service.dingtalk.DDClient;
- import com.malk.service.dingtalk.DDClient_Contacts;
- import org.junit.jupiter.api.Test;
- import org.mockito.ArgumentCaptor;
- import org.springframework.test.util.ReflectionTestUtils;
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import java.util.concurrent.CompletableFuture;
- import java.util.concurrent.CountDownLatch;
- import java.util.concurrent.TimeUnit;
- import static org.junit.jupiter.api.Assertions.assertFalse;
- import static org.junit.jupiter.api.Assertions.assertEquals;
- import static org.junit.jupiter.api.Assertions.assertTrue;
- import static org.junit.jupiter.api.Assertions.assertThrows;
- import static org.mockito.ArgumentMatchers.any;
- import static org.mockito.ArgumentMatchers.eq;
- import static org.mockito.Mockito.mock;
- import static org.mockito.Mockito.verifyNoInteractions;
- import static org.mockito.Mockito.times;
- import static org.mockito.Mockito.when;
- import static org.mockito.Mockito.verify;
- class ReSubmitApprovalServiceTest {
- private static final String DEFAULT_MANAGER_ID = "634735129";
- @Test
- void shouldTreatBlankHistoricalOpinionAsCompletedApprovalCoverage() {
- assertTrue(ReSubmitApprovalService.isCompletedApprovedRow("COMPLETED", "agree", ""));
- assertTrue(ReSubmitApprovalService.isCompletedApprovedRow("COMPLETED", "agree", null));
- assertTrue(ReSubmitApprovalService.isCompletedApprovedRow("COMPLETED", "agree", "同意"));
- assertFalse(ReSubmitApprovalService.isCompletedApprovedRow("COMPLETED", "agree", "拒绝"));
- assertFalse(ReSubmitApprovalService.isCompletedApprovedRow("RUNNING", "agree", ""));
- }
- @Test
- void shouldSkipRowsAlreadyInRunningApproval() {
- ReSubmitApprovalService.ApprovalCoverage coverage =
- new ReSubmitApprovalService.ApprovalCoverage();
- String key = ReSubmitApprovalService.approvalKey(
- "billable", "user-1", "20260611", "P1");
- coverage.runningKeys.add(key);
- assertTrue(coverage.shouldSkip(key, 0));
- }
- @Test
- void shouldRouteUnaccountedCompletedApprovalToWriteBackInsteadOfResubmit() {
- ReSubmitApprovalService.ApprovalCoverage coverage =
- new ReSubmitApprovalService.ApprovalCoverage();
- String key = ReSubmitApprovalService.approvalKey(
- "billable", "user-1", "20260611", "P1");
- coverage.completedAgreeHours.put(key, 8d);
- assertTrue(coverage.shouldSkip(key, 0));
- assertFalse(coverage.shouldSkip(key, 8));
- }
- @Test
- void shouldStartApprovalWithConfiguredHumanOriginator() {
- YDClient ydClient = mock(YDClient.class);
- WHConf whConf = new WHConf();
- whConf.setYidaAppType("APP");
- whConf.setYidaSystemToken("TOKEN");
- whConf.setFormUuidApproval("FORM-APPROVAL");
- whConf.setApprovalProcessCode("PROCESS-APPROVAL");
- whConf.setApprovalOriginatorUserId("system-user");
- whConf.setApprovalOriginatorDeptId("dept-default");
- whConf.setApprovalFillTypeField("radioField_fill_type");
- ReSubmitApprovalService service = new ReSubmitApprovalService();
- ReflectionTestUtils.setField(service, "ydClient", ydClient);
- ReflectionTestUtils.setField(service, "whConf", whConf);
- attachOpenMonth(service);
- TimeCardApprovalStartRequest request = new TimeCardApprovalStartRequest();
- request.setFormUuid("FORM-APPROVAL");
- request.setProcessCode("PROCESS-APPROVAL");
- request.setDeptId("dept-request");
- request.setFormDataJson("{\"textField_mmd2lv0y\":\"202609\",\"textField_test\":\"value\"}");
- assertTrue(service.startApproval(request));
- ArgumentCaptor<YDParam> captor = ArgumentCaptor.forClass(YDParam.class);
- verify(ydClient).operateData(captor.capture(), eq(YDConf.FORM_OPERATION.start));
- assertEquals("system-user", captor.getValue().getUserId());
- assertEquals("dept-request", captor.getValue().getDeptId());
- Map started = com.alibaba.fastjson.JSON.parseObject(
- captor.getValue().getFormDataJson(), Map.class);
- assertEquals("正常", started.get("radioField_fill_type"));
- }
- @Test
- void shouldNotStartSameNormalApprovalTwiceWithinGuardWindow() {
- YDClient ydClient = mock(YDClient.class);
- WHConf whConf = new WHConf();
- whConf.setYidaAppType("APP");
- whConf.setYidaSystemToken("TOKEN");
- whConf.setFormUuidApproval("FORM-APPROVAL");
- whConf.setApprovalProcessCode("PROCESS-APPROVAL");
- whConf.setApprovalOriginatorUserId("system-user");
- whConf.setApprovalFillTypeField("radioField_fill_type");
- ReSubmitApprovalService service = new ReSubmitApprovalService();
- ReflectionTestUtils.setField(service, "ydClient", ydClient);
- ReflectionTestUtils.setField(service, "whConf", whConf);
- attachOpenMonth(service);
- TimeCardApprovalStartRequest request = new TimeCardApprovalStartRequest();
- request.setFormUuid("FORM-APPROVAL");
- request.setProcessCode("PROCESS-APPROVAL");
- request.setFormDataJson("{\"textField_mmd2lv0y\":\"202609\",\"textField_test\":\"same-hours\"}");
- assertTrue(service.startApproval(request));
- assertTrue(service.startApproval(request));
- verify(ydClient, times(1)).operateData(any(YDParam.class), eq(YDConf.FORM_OPERATION.start));
- request.setFormDataJson("{\"textField_mmd2lv0y\":\"202609\",\"textField_test\":\"changed-hours\"}");
- assertTrue(service.startApproval(request));
- verify(ydClient, times(2)).operateData(any(YDParam.class), eq(YDConf.FORM_OPERATION.start));
- }
- @Test
- void shouldBlockConcurrentNormalApprovalStart() throws Exception {
- YDClient ydClient = mock(YDClient.class);
- WHConf whConf = new WHConf();
- whConf.setYidaAppType("APP");
- whConf.setYidaSystemToken("TOKEN");
- whConf.setFormUuidApproval("FORM-APPROVAL");
- whConf.setApprovalProcessCode("PROCESS-APPROVAL");
- whConf.setApprovalOriginatorUserId("system-user");
- CountDownLatch entered = new CountDownLatch(1);
- CountDownLatch release = new CountDownLatch(1);
- when(ydClient.operateData(any(YDParam.class), eq(YDConf.FORM_OPERATION.start)))
- .thenAnswer(invocation -> {
- entered.countDown();
- release.await(5, TimeUnit.SECONDS);
- return null;
- });
- ReSubmitApprovalService service = new ReSubmitApprovalService();
- ReflectionTestUtils.setField(service, "ydClient", ydClient);
- ReflectionTestUtils.setField(service, "whConf", whConf);
- attachOpenMonth(service);
- TimeCardApprovalStartRequest request = new TimeCardApprovalStartRequest();
- request.setFormUuid("FORM-APPROVAL");
- request.setProcessCode("PROCESS-APPROVAL");
- request.setFormDataJson("{\"textField_mmd2lv0y\":\"202609\",\"textField_test\":\"same-hours\"}");
- CompletableFuture<Boolean> first = CompletableFuture.supplyAsync(() -> service.startApproval(request));
- try {
- assertTrue(entered.await(5, TimeUnit.SECONDS));
- assertThrows(RuntimeException.class, () -> service.startApproval(request));
- } finally {
- release.countDown();
- }
- assertTrue(first.get(5, TimeUnit.SECONDS));
- verify(ydClient, times(1)).operateData(any(YDParam.class), eq(YDConf.FORM_OPERATION.start));
- }
- @Test
- void shouldBlockNewApprovalAndResubmitWhileMonthIsLocked() {
- YDClient ydClient = mock(YDClient.class);
- MonthClosingService monthClosingService = mock(MonthClosingService.class);
- when(monthClosingService.isLocked("202609")).thenReturn(true);
- WHConf whConf = new WHConf();
- whConf.setFormUuidApproval("FORM-APPROVAL");
- whConf.setApprovalProcessCode("PROCESS-APPROVAL");
- whConf.setApprovalOriginatorUserId("system-user");
- ReSubmitApprovalService service = new ReSubmitApprovalService();
- ReflectionTestUtils.setField(service, "ydClient", ydClient);
- ReflectionTestUtils.setField(service, "whConf", whConf);
- ReflectionTestUtils.setField(service, "monthClosingService", monthClosingService);
- TimeCardApprovalStartRequest request = new TimeCardApprovalStartRequest();
- request.setFormUuid("FORM-APPROVAL");
- request.setProcessCode("PROCESS-APPROVAL");
- request.setFormDataJson("{\"textField_mmd2lv0y\":\"202609\"}");
- assertThrows(McException.class, () -> service.startApproval(request));
- assertThrows(McException.class, () -> service.resubmit("202609", "user-1", false));
- verifyNoInteractions(ydClient);
- }
- @Test
- void shouldBlockRepairApprovalBySubmitMonthWhileSourceMonthIsOpen() {
- YDClient ydClient = mock(YDClient.class);
- MonthClosingService monthClosingService = mock(MonthClosingService.class);
- when(monthClosingService.isLocked("202609")).thenReturn(true);
- WHConf whConf = new WHConf();
- whConf.setFormUuidApproval("FORM-APPROVAL");
- whConf.setApprovalProcessCode("PROCESS-APPROVAL");
- whConf.setApprovalOriginatorUserId("system-user");
- whConf.setApprovalFillTypeField("radioField_fill_type");
- whConf.setApprovalRepairSubmitDateField("dateField_repair_submit");
- ReSubmitApprovalService service = new ReSubmitApprovalService();
- ReflectionTestUtils.setField(service, "ydClient", ydClient);
- ReflectionTestUtils.setField(service, "whConf", whConf);
- ReflectionTestUtils.setField(service, "monthClosingService", monthClosingService);
- TimeCardApprovalStartRequest request = new TimeCardApprovalStartRequest();
- request.setFormUuid("FORM-APPROVAL");
- request.setProcessCode("PROCESS-APPROVAL");
- request.setFormDataJson("{\"textField_mmd2lv0y\":\"202608\",\"radioField_fill_type\":\"补填\",\"dateField_repair_submit\":\"2026-09-22\"}");
- assertThrows(McException.class, () -> service.startApproval(request));
- verify(monthClosingService).isLocked("202609");
- verify(monthClosingService, org.mockito.Mockito.never()).isLocked("202608");
- verifyNoInteractions(ydClient);
- }
- @Test
- void shouldKeepExplicitRepairFillTypeWhenStartingApproval() {
- YDClient ydClient = mock(YDClient.class);
- WHConf whConf = new WHConf();
- whConf.setYidaAppType("APP");
- whConf.setYidaSystemToken("TOKEN");
- whConf.setFormUuidApproval("FORM-APPROVAL");
- whConf.setApprovalProcessCode("PROCESS-APPROVAL");
- whConf.setApprovalOriginatorUserId("system-user");
- whConf.setApprovalFillTypeField("radioField_fill_type");
- whConf.setApprovalRepairSubmitDateField("dateField_repair_submit");
- ReSubmitApprovalService service = new ReSubmitApprovalService();
- ReflectionTestUtils.setField(service, "ydClient", ydClient);
- ReflectionTestUtils.setField(service, "whConf", whConf);
- MonthClosingService monthClosingService = attachOpenMonth(service);
- TimeCardApprovalStartRequest request = new TimeCardApprovalStartRequest();
- request.setFormUuid("FORM-APPROVAL");
- request.setProcessCode("PROCESS-APPROVAL");
- request.setFormDataJson("{\"textField_mmd2lv0y\":\"202608\",\"radioField_fill_type\":\"补填\",\"dateField_repair_submit\":\"2026-09-22\"}");
- assertTrue(service.startApproval(request));
- ArgumentCaptor<YDParam> captor = ArgumentCaptor.forClass(YDParam.class);
- verify(ydClient).operateData(captor.capture(), eq(YDConf.FORM_OPERATION.start));
- Map started = com.alibaba.fastjson.JSON.parseObject(
- captor.getValue().getFormDataJson(), Map.class);
- assertEquals("补填", started.get("radioField_fill_type"));
- verify(monthClosingService, org.mockito.Mockito.times(2)).isLocked("202609");
- verify(monthClosingService, org.mockito.Mockito.never()).isLocked("202608");
- }
- @Test
- void shouldPaginateSummaryRecordsWithCurrentPage() {
- YDClient ydClient = mock(YDClient.class);
- WHConf whConf = new WHConf();
- whConf.setYidaAppType("APP");
- whConf.setYidaSystemToken("TOKEN");
- ReSubmitApprovalService service = new ReSubmitApprovalService();
- ReflectionTestUtils.setField(service, "ydClient", ydClient);
- ReflectionTestUtils.setField(service, "whConf", whConf);
- when(ydClient.queryData(any(YDParam.class), eq(YDConf.FORM_QUERY.retrieve_search_form)))
- .thenAnswer(invocation -> {
- YDParam param = invocation.getArgument(0);
- com.malk.server.dingtalk.DDR_New response =
- new com.malk.server.dingtalk.DDR_New();
- List<Map> rows = new ArrayList<>();
- int size = param.getCurrentPage() == 1 ? 100 : 1;
- for (int index = 0; index < size; index++) {
- rows.add(Collections.singletonMap(
- "formInstanceId",
- param.getCurrentPage() + "-" + index));
- }
- response.setData(rows);
- return response;
- });
- List<Map> rows = service.queryAll("FORM-SUMMARY", Collections.emptyMap());
- assertEquals(101, rows.size());
- ArgumentCaptor<YDParam> captor = ArgumentCaptor.forClass(YDParam.class);
- verify(ydClient, org.mockito.Mockito.times(2))
- .queryData(captor.capture(), eq(YDConf.FORM_QUERY.retrieve_search_form));
- assertEquals(1, captor.getAllValues().get(0).getCurrentPage());
- assertEquals(2, captor.getAllValues().get(1).getCurrentPage());
- }
- @Test
- void shouldCreateApprovalShardWhenSubtableWouldExceedLimit() {
- assertTrue(ReSubmitApprovalService.hasSubtableCapacity(500));
- assertFalse(ReSubmitApprovalService.hasSubtableCapacity(501));
- assertTrue(ReSubmitApprovalService.canAppendToApprovalShard(250, 300));
- assertFalse(ReSubmitApprovalService.canAppendToApprovalShard(250, 301));
- assertTrue(ReSubmitApprovalService.canAppendToApprovalShard(0, 450));
- assertTrue(ReSubmitApprovalService.canAppendToApprovalShard(450, 450));
- assertFalse(ReSubmitApprovalService.canAppendToApprovalShard(0, 501));
- }
- @Test
- void shouldSplitFallbackManagerGroupByProject() {
- String projectA = ReSubmitApprovalService.approvalGroupKey(DEFAULT_MANAGER_ID, "P-A", "项目 A");
- String projectB = ReSubmitApprovalService.approvalGroupKey(DEFAULT_MANAGER_ID, "P-B", "项目 B");
- assertFalse(projectA.equals(projectB));
- assertEquals(DEFAULT_MANAGER_ID + "|project|P-A", projectA);
- }
- @Test
- void shouldKeepNormalManagerGroupAcrossProjects() {
- assertEquals(
- ReSubmitApprovalService.approvalGroupKey("manager-1", "P-A", "项目 A"),
- ReSubmitApprovalService.approvalGroupKey("manager-1", "P-B", "项目 B"));
- }
- @Test
- void shouldAppendFallbackApprovalOnlyToMatchingProject() {
- Map<String, Object> projectABillable = new HashMap<>();
- projectABillable.put("textField_mmacxew3", "P-A");
- Map<String, Object> projectANonBillable = new HashMap<>();
- projectANonBillable.put("textField_mmd1wu9d", "P-A");
- Map<String, Object> projectBRow = new HashMap<>();
- projectBRow.put("textField_mmacxew3", "P-B");
- assertTrue(ReSubmitApprovalService.approvalMatchesProject(
- Collections.singletonList((Map) projectABillable),
- Collections.singletonList((Map) projectANonBillable),
- "P-A", "项目 A"));
- assertFalse(ReSubmitApprovalService.approvalMatchesProject(
- Collections.singletonList((Map) projectABillable),
- Collections.singletonList((Map) projectBRow),
- "P-A", "项目 A"));
- assertFalse(ReSubmitApprovalService.approvalMatchesProject(
- Collections.emptyList(), Collections.emptyList(), "P-A", "项目 A"));
- assertTrue(ReSubmitApprovalService.approvalMatchesProject(
- Collections.singletonList((Map) projectABillable),
- Collections.singletonList((Map) projectBRow),
- "", ""));
- }
- @Test
- void shouldUseProjectNameWhenFallbackProjectCodeIsBlank() {
- assertFalse(ReSubmitApprovalService.approvalGroupKey(
- DEFAULT_MANAGER_ID, "", "项目 A").equals(
- ReSubmitApprovalService.approvalGroupKey(DEFAULT_MANAGER_ID, "", "项目 B")));
- Map<String, Object> projectA = new HashMap<>();
- projectA.put("textField_mmacxew3", "");
- projectA.put("textField_mkov5ozd", "项目 A");
- Map<String, Object> projectB = new HashMap<>();
- projectB.put("textField_mmacxew3", "");
- projectB.put("textField_mkov5ozd", "项目 B");
- assertTrue(ReSubmitApprovalService.approvalMatchesProject(
- Collections.singletonList((Map) projectA), Collections.emptyList(), "", "项目 A"));
- assertFalse(ReSubmitApprovalService.approvalMatchesProject(
- Collections.singletonList((Map) projectB), Collections.emptyList(), "", "项目 A"));
- }
- @Test
- void shouldKeepSingleSubmitterRowsTogetherWithinHardLimit() {
- YDClient ydClient = mock(YDClient.class);
- WHConf whConf = new WHConf();
- whConf.setYidaAppType("APP");
- whConf.setYidaSystemToken("TOKEN");
- whConf.setFormUuidApproval("FORM-APPROVAL");
- whConf.setApprovalProcessCode("PROCESS-APPROVAL");
- whConf.setApprovalOriginatorUserId("system-user");
- ReSubmitApprovalService service = new ReSubmitApprovalService();
- ReflectionTestUtils.setField(service, "ydClient", ydClient);
- ReflectionTestUtils.setField(service, "whConf", whConf);
- attachOpenMonth(service);
- Map<String, Object> formData = new HashMap<>();
- formData.put("textField_mmd2lv0y", "202609");
- List<Map<String, Object>> rows = new ArrayList<>();
- for (int index = 0; index < 450; index++) {
- rows.add(Collections.singletonMap("numberField_mmacxew9", 1));
- }
- formData.put("tableField_mmae8t99", rows);
- TimeCardApprovalStartRequest request = new TimeCardApprovalStartRequest();
- request.setFormUuid("FORM-APPROVAL");
- request.setProcessCode("PROCESS-APPROVAL");
- request.setFormDataJson(com.alibaba.fastjson.JSON.toJSONString(formData));
- assertTrue(service.startApproval(request));
- ArgumentCaptor<YDParam> captor = ArgumentCaptor.forClass(YDParam.class);
- verify(ydClient).operateData(captor.capture(), eq(YDConf.FORM_OPERATION.start));
- Map started = com.alibaba.fastjson.JSON.parseObject(
- captor.getValue().getFormDataJson(), Map.class);
- assertEquals(450, ((List) started.get("tableField_mmae8t99")).size());
- }
- @Test
- void shouldSplitSingleSubmitterOnlyWhenStartRowsExceedHardLimit() {
- YDClient ydClient = mock(YDClient.class);
- WHConf whConf = new WHConf();
- whConf.setYidaAppType("APP");
- whConf.setYidaSystemToken("TOKEN");
- whConf.setFormUuidApproval("FORM-APPROVAL");
- whConf.setApprovalProcessCode("PROCESS-APPROVAL");
- whConf.setApprovalOriginatorUserId("system-user");
- ReSubmitApprovalService service = new ReSubmitApprovalService();
- ReflectionTestUtils.setField(service, "ydClient", ydClient);
- ReflectionTestUtils.setField(service, "whConf", whConf);
- attachOpenMonth(service);
- Map<String, Object> formData = new HashMap<>();
- formData.put("textField_mmd2lv0y", "202609");
- List<Map<String, Object>> rows = new ArrayList<>();
- for (int index = 0; index < 501; index++) {
- Map<String, Object> row = new HashMap<>();
- row.put("numberField_mmacxew9", 1);
- rows.add(row);
- }
- formData.put("tableField_mmae8t99", rows);
- TimeCardApprovalStartRequest request = new TimeCardApprovalStartRequest();
- request.setFormUuid("FORM-APPROVAL");
- request.setProcessCode("PROCESS-APPROVAL");
- request.setFormDataJson(com.alibaba.fastjson.JSON.toJSONString(formData));
- assertTrue(service.startApproval(request));
- ArgumentCaptor<YDParam> captor = ArgumentCaptor.forClass(YDParam.class);
- verify(ydClient, org.mockito.Mockito.times(2))
- .operateData(captor.capture(), eq(YDConf.FORM_OPERATION.start));
- Map first = com.alibaba.fastjson.JSON.parseObject(
- captor.getAllValues().get(0).getFormDataJson(), Map.class);
- Map second = com.alibaba.fastjson.JSON.parseObject(
- captor.getAllValues().get(1).getFormDataJson(), Map.class);
- assertEquals(500, ((List) first.get("tableField_mmae8t99")).size());
- assertEquals(1, ((List) second.get("tableField_mmae8t99")).size());
- assertEquals(500d, ((Number) first.get("numberField_mmd5b5gl")).doubleValue());
- assertEquals(1d, ((Number) second.get("numberField_mmd5b5gl")).doubleValue());
- }
- @Test
- void shouldSplitOtherApprovalRowsAtHardLimit() {
- YDClient ydClient = mock(YDClient.class);
- WHConf whConf = new WHConf();
- whConf.setYidaAppType("APP");
- whConf.setYidaSystemToken("TOKEN");
- whConf.setFormUuidOtherApproval("FORM-OTHER");
- whConf.setOtherApprovalProcessCode("PROCESS-OTHER");
- whConf.setApprovalOriginatorUserId("system-user");
- ReSubmitApprovalService service = new ReSubmitApprovalService();
- ReflectionTestUtils.setField(service, "ydClient", ydClient);
- ReflectionTestUtils.setField(service, "whConf", whConf);
- attachOpenMonth(service);
- Map<String, Object> formData = new HashMap<>();
- formData.put("textField_mmd2lv0y", "202609");
- List<Map<String, Object>> rows = new ArrayList<>();
- for (int index = 0; index < 501; index++) {
- rows.add(Collections.singletonMap("numberField_mmd1wu9e", 2));
- }
- formData.put("tableField_mmd1wu9h", rows);
- TimeCardApprovalStartRequest request = new TimeCardApprovalStartRequest();
- request.setFormUuid("FORM-OTHER");
- request.setProcessCode("PROCESS-OTHER");
- request.setFormDataJson(com.alibaba.fastjson.JSON.toJSONString(formData));
- assertTrue(service.startApproval(request));
- ArgumentCaptor<YDParam> captor = ArgumentCaptor.forClass(YDParam.class);
- verify(ydClient, org.mockito.Mockito.times(2))
- .operateData(captor.capture(), eq(YDConf.FORM_OPERATION.start));
- Map first = com.alibaba.fastjson.JSON.parseObject(
- captor.getAllValues().get(0).getFormDataJson(), Map.class);
- Map second = com.alibaba.fastjson.JSON.parseObject(
- captor.getAllValues().get(1).getFormDataJson(), Map.class);
- assertEquals(500, ((List) first.get("tableField_mmd1wu9h")).size());
- assertEquals(1, ((List) second.get("tableField_mmd1wu9h")).size());
- assertEquals(1000d, ((Number) first.get("numberField_mmd5b5gl")).doubleValue());
- assertEquals(2d, ((Number) second.get("numberField_mmd5b5gl")).doubleValue());
- }
- @Test
- void shouldKeepActiveProjectManager() {
- DDClient ddClient = mock(DDClient.class);
- DDClient_Contacts contacts = mock(DDClient_Contacts.class);
- YDClient ydClient = mock(YDClient.class);
- ReSubmitApprovalService service = managerResolutionService(ddClient, contacts, ydClient);
- when(ddClient.getAccessToken()).thenReturn("token");
- when(contacts.getUserInfoById("token", "pm-active"))
- .thenReturn(Collections.singletonMap("userid", "pm-active"));
- assertEquals("pm-active", service.resolveProjectManager("pm-active"));
- verifyNoInteractions(ydClient);
- }
- @Test
- void shouldUseActiveSupervisorWhenProjectManagerHasLeft() {
- DDClient ddClient = mock(DDClient.class);
- DDClient_Contacts contacts = mock(DDClient_Contacts.class);
- YDClient ydClient = mock(YDClient.class);
- ReSubmitApprovalService service = managerResolutionService(ddClient, contacts, ydClient);
- when(ddClient.getAccessToken()).thenReturn("token");
- when(contacts.getUserInfoById("token", "pm-left"))
- .thenThrow(new IllegalStateException("user not found"));
- when(contacts.getUserInfoById("token", "supervisor-active"))
- .thenReturn(Collections.singletonMap("userid", "supervisor-active"));
- when(ydClient.queryData(any(YDParam.class), eq(YDConf.FORM_QUERY.retrieve_search_form)))
- .thenReturn(personnelResponse("supervisor-active"));
- assertEquals("supervisor-active", service.resolveProjectManager("pm-left"));
- }
- @Test
- void shouldFallBackWhenSupervisorIsInactive() {
- DDClient ddClient = mock(DDClient.class);
- DDClient_Contacts contacts = mock(DDClient_Contacts.class);
- YDClient ydClient = mock(YDClient.class);
- ReSubmitApprovalService service = managerResolutionService(ddClient, contacts, ydClient);
- when(ddClient.getAccessToken()).thenReturn("token");
- when(contacts.getUserInfoById("token", "pm-left"))
- .thenThrow(new IllegalStateException("user not found"));
- when(contacts.getUserInfoById("token", "supervisor-left"))
- .thenThrow(new IllegalStateException("user not found"));
- when(ydClient.queryData(any(YDParam.class), eq(YDConf.FORM_QUERY.retrieve_search_form)))
- .thenReturn(personnelResponse("supervisor-left"));
- assertEquals(DEFAULT_MANAGER_ID, service.resolveProjectManager("pm-left"));
- }
- @Test
- void shouldFallBackWhenSupervisorIsMissing() {
- DDClient ddClient = mock(DDClient.class);
- DDClient_Contacts contacts = mock(DDClient_Contacts.class);
- YDClient ydClient = mock(YDClient.class);
- ReSubmitApprovalService service = managerResolutionService(ddClient, contacts, ydClient);
- when(ddClient.getAccessToken()).thenReturn("token");
- when(contacts.getUserInfoById("token", "pm-left"))
- .thenThrow(new IllegalStateException("user not found"));
- when(ydClient.queryData(any(YDParam.class), eq(YDConf.FORM_QUERY.retrieve_search_form)))
- .thenReturn(new DDR_New());
- assertEquals(DEFAULT_MANAGER_ID, service.resolveProjectManager("pm-left"));
- }
- @Test
- void shouldFallBackWhenPersonnelLookupFails() {
- DDClient ddClient = mock(DDClient.class);
- DDClient_Contacts contacts = mock(DDClient_Contacts.class);
- YDClient ydClient = mock(YDClient.class);
- ReSubmitApprovalService service = managerResolutionService(ddClient, contacts, ydClient);
- when(ddClient.getAccessToken()).thenReturn("token");
- when(contacts.getUserInfoById("token", "pm-left"))
- .thenThrow(new IllegalStateException("user not found"));
- when(ydClient.queryData(any(YDParam.class), eq(YDConf.FORM_QUERY.retrieve_search_form)))
- .thenThrow(new IllegalStateException("query failed"));
- assertEquals(DEFAULT_MANAGER_ID, service.resolveProjectManager("pm-left"));
- }
- private static MonthClosingService attachOpenMonth(ReSubmitApprovalService service) {
- MonthClosingService monthClosingService = mock(MonthClosingService.class);
- ReflectionTestUtils.setField(service, "monthClosingService", monthClosingService);
- return monthClosingService;
- }
- private ReSubmitApprovalService managerResolutionService(DDClient ddClient,
- DDClient_Contacts contacts,
- YDClient ydClient) {
- WHConf whConf = new WHConf();
- whConf.setYidaAppType("APP");
- whConf.setYidaSystemToken("TOKEN");
- whConf.setFormUuidPersonnel("FORM-PERSONNEL");
- ReSubmitApprovalService service = new ReSubmitApprovalService();
- ReflectionTestUtils.setField(service, "ddClient", ddClient);
- ReflectionTestUtils.setField(service, "ddClient_contacts", contacts);
- ReflectionTestUtils.setField(service, "ydClient", ydClient);
- ReflectionTestUtils.setField(service, "whConf", whConf);
- return service;
- }
- private DDR_New personnelResponse(String supervisorId) {
- Map<String, Object> formData = new HashMap<>();
- formData.put("employeeField_mh8xhqc3_id", Collections.singletonList(supervisorId));
- Map<String, Object> record = new HashMap<>();
- record.put("formData", formData);
- DDR_New response = new DDR_New();
- response.setData(Collections.singletonList(record));
- return response;
- }
- }
|