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
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
public class AdminLocationController {

private final LocationService locationService;
private static final String LOC_ID_PATH = "/{locationId}";

@PostMapping
@ResponseStatus(HttpStatus.CREATED)
Expand All @@ -28,14 +29,20 @@ public List<LocationDto> getAllLocations() {
return locationService.getAllLocations();
}

@GetMapping("/{locationId}")
@GetMapping(LOC_ID_PATH)
public LocationDto getLocation(@PathVariable Long locationId) {
return locationService.getLocation(locationId);
}

@DeleteMapping("/{locationId}")
@PatchMapping(LOC_ID_PATH)
public LocationDto updateLocation(@PathVariable Long locationId,
@Valid @RequestBody NewLocationDto locationDto) {
return locationService.updateLocation(locationId, locationDto);
}

@DeleteMapping(LOC_ID_PATH)
@ResponseStatus(HttpStatus.NO_CONTENT)
public void deleteLocation(@PathVariable Long locationId) {
locationService.deleteLocation(locationId);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import ru.practicum.ewm.dto.response.EventShortDto;
import ru.practicum.ewm.dto.response.LocationDto;
import ru.practicum.ewm.service.LocationService;

Expand All @@ -26,4 +27,9 @@ public List<LocationDto> getAllLocations() {
public LocationDto getLocation(@PathVariable Long locationId) {
return locationService.getLocation(locationId);
}
}

@GetMapping("/{locationId}/events")
public List<EventShortDto> getEventsInLocation(@PathVariable Long locationId) {
return locationService.getEventsInLocation(locationId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ public class Location {

@Column
Float radius;

}
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,13 @@ List<Event> findPublishedEvents(
@Param("rangeEnd") LocalDateTime rangeEnd,
@Param("onlyAvailable") Boolean onlyAvailable,
Pageable pageable);

@Query(value = "SELECT e.* FROM events e " +
"JOIN locations l ON e.location_id = l.id " +
"WHERE distance(l.lat, l.lon, :targetLat, :targetLon) <= :targetRadius " +
"AND e.state = 'PUBLISHED'", nativeQuery = true)
List<Event> findEventsNearby(@Param("targetLat") float lat,
@Param("targetLon") float lon,
@Param("targetRadius") float radius);
Optional<Event> findByIdAndState(Long id, EventState state);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package ru.practicum.ewm.service;

import ru.practicum.ewm.dto.request.NewLocationDto;
import ru.practicum.ewm.dto.response.EventShortDto;
import ru.practicum.ewm.dto.response.LocationDto;

import java.util.List;
Expand All @@ -14,4 +15,8 @@ public interface LocationService {
List<LocationDto> getAllLocations();

void deleteLocation(Long locationId);

List<EventShortDto> getEventsInLocation(Long locationId);

LocationDto updateLocation(Long locationId, NewLocationDto dto);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,13 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ru.practicum.ewm.dto.request.NewLocationDto;
import ru.practicum.ewm.dto.response.EventShortDto;
import ru.practicum.ewm.dto.response.LocationDto;
import ru.practicum.ewm.exception.NotFoundException;
import ru.practicum.ewm.mapper.EventMapper;
import ru.practicum.ewm.mapper.LocationMapper;
import ru.practicum.ewm.model.Location;
import ru.practicum.ewm.repository.EventRepository;
import ru.practicum.ewm.repository.LocationRepository;

import java.util.List;
Expand All @@ -21,18 +25,19 @@
public class LocationServiceImpl implements LocationService {

LocationRepository locationRepository;
EventRepository eventRepository;

@Override
@Transactional
public LocationDto createLocation(NewLocationDto newLocationDto) {
Location location = LocationMapper.toLocation(newLocationDto);
Location savedLocation = locationRepository.save(location);
return LocationMapper.toDto(savedLocation);
return LocationMapper.toDto(locationRepository.save(location));
}

@Override
public LocationDto getLocation(Long locationId) {
Location location = locationRepository.findById(locationId)
.orElseThrow(() -> new RuntimeException("Location not found"));
.orElseThrow(() -> new NotFoundException("Location with id=" + locationId + " was not found"));
return LocationMapper.toDto(location);
}

Expand All @@ -46,6 +51,34 @@ public List<LocationDto> getAllLocations() {
@Override
@Transactional
public void deleteLocation(Long locationId) {
if (!locationRepository.existsById(locationId)) {
throw new NotFoundException("Location with id=" + locationId + " was not found");
}
locationRepository.deleteById(locationId);
}

@Override
public List<EventShortDto> getEventsInLocation(Long locationId) {
Location location = locationRepository.findById(locationId)
.orElseThrow(() -> new NotFoundException("Location with id=" + locationId + " was not found"));

return eventRepository.findEventsNearby(location.getLat(), location.getLon(), location.getRadius())
.stream()
.map(EventMapper::toShortDto)
.collect(Collectors.toList());
}

@Override
@Transactional
public LocationDto updateLocation(Long locationId, NewLocationDto dto) {
Location location = locationRepository.findById(locationId)
.orElseThrow(() -> new NotFoundException("Location with id=" + locationId + " was not found"));

if (dto.getName() != null && !dto.getName().isBlank()) location.setName(dto.getName());
if (dto.getLat() != null) location.setLat(dto.getLat());
if (dto.getLon() != null) location.setLon(dto.getLon());
if (dto.getRadius() != null) location.setRadius(dto.getRadius());

return LocationMapper.toDto(locationRepository.save(location));
}
}
4 changes: 2 additions & 2 deletions ewm-main-service/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ server.port=8080
spring.datasource.url=jdbc:postgresql://localhost:5432/ewm
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect

spring.sql.init.mode=always
spring.jpa.hibernate.ddl-auto=update
stats.server.url=http://localhost:9090
32 changes: 32 additions & 0 deletions ewm-main-service/src/main/resources/schema.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
CREATE OR REPLACE FUNCTION distance(lat1 float, lon1 float, lat2 float, lon2 float)
RETURNS float
AS
'
declare
dist float = 0;
rad_lat1 float;
rad_lat2 float;
theta float;
rad_theta float;
BEGIN
IF lat1 = lat2 AND lon1 = lon2
THEN
RETURN dist;
ELSE
rad_lat1 = pi() * lat1 / 180;
rad_lat2 = pi() * lat2 / 180;
theta = lon1 - lon2;
rad_theta = pi() * theta / 180;
dist = sin(rad_lat1) * sin(rad_lat2) + cos(rad_lat1) * cos(rad_lat2) * cos(rad_theta);

IF dist > 1 THEN dist = 1; END IF;

dist = acos(dist);
dist = dist * 180 / pi();
dist = dist * 60 * 1.8524;

RETURN dist;
END IF;
END;
'
LANGUAGE PLPGSQL;
178 changes: 178 additions & 0 deletions postman/feature.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
{
"info": {
"_postman_id": "a70aa31c-9893-4c9e-af88-b5f4f554393b",
"name": "Location-Final",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
"_exporter_id": "51668874"
},
"item": [
{
"name": "New Request",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{ \"name\": \"Dasha\", \"email\": \"dasha@test.com\" }",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://localhost:8080/admin/users",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"admin",
"users"
]
}
},
"response": []
},
{
"name": "New Request",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{ \"name\": \"Концерты\" }",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://localhost:8080/admin/categories",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"admin",
"categories"
]
}
},
"response": []
},
{
"name": "New Request",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"name\": \"Центр\",\r\n \"lat\": 55.75,\r\n \"lon\": 37.61,\r\n \"radius\": 5.0\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://localhost:8080/admin/locations",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"admin",
"locations"
]
}
},
"response": []
},
{
"name": "New Request",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"annotation\": \"Очень крутой концерт в самом центре города\",\r\n \"category\": 1,\r\n \"description\": \"Длинное описание события более двадцати символов\",\r\n \"eventDate\": \"2026-12-31 20:00:00\",\r\n \"location\": { \"lat\": 55.751, \"lon\": 37.611 },\r\n \"paid\": false,\r\n \"participantLimit\": 0,\r\n \"requestModeration\": false,\r\n \"title\": \"Супер Концерт\"\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://localhost:8080/users/1/events",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"users",
"1",
"events"
]
}
},
"response": []
},
{
"name": "New Request",
"request": {
"method": "PATCH",
"header": [],
"body": {
"mode": "raw",
"raw": "{ \"stateAction\": \"PUBLISH_EVENT\" }",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://localhost:8080/admin/events/1",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"admin",
"events",
"1"
]
}
},
"response": []
},
{
"name": "New Request",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "http://localhost:8080/locations/1/events",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"locations",
"1",
"events"
]
}
},
"response": []
}
]
}
Loading