Skip to content

Commit db21326

Browse files
authored
Merge pull request #291 from mosu-dev/develop
[배포] 내 문의 내역 조회 시 답변도 같이 반환
2 parents 40940e7 + 76d795e commit db21326

8 files changed

Lines changed: 100 additions & 35 deletions

File tree

src/main/java/life/mosu/mosuserver/application/inquiry/InquiryService.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import life.mosu.mosuserver.presentation.inquiry.dto.InquiryCreateRequest;
1111
import life.mosu.mosuserver.presentation.inquiry.dto.InquiryDetailResponse;
1212
import life.mosu.mosuserver.presentation.inquiry.dto.InquiryDetailResponse.InquiryAnswerDetailResponse;
13+
import life.mosu.mosuserver.presentation.inquiry.dto.InquiryListResponse;
1314
import life.mosu.mosuserver.presentation.inquiry.dto.InquiryResponse;
1415
import life.mosu.mosuserver.presentation.inquiry.dto.InquiryUpdateRequest;
1516
import lombok.RequiredArgsConstructor;
@@ -56,8 +57,9 @@ public InquiryDetailResponse getInquiryDetail(UserJpaEntity user, Long postId) {
5657
}
5758

5859
@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
59-
public Page<InquiryResponse> getMyInquiry(Long userId, Pageable pageable) {
60-
return inquiryJpaRepository.searchMyInquiry(userId, pageable);
60+
public Page<InquiryListResponse> getMyInquiry(Long userId, Pageable pageable) {
61+
return inquiryJpaRepository.searchMyInquiry(userId,
62+
pageable);
6163
}
6264

6365
@Transactional

src/main/java/life/mosu/mosuserver/domain/inquiry/repository/InquiryQueryRepository.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package life.mosu.mosuserver.domain.inquiry.repository;
22

33
import life.mosu.mosuserver.domain.inquiry.entity.InquiryStatus;
4+
import life.mosu.mosuserver.presentation.inquiry.dto.InquiryListResponse;
45
import life.mosu.mosuserver.presentation.inquiry.dto.InquiryResponse;
56
import org.springframework.data.domain.Page;
67
import org.springframework.data.domain.Pageable;
@@ -10,5 +11,5 @@ public interface InquiryQueryRepository {
1011
Page<InquiryResponse> searchInquiries(InquiryStatus status, String sortField, boolean asc,
1112
Pageable pageable);
1213

13-
Page<InquiryResponse> searchMyInquiry(Long userId, Pageable pageable);
14+
Page<InquiryListResponse> searchMyInquiry(Long userId, Pageable pageable);
1415
}

src/main/java/life/mosu/mosuserver/infra/persistence/jpa/InquiryJpaRepositoryImpl.java

Lines changed: 59 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
import life.mosu.mosuserver.domain.inquiry.entity.InquiryStatus;
1616
import life.mosu.mosuserver.domain.inquiry.entity.QInquiryJpaEntity;
1717
import life.mosu.mosuserver.domain.inquiry.repository.InquiryQueryRepository;
18+
import life.mosu.mosuserver.domain.inquiryAnswer.entity.QInquiryAnswerJpaEntity;
19+
import life.mosu.mosuserver.presentation.inquiry.dto.InquiryAnswerResponse;
20+
import life.mosu.mosuserver.presentation.inquiry.dto.InquiryListResponse;
1821
import life.mosu.mosuserver.presentation.inquiry.dto.InquiryResponse;
1922
import lombok.RequiredArgsConstructor;
2023
import org.springframework.data.domain.Page;
@@ -29,6 +32,7 @@ public class InquiryJpaRepositoryImpl implements InquiryQueryRepository {
2932
private final JPAQueryFactory queryFactory;
3033
private final EntityManager entityManager;
3134
private final QInquiryJpaEntity inquiry = QInquiryJpaEntity.inquiryJpaEntity;
35+
private final QInquiryAnswerJpaEntity inquiryAnswer = QInquiryAnswerJpaEntity.inquiryAnswerJpaEntity;
3236

3337
@Override
3438
public Page<InquiryResponse> searchInquiries(
@@ -38,40 +42,42 @@ public Page<InquiryResponse> searchInquiries(
3842
Pageable pageable
3943
) {
4044

41-
JPAQuery<Tuple> query = baseQuery(inquiry)
42-
.where(buildStatusCondition(inquiry, status))
43-
.orderBy(buildOrderByCondition(sortField, asc))
44-
.offset(pageable.getOffset())
45-
.limit(pageable.getPageSize());
45+
JPAQuery<Tuple> query = baseQuery()
46+
.where(buildStatusCondition(inquiry, status));
4647

4748
long total = getTotalCount(query, inquiry.count());
4849

49-
List<InquiryResponse> content = query.fetch().stream()
50-
.map(this::mapToResponse)
50+
List<InquiryResponse> content = query
51+
.orderBy(buildOrderByCondition(sortField, asc))
52+
.offset(pageable.getOffset())
53+
.limit(pageable.getPageSize())
54+
.fetch().stream()
55+
.map(this::mapToInquiryResponse)
5156
.toList();
5257

5358
return new PageImpl<>(content, pageable, total);
5459
}
5560

5661
@Override
57-
public Page<InquiryResponse> searchMyInquiry(Long userId, Pageable pageable) {
58-
JPAQuery<Tuple> query = baseQuery(inquiry)
62+
public Page<InquiryListResponse> searchMyInquiry(Long userId, Pageable pageable) {
63+
JPAQuery<Tuple> query = baseQueryWithAnswer()
5964
.where(inquiry.userId.eq(userId));
6065

61-
long total = getTotalCount(query, inquiry.count());
66+
long total = getTotalCount(query, inquiry.countDistinct());
6267

63-
List<InquiryResponse> content = query
68+
List<InquiryListResponse> content = query
69+
.orderBy(inquiry.createdAt.desc())
6470
.offset(pageable.getOffset())
6571
.limit(pageable.getPageSize())
6672
.fetch().stream()
67-
.map(this::mapToResponse)
73+
.map(this::mapToInquiryListResponse)
6874
.toList();
6975

7076
return new PageImpl<>(content, pageable, total);
7177
}
7278

7379

74-
private JPAQuery<Tuple> baseQuery(QInquiryJpaEntity inquiry) {
80+
private JPAQuery<Tuple> baseQuery() {
7581
return queryFactory
7682
.select(
7783
inquiry.id,
@@ -85,6 +91,27 @@ private JPAQuery<Tuple> baseQuery(QInquiryJpaEntity inquiry) {
8591

8692
}
8793

94+
private JPAQuery<Tuple> baseQueryWithAnswer() {
95+
return queryFactory
96+
.select(
97+
inquiry.id,
98+
inquiry.title,
99+
inquiry.content,
100+
inquiry.author,
101+
inquiry.status,
102+
inquiry.createdAt,
103+
inquiryAnswer.id,
104+
inquiryAnswer.title,
105+
inquiryAnswer.content,
106+
inquiryAnswer.author,
107+
inquiryAnswer.createdAt,
108+
inquiryAnswer.updatedAt
109+
)
110+
.from(inquiry)
111+
.leftJoin(inquiryAnswer)
112+
.on(inquiryAnswer.inquiryId.eq(inquiry.id));
113+
}
114+
88115
private BooleanExpression buildStatusCondition(QInquiryJpaEntity inquiry,
89116
InquiryStatus status) {
90117
return status != null ? inquiry.status.eq(status) : null;
@@ -108,7 +135,7 @@ private <T> long getTotalCount(JPAQuery<T> query, Expression<Long> countExpressi
108135
).orElse(0L);
109136
}
110137

111-
private InquiryResponse mapToResponse(Tuple tuple) {
138+
private InquiryResponse mapToInquiryResponse(Tuple tuple) {
112139
InquiryStatus status = tuple.get(inquiry.status);
113140
return new InquiryResponse(
114141
tuple.get(inquiry.id),
@@ -119,4 +146,22 @@ private InquiryResponse mapToResponse(Tuple tuple) {
119146
formatDate(tuple.get(inquiry.createdAt))
120147
);
121148
}
149+
150+
151+
private InquiryListResponse mapToInquiryListResponse(Tuple tuple) {
152+
InquiryResponse inquiryDto = mapToInquiryResponse(tuple);
153+
InquiryAnswerResponse answerDto = null;
154+
155+
if (tuple.get(inquiryAnswer.id) != null) {
156+
answerDto = new InquiryAnswerResponse(
157+
tuple.get(inquiryAnswer.title),
158+
tuple.get(inquiryAnswer.content),
159+
tuple.get(inquiryAnswer.author),
160+
formatDate(tuple.get(inquiryAnswer.createdAt)),
161+
formatDate(tuple.get(inquiryAnswer.updatedAt))
162+
);
163+
}
164+
165+
return InquiryListResponse.of(inquiryDto, answerDto);
166+
}
122167
}

src/main/java/life/mosu/mosuserver/presentation/inquiry/InquiryController.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import life.mosu.mosuserver.global.util.ApiResponseWrapper;
88
import life.mosu.mosuserver.presentation.inquiry.dto.InquiryCreateRequest;
99
import life.mosu.mosuserver.presentation.inquiry.dto.InquiryDetailResponse;
10-
import life.mosu.mosuserver.presentation.inquiry.dto.InquiryResponse;
10+
import life.mosu.mosuserver.presentation.inquiry.dto.InquiryListResponse;
1111
import life.mosu.mosuserver.presentation.inquiry.dto.InquiryUpdateRequest;
1212
import lombok.RequiredArgsConstructor;
1313
import org.springframework.data.domain.Page;
@@ -54,12 +54,13 @@ public ResponseEntity<ApiResponseWrapper<Void>> update(
5454

5555
@GetMapping("/my")
5656
@PreAuthorize("isAuthenticated() and hasRole('USER')")
57-
public ResponseEntity<ApiResponseWrapper<Page<InquiryResponse>>> getMyInquiries(
57+
public ResponseEntity<ApiResponseWrapper<Page<InquiryListResponse>>> getMyInquiries(
5858
@UserId Long userId,
5959
@PageableDefault(size = 10) Pageable pageable
6060
) {
61-
Page<InquiryResponse> inquiries = inquiryService.getMyInquiry(userId, pageable);
62-
return ResponseEntity.ok(ApiResponseWrapper.success(HttpStatus.OK, "내 질문 목록 조회 성공", inquiries));
61+
Page<InquiryListResponse> inquiries = inquiryService.getMyInquiry(userId, pageable);
62+
return ResponseEntity.ok(
63+
ApiResponseWrapper.success(HttpStatus.OK, "내 질문 목록 조회 성공", inquiries));
6364
}
6465

6566
@GetMapping("/{postId}")
@@ -68,7 +69,8 @@ public ResponseEntity<ApiResponseWrapper<InquiryDetailResponse>> getInquiryDetai
6869
@AuthenticationPrincipal PrincipalDetails principalDetails,
6970
@PathVariable Long postId) {
7071

71-
InquiryDetailResponse inquiry = inquiryService.getInquiryDetail(principalDetails.user(), postId);
72+
InquiryDetailResponse inquiry = inquiryService.getInquiryDetail(principalDetails.user(),
73+
postId);
7274
return ResponseEntity.ok(ApiResponseWrapper.success(HttpStatus.OK, "질문 상세 조회 성공",
7375
inquiry));
7476
}

src/main/java/life/mosu/mosuserver/presentation/inquiry/InquiryControllerDocs.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import life.mosu.mosuserver.global.util.ApiResponseWrapper;
1414
import life.mosu.mosuserver.presentation.inquiry.dto.InquiryCreateRequest;
1515
import life.mosu.mosuserver.presentation.inquiry.dto.InquiryDetailResponse;
16-
import life.mosu.mosuserver.presentation.inquiry.dto.InquiryResponse;
16+
import life.mosu.mosuserver.presentation.inquiry.dto.InquiryListResponse;
1717
import org.springframework.data.domain.Page;
1818
import org.springframework.data.domain.Pageable;
1919
import org.springframework.http.ResponseEntity;
@@ -37,7 +37,7 @@ ResponseEntity<ApiResponseWrapper<Void>> create(
3737
@ApiResponse(responseCode = "200", description = "내 문의글 목록 조회 성공",
3838
content = @Content(schema = @Schema(implementation = Page.class)))
3939
})
40-
ResponseEntity<ApiResponseWrapper<Page<InquiryResponse>>> getMyInquiries(
40+
ResponseEntity<ApiResponseWrapper<Page<InquiryListResponse>>> getMyInquiries(
4141
@Parameter(description = "사용자 ID", required = true) Long userId,
4242
@Parameter(description = "페이지 정보") Pageable pageable
4343
);
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package life.mosu.mosuserver.presentation.inquiry.dto;
2+
3+
public record InquiryAnswerResponse(
4+
String title,
5+
String content,
6+
String author,
7+
String createdAt,
8+
String updatedAt
9+
) {
10+
11+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package life.mosu.mosuserver.presentation.inquiry.dto;
2+
3+
public record InquiryListResponse(
4+
InquiryResponse inquiry,
5+
InquiryAnswerResponse reply
6+
) {
7+
8+
public static InquiryListResponse of(
9+
InquiryResponse inquiry,
10+
InquiryAnswerResponse reply
11+
) {
12+
return new InquiryListResponse(inquiry, reply);
13+
}
14+
}

src/main/java/life/mosu/mosuserver/presentation/inquiry/dto/InquiryResponse.java

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package life.mosu.mosuserver.presentation.inquiry.dto;
22

33
import io.swagger.v3.oas.annotations.media.Schema;
4-
import life.mosu.mosuserver.domain.inquiry.entity.InquiryJpaEntity;
54

65
@Schema(description = "1:1 문의 응답 DTO")
76
public record InquiryResponse(
@@ -24,14 +23,5 @@ public record InquiryResponse(
2423
String createdAt
2524
) {
2625

27-
public static InquiryResponse of(InquiryJpaEntity inquiry) {
28-
return new InquiryResponse(
29-
inquiry.getId(),
30-
inquiry.getTitle(),
31-
inquiry.getContent(),
32-
inquiry.getAuthor(),
33-
inquiry.getStatus().getStatusName(),
34-
inquiry.getCreatedAt()
35-
);
36-
}
26+
3727
}

0 commit comments

Comments
 (0)