Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import ru.yandex.practicum.filmorate.dto.review.NewReviewRequest;
import ru.yandex.practicum.filmorate.dto.review.ReviewDto;
import ru.yandex.practicum.filmorate.dto.review.UpdateReviewRequest;
import ru.yandex.practicum.filmorate.model.Reaction;
import ru.yandex.practicum.filmorate.service.review.ReviewService;

import java.util.Collection;
Expand Down Expand Up @@ -72,13 +73,13 @@ public void setDislike(@PathVariable @Positive long id,
public void removeLike(@PathVariable @Positive long id,
@PathVariable @Positive long userId) {
log.trace("Remove review like by reviewId: {}, from userId: {}", id, userId);
reviewService.removeLike(id, userId);
reviewService.removeReaction(id, userId, Reaction.LIKE);
}

@DeleteMapping("/{id}/dislike/{userId}")
public void removeDislike(@PathVariable @Positive long id,
@PathVariable @Positive long userId) {
log.trace("Remove review dislike by reviewId: {}, from userId: {}", id, userId);
reviewService.removeDislike(id, userId);
reviewService.removeReaction(id, userId, Reaction.DISLIKE);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package ru.yandex.practicum.filmorate.model;

public enum Reaction {
LIKE, DISLIKE
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.stereotype.Repository;
import ru.yandex.practicum.filmorate.model.Reaction;
import ru.yandex.practicum.filmorate.model.Review;

import java.util.Collection;
Expand All @@ -25,10 +26,6 @@ public class JdbcReviewRepository implements ReviewRepository {
FROM reviews r
JOIN film_reviews fr ON r.review_id = fr.review_id
""";
private static final int UP_UR = 1;
private static final int DOUBLE_UP_UR = 2;
private static final int DROP_UR = -1;
private static final int DOUBLE_DROP_UR = -2;
private final NamedParameterJdbcOperations jdbc;
private final RowMapper<Review> mapper;

Expand Down Expand Up @@ -95,59 +92,30 @@ public Collection<Review> findAllByFilm(Long filmId, long count) {
}

@Override
public void setLike(long id, long userId) {
public void setReaction(long id, long userId, Reaction reaction) {
MapSqlParameterSource params = new MapSqlParameterSource("review_id", id)
.addValue("user_id", userId);
Boolean isPositiveYet = isPositive(params);
jdbc.update("""
MERGE INTO review_likes (review_id, user_id, is_positive)
KEY (review_id, user_id)
VALUES (:review_id, :user_id, TRUE)
""", params);
if (isPositiveYet == null) {
changeUsefulRating(params, UP_UR);
} else if (isPositiveYet) {
changeUsefulRating(params, DOUBLE_UP_UR);
switch (reaction) {
case LIKE -> params.addValue("is_positive", true);
case DISLIKE -> params.addValue("is_positive", false);
}
}

@Override
public void setDislike(long id, long userId) {
MapSqlParameterSource params = new MapSqlParameterSource("review_id", id)
.addValue("user_id", userId);
Boolean isPositiveYet = isPositive(params);
jdbc.update("""
MERGE INTO review_likes (review_id, user_id, is_positive)
KEY (review_id, user_id)
VALUES (:review_id, :user_id, FALSE)
""", params);
if (isPositiveYet == null) {
changeUsefulRating(params, DROP_UR);
} else if (isPositiveYet) {
changeUsefulRating(params, DOUBLE_DROP_UR);
}
}

@Override
public void removeLike(long id, long userId) {
MapSqlParameterSource params = new MapSqlParameterSource("review_id", id)
.addValue("user_id", userId);
jdbc.update("""
DELETE FROM review_likes
WHERE review_id = :review_id AND user_id = :user_id
VALUES (:review_id, :user_id, :is_positive)
""", params);
changeUsefulRating(params, DROP_UR);
updateUsefulRating(params);
}

@Override
public void removeDislike(long id, long userId) {
public void removeReaction(long id, long userId) {
MapSqlParameterSource params = new MapSqlParameterSource("review_id", id)
.addValue("user_id", userId);
jdbc.update("""
DELETE FROM review_likes
WHERE review_id = :review_id AND user_id = :user_id
""", params);
changeUsefulRating(params, UP_UR);
updateUsefulRating(params);
}

private MapSqlParameterSource getBaseParams(Review review) {
Expand All @@ -156,21 +124,15 @@ private MapSqlParameterSource getBaseParams(Review review) {
.addValue("is_Positive", review.getIsPositive());
}

private Boolean isPositive(MapSqlParameterSource params) {
List<Boolean> list = jdbc.query("""
SELECT is_positive
FROM review_likes
WHERE review_id = :review_id AND user_id = :user_id
""", params, (rs, rowNum) -> rs.getBoolean("is_positive"));
return list.isEmpty() ? null : list.getFirst();
}

private void changeUsefulRating(MapSqlParameterSource params, int points) {
params.addValue("points", points);
private void updateUsefulRating(MapSqlParameterSource params) {
jdbc.update("""
UPDATE reviews
SET useful_rating = useful_rating + :points
WHERE review_id = :review_id
UPDATE reviews r
SET useful_rating = COALESCE((
SELECT SUM(CASE WHEN is_positive THEN 1 ELSE -1 END)
FROM review_likes rl
WHERE rl.review_id = r.review_id),
0)
WHERE r.review_id = :review_id;
""", params);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package ru.yandex.practicum.filmorate.repository.review;

import ru.yandex.practicum.filmorate.model.Reaction;
import ru.yandex.practicum.filmorate.model.Review;

import java.util.Collection;
Expand All @@ -16,11 +17,7 @@ public interface ReviewRepository {

Collection<Review> findAllByFilm(Long filmId, long count);

void setLike(long id, long userId);
void setReaction(long id, long userId, Reaction reaction);

void setDislike(long id, long userId);

void removeLike(long id, long userId);

void removeDislike(long id, long userId);
void removeReaction(long id, long userId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import ru.yandex.practicum.filmorate.dto.review.NewReviewRequest;
import ru.yandex.practicum.filmorate.dto.review.ReviewDto;
import ru.yandex.practicum.filmorate.dto.review.UpdateReviewRequest;
import ru.yandex.practicum.filmorate.model.Reaction;

import java.util.Collection;

Expand All @@ -22,7 +23,5 @@ public interface ReviewService {

void setDislike(long id, long userId);

void removeLike(long id, long userId);

void removeDislike(long id, long userId);
}
void removeReaction(long id, long userId, Reaction reaction);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import ru.yandex.practicum.filmorate.dto.review.NewReviewRequest;
import ru.yandex.practicum.filmorate.dto.review.ReviewDto;
import ru.yandex.practicum.filmorate.dto.review.UpdateReviewRequest;
import ru.yandex.practicum.filmorate.dto.review.*;
import ru.yandex.practicum.filmorate.exception.NotFoundException;
import ru.yandex.practicum.filmorate.mapper.ReviewMapper;
import ru.yandex.practicum.filmorate.model.EventType;
import ru.yandex.practicum.filmorate.model.Operation;
import ru.yandex.practicum.filmorate.model.Reaction;
import ru.yandex.practicum.filmorate.model.Review;
import ru.yandex.practicum.filmorate.repository.film.FilmRepository;
import ru.yandex.practicum.filmorate.repository.review.ReviewRepository;
Expand Down Expand Up @@ -77,31 +76,26 @@ public void setLike(long id, long userId) {
getReviewOrThrow(id);
throwIfUserNotFound(userId);
log.info("Like to review {} has been added by user {}", id, userId);
reviewRepository.setLike(id, userId);
reviewRepository.setReaction(id, userId, Reaction.LIKE);
}

@Override
public void setDislike(long id, long userId) {
getReviewOrThrow(id);
throwIfUserNotFound(userId);
log.info("Dislike to review {} has been added by user {}", id, userId);
reviewRepository.setDislike(id, userId);
reviewRepository.setReaction(id, userId, Reaction.DISLIKE);
}

@Override
public void removeLike(long id, long userId) {
public void removeReaction(long id, long userId, Reaction reaction) {
getReviewOrThrow(id);
throwIfUserNotFound(userId);
log.info("Like to review {} has been removed by user {}", id, userId);
reviewRepository.removeLike(id, userId);
}

@Override
public void removeDislike(long id, long userId) {
getReviewOrThrow(id);
throwIfUserNotFound(userId);
log.info("Dislike to review {} has been removed by user {}", id, userId);
reviewRepository.removeDislike(id, userId);
switch (reaction) {
case LIKE -> log.info("Like to review {} has been removed by user {}", id, userId);
case DISLIKE -> log.info("Dislike to review {} has been removed by user {}", id, userId);
}
reviewRepository.removeReaction(id, userId);
}

private Review getReviewOrThrow(long id) {
Expand All @@ -118,4 +112,4 @@ private void throwIfFilmNotFound(long id) {
filmRepository.findById(id)
.orElseThrow(NotFoundException.supplier("Film with filmId %d not found", id));
}
}
}