Skip to content

Commit

Permalink
Merge pull request #70 from Try-AngIe/feat/product
Browse files Browse the repository at this point in the history
feat: 상품 목록을 조회할 수 있다.
  • Loading branch information
rlatkd authored Jul 10, 2024
2 parents 7af4397 + d5115ac commit ac19ecf
Show file tree
Hide file tree
Showing 9 changed files with 233 additions and 68 deletions.
2 changes: 0 additions & 2 deletions client/src/components/vendor/modal/ProductModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ const ProductModal = ({ isShowModal, setIsShowModal, modalTitle, productDetailDa
return <div />;
}

console.log(productDetailData);

return (
<BaseModal
isShowModal={isShowModal}
Expand Down
22 changes: 15 additions & 7 deletions client/src/pages/vendor/product/ProductListPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import ProductModal from '@/components/vendor/modal/ProductModal';
import { useEffect, useState } from 'react';

const ProductListPage = () => {
const [isShowModal, setIsShowModal] = useState(false);
const [modalTitle, setModalTitle] = useState(''); //모달 제목 상태
const [productId, setProductId] = useState('');
const [isShowModal, setIsShowModal] = useState(false); // 모달 on,off
const [modalTitle, setModalTitle] = useState(''); // 모달 제목 상태
const [productId, setProductId] = useState(''); // 상품ID
const [productList, setProductList] = useState([]); // 상품 목록
const [productDetailData, setProductDetailData] = useState(null); // 상품 상세 정보
const [pageNum, setPageNum] = useState(''); // 페이지번호
const [size, setSize] = useState(''); // 페이지 사이즈

// 상품 상세 조회용 더미데이터(상품 목록 조회에서 가져온 데이터라 가정)
const dummyData = {
Expand Down Expand Up @@ -44,9 +46,9 @@ const ProductListPage = () => {
};

// 컴포넌트 마운트시 더미데이터 세팅
useEffect(() => {
setProductId(dummyData.data[0].id);
}, []);
// useEffect(() => {
// setProductId(dummyData.data[0].id);
// }, []);

// useEffect(() => {
// const fetchProductList = async () => {
Expand Down Expand Up @@ -80,6 +82,8 @@ const ProductListPage = () => {
}
};

const pageButtonClickHandle = () => {};

return (
<div className='primary-dashboard h-full w-full'>
<button
Expand All @@ -90,7 +94,7 @@ const ProductListPage = () => {

{/* 이건 목록에서 상품 하나 클릭하면 들어가도록 */}
<button
className='rounded-lg bg-mint p-3 font-bold text-white'
className='rounded-lg bg-mint p-3 font-bold text-white mr-10'
onClick={openDetailModalHandle}>
임시 상품 상세 모달
</button>
Expand All @@ -101,6 +105,10 @@ const ProductListPage = () => {
modalTitle={modalTitle}
productDetailData={productDetailData}
/>

<button className='rounded-lg bg-mint p-3 font-bold text-white mr-10'>1</button>

<button className='rounded-lg bg-mint p-3 font-bold text-white mr-10'>2</button>
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ protected BooleanExpression contractProductNotDel() {
return contractProduct.deleted.isFalse();
}

protected BooleanExpression productNotDel() {
return product.deleted.isFalse();
}

protected BooleanExpression memberNameContains(String memberName) {
return hasText(memberName) ? member.name.containsIgnoreCase(memberName) : null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package kr.or.kosa.cmsplusmain.domain.product.controller;

import kr.or.kosa.cmsplusmain.domain.product.dto.ProductDetail;
import kr.or.kosa.cmsplusmain.domain.product.entity.Product;
import kr.or.kosa.cmsplusmain.domain.base.dto.SortPageDto;
import kr.or.kosa.cmsplusmain.domain.product.dto.ProductRes;
import kr.or.kosa.cmsplusmain.domain.product.service.ProductService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
Expand All @@ -17,13 +17,15 @@ public class ProductController {
private final ProductService productService;

@GetMapping("/{productId}")
public ProductDetail getProduct(@PathVariable("productId") Long productId) {
return productService.findById(productId);
public ProductRes getProduct(@PathVariable("productId") Long productId) {
String vendorUserName = "vendor1";
return productService.findById(productId, vendorUserName);
}





@GetMapping
public SortPageDto.Res<ProductRes> getProductListItem(SortPageDto.Req pageable) {
String vendorUserName = "vendor1";
return productService.findProductsByUser(vendorUserName, pageable);
}

}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package kr.or.kosa.cmsplusmain.domain.product.dto;

import com.querydsl.core.annotations.QueryProjection;
import kr.or.kosa.cmsplusmain.domain.product.entity.Product;
import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class ProductQRes {

private final Product product;
private final int contractNumber;

// 쿼리프로젝션을 이용해서 repository->service용 DTO
@QueryProjection
public ProductQRes(Product product, int contractNumber) {
this.product = product;
this.contractNumber = contractNumber;
}

public ProductRes toProductRes() {
return ProductRes.builder()
.productId(product.getId())
.productName(product.getName())
.productPrice(product.getPrice())
.productMemo(product.getMemo())
.contractNumber(contractNumber)
.createdDateTime(product.getCreatedDateTime()) // 엔티티에서 가져옴
.build();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package kr.or.kosa.cmsplusmain.domain.product.dto;

import kr.or.kosa.cmsplusmain.domain.product.entity.Product;
import lombok.Builder;
import lombok.Getter;
import java.time.LocalDateTime;

@Getter
@Builder
public class ProductRes {

private final Long productId;
private final String productName;
private final LocalDateTime createdDateTime;
private final int productPrice;
private final String productMemo;

private final int contractNumber; // 계약 건수

public static ProductRes fromEntity(Product product, int contractNumber) {
return ProductRes.builder()
.productId(product.getId())
.productName(product.getName())
.createdDateTime(product.getCreatedDateTime())
.productPrice(product.getPrice())
.productMemo(product.getMemo())
.contractNumber(contractNumber)
.build();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@

import com.querydsl.jpa.impl.JPAQueryFactory;
import jakarta.persistence.EntityManager;
import kr.or.kosa.cmsplusmain.domain.base.dto.SortPageDto;
import kr.or.kosa.cmsplusmain.domain.base.repository.BaseCustomRepository;
import kr.or.kosa.cmsplusmain.domain.product.dto.ProductQRes;
import kr.or.kosa.cmsplusmain.domain.product.dto.QProductQRes;
import kr.or.kosa.cmsplusmain.domain.product.entity.Product;
import org.springframework.stereotype.Repository;
import java.util.List;

import static kr.or.kosa.cmsplusmain.domain.contract.entity.QContract.contract;
import static kr.or.kosa.cmsplusmain.domain.contract.entity.QContractProduct.contractProduct;
import static kr.or.kosa.cmsplusmain.domain.product.entity.QProduct.product;
import static kr.or.kosa.cmsplusmain.domain.vendor.entity.QVendor.vendor;

@Repository
public class ProductCustomRepository extends BaseCustomRepository<Product> {
Expand All @@ -16,20 +22,113 @@ public ProductCustomRepository(EntityManager em, JPAQueryFactory jpaQueryFactory
super(em, jpaQueryFactory);
}

// 상품이 매핑되어있는 계약수
public int getContractNumber(Long productId) {

// 상품이 포함된 계약의 개수를 구하는 sql
// select count(distinct pc.contract_id)
// from product_contract pc
// join contract c
// where pc.product_id = #{productId} and c.deleted = 0
/*
* 상품이 포함된 계약의 개수를 구함
* select count(distinct pc.contract_id)
* from contract_product cp
* join contract c
* where cp.product_id = #{productId} and c.deleted = 0
* */
return jpaQueryFactory
.select(contract.id.countDistinct())
.from(contractProduct)
.join(contractProduct.contract, contract) // 계약-상품 테이블의 외래키인 계약ID를 타고 들어감
.where(contractProduct.product.id.eq(productId), contract.deleted.eq(false))
.where(contractProduct.product.id.eq(productId),
contractNotDel())
.fetchOne().intValue();
}

// 고객의 상품 목록
// 프로젝션 대상이 2개이기 떄문에 QueryProjection을 이용해 해결
public List<ProductQRes> findProductListWithCondition(String vendorUserName, SortPageDto.Req pageable) {
/*
* 해당 고객의 모든 상품(삭제되지않은)을 가져오는데, 상품의 정보와 상품이 포함된 계약 갯수를 가져와야함
*
* 해당 고객의 모든 상품(삭제되지않은)
* select *
* from product p
* join vendor v
* where v.vendor_userName = #{userName} and p.deleted = 0
*
* 상품의 정보와 상품이 포함된 계약 갯수
* select count(distinct pc.contract_id)
* from product_contract pc
* join contract c
* where pc.product_id = #{productId} and c.deleted = 0
*
* 1. 해당 고객의 모든 상품(삭제되지않은)을 가져오는데, 상품의 정보와 상품이 포함된 계약 갯수를 가져와야함
* select vendor_product.* count(distinct pc.contract_id)
* from (select *
* from product p
* join vendor v
* where v.vendor_userName = #{userName} and p.deleted = 0) vp , product_contract pc
* join contract c
* where pc.product_id = vp.product_id and c.deleted = 0
*
* 2. (최종)
* select p.*, count(distinct cp.contract_id) as contract_count
* from product p
* join vendor v on v.vendor_id = p.vendor_id
* left join contract_product cp on cp.product_id = p.product_id and cp.deleted = 0
* left join contract c on c.contract_id = cp.contract_id and c.deleted = 0
* where v.vendor_username = 'vendor1' and p.deleted = 0
* group by p.product_id;
* */
List<ProductQRes> result = jpaQueryFactory
.select(new QProductQRes(product, contractProduct.contract.countDistinct().intValue()))
.from(product)
.join(product.vendor, vendor)
.leftJoin(contractProduct)
.on(contractProduct.product.eq(product),
(contractProductNotDel()))
.leftJoin(contract)
.on(contractProduct.contract.eq(contract),
(contractNotDel()))
.where(
vendor.username.eq(vendorUserName),
productNotDel()
)
.groupBy(product.id)
.offset(pageable.getPage())
.limit(pageable.getSize())
.fetch();

return result;
}

// 고객의 상품 총 갯수
public int countAllProducts(String vendorUsername) {
return jpaQueryFactory
.select(product.id.count())
.from(product)
.join(product.vendor, vendor)
.where(
vendorUsernameEq(vendorUsername),
productNotDel()
)
.fetchOne().intValue();
}

// 특정 고객이 본인의 상품이 아닌거 조회하는거 처리
public boolean isExistProductByUsername(Long productId, String vendorUsername) {
/*
* 고객테이블에 있는 고객이름이 해당 상품의 고객ID의 이름인지 확인
* select 1
* from product p
* join vendor v on p.vendor_id = v.vendor_id
* where p.product_id = #{productId} and v.vendor_username = #{vendorUsername}
* */
Integer count = jpaQueryFactory
.selectOne()
.from(product)
.join(product.vendor, vendor)
.where(product.id.eq(productId),
vendor.username.eq(vendorUsername))
.fetchFirst();

return count != null;
}

}
}
Loading

0 comments on commit ac19ecf

Please sign in to comment.