Skip to content

Commit

Permalink
Feat: Chat-210-BE-api-태그-통계 (#26)
Browse files Browse the repository at this point in the history
* Feat: TagStatisticResponse 추가

레포지 작성을 위해 DTO 계층 추가, 태그이름 횟수 퍼센트 반영
정렬은 프론트에서 처리하는 것이 맞다고 판단

* Feat: DiaryTagRepository 작성, DiaryTagStatisticsService 작성
레포지 작성 후 레포지에서 얻은 카운트값을 이용해서 비율계산까지 서비스 계층에서 처리

* Feat: DiaryTagStatisticsController 작성

주간,월간,연간 타입에따라 다르게 처리하도록 컨트롤러 구성

* Refactor: DiaryTagStatistics 리펙토링

응답에 카테고리까지 추가, 길어진 컨트롤러 서비스로 매소드 분리, 서비스계층에서 퍼센트 계산 매서드로 분리

* Fix: DateRange 추가

깃에 실수로..포함 안시켜서 포함시킵니다..!

* Chore: 주석 추가

학습 내용 잊을 까바 주석 추가 ..

* Feat : Response 에 반환 할 필드 추가

피그마에 기간이 표시되므로 통계 시작과 끝 날짜 추가하도록 수정

* Fix : 파일 구조 수정

* Fix : 정소민 제거

* Feat : 리스트 count 많은 순으로 정렬

---------

Co-authored-by: nonaninona <[email protected]>
  • Loading branch information
Mouon and nonaninona authored Jan 30, 2024
1 parent 101254c commit 2a1cc61
Show file tree
Hide file tree
Showing 6 changed files with 182 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.kuit.chatdiary.controller.diary;

import com.kuit.chatdiary.dto.diary.DateRangeDTO;
import com.kuit.chatdiary.dto.diary.TagStatisticResponseDTO;
import com.kuit.chatdiary.service.diary.DiaryTagStatisticsService;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDate;
import java.util.List;

@RestController
@RequestMapping("/diary")
public class DiaryTagStatisticsController {

private final DiaryTagStatisticsService diaryTagStatisticsService;

public DiaryTagStatisticsController(DiaryTagStatisticsService diaryTagStatisticsService) {
this.diaryTagStatisticsService = diaryTagStatisticsService;
}

@GetMapping("/tags")
public ResponseEntity<List<TagStatisticResponseDTO>> getTagStatistics(
@RequestParam("memberId") Long memberId,
@RequestParam("type") String type,
@RequestParam("date") @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate localDate) {
DateRangeDTO dateRange = diaryTagStatisticsService.staticsType(type,localDate);
List<TagStatisticResponseDTO> tagStatistics = diaryTagStatisticsService.calculateTagStatistics(memberId, dateRange.getStartDate()
,dateRange.getEndDate());
return ResponseEntity.ok(tagStatistics);
}
}
16 changes: 16 additions & 0 deletions src/main/java/com/kuit/chatdiary/dto/diary/DateRangeDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.kuit.chatdiary.dto.diary;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;

import java.sql.Date;


@AllArgsConstructor
@Getter
@Setter
public class DateRangeDTO {
private final Date startDate;
private final Date endDate;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.kuit.chatdiary.dto.diary;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.sql.Date;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class TagStatisticResponseDTO {
private String category;
private String tagName;
private Long count;
private double percentage;
private Date startDate;
private Date endDate;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.kuit.chatdiary.repository.diary;

import com.kuit.chatdiary.domain.Diary;
import com.kuit.chatdiary.domain.DiaryTag;
import jakarta.persistence.EntityManager;
import org.springframework.stereotype.Repository;

import java.sql.Date;
import java.util.List;

@Repository
public class DiaryTagRepository {
private final EntityManager em;

public DiaryTagRepository(EntityManager em) {
this.em = em;
}

public List<Object[]> findTagStatisticsByMember(Long memberId, Date startDate, Date endDate) {
String jpql = "SELECT dt.tag.category, dt.tag.tagName, COUNT(dt) FROM diarytag dt " +
"JOIN dt.diary.member m " +
"WHERE m.id = :memberId AND dt.diary.diaryDate BETWEEN :startDate AND :endDate " +
"GROUP BY dt.tag.category, dt.tag.tagName";
return em.createQuery(jpql, Object[].class)
.setParameter("memberId", memberId)
.setParameter("startDate", startDate)
.setParameter("endDate", endDate)
.getResultList();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.kuit.chatdiary.service.diary;

import com.kuit.chatdiary.dto.diary.DateRangeDTO;
import com.kuit.chatdiary.dto.diary.TagStatisticResponseDTO;
import com.kuit.chatdiary.repository.diary.DiaryTagRepository;
import org.springframework.stereotype.Service;

import java.sql.Date;
import java.time.LocalDate;
import java.util.*;

@Service
public class DiaryTagStatisticsService {

private final DiaryTagRepository diaryTagRepository;

public DiaryTagStatisticsService(DiaryTagRepository diaryTagRepository) {
this.diaryTagRepository = diaryTagRepository;
}

public List<TagStatisticResponseDTO> calculateTagStatistics(Long memberId, Date startDate, Date endDate) {
List<Object[]> tagStatistics = diaryTagRepository.findTagStatisticsByMember(memberId, startDate, endDate);
/** 쿼리 3번째 결과를 추출해서 스트림으로 탐색해서 다 더해서 전체 카운트 계산..! */
long totalTags = tagStatistics.stream().mapToLong(e -> (Long) e[2]).sum();
List<TagStatisticResponseDTO> statisticsList = new ArrayList<>();
for (Object[] result : tagStatistics) {
String category = (String) result[0];
String tagName = (String) result[1];
Long count = (Long) result[2];
statisticsList.add(new TagStatisticResponseDTO(category, tagName, count, calculatePercent(count, totalTags), startDate, endDate));
}

statisticsList.sort((o1, o2) -> {
return (int) (o2.getCount() - o1.getCount());
});

return statisticsList;
}

public double calculatePercent(long count,long totalTags){
double percentage = (double) count / totalTags * 100;
return Math.round(percentage*10)/10.0;
}

/** 코드 더 줄이고 싶은데.. */
public DateRangeDTO staticsType(String type, LocalDate localDate){
Calendar calendar = Calendar.getInstance();
calendar.setTime(java.sql.Date.valueOf(localDate));
Date startDate, endDate;
switch (type) {
case "weekly":
/** 주간 -> 해당 주의 시작일과 종료일을 계산 */
calendar.set(Calendar.DAY_OF_WEEK, calendar.getFirstDayOfWeek());
startDate = new Date(calendar.getTimeInMillis());
calendar.add(Calendar.DAY_OF_WEEK, 6);
endDate = new Date(calendar.getTimeInMillis());
break;
case "monthly":
/** 월간 -> 해당 월의 시작일과 종료일을 계산 */
calendar.set(Calendar.DAY_OF_MONTH, 1);
startDate = new Date(calendar.getTimeInMillis());
calendar.add(Calendar.MONTH, 1);
calendar.add(Calendar.DAY_OF_MONTH, -1);
endDate = new Date(calendar.getTimeInMillis());
break;
case "yearly":
/** 연간 -> 해당 연도의 시작일과 종료일을 계산 */
calendar.set(Calendar.DAY_OF_YEAR, 1);
startDate = new Date(calendar.getTimeInMillis());
calendar.add(Calendar.YEAR, 1);
calendar.add(Calendar.DAY_OF_YEAR, -1);
endDate = new Date(calendar.getTimeInMillis());
break;
default:
throw new IllegalArgumentException("Invalid type: " + type);
}
return new DateRangeDTO(startDate, endDate);
}
}
2 changes: 1 addition & 1 deletion src/main/resources/application-local.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
정spring:
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/ChatDiary?allowPublicKeyRetrieval=true&useSSL=false&useUnicode=true&serverTimezone=Asia/Seoul
Expand Down

0 comments on commit 2a1cc61

Please sign in to comment.