-
Notifications
You must be signed in to change notification settings - Fork 71
BJS2-77992. Добавлено создание цели #2969
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 8 commits
f529c50
fbf4321
972ce80
323e88d
9d1d6f2
5e767bb
91a5a5b
e081b0e
242860e
4a7c384
d095715
b4ce6a0
c2148de
38546a0
ac6a6e1
1b05279
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| package school.faang.user_service.controller.goal; | ||
|
|
||
| import jakarta.validation.Valid; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.http.ResponseEntity; | ||
| import org.springframework.web.bind.annotation.DeleteMapping; | ||
| import org.springframework.web.bind.annotation.GetMapping; | ||
| import org.springframework.web.bind.annotation.PathVariable; | ||
| import org.springframework.web.bind.annotation.PostMapping; | ||
| import org.springframework.web.bind.annotation.PutMapping; | ||
| import org.springframework.web.bind.annotation.RequestBody; | ||
| import org.springframework.web.bind.annotation.RequestMapping; | ||
| import org.springframework.web.bind.annotation.RestController; | ||
| import org.springframework.web.servlet.support.ServletUriComponentsBuilder; | ||
| import school.faang.user_service.entity.filter.GoalFilterDto; | ||
| import school.faang.user_service.entity.goal.Goal; | ||
| import school.faang.user_service.entity.goal.dto.GoalDto; | ||
| import school.faang.user_service.entity.goal.mapper.GoalMapper; | ||
| import school.faang.user_service.service.GoalService; | ||
|
|
||
| import java.net.URI; | ||
| import java.util.List; | ||
|
|
||
| @RestController | ||
| @RequestMapping("/api/v1/goals") | ||
| @RequiredArgsConstructor | ||
| public class GoalController { | ||
|
|
||
| private final GoalService goalService; | ||
| private final GoalMapper goalMapper; | ||
|
|
||
| @GetMapping("/{goalId}") | ||
| public ResponseEntity<GoalDto> getGoal(@PathVariable long goalId) { | ||
| Goal goal = goalService.getGoalById(goalId); | ||
| return ResponseEntity.ok(goalMapper.toGoalDto(goal)); | ||
| } | ||
|
|
||
| @GetMapping | ||
| public ResponseEntity<List<GoalDto>> getGoals(@RequestBody GoalFilterDto goalFilterDto) { | ||
| List<Goal> filteredGoals = goalService.getGoalsByFilter(goalFilterDto); | ||
| return ResponseEntity.ok(goalMapper.toGoalDtoList(filteredGoals)); | ||
| } | ||
|
|
||
| @GetMapping("/{parentId}/subGoals") | ||
| public ResponseEntity<List<GoalDto>> getSubGoals(@PathVariable long parentId, @RequestBody GoalFilterDto goalFilterDto) { | ||
FROLOV-KI marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| List<Goal> filteredSubGoals = goalService.getSubGoalsByFilter(parentId, goalFilterDto); | ||
| return ResponseEntity.ok(goalMapper.toGoalDtoList(filteredSubGoals)); | ||
| } | ||
|
|
||
| @PostMapping | ||
| public ResponseEntity<GoalDto> createGoal(@RequestBody @Valid GoalDto goalDto) { | ||
FROLOV-KI marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| Goal createdGoal = goalService.createGoal( | ||
| goalMapper.toGoal(goalDto), | ||
| goalDto.skillsId(), | ||
| goalDto.parentId() | ||
| ); | ||
|
|
||
| URI location = ServletUriComponentsBuilder | ||
| .fromCurrentRequest() | ||
| .path("/{id}") | ||
| .buildAndExpand(createdGoal.getId()) | ||
| .toUri(); | ||
FROLOV-KI marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| return ResponseEntity.created(location) | ||
| .body(goalMapper.toGoalDto(createdGoal)); | ||
| } | ||
|
|
||
| @PutMapping("/{goalId}") | ||
FROLOV-KI marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| public ResponseEntity<GoalDto> updateGoal(@PathVariable long goalId, @RequestBody @Valid GoalDto goalDto) { | ||
| Goal createdGoal = goalService.update( | ||
| goalId, | ||
| goalMapper.toGoal(goalDto), | ||
| goalDto.skillsId() | ||
| ); | ||
| return ResponseEntity.ok(goalMapper.toGoalDto(createdGoal)); | ||
| } | ||
|
|
||
| @DeleteMapping("/{goalId}") | ||
| public ResponseEntity<Void> deleteGoal(@PathVariable long goalId) { | ||
| goalService.delete(goalId); | ||
| return ResponseEntity.ok().build(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| package school.faang.user_service.entity.error; | ||
|
|
||
| public record DefaultErrorResponse(String code, String message) {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| package school.faang.user_service.entity.filter; | ||
|
|
||
| import com.fasterxml.jackson.annotation.JsonInclude; | ||
| import school.faang.user_service.entity.goal.GoalStatus; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| @JsonInclude(JsonInclude.Include.NON_EMPTY) | ||
| public record GoalFilterDto( | ||
| List<Long> usersId, | ||
| String title, | ||
| GoalStatus status, | ||
| List<Long> skillsId | ||
| ) { | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| package school.faang.user_service.entity.goal.dto; | ||
|
|
||
| import jakarta.validation.constraints.NotBlank; | ||
| import school.faang.user_service.entity.goal.GoalStatus; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| public record GoalDto( | ||
| Long id, | ||
| String description, | ||
| Long parentId, | ||
| @NotBlank(message = "Empty goal title not allowed!") String title, | ||
FROLOV-KI marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| GoalStatus status, | ||
| List<Long> skillsId | ||
| ) {} | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| package school.faang.user_service.entity.goal.mapper; | ||
|
|
||
| import org.mapstruct.BeanMapping; | ||
| import org.mapstruct.Mapper; | ||
| import org.mapstruct.Mapping; | ||
| import org.mapstruct.MappingTarget; | ||
| import org.mapstruct.NullValuePropertyMappingStrategy; | ||
| import school.faang.user_service.entity.Skill; | ||
| import school.faang.user_service.entity.goal.Goal; | ||
| import school.faang.user_service.entity.goal.dto.GoalDto; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| @Mapper(componentModel = "spring") | ||
| public interface GoalMapper { | ||
FROLOV-KI marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| @Mapping(source = "parent.id", target = "parentId") | ||
| @Mapping(target = "skillsId", expression = "java(mapSkillsToIds(goal.getSkillsToAchieve()))") | ||
| GoalDto toGoalDto(Goal goal); | ||
|
|
||
| @Mapping(target = "parent", ignore = true) | ||
| @Mapping(target = "skillsToAchieve", ignore = true) | ||
| @Mapping(target = "deadline", ignore = true) | ||
| @Mapping(target = "createdAt", ignore = true) | ||
| @Mapping(target = "updatedAt", ignore = true) | ||
| @Mapping(target = "mentor", ignore = true) | ||
| @Mapping(target = "invitations", ignore = true) | ||
| @Mapping(target = "users", ignore = true) | ||
| Goal toGoal(GoalDto goalDto); | ||
|
|
||
| @Mapping(target = "id", ignore = true) | ||
| @Mapping(target = "parent", ignore = true) | ||
| @Mapping(target = "skillsToAchieve", ignore = true) | ||
| @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) | ||
| void update(@MappingTarget Goal goal, Goal goalData); | ||
FROLOV-KI marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| default List<Long> mapSkillsToIds(List<Skill> skills) { | ||
| return skills.stream() | ||
| .map(Skill::getId) | ||
| .toList(); | ||
| } | ||
|
|
||
| List<GoalDto> toGoalDtoList(List<Goal> goals); | ||
|
|
||
| List<Goal> toGoalList(List<GoalDto> goalsDto); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| package school.faang.user_service.exception.goal; | ||
|
|
||
| public class GoalNotExistException extends RuntimeException { | ||
|
|
||
| public GoalNotExistException(long goalId) { | ||
| super("Goal with id %d not exist".formatted(goalId)); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| package school.faang.user_service.exception.goal; | ||
|
|
||
| public class MaxActiveGoalPerUserException extends RuntimeException { | ||
|
|
||
| public MaxActiveGoalPerUserException(Long userId, int goalLimit) { | ||
| super("User with id %s reach max goals active limit of %d".formatted(userId, goalLimit)); | ||
20cognosce marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| package school.faang.user_service.exception.goal; | ||
|
|
||
| public class UpdateComleteGoalException extends RuntimeException { | ||
|
|
||
| public UpdateComleteGoalException(long goalId) { | ||
| super("Goal with id %d is complete. Update not allowed.".formatted(goalId)); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| package school.faang.user_service.exception.goal; | ||
|
|
||
| public class UpdateGoalWithActiveSubGoalsException extends RuntimeException { | ||
|
|
||
| public UpdateGoalWithActiveSubGoalsException(long goalId, String activeSubGoalsId) { | ||
| super("Goal with id %d have active sub goals [%s]. Update not allowed.".formatted(goalId, activeSubGoalsId)); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| package school.faang.user_service.exception.goal; | ||
|
|
||
| public class UserNotGoalOwnerException extends RuntimeException { | ||
|
|
||
| public UserNotGoalOwnerException(long userId, long goalId) { | ||
| super("User with id %d not the owner of goal with id %d".formatted(userId, goalId)); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| package school.faang.user_service.exception.skill; | ||
|
|
||
| public class AddedSkillNotExistException extends RuntimeException { | ||
|
|
||
| public AddedSkillNotExistException(String skillsId) { | ||
| super("Contains skills [%s] that not exist!!".formatted(skillsId)); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| package school.faang.user_service.filter; | ||
|
|
||
| public interface Filter<T, P> { | ||
|
|
||
| boolean isApplicable(T filterDto); | ||
|
|
||
| P apply(P filteredData, T filterDto); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| package school.faang.user_service.filter.goal; | ||
|
|
||
| import school.faang.user_service.entity.filter.GoalFilterDto; | ||
| import school.faang.user_service.entity.goal.Goal; | ||
| import school.faang.user_service.filter.Filter; | ||
|
|
||
| import java.util.stream.Stream; | ||
|
|
||
| public interface GoalFilter extends Filter<GoalFilterDto, Stream<Goal>> {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| package school.faang.user_service.filter.goal; | ||
|
|
||
| import org.springframework.stereotype.Component; | ||
| import school.faang.user_service.entity.filter.GoalFilterDto; | ||
| import school.faang.user_service.entity.goal.Goal; | ||
|
|
||
| import java.util.Objects; | ||
| import java.util.stream.Stream; | ||
|
|
||
| @Component | ||
| public class GoalFilterBySkills implements GoalFilter { | ||
|
|
||
| @Override | ||
| public boolean isApplicable(GoalFilterDto filterDto) { | ||
| return Objects.nonNull(filterDto.skillsId()) && !filterDto.skillsId().isEmpty(); | ||
| } | ||
|
|
||
| @Override | ||
| public Stream<Goal> apply(Stream<Goal> filteredData, GoalFilterDto filterDto) { | ||
| return filteredData.filter(goal -> | ||
| goal.getSkillsToAchieve() | ||
| .stream() | ||
|
||
| .anyMatch(skill -> filterDto.skillsId().contains(skill.getId())) | ||
| ); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| package school.faang.user_service.filter.goal; | ||
|
|
||
| import org.springframework.stereotype.Component; | ||
| import school.faang.user_service.entity.filter.GoalFilterDto; | ||
| import school.faang.user_service.entity.goal.Goal; | ||
|
|
||
| import java.util.Objects; | ||
| import java.util.stream.Stream; | ||
|
|
||
| @Component | ||
| public class GoalFilterByStatus implements GoalFilter { | ||
|
|
||
| @Override | ||
| public boolean isApplicable(GoalFilterDto filterDto) { | ||
| return Objects.nonNull(filterDto.status()); | ||
| } | ||
|
|
||
| @Override | ||
| public Stream<Goal> apply(Stream<Goal> filteredData, GoalFilterDto filterDto) { | ||
| return filteredData.filter(goal -> goal.getStatus().equals(filterDto.status())); | ||
|
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| package school.faang.user_service.filter.goal; | ||
|
|
||
| import org.springframework.stereotype.Component; | ||
| import school.faang.user_service.entity.filter.GoalFilterDto; | ||
| import school.faang.user_service.entity.goal.Goal; | ||
|
|
||
| import java.util.Objects; | ||
| import java.util.stream.Stream; | ||
|
|
||
| @Component | ||
| public class GoalFilterByTitle implements GoalFilter { | ||
|
|
||
| @Override | ||
| public boolean isApplicable(GoalFilterDto filterDto) { | ||
| return Objects.nonNull(filterDto.title()); | ||
| } | ||
|
|
||
| @Override | ||
| public Stream<Goal> apply(Stream<Goal> filteredData, GoalFilterDto filterDto) { | ||
| return filteredData.filter(goal -> goal.getTitle() | ||
| .toLowerCase() | ||
|
||
| .contains(filterDto.title().toLowerCase())); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| package school.faang.user_service.filter.goal; | ||
|
|
||
| import org.springframework.stereotype.Component; | ||
| import school.faang.user_service.entity.filter.GoalFilterDto; | ||
| import school.faang.user_service.entity.goal.Goal; | ||
|
|
||
| import java.util.Objects; | ||
| import java.util.stream.Stream; | ||
|
|
||
| @Component | ||
| public class GoalFilterByUsers implements GoalFilter { | ||
|
|
||
| @Override | ||
| public boolean isApplicable(GoalFilterDto filterDto) { | ||
| return Objects.nonNull(filterDto.usersId()) && !filterDto.usersId().isEmpty(); | ||
| } | ||
|
|
||
| @Override | ||
| public Stream<Goal> apply(Stream<Goal> filteredData, GoalFilterDto filterDto) { | ||
| return filteredData.filter(goal -> | ||
| goal.getUsers() | ||
| .stream() | ||
|
||
| .anyMatch(user -> filterDto.usersId().contains(user.getId())) | ||
| ); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.