diff --git a/pom.xml b/pom.xml
new file mode 100644
index 00000000..c5236f5e
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,95 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.2.4
+
+
+ ru.yandex.practicum
+ filmorate
+ 0.0.1-SNAPSHOT
+ filmorate
+ filmorate
+
+ 21
+
+
+
+ jakarta.validation
+ jakarta.validation-api
+ 3.0.2
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.slf4j
+ slf4j-api
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ ch.qos.logback
+ logback-classic
+
+
+ junit
+ junit
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+ org.zalando
+ logbook-spring-boot-starter
+ 3.7.2
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+ 3.3.1
+
+ checkstyle.xml
+ true
+ true
+ true
+
+
+
+
+ check
+
+ compile
+
+
+
+
+
+
+
diff --git a/src/main/java/ru/yandex/practicum/filmorate/FilmorateApplication.java b/src/main/java/ru/yandex/practicum/filmorate/FilmorateApplication.java
new file mode 100644
index 00000000..eb0225c0
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/FilmorateApplication.java
@@ -0,0 +1,14 @@
+package ru.yandex.practicum.filmorate;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@Slf4j
+@SpringBootApplication
+public class FilmorateApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(FilmorateApplication.class, args);
+ log.info("Приложение запущено");
+ }
+}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/ErrorHandler.java b/src/main/java/ru/yandex/practicum/filmorate/controller/ErrorHandler.java
new file mode 100644
index 00000000..750cdb26
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/controller/ErrorHandler.java
@@ -0,0 +1,31 @@
+package ru.yandex.practicum.filmorate.controller;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import ru.yandex.practicum.filmorate.ecxeption.NotFoundException;
+import ru.yandex.practicum.filmorate.ecxeption.OccurredException;
+import ru.yandex.practicum.filmorate.ecxeption.ValidationException;
+import ru.yandex.practicum.filmorate.model.ErrorResponse;
+
+@RestControllerAdvice
+public class ErrorHandler {
+ @ExceptionHandler
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ public ErrorResponse validationException(final ValidationException e) {
+ return new ErrorResponse(e.getMessage());
+ }
+
+ @ExceptionHandler
+ @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+ public ErrorResponse occurredException(final OccurredException e) {
+ return new ErrorResponse(e.getMessage());
+ }
+
+ @ExceptionHandler
+ @ResponseStatus(HttpStatus.NOT_FOUND)
+ public ErrorResponse notFoundException(final NotFoundException e) {
+ return new ErrorResponse(e.getMessage());
+ }
+}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java
new file mode 100644
index 00000000..8d422bf6
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java
@@ -0,0 +1,54 @@
+package ru.yandex.practicum.filmorate.controller;
+
+import jakarta.validation.Valid;
+import ru.yandex.practicum.filmorate.model.Film;
+import org.springframework.web.bind.annotation.*;
+import ru.yandex.practicum.filmorate.service.FilmService;
+
+import java.util.Collection;
+
+@RestController
+@RequestMapping("/films")
+public class FilmController {
+ private final FilmService filmService;
+
+ public FilmController(FilmService filmService) {
+ this.filmService = filmService;
+ }
+
+ @GetMapping
+ public Collection getAllFilms() {
+ return filmService.getAllFilms();
+ }
+
+ @GetMapping("/{id}")
+ public Film getFilmById(@PathVariable("id") long id) {
+ return filmService.getFilmById(id);
+ }
+
+ @PostMapping
+ public Film createFilm(@Valid @RequestBody Film film) {
+ return filmService.createFilm(film);
+ }
+
+ @PutMapping
+ public Film updateFilm(@Valid @RequestBody Film film) {
+ return filmService.updateFilm(film);
+ }
+
+ @PutMapping("/{id}/like/{userId}")
+ public Film userLikesFilm(@PathVariable("id") Long id, @PathVariable("userId") Long userId) {
+ return filmService.userLikesFilm(id, userId);
+ }
+
+ @DeleteMapping("/{id}/like/{userId}")
+ public Film deleteLikesFilm(@PathVariable("id") Long id, @PathVariable("userId") Long userId) {
+ return filmService.deleteLikesFilm(id, userId);
+ }
+
+ @GetMapping("/popular")
+ public Collection listFirstCountFilm(@RequestParam(defaultValue = "10") int count) {
+ return filmService.listFirstCountFilm(count);
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java
new file mode 100644
index 00000000..badda64a
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java
@@ -0,0 +1,60 @@
+package ru.yandex.practicum.filmorate.controller;
+
+import jakarta.validation.Valid;
+import ru.yandex.practicum.filmorate.model.User;
+import org.springframework.web.bind.annotation.*;
+import ru.yandex.practicum.filmorate.service.UserService;
+
+import java.util.Collection;
+
+@RestController
+@RequestMapping("/users")
+public class UserController {
+
+ private final UserService userService;
+
+ UserController(UserService userService) {
+ this.userService = userService;
+ }
+
+ @GetMapping
+ public Collection getAllUsers() {
+ return userService.getAllUsers();
+ }
+
+ @GetMapping("/{id}")
+ public User getUserById(@PathVariable("id") long id) {
+ return userService.getUserById(id);
+ }
+
+ @PostMapping
+ public User createUser(@Valid @RequestBody User user) {
+ return userService.createUser(user);
+ }
+
+ @PutMapping
+ public User updateUser(@Valid @RequestBody User user) {
+ return userService.updateUser(user);
+ }
+
+ @PutMapping("/{id}/friends/{friendId}")
+ public User putFriends(@PathVariable("id") long id, @PathVariable("friendId") long friendId) {
+ return userService.makeFriendship(id, friendId);
+ }
+
+ @DeleteMapping("/{id}/friends/{friendId}")
+ public User deleteFriends(@PathVariable("id") long id, @PathVariable("friendId") long friendId) {
+ return userService.deleteFriendship(id, friendId);
+ }
+
+ @GetMapping("/{id}/friends")
+ public Collection listFriends(@PathVariable("id") long id) {
+ return userService.listOfFriends(id);
+ }
+
+ @GetMapping("/{id}/friends/common/{otherId}")
+ public Collection commonFriends(@PathVariable("id") long id, @PathVariable("otherId") long otherId) {
+ return userService.listOfCommonFriends(id, otherId);
+ }
+
+}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/ecxeption/NotFoundException.java b/src/main/java/ru/yandex/practicum/filmorate/ecxeption/NotFoundException.java
new file mode 100644
index 00000000..db265b31
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/ecxeption/NotFoundException.java
@@ -0,0 +1,7 @@
+package ru.yandex.practicum.filmorate.ecxeption;
+
+public class NotFoundException extends RuntimeException {
+ public NotFoundException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/ecxeption/OccurredException.java b/src/main/java/ru/yandex/practicum/filmorate/ecxeption/OccurredException.java
new file mode 100644
index 00000000..7b774095
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/ecxeption/OccurredException.java
@@ -0,0 +1,7 @@
+package ru.yandex.practicum.filmorate.ecxeption;
+
+public class OccurredException extends RuntimeException {
+ public OccurredException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/ecxeption/ValidationException.java b/src/main/java/ru/yandex/practicum/filmorate/ecxeption/ValidationException.java
new file mode 100644
index 00000000..4f13aa60
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/ecxeption/ValidationException.java
@@ -0,0 +1,7 @@
+package ru.yandex.practicum.filmorate.ecxeption;
+
+public class ValidationException extends RuntimeException {
+ public ValidationException(String string) {
+ super(string);
+ }
+}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/ErrorResponse.java b/src/main/java/ru/yandex/practicum/filmorate/model/ErrorResponse.java
new file mode 100644
index 00000000..756207ee
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/model/ErrorResponse.java
@@ -0,0 +1,11 @@
+package ru.yandex.practicum.filmorate.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public class ErrorResponse {
+ String error;
+}
+
diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java
new file mode 100644
index 00000000..1241d0f2
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java
@@ -0,0 +1,27 @@
+package ru.yandex.practicum.filmorate.model;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Positive;
+import jakarta.validation.constraints.Size;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDate;
+import java.util.HashSet;
+import java.util.Set;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class Film {
+ Long id;
+ @NotBlank(message = "Название не может быть пустым!")
+ String name;
+ @Size(max = 200, message = "Максимальная длина описания — 200 символов!")
+ String description;
+ LocalDate releaseDate;
+ @Positive(message = "Продолжительность фильма должна быть положительным числом!")
+ int duration;
+ Set likes = new HashSet<>();
+}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/User.java b/src/main/java/ru/yandex/practicum/filmorate/model/User.java
new file mode 100644
index 00000000..e7d84235
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/model/User.java
@@ -0,0 +1,27 @@
+package ru.yandex.practicum.filmorate.model;
+
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Past;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDate;
+import java.util.HashSet;
+import java.util.Set;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class User {
+ Long id;
+ @Email(message = "Введенный email не соответствует формату email-адресов!")
+ String email;
+ @NotBlank(message = "Логин не может быть пустым и содержать пробелы!")
+ String login;
+ String name;
+ @Past(message = "Дата рождения не может быть в будущем!")
+ LocalDate birthday;
+ Set friends = new HashSet<>();
+}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java
new file mode 100644
index 00000000..41e572ab
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java
@@ -0,0 +1,76 @@
+package ru.yandex.practicum.filmorate.service;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import ru.yandex.practicum.filmorate.ecxeption.NotFoundException;
+import ru.yandex.practicum.filmorate.model.Film;
+import ru.yandex.practicum.filmorate.storage.film.FilmStorage;
+import ru.yandex.practicum.filmorate.storage.user.UserStorage;
+
+import java.util.*;
+
+@Service
+@RequiredArgsConstructor
+public class FilmService {
+ private final FilmStorage filmStorage;
+ private final UserStorage userStorage;
+
+ public Film getFilmById(Long id) {
+ if (filmStorage.getFilmById(id) == null) {
+ throw new NotFoundException("Такого фильма нет в списке!");
+ }
+ return filmStorage.getFilmById(id);
+ }
+
+ public Film userLikesFilm(Long id, Long userId) {
+ Film film = filmStorage.getFilmById(id);
+ if (userStorage.getUserById(userId) == null) {
+ throw new NotFoundException("Такого юзера нет в списке!");
+ }
+ if (film == null) {
+ throw new NotFoundException("Такого фильма нет в списке!");
+ }
+ film.getLikes().add(userId);
+ return film;
+ }
+
+ public Film deleteLikesFilm(Long id, Long userId) {
+ if (userStorage.getUserById(userId) == null) {
+ throw new NotFoundException("Такого юзера нет!");
+ }
+ Film film = filmStorage.getFilmById(id);
+ if (film == null) {
+ throw new NotFoundException("Такого фильма нет в списке!");
+ }
+ film.getLikes().remove(userId);
+ return film;
+ }
+
+ public Collection listFirstCountFilm(int count) {
+ Collection films;
+ films = sortingToDown().stream()
+ .limit(count)
+ .toList();
+ return films;
+ }
+
+ public List sortingToDown() {
+ ArrayList listFilms = new ArrayList<>(filmStorage.getAllFilms());
+ listFilms.sort((Film film1, Film film2) ->
+ Integer.compare(film2.getLikes().size(), film1.getLikes().size())
+ );
+ return listFilms;
+ }
+
+ public Collection getAllFilms() {
+ return filmStorage.getAllFilms();
+ }
+
+ public Film createFilm(Film film) {
+ return filmStorage.createFilm(film);
+ }
+
+ public Film updateFilm(Film film) {
+ return filmStorage.updateFilm(film);
+ }
+}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java
new file mode 100644
index 00000000..3813fd68
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java
@@ -0,0 +1,85 @@
+package ru.yandex.practicum.filmorate.service;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import ru.yandex.practicum.filmorate.ecxeption.NotFoundException;
+import ru.yandex.practicum.filmorate.model.User;
+import ru.yandex.practicum.filmorate.storage.user.UserStorage;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Service
+@RequiredArgsConstructor
+public class UserService {
+
+ private final UserStorage userStorage;
+
+ public User getUserById(Long id) {
+ if (userStorage.getUserById(id) == null) {
+ throw new NotFoundException("Такого юзера нет в списке!");
+ }
+ return userStorage.getUserById(id);
+ }
+
+ public User makeFriendship(long id, long friendId) {
+ if (userStorage.getUserById(id) == null) {
+ throw new NotFoundException("Такого юзера нет в списке!");
+ }
+ if (userStorage.getUserById(friendId) == null) {
+ throw new NotFoundException("Невозможно добавить в друзья несуществующего юзера!");
+ }
+ userStorage.getUserById(id).getFriends().add(friendId);
+ userStorage.getUserById(friendId).getFriends().add(id);
+ return userStorage.getUserById(id);
+ }
+
+ public User deleteFriendship(long id, long friendId) {
+ if (userStorage.getUserById(id) == null) {
+ throw new NotFoundException("Такого юзера нет в списке!");
+ }
+ if (userStorage.getUserById(friendId) == null) {
+ throw new NotFoundException("Добавляемого в друзья юзера нет в списке!");
+ }
+ userStorage.getUserById(id).getFriends().remove(friendId);
+ userStorage.getUserById(friendId).getFriends().remove(id);
+ return userStorage.getUserById(id);
+ }
+
+ public Collection listOfFriends(long id) {
+ if (userStorage.getUserById(id) == null) {
+ throw new NotFoundException("Такого юзера нет в списке!");
+ }
+ if (userStorage.getUserById(id).getFriends() == null) {
+ throw new NotFoundException("Список друзей пуст!");
+ }
+ return userStorage.getUserById(id).getFriends().stream()
+ .map(friends -> userStorage.getUserById(friends))
+ .collect(Collectors.toList());
+ }
+
+ public Collection listOfCommonFriends(Long id, Long otherId) {
+ if (userStorage.getUserById(id) == null || userStorage.getUserById(otherId) == null) {
+ throw new NotFoundException("Одного из юзеров нет в списке!");
+ }
+ if (userStorage.getUserById(id).getFriends() == null || userStorage.getUserById(otherId).getFriends() == null) {
+ throw new NotFoundException("Один из списков друзей пуст!");
+ }
+ userStorage.getUserById(id).getFriends().retainAll(userStorage.getUserById(otherId).getFriends());
+ return userStorage.getUserById(id).getFriends().stream()
+ .map(friends -> userStorage.getUserById(friends))
+ .collect(Collectors.toList());
+ }
+
+ public Collection getAllUsers() {
+ return userStorage.getAllUsers();
+ }
+
+ public User createUser(User user) {
+ return userStorage.createUser(user);
+ }
+
+ public User updateUser(User user) {
+ return userStorage.updateUser(user);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmStorage.java
new file mode 100644
index 00000000..6e5b828a
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmStorage.java
@@ -0,0 +1,16 @@
+package ru.yandex.practicum.filmorate.storage.film;
+
+import ru.yandex.practicum.filmorate.model.Film;
+
+import java.util.Collection;
+
+public interface FilmStorage {
+
+ Film getFilmById(Long id);
+
+ Collection getAllFilms();
+
+ Film createFilm(Film film);
+
+ Film updateFilm(Film film);
+}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java
new file mode 100644
index 00000000..728311f2
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java
@@ -0,0 +1,65 @@
+package ru.yandex.practicum.filmorate.storage.film;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+import ru.yandex.practicum.filmorate.ecxeption.NotFoundException;
+import ru.yandex.practicum.filmorate.ecxeption.ValidationException;
+import ru.yandex.practicum.filmorate.model.Film;
+
+import java.time.LocalDate;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+@Slf4j
+@Component
+public class InMemoryFilmStorage implements FilmStorage {
+
+ private final Map films = new HashMap<>();
+
+ @Override
+ public Film getFilmById(Long id) {
+ return films.get(id);
+ }
+
+ @Override
+ public Collection getAllFilms() {
+ return films.values();
+ }
+
+ @Override
+ public Film createFilm(Film film) {
+ if (film.getReleaseDate().isBefore(LocalDate.of(1895, 12, 28))) {
+ throw new ValidationException("Дата релиза — не раньше 28 декабря 1895 года!");
+ }
+ film.setId(getNextId());
+ log.debug("Валидация пройдена.");
+ films.put(film.getId(), film);
+ log.debug("Фильм добавлен в список.");
+ return film;
+ }
+
+ @Override
+ public Film updateFilm(Film film) {
+ // validateFilm(film);
+ if (film.getId() == null) {
+ throw new ValidationException("Id должен быть указан!");
+ }
+ if (films.containsKey(film.getId())) {
+ if (film.getReleaseDate().isBefore(LocalDate.of(1895, 12, 28))) {
+ throw new ValidationException("Дата релиза — не раньше 28 декабря 1895 года!");
+ }
+ films.put(film.getId(), film);
+ return film;
+ } else throw new NotFoundException("Такого фильма нет в списке!");
+ }
+
+ private Long getNextId() {
+ long currentMaxId = films.keySet()
+ .stream()
+ .mapToLong(id -> id)
+ .max()
+ .orElse(0);
+ return ++currentMaxId;
+ }
+}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/user/InMemoryUserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/user/InMemoryUserStorage.java
new file mode 100644
index 00000000..02d314bb
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/storage/user/InMemoryUserStorage.java
@@ -0,0 +1,65 @@
+package ru.yandex.practicum.filmorate.storage.user;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+import ru.yandex.practicum.filmorate.ecxeption.NotFoundException;
+import ru.yandex.practicum.filmorate.ecxeption.ValidationException;
+import ru.yandex.practicum.filmorate.model.User;
+
+import java.util.*;
+
+@Slf4j
+@Component
+public class InMemoryUserStorage implements UserStorage {
+
+ private final Map users = new HashMap<>();
+
+ @Override
+ public Collection getAllUsers() {
+ return users.values();
+ }
+
+ @Override
+ public User getUserById(Long id) {
+ return users.get(id);
+ }
+
+ @Override
+ public User createUser(User user) {
+ user.setId(getNextId());
+ log.debug("Валидация пройдена.");
+ if (user.getName() == null) {
+ user.setName(user.getLogin());
+ }
+ users.put(user.getId(), user);
+ return user;
+ }
+
+ @Override
+ public User updateUser(User user) {
+ if (user.getId() == null) {
+ throw new ValidationException("Id должен быть указан!");
+ }
+ if (users.containsKey(user.getId())) {
+ user.setBirthday(user.getBirthday());
+ user.setLogin(user.getLogin());
+ user.setEmail(user.getEmail());
+ if (user.getName() == null) {
+ user.setName(user.getLogin());
+ log.debug("Заменили имя на логин.");
+ } else {
+ user.setName(user.getName());
+ }
+ return user;
+ } else throw new NotFoundException("Такого пользователя нет в списке!");
+ }
+
+ private Long getNextId() {
+ long currentMaxId = users.keySet()
+ .stream()
+ .mapToLong(id -> id)
+ .max()
+ .orElse(0);
+ return ++currentMaxId;
+ }
+}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserStorage.java
new file mode 100644
index 00000000..8d013fd4
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserStorage.java
@@ -0,0 +1,16 @@
+package ru.yandex.practicum.filmorate.storage.user;
+
+import ru.yandex.practicum.filmorate.model.User;
+
+import java.util.Collection;
+
+public interface UserStorage {
+
+ User getUserById(Long id);
+
+ Collection getAllUsers();
+
+ User createUser(User user);
+
+ User updateUser(User user);
+}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
new file mode 100644
index 00000000..21af5c78
--- /dev/null
+++ b/src/main/resources/application.properties
@@ -0,0 +1 @@
+logging.level.org.zalando.logbook=TRACE
diff --git a/src/test/java/ru/yandex/practicum/filmorate/FilmorateApplicationTests.java b/src/test/java/ru/yandex/practicum/filmorate/FilmorateApplicationTests.java
new file mode 100644
index 00000000..00b99fcb
--- /dev/null
+++ b/src/test/java/ru/yandex/practicum/filmorate/FilmorateApplicationTests.java
@@ -0,0 +1,104 @@
+package ru.yandex.practicum.filmorate;
+
+import jakarta.validation.ConstraintViolation;
+import jakarta.validation.Validation;
+import jakarta.validation.Validator;
+import jakarta.validation.ValidatorFactory;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.springframework.boot.test.context.SpringBootTest;
+//import ru.yandex.practicum.filmorate.ecxeption.ValidationException;
+import ru.yandex.practicum.filmorate.model.Film;
+import ru.yandex.practicum.filmorate.model.User;
+//import ru.yandex.practicum.filmorate.controller.FilmController;
+//import ru.yandex.practicum.filmorate.service.FilmService;
+//import ru.yandex.practicum.filmorate.storage.film.InMemoryFilmStorage;
+
+import java.io.IOException;
+import java.time.LocalDate;
+import java.util.Set;
+
+@SpringBootTest
+public class FilmorateApplicationTests {
+
+ private final ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
+ private final Validator validator = factory.getValidator();
+
+ @Test
+ public void testValidateEmailUser() throws IOException {
+ User user = new User();
+ user.setEmail("@exampleexample.com");
+ user.setLogin("exampleLogin");
+ user.setName("Example");
+ user.setBirthday(LocalDate.of(2000, 1, 1));
+ Set> violations = validator.validate(user);
+ Assertions.assertFalse(violations.isEmpty(), "Пользователь с неправильным емейлом не должен создаваться");
+ }
+
+ @Test
+ public void testValidateLoginUser() throws IOException {
+ User user = new User();
+ user.setEmail("example@example.com");
+ user.setLogin("");
+ user.setName("Example");
+ user.setBirthday(LocalDate.of(2000, 1, 1));
+ Set> violations = validator.validate(user);
+ Assertions.assertFalse(violations.isEmpty(), "Пользователь с пустым логином не должен создаваться");
+ }
+
+ @Test
+ public void testValidateDateUser() throws IOException {
+ User user = new User();
+ user.setEmail("example@example.com");
+ user.setLogin("exampleLogin");
+ user.setName("Example");
+ user.setBirthday(LocalDate.of(2050, 1, 1));
+ Set> violations = validator.validate(user);
+ Assertions.assertFalse(violations.isEmpty(), "Пользователь с датой др в будущем не должен создаваться");
+ }
+
+ @Test
+ public void testValidateFilmName() throws IOException {
+ Film film = new Film();
+ film.setName("");
+ film.setDescription("exampleFilm");
+ film.setReleaseDate(LocalDate.of(2000, 1, 1));
+ film.setDuration(100);
+ Set> violations = validator.validate(film);
+ Assertions.assertFalse(violations.isEmpty(), "Фильм с пустым именем не должен создаваться");
+ }
+
+ @Test
+ public void testValidateFilmDescription() throws IOException {
+ Film film = new Film();
+ film.setName("Example");
+ film.setDescription("exampleFilmexampleFilmexampleFilmexampleFilmexampleFilmexampleFilmexampleFilmexampleFilmexampleFilmexampleFilmexampleFilmexampleFilmexampleFilmexampleFilmexampleFilmexampleFilmexampleFilmFilmexampleFilmFilmexampleFilmFilmexampleFilmFilmexampleFilmFilmexampleFilmFilmexampleFilm");
+ film.setReleaseDate(LocalDate.of(2000, 1, 1));
+ film.setDuration(100);
+ Set> violations = validator.validate(film);
+ Assertions.assertFalse(violations.isEmpty(), "Фильм с описанием более 200 смволов не должен создаваться");
+ }
+
+// @Test(expected = ValidationException.class)
+// public void testValidateFilmRelease() throws IOException {
+// Film film = new Film();
+// film.setName("Example");
+// film.setDescription("exampleFilm");
+// film.setReleaseDate(LocalDate.of(1895, 12, 27));
+// film.setDuration(100);
+// FilmController filmController = new FilmController(new FilmService());
+// filmController.createFilm(film);
+// }
+
+ @Test
+ public void testValidateFilmDuration() throws IOException {
+ Film film = new Film();
+ film.setName("Example");
+ film.setDescription("exampleFilm");
+ film.setReleaseDate(LocalDate.of(2000, 1, 1));
+ film.setDuration(0);
+ Set> violations = validator.validate(film);
+ Assertions.assertFalse(violations.isEmpty(), "Фильм с продолжительностью 0 не должен создаваться");
+ }
+
+}