주문당 하나의 리뷰만 쓰게 하면서 각 주문마다 원하는 대로 리뷰를 , 즉 4번주문엔 리뷰 안쓰고 6번에만 쓴다던가 할수있게 하기 위해서 방법을 강구해 봤다.
먼저
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "order_id", nullable = false)
val order: OrdersEntity,
리뷰를 오더랑 연결시켜서 오더 아이디를 받게 한다.
리뷰리포지터리에는 이걸 넣는다
fun findByOrderId(orderId: Long): Optional<Review>
이걸통해 오더아이디로 얘가내가 쓴주문인지 알도록 하고
오더리포지터리에
fun findByIdAndSocialUserId(orderId: Long, socialUserId: Long): Optional<OrdersEntity>
이것을 넣어서 나중에 해당 유저가 주문을 생성했는지를 알도록 한다.
서비스에도 주문 아이디를 넣고
fun createReview(
productId: Long,
socialUser: UserPrincipal,
createReviewRequest: CreateReviewRequest,
orderId: Long,
): ReviewResponse
서비스임플은
@Transactional
override fun createReview(
productId: Long,
socialUser: UserPrincipal,
createReviewRequest: CreateReviewRequest,
orderId: Long,
): ReviewResponse {
// 주문에 대한 리뷰가 이미 있는지 확인
reviewRepository.findByOrderId(orderId).ifPresent {
throw IllegalStateException("이미 이 주문에 대한 리뷰가 작성되었습니다.")
}
//이메일로 유저가 있는지 확인
val socialUser = socialUserRepository.findByEmail(socialUser.email)
.orElseThrow { ModelNotFoundException("User not found", socialUser.id) }
//제품이 있는지, 소프트딜리트인지 확인
val product = productRepository.findByIdAndDeletedAtIsNull(productId)
.orElseThrow { ModelNotFoundException("Product not found or deleted", productId) }
//아이디가 없으면
val userId = socialUser.id ?: throw IllegalArgumentException("사용자 ID가 없습니다")
// orderId와 userId로 주문을 했는지
val order = orderRepository.findByIdAndSocialUserId(orderId, userId)
.orElseThrow { ModelNotFoundException("주문내역을 확인할 수 없습니다", orderId) }
val review = createReviewRequest.toReview(product, socialUser, order)
val savedReview = reviewRepository.save(review)
return ReviewResponse.toReviewResponse(savedReview)
}
컨트롤러는
@PostMapping("/{productId}/reviews/{orderId}")
fun createReview(
@PathVariable productId: Long,
@PathVariable orderId: Long,
@AuthenticationPrincipal socialUser: UserPrincipal,
@Valid @RequestBody createReviewRequest: CreateReviewRequest,
): ResponseEntity<List<ReviewResponse>> {
val result = reviewService.createReview(productId, socialUser, createReviewRequest, orderId)
val results = listOf(result)
return ResponseEntity
.status(HttpStatus.CREATED)
.body(results)
}
@PathVariable orderId: Long,이걸로 자기가 원하는 주문에 id를 입력해서 원하는 주문에만 리뷰를 남길수 있다.
다음엔 providerid를 유저프린시플이 인식하도록 하는 거였다.
fun createReview(
productId: Long,
providerId: Long,
createReviewRequest: CreateReviewRequest,
orderId: Long,
): ReviewResponse
이런식으로 유처프린시플이 있던 자리에 providerid를 집어넣고
@Transactional
override fun createReview(
productId: Long,
providerId: Long, 이렇게 providerid를 넣어준다.
createReviewRequest: CreateReviewRequest,
orderId: Long,
): ReviewResponse {
// 주문에 대한 리뷰가 이미 있는지 확인
reviewRepository.findByOrderId(orderId).ifPresent {
throw IllegalStateException("이미 이 주문에 대한 리뷰가 작성되었습니다.")
}
여기도 이메일 부분을 findByProviderId로 바꾼다.
val socialUser = socialUserRepository.findByProviderId(providerId.toString())
.orElseThrow { ModelNotFoundException("User not found", providerId) }
// 제품이 있는지, 소프트딜리트인지 확인
val product = productRepository.findByIdAndDeletedAtIsNull(productId)
.orElseThrow { ModelNotFoundException("Product not found or deleted", productId) }
// 아이디가 없으면
val userId = socialUser.id ?: throw IllegalArgumentException("사용자 ID가 없습니다")
// orderId와 userId로 주문을 했는지
val order = orderRepository.findByIdAndSocialUserId(orderId, userId)
.orElseThrow { ModelNotFoundException("주문내역을 확인할 수 없습니다", orderId) }
// 이제 리뷰를 생성
val review = createReviewRequest.toReview(product, socialUser, order)
val savedReview = reviewRepository.save(review)
return ReviewResponse.toReviewResponse(savedReview)
}
참고로 소셜유저리포지터리에
fun findByProviderId(providerId: String): Optional<SocialUser>//providerId를 인식하기 위해 추가
이걸 findbyemail 대신 넣어준다.
리뷰컨트롤러에
@PostMapping("/{productId}/reviews/{orderId}")
fun createReview(
@PathVariable productId: Long,
@PathVariable orderId: Long,
@AuthenticationPrincipal user: UserPrincipal, // providerId를 받도록 된듯하다
@Valid @RequestBody createReviewRequest: CreateReviewRequest,
): ResponseEntity<List<ReviewResponse>> {
val result = reviewService.createReview(productId, user.id, createReviewRequest, orderId)
val results = listOf(result)
return ResponseEntity
.status(HttpStatus.CREATED)
.body(results)
}
서비스, 서비스 임플 등에서 프로바이더 아이디를 계속 넣어준 덕분에 이제 userprincipal은 프로바이더 아이디를 잘 받게 된다.
처음 userprincipal이 유저아이디를 인식시키려 했을때, userprincipal은 유저아이디를 받으려 했으나 providerid가 인식이 된다며 작동하지 않았던 것으로 시작해서 providerid를 인식 시키기 위해 userprincipal이 직접 providerid를 받도록 바꾸고, jwt도 수정해서 providerid를 인식 시키려다 이상하게 계속 터지는 오류들에 항복했다가 그것들을 전혀 건드리지 않은채 providerid를 받게 하는 방법을 드디어 알아낸 것이다. 이걸로 오랜 싸움으 끝났다.