Skip to content

Commit 37981eb

Browse files
committed
refactor: 스탬프 엔티티 필드 추가 및 관련 작업 리팩토링 (#83)
* feat: 스탬프 엔티티 end_date, total_missions, completed_missions 필드 추가 * feat: Flyway V4__add_columns_to_stamp.sql 파일 추가 * feat: 스탬프 종료일 검증 Policy 메서드 구현 * feat: 스탬프 종료일 ErrorCode 추가 * refactor: 스탬프 생성/수정 로직 리팩토링 * refactor: 미션 생성/삭제 로직 리팩토링 * refactor: 학습 로그 생성(미션 완료 기능 포함) 로직 리팩토링 * refactor: LoadStampDetailResponse DTO 리팩토링 * refactor: LoadStampInfoResponse DTO 리팩토링 * test: 스탬프 생성/수정, 미션 생성/삭제, 학습 로그 생성 테스트 코드 수정
1 parent 1f5eda5 commit 37981eb

24 files changed

Lines changed: 482 additions & 31 deletions

File tree

src/main/java/com/ject/studytrip/mission/application/facade/MissionFacade.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.ject.studytrip.mission.domain.model.Mission;
1010
import com.ject.studytrip.mission.presentation.dto.request.CreateMissionRequest;
1111
import com.ject.studytrip.mission.presentation.dto.request.UpdateMissionRequest;
12+
import com.ject.studytrip.stamp.application.service.StampCommandService;
1213
import com.ject.studytrip.stamp.application.service.StampQueryService;
1314
import com.ject.studytrip.stamp.domain.model.Stamp;
1415
import com.ject.studytrip.trip.application.service.TripQueryService;
@@ -28,6 +29,7 @@ public class MissionFacade {
2829
private final StampQueryService stampQueryService;
2930
private final MissionQueryService missionQueryService;
3031

32+
private final StampCommandService stampCommandService;
3133
private final MissionCommandService missionCommandService;
3234

3335
@Caching(
@@ -47,6 +49,7 @@ public MissionInfo createMission(
4749
Stamp stamp = getValidStampFromTripOwnedByMember(memberId, tripId, stampId);
4850
Mission mission = missionCommandService.createMission(stamp, request);
4951

52+
stampCommandService.increaseTotalMissions(stamp);
5053
return MissionInfo.from(mission);
5154
}
5255

@@ -91,6 +94,7 @@ public void deleteMission(Long memberId, Long tripId, Long stampId, Long mission
9194
Mission mission = missionQueryService.getValidMission(stamp.getId(), missionId);
9295

9396
missionCommandService.deleteMission(mission);
97+
stampCommandService.decreaseTotalMissions(stamp);
9498
}
9599

96100
@Cacheable(

src/main/java/com/ject/studytrip/mission/application/service/DailyMissionQueryService.java

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,31 @@ public class DailyMissionQueryService {
1717
public List<DailyMission> getValidDailyMissionsByIds(
1818
Long dailyGoalId, List<Long> dailyMissionIds) {
1919
List<DailyMission> dailyMissions = dailyMissionRepository.findAllByIdIn(dailyMissionIds);
20+
validateDailyMissions(dailyMissions, dailyMissionIds, dailyGoalId);
2021

21-
DailyMissionPolicy.validateExistAll(dailyMissions, dailyMissionIds);
22-
dailyMissions.forEach(
23-
dailyMission -> {
24-
DailyMissionPolicy.validateBelongsToDailyGoal(dailyMission, dailyGoalId);
25-
DailyMissionPolicy.validateNotDeleted(dailyMission);
26-
});
22+
return dailyMissions;
23+
}
24+
25+
public List<DailyMission> getValidDailyMissionsWithMissionAndStampByIds(
26+
Long dailyGoalId, List<Long> dailyMissionIds) {
27+
List<DailyMission> dailyMissions =
28+
dailyMissionQueryRepository.findAllWithMissionAndStampByIds(dailyMissionIds);
29+
validateDailyMissions(dailyMissions, dailyMissionIds, dailyGoalId);
2730

2831
return dailyMissions;
2932
}
3033

3134
public List<DailyMission> getDailyMissionsByDailyGoal(Long dailyGoalId) {
3235
return dailyMissionQueryRepository.findAllByDailyGoalIdFetchJoinMission(dailyGoalId);
3336
}
37+
38+
private void validateDailyMissions(
39+
List<DailyMission> dailyMissions, List<Long> dailyMissionIds, Long dailyGoalId) {
40+
DailyMissionPolicy.validateExistAll(dailyMissions, dailyMissionIds);
41+
dailyMissions.forEach(
42+
dailyMission -> {
43+
DailyMissionPolicy.validateBelongsToDailyGoal(dailyMission, dailyGoalId);
44+
DailyMissionPolicy.validateNotDeleted(dailyMission);
45+
});
46+
}
3447
}

src/main/java/com/ject/studytrip/mission/domain/repository/DailyMissionQueryRepository.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
public interface DailyMissionQueryRepository {
77
List<DailyMission> findAllByDailyGoalIdFetchJoinMission(Long dailyGoalId);
88

9+
List<DailyMission> findAllWithMissionAndStampByIds(List<Long> ids);
10+
911
long deleteAllByDeletedAtIsNotNull();
1012

1113
long deleteAllByDeletedMissionOwner();

src/main/java/com/ject/studytrip/mission/infra/querydsl/DailyMissionQueryRepositoryAdapter.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.ject.studytrip.mission.domain.model.QDailyMission;
55
import com.ject.studytrip.mission.domain.model.QMission;
66
import com.ject.studytrip.mission.domain.repository.DailyMissionQueryRepository;
7+
import com.ject.studytrip.stamp.domain.model.QStamp;
78
import com.ject.studytrip.trip.domain.model.QDailyGoal;
89
import com.querydsl.jpa.JPAExpressions;
910
import com.querydsl.jpa.impl.JPAQueryFactory;
@@ -16,6 +17,7 @@
1617
public class DailyMissionQueryRepositoryAdapter implements DailyMissionQueryRepository {
1718
private final JPAQueryFactory queryFactory;
1819
private final QDailyMission dailyMission = QDailyMission.dailyMission;
20+
private final QStamp stamp = QStamp.stamp;
1921
private final QMission mission = QMission.mission;
2022
private final QDailyGoal dailyGoal = QDailyGoal.dailyGoal;
2123

@@ -29,6 +31,18 @@ public List<DailyMission> findAllByDailyGoalIdFetchJoinMission(Long dailyGoalId)
2931
.fetch();
3032
}
3133

34+
@Override
35+
public List<DailyMission> findAllWithMissionAndStampByIds(List<Long> ids) {
36+
return queryFactory
37+
.selectFrom(dailyMission)
38+
.join(dailyMission.mission, mission)
39+
.fetchJoin()
40+
.join(mission.stamp, stamp)
41+
.fetchJoin()
42+
.where(dailyMission.id.in(ids))
43+
.fetch();
44+
}
45+
3246
@Override
3347
public long deleteAllByDeletedAtIsNotNull() {
3448
return queryFactory

src/main/java/com/ject/studytrip/stamp/application/dto/StampInfo.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ public record StampInfo(
77
Long stampId,
88
String stampName,
99
int stampOrder,
10+
String endDate,
11+
int totalMissions,
12+
int completedMissions,
1013
boolean completed,
1114
String createdAt,
1215
String updatedAt,
@@ -16,6 +19,9 @@ public static StampInfo from(Stamp stamp) {
1619
stamp.getId(),
1720
stamp.getName(),
1821
stamp.getStampOrder(),
22+
DateUtil.formatDate(stamp.getEndDate()),
23+
stamp.getTotalMissions(),
24+
stamp.getCompletedMissions(),
1925
stamp.isCompleted(),
2026
DateUtil.formatDateTime(stamp.getCreatedAt()),
2127
DateUtil.formatDateTime(stamp.getUpdatedAt()),

src/main/java/com/ject/studytrip/stamp/application/facade/StampFacade.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public void updateStamp(Long memberId, Long tripId, Long stampId, UpdateStampReq
7373
Trip trip = tripQueryService.getValidTrip(memberId, tripId);
7474
Stamp stamp = stampQueryService.getValidStamp(trip.getId(), stampId);
7575

76-
stampCommandService.updateStampName(stamp, request);
76+
stampCommandService.updateStamp(trip, stamp, request);
7777
}
7878

7979
@Caching(

src/main/java/com/ject/studytrip/stamp/application/service/StampCommandService.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import com.ject.studytrip.stamp.presentation.dto.request.UpdateStampRequest;
1111
import com.ject.studytrip.trip.domain.model.Trip;
1212
import com.ject.studytrip.trip.domain.model.TripCategory;
13+
import java.time.LocalDate;
1314
import java.util.*;
1415
import java.util.function.Function;
1516
import java.util.stream.Collectors;
@@ -23,31 +24,40 @@ public class StampCommandService {
2324
private final StampQueryRepository stampQueryRepository;
2425

2526
public Stamp createStamp(Trip trip, CreateStampRequest request) {
26-
Stamp newStamp = StampFactory.create(trip, request.name(), request.order());
27+
Stamp newStamp =
28+
StampFactory.create(trip, request.name(), request.order(), request.endDate());
2729

2830
List<Stamp> existingStamps =
2931
stampRepository.findAllByTripIdAndDeletedAtIsNull(trip.getId());
3032
List<Stamp> combinedStamps = new ArrayList<>(existingStamps);
3133
combinedStamps.add(newStamp);
3234

3335
StampPolicy.validateStampOrders(trip.getCategory(), combinedStamps);
36+
StampPolicy.validateEndDate(trip.getEndDate(), newStamp.getEndDate());
3437

3538
return stampRepository.save(newStamp);
3639
}
3740

3841
public void createStamps(Trip trip, List<CreateStampRequest> requests) {
3942
List<Stamp> stamps =
4043
requests.stream()
41-
.map(stamp -> StampFactory.create(trip, stamp.name(), stamp.order()))
44+
.map(
45+
stamp ->
46+
StampFactory.create(
47+
trip, stamp.name(), stamp.order(), stamp.endDate()))
4248
.toList();
4349

4450
StampPolicy.validateStampOrders(trip.getCategory(), stamps);
4551

4652
stampRepository.saveAll(stamps);
4753
}
4854

49-
public void updateStampName(Stamp stamp, UpdateStampRequest request) {
55+
public void updateStamp(Trip trip, Stamp stamp, UpdateStampRequest request) {
5056
stamp.updateName(request.name());
57+
58+
LocalDate endDate = request.endDate();
59+
StampPolicy.validateEndDate(trip.getEndDate(), endDate);
60+
stamp.updateEndDate(endDate);
5161
}
5262

5363
public void updateStampOrders(Trip trip, UpdateStampOrderRequest request) {
@@ -129,4 +139,16 @@ private void shiftStampOrdersAfterDeleted(Long tripId, int deletedStampOrder) {
129139
stamp.updateStampOrder(stamp.getStampOrder() - 1);
130140
}
131141
}
142+
143+
public void increaseTotalMissions(Stamp stamp) {
144+
stamp.increaseTotalMissions();
145+
}
146+
147+
public void decreaseTotalMissions(Stamp stamp) {
148+
stamp.decreaseTotalMissions();
149+
}
150+
151+
public void increaseCompletedMissions(Stamp stamp, int count) {
152+
stamp.increaseCompletedMissions(count);
153+
}
132154
}

src/main/java/com/ject/studytrip/stamp/domain/error/StampErrorCode.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ public enum StampErrorCode implements ErrorCode {
1818
STAMP_LIST_CANNOT_BE_EMPTY(HttpStatus.BAD_REQUEST, "스탬프 목록은 비어있을 수 없습니다."),
1919
STAMP_ALREADY_COMPLETED(HttpStatus.BAD_REQUEST, "이미 완료된 스탬프입니다."),
2020
ALL_STAMPS_NOT_COMPLETED(HttpStatus.BAD_REQUEST, "모든 스탬프가 완료되지 않았습니다."),
21+
STAMP_END_DATE_CANNOT_BE_IN_PAST(HttpStatus.BAD_REQUEST, "스탬프의 종료일은 과거일 수 없습니다."),
22+
STAMP_END_DATE_AFTER_TRIP_END_DATE_NOT_ALLOWED(
23+
HttpStatus.BAD_REQUEST, "스탬프의 종료일은 여행 종료일보다 이후일 수 없습니다."),
2124

2225
// 403
2326
STAMP_NOT_BELONG_TO_TRIP(HttpStatus.FORBIDDEN, "해당 스탬프는 요청한 여행에 속하지 않습니다."),

src/main/java/com/ject/studytrip/stamp/domain/factory/StampFactory.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22

33
import com.ject.studytrip.stamp.domain.model.Stamp;
44
import com.ject.studytrip.trip.domain.model.Trip;
5+
import java.time.LocalDate;
56
import lombok.AccessLevel;
67
import lombok.NoArgsConstructor;
78

89
@NoArgsConstructor(access = AccessLevel.PRIVATE)
910
public class StampFactory {
10-
public static Stamp create(Trip trip, String name, int stampOrder) {
11-
return Stamp.of(trip, name, stampOrder);
11+
public static Stamp create(Trip trip, String name, int stampOrder, LocalDate endDate) {
12+
return Stamp.of(trip, name, stampOrder, endDate);
1213
}
1314
}

src/main/java/com/ject/studytrip/stamp/domain/model/Stamp.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.ject.studytrip.global.common.entity.BaseTimeEntity;
66
import com.ject.studytrip.trip.domain.model.Trip;
77
import jakarta.persistence.*;
8+
import java.time.LocalDate;
89
import java.time.LocalDateTime;
910
import lombok.*;
1011

@@ -28,13 +29,22 @@ public class Stamp extends BaseTimeEntity {
2829

2930
private int stampOrder;
3031

32+
private LocalDate endDate;
33+
34+
private int totalMissions;
35+
36+
private int completedMissions;
37+
3138
private boolean completed;
3239

33-
public static Stamp of(Trip trip, String name, int stampOrder) {
40+
public static Stamp of(Trip trip, String name, int stampOrder, LocalDate endDate) {
3441
return Stamp.builder()
3542
.trip(trip)
3643
.name(name)
3744
.stampOrder(stampOrder)
45+
.endDate(endDate)
46+
.totalMissions(0)
47+
.completedMissions(0)
3848
.completed(false)
3949
.build();
4050
}
@@ -47,11 +57,27 @@ public void updateStampOrder(int newOrder) {
4757
this.stampOrder = newOrder;
4858
}
4959

60+
public void updateEndDate(LocalDate endDate) {
61+
this.endDate = endDate;
62+
}
63+
5064
public void updateCompleted() {
5165
this.completed = true;
5266
}
5367

5468
public void updateDeletedAt() {
5569
this.deletedAt = LocalDateTime.now();
5670
}
71+
72+
public void increaseTotalMissions() {
73+
this.totalMissions += 1;
74+
}
75+
76+
public void decreaseTotalMissions() {
77+
this.totalMissions -= 1;
78+
}
79+
80+
public void increaseCompletedMissions(int count) {
81+
this.completedMissions += count;
82+
}
5783
}

0 commit comments

Comments
 (0)