Skip to content
Merged
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,43 @@
package school.faang.user_service.controller;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import school.faang.user_service.dto.skill.SkillCandidateDto;
import school.faang.user_service.dto.skill.SkillDto;
import school.faang.user_service.service.SkillService;

import java.util.List;

@Slf4j
@RestController
@RequestMapping("/skills")
@RequiredArgsConstructor
public class SkillController {
private final SkillService skillService;

@PostMapping
public SkillDto create(@RequestBody SkillDto skill) {
return skillService.create(skill);
}

@GetMapping(params = "userId")
public List<SkillDto> getUserSkills(@RequestParam Long userId) {
return skillService.getUserSkills(userId);
}

@GetMapping(value = "/offered", params = "userId")
public List<SkillCandidateDto> getOfferedSkills(@RequestParam long userId) {
return skillService.getOfferedSkills(userId);
}

@GetMapping(value = "/acquire", params = {"skillId", "userId"})
public SkillDto acquireSkillFromOffers(@RequestParam long skillId, @RequestParam long userId) {
return skillService.acquireSkillFromOffers(skillId, userId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package school.faang.user_service.dto.skill;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class SkillCandidateDto {
private SkillDto skill;
private Long offersAmount;
}
11 changes: 11 additions & 0 deletions src/main/java/school/faang/user_service/dto/skill/SkillDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package school.faang.user_service.dto.skill;

import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
public class SkillDto {
private Long id;
private String title;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package school.faang.user_service.exception;

public class DataValidationException extends RuntimeException {
public DataValidationException(String message) {
super(message);
}
}
30 changes: 30 additions & 0 deletions src/main/java/school/faang/user_service/mapper/SkillMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package school.faang.user_service.mapper;

import org.mapstruct.Mapper;
import school.faang.user_service.dto.skill.SkillCandidateDto;
import school.faang.user_service.dto.skill.SkillDto;
import school.faang.user_service.entity.Skill;
import school.faang.user_service.entity.UserSkillGuarantee;
import school.faang.user_service.entity.recommendation.SkillOffer;
import school.faang.user_service.repository.UserRepository;

@Mapper(componentModel = "spring")
public interface SkillMapper {
Skill toEntity(SkillDto skillDto);

SkillDto toDto(Skill skill);

default SkillCandidateDto toSkillCandidateDto(SkillDto skillDto, long count) {
return new SkillCandidateDto(skillDto, count);
}

default UserSkillGuarantee toUserSkillGuarantee(UserRepository userRepository,
SkillOffer offer,
long userId) {
return UserSkillGuarantee.builder()
.user(userRepository.getReferenceById(userId))
.skill(offer.getSkill())
.guarantor(offer.getRecommendation().getAuthor())
.build();
}
}
87 changes: 87 additions & 0 deletions src/main/java/school/faang/user_service/service/SkillService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package school.faang.user_service.service;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import school.faang.user_service.dto.skill.SkillCandidateDto;
import school.faang.user_service.dto.skill.SkillDto;
import school.faang.user_service.entity.Skill;
import school.faang.user_service.entity.UserSkillGuarantee;
import school.faang.user_service.entity.recommendation.SkillOffer;
import school.faang.user_service.exception.DataValidationException;
import school.faang.user_service.mapper.SkillMapper;
import school.faang.user_service.repository.SkillRepository;
import school.faang.user_service.repository.UserRepository;
import school.faang.user_service.repository.UserSkillGuaranteeRepository;
import school.faang.user_service.repository.recommendation.SkillOfferRepository;

import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class SkillService {
private final SkillRepository skillRepository;
private final SkillMapper skillMapper;
private final SkillOfferRepository offerRepository;
private final UserSkillGuaranteeRepository guaranteeRepository;
private final UserRepository userRepository;
private static final int MIN_SKILL_OFFERS = 3;

public SkillDto create(SkillDto skill) {
validateSkill(skill);
if (!skillRepository.existsByTitle(skill.getTitle())) {
Skill newSkill = skillRepository.save(skillMapper.toEntity(skill));
return skillMapper.toDto(newSkill);
}
throw new DataValidationException("Skill " + skill.getTitle() + " already exists!");
}

public List<SkillCandidateDto> getOfferedSkills(long userId) {
return skillRepository.findSkillsOfferedToUser(userId).stream()
.map(skillMapper::toDto)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet().stream()
.map(entry -> skillMapper.toSkillCandidateDto(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
}

@Transactional
public SkillDto acquireSkillFromOffers(long skillId, long userId) {
if (skillRepository.findUserSkill(skillId, userId).isPresent()) {
throw new DataValidationException("User already have this skill!");
}
if (offerRepository.findAllOffersOfSkill(skillId, userId).size() < MIN_SKILL_OFFERS) {
throw new DataValidationException("Not enough skill offers!");
}
skillRepository.assignSkillToUser(skillId, userId);
for (SkillOffer offer : offerRepository.findAllOffersOfSkill(skillId, userId)) {
UserSkillGuarantee skillGuarantor =
skillMapper.toUserSkillGuarantee(userRepository, offer, userId);
guaranteeRepository.save(skillGuarantor);
}
return skillMapper.toDto(skillRepository.getReferenceById(skillId));
}

public List<SkillDto> getUserSkills(long userId) {
return skillRepository.findAllByUserId(userId)
.stream()
.map(skillMapper::toDto)
.toList();
}

private void validateSkill(SkillDto skill) {
if (Objects.isNull(skill)) {
log.error("The SkillDto submitted in method validateSkill is null!");
throw new DataValidationException("SkillDto from argument is null!");
}
if (skill.getTitle() == null || skill.getTitle().isBlank()) {
log.error("The SkillDto submitted to method validateSkill doesn't have a name!");
throw new DataValidationException("SkillDto has no name!");
}
}
}