package ru.ulstu.grant.service; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.Errors; import ru.ulstu.activity.service.ActivityService; import ru.ulstu.deadline.model.Deadline; import ru.ulstu.deadline.service.DeadlineService; import ru.ulstu.file.model.FileDataDto; import ru.ulstu.file.service.FileService; import ru.ulstu.grant.model.Grant; import ru.ulstu.grant.model.GrantDto; import ru.ulstu.grant.repository.GrantRepository; import ru.ulstu.name.BaseService; import ru.ulstu.paper.model.Paper; import ru.ulstu.paper.model.PaperDto; import ru.ulstu.paper.service.PaperService; import ru.ulstu.ping.service.PingService; import ru.ulstu.project.model.ProjectDto; import ru.ulstu.project.service.ProjectService; import ru.ulstu.timeline.service.EventService; import ru.ulstu.user.model.User; import ru.ulstu.user.service.UserService; import java.io.IOException; import java.text.ParseException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; import static java.util.stream.Collectors.toList; import static org.springframework.util.ObjectUtils.isEmpty; import static ru.ulstu.core.util.StreamApiUtils.convert; import static ru.ulstu.grant.model.Grant.GrantStatus.APPLICATION; @Service public class GrantService extends BaseService { private final Logger log = LoggerFactory.getLogger(GrantService.class); private final GrantRepository grantRepository; private final ProjectService projectService; private final DeadlineService deadlineService; private final FileService fileService; private final UserService userService; private final PaperService paperService; private final EventService eventService; private final GrantNotificationService grantNotificationService; private final KiasService kiasService; private final PingService pingService; private final ActivityService activityService; public GrantService(GrantRepository grantRepository, FileService fileService, DeadlineService deadlineService, ProjectService projectService, UserService userService, PaperService paperService, EventService eventService, GrantNotificationService grantNotificationService, KiasService kiasService, PingService pingService, ActivityService activityService) { this.grantRepository = grantRepository; this.kiasService = kiasService; this.baseRepository = grantRepository; this.fileService = fileService; this.deadlineService = deadlineService; this.projectService = projectService; this.userService = userService; this.paperService = paperService; this.eventService = eventService; this.grantNotificationService = grantNotificationService; this.pingService = pingService; this.activityService = activityService; } public GrantDto getExistGrantById(Integer id) { GrantDto grantDto = new GrantDto(findById(id)); return grantDto; } public List findAll() { return grantRepository.findAll(); } public List findAllDto() { return convert(findAll(), GrantDto::new); } @Transactional public Grant create(GrantDto grantDto) throws IOException { Grant newGrant = copyFromDto(new Grant(), grantDto); newGrant = grantRepository.save(newGrant); eventService.createFromObject(newGrant, Collections.emptyList(), false, "гранта"); activityService.createActivity(new ArrayList<>(newGrant.getAuthors()), newGrant.getCommonActivityState()); grantNotificationService.sendCreateNotification(newGrant); return newGrant; } private Grant copyFromDto(Grant grant, GrantDto grantDto) throws IOException { grant.setComment(grantDto.getComment()); grant.setStatus(grantDto.getStatus() == null ? APPLICATION : grantDto.getStatus()); grant.setTitle(grantDto.getTitle()); if (grantDto.getProject() != null && grantDto.getProject().getId() != null) { grant.setProject(projectService.findById(grantDto.getProject().getId())); } grant.setDeadlines(deadlineService.saveOrCreate(grantDto.getDeadlines())); if (!grant.getFiles().isEmpty()) { grant.setFiles(fileService.saveOrCreate(grantDto.getFiles().stream() .filter(f -> !f.isDeleted()) .collect(toList()))); } grant.getAuthors().clear(); if (grantDto.getAuthorIds() != null && !grantDto.getAuthorIds().isEmpty()) { grantDto.getAuthorIds().forEach(authorIds -> grant.getAuthors().add(userService.findById(authorIds))); } if (grantDto.getLeaderId() != null) { grant.setLeader(userService.findById(grantDto.getLeaderId())); } grant.getPapers().clear(); if (grantDto.getPaperIds() != null && !grantDto.getPaperIds().isEmpty()) { grantDto.getPaperIds().forEach(paperIds -> grant.getPapers().add(paperService.findPaperById(paperIds))); } return grant; } public void createProject(GrantDto grantDto) throws IOException { grantDto.setProject( new ProjectDto(projectService.save(new ProjectDto(grantDto.getTitle())))); } @Transactional public Integer update(GrantDto grantDto) throws IOException { Grant grant = findById(grantDto.getId()); Set oldAuthors = new HashSet<>(grant.getAuthors()); User oldLeader = grant.getLeader(); Grant.GrantStatus oldStatus = grant.getStatus(); for (FileDataDto file : grantDto.getFiles().stream() .filter(f -> f.isDeleted() && f.getId() != null) .collect(toList())) { fileService.delete(file.getId()); } grantDto.getRemovedDeadlineIds().forEach(deadlineService::remove); grantRepository.save(copyFromDto(grant, grantDto)); grant.getAuthors().forEach(author -> { if (!oldAuthors.contains(author)) { grantNotificationService.sendAuthorsChangeNotification(grant, oldAuthors); } }); oldAuthors.forEach(oldAuthor -> { if (!grant.getAuthors().contains(oldAuthor)) { grantNotificationService.sendAuthorsChangeNotification(grant, oldAuthors); } }); if (grant.getLeader() != oldLeader) { grantNotificationService.sendLeaderChangeNotification(grant, oldLeader); } if(grant.getStatus() != oldStatus) { activityService.createActivity(new ArrayList<>(grant.getAuthors()), grant.getCommonActivityState()); } eventService.updateGrantDeadlines(grant); return grant.getId(); } @Transactional public boolean delete(Integer grantId) throws IOException { Grant grant = findById(grantId); if (grant != null) { grantRepository.delete(grant); return true; } return false; } public List getGrantStatuses() { return Arrays.asList(Grant.GrantStatus.values()); } public boolean save(GrantDto grantDto, Errors errors) throws IOException { grantDto.setName(grantDto.getTitle()); filterEmptyDeadlines(grantDto); checkEmptyDeadlines(grantDto, errors); checkEmptyLeader(grantDto, errors); checkUniqueName(grantDto, errors, grantDto.getId(), "title", "Грант с таким именем уже существует"); if (errors.hasErrors()) { return false; } if (isEmpty(grantDto.getId())) { create(grantDto); } else { update(grantDto); } return true; } public boolean saveFromKias(GrantDto grantDto) throws IOException { grantDto.setName(grantDto.getTitle()); String title = checkUniqueName(grantDto, grantDto.getId()); //проверка уникальности имени if (title != null) { Grant grantFromDB = grantRepository.findByTitle(title); //грант с таким же названием из бд if (checkSameDeadline(grantDto, grantFromDB.getId())) { //если дедайны тоже совпадают return false; } else { //иначе грант уже был в системе, но в другом году, поэтому надо создать create(grantDto); return true; } } else { //иначе такого гранта ещё нет, поэтому надо создать create(grantDto); return true; } } private void checkEmptyLeader(GrantDto grantDto, Errors errors) { if (grantDto.getLeaderId().equals(-1)) { errors.rejectValue("leaderId", "errorCode", "Укажите руководителя"); } } private void checkEmptyDeadlines(GrantDto grantDto, Errors errors) { if (grantDto.getDeadlines().isEmpty()) { errors.rejectValue("deadlines", "errorCode", "Не может быть пусто"); } } private boolean checkSameDeadline(GrantDto grantDto, Integer id) { Date date = grantDto.getDeadlines().get(0).getDate(); //дата с сайта киас Date foundGrantDate = deadlineService.findByGrantIdAndDate(id, date); return foundGrantDate != null && foundGrantDate.compareTo(date) == 0; } public List getGrantAuthors(GrantDto grantDto) { List filteredUsers = userService.filterByAgeAndDegree(grantDto.isHasAge(), grantDto.isHasDegree()); if (grantDto.isWasLeader()) { filteredUsers = checkContains(filteredUsers, getCompletedGrantLeaders()); } if (grantDto.isHasBAKPapers()) { filteredUsers = checkContains(filteredUsers, getBAKAuthors()); } if (grantDto.isHasScopusPapers()) { filteredUsers = checkContains(filteredUsers, getScopusAuthors()); } return filteredUsers; } private List checkContains(List filteredUsers, List checkUsers) { return filteredUsers.stream() .filter(checkUsers::contains) .collect(toList()); } private List getCompletedGrantLeaders() { return grantRepository.findByStatus(Grant.GrantStatus.COMPLETED) .stream() .map(Grant::getLeader) .collect(toList()); } public List getGrantPapers(List paperIds) { return paperService.findAllSelect(paperIds); } public List getAllUncompletedPapers() { return paperService.findAllNotCompleted(); } public List attachPaper(GrantDto grantDto) { if (!grantDto.getPaperIds().isEmpty()) { grantDto.getPapers().clear(); grantDto.setPapers(getGrantPapers(grantDto.getPaperIds())); } else { grantDto.getPapers().clear(); } return grantDto.getPapers(); } public GrantDto removeDeadline(GrantDto grantDto, Integer deadlineId) { if (grantDto.getDeadlines().get(deadlineId).getId() != null) { grantDto.getRemovedDeadlineIds().add(grantDto.getDeadlines().get(deadlineId).getId()); } grantDto.getDeadlines().remove((int) deadlineId); return grantDto; } private List getCompletedPapersAuthors(Paper.PaperType type) { List papers = paperService.findAllCompletedByType(type); return papers.stream() .filter(paper -> paper.getAuthors() != null) .flatMap(paper -> paper.getAuthors().stream()) .collect(toList()); } private List getBAKAuthors() { return getCompletedPapersAuthors(Paper.PaperType.VAK) .stream() .distinct() .collect(toList()); } private List getScopusAuthors() { List authors = getCompletedPapersAuthors(Paper.PaperType.SCOPUS); return authors .stream() .filter(author -> Collections.frequency(authors, author) > 3) .collect(toList()); } public List filterEmptyDeadlines(GrantDto grantDto) { grantDto.setDeadlines(grantDto.getDeadlines().stream() .filter(dto -> dto.getDate() != null || !StringUtils.isEmpty(dto.getDescription())) .collect(Collectors.toList())); return grantDto.getDeadlines(); } @Transactional public void createFromKias() throws IOException, ParseException { for (GrantDto grantDto : kiasService.getNewGrantsDto()) { if (saveFromKias(grantDto)) { log.debug("GrantScheduler.loadGrantsFromKias new grant was loaded"); } else { log.debug("GrantScheduler.loadGrantsFromKias grant wasn't loaded, cause it's already exists"); } } } public List findAllActiveDto() { return convert(findAllActive(), GrantDto::new); } private List findAllActive() { return grantRepository.findAllActive(); } public Grant findById(Integer id) { return grantRepository.findOne(id); } @Transactional public void ping(int grantId) throws IOException { pingService.addPing(findById(grantId)); } }