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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
# java-explore-with-me
Итоговый проект учебного курса. май 2025. гр. 53.
Итоговый проект учебного курса. июль 2025.

Pull request:
https://github.com/andrej1307/java-explore-with-me/pull/3
Binary file removed ewm-service/schema.png
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,15 @@
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import ru.practicum.evmsevice.client.StatsClient;
import ru.practicum.evmsevice.dto.CategoryDto;
import ru.practicum.evmsevice.dto.CompilationDto;
import ru.practicum.evmsevice.dto.EventFullDto;
import ru.practicum.evmsevice.dto.EventShortDto;
import ru.practicum.evmsevice.dto.*;
import ru.practicum.evmsevice.enums.CommentState;
import ru.practicum.evmsevice.enums.EventState;
import ru.practicum.evmsevice.exception.NotFoundException;
import ru.practicum.evmsevice.mapper.CategoryMapper;
import ru.practicum.evmsevice.mapper.EventMapper;
import ru.practicum.evmsevice.model.Event;
import ru.practicum.evmsevice.service.CategoryService;
import ru.practicum.evmsevice.service.CommentService;
import ru.practicum.evmsevice.service.CompilationService;
import ru.practicum.evmsevice.service.EventService;

Expand All @@ -31,6 +30,7 @@ public class PublicController {
private final EventService eventService;
private final CompilationService compilationService;
private final CategoryService categoryService;
private final CommentService commentService;
@Value("${spring.application.name}")
private String appName;

Expand Down Expand Up @@ -108,4 +108,28 @@ public CategoryDto findCategoryById(@PathVariable("catId") int catId) {
log.info("Пользователь запрашивает категорию id={}.", catId);
return CategoryMapper.toDto(categoryService.getCategoryById(catId));
}

@GetMapping("/events/{eventId}/comments")
@ResponseStatus(HttpStatus.OK)
public List<CommentDto> getCommentsByEventId(@PathVariable Integer eventId,
@RequestParam(name = "text", required = false) String text,
@RequestParam(name = "authorIds", required = false) List<Integer> authorIds,
@RequestParam(name = "rangeStart", required = false) String rangeStart,
@RequestParam(name = "rangeEnd", required = false) String rangeEnd,
@RequestParam(name = "state", defaultValue = "APPROVED") String state,
@RequestParam(name = "sort", defaultValue = "new") String sort,
@RequestParam(name = "from", defaultValue = "0") Integer from,
@RequestParam(name = "size", defaultValue = "10") Integer size) {
CommentState commentState = CommentState.from(state).orElse(CommentState.APPROVED);
log.info("Поиск коментариев к событию id={}.", eventId);
return commentService.getCommentsByEventId(eventId, text, authorIds, rangeStart, rangeEnd, commentState, sort, from, size);
}

@GetMapping("/comments/{commentId}")
@ResponseStatus(HttpStatus.OK)
public CommentDto getComment(@PathVariable Integer commentId) {
log.info("Поиск коментария id={}.", commentId);
return commentService.getCommentById(commentId);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package ru.practicum.evmsevice.controller;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import ru.practicum.evmsevice.dto.CommentDto;
import ru.practicum.evmsevice.dto.CommentModerationDto;
import ru.practicum.evmsevice.dto.CommentsGroupDto;
import ru.practicum.evmsevice.dto.NewCommentDto;
import ru.practicum.evmsevice.service.CommentService;

import java.util.List;

@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/users")
public class UserCommentController {
private final CommentService commentService;

@PostMapping("/{userId}/events/{eventId}/comments")
@ResponseStatus(HttpStatus.CREATED)
public CommentDto addNewComment(@PathVariable Integer userId,
@PathVariable Integer eventId,
@RequestBody @Validated NewCommentDto commentDto) {
log.info("Пользователь id={} добавляет комментарий к событию id={}. {}",
userId, eventId, commentDto.toString());
return commentService.addComment(userId, eventId, commentDto);
}

@PatchMapping("/{userId}/comments/{commentId}")
@ResponseStatus(HttpStatus.OK)
public CommentDto updateComment(@PathVariable Integer userId,
@PathVariable Integer commentId,
@RequestBody @Validated NewCommentDto commentDto) {
log.info("Пользователь id={} редактирует комментарий id={}. {}",
userId, commentId, commentDto.toString());
return commentService.updateComment(userId, commentId, commentDto);
}

@PatchMapping("/{userId}/events/{eventId}/comments")
@ResponseStatus(HttpStatus.OK)
public CommentsGroupDto addNewComment(@PathVariable Integer userId,
@PathVariable Integer eventId,
@RequestBody CommentModerationDto cmModDto) {
log.info("Пользователь id={} модерирует комментарии к событию id={}. {}",
userId, eventId, cmModDto.toString());
return commentService.moderationComments(userId, eventId, cmModDto);
}


@GetMapping("/{userId}/comments")
@ResponseStatus(HttpStatus.OK)
public List<CommentDto> getCommentsByUserId(@PathVariable Integer userId,
@RequestParam(name = "from", defaultValue = "0") Integer from,
@RequestParam(name = "size", defaultValue = "10") Integer size) {
log.info("Поиск всех комментариев пользователя id={}.", userId);
return commentService.getCommentsByUserId(userId, from, size);
}


@DeleteMapping("/{userId}/comments/{commentId}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void deleteComment(@PathVariable Integer commentId,
@PathVariable Integer userId) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Лишний отступ

log.info("Пользователь id={} удаляет комментарий id={}.", userId, commentId);
commentService.deleteComment(userId, commentId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import ru.practicum.evmsevice.dto.*;
import ru.practicum.evmsevice.mapper.RequestMapper;
import ru.practicum.evmsevice.model.Request;
import ru.practicum.evmsevice.service.CommentService;
import ru.practicum.evmsevice.service.EventService;
import ru.practicum.evmsevice.service.RequestService;

Expand All @@ -20,6 +21,7 @@
public class UserController {
private final EventService eventService;
private final RequestService requestService;
private final CommentService commentService;

@PostMapping("/{id}/events")
@ResponseStatus(HttpStatus.CREATED)
Expand Down Expand Up @@ -103,4 +105,6 @@ public RequestDto canceledRequestById(@PathVariable Integer userId,
log.info("Пользователь id={} отменяет запрос id={}.", userId, requestId);
return RequestMapper.toRequestDto(requestService.canceledRequest(userId, requestId));
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package ru.practicum.evmsevice.dto;

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import ru.practicum.evmsevice.enums.CommentState;

import java.time.LocalDateTime;

@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class CommentDto {
private Integer id;
private UserDto author;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createdOn;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime editedOn;
private Integer eventId;
private String text;
private CommentState state;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package ru.practicum.evmsevice.dto;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import ru.practicum.evmsevice.enums.CommentState;

import java.util.ArrayList;
import java.util.List;

@Setter
@Getter
@NoArgsConstructor
@ToString
public class CommentModerationDto {
private List<Integer> commentIds = new ArrayList<>();
private CommentState state;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package ru.practicum.evmsevice.dto;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

import java.util.ArrayList;
import java.util.List;

@Setter
@Getter
@NoArgsConstructor
@ToString

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Лишний отступ

public class CommentsGroupDto {
private List<CommentDto> approvedComments = new ArrayList<>();
private List<CommentDto> rejectedComments = new ArrayList<>();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package ru.practicum.evmsevice.dto;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.*;

@Setter
@Getter
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class NewCommentDto {
@NotBlank(message = "Текст комментария должен быть задан.")
@Size(min = 3, max = 2000, message = "Длина комментария должна быть от 3 до 2000 символов.")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Хорошая валидация

private String text;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package ru.practicum.evmsevice.enums;

import java.util.Optional;

public enum CommentState {
PENDING,
APPROVED,
REJECTED;

public static Optional<CommentState> from(String state) {
for (CommentState commentState : CommentState.values()) {
if (commentState.name().equalsIgnoreCase(state)) {
return Optional.of(commentState);
}
}
return Optional.empty();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package ru.practicum.evmsevice.mapper;

import ru.practicum.evmsevice.dto.CommentDto;
import ru.practicum.evmsevice.dto.NewCommentDto;
import ru.practicum.evmsevice.model.Comment;

import java.time.LocalDateTime;

public class CommentMapper {
private CommentMapper() {
}

public static Comment getComment(NewCommentDto newCommemtDto) {
Comment comment = new Comment();
comment.setCreatedOn(LocalDateTime.now());
comment.setText(newCommemtDto.getText());
return comment;
}

public static CommentDto toDto(Comment comment) {
CommentDto commentDto = new CommentDto();
commentDto.setId(comment.getId());
commentDto.setEventId(comment.getEventId());
commentDto.setText(comment.getText());
commentDto.setCreatedOn(comment.getCreatedOn());
commentDto.setEditedOn(comment.getEditedOn());
commentDto.setAuthor(UserMapper.toUserDto(comment.getAuthor()));
commentDto.setState(comment.getState());
return commentDto;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package ru.practicum.evmsevice.model;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import ru.practicum.evmsevice.enums.CommentState;

import java.time.LocalDateTime;

@Entity
@Setter
@Getter
@Table(name = "comments", schema = "public")
@NoArgsConstructor
public class Comment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@ManyToOne
@JoinColumn(name = "author_id", nullable = false)
private User author;
@Column(name = "event_id", nullable = false)
private Integer eventId;
@Column(name = "text", nullable = false)
private String text;
@Column(name = "created_on", nullable = false)
private LocalDateTime createdOn;
@Column(name = "edited_on")
private LocalDateTime editedOn;
@Column(name = "state")
@Enumerated(EnumType.STRING)
private CommentState state;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package ru.practicum.evmsevice.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import ru.practicum.evmsevice.model.Comment;

import java.util.List;

public interface CommentRepository extends JpaRepository<Comment, Integer>,
JpaSpecificationExecutor<Comment> {
List<Comment> findAllByEventId(Integer eventId);

List<Comment> findAllByAuthor_Id(Integer authorId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package ru.practicum.evmsevice.repository;

import org.springframework.data.jpa.domain.Specification;
import ru.practicum.evmsevice.enums.CommentState;
import ru.practicum.evmsevice.model.Comment;

import java.time.LocalDateTime;
import java.util.List;

public class CommentSpecification {
public static Specification<Comment> commentEventIdEqual(Integer eventId) {
return ((root, query, criteriaBuilder) ->
criteriaBuilder.in(root.get("eventId")).value(eventId));
}

public static Specification<Comment> commentStateEqual(CommentState state) {
return ((root, query, criteriaBuilder) ->
criteriaBuilder.in(root.get("state")).value(state));
}

public static Specification<Comment> commentContains(String text) {
return ((root, query, criteriaBuilder) ->
criteriaBuilder.like(root.get("text"), "%" + text + "%"));
}

public static Specification<Comment> commentAuthorIdIn(List<Integer> userIds) {
return ((root, query, criteriaBuilder) ->
criteriaBuilder.in(root.join("author").get("id")).value(userIds));
}

public static Specification<Comment> commentCreatedAfter(LocalDateTime startDateTime) {
return ((root, query, criteriaBuilder) ->
criteriaBuilder.greaterThanOrEqualTo(root.get("createdOn"), startDateTime));
}

public static Specification<Comment> commentCreatedBefore(LocalDateTime endDateTime) {
return ((root, query, criteriaBuilder) ->
criteriaBuilder.lessThan(root.get("createdOn"), endDateTime));
}

}
Loading