Skip to content

Commit 0ba8b8b

Browse files
authored
Merge pull request #65 from prgrms-web-devcourse-final-project/feat/mission
Feat getmission
2 parents ff0910f + 2ca7165 commit 0ba8b8b

File tree

9 files changed

+89
-39
lines changed

9 files changed

+89
-39
lines changed

backend/src/main/java/com/back/domain/mission/dto/response/MissionOverviewResponse.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
@AllArgsConstructor
1111
@Builder
1212
public class MissionOverviewResponse {
13-
private List<MissionResponse> activeMissions;
14-
private List<MissionResponse> completedMissions;
15-
private Integer activeMissionCount;
16-
private Integer remainingSlots;
13+
private List<MissionResponse> activeMissions; //진행 중인 미션들을 담는 리스트
14+
private List<MissionResponse> completedMissions; //완료된 미션들을 담는 리스트
15+
private Integer activeMissionCount; // 현재 진행 중인 미션 개수
16+
private Integer remainingSlots; // 사용자가 추가로 만들 수 있는 미션 수
1717
}

backend/src/main/java/com/back/domain/mission/dto/response/MissionResponse.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ public class MissionResponse {
1717
private String title;
1818
private MissionCategory category;
1919
private MissionType type;
20-
private LocalDate startDate;
20+
private LocalDate startDate; // 시작일 (항상 월요일)
2121
private LocalDate endDate;
22-
private Integer totalWeeks;
23-
private Integer currentWeek;
24-
private boolean isCompleted;
25-
private boolean isPartyMission;
26-
private Integer partyId;
27-
private Integer progressRate;
22+
private Integer totalWeeks; // 전체 기간 주단위
23+
private Integer currentWeek; // 현재 몇주차인지
24+
private boolean isCompleted; //미션 완료 여부
25+
private boolean isPartyMission; //파티 미션 여부 (개인인지 / 파티인지)
26+
private Integer partyId; // 파티일경우
27+
private Integer progressRate; //미션 전체 진행률 (개인)
2828
private List<SubGoalResponse> subGoals;
2929
}

backend/src/main/java/com/back/domain/mission/dto/response/SubGoalResponse.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@
1313
public class SubGoalResponse {
1414
private Integer subGoalId;
1515
private String title;
16-
private Integer weekNum;
16+
private Integer weekNum; // 몇번쨰 주차인지
1717
private LocalDate startDate;
1818
private LocalDate endDate;
19-
private boolean hasBeenEdited;
20-
private LocalDate editableUntil;
21-
private String editStatus;
22-
private Integer weekProgressRate;
19+
private boolean hasBeenEdited; //사용자가 한번이라도 수정했는지
20+
private LocalDate editableUntil; // 수정 가능 기한
21+
private String editStatus; // 수정 상태 표시
22+
private Integer weekProgressRate; //해당주차 진행률
2323
private List<TaskResponse> tasks;
2424
}

backend/src/main/java/com/back/domain/mission/dto/response/TaskResponse.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,13 @@
1313
public class TaskResponse {
1414
private Integer taskId;
1515
private String title;
16-
private Integer dayNum;
17-
private TaskStatus status;
18-
private LocalDate lastCompletedDate;
19-
private boolean isToday;
16+
private Integer dayNum; // 요일
17+
private TaskStatus status; // 상태
18+
private LocalDate lastCompletedDate; // 마지막 완료 일자
19+
private boolean isToday; // 오늘 해야하는 task인지 여부
20+
21+
//private boolean hasBeenEdited;// 이미 수정된 Task인지 여부 (true면 1회 수정 끝)
22+
//private LocalDate editableUntil;// 수정 가능 기한 (ex: 이번 주 종료일까지)
23+
//private String editStatus; // 수정 상태 표시 ("가능", "불가", "기간만료")
24+
2025
}

backend/src/main/java/com/back/domain/mission/entity/SubGoal.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,6 @@ public class SubGoal {
4545
@Builder.Default
4646
private List<Task> tasks = new ArrayList<>();
4747

48-
// Lombok @Getter가 Boolean 타입에 대해 getHasBeenEdited() 생성
49-
// 필요시 명시적으로 추가
5048
public Boolean getHasBeenEdited() {
5149
return hasBeenEdited;
5250
}

backend/src/main/java/com/back/domain/mission/service/MissionCalculateService.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
public class MissionCalculateService {
1616

1717
private final TaskLogRepository taskLogRepository;
18-
18+
//시작일 계산 ( 오늘이 월요일 = 당일 시작 ) 아니면 무조건 다음주 월
1919
public LocalDate calculateStartDate() {
2020
LocalDate today = LocalDate.now();
2121
DayOfWeek todayDayOfWeek = today.getDayOfWeek();
@@ -32,10 +32,12 @@ public LocalDate calculateStartDate() {
3232
return today.plusDays(daysUntilMonday);
3333
}
3434

35+
// 종료일 계산
3536
public LocalDate calculateEndDate(LocalDate startDate, Integer weeks) {
3637
return startDate.plusWeeks(weeks).minusDays(1);
3738
}
3839

40+
// 특정 날짜 기준으로 현재 주차 계산 ( 기준일이 시작 전이면 0, 종료일 이후면 null)
3941
public Integer calculateCurrentWeek(Mission mission) {
4042
LocalDate today = LocalDate.now();
4143
if (today.isBefore(mission.getStartDate())) {
@@ -49,6 +51,7 @@ public Integer calculateCurrentWeek(Mission mission) {
4951
return (int) (daysPassed / 7) + 1;
5052
}
5153

54+
// 주어진 task가 오늘 해야 하는 일인지 판단
5255
public boolean isToday(Task task) {
5356
LocalDate today = LocalDate.now();
5457
DayOfWeek todayDayOfWeek = today.getDayOfWeek();
@@ -60,6 +63,7 @@ public boolean isToday(Task task) {
6063
!today.isAfter(subGoal.getEndDate());
6164
}
6265

66+
// 하루 진행률(개인)
6367
public Integer calculateDailyProgress(Integer memberId, LocalDate date) {
6468
int dayOfWeek = date.getDayOfWeek().getValue();
6569

@@ -74,6 +78,7 @@ public Integer calculateDailyProgress(Integer memberId, LocalDate date) {
7478
return (int) (completedTasks * 100 / totalTasks);
7579
}
7680

81+
// 주간 진행률(개인)
7782
public Integer calculateWeeklyProgress(Integer memberId, Mission mission, LocalDate date) {
7883
SubGoal currentSubGoal = mission.getSubGoals().stream()
7984
.filter(sg -> !date.isBefore(sg.getStartDate()) && !date.isAfter(sg.getEndDate()))
@@ -87,6 +92,7 @@ public Integer calculateWeeklyProgress(Integer memberId, Mission mission, LocalD
8792
return calculateWeekProgress(currentSubGoal);
8893
}
8994

95+
//미션 전체 진행률
9096
public Integer calculateMissionProgress(Mission mission) {
9197
if (mission.getSubGoals().isEmpty()) {
9298
return 0;
@@ -104,6 +110,7 @@ public Integer calculateMissionProgress(Mission mission) {
104110
return (int) Math.min(completedTasks * 100 / totalTasks, 100);
105111
}
106112

113+
// 특정 주차 진행률
107114
public Integer calculateWeekProgress(SubGoal subGoal) {
108115
if (subGoal.getTasks().isEmpty()) return 0;
109116

@@ -113,4 +120,6 @@ public Integer calculateWeekProgress(SubGoal subGoal) {
113120

114121
return (int) (completedTasks * 100 / totalTasks);
115122
}
123+
124+
116125
}

backend/src/main/java/com/back/domain/mission/service/MissionService.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public class MissionService {
2121
private final MissionRepository missionRepository;
2222
private final PartyMissionService partyMissionService;
2323

24+
// 특정 회원의 전체 미션 조회 ( 진행 중과 완료로 분리)
2425
public MissionOverviewResponse getMissions(Integer memberId) {
2526
List<Mission> activeMissions = missionRepository.findByMemberIdAndIsCompleted(memberId, false);
2627
List<Mission> completedMissions = missionRepository.findByMemberIdAndIsCompleted(memberId, true);
@@ -41,6 +42,7 @@ public MissionOverviewResponse getMissions(Integer memberId) {
4142
.build();
4243
}
4344

45+
// 미션 상세 조회 - task 까지 나옴
4446
public MissionResponse getMissionDetail(Integer memberId, Integer missionId) {
4547
Mission mission = missionRepository.findById(missionId)
4648
.orElseThrow(() -> new MissionException(MissionErrorCode.MISSION_NOT_FOUND));
@@ -52,6 +54,7 @@ public MissionResponse getMissionDetail(Integer memberId, Integer missionId) {
5254
return partyMissionService.convertToResponse(mission, true);
5355
}
5456

57+
//미션 삭제
5558
@Transactional
5659
public void deleteMission(Integer memberId, Integer missionId) {
5760
Mission mission = missionRepository.findById(missionId)

backend/src/main/java/com/back/domain/mission/service/PartyMissionService.java

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public class PartyMissionService {
3939
private final TaskService taskService;
4040
private static final int MAX_MISSIONS_PER_USER = 5;
4141

42+
// 파티 미션 생성
4243
public MissionResponse createPartyMission(Integer memberId, PartyMissionCreateRequest request) {
4344
Member member = memberRepository.findById(memberId)
4445
.orElseThrow(() -> new MissionException(MissionErrorCode.MEMBER_NOT_FOUND));
@@ -55,7 +56,6 @@ public MissionResponse createPartyMission(Integer memberId, PartyMissionCreateRe
5556
PartyRequestDto partyRequest = new PartyRequestDto();
5657
partyRequest.setName(request.getTitle());
5758
partyRequest.setMaxMembers(request.getMaxMembers());
58-
// setPublic 대신 setIsPublic 사용 (또는 PartyRequestDto 확인 필요)
5959
partyRequest.setIsPublicStatus(request.isPublic());
6060
party = partyService.createParty(partyRequest, memberId);
6161
}
@@ -76,6 +76,7 @@ public MissionResponse createPartyMission(Integer memberId, PartyMissionCreateRe
7676
.subGoals(new ArrayList<>())
7777
.build();
7878

79+
7980
if (request.getType() == MissionType.AI) {
8081
generateAiSubGoals(mission, request);
8182
} else {
@@ -86,6 +87,29 @@ public MissionResponse createPartyMission(Integer memberId, PartyMissionCreateRe
8687
return convertToResponse(savedMission, true);
8788
}
8889

90+
@Transactional(readOnly = true)
91+
public List<MissionResponse> getPartyMissions(Integer partyId) {
92+
List<Mission> missions = missionRepository.findByPartyId(partyId);
93+
94+
return missions.stream()
95+
.map(mission -> convertToResponse(mission, false)) // 목록 조회니까 false
96+
.collect(Collectors.toList());
97+
}
98+
99+
@Transactional(readOnly = true)
100+
public MissionResponse getPartyMissionDetail(Integer partyId, Integer missionId) {
101+
Mission mission = missionRepository.findById(missionId)
102+
.orElseThrow(() -> new MissionException(MissionErrorCode.MISSION_NOT_FOUND));
103+
104+
if (mission.getParty() == null || !mission.getParty().getId().equals(partyId)) {
105+
throw new MissionException(MissionErrorCode.MEMBER_FORBIDDEN); // 파티 불일치 시 예외
106+
}
107+
108+
return convertToResponse(mission, true); // 상세니까 subGoals까지 포함
109+
}
110+
111+
112+
// AI 기반으로 주차별 subgoal + task 생성
89113
private void generateAiSubGoals(Mission mission, PartyMissionCreateRequest request) {
90114
AiMissionResult aiResult = aiGeneratorService.generateMission(
91115
request.getTitle(),
@@ -124,6 +148,7 @@ private void generateAiSubGoals(Mission mission, PartyMissionCreateRequest reque
124148
}
125149
}
126150

151+
// 단순 기본 생성 로직 ( AI 아닐 경우)
127152
private void generateBasicSubGoals(Mission mission, Integer weeks) {
128153
String[] dayNames = {"", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일", "일요일"};
129154

@@ -156,6 +181,8 @@ private void generateBasicSubGoals(Mission mission, Integer weeks) {
156181
}
157182
}
158183

184+
// Mission 엔티티 -> MissionResponse 변환
185+
//includeSubGoals=true면 주차별(SubGoal, Task)까지 전부 포함
159186
public MissionResponse convertToResponse(Mission mission, boolean includeSubGoals) {
160187
Integer totalWeeks = (int) ChronoUnit.WEEKS.between(
161188
mission.getStartDate(),
@@ -171,7 +198,6 @@ public MissionResponse convertToResponse(Mission mission, boolean includeSubGoal
171198
.weekNum(sg.getOrderNum())
172199
.startDate(sg.getStartDate())
173200
.endDate(sg.getEndDate())
174-
// getHasBeenEdited() 대신 isHasBeenEdited() 또는 getHasBeenEdited() 직접 접근
175201
.hasBeenEdited(sg.getHasBeenEdited()) // Boolean 타입이므로 바로 접근
176202
.editableUntil(sg.getEditableUntil())
177203
.weekProgressRate(calculateService.calculateWeekProgress(sg))
@@ -184,20 +210,21 @@ public MissionResponse convertToResponse(Mission mission, boolean includeSubGoal
184210
.collect(Collectors.toList());
185211
}
186212

187-
MissionResponse build = MissionResponse.builder()
188-
.missionId(mission.getId())
189-
.title(mission.getTitle())
190-
.category(mission.getCategory())
191-
.type(mission.getType())
192-
.startDate(mission.getStartDate())
193-
.endDate(mission.getEndDate())
194-
.totalWeeks(totalWeeks)
195-
.currentWeek(calculateService.calculateCurrentWeek(mission))
196-
.isCompleted(mission.isCompleted())
197-
.isPartyMission(mission.isPartyMission())
198-
.partyId(mission.getParty() != null ? mission.getParty().getId() : null)
199-
.progressRate(calculateService.calculateMissionProgress(mission))
200-
.subGoals(subGoalResponses)
213+
MissionResponse.MissionResponseBuilder builder = MissionResponse.builder();
214+
builder.missionId(mission.getId());
215+
builder.title(mission.getTitle());
216+
builder.category(mission.getCategory());
217+
builder.type(mission.getType());
218+
builder.startDate(mission.getStartDate());
219+
builder.endDate(mission.getEndDate());
220+
builder.totalWeeks(totalWeeks);
221+
builder.currentWeek(calculateService.calculateCurrentWeek(mission));
222+
builder.isCompleted(mission.isCompleted());
223+
builder.isPartyMission(mission.isPartyMission());
224+
builder.partyId(mission.getParty() != null ? mission.getParty().getId() : null);
225+
builder.progressRate(calculateService.calculateMissionProgress(mission));
226+
builder.subGoals(subGoalResponses);
227+
MissionResponse build = builder
201228
.build();
202229
return build;
203230
}

backend/src/main/java/com/back/domain/mission/service/TaskService.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,25 @@ public class TaskService {
2727
private final MissionRepository missionRepository;
2828
private final MissionCalculateService calculateService;
2929

30+
31+
// 특정 task 완료 처리
3032
public TaskCompleteResponse completeTask(Integer memberId, TaskCompleteRequest request) {
33+
//task 찾기
3134
Task task = taskRepository.findById(request.getTaskId())
3235
.orElseThrow(() -> new MissionException(MissionErrorCode.TASK_NOT_FOUND));
3336

37+
// 완료 날짜 ( 없을 시 오늘 )
3438
LocalDate completedDate = request.getDate() != null ? request.getDate() : LocalDate.now();
3539

40+
// 이미 완료한 기록이 있다면 예외처리
3641
if (taskLogRepository.existsByTaskIdAndMemberIdAndDate(
3742
request.getTaskId(), memberId, completedDate)) {
3843
throw new MissionException(MissionErrorCode.TASK_ALREADY_COMPLETED);
3944
}
4045

4146
Mission mission = task.getSubGoal().getMission();
4247

48+
//tasklog에 기록처리
4349
TaskLog taskLog = TaskLog.builder()
4450
.task(task)
4551
.memberId(memberId)
@@ -50,6 +56,7 @@ public TaskCompleteResponse completeTask(Integer memberId, TaskCompleteRequest r
5056

5157
taskLogRepository.save(taskLog);
5258

59+
// 완료 응답 반환 ( 포인트/경험치 + 진행률 포함 )
5360
return TaskCompleteResponse.builder()
5461
.taskId(task.getId())
5562
.status(request.getStatus())
@@ -62,6 +69,7 @@ public TaskCompleteResponse completeTask(Integer memberId, TaskCompleteRequest r
6269
.build();
6370
}
6471

72+
//ㅅㅁ
6573
@Transactional(readOnly = true)
6674
public List<TaskResponse> getTodayTasks(Integer memberId) {
6775
LocalDate today = LocalDate.now();

0 commit comments

Comments
 (0)