diff --git a/build.gradle b/build.gradle index d8135831..ac26df6a 100644 --- a/build.gradle +++ b/build.gradle @@ -2,6 +2,7 @@ plugins { id 'java' id 'org.springframework.boot' version '3.3.5' id 'io.spring.dependency-management' version '1.1.6' + id 'com.ewerk.gradle.plugins.querydsl' version '1.0.10' } group = 'com.example' @@ -62,7 +63,7 @@ dependencies { // Query DSL implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' - annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta" + annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jakarta" annotationProcessor "jakarta.annotation:jakarta.annotation-api" annotationProcessor "jakarta.persistence:jakarta.persistence-api" diff --git a/src/main/java/com/example/api/domain/Review.java b/src/main/java/com/example/api/domain/Review.java index d8294804..1ff66018 100644 --- a/src/main/java/com/example/api/domain/Review.java +++ b/src/main/java/com/example/api/domain/Review.java @@ -8,8 +8,8 @@ @Entity @Getter @Table(name = "REVIEW") -@EqualsAndHashCode(callSuper = true) @NoArgsConstructor +@EqualsAndHashCode(callSuper = true) public class Review extends BaseEntity { @Id @Column(name ="REVIEW_ID") @@ -37,7 +37,6 @@ public class Review extends BaseEntity { @Column(name = "REVIEW_CONTENT") private String reviewContent; - public Review(int reviewStarPoint, String reviewContent, Contract contract) { this.reviewStarPoint = reviewStarPoint; this.reviewContent = reviewContent; diff --git a/src/main/java/com/example/api/review/ReviewRepository.java b/src/main/java/com/example/api/review/ReviewRepository.java index 85331d69..07776345 100644 --- a/src/main/java/com/example/api/review/ReviewRepository.java +++ b/src/main/java/com/example/api/review/ReviewRepository.java @@ -1,18 +1,34 @@ package com.example.api.review; import com.example.api.domain.Review; -import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; +import java.util.List; + @Repository public interface ReviewRepository extends JpaRepository { - @Query("SELECT r FROM Review r JOIN FETCH r.contract WHERE r.contract.offerEmployment.business.employer.accountId = :employerId") + @Query("SELECT r FROM Review r " + + "JOIN FETCH r.contract c " + + "WHERE c.offerEmployment.business.businessId = :employerId") List loadReviewsByEmployerId(@Param("employerId") Long employerId); - @Query("SELECT r FROM Review r WHERE (:reviewId IS NULL OR r.reviewId = :reviewId)") + @Query("SELECT r FROM Review r " + + "WHERE (:reviewId IS NULL OR r.reviewId = :reviewId)") List findReviewsByDynamicQuery(@Param("reviewId") Long reviewId); + + @Query("SELECT r FROM Review r " + + "JOIN FETCH r.writer b " + + "JOIN FETCH r.employee a " + + "JOIN FETCH r.contract c " + + "WHERE a.accountId = :accountId") + List findReviewsByAccountIdWithDetails(@Param("accountId") Long accountId); + + List findReviewsByEmployee_AccountId(Long accountId); } + + + diff --git a/src/main/java/com/example/api/review/ReviewService.java b/src/main/java/com/example/api/review/ReviewService.java index da731d05..5ab0109c 100644 --- a/src/main/java/com/example/api/review/ReviewService.java +++ b/src/main/java/com/example/api/review/ReviewService.java @@ -8,6 +8,11 @@ import java.util.List; +import com.example.api.domain.Review; +import com.example.api.review.dto.ReviewCommand; + +import java.time.LocalDateTime; + @Service @RequiredArgsConstructor public class ReviewService { @@ -21,15 +26,49 @@ public List getAllReviews() { .toList(); } - @Transactional - public List getReviewsByEmployee( - @Validated final Long reviewId - ) { + public List getReviewsByEmployee(@Validated final Long reviewId) { return reviewRepository.findReviewsByDynamicQuery(reviewId) .stream() .map(ReviewResponse::from) .toList(); } + + @Transactional + public List getReviews(@Validated final ReviewCommand reviewCommand) { + final List reviews = reviewRepository.findReviewsByEmployee_AccountId(reviewCommand.accountId()); + return mapToReviewResponses(reviews); + } + + @Transactional + public List getReviewsByEmployeeWithDetails(@Validated final ReviewCommand reviewCommand) { + final List reviews = reviewRepository.findReviewsByAccountIdWithDetails(reviewCommand.accountId()); + return mapToReviewResponses(reviews); + } + + private List mapToReviewResponses(final List reviews) { + return reviews.stream() + .map(this::mapToReviewResponse) + .toList(); + } + + private ReviewResponse mapToReviewResponse(final Review review) { + final String businessName = review.getContract().getOfferEmployment().getBusiness().getBusinessName(); + final Long businessId = review.getContract().getOfferEmployment().getBusiness().getBusinessId(); + final LocalDateTime contractStartTime = review.getContract().getContractStartTime(); + final LocalDateTime contractEndTime = review.getContract().getContractEndTime(); + final int reviewStarPoint = review.getReviewStarPoint(); + final String reviewContent = review.getReviewContent(); + + return new ReviewResponse( + review.getReviewId(), + businessName, + businessId, + contractStartTime, + contractEndTime, + reviewStarPoint, + reviewContent + ); + } } diff --git a/src/main/java/com/example/api/review/controller/ReviewController.java b/src/main/java/com/example/api/review/controller/ReviewController.java index dba6f492..f3f65911 100644 --- a/src/main/java/com/example/api/review/controller/ReviewController.java +++ b/src/main/java/com/example/api/review/controller/ReviewController.java @@ -1,3 +1,5 @@ +<<<<<<< HEAD +<<<<<<< HEAD package com.example.api.review.controller; import com.example.api.review.ReviewService; @@ -27,4 +29,39 @@ public ResponseEntity> getReviewsByEmployee( final List reviews = reviewService.getReviewsByEmployee(reivewId); return ResponseEntity.ok(reviews); } -} \ No newline at end of file +} +======= +package com.example.api.review.controller;public class ReviewController { +======= +package com.example.api.review.controller; + +import com.example.api.review.ReviewService; +import com.example.api.review.dto.ReviewCommand; +import com.example.api.review.dto.ReviewResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/api/v1/info") +@RequiredArgsConstructor +public class ReviewController { +<<<<<<< HEAD +>>>>>>> 0ff3ba1 (#53 feat(ReviewService): 서비스 코드 구현) +} +>>>>>>> 2f6b5cc (#53 feat(ReviewCommand): DTO 작성) +======= + private final ReviewService reviewService; + + @GetMapping("/my/reviews") + public ResponseEntity> getMyReviews( + @RequestParam final Long accountId + ) { + final ReviewCommand reviewCommand = new ReviewCommand(accountId); + final List reviews = reviewService.getReviews(reviewCommand); + return ResponseEntity.ok(reviews); + } +} +>>>>>>> 27670a3 (#53 feat(ReviewController): 컨트롤러 코드 구현) diff --git a/src/main/java/com/example/api/review/dto/ReviewCommand.java b/src/main/java/com/example/api/review/dto/ReviewCommand.java new file mode 100644 index 00000000..58f47028 --- /dev/null +++ b/src/main/java/com/example/api/review/dto/ReviewCommand.java @@ -0,0 +1,7 @@ +package com.example.api.review.dto; + +public record ReviewCommand( + Long accountId +){} + + diff --git a/src/main/java/com/example/api/review/dto/ReviewResponse.java b/src/main/java/com/example/api/review/dto/ReviewResponse.java index 9a02b3b0..cf42c2ec 100644 --- a/src/main/java/com/example/api/review/dto/ReviewResponse.java +++ b/src/main/java/com/example/api/review/dto/ReviewResponse.java @@ -1,25 +1,28 @@ package com.example.api.review.dto; -import com.example.api.domain.Account; -import com.example.api.domain.Business; import com.example.api.domain.Review; +import java.time.LocalDateTime; public record ReviewResponse( - Long reviewId, - Business writer, - Account employee, + Long reviewId, //Id + String businessName, + Long businessId, + LocalDateTime contractStartTime, + LocalDateTime contractEndTime, int reviewStarPoint, String reviewContent - ) { - public static ReviewResponse from(Review review) { + public static ReviewResponse from(final Review review) { return new ReviewResponse( review.getReviewId(), - review.getWriter(), - review.getEmployee(), + review.getContract().getOfferEmployment().getBusiness().getBusinessName(), + review.getContract().getOfferEmployment().getBusiness().getBusinessId(), + review.getContract().getContractStartTime(), + review.getContract().getContractEndTime(), review.getReviewStarPoint(), review.getReviewContent() ); } } + diff --git a/src/test/java/com/example/api/inquiry/InquiryServiceTest.java b/src/test/java/com/example/api/inquiry/InquiryServiceTest.java index 5fada952..9445e74f 100644 --- a/src/test/java/com/example/api/inquiry/InquiryServiceTest.java +++ b/src/test/java/com/example/api/inquiry/InquiryServiceTest.java @@ -1,5 +1,7 @@ package com.example.api.inquiry; +import com.example.api.account.entity.Nationality; +import com.example.api.account.entity.UserRole; import com.example.api.account.repository.AccountRepository; import com.example.api.domain.Account; import com.example.api.domain.Inquiry; @@ -35,18 +37,17 @@ void setUp() { accountRepository.deleteAll(); inquiryRepository.deleteAll(); - Account account = new Account(); - account.setAccountId(1L); - account.setName("Alice"); - account.setEmail("alice@example.com"); - account.setAge(25); - account.setSex("F"); - account.setPhoneNumber("010-1234-5678"); - account.setProfileImage("user-uploads/1/profile.png"); - account.setStarPoint(4.5f); - account.setWorkCount(10); - account.setOpenStatus(true); - account.setDeleted(false); + Account account = new Account( + "user01", + "password123", + "Alice", + "nickname01", + "010-1234-5678", + "alice@example.com", + Nationality.KOREAN, + List.of(UserRole.EMPLOYEE), + false + ); accountRepository.save(account); } @@ -111,4 +112,4 @@ void mapToInquiry_shouldMapCommandToInquiry() { assertThat(inquiry).isNotNull(); assertThat(inquiry.getTitle()).isEqualTo("Test Title"); } -} +} \ No newline at end of file diff --git a/src/test/java/com/example/api/review/controller/ReviewControllerTest.java b/src/test/java/com/example/api/review/controller/ReviewControllerTest.java new file mode 100644 index 00000000..595e2ee6 --- /dev/null +++ b/src/test/java/com/example/api/review/controller/ReviewControllerTest.java @@ -0,0 +1,65 @@ +package com.example.api.review.controller; + +import com.example.api.review.ReviewService; +import com.example.api.review.dto.ReviewCommand; +import com.example.api.review.dto.ReviewResponse; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.test.web.servlet.MockMvc; + +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.List; + +import static org.mockito.Mockito.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +@WebMvcTest(ReviewController.class) +public class ReviewControllerTest { + @Autowired + private MockMvc mockMvc; + + @Mock + private ReviewService reviewService; + + @InjectMocks + private ReviewController reviewController; + + private ReviewResponse reviewResponse1; + private ReviewResponse reviewResponse2; + + @BeforeEach + void setUp() { + reviewResponse1 = new ReviewResponse( + "Business A", 101L, LocalDateTime.now(), LocalDateTime.now(), 5, "Great service!"); + reviewResponse2 = new ReviewResponse( + "Business B", 102L, LocalDateTime.now(), LocalDateTime.now(), 4, "Good experience."); + } + + @Test + void testGetMyReviews() throws Exception { + when(reviewService.getReviews(any(ReviewCommand.class))) + .thenReturn(List.of(reviewResponse1, reviewResponse2)); + mockMvc.perform(get("/api/v1/info/my/reviews") + .param("accountId", "123")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.reviews").isArray()) + .andExpect(jsonPath("$.reviews[0].businessName").value("Business A")) + .andExpect(jsonPath("$.reviews[1].reviewContent").value("Good experience.")); + } + + @Test + void testGetMyReviewsNoData() throws Exception { + when(reviewService.getReviews(any(ReviewCommand.class))) + .thenReturn(Collections.emptyList()); + mockMvc.perform(get("/api/v1/info/my/reviews") + .param("accountId", "123")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.reviews").isEmpty()); + } +} diff --git a/src/test/java/com/example/api/review/service/ReviewServiceTest.java b/src/test/java/com/example/api/review/service/ReviewServiceTest.java new file mode 100644 index 00000000..bd8a6e44 --- /dev/null +++ b/src/test/java/com/example/api/review/service/ReviewServiceTest.java @@ -0,0 +1,41 @@ +package com.example.api.review.service; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.example.api.global.BaseIntegrationTest; +import com.example.api.review.ReviewService; +import com.example.api.review.dto.ReviewCommand; +import com.example.api.review.dto.ReviewResponse; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import java.util.List; + +@SpringBootTest +public class ReviewServiceTest extends BaseIntegrationTest { + @Autowired + private ReviewService reviewService; + + @BeforeEach + void setUp() { + } + + @Test + void testGetReviews() { + ReviewCommand reviewCommand = new ReviewCommand(1L); + List reviews = reviewService.getReviews(reviewCommand); + assertThat(reviews).isNotEmpty(); + assertThat(reviews.get(0).businessName()).isEqualTo("Tech Solutions Inc."); + assertThat(reviews.get(0).reviewContent()).isEqualTo("Good work"); + } + + @Test + void testGetReviewsWhenNoReviews() { + ReviewCommand reviewCommand = new ReviewCommand(999L); + List reviews = reviewService.getReviews(reviewCommand); + assertThat(reviews).isEmpty(); + } +} +