Skip to content

Commit

Permalink
feat: update manage review product
Browse files Browse the repository at this point in the history
  • Loading branch information
ngntu10 committed Oct 17, 2024
1 parent 1f0fb3e commit 289f1ec
Show file tree
Hide file tree
Showing 25 changed files with 513 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public ModelMapper modelMapper() {
modelMapper.typeMap(Product.class, ProductResponse.class).addMappings(mapper -> {
mapper.skip(ProductResponse::setUserLikedList);
mapper.skip(ProductResponse::setUserViewedList);
mapper.skip(ProductResponse::setReviewList);
});
return modelMapper;
}
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/com/Optimart/constants/Endpoint.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,11 @@ public static class Order{
public static final String ID_ME = "/me/{orderId}";
public static final String ID = "/{orderId}";
}

public static class Reivew{
public static final String BASE = API_PREFIX + "/reviews";
public static final String ID = "/{reviewId}";
public static final String DELETE_MANY = "/delete-many";
public static final String ID_ME = "/me/{reviewId}";
}
}
8 changes: 8 additions & 0 deletions src/main/java/com/Optimart/constants/MessageKeys.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,5 +74,13 @@ public class MessageKeys {
public static final String ORDER_GET_SUCCESS = "order.get_success";
public static final String ORDER_LIST_GET_SUCCESS = "order_list.get_success";
public static final String ORDER_CANCEL_SUCCESS = "order.cancel_success";
public static final String ORDER_DELETE_SUCCESS = "order.delete_success";

// REVIEW
public static final String REVIEW_GET_SUCCESS = "review.get_success";
public static final String REVIEW_LIST_GET_SUCCESS = "review_list.get_success";
public static final String REVIEW_WRITE_SUCCESS = "review.write_success";
public static final String REVIEW_NOT_EXISTED = "review.not_existed";
public static final String REVIEW_DELETE_SUCCESS = "review.delete_success";

}
7 changes: 7 additions & 0 deletions src/main/java/com/Optimart/controllers/OrderController.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,11 @@ public ResponseEntity<APIResponse<Order>> getOrderMeById(@PathVariable String or
public ResponseEntity<APIResponse<Order>> getOrderById(@PathVariable String orderId){
return ResponseEntity.ok(orderService.getOneOrderById(orderId));
}

@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = Object.class), mediaType = "application/json"))
@SecuredSwaggerOperation(summary = "Delete an existing order by id")
@DeleteMapping(Endpoint.Order.ID)
public ResponseEntity<APIResponse<Boolean>> deleteOrderById(@PathVariable String orderId){
return ResponseEntity.ok(orderService.deleteOrder(orderId));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import java.util.Map;
import java.util.Optional;

@Service
@RequiredArgsConstructor
@RestController
@Tag(name = "Product", description = "Everything about product")
Expand Down
87 changes: 87 additions & 0 deletions src/main/java/com/Optimart/controllers/ReviewController.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,91 @@
package com.Optimart.controllers;

import com.Optimart.annotations.SecuredSwaggerOperation;
import com.Optimart.constants.Endpoint;
import com.Optimart.dto.Product.CreateProductDTO;
import com.Optimart.dto.Review.DeleteMultiReviewDTO;
import com.Optimart.dto.Review.UpdateReviewDTO;
import com.Optimart.dto.Review.WriteReviewDTO;
import com.Optimart.models.Product;
import com.Optimart.models.Review;
import com.Optimart.responses.APIResponse;
import com.Optimart.responses.Review.ReviewResponse;
import com.Optimart.services.Review.ReviewService;
import com.Optimart.utils.LocalizationUtils;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

@Service
@RequiredArgsConstructor
@RestController
@Tag(name = "Review", description = "Everything about reviews")
@RequestMapping(Endpoint.Reivew.BASE)
public class ReviewController {
private final LocalizationUtils localizationUtils;
private final ReviewService reviewService;

@ApiResponse(responseCode = "201", description = "CREATED", content = @Content(schema = @Schema(implementation = Object.class), mediaType = "application/json"))
@SecuredSwaggerOperation(summary = "Write a new review")
@PostMapping
public ResponseEntity<APIResponse<ReviewResponse>> createNewReview(@RequestBody WriteReviewDTO writeReviewDTO){
return ResponseEntity.ok(reviewService.writeNewReview(writeReviewDTO));
}

@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = Product.class), mediaType = "application/json"))
@SecuredSwaggerOperation(summary = "Update a review")
@PutMapping(Endpoint.Reivew.ID)
public ResponseEntity<?> updateReview(@PathVariable String reviewId, @RequestBody UpdateReviewDTO updateReviewDTO) {
return ResponseEntity.ok(reviewService.updateReview(updateReviewDTO, reviewId));
}

@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = Product.class), mediaType = "application/json"))
@SecuredSwaggerOperation(summary = "Update a review by me")
@PutMapping(Endpoint.Reivew.ID_ME)
public ResponseEntity<?> updateReviewByMe(@PathVariable String reviewId, @RequestBody UpdateReviewDTO updateReviewDTO) {
return ResponseEntity.ok(reviewService.updateReview(updateReviewDTO, reviewId));
}

@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = Product.class), mediaType = "application/json"))
@SecuredSwaggerOperation(summary = "Get a existing review by id")
@GetMapping(Endpoint.Reivew.ID)
public ResponseEntity<?> getOneReview(@PathVariable String reviewId) {
return ResponseEntity.ok(reviewService.getOneReview(reviewId));
}

@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = Product.class), mediaType = "application/json"))
@SecuredSwaggerOperation(summary = "Get all reviews")
@GetMapping
public ResponseEntity<?> getAllReview(@RequestParam Map<Object, String> filters) {
return ResponseEntity.ok(reviewService.getAllReview(filters));
}

@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = Product.class), mediaType = "application/json"))
@SecuredSwaggerOperation(summary = "Delete a existing review by id")
@DeleteMapping(Endpoint.Reivew.ID)
public ResponseEntity<?> deleteOneReview(@PathVariable String reviewId) {
return ResponseEntity.ok(reviewService.deleteOneReview(reviewId));
}

@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = Product.class), mediaType = "application/json"))
@SecuredSwaggerOperation(summary = "Delete a existing review by me")
@DeleteMapping(Endpoint.Reivew.ID_ME)
public ResponseEntity<?> deleteOneReviewByMe(@PathVariable String reviewId) {
return ResponseEntity.ok(reviewService.deleteOneReview(reviewId));
}

@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = Product.class), mediaType = "application/json"))
@SecuredSwaggerOperation(summary = "Delete multiple review")
@DeleteMapping(Endpoint.Reivew.DELETE_MANY)
public ResponseEntity<?> deleteMultiReview(@RequestBody DeleteMultiReviewDTO deleteMultiReviewDTO) {
return ResponseEntity.ok(reviewService.deleteMultiReview(deleteMultiReviewDTO));
}
}
16 changes: 16 additions & 0 deletions src/main/java/com/Optimart/dto/Review/DeleteMultiReviewDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.Optimart.dto.Review;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.util.List;

@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class DeleteMultiReviewDTO {
List<String> reviewIds;
}
16 changes: 16 additions & 0 deletions src/main/java/com/Optimart/dto/Review/UpdateReviewDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.Optimart.dto.Review;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class UpdateReviewDTO {
private String id;
private String content;
private double star;
}
20 changes: 20 additions & 0 deletions src/main/java/com/Optimart/dto/Review/WriteReviewDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.Optimart.dto.Review;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class WriteReviewDTO {
@JsonProperty("product")
private String productId;
@JsonProperty("user")
private String userId;
private String content;
private double star;
}
9 changes: 5 additions & 4 deletions src/main/java/com/Optimart/models/Review.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.Optimart.models;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import jakarta.persistence.*;
import lombok.*;
Expand All @@ -19,17 +20,17 @@ public class Review extends BaseEntity {
@Column(name = "id")
private UUID id;

@JsonIgnore
@ManyToOne
@JsonManagedReference
@JoinColumn(name = "product_id", nullable = false)
private Product product;

@JsonIgnore
@ManyToOne
@JsonManagedReference
@JoinColumn(name = "user_id", nullable = false)
@JoinColumn(name = "user_id")
private User user;

@Column(name = "content", nullable = false)
@Column(name = "content")
private String content;

@Column(name = "star", nullable = false)
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/Optimart/models/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -160,4 +160,5 @@ public boolean isEnabled() {

@OneToMany(mappedBy = "user", cascade = {CascadeType.PERSIST,CascadeType.REMOVE})
private List<Order> orderList;

}
11 changes: 11 additions & 0 deletions src/main/java/com/Optimart/repositories/ReviewRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.Optimart.repositories;

import com.Optimart.models.Review;
import com.Optimart.models.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;

import java.util.UUID;

public interface ReviewRepository extends JpaRepository<Review, UUID>, JpaSpecificationExecutor<Review> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.Optimart.repositories.Specification;

import com.Optimart.models.Review;
import com.Optimart.models.User;
import jakarta.persistence.criteria.Join;
import jakarta.persistence.criteria.JoinType;
import org.springframework.data.jpa.domain.Specification;

public class ReviewSpecification {
public static Specification<Review> searchByKeyword(String search) {
return (root, query, criteriaBuilder) -> {
if (search == null || search.isEmpty()) {
return criteriaBuilder.conjunction();
}
Join<Review, User> userJoin = root.join("user", JoinType.INNER);
return criteriaBuilder.or(
criteriaBuilder.like(criteriaBuilder.lower(root.get("content")), "%" + search.toLowerCase() + "%"),
criteriaBuilder.like(criteriaBuilder.lower(userJoin.get("fullName")), "%" + search.toLowerCase() + "%")
);
};
}
public static Specification<Review> filterReviews(String search) {
return Specification.where(searchByKeyword(search));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.Optimart.responses.Product;

import lombok.*;

import java.util.UUID;

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class BaseProductResponse {
private UUID id;
private String name;
private String slug;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.Optimart.responses.Product;

import com.Optimart.models.*;
import com.Optimart.responses.Review.ReviewResponse;
import lombok.*;

import java.time.LocalDateTime;
Expand Down Expand Up @@ -35,6 +36,6 @@ public class ProductResponse {
private Set<UUID> userViewedList;
private ProductType productType;
private City city;
private List<Review> reviewList;
private List<ReviewResponse> reviewList;
private List<Comment> commentList;
}
20 changes: 20 additions & 0 deletions src/main/java/com/Optimart/responses/Review/ReviewResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.Optimart.responses.Review;

import com.Optimart.responses.Product.BaseProductResponse;
import com.Optimart.responses.User.BaseUserResponse;
import lombok.*;

import java.util.UUID;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ReviewResponse {
private UUID id;
private String content;
private double star;
private BaseProductResponse product;
private BaseUserResponse user;
}
19 changes: 19 additions & 0 deletions src/main/java/com/Optimart/responses/User/BaseUserResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.Optimart.responses.User;

import lombok.*;

import java.util.UUID;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class BaseUserResponse {
private UUID id;
private String fullName;
private String firstName;
private String middleName;
private String lastName;
private String imageUrl;
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ public interface IOrderService {
PagingResponse<List<Order>> getAllOrder(Map<Object, String> filters);
APIResponse<OrderResponse> cancelOrder(String id);
APIResponse<Order> getOneOrderById(String id);
APIResponse<Boolean> deleteOrder(String id);
}
7 changes: 7 additions & 0 deletions src/main/java/com/Optimart/services/Order/OrderService.java
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,13 @@ public APIResponse<Order> getOneOrderById(String id) {
return new APIResponse<>(order, MessageKeys.ORDER_GET_SUCCESS);
}

@Override
public APIResponse<Boolean> deleteOrder(String id) {
Order order = orderRepository.findById(UUID.fromString(id)).get();
orderRepository.delete(order);
return new APIResponse<>(true, localizationUtils.getLocalizedMessage(MessageKeys.ORDER_DELETE_SUCCESS));
}

private User getUser(String token){
String jwtToken = token.substring(7);
String email = jwtTokenUtil.extractEmail(jwtToken);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public interface IProductService {
PagingResponse<List<ProductResponse>> getLikedProducts (Map<Object, String> filters, String token);
PagingResponse<List<ProductResponse>> getViewedProducts (Map<Object, String> filters, String token);
Product getOneProduct(String productId);
Product getOneProductBySlug(String slug);
ProductResponse getOneProductBySlug(String slug);
Product getOneProductPublic(String productId, Boolean isViewed);
APIResponse<Product> updateProduct(ProductDTO product, String productId);
APIResponse<Boolean> deleteProduct(String productId);
Expand Down
Loading

0 comments on commit 289f1ec

Please sign in to comment.