diff --git a/backend/src/main/java/heartbeat/service/board/jira/JiraService.java b/backend/src/main/java/heartbeat/service/board/jira/JiraService.java index 78d94c64c4..7d72b4e6bd 100644 --- a/backend/src/main/java/heartbeat/service/board/jira/JiraService.java +++ b/backend/src/main/java/heartbeat/service/board/jira/JiraService.java @@ -471,13 +471,19 @@ private List getRealDoneCards(StoryPointsAndCycleTimeRequest reques private boolean isRealDoneCardByHistory(CardHistoryResponseDTO jiraCardHistory, StoryPointsAndCycleTimeRequest request) { List upperDoneStatuses = request.getStatus().stream().map(String::toUpperCase).toList(); - long validStartTime = parseLong(request.getStartTime()); - return jiraCardHistory.getItems() + List doneTimes = jiraCardHistory.getItems() .stream() .filter(history -> STATUS_FIELD_ID.equals(history.getFieldId())) .filter(history -> upperDoneStatuses.contains(history.getTo().getDisplayValue().toUpperCase())) - .allMatch(history -> history.getTimestamp() > validStartTime); + .map(HistoryDetail::getTimestamp) + .toList(); + + long validStartTime = parseLong(request.getStartTime()); + long validEndTime = parseLong(request.getEndTime()); + + return doneTimes.stream().allMatch(time -> validStartTime <= time) + && doneTimes.stream().anyMatch(time -> validEndTime >= time); } private CycleTimeInfoDTO getCycleTime(URI baseUrl, String doneCardKey, String token, Boolean treatFlagCardAsBlock, diff --git a/backend/src/test/java/heartbeat/service/jira/JiraBoardConfigDTOFixture.java b/backend/src/test/java/heartbeat/service/jira/JiraBoardConfigDTOFixture.java index a2454f4beb..2a19426018 100644 --- a/backend/src/test/java/heartbeat/service/jira/JiraBoardConfigDTOFixture.java +++ b/backend/src/test/java/heartbeat/service/jira/JiraBoardConfigDTOFixture.java @@ -124,6 +124,16 @@ public static AllDoneCardsResponseDTO.AllDoneCardsResponseDTOBuilder ALL_DONE_CA JiraCardField.builder().assignee(new Assignee(ASSIGNEENAME)).storyPoints(5).build()))); } + public static AllDoneCardsResponseDTO.AllDoneCardsResponseDTOBuilder NEED_FILTERED_ALL_DONE_CARDS_BUILDER() { + return AllDoneCardsResponseDTO.builder() + .total("2") + .issues(List.of( + new JiraCard("1", + JiraCardField.builder().assignee(new Assignee(ASSIGNEENAME)).storyPoints(5).build()), + new JiraCard("2", + JiraCardField.builder().assignee(new Assignee(ASSIGNEENAME)).storyPoints(5).build()))); + } + public static AllDoneCardsResponseDTO.AllDoneCardsResponseDTOBuilder ALL_NON_DONE_CARDS_RESPONSE_FOR_STORY_POINT_BUILDER() { return AllDoneCardsResponseDTO.builder() .total("3") @@ -202,6 +212,20 @@ public static CardHistoryResponseDTO.CardHistoryResponseDTOBuilder CARD_HISTORY_ new Status("removeFlag")))); } + public static CardHistoryResponseDTO.CardHistoryResponseDTOBuilder CARD_HISTORY_DONE_TIME_GREATER_THAN_END_TIME_BUILDER() { + return CardHistoryResponseDTO.builder() + .items(List.of(new HistoryDetail(1, "status", new Status("To do"), new Status(BLOCK)), + new HistoryDetail(2, "assignee", new Status("In Dev"), new Status("To do")), + new HistoryDetail(3, "status", new Status(REVIEW), new Status("In Dev")), + new HistoryDetail(4, "status", new Status(WAITING_FOR_TESTING), new Status(REVIEW)), + new HistoryDetail(1682642740000L, "status", new Status(TESTING), new Status(WAITING_FOR_TESTING)), + new HistoryDetail(1682642740001L, "status", new Status(BLOCK), new Status(TESTING)), + new HistoryDetail(1682642740002L, "status", new Status(FLAG), new Status(BLOCK)), + new HistoryDetail(1682642750001L, "customfield_10021", new Status("Impediment"), new Status(FLAG)), + new HistoryDetail(1682642750002L, "flagged", new Status("Impediment"), new Status("removeFlag")), + new HistoryDetail(1686908799000L, "status", new Status("Done"), new Status(TESTING)))); + } + public static FieldResponseDTO.FieldResponseDTOBuilder FIELD_RESPONSE_BUILDER() { IssueField storyPointIssueField = new IssueField("customfield_10016", "Story point estimate"); IssueField sprintIssueField = new IssueField("customfield_10020", "Sprint"); diff --git a/backend/src/test/java/heartbeat/service/jira/JiraServiceTest.java b/backend/src/test/java/heartbeat/service/jira/JiraServiceTest.java index 57c3505939..87d138fb73 100644 --- a/backend/src/test/java/heartbeat/service/jira/JiraServiceTest.java +++ b/backend/src/test/java/heartbeat/service/jira/JiraServiceTest.java @@ -42,6 +42,7 @@ import static heartbeat.service.jira.JiraBoardConfigDTOFixture.ALL_FIELD_RESPONSE_BUILDER; import static heartbeat.service.jira.JiraBoardConfigDTOFixture.ALL_NON_DONE_CARDS_RESPONSE_FOR_STORY_POINT_BUILDER; import static heartbeat.service.jira.JiraBoardConfigDTOFixture.BOARD_ID; +import static heartbeat.service.jira.JiraBoardConfigDTOFixture.CARD_HISTORY_DONE_TIME_GREATER_THAN_END_TIME_BUILDER; import static heartbeat.service.jira.JiraBoardConfigDTOFixture.CARD_HISTORY_MULTI_RESPONSE_BUILDER; import static heartbeat.service.jira.JiraBoardConfigDTOFixture.CARD_HISTORY_RESPONSE_BUILDER; import static heartbeat.service.jira.JiraBoardConfigDTOFixture.CARD_HISTORY_RESPONSE_BUILDER_TO_DONE; @@ -61,6 +62,7 @@ import static heartbeat.service.jira.JiraBoardConfigDTOFixture.JIRA_BOARD_CONFIG_RESPONSE_BUILDER; import static heartbeat.service.jira.JiraBoardConfigDTOFixture.JIRA_BOARD_SETTING_BUILD; import static heartbeat.service.jira.JiraBoardConfigDTOFixture.JIRA_BOARD_SETTING_HAVE_UNKNOWN_COLUMN_BUILD; +import static heartbeat.service.jira.JiraBoardConfigDTOFixture.NEED_FILTERED_ALL_DONE_CARDS_BUILDER; import static heartbeat.service.jira.JiraBoardConfigDTOFixture.NONE_STATUS_SELF_RESPONSE_BUILDER; import static heartbeat.service.jira.JiraBoardConfigDTOFixture.ONE_PAGE_NO_DONE_CARDS_RESPONSE_BUILDER; import static heartbeat.service.jira.JiraBoardConfigDTOFixture.STORY_POINTS_FORM_ALL_DONE_CARD; @@ -499,6 +501,33 @@ void shouldGetCardsWhenCallGetStoryPointsAndCycleTimeWhenBoardTypeIsClassicJira( assertThat(cardCollection.getCardsNumber()).isEqualTo(1); } + @Test + void shouldGetCardsWhenCallGetStoryPointsAndCycleTimeWhenDoneTimeGreaterThanSelectedEndTime() + throws JsonProcessingException { + // given + URI baseUrl = URI.create(SITE_ATLASSIAN_NET); + String token = "token"; + + JiraBoardSetting jiraBoardSetting = CLASSIC_JIRA_BOARD_SETTING_BUILD().build(); + StoryPointsAndCycleTimeRequest storyPointsAndCycleTimeRequest = CLASSIC_JIRA_STORY_POINTS_FORM_ALL_DONE_CARD() + .build(); + String allDoneCards = objectMapper.writeValueAsString(NEED_FILTERED_ALL_DONE_CARDS_BUILDER().build()); + + // when + when(urlGenerator.getUri(any())).thenReturn(baseUrl); + when(jiraFeignClient.getJiraCards(any(), any(), anyInt(), anyInt(), any(), any())).thenReturn(allDoneCards); + when(jiraFeignClient.getJiraCardHistory(baseUrl, "1", token)) + .thenReturn(CARD_HISTORY_MULTI_RESPONSE_BUILDER().build()); + when(jiraFeignClient.getJiraCardHistory(baseUrl, "2", token)) + .thenReturn(CARD_HISTORY_DONE_TIME_GREATER_THAN_END_TIME_BUILDER().build()); + when(jiraFeignClient.getTargetField(baseUrl, "PLL", token)).thenReturn(ALL_FIELD_RESPONSE_BUILDER().build()); + // then + + CardCollection cardCollection = jiraService.getStoryPointsAndCycleTimeForDoneCards( + storyPointsAndCycleTimeRequest, jiraBoardSetting.getBoardColumns(), List.of("Zhang San")); + assertThat(cardCollection.getCardsNumber()).isEqualTo(1); + } + @Test void shouldReturnBadRequestExceptionWhenBoardTypeIsNotCorrect() { // given