This commit is contained in:
ShabOl 2024-06-10 11:49:41 +04:00
parent 9cfdbef69b
commit 34e82cc1d8
38 changed files with 1762 additions and 280 deletions

View File

@ -1,5 +1,6 @@
package com.example.demo;
import java.time.Period;
import java.util.Objects;
import org.slf4j.Logger;
@ -12,8 +13,12 @@ import com.example.demo.ageRatings.model.AgeRatingEntity;
import com.example.demo.ageRatings.service.AgeRatingService;
import com.example.demo.movies.model.MovieEntity;
import com.example.demo.movies.service.MovieService;
import com.example.demo.subscriptions.model.SubscriptionEntity;
import com.example.demo.subscriptions.service.SubscriptionService;
import com.example.demo.types.model.TypeEntity;
import com.example.demo.types.service.TypeService;
import com.example.demo.users.model.UserEntity;
import com.example.demo.users.service.UserService;
@SpringBootApplication
public class DemoApplication implements CommandLineRunner {
@ -22,11 +27,16 @@ public class DemoApplication implements CommandLineRunner {
private final TypeService typeService;
private final AgeRatingService ageRatingService;
private final MovieService movieService;
private final UserService userService;
private final SubscriptionService subscriptionService;
public DemoApplication(TypeService typeService, AgeRatingService ageRatingService, MovieService movieService) {
public DemoApplication(TypeService typeService, AgeRatingService ageRatingService, MovieService movieService,
UserService userService, SubscriptionService subscriptionService) {
this.typeService = typeService;
this.ageRatingService = ageRatingService;
this.movieService = movieService;
this.userService = userService;
this.subscriptionService = subscriptionService;
}
public static void main(String[] args) {
@ -37,35 +47,42 @@ public class DemoApplication implements CommandLineRunner {
public void run(String... args) throws Exception {
if (args.length > 0 && Objects.equals("--populate", args[0])) {
log.info("Create default types values");
final var type1 = typeService.create(new TypeEntity(null, "Фильм"));
final var type2 = typeService.create(new TypeEntity(null, "Сериал"));
final var type1 = typeService.create(new TypeEntity("Фильм"));
final var type2 = typeService.create(new TypeEntity("Сериал"));
log.info("Create default ageRatings values");
// final var ageRating1 = ageRatingService.create(new AgeRatingEntity(null,
// "0+"));
// final var ageRating2 = ageRatingService.create(new AgeRatingEntity(null,
// "6+"));
// final var ageRating3 = ageRatingService.create(new AgeRatingEntity(null,
// "12+"));
final var ageRating4 = ageRatingService.create(new AgeRatingEntity(null, "16+"));
final var ageRating5 = ageRatingService.create(new AgeRatingEntity(null, "18+"));
// final var ageRating1 = ageRatingService.create(new AgeRatingEntity("0+"));
// final var ageRating2 = ageRatingService.create(new AgeRatingEntity("6+"));
// final var ageRating3 = ageRatingService.create(new AgeRatingEntity("12+"));
final var ageRating4 = ageRatingService.create(new AgeRatingEntity("16+"));
final var ageRating5 = ageRatingService.create(new AgeRatingEntity("18+"));
log.info("Create default movies values");
movieService.create(new MovieEntity(null, "Бойцовский клуб", type1, false,
movieService.create(new MovieEntity("Бойцовский клуб", type1, false,
"src/assets/main-page/posters/PeakyBlinders.png",
"Сотрудник страховой компании страдает хронической бессонницей и отчаянно пытается вырваться из мучительно скучной жизни...",
1999, "США", "Интриги. Хаос. Мыло", "Дэвид Финчер", ageRating5,
"https://www.youtube.com/embed/dfeUzm6KF4g?si=U2D-2WNsJzkcxlBX"));
movieService.create(new MovieEntity(null, "Американский психопат", type1, true,
movieService.create(new MovieEntity("Американский психопат", type1, true,
"src/assets/main-page/posters/AmericanPsycho.jpg",
"Днем он ничем не отличается от окружающих, и в толпе вы не обратите на него внимания...",
2000, "США, Канада", "Респектабельная внешность дьявола", "Мэри Хэррон", ageRating5,
"https://www.youtube.com/embed/PpUWjff_OcM?si=e7tSm4V6qYkz406B"));
movieService.create(new MovieEntity(null, "Острые козырьки", type2, false,
movieService.create(new MovieEntity("Острые козырьки", type2, false,
"src/assets/main-page/posters/PeakyBlinders.png",
"Сериал рассказывает историю восхождения одной ирландской семьи...",
2013, "Великобритания", "The streets are theirs", "Энтони Бирн, Колм МакКарти", ageRating4,
"https://www.youtube.com/embed/7cOfn_sjlXM?si=fxNoZjlUon1SZd70"));
log.info("Create default subscription values");
subscriptionService.create(new SubscriptionEntity("Подписка 1", Period.of(0, 0, 7), 199.99));
subscriptionService.create(new SubscriptionEntity("Подписка 2", Period.of(0, 1, 0), 299.99));
subscriptionService.create(new SubscriptionEntity("Подписка 3", Period.of(0, 6, 0), 799.99));
log.info("Create default users values");
userService.create(new UserEntity("email01@mail.com", "12345"));
userService.create(new UserEntity("email002@mail.com", "admin"));
userService.create(new UserEntity("email0003@mail.com", "qwerty"));
}
}
}

View File

@ -53,7 +53,7 @@ public class AgeRatingController {
}
@PutMapping("/{id}")
public AgeRatingDto update(@PathVariable(name = "id") Long id, @RequestBody AgeRatingDto dto) {
public AgeRatingDto update(@PathVariable(name = "id") Long id, @RequestBody @Valid AgeRatingDto dto) {
return toDto(ageRatingService.update(id, toEntity(dto)));
}

View File

@ -3,13 +3,16 @@ package com.example.demo.ageRatings.api;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
public class AgeRatingDto {
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
private Long id;
@NotBlank
@Size(min = 2, max = 4)
private String name;
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
public Long getId() {
return id;
}

View File

@ -8,6 +8,7 @@ import org.springframework.transaction.annotation.Transactional;
import com.example.demo.ageRatings.model.AgeRatingEntity;
import com.example.demo.ageRatings.repository.AgeRatingRepository;
import com.example.demo.core.error.AlreadyExistsException;
import com.example.demo.core.error.NotFoundException;
@Service
@ -18,6 +19,12 @@ public class AgeRatingService {
this.repository = repository;
}
private void checkNameUnique(String name) {
if (repository.findByNameIgnoreCase(name).isPresent()) {
throw new AlreadyExistsException();
}
}
@Transactional(readOnly = true)
public List<AgeRatingEntity> getAll() {
return StreamSupport.stream(repository.findAll().spliterator(), false).toList();
@ -35,6 +42,7 @@ public class AgeRatingService {
throw new IllegalArgumentException("Entity is null");
}
checkNameUnique(entity.getName());
return repository.save(entity);
}
@ -42,6 +50,7 @@ public class AgeRatingService {
public AgeRatingEntity update(Long id, AgeRatingEntity entity) {
final AgeRatingEntity existsEntity = get(id);
checkNameUnique(entity.getName());
existsEntity.setName(entity.getName());
return repository.save(existsEntity);
}
@ -54,6 +63,7 @@ public class AgeRatingService {
return existsEntity;
}
@Transactional
public void deleteAll() {
repository.deleteAll();
}

View File

@ -0,0 +1,97 @@
package com.example.demo.core.api;
import java.util.ArrayList;
import java.util.List;
public class PageDto<D> {
private List<D> items = new ArrayList<>();
private int itemsCount;
private int currentPage;
private int currentSize;
private int totalPages;
private long totalItems;
private boolean isFirst;
private boolean isLast;
private boolean hasNext;
private boolean hasPrevious;
public List<D> getItems() {
return items;
}
public void setItems(List<D> items) {
this.items = items;
}
public int getItemsCount() {
return itemsCount;
}
public void setItemsCount(int itemsCount) {
this.itemsCount = itemsCount;
}
public int getCurrentPage() {
return currentPage;
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
public int getCurrentSize() {
return currentSize;
}
public void setCurrentSize(int currentSize) {
this.currentSize = currentSize;
}
public int getTotalPages() {
return totalPages;
}
public void setTotalPages(int totalPages) {
this.totalPages = totalPages;
}
public long getTotalItems() {
return totalItems;
}
public void setTotalItems(long totalItems) {
this.totalItems = totalItems;
}
public boolean isFirst() {
return isFirst;
}
public void setFirst(boolean isFirst) {
this.isFirst = isFirst;
}
public boolean isLast() {
return isLast;
}
public void setLast(boolean isLast) {
this.isLast = isLast;
}
public boolean isHasNext() {
return hasNext;
}
public void setHasNext(boolean hasNext) {
this.hasNext = hasNext;
}
public boolean isHasPrevious() {
return hasPrevious;
}
public void setHasPrevious(boolean hasPrevious) {
this.hasPrevious = hasPrevious;
}
}

View File

@ -0,0 +1,25 @@
package com.example.demo.core.api;
import java.util.function.Function;
import org.springframework.data.domain.Page;
public class PageDtoMapper {
private PageDtoMapper() {
}
public static <D, E> PageDto<D> toDto(Page<E> page, Function<E, D> mapper) {
final PageDto<D> dto = new PageDto<>();
dto.setItems(page.getContent().stream().map(mapper::apply).toList());
dto.setItemsCount(page.getNumberOfElements());
dto.setCurrentPage(page.getNumber());
dto.setCurrentSize(page.getSize());
dto.setTotalPages(page.getTotalPages());
dto.setTotalItems(page.getTotalElements());
dto.setFirst(page.isFirst());
dto.setLast(page.isLast());
dto.setHasNext(page.hasNext());
dto.setHasPrevious(page.hasPrevious());
return dto;
}
}

View File

@ -3,6 +3,7 @@ package com.example.demo.core.configuration;
public class Constants {
public static final String SEQUENCE_NAME = "hibernate_sequence";
public static final String API_URL = "/api/1.0";
public static final String DEFAULT_PAGE_SIZE = "5";
private Constants() {
}

View File

@ -0,0 +1,7 @@
package com.example.demo.core.error;
public class AlreadyExistsException extends RuntimeException {
public AlreadyExistsException() {
super("Entity already exists");
}
}

View File

@ -1,7 +1,5 @@
package com.example.demo.movies.api;
import java.util.List;
import org.modelmapper.ModelMapper;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
@ -13,6 +11,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.ageRatings.service.AgeRatingService;
import com.example.demo.core.api.PageDto;
import com.example.demo.core.api.PageDtoMapper;
import com.example.demo.core.configuration.Constants;
import com.example.demo.movies.model.MovieEntity;
import com.example.demo.movies.service.MovieService;
@ -23,13 +24,16 @@ import jakarta.validation.Valid;
@RestController
@RequestMapping(Constants.API_URL + "/movie")
public class MovieController {
private final MovieService itemService;
private final MovieService movieService;
private final TypeService typeService;
private final AgeRatingService ageRatingService;
private final ModelMapper modelMapper;
public MovieController(MovieService itemService, TypeService typeService, ModelMapper modelMapper) {
this.itemService = itemService;
public MovieController(MovieService movieService, TypeService typeService, AgeRatingService ageRatingService,
ModelMapper modelMapper) {
this.movieService = movieService;
this.typeService = typeService;
this.ageRatingService = ageRatingService;
this.modelMapper = modelMapper;
}
@ -39,32 +43,44 @@ public class MovieController {
private MovieEntity toEntity(MovieDto dto) {
final MovieEntity entity = modelMapper.map(dto, MovieEntity.class);
entity.setType(typeService.get(dto.getTypeId()));
entity.setAgeRating(ageRatingService.get(dto.getAgeRatingId()));
return entity;
}
@GetMapping
public List<MovieDto> getAll(@RequestParam(name = "typeId", defaultValue = "0") Long typeId) {
return itemService.getAll(typeId).stream().map(this::toDto).toList();
public PageDto<MovieDto> getAll(
@RequestParam(name = "typeId", defaultValue = "0") Long typeId,
@RequestParam(name = "ageRatingId", defaultValue = "0") Long ageRatingId,
@RequestParam(name = "page", defaultValue = "0") int page,
@RequestParam(name = "size", defaultValue = Constants.DEFAULT_PAGE_SIZE) int size) {
return PageDtoMapper.toDto(movieService.getAll(typeId, ageRatingId, page, size), this::toDto);
}
@GetMapping("/{id}")
public MovieDto get(@PathVariable(name = "id") Long id) {
return toDto(itemService.get(id));
return toDto(movieService.get(id));
}
@PostMapping
public MovieDto create(@RequestBody @Valid MovieDto dto) {
return toDto(itemService.create(toEntity(dto)));
return toDto(movieService.create(toEntity(dto)));
}
@PutMapping("/{id}")
public MovieDto update(@PathVariable(name = "id") Long id, @RequestBody MovieDto dto) {
return toDto(itemService.update(id, toEntity(dto)));
public MovieDto update(@PathVariable(name = "id") Long id, @RequestBody @Valid MovieDto dto) {
return toDto(movieService.update(id, toEntity(dto)));
}
@DeleteMapping("/{id}")
public MovieDto delete(@PathVariable(name = "id") Long id) {
return toDto(itemService.delete(id));
return toDto(movieService.delete(id));
}
@GetMapping("/{id}/rating")
public Double getAverageRating(@PathVariable(name = "id") Long id) {
return movieService.getAverageRating(id);
}
}

View File

@ -7,6 +7,7 @@ import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
public class MovieDto {
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
private Long id;
@NotNull

View File

@ -8,7 +8,6 @@ import com.example.demo.types.model.TypeEntity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.JoinTable;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
@ -24,37 +23,37 @@ public class MovieEntity extends BaseEntity {
@JoinColumn(name = "typeId", nullable = false)
private TypeEntity type;
@ManyToOne
@JoinColumn(name = "ageRatingId", nullable = false)
private AgeRatingEntity ageRating;
@Column(nullable = false)
private boolean requiresSubscription;
@Column(length = 50)
private String poster;
@Column(nullable = false, unique = true, length = 100)
@Column(nullable = false, length = 200)
private String description;
private Integer releaseDate;
@Column(nullable = false, unique = true, length = 20)
@Column(nullable = false, length = 20)
private String country;
@Column(nullable = false, unique = true, length = 30)
@Column(nullable = false, length = 50)
private String tagline;
@Column(nullable = false, unique = true, length = 30)
@Column(nullable = false, length = 50)
private String director;
@Column(nullable = false, unique = true, length = 100)
@ManyToOne
@JoinColumn(name = "ageRatingId", nullable = false)
private AgeRatingEntity ageRating;
@Column(nullable = false, length = 100)
private String video;
public MovieEntity() {
}
public MovieEntity(Long id, String title, TypeEntity type, boolean requiresSubscription, String poster,
public MovieEntity(String title, TypeEntity type, boolean requiresSubscription, String poster,
String description, Integer releaseDate, String country, String tagline, String director,
AgeRatingEntity ageRating, String video) {
this.title = title;

View File

@ -1,10 +1,32 @@
package com.example.demo.movies.repository;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.PagingAndSortingRepository;
import com.example.demo.core.repository.MapRepository;
import com.example.demo.movies.model.MovieEntity;
@Repository
public class MovieRepository extends MapRepository<MovieEntity> {
public interface MovieRepository
extends CrudRepository<MovieEntity, Long>, PagingAndSortingRepository<MovieEntity, Long> {
Optional<MovieEntity> findByTitleIgnoreCase(String title);
List<MovieEntity> findByTypeId(Long typeId);
Page<MovieEntity> findByTypeId(long typeId, Pageable pageable);
List<MovieEntity> findByAgeRatingId(Long ageRatingId);
Page<MovieEntity> findByAgeRatingId(Long ageRatingId, Pageable pageable);
List<MovieEntity> findByTypeIdAndAgeRatingId(Long typeId, Long ageRatingId);
Page<MovieEntity> findByTypeIdAndAgeRatingId(Long typeId, Long ageRatingId, Pageable pageable);
@Query("SELECT CAST(SUM(r.rate) as double) / COUNT(*) as average_rate FROM MovieEntity as m JOIN ReviewEntity as r ON r.movie.id=m.id WHERE m.id=?1")
Double getAverageRating(long id);
}

View File

@ -1,11 +1,16 @@
package com.example.demo.movies.service;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.StreamSupport;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.example.demo.core.error.AlreadyExistsException;
import com.example.demo.core.error.NotFoundException;
import com.example.demo.movies.model.MovieEntity;
import com.example.demo.movies.repository.MovieRepository;
@ -18,26 +23,60 @@ public class MovieService {
this.repository = repository;
}
public List<MovieEntity> getAll(Long typeId) {
if (Objects.equals(typeId, 0L)) {
return repository.getAll();
private void checkTitleUnique(String title) {
if (repository.findByTitleIgnoreCase(title).isPresent()) {
throw new AlreadyExistsException();
}
return repository.getAll().stream()
.filter(item -> item.getType().getId().equals(typeId))
.toList();
}
@Transactional(readOnly = true)
public List<MovieEntity> getAll(Long typeId, Long ageRatingId) {
if (typeId <= 0L && ageRatingId <= 0L) {
return StreamSupport.stream(repository.findAll().spliterator(), false).toList();
} else if (typeId <= 0L) {
return repository.findByAgeRatingId(ageRatingId);
} else if (ageRatingId <= 0L) {
return repository.findByTypeId(typeId);
}
return repository.findByTypeIdAndAgeRatingId(typeId, ageRatingId);
}
@Transactional(readOnly = true)
public Page<MovieEntity> getAll(Long typeId, Long ageRatingId, int page, int size) {
final Pageable pageRequest = PageRequest.of(page, size);
if (typeId <= 0L && ageRatingId <= 0L) {
return repository.findAll(pageRequest);
} else if (typeId <= 0L) {
return repository.findByAgeRatingId(ageRatingId, pageRequest);
} else if (ageRatingId <= 0L) {
return repository.findByTypeId(typeId, pageRequest);
}
return repository.findByTypeIdAndAgeRatingId(typeId, ageRatingId, pageRequest);
}
@Transactional(readOnly = true)
public MovieEntity get(Long id) {
return Optional.ofNullable(repository.get(id))
.orElseThrow(() -> new NotFoundException(id));
return repository.findById(id)
.orElseThrow(() -> new NotFoundException(MovieEntity.class, id));
}
@Transactional
public MovieEntity create(MovieEntity entity) {
return repository.create(entity);
if (entity == null) {
throw new IllegalArgumentException("Entity is null");
}
checkTitleUnique(entity.getTitle());
return repository.save(entity);
}
@Transactional
public MovieEntity update(Long id, MovieEntity entity) {
final MovieEntity existsEntity = get(id);
existsEntity.setTitle(entity.getTitle());
existsEntity.setType(entity.getType());
existsEntity.setRequiresSubscription(entity.getRequiresSubscription());
@ -49,15 +88,39 @@ public class MovieService {
existsEntity.setDirector(entity.getDirector());
existsEntity.setAgeRating(entity.getAgeRating());
existsEntity.setVideo(entity.getVideo());
return repository.update(existsEntity);
return repository.save(existsEntity);
}
@Transactional
public MovieEntity delete(Long id) {
final MovieEntity existsEntity = get(id);
return repository.delete(existsEntity);
repository.delete(existsEntity);
return existsEntity;
}
@Transactional
public void deleteAll() {
repository.deleteAll();
}
@Transactional
public Double getAverageRating(Long id) {
final MovieEntity existsEntity = get(id);
Double rating = repository.getAverageRating(existsEntity.getId());
if (rating == null) {
return 0D;
}
return rating;
}
@Transactional
public List<MovieEntity> getItemsByIds(List<Long> ids) {
List<MovieEntity> items = new ArrayList<>();
repository.findAllById(ids).forEach(item -> items.add(item));
return items;
}
}

View File

@ -0,0 +1,81 @@
package com.example.demo.reviews.api;
import org.modelmapper.ModelMapper;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.core.api.PageDto;
import com.example.demo.core.api.PageDtoMapper;
import com.example.demo.core.configuration.Constants;
import com.example.demo.reviews.model.ReviewEntity;
import com.example.demo.reviews.service.ReviewService;
import jakarta.validation.Valid;
@RestController
@RequestMapping(Constants.API_URL + "/review")
public class ReviewController {
private final ReviewService reviewService;
private final ModelMapper modelMapper;
public ReviewController(ReviewService reviewService,
ModelMapper modelMapper) {
this.reviewService = reviewService;
this.modelMapper = modelMapper;
}
private ReviewDto toDto(ReviewEntity entity) {
return modelMapper.map(entity, ReviewDto.class);
}
private ReviewEntity toEntity(ReviewDto dto) {
final ReviewEntity entity = modelMapper.map(dto, ReviewEntity.class);
return entity;
}
@GetMapping
public PageDto<ReviewDto> getAll(
@RequestParam(name = "userId") Long userId,
@RequestParam(name = "movieId") Long movieId,
@RequestParam(name = "page", defaultValue = "0") int page,
@RequestParam(name = "size", defaultValue = Constants.DEFAULT_PAGE_SIZE) int size) {
return PageDtoMapper.toDto(reviewService.getAll(movieId, userId, page, size), this::toDto);
}
@GetMapping("/{id}")
public ReviewDto get(
@PathVariable(name = "id") Long id,
@RequestParam(name = "userId") Long userId) {
return toDto(reviewService.get(userId, id));
}
@PostMapping
public ReviewDto create(
@RequestParam(name = "userId") Long userId,
@RequestParam(name = "movieId") Long movieId,
@RequestBody @Valid ReviewDto dto) {
return toDto(reviewService.create(userId, movieId, toEntity(dto)));
}
@PutMapping("/{id}")
public ReviewDto update(
@PathVariable(name = "id") Long id,
@RequestParam(name = "userId") Long userId,
@RequestBody ReviewDto dto) {
return toDto(reviewService.update(userId, id, toEntity(dto)));
}
@DeleteMapping("/{id}")
public ReviewDto delete(
@PathVariable(name = "userId") Long userId,
@PathVariable(name = "id") Long id) {
return toDto(reviewService.delete(userId, id));
}
}

View File

@ -0,0 +1,43 @@
package com.example.demo.reviews.api;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
public class ReviewDto {
private Long id;
private String description;
@NotNull
@Min(1)
@Max(5)
private Integer rate;
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Integer getRate() {
return rate;
}
public void setRate(Integer rate) {
this.rate = rate;
}
}

View File

@ -0,0 +1,87 @@
package com.example.demo.reviews.model;
import java.util.Objects;
import com.example.demo.core.model.BaseEntity;
import com.example.demo.movies.model.MovieEntity;
import com.example.demo.users.model.UserEntity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
@Entity
@Table(name = "reviews")
public class ReviewEntity extends BaseEntity {
@ManyToOne
@JoinColumn(name = "userId", nullable = false)
private UserEntity user;
@ManyToOne
@JoinColumn(name = "movieId", nullable = false)
private MovieEntity movie;
@Column(nullable = false)
private String description;
@Column(nullable = false)
private Integer rate;
public ReviewEntity() {
}
public ReviewEntity(String description, Integer rate) {
this.description = description;
this.rate = rate;
}
public UserEntity getUser() {
return user;
}
public void setUser(UserEntity user) {
this.user = user;
}
public MovieEntity getMovie() {
return movie;
}
public void setMovie(MovieEntity movie) {
this.movie = movie;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Integer getRate() {
return rate;
}
public void setRate(Integer rate) {
this.rate = rate;
}
@Override
public int hashCode() {
return Objects.hash(id, user, movie, description, rate);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null || getClass() != obj.getClass())
return false;
final ReviewEntity other = (ReviewEntity) obj;
return Objects.equals(other.getId(), id)
&& Objects.equals(other.getUser(), user)
&& Objects.equals(other.getMovie(), movie)
&& Objects.equals(other.getDescription(), description)
&& Objects.equals(other.getRate(), rate);
}
}

View File

@ -0,0 +1,30 @@
package com.example.demo.reviews.repository;
import com.example.demo.reviews.model.ReviewEntity;
import java.util.List;
import java.util.Optional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.PagingAndSortingRepository;
public interface ReviewRepository
extends CrudRepository<ReviewEntity, Long>, PagingAndSortingRepository<ReviewEntity, Long> {
List<ReviewEntity> findByUserId(long userId);
Page<ReviewEntity> findByUserId(long userId, Pageable pageable);
List<ReviewEntity> findByMovieId(long movieId);
Page<ReviewEntity> findByMovieId(long movieId, Pageable pageable);
Optional<ReviewEntity> findOneByUserIdAndId(long userId, long id);
Optional<ReviewEntity> findOneByUserIdAndMovieId(long userId, long movieId);
List<ReviewEntity> findByUserIdAndMovieId(long userId, long movieId);
Page<ReviewEntity> findByUserIdAndMovieId(long userId, long movieId, Pageable pageable);
}

View File

@ -0,0 +1,110 @@
package com.example.demo.reviews.service;
import java.util.List;
import java.util.stream.StreamSupport;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.example.demo.core.error.AlreadyExistsException;
import com.example.demo.core.error.NotFoundException;
import com.example.demo.movies.model.MovieEntity;
import com.example.demo.movies.service.MovieService;
import com.example.demo.reviews.model.ReviewEntity;
import com.example.demo.reviews.repository.ReviewRepository;
import com.example.demo.users.model.UserEntity;
import com.example.demo.users.service.UserService;
@Service
public class ReviewService {
private final ReviewRepository repository;
private final UserService userService;
private final MovieService movieService;
public ReviewService(ReviewRepository repository, UserService userService, MovieService movieService) {
this.repository = repository;
this.userService = userService;
this.movieService = movieService;
}
private void checkReview(Long userId, Long movieId) {
if (repository.findByUserIdAndMovieId(userId, movieId).size() == 1) {
throw new AlreadyExistsException();
}
}
@Transactional(readOnly = true)
public List<ReviewEntity> getAll(Long movieId, Long userId) {
if (movieId <= 0L && userId <= 0L) {
return StreamSupport.stream(repository.findAll().spliterator(), false).toList();
}
if (userId <= 0L && movieId > 0L) {
return repository.findByMovieId(movieId);
}
if (movieId <= 0L && userId > 0L) {
return repository.findByUserId(userId);
} else {
return repository.findByUserIdAndMovieId(userId, movieId);
}
}
@Transactional(readOnly = true)
public Page<ReviewEntity> getAll(Long movieId, Long userId, int page, int size) {
final Pageable pageRequest = PageRequest.of(page, size);
if (movieId <= 0L && userId <= 0L) {
return repository.findAll(pageRequest);
}
if (userId <= 0L && movieId > 0L) {
return repository.findByMovieId(movieId, pageRequest);
}
if (movieId <= 0L && userId > 0L) {
return repository.findByUserId(userId, pageRequest);
} else {
return repository.findByUserIdAndMovieId(userId, movieId, pageRequest);
}
}
@Transactional(readOnly = true)
public ReviewEntity get(Long userId, Long id) {
userService.get(userId);
return repository.findOneByUserIdAndId(userId, id)
.orElseThrow(() -> new NotFoundException(ReviewEntity.class, id));
}
@Transactional
public ReviewEntity create(long userId, long movieId, ReviewEntity entity) {
checkReview(userId, movieId);
final UserEntity existsUser = userService.get(userId);
final MovieEntity existsmovie = movieService.get(movieId);
entity.setMovie(existsmovie);
entity.setUser(existsUser);
return repository.save(entity);
}
@Transactional
public ReviewEntity update(Long userId, Long id, ReviewEntity entity) {
final ReviewEntity existsEntity = get(userId, id);
existsEntity.setDescription(entity.getDescription());
existsEntity.setRate(entity.getRate());
return repository.save(existsEntity);
}
@Transactional
public ReviewEntity delete(Long userId, Long id) {
final ReviewEntity existsEntity = get(userId, id);
repository.delete(existsEntity);
return existsEntity;
}
public void deleteAll() {
repository.deleteAll();
}
}

View File

@ -0,0 +1,68 @@
package com.example.demo.subscriptions.api;
import java.util.List;
import org.modelmapper.ModelMapper;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.core.configuration.Constants;
import com.example.demo.subscriptions.model.SubscriptionEntity;
import com.example.demo.subscriptions.service.SubscriptionService;
import jakarta.validation.Valid;
@RestController
@RequestMapping(Constants.API_URL + "/subsciption")
public class SubscriptionController {
private final SubscriptionService subscriptionService;
private final ModelMapper modelMapper;
public SubscriptionController(SubscriptionService subscriptionService, ModelMapper modelMapper) {
this.subscriptionService = subscriptionService;
this.modelMapper = modelMapper;
}
private SubscriptionDto toDto(SubscriptionEntity entity) {
return modelMapper.map(entity, SubscriptionDto.class);
}
private SubscriptionEntity toEntity(SubscriptionDto dto) {
return modelMapper.map(dto, SubscriptionEntity.class);
}
@GetMapping
public List<SubscriptionDto> getAll() {
return subscriptionService.getAll().stream()
.map(this::toDto)
.toList();
}
@GetMapping("/{id}")
public SubscriptionDto get(@PathVariable(name = "id") Long id) {
return toDto(subscriptionService.get(id));
}
@PostMapping
public SubscriptionDto create(@RequestBody @Valid SubscriptionDto dto) {
return toDto(subscriptionService.create(toEntity(dto)));
}
@PutMapping("/{id}")
public SubscriptionDto update(
@PathVariable(name = "id") Long id,
@RequestBody @Valid SubscriptionDto dto) {
return toDto(subscriptionService.update(id, toEntity(dto)));
}
@DeleteMapping("/{id}")
public SubscriptionDto delete(@PathVariable(name = "id") Long id) {
return toDto(subscriptionService.delete(id));
}
}

View File

@ -0,0 +1,55 @@
package com.example.demo.subscriptions.api;
import java.time.Period;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
public class SubscriptionDto {
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
private Long id;
@NotBlank
@Size(min = 5, max = 50)
private String name;
@NotBlank
private Period duration;
@NotBlank
private Double price;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Period getDuration() {
return duration;
}
public void setDuration(Period duration) {
this.duration = duration;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
}

View File

@ -0,0 +1,74 @@
package com.example.demo.subscriptions.model;
import java.time.Period;
import java.util.Objects;
import com.example.demo.core.model.BaseEntity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
@Entity
@Table(name = "subscriptions")
public class SubscriptionEntity extends BaseEntity {
@Column(nullable = false, unique = true, length = 50)
private String name;
@Column(nullable = false, unique = true)
private Period duration;
@Column(nullable = false)
private Double price;
public SubscriptionEntity() {
}
public SubscriptionEntity(String name, Period duration, Double price) {
this.name = name;
this.duration = duration;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Period getDuration() {
return duration;
}
public void setDuration(Period duration) {
this.duration = duration;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
@Override
public int hashCode() {
return Objects.hash(id, name, duration, price);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null || getClass() != obj.getClass())
return false;
SubscriptionEntity other = (SubscriptionEntity) obj;
return Objects.equals(id, other.id)
&& Objects.equals(name, other.name)
&& Objects.equals(duration, other.duration)
&& Objects.equals(price, other.price);
}
}

View File

@ -0,0 +1,11 @@
package com.example.demo.subscriptions.repository;
import java.util.Optional;
import org.springframework.data.repository.CrudRepository;
import com.example.demo.subscriptions.model.SubscriptionEntity;
public interface SubscriptionRepository extends CrudRepository<SubscriptionEntity, Long> {
Optional<SubscriptionEntity> findByNameIgnoreCase(String name);
}

View File

@ -0,0 +1,70 @@
package com.example.demo.subscriptions.service;
import java.util.List;
import java.util.stream.StreamSupport;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.example.demo.core.error.NotFoundException;
import com.example.demo.subscriptions.model.SubscriptionEntity;
import com.example.demo.subscriptions.repository.SubscriptionRepository;
@Service
public class SubscriptionService {
private final SubscriptionRepository repository;
public SubscriptionService(SubscriptionRepository repository) {
this.repository = repository;
}
private void checkName(String name) {
if (repository.findByNameIgnoreCase(name).isPresent()) {
throw new IllegalArgumentException(
String.format("Subscription with name %s is already exists", name));
}
}
@Transactional(readOnly = true)
public List<SubscriptionEntity> getAll() {
return StreamSupport.stream(repository.findAll().spliterator(), false).toList();
}
@Transactional(readOnly = true)
public SubscriptionEntity get(long id) {
return repository.findById(id)
.orElseThrow(() -> new NotFoundException(SubscriptionEntity.class, id));
}
@Transactional
public SubscriptionEntity create(SubscriptionEntity entity) {
if (entity == null) {
throw new IllegalArgumentException("Entity is null");
}
checkName(entity.getName());
return repository.save(entity);
}
@Transactional
public SubscriptionEntity update(Long id, SubscriptionEntity entity) {
final SubscriptionEntity existsEntity = get(id);
checkName(entity.getName());
existsEntity.setName(entity.getName());
existsEntity.setDuration(entity.getDuration());
existsEntity.setPrice(existsEntity.getPrice());
return repository.save(existsEntity);
}
@Transactional
public SubscriptionEntity delete(Long id) {
final SubscriptionEntity existsEntity = get(id);
repository.delete(existsEntity);
return existsEntity;
}
@Transactional
public void deleteAll() {
repository.deleteAll();
}
}

View File

@ -53,7 +53,7 @@ public class TypeController {
}
@PutMapping("/{id}")
public TypeDto update(@PathVariable(name = "id") Long id, @RequestBody TypeDto dto) {
public TypeDto update(@PathVariable(name = "id") Long id, @RequestBody @Valid TypeDto dto) {
return toDto(typeService.update(id, toEntity(dto)));
}

View File

@ -3,14 +3,16 @@ package com.example.demo.types.api;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
public class TypeDto {
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
private Long id;
@NotBlank
@Size(min = 3, max = 20)
private String name;
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
public Long getId() {
return id;
}

View File

@ -6,6 +6,7 @@ import java.util.stream.StreamSupport;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.example.demo.core.error.AlreadyExistsException;
import com.example.demo.core.error.NotFoundException;
import com.example.demo.types.model.TypeEntity;
import com.example.demo.types.repository.TypeRepository;
@ -18,6 +19,12 @@ public class TypeService {
this.repository = repository;
}
private void checkNameUnique(String name) {
if (repository.findByNameIgnoreCase(name).isPresent()) {
throw new AlreadyExistsException();
}
}
@Transactional(readOnly = true)
public List<TypeEntity> getAll() {
return StreamSupport.stream(repository.findAll().spliterator(), false).toList();
@ -35,6 +42,7 @@ public class TypeService {
throw new IllegalArgumentException("Entity is null");
}
checkNameUnique(entity.getName());
return repository.save(entity);
}
@ -42,6 +50,7 @@ public class TypeService {
public TypeEntity update(Long id, TypeEntity entity) {
final TypeEntity existsEntity = get(id);
checkNameUnique(entity.getName());
existsEntity.setName(entity.getName());
return repository.save(existsEntity);
}
@ -54,6 +63,7 @@ public class TypeService {
return existsEntity;
}
@Transactional
public void deleteAll() {
repository.deleteAll();
}

View File

@ -1,6 +1,8 @@
package com.example.demo.users.api;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import org.modelmapper.ModelMapper;
import org.springframework.web.bind.annotation.DeleteMapping;
@ -10,13 +12,19 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.movies.api.MovieDto;
import com.example.demo.core.api.PageDto;
import com.example.demo.core.api.PageDtoMapper;
import com.example.demo.core.configuration.Constants;
import com.example.demo.movies.model.MovieEntity;
import com.example.demo.movies.service.MovieService;
import com.example.demo.users.model.UserEntity;
import com.example.demo.users.service.UserService;
import com.example.demo.usersubscription.api.SubscriptionInfoDto;
import com.example.demo.usersubscription.model.UserSubscriptionEntity;
import jakarta.validation.Valid;
@ -25,13 +33,11 @@ import jakarta.validation.Valid;
public class UserController {
private final UserService userService;
private final MovieService movieService;
private final ModelMapper modelMapper;
public UserController(UserService userService, MovieService movieService, ModelMapper modelMapper) {
this.userService = userService;
this.movieService = movieService;
this.modelMapper = modelMapper;
}
@ -39,13 +45,28 @@ public class UserController {
return modelMapper.map(entity, UserDto.class);
}
private SubscriptionInfoDto toSubscriptionDto(UserSubscriptionEntity entity) {
if (!Objects.isNull(entity)) {
return new SubscriptionInfoDto(entity.getExpirationDate().after(new Date()), entity.getActivationDate(),
entity.getExpirationDate());
} else {
return new SubscriptionInfoDto(false, null, null);
}
}
private MovieDto toMovieDto(MovieEntity entity) {
return modelMapper.map(entity, MovieDto.class);
}
private UserEntity toEntity(UserDto dto) {
return modelMapper.map(dto, UserEntity.class);
}
@GetMapping
public List<UserDto> getAll() {
return userService.getAll().stream().map(this::toDto).toList();
public PageDto<UserDto> getAll(
@RequestParam(name = "page", defaultValue = "0") int page,
@RequestParam(name = "size", defaultValue = Constants.DEFAULT_PAGE_SIZE) int size) {
return PageDtoMapper.toDto(userService.getAll(page, size), this::toDto);
}
@GetMapping("/{id}")
@ -68,12 +89,48 @@ public class UserController {
return toDto(userService.delete(id));
}
@PutMapping("/{id}/movie/{movieId}")
public UserDto addMovie(@PathVariable(name = "id") Long id, @RequestBody UserDto dto,
@PathVariable(name = "movieId") Long movieId) {
MovieEntity movie = movieService.get(movieId);
userService.addMovie(id, movie.getId());
@GetMapping("/{id}/subscription")
public SubscriptionInfoDto getActiveSubscription(@PathVariable(name = "id") Long id) {
return toSubscriptionDto(userService.getActiveSubscription(id));
}
return toDto(userService.update(id, toEntity(dto)));
@PostMapping("/{id}/subscription/all")
public List<SubscriptionInfoDto> getAllSubscriptions(@PathVariable(name = "id") Long id) {
return userService.getUserSubscriptions(id).stream().map(this::toSubscriptionDto).toList();
}
@PostMapping("/{id}/subscription")
public SubscriptionInfoDto activateSubscription(
@PathVariable(name = "id") Long id,
@RequestParam(name = "subscriptionId", defaultValue = "") Long subscriptionId) {
return toSubscriptionDto(userService.activateSubscription(id, subscriptionId));
}
@DeleteMapping("/{id}/subscription")
public SubscriptionInfoDto deactivateSubscription(@PathVariable(name = "id") Long id) {
return toSubscriptionDto(userService.deactivateSubscription(id));
}
@GetMapping("/{id}/watchLater")
public List<MovieDto> getWatchLater(@PathVariable(name = "id") Long id) {
return userService.getWatchLater(id).stream().map(this::toMovieDto).toList();
}
@PostMapping("/{id}/watchLater")
public UserDto addToWatchLater(@PathVariable(name = "id") Long id,
@RequestParam(name = "movieId", defaultValue = "") Long movieId) {
MovieEntity movie = movieService.get(movieId);
UserEntity user = userService.addMovieToWatchLater(id, movie);
return toDto(user);
}
@DeleteMapping("/{id}/watchLater")
public UserDto deleteFromWatchLater(@PathVariable(name = "id") Long id,
@RequestParam(name = "movieId", defaultValue = "") Long movieId) {
MovieEntity movie = movieService.get(movieId);
UserEntity user = userService.deleteMovieFromWatchLater(id, movie);
return toDto(user);
}
}

View File

@ -1,29 +1,26 @@
package com.example.demo.users.api;
import java.util.Date;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonProperty.Access;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
public class UserDto {
@JsonProperty(access = Access.READ_ONLY)
private Long id;
@NotNull
@NotBlank
@Size(min = 5, max = 30)
private String email;
@NotNull
@NotBlank
@Size(min = 5, max = 30)
private String password;
private Date expirationDate;
private List<Long> watchLater;
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
public Long getId() {
return id;
}
@ -47,20 +44,4 @@ public class UserDto {
public void setPassword(String password) {
this.password = password;
}
public Date getExpirationDate() {
return expirationDate;
}
public void setExpirationDate(Date expirationDate) {
this.expirationDate = expirationDate;
}
public List<Long> getWatchLater() {
return watchLater;
}
public void setWatchLater(List<Long> watchLater) {
this.watchLater = watchLater;
}
}

View File

@ -1,28 +1,49 @@
package com.example.demo.users.model;
import java.util.Date;
import java.util.List;
import java.util.HashSet;
import java.util.Collections;
import java.util.Set;
import java.util.Objects;
import java.util.Optional;
import com.example.demo.core.model.BaseEntity;
import com.example.demo.movies.model.MovieEntity;
import com.example.demo.usersubscription.model.UserSubscriptionEntity;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.JoinTable;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OrderBy;
import jakarta.persistence.Table;
@Entity
@Table(name = "users")
public class UserEntity extends BaseEntity {
@Column(nullable = false, unique = true, length = 30)
private String email;
@Column(nullable = false, length = 30)
private String password;
private Date expirationDate;
private List<Long> watchLater;
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
@OrderBy("id ASC")
private Set<UserSubscriptionEntity> userSubscriptions = new HashSet<>();
@ManyToMany()
@JoinTable(name = "user_movie", joinColumns = @JoinColumn(name = "userId"), inverseJoinColumns = @JoinColumn(name = "movieId"))
@OrderBy("id ASC")
private Set<MovieEntity> watchLater = new HashSet<>();
public UserEntity() {
super();
}
public UserEntity(Long id, String email, String password, Date expirationDate, List<Long> watchLater) {
super(id);
public UserEntity(String email, String password) {
this.email = email;
this.password = password;
this.expirationDate = expirationDate;
this.watchLater = watchLater;
}
public String getEmail() {
@ -41,25 +62,46 @@ public class UserEntity extends BaseEntity {
this.password = password;
}
public Date getExpirationDate() {
return expirationDate;
public Set<UserSubscriptionEntity> getUserSubscriptions() {
return userSubscriptions;
}
public void setExpirationDate(Date expirationDate) {
this.expirationDate = expirationDate;
public void addSubscription(UserSubscriptionEntity userSubscription) {
if (userSubscription.getUser() != this) {
userSubscription.setUser(this);
}
userSubscriptions.add(userSubscription);
}
public List<Long> getWatchLater() {
public void deleteSubscription(UserSubscriptionEntity userSubscription) {
if (userSubscription.getUser() != this) {
return;
}
userSubscriptions.remove(userSubscription);
}
public Set<MovieEntity> getWatchLater() {
return watchLater;
}
public void setWatchLater(List<Long> watchLater) {
this.watchLater = watchLater;
public void setWatchLater(Set<MovieEntity> watchLater) {
Set<MovieEntity> newWatchLater = new HashSet<>();
newWatchLater.addAll(watchLater);
this.watchLater.clear();
this.watchLater.addAll(Optional.ofNullable(newWatchLater).orElse(Collections.emptySet()));
}
public void addMovieToWatchLater(MovieEntity movie) {
watchLater.add(movie);
}
public void deleteMovieFromWatchLater(MovieEntity movie) {
watchLater.remove(movie);
}
@Override
public int hashCode() {
return Objects.hash(id, email, password, expirationDate, watchLater);
return Objects.hash(id, email, password, userSubscriptions, watchLater);
}
@Override
@ -71,8 +113,6 @@ public class UserEntity extends BaseEntity {
final UserEntity other = (UserEntity) obj;
return Objects.equals(other.getId(), id)
&& Objects.equals(other.getEmail(), email)
&& Objects.equals(other.getPassword(), password)
&& Objects.equals(other.getExpirationDate(), expirationDate)
&& Objects.equals(other.getWatchLater(), watchLater);
&& Objects.equals(other.getPassword(), password);
}
}

View File

@ -1,10 +1,20 @@
package com.example.demo.users.repository;
import org.springframework.stereotype.Repository;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.Param;
import com.example.demo.core.repository.MapRepository;
import com.example.demo.users.model.UserEntity;
import com.example.demo.usersubscription.model.UserSubscriptionEntity;
@Repository
public class UserRepository extends MapRepository<UserEntity> {
public interface UserRepository extends CrudRepository<UserEntity, Long>, PagingAndSortingRepository<UserEntity, Long> {
Optional<UserEntity> findByEmailIgnoreCase(String login);
@Query("SELECT us FROM UserSubscriptionEntity us WHERE us.user.id = :userId AND us.expirationDate > :now")
List<UserSubscriptionEntity> getActiveSubscriptions(@Param("userId") Long userId, @Param("now") Date now);
}

View File

@ -1,61 +1,167 @@
package com.example.demo.users.service;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.Objects;
import java.util.stream.StreamSupport;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.example.demo.users.model.UserEntity;
import com.example.demo.users.repository.UserRepository;
import com.example.demo.usersubscription.model.UserSubscriptionEntity;
import com.example.demo.core.error.NotFoundException;
import com.example.demo.movies.model.MovieEntity;
import com.example.demo.movies.service.MovieService;
import com.example.demo.subscriptions.model.SubscriptionEntity;
import com.example.demo.subscriptions.service.SubscriptionService;
@Service
public class UserService {
private final UserRepository repository;
private final MovieService movieService;
private final SubscriptionService subscriptionService;
public UserService(UserRepository repository, MovieService movieService) {
this.movieService = movieService;
public UserService(UserRepository repository, SubscriptionService subscriptionService) {
this.repository = repository;
this.subscriptionService = subscriptionService;
}
private void checkEmail(String email) {
if (repository.findByEmailIgnoreCase(email).isPresent()) {
throw new IllegalArgumentException(
String.format("User with email %s is already exists", email));
}
}
@Transactional(readOnly = true)
public List<UserEntity> getAll() {
return repository.getAll();
return StreamSupport.stream(repository.findAll().spliterator(), false).toList();
}
@Transactional(readOnly = true)
public Page<UserEntity> getAll(int page, int size) {
final Pageable pageRequest = PageRequest.of(page, size);
return repository.findAll(pageRequest);
}
@Transactional(readOnly = true)
public UserEntity get(Long id) {
return Optional.ofNullable(repository.get(id))
.orElseThrow(() -> new NotFoundException(id));
return repository.findById(id)
.orElseThrow(() -> new NotFoundException(UserEntity.class, id));
}
@Transactional
public UserEntity create(UserEntity entity) {
return repository.create(entity);
if (entity == null) {
throw new IllegalArgumentException("Entity is null");
}
checkEmail(entity.getEmail());
repository.save(entity);
return repository.save(entity);
}
public UserEntity update(Long id, UserEntity entity) {
@Transactional
public UserEntity update(long id, UserEntity entity) {
final UserEntity existsEntity = get(id);
checkEmail(entity.getEmail());
existsEntity.setEmail(entity.getEmail());
return repository.update(existsEntity);
existsEntity.setPassword(entity.getPassword());
return repository.save(existsEntity);
}
public UserEntity delete(Long id) {
@Transactional
public UserEntity delete(long id) {
final UserEntity existsEntity = get(id);
return repository.delete(existsEntity);
repository.delete(existsEntity);
return existsEntity;
}
@Transactional
public void deleteAll() {
repository.deleteAll();
}
public UserEntity addMovie(Long id, Long movieId) {
@Transactional(readOnly = true)
public List<UserSubscriptionEntity> getUserSubscriptions(Long id) {
return get(id).getUserSubscriptions().stream().toList();
}
@Transactional(readOnly = true)
public UserSubscriptionEntity getActiveSubscription(Long id) {
List<UserSubscriptionEntity> activeSubscriptions = repository.getActiveSubscriptions(id, new Date());
if (activeSubscriptions.size() != 1) {
return null;
}
return activeSubscriptions.get(0);
}
@Transactional()
public UserSubscriptionEntity activateSubscription(Long id, Long subscriptionId) {
UserSubscriptionEntity activeSubscription = getActiveSubscription(id);
if (!Objects.isNull(activeSubscription)) {
return activeSubscription;
}
final UserEntity existsUser = get(id);
final SubscriptionEntity subscription = subscriptionService.get(subscriptionId);
Date now = new Date();
Date expirationDate = Date
.from(now.toInstant().atZone(ZoneId.systemDefault()).plus(subscription.getDuration()).toInstant());
final UserSubscriptionEntity newUserSubscription = new UserSubscriptionEntity(existsUser, subscription, now,
expirationDate);
newUserSubscription.setUser(existsUser);
repository.save(existsUser);
return newUserSubscription;
}
@Transactional
public UserSubscriptionEntity deactivateSubscription(Long id) {
UserSubscriptionEntity subscriptionToDeactivate = getActiveSubscription(id);
if (Objects.isNull(subscriptionToDeactivate)) {
return null;
}
final UserEntity existsUser = get(id);
subscriptionToDeactivate.setExpirationDate(new Date());
repository.save(existsUser);
return subscriptionToDeactivate;
}
@Transactional(readOnly = true)
public List<MovieEntity> getWatchLater(long id) {
return get(id).getWatchLater().stream().toList();
}
@Transactional
public UserEntity addMovieToWatchLater(Long id, MovieEntity movie) {
final UserEntity existsEntity = get(id);
MovieEntity movie = movieService.get(movieId);
if (!existsEntity.getWatchLater().contains(movie)) {
existsEntity.addMovieToWatchLater(movie);
return repository.save(existsEntity);
}
if (!existsEntity.getWatchLater().contains(movie.getId())) {
existsEntity.getWatchLater().add(movie.getId());
return existsEntity;
}
@Transactional
public UserEntity deleteMovieFromWatchLater(Long id, MovieEntity movie) {
final UserEntity existsEntity = get(id);
if (existsEntity.getWatchLater().contains(movie)) {
existsEntity.deleteMovieFromWatchLater(movie);
return repository.save(existsEntity);
}
return existsEntity;

View File

@ -0,0 +1,34 @@
package com.example.demo.usersubscription.api;
import java.util.Date;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
public class SubscriptionInfoDto {
@NotNull
@NotBlank
private boolean isActive;
Date activationDate;
Date expirationDate;
public SubscriptionInfoDto(boolean isActive, Date activationDate, Date expirationDate) {
this.isActive = isActive;
this.activationDate = activationDate;
this.expirationDate = expirationDate;
}
public boolean getIsActive() {
return isActive;
}
public Date getActivationDate() {
return activationDate;
}
public Date getExpirationDate() {
return expirationDate;
}
}

View File

@ -0,0 +1,98 @@
package com.example.demo.usersubscription.model;
import java.util.Date;
import java.util.Objects;
import com.example.demo.core.model.BaseEntity;
import com.example.demo.subscriptions.model.SubscriptionEntity;
import com.example.demo.users.model.UserEntity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
@Entity
@Table(name = "users_subscriptions")
public class UserSubscriptionEntity extends BaseEntity {
@ManyToOne
@JoinColumn(name = "user_id", nullable = false)
private UserEntity user;
@ManyToOne
@JoinColumn(name = "subscription_id", nullable = false)
private SubscriptionEntity subscription;
@Column(nullable = false)
private Date activationDate;
@Column(nullable = false)
private Date expirationDate;
public UserSubscriptionEntity() {
}
public UserSubscriptionEntity(UserEntity user, SubscriptionEntity subscription, Date activationDate,
Date expirationDate) {
this.user = user;
this.subscription = subscription;
this.activationDate = activationDate;
this.expirationDate = expirationDate;
}
public UserEntity getUser() {
return user;
}
public void setUser(UserEntity user) {
this.user = user;
if (!user.getUserSubscriptions().contains(this)) {
user.getUserSubscriptions().add(this);
}
}
public SubscriptionEntity getSubscription() {
return subscription;
}
public void setSubscription(SubscriptionEntity subscription) {
this.subscription = subscription;
}
public Date getExpirationDate() {
return expirationDate;
}
public void setExpirationDate(Date expirationDate) {
this.expirationDate = expirationDate;
}
public Date getActivationDate() {
return activationDate;
}
public void setActivationDate(Date activationDate) {
this.activationDate = activationDate;
}
@Override
public int hashCode() {
return Objects.hash(id, user.getId(), subscription.getId(), activationDate, expirationDate);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null || getClass() != obj.getClass())
return false;
UserSubscriptionEntity other = (UserSubscriptionEntity) obj;
return Objects.equals(id, other.id)
&& Objects.equals(user.getId(), other.user.getId())
&& Objects.equals(subscription.getId(), other.subscription.getId())
&& Objects.equals(activationDate, other.activationDate)
&& Objects.equals(expirationDate, other.expirationDate);
}
}

View File

@ -1,15 +1,18 @@
package com.example.demo;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.dao.DataIntegrityViolationException;
import com.example.demo.ageRatings.model.AgeRatingEntity;
import com.example.demo.ageRatings.service.AgeRatingService;
import com.example.demo.core.error.AlreadyExistsException;
import com.example.demo.core.error.NotFoundException;
@SpringBootTest
@ -18,48 +21,64 @@ class AgeRatingServiceTests {
@Autowired
private AgeRatingService ageRatingService;
private AgeRatingEntity ageRating;
@BeforeEach
void createData() {
removeData();
ageRating = ageRatingService.create(new AgeRatingEntity("12+"));
ageRatingService.create(new AgeRatingEntity("16+"));
ageRatingService.create(new AgeRatingEntity("18+"));
}
@AfterEach
void removeData() {
ageRatingService.getAll().forEach(item -> ageRatingService.delete(item.getId()));
}
@Test
void getTest() {
Assertions.assertThrows(NotFoundException.class, () -> ageRatingService.get(0L));
}
@Test
@Order(1)
void createTest() {
ageRatingService.deleteAll();
ageRatingService.create(new AgeRatingEntity(null, "12+"));
ageRatingService.create(new AgeRatingEntity(null, "16+"));
final AgeRatingEntity last = ageRatingService.create(new AgeRatingEntity(null, "18+"));
Assertions.assertEquals(3, ageRatingService.getAll().size());
Assertions.assertEquals(last, ageRatingService.get(3L));
Assertions.assertEquals(ageRating, ageRatingService.get(ageRating.getId()));
}
@Test
void createNotUniqueTest() {
final AgeRatingEntity nonUniqueAgeRating = new AgeRatingEntity("16+");
Assertions.assertThrows(AlreadyExistsException.class, () -> ageRatingService.create(nonUniqueAgeRating));
}
@Test
void createNullableTest() {
final AgeRatingEntity nullableType = new AgeRatingEntity(null);
Assertions.assertThrows(DataIntegrityViolationException.class, () -> ageRatingService.create(nullableType));
}
@Test
@Order(2)
void updateTest() {
final String test = "TEST";
final AgeRatingEntity entity = ageRatingService.get(3L);
final String oldName = entity.getName();
final AgeRatingEntity newEntity = ageRatingService.update(3L, new AgeRatingEntity(2L, test));
final String oldName = ageRating.getName();
final AgeRatingEntity newEntity = ageRatingService.update(ageRating.getId(), new AgeRatingEntity(test));
Assertions.assertEquals(3, ageRatingService.getAll().size());
Assertions.assertEquals(newEntity, ageRatingService.get(3L));
Assertions.assertEquals(newEntity, ageRatingService.get(ageRating.getId()));
Assertions.assertEquals(test, newEntity.getName());
Assertions.assertNotEquals(oldName, newEntity.getName());
}
@Test
@Order(3)
void deleteTest() {
ageRatingService.delete(3L);
ageRatingService.delete(ageRating.getId());
Assertions.assertEquals(2, ageRatingService.getAll().size());
final AgeRatingEntity last = ageRatingService.get(2L);
Assertions.assertEquals(2L, last.getId());
final AgeRatingEntity newEntity = ageRatingService.create(new AgeRatingEntity(null, "18+"));
final AgeRatingEntity newEntity = ageRatingService.create(new AgeRatingEntity("12+"));
Assertions.assertEquals(3, ageRatingService.getAll().size());
Assertions.assertEquals(4L, newEntity.getId());
Assertions.assertNotEquals(ageRating.getId(), newEntity.getId());
}
}

View File

@ -1,15 +1,18 @@
package com.example.demo;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.dao.DataIntegrityViolationException;
import com.example.demo.ageRatings.model.AgeRatingEntity;
import com.example.demo.ageRatings.service.AgeRatingService;
import com.example.demo.core.error.AlreadyExistsException;
import com.example.demo.core.error.NotFoundException;
import com.example.demo.movies.model.MovieEntity;
import com.example.demo.movies.service.MovieService;
@ -28,82 +31,108 @@ class MovieServiceTests {
@Autowired
private MovieService movieService;
private TypeEntity type1;
private TypeEntity type2;
private AgeRatingEntity ageRating1;
private AgeRatingEntity ageRating2;
private MovieEntity last;
@BeforeEach
void createData() {
removeData();
type1 = typeService.create(new TypeEntity("Фильм"));
type2 = typeService.create(new TypeEntity("Сериал"));
ageRating1 = ageRatingService.create(new AgeRatingEntity("16+"));
ageRating2 = ageRatingService.create(new AgeRatingEntity("18+"));
movieService.create(new MovieEntity("Бойцовский клуб", type1, false,
"src/assets/main-page/posters/PeakyBlinders.png",
"Сотрудник страховой компании страдает хронической бессонницей...",
1999, "США", "Интриги. Хаос. Мыло", "Дэвид Финчер", ageRating2,
"https://www.youtube.com/embed/dfeUzm6KF4g?si=U2D-2WNsJzkcxlBX"));
movieService.create(new MovieEntity("Американский психопат", type1, true,
"src/assets/main-page/posters/AmericanPsycho.jpg",
"Днем он ничем не отличается от окружающих, и в толпе вы не обратите на него внимания...",
2000, "США, Канада", "Респектабельная внешность дьявола", "Мэри Хэррон", ageRating2,
"https://www.youtube.com/embed/PpUWjff_OcM?si=e7tSm4V6qYkz406B"));
last = movieService.create(new MovieEntity("Острые козырьки", type2, false,
"src/assets/main-page/posters/PeakyBlinders.png",
"Сериал рассказывает историю восхождения одной ирландской семьи...",
2013, "Великобритания", "The streets are theirs", "Энтони Бирн, Колм МакКарти", ageRating1,
"https://www.youtube.com/embed/7cOfn_sjlXM?si=fxNoZjlUon1SZd70"));
}
@AfterEach
void removeData() {
movieService.deleteAll();
typeService.deleteAll();
ageRatingService.deleteAll();
}
@Test
void getTest() {
Assertions.assertThrows(NotFoundException.class, () -> movieService.get(0L));
}
@Test
@Order(1)
void createTest() {
movieService.deleteAll();
final var type1 = typeService.create(new TypeEntity(null, "Фильм"));
final var type2 = typeService.create(new TypeEntity(null, "Сериал"));
final var ageRating4 = ageRatingService.create(new AgeRatingEntity(null, "16+"));
final var ageRating5 = ageRatingService.create(new AgeRatingEntity(null, "18+"));
movieService.create(new MovieEntity(null, "Бойцовский клуб", type1, false,
"src/assets/main-page/posters/PeakyBlinders.png",
"Сотрудник страховой компании страдает хронической бессонницей и отчаянно пытается вырваться из мучительно скучной жизни...",
1999, "США", "Интриги. Хаос. Мыло", "Дэвид Финчер", ageRating5,
"https://www.youtube.com/embed/dfeUzm6KF4g?si=U2D-2WNsJzkcxlBX"));
movieService.create(new MovieEntity(null, "Американский психопат", type1, true,
"src/assets/main-page/posters/AmericanPsycho.jpg",
"Днем он ничем не отличается от окружающих, и в толпе вы не обратите на него внимания...",
2000, "США, Канада", "Респектабельная внешность дьявола", "Мэри Хэррон", ageRating5,
"https://www.youtube.com/embed/PpUWjff_OcM?si=e7tSm4V6qYkz406B"));
final MovieEntity last = movieService.create(new MovieEntity(null, "Острые козырьки", type2, false,
"src/assets/main-page/posters/PeakyBlinders.png",
"Сериал рассказывает историю восхождения одной ирландской семьи...",
2013, "Великобритания", "The streets are theirs", "Энтони Бирн, Колм МакКарти", ageRating4,
"https://www.youtube.com/embed/7cOfn_sjlXM?si=fxNoZjlUon1SZd70"));
Assertions.assertEquals(3, movieService.getAll(0L).size());
Assertions.assertEquals(2, movieService.getAll(1L).size());
Assertions.assertEquals(last, movieService.get(3L));
Assertions.assertEquals(3, movieService.getAll(0L, 0L).size());
Assertions.assertEquals(2, movieService.getAll(type1.getId(), 0L).size());
Assertions.assertEquals(last, movieService.get(last.getId()));
}
@Test
@Order(2)
void updateTest() {
final var type2 = typeService.create(new TypeEntity(null, "Сериал"));
final var ageRating4 = ageRatingService.create(new AgeRatingEntity(null, "16+"));
final String test = "TEST";
final MovieEntity entity = movieService.get(3L);
final String oldName = entity.getTitle();
final MovieEntity newEntity = movieService.update(3L, new MovieEntity(null,
test, type2, false,
void createNotUniqueTest() {
final MovieEntity nonUniqueMovie = new MovieEntity("Острые козырьки", type2, false,
"src/assets/main-page/posters/PeakyBlinders.png",
"Сериал рассказывает историю восхождения одной ирландской семьи...",
2013, "Великобритания", "The streets are theirs", "Энтони Бирн, Колм МакКарти", ageRating4,
"https://www.youtube.com/embed/7cOfn_sjlXM?si=fxNoZjlUon1SZd70"));
2013, "Великобритания", "The streets are theirs", "Энтони Бирн, Колм МакКарти", ageRating1,
"https://www.youtube.com/embed/7cOfn_sjlXM?si=fxNoZjlUon1SZd70");
Assertions.assertThrows(AlreadyExistsException.class, () -> movieService.create(nonUniqueMovie));
}
Assertions.assertEquals(3, movieService.getAll(0L).size());
Assertions.assertEquals(newEntity, movieService.get(3L));
@Test
void createNullableTest() {
final MovieEntity nullableItem = new MovieEntity(null, null, false, null, null, null, null, null, null, null,
null);
Assertions.assertThrows(DataIntegrityViolationException.class, () -> movieService.create(nullableItem));
}
@Test
void updateTest() {
final String test = "TEST";
final MovieEntity entity = movieService.get(last.getId());
final String oldName = entity.getTitle();
final MovieEntity newEntity = movieService.update(last.getId(), new MovieEntity(
test, entity.getType(), entity.getRequiresSubscription(),
entity.getPoster(),
entity.getDescription(),
entity.getReleaseDate(), entity.getCountry(), entity.getTagline(), entity.getDirector(),
entity.getAgeRating(),
entity.getVideo()));
Assertions.assertEquals(3, movieService.getAll(0L, 0L).size());
Assertions.assertEquals(newEntity, movieService.get(last.getId()));
Assertions.assertEquals(test, newEntity.getTitle());
Assertions.assertNotEquals(oldName, newEntity.getTitle());
}
@Test
@Order(3)
void deleteTest() {
final var type2 = typeService.create(new TypeEntity(null, "Сериал"));
final var ageRating4 = ageRatingService.create(new AgeRatingEntity(null, "16+"));
movieService.delete(last.getId());
Assertions.assertEquals(2, movieService.getAll(0L, 0L).size());
movieService.delete(3L);
Assertions.assertEquals(2, movieService.getAll(0L).size());
final MovieEntity last = movieService.get(2L);
Assertions.assertEquals(2L, last.getId());
final MovieEntity newEntity = movieService.create(new MovieEntity(null,
"Острые козырьки", type2, false,
"src/assets/main-page/posters/PeakyBlinders.png",
"Сериал рассказывает историю восхождения одной ирландской семьи...",
2013, "Великобритания", "The streets are theirs", "Энтони Бирн, Колм МакКарти", ageRating4,
"https://www.youtube.com/embed/7cOfn_sjlXM?si=fxNoZjlUon1SZd70"));
Assertions.assertEquals(3, movieService.getAll(0L).size());
Assertions.assertEquals(4L, newEntity.getId());
final MovieEntity newEntity = movieService.create(new MovieEntity(
last.getTitle(), last.getType(), last.getRequiresSubscription(),
last.getPoster(),
last.getDescription(),
last.getReleaseDate(), last.getCountry(), last.getTagline(), last.getDirector(),
last.getAgeRating(),
last.getVideo()));
Assertions.assertEquals(3, movieService.getAll(0L, 0L).size());
Assertions.assertNotEquals(last.getId(), newEntity.getId());
}
}

View File

@ -0,0 +1,139 @@
package com.example.demo;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.dao.DataIntegrityViolationException;
import com.example.demo.ageRatings.model.AgeRatingEntity;
import com.example.demo.ageRatings.service.AgeRatingService;
import com.example.demo.core.error.AlreadyExistsException;
import com.example.demo.core.error.NotFoundException;
import com.example.demo.movies.model.MovieEntity;
import com.example.demo.movies.service.MovieService;
import com.example.demo.reviews.model.ReviewEntity;
import com.example.demo.reviews.service.ReviewService;
import com.example.demo.types.model.TypeEntity;
import com.example.demo.types.service.TypeService;
import com.example.demo.users.model.UserEntity;
import com.example.demo.users.service.UserService;
@SpringBootTest
@TestMethodOrder(OrderAnnotation.class)
class ReviewServiceTests {
@Autowired
private MovieService movieService;
@Autowired
private TypeService typeService;
@Autowired
private AgeRatingService ageRatingService;
@Autowired
private ReviewService reviewService;
@Autowired
private UserService userService;
private MovieEntity movie1;
private MovieEntity movie2;
private UserEntity user1;
private UserEntity user2;
private ReviewEntity last;
@Test
void getTest() {
Assertions.assertThrows(NotFoundException.class, () -> reviewService.get(0L, 0L));
}
@BeforeEach
void createData() {
removeData();
var type1 = typeService.create(new TypeEntity("Фильм"));
var type2 = typeService.create(new TypeEntity("Сериал"));
var ageRating1 = ageRatingService.create(new AgeRatingEntity("16+"));
var ageRating2 = ageRatingService.create(new AgeRatingEntity("18+"));
movie1 = movieService.create(new MovieEntity("Американский психопат", type1, true,
"src/assets/main-page/posters/AmericanPsycho.jpg",
"Днем он ничем не отличается от окружающих, и в толпе вы не обратите на него внимания...",
2000, "США, Канада", "Респектабельная внешность дьявола", "Мэри Хэррон", ageRating2,
"https://www.youtube.com/embed/PpUWjff_OcM?si=e7tSm4V6qYkz406B"));
movie2 = movieService.create(new MovieEntity("Острые козырьки", type2, false,
"src/assets/main-page/posters/PeakyBlinders.png",
"Сериал рассказывает историю восхождения одной ирландской семьи...",
2013, "Великобритания", "The streets are theirs", "Энтони Бирн, Колм МакКарти", ageRating1,
"https://www.youtube.com/embed/7cOfn_sjlXM?si=fxNoZjlUon1SZd70"));
user1 = userService.create(new UserEntity("myemail@mail.com", "123"));
user2 = userService.create(new UserEntity("secondemail@mail.com", "321"));
reviewService.create(user1.getId(), movie1.getId(), new ReviewEntity("dsdd", 5));
reviewService.create(user2.getId(), movie1.getId(), new ReviewEntity("dggfg", 4));
last = reviewService.create(user1.getId(), movie2.getId(), new ReviewEntity("dsddddd", 5));
}
@AfterEach
void removeData() {
reviewService.deleteAll();
movieService.deleteAll();
typeService.deleteAll();
ageRatingService.deleteAll();
userService.deleteAll();
}
@Test
void createTest() {
Assertions.assertEquals(3, reviewService.getAll(0L, 0L).size());
Assertions.assertEquals(1, reviewService.getAll(movie1.getId(), user1.getId()).size());
Assertions.assertEquals(last, reviewService.get(user1.getId(), last.getId()));
Assertions.assertThrows(AlreadyExistsException.class,
() -> reviewService.create(user1.getId(), movie1.getId(), new ReviewEntity("dsdd", 5)));
}
@Test
void createNotUniqueTest() {
final ReviewEntity nonUniqueReview = new ReviewEntity("dsdd", 5);
Assertions.assertThrows(AlreadyExistsException.class, () -> reviewService.create(user1.getId(), movie1.getId(),
nonUniqueReview));
}
@Test
void createNullableTest() {
final ReviewEntity nullableReview = new ReviewEntity(null, null);
Assertions.assertThrows(NotFoundException.class,
() -> reviewService.create(0L, 0L, nullableReview));
Assertions.assertThrows(NotFoundException.class,
() -> reviewService.create(user2.getId(), 0L, nullableReview));
Assertions.assertThrows(DataIntegrityViolationException.class,
() -> reviewService.create(user2.getId(), movie2.getId(), nullableReview));
}
@Test
void updateTest() {
final String test = "TEST";
final ReviewEntity entity = reviewService.get(user1.getId(), last.getId());
final String oldDesc = entity.getDescription();
final ReviewEntity newEntity = reviewService.update(user1.getId(), last.getId(),
new ReviewEntity(test, 5));
Assertions.assertEquals(3, reviewService.getAll(0L, 0L).size());
Assertions.assertEquals(newEntity, reviewService.get(user1.getId(), last.getId()));
Assertions.assertEquals(test, newEntity.getDescription());
Assertions.assertNotEquals(oldDesc, newEntity.getDescription());
}
@Test
void deleteTest() {
reviewService.delete(last.getUser().getId(), last.getId());
Assertions.assertEquals(2, reviewService.getAll(0L, 0L).size());
final ReviewEntity newEntity = reviewService.create(user1.getId(), movie2.getId(),
new ReviewEntity("3210", 5));
Assertions.assertEquals(3, reviewService.getAll(0L, 0L).size());
Assertions.assertNotEquals(last.getId(), newEntity.getId());
}
}

View File

@ -1,13 +1,16 @@
package com.example.demo;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.dao.DataIntegrityViolationException;
import com.example.demo.core.error.AlreadyExistsException;
import com.example.demo.core.error.NotFoundException;
import com.example.demo.types.model.TypeEntity;
import com.example.demo.types.service.TypeService;
@ -18,47 +21,63 @@ class TypeServiceTests {
@Autowired
private TypeService typeService;
private TypeEntity type;
@BeforeEach
void createData() {
removeData();
type = typeService.create(new TypeEntity("Фильм"));
typeService.create(new TypeEntity("Сериал"));
}
@AfterEach
void removeData() {
typeService.getAll().forEach(item -> typeService.delete(item.getId()));
}
@Test
void getTest() {
Assertions.assertThrows(NotFoundException.class, () -> typeService.get(0L));
}
@Test
@Order(1)
void createTest() {
typeService.deleteAll();
typeService.create(new TypeEntity(null, "Фильм"));
final TypeEntity last = typeService.create(new TypeEntity(null, "Сериал"));
Assertions.assertEquals(2, typeService.getAll().size());
Assertions.assertEquals(last, typeService.get(2L));
Assertions.assertEquals(type, typeService.get(type.getId()));
}
@Test
void createNotUniqueTest() {
final TypeEntity nonUniqueType = new TypeEntity("Фильм");
Assertions.assertThrows(AlreadyExistsException.class, () -> typeService.create(nonUniqueType));
}
@Test
void createNullableTest() {
final TypeEntity nullableType = new TypeEntity(null);
Assertions.assertThrows(DataIntegrityViolationException.class, () -> typeService.create(nullableType));
}
@Test
@Order(2)
void updateTest() {
final String test = "TEST";
final TypeEntity entity = typeService.get(2L);
final String oldName = entity.getName();
final TypeEntity newEntity = typeService.update(2L, new TypeEntity(1L, test));
final String oldName = type.getName();
final TypeEntity newEntity = typeService.update(type.getId(), new TypeEntity(test));
Assertions.assertEquals(2, typeService.getAll().size());
Assertions.assertEquals(newEntity, typeService.get(2L));
Assertions.assertEquals(newEntity, typeService.get(type.getId()));
Assertions.assertEquals(test, newEntity.getName());
Assertions.assertNotEquals(oldName, newEntity.getName());
}
@Test
@Order(3)
void deleteTest() {
typeService.delete(2L);
typeService.delete(type.getId());
Assertions.assertEquals(1, typeService.getAll().size());
final TypeEntity last = typeService.get(1L);
Assertions.assertEquals(1L, last.getId());
final TypeEntity newEntity = typeService.create(new TypeEntity(null, "Сериал"));
final TypeEntity newEntity = typeService.create(new TypeEntity("Фильм"));
Assertions.assertEquals(2, typeService.getAll().size());
Assertions.assertEquals(3L, newEntity.getId());
Assertions.assertNotEquals(type.getId(), newEntity.getId());
}
}

View File

@ -1,11 +1,12 @@
package com.example.demo;
import java.util.ArrayList;
import java.time.Period;
import java.util.Date;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.springframework.beans.factory.annotation.Autowired;
@ -16,87 +17,134 @@ import com.example.demo.ageRatings.service.AgeRatingService;
import com.example.demo.core.error.NotFoundException;
import com.example.demo.movies.model.MovieEntity;
import com.example.demo.movies.service.MovieService;
import com.example.demo.subscriptions.model.SubscriptionEntity;
import com.example.demo.subscriptions.service.SubscriptionService;
import com.example.demo.types.model.TypeEntity;
import com.example.demo.types.service.TypeService;
import com.example.demo.users.model.UserEntity;
import com.example.demo.users.service.UserService;
import com.example.demo.usersubscription.model.UserSubscriptionEntity;
@SpringBootTest
@TestMethodOrder(OrderAnnotation.class)
class UserServiceTests {
@Autowired
private TypeService typeService;
@Autowired
private AgeRatingService ageRatingService;
@Autowired
private MovieService movieService;
@Autowired
private UserService userService;
@Autowired
private SubscriptionService subscriptionService;
private UserEntity last;
private TypeEntity type1;
private AgeRatingEntity ageRating1;
private MovieEntity movie1;
private MovieEntity movie2;
private SubscriptionEntity subscription1;
private SubscriptionEntity subscription2;
@Test
void getTest() {
Assertions.assertThrows(NotFoundException.class, () -> userService.get(0L));
}
@Test
@Order(1)
void createTest() {
ageRatingService.deleteAll();
typeService.deleteAll();
movieService.deleteAll();
userService.deleteAll();
@BeforeEach
void createData() {
removeData();
userService.create(new UserEntity(null, "myemail@mail.com", "12345678", new Date(), new ArrayList<>()));
userService.create(new UserEntity(null, "secondemail@mail.com", "qwwerty", new Date(), new ArrayList<>()));
final var last = userService
.create(new UserEntity(null, "thirdemail@mail.com", "ytrewq", new Date(), new ArrayList<>()));
userService.create(new UserEntity("myemail@mail.com", "123"));
userService.create(new UserEntity("secondemail@mail.com", "321"));
last = userService.create(new UserEntity("thirdemail@mail.com", "3210"));
Assertions.assertEquals(3, userService.getAll().size());
Assertions.assertEquals(last, userService.get(3L));
}
@Test
@Order(2)
void updateTest() {
final var type1 = typeService.create(new TypeEntity(null, "Фильм"));
final var ageRating5 = ageRatingService.create(new AgeRatingEntity(null, "18+"));
final var movie1 = movieService.create(new MovieEntity(null, "Бойцовский клуб", type1, false,
type1 = typeService.create(new TypeEntity("Фильм"));
ageRating1 = ageRatingService.create(new AgeRatingEntity("18+"));
movie1 = movieService.create(new MovieEntity("Бойцовский клуб", type1, false,
"src/assets/main-page/posters/PeakyBlinders.png",
"Сотрудник страховой компании страдает хронической бессонницей и отчаянно пытается вырваться из мучительно скучной жизни...",
1999, "США", "Интриги. Хаос. Мыло", "Дэвид Финчер", ageRating5,
1999, "США", "Интриги. Хаос. Мыло", "Дэвид Финчер", ageRating1,
"https://www.youtube.com/embed/dfeUzm6KF4g?si=U2D-2WNsJzkcxlBX"));
final var movie2 = movieService.create(new MovieEntity(null, "Американский психопат", type1, true,
movie2 = movieService.create(new MovieEntity("Американский психопат", type1, true,
"src/assets/main-page/posters/AmericanPsycho.jpg",
"Днем он ничем не отличается от окружающих, и в толпе вы не обратите на него внимания...",
2000, "США, Канада", "Респектабельная внешность дьявола", "Мэри Хэррон", ageRating5,
2000, "США, Канада", "Респектабельная внешность дьявола", "Мэри Хэррон", ageRating1,
"https://www.youtube.com/embed/PpUWjff_OcM?si=e7tSm4V6qYkz406B"));
userService.addMovie(1L, movie1.getId());
final UserEntity newEntity = userService.addMovie(1L, movie2.getId());
subscription1 = subscriptionService.create(new SubscriptionEntity("Подписка 1", Period.of(0, 0, 7), 199.99));
subscription2 = subscriptionService.create(new SubscriptionEntity("Подписка 2", Period.of(0, 1, 0), 299.99));
}
Assertions.assertEquals(3, userService.getAll().size());
Assertions.assertEquals(newEntity, userService.get(1L));
Assertions.assertEquals(2, userService.get(1L).getWatchLater().size());
userService.addMovie(1L, movie1.getId());
Assertions.assertEquals(2, userService.get(1L).getWatchLater().size());
@AfterEach
void removeData() {
userService.deleteAll();
movieService.deleteAll();
typeService.deleteAll();
ageRatingService.deleteAll();
subscriptionService.deleteAll();
}
@Test
@Order(3)
void deleteTest() {
userService.delete(3L);
Assertions.assertEquals(2, userService.getAll().size());
final UserEntity last = userService.get(2L);
Assertions.assertEquals(2L, last.getId());
final var newEntity = userService
.create(new UserEntity(null, "thirdemail@mail.com", "ytrewq", new Date(), new ArrayList<>()));
void createTest() {
Assertions.assertEquals(3, userService.getAll().size());
Assertions.assertEquals(4L, newEntity.getId());
Assertions.assertEquals(last, userService.get(last.getId()));
}
@Test
void updateTest() {
final String test = "TEST";
final UserEntity entity = userService.get(last.getId());
final String oldEmail = entity.getEmail();
final UserEntity newEntity = userService.update(entity.getId(),
new UserEntity(test, entity.getPassword()));
Assertions.assertEquals(3, userService.getAll().size());
Assertions.assertEquals(newEntity, userService.get(newEntity.getId()));
Assertions.assertEquals(test, newEntity.getEmail());
Assertions.assertNotEquals(oldEmail, newEntity.getEmail());
}
@Test
void deleteTest() {
userService.delete(last.getId());
Assertions.assertEquals(2, userService.getAll().size());
final var newEntity = userService.create(new UserEntity("thirdemail@mail.com", "3210"));
Assertions.assertEquals(3, userService.getAll().size());
Assertions.assertNotEquals(last.getId(), newEntity.getId());
}
@Test
void watchLaterTest() {
userService.addMovieToWatchLater(last.getId(), movie1);
userService.addMovieToWatchLater(last.getId(), movie1);
Assertions.assertEquals(1, userService.getWatchLater(last.getId()).size());
userService.addMovieToWatchLater(last.getId(), movie2);
Assertions.assertEquals(2, userService.getWatchLater(last.getId()).size());
userService.deleteMovieFromWatchLater(last.getId(), movie1);
Assertions.assertEquals(1, userService.getWatchLater(last.getId()).size());
}
@Test
void subscriptionsTest() {
Assertions.assertNull(userService.getActiveSubscription(last.getId()));
userService.activateSubscription(last.getId(), subscription1.getId());
userService.activateSubscription(last.getId(), subscription1.getId());
Assertions.assertEquals(1, userService.getUserSubscriptions(last.getId()).size());
UserSubscriptionEntity activeSubscription = userService.getActiveSubscription(last.getId());
Assertions.assertNotNull(activeSubscription);
Assertions.assertTrue(activeSubscription.getExpirationDate().after(new Date()));
userService.deactivateSubscription(last.getId());
Assertions.assertNull(userService.getActiveSubscription(last.getId()));
userService.activateSubscription(last.getId(), subscription2.getId());
Assertions.assertNotNull(userService.getActiveSubscription(last.getId()));
Assertions.assertEquals(2, userService.getUserSubscriptions(last.getId()).size());
}
}