diff --git a/eatery-service/src/main/java/com/drinkool/dtos/DtoMapper.java b/eatery-service/src/main/java/com/drinkool/dtos/DtoMapper.java index ea734ed..659bec5 100644 --- a/eatery-service/src/main/java/com/drinkool/dtos/DtoMapper.java +++ b/eatery-service/src/main/java/com/drinkool/dtos/DtoMapper.java @@ -1,6 +1,8 @@ package com.drinkool.dtos; import com.drinkool.entities.MenuItemEntity; +import com.drinkool.entities.ReviewEntity; +import com.drinkool.lib.dtos.SendReview; import org.mapstruct.BeanMapping; import org.mapstruct.Mapper; import org.mapstruct.MappingTarget; @@ -15,4 +17,6 @@ public interface DtoMapper { UpdateMenuItem input, @MappingTarget MenuItemEntity entity ); + + ReviewEntity toReviewEntity(SendReview source); } diff --git a/eatery-service/src/main/java/com/drinkool/entities/ReviewEntity.java b/eatery-service/src/main/java/com/drinkool/entities/ReviewEntity.java index 4477958..d563242 100644 --- a/eatery-service/src/main/java/com/drinkool/entities/ReviewEntity.java +++ b/eatery-service/src/main/java/com/drinkool/entities/ReviewEntity.java @@ -1,35 +1,34 @@ package com.drinkool.entities; -import com.drinkool.lib.models.ReviewModel; +import com.drinkool.interfaces.ReviewInterface; +import com.drinkool.lib.entities.BaseEntity; import jakarta.persistence.*; -import jakarta.transaction.Transactional; import java.util.UUID; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; @Entity +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor @Table(name = "reviews") -public class ReviewEntity extends ReviewModel { +public class ReviewEntity extends BaseEntity implements ReviewInterface { public UUID reviewerId; public UUID eateryId; - private ReviewEntity(ReviewModel input) { - super(input); - } + public Integer rating; - @Transactional - public static ReviewEntity create( - UUID reviewerId, - UUID eateryId, - ReviewModel reviewInput - ) { - ReviewEntity review = new ReviewEntity(reviewInput); + public String comment; - review.reviewerId = reviewerId; - review.eateryId = eateryId; - - review.persist(); - - return review; + public void setRating(Integer score) { + if (score < 1 || score > 5) { + throw new IllegalArgumentException("InvalidRatingValue"); + } + this.rating = score; } } diff --git a/eatery-service/src/main/java/com/drinkool/services/ReviewService.java b/eatery-service/src/main/java/com/drinkool/services/ReviewService.java index 555ba74..b5504b5 100644 --- a/eatery-service/src/main/java/com/drinkool/services/ReviewService.java +++ b/eatery-service/src/main/java/com/drinkool/services/ReviewService.java @@ -1,7 +1,9 @@ package com.drinkool.services; +import com.drinkool.dtos.DtoMapper; import com.drinkool.entities.ReviewEntity; import com.drinkool.lib.dtos.SendReview; +import jakarta.inject.Inject; import jakarta.transaction.Transactional; import jakarta.ws.rs.*; import jakarta.ws.rs.core.Response; @@ -9,12 +11,22 @@ import jakarta.ws.rs.core.Response; @Path("/api/review") public class ReviewService { - @POST - @Path("/create") - @Transactional - public Response create(SendReview input) { - ReviewEntity.create(input.reviewerId, input.orderId, input.review); + @Inject + DtoMapper dtoMapper; - return Response.status(201).build(); + @POST + @Transactional + public Response receiveReview(SendReview input) { + try { + ReviewEntity entity = dtoMapper.toReviewEntity(input); + + entity.persist(); + + return Response.status(Response.Status.CREATED).build(); + } catch (Exception e) { + return Response.status(Response.Status.BAD_REQUEST) + .entity(e.getMessage()) + .build(); + } } } diff --git a/eatery-service/src/test/java/com/drinkool/entities/ReviewEntityTest.java b/eatery-service/src/test/java/com/drinkool/entities/ReviewEntityTest.java index 9dedee1..cf83d28 100644 --- a/eatery-service/src/test/java/com/drinkool/entities/ReviewEntityTest.java +++ b/eatery-service/src/test/java/com/drinkool/entities/ReviewEntityTest.java @@ -1,32 +1,34 @@ package com.drinkool.entities; -import com.drinkool.lib.models.ReviewModel; import io.quarkus.test.junit.QuarkusTest; import jakarta.transaction.Transactional; import java.util.UUID; +import net.datafaker.Faker; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @QuarkusTest public class ReviewEntityTest { + private final Faker faker = new Faker(); + @Test @Transactional public void testCreateReview() { - // 1. Chuẩn bị dữ liệu (Arrange) UUID testReviewerId = UUID.randomUUID(); UUID testEateryId = UUID.randomUUID(); + String comment = faker.famousLastWords().lastWords(); + int rating = faker.random().nextInt(1, 5); - // Truyền trực tiếp rating và comment vào constructor của ReviewModel - ReviewModel inputModel = new ReviewModel(5, "Món ăn tuyệt vời!"); - - // 2. Thực thi (Act) - ReviewEntity savedReview = ReviewEntity.create( + ReviewEntity savedReview = new ReviewEntity( testReviewerId, testEateryId, - inputModel + rating, + comment ); + savedReview.persist(); + // 3. Kiểm chứng (Assert) Assertions.assertNotNull( savedReview, @@ -42,12 +44,8 @@ public class ReviewEntityTest { savedReview.eateryId, "Eatery ID không khớp" ); - Assertions.assertEquals(5, savedReview.rating, "Rating không khớp"); - Assertions.assertEquals( - "Món ăn tuyệt vời!", - savedReview.comment, - "Comment không khớp" - ); + Assertions.assertEquals(rating, savedReview.rating, "Rating không khớp"); + Assertions.assertEquals(comment, savedReview.comment, "Comment không khớp"); Assertions.assertNotNull( savedReview.id, diff --git a/eatery-service/src/test/java/com/drinkool/services/ReviewServiceTest.java b/eatery-service/src/test/java/com/drinkool/services/ReviewServiceTest.java index bdab888..f7072c8 100644 --- a/eatery-service/src/test/java/com/drinkool/services/ReviewServiceTest.java +++ b/eatery-service/src/test/java/com/drinkool/services/ReviewServiceTest.java @@ -1,42 +1,61 @@ package com.drinkool.services; import static io.restassured.RestAssured.given; +import static org.hamcrest.CoreMatchers.is; import static org.junit.jupiter.api.Assertions.*; import com.drinkool.entities.ReviewEntity; import com.drinkool.lib.dtos.SendReview; -import com.drinkool.lib.models.ReviewModel; import io.quarkus.test.junit.QuarkusTest; import io.restassured.http.ContentType; -import java.util.Random; +import jakarta.ws.rs.core.Response; import java.util.UUID; +import net.datafaker.Faker; import org.junit.jupiter.api.*; @QuarkusTest public class ReviewServiceTest { + private final Faker faker = new Faker(); + @Test - void receiveReview() { - Random random = new Random(); - + void receiveReview_Success() { UUID reviewerId = UUID.randomUUID(); - UUID orderId = UUID.randomUUID(); - String comment = UUID.randomUUID().toString(); - int rating = random.nextInt(); + UUID eateryId = UUID.randomUUID(); + String comment = faker.famousLastWords().lastWords(); + int rating = faker.random().nextInt(1, 5); - SendReview input = new SendReview(); - input.reviewerId = reviewerId; - input.orderId = orderId; - ReviewModel reviewModel = new ReviewModel(rating, comment); - input.review = reviewModel; + SendReview input = new SendReview(reviewerId, eateryId, rating, comment); given() .contentType(ContentType.JSON) .body(input) .when() - .post("/api/review/create") + .post("/api/review") .then() - .statusCode(201); + .statusCode(Response.Status.CREATED.getStatusCode()); + + assertEquals(1, ReviewEntity.find("reviewerId", reviewerId).count()); + } + + @Test + void receiveReview_FailedDueToInvalidRating() { + UUID reviewerId = UUID.randomUUID(); + UUID eateryId = UUID.randomUUID(); + String comment = faker.famousLastWords().lastWords(); + int rating = faker.random().nextInt(6, 10); + + SendReview input = new SendReview(reviewerId, eateryId, rating, comment); + + given() + .contentType(ContentType.JSON) + .body(input) + .when() + .post("/api/review") + .then() + .contentType(ContentType.TEXT) + .body(is("InvalidRatingValue")) + .statusCode(Response.Status.BAD_REQUEST.getStatusCode()); assertEquals(1, ReviewEntity.find("reviewerId", reviewerId).count()); } diff --git a/lib/pom.xml b/lib/pom.xml index bc83c1a..a1a0976 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -1,8 +1,8 @@ - + 4.0.0 @@ -18,6 +18,7 @@ 25 25 UTF-8 + 1.18.46 @@ -41,7 +42,7 @@ org.projectlombok lombok - 1.18.46 + ${org.projectlombok.version} provided @@ -67,4 +68,38 @@ quarkus-smallrye-graphql - + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + true + + + org.projectlombok + lombok + ${org.projectlombok.version} + + + + + + + io.smallrye + jandex-maven-plugin + 3.2.7 + + + make-index + + jandex + + + + + + + \ No newline at end of file diff --git a/lib/src/main/java/com/drinkool/interfaces/ReviewInterface.java b/lib/src/main/java/com/drinkool/interfaces/ReviewInterface.java new file mode 100644 index 0000000..8a006df --- /dev/null +++ b/lib/src/main/java/com/drinkool/interfaces/ReviewInterface.java @@ -0,0 +1,17 @@ +package com.drinkool.interfaces; + +import java.util.UUID; + +public interface ReviewInterface { + UUID getReviewerId(); + void setReviewerId(UUID x); + + UUID getEateryId(); + void setEateryId(UUID x); + + Integer getRating(); + void setRating(Integer x); + + String getComment(); + void setComment(String x); +} diff --git a/lib/src/main/java/com/drinkool/lib/dtos/SendReview.java b/lib/src/main/java/com/drinkool/lib/dtos/SendReview.java index 2793753..a9661f5 100644 --- a/lib/src/main/java/com/drinkool/lib/dtos/SendReview.java +++ b/lib/src/main/java/com/drinkool/lib/dtos/SendReview.java @@ -1,11 +1,22 @@ package com.drinkool.lib.dtos; -import com.drinkool.lib.models.ReviewModel; +import com.drinkool.interfaces.ReviewInterface; +import io.quarkus.runtime.annotations.RegisterForReflection; import java.util.UUID; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; -public class SendReview { +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@RegisterForReflection +public class SendReview implements ReviewInterface { - public UUID reviewerId; - public UUID orderId; - public ReviewModel review; + private UUID reviewerId; + private UUID eateryId; + private Integer rating; + private String comment; } diff --git a/lib/src/main/java/com/drinkool/lib/entities/BaseEntity.java b/lib/src/main/java/com/drinkool/lib/entities/BaseEntity.java index 0a33368..a28ca88 100644 --- a/lib/src/main/java/com/drinkool/lib/entities/BaseEntity.java +++ b/lib/src/main/java/com/drinkool/lib/entities/BaseEntity.java @@ -4,7 +4,10 @@ import io.quarkus.hibernate.orm.panache.PanacheEntityBase; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.MappedSuperclass; +import java.time.LocalDateTime; import java.util.UUID; +import org.hibernate.annotations.CreationTimestamp; +import org.hibernate.annotations.UpdateTimestamp; @MappedSuperclass public class BaseEntity extends PanacheEntityBase { @@ -12,4 +15,10 @@ public class BaseEntity extends PanacheEntityBase { @jakarta.persistence.Id @GeneratedValue(strategy = GenerationType.UUID) public UUID id; + + @CreationTimestamp + public LocalDateTime createDate; + + @UpdateTimestamp + public LocalDateTime updateDate; } diff --git a/lib/src/main/java/com/drinkool/lib/models/ReviewModel.java b/lib/src/main/java/com/drinkool/lib/models/ReviewModel.java deleted file mode 100644 index 6412d6f..0000000 --- a/lib/src/main/java/com/drinkool/lib/models/ReviewModel.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.drinkool.lib.models; - -import com.drinkool.lib.entities.BaseEntity; -import jakarta.persistence.*; -import java.time.LocalDateTime; - -@MappedSuperclass -public class ReviewModel extends BaseEntity { - - @Column - public int rating; - - @Column - public String comment; - - public ReviewModel(int rating, String comment) { - this.rating = rating; - this.comment = comment; - } - - public ReviewModel() {} - - public ReviewModel(ReviewModel input) { - this(input.rating, input.comment); - } - - @org.hibernate.annotations.CreationTimestamp - @Column(name = "review_date", updatable = false) - public LocalDateTime reviewDate; -}