Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
9cffcc0
feat: add jpa eventRepo
LightInTheFire Dec 28, 2025
2bba240
feat: add EventMapper
LightInTheFire Dec 28, 2025
c3c5595
feat: add Event sort options enum
LightInTheFire Dec 28, 2025
d35a389
feat: add event requests for services
LightInTheFire Dec 28, 2025
78c81a4
feat: add event controllers
LightInTheFire Dec 28, 2025
bfbb961
feat: add eventService and implementation
LightInTheFire Dec 28, 2025
26ce235
feat: add querydsl
LightInTheFire Dec 28, 2025
562d77a
fix: add logging to public controller
LightInTheFire Dec 28, 2025
1c18b61
fix: add logging to admin controller
LightInTheFire Dec 28, 2025
f29732a
feat: update event private controller
LightInTheFire Dec 28, 2025
1c9e128
feat: add EventsPrivateGetRequest
LightInTheFire Dec 28, 2025
0e95767
feat: add methods to event service interface
LightInTheFire Dec 28, 2025
16ef3ed
feat: add validation exception
LightInTheFire Dec 28, 2025
0efb5ff
feat: add location mapper
LightInTheFire Dec 28, 2025
52ff7fe
fix: increase limit in event model
LightInTheFire Dec 28, 2025
5dca3fa
fix: update querydsl
LightInTheFire Dec 28, 2025
0c91cc6
feat: add constraint to newEventDto eventdate to be in future
LightInTheFire Dec 28, 2025
5b6d828
feat: separate state actions to two enums
LightInTheFire Dec 28, 2025
61a2340
feat: add updatableevent interface and mapper methods
LightInTheFire Dec 28, 2025
7e695b8
fix: method names
LightInTheFire Dec 28, 2025
b64669e
feat: add datetime properties, correct LDT requestparam mapping and c…
LightInTheFire Dec 29, 2025
fd3d167
feat: add boolean predicate as static methods
LightInTheFire Dec 29, 2025
dc0b62e
chore: move methods
LightInTheFire Dec 29, 2025
03aa2d9
feat: add IllegalEventUpdateException
LightInTheFire Dec 29, 2025
3f95437
fix: typo in Enum
LightInTheFire Dec 29, 2025
db07b1a
feat: add check to eventstate
LightInTheFire Dec 29, 2025
cccadff
feat: add httprequest param
LightInTheFire Dec 29, 2025
8f1374b
feat: add @Future constraint
LightInTheFire Dec 29, 2025
b2b0711
feat: implement interface methods
LightInTheFire Dec 29, 2025
ebfb955
feat: update tests to containt events
LightInTheFire Dec 29, 2025
8db8049
feat: add client method to accept ip and uri strings
LightInTheFire Dec 29, 2025
f553d4f
fix: send actual uri to service
LightInTheFire Dec 29, 2025
4d87b98
fix: change transactional to readonly
LightInTheFire Dec 29, 2025
c7d5623
feat: add sql params logging
LightInTheFire Dec 30, 2025
525a482
fix: update pagerequest to work correctly
LightInTheFire Dec 30, 2025
bdfbe31
feat: add ForbiddenAccessException
LightInTheFire Dec 30, 2025
d72064d
fix: add check to private api methods
LightInTheFire Dec 30, 2025
7f5312b
fix: add call to parent constructor in FAE
LightInTheFire Dec 30, 2025
3e4a447
Revert "feat: add client method to accept ip and uri strings"
LightInTheFire Dec 30, 2025
10e0c8f
feat: update stats server tests
LightInTheFire Dec 30, 2025
0adbb62
fix: save /events endpoint when request multiple events and send null…
LightInTheFire Dec 30, 2025
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
35 changes: 35 additions & 0 deletions main-service/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,43 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>

<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<classifier>jakarta</classifier>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>target/generated-sources/java</outputDirectory>
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<classifier>jakarta</classifier>
<version>${querydsl.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>

<profiles>
<profile>
<id>dev</id>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package ru.practicum.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import lombok.Getter;
import lombok.Setter;

@Component
@ConfigurationProperties(prefix = "app")
public class DateTimeProperties {
@Getter @Setter private String dateTimeFormat = "yyyy-MM-dd HH:mm:ss";
}
13 changes: 9 additions & 4 deletions main-service/src/main/java/ru/practicum/config/JsonConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,23 @@
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;

import lombok.RequiredArgsConstructor;

@Configuration
@RequiredArgsConstructor
public class JsonConfig {
private static final String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
private final DateTimeProperties properties;

@Bean
public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() {
return builder -> {
builder.simpleDateFormat(DATE_TIME_PATTERN);
builder.simpleDateFormat(properties.getDateTimeFormat());
builder.serializers(
new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DATE_TIME_PATTERN)));
new LocalDateTimeSerializer(
DateTimeFormatter.ofPattern(properties.getDateTimeFormat())));
builder.deserializers(
new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DATE_TIME_PATTERN)));
new LocalDateTimeDeserializer(
DateTimeFormatter.ofPattern(properties.getDateTimeFormat())));
};
}
}
38 changes: 38 additions & 0 deletions main-service/src/main/java/ru/practicum/config/WebConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package ru.practicum.config;

import java.text.ParseException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

import org.springframework.context.annotation.Configuration;
import org.springframework.format.Formatter;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import lombok.RequiredArgsConstructor;

@Configuration
@RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer {
private final DateTimeProperties properties;

@Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatter(
new Formatter<LocalDateTime>() {

@Override
public String print(LocalDateTime object, Locale locale) {
return object.format(
DateTimeFormatter.ofPattern(properties.getDateTimeFormat()));
}

@Override
public LocalDateTime parse(String text, Locale locale) throws ParseException {
return LocalDateTime.parse(
text, DateTimeFormatter.ofPattern(properties.getDateTimeFormat()));
}
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package ru.practicum.event.controller;

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

import jakarta.validation.Valid;

import ru.practicum.event.dto.EventFullDto;
import ru.practicum.event.dto.UpdateEventAdminRequest;
import ru.practicum.event.model.EventState;
import ru.practicum.event.service.EventService;
import ru.practicum.event.service.EventsAdminGetRequest;

import org.springframework.web.bind.annotation.*;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/admin/events")
public class EventAdminController {
private final EventService eventService;

@GetMapping
public Collection<EventFullDto> getEventsFiltered(
@RequestParam(required = false) List<Long> users,
@RequestParam(required = false) List<EventState> states,
@RequestParam(required = false) List<Long> categories,
@RequestParam(required = false) LocalDateTime rangeStart,
@RequestParam(required = false) LocalDateTime rangeEnd,
@RequestParam(defaultValue = "0") int from,
@RequestParam(defaultValue = "10") int size) {
EventsAdminGetRequest getRequest =
new EventsAdminGetRequest(
users, states, categories, rangeStart, rangeEnd, from, size);
log.info("Admin get events requested with params= {}", getRequest);
return eventService.getEvents(getRequest);
}

@PatchMapping("/{eventId}")
public EventFullDto updateEvent(
@PathVariable Long eventId, @RequestBody @Valid UpdateEventAdminRequest updateRequest) {
log.info("Admin update event requested with body= {}", updateRequest);
return eventService.updateEvent(eventId, updateRequest);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package ru.practicum.event.controller;

import java.util.Collection;

import jakarta.validation.Valid;

import ru.practicum.event.dto.EventFullDto;
import ru.practicum.event.dto.EventShortDto;
import ru.practicum.event.dto.NewEventDto;
import ru.practicum.event.dto.UpdateEventUserRequest;
import ru.practicum.event.service.EventService;
import ru.practicum.event.service.EventsPrivateGetRequest;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/users/{userId}/events")
public class EventPrivateController {
private final EventService eventService;

@GetMapping()
public Collection<EventShortDto> getEventsOfUserPaged(
@PathVariable Long userId,
@RequestParam(defaultValue = "0") int from,
@RequestParam(defaultValue = "10") int size) {
EventsPrivateGetRequest getRequest = new EventsPrivateGetRequest(userId, from, size);
log.info("Private get events requested with params= {}", getRequest);
return eventService.getEvents(getRequest);
}

@PostMapping()
@ResponseStatus(HttpStatus.CREATED)
public EventFullDto createEvent(
@PathVariable Long userId, @RequestBody @Valid NewEventDto newEventDto) {
log.info("Create event requested with body= {}", newEventDto);
return eventService.createEvent(userId, newEventDto);
}

@GetMapping("/{eventId}")
public EventFullDto getEvent(@PathVariable Long userId, @PathVariable Long eventId) {
log.info("Private get event requested with userId= {}, eventId= {}", userId, eventId);
return eventService.getByUserById(userId, eventId);
}

@PatchMapping("/{eventId}")
public EventFullDto updateEvent(
@PathVariable Long userId,
@PathVariable Long eventId,
@RequestBody @Valid UpdateEventUserRequest updateRequest) {
log.info(
"Private update event requested with userId= {}, eventId= {}, body = {}",
userId,
eventId,
updateRequest);
return eventService.updateEventByUser(userId, eventId, updateRequest);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package ru.practicum.event.controller;

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

import jakarta.servlet.http.HttpServletRequest;

import ru.practicum.event.dto.EventFullDto;
import ru.practicum.event.dto.EventShortDto;
import ru.practicum.event.service.EventService;
import ru.practicum.event.service.EventsPublicGetRequest;
import ru.practicum.exception.ValidationException;

import org.springframework.web.bind.annotation.*;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/events")
public class EventPublicController {
private final EventService eventService;

@GetMapping()
public Collection<EventShortDto> getEventsFiltered(
@RequestParam(required = false) String text,
@RequestParam(required = false) List<Long> categories,
@RequestParam(required = false) Boolean paid,
@RequestParam(required = false) LocalDateTime rangeStart,
Comment thread
LightInTheFire marked this conversation as resolved.
@RequestParam(required = false) LocalDateTime rangeEnd,
@RequestParam(defaultValue = "false") boolean onlyAvailable,
@RequestParam(required = false) EventSortBy sort,
@RequestParam(defaultValue = "0") int from,
@RequestParam(defaultValue = "10") int size,
HttpServletRequest request) {
EventsPublicGetRequest getRequest =
new EventsPublicGetRequest(
text,
categories,
paid,
rangeStart,
rangeEnd,
onlyAvailable,
sort,
from,
size,
request);
if (getRequest.hasRangeStart() && getRequest.hasRangeEnd()) {
if (getRequest.rangeEnd().isBefore(getRequest.rangeStart())) {
throw new ValidationException("End date must be before start date");
}
}
log.info("Public get events requested with params= {}", getRequest);
return eventService.getEvents(getRequest);
}

@GetMapping("/{eventId}")
public EventFullDto getEventById(@PathVariable Long eventId, HttpServletRequest request) {
log.info("Public get event with eventId={} requested", eventId);
return eventService.getById(eventId, request);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package ru.practicum.event.controller;

public enum EventSortBy {
EVENT_DATE,
VIEWS
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,13 @@

import java.time.LocalDateTime;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.PositiveOrZero;
import jakarta.validation.constraints.Size;
import jakarta.validation.constraints.*;

public record NewEventDto(
@NotBlank @Size(min = 20, max = 2000) String annotation,
@NotNull Long category,
@NotBlank @Size(min = 20, max = 7000) String description,
@NotNull LocalDateTime eventDate,
@NotNull @Future LocalDateTime eventDate,
@NotNull LocationDto location,
Boolean paid,
@PositiveOrZero Integer participantLimit,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package ru.practicum.event.dto;

import java.time.LocalDateTime;

public interface UpdatableEvent {
boolean hasAnnotation();

String annotation();

boolean hasEventDate();

LocalDateTime eventDate();

boolean hasCategory();

boolean hasLocation();

LocationDto location();

boolean hasParticipantLimit();

Integer participantLimit();

boolean hasPaid();

Boolean paid();

boolean hasRequestModeration();

Boolean requestModeration();

boolean hasTitle();

String title();

boolean hasDescription();

String description();
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,24 @@

import java.time.LocalDateTime;

import jakarta.validation.constraints.Future;
import jakarta.validation.constraints.PositiveOrZero;
import jakarta.validation.constraints.Size;

import ru.practicum.event.model.StateAction;
import ru.practicum.event.model.AdminStateAction;

public record UpdateEventAdminRequest(
@Size(min = 20, max = 2000) String annotation,
Long category,
@Size(min = 20, max = 7000) String description,
LocalDateTime eventDate,
@Future LocalDateTime eventDate,
LocationDto location,
Boolean paid,
@PositiveOrZero Integer participantLimit,
Boolean requestModeration,
StateAction stateAction,
@Size(min = 3, max = 120) String title) {
AdminStateAction stateAction,
@Size(min = 3, max = 120) String title)
implements UpdatableEvent {

public boolean hasAnnotation() {
return annotation != null && !annotation.isBlank();
Expand Down
Loading