appling 프로젝트

[appling] 주문 상세 조회

studyingJuno 2024. 9. 22. 15:24
728x90
반응형

🔴 주문 상세 조회

🟠 주문 상세 Domain 정의

🟢 주문 상세 요청 정의

@Getter
@Builder
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class GetOrderListRequest {
    private int size;
    private int page;
    private Sort sort;
    private String orderContact;

    public static GetOrderListRequest from(int size, int page, Sort sort, String orderContact) {
        return GetOrderListRequest.builder()
                .size(size)
                .page(page)
                .sort(sort)
                .orderContact(orderContact)
                .build();
    }
}

🟢 주문 상세 응답 정의

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
@Builder
@Schema(description = "주문 리스트")
public record OrderResponseList (
        @Schema(description = "페이지 마지막 여부", example = "true")
        Boolean last,
        @Schema(description = "페이지 비어있음 여부", example = "false")
        Boolean empty,
        @Schema(description = "총 페이지", example = "1")
        int totalPage,
        @Schema(description = "총 데이터 수", example = "1")
        Long totalElements,
        @Schema(description = "페이지에 존재하는 데이터 수", example = "1")
        int numberOfElement,
        @Schema(description = "리스트")
        List<OrderVo> orderList
) {
    public static OrderResponseList from(Page<OrderEntity> orderPage) {
        int totalPage = orderPage.getTotalPages();
        Long totalElements = orderPage.getTotalElements();
        int numberOfElement = orderPage.getNumberOfElements();
        Boolean last = orderPage.isLast();
        Boolean empty = orderPage.isEmpty();

        List<OrderVo> orderVoList = orderPage.stream()
                .map(OrderVo::from)
                .toList();

        return OrderResponseList.builder()
                .orderList(orderVoList)
                .totalPage(totalPage)
                .totalElements(totalElements)
                .numberOfElement(numberOfElement)
                .last(last)
                .empty(empty)
                .build();
    }
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
@Builder
@Schema(description = "주문")
public record OrderVo(
        @Schema(description = "주문번호", example = "1")
        Long orderId,
        @Schema(description = "주문상태", example = "COMPLETE")
        OrderStatus orderStatus,
        @Schema(description = "주문자", example = "주문자")
        String orderName,
        @Schema(description = "주문자 전화번호", example = "010-1234-5678")
        String orderContact,
        @Schema(description = "주문자 주소", example = "주소")
        String orderAddress,
        @Schema(description = "주문자 상세 주소", example = "상세 주소")
        String orderAddressDetail,
        @Schema(description = "주문자 우편번호", example = "12345")
        String orderZipcode,
        @Schema(description = "수령인", example = "수령인")
        String recipientName,
        @Schema(description = "수령인 전화번호", example = "010-1234-5678")
        String recipientContact,
        @Schema(description = "수령인 주소", example = "주소")
        String recipientAddress,
        @Schema(description = "수령인 상세 주소", example = "상세 주소")
        String recipientAddressDetail,
        @Schema(description = "수령인 우편번호", example = "12345")
        String recipientZipcode,
        @Schema(description = "주문금액", example = "100000")
        int orderAmount
) {
    public static OrderVo from(OrderEntity orderEntity) {
        return OrderVo.builder()
                .orderId(orderEntity.getOrderId())
                .orderStatus(orderEntity.getOrderStatus())
                .orderName(orderEntity.getOrderName())
                .orderContact(orderEntity.getOrderContact())
                .orderAddress(orderEntity.getOrderAddress())
                .orderAddressDetail(orderEntity.getOrderAddressDetail())
                .orderZipcode(orderEntity.getOrderZipcode())
                .recipientName(orderEntity.getRecipientName())
                .recipientContact(orderEntity.getRecipientContact())
                .recipientAddress(orderEntity.getRecipientAddress())
                .recipientAddressDetail(orderEntity.getRecipientAddressDetail())
                .recipientZipcode(orderEntity.getRecipientZipcode())
                .orderAmount(orderEntity.getOrderAmount())
                .build();
    }
}

🟢 주문 상세 조회 서비스 정의

public interface OrderService {
    ...
    OrderResponseList getOrderList(GetOrderListRequest getOrderListRequest);
}
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class OrderServiceImpl implements OrderService {
    private final OrderRepository orderRepository;
    private final ProductOptionCustomRepository productOptionCustomRepository;
    private final OrderCustomRepository orderCustomRepository;

    ...

    @Override
    public OrderResponseList getOrderList(GetOrderListRequest getOrderListRequest) {
        // todo 요청 받은 값으로 주문 리스트를 가져오기
        Page<OrderEntity> orderList = orderCustomRepository.getOrderList(getOrderListRequest);
        return OrderResponseList.from(orderList);
    }
}

🟢 주문 상세 조회 Repository 정의

public interface OrderCustomRepository {
    Page<OrderEntity> getOrderList(GetOrderListRequest getOrderListRequest);
}
@Repository
@RequiredArgsConstructor
public class OrderCustomRepositoryImpl implements OrderCustomRepository {
    private final JPAQueryFactory querydsl;

    @Override
    public Page<OrderEntity> getOrderList(GetOrderListRequest getOrderListRequest) {
        String orderContact = getOrderListRequest.getOrderContact().replace("-", "");
        Pageable pageable = Pageable.ofSize(getOrderListRequest.getSize()).withPage(getOrderListRequest.getPage());

        Sort sort = getOrderListRequest.getSort();
        QOrderEntity order = QOrderEntity.orderEntity;
        BooleanBuilder builder = new BooleanBuilder();
        builder.and(order.orderContact.eq(orderContact));

        List<OrderEntity> fetch = querydsl.selectFrom(order)
                .where(builder)
                .orderBy(sort == Sort.ASC ? order.orderId.asc() : order.orderId.desc())
                .offset(pageable.getOffset())
                .limit(pageable.getPageSize())
                .fetch();

        Long total = querydsl.selectFrom(order)
                .where(builder)
                .fetch()
                .stream().count();

        return new PageImpl<>(fetch, pageable, total);
    }
}

🟢 주문 상세 조회 Test Code 작성

@SpringBootTest
class OrderServiceImplTest {
    @Autowired
    private OrderServiceImpl orderService;

    @Autowired
    private ProductRepository productRepository;

    @Autowired
    private ProductOptionRepository productOptionRepository;

    @Autowired
    private OrderRepository orderRepository;

    ...

    @Test
    @DisplayName("주문을 조회하는데 성공한다.")
    void getOrderList() {
        //given
        final String orderContact = "01012345678";

        PostProductOptionDto option = PostProductOptionDto.builder()
                .productOptionName("11-12과")
                .productOptionPrice(100000)
                .productOptionStatus(ProductOptionStatus.ON_SALE)
                .productOptionStock(100)
                .productOptionDescription("아리수 11-12과 입니다.")
                .productOptionSort(1)
                .build();

        PostProductRequest productRequest = PostProductRequest.builder()
                .productName("아리수")
                .productType(ProductType.OPTION)
                .productOption(List.of(option))
                .build();

        ProductEntity productEntity = ProductEntity.from(productRequest);
        ProductOptionEntity productOptionEntity = ProductOptionEntity.from(option, productEntity);
        productEntity.getProductOptionList().add(productOptionEntity);
        ProductEntity saveProduct = productRepository.save(productEntity);

        PostOrderDto postOrderDto = PostOrderDto.builder()
                .productOptionId(saveProduct.getProductOptionList().get(0).getProductOptionId())
                .quantity(1)
                .build();

        PostOrderRequest postOrderRequest = PostOrderRequest.builder()
                .orderProductList(List.of(postOrderDto))
                .orderName("주문자")
                .orderContact(orderContact)
                .orderAddress("경기도 성남시 분당구 판교역로 231")
                .orderAddressDetail("H스퀘어 S동 5층")
                .orderZipcode("12345")
                .recipientName("받는이")
                .recipientContact("010-1234-5678")
                .recipientAddress("경기도 성남시 분당구 판교역로 231")
                .recipientAddressDetail("H스퀘어 S동 6층")
                .recipientZipcode("12345")
                .build();

        for (int i=0; i<30; i++) {
            orderRepository.save(OrderEntity.from(postOrderRequest));
        }

        GetOrderListRequest getOrderListRequest = GetOrderListRequest.builder()
                .size(10)
                .page(0)
                .orderContact(orderContact)
                .build();
        //when
        OrderResponseList orderList = orderService.getOrderList(getOrderListRequest);
        //then
        Assertions.assertThat(orderList.orderList().size()).isGreaterThan(0);
    }

}

🟠 주문 상세 조회 Controller

🟢 주문 상세 조회 Controller 정의

@ApiController
@RequiredArgsConstructor
@Tag(name = "Order", description = "Order API Documentation")
public class OrderController {
    private final OrderService orderService;

    ...

    @GetMapping("/order")
    @Operation(summary = "주문리스트", description = "주문리스트 api")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "정상", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = PostProductResponse.class))),
            @ApiResponse(responseCode = "500", description = "서버 에러", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)),
    })
    public ResponseEntity<ResponseData<OrderResponseList>> getOrderList(
            @Schema(description = "페이지 크기", defaultValue = "10", nullable = true) @RequestParam(name = "size", required = false, defaultValue = "10" ) int size,
            @Schema(description = "페이지 번호", defaultValue = "0", nullable = true) @RequestParam(name = "page", required = false, defaultValue = "0") int page,
            @Schema(description = "페이지 정렬(order id 기준)", defaultValue = "DESC", nullable = true) @RequestParam(name = "sort",required = false, defaultValue = "DESC" ) Sort sort,
            @Schema(description = "사용자 연락처", defaultValue = "") @RequestParam(name = "orderContact") String orderContact) {
        OrderResponseList orderResponseList = orderService.getOrderList(GetOrderListRequest.from(size, page, sort, orderContact));
        return ResponseEntity.ok(ResponseData.from(ResponseDataCode.SUCCESS, orderResponseList));
    }
}
@SpringBootTest
@AutoConfigureMockMvc
@Transactional(readOnly = true)
class OrderControllerTest {
    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private OrderServiceImpl orderService;

    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private ProductRepository productRepository;

    @Autowired
    private ProductOptionRepository productOptionRepository;

    @Autowired
    private ObjectMapper objectMapper;

    ...

    @Test
    @DisplayName("[GET] /api/v1/order")
    void getOrderList() throws Exception {
        //given
        final String orderContact = "01012345678";

        PostProductOptionDto option = PostProductOptionDto.builder()
                .productOptionName("11-12과")
                .productOptionPrice(100000)
                .productOptionStatus(ProductOptionStatus.ON_SALE)
                .productOptionStock(100)
                .productOptionDescription("아리수 11-12과 입니다.")
                .productOptionSort(1)
                .build();

        PostProductRequest productRequest = PostProductRequest.builder()
                .productName("아리수")
                .productType(ProductType.OPTION)
                .productOption(List.of(option))
                .build();

        ProductEntity productEntity = ProductEntity.from(productRequest);
        ProductOptionEntity productOptionEntity = ProductOptionEntity.from(option, productEntity);
        productEntity.getProductOptionList().add(productOptionEntity);
        ProductEntity saveProduct = productRepository.save(productEntity);

        PostOrderDto postOrderDto = PostOrderDto.builder()
                .productOptionId(saveProduct.getProductOptionList().get(0).getProductOptionId())
                .quantity(1)
                .build();

        PostOrderRequest postOrderRequest = PostOrderRequest.builder()
                .orderProductList(List.of(postOrderDto))
                .orderName("주문자")
                .orderContact(orderContact)
                .orderAddress("경기도 성남시 분당구 판교역로 231")
                .orderAddressDetail("H스퀘어 S동 5층")
                .orderZipcode("12345")
                .recipientName("받는이")
                .recipientContact("010-1234-5678")
                .recipientAddress("경기도 성남시 분당구 판교역로 231")
                .recipientAddressDetail("H스퀘어 S동 6층")
                .recipientZipcode("12345")
                .build();

        for (int i=0; i<30; i++) {
            orderRepository.save(OrderEntity.from(postOrderRequest));
        }

        //when
        ResultActions perform = mockMvc.perform(
                get("/api/v1/order")
                        .param("size", "10")
                        .param("page", "0")
                        .param("sort", "DESC")
                        .param("orderContact", orderContact));
        //then
        perform.andExpect(status().isOk());
        Assertions.assertThat(perform.andReturn().getResponse().getContentAsString(StandardCharsets.UTF_8)).contains("0000");
    }

}
728x90
반응형