From 6451bd7ca8a4a289fe2a59755228ca6e14f85fd4 Mon Sep 17 00:00:00 2001 From: thguss Date: Mon, 16 Dec 2024 22:26:01 +0900 Subject: [PATCH 01/24] delete: deleted unused file --- .../server/domain/challenge/Mission.java | 20 -- .../adapter/mission/ChallengeAdapter.java | 31 --- .../entity/mission/ChallengeEntity.java | 25 --- .../repository/mission/MissionRepository.java | 13 -- .../soptie/server/temporary/TemporaryApi.java | 199 ------------------ .../server/temporary/data/ThemeData.java | 73 ------- .../dto/CreateMemberDailyRoutine.java | 6 - .../dto/DailyRoutineThemesResponse.java | 40 ---- .../temporary/dto/DailyRoutinesResponse.java | 35 --- .../server/temporary/dto/DollResponse.java | 23 -- .../dto/GetDailyRoutinesResponse.java | 38 ---- .../dto/GetHappinessRoutinesResponse.java | 47 ----- .../dto/GetHappinessSubRoutinesResponse.java | 54 ----- .../dto/GetMemberDailyRoutinesResponse.java | 45 ---- .../dto/HappinessRoutineThemesResponse.java | 35 --- .../dto/MemberHappinessRoutinesResponse.java | 57 ----- 16 files changed, 741 deletions(-) delete mode 100644 src/main/java/com/soptie/server/domain/challenge/Mission.java delete mode 100644 src/main/java/com/soptie/server/persistence/adapter/mission/ChallengeAdapter.java delete mode 100644 src/main/java/com/soptie/server/persistence/entity/mission/ChallengeEntity.java delete mode 100644 src/main/java/com/soptie/server/persistence/repository/mission/MissionRepository.java delete mode 100644 src/main/java/com/soptie/server/temporary/TemporaryApi.java delete mode 100644 src/main/java/com/soptie/server/temporary/data/ThemeData.java delete mode 100644 src/main/java/com/soptie/server/temporary/dto/CreateMemberDailyRoutine.java delete mode 100644 src/main/java/com/soptie/server/temporary/dto/DailyRoutineThemesResponse.java delete mode 100644 src/main/java/com/soptie/server/temporary/dto/DailyRoutinesResponse.java delete mode 100644 src/main/java/com/soptie/server/temporary/dto/DollResponse.java delete mode 100644 src/main/java/com/soptie/server/temporary/dto/GetDailyRoutinesResponse.java delete mode 100644 src/main/java/com/soptie/server/temporary/dto/GetHappinessRoutinesResponse.java delete mode 100644 src/main/java/com/soptie/server/temporary/dto/GetHappinessSubRoutinesResponse.java delete mode 100644 src/main/java/com/soptie/server/temporary/dto/GetMemberDailyRoutinesResponse.java delete mode 100644 src/main/java/com/soptie/server/temporary/dto/HappinessRoutineThemesResponse.java delete mode 100644 src/main/java/com/soptie/server/temporary/dto/MemberHappinessRoutinesResponse.java diff --git a/src/main/java/com/soptie/server/domain/challenge/Mission.java b/src/main/java/com/soptie/server/domain/challenge/Mission.java deleted file mode 100644 index c403f91d..00000000 --- a/src/main/java/com/soptie/server/domain/challenge/Mission.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.soptie.server.domain.challenge; - -import jakarta.validation.constraints.NotNull; -import lombok.Builder; -import lombok.Getter; - -@Builder -@Getter -public class Mission { - private Long id; - @NotNull - private String content; - @NotNull - private String description; - @NotNull - private String requiredTime; - @NotNull - private String place; - private long challengeId; -} diff --git a/src/main/java/com/soptie/server/persistence/adapter/mission/ChallengeAdapter.java b/src/main/java/com/soptie/server/persistence/adapter/mission/ChallengeAdapter.java deleted file mode 100644 index 0e96cafc..00000000 --- a/src/main/java/com/soptie/server/persistence/adapter/mission/ChallengeAdapter.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.soptie.server.persistence.adapter.mission; - -import java.util.List; - -import com.soptie.server.common.exception.ExceptionCode; -import com.soptie.server.common.exception.SoftieException; -import com.soptie.server.common.support.RepositoryAdapter; -import com.soptie.server.domain.challenge.Challenge; -import com.soptie.server.persistence.entity.mission.ChallengeEntity; -import com.soptie.server.persistence.repository.mission.ChallengeRepository; - -import lombok.RequiredArgsConstructor; - -@RepositoryAdapter -@RequiredArgsConstructor -public class ChallengeAdapter { - private final ChallengeRepository challengeRepository; - - public List findByThemeId(long themeId) { - return challengeRepository.findByThemeId(themeId).stream().map(ChallengeEntity::toDomain).toList(); - } - - public Challenge findById(long challengeId) { - return find(challengeId).toDomain(); - } - - private ChallengeEntity find(long id) { - return challengeRepository.findById(id) - .orElseThrow(() -> new SoftieException(ExceptionCode.NOT_FOUND, "Challenge ID: " + id)); - } -} diff --git a/src/main/java/com/soptie/server/persistence/entity/mission/ChallengeEntity.java b/src/main/java/com/soptie/server/persistence/entity/mission/ChallengeEntity.java deleted file mode 100644 index 8a7e08a8..00000000 --- a/src/main/java/com/soptie/server/persistence/entity/mission/ChallengeEntity.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.soptie.server.persistence.entity.mission; - -import com.soptie.server.domain.challenge.Challenge; -import com.soptie.server.persistence.entity.BaseEntity; - -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.Table; - -@Entity -@Table(name = "challenge", schema = "softie") -public class ChallengeEntity extends BaseEntity { - @Column(nullable = false) - private String name; - @Column(nullable = false) - private long themeId; - - public Challenge toDomain() { - return Challenge.builder() - .id(this.id) - .name(this.name) - .themeId(this.themeId) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/persistence/repository/mission/MissionRepository.java b/src/main/java/com/soptie/server/persistence/repository/mission/MissionRepository.java deleted file mode 100644 index 09d92cfa..00000000 --- a/src/main/java/com/soptie/server/persistence/repository/mission/MissionRepository.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.soptie.server.persistence.repository.mission; - -import java.util.List; - -import org.springframework.data.jpa.repository.JpaRepository; - -import com.soptie.server.persistence.entity.mission.MissionEntity; - -public interface MissionRepository extends JpaRepository { - List findByChallengeIdIn(List challengeIds); - - List findByIdIn(List ids); -} diff --git a/src/main/java/com/soptie/server/temporary/TemporaryApi.java b/src/main/java/com/soptie/server/temporary/TemporaryApi.java deleted file mode 100644 index 5e1d373e..00000000 --- a/src/main/java/com/soptie/server/temporary/TemporaryApi.java +++ /dev/null @@ -1,199 +0,0 @@ -package com.soptie.server.temporary; - -import java.security.Principal; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Function; -import java.util.stream.Collectors; - -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestController; - -import com.soptie.server.api.controller.dto.response.SuccessResponse; -import com.soptie.server.domain.doll.DollType; -import com.soptie.server.domain.memberroutine.MemberRoutine; -import com.soptie.server.domain.routine.Routine; -import com.soptie.server.persistence.adapter.MemberAdapter; -import com.soptie.server.persistence.adapter.ThemeAdapter; -import com.soptie.server.persistence.adapter.mission.ChallengeAdapter; -import com.soptie.server.persistence.adapter.mission.MemberMissionAdapter; -import com.soptie.server.persistence.adapter.mission.MissionAdapter; -import com.soptie.server.persistence.adapter.routine.MemberRoutineAdapter; -import com.soptie.server.persistence.adapter.routine.RoutineAdapter; -import com.soptie.server.persistence.entity.ThemeEntity; -import com.soptie.server.persistence.entity.mission.ChallengeEntity; -import com.soptie.server.persistence.repository.ThemeRepository; -import com.soptie.server.persistence.repository.mission.ChallengeRepository; -import com.soptie.server.temporary.dto.CreateMemberDailyRoutine; -import com.soptie.server.temporary.dto.DailyRoutineThemesResponse; -import com.soptie.server.temporary.dto.DailyRoutinesResponse; -import com.soptie.server.temporary.dto.DollResponse; -import com.soptie.server.temporary.dto.GetDailyRoutinesResponse; -import com.soptie.server.temporary.dto.GetHappinessRoutinesResponse; -import com.soptie.server.temporary.dto.GetHappinessSubRoutinesResponse; -import com.soptie.server.temporary.dto.GetMemberDailyRoutinesResponse; -import com.soptie.server.temporary.dto.HappinessRoutineThemesResponse; -import com.soptie.server.temporary.dto.MemberHappinessRoutinesResponse; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/v1") -public class TemporaryApi { - private final ThemeAdapter themeAdapter; - private final ChallengeAdapter challengeAdapter; - private final MissionAdapter missionAdapter; - private final ThemeRepository themeRepository; - private final ChallengeRepository challengeRepository; - private final RoutineAdapter routineAdapter; - private final MemberRoutineAdapter memberRoutineAdapter; - private final MemberAdapter memberAdapter; - private final MemberMissionAdapter memberMissionAdapter; - - @ResponseStatus(HttpStatus.OK) - @GetMapping("/routines/happiness/routine/{routineId}") - public SuccessResponse getHappinessRoutinesByRoutine( - @PathVariable long routineId - ) { - val challenge = challengeAdapter.findById(routineId); - val theme = themeAdapter.findById(challenge.getThemeId()); - val missions = missionAdapter.findByChallengeIds(List.of(challenge.getId())); - return SuccessResponse.success( - "루틴별 행복 서브 루틴 내용 조회 성공", - GetHappinessSubRoutinesResponse.of(theme, challenge, missions)); - } - - @ResponseStatus(HttpStatus.OK) - @GetMapping("/routines/happiness") - public SuccessResponse getHappinessRoutinesByTheme( - @RequestParam(required = false) Long themeId - ) { - val themes = themeId == null - ? themeRepository.findAll().stream().map(ThemeEntity::toDomain).toList() - : List.of(themeAdapter.findById(themeId)); - val challenges = challengeRepository.findAll().stream().map(ChallengeEntity::toDomain).toList(); - - val map = themes.stream() - .collect(Collectors.toMap( - theme -> theme, - theme -> challenges.stream() - .filter(challenge -> challenge.getThemeId() == theme.getId()) - .toList() - )); - - return SuccessResponse.success( - "테마 목록별 행복 루틴 목록 조회 성공", - GetHappinessRoutinesResponse.of(map)); - } - - @ResponseStatus(HttpStatus.CREATED) - @PostMapping("/routines/daily/member") - @Transactional - public SuccessResponse createMemberDailyRoutine( - Principal principal, - @RequestBody CreateMemberDailyRoutine request - ) { - val memberId = Long.parseLong(principal.getName()); - val member = memberAdapter.findById(memberId); - val routine = routineAdapter.findById(request.routineId()); - val memberRoutine = memberRoutineAdapter.saveAll(member, List.of(routine)); - return SuccessResponse.success( - "데일리 루틴 추가 성공", - new CreateMemberDailyRoutine(!memberRoutine.isEmpty() ? memberRoutine.get(0).getId() : 0L)); - } - - @ResponseStatus(HttpStatus.OK) - @GetMapping("/routines/daily/member") - public SuccessResponse getMemberDailyRoutines(Principal principal) { - val memberId = Long.parseLong(principal.getName()); - val memberRoutines = memberRoutineAdapter.findByMemberId(memberId); - val routines = routineAdapter.findByIds(memberRoutines.stream().map(MemberRoutine::getRoutineId).toList()); - - val routineMap = routines.stream() - .collect(Collectors.toMap(Routine::getId, Function.identity())); - - val memberRoutineMap = memberRoutines.stream() - .collect(Collectors.toMap( - Function.identity(), // Key: MemberRoutine 자체 - memberRoutine -> routineMap.get(memberRoutine.getRoutineId()) // Value: 해당 MemberRoutine의 Routine - )); - - return SuccessResponse.success( - "회원의 데일리 루틴 목록 조회 성공", - GetMemberDailyRoutinesResponse.of(memberRoutineMap)); - } - - @ResponseStatus(HttpStatus.OK) - @GetMapping("/routines/happiness/themes") - public SuccessResponse getHappinessRoutineThemes() { - val themes = themeRepository.findAll().stream().map(ThemeEntity::toDomain).toList(); - return SuccessResponse.success( - "행복 루틴 테마 목록 조회 성공", - HappinessRoutineThemesResponse.of(themes)); - } - - @ResponseStatus(HttpStatus.OK) - @GetMapping("/routines/daily") - public SuccessResponse getDailyRoutines(@RequestParam List themes) { - val routines = new ArrayList(); - for (val themeId : themes) { - routines.addAll(routineAdapter.findByThemeId(themeId)); - } - return SuccessResponse.success( - "테마 목록별 데일리 루틴 목록 조회 성공", - DailyRoutinesResponse.of(routines)); - } - - @ResponseStatus(HttpStatus.OK) - @GetMapping("/routines/daily/theme/{themeId}") - public SuccessResponse getDailyRoutines(@PathVariable long themeId) { - val routines = routineAdapter.findByThemeId(themeId); - return SuccessResponse.success( - "테마별 데일리 루틴 목록 조회 성공", - GetDailyRoutinesResponse.of(themeId, routines)); - } - - @ResponseStatus(HttpStatus.OK) - @GetMapping("/routines/daily/themes") - public SuccessResponse getDailyRoutineThemes() { - val themes = themeAdapter.findByBasic(); - return SuccessResponse.success( - "테마별 데일리 루틴 목록 조회 성공", - DailyRoutineThemesResponse.of(themes)); - } - - @ResponseStatus(HttpStatus.OK) - @GetMapping("/dolls/image/{type}") - public SuccessResponse getDolls(@PathVariable DollType type) { - return SuccessResponse.success( - "인형 이미지 불러오기 성공", - DollResponse.of(type)); - } - - @ResponseStatus(HttpStatus.OK) - @GetMapping("/routines/happiness/member") - public ResponseEntity getDolls(Principal principal) { - val memberId = Long.parseLong(principal.getName()); - return memberMissionAdapter.findByMember(memberId) - .map(it -> { - val mission = missionAdapter.findById(it.getMissionId()); - val challenge = challengeAdapter.findById(mission.getChallengeId()); - val theme = themeAdapter.findById(challenge.getThemeId()); - return ResponseEntity.ok(SuccessResponse.success( - "인형 이미지 불러오기 성공", - MemberHappinessRoutinesResponse.of(it, challenge, mission, theme))); - }) - .orElseGet(() -> ResponseEntity.noContent().build()); - } -} diff --git a/src/main/java/com/soptie/server/temporary/data/ThemeData.java b/src/main/java/com/soptie/server/temporary/data/ThemeData.java deleted file mode 100644 index 882eb928..00000000 --- a/src/main/java/com/soptie/server/temporary/data/ThemeData.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.soptie.server.temporary.data; - -public class ThemeData { - - public static String getColor(long id) { - return switch ((int)id) { - case 1 -> "#E19098"; - case 2 -> "#38B662"; - case 3 -> "#6392D8"; - case 4 -> "#EF596F"; - case 5 -> "#52A1DA"; - case 6 -> "#EDBF4F"; - default -> "#EB9D07"; - }; - } - - public static String getHappinessBackgroundUrl(long id) { - return switch ((int)id) { - case 1 -> - "https://github.com/Team-Sopetit/sopetit-image/blob/main/happiness/card/img_happycard_1ver2@3x.png?raw=true"; - case 2 -> - "https://github.com/Team-Sopetit/sopetit-image/blob/main/happiness/card/img_happycard_3ver2@3x.png?raw=true"; - case 3 -> - "https://github.com/Team-Sopetit/sopetit-image/blob/main/happiness/card/img_happycard_4ver2@3x.png?raw=true"; - case 4 -> - "https://github.com/Team-Sopetit/sopetit-image/blob/main/happiness/card/img_happycard_5ver2@3x.png?raw=true"; - case 5 -> - "https://github.com/Team-Sopetit/sopetit-image/blob/main/happiness/card/img_happycard_6ver2@3x.png?raw=true"; - case 6 -> - "https://github.com/Team-Sopetit/sopetit-image/blob/main/happiness/card/img_happycard_7ver2@3x.png?raw=true"; - default -> - "https://github.com/Team-Sopetit/sopetit-image/blob/main/happiness/card/img_happycard_2ver2@3x.png?raw=true"; - }; - } - - public static String getIconImageUrl(long id) { - return switch ((int)id) { - case 1 -> - "https://softie-data-image.s3.ap-northeast-2.amazonaws.com/icon/%E1%84%80%E1%85%AA%E1%86%AB%E1%84%80%E1%85%A8_%E1%84%8A%E1%85%A1%E1%87%82%E1%84%80%E1%85%B5.png"; - case 2 -> - "https://softie-data-image.s3.ap-northeast-2.amazonaws.com/icon/%E1%84%92%E1%85%A1%E1%86%AB_%E1%84%80%E1%85%A5%E1%86%AF%E1%84%8B%E1%85%B3%E1%86%B7_%E1%84%89%E1%85%A5%E1%86%BC%E1%84%8C%E1%85%A1%E1%86%BC.png"; - case 3 -> - "https://softie-data-image.s3.ap-northeast-2.amazonaws.com/icon/%E1%84%82%E1%85%A1%E1%84%8B%E1%85%AA_%E1%84%8E%E1%85%B5%E1%86%AB%E1%84%92%E1%85%A2%E1%84%8C%E1%85%B5%E1%84%80%E1%85%B5.png"; - case 4 -> - "https://softie-data-image.s3.ap-northeast-2.amazonaws.com/icon/%E1%84%86%E1%85%A1%E1%84%8B%E1%85%B3%E1%86%B7_%E1%84%8E%E1%85%A2%E1%86%BC%E1%84%80%E1%85%B5%E1%86%B7.png"; - case 5 -> - "https://softie-data-image.s3.ap-northeast-2.amazonaws.com/icon/%E1%84%80%E1%85%A5%E1%86%AB%E1%84%80%E1%85%A1%E1%86%BC%E1%84%92%E1%85%A1%E1%86%AB_%E1%84%86%E1%85%A9%E1%86%B7.png"; - case 6 -> - "https://softie-data-image.s3.ap-northeast-2.amazonaws.com/icon/%E1%84%90%E1%85%A9%E1%86%BC%E1%84%90%E1%85%A9%E1%86%BC%E1%84%92%E1%85%A1%E1%86%AB_%E1%84%90%E1%85%A9%E1%86%BC%E1%84%8C%E1%85%A1%E1%86%BC.png"; - default -> - "https://softie-data-image.s3.ap-northeast-2.amazonaws.com/icon/%E1%84%89%E1%85%A1%E1%86%AB%E1%84%84%E1%85%B3%E1%86%BA%E1%84%92%E1%85%A1%E1%86%AB_%E1%84%8B%E1%85%B5%E1%86%AF%E1%84%89%E1%85%A1%E1%86%BC.png"; - }; - } - - public static String getDailyBackgroundImageUrl(long id) { - return switch ((int)id) { - case 1 -> - "https://github.com/Team-Sopetit/sopetit-image/blob/main/routine/daily/small_kindness/background.png?raw=true"; - case 2 -> - "https://github.com/Team-Sopetit/sopetit-image/blob/main/routine/daily/overcome_helplessness/background.png?raw=true"; - case 3 -> - "https://github.com/Team-Sopetit/sopetit-image/blob/main/routine/daily/restful_sleep/background.png?raw=true"; - case 4 -> - "https://github.com/Team-Sopetit/sopetit-image/blob/main/routine/daily/environmental_guard/background.png?raw=true"; - case 5 -> - "https://github.com/Team-Sopetit/sopetit-image/blob/main/routine/daily/healthly_body/background.png?raw=true"; - case 6 -> - "https://github.com/Team-Sopetit/sopetit-image/blob/main/routine/daily/chubby_bank_account/background.png?raw=true"; - default -> - "https://github.com/Team-Sopetit/sopetit-image/blob/main/routine/daily/fresh_start/background.png?raw=true"; - }; - } -} diff --git a/src/main/java/com/soptie/server/temporary/dto/CreateMemberDailyRoutine.java b/src/main/java/com/soptie/server/temporary/dto/CreateMemberDailyRoutine.java deleted file mode 100644 index 762a961e..00000000 --- a/src/main/java/com/soptie/server/temporary/dto/CreateMemberDailyRoutine.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.soptie.server.temporary.dto; - -public record CreateMemberDailyRoutine( - long routineId -) { -} diff --git a/src/main/java/com/soptie/server/temporary/dto/DailyRoutineThemesResponse.java b/src/main/java/com/soptie/server/temporary/dto/DailyRoutineThemesResponse.java deleted file mode 100644 index fd7d384f..00000000 --- a/src/main/java/com/soptie/server/temporary/dto/DailyRoutineThemesResponse.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.soptie.server.temporary.dto; - -import java.util.List; - -import com.soptie.server.domain.theme.Theme; -import com.soptie.server.temporary.data.ThemeData; - -import lombok.AccessLevel; -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = AccessLevel.PRIVATE) -public record DailyRoutineThemesResponse( - @NonNull List themes -) { - - public static DailyRoutineThemesResponse of(List themes) { - return DailyRoutineThemesResponse.builder() - .themes(themes.stream().map(DailyThemeResponse::of).toList()) - .build(); - } - - @Builder(access = AccessLevel.PRIVATE) - public record DailyThemeResponse( - long themeId, - @NonNull String name, - @NonNull String iconImageUrl, - @NonNull String backgroundImageUrl - ) { - - public static DailyThemeResponse of(Theme theme) { - return DailyThemeResponse.builder() - .themeId(theme.getId()) - .name(theme.getName()) - .iconImageUrl(ThemeData.getIconImageUrl(theme.getId())) - .backgroundImageUrl(ThemeData.getDailyBackgroundImageUrl(theme.getId())) - .build(); - } - } -} diff --git a/src/main/java/com/soptie/server/temporary/dto/DailyRoutinesResponse.java b/src/main/java/com/soptie/server/temporary/dto/DailyRoutinesResponse.java deleted file mode 100644 index 822de425..00000000 --- a/src/main/java/com/soptie/server/temporary/dto/DailyRoutinesResponse.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.soptie.server.temporary.dto; - -import java.util.List; - -import com.soptie.server.domain.routine.Routine; - -import lombok.AccessLevel; -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = AccessLevel.PRIVATE) -public record DailyRoutinesResponse( - @NonNull List routines -) { - - public static DailyRoutinesResponse of(List routines) { - return DailyRoutinesResponse.builder() - .routines(routines.stream().map(DailyRoutineResponse::of).toList()) - .build(); - } - - @Builder(access = AccessLevel.PRIVATE) - private record DailyRoutineResponse( - long routineId, - @NonNull String content - ) { - - private static DailyRoutineResponse of(Routine routine) { - return DailyRoutineResponse.builder() - .routineId(routine.getId()) - .content(routine.getContent()) - .build(); - } - } -} diff --git a/src/main/java/com/soptie/server/temporary/dto/DollResponse.java b/src/main/java/com/soptie/server/temporary/dto/DollResponse.java deleted file mode 100644 index cf14c2bc..00000000 --- a/src/main/java/com/soptie/server/temporary/dto/DollResponse.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.soptie.server.temporary.dto; - -import com.soptie.server.domain.doll.DollType; - -import lombok.NonNull; - -public record DollResponse( - @NonNull String faceImageUrl -) { - - public static DollResponse of(DollType type) { - return new DollResponse(getFaceImageUrl(type)); - } - - private static String getFaceImageUrl(DollType type) { - return switch (type) { - case BROWN -> "https://github.com/Team-Sopetit/sopetit-image/blob/main/character/brown/face.png?raw=true"; - case RED -> "https://github.com/Team-Sopetit/sopetit-image/blob/main/character/red/face.png?raw=true"; - case GRAY -> "https://github.com/Team-Sopetit/sopetit-image/blob/main/character/gray/face.png?raw=true"; - case WHITE -> "https://github.com/Team-Sopetit/sopetit-image/blob/main/character/white/face.png?raw=true"; - }; - } -} diff --git a/src/main/java/com/soptie/server/temporary/dto/GetDailyRoutinesResponse.java b/src/main/java/com/soptie/server/temporary/dto/GetDailyRoutinesResponse.java deleted file mode 100644 index ef0b43cc..00000000 --- a/src/main/java/com/soptie/server/temporary/dto/GetDailyRoutinesResponse.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.soptie.server.temporary.dto; - -import java.util.List; - -import com.soptie.server.domain.routine.Routine; -import com.soptie.server.temporary.data.ThemeData; - -import lombok.AccessLevel; -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = AccessLevel.PRIVATE) -public record GetDailyRoutinesResponse( - @NonNull String backgroundImageUrl, - @NonNull List routines -) { - - public static GetDailyRoutinesResponse of(long themeId, List routines) { - return GetDailyRoutinesResponse.builder() - .backgroundImageUrl(ThemeData.getDailyBackgroundImageUrl(themeId)) - .routines(routines.stream().map(DailyRoutineResponse::of).toList()) - .build(); - } - - @Builder(access = AccessLevel.PRIVATE) - private record DailyRoutineResponse( - long routineId, - @NonNull String content - ) { - - private static DailyRoutineResponse of(Routine routine) { - return DailyRoutineResponse.builder() - .routineId(routine.getId()) - .content(routine.getContent()) - .build(); - } - } -} diff --git a/src/main/java/com/soptie/server/temporary/dto/GetHappinessRoutinesResponse.java b/src/main/java/com/soptie/server/temporary/dto/GetHappinessRoutinesResponse.java deleted file mode 100644 index b1788277..00000000 --- a/src/main/java/com/soptie/server/temporary/dto/GetHappinessRoutinesResponse.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.soptie.server.temporary.dto; - -import java.util.List; -import java.util.Map; - -import com.soptie.server.domain.challenge.Challenge; -import com.soptie.server.domain.theme.Theme; -import com.soptie.server.temporary.data.ThemeData; - -import lombok.AccessLevel; -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = AccessLevel.PRIVATE) -public record GetHappinessRoutinesResponse( - List routines -) { - - public static GetHappinessRoutinesResponse of(Map> map) { - return GetHappinessRoutinesResponse.builder() - .routines(map.entrySet().stream() - .flatMap(entry -> entry.getValue().stream() - .map(challenge -> HappinessRoutineResponse.of(entry.getKey(), challenge))) - .toList()) - .build(); - } - - @Builder(access = AccessLevel.PRIVATE) - public record HappinessRoutineResponse( - long routineId, - @NonNull String name, - @NonNull String nameColor, - @NonNull String title, - @NonNull String iconImageUrl - ) { - - public static HappinessRoutineResponse of(Theme theme, Challenge challenge) { - return HappinessRoutineResponse.builder() - .routineId(challenge.getId()) - .name(theme.getName()) - .nameColor(ThemeData.getColor(theme.getId())) - .title(challenge.getName()) - .iconImageUrl(ThemeData.getIconImageUrl(theme.getId())) - .build(); - } - } -} diff --git a/src/main/java/com/soptie/server/temporary/dto/GetHappinessSubRoutinesResponse.java b/src/main/java/com/soptie/server/temporary/dto/GetHappinessSubRoutinesResponse.java deleted file mode 100644 index 205cb699..00000000 --- a/src/main/java/com/soptie/server/temporary/dto/GetHappinessSubRoutinesResponse.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.soptie.server.temporary.dto; - -import java.util.List; - -import com.soptie.server.domain.challenge.Challenge; -import com.soptie.server.domain.challenge.Mission; -import com.soptie.server.domain.theme.Theme; -import com.soptie.server.temporary.data.ThemeData; - -import lombok.AccessLevel; -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = AccessLevel.PRIVATE) -public record GetHappinessSubRoutinesResponse( - @NonNull String title, - @NonNull String name, - @NonNull String nameColor, - @NonNull String iconImageUrl, - @NonNull String contentImageUrl, - @NonNull List subRoutines -) { - - public static GetHappinessSubRoutinesResponse of(Theme theme, Challenge challenge, List missions) { - return GetHappinessSubRoutinesResponse.builder() - .title(challenge.getName()) - .name(theme.getName()) - .nameColor(ThemeData.getColor(theme.getId())) - .iconImageUrl(ThemeData.getIconImageUrl(theme.getId())) - .contentImageUrl(ThemeData.getHappinessBackgroundUrl(theme.getId())) - .subRoutines(missions.stream().map(HappinessSubRoutineResponse::of).toList()) - .build(); - } - - @Builder(access = AccessLevel.PRIVATE) - public record HappinessSubRoutineResponse( - long subRoutineId, - @NonNull String content, - @NonNull String detailContent, - @NonNull String timeTaken, - @NonNull String place - ) { - - public static HappinessSubRoutineResponse of(Mission mission) { - return HappinessSubRoutineResponse.builder() - .subRoutineId(mission.getId()) - .content(mission.getContent()) - .detailContent(mission.getDescription()) - .timeTaken(mission.getRequiredTime()) - .place(mission.getPlace()) - .build(); - } - } -} diff --git a/src/main/java/com/soptie/server/temporary/dto/GetMemberDailyRoutinesResponse.java b/src/main/java/com/soptie/server/temporary/dto/GetMemberDailyRoutinesResponse.java deleted file mode 100644 index 9acefd59..00000000 --- a/src/main/java/com/soptie/server/temporary/dto/GetMemberDailyRoutinesResponse.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.soptie.server.temporary.dto; - -import java.util.List; -import java.util.Map; - -import com.soptie.server.domain.memberroutine.MemberRoutine; -import com.soptie.server.domain.routine.Routine; -import com.soptie.server.temporary.data.ThemeData; - -import lombok.AccessLevel; -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = AccessLevel.PRIVATE) -public record GetMemberDailyRoutinesResponse( - List routines -) { - - public static GetMemberDailyRoutinesResponse of(Map map) { - return GetMemberDailyRoutinesResponse.builder() - .routines(map.entrySet().stream() - .map(it -> MemberDailyRoutineResponse.of(it.getKey(), it.getValue())).toList()) - .build(); - } - - @Builder(access = AccessLevel.PRIVATE) - private record MemberDailyRoutineResponse( - long routineId, - @NonNull String content, - @NonNull String iconImageUrl, - int achieveCount, - boolean isAchieve - ) { - - private static MemberDailyRoutineResponse of(MemberRoutine memberRoutine, Routine routine) { - return MemberDailyRoutineResponse.builder() - .routineId(memberRoutine.getId()) - .content(routine.getContent()) - .iconImageUrl(ThemeData.getIconImageUrl(routine.getThemeId())) - .achieveCount(memberRoutine.getAchievementCount()) - .isAchieve(memberRoutine.isAchieved()) - .build(); - } - } -} diff --git a/src/main/java/com/soptie/server/temporary/dto/HappinessRoutineThemesResponse.java b/src/main/java/com/soptie/server/temporary/dto/HappinessRoutineThemesResponse.java deleted file mode 100644 index 8efe36a2..00000000 --- a/src/main/java/com/soptie/server/temporary/dto/HappinessRoutineThemesResponse.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.soptie.server.temporary.dto; - -import java.util.List; - -import com.soptie.server.domain.theme.Theme; - -import lombok.AccessLevel; -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = AccessLevel.PRIVATE) -public record HappinessRoutineThemesResponse( - @NonNull List themes -) { - - public static HappinessRoutineThemesResponse of(List themes) { - return HappinessRoutineThemesResponse.builder() - .themes(themes.stream().map(HappinessThemeResponse::of).toList()) - .build(); - } - - @Builder(access = AccessLevel.PRIVATE) - private record HappinessThemeResponse( - long themeId, - @NonNull String name - ) { - - private static HappinessThemeResponse of(Theme theme) { - return HappinessThemeResponse.builder() - .themeId(theme.getId()) - .name(theme.getName()) - .build(); - } - } -} diff --git a/src/main/java/com/soptie/server/temporary/dto/MemberHappinessRoutinesResponse.java b/src/main/java/com/soptie/server/temporary/dto/MemberHappinessRoutinesResponse.java deleted file mode 100644 index aae5dba5..00000000 --- a/src/main/java/com/soptie/server/temporary/dto/MemberHappinessRoutinesResponse.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.soptie.server.temporary.dto; - -import com.soptie.server.domain.challenge.Challenge; -import com.soptie.server.domain.challenge.Mission; -import com.soptie.server.domain.membermission.MemberMission; -import com.soptie.server.domain.theme.Theme; -import com.soptie.server.temporary.data.ThemeData; - -import lombok.AccessLevel; -import lombok.Builder; - -@Builder(access = AccessLevel.PRIVATE) -public record MemberHappinessRoutinesResponse( - long routineId, - ThemeServiceResponse theme, - String routineContent, - String content, - String description, - String place, - String requiredTime -) { - - public static MemberHappinessRoutinesResponse of( - MemberMission memberMission, - Challenge challenge, - Mission mission, - Theme theme - ) { - return MemberHappinessRoutinesResponse.builder() - .routineId(memberMission.getId()) - .theme(ThemeServiceResponse.of(theme)) - .routineContent(challenge.getName()) - .content(mission.getContent()) - .description(mission.getDescription()) - .place(mission.getPlace()) - .requiredTime(mission.getRequiredTime()) - .build(); - } - - @Builder(access = AccessLevel.PRIVATE) - private record ThemeServiceResponse( - String iconImageUrl, - String cardImageUrl, - String name, - String color - ) { - - private static ThemeServiceResponse of(Theme theme) { - return ThemeServiceResponse.builder() - .iconImageUrl(ThemeData.getIconImageUrl(theme.getId())) - .cardImageUrl(ThemeData.getHappinessBackgroundUrl(theme.getId())) - .name(theme.getName()) - .color(ThemeData.getColor(theme.getId())) - .build(); - } - } -} From b7b47b9639d10a7050c8f9159019e1b70ca70769 Mon Sep 17 00:00:00 2001 From: thguss Date: Mon, 16 Dec 2024 22:26:40 +0900 Subject: [PATCH 02/24] fix: updated challenge --- .../domain/challenge/ChallengeService.java | 44 +++++-------------- 1 file changed, 10 insertions(+), 34 deletions(-) diff --git a/src/main/java/com/soptie/server/domain/challenge/ChallengeService.java b/src/main/java/com/soptie/server/domain/challenge/ChallengeService.java index d8f9a426..6c9731c3 100644 --- a/src/main/java/com/soptie/server/domain/challenge/ChallengeService.java +++ b/src/main/java/com/soptie/server/domain/challenge/ChallengeService.java @@ -1,17 +1,12 @@ package com.soptie.server.domain.challenge; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import com.soptie.server.api.controller.dto.response.challenge.GetChallengesByMemberResponse; -import com.soptie.server.domain.membermission.MemberMission; -import com.soptie.server.persistence.adapter.mission.ChallengeAdapter; -import com.soptie.server.persistence.adapter.mission.MemberMissionAdapter; -import com.soptie.server.persistence.adapter.mission.MissionAdapter; +import com.soptie.server.api.controller.dto.response.challenge.ChallengesResponse; +import com.soptie.server.domain.membermission.MemberChallenge; +import com.soptie.server.persistence.adapter.challenge.ChallengeAdapter; +import com.soptie.server.persistence.adapter.mission.MemberChallengeAdapter; import lombok.RequiredArgsConstructor; import lombok.val; @@ -21,33 +16,14 @@ @Transactional(readOnly = true) public class ChallengeService { private final ChallengeAdapter challengeAdapter; - private final MissionAdapter missionAdapter; - private final MemberMissionAdapter memberMissionAdapter; + private final MemberChallengeAdapter memberChallengeAdapter; - public GetChallengesByMemberResponse getChallengesByTheme(long memberId, long themeId) { - val challenges = challengeAdapter.findByThemeId(themeId); - val missions = missionAdapter.findByChallengeIds(challenges.stream().map(Challenge::getId).toList()); - val missionIds = missions.stream().map(Mission::getId).toList(); - val memberMissionIds = memberMissionAdapter.findByMemberIdAndMissionIds(memberId, missionIds).stream() - .map(MemberMission::getMissionId) + public ChallengesResponse getChallengesByTheme(long memberId, long themeId) { + val challenges = challengeAdapter.findAllByTheme(themeId); + val challengeIdsInMember = memberChallengeAdapter.findAllByMember(memberId) + .stream().map(MemberChallenge::getId) .toList(); - return GetChallengesByMemberResponse.of(toChallengesByMember(challenges, missions, memberMissionIds)); + return ChallengesResponse.of(challenges, challengeIdsInMember); } - private Map>> toChallengesByMember( - List challenges, - List missions, - List memberMissionIds - ) { - return challenges.stream().collect(Collectors.toMap( - // challenge-key - challenge -> challenge, - // map-value - challenge -> missions.stream() - .filter(mission -> mission.getChallengeId() == challenge.getId()) - .collect(Collectors.partitioningBy( // missionId in memberMissionIds 조건에 따라 true/false 분류 - mission -> memberMissionIds.contains(mission.getId()) - )) - )); - } } From 2cc7c02a97a621766acd72d9ad56666726b1c9cd Mon Sep 17 00:00:00 2001 From: thguss Date: Mon, 16 Dec 2024 22:30:20 +0900 Subject: [PATCH 03/24] fix: updated challenge --- .../soptie/server/api/controller/ChallengeApi.java | 9 +++------ .../server/api/controller/docs/ChallengeApiDocs.java | 12 ++++++------ 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/soptie/server/api/controller/ChallengeApi.java b/src/main/java/com/soptie/server/api/controller/ChallengeApi.java index 827399bd..379cfe9d 100644 --- a/src/main/java/com/soptie/server/api/controller/ChallengeApi.java +++ b/src/main/java/com/soptie/server/api/controller/ChallengeApi.java @@ -11,7 +11,7 @@ import com.soptie.server.api.controller.docs.ChallengeApiDocs; import com.soptie.server.api.controller.dto.response.SuccessResponse; -import com.soptie.server.api.controller.dto.response.challenge.GetChallengesByMemberResponse; +import com.soptie.server.api.controller.dto.response.challenge.ChallengesResponse; import com.soptie.server.api.controller.generic.SuccessMessage; import com.soptie.server.domain.challenge.ChallengeService; @@ -20,16 +20,13 @@ @RestController @RequiredArgsConstructor -@RequestMapping("/api/v2/routines/challenge") +@RequestMapping("/api/v2/challenge") public class ChallengeApi implements ChallengeApiDocs { private final ChallengeService challengeService; @ResponseStatus(HttpStatus.OK) @GetMapping - public SuccessResponse getChallengesByTheme( - Principal principal, - @RequestParam long themeId - ) { + public SuccessResponse getChallengesByTheme(Principal principal, @RequestParam long themeId) { val memberId = Long.parseLong(principal.getName()); val response = challengeService.getChallengesByTheme(memberId, themeId); return SuccessResponse.success(SuccessMessage.GET_CHALLENGE.getMessage(), response); diff --git a/src/main/java/com/soptie/server/api/controller/docs/ChallengeApiDocs.java b/src/main/java/com/soptie/server/api/controller/docs/ChallengeApiDocs.java index cc2c4b57..2ac4d946 100644 --- a/src/main/java/com/soptie/server/api/controller/docs/ChallengeApiDocs.java +++ b/src/main/java/com/soptie/server/api/controller/docs/ChallengeApiDocs.java @@ -6,7 +6,7 @@ import com.soptie.server.api.controller.dto.response.ErrorResponse; import com.soptie.server.api.controller.dto.response.SuccessResponse; -import com.soptie.server.api.controller.dto.response.challenge.GetChallengesByMemberResponse; +import com.soptie.server.api.controller.dto.response.challenge.ChallengesResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -16,12 +16,12 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; -@Tag(name = "[Challenge] 도전 루틴 API", description = "도전 루틴 API version2") +@Tag(name = "[Challenge] 챌린지 API", description = "챌린지 API version2") public interface ChallengeApiDocs { @Operation( - summary = "테마별 도전 루틴 목록 조회", - description = "테마에 해당되는 도전 루틴 목록을 조회한다.", + summary = "테마별 챌린지 목록 조회", + description = "테마별 챌린지 목록을 조회한다.", responses = { @ApiResponse(responseCode = "200", description = "성공"), @ApiResponse( @@ -33,11 +33,11 @@ public interface ChallengeApiDocs { description = "서버 내부 오류", content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} ) - SuccessResponse getChallengesByTheme( + SuccessResponse getChallengesByTheme( @Parameter(hidden = true) Principal principal, @Parameter( name = "themeId", - description = "조회할 도전 루틴 테마 id", + description = "조회하려는 테마 id", in = ParameterIn.QUERY, example = "1" ) @RequestParam long themeId From 86a110016ab3d4b4b5c57ede8d17219184304ccc Mon Sep 17 00:00:00 2001 From: thguss Date: Mon, 16 Dec 2024 22:30:45 +0900 Subject: [PATCH 04/24] delete: deleted unused file --- .../repository/mission/ChallengeRepository.java | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 src/main/java/com/soptie/server/persistence/repository/mission/ChallengeRepository.java diff --git a/src/main/java/com/soptie/server/persistence/repository/mission/ChallengeRepository.java b/src/main/java/com/soptie/server/persistence/repository/mission/ChallengeRepository.java deleted file mode 100644 index 056dceb9..00000000 --- a/src/main/java/com/soptie/server/persistence/repository/mission/ChallengeRepository.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.soptie.server.persistence.repository.mission; - -import java.util.List; - -import org.springframework.data.jpa.repository.JpaRepository; - -import com.soptie.server.persistence.entity.mission.ChallengeEntity; - -public interface ChallengeRepository extends JpaRepository { - List findByThemeId(long themeId); -} From b18afa6cf004f199122811693e791e2119f9be71 Mon Sep 17 00:00:00 2001 From: thguss Date: Mon, 16 Dec 2024 22:30:50 +0900 Subject: [PATCH 05/24] delete: deleted unused file --- .../GetChallengesByMemberResponse.java | 89 ------------------- .../adapter/mission/MemberMissionAdapter.java | 79 ---------------- .../adapter/mission/MissionAdapter.java | 37 -------- 3 files changed, 205 deletions(-) delete mode 100644 src/main/java/com/soptie/server/api/controller/dto/response/challenge/GetChallengesByMemberResponse.java delete mode 100644 src/main/java/com/soptie/server/persistence/adapter/mission/MemberMissionAdapter.java delete mode 100644 src/main/java/com/soptie/server/persistence/adapter/mission/MissionAdapter.java diff --git a/src/main/java/com/soptie/server/api/controller/dto/response/challenge/GetChallengesByMemberResponse.java b/src/main/java/com/soptie/server/api/controller/dto/response/challenge/GetChallengesByMemberResponse.java deleted file mode 100644 index a11bcacc..00000000 --- a/src/main/java/com/soptie/server/api/controller/dto/response/challenge/GetChallengesByMemberResponse.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.soptie.server.api.controller.dto.response.challenge; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import com.soptie.server.domain.challenge.Challenge; -import com.soptie.server.domain.challenge.Mission; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.val; - -@Builder(access = AccessLevel.PRIVATE) -public record GetChallengesByMemberResponse( - @Schema(description = "도전루틴 정보 목록") - @NotNull List routines -) { - - public static GetChallengesByMemberResponse of(Map>> challengeByMember) { - return GetChallengesByMemberResponse.builder() - .routines(toChallenges(challengeByMember)) - .build(); - } - - private static List toChallenges( - Map>> challengeByMember - ) { - return challengeByMember.entrySet().stream() - .map(entry -> ChallengeResponse.of(entry.getKey(), entry.getValue())) - .toList(); - } - - @Builder(access = AccessLevel.PRIVATE) - private record ChallengeResponse( - @Schema(description = "도전루틴 제목", example = "오래가는 인연을 위한 준비") - @NotNull String title, - @Schema(description = "미션 정보 목록") - @NotNull List challenges - ) { - - private static ChallengeResponse of(Challenge challenge, Map> missionsByMember) { - return ChallengeResponse.builder() - .title(challenge.getName()) - .challenges(ofMissions(missionsByMember)) - .build(); - } - - private static List ofMissions(Map> missionsByMember) { - val missions = new ArrayList(); - for (val key : missionsByMember.keySet()) { - missions.addAll(missionsByMember.get(key).stream() - .map(mission -> MissionResponse.of(mission, key)) - .toList()); - } - return missions; - } - } - - @Builder(access = AccessLevel.PRIVATE) - private record MissionResponse( - @Schema(description = "미션(도전루틴) id", example = "1") - long challengeId, - @Schema(description = "미션 내용", example = "나의 소통 방식을 파악하기") - @NotNull String content, - @Schema(description = "미션 설명", example = "이상형의 특성을 생각해보고 ...더보기") - @NotNull String description, - @Schema(description = "소요 시간", example = "5~10분") - @NotNull String requiredTime, - @Schema(description = "장소", example = "퇴근길") - @NotNull String place, - @Schema(description = "미션 추가 여부", example = "true") - boolean hasRoutine - ) { - - private static MissionResponse of(Mission mission, boolean existedInMember) { - return MissionResponse.builder() - .challengeId(mission.getId()) - .content(mission.getContent()) - .description(mission.getDescription()) - .requiredTime(mission.getRequiredTime()) - .place(mission.getPlace()) - .hasRoutine(existedInMember) - .build(); - } - } -} diff --git a/src/main/java/com/soptie/server/persistence/adapter/mission/MemberMissionAdapter.java b/src/main/java/com/soptie/server/persistence/adapter/mission/MemberMissionAdapter.java deleted file mode 100644 index d8ce342e..00000000 --- a/src/main/java/com/soptie/server/persistence/adapter/mission/MemberMissionAdapter.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.soptie.server.persistence.adapter.mission; - -import java.util.List; -import java.util.Optional; - -import com.soptie.server.common.exception.ExceptionCode; -import com.soptie.server.common.exception.SoftieException; -import com.soptie.server.common.support.RepositoryAdapter; -import com.soptie.server.domain.challenge.Mission; -import com.soptie.server.domain.member.Member; -import com.soptie.server.domain.membermission.MemberMission; -import com.soptie.server.persistence.entity.mission.MemberMissionEntity; -import com.soptie.server.persistence.repository.mission.MemberMissionRepository; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@RepositoryAdapter -@RequiredArgsConstructor -public class MemberMissionAdapter { - private final MemberMissionRepository memberMissionRepository; - - public List findByMemberIdAndMissionIds(long memberId, List missionIds) { - return memberMissionRepository.findByMemberIdAndMissionIdIn(memberId, missionIds) - .stream().map(MemberMissionEntity::toDomain) - .toList(); - } - - public void deleteAllByMemberId(long memberId) { - memberMissionRepository.deleteAllByMemberId(memberId); - } - - public Optional findByMember(long memberId) { - return memberMissionRepository.findByMemberId(memberId).map(MemberMissionEntity::toDomain); - } - - public void delete(MemberMission memberMission) { - val memberMissionEntity = find(memberMission.getId()); - memberMissionRepository.delete(memberMissionEntity); - } - - public void update(MemberMission memberMission) { - val memberMissionEntity = find(memberMission.getId()); - memberMissionEntity.update(memberMission); - } - - public MemberMission save(Member member, Mission mission) { - val deletedMemberMissions = memberMissionRepository.findDeletedByMemberId(member.getId()); - val deletedMemberMissionIds = deletedMemberMissions.stream().map(MemberMissionEntity::getMissionId).toList(); - return (deletedMemberMissionIds.contains(mission.getId()) - ? restore(deletedMemberMissions, member, mission) - : memberMissionRepository.save(new MemberMissionEntity(member, mission))) - .toDomain(); - } - - public void flush() { - memberMissionRepository.flush(); - } - - private MemberMissionEntity restore( - List deletedMemberMissions, - Member member, - Mission mission - ) { - val deletedMemberMission = deletedMemberMissions.stream() - .filter(mm -> mm.getMissionId() == mission.getId()) - .findFirst() - .orElseThrow(() -> new SoftieException( - ExceptionCode.NOT_FOUND, - "Member ID: " + member.getId() + " Mission ID: " + mission.getId())); - deletedMemberMission.restore(); - return deletedMemberMission; - } - - private MemberMissionEntity find(long id) { - return memberMissionRepository.findById(id) - .orElseThrow(() -> new SoftieException(ExceptionCode.NOT_FOUND, "MemberMission ID: " + id)); - } -} diff --git a/src/main/java/com/soptie/server/persistence/adapter/mission/MissionAdapter.java b/src/main/java/com/soptie/server/persistence/adapter/mission/MissionAdapter.java deleted file mode 100644 index 6e0eb886..00000000 --- a/src/main/java/com/soptie/server/persistence/adapter/mission/MissionAdapter.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.soptie.server.persistence.adapter.mission; - -import java.util.List; - -import com.soptie.server.common.exception.ExceptionCode; -import com.soptie.server.common.exception.SoftieException; -import com.soptie.server.common.support.RepositoryAdapter; -import com.soptie.server.domain.challenge.Mission; -import com.soptie.server.persistence.entity.mission.MissionEntity; -import com.soptie.server.persistence.repository.mission.MissionRepository; - -import lombok.RequiredArgsConstructor; - -@RepositoryAdapter -@RequiredArgsConstructor -public class MissionAdapter { - private final MissionRepository missionRepository; - - public List findByChallengeIds(List challengeIds) { - return missionRepository.findByChallengeIdIn(challengeIds) - .stream().map(MissionEntity::toDomain) - .toList(); - } - - public Mission findById(long missionId) { - return find(missionId).toDomain(); - } - - public List findByIds(List ids) { - return missionRepository.findByIdIn(ids).stream().map(MissionEntity::toDomain).toList(); - } - - private MissionEntity find(long id) { - return missionRepository.findById(id) - .orElseThrow(() -> new SoftieException(ExceptionCode.NOT_FOUND, "Mission ID: " + id)); - } -} From 5f957b86acf8e693f4b810de2ae197c6441ff4d1 Mon Sep 17 00:00:00 2001 From: thguss Date: Mon, 16 Dec 2024 22:31:31 +0900 Subject: [PATCH 06/24] fix: updated challenge --- .../challenge/ChallengesResponse.java | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/main/java/com/soptie/server/api/controller/dto/response/challenge/ChallengesResponse.java diff --git a/src/main/java/com/soptie/server/api/controller/dto/response/challenge/ChallengesResponse.java b/src/main/java/com/soptie/server/api/controller/dto/response/challenge/ChallengesResponse.java new file mode 100644 index 00000000..a9647402 --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/dto/response/challenge/ChallengesResponse.java @@ -0,0 +1,52 @@ +package com.soptie.server.api.controller.dto.response.challenge; + +import java.util.List; + +import com.soptie.server.domain.challenge.Challenge; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.AccessLevel; +import lombok.Builder; + +@Builder(access = AccessLevel.PRIVATE) +public record ChallengesResponse( + @Schema(description = "챌린지 정보 목록") + @NotNull List challenges +) { + + public static ChallengesResponse of(List challenges, List challengeIdsInMember) { + return ChallengesResponse.builder() + .challenges(challenges.stream() + .map(it -> ChallengeResponse.of(it, challengeIdsInMember)).toList()) + .build(); + } + + @Builder(access = AccessLevel.PRIVATE) + private record ChallengeResponse( + @Schema(description = "챌린지 id", example = "1") + long challengeId, + @Schema(description = "챌린지 내용", example = "나의 소통 방식을 파악하기") + @NotNull String content, + @Schema(description = "챌린지 설명", example = "이상형의 특성을 생각해보고 ...더보기") + @NotNull String description, + @Schema(description = "소요 시간", example = "5~10분") + @NotNull String requiredTime, + @Schema(description = "장소", example = "퇴근길") + @NotNull String place, + @Schema(description = "추가된 여부", example = "true") + boolean hasRoutine + ) { + + private static ChallengeResponse of(Challenge challenge, List challengeIdsInMember) { + return ChallengeResponse.builder() + .challengeId(challenge.getId()) + .content(challenge.getContent()) + .description(challenge.getDescription()) + .requiredTime(challenge.getRequiredTime()) + .place(challenge.getPlace()) + .hasRoutine(challengeIdsInMember.contains(challenge.getId())) + .build(); + } + } +} From 3b86ba9a0cbf436e49e98aa61a7602f24638fc65 Mon Sep 17 00:00:00 2001 From: thguss Date: Mon, 16 Dec 2024 22:34:48 +0900 Subject: [PATCH 07/24] fix: updated prefix --- .../java/com/soptie/server/api/controller/ChallengeApi.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/soptie/server/api/controller/ChallengeApi.java b/src/main/java/com/soptie/server/api/controller/ChallengeApi.java index 379cfe9d..3b1d007b 100644 --- a/src/main/java/com/soptie/server/api/controller/ChallengeApi.java +++ b/src/main/java/com/soptie/server/api/controller/ChallengeApi.java @@ -20,7 +20,7 @@ @RestController @RequiredArgsConstructor -@RequestMapping("/api/v2/challenge") +@RequestMapping("/api/v2/challenges") public class ChallengeApi implements ChallengeApiDocs { private final ChallengeService challengeService; From dbdde1f148075a79f220d93563141ced4df4cb16 Mon Sep 17 00:00:00 2001 From: thguss Date: Mon, 16 Dec 2024 23:10:05 +0900 Subject: [PATCH 08/24] fix: updated prefix --- .../CreateMemberChallengeRequest.java | 9 +++++++++ .../CreateMemberMissionRequest.java | 9 --------- .../CreateMemberChallengeResponse.java | 20 +++++++++++++++++++ .../CreateMemberMissionResponse.java | 20 ------------------- 4 files changed, 29 insertions(+), 29 deletions(-) create mode 100644 src/main/java/com/soptie/server/api/controller/dto/request/membermission/CreateMemberChallengeRequest.java delete mode 100644 src/main/java/com/soptie/server/api/controller/dto/request/membermission/CreateMemberMissionRequest.java create mode 100644 src/main/java/com/soptie/server/api/controller/dto/response/membermission/CreateMemberChallengeResponse.java delete mode 100644 src/main/java/com/soptie/server/api/controller/dto/response/membermission/CreateMemberMissionResponse.java diff --git a/src/main/java/com/soptie/server/api/controller/dto/request/membermission/CreateMemberChallengeRequest.java b/src/main/java/com/soptie/server/api/controller/dto/request/membermission/CreateMemberChallengeRequest.java new file mode 100644 index 00000000..4bfe04cf --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/dto/request/membermission/CreateMemberChallengeRequest.java @@ -0,0 +1,9 @@ +package com.soptie.server.api.controller.dto.request.membermission; + +import io.swagger.v3.oas.annotations.media.Schema; + +public record CreateMemberChallengeRequest( + @Schema(description = "추가하려는 챌린지 id", example = "1") + long challengeId +) { +} diff --git a/src/main/java/com/soptie/server/api/controller/dto/request/membermission/CreateMemberMissionRequest.java b/src/main/java/com/soptie/server/api/controller/dto/request/membermission/CreateMemberMissionRequest.java deleted file mode 100644 index 67d89bda..00000000 --- a/src/main/java/com/soptie/server/api/controller/dto/request/membermission/CreateMemberMissionRequest.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.soptie.server.api.controller.dto.request.membermission; - -import io.swagger.v3.oas.annotations.media.Schema; - -public record CreateMemberMissionRequest( - @Schema(description = "미션(도전루틴) id", example = "1") - long subRoutineId -) { -} diff --git a/src/main/java/com/soptie/server/api/controller/dto/response/membermission/CreateMemberChallengeResponse.java b/src/main/java/com/soptie/server/api/controller/dto/response/membermission/CreateMemberChallengeResponse.java new file mode 100644 index 00000000..cae360f3 --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/dto/response/membermission/CreateMemberChallengeResponse.java @@ -0,0 +1,20 @@ +package com.soptie.server.api.controller.dto.response.membermission; + +import com.soptie.server.domain.membermission.MemberChallenge; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AccessLevel; +import lombok.Builder; + +@Builder(access = AccessLevel.PRIVATE) +public record CreateMemberChallengeResponse( + @Schema(description = "추가한 회원의 챌린지 id", example = "1") + long memberChallengeId +) { + + public static CreateMemberChallengeResponse of(MemberChallenge memberChallenge) { + return CreateMemberChallengeResponse.builder() + .memberChallengeId(memberChallenge.getId()) + .build(); + } +} diff --git a/src/main/java/com/soptie/server/api/controller/dto/response/membermission/CreateMemberMissionResponse.java b/src/main/java/com/soptie/server/api/controller/dto/response/membermission/CreateMemberMissionResponse.java deleted file mode 100644 index b56368fa..00000000 --- a/src/main/java/com/soptie/server/api/controller/dto/response/membermission/CreateMemberMissionResponse.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.soptie.server.api.controller.dto.response.membermission; - -import com.soptie.server.domain.membermission.MemberMission; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AccessLevel; -import lombok.Builder; - -@Builder(access = AccessLevel.PRIVATE) -public record CreateMemberMissionResponse( - @Schema(description = "추가한 회원의 미션 id", example = "1") - long routineId -) { - - public static CreateMemberMissionResponse of(MemberMission memberMission) { - return CreateMemberMissionResponse.builder() - .routineId(memberMission.getId()) - .build(); - } -} From 07e80844412100628f92be3637898050a6fdc1d4 Mon Sep 17 00:00:00 2001 From: thguss Date: Mon, 16 Dec 2024 23:32:01 +0900 Subject: [PATCH 09/24] fix: updated challenge --- .../api/controller/MemberChallengeApi.java | 75 +++++++++++ .../docs/MemberChallengeApiDocs.java | 121 ++++++++++++++++++ ...emberMission.java => MemberChallenge.java} | 10 +- 3 files changed, 202 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/soptie/server/api/controller/MemberChallengeApi.java create mode 100644 src/main/java/com/soptie/server/api/controller/docs/MemberChallengeApiDocs.java rename src/main/java/com/soptie/server/domain/membermission/{MemberMission.java => MemberChallenge.java} (53%) diff --git a/src/main/java/com/soptie/server/api/controller/MemberChallengeApi.java b/src/main/java/com/soptie/server/api/controller/MemberChallengeApi.java new file mode 100644 index 00000000..06d4f2b9 --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/MemberChallengeApi.java @@ -0,0 +1,75 @@ +package com.soptie.server.api.controller; + +import java.security.Principal; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +import com.soptie.server.api.controller.docs.MemberChallengeApiDocs; +import com.soptie.server.api.controller.dto.request.membermission.CreateMemberChallengeRequest; +import com.soptie.server.api.controller.dto.response.SuccessResponse; +import com.soptie.server.api.controller.dto.response.membermission.CreateMemberChallengeResponse; +import com.soptie.server.api.controller.generic.SuccessMessage; +import com.soptie.server.domain.membermission.MemberChallengeService; + +import lombok.RequiredArgsConstructor; +import lombok.val; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v2/members/challenges") +public class MemberChallengeApi implements MemberChallengeApiDocs { + private final MemberChallengeService memberChallengeService; + + @GetMapping + public ResponseEntity getMemberChallenge(Principal principal) { + val memberId = Long.parseLong(principal.getName()); + return memberChallengeService.getMemberChallenge(memberId) + .map(response -> + ResponseEntity.ok(SuccessResponse.success(SuccessMessage.GET_ROUTINE.getMessage(), response))) + .orElseGet(() -> ResponseEntity.noContent().build()); + } + + @ResponseStatus(HttpStatus.CREATED) + @PostMapping + public SuccessResponse createMemberChallenge( + Principal principal, + @RequestBody CreateMemberChallengeRequest request + ) { + val memberId = Long.parseLong(principal.getName()); + val response = memberChallengeService.createMemberChallenge(memberId, request); + return SuccessResponse.success(SuccessMessage.CREATE_ROUTINE.getMessage(), response); + } + + @ResponseStatus(HttpStatus.OK) + @DeleteMapping + public SuccessResponse deleteMemberChallenge(Principal principal) { + val memberId = Long.parseLong(principal.getName()); + memberChallengeService.deleteMemberChallenge(memberId); + return SuccessResponse.success(SuccessMessage.DELETE_ROUTINE.getMessage()); + } + + @ResponseStatus(HttpStatus.OK) + @PatchMapping("/achievement") + public SuccessResponse achieveMemberChallenge(Principal principal) { + val memberId = Long.parseLong(principal.getName()); + memberChallengeService.achieveMemberChallenge(memberId); + return SuccessResponse.success(SuccessMessage.ACHIEVE_ROUTINE.getMessage()); + } + + @ResponseStatus(HttpStatus.OK) + @DeleteMapping("/history/{historyId}") + public SuccessResponse deleteHistory(@PathVariable long historyId) { + memberChallengeService.deleteHistory(historyId); + return SuccessResponse.success(SuccessMessage.DELETE_ROUTINE.getMessage()); + } +} diff --git a/src/main/java/com/soptie/server/api/controller/docs/MemberChallengeApiDocs.java b/src/main/java/com/soptie/server/api/controller/docs/MemberChallengeApiDocs.java new file mode 100644 index 00000000..cec0ce35 --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/docs/MemberChallengeApiDocs.java @@ -0,0 +1,121 @@ +package com.soptie.server.api.controller.docs; + +import java.security.Principal; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; + +import com.soptie.server.api.controller.dto.request.membermission.CreateMemberChallengeRequest; +import com.soptie.server.api.controller.dto.response.ErrorResponse; +import com.soptie.server.api.controller.dto.response.SuccessResponse; +import com.soptie.server.api.controller.dto.response.membermission.CreateMemberChallengeResponse; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; + +@Tag(name = "[MemberChallenge] 회원 챌린지 API", description = "회원 챌린지 API version2") +public interface MemberChallengeApiDocs { + + @Operation( + summary = "회원 챌린지 조회", + description = "회원의 챌린지를 조회한다.", + responses = { + @ApiResponse(responseCode = "200", description = "OK success"), + @ApiResponse(responseCode = "204", description = "NoContent success"), + @ApiResponse( + responseCode = "4xx", + description = "클라이언트(요청) 오류", + content = @Content(schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse( + responseCode = "500", + description = "서버 내부 오류", + content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} + ) + ResponseEntity getMemberChallenge( + @Parameter(hidden = true) Principal principal + ); + + @Operation( + summary = "회원 챌린지 추가", + description = "회원의 챌린지를 추가한다.", + responses = { + @ApiResponse(responseCode = "201", description = "Created success"), + @ApiResponse( + responseCode = "4xx", + description = "클라이언트(요청) 오류", + content = @Content(schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse( + responseCode = "500", + description = "서버 내부 오류", + content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} + ) + SuccessResponse createMemberChallenge( + @Parameter(hidden = true) Principal principal, + @RequestBody CreateMemberChallengeRequest request + ); + + @Operation( + summary = "회원 챌린지 삭제", + description = "회원의 챌린지를 삭제한다.", + responses = { + @ApiResponse(responseCode = "200", description = "성공"), + @ApiResponse( + responseCode = "4xx", + description = "클라이언트(요청) 오류", + content = @Content(schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse( + responseCode = "500", + description = "서버 내부 오류", + content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} + ) + SuccessResponse deleteMemberChallenge( + @Parameter(hidden = true) Principal principal + ); + + @Operation( + summary = "회원 챌린지 달성", + description = "회원의 챌린지를 달성한다.", + responses = { + @ApiResponse(responseCode = "200", description = "성공"), + @ApiResponse( + responseCode = "4xx", + description = "클라이언트(요청) 오류", + content = @Content(schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse( + responseCode = "500", + description = "서버 내부 오류", + content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} + ) + SuccessResponse achieveMemberChallenge( + @Parameter(hidden = true) Principal principal + ); + + @Operation( + summary = "챌린지 기록 삭제", + description = "달성한 챌린지 기록을 삭제합니다.", + responses = { + @ApiResponse(responseCode = "200", description = "성공"), + @ApiResponse( + responseCode = "4xx", + description = "클라이언트(요청) 오류", + content = @Content(schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse( + responseCode = "500", + description = "서버 내부 오류", + content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} + ) + SuccessResponse deleteHistory( + @Parameter( + name = "historyId", + description = "삭제하려는 이력 id", + in = ParameterIn.PATH, + example = "1" + ) @PathVariable long historyId + ); +} diff --git a/src/main/java/com/soptie/server/domain/membermission/MemberMission.java b/src/main/java/com/soptie/server/domain/membermission/MemberChallenge.java similarity index 53% rename from src/main/java/com/soptie/server/domain/membermission/MemberMission.java rename to src/main/java/com/soptie/server/domain/membermission/MemberChallenge.java index fdb6f549..88d3d769 100644 --- a/src/main/java/com/soptie/server/domain/membermission/MemberMission.java +++ b/src/main/java/com/soptie/server/domain/membermission/MemberChallenge.java @@ -5,13 +5,15 @@ @Builder @Getter -public class MemberMission { +public class MemberChallenge { private Long id; - private int achievementCount; + private int achievedCount; + private boolean achieved; + private long challengeId; private long memberId; - private long missionId; public void achieve() { - this.achievementCount++; + this.achievedCount++; + this.achieved = true; } } From f9e1a78f333bb0f6b4cd290bd093190870f2e17a Mon Sep 17 00:00:00 2001 From: thguss Date: Mon, 16 Dec 2024 23:32:16 +0900 Subject: [PATCH 10/24] delete: deleted unused file --- .../api/controller/MemberMissionApi.java | 64 ---------- .../api/controller/MemberMissionApiV2.java | 32 ----- .../controller/docs/MemberMissionApiDocs.java | 114 ------------------ .../docs/MemberMissionApiV2Docs.java | 37 ------ .../GetMemberMissionResponse.java | 47 -------- .../entity/mission/MemberMissionEntity.java | 60 --------- 6 files changed, 354 deletions(-) delete mode 100644 src/main/java/com/soptie/server/api/controller/MemberMissionApi.java delete mode 100644 src/main/java/com/soptie/server/api/controller/MemberMissionApiV2.java delete mode 100644 src/main/java/com/soptie/server/api/controller/docs/MemberMissionApiDocs.java delete mode 100644 src/main/java/com/soptie/server/api/controller/docs/MemberMissionApiV2Docs.java delete mode 100644 src/main/java/com/soptie/server/api/controller/dto/response/membermission/GetMemberMissionResponse.java delete mode 100644 src/main/java/com/soptie/server/persistence/entity/mission/MemberMissionEntity.java diff --git a/src/main/java/com/soptie/server/api/controller/MemberMissionApi.java b/src/main/java/com/soptie/server/api/controller/MemberMissionApi.java deleted file mode 100644 index 955f104c..00000000 --- a/src/main/java/com/soptie/server/api/controller/MemberMissionApi.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.soptie.server.api.controller; - -import java.security.Principal; - -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.PatchMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestController; - -import com.soptie.server.api.controller.docs.MemberMissionApiDocs; -import com.soptie.server.api.controller.dto.request.membermission.CreateMemberMissionRequest; -import com.soptie.server.api.controller.dto.response.SuccessResponse; -import com.soptie.server.api.controller.dto.response.membermission.CreateMemberMissionResponse; -import com.soptie.server.api.controller.generic.SuccessMessage; -import com.soptie.server.domain.membermission.MemberMissionService; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/v1/routines/happiness/member") -public class MemberMissionApi implements MemberMissionApiDocs { - private final MemberMissionService memberMissionService; - - @ResponseStatus(HttpStatus.CREATED) - @PostMapping - public SuccessResponse createMemberMission( - Principal principal, - @RequestBody CreateMemberMissionRequest request - ) { - val memberId = Long.parseLong(principal.getName()); - val response = memberMissionService.createMemberMission(memberId, request); - return SuccessResponse.success(SuccessMessage.CREATE_ROUTINE.getMessage(), response); - } - - @ResponseStatus(HttpStatus.OK) - @DeleteMapping("/routine/{routineId}") - public SuccessResponse deleteMemberMission(Principal principal, @PathVariable long routineId) { - val memberId = Long.parseLong(principal.getName()); - memberMissionService.deleteMemberMission(memberId, routineId); - return SuccessResponse.success(SuccessMessage.DELETE_ROUTINE.getMessage()); - } - - @ResponseStatus(HttpStatus.OK) - @PatchMapping("/routine/{routineId}") - public SuccessResponse achieveMemberMission(Principal principal, @PathVariable long routineId) { - val memberId = Long.parseLong(principal.getName()); - memberMissionService.achieveMemberMission(memberId, routineId); - return SuccessResponse.success(SuccessMessage.ACHIEVE_ROUTINE.getMessage()); - } - - @ResponseStatus(HttpStatus.OK) - @DeleteMapping("/history/{historyId}") - public SuccessResponse deleteMissionHistory(@PathVariable long historyId) { - memberMissionService.deleteHistory(historyId); - return SuccessResponse.success(SuccessMessage.DELETE_ROUTINE.getMessage()); - } -} diff --git a/src/main/java/com/soptie/server/api/controller/MemberMissionApiV2.java b/src/main/java/com/soptie/server/api/controller/MemberMissionApiV2.java deleted file mode 100644 index a5094be3..00000000 --- a/src/main/java/com/soptie/server/api/controller/MemberMissionApiV2.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.soptie.server.api.controller; - -import java.security.Principal; - -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.RestController; - -import com.soptie.server.api.controller.docs.MemberMissionApiV2Docs; -import com.soptie.server.api.controller.dto.response.SuccessResponse; -import com.soptie.server.api.controller.generic.SuccessMessage; -import com.soptie.server.domain.membermission.MemberMissionService; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/v2/routines/challenge/member") -public class MemberMissionApiV2 implements MemberMissionApiV2Docs { - private final MemberMissionService memberMissionService; - - @GetMapping - public ResponseEntity getMemberMission(Principal principal) { - val memberId = Long.parseLong(principal.getName()); - return memberMissionService.getMemberMission(memberId) - .map(response -> - ResponseEntity.ok(SuccessResponse.success(SuccessMessage.GET_ROUTINE.getMessage(), response))) - .orElseGet(() -> ResponseEntity.noContent().build()); - } -} diff --git a/src/main/java/com/soptie/server/api/controller/docs/MemberMissionApiDocs.java b/src/main/java/com/soptie/server/api/controller/docs/MemberMissionApiDocs.java deleted file mode 100644 index ff6cfafb..00000000 --- a/src/main/java/com/soptie/server/api/controller/docs/MemberMissionApiDocs.java +++ /dev/null @@ -1,114 +0,0 @@ -package com.soptie.server.api.controller.docs; - -import java.security.Principal; - -import org.springframework.web.bind.annotation.PathVariable; - -import com.soptie.server.api.controller.dto.request.membermission.CreateMemberMissionRequest; -import com.soptie.server.api.controller.dto.response.ErrorResponse; -import com.soptie.server.api.controller.dto.response.SuccessResponse; -import com.soptie.server.api.controller.dto.response.membermission.CreateMemberMissionResponse; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.enums.ParameterIn; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.parameters.RequestBody; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; - -@Tag(name = "[MemberMission] 회원의 도전 루틴", description = "회원의 도전 루틴 API") -public interface MemberMissionApiDocs { - - @Operation( - summary = "미션(도전 루틴) 추가", - description = "회원의 미션을 추가한다.", - responses = { - @ApiResponse(responseCode = "201", description = "Created success"), - @ApiResponse( - responseCode = "4xx", - description = "클라이언트(요청) 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "500", - description = "서버 내부 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} - ) - SuccessResponse createMemberMission( - @Parameter(hidden = true) Principal principal, - @RequestBody CreateMemberMissionRequest request - ); - - @Operation( - summary = "미션 삭제", - description = "회원의 미션을 삭제한다.", - responses = { - @ApiResponse(responseCode = "200", description = "성공"), - @ApiResponse( - responseCode = "4xx", - description = "클라이언트(요청) 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "500", - description = "서버 내부 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} - ) - SuccessResponse deleteMemberMission( - @Parameter(hidden = true) Principal principal, - @Parameter( - name = "routineId", - description = "삭제할 회원의 미션 id", - in = ParameterIn.PATH, - example = "1" - ) @PathVariable long routineId - ); - - @Operation( - summary = "미션 달성", - description = "회원의 미션을 달성한다.", - responses = { - @ApiResponse(responseCode = "200", description = "성공"), - @ApiResponse( - responseCode = "4xx", - description = "클라이언트(요청) 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "500", - description = "서버 내부 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} - ) - SuccessResponse achieveMemberMission( - @Parameter(hidden = true) Principal principal, - @Parameter( - name = "routineId", - description = "달성할 회원의 미션 id", - in = ParameterIn.PATH, - example = "1" - ) - @PathVariable long routineId - ); - - @Operation( - summary = "미션 기록 삭제", - description = "달성한 미션 기록을 삭제합니다.", - responses = { - @ApiResponse(responseCode = "200", description = "성공"), - @ApiResponse( - responseCode = "4xx", - description = "클라이언트(요청) 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "500", - description = "서버 내부 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} - ) - SuccessResponse deleteMissionHistory( - @Parameter( - name = "historyId", - description = "달성 이력 id", - in = ParameterIn.PATH, - example = "1" - ) @PathVariable long historyId - ); -} diff --git a/src/main/java/com/soptie/server/api/controller/docs/MemberMissionApiV2Docs.java b/src/main/java/com/soptie/server/api/controller/docs/MemberMissionApiV2Docs.java deleted file mode 100644 index b3083157..00000000 --- a/src/main/java/com/soptie/server/api/controller/docs/MemberMissionApiV2Docs.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.soptie.server.api.controller.docs; - -import java.security.Principal; - -import org.springframework.http.ResponseEntity; - -import com.soptie.server.api.controller.dto.response.ErrorResponse; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; - -@Tag(name = "[MemberMission] 회원의 도전 루틴 Version2", description = "회원의 도전 루틴 API Version2") -public interface MemberMissionApiV2Docs { - - @Operation( - summary = "회원의 도전 루틴 조회", - description = "회원의 도전 루틴을 조회한다.", - responses = { - @ApiResponse(responseCode = "200", description = "OK success"), - @ApiResponse(responseCode = "204", description = "NoContent success"), - @ApiResponse( - responseCode = "4xx", - description = "클라이언트(요청) 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "500", - description = "서버 내부 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} - ) - ResponseEntity getMemberMission( - @Parameter(hidden = true) Principal principal - ); -} diff --git a/src/main/java/com/soptie/server/api/controller/dto/response/membermission/GetMemberMissionResponse.java b/src/main/java/com/soptie/server/api/controller/dto/response/membermission/GetMemberMissionResponse.java deleted file mode 100644 index 3dd70be5..00000000 --- a/src/main/java/com/soptie/server/api/controller/dto/response/membermission/GetMemberMissionResponse.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.soptie.server.api.controller.dto.response.membermission; - -import com.soptie.server.domain.challenge.Challenge; -import com.soptie.server.domain.challenge.Mission; -import com.soptie.server.domain.membermission.MemberMission; -import com.soptie.server.domain.theme.Theme; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.AccessLevel; -import lombok.Builder; - -@Builder(access = AccessLevel.PRIVATE) -public record GetMemberMissionResponse( - @Schema(description = "미션(도전루틴) id", example = "1") - long routineId, - @Schema(description = "테마 id", example = "1") - long themeId, - @Schema(description = "테마 이름", example = "관계 쌓기") - @NotNull String themeName, - @Schema(description = "도전 이름", example = "오래가는 인연을 위한 준비") - @NotNull String title, - @Schema(description = "미션 내용", example = "일어나면 5분 안에 이불 개기") - @NotNull String content, - @Schema(description = "미션 상세 내용", example = "평소에 바빠서 ...더보기") - @NotNull String detailContent, - @Schema(description = "장소", example = "침대") - @NotNull String place, - @Schema(description = "소요시간", example = "3분") - @NotNull String timeTaken -) { - - public static GetMemberMissionResponse of( - MemberMission memberMission, Theme theme, Challenge challenge, Mission mission - ) { - return GetMemberMissionResponse.builder() - .routineId(memberMission.getId()) - .themeId(theme.getId()) - .themeName(theme.getName()) - .title(challenge.getName()) - .content(mission.getContent()) - .detailContent(mission.getDescription()) - .place(mission.getPlace()) - .timeTaken(mission.getRequiredTime()) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/persistence/entity/mission/MemberMissionEntity.java b/src/main/java/com/soptie/server/persistence/entity/mission/MemberMissionEntity.java deleted file mode 100644 index 66e4d69e..00000000 --- a/src/main/java/com/soptie/server/persistence/entity/mission/MemberMissionEntity.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.soptie.server.persistence.entity.mission; - -import org.hibernate.annotations.SQLDelete; -import org.hibernate.annotations.SQLRestriction; - -import com.soptie.server.domain.challenge.Mission; -import com.soptie.server.domain.member.Member; -import com.soptie.server.domain.membermission.MemberMission; -import com.soptie.server.persistence.entity.BaseEntity; - -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.Table; -import jakarta.persistence.UniqueConstraint; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Entity -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@SQLRestriction("is_deleted = false") -@SQLDelete(sql = "UPDATE softie.member_mission SET is_deleted = true WHERE id = ?") -@Table( - name = "member_mission", - schema = "softie", - uniqueConstraints = @UniqueConstraint(columnNames = {"member_id", "mission_id"})) -public class MemberMissionEntity extends BaseEntity { - @Column(nullable = false) - private int achievementCount; - @Column(nullable = false) - private boolean isDeleted; - @Column(nullable = false) - private long memberId; - @Column(nullable = false) - private long missionId; - - public MemberMissionEntity(Member member, Mission mission) { - this.achievementCount = 0; - this.memberId = member.getId(); - this.missionId = mission.getId(); - } - - public MemberMission toDomain() { - return MemberMission.builder() - .id(this.id) - .achievementCount(this.achievementCount) - .memberId(this.memberId) - .missionId(this.missionId) - .build(); - } - - public void update(MemberMission memberMission) { - this.achievementCount += memberMission.getAchievementCount(); - } - - public void restore() { - this.isDeleted = false; - } -} From 29b580a40556aa6651dbd2c5bc467c3661fc622a Mon Sep 17 00:00:00 2001 From: thguss Date: Mon, 16 Dec 2024 23:33:18 +0900 Subject: [PATCH 11/24] fix: updated package --- .../adapter/challenge/ChallengeAdapter.java | 41 +++++++++++++++++++ .../ChallengeHistoryAdapter.java} | 20 ++++----- 2 files changed, 51 insertions(+), 10 deletions(-) create mode 100644 src/main/java/com/soptie/server/persistence/adapter/challenge/ChallengeAdapter.java rename src/main/java/com/soptie/server/persistence/adapter/{mission/MissionHistoryAdapter.java => challenge/ChallengeHistoryAdapter.java} (55%) diff --git a/src/main/java/com/soptie/server/persistence/adapter/challenge/ChallengeAdapter.java b/src/main/java/com/soptie/server/persistence/adapter/challenge/ChallengeAdapter.java new file mode 100644 index 00000000..ee24e010 --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/adapter/challenge/ChallengeAdapter.java @@ -0,0 +1,41 @@ +package com.soptie.server.persistence.adapter.challenge; + +import java.util.List; + +import com.soptie.server.common.exception.ExceptionCode; +import com.soptie.server.common.exception.SoftieException; +import com.soptie.server.common.support.RepositoryAdapter; +import com.soptie.server.domain.challenge.Challenge; +import com.soptie.server.persistence.entity.challenge.ChallengeEntity; +import com.soptie.server.persistence.repository.challenge.ChallengeRepository; + +import lombok.RequiredArgsConstructor; + +@RepositoryAdapter +@RequiredArgsConstructor +public class ChallengeAdapter { + private final ChallengeRepository challengeRepository; + + public List findAllByTheme(long themeId) { + return challengeRepository.findByThemeId(themeId).stream().map(ChallengeEntity::toDomain).toList(); + } + + public List findByChallengeIds(List challengeIds) { + return challengeRepository.findByChallengeIdIn(challengeIds) + .stream().map(ChallengeEntity::toDomain) + .toList(); + } + + public Challenge findById(long missionId) { + return find(missionId).toDomain(); + } + + public List findByIds(List ids) { + return challengeRepository.findByIdIn(ids).stream().map(ChallengeEntity::toDomain).toList(); + } + + private ChallengeEntity find(long id) { + return challengeRepository.findById(id) + .orElseThrow(() -> new SoftieException(ExceptionCode.NOT_FOUND, "Mission ID: " + id)); + } +} diff --git a/src/main/java/com/soptie/server/persistence/adapter/mission/MissionHistoryAdapter.java b/src/main/java/com/soptie/server/persistence/adapter/challenge/ChallengeHistoryAdapter.java similarity index 55% rename from src/main/java/com/soptie/server/persistence/adapter/mission/MissionHistoryAdapter.java rename to src/main/java/com/soptie/server/persistence/adapter/challenge/ChallengeHistoryAdapter.java index 2a6a4dd5..722b37c9 100644 --- a/src/main/java/com/soptie/server/persistence/adapter/mission/MissionHistoryAdapter.java +++ b/src/main/java/com/soptie/server/persistence/adapter/challenge/ChallengeHistoryAdapter.java @@ -1,4 +1,4 @@ -package com.soptie.server.persistence.adapter.mission; +package com.soptie.server.persistence.adapter.challenge; import java.time.LocalDate; import java.time.LocalDateTime; @@ -6,21 +6,21 @@ import org.springframework.stereotype.Component; -import com.soptie.server.domain.challenge.Mission; -import com.soptie.server.domain.membermission.MemberMission; +import com.soptie.server.domain.challenge.Challenge; +import com.soptie.server.domain.membermission.MemberChallenge; import com.soptie.server.domain.membermission.MissionHistory; -import com.soptie.server.persistence.entity.mission.MissionHistoryEntity; -import com.soptie.server.persistence.repository.mission.MissionHistoryRepository; +import com.soptie.server.persistence.entity.mission.ChallengeHistoryEntity; +import com.soptie.server.persistence.repository.mission.ChallengeHistoryRepository; import lombok.RequiredArgsConstructor; @Component @RequiredArgsConstructor -public class MissionHistoryAdapter { - private final MissionHistoryRepository historyRepository; +public class ChallengeHistoryAdapter { + private final ChallengeHistoryRepository historyRepository; - public void save(final MemberMission memberMission, final Mission mission) { - historyRepository.save(new MissionHistoryEntity(memberMission, mission)); + public void save(final MemberChallenge memberChallenge, final Challenge challenge) { + historyRepository.save(new ChallengeHistoryEntity(memberChallenge, challenge)); } public void deleteById(long historyId) { @@ -37,6 +37,6 @@ public List findAllByMemberIdAndCreatedAtBetween( final LocalDateTime endDateTime ) { return historyRepository.findAllByMemberIdAndCreatedAtBetween(memberId, startDateTime, endDateTime).stream() - .map(MissionHistoryEntity::toDomain).toList(); + .map(ChallengeHistoryEntity::toDomain).toList(); } } From c67c9d9191814e8ac1a31d8d543f0c43e6872b95 Mon Sep 17 00:00:00 2001 From: thguss Date: Mon, 16 Dec 2024 23:33:28 +0900 Subject: [PATCH 12/24] delete: deleted unused file --- .../membermission/MemberMissionService.java | 92 ------------------- 1 file changed, 92 deletions(-) delete mode 100644 src/main/java/com/soptie/server/domain/membermission/MemberMissionService.java diff --git a/src/main/java/com/soptie/server/domain/membermission/MemberMissionService.java b/src/main/java/com/soptie/server/domain/membermission/MemberMissionService.java deleted file mode 100644 index 9968c8ad..00000000 --- a/src/main/java/com/soptie/server/domain/membermission/MemberMissionService.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.soptie.server.domain.membermission; - -import java.util.Optional; - -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import com.soptie.server.api.controller.dto.request.membermission.CreateMemberMissionRequest; -import com.soptie.server.api.controller.dto.response.membermission.CreateMemberMissionResponse; -import com.soptie.server.api.controller.dto.response.membermission.GetMemberMissionResponse; -import com.soptie.server.common.exception.ExceptionCode; -import com.soptie.server.common.exception.SoftieException; -import com.soptie.server.persistence.adapter.MemberAdapter; -import com.soptie.server.persistence.adapter.ThemeAdapter; -import com.soptie.server.persistence.adapter.mission.ChallengeAdapter; -import com.soptie.server.persistence.adapter.mission.MemberMissionAdapter; -import com.soptie.server.persistence.adapter.mission.MissionAdapter; -import com.soptie.server.persistence.adapter.mission.MissionHistoryAdapter; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@Service -@RequiredArgsConstructor -@Transactional(readOnly = true) -public class MemberMissionService { - private final MemberMissionAdapter memberMissionAdapter; - private final ThemeAdapter themeAdapter; - private final ChallengeAdapter challengeAdapter; - private final MissionAdapter missionAdapter; - private final MemberAdapter memberAdapter; - private final MissionHistoryAdapter missionHistoryAdapter; - - @Transactional - public CreateMemberMissionResponse createMemberMission(long memberId, CreateMemberMissionRequest request) { - if (memberMissionAdapter.findByMember(memberId).isPresent()) { - throw new SoftieException(ExceptionCode.BAD_REQUEST, "이미 미션을 추가한 회원"); - } - val member = memberAdapter.findById(memberId); - val mission = missionAdapter.findById(request.subRoutineId()); - val savedMemberMission = memberMissionAdapter.save(member, mission); - return CreateMemberMissionResponse.of(savedMemberMission); - } - - @Transactional - public void deleteMemberMission(long memberId, long missionId) { - val memberMission = memberMissionAdapter.findByMember(memberId) - .orElseThrow(() -> new SoftieException(ExceptionCode.NOT_FOUND, "Member ID: " + memberId)); - if (memberMission.getId() != missionId) { - throw new SoftieException( - ExceptionCode.NOT_AVAILABLE, - "Member ID: " + memberId + ", Mission ID: " + missionId); - } - memberMissionAdapter.delete(memberMission); - } - - @Transactional - public void achieveMemberMission(long memberId, long missionId) { - val member = memberAdapter.findById(memberId); - val memberMission = memberMissionAdapter.findByMember(memberId) - .orElseThrow(() -> new SoftieException(ExceptionCode.NOT_FOUND, "Member ID: " + memberId)); - if (memberMission.getId() != missionId) { - throw new SoftieException( - ExceptionCode.NOT_AVAILABLE, - "Member ID: " + memberId + ", Mission ID: " + missionId); - } - val mission = missionAdapter.findById(memberMission.getMissionId()); - member.getCottonInfo().addRainbowCottonCount(); - memberAdapter.update(member); - memberMission.achieve(); - memberMissionAdapter.update(memberMission); - memberMissionAdapter.flush(); - memberMissionAdapter.delete(memberMission); - missionHistoryAdapter.save(memberMission, mission); - } - - public Optional getMemberMission(long memberId) { - return memberMissionAdapter.findByMember(memberId).map(this::toGetMemberMissionResponse); - } - - private GetMemberMissionResponse toGetMemberMissionResponse(MemberMission memberMission) { - val mission = missionAdapter.findById(memberMission.getMissionId()); - val challenge = challengeAdapter.findById(mission.getChallengeId()); - val theme = themeAdapter.findById(challenge.getThemeId()); - return GetMemberMissionResponse.of(memberMission, theme, challenge, mission); - } - - @Transactional - public void deleteHistory(long historyId) { - missionHistoryAdapter.deleteById(historyId); - } -} From 77eab1b6534d0ddb61a2720fb95a08a07dd66d65 Mon Sep 17 00:00:00 2001 From: thguss Date: Mon, 16 Dec 2024 23:34:00 +0900 Subject: [PATCH 13/24] fix: updated package --- .../challenge/MemberChallengeAdapter.java | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 src/main/java/com/soptie/server/persistence/adapter/challenge/MemberChallengeAdapter.java diff --git a/src/main/java/com/soptie/server/persistence/adapter/challenge/MemberChallengeAdapter.java b/src/main/java/com/soptie/server/persistence/adapter/challenge/MemberChallengeAdapter.java new file mode 100644 index 00000000..7abdfd8a --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/adapter/challenge/MemberChallengeAdapter.java @@ -0,0 +1,76 @@ +package com.soptie.server.persistence.adapter.challenge; + +import java.util.List; +import java.util.Optional; + +import com.soptie.server.common.exception.ExceptionCode; +import com.soptie.server.common.exception.SoftieException; +import com.soptie.server.common.support.RepositoryAdapter; +import com.soptie.server.domain.challenge.Challenge; +import com.soptie.server.domain.member.Member; +import com.soptie.server.domain.membermission.MemberChallenge; +import com.soptie.server.persistence.entity.mission.MemberChallengeEntity; +import com.soptie.server.persistence.repository.mission.MemberChallengeRepository; + +import lombok.RequiredArgsConstructor; +import lombok.val; + +@RepositoryAdapter +@RequiredArgsConstructor +public class MemberChallengeAdapter { + private final MemberChallengeRepository memberChallengeRepository; + + public Optional findByMember(long memberId) { + return memberChallengeRepository.findByMemberIdAndAchievedIsFalse(memberId) + .map(MemberChallengeEntity::toDomain); + } + + public MemberChallenge save(Member member, Challenge challenge) { + val memberChallenge = memberChallengeRepository + .findByMemberIdAndChallengeIdAndAchievedTrue(member.getId(), challenge.getId()); + return memberChallenge + // 달성한 이력이 있는 회원 + .map(MemberChallengeEntity::restore) + // 처음 추가하는 회원 + .orElse(memberChallengeRepository.save(new MemberChallengeEntity(member, challenge))) + .toDomain(); + } + + public void delete(MemberChallenge memberChallenge) { + val memberChallengeEntity = find(memberChallenge.getId()); + memberChallengeEntity.delete(); + } + + public void deleteAllByMemberId(long memberId) { + memberChallengeRepository.deleteAllByMemberId(memberId); + } + + public void update(MemberChallenge memberChallenge) { + val memberMissionEntity = find(memberChallenge.getId()); + memberMissionEntity.update(memberChallenge); + } + + public void flush() { + memberChallengeRepository.flush(); + } + + private MemberChallengeEntity restore( + List deletedMemberMissions, + Member member, + Challenge challenge + ) { + val deletedMemberMission = deletedMemberMissions.stream() + .filter(mm -> mm.getMissionId() == challenge.getId()) + .findFirst() + .orElseThrow(() -> new SoftieException( + ExceptionCode.NOT_FOUND, + "Member ID: " + member.getId() + " Mission ID: " + challenge.getId())); + deletedMemberMission.restore(); + return deletedMemberMission; + } + + private MemberChallengeEntity find(long id) { + return memberChallengeRepository.findById(id) + .orElseThrow(() -> new SoftieException(ExceptionCode.NOT_FOUND, "MemberMission ID: " + id)); + } +} From 54cc309aa5a0df151a53b33b6cfa2f5be6e01eac Mon Sep 17 00:00:00 2001 From: thguss Date: Mon, 16 Dec 2024 23:34:54 +0900 Subject: [PATCH 14/24] delete: deleted unused method --- .../challenge/MemberChallengeAdapter.java | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/src/main/java/com/soptie/server/persistence/adapter/challenge/MemberChallengeAdapter.java b/src/main/java/com/soptie/server/persistence/adapter/challenge/MemberChallengeAdapter.java index 7abdfd8a..b629e50f 100644 --- a/src/main/java/com/soptie/server/persistence/adapter/challenge/MemberChallengeAdapter.java +++ b/src/main/java/com/soptie/server/persistence/adapter/challenge/MemberChallengeAdapter.java @@ -1,6 +1,5 @@ package com.soptie.server.persistence.adapter.challenge; -import java.util.List; import java.util.Optional; import com.soptie.server.common.exception.ExceptionCode; @@ -50,25 +49,6 @@ public void update(MemberChallenge memberChallenge) { memberMissionEntity.update(memberChallenge); } - public void flush() { - memberChallengeRepository.flush(); - } - - private MemberChallengeEntity restore( - List deletedMemberMissions, - Member member, - Challenge challenge - ) { - val deletedMemberMission = deletedMemberMissions.stream() - .filter(mm -> mm.getMissionId() == challenge.getId()) - .findFirst() - .orElseThrow(() -> new SoftieException( - ExceptionCode.NOT_FOUND, - "Member ID: " + member.getId() + " Mission ID: " + challenge.getId())); - deletedMemberMission.restore(); - return deletedMemberMission; - } - private MemberChallengeEntity find(long id) { return memberChallengeRepository.findById(id) .orElseThrow(() -> new SoftieException(ExceptionCode.NOT_FOUND, "MemberMission ID: " + id)); From c2143b7787c7a17b1cd3d17dd631503ade4ea431 Mon Sep 17 00:00:00 2001 From: thguss Date: Mon, 16 Dec 2024 23:35:46 +0900 Subject: [PATCH 15/24] fix: updated challenge --- .../ChallengeEntity.java} | 16 ++--- .../challenge/ChallengeHistoryEntity.java | 39 ++++++++++++ .../challenge/MemberChallengeEntity.java | 62 +++++++++++++++++++ .../entity/mission/MissionHistoryEntity.java | 39 ------------ 4 files changed, 109 insertions(+), 47 deletions(-) rename src/main/java/com/soptie/server/persistence/entity/{mission/MissionEntity.java => challenge/ChallengeEntity.java} (64%) create mode 100644 src/main/java/com/soptie/server/persistence/entity/challenge/ChallengeHistoryEntity.java create mode 100644 src/main/java/com/soptie/server/persistence/entity/challenge/MemberChallengeEntity.java delete mode 100644 src/main/java/com/soptie/server/persistence/entity/mission/MissionHistoryEntity.java diff --git a/src/main/java/com/soptie/server/persistence/entity/mission/MissionEntity.java b/src/main/java/com/soptie/server/persistence/entity/challenge/ChallengeEntity.java similarity index 64% rename from src/main/java/com/soptie/server/persistence/entity/mission/MissionEntity.java rename to src/main/java/com/soptie/server/persistence/entity/challenge/ChallengeEntity.java index 1ed25042..e6c349fd 100644 --- a/src/main/java/com/soptie/server/persistence/entity/mission/MissionEntity.java +++ b/src/main/java/com/soptie/server/persistence/entity/challenge/ChallengeEntity.java @@ -1,6 +1,6 @@ -package com.soptie.server.persistence.entity.mission; +package com.soptie.server.persistence.entity.challenge; -import com.soptie.server.domain.challenge.Mission; +import com.soptie.server.domain.challenge.Challenge; import com.soptie.server.persistence.entity.BaseEntity; import jakarta.persistence.Column; @@ -8,8 +8,8 @@ import jakarta.persistence.Table; @Entity -@Table(name = "mission", schema = "softie") -public class MissionEntity extends BaseEntity { +@Table(name = "challenge", schema = "softie") +public class ChallengeEntity extends BaseEntity { @Column(nullable = false) private String content; @Column(nullable = false) @@ -19,16 +19,16 @@ public class MissionEntity extends BaseEntity { @Column(nullable = false) private String place; @Column(nullable = false) - private long challengeId; + private long themeId; - public Mission toDomain() { - return Mission.builder() + public Challenge toDomain() { + return Challenge.builder() .id(this.id) .content(this.content) .description(this.description) .requiredTime(this.requiredTime) .place(this.place) - .challengeId(this.challengeId) + .themeId(this.themeId) .build(); } } diff --git a/src/main/java/com/soptie/server/persistence/entity/challenge/ChallengeHistoryEntity.java b/src/main/java/com/soptie/server/persistence/entity/challenge/ChallengeHistoryEntity.java new file mode 100644 index 00000000..80e5c7d9 --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/entity/challenge/ChallengeHistoryEntity.java @@ -0,0 +1,39 @@ +package com.soptie.server.persistence.entity.challenge; + +import com.soptie.server.domain.challenge.Challenge; +import com.soptie.server.domain.membermission.MemberChallenge; +import com.soptie.server.domain.membermission.MissionHistory; +import com.soptie.server.persistence.entity.BaseEntity; + +import jakarta.persistence.Entity; +import jakarta.persistence.Table; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Table(name = "challenge_history", schema = "softie") +public class ChallengeHistoryEntity extends BaseEntity { + private long memberChallengeId; + private long memberId; + private long missionId; + private String content; + + public ChallengeHistoryEntity(final MemberChallenge memberChallenge, final Challenge challenge) { + this.memberChallengeId = memberChallenge.getId(); + this.memberId = memberChallenge.getMemberId(); + this.missionId = challenge.getId(); + this.content = challenge.getContent(); + } + + public MissionHistory toDomain() { + return MissionHistory.builder() + .id(this.id) + .memberMissionId(this.memberChallengeId) + .memberId(this.memberId) + .missionId(this.missionId) + .content(this.content) + .createdAt(this.createdAt) + .build(); + } +} diff --git a/src/main/java/com/soptie/server/persistence/entity/challenge/MemberChallengeEntity.java b/src/main/java/com/soptie/server/persistence/entity/challenge/MemberChallengeEntity.java new file mode 100644 index 00000000..1ecabcc1 --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/entity/challenge/MemberChallengeEntity.java @@ -0,0 +1,62 @@ +package com.soptie.server.persistence.entity.challenge; + +import com.soptie.server.domain.challenge.Challenge; +import com.soptie.server.domain.member.Member; +import com.soptie.server.domain.membermission.MemberChallenge; +import com.soptie.server.persistence.entity.BaseEntity; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Table( + name = "member_challenge", + schema = "softie", + uniqueConstraints = @UniqueConstraint(columnNames = {"member_id", "challenge_id"})) +public class MemberChallengeEntity extends BaseEntity { + @Column(nullable = false) + private boolean achieved; + @Column(nullable = false) + private int achievedCount; + @Column(nullable = false) + private long challengeId; + @Column(nullable = false) + private long memberId; + + public MemberChallengeEntity(Member member, Challenge challenge) { + this.achieved = false; + this.achievedCount = 0; + this.challengeId = challenge.getId(); + this.memberId = member.getId(); + } + + public MemberChallenge toDomain() { + return MemberChallenge.builder() + .id(this.id) + .achievedCount(this.achievedCount) + .challengeId(this.challengeId) + .memberId(this.memberId) + .build(); + } + + public MemberChallengeEntity restore() { + this.achieved = false; + return this; + } + + public void delete() { + this.achieved = true; + } + + public void update(MemberChallenge memberChallenge) { + this.achievedCount = memberChallenge.getAchievedCount(); + this.achieved = memberChallenge.isAchieved(); + } +} diff --git a/src/main/java/com/soptie/server/persistence/entity/mission/MissionHistoryEntity.java b/src/main/java/com/soptie/server/persistence/entity/mission/MissionHistoryEntity.java deleted file mode 100644 index 55244abe..00000000 --- a/src/main/java/com/soptie/server/persistence/entity/mission/MissionHistoryEntity.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.soptie.server.persistence.entity.mission; - -import com.soptie.server.domain.challenge.Mission; -import com.soptie.server.domain.membermission.MemberMission; -import com.soptie.server.domain.membermission.MissionHistory; -import com.soptie.server.persistence.entity.BaseEntity; - -import jakarta.persistence.Entity; -import jakarta.persistence.Table; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; - -@Entity -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Table(name = "mission_history", schema = "softie") -public class MissionHistoryEntity extends BaseEntity { - private long memberMissionId; - private long memberId; - private long missionId; - private String content; - - public MissionHistoryEntity(final MemberMission memberMission, final Mission mission) { - this.memberMissionId = memberMission.getId(); - this.memberId = memberMission.getMemberId(); - this.missionId = mission.getId(); - this.content = mission.getContent(); - } - - public MissionHistory toDomain() { - return MissionHistory.builder() - .id(this.id) - .memberMissionId(this.memberMissionId) - .memberId(this.memberId) - .missionId(this.missionId) - .content(this.content) - .createdAt(this.createdAt) - .build(); - } -} From 3b0cb7686f8499c11750fd051b69cb5d22aff0cc Mon Sep 17 00:00:00 2001 From: thguss Date: Mon, 16 Dec 2024 23:38:06 +0900 Subject: [PATCH 16/24] fix: updated challenge --- .../adapter/challenge/ChallengeAdapter.java | 10 ------- .../ChallengeHistoryRepository.java} | 12 ++++----- .../challenge/ChallengeRepository.java | 11 ++++++++ .../challenge/MemberChallengeRepository.java | 13 +++++++++ .../mission/MemberMissionRepository.java | 27 ------------------- 5 files changed, 30 insertions(+), 43 deletions(-) rename src/main/java/com/soptie/server/persistence/repository/{mission/MissionHistoryRepository.java => challenge/ChallengeHistoryRepository.java} (57%) create mode 100644 src/main/java/com/soptie/server/persistence/repository/challenge/ChallengeRepository.java create mode 100644 src/main/java/com/soptie/server/persistence/repository/challenge/MemberChallengeRepository.java delete mode 100644 src/main/java/com/soptie/server/persistence/repository/mission/MemberMissionRepository.java diff --git a/src/main/java/com/soptie/server/persistence/adapter/challenge/ChallengeAdapter.java b/src/main/java/com/soptie/server/persistence/adapter/challenge/ChallengeAdapter.java index ee24e010..e176b07a 100644 --- a/src/main/java/com/soptie/server/persistence/adapter/challenge/ChallengeAdapter.java +++ b/src/main/java/com/soptie/server/persistence/adapter/challenge/ChallengeAdapter.java @@ -20,20 +20,10 @@ public List findAllByTheme(long themeId) { return challengeRepository.findByThemeId(themeId).stream().map(ChallengeEntity::toDomain).toList(); } - public List findByChallengeIds(List challengeIds) { - return challengeRepository.findByChallengeIdIn(challengeIds) - .stream().map(ChallengeEntity::toDomain) - .toList(); - } - public Challenge findById(long missionId) { return find(missionId).toDomain(); } - public List findByIds(List ids) { - return challengeRepository.findByIdIn(ids).stream().map(ChallengeEntity::toDomain).toList(); - } - private ChallengeEntity find(long id) { return challengeRepository.findById(id) .orElseThrow(() -> new SoftieException(ExceptionCode.NOT_FOUND, "Mission ID: " + id)); diff --git a/src/main/java/com/soptie/server/persistence/repository/mission/MissionHistoryRepository.java b/src/main/java/com/soptie/server/persistence/repository/challenge/ChallengeHistoryRepository.java similarity index 57% rename from src/main/java/com/soptie/server/persistence/repository/mission/MissionHistoryRepository.java rename to src/main/java/com/soptie/server/persistence/repository/challenge/ChallengeHistoryRepository.java index 7456a21c..0930a53c 100644 --- a/src/main/java/com/soptie/server/persistence/repository/mission/MissionHistoryRepository.java +++ b/src/main/java/com/soptie/server/persistence/repository/challenge/ChallengeHistoryRepository.java @@ -1,4 +1,4 @@ -package com.soptie.server.persistence.repository.mission; +package com.soptie.server.persistence.repository.challenge; import java.time.LocalDate; import java.time.LocalDateTime; @@ -9,17 +9,17 @@ import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; -import com.soptie.server.persistence.entity.mission.MissionHistoryEntity; +import com.soptie.server.persistence.entity.challenge.ChallengeHistoryEntity; -public interface MissionHistoryRepository extends JpaRepository { +public interface ChallengeHistoryRepository extends JpaRepository { @Query(value = "SELECT * FROM mission_history m " + "WHERE m.member_id = :memberId AND DATE(m.created_at) = :date LIMIT 1", nativeQuery = true) - Optional findByMemberIdAndCreatedAt(long memberId, LocalDate date); + Optional findByMemberIdAndCreatedAt(long memberId, LocalDate date); - @Query("SELECT m FROM MissionHistoryEntity m WHERE m.memberId = :memberId " + @Query("SELECT m FROM ChallengeHistoryEntity m WHERE m.memberId = :memberId " + "AND m.createdAt BETWEEN :startDateTime AND :endDateTime") - List findAllByMemberIdAndCreatedAtBetween( + List findAllByMemberIdAndCreatedAtBetween( @Param("memberId") long memberId, @Param("startDateTime") LocalDateTime startDateTime, @Param("endDateTime") LocalDateTime endDateTime diff --git a/src/main/java/com/soptie/server/persistence/repository/challenge/ChallengeRepository.java b/src/main/java/com/soptie/server/persistence/repository/challenge/ChallengeRepository.java new file mode 100644 index 00000000..5823d2b2 --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/repository/challenge/ChallengeRepository.java @@ -0,0 +1,11 @@ +package com.soptie.server.persistence.repository.challenge; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.soptie.server.persistence.entity.challenge.ChallengeEntity; + +public interface ChallengeRepository extends JpaRepository { + List findByThemeId(long themeId); +} diff --git a/src/main/java/com/soptie/server/persistence/repository/challenge/MemberChallengeRepository.java b/src/main/java/com/soptie/server/persistence/repository/challenge/MemberChallengeRepository.java new file mode 100644 index 00000000..73903d40 --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/repository/challenge/MemberChallengeRepository.java @@ -0,0 +1,13 @@ +package com.soptie.server.persistence.repository.challenge; + +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.soptie.server.persistence.entity.challenge.MemberChallengeEntity; + +public interface MemberChallengeRepository extends JpaRepository { + Optional findByMemberIdAndAchievedIsFalse(long memberId); + + Optional findByMemberIdAndChallengeIdAndAchievedTrue(long memberId, long challengeId); +} diff --git a/src/main/java/com/soptie/server/persistence/repository/mission/MemberMissionRepository.java b/src/main/java/com/soptie/server/persistence/repository/mission/MemberMissionRepository.java deleted file mode 100644 index 870ef748..00000000 --- a/src/main/java/com/soptie/server/persistence/repository/mission/MemberMissionRepository.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.soptie.server.persistence.repository.mission; - -import java.util.List; -import java.util.Optional; - -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Modifying; -import org.springframework.data.jpa.repository.Query; - -import com.soptie.server.persistence.entity.mission.MemberMissionEntity; - -public interface MemberMissionRepository extends JpaRepository { - List findByMemberIdAndMissionIdIn(long memberId, List missionIds); - - @Modifying - @Query( - value = "DELETE FROM member_mission WHERE member_id = :memberId", - nativeQuery = true) - void deleteAllByMemberId(long memberId); - - Optional findByMemberId(long memberId); - - @Query( - value = "SELECT * FROM member_mission WHERE member_id = :memberId AND is_deleted = true", - nativeQuery = true) - List findDeletedByMemberId(long memberId); -} From b5754b59b09675b53330340329a75d3e95c3cb48 Mon Sep 17 00:00:00 2001 From: thguss Date: Mon, 16 Dec 2024 23:39:34 +0900 Subject: [PATCH 17/24] fix: updated delete method --- .../adapter/challenge/MemberChallengeAdapter.java | 6 +++--- .../repository/challenge/MemberChallengeRepository.java | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/soptie/server/persistence/adapter/challenge/MemberChallengeAdapter.java b/src/main/java/com/soptie/server/persistence/adapter/challenge/MemberChallengeAdapter.java index b629e50f..c1650548 100644 --- a/src/main/java/com/soptie/server/persistence/adapter/challenge/MemberChallengeAdapter.java +++ b/src/main/java/com/soptie/server/persistence/adapter/challenge/MemberChallengeAdapter.java @@ -8,8 +8,8 @@ import com.soptie.server.domain.challenge.Challenge; import com.soptie.server.domain.member.Member; import com.soptie.server.domain.membermission.MemberChallenge; -import com.soptie.server.persistence.entity.mission.MemberChallengeEntity; -import com.soptie.server.persistence.repository.mission.MemberChallengeRepository; +import com.soptie.server.persistence.entity.challenge.MemberChallengeEntity; +import com.soptie.server.persistence.repository.challenge.MemberChallengeRepository; import lombok.RequiredArgsConstructor; import lombok.val; @@ -41,7 +41,7 @@ public void delete(MemberChallenge memberChallenge) { } public void deleteAllByMemberId(long memberId) { - memberChallengeRepository.deleteAllByMemberId(memberId); + memberChallengeRepository.deleteByMemberId(memberId); } public void update(MemberChallenge memberChallenge) { diff --git a/src/main/java/com/soptie/server/persistence/repository/challenge/MemberChallengeRepository.java b/src/main/java/com/soptie/server/persistence/repository/challenge/MemberChallengeRepository.java index 73903d40..c1570092 100644 --- a/src/main/java/com/soptie/server/persistence/repository/challenge/MemberChallengeRepository.java +++ b/src/main/java/com/soptie/server/persistence/repository/challenge/MemberChallengeRepository.java @@ -10,4 +10,6 @@ public interface MemberChallengeRepository extends JpaRepository findByMemberIdAndAchievedIsFalse(long memberId); Optional findByMemberIdAndChallengeIdAndAchievedTrue(long memberId, long challengeId); + + void deleteByMemberId(long memberId); } From e8764bf86994b33c9bbab027a85b0ab33a85cd46 Mon Sep 17 00:00:00 2001 From: thguss Date: Mon, 16 Dec 2024 23:43:15 +0900 Subject: [PATCH 18/24] fix: updated challenge --- .../calendar/DateHistoryResponse.java | 16 ++-- .../challenge/ChallengesResponse.java | 9 ++- .../MemberChallengeResponse.java | 54 +++++++++++++ .../server/domain/auth/AuthService.java | 6 +- .../server/domain/challenge/Challenge.java | 8 +- .../domain/challenge/ChallengeService.java | 10 +-- .../membermission/MemberChallengeService.java | 78 +++++++++++++++++++ .../server/domain/memo/MemoService.java | 6 +- .../challenge/ChallengeHistoryAdapter.java | 8 +- .../challenge/ChallengeHistoryEntity.java | 12 +-- 10 files changed, 173 insertions(+), 34 deletions(-) create mode 100644 src/main/java/com/soptie/server/api/controller/dto/response/membermission/MemberChallengeResponse.java create mode 100644 src/main/java/com/soptie/server/domain/membermission/MemberChallengeService.java diff --git a/src/main/java/com/soptie/server/api/controller/dto/response/calendar/DateHistoryResponse.java b/src/main/java/com/soptie/server/api/controller/dto/response/calendar/DateHistoryResponse.java index 3e53d8c7..b5e0e24e 100644 --- a/src/main/java/com/soptie/server/api/controller/dto/response/calendar/DateHistoryResponse.java +++ b/src/main/java/com/soptie/server/api/controller/dto/response/calendar/DateHistoryResponse.java @@ -1,6 +1,6 @@ package com.soptie.server.api.controller.dto.response.calendar; -import static lombok.AccessLevel.PRIVATE; +import static lombok.AccessLevel.*; import java.util.Collections; import java.util.Comparator; @@ -10,7 +10,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import com.soptie.server.domain.membermission.MissionHistory; +import com.soptie.server.domain.membermission.ChallengeHistory; import com.soptie.server.domain.memberroutine.RoutineHistory; import com.soptie.server.domain.theme.Theme; @@ -33,7 +33,7 @@ public static DateHistoryResponse of( final long memoId, final String memoContent, final Map> routines, - final Map> missions + final Map> missions ) { return DateHistoryResponse.builder() .memoId(memoId) @@ -44,7 +44,7 @@ public static DateHistoryResponse of( private static List toHistories( final Map> routines, - final Map> missions + final Map> missions ) { val histories = getHistories(routines, missions); return histories.values().stream().toList(); @@ -52,7 +52,7 @@ private static List toHistories( private static Map getHistories( final Map> routines, - final Map> missions + final Map> missions ) { return Stream.concat(routines.keySet().stream(), missions.keySet().stream()) .distinct() @@ -82,7 +82,7 @@ private record HistoriesResponse( private static HistoriesResponse of( final Theme theme, final List routines, - final List missions + final List missions ) { return HistoriesResponse.builder() .themeId(theme.getId()) @@ -93,7 +93,7 @@ private static HistoriesResponse of( private static List getHistoryResponse( final List routines, - final List missions + final List missions ) { return Stream.concat( missions.stream().map(HistoryResponse::createMissions), @@ -119,7 +119,7 @@ private static HistoryResponse createRoutines(final RoutineHistory history) { .build(); } - private static HistoryResponse createMissions(final MissionHistory history) { + private static HistoryResponse createMissions(final ChallengeHistory history) { return HistoryResponse.builder() .historyId(history.getId()) .content(history.getContent()) diff --git a/src/main/java/com/soptie/server/api/controller/dto/response/challenge/ChallengesResponse.java b/src/main/java/com/soptie/server/api/controller/dto/response/challenge/ChallengesResponse.java index a9647402..855988be 100644 --- a/src/main/java/com/soptie/server/api/controller/dto/response/challenge/ChallengesResponse.java +++ b/src/main/java/com/soptie/server/api/controller/dto/response/challenge/ChallengesResponse.java @@ -1,6 +1,7 @@ package com.soptie.server.api.controller.dto.response.challenge; import java.util.List; +import java.util.Objects; import com.soptie.server.domain.challenge.Challenge; @@ -15,10 +16,10 @@ public record ChallengesResponse( @NotNull List challenges ) { - public static ChallengesResponse of(List challenges, List challengeIdsInMember) { + public static ChallengesResponse of(List challenges, Long challengeIdInMember) { return ChallengesResponse.builder() .challenges(challenges.stream() - .map(it -> ChallengeResponse.of(it, challengeIdsInMember)).toList()) + .map(it -> ChallengeResponse.of(it, challengeIdInMember)).toList()) .build(); } @@ -38,14 +39,14 @@ private record ChallengeResponse( boolean hasRoutine ) { - private static ChallengeResponse of(Challenge challenge, List challengeIdsInMember) { + private static ChallengeResponse of(Challenge challenge, Long challengeIdInMember) { return ChallengeResponse.builder() .challengeId(challenge.getId()) .content(challenge.getContent()) .description(challenge.getDescription()) .requiredTime(challenge.getRequiredTime()) .place(challenge.getPlace()) - .hasRoutine(challengeIdsInMember.contains(challenge.getId())) + .hasRoutine(Objects.equals(challenge.getId(), challengeIdInMember)) .build(); } } diff --git a/src/main/java/com/soptie/server/api/controller/dto/response/membermission/MemberChallengeResponse.java b/src/main/java/com/soptie/server/api/controller/dto/response/membermission/MemberChallengeResponse.java new file mode 100644 index 00000000..8b514acf --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/dto/response/membermission/MemberChallengeResponse.java @@ -0,0 +1,54 @@ +package com.soptie.server.api.controller.dto.response.membermission; + +import com.soptie.server.domain.challenge.Challenge; +import com.soptie.server.domain.membermission.MemberChallenge; +import com.soptie.server.domain.theme.Theme; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.AccessLevel; +import lombok.Builder; + +@Builder(access = AccessLevel.PRIVATE) +public record MemberChallengeResponse( + @Schema(description = "회원 챌린지 id", example = "1") + long memberChallengeId, + @Schema(description = "테마 정보") + ThemeResponse theme, + @Schema(description = "챌린지 내용", example = "일어나면 5분 안에 이불 개기") + @NotNull String content, + @Schema(description = "챌린지 상세 내용", example = "평소에 바빠서 ...더보기") + @NotNull String description, + @Schema(description = "장소", example = "침대") + @NotNull String place, + @Schema(description = "소요시간", example = "3분") + @NotNull String timeTaken +) { + + public static MemberChallengeResponse of(MemberChallenge memberChallenge, Theme theme, Challenge challenge) { + return MemberChallengeResponse.builder() + .memberChallengeId(memberChallenge.getId()) + .theme(ThemeResponse.of(theme)) + .content(challenge.getContent()) + .description(challenge.getDescription()) + .place(challenge.getPlace()) + .timeTaken(challenge.getRequiredTime()) + .build(); + } + + @Builder(access = AccessLevel.PRIVATE) + private record ThemeResponse( + @Schema(description = "테마 id", example = "1") + long themeId, + @Schema(description = "테마 이름", example = "관계 쌓기") + @NotNull String themeName + ) { + + private static ThemeResponse of(Theme theme) { + return ThemeResponse.builder() + .themeId(theme.getId()) + .themeName(theme.getName()) + .build(); + } + } +} diff --git a/src/main/java/com/soptie/server/domain/auth/AuthService.java b/src/main/java/com/soptie/server/domain/auth/AuthService.java index 0aaf9840..41a31ead 100644 --- a/src/main/java/com/soptie/server/domain/auth/AuthService.java +++ b/src/main/java/com/soptie/server/domain/auth/AuthService.java @@ -16,7 +16,7 @@ import com.soptie.server.external.oauth.KakaoService; import com.soptie.server.persistence.adapter.MemberAdapter; import com.soptie.server.persistence.adapter.MemberDollAdapter; -import com.soptie.server.persistence.adapter.mission.MemberMissionAdapter; +import com.soptie.server.persistence.adapter.challenge.MemberChallengeAdapter; import com.soptie.server.persistence.adapter.routine.MemberRoutineAdapter; import lombok.RequiredArgsConstructor; @@ -34,7 +34,7 @@ public class AuthService { private final MemberDollAdapter memberDollAdapter; private final MemberRoutineAdapter memberRoutineAdapter; - private final MemberMissionAdapter memberMissionAdapter; + private final MemberChallengeAdapter memberChallengeAdapter; private final MemberAdapter memberAdapter; @Transactional @@ -63,7 +63,7 @@ public void signOut(long memberId) { public void withdraw(long memberId) { memberAdapter.findById(memberId); memberRoutineAdapter.deleteAllByMemberId(memberId); - memberMissionAdapter.deleteAllByMemberId(memberId); + memberChallengeAdapter.deleteAllByMemberId(memberId); memberDollAdapter.deleteByMember(memberId); memberAdapter.delete(memberId); } diff --git a/src/main/java/com/soptie/server/domain/challenge/Challenge.java b/src/main/java/com/soptie/server/domain/challenge/Challenge.java index ee5e9fc5..85e63906 100644 --- a/src/main/java/com/soptie/server/domain/challenge/Challenge.java +++ b/src/main/java/com/soptie/server/domain/challenge/Challenge.java @@ -9,6 +9,12 @@ public class Challenge { private Long id; @NotNull - private String name; + private String content; + @NotNull + private String description; + @NotNull + private String requiredTime; + @NotNull + private String place; private long themeId; } diff --git a/src/main/java/com/soptie/server/domain/challenge/ChallengeService.java b/src/main/java/com/soptie/server/domain/challenge/ChallengeService.java index 6c9731c3..6fb78e08 100644 --- a/src/main/java/com/soptie/server/domain/challenge/ChallengeService.java +++ b/src/main/java/com/soptie/server/domain/challenge/ChallengeService.java @@ -6,7 +6,7 @@ import com.soptie.server.api.controller.dto.response.challenge.ChallengesResponse; import com.soptie.server.domain.membermission.MemberChallenge; import com.soptie.server.persistence.adapter.challenge.ChallengeAdapter; -import com.soptie.server.persistence.adapter.mission.MemberChallengeAdapter; +import com.soptie.server.persistence.adapter.challenge.MemberChallengeAdapter; import lombok.RequiredArgsConstructor; import lombok.val; @@ -20,10 +20,10 @@ public class ChallengeService { public ChallengesResponse getChallengesByTheme(long memberId, long themeId) { val challenges = challengeAdapter.findAllByTheme(themeId); - val challengeIdsInMember = memberChallengeAdapter.findAllByMember(memberId) - .stream().map(MemberChallenge::getId) - .toList(); - return ChallengesResponse.of(challenges, challengeIdsInMember); + val challengeIdInMember = memberChallengeAdapter.findByMember(memberId) + .map(MemberChallenge::getChallengeId) + .orElse(null); + return ChallengesResponse.of(challenges, challengeIdInMember); } } diff --git a/src/main/java/com/soptie/server/domain/membermission/MemberChallengeService.java b/src/main/java/com/soptie/server/domain/membermission/MemberChallengeService.java new file mode 100644 index 00000000..68a93c17 --- /dev/null +++ b/src/main/java/com/soptie/server/domain/membermission/MemberChallengeService.java @@ -0,0 +1,78 @@ +package com.soptie.server.domain.membermission; + +import java.util.Optional; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.soptie.server.api.controller.dto.request.membermission.CreateMemberChallengeRequest; +import com.soptie.server.api.controller.dto.response.membermission.CreateMemberChallengeResponse; +import com.soptie.server.api.controller.dto.response.membermission.MemberChallengeResponse; +import com.soptie.server.common.exception.ExceptionCode; +import com.soptie.server.common.exception.SoftieException; +import com.soptie.server.persistence.adapter.MemberAdapter; +import com.soptie.server.persistence.adapter.ThemeAdapter; +import com.soptie.server.persistence.adapter.challenge.ChallengeAdapter; +import com.soptie.server.persistence.adapter.challenge.ChallengeHistoryAdapter; +import com.soptie.server.persistence.adapter.challenge.MemberChallengeAdapter; + +import lombok.RequiredArgsConstructor; +import lombok.val; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class MemberChallengeService { + private final MemberChallengeAdapter memberChallengeAdapter; + private final ThemeAdapter themeAdapter; + private final ChallengeAdapter challengeAdapter; + private final MemberAdapter memberAdapter; + private final ChallengeHistoryAdapter challengeHistoryAdapter; + + public Optional getMemberChallenge(long memberId) { + val memberChallenge = memberChallengeAdapter.findByMember(memberId); + return memberChallenge.map(this::toMemberChallenge); + } + + private MemberChallengeResponse toMemberChallenge(MemberChallenge memberChallenge) { + val challenge = challengeAdapter.findById(memberChallenge.getChallengeId()); + val theme = themeAdapter.findById(challenge.getThemeId()); + return MemberChallengeResponse.of(memberChallenge, theme, challenge); + } + + @Transactional + public CreateMemberChallengeResponse createMemberChallenge(long memberId, CreateMemberChallengeRequest request) { + if (memberChallengeAdapter.findByMember(memberId).isPresent()) { + throw new SoftieException(ExceptionCode.BAD_REQUEST, "챌린지가 존재하는 회원"); + } + val member = memberAdapter.findById(memberId); + val challenge = challengeAdapter.findById(request.challengeId()); + val savedMemberChallenge = memberChallengeAdapter.save(member, challenge); + return CreateMemberChallengeResponse.of(savedMemberChallenge); + } + + @Transactional + public void deleteMemberChallenge(long memberId) { + val memberChallenge = memberChallengeAdapter.findByMember(memberId) + .orElseThrow(() -> new SoftieException(ExceptionCode.NOT_FOUND, "챌린지가 없는 회원, Member ID: " + memberId)); + memberChallengeAdapter.delete(memberChallenge); + } + + @Transactional + public void achieveMemberChallenge(long memberId) { + val memberChallenge = memberChallengeAdapter.findByMember(memberId) + .orElseThrow(() -> new SoftieException(ExceptionCode.NOT_FOUND, "챌린지가 없는 회원, Member ID: " + memberId)); + val member = memberAdapter.findById(memberId); + member.getCottonInfo().addRainbowCottonCount(); + memberAdapter.update(member); + memberChallenge.achieve(); + memberChallengeAdapter.update(memberChallenge); + val challenge = challengeAdapter.findById(memberChallenge.getChallengeId()); + challengeHistoryAdapter.save(memberChallenge, challenge); + } + + @Transactional + public void deleteHistory(long historyId) { + challengeHistoryAdapter.deleteById(historyId); + } +} diff --git a/src/main/java/com/soptie/server/domain/memo/MemoService.java b/src/main/java/com/soptie/server/domain/memo/MemoService.java index 97c87cf1..27453498 100644 --- a/src/main/java/com/soptie/server/domain/memo/MemoService.java +++ b/src/main/java/com/soptie/server/domain/memo/MemoService.java @@ -10,7 +10,7 @@ import com.soptie.server.common.exception.SoftieException; import com.soptie.server.persistence.adapter.MemberAdapter; import com.soptie.server.persistence.adapter.MemoAdapter; -import com.soptie.server.persistence.adapter.mission.MissionHistoryAdapter; +import com.soptie.server.persistence.adapter.challenge.ChallengeHistoryAdapter; import com.soptie.server.persistence.adapter.routine.RoutineHistoryAdapter; import lombok.RequiredArgsConstructor; @@ -23,7 +23,7 @@ public class MemoService { private final MemberAdapter memberAdapter; private final MemoAdapter memoAdapter; - private final MissionHistoryAdapter missionHistoryAdapter; + private final ChallengeHistoryAdapter challengeHistoryAdapter; private final RoutineHistoryAdapter routineHistoryAdapter; @Transactional @@ -62,6 +62,6 @@ private boolean hasNoRoutineHistory(final long memberId, final CreateMemoRequest } private boolean hasNoMissionHistory(final long memberId, final CreateMemoRequest request) { - return !missionHistoryAdapter.isExistByMemberIdAndCreatedAt(memberId, request.achievedDate()); + return !challengeHistoryAdapter.isExistByMemberIdAndCreatedAt(memberId, request.achievedDate()); } } diff --git a/src/main/java/com/soptie/server/persistence/adapter/challenge/ChallengeHistoryAdapter.java b/src/main/java/com/soptie/server/persistence/adapter/challenge/ChallengeHistoryAdapter.java index 722b37c9..c283664b 100644 --- a/src/main/java/com/soptie/server/persistence/adapter/challenge/ChallengeHistoryAdapter.java +++ b/src/main/java/com/soptie/server/persistence/adapter/challenge/ChallengeHistoryAdapter.java @@ -7,10 +7,10 @@ import org.springframework.stereotype.Component; import com.soptie.server.domain.challenge.Challenge; +import com.soptie.server.domain.membermission.ChallengeHistory; import com.soptie.server.domain.membermission.MemberChallenge; -import com.soptie.server.domain.membermission.MissionHistory; -import com.soptie.server.persistence.entity.mission.ChallengeHistoryEntity; -import com.soptie.server.persistence.repository.mission.ChallengeHistoryRepository; +import com.soptie.server.persistence.entity.challenge.ChallengeHistoryEntity; +import com.soptie.server.persistence.repository.challenge.ChallengeHistoryRepository; import lombok.RequiredArgsConstructor; @@ -31,7 +31,7 @@ public boolean isExistByMemberIdAndCreatedAt(final long memberId, final LocalDat return historyRepository.findByMemberIdAndCreatedAt(memberId, date).isPresent(); } - public List findAllByMemberIdAndCreatedAtBetween( + public List findAllByMemberIdAndCreatedAtBetween( final long memberId, final LocalDateTime startDateTime, final LocalDateTime endDateTime diff --git a/src/main/java/com/soptie/server/persistence/entity/challenge/ChallengeHistoryEntity.java b/src/main/java/com/soptie/server/persistence/entity/challenge/ChallengeHistoryEntity.java index 80e5c7d9..28598299 100644 --- a/src/main/java/com/soptie/server/persistence/entity/challenge/ChallengeHistoryEntity.java +++ b/src/main/java/com/soptie/server/persistence/entity/challenge/ChallengeHistoryEntity.java @@ -1,8 +1,8 @@ package com.soptie.server.persistence.entity.challenge; import com.soptie.server.domain.challenge.Challenge; +import com.soptie.server.domain.membermission.ChallengeHistory; import com.soptie.server.domain.membermission.MemberChallenge; -import com.soptie.server.domain.membermission.MissionHistory; import com.soptie.server.persistence.entity.BaseEntity; import jakarta.persistence.Entity; @@ -16,22 +16,22 @@ public class ChallengeHistoryEntity extends BaseEntity { private long memberChallengeId; private long memberId; - private long missionId; + private long challengeId; private String content; public ChallengeHistoryEntity(final MemberChallenge memberChallenge, final Challenge challenge) { this.memberChallengeId = memberChallenge.getId(); this.memberId = memberChallenge.getMemberId(); - this.missionId = challenge.getId(); + this.challengeId = challenge.getId(); this.content = challenge.getContent(); } - public MissionHistory toDomain() { - return MissionHistory.builder() + public ChallengeHistory toDomain() { + return ChallengeHistory.builder() .id(this.id) .memberMissionId(this.memberChallengeId) .memberId(this.memberId) - .missionId(this.missionId) + .challengeId(this.challengeId) .content(this.content) .createdAt(this.createdAt) .build(); From 56b6e3ae35ca99826ca57d39708fa7a0127f53cf Mon Sep 17 00:00:00 2001 From: thguss Date: Mon, 16 Dec 2024 23:43:24 +0900 Subject: [PATCH 19/24] fix: updated challenge --- .../{MissionHistory.java => ChallengeHistory.java} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename src/main/java/com/soptie/server/domain/membermission/{MissionHistory.java => ChallengeHistory.java} (82%) diff --git a/src/main/java/com/soptie/server/domain/membermission/MissionHistory.java b/src/main/java/com/soptie/server/domain/membermission/ChallengeHistory.java similarity index 82% rename from src/main/java/com/soptie/server/domain/membermission/MissionHistory.java rename to src/main/java/com/soptie/server/domain/membermission/ChallengeHistory.java index 58c5b67d..1e609324 100644 --- a/src/main/java/com/soptie/server/domain/membermission/MissionHistory.java +++ b/src/main/java/com/soptie/server/domain/membermission/ChallengeHistory.java @@ -7,11 +7,11 @@ @Builder @Getter -public class MissionHistory { +public class ChallengeHistory { private Long id; private long memberMissionId; private long memberId; - private long missionId; + private long challengeId; private String content; private LocalDateTime createdAt; } From d763bf529e54ad7cd3d32f383926eee0e23937e7 Mon Sep 17 00:00:00 2001 From: thguss Date: Mon, 16 Dec 2024 23:48:22 +0900 Subject: [PATCH 20/24] fix: updated challenge word --- .../api/controller/MemberChallengeApi.java | 2 +- .../calendar/DateHistoryResponse.java | 2 +- .../CreateMemberChallengeResponse.java | 2 +- .../MemberChallengeResponse.java | 2 +- .../domain/calendar/CalendarService.java | 61 +++++++++---------- .../ChallengeHistory.java | 2 +- .../domain/challenge/ChallengeService.java | 1 - .../MemberChallenge.java | 2 +- .../MemberChallengeService.java | 2 +- .../challenge/ChallengeHistoryAdapter.java | 4 +- .../challenge/MemberChallengeAdapter.java | 2 +- .../challenge/ChallengeHistoryEntity.java | 4 +- .../challenge/MemberChallengeEntity.java | 2 +- 13 files changed, 42 insertions(+), 46 deletions(-) rename src/main/java/com/soptie/server/domain/{membermission => challenge}/ChallengeHistory.java (85%) rename src/main/java/com/soptie/server/domain/{membermission => challenge}/MemberChallenge.java (86%) rename src/main/java/com/soptie/server/domain/{membermission => challenge}/MemberChallengeService.java (98%) diff --git a/src/main/java/com/soptie/server/api/controller/MemberChallengeApi.java b/src/main/java/com/soptie/server/api/controller/MemberChallengeApi.java index 06d4f2b9..dd3cd4dd 100644 --- a/src/main/java/com/soptie/server/api/controller/MemberChallengeApi.java +++ b/src/main/java/com/soptie/server/api/controller/MemberChallengeApi.java @@ -19,7 +19,7 @@ import com.soptie.server.api.controller.dto.response.SuccessResponse; import com.soptie.server.api.controller.dto.response.membermission.CreateMemberChallengeResponse; import com.soptie.server.api.controller.generic.SuccessMessage; -import com.soptie.server.domain.membermission.MemberChallengeService; +import com.soptie.server.domain.challenge.MemberChallengeService; import lombok.RequiredArgsConstructor; import lombok.val; diff --git a/src/main/java/com/soptie/server/api/controller/dto/response/calendar/DateHistoryResponse.java b/src/main/java/com/soptie/server/api/controller/dto/response/calendar/DateHistoryResponse.java index b5e0e24e..63121dd2 100644 --- a/src/main/java/com/soptie/server/api/controller/dto/response/calendar/DateHistoryResponse.java +++ b/src/main/java/com/soptie/server/api/controller/dto/response/calendar/DateHistoryResponse.java @@ -10,7 +10,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import com.soptie.server.domain.membermission.ChallengeHistory; +import com.soptie.server.domain.challenge.ChallengeHistory; import com.soptie.server.domain.memberroutine.RoutineHistory; import com.soptie.server.domain.theme.Theme; diff --git a/src/main/java/com/soptie/server/api/controller/dto/response/membermission/CreateMemberChallengeResponse.java b/src/main/java/com/soptie/server/api/controller/dto/response/membermission/CreateMemberChallengeResponse.java index cae360f3..33f18e19 100644 --- a/src/main/java/com/soptie/server/api/controller/dto/response/membermission/CreateMemberChallengeResponse.java +++ b/src/main/java/com/soptie/server/api/controller/dto/response/membermission/CreateMemberChallengeResponse.java @@ -1,6 +1,6 @@ package com.soptie.server.api.controller.dto.response.membermission; -import com.soptie.server.domain.membermission.MemberChallenge; +import com.soptie.server.domain.challenge.MemberChallenge; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AccessLevel; diff --git a/src/main/java/com/soptie/server/api/controller/dto/response/membermission/MemberChallengeResponse.java b/src/main/java/com/soptie/server/api/controller/dto/response/membermission/MemberChallengeResponse.java index 8b514acf..74e10f83 100644 --- a/src/main/java/com/soptie/server/api/controller/dto/response/membermission/MemberChallengeResponse.java +++ b/src/main/java/com/soptie/server/api/controller/dto/response/membermission/MemberChallengeResponse.java @@ -1,7 +1,7 @@ package com.soptie.server.api.controller.dto.response.membermission; import com.soptie.server.domain.challenge.Challenge; -import com.soptie.server.domain.membermission.MemberChallenge; +import com.soptie.server.domain.challenge.MemberChallenge; import com.soptie.server.domain.theme.Theme; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/src/main/java/com/soptie/server/domain/calendar/CalendarService.java b/src/main/java/com/soptie/server/domain/calendar/CalendarService.java index 5cf87094..e3fc029b 100644 --- a/src/main/java/com/soptie/server/domain/calendar/CalendarService.java +++ b/src/main/java/com/soptie/server/domain/calendar/CalendarService.java @@ -1,7 +1,6 @@ package com.soptie.server.domain.calendar; -import static com.soptie.server.common.support.ValueConfig.BLANK; -import static com.soptie.server.common.support.ValueConfig.MEMBER_HAS_NOT_MEMO; +import static com.soptie.server.common.support.ValueConfig.*; import java.time.LocalDate; import java.time.LocalDateTime; @@ -16,16 +15,15 @@ import org.springframework.transaction.annotation.Transactional; import com.soptie.server.api.controller.dto.response.calendar.DateHistoryResponse; -import com.soptie.server.domain.membermission.MissionHistory; +import com.soptie.server.domain.challenge.ChallengeHistory; import com.soptie.server.domain.memberroutine.RoutineHistory; import com.soptie.server.domain.memo.Memo; import com.soptie.server.domain.theme.Theme; import com.soptie.server.persistence.adapter.MemberAdapter; import com.soptie.server.persistence.adapter.MemoAdapter; import com.soptie.server.persistence.adapter.ThemeAdapter; -import com.soptie.server.persistence.adapter.mission.ChallengeAdapter; -import com.soptie.server.persistence.adapter.mission.MissionAdapter; -import com.soptie.server.persistence.adapter.mission.MissionHistoryAdapter; +import com.soptie.server.persistence.adapter.challenge.ChallengeAdapter; +import com.soptie.server.persistence.adapter.challenge.ChallengeHistoryAdapter; import com.soptie.server.persistence.adapter.routine.RoutineAdapter; import com.soptie.server.persistence.adapter.routine.RoutineHistoryAdapter; @@ -40,10 +38,9 @@ public class CalendarService { private final MemberAdapter memberAdapter; private final MemoAdapter memoAdapter; private final RoutineHistoryAdapter routineHistoryAdapter; - private final MissionHistoryAdapter missionHistoryAdapter; + private final ChallengeHistoryAdapter challengeHistoryAdapter; private final ThemeAdapter themeAdapter; private final RoutineAdapter routineAdapter; - private final MissionAdapter missionAdapter; private final ChallengeAdapter challengeAdapter; public Map getCalendar(final long memberId, final int year, final int month) { @@ -52,8 +49,8 @@ public Map getCalendar(final long memberId, fina val endDateTime = startDateTime.plusMonths(1).withDayOfMonth(1).minusSeconds(1); val memos = getMemos(memberId, year, month); val routines = getRoutines(memberId, startDateTime, endDateTime); - val missions = getMissions(memberId, startDateTime, endDateTime); - return getHistories(memos, routines, missions); + val challenges = getChallenges(memberId, startDateTime, endDateTime); + return getHistories(memos, routines, challenges); } private Map getMemos(final long memberId, final int year, final int month) { @@ -82,17 +79,18 @@ private Map> getRoutines( )); } - private Map> getMissions( + private Map> getChallenges( final long memberId, final LocalDateTime startDateTime, final LocalDateTime endDateTime ) { - val missions = missionHistoryAdapter.findAllByMemberIdAndCreatedAtBetween(memberId, startDateTime, endDateTime); - return missions.stream() + val challenges = challengeHistoryAdapter.findAllByMemberIdAndCreatedAtBetween(memberId, startDateTime, + endDateTime); + return challenges.stream() .collect(Collectors.groupingBy( - mission -> mission.getCreatedAt().toLocalDate(), + challenge -> challenge.getCreatedAt().toLocalDate(), Collectors.mapping( - mission -> mission, + challenge -> challenge, Collectors.toUnmodifiableList() ) )); @@ -101,18 +99,18 @@ private Map> getMissions( private Map getHistories( final Map memos, final Map> routines, - final Map> missions + final Map> challenges ) { - val dates = getDates(memos, routines, missions); - return getDateAndHistories(dates, memos, routines, missions); + val dates = getDates(memos, routines, challenges); + return getDateAndHistories(dates, memos, routines, challenges); } private Set getDates( final Map memos, final Map> routines, - final Map> missions + final Map> challenges ) { - return Stream.of(memos.keySet(), routines.keySet(), missions.keySet()) + return Stream.of(memos.keySet(), routines.keySet(), challenges.keySet()) .flatMap(Set::stream) .collect(Collectors.toUnmodifiableSet()); } @@ -121,12 +119,12 @@ private Map getDateAndHistories( final Set dates, final Map memos, final Map> routines, - final Map> missions + final Map> challenges ) { return dates.stream() .collect(Collectors.toMap( date -> date, - date -> getDateHistory(date, memos, routines, missions) + date -> getDateHistory(date, memos, routines, challenges) )); } @@ -134,14 +132,14 @@ private DateHistoryResponse getDateHistory( final LocalDate date, final Map memos, final Map> routines, - final Map> missions + final Map> challenges ) { val memo = memos.get(date); val routineHistories = getRoutines(date, routines); - val missionHistories = getMissions(date, missions); + val challengeHistories = getChallenges(date, challenges); val memoId = memo == null ? MEMBER_HAS_NOT_MEMO : memo.getId(); val content = memo == null ? BLANK : memo.getContent(); - return DateHistoryResponse.of(memoId, content, routineHistories, missionHistories); + return DateHistoryResponse.of(memoId, content, routineHistories, challengeHistories); } private Map> getRoutines( @@ -160,20 +158,19 @@ private Theme getRoutineTheme(final RoutineHistory history) { return themeAdapter.findById(routine.getThemeId()); } - private Map> getMissions( + private Map> getChallenges( final LocalDate date, - final Map> missions + final Map> challenges ) { - val histories = missions.getOrDefault(date, Collections.emptyList()); + val histories = challenges.getOrDefault(date, Collections.emptyList()); return histories.stream() .collect(Collectors.groupingBy( - this::getMissionTheme + this::getChallengeTheme )); } - private Theme getMissionTheme(final MissionHistory history) { - val mission = missionAdapter.findById(history.getMissionId()); - val challenge = challengeAdapter.findById(mission.getChallengeId()); + private Theme getChallengeTheme(final ChallengeHistory history) { + val challenge = challengeAdapter.findById(history.getChallengeId()); return themeAdapter.findById(challenge.getThemeId()); } } diff --git a/src/main/java/com/soptie/server/domain/membermission/ChallengeHistory.java b/src/main/java/com/soptie/server/domain/challenge/ChallengeHistory.java similarity index 85% rename from src/main/java/com/soptie/server/domain/membermission/ChallengeHistory.java rename to src/main/java/com/soptie/server/domain/challenge/ChallengeHistory.java index 1e609324..6cc77b16 100644 --- a/src/main/java/com/soptie/server/domain/membermission/ChallengeHistory.java +++ b/src/main/java/com/soptie/server/domain/challenge/ChallengeHistory.java @@ -1,4 +1,4 @@ -package com.soptie.server.domain.membermission; +package com.soptie.server.domain.challenge; import java.time.LocalDateTime; diff --git a/src/main/java/com/soptie/server/domain/challenge/ChallengeService.java b/src/main/java/com/soptie/server/domain/challenge/ChallengeService.java index 6fb78e08..48f6cd1f 100644 --- a/src/main/java/com/soptie/server/domain/challenge/ChallengeService.java +++ b/src/main/java/com/soptie/server/domain/challenge/ChallengeService.java @@ -4,7 +4,6 @@ import org.springframework.transaction.annotation.Transactional; import com.soptie.server.api.controller.dto.response.challenge.ChallengesResponse; -import com.soptie.server.domain.membermission.MemberChallenge; import com.soptie.server.persistence.adapter.challenge.ChallengeAdapter; import com.soptie.server.persistence.adapter.challenge.MemberChallengeAdapter; diff --git a/src/main/java/com/soptie/server/domain/membermission/MemberChallenge.java b/src/main/java/com/soptie/server/domain/challenge/MemberChallenge.java similarity index 86% rename from src/main/java/com/soptie/server/domain/membermission/MemberChallenge.java rename to src/main/java/com/soptie/server/domain/challenge/MemberChallenge.java index 88d3d769..d5ab2882 100644 --- a/src/main/java/com/soptie/server/domain/membermission/MemberChallenge.java +++ b/src/main/java/com/soptie/server/domain/challenge/MemberChallenge.java @@ -1,4 +1,4 @@ -package com.soptie.server.domain.membermission; +package com.soptie.server.domain.challenge; import lombok.Builder; import lombok.Getter; diff --git a/src/main/java/com/soptie/server/domain/membermission/MemberChallengeService.java b/src/main/java/com/soptie/server/domain/challenge/MemberChallengeService.java similarity index 98% rename from src/main/java/com/soptie/server/domain/membermission/MemberChallengeService.java rename to src/main/java/com/soptie/server/domain/challenge/MemberChallengeService.java index 68a93c17..aa4275dc 100644 --- a/src/main/java/com/soptie/server/domain/membermission/MemberChallengeService.java +++ b/src/main/java/com/soptie/server/domain/challenge/MemberChallengeService.java @@ -1,4 +1,4 @@ -package com.soptie.server.domain.membermission; +package com.soptie.server.domain.challenge; import java.util.Optional; diff --git a/src/main/java/com/soptie/server/persistence/adapter/challenge/ChallengeHistoryAdapter.java b/src/main/java/com/soptie/server/persistence/adapter/challenge/ChallengeHistoryAdapter.java index c283664b..13ddcbee 100644 --- a/src/main/java/com/soptie/server/persistence/adapter/challenge/ChallengeHistoryAdapter.java +++ b/src/main/java/com/soptie/server/persistence/adapter/challenge/ChallengeHistoryAdapter.java @@ -7,8 +7,8 @@ import org.springframework.stereotype.Component; import com.soptie.server.domain.challenge.Challenge; -import com.soptie.server.domain.membermission.ChallengeHistory; -import com.soptie.server.domain.membermission.MemberChallenge; +import com.soptie.server.domain.challenge.ChallengeHistory; +import com.soptie.server.domain.challenge.MemberChallenge; import com.soptie.server.persistence.entity.challenge.ChallengeHistoryEntity; import com.soptie.server.persistence.repository.challenge.ChallengeHistoryRepository; diff --git a/src/main/java/com/soptie/server/persistence/adapter/challenge/MemberChallengeAdapter.java b/src/main/java/com/soptie/server/persistence/adapter/challenge/MemberChallengeAdapter.java index c1650548..1e040f2d 100644 --- a/src/main/java/com/soptie/server/persistence/adapter/challenge/MemberChallengeAdapter.java +++ b/src/main/java/com/soptie/server/persistence/adapter/challenge/MemberChallengeAdapter.java @@ -6,8 +6,8 @@ import com.soptie.server.common.exception.SoftieException; import com.soptie.server.common.support.RepositoryAdapter; import com.soptie.server.domain.challenge.Challenge; +import com.soptie.server.domain.challenge.MemberChallenge; import com.soptie.server.domain.member.Member; -import com.soptie.server.domain.membermission.MemberChallenge; import com.soptie.server.persistence.entity.challenge.MemberChallengeEntity; import com.soptie.server.persistence.repository.challenge.MemberChallengeRepository; diff --git a/src/main/java/com/soptie/server/persistence/entity/challenge/ChallengeHistoryEntity.java b/src/main/java/com/soptie/server/persistence/entity/challenge/ChallengeHistoryEntity.java index 28598299..1fda485c 100644 --- a/src/main/java/com/soptie/server/persistence/entity/challenge/ChallengeHistoryEntity.java +++ b/src/main/java/com/soptie/server/persistence/entity/challenge/ChallengeHistoryEntity.java @@ -1,8 +1,8 @@ package com.soptie.server.persistence.entity.challenge; import com.soptie.server.domain.challenge.Challenge; -import com.soptie.server.domain.membermission.ChallengeHistory; -import com.soptie.server.domain.membermission.MemberChallenge; +import com.soptie.server.domain.challenge.ChallengeHistory; +import com.soptie.server.domain.challenge.MemberChallenge; import com.soptie.server.persistence.entity.BaseEntity; import jakarta.persistence.Entity; diff --git a/src/main/java/com/soptie/server/persistence/entity/challenge/MemberChallengeEntity.java b/src/main/java/com/soptie/server/persistence/entity/challenge/MemberChallengeEntity.java index 1ecabcc1..3b2cf88a 100644 --- a/src/main/java/com/soptie/server/persistence/entity/challenge/MemberChallengeEntity.java +++ b/src/main/java/com/soptie/server/persistence/entity/challenge/MemberChallengeEntity.java @@ -1,8 +1,8 @@ package com.soptie.server.persistence.entity.challenge; import com.soptie.server.domain.challenge.Challenge; +import com.soptie.server.domain.challenge.MemberChallenge; import com.soptie.server.domain.member.Member; -import com.soptie.server.domain.membermission.MemberChallenge; import com.soptie.server.persistence.entity.BaseEntity; import jakarta.persistence.Column; From db5cb5f9ad9d72ba7578db52dad2bdb9dbe9e73e Mon Sep 17 00:00:00 2001 From: thguss Date: Tue, 17 Dec 2024 20:02:40 +0900 Subject: [PATCH 21/24] [DELETE] deleted base column --- .../persistence/entity/challenge/ChallengeEntity.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/soptie/server/persistence/entity/challenge/ChallengeEntity.java b/src/main/java/com/soptie/server/persistence/entity/challenge/ChallengeEntity.java index e6c349fd..0d3f61f0 100644 --- a/src/main/java/com/soptie/server/persistence/entity/challenge/ChallengeEntity.java +++ b/src/main/java/com/soptie/server/persistence/entity/challenge/ChallengeEntity.java @@ -1,15 +1,20 @@ package com.soptie.server.persistence.entity.challenge; import com.soptie.server.domain.challenge.Challenge; -import com.soptie.server.persistence.entity.BaseEntity; import jakarta.persistence.Column; import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; import jakarta.persistence.Table; @Entity @Table(name = "challenge", schema = "softie") -public class ChallengeEntity extends BaseEntity { +public class ChallengeEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; @Column(nullable = false) private String content; @Column(nullable = false) From 31405838d2af49b172e9c5b5c35715365b4abb7e Mon Sep 17 00:00:00 2001 From: thguss Date: Tue, 17 Dec 2024 20:26:51 +0900 Subject: [PATCH 22/24] [ADD] added challenge validator --- .../challenge/MemberChallengeService.java | 6 ++--- .../challenge/util/ChallengeValidator.java | 22 +++++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/soptie/server/domain/challenge/util/ChallengeValidator.java diff --git a/src/main/java/com/soptie/server/domain/challenge/MemberChallengeService.java b/src/main/java/com/soptie/server/domain/challenge/MemberChallengeService.java index aa4275dc..b1e39da3 100644 --- a/src/main/java/com/soptie/server/domain/challenge/MemberChallengeService.java +++ b/src/main/java/com/soptie/server/domain/challenge/MemberChallengeService.java @@ -10,6 +10,7 @@ import com.soptie.server.api.controller.dto.response.membermission.MemberChallengeResponse; import com.soptie.server.common.exception.ExceptionCode; import com.soptie.server.common.exception.SoftieException; +import com.soptie.server.domain.challenge.util.ChallengeValidator; import com.soptie.server.persistence.adapter.MemberAdapter; import com.soptie.server.persistence.adapter.ThemeAdapter; import com.soptie.server.persistence.adapter.challenge.ChallengeAdapter; @@ -28,6 +29,7 @@ public class MemberChallengeService { private final ChallengeAdapter challengeAdapter; private final MemberAdapter memberAdapter; private final ChallengeHistoryAdapter challengeHistoryAdapter; + private final ChallengeValidator challengeValidator; public Optional getMemberChallenge(long memberId) { val memberChallenge = memberChallengeAdapter.findByMember(memberId); @@ -42,9 +44,7 @@ private MemberChallengeResponse toMemberChallenge(MemberChallenge memberChalleng @Transactional public CreateMemberChallengeResponse createMemberChallenge(long memberId, CreateMemberChallengeRequest request) { - if (memberChallengeAdapter.findByMember(memberId).isPresent()) { - throw new SoftieException(ExceptionCode.BAD_REQUEST, "챌린지가 존재하는 회원"); - } + challengeValidator.checkChallengeNotExists(memberId); val member = memberAdapter.findById(memberId); val challenge = challengeAdapter.findById(request.challengeId()); val savedMemberChallenge = memberChallengeAdapter.save(member, challenge); diff --git a/src/main/java/com/soptie/server/domain/challenge/util/ChallengeValidator.java b/src/main/java/com/soptie/server/domain/challenge/util/ChallengeValidator.java new file mode 100644 index 00000000..380d0100 --- /dev/null +++ b/src/main/java/com/soptie/server/domain/challenge/util/ChallengeValidator.java @@ -0,0 +1,22 @@ +package com.soptie.server.domain.challenge.util; + +import org.springframework.stereotype.Component; + +import com.soptie.server.common.exception.ExceptionCode; +import com.soptie.server.common.exception.SoftieException; +import com.soptie.server.persistence.adapter.challenge.MemberChallengeAdapter; + +import lombok.RequiredArgsConstructor; + +@Component +@RequiredArgsConstructor +public class ChallengeValidator { + + private final MemberChallengeAdapter memberChallengeAdapter; + + public void checkChallengeNotExists(long memberId) { + if (memberChallengeAdapter.findByMember(memberId).isPresent()) { + throw new SoftieException(ExceptionCode.BAD_REQUEST, "챌린지가 존재하는 회원"); + } + } +} From 87e1cf46445983121b51531b32076d6074390346 Mon Sep 17 00:00:00 2001 From: thguss Date: Tue, 17 Dec 2024 20:48:15 +0900 Subject: [PATCH 23/24] [FIX] updated lambda method --- .../adapter/challenge/MemberChallengeAdapter.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/soptie/server/persistence/adapter/challenge/MemberChallengeAdapter.java b/src/main/java/com/soptie/server/persistence/adapter/challenge/MemberChallengeAdapter.java index 1e040f2d..f9de9d25 100644 --- a/src/main/java/com/soptie/server/persistence/adapter/challenge/MemberChallengeAdapter.java +++ b/src/main/java/com/soptie/server/persistence/adapter/challenge/MemberChallengeAdapter.java @@ -28,11 +28,10 @@ public MemberChallenge save(Member member, Challenge challenge) { val memberChallenge = memberChallengeRepository .findByMemberIdAndChallengeIdAndAchievedTrue(member.getId(), challenge.getId()); return memberChallenge - // 달성한 이력이 있는 회원 - .map(MemberChallengeEntity::restore) - // 처음 추가하는 회원 - .orElse(memberChallengeRepository.save(new MemberChallengeEntity(member, challenge))) - .toDomain(); + // 추가한 이력이 있는 경우 + .map(entity -> entity.restore().toDomain()) + // 처음 추가하는 경우 + .orElseGet(() -> memberChallengeRepository.save(new MemberChallengeEntity(member, challenge)).toDomain()); } public void delete(MemberChallenge memberChallenge) { From d46f9c347bebd52ba7b0850c6e45a1d554a847b9 Mon Sep 17 00:00:00 2001 From: thguss Date: Tue, 17 Dec 2024 20:53:01 +0900 Subject: [PATCH 24/24] [FIX] updated field name --- .../dto/response/calendar/DateHistoryResponse.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/soptie/server/api/controller/dto/response/calendar/DateHistoryResponse.java b/src/main/java/com/soptie/server/api/controller/dto/response/calendar/DateHistoryResponse.java index 63121dd2..84fdde23 100644 --- a/src/main/java/com/soptie/server/api/controller/dto/response/calendar/DateHistoryResponse.java +++ b/src/main/java/com/soptie/server/api/controller/dto/response/calendar/DateHistoryResponse.java @@ -107,15 +107,15 @@ private record HistoryResponse( long historyId, @Schema(description = "루틴 내용", example = "밥 먹기") @NotNull String content, - @Schema(description = "도전 루틴 여부", example = "true") - boolean isMission + @Schema(description = "챌린지 여부", example = "true") + boolean isChallenge ) { private static HistoryResponse createRoutines(final RoutineHistory history) { return HistoryResponse.builder() .historyId(history.getId()) .content(history.getContent()) - .isMission(false) + .isChallenge(false) .build(); } @@ -123,7 +123,7 @@ private static HistoryResponse createMissions(final ChallengeHistory history) { return HistoryResponse.builder() .historyId(history.getId()) .content(history.getContent()) - .isMission(true) + .isChallenge(true) .build(); } }