├── README.md ├── ewm-stat-service ├── stat_client │ ├── src │ │ └── main │ │ │ ├── resources │ │ │ └── application.properties │ │ │ └── java │ │ │ └── ru │ │ │ └── practicum │ │ │ └── client │ │ │ ├── StatClient.java │ │ │ └── BaseClient.java │ ├── Dockerfile │ ├── .gitignore │ └── pom.xml ├── stat_dto │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── ru │ │ │ └── practicum │ │ │ └── dto │ │ │ ├── Validator.java │ │ │ ├── StatResponseDto.java │ │ │ └── StatDto.java │ ├── .gitignore │ └── pom.xml ├── stat_server │ ├── Dockerfile │ ├── src │ │ └── main │ │ │ ├── java │ │ │ └── ru │ │ │ │ └── practicum │ │ │ │ ├── exception │ │ │ │ ├── WrongTimeException.java │ │ │ │ ├── ErrorResponse.java │ │ │ │ └── ErrorHandler.java │ │ │ │ ├── utill │ │ │ │ └── Constants.java │ │ │ │ ├── StatServerApplication.java │ │ │ │ ├── service │ │ │ │ ├── StatService.java │ │ │ │ └── StatServiceImpl.java │ │ │ │ ├── model │ │ │ │ ├── Stat.java │ │ │ │ └── mapper │ │ │ │ │ └── StatMapper.java │ │ │ │ ├── controller │ │ │ │ └── StatServiceController.java │ │ │ │ └── repository │ │ │ │ └── StatServiceRepository.java │ │ │ └── resources │ │ │ ├── schema.sql │ │ │ └── application.properties │ ├── .gitignore │ └── pom.xml ├── .gitignore └── pom.xml ├── lombok.config ├── ewm-main-service ├── src │ └── main │ │ ├── java │ │ └── ru │ │ │ └── practicum │ │ │ ├── main │ │ │ ├── event │ │ │ │ ├── status │ │ │ │ │ ├── State.java │ │ │ │ │ ├── AdminEventStatus.java │ │ │ │ │ └── UserEventStatus.java │ │ │ │ ├── dto │ │ │ │ │ ├── EventCommentDto.java │ │ │ │ │ ├── RequestShortDto.java │ │ │ │ │ ├── RequestShortUpdateDto.java │ │ │ │ │ ├── EventDto.java │ │ │ │ │ ├── EventShortDto.java │ │ │ │ │ ├── EventAdminDto.java │ │ │ │ │ ├── PatchEventDto.java │ │ │ │ │ ├── EventFullDto.java │ │ │ │ │ ├── EventRequestDto.java │ │ │ │ │ ├── EventFullWithComment.java │ │ │ │ │ ├── EventFullWithCommentDto.java │ │ │ │ │ ├── UpdateEventDto.java │ │ │ │ │ └── AdminEventRequestDto.java │ │ │ │ ├── location │ │ │ │ │ ├── dto │ │ │ │ │ │ └── LocationDto.java │ │ │ │ │ ├── repository │ │ │ │ │ │ └── LocationMainServiceRepository.java │ │ │ │ │ ├── mapper │ │ │ │ │ │ └── LocationMapper.java │ │ │ │ │ └── model │ │ │ │ │ │ └── Location.java │ │ │ │ ├── service │ │ │ │ │ ├── EventAdminService.java │ │ │ │ │ ├── EventPublicService.java │ │ │ │ │ ├── EventPrivateService.java │ │ │ │ │ ├── EventPublicServiceImpl.java │ │ │ │ │ └── EventAdminServiceImpl.java │ │ │ │ ├── repository │ │ │ │ │ └── EventMainServiceRepository.java │ │ │ │ ├── controller │ │ │ │ │ ├── EventAdminController.java │ │ │ │ │ ├── EventPublicController.java │ │ │ │ │ └── EventPrivateController.java │ │ │ │ ├── model │ │ │ │ │ └── Event.java │ │ │ │ └── mapper │ │ │ │ │ └── EventMapper.java │ │ │ ├── request │ │ │ │ ├── Status.java │ │ │ │ ├── dto │ │ │ │ │ ├── RequestShortDto.java │ │ │ │ │ ├── RequestUpdateDto.java │ │ │ │ │ ├── RequestDto.java │ │ │ │ │ └── ConfirmedRequestShortDto.java │ │ │ │ ├── service │ │ │ │ │ ├── RequestService.java │ │ │ │ │ └── RequestServiceImpl.java │ │ │ │ ├── repository │ │ │ │ │ └── RequestMainServiceRepository.java │ │ │ │ ├── model │ │ │ │ │ └── Request.java │ │ │ │ ├── mapper │ │ │ │ │ └── RequestMapper.java │ │ │ │ └── controller │ │ │ │ │ └── RequestController.java │ │ │ ├── exception │ │ │ │ ├── NotUniqueException.java │ │ │ │ ├── ConflictException.java │ │ │ │ ├── NotFoundException.java │ │ │ │ ├── StatParseException.java │ │ │ │ ├── BadRequestException.java │ │ │ │ └── handler │ │ │ │ │ ├── ErrorResponse.java │ │ │ │ │ └── MainServiceHandler.java │ │ │ ├── user │ │ │ │ ├── dto │ │ │ │ │ ├── UserDto.java │ │ │ │ │ ├── AdminUserDto.java │ │ │ │ │ ├── UserShortDto.java │ │ │ │ │ └── UserDtoReceived.java │ │ │ │ ├── service │ │ │ │ │ ├── UserService.java │ │ │ │ │ └── UserServiceImpl.java │ │ │ │ ├── repository │ │ │ │ │ └── UserMainServiceRepository.java │ │ │ │ ├── model │ │ │ │ │ └── User.java │ │ │ │ ├── mapper │ │ │ │ │ └── UserMapper.java │ │ │ │ └── controller │ │ │ │ │ └── UserController.java │ │ │ ├── category │ │ │ │ ├── service │ │ │ │ │ ├── CategoryPublicService.java │ │ │ │ │ ├── CategoryAdminService.java │ │ │ │ │ ├── CategoryPublicServiceImpl.java │ │ │ │ │ └── CategoryAdminServiceImpl.java │ │ │ │ ├── repository │ │ │ │ │ └── CategoryMainServiceRepository.java │ │ │ │ ├── dto │ │ │ │ │ └── CategoryDto.java │ │ │ │ ├── model │ │ │ │ │ └── Category.java │ │ │ │ ├── mapper │ │ │ │ │ └── CategoryMapper.java │ │ │ │ └── controller │ │ │ │ │ ├── CategoryPublicController.java │ │ │ │ │ └── CategoryAdminController.java │ │ │ ├── comment │ │ │ │ ├── service │ │ │ │ │ ├── AdminCommentService.java │ │ │ │ │ ├── CommentService.java │ │ │ │ │ ├── PrivateCommentService.java │ │ │ │ │ ├── AdminCommentServiceImpl.java │ │ │ │ │ ├── CommentServiceImpl.java │ │ │ │ │ └── PrivateCommentServiceImpl.java │ │ │ │ ├── dto │ │ │ │ │ ├── CommentShortDto.java │ │ │ │ │ ├── CommentCreateDto.java │ │ │ │ │ ├── CommentCountDto.java │ │ │ │ │ └── CommentDto.java │ │ │ │ ├── model │ │ │ │ │ └── Comment.java │ │ │ │ ├── repository │ │ │ │ │ └── CommentMainServiceRepository.java │ │ │ │ ├── controller │ │ │ │ │ ├── PublicCommentController.java │ │ │ │ │ ├── AdminCommentController.java │ │ │ │ │ └── PrivateCommentController.java │ │ │ │ └── mapper │ │ │ │ │ └── CommentMapper.java │ │ │ ├── compilation │ │ │ │ ├── service │ │ │ │ │ ├── CompilationPublicService.java │ │ │ │ │ ├── CompilationAdminService.java │ │ │ │ │ ├── CompilationPublicServiceImpl.java │ │ │ │ │ └── CompilationAdminServiceImpl.java │ │ │ │ ├── dto │ │ │ │ │ ├── CompilationShortDto.java │ │ │ │ │ ├── CompilationDto.java │ │ │ │ │ └── NewCompilationDto.java │ │ │ │ ├── repository │ │ │ │ │ └── CompilationMainServiceRepository.java │ │ │ │ ├── model │ │ │ │ │ └── Compilation.java │ │ │ │ ├── mapper │ │ │ │ │ └── CompilationMapper.java │ │ │ │ └── controller │ │ │ │ │ ├── CompilationPublicController.java │ │ │ │ │ └── CompilationAdminController.java │ │ │ ├── stat │ │ │ │ └── service │ │ │ │ │ ├── StatService.java │ │ │ │ │ └── StatServiceImpl.java │ │ │ └── util │ │ │ │ └── Util.java │ │ │ └── MainServiceApp.java │ │ └── resources │ │ ├── application.properties │ │ └── schema.sql ├── Dockerfile └── pom.xml ├── .github └── workflows │ ├── api-tests.yml │ └── wait-for-it.sh ├── suppressions.xml ├── .gitignore ├── docker-compose.yml ├── ewm-stats-service-spec.json └── pom.xml /README.md: -------------------------------------------------------------------------------- 1 | # java-explore-with-me 2 | Template repository for ExploreWithMe project. 3 | -------------------------------------------------------------------------------- /ewm-stat-service/stat_client/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=9091 2 | 3 | stats-service.url=http://localhost:9090 -------------------------------------------------------------------------------- /lombok.config: -------------------------------------------------------------------------------- 1 | config.stopBubbling = true 2 | lombok.anyconstructor.addconstructorproperties = false 3 | lombok.addLombokGeneratedAnnotation = true 4 | lombok.addSuppressWarnings = false -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/event/status/State.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.event.status; 2 | 3 | public enum State { 4 | PENDING, 5 | PUBLISHED, 6 | CANCELED 7 | } 8 | -------------------------------------------------------------------------------- /.github/workflows/api-tests.yml: -------------------------------------------------------------------------------- 1 | name: Explore With Me API Tests 2 | 3 | on: 4 | pull_request: 5 | 6 | jobs: 7 | build: 8 | uses: yandex-praktikum/java-explore-with-me/.github/workflows/api-tests.yml@ci -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/event/status/AdminEventStatus.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.event.status; 2 | 3 | public enum AdminEventStatus { 4 | PUBLISH_EVENT, 5 | REJECT_EVENT 6 | } 7 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/event/status/UserEventStatus.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.event.status; 2 | 3 | public enum UserEventStatus { 4 | 5 | SEND_TO_REVIEW, 6 | CANCEL_REVIEW 7 | } 8 | -------------------------------------------------------------------------------- /ewm-stat-service/stat_client/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM amazoncorretto:11 2 | ENV JAVA_TOOL_OPTIONS -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:9191 3 | COPY target/*.jar app.jar 4 | ENTRYPOINT ["java","-jar","/app.jar"] -------------------------------------------------------------------------------- /ewm-stat-service/stat_dto/src/main/java/ru/practicum/dto/Validator.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.dto; 2 | 3 | public interface Validator { 4 | 5 | interface Create {} 6 | 7 | interface Update {} 8 | } 9 | 10 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/request/Status.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.request; 2 | 3 | public enum Status { 4 | 5 | CONFIRMED, 6 | PENDING, 7 | REJECTED, 8 | CANCELED 9 | } 10 | -------------------------------------------------------------------------------- /ewm-main-service/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM amazoncorretto:11 2 | ENV JAVA_TOOL_OPTIONS -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8081 3 | ENV TZ=Europe/Moscow 4 | COPY target/*.jar app.jar 5 | ENTRYPOINT ["java","-jar","/app.jar"] -------------------------------------------------------------------------------- /ewm-stat-service/stat_server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM amazoncorretto:11 2 | ENV JAVA_TOOL_OPTIONS -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:9091 3 | ENV TZ=Europe/Moscow 4 | COPY target/*.jar app.jar 5 | ENTRYPOINT ["java","-jar","/app.jar"] -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/exception/NotUniqueException.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.exception; 2 | 3 | public class NotUniqueException extends RuntimeException { 4 | public NotUniqueException(String message) { 5 | super(message); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/exception/ConflictException.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.exception; 2 | 3 | public class ConflictException extends RuntimeException { 4 | public ConflictException(final String massage) { 5 | super(massage); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/exception/NotFoundException.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.exception; 2 | 3 | public class NotFoundException extends RuntimeException { 4 | public NotFoundException(final String massage) { 5 | super(massage); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/exception/StatParseException.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.exception; 2 | 3 | public class StatParseException extends RuntimeException { 4 | public StatParseException(final String massage) { 5 | super(massage); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/exception/BadRequestException.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.exception; 2 | 3 | public class BadRequestException extends RuntimeException { 4 | public BadRequestException(final String massage) { 5 | super(massage); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /ewm-stat-service/stat_server/src/main/java/ru/practicum/exception/WrongTimeException.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.exception; 2 | 3 | public class WrongTimeException extends RuntimeException { 4 | public WrongTimeException(final String massage) { 5 | super(massage); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /suppressions.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/user/dto/UserDto.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.user.dto; 2 | 3 | import lombok.*; 4 | 5 | 6 | @Data 7 | @Builder 8 | @AllArgsConstructor 9 | @NoArgsConstructor 10 | public class UserDto { 11 | 12 | private Long id; 13 | 14 | private String name; 15 | } 16 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/event/dto/EventCommentDto.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.event.dto; 2 | 3 | import lombok.*; 4 | 5 | @Getter 6 | @Setter 7 | @Builder 8 | @AllArgsConstructor 9 | @NoArgsConstructor 10 | public class EventCommentDto { 11 | 12 | private long id; 13 | 14 | private String title; 15 | } 16 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/event/location/dto/LocationDto.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.event.location.dto; 2 | 3 | 4 | import lombok.*; 5 | 6 | @Data 7 | @Builder 8 | @AllArgsConstructor 9 | @NoArgsConstructor 10 | public class LocationDto { 11 | 12 | private double lat; 13 | 14 | private double lon; 15 | } 16 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/user/dto/AdminUserDto.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.user.dto; 2 | 3 | import lombok.*; 4 | 5 | @Data 6 | @Builder 7 | @AllArgsConstructor 8 | @NoArgsConstructor 9 | public class AdminUserDto { 10 | private Long id; 11 | 12 | private String name; 13 | 14 | private String email; 15 | } 16 | -------------------------------------------------------------------------------- /ewm-stat-service/stat_server/src/main/java/ru/practicum/utill/Constants.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.utill; 2 | 3 | import java.time.format.DateTimeFormatter; 4 | 5 | public class Constants { 6 | 7 | public static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); 8 | public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; 9 | } 10 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/MainServiceApp.java: -------------------------------------------------------------------------------- 1 | package ru.practicum; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class MainServiceApp { 8 | public static void main(String[] args) { 9 | SpringApplication.run(MainServiceApp.class, args); 10 | } 11 | } -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/request/dto/RequestShortDto.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.request.dto; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | import ru.practicum.main.request.Status; 6 | 7 | import java.util.List; 8 | 9 | 10 | @Data 11 | @Builder 12 | public class RequestShortDto { 13 | private List requestIds; 14 | 15 | private Status status; 16 | } 17 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/category/service/CategoryPublicService.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.category.service; 2 | 3 | import ru.practicum.main.category.dto.CategoryDto; 4 | 5 | import java.util.List; 6 | 7 | public interface CategoryPublicService { 8 | List readAllCategories(Integer from, Integer size); 9 | 10 | CategoryDto readCategoryById(Long catId); 11 | } 12 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/comment/service/AdminCommentService.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.comment.service; 2 | 3 | 4 | import ru.practicum.main.comment.dto.CommentDto; 5 | 6 | import java.util.List; 7 | 8 | public interface AdminCommentService { 9 | void delete(Long comId); 10 | 11 | List search(String text); 12 | 13 | List findAllById(Long userId); 14 | } -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/event/dto/RequestShortDto.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.event.dto; 2 | 3 | import lombok.*; 4 | import ru.practicum.main.request.Status; 5 | 6 | import java.util.List; 7 | 8 | @Data 9 | @Builder 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class RequestShortDto { 13 | 14 | private List requestIds; 15 | 16 | private Status status; 17 | } 18 | -------------------------------------------------------------------------------- /ewm-stat-service/stat_server/src/main/java/ru/practicum/exception/ErrorResponse.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.exception; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | 6 | @Data 7 | @AllArgsConstructor 8 | public class ErrorResponse { 9 | 10 | private String status; 11 | 12 | private String reason; 13 | 14 | private String message; 15 | 16 | private String timestamp; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/category/service/CategoryAdminService.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.category.service; 2 | 3 | import ru.practicum.main.category.dto.CategoryDto; 4 | 5 | public interface CategoryAdminService { 6 | CategoryDto createCategory(CategoryDto categoryDto); 7 | 8 | void deleteCategory(Long catId); 9 | 10 | CategoryDto updateCategory(Long catId, CategoryDto categoryDto); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /ewm-stat-service/stat_server/src/main/java/ru/practicum/StatServerApplication.java: -------------------------------------------------------------------------------- 1 | package ru.practicum; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class StatServerApplication { 8 | public static void main(String[] args) { 9 | SpringApplication.run(StatServerApplication.class, args); 10 | } 11 | } -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/compilation/service/CompilationPublicService.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.compilation.service; 2 | 3 | import ru.practicum.main.compilation.dto.CompilationDto; 4 | 5 | import java.util.List; 6 | 7 | public interface CompilationPublicService { 8 | CompilationDto readCompilationById(Long compId); 9 | 10 | List readAllCompilations(Boolean pinned, int from, int size); 11 | } 12 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/request/service/RequestService.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.request.service; 2 | 3 | import ru.practicum.main.request.dto.RequestDto; 4 | 5 | import java.util.List; 6 | 7 | public interface RequestService { 8 | RequestDto createRequest(Long userId, Long eventId); 9 | 10 | List readAllRequests(Long userId); 11 | 12 | RequestDto cancelRequest(Long userId, Long requestId); 13 | } 14 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/user/service/UserService.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.user.service; 2 | 3 | import ru.practicum.main.user.dto.AdminUserDto; 4 | import ru.practicum.main.user.model.User; 5 | 6 | import java.util.List; 7 | 8 | public interface UserService { 9 | AdminUserDto createUser(User user); 10 | 11 | void deleteUser(Long userId); 12 | 13 | List readUsers(List idList, int from, int size); 14 | } 15 | -------------------------------------------------------------------------------- /ewm-stat-service/stat_server/src/main/resources/schema.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS stat ( 2 | id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, 3 | app VARCHAR(50) NOT NULL, 4 | uri VARCHAR(50) NOT NULL, 5 | ip VARCHAR(15) NOT NULL, 6 | time_stamp TIMESTAMP NOT NULL, 7 | CONSTRAINT pk_stat PRIMARY KEY (id) 8 | ); 9 | 10 | 11 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/comment/service/CommentService.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.comment.service; 2 | 3 | 4 | import ru.practicum.main.comment.dto.CommentDto; 5 | import ru.practicum.main.comment.dto.CommentShortDto; 6 | 7 | import java.util.List; 8 | 9 | public interface CommentService { 10 | 11 | CommentDto getComment(Long comId); 12 | 13 | List getCommentsByEvent(Long eventId, int from, int size); 14 | } 15 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/request/dto/RequestUpdateDto.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.request.dto; 2 | 3 | import lombok.Data; 4 | import ru.practicum.main.request.model.Request; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | @Data 10 | public class RequestUpdateDto { 11 | 12 | private List conformedRequest = new ArrayList<>(); 13 | 14 | private List canselRequest = new ArrayList<>(); 15 | } 16 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/comment/dto/CommentShortDto.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.comment.dto; 2 | 3 | import lombok.*; 4 | import ru.practicum.main.user.dto.UserDto; 5 | 6 | @Getter 7 | @Setter 8 | @Builder 9 | @AllArgsConstructor 10 | @NoArgsConstructor 11 | public class CommentShortDto { 12 | 13 | private long id; 14 | 15 | private String text; 16 | 17 | private UserDto author; 18 | 19 | private String createTime; 20 | } 21 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/user/dto/UserShortDto.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.user.dto; 2 | 3 | import lombok.*; 4 | 5 | import javax.validation.constraints.NotEmpty; 6 | import javax.validation.constraints.NotNull; 7 | 8 | @Builder 9 | @Getter 10 | @Setter 11 | @NoArgsConstructor 12 | @AllArgsConstructor 13 | public class UserShortDto { // Добавил 14 | @NotNull 15 | private Long id; 16 | @NotEmpty 17 | private String name; 18 | } 19 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/comment/dto/CommentCreateDto.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.comment.dto; 2 | 3 | import lombok.*; 4 | 5 | import javax.validation.constraints.NotBlank; 6 | import javax.validation.constraints.Size; 7 | 8 | @Getter 9 | @Setter 10 | @Builder 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | public class CommentCreateDto { 14 | 15 | @NotBlank 16 | @Size(min = 1, max = 1000) 17 | private String text; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/comment/dto/CommentCountDto.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.comment.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | @Getter 7 | @Setter 8 | public class CommentCountDto { 9 | 10 | private Long eventId; 11 | 12 | private Long commentCount; 13 | 14 | public CommentCountDto(Long eventId, Long commentCount) { 15 | this.eventId = eventId; 16 | this.commentCount = commentCount; 17 | } 18 | } -------------------------------------------------------------------------------- /ewm-stat-service/stat_server/src/main/java/ru/practicum/service/StatService.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.service; 2 | 3 | import ru.practicum.dto.StatDto; 4 | import ru.practicum.dto.StatResponseDto; 5 | 6 | import java.time.LocalDateTime; 7 | import java.util.List; 8 | 9 | public interface StatService { 10 | 11 | StatDto createStat(StatDto statDto); 12 | 13 | List readStat(LocalDateTime start, LocalDateTime end, List uris, boolean unique); 14 | } 15 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/event/location/repository/LocationMainServiceRepository.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.event.location.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import ru.practicum.main.event.location.model.Location; 5 | 6 | import java.util.Optional; 7 | 8 | public interface LocationMainServiceRepository extends JpaRepository { 9 | Optional findByLatAndLon(double lat, double lon); 10 | } 11 | -------------------------------------------------------------------------------- /ewm-stat-service/stat_dto/src/main/java/ru/practicum/dto/StatResponseDto.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.dto; 2 | 3 | import lombok.*; 4 | 5 | @Data 6 | @Builder 7 | @NoArgsConstructor 8 | public class StatResponseDto { 9 | 10 | private String app; 11 | 12 | private String uri; 13 | 14 | private long hits; 15 | 16 | public StatResponseDto(String app, String uri, long hits) { 17 | this.app = app; 18 | this.uri = uri; 19 | this.hits = hits; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/request/dto/RequestDto.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.request.dto; 2 | 3 | import lombok.*; 4 | import ru.practicum.main.request.Status; 5 | 6 | import java.time.LocalDateTime; 7 | 8 | @Data 9 | @Builder 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class RequestDto { 13 | private LocalDateTime created; 14 | 15 | private Long event; 16 | 17 | private Long id; 18 | 19 | private Long requester; 20 | 21 | private Status status; 22 | } 23 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/stat/service/StatService.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.stat.service; 2 | 3 | import ru.practicum.main.event.model.Event; 4 | 5 | import javax.servlet.http.HttpServletRequest; 6 | import java.util.Collection; 7 | import java.util.Map; 8 | 9 | public interface StatService { 10 | 11 | Map toConfirmedRequest(Collection list); 12 | 13 | Map toView(Collection list); 14 | 15 | void addHits(HttpServletRequest request); 16 | } 17 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/compilation/dto/CompilationShortDto.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.compilation.dto; 2 | 3 | import lombok.*; 4 | import ru.practicum.main.event.dto.EventDto; 5 | 6 | import java.util.List; 7 | 8 | 9 | @Data 10 | @Builder 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | public class CompilationShortDto { 14 | 15 | private List events; 16 | 17 | private Long id; 18 | 19 | private Boolean pinned; 20 | 21 | private String title; 22 | 23 | 24 | } 25 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/event/dto/RequestShortUpdateDto.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.event.dto; 2 | 3 | import lombok.*; 4 | import ru.practicum.main.request.dto.RequestDto; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | @Data 10 | @Builder 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | public class RequestShortUpdateDto { 14 | 15 | private List confirmedRequests = new ArrayList<>(); 16 | 17 | private List rejectedRequests = new ArrayList<>(); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/mainservice/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/compilation/service/CompilationAdminService.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.compilation.service; 2 | 3 | import ru.practicum.main.compilation.dto.CompilationDto; 4 | import ru.practicum.main.compilation.dto.NewCompilationDto; 5 | 6 | public interface CompilationAdminService { 7 | CompilationDto createCompilation(NewCompilationDto newCompilationDto); 8 | 9 | void deleteCompilation(Long compId); 10 | 11 | CompilationDto updateCompilation(Long compId, NewCompilationDto newCompilationDto); 12 | } 13 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/comment/dto/CommentDto.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.comment.dto; 2 | 3 | import lombok.*; 4 | import ru.practicum.main.event.dto.EventCommentDto; 5 | import ru.practicum.main.user.dto.UserDto; 6 | 7 | @Getter 8 | @Setter 9 | @Builder 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class CommentDto { 13 | 14 | private long id; 15 | 16 | private String text; 17 | 18 | private UserDto author; 19 | 20 | private EventCommentDto event; 21 | 22 | private String createTime; 23 | } 24 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/exception/handler/ErrorResponse.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.exception.handler; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class ErrorResponse { 7 | 8 | private String status; 9 | private String reason; 10 | private String message; 11 | private String timestamp; 12 | 13 | 14 | public ErrorResponse(String status, String reason, String message, String timestamp) { 15 | this.status = status; 16 | this.reason = reason; 17 | this.message = message; 18 | this.timestamp = timestamp; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/request/dto/ConfirmedRequestShortDto.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.request.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | 7 | @Getter 8 | @Setter 9 | @NoArgsConstructor 10 | public class ConfirmedRequestShortDto { 11 | 12 | private Long eventId; 13 | 14 | private Long confirmedRequestsCount; 15 | 16 | public ConfirmedRequestShortDto(Long eventId, Long confirmedRequestsCount) { 17 | this.eventId = eventId; 18 | this.confirmedRequestsCount = confirmedRequestsCount; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/compilation/dto/CompilationDto.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.compilation.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import ru.practicum.main.event.dto.EventShortDto; 8 | 9 | import java.util.List; 10 | 11 | @Data 12 | @Builder 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | public class CompilationDto { 16 | 17 | private List events; 18 | 19 | private Long id; 20 | 21 | private Boolean pinned; 22 | 23 | private String title; 24 | } 25 | -------------------------------------------------------------------------------- /ewm-stat-service/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | !**/src/main/**/target/ 4 | !**/src/test/**/target/ 5 | 6 | ### IntelliJ IDEA ### 7 | .idea/modules.xml 8 | .idea/jarRepositories.xml 9 | .idea/compiler.xml 10 | .idea/libraries/ 11 | *.iws 12 | *.iml 13 | *.ipr 14 | 15 | ### Eclipse ### 16 | .apt_generated 17 | .classpath 18 | .factorypath 19 | .project 20 | .settings 21 | .springBeans 22 | .sts4-cache 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | build/ 31 | !**/src/main/**/build/ 32 | !**/src/test/**/build/ 33 | 34 | ### VS Code ### 35 | .vscode/ 36 | 37 | ### Mac OS ### 38 | .DS_Store -------------------------------------------------------------------------------- /ewm-stat-service/stat_dto/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | !**/src/main/**/target/ 4 | !**/src/test/**/target/ 5 | 6 | ### IntelliJ IDEA ### 7 | .idea/modules.xml 8 | .idea/jarRepositories.xml 9 | .idea/compiler.xml 10 | .idea/libraries/ 11 | *.iws 12 | *.iml 13 | *.ipr 14 | 15 | ### Eclipse ### 16 | .apt_generated 17 | .classpath 18 | .factorypath 19 | .project 20 | .settings 21 | .springBeans 22 | .sts4-cache 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | build/ 31 | !**/src/main/**/build/ 32 | !**/src/test/**/build/ 33 | 34 | ### VS Code ### 35 | .vscode/ 36 | 37 | ### Mac OS ### 38 | .DS_Store -------------------------------------------------------------------------------- /ewm-stat-service/stat_client/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | !**/src/main/**/target/ 4 | !**/src/test/**/target/ 5 | 6 | ### IntelliJ IDEA ### 7 | .idea/modules.xml 8 | .idea/jarRepositories.xml 9 | .idea/compiler.xml 10 | .idea/libraries/ 11 | *.iws 12 | *.iml 13 | *.ipr 14 | 15 | ### Eclipse ### 16 | .apt_generated 17 | .classpath 18 | .factorypath 19 | .project 20 | .settings 21 | .springBeans 22 | .sts4-cache 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | build/ 31 | !**/src/main/**/build/ 32 | !**/src/test/**/build/ 33 | 34 | ### VS Code ### 35 | .vscode/ 36 | 37 | ### Mac OS ### 38 | .DS_Store -------------------------------------------------------------------------------- /ewm-stat-service/stat_server/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | !**/src/main/**/target/ 4 | !**/src/test/**/target/ 5 | 6 | ### IntelliJ IDEA ### 7 | .idea/modules.xml 8 | .idea/jarRepositories.xml 9 | .idea/compiler.xml 10 | .idea/libraries/ 11 | *.iws 12 | *.iml 13 | *.ipr 14 | 15 | ### Eclipse ### 16 | .apt_generated 17 | .classpath 18 | .factorypath 19 | .project 20 | .settings 21 | .springBeans 22 | .sts4-cache 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | build/ 31 | !**/src/main/**/build/ 32 | !**/src/test/**/build/ 33 | 34 | ### VS Code ### 35 | .vscode/ 36 | 37 | ### Mac OS ### 38 | .DS_Store -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/category/repository/CategoryMainServiceRepository.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.category.repository; 2 | 3 | import org.springframework.data.domain.Pageable; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.data.jpa.repository.Query; 6 | import ru.practicum.main.category.model.Category; 7 | 8 | import java.util.List; 9 | 10 | public interface CategoryMainServiceRepository extends JpaRepository { 11 | 12 | boolean existsByName(String name); 13 | 14 | @Query("SELECT c " + 15 | "FROM Category c ") 16 | List findAllCategories(Pageable pageable); 17 | } 18 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/event/service/EventAdminService.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.event.service; 2 | 3 | import ru.practicum.main.event.status.State; 4 | import ru.practicum.main.event.dto.AdminEventRequestDto; 5 | import ru.practicum.main.event.dto.EventFullDto; 6 | 7 | import java.time.LocalDateTime; 8 | import java.util.List; 9 | 10 | public interface EventAdminService { 11 | 12 | EventFullDto updateAdminEvent(Long eventId, AdminEventRequestDto requestAdminDto); 13 | 14 | List readAdminEvents(List users, List states, List categories, 15 | LocalDateTime start, LocalDateTime end, int from, int size); 16 | } 17 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/category/dto/CategoryDto.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.category.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import ru.practicum.dto.Validator; 8 | 9 | import javax.validation.constraints.NotBlank; 10 | import javax.validation.constraints.Size; 11 | 12 | @Data 13 | @Builder 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | public class CategoryDto { 17 | 18 | private Long id; 19 | 20 | @NotBlank(groups = {Validator.Create.class, Validator.Update.class}) 21 | @Size(min = 1, max = 50, groups = {Validator.Create.class, Validator.Update.class}) 22 | private String name; 23 | } 24 | -------------------------------------------------------------------------------- /ewm-stat-service/stat_server/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=9090 2 | 3 | spring.jpa.hibernate.ddl-auto=none 4 | spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL10Dialect 5 | spring.jpa.properties.hibernate.format_sql=true 6 | spring.sql.init.mode=always 7 | 8 | #--- 9 | spring.datasource.driverClassName=org.postgresql.Driver 10 | spring.datasource.url=jdbc:postgresql://stats_service-db:5432/stat_db 11 | spring.datasource.username=asd 12 | spring.datasource.password=123 13 | 14 | #--- 15 | spring.config.activate.on-profile=ci,test 16 | spring.datasource.driverClassName=org.h2.Driver 17 | spring.datasource.url=jdbc:h2:mem:stat_db 18 | spring.datasource.username=test 19 | spring.datasource.password=test -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/comment/service/PrivateCommentService.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.comment.service; 2 | 3 | 4 | import ru.practicum.main.comment.dto.CommentDto; 5 | import ru.practicum.main.comment.dto.CommentCreateDto; 6 | import ru.practicum.main.event.model.Event; 7 | 8 | import java.util.Collection; 9 | import java.util.Map; 10 | 11 | public interface PrivateCommentService { 12 | 13 | CommentDto createComment(Long userId, Long eventId, CommentCreateDto commentDto); 14 | 15 | void deleteComment(Long userId, Long comId); 16 | 17 | CommentDto patchComment(Long userId, Long comId, CommentCreateDto commentCreateDto); 18 | 19 | Map getCommentCount(Collection list); 20 | } 21 | -------------------------------------------------------------------------------- /ewm-stat-service/stat_server/src/main/java/ru/practicum/model/Stat.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.model; 2 | 3 | import lombok.*; 4 | 5 | import javax.persistence.*; 6 | import java.time.LocalDateTime; 7 | 8 | @Data 9 | @Builder 10 | @EqualsAndHashCode 11 | @Entity 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class Stat { 15 | 16 | @Id 17 | @GeneratedValue(strategy = GenerationType.IDENTITY) 18 | @Column(name = "id") 19 | private long statId; 20 | 21 | @Column(name = "app") 22 | private String app; 23 | 24 | @Column(name = "ip") 25 | private String ip; 26 | 27 | @Column(name = "time_stamp") 28 | private LocalDateTime timestamp; 29 | 30 | @Column(name = "uri") 31 | private String uri; 32 | } 33 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/category/model/Category.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.category.model; 2 | 3 | import lombok.*; 4 | 5 | import javax.persistence.*; 6 | 7 | @Getter 8 | @Setter 9 | @Builder 10 | @Entity 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | @Table(name = "categories") 14 | public class Category { 15 | 16 | @Id 17 | @GeneratedValue(strategy = GenerationType.IDENTITY) 18 | @Column(name = "id") 19 | private Long id; 20 | 21 | @Column(name = "cat_name") 22 | private String name; 23 | 24 | @Override 25 | public String toString() { 26 | return "Categories{" + 27 | "id=" + id + 28 | ", name='" + name + '\'' + 29 | '}'; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/event/service/EventPublicService.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.event.service; 2 | 3 | import ru.practicum.main.event.dto.EventFullDto; 4 | import ru.practicum.main.event.dto.EventShortDto; 5 | 6 | import javax.servlet.http.HttpServletRequest; 7 | import java.time.LocalDateTime; 8 | import java.util.List; 9 | 10 | public interface EventPublicService { 11 | List readPublicEvents(String text, List categories, Boolean paid, LocalDateTime rangeStart, 12 | LocalDateTime rangeEnd, Boolean onlyAvailable, String sort, Integer from, Integer size, HttpServletRequest request); 13 | 14 | EventFullDto getPublicEvent(Long id, HttpServletRequest request); 15 | } 16 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | main.port=8080 2 | stats-service.url=http://stats-server:9090 3 | main_app=ewm-main-service 4 | spring.jpa.hibernate.ddl-auto=none 5 | spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL10Dialect 6 | spring.jpa.properties.hibernate.format_sql=true 7 | spring.sql.init.mode=always 8 | 9 | #--- 10 | spring.datasource.driverClassName=org.postgresql.Driver 11 | spring.datasource.url=${MAIN_DB} 12 | spring.datasource.username=${MAIN_USER} 13 | spring.datasource.password=${MAIN_PASSWORD} 14 | 15 | spring.config.activate.on-profile=ci,test 16 | spring.datasource.driverClassName=org.h2.Driver 17 | spring.datasource.url=jdbc:h2:mem:ewm_db 18 | spring.datasource.username=test 19 | spring.datasource.password=test -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/compilation/repository/CompilationMainServiceRepository.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.compilation.repository; 2 | 3 | import org.springframework.data.domain.Pageable; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.data.jpa.repository.Query; 6 | import ru.practicum.main.compilation.model.Compilation; 7 | 8 | import java.util.List; 9 | 10 | public interface CompilationMainServiceRepository extends JpaRepository { 11 | 12 | 13 | @Query("SELECT c " + 14 | "FROM Compilation c " + 15 | "WHERE c.pinned = ?1") 16 | List findAllByPinned(Boolean pinned, Pageable pageable); 17 | 18 | boolean existsByTitle(String title); 19 | } 20 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/event/dto/EventDto.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.event.dto; 2 | 3 | import lombok.*; 4 | import ru.practicum.main.category.model.Category; 5 | import ru.practicum.main.user.model.User; 6 | 7 | import java.time.LocalDateTime; 8 | 9 | @Getter 10 | @Setter 11 | @Builder 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class EventDto { 15 | private Long id; 16 | 17 | private String annotation; 18 | 19 | private Category category; 20 | 21 | private Long confirmedRequests; 22 | 23 | private LocalDateTime eventDate; 24 | 25 | private User initiator; 26 | 27 | private Boolean paid; 28 | 29 | private String title; 30 | 31 | private Long views; 32 | 33 | private Long commentCount; 34 | } 35 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/event/dto/EventShortDto.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.event.dto; 2 | 3 | import lombok.Builder; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import ru.practicum.main.category.dto.CategoryDto; 7 | import ru.practicum.main.user.dto.UserShortDto; 8 | 9 | @Getter 10 | @Setter 11 | @Builder 12 | public class EventShortDto { 13 | private Long id; 14 | 15 | private String annotation; 16 | 17 | private CategoryDto category; 18 | 19 | private Long confirmedRequests; 20 | 21 | private String eventDate; 22 | 23 | private UserShortDto initiator; 24 | 25 | private Boolean paid; 26 | 27 | private String title; 28 | 29 | private Long views; 30 | 31 | private Long commentCount; 32 | 33 | } 34 | 35 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/user/repository/UserMainServiceRepository.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.user.repository; 2 | 3 | import org.springframework.data.domain.Pageable; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.data.jpa.repository.Query; 6 | import ru.practicum.main.user.model.User; 7 | 8 | import java.util.List; 9 | 10 | public interface UserMainServiceRepository extends JpaRepository { 11 | 12 | @Query("SELECT u " + 13 | "FROM User u " + 14 | "WHERE u.id IN ?1 ") 15 | List findAllById(List id, Pageable pageable); 16 | 17 | @Query("SELECT u " + 18 | "FROM User u") 19 | List findAllUser(Pageable pageable); 20 | 21 | Boolean existsByEmail(String email); 22 | } 23 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/user/dto/UserDtoReceived.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.user.dto; 2 | 3 | import lombok.*; 4 | import ru.practicum.dto.Validator; 5 | 6 | import javax.validation.constraints.Email; 7 | import javax.validation.constraints.NotBlank; 8 | import javax.validation.constraints.Size; 9 | 10 | @Data 11 | @Builder 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class UserDtoReceived { 15 | 16 | private Long id; 17 | 18 | @Email(groups = {Validator.Create.class}) 19 | @Size(min = 6, max = 254, groups = {Validator.Create.class}) 20 | @NotBlank(groups = {Validator.Create.class}) 21 | private String email; 22 | 23 | @NotBlank(groups = {Validator.Create.class}) 24 | @Size(min = 2, max = 250, groups = {Validator.Create.class}) 25 | private String name; 26 | } 27 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/compilation/dto/NewCompilationDto.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.compilation.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import ru.practicum.dto.Validator; 8 | 9 | import javax.validation.constraints.NotBlank; 10 | import javax.validation.constraints.Size; 11 | import java.util.HashSet; 12 | import java.util.Set; 13 | 14 | @Data 15 | @Builder 16 | @AllArgsConstructor 17 | @NoArgsConstructor 18 | public class NewCompilationDto { 19 | 20 | private Set events = new HashSet<>(); 21 | 22 | private Boolean pinned; 23 | 24 | @NotBlank(groups = {Validator.Create.class}) 25 | @Size(max = 50, groups = {Validator.Create.class, Validator.Update.class}) 26 | private String title; 27 | } 28 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/event/location/mapper/LocationMapper.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.event.location.mapper; 2 | 3 | import lombok.experimental.UtilityClass; 4 | import ru.practicum.main.event.location.dto.LocationDto; 5 | import ru.practicum.main.event.location.model.Location; 6 | 7 | @UtilityClass 8 | public class LocationMapper { 9 | public Location toLocation(LocationDto locationDto) { 10 | return Location.builder() 11 | .lon(locationDto.getLon()) 12 | .lat(locationDto.getLat()) 13 | .build(); 14 | } 15 | 16 | public LocationDto toLocationDto(Location location) { 17 | return LocationDto.builder() 18 | .lat(location.getLat()) 19 | .lon(location.getLon()) 20 | .build(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/event/dto/EventAdminDto.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.event.dto; 2 | 3 | import lombok.*; 4 | import ru.practicum.main.event.status.AdminEventStatus; 5 | import ru.practicum.main.event.location.model.Location; 6 | 7 | import java.time.LocalDateTime; 8 | 9 | 10 | 11 | @Data 12 | @Builder 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | public class EventAdminDto { 16 | 17 | private String annotation; 18 | 19 | private Long category; 20 | 21 | private String description; 22 | 23 | private LocalDateTime eventDate; 24 | 25 | private Location location; 26 | 27 | private Boolean paid; 28 | 29 | private Integer participantLimit; 30 | 31 | private Boolean requestModeration; 32 | 33 | private String title; 34 | 35 | private AdminEventStatus stateAction; 36 | } 37 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/user/model/User.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.user.model; 2 | 3 | import lombok.*; 4 | 5 | import javax.persistence.*; 6 | 7 | @Getter 8 | @Setter 9 | @Builder 10 | @Entity 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | @Table(name = "users") 14 | public class User { 15 | 16 | @Id 17 | @GeneratedValue(strategy = GenerationType.IDENTITY) 18 | @Column(name = "id") 19 | private Long id; 20 | 21 | @Column(name = "user_name") 22 | private String name; 23 | 24 | @Column(name = "email") 25 | private String email; 26 | 27 | 28 | @Override 29 | public String toString() { 30 | return "User{" + 31 | "id=" + id + 32 | ", name='" + name + '\'' + 33 | ", email='" + email + '\'' + 34 | '}'; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/event/location/model/Location.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.event.location.model; 2 | 3 | 4 | import lombok.*; 5 | 6 | import javax.persistence.*; 7 | 8 | @Getter 9 | @Setter 10 | @Builder 11 | @Entity 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | @Table(name = "location") 15 | public class Location { 16 | 17 | @Id 18 | @GeneratedValue(strategy = GenerationType.IDENTITY) 19 | @Column(name = "id") 20 | private Long id; 21 | 22 | @Column(name = "lat") 23 | private double lat; 24 | 25 | @Column(name = "lon") 26 | private double lon; 27 | 28 | @Override 29 | public String toString() { 30 | return "Location{" + 31 | "id=" + id + 32 | ", lat='" + lat + '\'' + 33 | ", lon='" + lon + '\'' + 34 | '}'; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ewm-stat-service/stat_server/src/main/java/ru/practicum/model/mapper/StatMapper.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.model.mapper; 2 | 3 | import ru.practicum.dto.StatDto; 4 | import ru.practicum.model.Stat; 5 | 6 | 7 | public class StatMapper { 8 | private StatMapper() { 9 | } 10 | 11 | public static Stat toStat(StatDto statDto) { 12 | 13 | return Stat.builder() 14 | .ip(statDto.getIp()) 15 | .uri(statDto.getUri()) 16 | .timestamp(statDto.getTimestamp()) 17 | .app(statDto.getApp()) 18 | .build(); 19 | } 20 | 21 | public static StatDto toStatDto(Stat stat) { 22 | return StatDto.builder() 23 | .timestamp(stat.getTimestamp()) 24 | .app(stat.getApp()) 25 | .uri(stat.getUri()) 26 | .ip(stat.getIp()) 27 | .build(); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/util/Util.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.util; 2 | 3 | import org.springframework.data.domain.PageRequest; 4 | import org.springframework.data.domain.Sort; 5 | 6 | public class Util { 7 | 8 | public static final String TIME_STRING = "yyyy-MM-dd HH:mm:ss"; 9 | 10 | private Util() { 11 | 12 | } 13 | 14 | public static PageRequest createPageRequestAsc(int from, int size) { 15 | return PageRequest.of(from, size, Sort.Direction.ASC, "id"); 16 | } 17 | 18 | public static PageRequest createPageRequestDesc(String sortBy, int from, int size) { 19 | return PageRequest.of(from > 0 ? from / size : 0, size, Sort.by(sortBy).descending()); 20 | } 21 | 22 | public static PageRequest createPageRequestAsc(String sortBy, int from, int size) { 23 | return PageRequest.of(from > 0 ? from / size : 0, size, Sort.by(sortBy).ascending()); 24 | } 25 | 26 | } 27 | 28 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/event/dto/PatchEventDto.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.event.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import ru.practicum.main.event.location.model.Location; 8 | import ru.practicum.main.event.status.UserEventStatus; 9 | 10 | import java.time.LocalDateTime; 11 | 12 | 13 | @Data 14 | @Builder 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | public class PatchEventDto { 18 | 19 | private String annotation; 20 | 21 | private Long category; 22 | 23 | private String description; 24 | 25 | private LocalDateTime eventDate; 26 | 27 | private Location location; 28 | 29 | private Boolean paid; 30 | 31 | private Integer participantLimit; 32 | 33 | private Boolean requestModeration; 34 | 35 | private String title; 36 | 37 | private UserEventStatus stateAction; 38 | } 39 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/comment/model/Comment.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.comment.model; 2 | 3 | import lombok.*; 4 | import ru.practicum.main.event.model.Event; 5 | import ru.practicum.main.user.model.User; 6 | 7 | import javax.persistence.*; 8 | import java.time.LocalDateTime; 9 | 10 | @Getter 11 | @Setter 12 | @Builder 13 | @Entity 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | @Table(name = "comments") 17 | public class Comment { 18 | 19 | @Id 20 | @GeneratedValue(strategy = GenerationType.IDENTITY) 21 | private Long id; 22 | 23 | @Column(name = "textual_content") 24 | private String text; 25 | 26 | @ManyToOne 27 | @JoinColumn(name = "author_id") 28 | private User author; 29 | 30 | @ManyToOne 31 | @JoinColumn(name = "event_id") 32 | private Event event; 33 | 34 | @Column(name = "create_time") 35 | private LocalDateTime createTime; 36 | 37 | @Column(name = "patch_time") 38 | private LocalDateTime patchTime; 39 | } 40 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/category/mapper/CategoryMapper.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.category.mapper; 2 | 3 | import lombok.experimental.UtilityClass; 4 | import ru.practicum.main.category.dto.CategoryDto; 5 | import ru.practicum.main.category.model.Category; 6 | 7 | import java.util.List; 8 | import java.util.stream.Collectors; 9 | 10 | @UtilityClass 11 | public class CategoryMapper { 12 | 13 | public CategoryDto toCategoryDto(Category category) { 14 | return CategoryDto.builder() 15 | .id(category.getId()) 16 | .name(category.getName()) 17 | .build(); 18 | } 19 | 20 | public Category toCategories(CategoryDto categoryDto) { 21 | return Category.builder() 22 | .name(categoryDto.getName()) 23 | .build(); 24 | } 25 | 26 | public List toListCategoriesDto(List list) { 27 | return list.stream().map(CategoryMapper::toCategoryDto).collect(Collectors.toList()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ewm-stat-service/stat_dto/src/main/java/ru/practicum/dto/StatDto.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.dto; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import lombok.*; 5 | 6 | import javax.validation.constraints.NotBlank; 7 | import javax.validation.constraints.NotNull; 8 | import javax.validation.constraints.Size; 9 | import java.time.LocalDateTime; 10 | 11 | @Data 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | @Builder 15 | public class StatDto { 16 | 17 | @NotBlank(groups = Validator.Create.class) 18 | @Size(max = 50, groups = Validator.Create.class) 19 | private String app; 20 | 21 | @NotBlank(groups = Validator.Create.class) 22 | @Size(max = 50, groups = Validator.Create.class) 23 | private String uri; 24 | 25 | @NotBlank(groups = Validator.Create.class) 26 | @Size(max = 15, groups = Validator.Create.class) 27 | private String ip; 28 | 29 | @NotNull(groups = Validator.Create.class) 30 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", shape = JsonFormat.Shape.STRING) 31 | private LocalDateTime timestamp; 32 | } 33 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/request/repository/RequestMainServiceRepository.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.request.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import org.springframework.data.jpa.repository.Query; 5 | import ru.practicum.main.request.dto.ConfirmedRequestShortDto; 6 | import ru.practicum.main.request.model.Request; 7 | 8 | import java.util.List; 9 | 10 | public interface RequestMainServiceRepository extends JpaRepository { 11 | 12 | @Query("SELECT new ru.practicum.main.request.dto.ConfirmedRequestShortDto(r.event.id , count(r.id)) " + 13 | "FROM Request r " + 14 | "WHERE r.event.id in ?1 " + 15 | "AND r.status = 'CONFIRMED' " + 16 | "GROUP BY r.event.id ") 17 | List countByEventId(List longs); 18 | 19 | boolean existsByRequesterIdAndEventId(long userId, long eventId); 20 | 21 | List findAllByRequesterId(long userId); 22 | 23 | List findAllByEventId(long eventId); 24 | } 25 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/event/service/EventPrivateService.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.event.service; 2 | 3 | import ru.practicum.main.request.dto.RequestDto; 4 | import ru.practicum.main.event.dto.RequestShortDto; 5 | import ru.practicum.main.event.dto.RequestShortUpdateDto; 6 | import ru.practicum.main.event.dto.EventFullDto; 7 | import ru.practicum.main.event.dto.EventRequestDto; 8 | import ru.practicum.main.event.dto.UpdateEventDto; 9 | 10 | import java.util.List; 11 | 12 | public interface EventPrivateService { 13 | EventFullDto createEvent(Long userId, EventRequestDto eventRequestDto); 14 | 15 | List readEventByUserId(Long userId, int from, int size); 16 | 17 | EventFullDto readEventByUserIdAndEventId(Long userId, Long eventId); 18 | 19 | EventFullDto updateEvent(Long userId, Long eventId, UpdateEventDto receivedDto); 20 | 21 | List readRequestByUserIdAndEventId(Long userId, Long eventId); 22 | 23 | RequestShortUpdateDto updateRequestByOwner(Long userId, Long eventId, RequestShortDto requestShortDto); 24 | 25 | } 26 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/event/dto/EventFullDto.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.event.dto; 2 | 3 | import lombok.*; 4 | import ru.practicum.main.category.dto.CategoryDto; 5 | import ru.practicum.main.event.location.dto.LocationDto; 6 | import ru.practicum.main.event.status.State; 7 | import ru.practicum.main.user.dto.UserDto; 8 | 9 | @Data 10 | @Builder 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | public class EventFullDto { 14 | private Long id; 15 | 16 | private String annotation; 17 | 18 | private CategoryDto category; 19 | 20 | private String createdOn; 21 | 22 | private String description; 23 | 24 | private String eventDate; 25 | 26 | private UserDto initiator; 27 | 28 | private LocationDto location; 29 | 30 | private Boolean paid; 31 | 32 | private Integer participantLimit; 33 | 34 | private Boolean requestModeration; 35 | 36 | private State state; 37 | 38 | private String title; 39 | 40 | private Long views; 41 | 42 | private Long confirmedRequests; 43 | 44 | private String publishedOn; 45 | } 46 | -------------------------------------------------------------------------------- /ewm-stat-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | ru.practicum 8 | explore-with-me 9 | 0.0.1-SNAPSHOT 10 | ../pom.xml 11 | 12 | 13 | 14 | Stat server 15 | 16 | stat_client 17 | stat_dto 18 | stat_server 19 | 20 | 21 | ewm-stat-service 22 | pom 23 | 24 | 25 | 11 26 | 11 27 | UTF-8 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/comment/repository/CommentMainServiceRepository.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.comment.repository; 2 | 3 | import org.springframework.data.domain.Pageable; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.data.jpa.repository.Query; 6 | import ru.practicum.main.comment.dto.CommentCountDto; 7 | import ru.practicum.main.comment.model.Comment; 8 | 9 | import java.util.List; 10 | 11 | 12 | public interface CommentMainServiceRepository extends JpaRepository { 13 | 14 | List findAllByEventId(Long eventId, Pageable pageable); 15 | 16 | @Query("select new ru.practicum.main.comment.dto.CommentCountDto(c.event.id, count(c.id)) " + 17 | "from Comment as c " + 18 | "where c.event.id in ?1 " + 19 | "group by c.event.id") 20 | List findAllCommentCount(List listEventId); 21 | 22 | @Query("select c " + 23 | "from Comment as c " + 24 | "where lower(c.text) like concat('%', lower(?1), '%') ") 25 | List findAllByText(String text); 26 | 27 | List findAllByAuthorId(Long userId); 28 | } 29 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/compilation/model/Compilation.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.compilation.model; 2 | 3 | import lombok.*; 4 | import ru.practicum.main.event.model.Event; 5 | 6 | import javax.persistence.*; 7 | import java.util.Set; 8 | 9 | @Getter 10 | @Setter 11 | @Builder 12 | @Entity 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | @Table(name = "compilations") 16 | public class Compilation { 17 | 18 | @Id 19 | @GeneratedValue(strategy = GenerationType.IDENTITY) 20 | @Column(name = "id") 21 | private Long id; 22 | 23 | @Column(name = "pinned") 24 | private Boolean pinned; 25 | 26 | @Column(name = "title") 27 | private String title; 28 | 29 | @ManyToMany 30 | @JoinTable(name = "compilations_events", 31 | joinColumns = @JoinColumn(name = "compilations_id"), 32 | inverseJoinColumns = @JoinColumn(name = "events_id")) 33 | private Set events; 34 | 35 | @Override 36 | public String toString() { 37 | return "Compilations{" + 38 | "id=" + id + 39 | ", pinned=" + pinned + 40 | ", title='" + title + '\'' + 41 | ", events=" + events + 42 | '}'; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/event/dto/EventRequestDto.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.event.dto; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import lombok.*; 5 | import ru.practicum.main.event.location.dto.LocationDto; 6 | 7 | import javax.validation.Valid; 8 | import javax.validation.constraints.*; 9 | import java.time.LocalDateTime; 10 | 11 | @Data 12 | @Builder 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | public class EventRequestDto { 16 | 17 | @NotBlank 18 | @Size(min = 20, max = 2000) 19 | private String annotation; 20 | 21 | @NotNull 22 | private Long category; 23 | 24 | @NotBlank 25 | @Size(min = 20, max = 7000) 26 | private String description; 27 | 28 | @Future 29 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", shape = JsonFormat.Shape.STRING) 30 | @NotNull 31 | private LocalDateTime eventDate; 32 | 33 | @Valid 34 | @NotNull 35 | private LocationDto location; 36 | 37 | private boolean paid; 38 | 39 | @PositiveOrZero 40 | private int participantLimit = 0; 41 | 42 | @NotNull 43 | private boolean requestModeration = true; 44 | 45 | @NotBlank 46 | @Size(min = 3, max = 120) 47 | private String title; 48 | 49 | } 50 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/event/dto/EventFullWithComment.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.event.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import ru.practicum.main.category.model.Category; 8 | import ru.practicum.main.comment.model.Comment; 9 | import ru.practicum.main.event.location.model.Location; 10 | import ru.practicum.main.event.status.State; 11 | import ru.practicum.main.user.model.User; 12 | 13 | import java.util.List; 14 | 15 | @Data 16 | @Builder 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | public class EventFullWithComment { 20 | private Long id; 21 | 22 | private String annotation; 23 | 24 | private Category category; 25 | 26 | private String createdOn; 27 | 28 | private String description; 29 | 30 | private String eventDate; 31 | 32 | private User initiator; 33 | 34 | private Location location; 35 | 36 | private Boolean paid; 37 | 38 | private Integer participantLimit; 39 | 40 | private Boolean requestModeration; 41 | 42 | private State state; 43 | 44 | private String title; 45 | 46 | private Long views; 47 | 48 | private Long confirmedRequests; 49 | 50 | private String publishedOn; 51 | 52 | private List comments; 53 | } 54 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/request/model/Request.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.request.model; 2 | 3 | import lombok.*; 4 | import ru.practicum.main.request.Status; 5 | import ru.practicum.main.event.model.Event; 6 | import ru.practicum.main.user.model.User; 7 | 8 | import javax.persistence.*; 9 | import java.time.LocalDateTime; 10 | 11 | @Getter 12 | @Setter 13 | @Builder 14 | @Entity 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | @Table(name = "request") 18 | public class Request { 19 | 20 | @Id 21 | @GeneratedValue(strategy = GenerationType.IDENTITY) 22 | @Column(name = "id") 23 | private long id; 24 | 25 | @Column(name = "created") 26 | private LocalDateTime created; 27 | 28 | @ManyToOne 29 | @JoinColumn(name = "event_id") 30 | private Event event; 31 | 32 | @ManyToOne 33 | @JoinColumn(name = "requester_id") 34 | private User requester; 35 | 36 | @Column(name = "status") 37 | @Enumerated(EnumType.STRING) 38 | private Status status; 39 | 40 | @Override 41 | public String toString() { 42 | return "Request{" + 43 | "id=" + id + 44 | ", created=" + created + 45 | ", event=" + event + 46 | ", requester=" + requester + 47 | ", status=" + status + 48 | '}'; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/event/dto/EventFullWithCommentDto.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.event.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import ru.practicum.main.category.dto.CategoryDto; 8 | import ru.practicum.main.comment.dto.CommentShortDto; 9 | import ru.practicum.main.event.location.dto.LocationDto; 10 | import ru.practicum.main.event.status.State; 11 | import ru.practicum.main.user.dto.UserDto; 12 | 13 | import java.util.List; 14 | 15 | @Data 16 | @Builder 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | public class EventFullWithCommentDto { 20 | private Long id; 21 | 22 | private String annotation; 23 | 24 | private CategoryDto category; 25 | 26 | private String createdOn; 27 | 28 | private String description; 29 | 30 | private String eventDate; 31 | 32 | private UserDto initiator; 33 | 34 | private LocationDto location; 35 | 36 | private Boolean paid; 37 | 38 | private Integer participantLimit; 39 | 40 | private Boolean requestModeration; 41 | 42 | private State state; 43 | 44 | private String title; 45 | 46 | private Long views; 47 | 48 | private Long confirmedRequests; 49 | 50 | private String publishedOn; 51 | 52 | private List comments; 53 | } 54 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | services: 3 | 4 | stats-server: 5 | build: ./ewm-stat-service/stat_server 6 | 7 | image: 8 | stat_server:latest 9 | container_name: stat_server 10 | 11 | ports: 12 | - "9090:9090" 13 | - "9091:9091" 14 | 15 | depends_on: 16 | - stats_service-db 17 | environment: 18 | - STAT_URL_DB=jdbc:postgresql://state_server-db:5432/stat_db 19 | - STAT_USERNAME_DB=asd 20 | - STAT_PASSWORD_DB=123 21 | 22 | 23 | stats_service-db: 24 | image: postgres:15-alpine 25 | container_name: stat_server-db 26 | ports: 27 | - "6666:5432" 28 | environment: 29 | - POSTGRES_DB=stat_db 30 | - POSTGRES_USER=asd 31 | - POSTGRES_PASSWORD=123 32 | 33 | 34 | ewm-service: 35 | build: ./ewm-main-service 36 | image: 37 | ewm-service:latest 38 | container_name: ewm-service 39 | 40 | ports: 41 | - "8080:8080" 42 | - "8081:8081" 43 | 44 | depends_on: 45 | - ewm-db 46 | environment: 47 | - MAIN_DB=jdbc:postgresql://postgres-main-db:5432/ewm_db 48 | - MAIN_USER=postgres 49 | - MAIN_PASSWORD=123 50 | 51 | ewm-db: 52 | image: postgres:15 53 | container_name: postgres-main-db 54 | ports: 55 | - "6464:5432" 56 | environment: 57 | - POSTGRES_DB=ewm_db 58 | - POSTGRES_USER=postgres 59 | - POSTGRES_PASSWORD=123 -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/event/dto/UpdateEventDto.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.event.dto; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import lombok.*; 5 | import ru.practicum.dto.Validator; 6 | import ru.practicum.main.event.location.dto.LocationDto; 7 | import ru.practicum.main.event.status.UserEventStatus; 8 | 9 | import javax.validation.constraints.Future; 10 | import javax.validation.constraints.PositiveOrZero; 11 | import javax.validation.constraints.Size; 12 | import java.time.LocalDateTime; 13 | 14 | @Data 15 | @Builder 16 | @AllArgsConstructor 17 | @NoArgsConstructor 18 | public class UpdateEventDto { 19 | 20 | @Size(min = 20, max = 2000, groups = Validator.Update.class) 21 | private String annotation; 22 | 23 | private Long category; 24 | 25 | @Size(min = 20, max = 7000, groups = Validator.Update.class) 26 | private String description; 27 | 28 | @Future(groups = Validator.Update.class) 29 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", shape = JsonFormat.Shape.STRING) 30 | private LocalDateTime eventDate; 31 | 32 | private LocationDto location; 33 | 34 | private Boolean paid; 35 | 36 | @PositiveOrZero(groups = Validator.Update.class) 37 | private Integer participantLimit; 38 | 39 | private Boolean requestModeration; 40 | 41 | @Size(min = 3, max = 120, groups = Validator.Update.class) 42 | private String title; 43 | 44 | private UserEventStatus stateAction; 45 | } 46 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/event/dto/AdminEventRequestDto.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.event.dto; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | import ru.practicum.dto.Validator; 9 | import ru.practicum.main.event.location.dto.LocationDto; 10 | import ru.practicum.main.event.status.AdminEventStatus; 11 | 12 | import javax.validation.constraints.Future; 13 | import javax.validation.constraints.PositiveOrZero; 14 | import javax.validation.constraints.Size; 15 | import java.time.LocalDateTime; 16 | 17 | 18 | @Data 19 | @Builder 20 | @AllArgsConstructor 21 | @NoArgsConstructor 22 | public class AdminEventRequestDto { 23 | 24 | @Size(min = 20, max = 2000, groups = Validator.Update.class) 25 | private String annotation; 26 | 27 | private Long category; 28 | 29 | @Size(min = 20, max = 7000, groups = Validator.Update.class) 30 | private String description; 31 | 32 | @Future(groups = Validator.Update.class) 33 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", shape = JsonFormat.Shape.STRING) 34 | private LocalDateTime eventDate; 35 | 36 | private LocationDto location; 37 | 38 | private Boolean paid; 39 | 40 | @PositiveOrZero(groups = Validator.Update.class) 41 | private Integer participantLimit; 42 | 43 | private Boolean requestModeration; 44 | 45 | @Size(min = 3, max = 120, groups = Validator.Update.class) 46 | private String title; 47 | 48 | private AdminEventStatus stateAction; 49 | } 50 | -------------------------------------------------------------------------------- /ewm-stat-service/stat_dto/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | ru.practicum 8 | ewm-stat-service 9 | 0.0.1-SNAPSHOT 10 | ../pom.xml 11 | 12 | 13 | stat_dto 14 | 15 | 16 | 17 | org.projectlombok 18 | lombok 19 | true 20 | 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-configuration-processor 25 | true 26 | 27 | 28 | 29 | jakarta.validation 30 | jakarta.validation-api 31 | 32 | 33 | com.fasterxml.jackson.core 34 | jackson-annotations 35 | 36 | 37 | org.springframework 38 | spring-context 39 | 40 | 41 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/category/controller/CategoryPublicController.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.category.controller; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.http.ResponseEntity; 6 | import org.springframework.validation.annotation.Validated; 7 | import org.springframework.web.bind.annotation.*; 8 | import ru.practicum.main.category.dto.CategoryDto; 9 | import ru.practicum.main.category.service.CategoryPublicService; 10 | 11 | import javax.validation.constraints.Positive; 12 | import javax.validation.constraints.PositiveOrZero; 13 | import java.util.List; 14 | 15 | @RestController 16 | @RequiredArgsConstructor 17 | @Validated 18 | @RequestMapping(path = "/categories") 19 | @Slf4j 20 | public class CategoryPublicController { 21 | 22 | private final CategoryPublicService service; 23 | 24 | @GetMapping 25 | public ResponseEntity> readAllCategories(@RequestParam(defaultValue = "0") @PositiveOrZero int from, 26 | @RequestParam(defaultValue = "10") @Positive int size) { 27 | log.info("Calling the POST request to - /categories - endpoint"); 28 | return ResponseEntity 29 | .ok(service.readAllCategories(from, size)); 30 | } 31 | 32 | @GetMapping("/{catId}") 33 | public ResponseEntity readCategoryById(@PathVariable Long catId) { 34 | log.info("Calling the GET request to - /categories/{catId} - endpoint"); 35 | return ResponseEntity 36 | .ok(service.readCategoryById(catId)); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/user/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.user.mapper; 2 | 3 | import lombok.experimental.UtilityClass; 4 | import ru.practicum.main.user.dto.AdminUserDto; 5 | import ru.practicum.main.user.dto.UserDto; 6 | import ru.practicum.main.user.dto.UserDtoReceived; 7 | import ru.practicum.main.user.dto.UserShortDto; 8 | import ru.practicum.main.user.model.User; 9 | 10 | import java.util.List; 11 | import java.util.stream.Collectors; 12 | 13 | @UtilityClass 14 | public class UserMapper { 15 | 16 | public UserDto toUserDto(User user) { 17 | return UserDto.builder() 18 | .name(user.getName()) 19 | .id(user.getId()) 20 | .build(); 21 | } 22 | 23 | public User toUser(UserDtoReceived userDto) { 24 | return User.builder() 25 | .email(userDto.getEmail()) 26 | .name(userDto.getName()) 27 | .build(); 28 | } 29 | 30 | public static UserShortDto toUserShortDto(User user) { 31 | return UserShortDto.builder() 32 | .id(user.getId()) 33 | .name(user.getName()) 34 | .build(); 35 | } 36 | 37 | public AdminUserDto toAdminUserDto(User newUser) { 38 | return AdminUserDto.builder() 39 | .email(newUser.getEmail()) 40 | .id(newUser.getId()) 41 | .name(newUser.getName()) 42 | .build(); 43 | } 44 | 45 | public List toListAdminUserDto(List users) { 46 | return users.stream().map(UserMapper::toAdminUserDto).collect(Collectors.toList()); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/comment/controller/PublicCommentController.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.comment.controller; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.http.ResponseEntity; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.PathVariable; 8 | import org.springframework.web.bind.annotation.RequestParam; 9 | import org.springframework.web.bind.annotation.RestController; 10 | import ru.practicum.main.comment.dto.CommentDto; 11 | import ru.practicum.main.comment.dto.CommentShortDto; 12 | import ru.practicum.main.comment.service.CommentService; 13 | 14 | import java.util.List; 15 | 16 | 17 | @RestController 18 | @RequiredArgsConstructor 19 | @Slf4j 20 | public class PublicCommentController { 21 | 22 | private final CommentService service; 23 | 24 | @GetMapping("/comment/{comId}") 25 | public ResponseEntity getById(@PathVariable Long comId) { 26 | log.info("Calling the GET request to /comment/{comId}endpoint"); 27 | return ResponseEntity.ok(service.getComment(comId)); 28 | } 29 | 30 | @GetMapping("/events/{eventId}/comment") 31 | public ResponseEntity> getByEventId(@PathVariable Long eventId, 32 | @RequestParam(defaultValue = "0") int from, 33 | @RequestParam(defaultValue = "10") int size) { 34 | log.info("Calling the GET request to /events/{eventId}/comment"); 35 | return ResponseEntity.ok(service.getCommentsByEvent(eventId, from, size)); 36 | } 37 | } -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/comment/controller/AdminCommentController.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.comment.controller; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.http.HttpStatus; 6 | import org.springframework.http.ResponseEntity; 7 | import org.springframework.web.bind.annotation.*; 8 | import ru.practicum.main.comment.dto.CommentDto; 9 | import ru.practicum.main.comment.service.AdminCommentService; 10 | 11 | import java.util.List; 12 | 13 | 14 | @RestController 15 | @RequestMapping(path = "/admin") 16 | @RequiredArgsConstructor 17 | @Slf4j 18 | public class AdminCommentController { 19 | 20 | private final AdminCommentService adminCommentService; 21 | 22 | 23 | @GetMapping("comment/search") 24 | public ResponseEntity> search(@RequestParam String text) { 25 | log.info("Calling the GET request to /admin/comment/search endpoint"); 26 | return ResponseEntity.ok(adminCommentService.search(text)); 27 | } 28 | 29 | @GetMapping("users/{userId}/comment") 30 | public ResponseEntity> get(@PathVariable Long userId) { 31 | log.info("Calling the GET request to admin/users/{userId}/comment endpoint"); 32 | return ResponseEntity.ok(adminCommentService.findAllById(userId)); 33 | } 34 | 35 | @DeleteMapping("comment/{comId}") 36 | @ResponseStatus(HttpStatus.NO_CONTENT) 37 | public ResponseEntity delete(@PathVariable Long comId) { 38 | log.info("Calling the GET request to admin/comment/{comId} endpoint"); 39 | adminCommentService.delete(comId); 40 | return ResponseEntity 41 | .status(HttpStatus.NO_CONTENT) 42 | .body("Comment deleted by admin: " + comId); 43 | } 44 | } -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/compilation/mapper/CompilationMapper.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.compilation.mapper; 2 | 3 | import lombok.experimental.UtilityClass; 4 | import ru.practicum.main.compilation.dto.CompilationDto; 5 | import ru.practicum.main.compilation.model.Compilation; 6 | import ru.practicum.main.event.dto.EventShortDto; 7 | import ru.practicum.main.event.mapper.EventMapper; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | import java.util.stream.Collectors; 12 | 13 | @UtilityClass 14 | public class CompilationMapper { 15 | 16 | public CompilationDto toCompilationsDtoFromCompilation(Compilation compilation) { 17 | return CompilationDto.builder() 18 | .events(EventMapper.toListEventShortDto(EventMapper.toListEventShort(new ArrayList<>(compilation.getEvents())))) 19 | .id(compilation.getId()) 20 | .pinned(compilation.getPinned()) 21 | .title(compilation.getTitle()) 22 | .build(); 23 | } 24 | 25 | public static CompilationDto toCompilationDto(Compilation compilation) { 26 | List eventShortDtoList = compilation.getEvents().stream() 27 | .map(EventMapper::toEventShortDto) 28 | .collect(Collectors.toList()); 29 | 30 | return CompilationDto.builder() 31 | .id(compilation.getId()) 32 | .pinned(compilation.getPinned()) 33 | .title(compilation.getTitle()) 34 | .events(eventShortDtoList) 35 | .build(); 36 | } 37 | 38 | public static List toCompilationDtoList(List compilations) { 39 | return compilations.stream() 40 | .map(CompilationMapper::toCompilationDto) 41 | .collect(Collectors.toList()); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/compilation/controller/CompilationPublicController.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.compilation.controller; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.http.ResponseEntity; 6 | import org.springframework.validation.annotation.Validated; 7 | import org.springframework.web.bind.annotation.*; 8 | import ru.practicum.main.compilation.dto.CompilationDto; 9 | import ru.practicum.main.compilation.service.CompilationPublicService; 10 | 11 | import javax.validation.constraints.Positive; 12 | import javax.validation.constraints.PositiveOrZero; 13 | import java.util.List; 14 | 15 | @RestController 16 | @Validated 17 | @RequestMapping("/compilations") 18 | @RequiredArgsConstructor 19 | @Slf4j 20 | public class CompilationPublicController { 21 | 22 | private final CompilationPublicService service; 23 | 24 | @GetMapping("/{compId}") 25 | public ResponseEntity getCompilationById(@PathVariable Long compId) { 26 | log.info("Calling the GET request to /compilations/{compId} endpoint"); 27 | CompilationDto response = service.readCompilationById(compId); 28 | return ResponseEntity.ok(response); 29 | 30 | 31 | } 32 | 33 | @GetMapping 34 | public ResponseEntity> getCompilation(@RequestParam(required = false) Boolean pinned, 35 | @RequestParam(defaultValue = "0") @PositiveOrZero int from, 36 | @RequestParam(defaultValue = "10") @Positive int size) { 37 | log.info("Calling the GET request to /compilations endpoint"); 38 | List list = service.readAllCompilations(pinned, from, size); 39 | return ResponseEntity.ok(list); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/request/mapper/RequestMapper.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.request.mapper; 2 | 3 | import lombok.experimental.UtilityClass; 4 | import ru.practicum.main.event.dto.RequestShortUpdateDto; 5 | import ru.practicum.main.request.dto.RequestDto; 6 | import ru.practicum.main.request.dto.RequestShortDto; 7 | import ru.practicum.main.request.dto.RequestUpdateDto; 8 | import ru.practicum.main.request.model.Request; 9 | 10 | import java.util.List; 11 | import java.util.stream.Collectors; 12 | 13 | @UtilityClass 14 | public class RequestMapper { 15 | 16 | public RequestDto toRequestDto(Request request) { 17 | return RequestDto.builder() 18 | .requester(request.getRequester().getId()) 19 | .id(request.getId()) 20 | .created(request.getCreated()) 21 | .event(request.getEvent().getId()) 22 | .status(request.getStatus()) 23 | .build(); 24 | } 25 | 26 | public List toListRequestDto(List requests) { 27 | return requests.stream().map(RequestMapper::toRequestDto).collect(Collectors.toList()); 28 | } 29 | 30 | public RequestShortDto toRequestShort(ru.practicum.main.event.dto.RequestShortDto shortDto) { 31 | return RequestShortDto.builder() 32 | .requestIds(shortDto.getRequestIds()) 33 | .status(shortDto.getStatus()) 34 | .build(); 35 | } 36 | 37 | public RequestShortUpdateDto toRequestShortUpdateDto(RequestUpdateDto requestShort) { 38 | return RequestShortUpdateDto.builder() 39 | .rejectedRequests(RequestMapper.toListRequestDto(requestShort.getCanselRequest())) 40 | .confirmedRequests(RequestMapper.toListRequestDto(requestShort.getConformedRequest())) 41 | .build(); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/request/controller/RequestController.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.request.controller; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.http.HttpStatus; 6 | import org.springframework.http.ResponseEntity; 7 | import org.springframework.validation.annotation.Validated; 8 | import org.springframework.web.bind.annotation.*; 9 | import ru.practicum.main.request.dto.RequestDto; 10 | import ru.practicum.main.request.service.RequestService; 11 | 12 | import java.util.List; 13 | 14 | @RestController 15 | @Validated 16 | @RequestMapping("/users/") 17 | @RequiredArgsConstructor 18 | @Slf4j 19 | public class RequestController { 20 | 21 | private final RequestService requestService; 22 | 23 | @PostMapping("/{userId}/requests") 24 | @ResponseStatus(HttpStatus.CREATED) 25 | public ResponseEntity createRequest(@PathVariable Long userId, @RequestParam Long eventId) { 26 | log.info("Calling the POST request to /users/{userId}/requests endpoint"); 27 | return ResponseEntity.status(HttpStatus.CREATED).body(requestService.createRequest(userId, eventId)); 28 | } 29 | 30 | @GetMapping("/{userId}/requests") 31 | public ResponseEntity> getRequests(@PathVariable Long userId) { 32 | log.info("Calling the GET request to /users/{userId}/requests endpoint"); 33 | return ResponseEntity.ok(requestService.readAllRequests(userId)); 34 | } 35 | 36 | @PatchMapping("/{userId}/requests/{requestId}/cancel") 37 | public ResponseEntity canselRequest(@PathVariable Long userId, @PathVariable Long requestId) { 38 | log.info("Calling the PATCH request to /users/{userId}/requests/{requestId}/cancel"); 39 | return ResponseEntity.ok(requestService.cancelRequest(userId, requestId)); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/category/service/CategoryPublicServiceImpl.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.category.service; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.stereotype.Service; 6 | import org.springframework.transaction.annotation.Transactional; 7 | import ru.practicum.main.category.dto.CategoryDto; 8 | import ru.practicum.main.category.mapper.CategoryMapper; 9 | import ru.practicum.main.category.model.Category; 10 | import ru.practicum.main.category.repository.CategoryMainServiceRepository; 11 | import ru.practicum.main.exception.NotFoundException; 12 | 13 | import java.util.List; 14 | 15 | import static ru.practicum.main.util.Util.createPageRequestAsc; 16 | 17 | @Service 18 | @RequiredArgsConstructor 19 | @Transactional(readOnly = true) 20 | @Slf4j 21 | public class CategoryPublicServiceImpl implements CategoryPublicService { 22 | 23 | private final CategoryMainServiceRepository repository; 24 | 25 | @Override 26 | public List readAllCategories(Integer from, Integer size) { 27 | log.info("readAllCategories - invoked"); 28 | List cat = repository.findAllCategories(createPageRequestAsc(from, size)); 29 | log.info("Result: categories size = {}", cat.size()); 30 | return CategoryMapper.toListCategoriesDto(cat); 31 | 32 | } 33 | 34 | @Override 35 | public CategoryDto readCategoryById(Long catId) { 36 | log.info("readAllCategories - invoked"); 37 | Category category = repository.findById(catId).orElseThrow(() -> { 38 | log.error("Category with id = {} not exist", catId); 39 | return new NotFoundException("Category not found"); 40 | }); 41 | log.info("Result: received a category - {}", category.getName()); 42 | return CategoryMapper.toCategoryDto(category); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /ewm-stat-service/stat_client/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | ru.practicum 8 | explore-with-me 9 | 0.0.1-SNAPSHOT 10 | ../../pom.xml 11 | 12 | 13 | stat_client 14 | 0.0.1-SNAPSHOT 15 | 16 | 17 | 11 18 | 11 19 | UTF-8 20 | 21 | 22 | 23 | 24 | org.springframework.boot 25 | spring-boot-starter-web 26 | 27 | 28 | 29 | org.apache.httpcomponents 30 | httpclient 31 | 32 | 33 | 34 | ru.practicum 35 | stat_dto 36 | 0.0.1-SNAPSHOT 37 | compile 38 | 39 | 40 | org.projectlombok 41 | lombok 42 | 43 | 44 | 45 | org.springframework.boot 46 | spring-boot-starter-actuator 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /ewm-stat-service/stat_server/src/main/java/ru/practicum/controller/StatServiceController.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.controller; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.format.annotation.DateTimeFormat; 6 | import org.springframework.http.HttpStatus; 7 | import org.springframework.http.ResponseEntity; 8 | import org.springframework.validation.annotation.Validated; 9 | import org.springframework.web.bind.annotation.*; 10 | import ru.practicum.dto.StatDto; 11 | import ru.practicum.dto.StatResponseDto; 12 | import ru.practicum.dto.Validator; 13 | import ru.practicum.service.StatService; 14 | 15 | import java.time.LocalDateTime; 16 | import java.util.List; 17 | 18 | import static ru.practicum.utill.Constants.DATE_FORMAT; 19 | 20 | 21 | @RestController 22 | @RequiredArgsConstructor 23 | @Validated 24 | @Slf4j 25 | public class StatServiceController { 26 | 27 | private final StatService statService; 28 | 29 | @PostMapping("/hit") 30 | public ResponseEntity addStatEvent(@RequestBody @Validated(Validator.Create.class) StatDto statDto) { 31 | log.info("Calling the POST request to /hit endpoint"); 32 | StatDto statEvent = statService.createStat(statDto); 33 | return new ResponseEntity<>(statEvent, HttpStatus.CREATED); 34 | } 35 | 36 | @GetMapping("/stats") 37 | public ResponseEntity> readStatEvent(@RequestParam @DateTimeFormat(pattern = DATE_FORMAT) LocalDateTime start, 38 | @RequestParam @DateTimeFormat(pattern = DATE_FORMAT) LocalDateTime end, 39 | @RequestParam(defaultValue = "") List uris, 40 | @RequestParam(defaultValue = "false") boolean unique) { 41 | log.info("Calling the GET request to /stats endpoint"); 42 | List stats = statService.readStat(start, end, uris, unique); 43 | return new ResponseEntity<>(stats, HttpStatus.OK); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /ewm-stat-service/stat_server/src/main/java/ru/practicum/exception/ErrorHandler.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.exception; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.http.ResponseEntity; 6 | import org.springframework.web.bind.MethodArgumentNotValidException; 7 | import org.springframework.web.bind.MissingRequestHeaderException; 8 | import org.springframework.web.bind.MissingServletRequestParameterException; 9 | import org.springframework.web.bind.annotation.ExceptionHandler; 10 | import org.springframework.web.bind.annotation.RestControllerAdvice; 11 | 12 | import javax.validation.ConstraintViolationException; 13 | import java.time.LocalDateTime; 14 | 15 | import static ru.practicum.utill.Constants.FORMATTER; 16 | 17 | @Slf4j 18 | @RestControllerAdvice 19 | public class ErrorHandler { 20 | 21 | @ExceptionHandler({MethodArgumentNotValidException.class, MissingRequestHeaderException.class, 22 | ConstraintViolationException.class, MissingServletRequestParameterException.class, 23 | WrongTimeException.class}) 24 | public ResponseEntity badRequest(final Exception e) { 25 | return handleException(e, HttpStatus.BAD_REQUEST); 26 | } 27 | 28 | @ExceptionHandler 29 | public ResponseEntity internalServerError(final Exception e) { 30 | return handleException(e, HttpStatus.INTERNAL_SERVER_ERROR); 31 | } 32 | 33 | private ResponseEntity handleException(final Exception e, HttpStatus status) { 34 | String errorMessage = status.is4xxClientError() ? "Incorrectly made request." : "Internal Server Error"; 35 | String timestamp = LocalDateTime.now().format(FORMATTER); 36 | String errorStatus = status.name(); 37 | String errorDescription = e.getMessage(); 38 | 39 | log.error("{} - Status: {}, Description: {}, Timestamp: {}", 40 | errorMessage, errorStatus, errorDescription, timestamp); 41 | 42 | return new ResponseEntity<>(new ErrorResponse(errorStatus, errorDescription, errorMessage, timestamp), status); 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /ewm-stat-service/stat_client/src/main/java/ru/practicum/client/StatClient.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.client; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.boot.web.client.RestTemplateBuilder; 5 | import org.springframework.http.ResponseEntity; 6 | import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; 7 | import org.springframework.lang.Nullable; 8 | import org.springframework.stereotype.Service; 9 | import org.springframework.web.util.DefaultUriBuilderFactory; 10 | import ru.practicum.dto.StatDto; 11 | 12 | import java.net.URLEncoder; 13 | import java.nio.charset.StandardCharsets; 14 | import java.util.List; 15 | import java.util.Map; 16 | 17 | @Service 18 | public class StatClient extends BaseClient { 19 | 20 | 21 | public StatClient(@Value("${stats-service.url}") String serverUrl, RestTemplateBuilder builder) { 22 | super( 23 | builder 24 | .uriTemplateHandler(new DefaultUriBuilderFactory(serverUrl)) 25 | .requestFactory(HttpComponentsClientHttpRequestFactory::new) 26 | .build() 27 | ); 28 | } 29 | 30 | public ResponseEntity addStatEvent(StatDto stat) { 31 | return post("/hit", stat); 32 | } 33 | 34 | public ResponseEntity readStatEvent(String start, String end, @Nullable List uris, boolean unique) { 35 | Map parameters; 36 | if (uris == null) { 37 | parameters = Map.of("start", encode(start), 38 | "end", encode(end), 39 | "unique", unique); 40 | return get("/stats?start={start}&end={end}&unique={unique}", parameters); 41 | } 42 | parameters = Map.of("start", start, 43 | "end", end, 44 | "uris", String.join(",", uris), 45 | "unique", unique); 46 | return get("/stats?start={start}&end={end}&unique={unique}&uris={uris}", parameters); 47 | } 48 | 49 | private String encode(String value) { 50 | return URLEncoder.encode(value, StandardCharsets.UTF_8); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/comment/mapper/CommentMapper.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.comment.mapper; 2 | 3 | import lombok.experimental.UtilityClass; 4 | import ru.practicum.main.comment.dto.CommentDto; 5 | import ru.practicum.main.comment.dto.CommentShortDto; 6 | import ru.practicum.main.comment.dto.CommentCreateDto; 7 | import ru.practicum.main.comment.model.Comment; 8 | import ru.practicum.main.event.mapper.EventMapper; 9 | import ru.practicum.main.user.mapper.UserMapper; 10 | 11 | import java.time.format.DateTimeFormatter; 12 | import java.util.List; 13 | import java.util.stream.Collectors; 14 | 15 | @UtilityClass 16 | public class CommentMapper { 17 | 18 | private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); 19 | 20 | public Comment toComment(CommentCreateDto commentDto) { 21 | return Comment.builder() 22 | .text(commentDto.getText()) 23 | .build(); 24 | } 25 | 26 | public CommentDto toCommentDto(Comment comment) { 27 | return CommentDto.builder() 28 | .id(comment.getId()) 29 | .author(UserMapper.toUserDto(comment.getAuthor())) 30 | .event(EventMapper.toEventComment(comment.getEvent())) 31 | .createTime(comment.getCreateTime().format(FORMATTER)) 32 | .text(comment.getText()) 33 | .build(); 34 | } 35 | 36 | public List toListCommentDto(List list) { 37 | return list.stream().map(CommentMapper::toCommentDto).collect(Collectors.toList()); 38 | } 39 | 40 | public CommentShortDto toCommentShortDto(Comment comment) { 41 | return CommentShortDto.builder() 42 | .author(UserMapper.toUserDto(comment.getAuthor())) 43 | .createTime(comment.getText()) 44 | .id(comment.getId()) 45 | .text(comment.getText()) 46 | .build(); 47 | } 48 | 49 | public List toListCommentShortDto(List list) { 50 | return list.stream().map(CommentMapper::toCommentShortDto).collect(Collectors.toList()); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/compilation/service/CompilationPublicServiceImpl.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.compilation.service; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.data.domain.PageRequest; 6 | import org.springframework.data.domain.Pageable; 7 | import org.springframework.data.domain.Sort; 8 | import org.springframework.stereotype.Service; 9 | import org.springframework.transaction.annotation.Transactional; 10 | import ru.practicum.main.compilation.dto.CompilationDto; 11 | import ru.practicum.main.compilation.mapper.CompilationMapper; 12 | import ru.practicum.main.compilation.model.Compilation; 13 | import ru.practicum.main.compilation.repository.CompilationMainServiceRepository; 14 | import ru.practicum.main.exception.NotFoundException; 15 | 16 | import java.util.List; 17 | 18 | @Service 19 | @Transactional(readOnly = true) 20 | @RequiredArgsConstructor 21 | @Slf4j 22 | public class CompilationPublicServiceImpl implements CompilationPublicService { 23 | 24 | private final CompilationMainServiceRepository compilationMainServiceRepository; 25 | 26 | 27 | @Override 28 | public CompilationDto readCompilationById(Long compId) { 29 | log.info("readCompilationById - invoked"); 30 | 31 | Compilation compilation = compilationMainServiceRepository.findById(compId).orElseThrow(() -> 32 | new NotFoundException("Compilation not found")); 33 | 34 | log.info("Result : {}", compilation); 35 | return CompilationMapper.toCompilationDto(compilation); 36 | } 37 | 38 | @Override 39 | public List readAllCompilations(Boolean pinned, int from, int size) { 40 | Pageable pageable = PageRequest.of(from, size, Sort.Direction.ASC, "id"); 41 | 42 | List compilations; 43 | compilations = (pinned == null) ? compilationMainServiceRepository.findAll(pageable).getContent() : 44 | compilationMainServiceRepository.findAllByPinned(pinned, pageable); 45 | log.info("Result : {}", compilations); 46 | return CompilationMapper.toCompilationDtoList(compilations); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/comment/service/AdminCommentServiceImpl.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.comment.service; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.stereotype.Service; 6 | import ru.practicum.main.comment.dto.CommentDto; 7 | import ru.practicum.main.comment.mapper.CommentMapper; 8 | import ru.practicum.main.comment.model.Comment; 9 | import ru.practicum.main.comment.repository.CommentMainServiceRepository; 10 | import ru.practicum.main.exception.NotFoundException; 11 | import ru.practicum.main.user.repository.UserMainServiceRepository; 12 | 13 | import java.util.List; 14 | 15 | @Service 16 | @RequiredArgsConstructor 17 | @Slf4j 18 | public class AdminCommentServiceImpl implements AdminCommentService { 19 | 20 | private final CommentMainServiceRepository repository; 21 | 22 | private final UserMainServiceRepository userMainServiceRepository; 23 | 24 | @Override 25 | public void delete(Long comId) { 26 | log.info("admin delete - invoked"); 27 | if (repository.existsById(comId)) { 28 | log.error("User with id = {} not exist", comId); 29 | throw new NotFoundException("Comment not found"); 30 | } 31 | log.info("Result: comment with id = {} deleted", comId); 32 | repository.deleteById(comId); 33 | } 34 | 35 | @Override 36 | public List search(String text) { 37 | log.info("admin search - invoked"); 38 | List list = repository.findAllByText(text); 39 | log.info("Result: list of comments size = {} ", list.size()); 40 | return CommentMapper.toListCommentDto(list); 41 | } 42 | 43 | @Override 44 | public List findAllById(Long userId) { 45 | log.info("admin findAllById - invoked"); 46 | if (userMainServiceRepository.existsById(userId)) { 47 | log.error("User with id = {} not exist", userId); 48 | throw new NotFoundException("User not found"); 49 | } 50 | List list = repository.findAllByAuthorId(userId); 51 | log.info("Result: list of comments size = {} ", list.size()); 52 | return CommentMapper.toListCommentDto(list); 53 | } 54 | } -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/event/repository/EventMainServiceRepository.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.event.repository; 2 | 3 | import org.springframework.data.domain.Pageable; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.data.jpa.repository.Query; 6 | import ru.practicum.main.event.status.State; 7 | import ru.practicum.main.event.model.Event; 8 | 9 | import java.time.LocalDateTime; 10 | import java.util.List; 11 | import java.util.Optional; 12 | 13 | public interface EventMainServiceRepository extends JpaRepository { 14 | List findAllByInitiatorId(long userId, Pageable pageable); 15 | 16 | 17 | Optional findByIdAndInitiatorId(long eventId, long userId); 18 | 19 | @Query("SELECT e " + 20 | "FROM Event e " + 21 | "WHERE (e.initiator.id IN ?1 OR ?1 IS null) " + 22 | "AND (e.state IN ?2 OR ?2 IS null) " + 23 | "AND (e.category.id IN ?3 OR ?3 IS null) " + 24 | "AND (e.eventDate > ?4 OR ?4 IS null) " + 25 | "AND (e.eventDate < ?5 OR ?5 IS null) ") 26 | 27 | List findAllByParam(List users, List states, List categories, 28 | LocalDateTime start, LocalDateTime end, Pageable pageable); 29 | 30 | boolean existsByIdAndInitiatorId(long eventId, long userId); 31 | 32 | @Query("SELECT e " + 33 | "FROM Event e " + 34 | "WHERE ((?1 IS null) OR ((lower(e.annotation) LIKE concat('%', lower(?1), '%')) OR (lower(e.description) LIKE concat('%', lower(?1), '%')))) " + 35 | "AND (e.category.id IN ?2 OR ?2 IS null) " + 36 | "AND (e.paid = ?3 OR ?3 IS null) " + 37 | "AND (e.eventDate > ?4 OR ?4 IS null) AND (e.eventDate < ?5 OR ?5 IS null) " + 38 | "AND (?6 = false OR ((?6 = true AND e.participantLimit > (SELECT count(*) FROM Request AS r WHERE e.id = r.event.id))) " + 39 | "OR (e.participantLimit > 0 )) ") 40 | List findAllEvents(String text, List categories, Boolean paid, LocalDateTime rangeStart, 41 | LocalDateTime rangeEnd, Boolean onlyAvailable, String sort, Pageable pageable); 42 | 43 | boolean existsByCategoryId(long catId); 44 | } 45 | -------------------------------------------------------------------------------- /ewm-stat-service/stat_server/src/main/java/ru/practicum/repository/StatServiceRepository.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import org.springframework.data.jpa.repository.Query; 5 | import ru.practicum.dto.StatResponseDto; 6 | import ru.practicum.model.Stat; 7 | 8 | import java.time.LocalDateTime; 9 | import java.util.List; 10 | 11 | public interface StatServiceRepository extends JpaRepository { 12 | 13 | @Query("select new ru.practicum.dto.StatResponseDto(stat.ip, stat.uri, count(distinct stat.ip)) " + 14 | "from Stat as stat " + 15 | "where stat.timestamp between ?1 and ?2 " + 16 | "group by stat.ip, stat.uri " + 17 | "order by count(distinct stat.ip) desc") 18 | List findAllByTimestampBetweenStartAndEndWithUniqueIp(LocalDateTime start, LocalDateTime end); 19 | 20 | @Query("select new ru.practicum.dto.StatResponseDto(stat.ip, stat.uri, count(stat.ip)) " + 21 | "from Stat as stat " + 22 | "where stat.timestamp between ?1 and ?2 " + 23 | "group by stat.ip, stat.uri " + 24 | "order by count(stat.ip) desc ") 25 | List findAllByTimestampBetweenStartAndEndWhereIpNotUnique(LocalDateTime start, LocalDateTime end); 26 | 27 | @Query("select new ru.practicum.dto.StatResponseDto(stat.ip, stat.uri, count(distinct stat.ip)) " + 28 | "from Stat as stat " + 29 | "where stat.timestamp between ?1 and ?2 and stat.uri in ?3 " + 30 | "group by stat.ip, stat.uri " + 31 | "order by count(distinct stat.ip) desc ") 32 | List findAllByTimestampBetweenStartAndEndWithUrisUniqueIp(LocalDateTime start, LocalDateTime end, List uris); 33 | 34 | @Query("select new ru.practicum.dto.StatResponseDto(stat.ip, stat.uri, count(stat.ip)) " + 35 | "from Stat as stat " + 36 | "where stat.timestamp between ?1 and ?2 and stat.uri in ?3 " + 37 | "group by stat.ip, stat.uri " + 38 | "order by count(stat.ip) desc ") 39 | List findAllByTimestampBetweenStartAndEndWithUrisIpNotUnique(LocalDateTime start, LocalDateTime end, List uris); 40 | 41 | } 42 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/comment/controller/PrivateCommentController.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.comment.controller; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.http.HttpStatus; 6 | import org.springframework.http.ResponseEntity; 7 | import org.springframework.validation.annotation.Validated; 8 | import org.springframework.web.bind.annotation.*; 9 | import ru.practicum.main.comment.dto.CommentDto; 10 | import ru.practicum.main.comment.dto.CommentCreateDto; 11 | import ru.practicum.main.comment.service.PrivateCommentService; 12 | 13 | @RestController 14 | @Validated 15 | @RequiredArgsConstructor 16 | @Slf4j 17 | public class PrivateCommentController { 18 | 19 | private final PrivateCommentService service; 20 | 21 | @PostMapping("/users/{userId}/events/{eventId}/comment") 22 | @ResponseStatus(HttpStatus.CREATED) 23 | public ResponseEntity create(@PathVariable Long userId, @PathVariable Long eventId, 24 | @RequestBody @Validated CommentCreateDto commentCreateDto) { 25 | log.info("Calling the GET request to /users/{userId}/events/{eventId}/comment endpoint"); 26 | return ResponseEntity.status(HttpStatus.CREATED) 27 | .body(service.createComment(userId, eventId, commentCreateDto)); 28 | } 29 | 30 | @DeleteMapping("/users/{userId}/comment/{comId}") 31 | @ResponseStatus(HttpStatus.NO_CONTENT) 32 | public ResponseEntity delete(@PathVariable Long userId, @PathVariable Long comId) { 33 | log.info("Calling the GET request to /users/{userId}/comment/{comId} endpoint"); 34 | service.deleteComment(userId, comId); 35 | return ResponseEntity 36 | .status(HttpStatus.NO_CONTENT) 37 | .body("Comment deleted by user: " + comId); 38 | } 39 | 40 | @PatchMapping("/users/{userId}/comment/{comId}") 41 | public ResponseEntity patch(@PathVariable Long userId, @PathVariable Long comId, 42 | @RequestBody @Validated CommentCreateDto commentCreateDto) { 43 | log.info("Calling the PATCH request to users/{userId}/comment/{comId} endpoint"); 44 | return ResponseEntity.ok(service.patchComment(userId, comId, commentCreateDto)); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/compilation/controller/CompilationAdminController.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.compilation.controller; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.http.HttpStatus; 6 | import org.springframework.http.ResponseEntity; 7 | import org.springframework.validation.annotation.Validated; 8 | import org.springframework.web.bind.annotation.*; 9 | import ru.practicum.dto.Validator; 10 | import ru.practicum.main.compilation.dto.CompilationDto; 11 | import ru.practicum.main.compilation.dto.NewCompilationDto; 12 | import ru.practicum.main.compilation.service.CompilationAdminService; 13 | 14 | @RestController 15 | @Validated 16 | @RequestMapping("/admin/compilations") 17 | @RequiredArgsConstructor 18 | @Slf4j 19 | public class CompilationAdminController { 20 | 21 | private final CompilationAdminService service; 22 | 23 | @PostMapping 24 | @ResponseStatus(HttpStatus.CREATED) 25 | public ResponseEntity postCompilations(@RequestBody @Validated(Validator.Create.class) NewCompilationDto newCompilationDto) { 26 | log.info("Calling the POST request to /admin/compilations endpoint"); 27 | return ResponseEntity 28 | .status(HttpStatus.CREATED) 29 | .body(service.createCompilation(newCompilationDto)); 30 | } 31 | 32 | @DeleteMapping("/{compId}") 33 | @ResponseStatus(HttpStatus.NO_CONTENT) 34 | public ResponseEntity deleteCompilation(@PathVariable Long compId) { 35 | log.info("Calling the DELETE request to /admin/endpoint/{compId}"); 36 | service.deleteCompilation(compId); 37 | return ResponseEntity 38 | .status(HttpStatus.NO_CONTENT) 39 | .body("Compilation deleted: " + compId); 40 | } 41 | 42 | @PatchMapping("/{compId}") 43 | public ResponseEntity patchCompilation(@PathVariable Long compId, 44 | @RequestBody @Validated(Validator.Update.class) NewCompilationDto newCompilationDto) { 45 | log.info("Calling the PATCH request to /admin/compilations/{compId} endpoint"); 46 | return ResponseEntity 47 | .status(HttpStatus.OK) 48 | .body(service.updateCompilation(compId, newCompilationDto)); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /ewm-stat-service/stat_client/src/main/java/ru/practicum/client/BaseClient.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.client; 2 | 3 | import org.springframework.http.HttpEntity; 4 | import org.springframework.http.HttpMethod; 5 | import org.springframework.http.ResponseEntity; 6 | import org.springframework.lang.Nullable; 7 | import org.springframework.web.client.HttpStatusCodeException; 8 | import org.springframework.web.client.RestTemplate; 9 | 10 | import java.util.Map; 11 | 12 | public class BaseClient { 13 | protected final RestTemplate restTemplate; 14 | 15 | public BaseClient(RestTemplate restTemplate) { 16 | this.restTemplate = restTemplate; 17 | } 18 | 19 | protected ResponseEntity get(String path, @Nullable Map parameters) { 20 | return makeAndSendRequest(HttpMethod.GET, path, parameters, null); 21 | } 22 | 23 | protected ResponseEntity post(String path, T body) { 24 | return makeAndSendRequest(HttpMethod.POST, path, null, body); 25 | } 26 | 27 | private ResponseEntity makeAndSendRequest(HttpMethod method, String path, @Nullable Map parameters, @Nullable T body) { 28 | HttpEntity requestEntity = body == null ? null : new HttpEntity<>(body); 29 | 30 | ResponseEntity statsServiceResponse; 31 | try { 32 | if (parameters != null) { 33 | statsServiceResponse = restTemplate.exchange(path, method, requestEntity, Object.class, parameters); 34 | } else { 35 | statsServiceResponse = restTemplate.exchange(path, method, requestEntity, Object.class); 36 | } 37 | } catch (HttpStatusCodeException e) { 38 | return ResponseEntity.status(e.getStatusCode()).body(e.getResponseBodyAsByteArray()); 39 | } 40 | return prepareStatsServiceResponse(statsServiceResponse); 41 | } 42 | 43 | private static ResponseEntity prepareStatsServiceResponse(ResponseEntity response) { 44 | if (response.getStatusCode().is2xxSuccessful()) { 45 | return response; 46 | } 47 | 48 | ResponseEntity.BodyBuilder responseBuilder = ResponseEntity.status(response.getStatusCode()); 49 | 50 | if (response.hasBody()) { 51 | return responseBuilder.body(response.getBody()); 52 | } 53 | 54 | return responseBuilder.build(); 55 | } 56 | } 57 | 58 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/comment/service/CommentServiceImpl.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.comment.service; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.data.domain.Pageable; 6 | import org.springframework.stereotype.Service; 7 | import org.springframework.transaction.annotation.Transactional; 8 | import ru.practicum.main.comment.dto.CommentDto; 9 | import ru.practicum.main.comment.dto.CommentShortDto; 10 | import ru.practicum.main.comment.mapper.CommentMapper; 11 | import ru.practicum.main.comment.model.Comment; 12 | import ru.practicum.main.comment.repository.CommentMainServiceRepository; 13 | import ru.practicum.main.event.repository.EventMainServiceRepository; 14 | import ru.practicum.main.exception.NotFoundException; 15 | 16 | import java.util.List; 17 | 18 | import static ru.practicum.main.util.Util.createPageRequestAsc; 19 | 20 | 21 | @Service 22 | @Transactional(readOnly = true) 23 | @RequiredArgsConstructor 24 | @Slf4j 25 | public class CommentServiceImpl implements CommentService { 26 | 27 | private final CommentMainServiceRepository repository; 28 | 29 | private final EventMainServiceRepository eventMainServiceRepository; 30 | 31 | 32 | @Override 33 | public CommentDto getComment(Long comId) { 34 | log.info("getComment - invoked"); 35 | Comment comment = repository.findById(comId) 36 | .orElseThrow(() -> { 37 | log.error("Comment with id = {} - not exist", comId); 38 | return new NotFoundException("Comment not found"); 39 | }); 40 | log.info("Result: comment with id= {}", comId); 41 | return CommentMapper.toCommentDto(comment); 42 | } 43 | 44 | @Override 45 | public List getCommentsByEvent(Long eventId, int from, int size) { 46 | log.info("getCommentsByEvent - invoked"); 47 | if (eventMainServiceRepository.existsById(eventId)) { 48 | log.error("Event with id = {} - not exist", eventId); 49 | throw new NotFoundException("Event not found"); 50 | } 51 | Pageable pageable = createPageRequestAsc("createTime", from, size); 52 | List comments = repository.findAllByEventId(eventId, pageable); 53 | log.info("Result : list of comments size = {}", comments.size()); 54 | return CommentMapper.toListCommentShortDto(comments); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/user/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.user.controller; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.http.HttpStatus; 6 | import org.springframework.http.ResponseEntity; 7 | import org.springframework.validation.annotation.Validated; 8 | import org.springframework.web.bind.annotation.*; 9 | import ru.practicum.dto.Validator; 10 | import ru.practicum.main.user.dto.AdminUserDto; 11 | import ru.practicum.main.user.dto.UserDtoReceived; 12 | import ru.practicum.main.user.mapper.UserMapper; 13 | import ru.practicum.main.user.service.UserService; 14 | 15 | import javax.validation.constraints.Positive; 16 | import javax.validation.constraints.PositiveOrZero; 17 | import java.util.List; 18 | 19 | @RestController 20 | @RequiredArgsConstructor 21 | @Validated 22 | @RequestMapping("/admin/users") 23 | @Slf4j 24 | public class UserController { 25 | 26 | private final UserService userService; 27 | 28 | @PostMapping 29 | @ResponseStatus(HttpStatus.CREATED) 30 | public ResponseEntity createUser(@RequestBody @Validated({Validator.Create.class}) UserDtoReceived userDto) { 31 | log.info("Calling the POST request to /admin/users endpoint"); 32 | return ResponseEntity.status(HttpStatus.CREATED).body(userService.createUser(UserMapper.toUser(userDto))); 33 | } 34 | 35 | 36 | @DeleteMapping("/{userId}") 37 | @ResponseStatus(HttpStatus.NO_CONTENT) 38 | public ResponseEntity deleteUser(@PathVariable Long userId) { 39 | log.info("Calling the DELETE request to /admin/users/{userId} endpoint"); 40 | userService.deleteUser(userId); 41 | return ResponseEntity 42 | .status(HttpStatus.NO_CONTENT) 43 | .body("User deleted: " + userId); 44 | } 45 | 46 | @GetMapping 47 | public ResponseEntity> getUsers(@RequestParam(defaultValue = "") List ids, 48 | @RequestParam(defaultValue = "0") @PositiveOrZero int from, 49 | @RequestParam(defaultValue = "10") @Positive int size) { 50 | log.info("Calling the GET request to /admin/users endpoint"); 51 | List response = UserMapper.toListAdminUserDto(userService.readUsers(ids, from, size)); 52 | return ResponseEntity.ok(response); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/category/controller/CategoryAdminController.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.category.controller; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.http.HttpStatus; 6 | import org.springframework.http.ResponseEntity; 7 | import org.springframework.validation.BindingResult; 8 | import org.springframework.validation.annotation.Validated; 9 | import org.springframework.web.bind.annotation.*; 10 | import ru.practicum.dto.Validator; 11 | import ru.practicum.main.category.dto.CategoryDto; 12 | import ru.practicum.main.category.service.CategoryAdminService; 13 | 14 | import javax.validation.constraints.Positive; 15 | 16 | @RestController 17 | @RequiredArgsConstructor 18 | @Validated 19 | @RequestMapping(path = "/admin/categories") 20 | @Slf4j 21 | public class CategoryAdminController { 22 | 23 | private final CategoryAdminService categoryAdminService; 24 | 25 | @PostMapping 26 | @ResponseStatus(HttpStatus.CREATED) 27 | public ResponseEntity addCategory(@RequestBody @Validated(Validator.Create.class) 28 | CategoryDto requestCategory, BindingResult bindingResult) { 29 | log.info("Calling the POST request to /admin/categories endpoint"); 30 | if (bindingResult.hasErrors()) { 31 | log.error("Validation error with category name"); 32 | return ResponseEntity.badRequest().body((requestCategory)); 33 | } 34 | return ResponseEntity 35 | .status(HttpStatus.CREATED) 36 | .body(categoryAdminService.createCategory(requestCategory)); 37 | } 38 | 39 | @DeleteMapping("/{catId}") 40 | @ResponseStatus(HttpStatus.NO_CONTENT) 41 | public ResponseEntity deleteCategories(@PathVariable @Positive Long catId) { 42 | log.info("Calling the DELETE request to /admin/categories/{catId} endpoint"); 43 | categoryAdminService.deleteCategory(catId); 44 | return ResponseEntity 45 | .status(HttpStatus.NO_CONTENT) 46 | .body("Category deleted: " + catId); 47 | } 48 | 49 | @PatchMapping("/{catId}") 50 | public ResponseEntity updateCategory(@PathVariable Long catId, 51 | @RequestBody @Validated(Validator.Update.class) CategoryDto categoryDto) { 52 | log.info("Calling the PATCH request to /admin/categories/{catId} endpoint"); 53 | return ResponseEntity 54 | .status(HttpStatus.OK) 55 | .body(categoryAdminService.updateCategory(catId, categoryDto)); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /ewm-stat-service/stat_server/src/main/java/ru/practicum/service/StatServiceImpl.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.service; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.stereotype.Service; 6 | import org.springframework.transaction.annotation.Transactional; 7 | import ru.practicum.dto.StatDto; 8 | import ru.practicum.dto.StatResponseDto; 9 | import ru.practicum.exception.WrongTimeException; 10 | import ru.practicum.model.Stat; 11 | import ru.practicum.repository.StatServiceRepository; 12 | 13 | import java.time.LocalDateTime; 14 | import java.util.List; 15 | 16 | import static ru.practicum.model.mapper.StatMapper.toStat; 17 | import static ru.practicum.model.mapper.StatMapper.toStatDto; 18 | 19 | @Service 20 | @RequiredArgsConstructor 21 | @Slf4j 22 | public class StatServiceImpl implements StatService { 23 | 24 | private final StatServiceRepository statServiceRepository; 25 | 26 | @Transactional 27 | public StatDto createStat(StatDto statDto) { 28 | log.info("createStat - invoked"); 29 | Stat stat = statServiceRepository.save(toStat(statDto)); 30 | log.info("createStat - stat saved successfully - {}", stat); 31 | return toStatDto(stat); 32 | } 33 | 34 | 35 | @Override 36 | @Transactional(readOnly = true) 37 | public List readStat(LocalDateTime start, LocalDateTime end, List uris, boolean unique) { 38 | log.info("readStat - invoked"); 39 | 40 | if (start.isAfter(end)) { 41 | log.error("Error occurred: The start date cannot be later than the end date"); 42 | throw new WrongTimeException("The start date cannot be later than the end date"); 43 | } 44 | 45 | if (uris.isEmpty()) { 46 | if (unique) { 47 | log.info("readStat - success - unique = true, uris empty"); 48 | return statServiceRepository.findAllByTimestampBetweenStartAndEndWithUniqueIp(start, end); 49 | } else { 50 | log.info("readStat - success - unique = false, uris empty"); 51 | return statServiceRepository.findAllByTimestampBetweenStartAndEndWhereIpNotUnique(start, end); 52 | } 53 | } else { 54 | if (unique) { 55 | log.info("readStat - success - unique = true, uris not empty"); 56 | return statServiceRepository.findAllByTimestampBetweenStartAndEndWithUrisUniqueIp(start, end, uris); 57 | } else { 58 | log.info("readStat - success - unique = false, uris not empty"); 59 | return statServiceRepository.findAllByTimestampBetweenStartAndEndWithUrisIpNotUnique(start, end, uris); 60 | } 61 | } 62 | } 63 | } 64 | 65 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/user/service/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.user.service; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.data.domain.Pageable; 6 | import org.springframework.stereotype.Service; 7 | import org.springframework.transaction.annotation.Transactional; 8 | import ru.practicum.main.exception.NotFoundException; 9 | import ru.practicum.main.exception.NotUniqueException; 10 | import ru.practicum.main.user.dto.AdminUserDto; 11 | import ru.practicum.main.user.mapper.UserMapper; 12 | import ru.practicum.main.user.model.User; 13 | import ru.practicum.main.user.repository.UserMainServiceRepository; 14 | 15 | import java.util.List; 16 | 17 | import static ru.practicum.main.util.Util.createPageRequestAsc; 18 | 19 | @Service 20 | @RequiredArgsConstructor 21 | @Transactional(readOnly = true) 22 | @Slf4j 23 | public class UserServiceImpl implements UserService { 24 | 25 | 26 | private final UserMainServiceRepository userMainServiceRepository; 27 | 28 | @Transactional 29 | @Override 30 | public AdminUserDto createUser(User user) { 31 | log.info("createUser - invoked"); 32 | if (userMainServiceRepository.existsByEmail(user.getEmail())) { 33 | throw new NotUniqueException("User with this email already exists"); 34 | } 35 | AdminUserDto adminDto = UserMapper.toAdminUserDto(userMainServiceRepository.save(user)); 36 | log.info("Result: user {} - created", adminDto); 37 | return adminDto; 38 | } 39 | 40 | @Transactional 41 | @Override 42 | public void deleteUser(Long userId) { 43 | log.info("deleteUser - invoked"); 44 | if (!userMainServiceRepository.existsById(userId)) { 45 | log.error("User with id = {} not exist", userId); 46 | throw new NotFoundException("User not found"); 47 | } 48 | log.info("Result: user with id = {} - removed", userId); 49 | userMainServiceRepository.deleteById(userId); 50 | } 51 | 52 | @Override 53 | public List readUsers(List idList, int from, int size) { 54 | log.info("readUsers - invoked"); 55 | Pageable pageable = createPageRequestAsc(from, size); 56 | 57 | if (idList.isEmpty()) { 58 | List allUsers = userMainServiceRepository.findAllUser(pageable); 59 | log.info("Result: idList is empty, returning all users size = {}", allUsers.size()); 60 | return allUsers; 61 | } 62 | List users = userMainServiceRepository.findAllById(idList, pageable); 63 | if (users.isEmpty()) { 64 | return List.of(); 65 | } 66 | log.info("Result: list of Users size = {}", users.size()); 67 | return users; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/event/controller/EventAdminController.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.event.controller; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.format.annotation.DateTimeFormat; 6 | import org.springframework.http.ResponseEntity; 7 | import org.springframework.validation.annotation.Validated; 8 | import org.springframework.web.bind.annotation.*; 9 | import ru.practicum.dto.Validator; 10 | import ru.practicum.main.event.dto.AdminEventRequestDto; 11 | import ru.practicum.main.event.dto.EventFullDto; 12 | import ru.practicum.main.event.service.EventAdminService; 13 | import ru.practicum.main.event.status.State; 14 | 15 | import javax.validation.constraints.Positive; 16 | import javax.validation.constraints.PositiveOrZero; 17 | import java.time.LocalDateTime; 18 | import java.util.List; 19 | 20 | import static ru.practicum.main.util.Util.TIME_STRING; 21 | 22 | @RestController 23 | @RequiredArgsConstructor 24 | @Validated 25 | @RequestMapping("/admin/events") 26 | @Slf4j 27 | public class EventAdminController { 28 | 29 | private final EventAdminService eventAdminService; 30 | 31 | @PatchMapping("/{eventId}") 32 | public ResponseEntity patchAdminEvent(@PathVariable Long eventId, @RequestBody @Validated({Validator.Update.class}) AdminEventRequestDto adminEventDto) { 33 | log.info("Calling the PATCH request to /admin/events/{eventId}"); 34 | return ResponseEntity.ok(eventAdminService.updateAdminEvent(eventId, adminEventDto)); 35 | } 36 | 37 | @GetMapping 38 | public ResponseEntity> getAdminEvents(@RequestParam(required = false) List users, 39 | @RequestParam(required = false) List states, 40 | @RequestParam(required = false) List categories, 41 | @RequestParam(required = false) 42 | @DateTimeFormat(pattern = TIME_STRING) LocalDateTime start, 43 | @RequestParam(required = false) 44 | @DateTimeFormat(pattern = TIME_STRING) LocalDateTime end, 45 | @RequestParam(defaultValue = "0") @PositiveOrZero int from, 46 | @RequestParam(defaultValue = "10") @Positive int size) { 47 | log.info("Calling the GET request to /admin/events endpoint"); 48 | return ResponseEntity.ok(eventAdminService.readAdminEvents(users, states, categories, start, end, from, size)); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/event/model/Event.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.event.model; 2 | 3 | import lombok.*; 4 | import ru.practicum.main.category.model.Category; 5 | import ru.practicum.main.event.status.State; 6 | import ru.practicum.main.event.location.model.Location; 7 | import ru.practicum.main.user.model.User; 8 | 9 | import javax.persistence.*; 10 | import java.time.LocalDateTime; 11 | 12 | @Getter 13 | @Setter 14 | @Builder 15 | @Entity 16 | @AllArgsConstructor 17 | @NoArgsConstructor 18 | @Table(name = "event") 19 | public class Event { 20 | 21 | @Id 22 | @GeneratedValue(strategy = GenerationType.IDENTITY) 23 | @Column(name = "id") 24 | private Long id; 25 | 26 | @Column(name = "annotation") 27 | private String annotation; 28 | 29 | @ManyToOne 30 | @JoinColumn(name = "category_id") 31 | private Category category; 32 | 33 | @Column(name = "created_on") 34 | private LocalDateTime createdOn; 35 | 36 | @Column(name = "description") 37 | private String description; 38 | 39 | @Column(name = "event_date") 40 | private LocalDateTime eventDate; 41 | 42 | @ManyToOne 43 | @JoinColumn(name = "initiator_id") 44 | private User initiator; 45 | 46 | @ManyToOne 47 | @JoinColumn(name = "location_id") 48 | private Location location; 49 | 50 | @Column(name = "paid") 51 | private Boolean paid; 52 | 53 | @Column(name = "participant_limit") 54 | private Integer participantLimit; 55 | 56 | @Column(name = "request_moderation") 57 | private Boolean requestModeration; 58 | 59 | @Column(name = "state_event") 60 | @Enumerated(EnumType.STRING) 61 | private State state; 62 | 63 | @Column(name = "title") 64 | private String title; 65 | 66 | @Column(name = "published_on") 67 | private LocalDateTime publishedOn; 68 | 69 | @Transient 70 | private long view; 71 | 72 | @Transient 73 | private long confirmedRequests; 74 | 75 | @Override 76 | public String toString() { 77 | return "Event{" + 78 | "id=" + id + 79 | ", annotation='" + annotation + '\'' + 80 | ", category=" + category + 81 | ", createdOn=" + createdOn + 82 | ", description='" + description + '\'' + 83 | ", eventDate=" + eventDate + 84 | ", initiator=" + initiator + 85 | ", location=" + location + 86 | ", paid=" + paid + 87 | ", participantLimit=" + participantLimit + 88 | ", requestModeration=" + requestModeration + 89 | ", state=" + state + 90 | ", title='" + title + '\'' + 91 | ", publishedOn=" + publishedOn + 92 | ", view=" + view + 93 | ", confirmedRequests=" + confirmedRequests + 94 | '}'; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /ewm-stat-service/stat_server/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | ru.practicum 8 | explore-with-me 9 | 0.0.1-SNAPSHOT 10 | ../../pom.xml 11 | 12 | 13 | stat_server 14 | 15 | 16 | 17 | org.springframework.boot 18 | spring-boot-starter-web 19 | 20 | 21 | 22 | org.apache.httpcomponents 23 | httpclient 24 | 25 | 26 | 27 | ru.practicum 28 | stat_dto 29 | ${project.version} 30 | compile 31 | 32 | 33 | 34 | org.projectlombok 35 | lombok 36 | true 37 | 38 | 39 | 40 | com.h2database 41 | h2 42 | runtime 43 | 44 | 45 | 46 | org.springframework.boot 47 | spring-boot-configuration-processor 48 | true 49 | 50 | 51 | 52 | org.postgresql 53 | postgresql 54 | runtime 55 | 56 | 57 | 58 | org.springframework.boot 59 | spring-boot-starter-data-jpa 60 | 61 | 62 | 63 | org.springframework.boot 64 | spring-boot-starter-test 65 | test 66 | 67 | 68 | 69 | org.springframework.boot 70 | spring-boot-starter-actuator 71 | 72 | 73 | 74 | 75 | 76 | org.springframework.boot 77 | spring-boot-maven-plugin 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/event/controller/EventPublicController.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.event.controller; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.format.annotation.DateTimeFormat; 6 | import org.springframework.http.ResponseEntity; 7 | import org.springframework.validation.annotation.Validated; 8 | import org.springframework.web.bind.annotation.*; 9 | import ru.practicum.main.event.dto.EventFullDto; 10 | import ru.practicum.main.event.dto.EventShortDto; 11 | import ru.practicum.main.event.service.EventPublicService; 12 | 13 | import javax.servlet.http.HttpServletRequest; 14 | import javax.validation.constraints.Positive; 15 | import javax.validation.constraints.PositiveOrZero; 16 | import java.time.LocalDateTime; 17 | import java.util.List; 18 | 19 | import static ru.practicum.main.util.Util.TIME_STRING; 20 | 21 | @RestController 22 | @RequiredArgsConstructor 23 | @Validated 24 | @RequestMapping("/events") 25 | @Slf4j 26 | public class EventPublicController { 27 | 28 | private final EventPublicService service; 29 | 30 | 31 | @GetMapping 32 | public ResponseEntity> findPublicEvents(@RequestParam(required = false) String text, 33 | @RequestParam(required = false) List<@Positive Long> categories, 34 | @RequestParam(required = false) Boolean paid, 35 | @RequestParam(required = false) 36 | @DateTimeFormat(pattern = TIME_STRING) LocalDateTime rangeStart, 37 | @RequestParam(required = false) 38 | @DateTimeFormat(pattern = TIME_STRING) LocalDateTime rangeEnd, 39 | @RequestParam(defaultValue = "false") Boolean onlyAvailable, 40 | @RequestParam(required = false) String sort, 41 | @RequestParam(defaultValue = "0") @PositiveOrZero int from, 42 | @RequestParam(defaultValue = "10") @Positive int size, 43 | HttpServletRequest request) { 44 | log.info("Calling the PATCH request to users/{userId}/events/{eventId}/requests"); 45 | return ResponseEntity.ok(service.readPublicEvents(text, categories, paid, 46 | rangeStart, rangeEnd, onlyAvailable, sort, from, size, request)); 47 | } 48 | 49 | 50 | @GetMapping("/{id}") 51 | public ResponseEntity getPublicEvent(@PathVariable Long id, HttpServletRequest request) { 52 | log.info("Calling the PATCH request to /events/{id}"); 53 | return ResponseEntity.ok(service.getPublicEvent(id, request)); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /ewm-main-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | ru.practicum 9 | explore-with-me 10 | 0.0.1-SNAPSHOT 11 | ../pom.xml 12 | 13 | 14 | ru.practicum 15 | ewm-main-service 16 | 0.0.1-SNAPSHOT 17 | 18 | 19 | 20 | org.springframework.boot 21 | spring-boot-starter-web 22 | 23 | 24 | 25 | ru.practicum 26 | stat_dto 27 | ${project.version} 28 | compile 29 | 30 | 31 | 32 | org.projectlombok 33 | lombok 34 | true 35 | 36 | 37 | 38 | com.h2database 39 | h2 40 | runtime 41 | 42 | 43 | 44 | org.springframework.boot 45 | spring-boot-configuration-processor 46 | true 47 | 48 | 49 | 50 | org.postgresql 51 | postgresql 52 | runtime 53 | 54 | 55 | 56 | org.springframework.boot 57 | spring-boot-starter-data-jpa 58 | 59 | 60 | 61 | org.springframework.boot 62 | spring-boot-starter-test 63 | test 64 | 65 | 66 | 67 | org.springframework.boot 68 | spring-boot-starter-actuator 69 | 70 | 71 | 72 | org.springframework.boot 73 | spring-boot-starter-validation 74 | 75 | 76 | ru.practicum 77 | stat_client 78 | ${project.version} 79 | compile 80 | 81 | 82 | 83 | 84 | 85 | org.springframework.boot 86 | spring-boot-maven-plugin 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/exception/handler/MainServiceHandler.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.exception.handler; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.dao.DataIntegrityViolationException; 5 | import org.springframework.http.HttpStatus; 6 | import org.springframework.http.ResponseEntity; 7 | import org.springframework.web.bind.MethodArgumentNotValidException; 8 | import org.springframework.web.bind.MissingRequestHeaderException; 9 | import org.springframework.web.bind.MissingServletRequestParameterException; 10 | import org.springframework.web.bind.annotation.ExceptionHandler; 11 | import org.springframework.web.bind.annotation.RestControllerAdvice; 12 | import ru.practicum.main.exception.*; 13 | 14 | import javax.validation.ConstraintViolationException; 15 | import java.time.LocalDateTime; 16 | import java.time.format.DateTimeFormatter; 17 | 18 | @Slf4j 19 | @RestControllerAdvice 20 | public class MainServiceHandler { 21 | 22 | private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); 23 | 24 | 25 | @ExceptionHandler({MissingRequestHeaderException.class, MethodArgumentNotValidException.class, 26 | BadRequestException.class, ConstraintViolationException.class, MissingServletRequestParameterException.class}) 27 | public ResponseEntity handleBadRequest(final Exception e) { 28 | log.error("{} - Status: {}, Description: {}, Timestamp: {}", 29 | "Bad Request", HttpStatus.BAD_REQUEST, e.getMessage(), LocalDateTime.now()); 30 | 31 | return new ResponseEntity<>(new ErrorResponse(HttpStatus.BAD_REQUEST.name(), e.getMessage(), 32 | "Bad Request", LocalDateTime.now().format(FORMATTER)), HttpStatus.BAD_REQUEST); 33 | } 34 | 35 | @ExceptionHandler 36 | public ResponseEntity handleInternalServerError(final Exception e) { 37 | log.error("{} - Status: {}, Description: {}, Timestamp: {}", 38 | "SERVER ERROR", HttpStatus.INTERNAL_SERVER_ERROR, e.getMessage(), LocalDateTime.now()); 39 | 40 | return new ResponseEntity<>(new ErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR.name(), e.getMessage(), 41 | "Internal Server Error", LocalDateTime.now().format(FORMATTER)), HttpStatus.INTERNAL_SERVER_ERROR); 42 | } 43 | 44 | 45 | @ExceptionHandler({ConflictException.class, DataIntegrityViolationException.class, NotUniqueException.class}) 46 | public ResponseEntity handleConflict(final Exception e) { 47 | log.error("{} - Status: {}, Description: {}, Timestamp: {}", 48 | "CONFLICT", HttpStatus.CONFLICT, e.getMessage(), LocalDateTime.now()); 49 | 50 | return new ResponseEntity<>(new ErrorResponse(HttpStatus.CONFLICT.name(), e.getMessage(), 51 | "Data Integrity constraint violation occurred", LocalDateTime.now().format(FORMATTER)), 52 | HttpStatus.CONFLICT); 53 | } 54 | 55 | @ExceptionHandler({NotFoundException.class}) 56 | public ResponseEntity handleNotFound(final RuntimeException e) { 57 | log.error("{} - Status: {}, Description: {}, Timestamp: {}", 58 | "NOT FOUND", HttpStatus.NOT_FOUND, e.getMessage(), LocalDateTime.now()); 59 | 60 | return new ResponseEntity<>(new ErrorResponse(HttpStatus.NOT_FOUND.name(), e.getMessage(), 61 | "Not Found", LocalDateTime.now().format(FORMATTER)), HttpStatus.NOT_FOUND); 62 | } 63 | 64 | } 65 | 66 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/event/controller/EventPrivateController.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.event.controller; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.http.HttpStatus; 6 | import org.springframework.http.ResponseEntity; 7 | import org.springframework.validation.annotation.Validated; 8 | import org.springframework.web.bind.annotation.*; 9 | import ru.practicum.dto.Validator; 10 | import ru.practicum.main.event.dto.*; 11 | import ru.practicum.main.event.service.EventPrivateService; 12 | import ru.practicum.main.request.dto.RequestDto; 13 | 14 | import javax.validation.constraints.Positive; 15 | import javax.validation.constraints.PositiveOrZero; 16 | import java.util.List; 17 | 18 | @RestController 19 | @RequiredArgsConstructor 20 | @Validated 21 | @RequestMapping(path = "/users") 22 | @Slf4j 23 | public class EventPrivateController { 24 | 25 | private final EventPrivateService eventPrivateService; 26 | 27 | @PostMapping("/{userId}/events") 28 | @ResponseStatus(HttpStatus.CREATED) 29 | public ResponseEntity createEvent(@PathVariable Long userId, @RequestBody @Validated EventRequestDto eventRequestDto) { 30 | log.info("Calling the POST request to /users/{userId}/events"); 31 | return ResponseEntity.status(HttpStatus.CREATED).body(eventPrivateService.createEvent(userId, eventRequestDto)); 32 | } 33 | 34 | @GetMapping("/{userId}/events") 35 | public ResponseEntity> getEventByUserId(@PathVariable Long userId, 36 | @RequestParam(defaultValue = "0") @PositiveOrZero int from, 37 | @RequestParam(defaultValue = "10") @Positive int size) { 38 | log.info("Calling the GET request to /users/{userId}/events"); 39 | return ResponseEntity.ok(eventPrivateService.readEventByUserId(userId, from, size)); 40 | } 41 | 42 | @PatchMapping("/{userId}/events/{eventId}") 43 | public ResponseEntity patchEvent(@PathVariable Long userId, @PathVariable Long eventId, 44 | @RequestBody @Validated(Validator.Update.class) UpdateEventDto receivedDto) { 45 | log.info("Calling the PATCH request to users/{userId}/events/{eventId}"); 46 | return ResponseEntity.ok(eventPrivateService.updateEvent(userId, eventId, receivedDto)); 47 | } 48 | 49 | @GetMapping("/{userId}/events/{eventId}") 50 | public ResponseEntity getEventByUserIdAndEventId(@PathVariable Long userId, @PathVariable Long eventId) { 51 | log.info("Calling the GET request to users/{userId}/events/{eventId}"); 52 | return ResponseEntity.ok(eventPrivateService.readEventByUserIdAndEventId(userId, eventId)); 53 | } 54 | 55 | @PatchMapping("/{userId}/events/{eventId}/requests") 56 | public ResponseEntity patchRequestByOwnerUser(@PathVariable Long userId, @PathVariable Long eventId, 57 | @RequestBody RequestShortDto requestShortDto) { 58 | log.info("Calling the PATCH request to users/{userId}/events/{eventId}/requests"); 59 | return ResponseEntity.ok(eventPrivateService.updateRequestByOwner(userId, eventId, requestShortDto)); 60 | } 61 | 62 | @GetMapping("/{userId}/events/{eventId}/requests") 63 | public ResponseEntity> getRequestByUserIdAndEventId(@PathVariable Long userId, @PathVariable Long eventId) { 64 | log.info("Calling the PATCH request to users/{userId}/events/{eventId}"); 65 | return ResponseEntity.ok(eventPrivateService.readRequestByUserIdAndEventId(userId, eventId)); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/compilation/service/CompilationAdminServiceImpl.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.compilation.service; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.stereotype.Service; 6 | import org.springframework.transaction.annotation.Transactional; 7 | import ru.practicum.main.compilation.dto.CompilationDto; 8 | import ru.practicum.main.compilation.dto.NewCompilationDto; 9 | import ru.practicum.main.compilation.mapper.CompilationMapper; 10 | import ru.practicum.main.compilation.model.Compilation; 11 | import ru.practicum.main.compilation.repository.CompilationMainServiceRepository; 12 | import ru.practicum.main.event.model.Event; 13 | import ru.practicum.main.event.repository.EventMainServiceRepository; 14 | import ru.practicum.main.exception.NotFoundException; 15 | import ru.practicum.main.exception.NotUniqueException; 16 | 17 | import java.util.HashSet; 18 | import java.util.Set; 19 | 20 | @Service 21 | @Transactional 22 | @RequiredArgsConstructor 23 | @Slf4j 24 | public class CompilationAdminServiceImpl implements CompilationAdminService { 25 | 26 | private final CompilationMainServiceRepository compilationMainServiceRepository; 27 | 28 | private final EventMainServiceRepository eventMainServiceRepository; 29 | 30 | 31 | @Override 32 | public CompilationDto createCompilation(NewCompilationDto request) { 33 | log.info("createCompilation - invoked"); 34 | 35 | if (compilationMainServiceRepository.existsByTitle(request.getTitle())) { 36 | throw new NotUniqueException("Title not unique"); 37 | } 38 | 39 | Set events; 40 | events = (request.getEvents() != null && request.getEvents().size() != 0) ? 41 | new HashSet<>(eventMainServiceRepository.findAllById(request.getEvents())) : new HashSet<>(); 42 | 43 | Compilation compilation = Compilation.builder() 44 | .pinned(request.getPinned() != null && request.getPinned()) 45 | .title(request.getTitle()) 46 | .events(events) 47 | .build(); 48 | 49 | return CompilationMapper.toCompilationsDtoFromCompilation(compilationMainServiceRepository.save(compilation)); 50 | } 51 | 52 | @Override 53 | public void deleteCompilation(Long compId) { 54 | log.info("deleteCompilation(- invoked"); 55 | 56 | if (!compilationMainServiceRepository.existsById(compId)) { 57 | throw new NotFoundException("Compilation Not Found"); 58 | } 59 | log.info("Result: compilation with id {} deleted ", compId); 60 | compilationMainServiceRepository.deleteById(compId); 61 | } 62 | 63 | 64 | @Override 65 | public CompilationDto updateCompilation(Long compId, NewCompilationDto newCompilationDto) { 66 | log.info("updateCompilation - invoked"); 67 | 68 | Compilation compilation = compilationMainServiceRepository.findById(compId) 69 | .orElseThrow(() -> new NotFoundException("Compilation with id " + compId + " not found")); 70 | 71 | if (newCompilationDto.getTitle() != null) { 72 | compilation.setTitle(newCompilationDto.getTitle()); 73 | } 74 | if (newCompilationDto.getPinned() != null) { 75 | compilation.setPinned(newCompilationDto.getPinned()); 76 | } 77 | if (newCompilationDto.getEvents() != null) { 78 | HashSet events = new HashSet<>(eventMainServiceRepository.findAllById(newCompilationDto.getEvents())); 79 | compilation.setEvents(events); 80 | } 81 | 82 | Compilation updatedCompilation = compilationMainServiceRepository.save(compilation); 83 | 84 | log.info("Result: compilation with id {} updated ", compId); 85 | 86 | return CompilationMapper.toCompilationsDtoFromCompilation(updatedCompilation); 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/event/service/EventPublicServiceImpl.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.event.service; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.stereotype.Service; 6 | import org.springframework.transaction.annotation.Transactional; 7 | import ru.practicum.main.comment.service.PrivateCommentService; 8 | import ru.practicum.main.event.status.State; 9 | import ru.practicum.main.event.dto.EventFullDto; 10 | import ru.practicum.main.event.dto.EventShortDto; 11 | import ru.practicum.main.event.repository.EventMainServiceRepository; 12 | import ru.practicum.main.exception.NotFoundException; 13 | import ru.practicum.main.event.mapper.EventMapper; 14 | import ru.practicum.main.event.model.Event; 15 | import ru.practicum.main.event.dto.EventDto; 16 | import ru.practicum.main.stat.service.StatService; 17 | 18 | import javax.servlet.http.HttpServletRequest; 19 | import java.time.LocalDateTime; 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | import java.util.Map; 23 | 24 | import static ru.practicum.main.util.Util.createPageRequestDesc; 25 | 26 | @Service 27 | @Transactional(readOnly = true) 28 | @RequiredArgsConstructor 29 | @Slf4j 30 | public class EventPublicServiceImpl implements EventPublicService { 31 | 32 | private final EventMainServiceRepository repository; 33 | 34 | private final StatService statService; 35 | 36 | private final PrivateCommentService privateCommentService; 37 | 38 | 39 | @Override 40 | public List readPublicEvents(String text, List categories, Boolean paid, LocalDateTime rangeStart, 41 | LocalDateTime rangeEnd, Boolean onlyAvailable, String sort, Integer from, 42 | Integer size, HttpServletRequest request) { 43 | log.info("readPublicEvents - invoked"); 44 | sort = (sort != null && sort.equals("EVENT_DATE")) ? "eventDate" : "id"; 45 | 46 | List list = repository.findAllEvents(text, categories, paid, rangeStart, rangeEnd, 47 | onlyAvailable, sort, createPageRequestDesc(sort, from, size)); 48 | 49 | Map confirmedRequest = statService.toConfirmedRequest(list); 50 | Map view = statService.toView(list); 51 | Map commentCount = privateCommentService.getCommentCount(list); 52 | 53 | List events = new ArrayList<>(); 54 | 55 | list.forEach(event -> events.add(EventMapper.toEventDto(event, view.getOrDefault(event.getId(), 0L), 56 | confirmedRequest.getOrDefault(event.getId(), 0L), commentCount.getOrDefault(event.getId(), 0L)))); 57 | 58 | statService.addHits(request); 59 | log.info("Result: list event size = {}", events.size()); 60 | return EventMapper.toListEventShortDto(events); 61 | } 62 | 63 | @Override 64 | public EventFullDto getPublicEvent(Long id, HttpServletRequest request) { 65 | log.info("getPublicEvent - invoked"); 66 | Event event = repository.findById(id).orElseThrow(() -> { 67 | log.error("Event with id = {} not exist", id); 68 | return new NotFoundException("Event not found"); 69 | }); 70 | 71 | if (!event.getState().equals(State.PUBLISHED)) { 72 | log.error("Event with id = {} not published", id); 73 | throw new NotFoundException("Event should pe published"); 74 | } 75 | 76 | Map confirmedRequest = statService.toConfirmedRequest(List.of(event)); 77 | Map view = statService.toView(List.of(event)); 78 | 79 | statService.addHits(request); 80 | 81 | event.setConfirmedRequests(confirmedRequest.getOrDefault(event.getId(), 0L)); 82 | event.setView(view.getOrDefault(event.getId(), 0L)); 83 | log.info("Result: event - {}", event.getTitle()); 84 | return EventMapper.toEventFullDto(event); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/category/service/CategoryAdminServiceImpl.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.category.service; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.dao.DataIntegrityViolationException; 6 | import org.springframework.stereotype.Service; 7 | import org.springframework.transaction.annotation.Transactional; 8 | import ru.practicum.main.category.dto.CategoryDto; 9 | import ru.practicum.main.category.mapper.CategoryMapper; 10 | import ru.practicum.main.category.model.Category; 11 | import ru.practicum.main.category.repository.CategoryMainServiceRepository; 12 | import ru.practicum.main.event.repository.EventMainServiceRepository; 13 | import ru.practicum.main.exception.ConflictException; 14 | import ru.practicum.main.exception.NotFoundException; 15 | import ru.practicum.main.exception.NotUniqueException; 16 | 17 | @Service 18 | @RequiredArgsConstructor 19 | @Transactional(readOnly = true) 20 | @Slf4j 21 | public class CategoryAdminServiceImpl implements CategoryAdminService { 22 | 23 | private final CategoryMainServiceRepository categoryMainServiceRepository; 24 | 25 | private final EventMainServiceRepository eventMainServiceRepository; 26 | 27 | @Override 28 | @Transactional 29 | public CategoryDto createCategory(CategoryDto requestCategory) { 30 | log.info("createCategories - invoked"); 31 | if (categoryMainServiceRepository.existsByName(requestCategory.getName())) { 32 | log.error("Category name not unique {}", requestCategory.getName()); 33 | throw new NotUniqueException("Category with this name already exists"); 34 | } 35 | try { 36 | Category result = categoryMainServiceRepository.saveAndFlush(CategoryMapper.toCategories(requestCategory)); 37 | log.info("Result: category - {} - saved", result.getName()); 38 | return CategoryMapper.toCategoryDto(result); 39 | 40 | } catch (DataIntegrityViolationException e) { 41 | log.error("Category already exist = {}", requestCategory); 42 | throw new ConflictException("Category with name " + requestCategory.getName() + " already exits"); 43 | } 44 | } 45 | 46 | @Override 47 | @Transactional 48 | public void deleteCategory(Long catId) { 49 | log.info("deleteCategories - invoked"); 50 | 51 | if (!categoryMainServiceRepository.existsById(catId)) { 52 | log.error("Category with this id does not exist {}", catId); 53 | throw new NotFoundException("Category with this id does not exist"); 54 | } 55 | 56 | if (eventMainServiceRepository.existsByCategoryId(catId)) { 57 | throw new ConflictException("Can't delete a category with associated events"); 58 | } 59 | 60 | if (!categoryMainServiceRepository.existsById(catId)) { 61 | throw new NotFoundException("Category does not exist"); 62 | } 63 | log.info("Result: category with id - {} - deleted", catId); 64 | categoryMainServiceRepository.deleteById(catId); 65 | } 66 | 67 | @Transactional 68 | @Override 69 | public CategoryDto updateCategory(Long catId, CategoryDto categoryDto) { 70 | log.info("updateCategories - invoked"); 71 | Category category = categoryMainServiceRepository.findById(catId).orElseThrow(() 72 | -> new NotFoundException("This Category not found")); 73 | 74 | if (!category.getName().equals(categoryDto.getName()) && 75 | categoryMainServiceRepository.existsByName(categoryDto.getName())) { 76 | log.error("Category with this name not unique: {}", categoryDto.getName()); 77 | throw new NotUniqueException("Category with this name not unique: " + categoryDto.getName()); 78 | } 79 | category.setName(categoryDto.getName()); 80 | log.info("Result: category - {} updated", category.getName()); 81 | return CategoryMapper.toCategoryDto(category); 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/stat/service/StatServiceImpl.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.stat.service; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import lombok.RequiredArgsConstructor; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.beans.factory.annotation.Value; 8 | import org.springframework.http.ResponseEntity; 9 | import org.springframework.stereotype.Service; 10 | import org.springframework.transaction.annotation.Transactional; 11 | import ru.practicum.client.StatClient; 12 | import ru.practicum.dto.StatDto; 13 | import ru.practicum.dto.StatResponseDto; 14 | import ru.practicum.main.event.model.Event; 15 | import ru.practicum.main.exception.StatParseException; 16 | import ru.practicum.main.request.dto.ConfirmedRequestShortDto; 17 | import ru.practicum.main.request.repository.RequestMainServiceRepository; 18 | 19 | import javax.servlet.http.HttpServletRequest; 20 | import java.time.LocalDateTime; 21 | import java.time.format.DateTimeFormatter; 22 | import java.util.*; 23 | import java.util.stream.Collectors; 24 | 25 | @Service 26 | @RequiredArgsConstructor 27 | @Transactional(readOnly = true) 28 | @Slf4j 29 | public class StatServiceImpl implements StatService { 30 | 31 | private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); 32 | 33 | private final RequestMainServiceRepository requestMainServiceRepository; 34 | 35 | private final StatClient statClient; 36 | 37 | private final ObjectMapper objectMapper; 38 | 39 | @Value("${main_app}") 40 | private String app; 41 | 42 | @Override 43 | public Map toConfirmedRequest(Collection list) { 44 | log.info("toConfirmedRequest - invoked"); 45 | List listEventId = list.stream().map(Event::getId).collect(Collectors.toList()); 46 | List confirmedRequestShortDtoList = requestMainServiceRepository.countByEventId(listEventId); 47 | Map confirmedRequest = confirmedRequestShortDtoList.stream() 48 | .collect(Collectors.toMap(ConfirmedRequestShortDto::getEventId, ConfirmedRequestShortDto::getConfirmedRequestsCount)); 49 | log.info("Result: map of confirmed request size = {}", confirmedRequest.size()); 50 | return confirmedRequest; 51 | } 52 | 53 | @Override 54 | public Map toView(Collection events) { 55 | log.info("toView - invoked"); 56 | Map view = new HashMap<>(); 57 | LocalDateTime start = events.stream().map(Event::getCreatedOn).min(LocalDateTime::compareTo).orElse(null); 58 | if (start == null) { 59 | return Map.of(); 60 | } 61 | List uris = events.stream().map(a -> "/events/" + a.getId()).collect(Collectors.toList()); 62 | 63 | ResponseEntity response = statClient.readStatEvent(start.format(FORMATTER), 64 | LocalDateTime.now().format(FORMATTER), uris, true); 65 | 66 | try { 67 | StatResponseDto[] stats = objectMapper.readValue( 68 | objectMapper.writeValueAsString(response.getBody()), StatResponseDto[].class); 69 | 70 | 71 | 72 | for (StatResponseDto stat : stats) { 73 | view.put( 74 | Long.parseLong(stat.getUri().replaceAll("\\D+", "")), 75 | stat.getHits()); 76 | } 77 | 78 | } catch (JsonProcessingException e) { 79 | log.error("JsonProcessingException exc - can't parse"); 80 | throw new StatParseException("Statistics error"); 81 | } 82 | log.info("Result: view size = {}", view.size()); 83 | return view; 84 | } 85 | 86 | @Transactional 87 | @Override 88 | public void addHits(HttpServletRequest request) { 89 | statClient.addStatEvent(StatDto.builder() 90 | .ip(request.getRemoteAddr()) 91 | .timestamp(LocalDateTime.now()) 92 | .uri(request.getRequestURI()) 93 | .app(app) 94 | .build()); 95 | log.info("add hits"); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/resources/schema.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS users ( 2 | id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, 3 | email VARCHAR(254) NOT NULL, 4 | user_name VARCHAR(250) NOT NULL, 5 | CONSTRAINT pk_users PRIMARY KEY (id), 6 | CONSTRAINT uq_user_email UNIQUE (email) 7 | ); 8 | 9 | CREATE TABLE IF NOT EXISTS categories ( 10 | id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, 11 | cat_name VARCHAR(200) NOT NULL, 12 | CONSTRAINT pk_categories PRIMARY KEY (id), 13 | CONSTRAINT uq_categories_name UNIQUE (cat_name) 14 | ); 15 | 16 | CREATE TABLE IF NOT EXISTS location ( 17 | id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, 18 | lat double NOT NULL, 19 | lon double NOT NULL, 20 | CONSTRAINT pk_location PRIMARY KEY (id) 21 | ); 22 | 23 | 24 | CREATE TABLE IF NOT EXISTS event ( 25 | id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, 26 | annotation VARCHAR(2000) NOT NULL, 27 | category_id BIGINT NOT NULL, 28 | created_on TIMESTAMP WITHOUT TIME ZONE NOT NULL, 29 | description VARCHAR(7000) NOT NULL, 30 | event_date TIMESTAMP WITHOUT TIME ZONE NOT NULL, 31 | initiator_id BIGINT NOT NULL, 32 | location_id BIGINT NOT NULL, 33 | paid BOOLEAN NOT NULL, 34 | participant_limit int NOT NULL, 35 | request_moderation BOOLEAN DEFAULT TRUE, 36 | state_event VARCHAR(50) NOT NULL, 37 | title VARCHAR(120) NOT NULL, 38 | published_on TIMESTAMP WITHOUT TIME ZONE, 39 | 40 | CONSTRAINT pk_event PRIMARY KEY (id), 41 | CONSTRAINT fk_event_category_id FOREIGN KEY (category_id) REFERENCES categories (id) ON DELETE CASCADE, 42 | CONSTRAINT fk_event_initiator_id FOREIGN KEY (initiator_id) REFERENCES users (id) ON DELETE CASCADE, 43 | CONSTRAINT fk_event_location_id FOREIGN KEY (location_id) REFERENCES location (id) ON DELETE CASCADE 44 | ); 45 | 46 | CREATE TABLE IF NOT EXISTS request ( 47 | id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, 48 | created TIMESTAMP WITHOUT TIME ZONE NOT NULL, 49 | event_id BIGINT NOT NULL, 50 | requester_id BIGINT NOT NULL, 51 | status VARCHAR(50) NOT NULL, 52 | 53 | CONSTRAINT pk_request PRIMARY KEY (id), 54 | CONSTRAINT fk_request_event_id FOREIGN KEY (event_id) REFERENCES event (id) ON DELETE CASCADE, 55 | CONSTRAINT fk_request_requester_id FOREIGN KEY (requester_id) REFERENCES users (id) ON DELETE CASCADE 56 | ); 57 | 58 | CREATE TABLE IF NOT EXISTS compilations ( 59 | id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, 60 | pinned BOOLEAN NOT NULL, 61 | title VARCHAR(200) NOT NULL, 62 | 63 | CONSTRAINT pk_compilations PRIMARY KEY (id) 64 | ); 65 | 66 | CREATE TABLE IF NOT EXISTS compilations_events ( 67 | compilations_id BIGINT NOT NULL, 68 | events_id BIGINT NOT NULL, 69 | 70 | CONSTRAINT pk_compilations_events PRIMARY KEY (compilations_id, events_id), 71 | CONSTRAINT fk_compilations FOREIGN KEY (compilations_id) REFERENCES compilations (id) ON DELETE CASCADE, 72 | CONSTRAINT fk_events FOREIGN KEY (events_id) REFERENCES event (id) ON DELETE CASCADE 73 | ); 74 | 75 | CREATE TABLE IF NOT EXISTS comments ( 76 | id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, 77 | textual_content VARCHAR(1000) NOT NULL, 78 | author_id BIGINT NOT NULL, 79 | event_id BIGINT NOT NULL, 80 | create_time TIMESTAMP WITHOUT TIME ZONE NOT NULL, 81 | patch_time TIMESTAMP WITHOUT TIME ZONE, 82 | 83 | CONSTRAINT pk_comment PRIMARY KEY (id), 84 | CONSTRAINT fk_user_comment FOREIGN KEY (author_id) REFERENCES users (id) ON DELETE CASCADE, 85 | CONSTRAINT fk_event_comment FOREIGN KEY (event_id) REFERENCES event (id) ON DELETE CASCADE 86 | ); 87 | 88 | CREATE INDEX idx_textual_content ON comments (textual_content); -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/request/service/RequestServiceImpl.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.request.service; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.stereotype.Service; 6 | import org.springframework.transaction.annotation.Transactional; 7 | import ru.practicum.main.request.Status; 8 | import ru.practicum.main.event.model.Event; 9 | import ru.practicum.main.event.repository.EventMainServiceRepository; 10 | import ru.practicum.main.event.status.State; 11 | import ru.practicum.main.exception.ConflictException; 12 | import ru.practicum.main.exception.NotFoundException; 13 | import ru.practicum.main.request.dto.ConfirmedRequestShortDto; 14 | import ru.practicum.main.request.dto.RequestDto; 15 | import ru.practicum.main.request.mapper.RequestMapper; 16 | import ru.practicum.main.request.model.Request; 17 | import ru.practicum.main.request.repository.RequestMainServiceRepository; 18 | import ru.practicum.main.user.model.User; 19 | import ru.practicum.main.user.repository.UserMainServiceRepository; 20 | 21 | import java.time.LocalDateTime; 22 | import java.util.List; 23 | 24 | @Service 25 | @Transactional(readOnly = true) 26 | @RequiredArgsConstructor 27 | @Slf4j 28 | public class RequestServiceImpl implements RequestService { 29 | 30 | private final RequestMainServiceRepository requestRepository; 31 | 32 | private final UserMainServiceRepository userMainServiceRepository; 33 | 34 | private final EventMainServiceRepository eventMainServiceRepository; 35 | 36 | 37 | @Override 38 | public List readAllRequests(Long userId) { 39 | log.info("readAllRequests - invoked"); 40 | List requests = RequestMapper.toListRequestDto(requestRepository.findAllByRequesterId(userId)); 41 | log.info("Result: list of {} requests", requests.size()); 42 | return requests; 43 | } 44 | 45 | @Transactional 46 | @Override 47 | public RequestDto createRequest(Long userId, Long eventId) { 48 | log.info("createRequest - invoked"); 49 | Status status; 50 | Event event = eventMainServiceRepository.findById(eventId).orElseThrow(() -> { 51 | log.error("Event with id = {} not exist", eventId); 52 | return new NotFoundException("Event not found"); 53 | }); 54 | 55 | if (event.getInitiator().getId().equals(userId)) { 56 | log.error("Unauthorized access by user"); 57 | throw new ConflictException("The initiator of the event cannot send a request for participation"); 58 | } 59 | 60 | if (!event.getState().equals(State.PUBLISHED)) { 61 | log.error("Event state = {} - it should be PUBLISHED", event.getState()); 62 | throw new ConflictException("The event must be published in order to participate"); 63 | } 64 | 65 | if (requestRepository.existsByRequesterIdAndEventId(userId, eventId)) { 66 | log.error("Unauthorized access by user - request already exist"); 67 | throw new ConflictException("You're already participating"); 68 | } 69 | 70 | status = (!event.getRequestModeration() || event.getParticipantLimit() == 0) ? Status.CONFIRMED : Status.PENDING; 71 | 72 | 73 | List confirmed = requestRepository.countByEventId(List.of(eventId)); 74 | 75 | if (confirmed.size() >= event.getParticipantLimit() && event.getParticipantLimit() != 0) { 76 | log.error("The list of participants is filled"); 77 | throw new ConflictException("There are no vacancies, try to send a request for another event"); 78 | } 79 | User user = userMainServiceRepository.findById(userId).orElseThrow(() -> { 80 | log.error("User with id = {} not exist", userId); 81 | return new NotFoundException("User not found"); 82 | }); 83 | 84 | Request request = requestRepository.save(Request.builder() 85 | .requester(user) 86 | .event(event) 87 | .created(LocalDateTime.now().withNano(0)) 88 | .status(status) 89 | .build()); 90 | 91 | log.info("Result: request {} - created", request); 92 | return RequestMapper.toRequestDto(request); 93 | } 94 | 95 | 96 | @Transactional 97 | @Override 98 | public RequestDto cancelRequest(Long userId, Long requestId) { 99 | log.info("cancelRequest - invoked"); 100 | if (!userMainServiceRepository.existsById(userId)) { 101 | log.error("User with id = {} not exist", userId); 102 | throw new NotFoundException("User not found"); 103 | } 104 | Request request = requestRepository.findById(requestId).orElseThrow(() -> { 105 | log.error("Request with id = {} not exist", requestId); 106 | return new NotFoundException("Request not found"); 107 | }); 108 | 109 | request.setStatus(Status.CANCELED); 110 | log.info("Result:request id = {}, request status = {}", requestId, request.getStatus()); 111 | return RequestMapper.toRequestDto(request); 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/comment/service/PrivateCommentServiceImpl.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.comment.service; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.stereotype.Service; 6 | import org.springframework.transaction.annotation.Transactional; 7 | import ru.practicum.main.comment.dto.CommentCountDto; 8 | import ru.practicum.main.comment.dto.CommentDto; 9 | import ru.practicum.main.comment.dto.CommentCreateDto; 10 | import ru.practicum.main.comment.mapper.CommentMapper; 11 | import ru.practicum.main.comment.model.Comment; 12 | import ru.practicum.main.comment.repository.CommentMainServiceRepository; 13 | import ru.practicum.main.event.model.Event; 14 | import ru.practicum.main.event.repository.EventMainServiceRepository; 15 | import ru.practicum.main.event.status.State; 16 | import ru.practicum.main.exception.ConflictException; 17 | import ru.practicum.main.exception.NotFoundException; 18 | import ru.practicum.main.user.model.User; 19 | import ru.practicum.main.user.repository.UserMainServiceRepository; 20 | 21 | import java.time.LocalDateTime; 22 | import java.util.Collection; 23 | import java.util.List; 24 | import java.util.Map; 25 | import java.util.stream.Collectors; 26 | 27 | @Service 28 | @Transactional(readOnly = true) 29 | @RequiredArgsConstructor 30 | @Slf4j 31 | public class PrivateCommentServiceImpl implements PrivateCommentService { 32 | 33 | private final CommentMainServiceRepository repository; 34 | 35 | private final UserMainServiceRepository userMainServiceRepository; 36 | 37 | private final EventMainServiceRepository eventMainServiceRepository; 38 | 39 | @Transactional 40 | @Override 41 | public CommentDto createComment(Long userId, Long eventId, CommentCreateDto commentDto) { 42 | log.info("createComment - invoked"); 43 | Comment comment = CommentMapper.toComment(commentDto); 44 | User author = userMainServiceRepository.findById(userId) 45 | .orElseThrow(() -> { 46 | log.error("User with id = {} - not registered", userId); 47 | return new NotFoundException("Please register first then you can comment"); 48 | }); 49 | 50 | Event event = eventMainServiceRepository.findById(eventId) 51 | .orElseThrow(() -> { 52 | log.error("Event with id = {} - not exist", eventId); 53 | return new NotFoundException("Event not found"); 54 | }); 55 | 56 | if (!event.getState().equals(State.PUBLISHED)) { 57 | log.error("Event state = {} - should be PUBLISHED", event.getState()); 58 | throw new ConflictException("Event not published you cant comment it"); 59 | } 60 | 61 | comment.setAuthor(author); 62 | comment.setEvent(event); 63 | comment.setCreateTime(LocalDateTime.now().withNano(0)); 64 | log.info("Result: new comment created"); 65 | return CommentMapper.toCommentDto(repository.save(comment)); 66 | } 67 | 68 | @Transactional 69 | @Override 70 | public void deleteComment(Long userId, Long comId) { 71 | log.info("deleteComment - invoked"); 72 | Comment comment = repository.findById(comId) 73 | .orElseThrow(() -> { 74 | log.error("Comment with id = {} - not exist", comId); 75 | return new NotFoundException("Comment not found"); 76 | }); 77 | 78 | if (!comment.getAuthor().getId().equals(userId)) { 79 | log.error("Unauthorized access by user"); 80 | throw new ConflictException("you didn't write this comment and can't delete it"); 81 | } 82 | log.info("Result: comment with id = {} - deleted", comId); 83 | repository.deleteById(comId); 84 | } 85 | 86 | @Transactional 87 | @Override 88 | public CommentDto patchComment(Long userId, Long comId, CommentCreateDto commentCreateDto) { 89 | log.info("patchComment - invoked"); 90 | 91 | Comment newComment = CommentMapper.toComment(commentCreateDto); 92 | 93 | Comment comment = repository.findById(comId) 94 | .orElseThrow(() -> { 95 | log.error("Comment with id = {} - not exist", comId); 96 | return new NotFoundException("Comment not found"); 97 | }); 98 | 99 | if (!comment.getAuthor().getId().equals(userId)) { 100 | log.error("Unauthorized access by user"); 101 | throw new ConflictException("you didn't write this comment and can't patch it"); 102 | } 103 | 104 | comment.setText(newComment.getText()); 105 | comment.setCreateTime(LocalDateTime.now().withNano(0)); 106 | log.info("Result: comment with id = {} - updated", comId); 107 | return CommentMapper.toCommentDto(comment); 108 | } 109 | 110 | @Override 111 | public Map getCommentCount(Collection list) { 112 | List listEventId = list.stream().map(Event::getId).collect(Collectors.toList()); 113 | List countList = repository.findAllCommentCount(listEventId); 114 | return countList.stream().collect(Collectors.toMap(CommentCountDto::getEventId, CommentCountDto::getCommentCount)); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /ewm-stats-service-spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.0.1", 3 | "info": { 4 | "title": "Stat service API", 5 | "version": "v0" 6 | }, 7 | "servers": [ 8 | { 9 | "url": "http://localhost:9090", 10 | "description": "Generated server url" 11 | } 12 | ], 13 | "tags": [ 14 | { 15 | "name": "StatsController", 16 | "description": "API для работы со статистикой посещений" 17 | } 18 | ], 19 | "paths": { 20 | "/hit": { 21 | "post": { 22 | "tags": [ 23 | "StatsController" 24 | ], 25 | "summary": "Сохранение информации о том, что к эндпоинту был запрос", 26 | "description": "Сохранение информации о том, что на uri конкретного сервиса был отправлен запрос пользователем. Название сервиса, uri и ip пользователя указаны в теле запроса.", 27 | "operationId": "hit", 28 | "requestBody": { 29 | "description": "данные запроса", 30 | "content": { 31 | "application/json": { 32 | "schema": { 33 | "$ref": "#/components/schemas/EndpointHit" 34 | } 35 | } 36 | }, 37 | "required": true 38 | }, 39 | "responses": { 40 | "201": { 41 | "description": "Информация сохранена" 42 | } 43 | } 44 | } 45 | }, 46 | "/stats": { 47 | "get": { 48 | "tags": [ 49 | "StatsController" 50 | ], 51 | "summary": "Получение статистики по посещениям. Обратите внимание: значение даты и времени нужно закодировать (например используя java.net.URLEncoder.encode) ", 52 | "operationId": "getStats", 53 | "parameters": [ 54 | { 55 | "name": "start", 56 | "in": "query", 57 | "description": "Дата и время начала диапазона за который нужно выгрузить статистику (в формате \"yyyy-MM-dd HH:mm:ss\")", 58 | "required": true, 59 | "schema": { 60 | "type": "string" 61 | } 62 | }, 63 | { 64 | "name": "end", 65 | "in": "query", 66 | "description": "Дата и время конца диапазона за который нужно выгрузить статистику (в формате \"yyyy-MM-dd HH:mm:ss\")", 67 | "required": true, 68 | "schema": { 69 | "type": "string" 70 | } 71 | }, 72 | { 73 | "name": "uris", 74 | "in": "query", 75 | "description": "Список uri для которых нужно выгрузить статистику", 76 | "required": false, 77 | "schema": { 78 | "type": "array", 79 | "items": { 80 | "type": "string" 81 | } 82 | } 83 | }, 84 | { 85 | "name": "unique", 86 | "in": "query", 87 | "description": "Нужно ли учитывать только уникальные посещения (только с уникальным ip)", 88 | "required": false, 89 | "schema": { 90 | "type": "boolean", 91 | "default": false 92 | } 93 | } 94 | ], 95 | "responses": { 96 | "200": { 97 | "description": "Статистика собрана", 98 | "content": { 99 | "application/json": { 100 | "schema": { 101 | "type": "array", 102 | "items": { 103 | "$ref": "#/components/schemas/ViewStats" 104 | } 105 | } 106 | } 107 | } 108 | } 109 | } 110 | } 111 | } 112 | }, 113 | "components": { 114 | "schemas": { 115 | "EndpointHit": { 116 | "type": "object", 117 | "properties": { 118 | "id": { 119 | "type": "integer", 120 | "description": "Идентификатор записи", 121 | "format": "int64", 122 | "readOnly": true, 123 | "example": 1 124 | }, 125 | "app": { 126 | "type": "string", 127 | "description": "Идентификатор сервиса для которого записывается информация", 128 | "example": "ewm-main-service" 129 | }, 130 | "uri": { 131 | "type": "string", 132 | "description": "URI для которого был осуществлен запрос", 133 | "example": "/events/1" 134 | }, 135 | "ip": { 136 | "type": "string", 137 | "description": "IP-адрес пользователя, осуществившего запрос", 138 | "example": "192.163.0.1" 139 | }, 140 | "timestamp": { 141 | "type": "string", 142 | "description": "Дата и время, когда был совершен запрос к эндпоинту (в формате \"yyyy-MM-dd HH:mm:ss\")", 143 | "example": "2022-09-06 11:00:23" 144 | } 145 | } 146 | }, 147 | "ViewStats": { 148 | "type": "object", 149 | "properties": { 150 | "app": { 151 | "type": "string", 152 | "description": "Название сервиса", 153 | "example": "ewm-main-service" 154 | }, 155 | "uri": { 156 | "type": "string", 157 | "description": "URI сервиса", 158 | "example": "/events/1" 159 | }, 160 | "hits": { 161 | "type": "integer", 162 | "description": "Количество просмотров", 163 | "format": "int64", 164 | "example": 6 165 | } 166 | } 167 | } 168 | } 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /.github/workflows/wait-for-it.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Use this script to test if a given TCP host/port are available 3 | 4 | WAITFORIT_cmdname=${0##*/} 5 | 6 | echoerr() { if [[ $WAITFORIT_QUIET -ne 1 ]]; then echo "$@" 1>&2; fi } 7 | 8 | usage() 9 | { 10 | cat << USAGE >&2 11 | Usage: 12 | $WAITFORIT_cmdname host:port [-s] [-t timeout] [-- command args] 13 | -h HOST | --host=HOST Host or IP under test 14 | -p PORT | --port=PORT TCP port under test 15 | Alternatively, you specify the host and port as host:port 16 | -s | --strict Only execute subcommand if the test succeeds 17 | -q | --quiet Don't output any status messages 18 | -t TIMEOUT | --timeout=TIMEOUT 19 | Timeout in seconds, zero for no timeout 20 | -- COMMAND ARGS Execute command with args after the test finishes 21 | USAGE 22 | exit 1 23 | } 24 | 25 | wait_for() 26 | { 27 | if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then 28 | echoerr "$WAITFORIT_cmdname: waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT" 29 | else 30 | echoerr "$WAITFORIT_cmdname: waiting for $WAITFORIT_HOST:$WAITFORIT_PORT without a timeout" 31 | fi 32 | WAITFORIT_start_ts=$(date +%s) 33 | while : 34 | do 35 | if [[ $WAITFORIT_ISBUSY -eq 1 ]]; then 36 | nc -z $WAITFORIT_HOST $WAITFORIT_PORT 37 | WAITFORIT_result=$? 38 | else 39 | # (echo -n > /dev/tcp/$WAITFORIT_HOST/$WAITFORIT_PORT) >/dev/null 2>&1 40 | (curl --fail --silent $WAITFORIT_HOST:$WAITFORIT_PORT/actuator/health | grep UP) >/dev/null 2>&1 41 | WAITFORIT_result=$? 42 | fi 43 | if [[ $WAITFORIT_result -eq 0 ]]; then 44 | WAITFORIT_end_ts=$(date +%s) 45 | echoerr "$WAITFORIT_cmdname: $WAITFORIT_HOST:$WAITFORIT_PORT is available after $((WAITFORIT_end_ts - WAITFORIT_start_ts)) seconds" 46 | break 47 | fi 48 | sleep 1 49 | done 50 | return $WAITFORIT_result 51 | } 52 | 53 | wait_for_wrapper() 54 | { 55 | # In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692 56 | if [[ $WAITFORIT_QUIET -eq 1 ]]; then 57 | timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --quiet --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT & 58 | else 59 | timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT & 60 | fi 61 | WAITFORIT_PID=$! 62 | trap "kill -INT -$WAITFORIT_PID" INT 63 | wait $WAITFORIT_PID 64 | WAITFORIT_RESULT=$? 65 | if [[ $WAITFORIT_RESULT -ne 0 ]]; then 66 | echoerr "$WAITFORIT_cmdname: timeout occurred after waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT" 67 | fi 68 | return $WAITFORIT_RESULT 69 | } 70 | 71 | # process arguments 72 | while [[ $# -gt 0 ]] 73 | do 74 | case "$1" in 75 | *:* ) 76 | WAITFORIT_hostport=(${1//:/ }) 77 | WAITFORIT_HOST=${WAITFORIT_hostport[0]} 78 | WAITFORIT_PORT=${WAITFORIT_hostport[1]} 79 | shift 1 80 | ;; 81 | --child) 82 | WAITFORIT_CHILD=1 83 | shift 1 84 | ;; 85 | -q | --quiet) 86 | WAITFORIT_QUIET=1 87 | shift 1 88 | ;; 89 | -s | --strict) 90 | WAITFORIT_STRICT=1 91 | shift 1 92 | ;; 93 | -h) 94 | WAITFORIT_HOST="$2" 95 | if [[ $WAITFORIT_HOST == "" ]]; then break; fi 96 | shift 2 97 | ;; 98 | --host=*) 99 | WAITFORIT_HOST="${1#*=}" 100 | shift 1 101 | ;; 102 | -p) 103 | WAITFORIT_PORT="$2" 104 | if [[ $WAITFORIT_PORT == "" ]]; then break; fi 105 | shift 2 106 | ;; 107 | --port=*) 108 | WAITFORIT_PORT="${1#*=}" 109 | shift 1 110 | ;; 111 | -t) 112 | WAITFORIT_TIMEOUT="$2" 113 | if [[ $WAITFORIT_TIMEOUT == "" ]]; then break; fi 114 | shift 2 115 | ;; 116 | --timeout=*) 117 | WAITFORIT_TIMEOUT="${1#*=}" 118 | shift 1 119 | ;; 120 | --) 121 | shift 122 | WAITFORIT_CLI=("$@") 123 | break 124 | ;; 125 | --help) 126 | usage 127 | ;; 128 | *) 129 | echoerr "Unknown argument: $1" 130 | usage 131 | ;; 132 | esac 133 | done 134 | 135 | if [[ "$WAITFORIT_HOST" == "" || "$WAITFORIT_PORT" == "" ]]; then 136 | echoerr "Error: you need to provide a host and port to test." 137 | usage 138 | fi 139 | 140 | WAITFORIT_TIMEOUT=${WAITFORIT_TIMEOUT:-15} 141 | WAITFORIT_STRICT=${WAITFORIT_STRICT:-0} 142 | WAITFORIT_CHILD=${WAITFORIT_CHILD:-0} 143 | WAITFORIT_QUIET=${WAITFORIT_QUIET:-0} 144 | 145 | # Check to see if timeout is from busybox? 146 | WAITFORIT_TIMEOUT_PATH=$(type -p timeout) 147 | WAITFORIT_TIMEOUT_PATH=$(realpath $WAITFORIT_TIMEOUT_PATH 2>/dev/null || readlink -f $WAITFORIT_TIMEOUT_PATH) 148 | 149 | WAITFORIT_BUSYTIMEFLAG="" 150 | if [[ $WAITFORIT_TIMEOUT_PATH =~ "busybox" ]]; then 151 | WAITFORIT_ISBUSY=1 152 | # Check if busybox timeout uses -t flag 153 | # (recent Alpine versions don't support -t anymore) 154 | if timeout &>/dev/stdout | grep -q -e '-t '; then 155 | WAITFORIT_BUSYTIMEFLAG="-t" 156 | fi 157 | else 158 | WAITFORIT_ISBUSY=0 159 | fi 160 | 161 | if [[ $WAITFORIT_CHILD -gt 0 ]]; then 162 | wait_for 163 | WAITFORIT_RESULT=$? 164 | exit $WAITFORIT_RESULT 165 | else 166 | if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then 167 | wait_for_wrapper 168 | WAITFORIT_RESULT=$? 169 | else 170 | wait_for 171 | WAITFORIT_RESULT=$? 172 | fi 173 | fi 174 | 175 | if [[ $WAITFORIT_CLI != "" ]]; then 176 | if [[ $WAITFORIT_RESULT -ne 0 && $WAITFORIT_STRICT -eq 1 ]]; then 177 | echoerr "$WAITFORIT_cmdname: strict mode, refusing to execute subprocess" 178 | exit $WAITFORIT_RESULT 179 | fi 180 | exec "${WAITFORIT_CLI[@]}" 181 | else 182 | exit $WAITFORIT_RESULT 183 | fi -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | org.springframework.boot 9 | spring-boot-starter-parent 10 | 2.7.5 11 | 12 | 13 | 14 | explore with me 15 | 16 | ewm-stat-service 17 | ewm-main-service 18 | 19 | 20 | ru.practicum 21 | explore-with-me 22 | 0.0.1-SNAPSHOT 23 | pom 24 | 25 | 26 | 11 27 | UTF-8 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | org.apache.maven.plugins 36 | maven-surefire-plugin 37 | 38 | 39 | test 40 | 41 | 42 | 43 | 44 | org.apache.maven.plugins 45 | maven-checkstyle-plugin 46 | 3.1.2 47 | 48 | checkstyle.xml 49 | true 50 | true 51 | true 52 | 53 | 54 | 55 | 56 | check 57 | 58 | compile 59 | 60 | 61 | 62 | 63 | com.puppycrawl.tools 64 | checkstyle 65 | 10.3 66 | 67 | 68 | 69 | 70 | com.github.spotbugs 71 | spotbugs-maven-plugin 72 | 4.7.0.0 73 | 74 | Max 75 | High 76 | 77 | 78 | 79 | 80 | check 81 | 82 | 83 | 84 | 85 | 86 | org.jacoco 87 | jacoco-maven-plugin 88 | 0.8.8 89 | 90 | file 91 | 92 | 93 | 94 | jacoco-initialize 95 | 96 | prepare-agent 97 | 98 | 99 | 100 | jacoco-check 101 | 102 | check 103 | 104 | 105 | 106 | 107 | BUNDLE 108 | 109 | 110 | INSTRUCTION 111 | COVERED-RATIO 112 | 0.01 113 | 114 | 115 | LINE 116 | COVERED-RATIO 117 | 0.2 118 | 119 | 120 | BRANCH 121 | COVERED-RATIO 122 | 0.2 123 | 124 | 125 | COMPLEXITY 126 | COVERED-RATIO 127 | 0.2 128 | 129 | 130 | METHOD 131 | COVERED-RATIO 132 | 0.2 133 | 134 | 135 | CLASS 136 | MISSED-COUNT 137 | 1 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | jacoco-site 146 | install 147 | 148 | report 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | check 159 | 160 | 161 | 162 | org.apache.maven.plugins 163 | maven-checkstyle-plugin 164 | 165 | 166 | com.github.spotbugs 167 | spotbugs-maven-plugin 168 | 169 | 170 | 171 | 172 | 173 | 174 | com.github.spotbugs 175 | spotbugs-maven-plugin 176 | 177 | 178 | 179 | 180 | 181 | coverage 182 | 183 | 184 | 185 | org.jacoco 186 | jacoco-maven-plugin 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/event/service/EventAdminServiceImpl.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.event.service; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.stereotype.Service; 6 | import org.springframework.transaction.annotation.Transactional; 7 | import ru.practicum.main.event.dto.AdminEventRequestDto; 8 | import ru.practicum.main.event.status.AdminEventStatus; 9 | import ru.practicum.main.event.status.State; 10 | import ru.practicum.main.category.repository.CategoryMainServiceRepository; 11 | import ru.practicum.main.event.dto.EventFullDto; 12 | import ru.practicum.main.event.mapper.EventMapper; 13 | import ru.practicum.main.event.repository.EventMainServiceRepository; 14 | import ru.practicum.main.event.location.repository.LocationMainServiceRepository; 15 | import ru.practicum.main.exception.BadRequestException; 16 | import ru.practicum.main.exception.ConflictException; 17 | import ru.practicum.main.exception.NotFoundException; 18 | import ru.practicum.main.event.dto.EventAdminDto; 19 | import ru.practicum.main.event.model.Event; 20 | import ru.practicum.main.event.location.model.Location; 21 | import ru.practicum.main.stat.service.StatService; 22 | 23 | import java.time.LocalDateTime; 24 | import java.util.List; 25 | import java.util.Map; 26 | import java.util.Optional; 27 | 28 | import static ru.practicum.main.util.Util.createPageRequestAsc; 29 | 30 | @Service 31 | @Transactional(readOnly = true) 32 | @RequiredArgsConstructor 33 | @Slf4j 34 | public class EventAdminServiceImpl implements EventAdminService { 35 | 36 | private final EventMainServiceRepository repository; 37 | 38 | private final CategoryMainServiceRepository categoryMainServiceRepository; 39 | 40 | private final LocationMainServiceRepository locationMainServiceRepository; 41 | 42 | private final StatService statService; 43 | 44 | 45 | @Transactional 46 | @Override 47 | public EventFullDto updateAdminEvent(Long eventId, AdminEventRequestDto adminEventRequestDto) { 48 | log.info("updateAdminEvent - invoked"); 49 | EventAdminDto eventAdminDto = EventMapper.toAdminEventFromAdminDto(adminEventRequestDto); 50 | Event event = repository.findById(eventId).orElseThrow(() -> 51 | new NotFoundException("Event with id = " + eventId + " not found ")); 52 | 53 | if (event.getEventDate().isBefore(LocalDateTime.now().plusHours(1))) { 54 | log.error("Event {} is already in progress or has passed, it cannot be changed", event.getTitle()); 55 | throw new BadRequestException("This event is already in progress or has passed, it cannot be changed"); 56 | } 57 | if (eventAdminDto.getEventDate() != null) { 58 | if (eventAdminDto.getEventDate().isBefore(LocalDateTime.now().plusHours(1))) { 59 | log.error("The data for updating the event date is incorrect. Date: {}", eventAdminDto.getEventDate()); 60 | throw new BadRequestException("The data for updating the event date is incorrect."); 61 | } else { 62 | event.setEventDate(eventAdminDto.getEventDate()); 63 | } 64 | } 65 | if (eventAdminDto.getStateAction() != null) { 66 | if (!event.getState().equals(State.PENDING)) { 67 | log.error("Сan not modify an event that state is {} ", eventAdminDto.getStateAction()); 68 | throw new ConflictException("Сan not modify an event that is not in the status of pending, published, or canceled"); 69 | } 70 | 71 | if (eventAdminDto.getStateAction().equals(AdminEventStatus.PUBLISH_EVENT)) { 72 | event.setState(State.PUBLISHED); 73 | event.setPublishedOn(LocalDateTime.now().withNano(0)); 74 | } 75 | if (eventAdminDto.getStateAction().equals(AdminEventStatus.REJECT_EVENT)) { 76 | event.setState(State.CANCELED); 77 | } 78 | } 79 | 80 | if (eventAdminDto.getRequestModeration() != null) { 81 | event.setRequestModeration(eventAdminDto.getRequestModeration()); 82 | } 83 | if (eventAdminDto.getPaid() != null) { 84 | event.setPaid(eventAdminDto.getPaid()); 85 | } 86 | if (eventAdminDto.getParticipantLimit() != null) { 87 | event.setParticipantLimit(eventAdminDto.getParticipantLimit()); 88 | } 89 | if (eventAdminDto.getLocation() != null) { 90 | event.setLocation(getLocation(eventAdminDto.getLocation()).orElse(saveLocation(eventAdminDto.getLocation()))); 91 | } 92 | if (eventAdminDto.getAnnotation() != null && !eventAdminDto.getTitle().isBlank()) { 93 | event.setAnnotation(eventAdminDto.getAnnotation()); 94 | } 95 | if (eventAdminDto.getDescription() != null && !eventAdminDto.getDescription().isBlank()) { 96 | event.setDescription(eventAdminDto.getDescription()); 97 | } 98 | if (eventAdminDto.getTitle() != null && !eventAdminDto.getTitle().isBlank()) { 99 | event.setTitle(eventAdminDto.getTitle()); 100 | } 101 | if (eventAdminDto.getCategory() != null) { 102 | event.setCategory(categoryMainServiceRepository.findById(eventAdminDto.getCategory()) 103 | .orElseThrow(() -> new NotFoundException("Категория не найдена"))); 104 | } 105 | 106 | Map confirmedRequest = statService.toConfirmedRequest(List.of(event)); 107 | Map view = statService.toView(List.of(event)); 108 | 109 | 110 | event.setView(view.getOrDefault(eventId, 0L)); 111 | event.setConfirmedRequests(confirmedRequest.getOrDefault(eventId, 0L)); 112 | log.info("Result: updated event {}", event); 113 | return EventMapper.toEventFullDto(event); 114 | } 115 | 116 | 117 | @Override 118 | public List readAdminEvents(List users, List states, List categories, LocalDateTime start, LocalDateTime end, int from, int size) { 119 | log.info("updateAdminEvent - invoked"); 120 | 121 | List events = repository.findAllByParam(users, states, categories, start, end, createPageRequestAsc(from, size)); 122 | 123 | Map confirmedRequest = statService.toConfirmedRequest(events); 124 | Map view = statService.toView(events); 125 | 126 | for (Event event : events) { 127 | event.setConfirmedRequests(confirmedRequest.getOrDefault(event.getId(), 0L)); 128 | event.setView(view.getOrDefault(event.getId(), 0L)); 129 | } 130 | 131 | log.info("Result: a list of events was returned - size = {}", events.size()); 132 | return EventMapper.toListEventFullDto(events); 133 | } 134 | 135 | private Location saveLocation(Location location) { 136 | Location loc = locationMainServiceRepository.save(location); 137 | log.info("save new location"); 138 | return loc; 139 | } 140 | 141 | private Optional getLocation(Location location) { 142 | Optional loc = locationMainServiceRepository.findByLatAndLon(location.getLat(), location.getLon()); 143 | log.info("find location"); 144 | return loc; 145 | } 146 | 147 | } -------------------------------------------------------------------------------- /ewm-main-service/src/main/java/ru/practicum/main/event/mapper/EventMapper.java: -------------------------------------------------------------------------------- 1 | package ru.practicum.main.event.mapper; 2 | 3 | import lombok.experimental.UtilityClass; 4 | import ru.practicum.main.category.mapper.CategoryMapper; 5 | import ru.practicum.main.category.model.Category; 6 | import ru.practicum.main.event.dto.*; 7 | import ru.practicum.main.event.location.mapper.LocationMapper; 8 | import ru.practicum.main.event.model.Event; 9 | import ru.practicum.main.user.mapper.UserMapper; 10 | 11 | import java.time.format.DateTimeFormatter; 12 | import java.util.List; 13 | import java.util.stream.Collectors; 14 | 15 | @UtilityClass 16 | public class EventMapper { 17 | 18 | private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); 19 | 20 | public Event toEvent(EventRequestDto receivedDto) { 21 | return Event.builder() 22 | .eventDate(receivedDto.getEventDate()) 23 | .annotation(receivedDto.getAnnotation()) 24 | .category(Category.builder().id(receivedDto.getCategory()).build()) 25 | .paid(receivedDto.isPaid()) 26 | .description(receivedDto.getDescription()) 27 | .title(receivedDto.getTitle()) 28 | .participantLimit(receivedDto.getParticipantLimit()) 29 | .requestModeration(receivedDto.isRequestModeration()) 30 | .location(LocationMapper.toLocation(receivedDto.getLocation())) 31 | .build(); 32 | } 33 | 34 | public EventFullDto toEventFullDto(Event event) { 35 | EventFullDto build = EventFullDto.builder() 36 | .createdOn(event.getCreatedOn().format(FORMATTER)) 37 | .initiator(UserMapper.toUserDto(event.getInitiator())) 38 | .confirmedRequests(event.getConfirmedRequests()) 39 | .views(event.getView()) 40 | .state(event.getState()) 41 | .annotation(event.getAnnotation()) 42 | .participantLimit(event.getParticipantLimit()) 43 | .requestModeration(event.getRequestModeration()) 44 | .paid(event.getPaid()) 45 | .title(event.getTitle()) 46 | .id(event.getId()) 47 | .category(CategoryMapper.toCategoryDto(event.getCategory())) 48 | .description(event.getDescription()) 49 | .eventDate(event.getEventDate().format(FORMATTER)) 50 | .location(LocationMapper.toLocationDto(event.getLocation())) 51 | .build(); 52 | 53 | if (event.getPublishedOn() != null) { 54 | build.setPublishedOn(event.getPublishedOn().format(FORMATTER)); 55 | } 56 | return build; 57 | } 58 | 59 | public List toListEventFullDto(List list) { 60 | return list.stream().map(EventMapper::toEventFullDto).collect(Collectors.toList()); 61 | } 62 | 63 | public PatchEventDto toEventFromUpdateEvent(UpdateEventDto updateEventDto) { 64 | PatchEventDto event = PatchEventDto.builder() 65 | .stateAction(updateEventDto.getStateAction()) 66 | .annotation(updateEventDto.getAnnotation()) 67 | .participantLimit(updateEventDto.getParticipantLimit()) 68 | .requestModeration(updateEventDto.getRequestModeration()) 69 | .category(updateEventDto.getCategory()) 70 | .description(updateEventDto.getDescription()) 71 | .title(updateEventDto.getTitle()) 72 | .paid(updateEventDto.getPaid()) 73 | .eventDate(updateEventDto.getEventDate()) 74 | .build(); 75 | 76 | event.setLocation(updateEventDto.getLocation() == null ? null : LocationMapper.toLocation(updateEventDto.getLocation())); 77 | 78 | return event; 79 | } 80 | 81 | public static EventAdminDto toAdminEventFromAdminDto(AdminEventRequestDto adminEvent) { 82 | EventAdminDto event = EventAdminDto.builder() 83 | .stateAction(adminEvent.getStateAction()) 84 | .annotation(adminEvent.getAnnotation()) 85 | .participantLimit(adminEvent.getParticipantLimit()) 86 | .requestModeration(adminEvent.getRequestModeration()) 87 | .category(adminEvent.getCategory()) 88 | .description(adminEvent.getDescription()) 89 | .eventDate(adminEvent.getEventDate()) 90 | .paid(adminEvent.getPaid()) 91 | .title(adminEvent.getTitle()) 92 | .build(); 93 | 94 | event.setLocation(adminEvent.getLocation() == null ? null : LocationMapper.toLocation(adminEvent.getLocation())); 95 | 96 | return event; 97 | } 98 | 99 | public EventDto toEventDto(Event event, Long view, Long confirmedRequests, Long commentCount) { 100 | return EventDto 101 | .builder() 102 | .id(event.getId()) 103 | .eventDate(event.getEventDate()) 104 | .confirmedRequests(confirmedRequests) 105 | .views(view) 106 | .annotation(event.getAnnotation()) 107 | .category(event.getCategory()) 108 | .initiator(event.getInitiator()) 109 | .paid(event.getPaid()) 110 | .title(event.getTitle()) 111 | .commentCount(commentCount) 112 | .build(); 113 | } 114 | 115 | public EventShortDto toEventShortDto(EventDto eventDto) { 116 | return EventShortDto.builder() 117 | .initiator(UserMapper.toUserShortDto(eventDto.getInitiator())) 118 | .views(eventDto.getViews()) 119 | .eventDate(eventDto.getEventDate().format(FORMATTER)) 120 | .annotation(eventDto.getAnnotation()) 121 | .title(eventDto.getTitle()) 122 | .category(CategoryMapper.toCategoryDto(eventDto.getCategory())) 123 | .confirmedRequests(eventDto.getConfirmedRequests()) 124 | .id(eventDto.getId()) 125 | .paid(eventDto.getPaid()) 126 | .build(); 127 | } 128 | 129 | public static List toListEventShortDto(List list) { 130 | return list.stream().map(EventMapper::toEventShortDto).collect(Collectors.toList()); 131 | } 132 | 133 | public EventDto toEventShort(Event event) { 134 | return EventDto.builder() 135 | .id(event.getId()) 136 | .eventDate(event.getEventDate()) 137 | .confirmedRequests(event.getConfirmedRequests()) 138 | .views(event.getView()) 139 | .annotation(event.getAnnotation()) 140 | .category(event.getCategory()) 141 | .initiator(event.getInitiator()) 142 | .paid(event.getPaid()) 143 | .title(event.getTitle()) 144 | .build(); 145 | } 146 | 147 | public static List toListEventShort(List list) { 148 | return list.stream().map(EventMapper::toEventShort).collect(Collectors.toList()); 149 | } 150 | 151 | public static EventShortDto toEventShortDto(Event event) { 152 | return EventShortDto.builder() 153 | .annotation(event.getAnnotation()) 154 | .category(CategoryMapper.toCategoryDto(event.getCategory())) 155 | .confirmedRequests(event.getConfirmedRequests()) 156 | .eventDate(event.getEventDate().toString()) 157 | .id(event.getId()) 158 | .initiator(UserMapper.toUserShortDto(event.getInitiator())) 159 | .paid(event.getPaid()) 160 | .title(event.getTitle()) 161 | .views(event.getView()) 162 | .build(); 163 | } 164 | 165 | public EventCommentDto toEventComment(Event event) { 166 | return EventCommentDto.builder() 167 | .id(event.getId()) 168 | .title(event.getTitle()) 169 | .build(); 170 | } 171 | } 172 | --------------------------------------------------------------------------------