-
Notifications
You must be signed in to change notification settings - Fork 0
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
feature: 봉달목록에 상품 추가 api #31
The head ref may contain hidden characters: "25-feature-\uBD09\uB2EC\uBAA9\uB85D\uC5D0-\uC0C1\uD488-\uCD94\uAC00-api"
Conversation
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.
깔꼼합니다 리더로이스
val deliveryMethod: String, | ||
) { | ||
|
||
fun toCommand(memberId: Long): SaveCartProductCommand { |
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.
presentation에서 쓰이는 Dto는 ~Request, ~Response
application에서 쓰이는 Dto는 ~Command
이렇게 쓰시는 거 맞나요?
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.
넵!
web 요청과 구분해서 application의 dto를 두었는데 어떠신가요?!
final fun signInAsMember(): AuthResponse { | ||
val response = requestSignIn() | ||
return response.`as`(AuthResponse::class.java) | ||
} | ||
|
||
private fun requestSignIn(): Response { | ||
return Given { | ||
log().all() | ||
.queryParam("code", "code") | ||
} When { | ||
get("/oauth/login/{oauthServerType}", "kakao") | ||
} Then { | ||
log().all() | ||
} Extract { | ||
response() | ||
} | ||
} |
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.
짱
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.
깔끔 대마왕
로이스 천재만재
고생하셨습니다!
fun save(command: SaveCartProductCommand): Long { | ||
// TODO memberRepository.existByIdOrThrow(command.memberId, MemberException(NOT_FOUND_MEMBER)) | ||
productRepository.existByIdOrThrow(command.productId, ProductException(NOT_FOUND_PRODUCT)) | ||
val savedCartProduct = cartProductRepository.save(command.toCartProduct()) | ||
return savedCartProduct.id |
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.
꼼꼼하네요 멋져요 👍
) { | ||
|
||
@PostMapping | ||
fun save( | ||
@Auth accessor: Accessor, |
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.
@hgo641 Accessor 이름을 LoginMember
로 짓는 건 어떠신가요?
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.
@Combi153 @TaeyeonRoyce
저는 좋습니다유
ㅎ... 저 그거말고도 cookie에 httpOnly등 몇 개 추가로 설정하고 싶은데 아예 auth 수정 PR하나 더 파서 변경해서 드려도 되나여
로이스도 LoginMember 이름 좋으시면 바로 작업하겠습니다앗
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.
LoginMember
가 더 좋아보여요!
제가 Accesor -> LoginMember로 이름만 수정해 두겠습니다
auth관련해서 issue파서 하고싶은거 하시죠!
val location = ServletUriComponentsBuilder.fromCurrentRequest() | ||
.path("/items/{id}") | ||
.buildAndExpand(cartProductId) | ||
.toUri() | ||
return ResponseEntity.created(location).build() |
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.
이 친구는 무엇인가요?
ResponseEntity.created(URI.create("/carts" + cartProductId)).build();
위 코드와 같은 걸까요?
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.
Location 헤더에 값이 달라져요!
위 방식으로 하면
"http://localhost:53077/carts/items/1" 이렇게 현재 온 요청의 url을 기반으로 추가되고,
URI.create("/carts" + cartProductId)).build();
이렇게 하면 "/carts/items/1" 이런 응답이 옵니다.
생성된 자원에 대해 접근가능한 URL을 제공하려고 사용했어요!!
data class SaveCartProductCommand( | ||
val memberId: Long, | ||
val productId: Long, | ||
val quantity: Int, | ||
val isMale: Boolean, | ||
val deliveryMethod: DeliveryMethod, | ||
) { | ||
fun toCartProduct(): CartProduct { | ||
return CartProduct( | ||
memberId = memberId, | ||
productId = productId, | ||
quantity = quantity, | ||
isMale = isMale, | ||
deliveryMethod = deliveryMethod, | ||
) | ||
} |
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.
Request -> Command -> CartProduct 이 느낌 썩 나쁘지 않네요! 따라할게요~ 👍
src/test/kotlin/com/petqua/presentation/cart/CartProductControllerTest.kt
Outdated
Show resolved
Hide resolved
class CartProductControllerTest( | ||
private val productRepository: ProductRepository | ||
) : ApiTestConfig() { | ||
init { | ||
val memberAuthResponse = signInAsMember() |
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.
꼼꼼 테스트 좋아요 😃
final fun signInAsMember(): AuthResponse { | ||
val response = requestSignIn() | ||
return response.`as`(AuthResponse::class.java) | ||
} | ||
|
||
private fun requestSignIn(): Response { | ||
return Given { | ||
log().all() | ||
.queryParam("code", "code") | ||
} When { | ||
get("/oauth/login/{oauthServerType}", "kakao") | ||
} Then { | ||
log().all() | ||
} Extract { | ||
response() | ||
} | ||
} |
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.
맛있겠다
Test Results15 files + 3 15 suites +3 2s ⏱️ ±0s Results for commit 5712afa. ± Comparison against base commit 5e8e1e5. This pull request removes 8 and adds 15 tests. Note that renamed tests count towards both.
♻️ This comment has been updated with latest results. |
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.
검증이 추가되니 든든하네요😎
fun save(command: SaveCartProductCommand): Long { | ||
memberRepository.existByIdOrThrow(command.memberId, MemberException(NOT_FOUND_MEMBER)) | ||
productRepository.existByIdOrThrow(command.productId, ProductException(NOT_FOUND_PRODUCT)) | ||
val savedCartProduct = cartProductRepository.save(command.toCartProduct()) | ||
return savedCartProduct.id | ||
} |
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.
앗 근데 장바구니에 같은 상품이 두 개 저장될 수 있나요? 보통 이미 동일한 상품이 장바구니에 존재하면 수량만 늘어났던 것 같아서요! 이 부분 펫쿠아 룰을 모르겠네요...
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.
엇 그렇네요. 이미 담긴 상품에 대해서 추가하는 경우에 대한 정책을 생각 못했네요..
이 부분 스크럼때 여쭤보고 반영 할게요!
감사합니다👍
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.
고생하셨습니다!
@@ -22,6 +23,7 @@ class CartProduct( | |||
val productId: Long, | |||
|
|||
@Embedded | |||
@AttributeOverride(name = "value", column = Column(name = "quantity", nullable = false)) |
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.
와 신기하다 지식이 늘어가네요
|
||
When("존재 하지 않는 회원이 요청 하는 경우") { | ||
val command = SaveCartProductCommand( | ||
memberId = 999L, |
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.
존재하지 않는 ID 설정을 Long.MIN_VALUE 로 해도 좋더라구요 지금도 좋아요!
* feat: CartProduct 도메인 추가 * feat: Entity 존재 여부 확인 확장 함수 추가 * feat: CartProduct 저장 로직 추가 * refactor: ProductController 패키지 이동 * feat: CartProduct 저장 API 추가 * test: CartProduct 저장시 예외 상황 테스트 추가 * refactor: 중복된 dependency 제거 * chore: mockk 의존성 추가 * test: 로그인 셋업 메서드 추가 * test: 구현된 Auth 헤더 사용 하도록 CartProduct API 테스트 수정 * refactor: 중복된 dependency 제거 * refactor: Accessor -> LoginMember 네이밍 수정 * test: 검증부 내용 이름 수정 * feat: 회원 존재 유무 검증 로직 추가 * test: application 테스트내 빈 등록 범위 수정 * test: 회원 검증 추가에 따른 테스트 로직 수정 * feat: 상품 수량 값객체 추가 * feat: 봉달 상품 수량 값객체 적용 * test: 잘못된 봉달 상품 수량에 대한 테스트 추가 * refactor: 이미 봉달 목록에 존재하는 상품에 대한 처리 추가 * fix: value 필드 예약어 사용에 의한 오류 해결
* refactor: 클래스명 변경 * refactor: DTO 분리 * refactor: 쿠키 설정 추가 * refactor: 메서드명 변경 * refactor: 인증 플로우 변경 * refactor: DTO 타입 변경 * refactor: 변수명 변경 * feature: 봉달목록에 상품 추가 api (#31) * feat: CartProduct 도메인 추가 * feat: Entity 존재 여부 확인 확장 함수 추가 * feat: CartProduct 저장 로직 추가 * refactor: ProductController 패키지 이동 * feat: CartProduct 저장 API 추가 * test: CartProduct 저장시 예외 상황 테스트 추가 * refactor: 중복된 dependency 제거 * chore: mockk 의존성 추가 * test: 로그인 셋업 메서드 추가 * test: 구현된 Auth 헤더 사용 하도록 CartProduct API 테스트 수정 * refactor: 중복된 dependency 제거 * refactor: Accessor -> LoginMember 네이밍 수정 * test: 검증부 내용 이름 수정 * feat: 회원 존재 유무 검증 로직 추가 * test: application 테스트내 빈 등록 범위 수정 * test: 회원 검증 추가에 따른 테스트 로직 수정 * feat: 상품 수량 값객체 추가 * feat: 봉달 상품 수량 값객체 적용 * test: 잘못된 봉달 상품 수량에 대한 테스트 추가 * refactor: 이미 봉달 목록에 존재하는 상품에 대한 처리 추가 * fix: value 필드 예약어 사용에 의한 오류 해결 * refactor: 클래스명 변경 * refactor: url 변경 * refactor: AccessToken으로만 인증을 수행하게 변경 * feat: 로그인 연장 API 추가 * test: 로그인 연장 테스트 추가 * refactor: GET 메서드로 변경 * test: 로그인 연장 테스트 추가 * test: �shouldNotBeNull() 사용 Co-authored-by: Taeyeon <[email protected]> * chore: import 정리 * refactor: 사용하지않는 ExceptionType 제거 * refactor: AuthException 패키지 이동 * chore: 서브모듈 업데이트 * chore: shouldNotBeNull 메서드 사용 --------- Co-authored-by: Taeyeon <[email protected]>
📌 관련 이슈
📁 작업 설명
상품의 옵션이
수량/암수구분/운송 방식
만 선택 가능하다고 생각하고 구현하였습니다.추후 옵션이 추가 된다면 product_option을 테이블로 분리하고, product_option_id를 가지는 방식으로 수정할 생각입니다.
기타
existByIdOrThrow
라는 확장함수 하나 추가했습니다. 042708b반환 값이 없는 검증용으로 사용 할 목적으로 만들었어요!
ControllerTest에서 자주 사용될 로그인셋업 메서드를 추가하였습니다.
d942e40
공통으로 사용되는
ApiTestConfig
에 추가 하였는데, 다들 괜찮은지 궁금합니다! (여진님이 만들어두신 FakeKakaoClient 사용 하였습니다)