-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
43 changed files
with
669 additions
and
64 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 0 additions & 9 deletions
9
src/main/java/wanted/media/content/controller/ContentController.java
This file was deleted.
Oops, something went wrong.
25 changes: 25 additions & 0 deletions
25
src/main/java/wanted/media/content/controller/StatController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package wanted.media.content.controller; | ||
|
||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.ModelAttribute; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import wanted.media.content.domain.dto.StatParam; | ||
import wanted.media.content.domain.dto.StatResponse; | ||
import wanted.media.content.service.StatService; | ||
|
||
@RestController | ||
@RequestMapping("/api") | ||
@RequiredArgsConstructor | ||
public class StatController { | ||
private final StatService statService; | ||
|
||
@GetMapping("/statistics") | ||
public ResponseEntity<StatResponse> statistics(@ModelAttribute StatParam param) { | ||
StatResponse response = StatResponse.from(statService.statistics(param)); | ||
return ResponseEntity.ok().body(response); | ||
} | ||
} |
5 changes: 5 additions & 0 deletions
5
src/main/java/wanted/media/content/domain/CountValueType.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package wanted.media.content.domain; | ||
|
||
public enum CountValueType { | ||
COUNT, LIKE_COUNT, VIEW_COUNT, SHARE_COUNT; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package wanted.media.content.domain; | ||
|
||
public enum StatDateType { | ||
DATE, HOUR; | ||
} |
59 changes: 59 additions & 0 deletions
59
src/main/java/wanted/media/content/domain/dto/StatParam.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package wanted.media.content.domain.dto; | ||
|
||
import java.time.LocalDate; | ||
import java.time.LocalDateTime; | ||
import java.time.LocalTime; | ||
import java.util.Optional; | ||
|
||
import wanted.media.content.domain.CountValueType; | ||
import wanted.media.content.domain.StatDateType; | ||
import wanted.media.exception.BadRequestException; | ||
import wanted.media.exception.ErrorCode; | ||
|
||
/** | ||
* | ||
* @param hashtag 계정, defaultValue = 본인 계정 | ||
* @param type DATE or HOUR, 필수 값 | ||
* @param start 검색 시작 기간, defaultValue = 오늘로 부터 7일 전 | ||
* @param end 검색 끝 기간, defaultValue = 오늘 | ||
* @param value COUNT or VIEW_COUNT, LIKE_COUNT, SHARE_COUNT, defaultValue = count | ||
*/ | ||
public record StatParam( | ||
String hashtag, | ||
StatDateType type, | ||
LocalDateTime start, | ||
LocalDateTime end, | ||
CountValueType value) { | ||
|
||
public StatParam(String hashtag, StatDateType type, LocalDateTime start, LocalDateTime end, CountValueType value) { | ||
// JWT 구현시 default 값 변경 예정 | ||
this.hashtag = (hashtag == null) ? "me" : hashtag; | ||
|
||
// Type(DATE, HOUR)에 맞춰 기본 값 설정 | ||
this.start = switch (type) { | ||
case DATE -> (start == null) ? LocalDateTime.of(LocalDate.now().minusDays(7), LocalTime.MIN) : start; | ||
case HOUR -> (start == null) ? LocalDateTime.now().minusDays(7) : start; | ||
}; | ||
this.end = switch (type) { | ||
case DATE -> (end == null) ? LocalDateTime.of(LocalDate.now(), LocalTime.MAX) : end; | ||
case HOUR -> (end == null) ? LocalDateTime.now() : end; | ||
}; | ||
validateDateRange(start, end); | ||
|
||
// Default 값 설정 | ||
this.value = (value == null) ? CountValueType.COUNT : value; | ||
|
||
// Default 값 설정 | ||
this.type = Optional.ofNullable(type) | ||
.orElseThrow(() -> new BadRequestException(ErrorCode.INVALID_PARAMETER)); | ||
} | ||
|
||
/** | ||
* start 일자가 end 일자보다 앞인지 검증 | ||
*/ | ||
private void validateDateRange(LocalDateTime start, LocalDateTime end) { | ||
if (start.isAfter(end)) { | ||
throw new BadRequestException(ErrorCode.INVALID_PARAMETER); | ||
} | ||
} | ||
} |
8 changes: 8 additions & 0 deletions
8
src/main/java/wanted/media/content/domain/dto/StatResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package wanted.media.content.domain.dto; | ||
|
||
public record StatResponse(Long count) { | ||
|
||
public static StatResponse from(Long count) { | ||
return new StatResponse(count); | ||
} | ||
} |
7 changes: 0 additions & 7 deletions
7
src/main/java/wanted/media/content/repository/ContentRepository.java
This file was deleted.
Oops, something went wrong.
41 changes: 41 additions & 0 deletions
41
src/main/java/wanted/media/content/repository/StatRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package wanted.media.content.repository; | ||
|
||
import com.querydsl.jpa.impl.JPAQueryFactory; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Repository; | ||
import wanted.media.content.domain.dto.StatParam; | ||
|
||
import static com.querydsl.core.types.ExpressionUtils.count; | ||
import static wanted.media.content.domain.QPost.*; | ||
import static wanted.media.user.domain.QUser.user; | ||
|
||
@Repository | ||
@RequiredArgsConstructor | ||
public class StatRepository { | ||
private final JPAQueryFactory queryFactory; | ||
|
||
/** | ||
* ex. | ||
* SELECT SUM(view_count) | ||
* FROM post p | ||
* LEFT JOIN members m ON p.user_id = m.user_id | ||
* where p.created_at between '2024-08-18 00:00:00' and '2024-08-25 23:59:59' | ||
* and m.account = 'user1'; | ||
*/ | ||
public Long statistics(StatParam param) { | ||
var selectQuery = switch (param.value()) { | ||
case COUNT -> queryFactory.select(count(post.id)); | ||
case LIKE_COUNT -> queryFactory.select(post.likeCount.sum()); | ||
case VIEW_COUNT -> queryFactory.select(post.viewCount.sum()); | ||
case SHARE_COUNT -> queryFactory.select(post.shareCount.sum()); | ||
}; | ||
|
||
return selectQuery.from(post) | ||
.leftJoin(user).on(post.user.userId.eq(user.userId)) | ||
.where( | ||
post.createdAt.between(param.start(), param.end()), | ||
post.user.account.eq(param.hashtag()) | ||
) | ||
.fetchFirst(); | ||
} | ||
} |
7 changes: 0 additions & 7 deletions
7
src/main/java/wanted/media/content/service/ContentService.java
This file was deleted.
Oops, something went wrong.
19 changes: 19 additions & 0 deletions
19
src/main/java/wanted/media/content/service/StatService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package wanted.media.content.service; | ||
|
||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import wanted.media.content.domain.dto.StatParam; | ||
import wanted.media.content.repository.StatRepository; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
@Transactional(readOnly = true) | ||
public class StatService { | ||
private final StatRepository statRepository; | ||
|
||
public Long statistics(StatParam param) { | ||
return statRepository.statistics(param); | ||
} | ||
} |
8 changes: 8 additions & 0 deletions
8
src/main/java/wanted/media/exception/BadRequestException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package wanted.media.exception; | ||
|
||
public class BadRequestException extends BaseException { | ||
|
||
public BadRequestException(ErrorCode errorCode) { | ||
super(errorCode); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package wanted.media.exception; | ||
|
||
import lombok.Getter; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
@Getter | ||
@RequiredArgsConstructor | ||
public class BaseException extends RuntimeException { | ||
private final ErrorCode errorCode; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,4 @@ | ||
package wanted.media.exception; | ||
|
||
import lombok.Getter; | ||
import lombok.RequiredArgsConstructor; | ||
@Getter | ||
@RequiredArgsConstructor | ||
public class ErrorResponse { | ||
|
||
private final int statusCode; | ||
private final String message; | ||
public record ErrorResponse(int statusCode, String message) { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,10 @@ | ||
package wanted.media.exception; | ||
|
||
import lombok.Getter; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
@Getter | ||
@RequiredArgsConstructor | ||
public class NotFoundException extends RuntimeException { | ||
public NotFoundException(String message) { | ||
super(message); | ||
} | ||
private final ErrorCode errorCode; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
src/main/java/wanted/media/global/config/QueryDslConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package wanted.media.global.config; | ||
|
||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
|
||
import com.querydsl.jpa.impl.JPAQueryFactory; | ||
|
||
import jakarta.persistence.EntityManager; | ||
|
||
@Configuration | ||
public class QueryDslConfig { | ||
|
||
@Bean | ||
public JPAQueryFactory jpaQueryFactory(EntityManager em) { | ||
return new JPAQueryFactory(em); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package wanted.media.global.config; | ||
|
||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.format.FormatterRegistry; | ||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | ||
|
||
import wanted.media.global.converter.StringToLocalDateTimeConverter; | ||
|
||
@Configuration | ||
public class WebConfig implements WebMvcConfigurer { | ||
|
||
@Override | ||
public void addFormatters(FormatterRegistry registry) { | ||
registry.addConverter(new StringToLocalDateTimeConverter()); | ||
} | ||
} |
Oops, something went wrong.