diff --git a/pom.xml b/pom.xml index 2db888c..a7fbefe 100644 --- a/pom.xml +++ b/pom.xml @@ -20,10 +20,19 @@ + + + + org.springframework.boot spring-boot-starter-web + + org.zalando + logbook-spring-boot-starter + 3.7.2 + org.springframework.boot spring-boot-starter-actuator diff --git a/src/main/java/ru/practicum/shareit/ShareItApp.java b/src/main/java/ru/practicum/shareit/ShareItApp.java index a00ad56..a10a87d 100644 --- a/src/main/java/ru/practicum/shareit/ShareItApp.java +++ b/src/main/java/ru/practicum/shareit/ShareItApp.java @@ -6,8 +6,8 @@ @SpringBootApplication public class ShareItApp { - public static void main(String[] args) { - SpringApplication.run(ShareItApp.class, args); - } + public static void main(String[] args) { + SpringApplication.run(ShareItApp.class, args); + } } diff --git a/src/main/java/ru/practicum/shareit/booking/Booking.java b/src/main/java/ru/practicum/shareit/booking/Booking.java index 2d9c666..192431e 100644 --- a/src/main/java/ru/practicum/shareit/booking/Booking.java +++ b/src/main/java/ru/practicum/shareit/booking/Booking.java @@ -1,7 +1,15 @@ package ru.practicum.shareit.booking; -/** - * TODO Sprint add-bookings. - */ +import lombok.Data; + +import java.time.LocalDateTime; + +@Data public class Booking { + private Long id; + private LocalDateTime start; + private LocalDateTime end; + private Long itemId; + private Long booker; + private Status status; } diff --git a/src/main/java/ru/practicum/shareit/booking/Status.java b/src/main/java/ru/practicum/shareit/booking/Status.java new file mode 100644 index 0000000..2037aa5 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/booking/Status.java @@ -0,0 +1,8 @@ +package ru.practicum.shareit.booking; + +public enum Status { + WAITING, + APPROVED, + REJECTED, + CANCELED; +} diff --git a/src/main/java/ru/practicum/shareit/booking/dto/BookingCreateDto.java b/src/main/java/ru/practicum/shareit/booking/dto/BookingCreateDto.java new file mode 100644 index 0000000..7728bf4 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/booking/dto/BookingCreateDto.java @@ -0,0 +1,21 @@ +package ru.practicum.shareit.booking.dto; + +import jakarta.validation.constraints.Null; +import lombok.Data; +import ru.practicum.shareit.booking.Status; + +import java.time.LocalDateTime; + +@Data +public class BookingCreateDto { + private Long id; + @Null + private LocalDateTime start; + @Null + private LocalDateTime end; + @Null + private Long itemId; + @Null + private Long booker; + private Status status; +} diff --git a/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java b/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java index 861de9e..9f9bd16 100644 --- a/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java +++ b/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java @@ -1,7 +1,16 @@ package ru.practicum.shareit.booking.dto; -/** - * TODO Sprint add-bookings. - */ -public class BookingDto { +import lombok.Data; +import ru.practicum.shareit.booking.Status; + +import java.time.LocalDateTime; + +@Data +public class BookingDto { + private Long id; + private LocalDateTime start; + private LocalDateTime end; + private Long itemId; + private Long booker; + private Status status; } diff --git a/src/main/java/ru/practicum/shareit/booking/dto/BookingUpdateDto.java b/src/main/java/ru/practicum/shareit/booking/dto/BookingUpdateDto.java new file mode 100644 index 0000000..2acf2a9 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/booking/dto/BookingUpdateDto.java @@ -0,0 +1,18 @@ +package ru.practicum.shareit.booking.dto; + +import jakarta.validation.constraints.Null; +import lombok.Data; +import ru.practicum.shareit.booking.Status; + +import java.time.LocalDateTime; + +@Data +public class BookingUpdateDto { + @Null + private Long id; + private LocalDateTime start; + private LocalDateTime end; + private Long itemId; + private Long booker; + private Status status; +} diff --git a/src/main/java/ru/practicum/shareit/exception/ConflictException.java b/src/main/java/ru/practicum/shareit/exception/ConflictException.java new file mode 100644 index 0000000..7885123 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/exception/ConflictException.java @@ -0,0 +1,7 @@ +package ru.practicum.shareit.exception; + +public class ConflictException extends RuntimeException { + public ConflictException(String message) { + super(message); + } +} diff --git a/src/main/java/ru/practicum/shareit/exception/ErrorHandler.java b/src/main/java/ru/practicum/shareit/exception/ErrorHandler.java new file mode 100644 index 0000000..b134feb --- /dev/null +++ b/src/main/java/ru/practicum/shareit/exception/ErrorHandler.java @@ -0,0 +1,38 @@ +package ru.practicum.shareit.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestControllerAdvice; + + +@RestControllerAdvice +public class ErrorHandler { + + @ExceptionHandler + @ResponseStatus(HttpStatus.NOT_FOUND) + public ErrorResponse handleNotFoundException(final NotFoundException e) { + return new ErrorResponse("Error", e.getMessage()); + } + + @ExceptionHandler + @ResponseStatus(HttpStatus.BAD_REQUEST) + public ErrorResponse handleValidationException(final ValidationException e) { + return new ErrorResponse("Error", e.getMessage()); + } + + @ExceptionHandler + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + public ErrorResponse handleInternalServerErrorException(final InternalServerErrorException e) { + return new ErrorResponse("Error", e.getMessage()); + } + + @ExceptionHandler + @ResponseStatus(HttpStatus.CONFLICT) + public ErrorResponse handleConflictException(final ConflictException e) { + return new ErrorResponse("Error", e.getMessage()); + } + +} + + diff --git a/src/main/java/ru/practicum/shareit/exception/ErrorResponse.java b/src/main/java/ru/practicum/shareit/exception/ErrorResponse.java new file mode 100644 index 0000000..f031b49 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/exception/ErrorResponse.java @@ -0,0 +1,19 @@ +package ru.practicum.shareit.exception; + +public class ErrorResponse { + private final String error; + private final String description; + + public ErrorResponse(String error, String description) { + this.error = error; + this.description = description; + } + + public String getError() { + return error; + } + + public String getDescription() { + return description; + } +} \ No newline at end of file diff --git a/src/main/java/ru/practicum/shareit/exception/InternalServerErrorException.java b/src/main/java/ru/practicum/shareit/exception/InternalServerErrorException.java new file mode 100644 index 0000000..f9f030b --- /dev/null +++ b/src/main/java/ru/practicum/shareit/exception/InternalServerErrorException.java @@ -0,0 +1,8 @@ +package ru.practicum.shareit.exception; + +public class InternalServerErrorException extends RuntimeException { + public InternalServerErrorException(String message) { + super(message); + } +} + diff --git a/src/main/java/ru/practicum/shareit/exception/NotFoundException.java b/src/main/java/ru/practicum/shareit/exception/NotFoundException.java new file mode 100644 index 0000000..508b545 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/exception/NotFoundException.java @@ -0,0 +1,7 @@ +package ru.practicum.shareit.exception; + +public class NotFoundException extends RuntimeException { + public NotFoundException(String message) { + super(message); + } +} diff --git a/src/main/java/ru/practicum/shareit/exception/ValidationException.java b/src/main/java/ru/practicum/shareit/exception/ValidationException.java new file mode 100644 index 0000000..56cb5a8 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/exception/ValidationException.java @@ -0,0 +1,8 @@ +package ru.practicum.shareit.exception; + +public class ValidationException extends RuntimeException { + + public ValidationException(String message) { + super(message); + } +} diff --git a/src/main/java/ru/practicum/shareit/item/ItemController.java b/src/main/java/ru/practicum/shareit/item/ItemController.java index bb17668..65d2be9 100644 --- a/src/main/java/ru/practicum/shareit/item/ItemController.java +++ b/src/main/java/ru/practicum/shareit/item/ItemController.java @@ -1,12 +1,52 @@ package ru.practicum.shareit.item; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import ru.practicum.shareit.item.dto.ItemCreateDto; +import ru.practicum.shareit.item.dto.ItemDto; +import ru.practicum.shareit.item.dto.ItemUpdateDto; +import ru.practicum.shareit.item.model.Item; +import ru.practicum.shareit.item.service.ItemService; -/** - * TODO Sprint add-controllers. - */ +import java.util.List; + +@Validated @RestController +@RequiredArgsConstructor @RequestMapping("/items") public class ItemController { + private final ItemService itemService; + private final ItemMapper itemMapper; + + @PostMapping + public ItemDto create(@RequestHeader("X-Sharer-User-Id") Long userId, + @Validated @RequestBody ItemCreateDto createDto) { + Item item = itemService.create(itemMapper.createDtoToModel(createDto, userId)); + return itemMapper.modelToItemDto(item); + } + + @PatchMapping("/{itemId}") + public ItemDto update(@RequestHeader("X-Sharer-User-Id") Long userId, @PathVariable Long itemId, + @Validated @RequestBody ItemUpdateDto updateDto) { + Item item = itemService.update(itemMapper.updateDtoToModel(updateDto, userId, itemId)); + return itemMapper.modelToItemDto(item); + } + + + @GetMapping("/{itemId}") + public ItemDto getItemById(@PathVariable Long itemId) { + return itemMapper.modelToItemDto(itemService.getItemById(itemId)); + } + + @GetMapping + public List getItemByOwnerId(@RequestHeader("X-Sharer-User-Id") Long userId) { + return itemMapper.listModelToDto(itemService.getItemByOwnerId(userId)); + } + + @GetMapping("/search") + public List getItemsByNameOrDescription(@RequestParam String text) { + return itemMapper.listModelToDto(itemService.getItemsByNameOrDescription(text)); + } + } 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 0000000..a86c789 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/ItemMapper.java @@ -0,0 +1,52 @@ +package ru.practicum.shareit.item; + +import org.springframework.stereotype.Component; +import ru.practicum.shareit.item.dto.ItemCreateDto; +import ru.practicum.shareit.item.dto.ItemDto; +import ru.practicum.shareit.item.dto.ItemUpdateDto; +import ru.practicum.shareit.item.model.Item; + +import java.util.ArrayList; +import java.util.List; + +@Component +public class ItemMapper { + + public Item createDtoToModel(ItemCreateDto dto, long ownerId) { + return Item.builder() + .name(dto.getName()) + .description(dto.getDescription()) + .available(dto.getAvailable()) + .owner(ownerId) + .build(); + } + + public Item updateDtoToModel(ItemUpdateDto dto, long ownerId, long itemId) { + return Item.builder() + .id(itemId) + .name(dto.getName()) + .description(dto.getDescription()) + .available(dto.getAvailable()) + .owner(ownerId) + .build(); + } + + public ItemDto modelToItemDto(Item item) { + return ItemDto.builder() + .id(item.getId()) + .name(item.getName()) + .description(item.getDescription()) + .available(item.getAvailable()) + .owner(item.getOwner()) + .build(); + } + + public List listModelToDto(List items) { + List list = new ArrayList<>(); + for (Item item : items) { + list.add(modelToItemDto(item)); + } + return list; + } + +} diff --git a/src/main/java/ru/practicum/shareit/item/dto/ItemCreateDto.java b/src/main/java/ru/practicum/shareit/item/dto/ItemCreateDto.java new file mode 100644 index 0000000..2cb517d --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/dto/ItemCreateDto.java @@ -0,0 +1,17 @@ +package ru.practicum.shareit.item.dto; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class ItemCreateDto { + @NotNull + @NotBlank + private String name; + @NotNull + private String description; + @NotNull + private Boolean available; + private Long owner; +} 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 9319d7d..b898db1 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,14 @@ package ru.practicum.shareit.item.dto; -/** - * TODO Sprint add-controllers. - */ +import lombok.Builder; +import lombok.Data; + +@Builder +@Data public class ItemDto { + private Long id; + private String name; + private String description; + private Boolean available; + private Long owner; } diff --git a/src/main/java/ru/practicum/shareit/item/dto/ItemUpdateDto.java b/src/main/java/ru/practicum/shareit/item/dto/ItemUpdateDto.java new file mode 100644 index 0000000..3d489dd --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/dto/ItemUpdateDto.java @@ -0,0 +1,10 @@ +package ru.practicum.shareit.item.dto; + +import lombok.Data; + +@Data +public class ItemUpdateDto { + private String name; + private String description; + private Boolean available; +} 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 44eb73d..07f84c6 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,15 @@ package ru.practicum.shareit.item.model; -/** - * TODO Sprint add-controllers. - */ +import lombok.Builder; +import lombok.Data; + +@Builder +@Data public class Item { + private long id; + private String name; + private String description; + private Boolean available; + private long owner; + private long requestId; } 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 0000000..1e454ac --- /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; + +public interface ItemRepository { + long getNextId(); + + Item create(Item item); + + Item update(Item item); + + Item getItemById(long itemId); + + List getItemByOwnerId(long ownerId); + + List getItemsByNameOrDescription(String text); +} diff --git a/src/main/java/ru/practicum/shareit/item/repository/ItemRepositoryImpl.java b/src/main/java/ru/practicum/shareit/item/repository/ItemRepositoryImpl.java new file mode 100644 index 0000000..978e29b --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/repository/ItemRepositoryImpl.java @@ -0,0 +1,84 @@ +package ru.practicum.shareit.item.repository; + +import org.springframework.stereotype.Component; +import ru.practicum.shareit.exception.NotFoundException; +import ru.practicum.shareit.item.model.Item; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class ItemRepositoryImpl implements ItemRepository { + private long id = 1L; + private final Map itemMap = new HashMap<>(); + + @Override + public long getNextId() { + return id++; + } + + @Override + public Item create(Item item) { + long id = getNextId(); + item.setId(id); + itemMap.put(id, item); + return item; + } + + @Override + public Item update(Item item) { + long id = item.getId(); + checkItemId(id); + checkOwnerId(item); + Item itemSaved = itemMap.get(id); + if (item.getName() != null) { + itemSaved.setName(item.getName()); + } + if (item.getDescription() != null) { + itemSaved.setDescription(item.getDescription()); + } + if (item.getAvailable() != null) { + itemSaved.setAvailable(item.getAvailable()); + } + itemMap.put(id, itemSaved); + return itemSaved; + } + + @Override + public Item getItemById(long itemId) { + checkItemId(itemId); + return itemMap.get(itemId); + } + + @Override + public List getItemByOwnerId(long ownerId) { + return itemMap.values() + .stream() + .filter(item -> item.getOwner() == ownerId) + .toList(); + } + + @Override + public List getItemsByNameOrDescription(String text) { + return itemMap.values().stream() + .filter(item -> item.getAvailable().equals(true)) + .filter(item -> item.getName().toLowerCase().contains(text) || + item.getDescription().toLowerCase().contains(text)) + .toList(); + } + + private void checkItemId(long id) { + if (!itemMap.containsKey(id)) { + throw new NotFoundException("item под номером: id = " + id + " отсутствует"); + } + } + + private void checkOwnerId(Item item) { + Item itemSaved = itemMap.get(item.getId()); + if (item.getOwner() != itemSaved.getOwner()) { + throw new NotFoundException("Редактировать item может только владелец"); + } + } + +} 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 0000000..cfc6682 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/service/ItemService.java @@ -0,0 +1,17 @@ +package ru.practicum.shareit.item.service; + +import ru.practicum.shareit.item.model.Item; + +import java.util.List; + +public interface ItemService { + Item create(Item item); + + Item update(Item item); + + Item getItemById(long itemId); + + List getItemByOwnerId(long ownerId); + + List getItemsByNameOrDescription(String text); +} 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 0000000..386fdf6 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java @@ -0,0 +1,55 @@ +package ru.practicum.shareit.item.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import ru.practicum.shareit.exception.NotFoundException; +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; + +@Service +@RequiredArgsConstructor +public class ItemServiceImpl implements ItemService { + private final ItemRepository itemRepository; + private final UserRepository userRepository; + + @Override + public Item create(Item item) { + checkUser(item); + return itemRepository.create(item); + } + + @Override + public Item update(Item item) { + checkUser(item); + return itemRepository.update(item); + } + + @Override + public Item getItemById(long itemId) { + return itemRepository.getItemById(itemId); + } + + @Override + public List getItemByOwnerId(long ownerId) { + return itemRepository.getItemByOwnerId(ownerId); + } + + @Override + public List getItemsByNameOrDescription(String text) { + if (text == null || text.isEmpty()) { + return List.of(); + } + return itemRepository.getItemsByNameOrDescription(text.toLowerCase()); + } + + private void checkUser(Item item) { + if (userRepository.getUserById(item.getOwner()) == null) { + System.out.println(item); + throw new NotFoundException("User отсутствует"); + } + } + +} diff --git a/src/main/java/ru/practicum/shareit/request/ItemRequest.java b/src/main/java/ru/practicum/shareit/request/ItemRequest.java index 95d6f23..1ae6480 100644 --- a/src/main/java/ru/practicum/shareit/request/ItemRequest.java +++ b/src/main/java/ru/practicum/shareit/request/ItemRequest.java @@ -1,7 +1,14 @@ package ru.practicum.shareit.request; -/** - * TODO Sprint add-item-requests. - */ + +import lombok.Data; + +import java.time.LocalDateTime; + +@Data public class ItemRequest { + private Long id; + private String description; + private Long requestor; + private LocalDateTime dateTimeRequest; } diff --git a/src/main/java/ru/practicum/shareit/request/dto/ItemRequestDto.java b/src/main/java/ru/practicum/shareit/request/dto/ItemRequestDto.java index 7b3ed54..a30555e 100644 --- a/src/main/java/ru/practicum/shareit/request/dto/ItemRequestDto.java +++ b/src/main/java/ru/practicum/shareit/request/dto/ItemRequestDto.java @@ -1,7 +1,14 @@ package ru.practicum.shareit.request.dto; -/** - * TODO Sprint add-item-requests. - */ + +import lombok.Data; + +import java.time.LocalDateTime; + +@Data public class ItemRequestDto { + private Long id; + private String description; + private Long requestor; + private LocalDateTime dateTimeRequest; } diff --git a/src/main/java/ru/practicum/shareit/user/User.java b/src/main/java/ru/practicum/shareit/user/User.java index ae6e7f3..c3373a9 100644 --- a/src/main/java/ru/practicum/shareit/user/User.java +++ b/src/main/java/ru/practicum/shareit/user/User.java @@ -1,7 +1,13 @@ package ru.practicum.shareit.user; -/** - * TODO Sprint add-controllers. - */ + +import lombok.Builder; +import lombok.Data; + +@Builder +@Data public class User { + private long id; + private String name; + private String email; } diff --git a/src/main/java/ru/practicum/shareit/user/UserController.java b/src/main/java/ru/practicum/shareit/user/UserController.java index 03039b9..9d688ce 100644 --- a/src/main/java/ru/practicum/shareit/user/UserController.java +++ b/src/main/java/ru/practicum/shareit/user/UserController.java @@ -1,12 +1,49 @@ package ru.practicum.shareit.user; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import ru.practicum.shareit.user.dto.UserCreateDto; +import ru.practicum.shareit.user.dto.UserDto; +import ru.practicum.shareit.user.dto.UserUpdateDto; +import ru.practicum.shareit.user.service.UserService; -/** - * TODO Sprint add-controllers. - */ +import java.util.Collection; + +@Validated @RestController -@RequestMapping(path = "/users") +@RequiredArgsConstructor +@RequestMapping("/users") public class UserController { + private final UserService userService; + private final UserMapper userMapper; + + @PostMapping + public UserDto create(@RequestBody @Validated UserCreateDto userDto) { + User user = userMapper.createDtoToModel(userDto); + return userMapper.modelToDto(userService.create(user)); + } + + @PatchMapping("/{userId}") + public UserDto update(@PathVariable Long userId, + @RequestBody @Validated UserUpdateDto userDto) { + User user = userMapper.updateDtoToModel(userDto, userId); + return userMapper.modelToDto(userService.update(user)); + } + + @GetMapping("/{userId}") + public UserDto getUserById(@PathVariable Long userId) { + return userMapper.modelToDto(userService.getUserById(userId)); + } + + @GetMapping() + public Collection getAll() { + return userMapper.listModelToDto(userService.getAll()); + } + + @DeleteMapping("/{userId}") + public void deleteUser(@PathVariable long userId) { + userService.deleteUser(userId); + } + } 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 0000000..0d28209 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/user/UserMapper.java @@ -0,0 +1,46 @@ +package ru.practicum.shareit.user; + +import org.springframework.stereotype.Component; +import ru.practicum.shareit.user.dto.UserCreateDto; +import ru.practicum.shareit.user.dto.UserDto; +import ru.practicum.shareit.user.dto.UserUpdateDto; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +@Component +public class UserMapper { + + public User createDtoToModel(UserCreateDto dto) { + return User.builder() + .name(dto.getName()) + .email(dto.getEmail()) + .build(); + } + + public User updateDtoToModel(UserUpdateDto dto, Long userId) { + return User.builder() + .id(userId) + .name(dto.getName()) + .email(dto.getEmail()) + .build(); + } + + public UserDto modelToDto(User user) { + return UserDto.builder() + .id(user.getId()) + .name(user.getName()) + .email(user.getEmail()) + .build(); + } + + public Collection listModelToDto(Collection users) { + List list = new ArrayList<>(); + for (User user : users) { + list.add(modelToDto(user)); + } + return list; + } + +} diff --git a/src/main/java/ru/practicum/shareit/user/dto/UserCreateDto.java b/src/main/java/ru/practicum/shareit/user/dto/UserCreateDto.java new file mode 100644 index 0000000..605a377 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/user/dto/UserCreateDto.java @@ -0,0 +1,16 @@ +package ru.practicum.shareit.user.dto; + +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UserCreateDto { + @NotNull + private String name; + @Email + @NotNull + @NotBlank + private String email; +} 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 0000000..ac7278e --- /dev/null +++ b/src/main/java/ru/practicum/shareit/user/dto/UserDto.java @@ -0,0 +1,12 @@ +package ru.practicum.shareit.user.dto; + +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class UserDto { + private Long id; + private String name; + private String email; +} diff --git a/src/main/java/ru/practicum/shareit/user/dto/UserUpdateDto.java b/src/main/java/ru/practicum/shareit/user/dto/UserUpdateDto.java new file mode 100644 index 0000000..96e7214 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/user/dto/UserUpdateDto.java @@ -0,0 +1,11 @@ +package ru.practicum.shareit.user.dto; + +import jakarta.validation.constraints.Email; +import lombok.Data; + +@Data +public class UserUpdateDto { + private String name; + @Email + private String email; +} 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 0000000..87f8453 --- /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.User; + +import java.util.Collection; + +public interface UserRepository { + User create(User user); + + User update(User user); + + User getUserById(long id); + + Collection getAll(); + + void deleteUser(long userId); +} diff --git a/src/main/java/ru/practicum/shareit/user/repository/UserRepositoryImpl.java b/src/main/java/ru/practicum/shareit/user/repository/UserRepositoryImpl.java new file mode 100644 index 0000000..dce0733 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/user/repository/UserRepositoryImpl.java @@ -0,0 +1,79 @@ +package ru.practicum.shareit.user.repository; + +import org.springframework.stereotype.Component; +import ru.practicum.shareit.exception.ConflictException; +import ru.practicum.shareit.exception.NotFoundException; +import ru.practicum.shareit.user.User; + +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class UserRepositoryImpl implements UserRepository { + private long id = 1L; + private final Map userMap = new HashMap<>(); + + public long getNextId() { + return id++; + } + + @Override + public User create(User user) { + checkCloneEmail(user.getEmail()); + long id = getNextId(); + user.setId(id); + userMap.put(id, user); + return user; + } + + @Override + public User update(User user) { + long id = user.getId(); + checkUserId(id); + User userSaved = userMap.get(id); + + if (user.getName() != null) { + userSaved.setName(user.getName()); + } + if (user.getEmail() != null) { + String email = user.getEmail(); + checkCloneEmail(email); + userSaved.setEmail(email); + } + return userSaved; + } + + @Override + public User getUserById(long id) { + checkUserId(id); + return userMap.get(id); + } + + @Override + public Collection getAll() { + return userMap.values(); + } + + @Override + public void deleteUser(long userId) { + userMap.remove(userId); + } + + private void checkCloneEmail(String email) { + List users = userMap.values().stream() + .filter(user -> user.getEmail().equals(email)) + .toList(); + if (!users.isEmpty()) { + throw new ConflictException("email уже существует"); + } + } + + private void checkUserId(long id) { + if (!userMap.containsKey(id)) { + throw new NotFoundException("User отсутствует"); + } + } + +} 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 0000000..fbae19e --- /dev/null +++ b/src/main/java/ru/practicum/shareit/user/service/UserService.java @@ -0,0 +1,17 @@ +package ru.practicum.shareit.user.service; + +import ru.practicum.shareit.user.User; + +import java.util.Collection; + +public interface UserService { + User create(User user); + + User update(User user); + + User getUserById(long id); + + Collection getAll(); + + void deleteUser(long userId); +} 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 0000000..2a99e6a --- /dev/null +++ b/src/main/java/ru/practicum/shareit/user/service/UserServiceImpl.java @@ -0,0 +1,39 @@ +package ru.practicum.shareit.user.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import ru.practicum.shareit.user.User; +import ru.practicum.shareit.user.repository.UserRepository; + +import java.util.Collection; + +@Service +@RequiredArgsConstructor +public class UserServiceImpl implements UserService { + private final UserRepository userRepository; + + @Override + public User create(User user) { + return userRepository.create(user); + } + + @Override + public User update(User user) { + return userRepository.update(user); + } + + @Override + public User getUserById(long id) { + return userRepository.getUserById(id); + } + + @Override + public Collection getAll() { + return userRepository.getAll(); + } + + @Override + public void deleteUser(long userId) { + userRepository.deleteUser(userId); + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index b9e5d4b..1a133c3 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -2,6 +2,8 @@ spring.jpa.hibernate.ddl-auto=none spring.jpa.properties.hibernate.format_sql=true spring.sql.init.mode=always +logging.level.org.zalando.logbook= TRACE + logging.level.org.springframework.orm.jpa=INFO logging.level.org.springframework.transaction=INFO logging.level.org.springframework.transaction.interceptor=TRACE