Skip to content
Open
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
@@ -0,0 +1,7 @@
package ru.practicum.shareit.exception;

public class ConflictException extends RuntimeException {
public ConflictException(String message) {
super(message);
}
}
41 changes: 41 additions & 0 deletions src/main/java/ru/practicum/shareit/exception/ErrorHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package ru.practicum.shareit.exception;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.*;

import java.util.Map;

@Slf4j
@RestControllerAdvice
public class ErrorHandler {

@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public Map<String, String> catchAllExceptions(Exception ex) {
log.error("500: ", ex);
return Map.of("error", "Произошла ошибка");
}

@ExceptionHandler({ValidationException.class, MethodArgumentNotValidException.class})
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Map<String, String> catchValidationErrors(Exception ex) {
log.error("400: {}", ex.getMessage());
return Map.of("error", "Ошибка валидации");
}

@ExceptionHandler(ConflictException.class)
@ResponseStatus(HttpStatus.CONFLICT)
public Map<String, String> catchConflictStatus(ConflictException ex) {
log.error("409: {}", ex.getMessage());
return Map.of("error", ex.getMessage());
}

@ExceptionHandler(NotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public Map<String, String> catchNotFoundStatus(NotFoundException ex) {
log.error("404: {}", ex.getMessage());
return Map.of("error", ex.getMessage());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ru.practicum.shareit.exception;

public class NotFoundException extends RuntimeException {
public NotFoundException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ru.practicum.shareit.exception;

public class ValidationException extends RuntimeException {
public ValidationException(String message) {
super(message);
}
}
52 changes: 46 additions & 6 deletions src/main/java/ru/practicum/shareit/item/ItemController.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,52 @@
package ru.practicum.shareit.item;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import ru.practicum.shareit.item.dto.ItemDto;

/**
* TODO Sprint add-controllers.
*/
import java.util.List;

@Slf4j
@RestController
@RequestMapping("/items")
@RequiredArgsConstructor
public class ItemController {
}

private final ItemService itemService;
private static final String USER_ID_HEADER = "X-Sharer-User-Id";

@GetMapping
public List<ItemDto> fetchAllUserItems(@RequestHeader(USER_ID_HEADER) Long ownerId) {
log.info("GET /items (владелец id={})", ownerId);
return itemService.getByOwner(ownerId);
}

@GetMapping("/search")
public List<ItemDto> findItems(@RequestParam(name = "text") String query) {
log.info("GET /items/search?text={}", query);
return itemService.search(query);
}

@PatchMapping("/{itemId}")
public ItemDto modifyItem(@RequestHeader(USER_ID_HEADER) Long requesterId,
@PathVariable(name = "itemId") Long id,
@RequestBody ItemDto payload) {
log.info("PATCH /items/{} от пользователя id={}", id, requesterId);
return itemService.update(requesterId, id, payload);
}

@PostMapping
public ItemDto addNewItem(@RequestHeader(USER_ID_HEADER) Long creatorId,
@Valid @RequestBody ItemDto payload) {
log.info("POST /items от пользователя id={}", creatorId);
return itemService.create(creatorId, payload);
}

@GetMapping("/{itemId}")
public ItemDto fetchItemById(@PathVariable(name = "itemId") Long id) {
log.info("GET /items/{}", id);
return itemService.getById(id);
}
}
25 changes: 25 additions & 0 deletions src/main/java/ru/practicum/shareit/item/ItemMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package ru.practicum.shareit.item;

import ru.practicum.shareit.item.dto.ItemDto;
import ru.practicum.shareit.item.model.Item;

public class ItemMapper {
public static Item toItem(ItemDto dto) {
return Item.builder()
.available(dto.getAvailable())
.description(dto.getDescription())
.name(dto.getName())
.id(dto.getId())
.build();
}

public static ItemDto toItemDto(Item entity) {
return ItemDto.builder()
.requestId(entity.getRequestId())
.available(entity.getAvailable())
.description(entity.getDescription())
.name(entity.getName())
.id(entity.getId())
.build();
}
}
16 changes: 16 additions & 0 deletions src/main/java/ru/practicum/shareit/item/ItemService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package ru.practicum.shareit.item;

import ru.practicum.shareit.item.dto.ItemDto;
import java.util.List;

public interface ItemService {
ItemDto update(Long userId, Long itemId, ItemDto itemDto);

List<ItemDto> search(String text);

ItemDto getById(Long itemId);

ItemDto create(Long userId, ItemDto itemDto);

List<ItemDto> getByOwner(Long userId);
}
97 changes: 97 additions & 0 deletions src/main/java/ru/practicum/shareit/item/ItemServiceImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package ru.practicum.shareit.item;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import ru.practicum.shareit.exception.NotFoundException;
import ru.practicum.shareit.item.dto.ItemDto;
import ru.practicum.shareit.item.model.Item;
import ru.practicum.shareit.user.User;
import ru.practicum.shareit.user.UserService;
import ru.practicum.shareit.user.UserMapper;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class ItemServiceImpl implements ItemService {

private final Map<Long, Item> repository = new HashMap<>();
private final UserService userService;
private Long lastGeneratedId = 1L;

@Override
public List<ItemDto> search(String searchStr) {
if (searchStr == null || searchStr.isBlank()) {
return Collections.emptyList();
}

String lowerCaseQuery = searchStr.toLowerCase();
return repository.values().stream()
.filter(Item::getAvailable)
.filter(item -> item.getName().toLowerCase().contains(lowerCaseQuery)
|| item.getDescription().toLowerCase().contains(lowerCaseQuery))
.map(ItemMapper::toItemDto)
.collect(Collectors.toList());
}

@Override
public ItemDto getById(Long id) {
Item found = repository.get(id);
if (found == null) {
throw new NotFoundException("Объект с идентификатором " + id + " не существует");
}
return ItemMapper.toItemDto(found);
}

@Override
public List<ItemDto> getByOwner(Long ownerId) {
userService.getById(ownerId);

return repository.values().stream()
.filter(obj -> obj.getOwner().getId().equals(ownerId))
.map(ItemMapper::toItemDto)
.collect(Collectors.toList());
}

@Override
public ItemDto update(Long userId, Long itemId, ItemDto dto) {
Item target = repository.get(itemId);

if (Objects.isNull(target)) {
throw new NotFoundException("Вещь с id " + itemId + " не найдена");
}

if (!Objects.equals(target.getOwner().getId(), userId)) {
throw new NotFoundException("Доступ запрещен: редактировать может только владелец");
}

if (dto.getName() != null && !dto.getName().trim().isEmpty()) {
target.setName(dto.getName());
}
if (dto.getDescription() != null && !dto.getDescription().trim().isEmpty()) {
target.setDescription(dto.getDescription());
}
if (dto.getAvailable() != null) {
target.setAvailable(dto.getAvailable());
}

return ItemMapper.toItemDto(target);
}

@Override
public ItemDto create(Long userId, ItemDto itemDto) {
User creator = UserMapper.toUser(userService.getById(userId));
Item newEntry = ItemMapper.toItem(itemDto);

newEntry.setId(lastGeneratedId++);
newEntry.setOwner(creator);

repository.put(newEntry.getId(), newEntry);
log.info("Сохранена новая вещь с ID: {}", newEntry.getId());

return ItemMapper.toItemDto(newEntry);
}
}
20 changes: 16 additions & 4 deletions src/main/java/ru/practicum/shareit/item/dto/ItemDto.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
package ru.practicum.shareit.item.dto;

/**
* TODO Sprint add-controllers.
*/
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class ItemDto {
}
private Long id;
@NotBlank
private String name;
@NotBlank
private String description;
@NotNull
private Boolean available;
private Long requestId;
}
21 changes: 17 additions & 4 deletions src/main/java/ru/practicum/shareit/item/model/Item.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
package ru.practicum.shareit.item.model;

/**
* TODO Sprint add-controllers.
*/
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import ru.practicum.shareit.user.User;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Item {
}
private Long id;
private String name;
private String description;
private Boolean available;
private User owner;
private Long requestId;
}
17 changes: 13 additions & 4 deletions src/main/java/ru/practicum/shareit/user/User.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
package ru.practicum.shareit.user;

/**
* TODO Sprint add-controllers.
*/
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class User {
}
private String email;
private String name;
private Long id;
}
49 changes: 42 additions & 7 deletions src/main/java/ru/practicum/shareit/user/UserController.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,47 @@
package ru.practicum.shareit.user;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import ru.practicum.shareit.user.dto.UserDto;

/**
* TODO Sprint add-controllers.
*/
import java.util.List;
//use
@Slf4j
@RestController
@RequestMapping(path = "/users")
@RequestMapping("/users")
@RequiredArgsConstructor
public class UserController {
}
private final UserService userService;

@DeleteMapping("/{id}")
public void removeUser(@PathVariable Long id) {
log.info("DELETE request for user ID: {}", id);
userService.delete(id);
}

@GetMapping
public List<UserDto> getAllUsers() {
log.info("GET request for all users");
return userService.findAll();
}

@PatchMapping("/{id}")
public UserDto patchUser(@PathVariable Long id, @RequestBody UserDto dto) {
log.info("PATCH request for user ID: {}", id);
return userService.update(id, dto);
}

@GetMapping("/{id}")
public UserDto getUser(@PathVariable Long id) {
log.info("GET request for user ID: {}", id);
return userService.getById(id);
}

@PostMapping
public UserDto saveUser(@Valid @RequestBody UserDto dto) {
log.info("POST request to create user: {}", dto.getEmail());
return userService.create(dto);
}
}
Loading
Loading