diff --git a/api/src/main/java/com/nexters/gaetteok/common/filter/RequestLoggingFilter.java b/api/src/main/java/com/nexters/gaetteok/common/filter/RequestLoggingFilter.java new file mode 100644 index 0000000..b4ced20 --- /dev/null +++ b/api/src/main/java/com/nexters/gaetteok/common/filter/RequestLoggingFilter.java @@ -0,0 +1,24 @@ +package com.nexters.gaetteok.common.filter; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + +import java.io.IOException; + +@Slf4j +@Component +public class RequestLoggingFilter extends OncePerRequestFilter { + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + log.info("[{}] {}, token: {}, parameterCount: {}", request.getMethod(), request.getRequestURI(), request.getHeader("Authorization"), request.getParameterMap().values().size()); + request.getParameterMap().forEach((key, value) -> log.info("Request Parameter: {}={}", key, value)); + filterChain.doFilter(request, response); + } + +} diff --git a/api/src/main/java/com/nexters/gaetteok/user/constant/MainScreenImage.java b/api/src/main/java/com/nexters/gaetteok/user/constant/MainScreenImage.java new file mode 100644 index 0000000..93bb88d --- /dev/null +++ b/api/src/main/java/com/nexters/gaetteok/user/constant/MainScreenImage.java @@ -0,0 +1,22 @@ +package com.nexters.gaetteok.user.constant; + +import lombok.Getter; + +@Getter +public enum MainScreenImage { + + BEFORE_WALKING("https://kr.object.ncloudstorage.com/gaetteok-image/home/home_beforewalking.png"), + AFTER_WALKING("https://kr.object.ncloudstorage.com/gaetteok-image/home/home_afterwalking.png"), + ; + + private final String imageUrl; + + MainScreenImage(String imageUrl) { + this.imageUrl = imageUrl; + } + + public static String getImageUrl(boolean walkDone) { + return walkDone ? AFTER_WALKING.imageUrl : BEFORE_WALKING.imageUrl; + } + +} diff --git a/api/src/main/java/com/nexters/gaetteok/user/presentation/UserController.java b/api/src/main/java/com/nexters/gaetteok/user/presentation/UserController.java index dd6e1ee..cfb6bf6 100644 --- a/api/src/main/java/com/nexters/gaetteok/user/presentation/UserController.java +++ b/api/src/main/java/com/nexters/gaetteok/user/presentation/UserController.java @@ -3,10 +3,13 @@ import com.nexters.gaetteok.domain.User; import com.nexters.gaetteok.jwt.UserInfo; import com.nexters.gaetteok.user.application.UserApplication; +import com.nexters.gaetteok.user.constant.MainScreenImage; import com.nexters.gaetteok.user.presentation.request.ReportUserRequest; import com.nexters.gaetteok.user.presentation.response.GetUserResponse; +import com.nexters.gaetteok.user.presentation.response.GetUserStatusResponse; import com.nexters.gaetteok.user.presentation.response.ReportUserResponse; import com.nexters.gaetteok.user.presentation.response.UpdateUserLocationResponse; +import com.nexters.gaetteok.walklog.application.WalkLogApplication; import com.nexters.gaetteok.weather.enums.City; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -26,11 +29,14 @@ public class UserController implements UserSpecification { private final UserApplication userApplication; + private final WalkLogApplication walkLogApplication; private final AtomicInteger atomicInteger = new AtomicInteger(1); @GetMapping(value = "", produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity getUser(UserInfo userInfo) { - return ResponseEntity.ok(GetUserResponse.of(userApplication.getUser(userInfo.getUserId()))); + public ResponseEntity getUser(UserInfo userInfo) { + User user = userApplication.getUser(userInfo.getUserId()); + boolean todayWalkLogExists = walkLogApplication.isTodayWalkLogExists(userInfo.getUserId()); + return ResponseEntity.ok(GetUserStatusResponse.of(user, todayWalkLogExists, MainScreenImage.getImageUrl(todayWalkLogExists))); } @PatchMapping(value = "/nickname", produces = MediaType.APPLICATION_JSON_VALUE) diff --git a/api/src/main/java/com/nexters/gaetteok/user/presentation/UserSpecification.java b/api/src/main/java/com/nexters/gaetteok/user/presentation/UserSpecification.java index 82d393f..0d4488e 100644 --- a/api/src/main/java/com/nexters/gaetteok/user/presentation/UserSpecification.java +++ b/api/src/main/java/com/nexters/gaetteok/user/presentation/UserSpecification.java @@ -3,6 +3,7 @@ import com.nexters.gaetteok.jwt.UserInfo; import com.nexters.gaetteok.user.presentation.request.ReportUserRequest; import com.nexters.gaetteok.user.presentation.response.GetUserResponse; +import com.nexters.gaetteok.user.presentation.response.GetUserStatusResponse; import com.nexters.gaetteok.user.presentation.response.ReportUserResponse; import com.nexters.gaetteok.user.presentation.response.UpdateUserLocationResponse; import com.nexters.gaetteok.weather.enums.City; @@ -28,10 +29,10 @@ public interface UserSpecification { description = "유저 조회 성공", content = @Content( mediaType = MediaType.APPLICATION_JSON_VALUE, - schema = @Schema(implementation = GetUserResponse.class) + schema = @Schema(implementation = GetUserStatusResponse.class) ) ) - ResponseEntity getUser( + ResponseEntity getUser( @Parameter(hidden = true) UserInfo userInfo ); diff --git a/api/src/main/java/com/nexters/gaetteok/user/presentation/response/GetUserStatusResponse.java b/api/src/main/java/com/nexters/gaetteok/user/presentation/response/GetUserStatusResponse.java new file mode 100644 index 0000000..358287f --- /dev/null +++ b/api/src/main/java/com/nexters/gaetteok/user/presentation/response/GetUserStatusResponse.java @@ -0,0 +1,57 @@ +package com.nexters.gaetteok.user.presentation.response; + +import com.nexters.gaetteok.domain.User; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Getter; + +import java.time.LocalDateTime; + +@Getter +public class GetUserStatusResponse { + + @Schema(description = "유저 ID", example = "1") + private final long id; + + @Schema(description = "유저 닉네임", example = "뽀삐") + private final String nickname; + + @Schema(description = "유저 프로필 이미지 URL", example = "https://profile.com/1") + private final String profileImageUrl; + + @Schema(description = "유저 코드", example = "1a2b3c") + private final String code; + + @Schema(description = "산책 완료 여부", example = "true") + private final boolean walkDone; + + @Schema(description = "메인 화면 이미지 URL", example = "https://main.com/wait.jpg") + private final String mainScreenImageUrl; + + @Schema(description = "유저 생성일", example = "2021-08-01T00:00:00") + private final LocalDateTime createdAt; + + @Builder + public GetUserStatusResponse(long id, String nickname, String profileImageUrl, String code, boolean walkDone, String mainScreenImageUrl, LocalDateTime createdAt) { + this.id = id; + this.nickname = nickname; + this.profileImageUrl = profileImageUrl; + this.code = code; + this.walkDone = walkDone; + this.mainScreenImageUrl = mainScreenImageUrl; + this.createdAt = createdAt; + } + + public static GetUserStatusResponse of(User user, boolean walkDone, String mainScreenImageUrl) { + return GetUserStatusResponse.builder() + .id(user.getId()) + .nickname(user.getNickname()) + .profileImageUrl(user.getProfileUrl()) + .code(user.getCode()) + .walkDone(walkDone) + .mainScreenImageUrl(mainScreenImageUrl) + .createdAt(user.getCreatedAt()) + .build(); + } + +} diff --git a/api/src/main/java/com/nexters/gaetteok/walklog/application/WalkLogApplication.java b/api/src/main/java/com/nexters/gaetteok/walklog/application/WalkLogApplication.java index 5532c0d..19eb8d7 100644 --- a/api/src/main/java/com/nexters/gaetteok/walklog/application/WalkLogApplication.java +++ b/api/src/main/java/com/nexters/gaetteok/walklog/application/WalkLogApplication.java @@ -17,19 +17,18 @@ import com.nexters.gaetteok.walklog.mapper.WalkLogMapper; import com.nexters.gaetteok.walklog.presentation.request.CreateWalkLogRequest; import com.nexters.gaetteok.walklog.presentation.request.PatchWalkLogRequest; -import java.io.IOException; -import java.util.Collections; -import java.util.Comparator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; +import java.io.IOException; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.*; +import java.util.stream.Collectors; + @Slf4j @Service @RequiredArgsConstructor @@ -91,6 +90,8 @@ public WalkLog create(long userId, CreateWalkLogRequest request, MultipartFile p .content(request.getContent()) .walkTime(request.getWalkTime()) .userId(userId) + .createdAt(LocalDateTime.now()) + .updatedAt(LocalDateTime.now()) .build()); return WalkLogMapper.toDomain(walkLog, me); } @@ -226,10 +227,14 @@ public WalkLog update(long id, long userId, PatchWalkLogRequest request, Multipa .content(request.getContent() != null ? request.getContent() : walkLog.getContent()) .userId(userId) .walkTime(walkLog.getWalkTime()) + .updatedAt(LocalDateTime.now()) .build() ); return WalkLogMapper.toDomain(walkLog, me); } + public boolean isTodayWalkLogExists(long userId) { + return walkLogRepository.isTodayWalkLogExists(userId, LocalDate.now()); + } } diff --git a/api/src/main/resources/application.yml b/api/src/main/resources/application.yml index 6bd2494..cc9dce5 100644 --- a/api/src/main/resources/application.yml +++ b/api/src/main/resources/application.yml @@ -10,6 +10,10 @@ spring: username: ${DB_USERNAME} password: ${DB_PASSWORD} driver-class-name: com.mysql.cj.jdbc.Driver + servlet: + multipart: + max-file-size: 20MB + max-request-size: 20MB ncloud: accessKey: ${NCP_ACCESS_KEY} diff --git a/domain/walklog/src/main/java/com/nexters/gaetteok/domain/WalkTime.java b/domain/walklog/src/main/java/com/nexters/gaetteok/domain/WalkTime.java index f0cd1d7..eb26d7b 100644 --- a/domain/walklog/src/main/java/com/nexters/gaetteok/domain/WalkTime.java +++ b/domain/walklog/src/main/java/com/nexters/gaetteok/domain/WalkTime.java @@ -11,6 +11,7 @@ public enum WalkTime { + NONE("없음"), // 없음 WITHIN_20_MINUTES("20분 내외"), // 20분 내외 BETWEEN_20_AND_40_MINUTES("20분~40분"), // 20분~40분 BETWEEN_40_MINUTES_AND_1_HOUR("40분~1시간"), // 40분~1시간 diff --git a/infra/src/main/java/com/nexters/gaetteok/persistence/entity/WalkLogEntity.java b/infra/src/main/java/com/nexters/gaetteok/persistence/entity/WalkLogEntity.java index 5cb5381..f57719e 100644 --- a/infra/src/main/java/com/nexters/gaetteok/persistence/entity/WalkLogEntity.java +++ b/infra/src/main/java/com/nexters/gaetteok/persistence/entity/WalkLogEntity.java @@ -7,6 +7,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; import java.time.LocalDateTime; @@ -41,8 +42,11 @@ public class WalkLogEntity { @Column(updatable = false) private LocalDateTime createdAt; + @LastModifiedDate + private LocalDateTime updatedAt; + @Builder - public WalkLogEntity(long id, String photoUrl, String title, String content, WalkTime walkTime, long userId, LocalDateTime createdAt) { + public WalkLogEntity(long id, String photoUrl, String title, String content, WalkTime walkTime, long userId, LocalDateTime createdAt, LocalDateTime updatedAt) { this.id = id; this.photoUrl = photoUrl; this.title = title; @@ -50,6 +54,7 @@ public WalkLogEntity(long id, String photoUrl, String title, String content, Wal this.walkTime = walkTime; this.userId = userId; this.createdAt = createdAt; + this.updatedAt = updatedAt; } } diff --git a/infra/src/main/java/com/nexters/gaetteok/persistence/repository/CustomWalkLogRepository.java b/infra/src/main/java/com/nexters/gaetteok/persistence/repository/CustomWalkLogRepository.java index ef5e350..7f69eff 100644 --- a/infra/src/main/java/com/nexters/gaetteok/persistence/repository/CustomWalkLogRepository.java +++ b/infra/src/main/java/com/nexters/gaetteok/persistence/repository/CustomWalkLogRepository.java @@ -3,6 +3,7 @@ import com.nexters.gaetteok.domain.WalkLog; import com.nexters.gaetteok.persistence.entity.WalkLogEntity; +import java.time.LocalDate; import java.util.List; public interface CustomWalkLogRepository { @@ -17,4 +18,6 @@ public interface CustomWalkLogRepository { WalkLogEntity getMaxIdLessThan(long walkLogId); + boolean isTodayWalkLogExists(long walkLogId, LocalDate date); + } diff --git a/infra/src/main/java/com/nexters/gaetteok/persistence/repository/CustomWalkLogRepositoryImpl.java b/infra/src/main/java/com/nexters/gaetteok/persistence/repository/CustomWalkLogRepositoryImpl.java index 689794b..4edcc93 100644 --- a/infra/src/main/java/com/nexters/gaetteok/persistence/repository/CustomWalkLogRepositoryImpl.java +++ b/infra/src/main/java/com/nexters/gaetteok/persistence/repository/CustomWalkLogRepositoryImpl.java @@ -2,17 +2,20 @@ import com.nexters.gaetteok.domain.WalkLog; import com.nexters.gaetteok.persistence.entity.WalkLogEntity; +import com.querydsl.core.types.Ops; import com.querydsl.core.types.Projections; import com.querydsl.jpa.impl.JPAQueryFactory; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Repository; +import java.time.LocalDate; import java.time.LocalDateTime; import java.util.List; import static com.nexters.gaetteok.persistence.entity.QFriendEntity.friendEntity; import static com.nexters.gaetteok.persistence.entity.QUserEntity.userEntity; import static com.nexters.gaetteok.persistence.entity.QWalkLogEntity.walkLogEntity; +import static com.querydsl.core.types.dsl.Expressions.dateTimeOperation; @Repository @RequiredArgsConstructor @@ -108,4 +111,20 @@ public WalkLogEntity getMaxIdLessThan(long walkLogId) { .orderBy(walkLogEntity.id.desc()) .fetchFirst(); } + + @Override + public boolean isTodayWalkLogExists(long userId, LocalDate date) { + Long id = jpaQueryFactory + .select(walkLogEntity.id) + .from(walkLogEntity) + .where( + walkLogEntity.userId.eq(userId), + dateTimeOperation(LocalDate.class, Ops.DateTimeOps.DATE, walkLogEntity.createdAt).eq(date) + ) + .fetchFirst(); + + return id != null; + } + + }