Skip to content

Commit 030e6f2

Browse files
authored
Merge pull request #18 from nayoung238/refactor/db-view
Refactor: Payment DB view 생성
2 parents 64b1027 + 3b0fec5 commit 030e6f2

21 files changed

+203
-90
lines changed

src/main/java/banking/account/entity/Account.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public class Account extends BaseTimeEntity {
2828
@JoinColumn(name = "user_id", nullable = false)
2929
private User user;
3030

31-
@Column(nullable = false, unique = true)
31+
@Column(nullable = false, unique = true, name = "account_number")
3232
private String accountNumber;
3333

3434
@Column(nullable = false)

src/main/java/banking/common/entity/BaseTimeEntity.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
public abstract class BaseTimeEntity {
1717

1818
@CreatedDate
19-
@Column(nullable = false, updatable = false)
19+
@Column(nullable = false, updatable = false, name = "created_at")
2020
private LocalDateTime createdAt;
2121

2222
@LastModifiedDate

src/main/java/banking/payment/api/PaymentController.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
import banking.auth.entity.UserPrincipal;
44
import banking.payment.dto.request.PaymentRefundRequest;
55
import banking.payment.dto.request.PaymentRequest;
6-
import banking.payment.dto.response.PaymentResponse;
76
import banking.payment.dto.response.RefundPaymentResponse;
7+
import banking.payment.entity.PaymentView;
88
import banking.payment.service.PaymentService;
99
import io.swagger.v3.oas.annotations.Operation;
1010
import io.swagger.v3.oas.annotations.media.Content;
@@ -37,7 +37,7 @@ public class PaymentController {
3737
description = "바디에 {withdrawAccountNumber, depositAccountNumber,amount, password} json 형식 추가 & Request Header에 Access Token 설정"
3838
)
3939
@ApiResponses({
40-
@ApiResponse(responseCode = "200", description = "결제 성공", content = @Content(schema = @Schema(implementation = PaymentResponse.class))),
40+
@ApiResponse(responseCode = "200", description = "결제 성공", content = @Content(schema = @Schema(implementation = PaymentView.class))),
4141
@ApiResponse(responseCode = "404", description = "존재하지 않는 계좌.", content = @Content(schema = @Schema(implementation = String.class))),
4242
@ApiResponse(responseCode = "401", description = "비밀번호 불알치", content = @Content(schema = @Schema(implementation = String.class))),
4343
@ApiResponse(responseCode = "400", description = "잔액 부족 / 같은 계좌 간 이체 불가", content = @Content(schema = @Schema(implementation = String.class)))
@@ -46,7 +46,7 @@ public class PaymentController {
4646
// @Decrypt
4747
public ResponseEntity<?> processPayment(@Valid @RequestBody PaymentRequest paymentRequest,
4848
@AuthenticationPrincipal UserPrincipal userPrincipal) {
49-
PaymentResponse response = paymentService.processPayment(userPrincipal.getId(), paymentRequest);
49+
PaymentView response = paymentService.processPayment(userPrincipal.getId(), paymentRequest);
5050
return ResponseEntity.ok(response);
5151
}
5252

@@ -78,13 +78,13 @@ public ResponseEntity<?> refundPayment(@Valid @RequestBody PaymentRefundRequest
7878
*/
7979
@Operation(summary = "결제 내역 조회", description = "url 변수에 결제 id 설정 & Request Header에 Access Token 설정")
8080
@ApiResponses({
81-
@ApiResponse(responseCode = "200", description = "결제 내역 조회 완료", content = @Content(schema = @Schema(implementation = PaymentResponse.class))),
81+
@ApiResponse(responseCode = "200", description = "결제 내역 조회 완료", content = @Content(schema = @Schema(implementation = PaymentView.class))),
8282
@ApiResponse(responseCode = "404", description = "존재하지 않는 결제 내역", content = @Content(schema = @Schema(implementation = String.class)))
8383
})
8484
@GetMapping("/{paymentId}")
8585
public ResponseEntity<?> findPaymentDetail(@PathVariable("paymentId") Long paymentId,
8686
@AuthenticationPrincipal UserPrincipal userPrincipal) {
87-
PaymentResponse response = paymentService.findPaymentById(userPrincipal.getId(), paymentId);
87+
PaymentView response = paymentService.findPaymentById(userPrincipal.getId(), paymentId);
8888
return ResponseEntity.ok(response);
8989
}
9090

src/main/java/banking/payment/dto/response/PaymentResponse.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public record PaymentResponse (
2222
PaymentStatus paymentStatus,
2323

2424
@Schema(description = "결제하는 계좌 번호", example = "5792214-80232581")
25-
String withdrawAccountNumber,
25+
String withdrawalAccountNumber,
2626

2727
@Schema(description = "수취인 이름", example = "홍길동")
2828
String payeeName,
@@ -41,11 +41,11 @@ public record PaymentResponse (
4141
LocalDateTime paidAt
4242
) {
4343
public static PaymentResponse of(Payment payment, PaymentTransferDetailResponse transferResponse,
44-
String withdrawAccountNumber, String payeeName) {
44+
String withdrawalAccountNumber, String payeeName) {
4545
return PaymentResponse.builder()
4646
.paymentId(payment.getId())
4747
.paymentStatus(payment.getPaymentStatus())
48-
.withdrawAccountNumber(withdrawAccountNumber)
48+
.withdrawalAccountNumber(withdrawalAccountNumber)
4949
.payeeName(payeeName)
5050
.amount(stripZeros(transferResponse.amount()))
5151
.exchangeRate(stripZeros(transferResponse.exchangeRate()))

src/main/java/banking/payment/entity/Payment.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,17 @@ public class Payment {
1515
@GeneratedValue(strategy = GenerationType.IDENTITY)
1616
private Long id;
1717

18-
@Column(nullable = false)
18+
@Column(nullable = false, name = "payer_id")
1919
private Long payerId;
2020

21-
@Column(nullable = false)
21+
@Column(nullable = false, name = "payee_id")
2222
private Long payeeId;
2323

24-
@Column(nullable = false, unique = true)
25-
private String transferGroupId;
24+
@Column(nullable = false, unique = true, name = "transfer_id")
25+
private Long transferId;
2626

2727
@Enumerated(EnumType.STRING)
28+
@Column(nullable = false, name = "payment_status")
2829
private PaymentStatus paymentStatus;
2930

3031
public void updatePaymentStatus(PaymentStatus newStatus){
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package banking.payment.entity;
2+
3+
import banking.payment.enums.PaymentStatus;
4+
import com.fasterxml.jackson.annotation.JsonFormat;
5+
import jakarta.persistence.*;
6+
import lombok.AllArgsConstructor;
7+
import lombok.Builder;
8+
import lombok.Getter;
9+
import lombok.NoArgsConstructor;
10+
import org.hibernate.annotations.Immutable;
11+
import org.hibernate.annotations.Subselect;
12+
13+
import java.math.BigDecimal;
14+
import java.time.LocalDateTime;
15+
16+
@Entity
17+
@Immutable
18+
@Subselect(
19+
"SELECT " +
20+
"p.id AS payment_id, " +
21+
"p.payment_status AS payment_status, " +
22+
"a.account_number AS withdrawal_account_number, " +
23+
"u.name AS payee_name, " +
24+
"t.amount AS amount, " +
25+
"t.exchange_rate AS exchange_rate, " +
26+
"t.currency AS currency, " +
27+
"t.created_at AS paid_at " +
28+
"FROM payment p " +
29+
"LEFT JOIN users u ON p.payee_id = u.id " +
30+
"LEFT JOIN transfer t ON p.transfer_id = t.id " +
31+
"LEFT JOIN account a ON t.withdrawal_account_id = a.id"
32+
)
33+
@Getter
34+
@Builder
35+
@NoArgsConstructor
36+
@AllArgsConstructor
37+
public class PaymentView {
38+
39+
@Id
40+
@Column(name = "payment_id")
41+
Long paymentId;
42+
43+
@Column(name = "payment_status")
44+
@Enumerated(EnumType.STRING)
45+
PaymentStatus paymentStatus;
46+
47+
@Column(name = "withdrawal_account_number")
48+
String withdrawalAccountNumber;
49+
50+
@Column(name = "payee_name")
51+
String payeeName;
52+
53+
@Column(name = "amount", precision = 38, scale = 2)
54+
BigDecimal amount;
55+
56+
@Column(name = "exchange_rate", precision = 38, scale = 2)
57+
BigDecimal exchangeRate;
58+
59+
@Column(name = "currency")
60+
String currency;
61+
62+
@Column(name = "paid_at")
63+
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy.MM.dd HH:mm")
64+
LocalDateTime paidAt;
65+
}

src/main/java/banking/payment/repository/PaymentRepository.java

+2
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,6 @@ public interface PaymentRepository extends JpaRepository<Payment, Long> {
1414
@Lock(LockModeType.PESSIMISTIC_WRITE)
1515
@Query("SELECT p FROM Payment p WHERE p.id=:paymentId")
1616
Optional<Payment> findByIdWithPessimisticLock(@Param("paymentId") Long paymentId);
17+
18+
boolean existsByIdAndPayerId(Long id, Long payerId);
1719
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package banking.payment.repository;
2+
3+
import banking.payment.entity.PaymentView;
4+
import org.springframework.data.jpa.repository.JpaRepository;
5+
6+
import java.util.Optional;
7+
8+
public interface PaymentViewRepository extends JpaRepository<PaymentView, Long> {
9+
10+
Optional<PaymentView> findByPaymentId(Long paymentId);
11+
}

src/main/java/banking/payment/service/PaymentService.java

+15-27
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,14 @@
55
import banking.common.exception.CustomException;
66
import banking.common.exception.ErrorCode;
77
import banking.payment.dto.request.PaymentRefundRequest;
8-
import banking.payment.dto.response.PaymentResponse;
98
import banking.payment.dto.response.RefundPaymentResponse;
109
import banking.payment.entity.Payment;
10+
import banking.payment.entity.PaymentView;
1111
import banking.payment.enums.PaymentStatus;
1212
import banking.payment.repository.PaymentRepository;
1313
import banking.payment.dto.request.PaymentRequest;
14+
import banking.payment.repository.PaymentViewRepository;
1415
import banking.transfer.dto.response.PaymentTransferDetailResponse;
15-
import banking.transfer.enums.TransferType;
16-
import banking.transfer.service.TransferQueryService;
1716
import banking.transfer.service.TransferService;
1817
import banking.user.dto.response.UserPublicInfoResponse;
1918
import banking.user.service.UserService;
@@ -27,26 +26,27 @@ public class PaymentService {
2726

2827
private final PaymentRepository paymentRepository;
2928
private final TransferService transferService;
30-
private final TransferQueryService transferQueryService;
3129
private final AccountService accountService;
3230
private final UserService userService;
31+
private final PaymentViewRepository paymentViewRepository;
3332

3433
@Transactional
35-
public PaymentResponse processPayment(Long userId, PaymentRequest request) {
34+
public PaymentView processPayment(Long userId, PaymentRequest request) {
3635
PaymentTransferDetailResponse transferResponse = transferService.transfer(userId, request);
3736

3837
UserPublicInfoResponse payeeUserPublicInfo = userService.findUserPublicInfo(transferResponse.depositAccountId());
3938

4039
Payment payment = Payment.builder()
4140
.payerId(userId)
42-
.payeeId(payeeUserPublicInfo.id())
43-
.transferGroupId(transferResponse.transferGroupId())
41+
.payeeId(payeeUserPublicInfo.userId())
42+
.transferId(transferResponse.transferId())
4443
.paymentStatus(PaymentStatus.PAYMENT_PENDING)
4544
.build();
4645

4746
paymentRepository.save(payment);
4847

49-
return createPaymentResponseDto(userId, payment.getId());
48+
return paymentViewRepository.findByPaymentId(payment.getId())
49+
.orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_PAYMENT));
5050
}
5151

5252
@Transactional
@@ -60,7 +60,7 @@ public RefundPaymentResponse refundPayment(Long userId, PaymentRefundRequest req
6060
throw new CustomException(ErrorCode.PAYMENT_ALREADY_CANCELLED);
6161
}
6262

63-
PaymentTransferDetailResponse refundTransferResponse = transferService.transferForRefund(userId, payment.getTransferGroupId(), request.withdrawalAccountPassword());
63+
PaymentTransferDetailResponse refundTransferResponse = transferService.transferForRefund(userId, payment.getTransferId(), request.withdrawalAccountPassword());
6464

6565
// Payment 상태 변경 (PENDING/COMPLETED -> CANCELLED)
6666
payment.updatePaymentStatus(PaymentStatus.PAYMENT_CANCELLED);
@@ -77,25 +77,13 @@ private void verifyRequesterOwnership(Payment payment, Long userId) {
7777
}
7878
}
7979

80-
public PaymentResponse findPaymentById(Long userId, Long paymentId) {
81-
return createPaymentResponseDto(userId, paymentId);
82-
}
80+
public PaymentView findPaymentById(Long userId, Long paymentId) {
81+
boolean isExist = paymentRepository.existsByIdAndPayerId(paymentId, userId);
82+
if (!isExist) {
83+
throw new CustomException(ErrorCode.NOT_FOUND_PAYMENT);
84+
}
8385

84-
private PaymentResponse createPaymentResponseDto(Long userId, Long paymentId) {
85-
Payment payment = paymentRepository.findById(paymentId)
86+
return paymentViewRepository.findByPaymentId(paymentId)
8687
.orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_PAYMENT));
87-
88-
PaymentTransferDetailResponse transferResponse = transferQueryService.findTransfer(payment.getTransferGroupId(), userId);
89-
90-
Long requesterAccountId = (transferResponse.transferType().equals(TransferType.WITHDRAWAL)) ?
91-
transferResponse.withdrawalAccountId() : transferResponse.depositAccountId();
92-
93-
// 공개용 계좌 정보 GET
94-
AccountPublicInfoResponse accountPublicInfo = accountService.findAccountPublicInfo(requesterAccountId, transferResponse);
95-
96-
// 공개용 사용자 정보 GET
97-
UserPublicInfoResponse userPublicInfo = userService.findUserPublicInfo(userId, requesterAccountId);
98-
99-
return PaymentResponse.of(payment, transferResponse, accountPublicInfo.accountNumber(), userPublicInfo.name());
10088
}
10189
}

src/main/java/banking/transfer/dto/response/PaymentTransferDetailResponse.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
@Builder
1111
public record PaymentTransferDetailResponse (
1212

13-
String transferGroupId,
13+
Long transferId,
1414
TransferType transferType,
1515
Long withdrawalAccountId,
1616
Long depositAccountId,
@@ -22,7 +22,7 @@ public record PaymentTransferDetailResponse (
2222

2323
public static PaymentTransferDetailResponse of(Transfer transfer) {
2424
return PaymentTransferDetailResponse.builder()
25-
.transferGroupId(transfer.getTransferGroupId())
25+
.transferId(transfer.getId())
2626
.transferType(transfer.getTransferType())
2727
.withdrawalAccountId(transfer.getWithdrawalAccountId())
2828
.depositAccountId(transfer.getDepositAccountId())

src/main/java/banking/transfer/entity/Transfer.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public class Transfer extends BaseTimeEntity {
2828
@Enumerated(EnumType.STRING)
2929
private TransferType transferType;
3030

31-
@Column(nullable = false)
31+
@Column(nullable = false, name = "withdrawal_account_id")
3232
private Long withdrawalAccountId;
3333

3434
@Column(nullable = false)
@@ -37,7 +37,7 @@ public class Transfer extends BaseTimeEntity {
3737
@Column(nullable = false)
3838
private String currency;
3939

40-
@Column(nullable = false)
40+
@Column(nullable = false, name = "exchange_rate")
4141
private BigDecimal exchangeRate;
4242

4343
@Column(nullable = false)

src/main/java/banking/transfer/repository/TransferRepository.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,11 @@
1212
public interface TransferRepository extends JpaRepository<Transfer, Long> {
1313

1414
boolean existsByTransferGroupId(String transferGroupId);
15-
List<Transfer> findAllByTransferGroupId(String transferGroupId);
16-
Optional<Transfer> findByTransferGroupIdAndTransferOwnerId(String transferGroupId, Long transferOwnerId);
15+
16+
@Query("SELECT t FROM Transfer t WHERE t.transferGroupId " +
17+
"= (SELECT t2.transferGroupId FROM Transfer t2 WHERE t2.id = :transferId)")
18+
List<Transfer> findTransferGroupByTransferId(Long transferId);
19+
1720
Optional<Transfer> findByTransferGroupIdAndTransferType(String transferGroupId, TransferType transferType);
1821

1922
@Query("SELECT t FROM Transfer t WHERE t.transferOwnerId = :userId " +

src/main/java/banking/transfer/service/TransferQueryService.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,8 @@ private void verifyTransferAccount(Long userId, TransferType transferType,
8989
}
9090
}
9191

92-
public PaymentTransferDetailResponse findTransfer(String transferGroupId, Long userId) {
93-
Transfer transfer = transferRepository.findByTransferGroupIdAndTransferOwnerId(transferGroupId, userId)
92+
public PaymentTransferDetailResponse findTransfer(Long transferId) {
93+
Transfer transfer = transferRepository.findById(transferId)
9494
.orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_TRANSFER));
9595

9696
return PaymentTransferDetailResponse.of(transfer);

src/main/java/banking/transfer/service/TransferService.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ public Transfer processWithdrawalAndSaveTransferDetail(Account withdrawalAccount
8484
}
8585

8686
@Transactional
87-
public PaymentTransferDetailResponse transferForRefund(Long userId, String transferGroupId, String accountPassword) {
88-
List<Transfer> transfers = transferRepository.findAllByTransferGroupId(transferGroupId);
87+
public PaymentTransferDetailResponse transferForRefund(Long userId, Long transferId, String accountPassword) {
88+
List<Transfer> transfers = transferRepository.findTransferGroupByTransferId(transferId);
8989
verifyTransfer(transfers, userId);
9090

9191
Transfer baseWithdrawalTransfer, baseDepositTransfer;

src/main/java/banking/user/dto/response/UserPublicInfoResponse.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66
@Builder
77
public record UserPublicInfoResponse (
88

9-
Long id,
9+
Long userId,
1010
String name
1111
) {
1212

1313
public static UserPublicInfoResponse of(User user) {
1414
return UserPublicInfoResponse.builder()
15-
.id(user.getId())
15+
.userId(user.getId())
1616
.name(user.getName())
1717
.build();
1818
}

src/main/java/banking/user/entity/User.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public class User {
2020
@GeneratedValue(strategy = GenerationType.IDENTITY)
2121
private Long id;
2222

23-
@OneToMany(mappedBy = "id")
23+
@OneToMany(mappedBy = "user")
2424
private List<Account> accounts;
2525

2626
@Column(nullable = false)

src/main/resources/application-test.yml

+10
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,13 @@ spring:
1717
redis:
1818
host: localhost
1919
port: 6379
20+
21+
logging:
22+
level:
23+
org:
24+
hibernate:
25+
SQL: DEBUG
26+
type:
27+
descriptor:
28+
sql:
29+
BasicBinder: TRACE

0 commit comments

Comments
 (0)