Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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,12 @@
package com.irum.come2us.domain.order.domain.repository;

import com.irum.come2us.domain.order.domain.entity.Order;
import com.irum.come2us.domain.order.domain.entity.OrderDetail;
import java.util.List;
import java.util.UUID;
import org.springframework.data.jpa.repository.JpaRepository;

public interface OrderDetailRepository extends JpaRepository<OrderDetail, UUID> {

List<OrderDetail> findAllByOrder(Order order);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.irum.come2us.domain.order.domain.repository;

import com.irum.come2us.domain.order.domain.entity.Order;
import java.util.Optional;
import java.util.UUID;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface OrderRepository extends JpaRepository<Order, UUID> {
@Query("SELECT o FROM Order o JOIN FETCH o.deliveryAddress da WHERE o.orderId =: orderId")
Comment thread
Bal1oon marked this conversation as resolved.
Outdated
Optional<Order> findOrderWithAddress(@Param("orderId") UUID orderId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.irum.come2us.domain.refund.application.service;

import com.irum.come2us.domain.order.domain.entity.Order;
import com.irum.come2us.domain.order.domain.entity.OrderDetail;
import com.irum.come2us.domain.order.domain.repository.OrderDetailRepository;
import com.irum.come2us.domain.order.domain.repository.OrderRepository;
import com.irum.come2us.domain.refund.domain.entity.Refund;
import com.irum.come2us.domain.refund.domain.repository.RefundRepository;
import com.irum.come2us.domain.refund.presentation.dto.request.CustomerRefundCreateRequest;
import com.irum.come2us.domain.refund.presentation.dto.response.CustomerRefundDetailResponse;
import com.irum.come2us.global.presentation.advice.exception.CommonException;
import com.irum.come2us.global.presentation.advice.exception.errorcode.RefundErrorCode;
import com.irum.come2us.global.util.MemberUtil;
import java.util.List;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
@Transactional
@Slf4j
public class CustomerRefundService {
private final MemberUtil memberUtil;
private final RefundRepository refundRepository;
private final OrderRepository orderRepository;
private final OrderDetailRepository orderDetailRepository;

public void createRefund(UUID orderId, CustomerRefundCreateRequest request) {
assertNoRefundExistsByOrder(orderId);
Order order = getValidOrder(orderId);
refundRepository.save(
Refund.create(
request.reason(), request.description(), order.getPayment().getAmount()));
}

@Transactional(readOnly = true)
public CustomerRefundDetailResponse findRefundDetail(UUID orderId) {
Order order = getValidOrderWithAddress(orderId);
Refund refund = getValidRefund(orderId);
List<OrderDetail> orderDetails = orderDetailRepository.findAllByOrder(order);
return CustomerRefundDetailResponse.of(order, orderDetails, refund);
}

private void assertNoRefundExistsByOrder(UUID orderId) {
if (refundRepository.existsByOrderId(orderId))
throw new CommonException(RefundErrorCode.REFUND_ALREADY_EXISTS);
}

private Order getValidOrder(UUID orderId) {
Order order =
orderRepository
.findById(orderId)
.orElseThrow(() -> new CommonException(OrderErrorCode.ORDER_NOT_FOUND));
memberUtil.assertMemberResourceAccess(order.getMember());
return order;
}

private Order getValidOrderWithAddress(UUID orderId) {
Order order =
orderRepository
.findOrderWithAddress(orderId)
.orElseThrow(() -> new CommonException(OrderErrorCode.ORDER_NOT_FOUND));
memberUtil.assertMemberResourceAccess(order.getMember());
return order;
}

private Refund getValidRefund(UUID orderId) {
return refundRepository
.findByOrderId(orderId)
.orElseThrow(() -> new CommonException(RefundErrorCode.REFUND_NOT_FOUND));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.irum.come2us.domain.refund.domain.repository;

import com.irum.come2us.domain.refund.domain.entity.Refund;
import java.util.Optional;
import java.util.UUID;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface RefundRepository extends JpaRepository<Refund, UUID> {
@Query("SELECT COUNT(r)>0 FROM Refund r WHERE r.order.orderId =: orderId")
boolean existsByOrderId(@Param("orderId") UUID orderId);

@Query("SELECT r FROM Refund r WHERE r.order.orderId =: orderId")
Optional<Refund> findByOrderId(@Param("orderId") UUID orderId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.irum.come2us.domain.refund.presentation.controller;

import com.irum.come2us.domain.refund.application.service.CustomerRefundService;
import com.irum.come2us.domain.refund.presentation.dto.request.CustomerRefundCreateRequest;
import com.irum.come2us.domain.refund.presentation.dto.response.CustomerRefundDetailResponse;
import jakarta.validation.Valid;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/refund/customer")
@RequiredArgsConstructor
public class CustomerRefundController {
private final CustomerRefundService customerRefundService;

@PostMapping("/{orderId}")
public ResponseEntity<Void> registerRefund(
@PathVariable UUID orderId, @Valid @RequestBody CustomerRefundCreateRequest request) {
customerRefundService.createRefund(orderId, request);
return ResponseEntity.status(HttpStatus.CREATED).build();
}

@GetMapping("/{orderId}/detail")
public CustomerRefundDetailResponse getRefundDetail(@PathVariable UUID orderId) {
return customerRefundService.findRefundDetail(orderId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.irum.come2us.domain.refund.presentation.dto.request;

import com.irum.come2us.domain.refund.domain.entity.enums.RefundReason;
import jakarta.annotation.Nullable;
import jakarta.validation.constraints.NotNull;

public record CustomerRefundCreateRequest(
@NotNull(message = "환불 사유는 필수 입력값입니다.") RefundReason reason,
@Nullable String description) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.irum.come2us.domain.refund.presentation.dto.response;

import com.irum.come2us.domain.deliveryaddress.domain.entity.DeliveryAddress;
import com.irum.come2us.domain.order.domain.entity.Order;
import com.irum.come2us.domain.order.domain.entity.OrderDetail;
import com.irum.come2us.domain.refund.domain.entity.Refund;
import com.irum.come2us.domain.refund.domain.entity.enums.RefundReason;
import com.irum.come2us.domain.refund.domain.entity.enums.RefundStatus;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;

public record CustomerRefundDetailResponse(
UUID orderId,
String orderNum,
List<ProductInfoDto> productList,
RecipientAddressDto recipientAddress,
LocalDateTime cancelDate,
UUID refundId,
RefundStatus refundStatus,
int refundPrice,
RefundReason refundReason) {
public record ProductInfoDto(
UUID orderDetailId,
int productPrice,
String productName,
String optionTitle,
int quantity) {
public static ProductInfoDto fromEntity(OrderDetail orderDetail) {
return new ProductInfoDto(
orderDetail.getOrderDetailId(),
orderDetail.getPrice(),
orderDetail.getProductName(),
orderDetail.getOptionName(),
orderDetail.getQuantity());
}
}

public record RecipientAddressDto(
String postalCode,
String city,
String sigungu,
String RoadName,
String AddressDetail,
String recipientName,
String recipientContact) {
public static RecipientAddressDto fromEntity(DeliveryAddress deliveryAddress) {
return new RecipientAddressDto(
deliveryAddress.getAddress().getPostalCode(),
deliveryAddress.getAddress().getCity(),
deliveryAddress.getAddress().getSigungu(),
deliveryAddress.getAddress().getRoadName(),
deliveryAddress.getAddress().getAddressDetail(),
deliveryAddress.getRecipientName(),
deliveryAddress.getRecipientContact());
}
}

public static CustomerRefundDetailResponse of(
Order order, List<OrderDetail> orderDetails, Refund refund) {

List<ProductInfoDto> productList =
orderDetails.stream().map(ProductInfoDto::fromEntity).toList();

RecipientAddressDto recipientAddress =
RecipientAddressDto.fromEntity(order.getDeliveryAddress());

return new CustomerRefundDetailResponse(
order.getOrderId(),
order.getOrderNum(),
productList,
recipientAddress,
refund.getRefundId(),
refund.getCreatedAt(),
refund.getRefundStatus(),
refund.getPrice(),
refund.getReason());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.irum.come2us.global.presentation.advice.exception.errorcode;

import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;

@Getter
@AllArgsConstructor
public enum RefundErrorCode implements BaseErrorCode {
REFUND_NOT_FOUND(HttpStatus.NOT_FOUND, "환불 정보를 찾을 수 없습니다."),
REFUND_ALREADY_EXISTS(HttpStatus.BAD_REQUEST, "이미 해당 주문에 대한 환불이 존재합니다.");

private final HttpStatus httpStatus;
private final String message;

@Override
public String errorClassName() {
return this.name();
}
}