diff --git a/src/main/java/com/provedcode/kudos/service/KudosService.java b/src/main/java/com/provedcode/kudos/service/KudosService.java index 051b126..595396e 100644 --- a/src/main/java/com/provedcode/kudos/service/KudosService.java +++ b/src/main/java/com/provedcode/kudos/service/KudosService.java @@ -89,10 +89,10 @@ public KudosAmountWithSponsor getProofKudos(long proofId, Authentication authent .collect(Collectors.toMap( Kudos::getAmount, proof -> proof.getSponsor() != null - ? sponsorMapper.toDto(proof.getSponsor()) - : SponsorDTO.builder().build(), - (prev, next) -> next, - HashMap::new)); + ? sponsorMapper.toDto(proof.getSponsor()) + : SponsorDTO.builder().build(), + (prev, next) -> next, + HashMap::new)); skillsMap.put(skill, kudosFromSponsor); }); return KudosAmountWithSponsor.builder() @@ -127,9 +127,9 @@ public void addKudosToProof(long proofId, SetAmountKudos amountOfKudoses, Authen if (sponsor.getAmountKudos() < obtainedAmount) { throw new ResponseStatusException(FORBIDDEN, "The sponsor cannot give more kudos than he has"); } - if (obtainedAmount % talentProof.getProofSkills().size() != 0) { - throw new ResponseStatusException(BAD_REQUEST, - "Sponsor cannot add amount of kudos that multiple of amount of skills"); + Long modula = obtainedAmount % talentProof.getProofSkills().size(); + if (modula != 0) { + obtainedAmount -= modula; } sponsor.setAmountKudos(sponsor.getAmountKudos() - obtainedAmount); diff --git a/src/main/java/com/provedcode/talent/controller/TalentController.java b/src/main/java/com/provedcode/talent/controller/TalentController.java index ecff1f5..3c0b319 100644 --- a/src/main/java/com/provedcode/talent/controller/TalentController.java +++ b/src/main/java/com/provedcode/talent/controller/TalentController.java @@ -4,6 +4,7 @@ import com.provedcode.talent.model.dto.FullTalentDTO; import com.provedcode.talent.model.dto.ShortTalentDTO; import com.provedcode.talent.model.dto.SkillIdDTO; +import com.provedcode.talent.model.dto.StatisticsDTO; import com.provedcode.talent.model.request.EditTalent; import com.provedcode.talent.service.TalentService; import com.provedcode.user.model.dto.SessionInfoDTO; @@ -90,4 +91,10 @@ Page getFilteredBySkillsTalents(@RequestParam(value = "page", de return talentService.getFilteredBySkillsTalentsPage(page, size, filterBy).map(talentMapper::talentToShortTalentDTO); } + @PreAuthorize("hasRole('TALENT')") + @GetMapping("v5/talents/{talent-id}/statistics") + StatisticsDTO getStatisticsForTalent(@PathVariable("talent-id") long talentId, + Authentication authentication) { + return talentService.getStatisticsForTalent(talentId, authentication); + } } \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/controller/TalentProofController.java b/src/main/java/com/provedcode/talent/controller/TalentProofController.java index ff89e09..775edf6 100644 --- a/src/main/java/com/provedcode/talent/controller/TalentProofController.java +++ b/src/main/java/com/provedcode/talent/controller/TalentProofController.java @@ -3,7 +3,6 @@ import com.provedcode.talent.mapper.TalentProofMapper; import com.provedcode.talent.model.dto.FullProofDTO; import com.provedcode.talent.model.dto.ProofDTO; -import com.provedcode.talent.model.dto.StatusDTO; import com.provedcode.talent.model.request.AddProof; import com.provedcode.talent.service.TalentProofService; import com.provedcode.util.annotations.doc.controller.proof.*; diff --git a/src/main/java/com/provedcode/talent/model/dto/StatisticsDTO.java b/src/main/java/com/provedcode/talent/model/dto/StatisticsDTO.java new file mode 100644 index 0000000..1914887 --- /dev/null +++ b/src/main/java/com/provedcode/talent/model/dto/StatisticsDTO.java @@ -0,0 +1,13 @@ +package com.provedcode.talent.model.dto; + +import lombok.Builder; + +import java.util.Map; + +@Builder +public record StatisticsDTO( + Long allKudosOnTalent, + Map skillWithLargestNumberOfKudos, + Map proofWithLargestNumberOfKudos +) { +} diff --git a/src/main/java/com/provedcode/talent/service/TalentService.java b/src/main/java/com/provedcode/talent/service/TalentService.java index 775b78a..d89b82d 100644 --- a/src/main/java/com/provedcode/talent/service/TalentService.java +++ b/src/main/java/com/provedcode/talent/service/TalentService.java @@ -1,7 +1,12 @@ package com.provedcode.talent.service; import com.provedcode.config.PageProperties; +import com.provedcode.kudos.model.entity.Kudos; +import com.provedcode.talent.mapper.TalentProofMapper; +import com.provedcode.talent.model.dto.ProofDTO; +import com.provedcode.talent.model.dto.SkillDTO; import com.provedcode.talent.model.dto.SkillIdDTO; +import com.provedcode.talent.model.dto.StatisticsDTO; import com.provedcode.talent.model.entity.*; import com.provedcode.talent.model.request.EditTalent; import com.provedcode.talent.repo.SkillsRepository; @@ -24,10 +29,7 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.server.ResponseStatusException; -import java.util.Arrays; -import java.util.List; -import java.util.Optional; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; import static org.springframework.http.HttpStatus.*; @@ -44,6 +46,7 @@ public class TalentService { PageProperties pageProperties; ValidateTalentForCompliance validateTalentForCompliance; SkillsRepository skillsRepository; + TalentProofMapper talentProofMapper; @Transactional(readOnly = true) public Page getTalentsPage(Integer page, Integer size) { @@ -214,4 +217,70 @@ public Page getFilteredBySkillsTalentsPage(@PositiveOrZero Integer page, talentRepository.findBySkills_SkillsInIgnoreCase(PageRequest.of(page, size), Arrays.stream(filterBy).map(String::toUpperCase).toList()) : talentRepository.findAll(PageRequest.of(page, size)); } + + public StatisticsDTO getStatisticsForTalent(long talentId, Authentication authentication) { + Optional talent = talentRepository.findById(talentId); + Optional userInfo = userInfoRepository.findByLogin(authentication.getName()); + validateTalentForCompliance.userVerification(talent, userInfo, talentId); + Talent talentObject = talent.get(); + return StatisticsDTO.builder() + .allKudosOnTalent(getAllKudosOnTalent(talentObject)) + .skillWithLargestNumberOfKudos(getSkillWithLargestNumberOfKudos(talentObject)) + .proofWithLargestNumberOfKudos(getProofWithLargestNumberOfKudos(talentObject)) + .build(); + } + + public Long getAllKudosOnTalent(Talent talent) { + return talent.getTalentProofs() + .stream() + .flatMap(x -> x.getProofSkills().stream()) + .flatMap(y -> y.getKudos().stream()) + .mapToLong(q -> q.getAmount()) + .sum(); + } + + public Map getSkillWithLargestNumberOfKudos(Talent talent) { + Map numberKudosOnSkill = new HashMap<>(); + for (TalentProof talentProof : talent.getTalentProofs()) { + for (ProofSkill proofSkill : talentProof.getProofSkills()) { + for (Kudos kudos : proofSkill.getKudos()) { + if (numberKudosOnSkill.containsKey(proofSkill.getSkill().getSkill())) { + Long amountKudosOnSkill = numberKudosOnSkill.get(proofSkill.getSkill().getSkill()); + numberKudosOnSkill.remove(proofSkill.getSkill().getSkill()); + numberKudosOnSkill.put(proofSkill.getSkill().getSkill(), amountKudosOnSkill + kudos.getAmount()); + } else { + numberKudosOnSkill.put(proofSkill.getSkill().getSkill(), kudos.getAmount()); + } + } + } + } + Long max = Collections.max(numberKudosOnSkill.values()); + Map result = new HashMap<>(); + for (Map.Entry entry : numberKudosOnSkill.entrySet()) { + if (entry.getValue().equals(max)) { + result.put(entry.getKey(), entry.getValue()); + } + } + + return result; + } + + public Map getProofWithLargestNumberOfKudos(Talent talent) { + Map result = new HashMap<>(); + Long maxForResult = 0L; + for (TalentProof talentProof : talent.getTalentProofs()) { + Long amountKudosOnSkills = 0L; + for (ProofSkill proofSkill : talentProof.getProofSkills()) { + for (Kudos kudos : proofSkill.getKudos()) { + amountKudosOnSkills += kudos.getAmount(); + } + } + if (amountKudosOnSkills > maxForResult) { + maxForResult = amountKudosOnSkills; + result.clear(); + result.put(talentProofMapper.toProofDTO(talentProof), amountKudosOnSkills); + } + } + return result; + } } \ No newline at end of file