Skip to content

Commit

Permalink
ADM-729:[backend]refactor is real done card
Browse files Browse the repository at this point in the history
  • Loading branch information
weiraneve committed Jan 22, 2024
1 parent 6d8fb28 commit 7831851
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 43 deletions.
6 changes: 6 additions & 0 deletions backend/src/main/java/heartbeat/client/JiraFeignClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,10 @@ CardHistoryResponseDTO getJiraCardHistory(URI baseUrl, @PathVariable String jira
@GetMapping(path = "/rest/api/2/issue/createmeta?projectKeys={projectKey}&expand=projects.issuetypes.fields")
FieldResponseDTO getTargetField(URI baseUrl, @PathVariable String projectKey, @RequestHeader String authorization);

@GetMapping(path = "/rest/internal/2/issue/{jiraCardKey}/activityfeed?startAt={startAt}&maxResults={queryCount}")
@Cacheable(cacheNames = "jiraCardHistoryByCount",
key = "#jiraCardKey+'-'+#queryCount+'-'+#startAt+'-'+#authorization")
CardHistoryResponseDTO getJiraCardHistoryByCount(URI baseUrl, @PathVariable String jiraCardKey,
@PathVariable int startAt, @PathVariable int queryCount, @RequestHeader String authorization);

}
68 changes: 27 additions & 41 deletions backend/src/main/java/heartbeat/service/board/jira/JiraService.java
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ private List<JiraCardDTO> getRealDoneCards(StoryPointsAndCycleTimeRequest reques
log.info(
"[Jira Service History] Successfully get jira card history, card key: {}, card history items size:{}",
allDoneCard.getKey(), jiraCardHistory.getItems().size());
if (isRealDoneCardByHistory(jiraCardHistory, request, allDoneCard.getKey())) {
if (isRealDoneCardByHistory(jiraCardHistory, request, allDoneCard)) {
futures.add(allDoneCard);
}
else {
Expand Down Expand Up @@ -571,52 +571,38 @@ private boolean useLastAssignee(String filterMethod) {
}

private boolean isRealDoneCardByHistory(CardHistoryResponseDTO jiraCardHistory,
StoryPointsAndCycleTimeRequest request, String card) {
StoryPointsAndCycleTimeRequest request, JiraCard allDoneCard) {
List<String> realDoneStatuses = request.getStatus().stream().map(String::toUpperCase).toList();
long validStartTime = parseLong(request.getStartTime());
long validEndTime = parseLong(request.getEndTime());

List<HistoryDetail> items = jiraCardHistory.getItems();
List<HistoryDetail> items2 = new ArrayList<>();
List<HistoryDetail> items3 = new ArrayList<>();
for (HistoryDetail item : items) {
if (STATUS_FIELD_ID.equals(item.getFieldId())) {
items2.add(item);
}
}
if (items2.isEmpty()) {
log.error("[Jira Service Card RealDoneCards] Failed card history field id equal to status, card:{}", card);
}
for (HistoryDetail item : items2) {
if (realDoneStatuses.contains(item.getTo().getDisplayValue().toUpperCase())) {
items3.add(item);
Optional<Long> moveUndoneLastTime = jiraCardHistory.getItems()
.stream()
.filter(history -> STATUS_FIELD_ID.equals(history.getFieldId()))
.filter(history -> realDoneStatuses.contains(history.getFrom().getDisplayValue().toUpperCase()))
.filter(history -> !realDoneStatuses.contains(history.getTo().getDisplayValue().toUpperCase()))
.map(HistoryDetail::getTimestamp)
.filter(time -> time >= validStartTime && time <= validEndTime)
.max(Long::compareTo);

Optional<HistoryDetail> realDoneHistory = jiraCardHistory.getItems()
.stream()
.filter(history -> STATUS_FIELD_ID.equals(history.getFieldId()))
.filter(history -> !realDoneStatuses.contains(history.getFrom().getDisplayValue().toUpperCase()))
.filter(history -> realDoneStatuses.contains(history.getTo().getDisplayValue().toUpperCase()))
.filter(history -> history.getTimestamp() >= validStartTime && history.getTimestamp() <= validEndTime)
.filter(history -> history.getTimestamp() > moveUndoneLastTime.orElse(0L))
.findFirst();

if (realDoneHistory.isPresent()) {
if (Objects.nonNull(allDoneCard.getFields().getStatus())) {
allDoneCard.getFields().getStatus().setName(realDoneHistory.get().getTo().getDisplayValue());
}
}
if (items3.isEmpty()) {
log.error(
"[Jira Service Card RealDoneCards] Failed to move card history to real done, card:{}, real done status: {}",
card, realDoneStatuses);
return true;
}
else {
log.info(
"[Jira Service Card RealDoneCards] Successfully to get history, card:{}, history{}, real done status: {}",
card, items3, realDoneStatuses);
return false;
}
Optional<Long> lastTimeToRealDone = items3.stream().map(HistoryDetail::getTimestamp).max(Long::compareTo);

long validStartTime = parseLong(request.getStartTime());
long validEndTime = parseLong(request.getEndTime());
return lastTimeToRealDone.filter(lastTime -> {
if (validStartTime <= lastTime && validEndTime >= lastTime) {
return true;
}
else {
log.error(
"[Jira Service Card RealDoneCards] Failed lastTime not in the valid time card:{} last time:{}, start time:{}, end time:{}",
card, new SimpleDateFormat("yyyy 年 MM 月 dd 日 HH 时").format(new Date(lastTime)),
new SimpleDateFormat("yyyy 年 MM 月 dd 日 HH 时").format(new Date(validStartTime)),
new SimpleDateFormat("yyyy 年 MM 月 dd 日 HH 时").format(new Date(validEndTime)));
return false;
}
}).isPresent();
}

private CycleTimeInfoDTO getCycleTime(CardHistoryResponseDTO cardHistoryResponseDTO, Boolean treatFlagCardAsBlock,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ public class JiraBoardConfigDTOFixture {

public static final String ASSIGNEE_NAME = "Zhang San";

public static final String START_TIME = "1672556350000";

public static final String END_TIME = "1676908799000";

public static JiraBoardConfigDTO.JiraBoardConfigDTOBuilder JIRA_BOARD_CONFIG_RESPONSE_BUILDER() {

return JiraBoardConfigDTO.builder()
Expand Down Expand Up @@ -228,6 +232,121 @@ public static CardHistoryResponseDTO.CardHistoryResponseDTOBuilder CARD_HISTORY_
new HistoryDetail(1686908799000L, "status", new Status("Done"), new Status(TESTING), null)));
}

public static AllDoneCardsResponseDTO.AllDoneCardsResponseDTOBuilder ALL_REAL_DONE_CARDS_RESPONSE_FOR_STORY_POINT_BUILDER() {
return AllDoneCardsResponseDTO.builder()
.total("2")
.issues(List.of(
new JiraCard("1",
JiraCardField.builder()
.status(new Status())
.assignee(new Assignee(ASSIGNEE_NAME))
.storyPoints(2)
.build()),
new JiraCard("1",
JiraCardField.builder()
.status(new Status())
.assignee(new Assignee(ASSIGNEE_NAME))
.storyPoints(1)
.build()),
new JiraCard("1",
JiraCardField.builder()
.status(new Status())
.assignee(new Assignee(ASSIGNEE_NAME))
.storyPoints(3)
.build()),
new JiraCard("1",
JiraCardField.builder()
.status(new Status())
.assignee(new Assignee(ASSIGNEE_NAME))
.storyPoints(5)
.build()),
new JiraCard("2",
JiraCardField.builder()
.status(new Status())
.assignee(new Assignee(ASSIGNEE_NAME))
.storyPoints(5)
.build())));
}

public static CardHistoryResponseDTO.CardHistoryResponseDTOBuilder CARD_HISTORY_REAL_DONE_RESPONSE_BUILDER() {
return CardHistoryResponseDTO.builder()
.isLast(true)
.items(List.of(new HistoryDetail(1672556350002L, "status", new Status("In Dev"), new Status("To do"), null),
new HistoryDetail(1672556350003L, "status", new Status(REVIEW), new Status("In Dev"), null),
new HistoryDetail(1672556350004L, "status", new Status(WAITING_FOR_TESTING), new Status(REVIEW),
null),
new HistoryDetail(1672556350005L, "status", new Status(TESTING), new Status(WAITING_FOR_TESTING),
null),
new HistoryDetail(1672556350006L, "status", new Status(BLOCK), new Status(TESTING), null),
new HistoryDetail(1672556350007L, "status", new Status(WAITING_FOR_TESTING), new Status(BLOCK),
null),
new HistoryDetail(1672556350008L, "status", new Status(TESTING), new Status(WAITING_FOR_TESTING),
null),
new HistoryDetail(1672556350010L, "status", new Status("Done"), new Status(TESTING), null)));
}

public static CardHistoryResponseDTO.CardHistoryResponseDTOBuilder CARD_HISTORY_MULTI_REAL_DONE_RESPONSE_BUILDER() {
return CardHistoryResponseDTO.builder()
.isLast(true)
.items(List.of(new HistoryDetail(1672642730000L, "status", new Status("To do"), new Status(BLOCK), null),
new HistoryDetail(1672642730000L, "assignee", new Status("In Dev"), new Status("To do"), null),
new HistoryDetail(1672642730000L, "status", new Status(REVIEW), new Status("In Dev"), null),
new HistoryDetail(1672642730000L, "status", new Status(WAITING_FOR_TESTING), new Status(REVIEW),
null),
new HistoryDetail(1672642740000L, "status", new Status(TESTING), new Status(WAITING_FOR_TESTING),
null),
new HistoryDetail(1672642740001L, "status", new Status(BLOCK), new Status(TESTING), null),
new HistoryDetail(1672642740002L, "status", new Status(FLAG), new Status(BLOCK), null),
new HistoryDetail(1672642750001L, "customfield_10021", new Status("Impediment"), new Status(FLAG),
null),
new HistoryDetail(1672642750002L, "flagged", new Status("Impediment"), new Status("removeFlag"),
null),
new HistoryDetail(1672642750003L, "status", new Status("Done"), new Status(TESTING), null),
new HistoryDetail(1672642750004L, "status", new Status("Done"), new Status(TESTING), null),
new HistoryDetail(1672642750005L, "customfield_10021", new Status(UNKNOWN),
new Status("removeFlag"), null)));
}

public static JiraBoardSetting.JiraBoardSettingBuilder JIRA_BOARD_REAL_DONE_SETTING_BUILD() {
return JiraBoardSetting.builder()
.boardId(BOARD_ID)
.boardColumns(List.of(RequestJiraBoardColumnSetting.builder().name(IN_DEV).value(IN_DEV).build(),
RequestJiraBoardColumnSetting.builder().name(ANALYSE).value(ANALYSE).build(),
RequestJiraBoardColumnSetting.builder()
.name(WAITING_FOR_TESTING)
.value(WAITING_FOR_TESTING)
.build(),
RequestJiraBoardColumnSetting.builder().name(BLOCK).value(BLOCK).build(),
RequestJiraBoardColumnSetting.builder().name(TESTING).value(DONE).build(),
RequestJiraBoardColumnSetting.builder().name(REVIEW).value(REVIEW).build(),
RequestJiraBoardColumnSetting.builder().name(FLAG).value(FLAG).build(),
RequestJiraBoardColumnSetting.builder().name(UNKNOWN).value(UNKNOWN).build()))
.token("token")
.site("site")
.doneColumn(List.of(TESTING, "DONE"))
.treatFlagCardAsBlock(true)
.type("jira")
.projectKey("PLL")
.targetFields(List.of(TargetField.builder().key("testKey1").name("Story Points").flag(true).build(),
TargetField.builder().key("testKey2").name("Sprint").flag(true).build(),
TargetField.builder().key("testKey3").name("Flagged").flag(true).build()));
}

public static StoryPointsAndCycleTimeRequest.StoryPointsAndCycleTimeRequestBuilder STORY_POINTS_FORM_ALL_REAL_DONE_CARD() {
JiraBoardSetting jiraBoardSetting = JIRA_BOARD_REAL_DONE_SETTING_BUILD().build();
return StoryPointsAndCycleTimeRequest.builder()
.token("token")
.type(jiraBoardSetting.getType())
.site(jiraBoardSetting.getSite())
.project(jiraBoardSetting.getProjectKey())
.boardId(jiraBoardSetting.getBoardId())
.status(jiraBoardSetting.getDoneColumn())
.startTime(START_TIME)
.endTime(END_TIME)
.targetFields(jiraBoardSetting.getTargetFields())
.treatFlagCardAsBlock(jiraBoardSetting.getTreatFlagCardAsBlock());
}

public static FieldResponseDTO.FieldResponseDTOBuilder FIELD_RESPONSE_BUILDER() {
IssueField storyPointIssueField = new IssueField("customfield_10016", "Story point estimate");
IssueField sprintIssueField = new IssueField("customfield_10020", "Sprint");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,17 @@
import static heartbeat.service.jira.JiraBoardConfigDTOFixture.ALL_DONE_TWO_PAGES_CARDS_RESPONSE_BUILDER;
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.ALL_REAL_DONE_CARDS_RESPONSE_FOR_STORY_POINT_BUILDER;
import static heartbeat.service.jira.JiraBoardConfigDTOFixture.BOARD_ID;
import static heartbeat.service.jira.JiraBoardConfigDTOFixture.CARD1_HISTORY_FOR_HISTORICAL_ASSIGNEE_FILTER_METHOD;
import static heartbeat.service.jira.JiraBoardConfigDTOFixture.CARD1_HISTORY_FOR_MULTIPLE_STATUSES;
import static heartbeat.service.jira.JiraBoardConfigDTOFixture.CARD2_HISTORY_FOR_HISTORICAL_ASSIGNEE_FILTER_METHOD;
import static heartbeat.service.jira.JiraBoardConfigDTOFixture.CARD2_HISTORY_FOR_MULTIPLE_STATUSES;
import static heartbeat.service.jira.JiraBoardConfigDTOFixture.CARD3_HISTORY_FOR_HISTORICAL_ASSIGNEE_FILTER_METHOD;
import static heartbeat.service.jira.JiraBoardConfigDTOFixture.CARD_HISTORY_DONE_TIME_GREATER_THAN_END_TIME_BUILDER;
import static heartbeat.service.jira.JiraBoardConfigDTOFixture.CARD_HISTORY_MULTI_REAL_DONE_RESPONSE_BUILDER;
import static heartbeat.service.jira.JiraBoardConfigDTOFixture.CARD_HISTORY_MULTI_RESPONSE_BUILDER;
import static heartbeat.service.jira.JiraBoardConfigDTOFixture.CARD_HISTORY_REAL_DONE_RESPONSE_BUILDER;
import static heartbeat.service.jira.JiraBoardConfigDTOFixture.CARD_HISTORY_RESPONSE_BUILDER;
import static heartbeat.service.jira.JiraBoardConfigDTOFixture.CARD_HISTORY_RESPONSE_BUILDER_TO_DONE;
import static heartbeat.service.jira.JiraBoardConfigDTOFixture.CARD_HISTORY_WITH_NO_STATUS_FIELD;
Expand All @@ -73,6 +76,7 @@
import static heartbeat.service.jira.JiraBoardConfigDTOFixture.INCORRECT_JIRA_BOARD_SETTING_BUILD;
import static heartbeat.service.jira.JiraBoardConfigDTOFixture.INCORRECT_JIRA_STORY_POINTS_FORM_ALL_DONE_CARD;
import static heartbeat.service.jira.JiraBoardConfigDTOFixture.JIRA_BOARD_CONFIG_RESPONSE_BUILDER;
import static heartbeat.service.jira.JiraBoardConfigDTOFixture.JIRA_BOARD_REAL_DONE_SETTING_BUILD;
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.JIRA_BOARD_SETTING_WITH_HISTORICAL_ASSIGNEE_FILTER_METHOD;
Expand All @@ -81,6 +85,7 @@
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;
import static heartbeat.service.jira.JiraBoardConfigDTOFixture.STORY_POINTS_FORM_ALL_DONE_CARD_WITH_EMPTY_STATUS;
import static heartbeat.service.jira.JiraBoardConfigDTOFixture.STORY_POINTS_FORM_ALL_REAL_DONE_CARD;
import static heartbeat.service.jira.JiraBoardConfigDTOFixture.STORY_POINTS_REQUEST_WITH_ASSIGNEE_FILTER_METHOD;
import static heartbeat.service.jira.JiraBoardConfigDTOFixture.STORY_POINTS_REQUEST_WITH_MULTIPLE_REAL_DONE_STATUSES;
import static org.assertj.core.api.Assertions.assertThat;
Expand Down Expand Up @@ -600,7 +605,7 @@ void shouldGetCardsWhenCallGetStoryPointsAndCycleTimeWhenBoardTypeIsClassicJira(

CardCollection cardCollection = jiraService.getStoryPointsAndCycleTimeForDoneCards(
storyPointsAndCycleTimeRequest, jiraBoardSetting.getBoardColumns(), List.of("Zhang San"), "");
assertThat(cardCollection.getCardsNumber()).isEqualTo(1);
assertThat(cardCollection.getCardsNumber()).isEqualTo(0);
}

@Test
Expand All @@ -627,7 +632,7 @@ void shouldGetCardsWhenCallGetStoryPointsAndCycleTimeWhenDoneTimeGreaterThanSele

CardCollection cardCollection = jiraService.getStoryPointsAndCycleTimeForDoneCards(
storyPointsAndCycleTimeRequest, jiraBoardSetting.getBoardColumns(), List.of("Zhang San"), "");
assertThat(cardCollection.getCardsNumber()).isEqualTo(1);
assertThat(cardCollection.getCardsNumber()).isEqualTo(0);
}

@Test
Expand Down

0 comments on commit 7831851

Please sign in to comment.