Skip to content

Commit 92f9497

Browse files
authored
BJS2-77358 Создание и настройка скиллов (#2967)
* Created custom exception DataValidationException. Created new packages with DTO and controller with service. Also created a new mapper interface SkillMapper with methods for mapping. * Added new method in SkillController. New method acquireSkillFromOffers in SkillService. * Fixed few issues with wrappers. * Added exceptions in acquireSkillFromOffers. Mapping to UserSkillGuarantee now is in default method in SkillMapper. * Moved validateSkill in SkillService for cleaner Controller. Added annotations for all methods from controller for rest requests.
1 parent 9cd3d43 commit 92f9497

File tree

6 files changed

+189
-0
lines changed

6 files changed

+189
-0
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package school.faang.user_service.controller;
2+
3+
import lombok.RequiredArgsConstructor;
4+
import lombok.extern.slf4j.Slf4j;
5+
import org.springframework.web.bind.annotation.GetMapping;
6+
import org.springframework.web.bind.annotation.PostMapping;
7+
import org.springframework.web.bind.annotation.RequestBody;
8+
import org.springframework.web.bind.annotation.RequestMapping;
9+
import org.springframework.web.bind.annotation.RequestParam;
10+
import org.springframework.web.bind.annotation.RestController;
11+
import school.faang.user_service.dto.skill.SkillCandidateDto;
12+
import school.faang.user_service.dto.skill.SkillDto;
13+
import school.faang.user_service.service.SkillService;
14+
15+
import java.util.List;
16+
17+
@Slf4j
18+
@RestController
19+
@RequestMapping("/skills")
20+
@RequiredArgsConstructor
21+
public class SkillController {
22+
private final SkillService skillService;
23+
24+
@PostMapping
25+
public SkillDto create(@RequestBody SkillDto skill) {
26+
return skillService.create(skill);
27+
}
28+
29+
@GetMapping(params = "userId")
30+
public List<SkillDto> getUserSkills(@RequestParam Long userId) {
31+
return skillService.getUserSkills(userId);
32+
}
33+
34+
@GetMapping(value = "/offered", params = "userId")
35+
public List<SkillCandidateDto> getOfferedSkills(@RequestParam long userId) {
36+
return skillService.getOfferedSkills(userId);
37+
}
38+
39+
@GetMapping(value = "/acquire", params = {"skillId", "userId"})
40+
public SkillDto acquireSkillFromOffers(@RequestParam long skillId, @RequestParam long userId) {
41+
return skillService.acquireSkillFromOffers(skillId, userId);
42+
}
43+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package school.faang.user_service.dto.skill;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Data;
5+
6+
@Data
7+
@AllArgsConstructor
8+
public class SkillCandidateDto {
9+
private SkillDto skill;
10+
private Long offersAmount;
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package school.faang.user_service.dto.skill;
2+
3+
import lombok.Data;
4+
import lombok.NoArgsConstructor;
5+
6+
@Data
7+
@NoArgsConstructor
8+
public class SkillDto {
9+
private Long id;
10+
private String title;
11+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package school.faang.user_service.exception;
2+
3+
public class DataValidationException extends RuntimeException {
4+
public DataValidationException(String message) {
5+
super(message);
6+
}
7+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package school.faang.user_service.mapper;
2+
3+
import org.mapstruct.Mapper;
4+
import school.faang.user_service.dto.skill.SkillCandidateDto;
5+
import school.faang.user_service.dto.skill.SkillDto;
6+
import school.faang.user_service.entity.Skill;
7+
import school.faang.user_service.entity.UserSkillGuarantee;
8+
import school.faang.user_service.entity.recommendation.SkillOffer;
9+
import school.faang.user_service.repository.UserRepository;
10+
11+
@Mapper(componentModel = "spring")
12+
public interface SkillMapper {
13+
Skill toEntity(SkillDto skillDto);
14+
15+
SkillDto toDto(Skill skill);
16+
17+
default SkillCandidateDto toSkillCandidateDto(SkillDto skillDto, long count) {
18+
return new SkillCandidateDto(skillDto, count);
19+
}
20+
21+
default UserSkillGuarantee toUserSkillGuarantee(UserRepository userRepository,
22+
SkillOffer offer,
23+
long userId) {
24+
return UserSkillGuarantee.builder()
25+
.user(userRepository.getReferenceById(userId))
26+
.skill(offer.getSkill())
27+
.guarantor(offer.getRecommendation().getAuthor())
28+
.build();
29+
}
30+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package school.faang.user_service.service;
2+
3+
import lombok.RequiredArgsConstructor;
4+
import lombok.extern.slf4j.Slf4j;
5+
import org.springframework.stereotype.Service;
6+
import org.springframework.transaction.annotation.Transactional;
7+
import school.faang.user_service.dto.skill.SkillCandidateDto;
8+
import school.faang.user_service.dto.skill.SkillDto;
9+
import school.faang.user_service.entity.Skill;
10+
import school.faang.user_service.entity.UserSkillGuarantee;
11+
import school.faang.user_service.entity.recommendation.SkillOffer;
12+
import school.faang.user_service.exception.DataValidationException;
13+
import school.faang.user_service.mapper.SkillMapper;
14+
import school.faang.user_service.repository.SkillRepository;
15+
import school.faang.user_service.repository.UserRepository;
16+
import school.faang.user_service.repository.UserSkillGuaranteeRepository;
17+
import school.faang.user_service.repository.recommendation.SkillOfferRepository;
18+
19+
import java.util.List;
20+
import java.util.Objects;
21+
import java.util.function.Function;
22+
import java.util.stream.Collectors;
23+
24+
@Slf4j
25+
@Service
26+
@RequiredArgsConstructor
27+
public class SkillService {
28+
private final SkillRepository skillRepository;
29+
private final SkillMapper skillMapper;
30+
private final SkillOfferRepository offerRepository;
31+
private final UserSkillGuaranteeRepository guaranteeRepository;
32+
private final UserRepository userRepository;
33+
private static final int MIN_SKILL_OFFERS = 3;
34+
35+
public SkillDto create(SkillDto skill) {
36+
validateSkill(skill);
37+
if (!skillRepository.existsByTitle(skill.getTitle())) {
38+
Skill newSkill = skillRepository.save(skillMapper.toEntity(skill));
39+
return skillMapper.toDto(newSkill);
40+
}
41+
throw new DataValidationException("Skill " + skill.getTitle() + " already exists!");
42+
}
43+
44+
public List<SkillCandidateDto> getOfferedSkills(long userId) {
45+
return skillRepository.findSkillsOfferedToUser(userId).stream()
46+
.map(skillMapper::toDto)
47+
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
48+
.entrySet().stream()
49+
.map(entry -> skillMapper.toSkillCandidateDto(entry.getKey(), entry.getValue()))
50+
.collect(Collectors.toList());
51+
}
52+
53+
@Transactional
54+
public SkillDto acquireSkillFromOffers(long skillId, long userId) {
55+
if (skillRepository.findUserSkill(skillId, userId).isPresent()) {
56+
throw new DataValidationException("User already have this skill!");
57+
}
58+
if (offerRepository.findAllOffersOfSkill(skillId, userId).size() < MIN_SKILL_OFFERS) {
59+
throw new DataValidationException("Not enough skill offers!");
60+
}
61+
skillRepository.assignSkillToUser(skillId, userId);
62+
for (SkillOffer offer : offerRepository.findAllOffersOfSkill(skillId, userId)) {
63+
UserSkillGuarantee skillGuarantor =
64+
skillMapper.toUserSkillGuarantee(userRepository, offer, userId);
65+
guaranteeRepository.save(skillGuarantor);
66+
}
67+
return skillMapper.toDto(skillRepository.getReferenceById(skillId));
68+
}
69+
70+
public List<SkillDto> getUserSkills(long userId) {
71+
return skillRepository.findAllByUserId(userId)
72+
.stream()
73+
.map(skillMapper::toDto)
74+
.toList();
75+
}
76+
77+
private void validateSkill(SkillDto skill) {
78+
if (Objects.isNull(skill)) {
79+
log.error("The SkillDto submitted in method validateSkill is null!");
80+
throw new DataValidationException("SkillDto from argument is null!");
81+
}
82+
if (skill.getTitle() == null || skill.getTitle().isBlank()) {
83+
log.error("The SkillDto submitted to method validateSkill doesn't have a name!");
84+
throw new DataValidationException("SkillDto has no name!");
85+
}
86+
}
87+
}

0 commit comments

Comments
 (0)