-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
멘토님 코드 리뷰용 PR #52
base: review
Are you sure you want to change the base?
멘토님 코드 리뷰용 PR #52
Changes from 250 commits
1533f9e
e62a738
60d6f8f
c8b12f4
c7b6650
aa83548
d4fa78b
e2657c7
b185508
5c9e85c
eb8b912
b74c78a
0d3b529
7c07040
6aabfda
49b9eda
04e2a85
7f8c0df
bdad3a8
be46d8c
837e4d0
b136b6a
5aa901f
222ad08
3f237e8
a6f230c
50e189f
db16793
1b54d04
b6379c0
7ce6947
6a5b517
fa52a8a
63585a0
91f8503
88eb3fe
bff553a
49ce459
b221666
0dfef98
f409687
c968707
1a89040
bf71887
79dba6f
afaddec
2240b21
833514b
903a080
5c341fc
606deaa
d0a9d16
3da4c09
c90d8e6
ceb95a8
0212880
48d1576
0153035
1bb52a6
41f2560
5198193
29cb0c8
4ec8217
96ae500
ca08666
ee4e819
cfd8b20
e0b3ce2
e1ceea3
647b929
7b4b220
fb9ed14
73e07e3
8767a46
7d2d8c6
a3ba9d8
3d72e6a
d1ce580
c53f9bb
f3c87a7
ca8e4de
698a68a
2d2711c
ab962bb
18184e8
e3733a9
364c72e
e19912b
7a2afbf
c7fd0b0
53fad75
b296f7c
19f7e0f
2532099
d627ed8
836f8af
f650d91
a60c155
8eafb4b
fe5a242
ff31663
f7f497a
f51202a
8e25478
9ec6e65
9297699
a52539e
8d0e636
0f5a837
8b9adc3
cc12dd9
da6db62
ca29de5
65f2ad3
ce961ec
a598652
9a60c84
475e57d
fe0e80e
ff1ef6c
ed15bb6
5fce07f
67973e3
562bd9f
9285282
94ecd90
4bc601c
0fbddce
3643d7b
9efc4a6
32b35f5
d549f83
06d22c6
d41db8b
0ad9c4e
ffec8db
e1df5ba
9d04c19
564df6b
1389686
58d8b40
6c84eaa
a8b064e
eca9d5e
564d711
746d09b
de43da7
cc80815
e0cddb7
5615b44
0587ca5
341708a
37b4b50
04be4c2
f126689
a9a35e4
b02bd2c
179727d
cf0bd08
0c51493
dad46ed
a8caf8a
652c6e8
8b66285
22dff01
54308ab
a7fdfd3
a13ec8a
50d4fab
1cafb1b
523e588
77e59e5
c99d9fe
6322b78
88f3ee0
49d8707
28d20b8
995f1e2
e4773ed
34b9deb
f23745f
0db04ae
d9312d3
0d259e5
065c1a0
2c53c1d
5c0d509
6e2bd5e
13c3dc0
91aa91e
32df6e0
0f3acb8
728058d
374256f
5f17820
382aefe
28de1a4
baf0718
9d0d6a9
c574037
5a363a1
bbeb54d
568a8ae
43d86d5
8c67142
c0ae709
edcb255
a617cc9
8e7d667
e71e45b
9030225
6e209b2
2de87ec
649ccda
f611f2d
f0928bf
22b21c0
d04c49a
e27faf8
97a9403
4f99ad4
d932354
be55bf2
dbc21ed
fe2a6e1
1bf4c48
92f621c
1641fba
399f09d
1622aea
4bb348b
35f26fa
466063b
fd3919f
e344ec4
233b0b2
9679a41
63c2fa6
719a2b3
aebd79c
aaa246f
d1dd5a5
81e663b
019dba4
88a9b93
c03be17
071689d
2406a9d
dd36856
fd2d678
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package com.example.backend.domain.cart.controller; | ||
|
||
import com.example.backend.domain.cart.dto.CartForm; | ||
import com.example.backend.domain.cart.service.CartService; | ||
import com.example.backend.domain.member.entity.Member; | ||
import com.example.backend.global.auth.model.CustomUserDetails; | ||
import com.example.backend.global.response.GenericResponse; | ||
import jakarta.validation.Valid; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.security.core.annotation.AuthenticationPrincipal; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
@RestController | ||
@RequiredArgsConstructor | ||
@RequestMapping("/api/v1/carts") | ||
public class CartController { | ||
private final CartService cartService; | ||
|
||
@PostMapping | ||
public ResponseEntity<GenericResponse<Long>> addCartItem( | ||
@RequestBody @Valid CartForm cartForm, | ||
@AuthenticationPrincipal CustomUserDetails customUserDetails) { | ||
|
||
Member member = customUserDetails.getMember(); | ||
|
||
Long cartId = cartService.addCartItem(cartForm, member); | ||
|
||
return ResponseEntity.status(HttpStatus.CREATED).body(GenericResponse.of(cartId)); | ||
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package com.example.backend.domain.cart.converter; | ||
|
||
import com.example.backend.domain.cart.dto.CartForm; | ||
import com.example.backend.domain.cart.dto.CartResponse; | ||
import com.example.backend.domain.cart.entity.Cart; | ||
import com.example.backend.domain.member.entity.Member; | ||
import com.example.backend.domain.product.entity.Product; | ||
import lombok.AccessLevel; | ||
import lombok.NoArgsConstructor; | ||
|
||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
public class CartConverter { | ||
|
||
/** | ||
* CartForm -> Cart 엔티티 변환 | ||
* | ||
* @param cartForm 요청 DTO | ||
* @param member 회원 엔티티 | ||
* @param product 상품 엔티티 | ||
* @return Cart 엔티티 | ||
*/ | ||
public static Cart from(CartForm cartForm, Member member, Product product) { | ||
return Cart.builder() | ||
.member(member) | ||
.product(product) | ||
.quantity(cartForm.quantity()) | ||
.build(); | ||
} | ||
|
||
/** | ||
* Cart 엔티티 -> CartResponse 변환 | ||
* | ||
* @param cart Cart 엔티티 | ||
* @return 응답 DTO | ||
*/ | ||
public static CartResponse toResponse(Cart cart) { | ||
return CartResponse.builder() | ||
.id(cart.getId()) | ||
.productName(cart.getProduct().getName()) | ||
.quantity(cart.getQuantity()) | ||
.productPrice(cart.getProduct().getPrice()) | ||
.totalPrice(cart.getProduct().getPrice() * cart.getQuantity()) | ||
.productImgUrl(cart.getProduct().getImgUrl()) | ||
.build(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package com.example.backend.domain.cart.dto; | ||
|
||
import jakarta.validation.constraints.Min; | ||
import jakarta.validation.constraints.NotNull; | ||
|
||
public record CartForm( | ||
@NotNull(message = "회원 ID는 필수 값입니다.") | ||
Long memberId, | ||
@NotNull(message = "상품 ID는 필수 값입니다.") | ||
Long productId, | ||
@Min(value = 1, message = "상품 수량은 최소 1개 이상이어야 합니다.") | ||
int quantity | ||
) { | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package com.example.backend.domain.cart.dto; | ||
|
||
import lombok.Builder; | ||
|
||
@Builder | ||
public record CartResponse( | ||
Long id, | ||
String productName, | ||
int quantity, | ||
int productPrice, | ||
int totalPrice, | ||
String productImgUrl | ||
) {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package com.example.backend.domain.cart.entity; | ||
|
||
import com.example.backend.domain.member.entity.Member; | ||
import com.example.backend.domain.product.entity.Product; | ||
import jakarta.persistence.*; | ||
import lombok.*; | ||
|
||
@Entity | ||
@Getter | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
public class Cart { | ||
|
||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long id; | ||
|
||
@ManyToOne(fetch = FetchType.LAZY) | ||
@JoinColumn(name = "member_id") | ||
private Member member; | ||
|
||
@ManyToOne(fetch = FetchType.LAZY) | ||
@JoinColumn(name = "product_id") | ||
private Product product; | ||
|
||
private int quantity; | ||
|
||
@Builder | ||
public Cart(Long id, Member member, Product product, int quantity) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lombok을 사용한다면, 확실하게 대체 가능한 것들은 전부 사용해 주세요. |
||
this.member = member; | ||
this.product = product; | ||
this.quantity = quantity; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package com.example.backend.domain.cart.exception; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
import org.springframework.http.HttpStatus; | ||
|
||
@AllArgsConstructor | ||
@Getter | ||
public enum CartErrorCode { | ||
ALREADY_EXISTS_IN_CART(HttpStatus.BAD_REQUEST, "이미 장바구니에 추가된 상품입니다.", "400-1"), | ||
INVALID_QUANTITY(HttpStatus.BAD_REQUEST,"상품을 최소 1개 이상 추가하여야 합니다." ,"400-2"); | ||
|
||
final HttpStatus httpStatus; | ||
final String message; | ||
final String code; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package com.example.backend.domain.cart.exception; | ||
|
||
import org.springframework.http.HttpStatus; | ||
|
||
public class CartException extends RuntimeException { | ||
private CartErrorCode cartErrorCode; | ||
|
||
public CartException(CartErrorCode cartErrorCode) { | ||
super(cartErrorCode.message); | ||
this.cartErrorCode = cartErrorCode; | ||
} | ||
|
||
public HttpStatus getStatus() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. lombok 대체 |
||
return cartErrorCode.httpStatus; | ||
} | ||
|
||
public String getCode() { | ||
return cartErrorCode.code; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package com.example.backend.domain.cart.repository; | ||
|
||
import com.example.backend.domain.cart.entity.Cart; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
|
||
public interface CartRepository extends JpaRepository<Cart, Long> { | ||
|
||
boolean existsByProductId_IdAndMemberId_Id(Long productId, Long memberId); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Google Java Convention/Naver Java Convention 모두에서, 메서드 이름에 언더스코어를 쓰지 말라고 적혀있을거에요. (일반적으로 테스트가 아니라면 메서드 이름에 언더스코어를 쓰지 않습니다.) |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package com.example.backend.domain.cart.service; | ||
|
||
import com.example.backend.domain.cart.converter.CartConverter; | ||
import com.example.backend.domain.cart.dto.CartForm; | ||
import com.example.backend.domain.cart.entity.Cart; | ||
import com.example.backend.domain.cart.exception.CartErrorCode; | ||
import com.example.backend.domain.cart.exception.CartException; | ||
import com.example.backend.domain.cart.repository.CartRepository; | ||
import com.example.backend.domain.member.entity.Member; | ||
import com.example.backend.domain.product.service.ProductService; | ||
import com.example.backend.global.auth.exception.AuthErrorCode; | ||
import com.example.backend.global.auth.exception.AuthException; | ||
import jakarta.transaction.Transactional; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Service; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class CartService { | ||
|
||
private final CartRepository cartRepository; | ||
private final ProductService productService; | ||
|
||
@Transactional | ||
public Long addCartItem(CartForm cartForm, Member member) { | ||
// 로그인한 회원과 요청한 회원이 다르면 exception 발생 | ||
if (member.getId() != cartForm.memberId()) { | ||
throw new AuthException(AuthErrorCode.MEMBER_NOT_FOUND); | ||
} | ||
// 요청한 상품 ID와 수량 | ||
Long productId = cartForm.productId(); | ||
int quantity = cartForm.quantity(); | ||
|
||
// 수량이 0 이하인 경우 exception 발생 | ||
if (quantity <= 0) { | ||
throw new CartException(CartErrorCode.INVALID_QUANTITY); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 현재 이미 Jakarta Validation 으로 검사 하고 있지 않나요? |
||
} | ||
|
||
// 이미 장바구니에 있는 상품인 경우 exception 발생 | ||
if (cartRepository.existsByProductId_IdAndMemberId_Id(productId, member.getId())) { | ||
throw new CartException(CartErrorCode.ALREADY_EXISTS_IN_CART); | ||
} | ||
|
||
// 장바구니에 상품 추가 | ||
Cart cart = CartConverter.from( | ||
cartForm, | ||
member, | ||
productService.findById(productId) | ||
); | ||
|
||
return cartRepository.save(cart).getId(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package com.example.backend.domain.common; | ||
|
||
import jakarta.persistence.Column; | ||
import jakarta.persistence.Embeddable; | ||
import lombok.AccessLevel; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
/** | ||
* Address | ||
* <p>주소지 정보를 관리하는 클래스 입니다.</p> | ||
* @author Kim Dong O | ||
*/ | ||
@Embeddable | ||
@Getter | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
public class Address { | ||
@Column(nullable = false) | ||
private String city; //시 | ||
|
||
@Column(nullable = false) | ||
private String district; //구 | ||
|
||
@Column(nullable = false) | ||
private String country; //도로명 주소 | ||
|
||
@Column(nullable = false) | ||
private String detail; //상세 주소 | ||
|
||
@Builder | ||
public Address(String city, String district, String country, String detail) { | ||
this.city = city; | ||
this.district = district; | ||
this.country = country; | ||
this.detail = detail; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package com.example.backend.domain.common; | ||
|
||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import lombok.ToString; | ||
|
||
/** | ||
* EmailCertification | ||
* <p>인증 코드와 타입, 전송 횟수를 저장하는 객체 입니다.</p> | ||
* @author Kim Dong O | ||
*/ | ||
@Getter | ||
@NoArgsConstructor | ||
@ToString | ||
public class EmailCertification { | ||
private String certificationCode; | ||
private String verifyType; | ||
private String sendCount; | ||
|
||
@Builder | ||
public EmailCertification(String certificationCode, String verifyType, String sendCount) { | ||
this.certificationCode = certificationCode; | ||
this.verifyType = verifyType; | ||
this.sendCount = sendCount; | ||
} | ||
|
||
public EmailCertification(String certificationCode, String verifyType) { | ||
this.certificationCode = certificationCode; | ||
this.verifyType = verifyType; | ||
this.sendCount = "1"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 혹시 이걸 String 으로 처리하는 이유가 있나요? |
||
} | ||
|
||
public void addResendCount() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 미사용 메서드들이 상당히 많네요. 확인 후 제거해 주세요. |
||
int count = Integer.parseInt(sendCount); | ||
this.sendCount = String.valueOf(count + 1); | ||
} | ||
|
||
public void setCertificationCode(String certificationCode) { | ||
this.certificationCode = certificationCode; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JPA가 아니죠?
일반적으로 이런 유틸리티 클래스는
protected
가 아닌private
로 생성자를 정의하는게 좀 더 자연스럽습니다.