Skip to content

Commit

Permalink
Update
Browse files Browse the repository at this point in the history
  • Loading branch information
haiphucnguyen committed Dec 2, 2024
1 parent 91a274b commit eed456d
Show file tree
Hide file tree
Showing 11 changed files with 122 additions and 113 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
import jakarta.persistence.Column;
import jakarta.persistence.Convert;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
Expand Down Expand Up @@ -52,8 +50,8 @@ public class TeamRequest extends AbstractAuditingEntity<Long> {

private String requestDescription;

@Column(nullable = false, length = 50)
@Enumerated(EnumType.STRING)
@Column(nullable = false)
@Convert(converter = TeamRequestPriorityConverter.class)
private TeamRequestPriority priority;

@Column(name = "is_deleted", nullable = false)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,28 @@
package io.flexwork.modules.teams.domain;

public enum TeamRequestPriority {
Critical,
High,
Medium,
Low,
Trivial
Critical(0),
High(1),
Medium(2),
Low(3),
Trivial(4);

private final int code;

TeamRequestPriority(int code) {
this.code = code;
}

public int getCode() {
return code;
}

public static TeamRequestPriority fromCode(int code) {
for (TeamRequestPriority priority : TeamRequestPriority.values()) {
if (priority.code == code) {
return priority;
}
}
throw new IllegalArgumentException("Invalid code for TeamRequestPriority: " + code);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package io.flexwork.modules.teams.domain;

import jakarta.persistence.AttributeConverter;
import jakarta.persistence.Converter;

@Converter(autoApply = true)
public class TeamRequestPriorityConverter
implements AttributeConverter<TeamRequestPriority, Integer> {

@Override
public Integer convertToDatabaseColumn(TeamRequestPriority priority) {
return (priority != null) ? priority.getCode() : null;
}

@Override
public TeamRequestPriority convertToEntityAttribute(Integer code) {
return (code != null) ? TeamRequestPriority.fromCode(code) : null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,29 +84,8 @@ public interface TeamRequestRepository
@Query(
"SELECT r FROM TeamRequest r "
+ "WHERE r.team.id = :teamId AND r.isCompleted = false AND r.isDeleted = false "
+ "AND r.assignUser IS NULL "
+ "ORDER BY CASE r.priority "
+ " WHEN io.flexwork.modules.teams.domain.TeamRequestPriority.Trivial THEN 1 "
+ " WHEN io.flexwork.modules.teams.domain.TeamRequestPriority.Low THEN 2 "
+ " WHEN io.flexwork.modules.teams.domain.TeamRequestPriority.Medium THEN 3 "
+ " WHEN io.flexwork.modules.teams.domain.TeamRequestPriority.High THEN 4 "
+ " WHEN io.flexwork.modules.teams.domain.TeamRequestPriority.Critical THEN 5 "
+ "END ASC")
Page<TeamRequest> findUnassignedTicketsByTeamIdAsc(
@Param("teamId") Long teamId, Pageable pageable);

@Query(
"SELECT r FROM TeamRequest r "
+ "WHERE r.team.id = :teamId AND r.isCompleted = false AND r.isDeleted = false "
+ "AND r.assignUser IS NULL "
+ "ORDER BY CASE r.priority "
+ " WHEN io.flexwork.modules.teams.domain.TeamRequestPriority.Trivial THEN 1 "
+ " WHEN io.flexwork.modules.teams.domain.TeamRequestPriority.Low THEN 2 "
+ " WHEN io.flexwork.modules.teams.domain.TeamRequestPriority.Medium THEN 3 "
+ " WHEN io.flexwork.modules.teams.domain.TeamRequestPriority.High THEN 4 "
+ " WHEN io.flexwork.modules.teams.domain.TeamRequestPriority.Critical THEN 5 "
+ "END DESC")
Page<TeamRequest> findUnassignedTicketsByTeamIdDesc(
+ "AND r.assignUser IS NULL")
Page<TeamRequest> findUnassignedTicketsByTeamId(
@Param("teamId") Long teamId, Pageable pageable);

// Query to count tickets by priority for a specific team
Expand Down Expand Up @@ -138,9 +117,10 @@ List<PriorityDistributionDTO> findTicketPriorityDistributionByTeamId(
+ "AND h.slaDueDate < CURRENT_TIMESTAMP "
+ "AND h.status <> :status "
+ "AND r.team.id = :teamId")
List<TeamRequest> findOverdueTicketsByTeamId(
Page<TeamRequest> findOverdueTicketsByTeamId(
@Param("teamId") Long teamId,
@Param("status") WorkflowTransitionHistoryStatus completedStatus);
@Param("status") WorkflowTransitionHistoryStatus completedStatus,
Pageable pageable);

@Query(
"SELECT COUNT(r.id) "
Expand All @@ -157,13 +137,24 @@ Long countOverdueTicketsByTeamId(
@Param("status") WorkflowTransitionHistoryStatus completedStatus);

@Query(
"SELECT new io.flexwork.modules.teams.service.dto.TicketActionCountByDateDTO(CAST(r.createdAt AS date), COUNT(r.id)) "
"SELECT new io.flexwork.modules.teams.service.dto.TicketActionCountByDateDTO("
+ "CAST(r.createdAt AS date), "
+ "COUNT(r.id), "
+ "COALESCE(closedTicketCounts.closedCount, 0)) "
+ "FROM TeamRequest r "
+ "LEFT JOIN ("
+ " SELECT CAST(c.actualCompletionDate AS date) AS completionDate, COUNT(c.id) AS closedCount "
+ " FROM TeamRequest c "
+ " WHERE c.isDeleted = false "
+ " AND c.team.id = :teamId "
+ " AND c.actualCompletionDate IS NOT NULL "
+ " GROUP BY CAST(c.actualCompletionDate AS date)"
+ ") closedTicketCounts ON CAST(r.createdAt AS date) = closedTicketCounts.completionDate "
+ "WHERE r.isDeleted = false "
+ "AND r.team.id = :teamId "
+ "AND r.createdAt >= :startDate "
+ "GROUP BY CAST(r.createdAt AS date) "
+ "GROUP BY CAST(r.createdAt AS date), closedTicketCounts.closedCount "
+ "ORDER BY CAST(r.createdAt AS date) ASC")
List<TicketActionCountByDateDTO> findTicketCreationCounts(
List<TicketActionCountByDateDTO> findTicketActionByDaySeries(
@Param("teamId") Long teamId, @Param("startDate") Instant startDate);
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@
import jakarta.persistence.EntityNotFoundException;
import jakarta.persistence.PersistenceContext;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import org.jclouds.rest.ResourceNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
Expand Down Expand Up @@ -162,6 +162,9 @@ public TeamRequestDTO updateTeamRequest(TeamRequestDTO teamRequestDTO) {
workflowStateRepository.isFinalState(
teamRequestDTO.getWorkflowId(), teamRequestDTO.getCurrentStateId());
existingTeamRequest.setIsCompleted(finalState);
if (teamRequestDTO.getActualCompletionDate() == null) {
existingTeamRequest.setActualCompletionDate(LocalDate.now());
}
}

TeamRequestDTO savedTeamRequest =
Expand Down Expand Up @@ -245,15 +248,9 @@ public List<TicketDistributionDTO> getTicketDistribution(Long teamId) {
}

// Fetch unassigned tickets
public Page<TeamRequestDTO> getUnassignedTickets(
Long teamId, String sortDirection, Pageable pageable) {
if ("desc".equalsIgnoreCase(sortDirection)) {
return teamRequestRepository
.findUnassignedTicketsByTeamIdDesc(teamId, pageable)
.map(teamRequestMapper::toDto);
}
public Page<TeamRequestDTO> getUnassignedTickets(Long teamId, Pageable pageable) {
return teamRequestRepository
.findUnassignedTicketsByTeamIdAsc(teamId, pageable)
.findUnassignedTicketsByTeamId(teamId, pageable)
.map(teamRequestMapper::toDto);
}

Expand Down Expand Up @@ -297,43 +294,40 @@ private ZonedDateTime calculateEarliestSlaDueDate(Long workflowId, Long sourceSt
return ZonedDateTime.now().plusMinutes(earliestTransition.getSlaDuration());
}

public List<TeamRequest> getOverdueTickets(Long teamId) {
return teamRequestRepository.findOverdueTicketsByTeamId(teamId, Completed);
public Page<TeamRequestDTO> getOverdueTickets(Long teamId, Pageable pageable) {
return teamRequestRepository
.findOverdueTicketsByTeamId(teamId, Completed, pageable)
.map(teamRequestMapper::toDto);
}

public Long countOverdueTickets(Long teamId) {
return teamRequestRepository.countOverdueTicketsByTeamId(teamId, Completed);
}

public List<TicketActionCountByDateDTO> getTicketCreationTimeseries(Long teamId, int days) {
// Default to 7 days if no input is provided
if (days <= 0) {
days = 7;
days = 7; // Default to 7 days
}

// Calculate the start date based on the number of days
LocalDate startDate = LocalDate.now().minusDays(days - 1);
List<TicketActionCountByDateDTO> trends =
teamRequestRepository.findTicketActionByDaySeries(
teamId, startDate.atStartOfDay().toInstant(ZoneOffset.UTC));

// Fill missing dates with zero counts
Map<LocalDate, TicketActionCountByDateDTO> trendMap = new HashMap<>();
for (TicketActionCountByDateDTO trend : trends) {
trendMap.put(trend.getDate(), trend);
}

// Fetch data from the repository
List<TicketActionCountByDateDTO> results =
teamRequestRepository.findTicketCreationCounts(
teamId, startDate.atStartOfDay(ZoneId.of("UTC")).toInstant());

// Fill gaps for dates with no tickets
Map<LocalDate, Long> dateToCountMap =
results.stream()
.collect(
Collectors.toMap(
TicketActionCountByDateDTO::getDate,
TicketActionCountByDateDTO::getTicketCount));

List<TicketActionCountByDateDTO> completeResults = new ArrayList<>();
List<TicketActionCountByDateDTO> ticketByDaySeries = new ArrayList<>();
for (int i = 0; i < days; i++) {
LocalDate date = startDate.plusDays(i);
Long count = dateToCountMap.getOrDefault(date, 0L);
completeResults.add(new TicketActionCountByDateDTO(date, count));
TicketActionCountByDateDTO trend =
trendMap.getOrDefault(date, new TicketActionCountByDateDTO(date, 0L, 0L));
ticketByDaySeries.add(trend);
}

return completeResults;
return ticketByDaySeries;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@
@AllArgsConstructor
public class TicketActionCountByDateDTO {
private LocalDate date;
private Long ticketCount;
private Long createdCount;
private Long closedCount;

public TicketActionCountByDateDTO(Date creationInstant, Long ticketCount) {
public TicketActionCountByDateDTO(Date creationInstant, Long createdCount, Long closedCount) {
// Convert Instant to LocalDate
this.date = creationInstant.toLocalDate();
this.ticketCount = ticketCount;
this.createdCount = createdCount;
this.closedCount = closedCount;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.flexwork.modules.teams.web.rest;

import io.flexwork.modules.teams.domain.TeamRequest;
import io.flexwork.modules.teams.service.TeamRequestService;
import io.flexwork.modules.teams.service.WorkflowTransitionHistoryService;
import io.flexwork.modules.teams.service.dto.PriorityDistributionDTO;
Expand All @@ -13,7 +12,6 @@
import jakarta.validation.Valid;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
Expand Down Expand Up @@ -99,15 +97,8 @@ public List<TicketDistributionDTO> getTicketDistribution(@PathVariable Long team

// Endpoint to get unassigned tickets for a specific team
@GetMapping("/{teamId}/unassigned-tickets")
public Page<TeamRequestDTO> getUnassignedTickets(
@PathVariable Long teamId,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size,
@RequestParam(defaultValue = "priority") String sortBy,
@RequestParam(defaultValue = "asc") String sortDirection) {

Pageable pageable = PageRequest.of(page, size);
return teamRequestService.getUnassignedTickets(teamId, sortDirection, pageable);
public Page<TeamRequestDTO> getUnassignedTickets(@PathVariable Long teamId, Pageable pageable) {
return teamRequestService.getUnassignedTickets(teamId, pageable);
}

// Endpoint to get priority distribution for a specific team
Expand Down Expand Up @@ -136,12 +127,12 @@ public TicketStatisticsDTO getTicketStatisticsByTeamId(@PathVariable Long teamId
return teamRequestService.getTicketStatisticsByTeamId(teamId);
}

@GetMapping("/{teamId}/overdue")
public List<TeamRequest> getOverdueTickets(@PathVariable Long teamId) {
return teamRequestService.getOverdueTickets(teamId);
@GetMapping("/{teamId}/overdue-tickets")
public Page<TeamRequestDTO> getOverdueTickets(@PathVariable Long teamId, Pageable pageable) {
return teamRequestService.getOverdueTickets(teamId, pageable);
}

@GetMapping("/{teamId}/overdue/count")
@GetMapping("/{teamId}/overdue-tickets/count")
public Long countOverdueTickets(@PathVariable Long teamId) {
return teamRequestService.countOverdueTickets(teamId);
}
Expand Down
Loading

0 comments on commit eed456d

Please sign in to comment.