Skip to content

Commit cf25724

Browse files
authored
Merge pull request #69 from fullstack-dev-hub/feature/#68-estimates-pagination
[Feature] 견적서 조회 페이지네이션 적용
2 parents e95fc64 + e783a11 commit cf25724

File tree

13 files changed

+201
-62
lines changed

13 files changed

+201
-62
lines changed

backend/src/main/java/com/postdm/backend/domain/estimate/controller/EstimateController.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
11
package com.postdm.backend.domain.estimate.controller;
22

3+
import com.postdm.backend.domain.estimate.dto.EstimateListResponseDto;
34
import com.postdm.backend.domain.estimate.dto.EstimateRequestDto;
45
import com.postdm.backend.domain.estimate.dto.EstimateResponseDto;
6+
import com.postdm.backend.domain.estimate.dto.PageResponse;
57
import com.postdm.backend.domain.estimate.service.EstimateService;
68
import com.postdm.backend.domain.member.dto.MemberPrincipalDto;
79
import com.postdm.backend.global.template.ResponseTemplate;
810
import io.swagger.v3.oas.annotations.Operation;
911
import io.swagger.v3.oas.annotations.tags.Tag;
1012
import lombok.extern.slf4j.Slf4j;
13+
import org.springframework.data.domain.Sort;
14+
import org.springframework.data.web.PageableDefault;
1115
import org.springframework.http.HttpStatus;
1216
import org.springframework.http.ResponseEntity;
1317
import org.springframework.security.core.annotation.AuthenticationPrincipal;
1418
import org.springframework.web.bind.annotation.*;
19+
import org.springframework.data.domain.Page;
1520

16-
import java.util.List;
21+
import org.springframework.data.domain.Pageable;
1722

1823
@Slf4j
1924
@Tag(name = "Estimate API", description = "견적서 관련 API")
@@ -41,8 +46,11 @@ public ResponseEntity<ResponseTemplate<EstimateResponseDto>> createEstimate(@Aut
4146

4247
@Operation(summary = "견적서 조회", description = "관리자는 모든 견적서를, 사용자는 본인의 견적서만 조회합니다.")
4348
@GetMapping
44-
public ResponseEntity<ResponseTemplate<List<EstimateResponseDto>>> getEstimates(@AuthenticationPrincipal MemberPrincipalDto currentUser) {
45-
List<EstimateResponseDto> response = estimateService.getEstimates(currentUser);
49+
public ResponseEntity<ResponseTemplate<PageResponse<EstimateListResponseDto>>> getEstimates(
50+
@AuthenticationPrincipal MemberPrincipalDto currentUser,
51+
@PageableDefault(page = 0, size = 6, sort = {"id"}, direction = Sort.Direction.DESC) Pageable pageable) {
52+
Page<EstimateListResponseDto> page = estimateService.getEstimates(currentUser, pageable);
53+
PageResponse<EstimateListResponseDto> response = PageResponse.from(page);
4654
return ResponseEntity
4755
.status(HttpStatus.OK)
4856
.body(new ResponseTemplate<>(HttpStatus.OK, "견적서 조회 성공", response));
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.postdm.backend.domain.estimate.dto;
2+
3+
import com.postdm.backend.domain.estimate.entity.Estimate;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Getter;
6+
7+
import java.time.LocalDateTime;
8+
9+
@Getter
10+
@AllArgsConstructor
11+
public class EstimateListResponseDto {
12+
private Long id;
13+
private String title;
14+
private LocalDateTime createdAt;
15+
private Long memberId;
16+
17+
public static EstimateListResponseDto from(Estimate estimate) {
18+
return new EstimateListResponseDto(
19+
estimate.getId(),
20+
estimate.getTitle(),
21+
estimate.getCreatedAt(),
22+
estimate.getMember().getId()
23+
);
24+
}
25+
}
Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
package com.postdm.backend.domain.estimate.dto;
22

3+
import com.postdm.backend.domain.estimate.entity.Estimate;
34
import io.swagger.v3.oas.annotations.media.Schema;
5+
import lombok.AllArgsConstructor;
46
import lombok.Getter;
57

68
import java.time.LocalDateTime;
79

810
@Getter
911
@Schema(description = "견적서 응답 DTO")
12+
@AllArgsConstructor
1013
public class EstimateResponseDto {
1114

1215
@Schema(description = "견적서 ID", example = "1")
1316
private Long id;
1417

15-
@Schema(description = "견적서 제목 (내용 앞 10글자 + ... 자동 생성)", example = "이것은 견적서의 내...")
18+
@Schema(description = "견적서 제목 (내용 앞 10글자 + **** 자동 생성)", example = "이것은 견적서의 내...")
1619
private String title;
1720

1821
@Schema(description = "견적서 내용", example = "이것은 견적서의 내용입니다.")
@@ -24,11 +27,13 @@ public class EstimateResponseDto {
2427
@Schema(description = "작성자", example = "user1")
2528
private Long memberId;
2629

27-
public EstimateResponseDto(Long id, String title, String content, LocalDateTime createdAt, Long memberId) {
28-
this.id = id;
29-
this.title = title;
30-
this.content = content;
31-
this.createdAt = createdAt;
32-
this.memberId = memberId;
30+
public static EstimateResponseDto from(Estimate estimate) {
31+
return new EstimateResponseDto(
32+
estimate.getId(),
33+
estimate.getTitle(),
34+
estimate.getContent(),
35+
estimate.getCreatedAt(),
36+
estimate.getMember().getId()
37+
);
3338
}
3439
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package com.postdm.backend.domain.estimate.dto;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Getter;
5+
import org.springframework.data.domain.Page;
6+
import org.springframework.data.domain.Sort;
7+
8+
import java.util.List;
9+
import java.util.stream.Collectors;
10+
11+
@Getter
12+
@AllArgsConstructor
13+
public class PageResponse<T> {
14+
private List<T> content;
15+
private int page;
16+
private int size;
17+
private long totalElements;
18+
private int totalPages;
19+
private boolean first;
20+
private boolean last;
21+
private List<SortInfo> sort;
22+
23+
public static <T> PageResponse<T> from(Page<T> page) {
24+
List<SortInfo> sortInfo = page.getSort().stream()
25+
.map(SortInfo::new)
26+
.collect(Collectors.toList());
27+
28+
return new PageResponse<>(
29+
page.getContent(),
30+
page.getNumber(),
31+
page.getSize(),
32+
page.getTotalElements(),
33+
page.getTotalPages(),
34+
page.isFirst(),
35+
page.isLast(),
36+
sortInfo
37+
);
38+
}
39+
40+
@Getter
41+
@AllArgsConstructor
42+
public static class SortInfo {
43+
private String property;
44+
private String direction;
45+
46+
public SortInfo(Sort.Order order) {
47+
this.property = order.getProperty();
48+
this.direction = order.getDirection().name();
49+
}
50+
}
51+
}

backend/src/main/java/com/postdm/backend/domain/estimate/entity/Estimate.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,6 @@ public void update(String content) {
4949
}
5050

5151
private String generateTitle(String content) {
52-
return content.length() > 10 ? content.substring(0, 10) + "..." : content;
52+
return content.length() > 10 ? content.substring(0, 10) + "****" : content;
5353
}
5454
}
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package com.postdm.backend.domain.estimate.entity;
22

3+
import com.postdm.backend.domain.member.domain.entity.Member;
4+
import org.springframework.data.domain.Page;
35
import org.springframework.data.jpa.repository.JpaRepository;
46

5-
import java.util.List;
7+
import org.springframework.data.domain.Pageable;
68

79
public interface EstimateRepository extends JpaRepository<Estimate, Long> {
8-
List<Estimate> findByMemberId(Long memberId);
10+
Page<Estimate> findAll(Pageable pageable); // 관리자용
11+
Page<Estimate> findByMember(Member member, Pageable pageable); // 사용자용
912
}

backend/src/main/java/com/postdm/backend/domain/estimate/service/EstimateService.java

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.postdm.backend.domain.estimate.service;
22

3+
import com.postdm.backend.domain.estimate.dto.EstimateListResponseDto;
34
import com.postdm.backend.domain.estimate.dto.EstimateResponseDto;
45
import com.postdm.backend.domain.estimate.entity.Estimate;
56
import com.postdm.backend.domain.estimate.entity.EstimateRepository;
@@ -13,14 +14,16 @@
1314
import com.postdm.backend.global.common.response.ErrorCode;
1415
import lombok.RequiredArgsConstructor;
1516
import lombok.extern.slf4j.Slf4j;
17+
import org.springframework.data.domain.Page;
1618
import org.springframework.stereotype.Service;
19+
import org.springframework.transaction.annotation.Transactional;
1720

18-
import java.util.List;
19-
import java.util.stream.Collectors;
21+
import org.springframework.data.domain.Pageable;
2022

2123
@Slf4j
2224
@Service
2325
@RequiredArgsConstructor
26+
@Transactional(readOnly = true)
2427
public class EstimateService {
2528
private final EstimateRepository estimateRepository;
2629
private final MemberRepository memberRepository;
@@ -46,18 +49,14 @@ public EstimateResponseDto createEstimate(String content, MemberPrincipalDto pri
4649
);
4750
}
4851

49-
public List<EstimateResponseDto> getEstimates(MemberPrincipalDto principal) {
52+
public Page<EstimateListResponseDto> getEstimates(MemberPrincipalDto principal, Pageable pageable) {
5053
Member member = findMemberOrThrow(principal.getId());
5154

52-
List<Estimate> estimates = (member.getRole() == MemberRole.ADMIN)
53-
? adminPolicy.getEstimates(member, estimateRepository)
54-
: userPolicy.getEstimates(member, estimateRepository);
55+
Page<Estimate> page = (member.getRole() == MemberRole.ADMIN)
56+
? adminPolicy.getEstimates(member, estimateRepository, pageable)
57+
: userPolicy.getEstimates(member, estimateRepository, pageable);
5558

56-
return estimates.stream()
57-
.map(e -> new EstimateResponseDto(
58-
e.getId(), e.getTitle(), e.getContent(), e.getCreatedAt(), e.getMember().getId()
59-
))
60-
.collect(Collectors.toList());
59+
return page.map(EstimateListResponseDto::from);
6160
}
6261

6362
public EstimateResponseDto getEstimateDetail(Long estimateId, MemberPrincipalDto principal) {

backend/src/main/java/com/postdm/backend/domain/estimate/service/policy/AdminEstimatePolicy.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,17 @@
33
import com.postdm.backend.domain.estimate.entity.Estimate;
44
import com.postdm.backend.domain.estimate.entity.EstimateRepository;
55
import com.postdm.backend.domain.member.domain.entity.Member;
6+
import lombok.RequiredArgsConstructor;
7+
import org.springframework.data.domain.Page;
68
import org.springframework.stereotype.Component;
79

8-
import java.util.List;
10+
import org.springframework.data.domain.Pageable;
911

1012
@Component
13+
@RequiredArgsConstructor
1114
public class AdminEstimatePolicy implements EstimatePolicy {
1215
@Override
13-
public List<Estimate> getEstimates(Member member, EstimateRepository repository) {
14-
return repository.findAll(); // 관리자: 전체 조회
16+
public Page<Estimate> getEstimates(Member member, EstimateRepository repository, Pageable pageable) {
17+
return repository.findAll(pageable);
1518
}
1619
}

backend/src/main/java/com/postdm/backend/domain/estimate/service/policy/EstimatePolicy.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
import com.postdm.backend.domain.estimate.entity.Estimate;
44
import com.postdm.backend.domain.estimate.entity.EstimateRepository;
55
import com.postdm.backend.domain.member.domain.entity.Member;
6+
import org.springframework.data.domain.Page;
67

7-
import java.util.List;
8+
import org.springframework.data.domain.Pageable;
89

910
public interface EstimatePolicy {
10-
List<Estimate> getEstimates(Member member, EstimateRepository repository);
11+
Page<Estimate> getEstimates(Member member, EstimateRepository repository, Pageable pageable);
1112
}

backend/src/main/java/com/postdm/backend/domain/estimate/service/policy/UserEstimatePolicy.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,17 @@
33
import com.postdm.backend.domain.estimate.entity.Estimate;
44
import com.postdm.backend.domain.estimate.entity.EstimateRepository;
55
import com.postdm.backend.domain.member.domain.entity.Member;
6+
import lombok.RequiredArgsConstructor;
7+
import org.springframework.data.domain.Page;
68
import org.springframework.stereotype.Component;
79

8-
import java.util.List;
10+
import org.springframework.data.domain.Pageable;
911

1012
@Component
13+
@RequiredArgsConstructor
1114
public class UserEstimatePolicy implements EstimatePolicy {
1215
@Override
13-
public List<Estimate> getEstimates(Member member, EstimateRepository repository) {
14-
return repository.findByMemberId(member.getId()); // 일반 유저: 본인만 조회
16+
public Page<Estimate> getEstimates(Member member, EstimateRepository repository, Pageable pageable) {
17+
return repository.findByMember(member, pageable);
1518
}
1619
}

0 commit comments

Comments
 (0)