diff --git a/src/main/java/com/cmc/mercury/domain/memo/service/MemoService.java b/src/main/java/com/cmc/mercury/domain/memo/service/MemoService.java index f511508..0430b66 100644 --- a/src/main/java/com/cmc/mercury/domain/memo/service/MemoService.java +++ b/src/main/java/com/cmc/mercury/domain/memo/service/MemoService.java @@ -5,6 +5,9 @@ import com.cmc.mercury.domain.memo.dto.MemoUpdateRequest; import com.cmc.mercury.domain.memo.entity.Memo; import com.cmc.mercury.domain.memo.repository.MemoRepository; +import com.cmc.mercury.domain.mypage.entity.HabitHistory; +import com.cmc.mercury.domain.mypage.repository.HabitHistoryRepository; +import com.cmc.mercury.domain.mypage.service.MyPageService; import com.cmc.mercury.domain.record.entity.Record; import com.cmc.mercury.domain.record.entity.RecordDetail; import com.cmc.mercury.domain.record.repository.RecordRepository; @@ -17,6 +20,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDate; import java.time.LocalDateTime; @Service @@ -30,7 +34,8 @@ public class MemoService { private final MemoRepository memoRepository; private final RecordRepository recordRepository; - private final UserService userService; + private final HabitHistoryRepository habitHistoryRepository; + private final MyPageService myPageService; @Transactional public MemoResponse createMemo(User user, Long recordId, MemoCreateRequest request) { @@ -67,6 +72,12 @@ public MemoResponse createMemo(User user, Long recordId, MemoCreateRequest reque // 사용자 경험치 업데이트 user.updateExp(user.getExp() + acquiredExp); + // 날짜별 습관쌓기 기록 + LocalDate date = LocalDate.now(); + HabitHistory history = myPageService.saveHabitHistoryIfNotExists(user.getId(), date, acquiredExp); + history.updateHasRecord(); + habitHistoryRepository.save(history); + return MemoResponse.from(savedMemo, recordId); } diff --git a/src/main/java/com/cmc/mercury/domain/mypage/controller/MyPageController.java b/src/main/java/com/cmc/mercury/domain/mypage/controller/MyPageController.java new file mode 100644 index 0000000..3666a35 --- /dev/null +++ b/src/main/java/com/cmc/mercury/domain/mypage/controller/MyPageController.java @@ -0,0 +1,41 @@ +package com.cmc.mercury.domain.mypage.controller; + +import com.cmc.mercury.domain.mypage.dto.HabitDetailResponse; +import com.cmc.mercury.domain.mypage.dto.MyPageResponse; +import com.cmc.mercury.domain.mypage.service.MyPageService; +import com.cmc.mercury.domain.user.entity.User; +import com.cmc.mercury.global.oauth.annotation.AuthUser; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.time.LocalDate; + +@RestController +@RequestMapping("/api/my-page") +@RequiredArgsConstructor +@Tag(name = "MyPageController", description = "마이페이지 관련 API") +public class MyPageController { + + private final MyPageService myPageService; + + @GetMapping("") + @Operation(summary = "마이페이지 조회", description = "마이페이지 메인 화면을 조회합니다.") + public ResponseEntity getMyPage(@AuthUser User user) { + return ResponseEntity.ok(myPageService.getMyPage(user)); + } + + @GetMapping("/history") + @Operation(summary = "날짜별 습관쌓기 조회", description = "쿼리파라미터의 date 값은 YYYY-MM-DD 형식입니다.") + public ResponseEntity getHabitDetail( + @AuthUser User user, + @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date) { + return ResponseEntity.ok(myPageService.getHabitDetail(user, date)); + } +} diff --git a/src/main/java/com/cmc/mercury/domain/mypage/dto/HabitDetailResponse.java b/src/main/java/com/cmc/mercury/domain/mypage/dto/HabitDetailResponse.java new file mode 100644 index 0000000..7684956 --- /dev/null +++ b/src/main/java/com/cmc/mercury/domain/mypage/dto/HabitDetailResponse.java @@ -0,0 +1,23 @@ +package com.cmc.mercury.domain.mypage.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.persistence.Column; + +@Schema(title = "날짜별 습관쌓기 응답 형식") +public record HabitDetailResponse( + + @Schema(description = "날짜별 습관쌓기 ID") + Long habitHistoryID, + @Schema(description = "요일") + String day, + @Schema(description = "습관쌓기 연속 일수") + int streakCount, + @Schema(description = "획득한 경험치") + int acquiredExp, + @Schema(description = "독서기록 또는 메모 작성 여부") + boolean hasRecord, + @Schema(description = "타이머 완료 여부") + boolean hasTimer +) { + +} diff --git a/src/main/java/com/cmc/mercury/domain/mypage/dto/MyPageResponse.java b/src/main/java/com/cmc/mercury/domain/mypage/dto/MyPageResponse.java new file mode 100644 index 0000000..9d2a686 --- /dev/null +++ b/src/main/java/com/cmc/mercury/domain/mypage/dto/MyPageResponse.java @@ -0,0 +1,26 @@ +package com.cmc.mercury.domain.mypage.dto; + +import io.swagger.v3.oas.annotations.media.Schema; + +import java.util.List; + +@Schema(title = "마이페이지 응답 형식") +public record MyPageResponse( + + @Schema(description = "습관쌓기 ID") + Long habitID, + @Schema(description = "가입 기간") + int joinDays, + @Schema(description = "사용자 닉네임") + String nickname, + @Schema(description = "사용자 경험치") + int exp, + @Schema(description = "습관쌓기 연속 일수") + int streakDays, + @Schema(description = "최근 7일 streak 정보") + List weeklyStreak + // @Schema(description = "가장 최근 독서기록 ID") + // Long latestRecordID +) { + +} diff --git a/src/main/java/com/cmc/mercury/domain/mypage/dto/WeeklyStreakResponse.java b/src/main/java/com/cmc/mercury/domain/mypage/dto/WeeklyStreakResponse.java new file mode 100644 index 0000000..913047d --- /dev/null +++ b/src/main/java/com/cmc/mercury/domain/mypage/dto/WeeklyStreakResponse.java @@ -0,0 +1,14 @@ +package com.cmc.mercury.domain.mypage.dto; + +import io.swagger.v3.oas.annotations.media.Schema; + +@Schema(title = "요일별 성공 여부") +public record WeeklyStreakResponse( + + @Schema(description = "요일") + String day, + @Schema(description = "성공 여부") + boolean isSuccess +) { + +} diff --git a/src/main/java/com/cmc/mercury/domain/mypage/entity/Habit.java b/src/main/java/com/cmc/mercury/domain/mypage/entity/Habit.java new file mode 100644 index 0000000..584a665 --- /dev/null +++ b/src/main/java/com/cmc/mercury/domain/mypage/entity/Habit.java @@ -0,0 +1,37 @@ +package com.cmc.mercury.domain.mypage.entity; + +import com.cmc.mercury.domain.user.entity.User; +import com.cmc.mercury.global.domain.BaseEntity; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Entity +@Getter +@RequiredArgsConstructor(access = AccessLevel.PROTECTED) +public class Habit extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "habit_id") + private Long id; + + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id", nullable = false) + private User user; + + @Column(nullable = false) + private int streakDays; + + @Builder + public Habit(User user, int streakDays) { + this.user = user; + this.streakDays = streakDays; + } + + public void updateStreakDays(int streakDays) { + this.streakDays = streakDays; + } +} diff --git a/src/main/java/com/cmc/mercury/domain/mypage/entity/HabitHistory.java b/src/main/java/com/cmc/mercury/domain/mypage/entity/HabitHistory.java new file mode 100644 index 0000000..b579168 --- /dev/null +++ b/src/main/java/com/cmc/mercury/domain/mypage/entity/HabitHistory.java @@ -0,0 +1,57 @@ +package com.cmc.mercury.domain.mypage.entity; + +import com.cmc.mercury.global.domain.BaseEntity; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Entity +@Getter +@RequiredArgsConstructor(access = AccessLevel.PROTECTED) +public class HabitHistory extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "habit_history_id") + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "habit_id") + private Habit habit; + + @Column(nullable = false) + private boolean hasRecord = false; + + @Column(nullable = false) + private boolean hasTimer = false; + + @Column(nullable = false) + private int streakCount = 0; + + @Column(nullable = false) + private int acquiredExp = 0; + + @Builder + public HabitHistory(Habit habit, Integer streakCount, Integer acquiredExp, Boolean hasRecord, Boolean hasTimer) { + this.habit = habit; + this.streakCount = (streakCount != null) ? streakCount : 0; + this.acquiredExp = (acquiredExp != null) ? acquiredExp : 0; + this.hasRecord = (hasRecord != null) ? hasRecord : false; + this.hasTimer = (hasTimer != null) ? hasTimer : false; + } + + public void updateHasRecord() { + this.hasRecord = true; + } + + public void updateHasTimer() { + this.hasTimer = true; + } + + public void updateAcquiredExp(int acquiredExp) { + this.acquiredExp += acquiredExp; + } + +} diff --git a/src/main/java/com/cmc/mercury/domain/mypage/repository/HabitHistoryRepository.java b/src/main/java/com/cmc/mercury/domain/mypage/repository/HabitHistoryRepository.java new file mode 100644 index 0000000..bcd70fc --- /dev/null +++ b/src/main/java/com/cmc/mercury/domain/mypage/repository/HabitHistoryRepository.java @@ -0,0 +1,30 @@ +package com.cmc.mercury.domain.mypage.repository; + +import com.cmc.mercury.domain.mypage.entity.HabitHistory; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; + +@Repository +public interface HabitHistoryRepository extends JpaRepository { + + // 해당 주간의 기록 조회 + @Query("SELECT h FROM HabitHistory h WHERE h.habit.id = :habitId AND h.createdAt BETWEEN :startOfWeek AND :endOfWeek") + List findThisWeekByHabitId( + @Param("habitId") Long habitId, + @Param("startOfWeek") LocalDateTime startOfWeek, @Param("endOfWeek") LocalDateTime endOfWeek + ); + + // 날짜별 기록 조회 + @Query("SELECT h FROM HabitHistory h WHERE h.habit.user.id = :userId AND h.createdAt BETWEEN :startOfDay AND :endOfDay") + Optional findByHabit_User_IdAndCreatedAt( + @Param("userId") Long userId, + @Param("startOfDay") LocalDateTime startOfDay, @Param("endOfDay") LocalDateTime endOfDay + ); +} diff --git a/src/main/java/com/cmc/mercury/domain/mypage/repository/HabitRepository.java b/src/main/java/com/cmc/mercury/domain/mypage/repository/HabitRepository.java new file mode 100644 index 0000000..060cab6 --- /dev/null +++ b/src/main/java/com/cmc/mercury/domain/mypage/repository/HabitRepository.java @@ -0,0 +1,13 @@ +package com.cmc.mercury.domain.mypage.repository; + +import com.cmc.mercury.domain.mypage.entity.Habit; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface HabitRepository extends JpaRepository { + + Optional findByUser_Id(Long userId); +} diff --git a/src/main/java/com/cmc/mercury/domain/mypage/service/MyPageService.java b/src/main/java/com/cmc/mercury/domain/mypage/service/MyPageService.java new file mode 100644 index 0000000..a31f880 --- /dev/null +++ b/src/main/java/com/cmc/mercury/domain/mypage/service/MyPageService.java @@ -0,0 +1,136 @@ +package com.cmc.mercury.domain.mypage.service; + +import com.cmc.mercury.domain.mypage.dto.HabitDetailResponse; +import com.cmc.mercury.domain.mypage.dto.MyPageResponse; +import com.cmc.mercury.domain.mypage.dto.WeeklyStreakResponse; +import com.cmc.mercury.domain.mypage.entity.Habit; +import com.cmc.mercury.domain.mypage.entity.HabitHistory; +import com.cmc.mercury.domain.mypage.repository.HabitHistoryRepository; +import com.cmc.mercury.domain.mypage.repository.HabitRepository; +import com.cmc.mercury.domain.user.entity.User; +import com.cmc.mercury.global.exception.CustomException; +import com.cmc.mercury.global.exception.ErrorCode; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.time.DayOfWeek; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.temporal.ChronoUnit; +import java.util.*; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +@Slf4j +public class MyPageService { + + private final HabitRepository habitRepository; + private final HabitHistoryRepository habitHistoryRepository; + + public MyPageResponse getMyPage(User user) { + + Habit habit = habitRepository.findByUser_Id(user.getId()) + .orElseThrow(() -> new CustomException(ErrorCode.HABIT_NOT_FOUND)); + + LocalDate today = LocalDate.now(); + LocalDateTime startOfWeek = today.with(DayOfWeek.MONDAY).atStartOfDay(); // 이번 주 월요일 00:00:00 + LocalDateTime endOfWeek = today.with(DayOfWeek.SUNDAY).atTime(LocalTime.MAX); // 이번 주 일요일 23:59:59 + List histories = habitHistoryRepository.findThisWeekByHabitId(habit.getId(), startOfWeek, endOfWeek); // 이번 주의 기록 + + // Map을 사용하여 빠른 조회 + Map historyMap = histories.stream() + .collect(Collectors.toMap(h -> h.getCreatedAt().getDayOfWeek(), h -> h)); + + List weeklyStreak = Arrays.stream(DayOfWeek.values()) + .map(day -> new WeeklyStreakResponse( + day.name(), + historyMap.get(day) != null && historyMap.get(day).getStreakCount() > 0 + )) + .collect(Collectors.toList()); + + return new MyPageResponse( + habit.getId(), + getJoinDays(user.getCreatedAt()), // 가입한 지 며칠인지 계산 + user.getNickname(), + user.getExp(), + habit.getStreakDays(), + weeklyStreak + ); + } + + public HabitDetailResponse getHabitDetail(User user, LocalDate date) { + + LocalDateTime startOfDay = date.atStartOfDay(); // 00:00:00 + LocalDateTime endOfDay = date.atTime(LocalTime.MAX); // 23:59:59 + + // 오늘 streak 확인 + HabitHistory history = habitHistoryRepository + .findByHabit_User_IdAndCreatedAt(user.getId(), startOfDay, endOfDay).orElse(null); + + // 어제 streakCount 확인 + LocalDateTime yesterdayStart = startOfDay.minusDays(1); + LocalDateTime yesterdayEnd = endOfDay.minusDays(1); + Optional yesterdayHistory = habitHistoryRepository.findByHabit_User_IdAndCreatedAt(user.getId(), yesterdayStart, yesterdayEnd); + int previousStreakCount = yesterdayHistory.map(HabitHistory::getStreakCount).orElse(0); + + return new HabitDetailResponse( + history != null ? history.getId() : null, // 기록이 없으면 null + date.getDayOfWeek().name(), + history != null ? history.getStreakCount() : previousStreakCount, + history != null ? history.getAcquiredExp() : 0, + history != null && history.isHasRecord(), + history != null && history.isHasTimer() + ); + } + + private int getJoinDays(LocalDateTime joinDate) { // 가입 기간 계산 + + return (int) ChronoUnit.DAYS.between(joinDate.toLocalDate(), LocalDate.now()) + 1; + } + + // 해당 날짜에 HabitHistory가 없으면 생성 + public HabitHistory saveHabitHistoryIfNotExists(Long userId, LocalDate date, int acquiredExp) { + + // 오늘 기록이 이미 존재하는지 확인 + LocalDateTime startOfDay = date.atStartOfDay(); // 00:00:00 + LocalDateTime endOfDay = date.atTime(LocalTime.MAX); // 23:59:59 + Optional existingHistory = habitHistoryRepository.findByHabit_User_IdAndCreatedAt(userId, startOfDay, endOfDay); + + if (existingHistory.isPresent()) { + // 이미 존재하면 acquiredExp를 증가시키고 반환 + HabitHistory history = existingHistory.get(); + history.updateAcquiredExp(acquiredExp); + return habitHistoryRepository.save(history); + } + + // 어제의 streak 확인 (어제 streak이 연속되었는지 확인) + LocalDateTime yesterdayStart = startOfDay.minusDays(1); + LocalDateTime yesterdayEnd = endOfDay.minusDays(1); + Optional yesterdayHistory = habitHistoryRepository.findByHabit_User_IdAndCreatedAt(userId, yesterdayStart, yesterdayEnd); + + int newStreakCount = (yesterdayHistory.isPresent() && yesterdayHistory.get().getStreakCount() > 0) + ? yesterdayHistory.get().getStreakCount() + 1 // 연속 streak이면 +1 + : 1; // 처음 streak 시작 + + // 새로운 오늘의 기록 + Habit habit = habitRepository.findByUser_Id(userId) + .orElseThrow(() -> new CustomException(ErrorCode.HABIT_NOT_FOUND)); + + // habit.streakDays도 함께 갱신 + habit.updateStreakDays(newStreakCount); + habitRepository.save(habit); + + HabitHistory newHistory = HabitHistory.builder() + .habit(habit) + .streakCount(newStreakCount) + .acquiredExp(acquiredExp) + .hasRecord(false) + .hasTimer(false) + .build(); + + return habitHistoryRepository.save(newHistory); + } +} diff --git a/src/main/java/com/cmc/mercury/domain/record/service/RecordService.java b/src/main/java/com/cmc/mercury/domain/record/service/RecordService.java index ebb129e..85ba55c 100644 --- a/src/main/java/com/cmc/mercury/domain/record/service/RecordService.java +++ b/src/main/java/com/cmc/mercury/domain/record/service/RecordService.java @@ -5,6 +5,9 @@ import com.cmc.mercury.domain.memo.dto.MemoResponse; import com.cmc.mercury.domain.memo.entity.Memo; import com.cmc.mercury.domain.memo.repository.MemoRepository; +import com.cmc.mercury.domain.mypage.entity.HabitHistory; +import com.cmc.mercury.domain.mypage.repository.HabitHistoryRepository; +import com.cmc.mercury.domain.mypage.service.MyPageService; import com.cmc.mercury.domain.record.dto.*; import com.cmc.mercury.domain.record.entity.Record; import com.cmc.mercury.domain.record.entity.RecordDetail; @@ -19,6 +22,7 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; +import java.time.LocalDate; import java.time.LocalDateTime; import java.util.List; @@ -34,7 +38,8 @@ public class RecordService { private final RecordRepository recordRepository; private final BookRepository bookRepository; private final MemoRepository memoRepository; - private final UserService userService; + private final HabitHistoryRepository habitHistoryRepository; + private final MyPageService myPageService; @Transactional public RecordResponse createRecord(User user, RecordRequest request) { @@ -87,6 +92,12 @@ public RecordResponse createRecord(User user, RecordRequest request) { // 사용자 경험치 업데이트 user.updateExp(user.getExp() + acquiredExp); + // 날짜별 습관쌓기 기록 + LocalDate date = LocalDate.now(); + HabitHistory history = myPageService.saveHabitHistoryIfNotExists(user.getId(), date, acquiredExp); + history.updateHasRecord(); + habitHistoryRepository.save(history); + //* return RecordResponse.of(record, recordDetail, savedMemo.getContent()); return RecordResponse.of(savedRecord, savedRecord.getRecordDetail(), memo.getContent()); } diff --git a/src/main/java/com/cmc/mercury/domain/timer/service/TimerService.java b/src/main/java/com/cmc/mercury/domain/timer/service/TimerService.java index 7770f76..8c1c27d 100644 --- a/src/main/java/com/cmc/mercury/domain/timer/service/TimerService.java +++ b/src/main/java/com/cmc/mercury/domain/timer/service/TimerService.java @@ -1,5 +1,8 @@ package com.cmc.mercury.domain.timer.service; +import com.cmc.mercury.domain.mypage.entity.HabitHistory; +import com.cmc.mercury.domain.mypage.repository.HabitHistoryRepository; +import com.cmc.mercury.domain.mypage.service.MyPageService; import com.cmc.mercury.domain.timer.dto.TimerListResponse; import com.cmc.mercury.domain.timer.dto.TimerRequest; import com.cmc.mercury.domain.timer.dto.TimerResponse; @@ -12,6 +15,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDate; import java.time.LocalDateTime; import java.util.List; @@ -21,7 +25,8 @@ public class TimerService { private final TimerRepository timerRepository; - private final UserService userService; + private final HabitHistoryRepository habitHistoryRepository; + private final MyPageService myPageService; private static final int MIN_EXP_MINUTES = 5; private static final int MAX_EXP_MINUTES = 25; @@ -51,6 +56,14 @@ public TimerResponse createTimer(User user, TimerRequest request) { // User의 총 경험치 업데이트 user.updateExp(user.getExp() + newExp); + // 날짜별 습관쌓기 기록 + if (request.seconds() >= 10) { + LocalDate date = LocalDate.now(); + HabitHistory history = myPageService.saveHabitHistoryIfNotExists(user.getId(), date, newExp); + history.updateHasTimer(); + habitHistoryRepository.save(history); + } + return TimerResponse.of(savedTimer); } diff --git a/src/main/java/com/cmc/mercury/domain/user/service/UserService.java b/src/main/java/com/cmc/mercury/domain/user/service/UserService.java index 06d9092..d1c265e 100644 --- a/src/main/java/com/cmc/mercury/domain/user/service/UserService.java +++ b/src/main/java/com/cmc/mercury/domain/user/service/UserService.java @@ -1,5 +1,7 @@ package com.cmc.mercury.domain.user.service; +import com.cmc.mercury.domain.mypage.entity.Habit; +import com.cmc.mercury.domain.mypage.repository.HabitRepository; import com.cmc.mercury.domain.user.entity.OAuthType; import com.cmc.mercury.domain.user.entity.User; import com.cmc.mercury.domain.user.entity.UserStatus; @@ -34,6 +36,7 @@ public class UserService { private final UserRepository userRepository; private final JwtProvider jwtProvider; private final HttpServletResponse response; + private final HabitRepository habitRepository; @Transactional public User createTestUser(UserTestRequest request) { @@ -65,6 +68,13 @@ public User createTestUser(UserTestRequest request) { setTestUserTokens(savedUser, request.isShortLivedAccessToken()); + // 새 User가 생성되면 Habit도 자동 생성 + Habit habit = Habit.builder() + .user(savedUser) + .streakDays(0) // 초기 streak = 0 + .build(); + habitRepository.save(habit); + return savedUser; } diff --git a/src/main/java/com/cmc/mercury/global/exception/ErrorCode.java b/src/main/java/com/cmc/mercury/global/exception/ErrorCode.java index 3f095d2..d5bbd74 100644 --- a/src/main/java/com/cmc/mercury/global/exception/ErrorCode.java +++ b/src/main/java/com/cmc/mercury/global/exception/ErrorCode.java @@ -49,6 +49,10 @@ public enum ErrorCode { MEMO_NOT_FOUND(HttpStatus.NOT_FOUND, "Memo404", "메모를 찾을 수 없습니다."), // MEMO_CREATE_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "Memo500", "메모 생성에 실패했습니다."); + // MyPage + HABIT_NOT_FOUND(HttpStatus.NOT_FOUND, "Habit404", "습관 기록을 찾을 수 없습니다."), + HABIT_HISTORY_NOT_FOUND(HttpStatus.NOT_FOUND, "HabitHistory404", "날짜별 습관 기록을 찾을 수 없습니다."), + // OAuth INVALID_OAUTH2_PROVIDER(HttpStatus.BAD_REQUEST, "OAuth400", "지원하지 않는 소셜 로그인 제공자입니다."), OAUTH2_PROCESSING_ERROR(HttpStatus.UNAUTHORIZED, "OAuth401", "소셜 로그인 처리 중 오류가 발생했습니다."), diff --git a/src/main/java/com/cmc/mercury/global/oauth/service/CustomOAuth2UserService.java b/src/main/java/com/cmc/mercury/global/oauth/service/CustomOAuth2UserService.java index f88dad6..13c8ba4 100644 --- a/src/main/java/com/cmc/mercury/global/oauth/service/CustomOAuth2UserService.java +++ b/src/main/java/com/cmc/mercury/global/oauth/service/CustomOAuth2UserService.java @@ -1,6 +1,8 @@ package com.cmc.mercury.global.oauth.service; import com.auth0.jwt.interfaces.DecodedJWT; +import com.cmc.mercury.domain.mypage.entity.Habit; +import com.cmc.mercury.domain.mypage.repository.HabitRepository; import com.cmc.mercury.domain.user.entity.OAuthType; import com.cmc.mercury.domain.user.entity.User; import com.cmc.mercury.domain.user.entity.UserStatus; @@ -34,6 +36,7 @@ public class CustomOAuth2UserService extends DefaultOAuth2UserService { private final UserRepository userRepository; private final AppleIdTokenVerifier appleIdTokenVerifier; + private final HabitRepository habitRepository; @Override public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException { @@ -157,6 +160,15 @@ private User createUser(OAuth2UserInfo oAuth2UserInfo) { .userStatus(UserStatus.ACTIVE) .build(); - return userRepository.save(user); + User savedUser = userRepository.save(user); + + // 새 User가 생성되면 Habit도 자동 생성 + Habit habit = Habit.builder() + .user(savedUser) + .streakDays(0) // 초기 streak = 0 + .build(); + habitRepository.save(habit); + + return savedUser; } }