TeamService.java
package no.nav.data.team.team;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import no.nav.data.common.TeamCatalogProps;
import no.nav.data.common.storage.StorageService;
import no.nav.data.common.storage.domain.GenericStorage;
import no.nav.data.common.validator.Validator;
import no.nav.data.team.cluster.domain.Cluster;
import no.nav.data.team.location.LocationRepository;
import no.nav.data.team.location.domain.LocationType;
import no.nav.data.team.naisteam.NaisConsoleClient;
import no.nav.data.team.po.domain.ProductArea;
import no.nav.data.team.resource.NomClient;
import no.nav.data.team.shared.domain.DomainObjectStatus;
import no.nav.data.team.team.domain.Team;
import no.nav.data.team.team.domain.TeamMember;
import no.nav.data.team.team.dto.TeamMemberRequest;
import no.nav.data.team.team.dto.TeamRequest;
import no.nav.data.team.team.dto.TeamRequest.Fields;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.DayOfWeek;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import static no.nav.data.common.utils.StreamUtils.convert;
import static no.nav.data.common.validator.Validator.*;
@Slf4j
@Service
public class TeamService {
private final StorageService storage;
private final NaisConsoleClient naisTeamService;
private final NomClient nomClient;
private final TeamRepository teamRepository;
private final LocationRepository locationRepository;
@Autowired
private TeamCatalogProps teamCatalogProps;
public TeamService(StorageService storage, NaisConsoleClient naisTeamService, NomClient nomClient, TeamRepository teamRepository, LocationRepository locationRepository) {
this.storage = storage;
this.naisTeamService = naisTeamService;
this.nomClient = nomClient;
this.teamRepository = teamRepository;
this.locationRepository = locationRepository;
}
public Team save(TeamRequest request) {
if (request.getProductAreaId() == null) {
request.setProductAreaId(teamCatalogProps.getDefaultProductareaUuid());
}
Validator.validate(request, storage)
.addValidations(validator -> validator.checkExists(request.getProductAreaId(), storage, ProductArea.class))
.addValidations(validator -> getaVoid(request, validator))
.addValidations(TeamRequest::getMembers, this::validateMembers)
.addValidation(TeamRequest::getContactPersonIdent, this::validateContactPerson)
.addValidations(TeamRequest::getNaisTeams, this::validateNaisTeam)
.addValidations(this::validateName)
.addValidations(this::validateTeamOwner)
.addValidations(this::validateLocationCode)
.addValidations(this::validateStatusNotNull)
.addValidations(this::validateTeamMemberRoleOk)
.ifErrorsThrowValidationException();
var team = request.isUpdate() ? storage.get(request.getIdAsUUID(), Team.class) : new Team();
storage.save(team.convert(request));
return team;
}
private void getaVoid(TeamRequest request, Validator<TeamRequest> validator) {
request.getClusterIds().forEach(cId -> validator.checkExists(cId, storage, Cluster.class));
}
public Team get(UUID id) {
return storage.get(id, Team.class);
}
public Team delete(UUID id) {
Team delete = storage.delete(id, Team.class);
//graphService.deleteTeam(delete);
return delete;
}
public List<Team> getAll() {
return storage.getAll(Team.class);
}
public List<Team> getAllActive() {
return getAll().stream().filter(team -> team.getStatus() == DomainObjectStatus.ACTIVE).toList();
}
public List<Team> findByProductArea(UUID productAreaId) {
return convert(teamRepository.findByProductArea(productAreaId), GenericStorage::toTeam);
}
public List<Team> findByCluster(UUID clusterId) {
return teamRepository.findByCluster(clusterId);
}
public List<Team> findByNaisTeam(String naisTeam) {
return teamRepository.findByNaisTeam(naisTeam);
}
public List<Team> search(String name) {
return convert(teamRepository.findByNameLike(name), GenericStorage::toTeam);
}
private void validateNaisTeam(Validator<TeamRequest> validator, String naisTeam) {
Team existingTeam = validator.getDomainItem();
if (!(existingTeam != null && existingTeam.getNaisTeams().contains(naisTeam)) && !naisTeamService.naisTeamExists(naisTeam)) {
validator.addError(Fields.naisTeams, DOES_NOT_EXIST, "Nais Team " + naisTeam + " does not exist");
}
}
private void validateMembers(Validator<TeamRequest> validator, TeamMemberRequest member) {
var existingMembers = validator.getDomainItem() == null ? List.<TeamMember>of() : validator.getDomainItem(Team.class).getMembers();
validateIdent(validator, member.getNavIdent(), Fields.members, convert(existingMembers, TeamMember::getNavIdent));
}
private void validateContactPerson(Validator<TeamRequest> validator, String ident) {
List<String> existingIdents = Optional.ofNullable(validator.getDomainItem(Team.class)).map(Team::getContactPersonIdent).map(List::of).orElse(List.of());
validateIdent(validator, ident, Fields.contactPersonIdent, existingIdents);
}
private void validateStatusNotNull(Validator<TeamRequest> teamRequestValidator) {
if(teamRequestValidator.getItem().getStatus() == null){
teamRequestValidator.addError("status", ILLEGAL_ARGUMENT, "Status cannot be null");
}
}
private void validateIdent(Validator<TeamRequest> validator, String ident, String fieldName, List<String> existingIdents) {
if (ident == null) {
return;
}
if (existingIdents.stream().noneMatch(m -> m.equals(ident)) && nomClient.getByNavIdent(ident).isEmpty()) {
validator.addError(fieldName, DOES_NOT_EXIST, "Resource " + ident + " does not exist");
}
}
private void validateName(Validator<TeamRequest> validator) {
String name = validator.getItem().getName();
if (name == null || name == "") {
validator.addError(Fields.name, ERROR_MESSAGE_MISSING, "Name is required");
}
}
private void validateTeamOwner(Validator<TeamRequest> validator) {
var teamRequest = validator.getItem();
var teamInDefaultProductArea = teamCatalogProps.getDefaultProductareaUuid().
equals(teamRequest.getProductAreaId());
if(teamInDefaultProductArea){
if(teamRequest.getTeamOwnerIdent() != null){
validateIdent(validator,teamRequest.getTeamOwnerIdent(), Fields.teamOwnerIdent, List.of());
}
}else{
if(teamRequest.getTeamOwnerIdent() != null) {
var errMsg = "Cannot specify teamOwner for team in non-default product-area.";
validator.addError(Fields.teamOwnerIdent, ILLEGAL_ARGUMENT, errMsg);
}
}
}
private void validateLocationCode(Validator<TeamRequest> validator){
val officeHours = validator.getItem().getOfficeHours();
if(officeHours != null){
if(officeHours.getDays().contains(DayOfWeek.SATURDAY) || officeHours.getDays().contains(DayOfWeek.SUNDAY)){
validator.addError(Fields.officeHours, ILLEGAL_ARGUMENT, "Officehours can't be on saturdays or sundays");
}
val location = locationRepository.getLocationByCode(officeHours.getLocationCode());
if(location.isEmpty()){
validator.addError(Fields.officeHours, DOES_NOT_EXIST, "Location for given location code does not exist.");
}
if(location.filter(l -> !l.getType().equals(LocationType.FLOOR)).isPresent()){
validator.addError(Fields.officeHours, ILLEGAL_ARGUMENT, "Team location must be of type FLOOR");
}
}
}
private void validateTeamMemberRoleOk(Validator<TeamRequest> validator) {
var members = validator.getItem().getMembers();
if(members == null) return;
for(var member : members){
var roles = member.getRoles();
if (roles == null) continue;
for(var role : roles){
if(role.isLeaderGroupRole()){
validator.addError("members", ILLEGAL_ARGUMENT, String.format("Role '%s' is not applicable for team member", role));
}
}
}
}
}