diff --git a/src/main/java/ru/practicum/shareit/item/ItemController.java b/src/main/java/ru/practicum/shareit/item/ItemController.java index bb17668b..8fa493a4 100644 --- a/src/main/java/ru/practicum/shareit/item/ItemController.java +++ b/src/main/java/ru/practicum/shareit/item/ItemController.java @@ -1,12 +1,56 @@ package ru.practicum.shareit.item; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; +import ru.practicum.shareit.item.dto.ItemDto; +import ru.practicum.shareit.item.service.ItemService; -/** - * TODO Sprint add-controllers. - */ +import java.util.List; + +@Slf4j @RestController @RequestMapping("/items") +@RequiredArgsConstructor public class ItemController { -} + private final ItemService itemService; + + @GetMapping + public List findAllByUser(@RequestHeader("X-Sharer-User-Id") Long userId) { + log.info("GET /items для пользователя {}", userId); + return itemService.findAllByUser(userId); + } + + @GetMapping("/{itemId}") + public ItemDto findById(@PathVariable Long itemId) { + log.info("GET /items/{}", itemId); + return itemService.findById(itemId); + } + + @PostMapping + public ItemDto create(@RequestHeader("X-Sharer-User-Id") Long userId, + @RequestBody ItemDto itemDto) { + log.info("POST /items для пользователя {}", userId); + return itemService.create(userId, itemDto); + } + + @PatchMapping("/{itemId}") + public ItemDto update(@RequestHeader("X-Sharer-User-Id") Long userId, + @PathVariable Long itemId, + @RequestBody ItemDto itemDto) { + log.info("PATCH /items/{} для пользователя {}", itemId, userId); + return itemService.update(userId, itemId, itemDto); + } + + @DeleteMapping("/{itemId}") + public void delete(@PathVariable Long itemId) { + log.info("DELETE /items/{}", itemId); + itemService.delete(itemId); + } + + @GetMapping("/search") + public List search(@RequestParam String text) { + log.info("GET /items/search?text={}", text); + return itemService.search(text); + } +} \ No newline at end of file diff --git a/src/main/java/ru/practicum/shareit/item/ItemMapper.java b/src/main/java/ru/practicum/shareit/item/ItemMapper.java new file mode 100644 index 00000000..bc570a74 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/ItemMapper.java @@ -0,0 +1,32 @@ +package ru.practicum.shareit.item; + +import ru.practicum.shareit.item.dto.ItemDto; +import ru.practicum.shareit.item.model.Item; + +public class ItemMapper { + public static ItemDto toItemDto(Item item) { + if (item == null) { + return null; + } + ItemDto dto = new ItemDto(); + dto.setId(item.getId()); + dto.setName(item.getName()); + dto.setDescription(item.getDescription()); + dto.setAvailable(item.getAvailable()); + dto.setRequestId(item.getRequestId()); + return dto; + } + + public static Item toItem(ItemDto itemDto) { + if (itemDto == null) { + return null; + } + Item item = new Item(); + item.setId(itemDto.getId()); + item.setName(itemDto.getName()); + item.setDescription(itemDto.getDescription()); + item.setAvailable(itemDto.getAvailable()); + item.setRequestId(itemDto.getRequestId()); + return item; + } +} \ No newline at end of file diff --git a/src/main/java/ru/practicum/shareit/item/dto/ItemDto.java b/src/main/java/ru/practicum/shareit/item/dto/ItemDto.java index 9319d7d7..9fdd86e2 100644 --- a/src/main/java/ru/practicum/shareit/item/dto/ItemDto.java +++ b/src/main/java/ru/practicum/shareit/item/dto/ItemDto.java @@ -1,7 +1,12 @@ package ru.practicum.shareit.item.dto; -/** - * TODO Sprint add-controllers. - */ +import lombok.Data; + +@Data public class ItemDto { -} + private Long id; + private String name; + private String description; + private Boolean available; + private Long requestId; +} \ No newline at end of file diff --git a/src/main/java/ru/practicum/shareit/item/model/Item.java b/src/main/java/ru/practicum/shareit/item/model/Item.java index 44eb73dd..11c6d5c3 100644 --- a/src/main/java/ru/practicum/shareit/item/model/Item.java +++ b/src/main/java/ru/practicum/shareit/item/model/Item.java @@ -1,7 +1,13 @@ package ru.practicum.shareit.item.model; -/** - * TODO Sprint add-controllers. - */ +import lombok.Data; + +@Data public class Item { -} + private Long id; + private String name; + private String description; + private Boolean available; + private Long ownerId; + private Long requestId; +} \ No newline at end of file diff --git a/src/main/java/ru/practicum/shareit/item/repository/InMemoryItemRepository.java b/src/main/java/ru/practicum/shareit/item/repository/InMemoryItemRepository.java new file mode 100644 index 00000000..c5800e37 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/repository/InMemoryItemRepository.java @@ -0,0 +1,56 @@ +package ru.practicum.shareit.item.repository; + +import org.springframework.stereotype.Repository; +import ru.practicum.shareit.item.model.Item; +import java.util.*; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Collectors; + +@Repository +public class InMemoryItemRepository implements ItemRepository { + private final Map items = new HashMap<>(); + private final AtomicLong idGenerator = new AtomicLong(1); + + @Override + public List findAllByOwnerId(Long ownerId) { + return items.values().stream() + .filter(item -> ownerId.equals(item.getOwnerId())) + .collect(Collectors.toList()); + } + + @Override + public Optional findById(Long id) { + return Optional.ofNullable(items.get(id)); + } + + @Override + public Item save(Item item) { + item.setId(idGenerator.getAndIncrement()); + items.put(item.getId(), item); + return item; + } + + @Override + public Item update(Item item) { + items.put(item.getId(), item); + return item; + } + + @Override + public void delete(Long id) { + items.remove(id); + } + + @Override + public List search(String text) { + if (text == null || text.isBlank()) { + return Collections.emptyList(); + } + String lowerText = text.toLowerCase(); + return items.values().stream() + .filter(Item::getAvailable) + .filter(item -> (item.getName() != null && item.getName().toLowerCase().contains(lowerText)) + || (item.getDescription() != null && item.getDescription().toLowerCase().contains(lowerText))) + .collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/src/main/java/ru/practicum/shareit/item/repository/ItemRepository.java b/src/main/java/ru/practicum/shareit/item/repository/ItemRepository.java new file mode 100644 index 00000000..0d7efc47 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/repository/ItemRepository.java @@ -0,0 +1,19 @@ +package ru.practicum.shareit.item.repository; + +import ru.practicum.shareit.item.model.Item; +import java.util.List; +import java.util.Optional; + +public interface ItemRepository { + List findAllByOwnerId(Long ownerId); + + Optional findById(Long id); + + Item save(Item item); + + Item update(Item item); + + void delete(Long id); + + List search(String text); +} \ No newline at end of file diff --git a/src/main/java/ru/practicum/shareit/item/service/ItemService.java b/src/main/java/ru/practicum/shareit/item/service/ItemService.java new file mode 100644 index 00000000..f57bd230 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/service/ItemService.java @@ -0,0 +1,18 @@ +package ru.practicum.shareit.item.service; + +import ru.practicum.shareit.item.dto.ItemDto; +import java.util.List; + +public interface ItemService { + List findAllByUser(Long userId); + + ItemDto findById(Long id); + + ItemDto create(Long userId, ItemDto itemDto); + + ItemDto update(Long userId, Long itemId, ItemDto itemDto); + + void delete(Long id); + + List search(String text); +} \ No newline at end of file diff --git a/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java b/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java new file mode 100644 index 00000000..99a81143 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java @@ -0,0 +1,88 @@ +package ru.practicum.shareit.item.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import ru.practicum.shareit.item.ItemMapper; +import ru.practicum.shareit.item.dto.ItemDto; +import ru.practicum.shareit.item.model.Item; +import ru.practicum.shareit.item.repository.ItemRepository; +import ru.practicum.shareit.user.repository.UserRepository; + +import java.util.List; +import java.util.stream.Collectors; + +@Slf4j +@Service +@RequiredArgsConstructor +public class ItemServiceImpl implements ItemService { + private final ItemRepository itemRepository; + private final UserRepository userRepository; + + @Override + public List findAllByUser(Long userId) { + log.info("Получение всех вещей пользователя {}", userId); + return itemRepository.findAllByOwnerId(userId).stream() + .map(ItemMapper::toItemDto) + .collect(Collectors.toList()); + } + + @Override + public ItemDto findById(Long id) { + log.info("Получение вещи с id {}", id); + Item item = itemRepository.findById(id) + .orElseThrow(() -> new RuntimeException("Вещь не найдена")); + return ItemMapper.toItemDto(item); + } + + @Override + public ItemDto create(Long userId, ItemDto itemDto) { + log.info("Создание вещи для пользователя {}", userId); + userRepository.findById(userId) + .orElseThrow(() -> new RuntimeException("Пользователь не найден")); + + Item item = ItemMapper.toItem(itemDto); + item.setOwnerId(userId); + + Item saved = itemRepository.save(item); + return ItemMapper.toItemDto(saved); + } + + @Override + public ItemDto update(Long userId, Long itemId, ItemDto itemDto) { + log.info("Обновление вещи {} для пользователя {}", itemId, userId); + Item existing = itemRepository.findById(itemId) + .orElseThrow(() -> new RuntimeException("Вещь не найдена")); + + if (!userId.equals(existing.getOwnerId())) { + throw new RuntimeException("Только владелец может редактировать вещь"); + } + + if (itemDto.getName() != null) { + existing.setName(itemDto.getName()); + } + if (itemDto.getDescription() != null) { + existing.setDescription(itemDto.getDescription()); + } + if (itemDto.getAvailable() != null) { + existing.setAvailable(itemDto.getAvailable()); + } + + Item updated = itemRepository.update(existing); + return ItemMapper.toItemDto(updated); + } + + @Override + public void delete(Long id) { + log.info("Удаление вещи {}", id); + itemRepository.delete(id); + } + + @Override + public List search(String text) { + log.info("Поиск вещей по тексту: {}", text); + return itemRepository.search(text).stream() + .map(ItemMapper::toItemDto) + .collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/src/main/java/ru/practicum/shareit/user/User.java b/src/main/java/ru/practicum/shareit/user/User.java deleted file mode 100644 index ae6e7f33..00000000 --- a/src/main/java/ru/practicum/shareit/user/User.java +++ /dev/null @@ -1,7 +0,0 @@ -package ru.practicum.shareit.user; - -/** - * TODO Sprint add-controllers. - */ -public class User { -} diff --git a/src/main/java/ru/practicum/shareit/user/UserController.java b/src/main/java/ru/practicum/shareit/user/UserController.java index 03039b9d..83266723 100644 --- a/src/main/java/ru/practicum/shareit/user/UserController.java +++ b/src/main/java/ru/practicum/shareit/user/UserController.java @@ -1,12 +1,47 @@ package ru.practicum.shareit.user; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; +import ru.practicum.shareit.user.dto.UserDto; +import ru.practicum.shareit.user.service.UserService; -/** - * TODO Sprint add-controllers. - */ +import java.util.List; + +@Slf4j @RestController -@RequestMapping(path = "/users") +@RequestMapping("/users") +@RequiredArgsConstructor public class UserController { -} + private final UserService userService; + + @GetMapping + public List findAll() { + log.info("GET /users"); + return userService.findAll(); + } + + @GetMapping("/{id}") + public UserDto findById(@PathVariable Long id) { + log.info("GET /users/{}", id); + return userService.findById(id); + } + + @PostMapping + public UserDto create(@RequestBody UserDto userDto) { + log.info("POST /users - создание пользователя"); + return userService.create(userDto); + } + + @PatchMapping("/{id}") + public UserDto update(@PathVariable Long id, @RequestBody UserDto userDto) { + log.info("PATCH /users/{} - обновление пользователя", id); + return userService.update(id, userDto); + } + + @DeleteMapping("/{id}") + public void delete(@PathVariable Long id) { + log.info("DELETE /users/{}", id); + userService.delete(id); + } +} \ No newline at end of file diff --git a/src/main/java/ru/practicum/shareit/user/UserMapper.java b/src/main/java/ru/practicum/shareit/user/UserMapper.java new file mode 100644 index 00000000..f8292e4f --- /dev/null +++ b/src/main/java/ru/practicum/shareit/user/UserMapper.java @@ -0,0 +1,28 @@ +package ru.practicum.shareit.user; + +import ru.practicum.shareit.user.dto.UserDto; +import ru.practicum.shareit.user.model.User; + +public class UserMapper { + public static UserDto toUserDto(User user) { + if (user == null) { + return null; + } + UserDto dto = new UserDto(); + dto.setId(user.getId()); + dto.setName(user.getName()); + dto.setEmail(user.getEmail()); + return dto; + } + + public static User toUser(UserDto userDto) { + if (userDto == null) { + return null; + } + User user = new User(); + user.setId(userDto.getId()); + user.setName(userDto.getName()); + user.setEmail(userDto.getEmail()); + return user; + } +} \ No newline at end of file diff --git a/src/main/java/ru/practicum/shareit/user/dto/UserDto.java b/src/main/java/ru/practicum/shareit/user/dto/UserDto.java new file mode 100644 index 00000000..c3101d78 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/user/dto/UserDto.java @@ -0,0 +1,10 @@ +package ru.practicum.shareit.user.dto; + +import lombok.Data; + +@Data +public class UserDto { + private Long id; + private String name; + private String email; +} \ No newline at end of file diff --git a/src/main/java/ru/practicum/shareit/user/model/User.java b/src/main/java/ru/practicum/shareit/user/model/User.java new file mode 100644 index 00000000..c30dbe09 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/user/model/User.java @@ -0,0 +1,10 @@ +package ru.practicum.shareit.user.model; + +import lombok.Data; + +@Data +public class User { + private Long id; + private String name; + private String email; +} \ No newline at end of file diff --git a/src/main/java/ru/practicum/shareit/user/repository/InMemoryUserRepository.java b/src/main/java/ru/practicum/shareit/user/repository/InMemoryUserRepository.java new file mode 100644 index 00000000..ade68078 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/user/repository/InMemoryUserRepository.java @@ -0,0 +1,40 @@ +package ru.practicum.shareit.user.repository; + +import org.springframework.stereotype.Repository; +import ru.practicum.shareit.user.model.User; +import java.util.*; +import java.util.concurrent.atomic.AtomicLong; + +@Repository +public class InMemoryUserRepository implements UserRepository { + private final Map users = new HashMap<>(); + private final AtomicLong idGenerator = new AtomicLong(1); + + @Override + public List findAll() { + return new ArrayList<>(users.values()); + } + + @Override + public Optional findById(Long id) { + return Optional.ofNullable(users.get(id)); + } + + @Override + public User save(User user) { + user.setId(idGenerator.getAndIncrement()); + users.put(user.getId(), user); + return user; + } + + @Override + public User update(User user) { + users.put(user.getId(), user); + return user; + } + + @Override + public void delete(Long id) { + users.remove(id); + } +} \ No newline at end of file diff --git a/src/main/java/ru/practicum/shareit/user/repository/UserRepository.java b/src/main/java/ru/practicum/shareit/user/repository/UserRepository.java new file mode 100644 index 00000000..691b47df --- /dev/null +++ b/src/main/java/ru/practicum/shareit/user/repository/UserRepository.java @@ -0,0 +1,17 @@ +package ru.practicum.shareit.user.repository; + +import ru.practicum.shareit.user.model.User; +import java.util.List; +import java.util.Optional; + +public interface UserRepository { + List findAll(); + + Optional findById(Long id); + + User save(User user); + + User update(User user); + + void delete(Long id); +} \ No newline at end of file diff --git a/src/main/java/ru/practicum/shareit/user/service/UserService.java b/src/main/java/ru/practicum/shareit/user/service/UserService.java new file mode 100644 index 00000000..c94c54ee --- /dev/null +++ b/src/main/java/ru/practicum/shareit/user/service/UserService.java @@ -0,0 +1,16 @@ +package ru.practicum.shareit.user.service; + +import ru.practicum.shareit.user.dto.UserDto; +import java.util.List; + +public interface UserService { + List findAll(); + + UserDto findById(Long id); + + UserDto create(UserDto userDto); + + UserDto update(Long id, UserDto userDto); + + void delete(Long id); +} \ No newline at end of file diff --git a/src/main/java/ru/practicum/shareit/user/service/UserServiceImpl.java b/src/main/java/ru/practicum/shareit/user/service/UserServiceImpl.java new file mode 100644 index 00000000..c06ef488 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/user/service/UserServiceImpl.java @@ -0,0 +1,66 @@ +package ru.practicum.shareit.user.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import ru.practicum.shareit.user.UserMapper; +import ru.practicum.shareit.user.dto.UserDto; +import ru.practicum.shareit.user.model.User; +import ru.practicum.shareit.user.repository.UserRepository; + +import java.util.List; +import java.util.stream.Collectors; + +@Slf4j +@Service +@RequiredArgsConstructor +public class UserServiceImpl implements UserService { + private final UserRepository userRepository; + + @Override + public List findAll() { + log.info("Получение всех пользователей"); + return userRepository.findAll().stream() + .map(UserMapper::toUserDto) + .collect(Collectors.toList()); + } + + @Override + public UserDto findById(Long id) { + log.info("Получение пользователя с id {}", id); + User user = userRepository.findById(id) + .orElseThrow(() -> new RuntimeException("Пользователь не найден")); + return UserMapper.toUserDto(user); + } + + @Override + public UserDto create(UserDto userDto) { + log.info("Создание пользователя с email {}", userDto.getEmail()); + User user = UserMapper.toUser(userDto); + User saved = userRepository.save(user); + return UserMapper.toUserDto(saved); + } + + @Override + public UserDto update(Long id, UserDto userDto) { + log.info("Обновление пользователя с id {}", id); + User existing = userRepository.findById(id) + .orElseThrow(() -> new RuntimeException("Пользователь не найден")); + + if (userDto.getName() != null) { + existing.setName(userDto.getName()); + } + if (userDto.getEmail() != null) { + existing.setEmail(userDto.getEmail()); + } + + User updated = userRepository.update(existing); + return UserMapper.toUserDto(updated); + } + + @Override + public void delete(Long id) { + log.info("Удаление пользователя с id {}", id); + userRepository.delete(id); + } +} \ No newline at end of file