Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.fisa.pg.controller;

import com.fisa.pg.dto.response.BaseResponse;
import com.fisa.pg.dto.response.TransactionLogResponseDto;
import com.fisa.pg.entity.transaction.TransactionStatus;
import com.fisa.pg.entity.user.Merchant;
import com.fisa.pg.service.TransactionLogService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.List;

@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/merchants/transactions/logs")
public class MerchantTransactionLogController {

private final TransactionLogService transactionLogService;

@GetMapping
public ResponseEntity<BaseResponse<Page<TransactionLogResponseDto>>> getTransactionLogs(
@AuthenticationPrincipal Merchant merchant,
@RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startDate,
@RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endDate,
@RequestParam(required = false) List<TransactionStatus> statuses,
@RequestParam(required = false) List<String> methods,
@RequestParam(required = false) String searchTerm,
Pageable pageable) {

log.info("[Controller] 트랜잭션 로그 조회 요청 | merchantId={} | page: {}", merchant.getId(), pageable);

Page<TransactionLogResponseDto> result = transactionLogService.getMerchantTransactionLogs(
merchant, startDate, endDate, statuses, methods, searchTerm, pageable
);

return ResponseEntity.ok(BaseResponse.onSuccess("가맹점 트랜잭션 로그 조회 성공", result));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package com.fisa.pg.dto.response;

import com.fisa.pg.entity.transaction.Transaction;
import com.fisa.pg.entity.transaction.TransactionLog;
import com.fisa.pg.entity.transaction.TransactionStatus;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TransactionLogResponseDto {

/**
* 트랜잭션 ID
*/
private String transactionId;

/**
* 결제 금액
*/
private Long amount;

/**
* 상태 (한글로 표시)
*/
private String status;

/**
* 결제 수단
*/
private String method;

/**
* 트랜잭션 처리 시간
*/
private LocalDateTime timestamp;

/**
* TransactionLog 엔티티로부터 응답 DTO 생성
*/
public static TransactionLogResponseDto from(TransactionLog log) {
Transaction transaction = log.getTransaction();

return TransactionLogResponseDto.builder()
.transactionId(transaction.getTransactionId())
.amount(transaction.getAmount())
.status(formatStatus(log.getStatus()))
.method(formatMethod(transaction.getMethod().name()))
.timestamp(log.getCreatedAt())
.build();
}

/**
* 상태값을 사용자 친화적인 한글 메시지로 변환
*/
private static String formatStatus(TransactionStatus status) {
return switch (status) {
case PENDING -> "대기중";
case CREATED -> "결제중";
case APPROVED -> "성공";
case FAILED -> "실패";
case CANCELED -> "환불됨";
case AUTH_FAILED -> "인증 실패";
};
}

/**
* 결제 수단을 사용자 친화적인 한글 메세지로 변환
*/
private static String formatMethod(String method) {
if (method == null) return "미지정";

return switch (method) {
case "WOORI_APP_CARD" -> "우리 앱카드";
case "CREDIT_CARD" -> "신용카드";
case "DEBIT_CARD" -> "체크카드";
default -> method;
};
}
}
42 changes: 42 additions & 0 deletions src/main/java/com/fisa/pg/repository/TransactionLogRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.fisa.pg.repository;

import com.fisa.pg.dto.response.TransactionLogResponseDto;
import com.fisa.pg.entity.transaction.TransactionLog;
import com.fisa.pg.entity.transaction.TransactionStatus;
import com.fisa.pg.entity.user.Merchant;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.time.LocalDateTime;
import java.util.List;

public interface TransactionLogRepository extends JpaRepository<TransactionLog, Long> {

@Query("""
SELECT new com.fisa.pg.dto.response.TransactionLogResponseDto(t)
FROM TransactionLog t
WHERE t.merchant = :merchant
AND (:startDate IS NULL OR t.createdAt >= :startDate)
AND (:endDate IS NULL OR t.createdAt <= :endDate)
AND (:statuses IS NULL OR t.status IN :statuses)
AND (:methods IS NULL OR t.transaction.method IN :methods)
AND (
:searchTerm IS NULL OR :searchTerm = '' OR
t.transaction.transactionId LIKE CONCAT('%', :searchTerm, '%') OR
t.message LIKE CONCAT('%', :searchTerm, '%')
)
ORDER BY t.createdAt DESC
""")
Page<TransactionLogResponseDto> findByFilters(
@Param("merchant") Merchant merchant,
@Param("startDate") LocalDateTime startDate,
@Param("endDate") LocalDateTime endDate,
@Param("statuses") List<TransactionStatus> statuses,
@Param("methods") List<String> methods,
@Param("searchTerm") String searchTerm,
Pageable pageable
);
}
39 changes: 39 additions & 0 deletions src/main/java/com/fisa/pg/service/TransactionLogService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.fisa.pg.service;

import com.fisa.pg.dto.response.TransactionLogResponseDto;
import com.fisa.pg.entity.transaction.TransactionStatus;
import com.fisa.pg.entity.user.Merchant;
import com.fisa.pg.repository.TransactionLogRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

@Slf4j
@Service
@RequiredArgsConstructor
public class TransactionLogService {

private final TransactionLogRepository transactionLogRepository;

@Transactional(readOnly = true)
public Page<TransactionLogResponseDto> getMerchantTransactionLogs(
Merchant merchant,
LocalDateTime startDate,
LocalDateTime endDate,
List<TransactionStatus> statuses,
List<String> methods,
String searchTerm,
Pageable pageable) {

log.info("[Service] 트랜잭션 로그 필터 조회 | merchantId={} | 기간: {}~{} | 상태: {} | 수단: {} | 검색: {}",
merchant.getId(), startDate, endDate, statuses, methods, searchTerm);

return transactionLogRepository.findByFilters(merchant, startDate, endDate, statuses, methods, searchTerm, pageable);
}
}
Loading