Skip to content

Commit bd166ab

Browse files
authored
Merge pull request #97 from Dalguring/feature/ming/point
민지 | 2026-04-05 | 포인트 이력 조회 추가, 결제 시 이력 description 추가
2 parents fd700b1 + bcb417a commit bd166ab

8 files changed

Lines changed: 184 additions & 0 deletions

File tree

src/main/java/com/rentify/rentify_api/payment/listener/PaymentEventListener.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,16 @@ public void handlePaymentCompleted(PaymentCompletedEvent event) {
4747
Payment payment = paymentRepository.findById(event.paymentId())
4848
.orElseThrow(PaymentNotFoundException::new);
4949

50+
String description = "[" + payment.getRental().getPost().getTitle() + "] 결제 완료";
51+
5052
PointHistory history = PointHistory.builder()
5153
.user(user)
5254
.rental(payment.getRental())
5355
.payment(payment)
5456
.type(PointHistoryType.EARN)
5557
.amount(rewardPoint)
5658
.finalBalance(user.getPoint())
59+
.description(description)
5760
.build();
5861
pointHistoryRepository.save(history);
5962
}

src/main/java/com/rentify/rentify_api/payment/service/PaymentService.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,13 +119,16 @@ public void completePayment(Long paymentId, Long userId, PaymentRequest request)
119119
User user = userRepository.findById(userId).orElseThrow(UserNotFoundException::new);
120120
user.usePoint(request.getPointAmount());
121121

122+
String description = "[" + post.getTitle() + "] 대여 시 사용";
123+
122124
PointHistory pointHistory = PointHistory.builder()
123125
.user(user)
124126
.rental(rental)
125127
.payment(payment)
126128
.type(PointHistoryType.SPEND)
127129
.amount(request.getPointAmount())
128130
.finalBalance(user.getPoint())
131+
.description(description)
129132
.build();
130133
pointHistoryRepository.save(pointHistory);
131134
}
@@ -204,27 +207,33 @@ public void cancelPayment(Long paymentId) {
204207

205208
user.usePoint(earnedPoint);
206209

210+
String description = "[" + payment.getRental().getPost().getTitle() + "] 결제 취소";
211+
207212
PointHistory reclaimHistory = PointHistory.builder()
208213
.user(user)
209214
.rental(payment.getRental())
210215
.payment(payment)
211216
.type(PointHistoryType.ADJUST)
212217
.amount(earnedPoint)
213218
.finalBalance(user.getPoint())
219+
.description(description)
214220
.build();
215221
pointHistoryRepository.save(reclaimHistory);
216222
});
217223

218224
if (payment.getUsedPoint() > 0) {
219225
user.addPoint(payment.getUsedPoint());
220226

227+
String description = "[" + payment.getRental().getPost().getTitle() + "] 대여 취소";
228+
221229
PointHistory pointHistory = PointHistory.builder()
222230
.user(user)
223231
.rental(payment.getRental())
224232
.payment(payment)
225233
.type(PointHistoryType.REFUND)
226234
.amount(payment.getUsedPoint())
227235
.finalBalance(user.getPoint())
236+
.description(description)
228237
.build();
229238
pointHistoryRepository.save(pointHistory);
230239
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package com.rentify.rentify_api.point.controller;
2+
3+
import com.rentify.rentify_api.point.dto.PointHistoryResponse;
4+
import io.swagger.v3.oas.annotations.Operation;
5+
import io.swagger.v3.oas.annotations.Parameter;
6+
import io.swagger.v3.oas.annotations.media.Content;
7+
import io.swagger.v3.oas.annotations.media.ExampleObject;
8+
import io.swagger.v3.oas.annotations.media.Schema;
9+
import io.swagger.v3.oas.annotations.responses.ApiResponse;
10+
import io.swagger.v3.oas.annotations.responses.ApiResponses;
11+
import io.swagger.v3.oas.annotations.tags.Tag;
12+
import java.util.List;
13+
import org.springframework.http.ResponseEntity;
14+
import org.springframework.security.core.annotation.AuthenticationPrincipal;
15+
import org.springframework.web.bind.annotation.GetMapping;
16+
17+
@Tag(name = "Point API", description = "포인트 관련 API")
18+
public interface PointApiDocs {
19+
20+
@Operation(
21+
summary = "포인트 이력 조회",
22+
description = "로그인한 사용자의 포인트 이력을 전체 조회합니다. 최신순으로 정렬됩니다."
23+
)
24+
@ApiResponses(value = {
25+
@ApiResponse(
26+
responseCode = "200",
27+
description = "포인트 이력 조회 성공",
28+
content = @Content(
29+
mediaType = "application/json",
30+
schema = @Schema(implementation = List.class),
31+
examples = @ExampleObject(
32+
value = """
33+
[
34+
{
35+
"historyId": 1,
36+
"type": "EARN",
37+
"amount": 1000,
38+
"finalBalance": 5000,
39+
"description": "대여 적립",
40+
"createdAt": "2026-04-05T10:30:00"
41+
},
42+
{
43+
"historyId": 2,
44+
"type": "SPEND",
45+
"amount": -500,
46+
"finalBalance": 4000,
47+
"description": "쿠폰 사용",
48+
"createdAt": "2026-04-04T15:20:00"
49+
}
50+
]
51+
"""
52+
)
53+
)
54+
),
55+
@ApiResponse(
56+
responseCode = "401",
57+
description = "인증 실패 (로그인 필요)",
58+
content = @Content(
59+
mediaType = "application/json",
60+
examples = @ExampleObject(
61+
value = "{\"success\": false, \"code\": \"401\", \"message\": \"인증이 필요합니다.\", \"data\": null}"
62+
)
63+
)
64+
),
65+
@ApiResponse(
66+
responseCode = "404",
67+
description = "존재하지 않는 사용자",
68+
content = @Content(
69+
mediaType = "application/json",
70+
examples = @ExampleObject(
71+
value = "{\"success\": false, \"code\": \"404\", \"message\": \"존재하지 않는 사용자입니다.\", \"data\": null}"
72+
)
73+
)
74+
)
75+
})
76+
@GetMapping("/history")
77+
ResponseEntity<List<PointHistoryResponse>> getPointHistory(
78+
@Parameter(hidden = true) @AuthenticationPrincipal Long userId
79+
);
80+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.rentify.rentify_api.point.controller;
2+
3+
import com.rentify.rentify_api.point.dto.PointHistoryResponse;
4+
import com.rentify.rentify_api.point.service.PointService;
5+
import java.util.List;
6+
import lombok.RequiredArgsConstructor;
7+
import org.springframework.http.ResponseEntity;
8+
import org.springframework.security.core.annotation.AuthenticationPrincipal;
9+
import org.springframework.web.bind.annotation.GetMapping;
10+
import org.springframework.web.bind.annotation.RequestMapping;
11+
import org.springframework.web.bind.annotation.RestController;
12+
13+
@RestController
14+
@RequestMapping("/api/points")
15+
@RequiredArgsConstructor
16+
public class PointController implements PointApiDocs {
17+
18+
private final PointService pointService;
19+
20+
@Override
21+
@GetMapping("/history")
22+
public ResponseEntity<List<PointHistoryResponse>> getPointHistory(
23+
@AuthenticationPrincipal Long userId
24+
) {
25+
List<PointHistoryResponse> histories = pointService.getPointHistories(userId);
26+
return ResponseEntity.ok(histories);
27+
}
28+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.rentify.rentify_api.point.dto;
2+
3+
import com.rentify.rentify_api.point.entity.PointHistory;
4+
import com.rentify.rentify_api.point.entity.PointHistoryType;
5+
import java.time.LocalDateTime;
6+
import lombok.Builder;
7+
8+
@Builder
9+
public record PointHistoryResponse(
10+
Long historyId,
11+
PointHistoryType type,
12+
Integer amount,
13+
Integer finalBalance,
14+
String description,
15+
LocalDateTime createdAt
16+
) {
17+
public static PointHistoryResponse from(PointHistory pointHistory) {
18+
return PointHistoryResponse.builder()
19+
.historyId(pointHistory.getId())
20+
.type(pointHistory.getType())
21+
.amount(pointHistory.getAmount())
22+
.finalBalance(pointHistory.getFinalBalance())
23+
.description(pointHistory.getDescription())
24+
.createdAt(pointHistory.getCreateAt())
25+
.build();
26+
}
27+
}

src/main/java/com/rentify/rentify_api/point/entity/PointHistory.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ public class PointHistory {
5757
@Column(name = "final_balance", nullable = false)
5858
private Integer finalBalance;
5959

60+
@Column(name = "description")
61+
private String description;
62+
6063
@CreationTimestamp
6164
@Column(name = "created_at", nullable = false)
6265
private LocalDateTime createAt;

src/main/java/com/rentify/rentify_api/point/repository/PointHistoryRepository.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@
33
import com.rentify.rentify_api.payment.entity.Payment;
44
import com.rentify.rentify_api.point.entity.PointHistory;
55
import com.rentify.rentify_api.point.entity.PointHistoryType;
6+
import com.rentify.rentify_api.user.entity.User;
7+
import java.util.List;
68
import java.util.Optional;
79
import org.springframework.data.jpa.repository.JpaRepository;
810

911
public interface PointHistoryRepository extends JpaRepository<PointHistory, Long> {
1012

1113
Optional<PointHistory> findByPaymentAndType(Payment payment, PointHistoryType earn);
14+
15+
List<PointHistory> findAllByUserOrderByCreateAtDesc(User user);
1216
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.rentify.rentify_api.point.service;
2+
3+
import com.rentify.rentify_api.point.dto.PointHistoryResponse;
4+
import com.rentify.rentify_api.point.repository.PointHistoryRepository;
5+
import com.rentify.rentify_api.user.entity.User;
6+
import com.rentify.rentify_api.user.exception.UserNotFoundException;
7+
import com.rentify.rentify_api.user.repository.UserRepository;
8+
import java.util.List;
9+
import lombok.RequiredArgsConstructor;
10+
import org.springframework.stereotype.Service;
11+
import org.springframework.transaction.annotation.Transactional;
12+
13+
@Service
14+
@RequiredArgsConstructor
15+
@Transactional(readOnly = true)
16+
public class PointService {
17+
18+
private final PointHistoryRepository pointHistoryRepository;
19+
private final UserRepository userRepository;
20+
21+
public List<PointHistoryResponse> getPointHistories(Long userId) {
22+
User user = userRepository.findById(userId)
23+
.orElseThrow(UserNotFoundException::new);
24+
25+
return pointHistoryRepository.findAllByUserOrderByCreateAtDesc(user)
26+
.stream()
27+
.map(PointHistoryResponse::from)
28+
.toList();
29+
}
30+
}

0 commit comments

Comments
 (0)