diff --git a/src/main/java/ru/ulstu/conference/model/Conference.java b/src/main/java/ru/ulstu/conference/model/Conference.java index 7e18ac0..4df1a1f 100644 --- a/src/main/java/ru/ulstu/conference/model/Conference.java +++ b/src/main/java/ru/ulstu/conference/model/Conference.java @@ -42,12 +42,12 @@ public class Conference extends BaseEntity { @Column(name = "begin_date") @Temporal(TemporalType.TIMESTAMP) @DateTimeFormat(pattern = "yyyy-MM-dd") - private Date beginDate; + private Date beginDate = new Date(); @Column(name = "end_date") @Temporal(TemporalType.TIMESTAMP) @DateTimeFormat(pattern = "yyyy-MM-dd") - private Date endDate; + private Date endDate = new Date(); @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) @JoinColumn(name = "conference_id", unique = true) diff --git a/src/main/java/ru/ulstu/conference/model/ConferenceDto.java b/src/main/java/ru/ulstu/conference/model/ConferenceDto.java index 9c9b37a..5759f4e 100644 --- a/src/main/java/ru/ulstu/conference/model/ConferenceDto.java +++ b/src/main/java/ru/ulstu/conference/model/ConferenceDto.java @@ -14,6 +14,7 @@ import javax.validation.constraints.Size; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Objects; import static ru.ulstu.core.util.StreamApiUtils.convert; @@ -219,4 +220,33 @@ public class ConferenceDto extends NameContainer { return BEGIN_DATE + beginDate.toString().split(" ")[0] + " " + END_DATE + endDate.toString().split(" ")[0]; } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ConferenceDto that = (ConferenceDto) o; + return ping == that.ping && + disabledTakePart == that.disabledTakePart && + Objects.equals(id, that.id) && + Objects.equals(title, that.title) && + Objects.equals(description, that.description) && + Objects.equals(url, that.url) && + Objects.equals(deadlines, that.deadlines) && + Objects.equals(removedDeadlineIds, that.removedDeadlineIds) && + Objects.equals(userIds, that.userIds) && + Objects.equals(paperIds, that.paperIds) && + Objects.equals(papers, that.papers) && + Objects.equals(notSelectedPapers, that.notSelectedPapers) && + Objects.equals(users, that.users); + } + + @Override + public int hashCode() { + return Objects.hash(id, title, description, url, ping, beginDate, endDate, deadlines, removedDeadlineIds, + userIds, paperIds, papers, notSelectedPapers, users, disabledTakePart); + } } diff --git a/src/main/java/ru/ulstu/conference/service/ConferenceService.java b/src/main/java/ru/ulstu/conference/service/ConferenceService.java index 1754987..38ce659 100644 --- a/src/main/java/ru/ulstu/conference/service/ConferenceService.java +++ b/src/main/java/ru/ulstu/conference/service/ConferenceService.java @@ -16,6 +16,7 @@ import ru.ulstu.deadline.service.DeadlineService; import ru.ulstu.name.BaseService; import ru.ulstu.paper.model.Paper; import ru.ulstu.paper.service.PaperService; +import ru.ulstu.ping.model.Ping; import ru.ulstu.ping.service.PingService; import ru.ulstu.timeline.service.EventService; import ru.ulstu.user.model.User; @@ -64,7 +65,7 @@ public class ConferenceService extends BaseService { } public ConferenceDto getExistConferenceById(Integer id) { - ConferenceDto conferenceDto = findOneDto(id); + ConferenceDto conferenceDto = new ConferenceDto(conferenceRepository.findOne(id)); conferenceDto.setNotSelectedPapers(getNotSelectPapers(conferenceDto.getPaperIds())); conferenceDto.setDisabledTakePart(isCurrentUserParticipant(conferenceDto.getUsers())); return conferenceDto; @@ -72,7 +73,7 @@ public class ConferenceService extends BaseService { public ConferenceDto getNewConference() { ConferenceDto conferenceDto = new ConferenceDto(); - conferenceDto.setNotSelectedPapers(getNotSelectPapers(new ArrayList())); + conferenceDto.setNotSelectedPapers(getNotSelectPapers(new ArrayList<>())); return conferenceDto; } @@ -87,10 +88,6 @@ public class ConferenceService extends BaseService { return conferences; } - public ConferenceDto findOneDto(Integer id) { - return new ConferenceDto(conferenceRepository.findOne(id)); - } - public boolean save(ConferenceDto conferenceDto, Errors errors) throws IOException { conferenceDto.setName(conferenceDto.getTitle()); filterEmptyDeadlines(conferenceDto); @@ -114,16 +111,16 @@ public class ConferenceService extends BaseService { } @Transactional - public Integer create(ConferenceDto conferenceDto) throws IOException { + public Conference create(ConferenceDto conferenceDto) throws IOException { Conference newConference = copyFromDto(new Conference(), conferenceDto); newConference = conferenceRepository.save(newConference); conferenceNotificationService.sendCreateNotification(newConference); eventService.createFromConference(newConference); - return newConference.getId(); + return newConference; } @Transactional - public Integer update(ConferenceDto conferenceDto) throws IOException { + public Conference update(ConferenceDto conferenceDto) throws IOException { Conference conference = conferenceRepository.findOne(conferenceDto.getId()); List oldDeadlines = conference.getDeadlines().stream() .map(this::copyDeadline) @@ -137,50 +134,56 @@ public class ConferenceService extends BaseService { conferenceNotificationService.updateConferencesDatesNotification(conference, oldBeginDate, oldEndDate); } conferenceDto.getRemovedDeadlineIds().forEach(deadlineService::remove); - return conference.getId(); + return conference; } @Transactional - public void delete(Integer conferenceId) { + public boolean delete(Integer conferenceId) { if (conferenceRepository.exists(conferenceId)) { eventService.removeConferencesEvent(conferenceRepository.findOne(conferenceId)); conferenceRepository.delete(conferenceId); + return true; } + return false; } - public void addDeadline(ConferenceDto conferenceDto) { + public ConferenceDto addDeadline(ConferenceDto conferenceDto) { conferenceDto.getDeadlines().add(new Deadline()); + return conferenceDto; } - public void removeDeadline(ConferenceDto conferenceDto, Integer deadlineIndex) throws IOException { + public ConferenceDto removeDeadline(ConferenceDto conferenceDto, Integer deadlineIndex) throws IOException { if (conferenceDto.getDeadlines().get(deadlineIndex).getId() != null) { conferenceDto.getRemovedDeadlineIds().add(conferenceDto.getDeadlines().get(deadlineIndex).getId()); } conferenceDto.getDeadlines().remove((int) deadlineIndex); + return conferenceDto; } - public void addPaper(ConferenceDto conferenceDto) { + public ConferenceDto addPaper(ConferenceDto conferenceDto) { Paper paper = new Paper(); paper.setTitle(userService.getCurrentUser().getLastName() + "_" + conferenceDto.getTitle() + "_" + (new Date()).getTime()); paper.setStatus(Paper.PaperStatus.DRAFT); - conferenceDto.getPapers().add(paper); + return conferenceDto; } - public void removePaper(ConferenceDto conferenceDto, Integer paperIndex) throws IOException { + public ConferenceDto removePaper(ConferenceDto conferenceDto, Integer paperIndex) throws IOException { Paper removedPaper = conferenceDto.getPapers().remove((int) paperIndex); if (removedPaper.getId() != null) { conferenceDto.getNotSelectedPapers().add(removedPaper); } + return conferenceDto; } - public void takePart(ConferenceDto conferenceDto) throws IOException { + public ConferenceDto takePart(ConferenceDto conferenceDto) throws IOException { conferenceDto.getUsers().add(new ConferenceUser(userService.getCurrentUser())); conferenceDto.setDisabledTakePart(true); + return conferenceDto; } - public List getNotSelectPapers(List paperIds) { + private List getNotSelectPapers(List paperIds) { return paperService.findAllNotSelect(paperIds); } @@ -214,7 +217,7 @@ public class ConferenceService extends BaseService { } - public boolean isCurrentUserParticipant(List conferenceUsers) { + private boolean isCurrentUserParticipant(List conferenceUsers) { return conferenceUsers.stream().anyMatch(participant -> participant.getUser().equals(userService.getCurrentUser())); } @@ -229,7 +232,7 @@ public class ConferenceService extends BaseService { return convert(findAllActive(), ConferenceDto::new); } - public List findAllActive() { + private List findAllActive() { return conferenceRepository.findAllActive(new Date()); } @@ -238,12 +241,13 @@ public class ConferenceService extends BaseService { } @Transactional - public void ping(ConferenceDto conferenceDto) throws IOException { - pingService.addPing(findOne(conferenceDto.getId())); + public Ping ping(ConferenceDto conferenceDto) throws IOException { + Ping ping = pingService.addPing(findOne(conferenceDto.getId())); conferenceRepository.updatePingConference(conferenceDto.getId()); + return ping; } - public Conference findOne(Integer conferenceId) { + private Conference findOne(Integer conferenceId) { return conferenceRepository.findOne(conferenceId); } @@ -269,7 +273,7 @@ public class ConferenceService extends BaseService { modelMap.addAttribute("offshoreSales", offshoreSales); } - public void sendNotificationAfterUpdateDeadlines(Conference conference, List oldDeadlines) { + private void sendNotificationAfterUpdateDeadlines(Conference conference, List oldDeadlines) { if (oldDeadlines.size() != conference.getDeadlines().size()) { conferenceNotificationService.updateDeadlineNotification(conference); return; @@ -283,7 +287,7 @@ public class ConferenceService extends BaseService { } } - public Deadline copyDeadline(Deadline oldDeadline) { + private Deadline copyDeadline(Deadline oldDeadline) { Deadline newDeadline = new Deadline(oldDeadline.getDate(), oldDeadline.getDescription()); newDeadline.setId(oldDeadline.getId()); return newDeadline; diff --git a/src/main/java/ru/ulstu/core/util/DateUtils.java b/src/main/java/ru/ulstu/core/util/DateUtils.java index 6122583..3a38452 100644 --- a/src/main/java/ru/ulstu/core/util/DateUtils.java +++ b/src/main/java/ru/ulstu/core/util/DateUtils.java @@ -54,4 +54,10 @@ public class DateUtils { cal.add(Calendar.DAY_OF_MONTH, count); return cal.getTime(); } + + public static Date addYears(Date date, int count) { + Calendar cal = getCalendar(date); + cal.add(Calendar.YEAR, count); + return cal.getTime(); + } } diff --git a/src/main/java/ru/ulstu/deadline/model/Deadline.java b/src/main/java/ru/ulstu/deadline/model/Deadline.java index 148697c..6c564aa 100644 --- a/src/main/java/ru/ulstu/deadline/model/Deadline.java +++ b/src/main/java/ru/ulstu/deadline/model/Deadline.java @@ -65,6 +65,11 @@ public class Deadline extends BaseEntity { return false; } Deadline deadline = (Deadline) o; + if (getId() == null && deadline.getId() == null && + description == null && deadline.description == null && + date == null && deadline.date == null) { + return true; + } return getId().equals(deadline.getId()) && description.equals(deadline.description) && date.equals(deadline.date); diff --git a/src/main/java/ru/ulstu/grant/service/GrantNotificationService.java b/src/main/java/ru/ulstu/grant/service/GrantNotificationService.java index 40c045b..677b38f 100644 --- a/src/main/java/ru/ulstu/grant/service/GrantNotificationService.java +++ b/src/main/java/ru/ulstu/grant/service/GrantNotificationService.java @@ -64,6 +64,7 @@ public class GrantNotificationService { Map variables = ImmutableMap.of("grant", grant, "oldLeader", oldLeader); sendForAllAuthors(variables, grant, TEMPLATE_LEADER_CHANGED, String.format(TITLE_LEADER_CHANGED, grant.getTitle())); } + private void sendForAllAuthors(Map variables, Grant grant, String template, String title) { Set allAuthors = grant.getAuthors(); allAuthors.forEach(author -> mailService.sendEmailFromTemplate(variables, author, template, title)); diff --git a/src/main/java/ru/ulstu/paper/model/Paper.java b/src/main/java/ru/ulstu/paper/model/Paper.java index 4536ce5..15ee4b4 100644 --- a/src/main/java/ru/ulstu/paper/model/Paper.java +++ b/src/main/java/ru/ulstu/paper/model/Paper.java @@ -29,6 +29,7 @@ import java.util.Comparator; import java.util.Date; import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.Set; @@ -264,4 +265,36 @@ public class Paper extends BaseEntity implements UserContainer { .findAny() .isPresent(); } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + if (!super.equals(o)) { + return false; + } + Paper paper = (Paper) o; + return Objects.equals(title, paper.title) && + status == paper.status && + type == paper.type && + Objects.equals(deadlines, paper.deadlines) && + Objects.equals(comment, paper.comment) && + Objects.equals(url, paper.url) && + Objects.equals(locked, paper.locked) && + Objects.equals(events, paper.events) && + Objects.equals(files, paper.files) && + Objects.equals(authors, paper.authors) && + Objects.equals(latexText, paper.latexText) && + Objects.equals(conferences, paper.conferences) && + Objects.equals(grants, paper.grants); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), title, status, type, createDate, updateDate, deadlines, comment, url, locked, events, files, authors, latexText, conferences, grants); + } } diff --git a/src/main/java/ru/ulstu/ping/service/PingService.java b/src/main/java/ru/ulstu/ping/service/PingService.java index f7156f0..6666fdd 100644 --- a/src/main/java/ru/ulstu/ping/service/PingService.java +++ b/src/main/java/ru/ulstu/ping/service/PingService.java @@ -23,10 +23,10 @@ public class PingService { } @Transactional - public void addPing(Conference conference) throws IOException { + public Ping addPing(Conference conference) throws IOException { Ping newPing = new Ping(new Date(), userService.getCurrentUser()); newPing.setConference(conference); - pingRepository.save(newPing); + return pingRepository.save(newPing); } public Integer countPingYesterday(Conference conference, Calendar calendar) { diff --git a/src/main/java/ru/ulstu/students/model/Scheduler.java b/src/main/java/ru/ulstu/students/model/Scheduler.java new file mode 100644 index 0000000..67005b1 --- /dev/null +++ b/src/main/java/ru/ulstu/students/model/Scheduler.java @@ -0,0 +1,49 @@ +package ru.ulstu.students.model; + +import org.springframework.format.annotation.DateTimeFormat; +import ru.ulstu.core.model.BaseEntity; + +import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.OneToOne; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; +import java.util.Date; + +@Entity +@Table(name = "scheduler") +public class Scheduler extends BaseEntity { + + @OneToOne(optional = false) + @JoinColumn(name = "task_id") + private Task task; + + @Temporal(value = TemporalType.TIMESTAMP) + @DateTimeFormat(pattern = "yyyy-MM-dd") + private Date date; + + public Scheduler() { + } + + public Scheduler(Task task, Date date) { + this.task = task; + this.date = date; + } + + public Task getTask() { + return task; + } + + public void setTask(Task task) { + this.task = task; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } +} diff --git a/src/main/java/ru/ulstu/students/repository/SchedulerRepository.java b/src/main/java/ru/ulstu/students/repository/SchedulerRepository.java new file mode 100644 index 0000000..7481692 --- /dev/null +++ b/src/main/java/ru/ulstu/students/repository/SchedulerRepository.java @@ -0,0 +1,11 @@ +package ru.ulstu.students.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import ru.ulstu.students.model.Scheduler; +import ru.ulstu.students.model.Task; + +public interface SchedulerRepository extends JpaRepository { + + Scheduler findOneByTask(Task task); + +} diff --git a/src/main/java/ru/ulstu/students/repository/TaskRepository.java b/src/main/java/ru/ulstu/students/repository/TaskRepository.java index ee49ab8..af277d1 100644 --- a/src/main/java/ru/ulstu/students/repository/TaskRepository.java +++ b/src/main/java/ru/ulstu/students/repository/TaskRepository.java @@ -6,6 +6,7 @@ import org.springframework.data.repository.query.Param; import ru.ulstu.students.model.Task; import ru.ulstu.tags.model.Tag; +import java.util.Date; import java.util.List; public interface TaskRepository extends JpaRepository { @@ -15,4 +16,12 @@ public interface TaskRepository extends JpaRepository { @Query("SELECT t FROM Task t WHERE (t.status = :status OR :status IS NULL) AND (:tag IS NULL OR :tag MEMBER OF t.tags) ORDER BY create_date ASC") List filterOld(@Param("status") Task.TaskStatus status, @Param("tag") Tag tag); + + @Query("SELECT t FROM Task t WHERE(:tag IS NULL OR :tag MEMBER OF t.tags) ORDER BY create_date DESC") + List findByTag(@Param("tag") Tag tag); + + @Query("SELECT t FROM Task t WHERE (t.createDate >= :date) ORDER BY create_date DESC") + List findAllYear(@Param("date") Date date); + + } diff --git a/src/main/java/ru/ulstu/students/service/SchedulerService.java b/src/main/java/ru/ulstu/students/service/SchedulerService.java new file mode 100644 index 0000000..9d14926 --- /dev/null +++ b/src/main/java/ru/ulstu/students/service/SchedulerService.java @@ -0,0 +1,116 @@ +package ru.ulstu.students.service; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import ru.ulstu.students.model.Scheduler; +import ru.ulstu.students.model.Task; +import ru.ulstu.students.repository.SchedulerRepository; +import ru.ulstu.tags.model.Tag; + +import java.util.Date; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +@Service +public class SchedulerService { + + private final TaskService taskService; + private final SchedulerRepository schedulerRepository; + + public SchedulerService(TaskService taskService, SchedulerRepository schedulerRepository) { + this.taskService = taskService; + this.schedulerRepository = schedulerRepository; + } + + + private void save(Tag tag) { + List taskList = taskService.findTasksByTag(tag); + create(taskList.get(0)); + } + + + @Transactional + private Scheduler create(Task task) { + Scheduler scheduler = new Scheduler(task, task.getDeadlines().get(task.getDeadlines().size() - 1).getDate()); + return schedulerRepository.save(scheduler); + } + + @Transactional + private void delete(Integer schedulerId) { + if (schedulerRepository.exists(schedulerId)) { + schedulerRepository.delete(schedulerId); + } + } + + public void checkPlanToday() { + List schedulerList = schedulerRepository.findAll(); + if (!schedulerList.isEmpty()) { + doTodayPlanIfNeed(schedulerList); + schedulerList = schedulerRepository.findAll(); + } + checkNewPlan(schedulerList); + } + + private void checkNewPlan(List schedulerList) { + Set tags = taskService.checkRepeatingTags(true); + Set newTags = null; + if (!schedulerList.isEmpty()) { + newTags = checkNewTags(tags, schedulerList); + } else { + if (!tags.isEmpty()) { + newTags = tags; + } + } + + if (newTags != null) { + newTags.forEach(tag -> { + if (!hasNewTag(tag, schedulerList)) { + save(tag); + Task task = taskService.findTasksByTag(tag).get(0); + schedulerList.add(new Scheduler(task, task.getDeadlines().get(task.getDeadlines().size() - 1).getDate())); + } + }); + } + } + + private boolean hasNewTag(Tag tag, List schedulerList) { + + return schedulerList + .stream() + .anyMatch(scheduler -> scheduler.getTask().getTags().contains(tag)); + + } + + + private Set checkNewTags(Set tags, List schedulerList) { + Set newTags = tags + .stream() + .filter(tag -> schedulerList + .stream() + .anyMatch(scheduler -> + !scheduler.getTask().getTags().contains(tag))) + .collect(Collectors.toSet()); + if (!newTags.isEmpty()) { + return newTags; + } + return null; + } + + private void doTodayPlanIfNeed(List schedulerList) { + List plan = schedulerList + .stream() + .filter(scheduler -> scheduler.getDate().before(new Date())) + .collect(Collectors.toList()); + doToday(plan); + } + + private void doToday(List plan) { + plan.forEach(scheduler -> { + taskService.createPeriodTask(scheduler); + delete(scheduler.getId()); + }); + } + + +} diff --git a/src/main/java/ru/ulstu/students/service/TaskGenerationService.java b/src/main/java/ru/ulstu/students/service/TaskGenerationService.java new file mode 100644 index 0000000..1c04c20 --- /dev/null +++ b/src/main/java/ru/ulstu/students/service/TaskGenerationService.java @@ -0,0 +1,32 @@ +package ru.ulstu.students.service; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; + +@Service +public class TaskGenerationService { + + private final Logger log = LoggerFactory.getLogger(TaskGenerationService.class); + private final TaskService taskService; + private final SchedulerService schedulerService; + + public TaskGenerationService(TaskService taskService, SchedulerService schedulerService) { + + this.taskService = taskService; + this.schedulerService = schedulerService; + } + + @Scheduled(cron = "0 0 0 * * ?", zone = "Europe/Samara") + public void generateTasks() { + log.debug("SchedulerService.checkPlanToday started"); + schedulerService.checkPlanToday(); + log.debug("SchedulerService.checkPlanToday finished"); + + log.debug("TaskService.generateYearTasks started"); + taskService.generateYearTasks(); + log.debug("TaskService.generateYearTasks finished"); + } + +} diff --git a/src/main/java/ru/ulstu/students/service/TaskService.java b/src/main/java/ru/ulstu/students/service/TaskService.java index 8f335ac..2be44cb 100644 --- a/src/main/java/ru/ulstu/students/service/TaskService.java +++ b/src/main/java/ru/ulstu/students/service/TaskService.java @@ -4,19 +4,29 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import ru.ulstu.core.util.DateUtils; +import ru.ulstu.deadline.model.Deadline; import ru.ulstu.deadline.service.DeadlineService; +import ru.ulstu.students.model.Scheduler; import ru.ulstu.students.model.Task; import ru.ulstu.students.model.TaskDto; import ru.ulstu.students.model.TaskFilterDto; +import ru.ulstu.students.repository.SchedulerRepository; import ru.ulstu.students.repository.TaskRepository; import ru.ulstu.tags.model.Tag; import ru.ulstu.tags.service.TagService; import ru.ulstu.timeline.service.EventService; import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Calendar; import java.util.Date; import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.stream.Collectors; import static org.springframework.util.ObjectUtils.isEmpty; import static ru.ulstu.core.util.StreamApiUtils.convert; @@ -28,16 +38,19 @@ public class TaskService { private final static int MAX_DISPLAY_SIZE = 40; private final TaskRepository taskRepository; + private final SchedulerRepository schedulerRepository; private final DeadlineService deadlineService; private final TagService tagService; private final EventService eventService; + public TaskService(TaskRepository taskRepository, - DeadlineService deadlineService, TagService tagService, EventService eventService) { + DeadlineService deadlineService, TagService tagService, SchedulerRepository schedulerRepository, EventService eventService) { this.taskRepository = taskRepository; this.deadlineService = deadlineService; this.tagService = tagService; this.eventService = eventService; + this.schedulerRepository = schedulerRepository; } public List findAll() { @@ -97,6 +110,11 @@ public class TaskService { @Transactional public void delete(Integer taskId) throws IOException { if (taskRepository.exists(taskId)) { + Task scheduleTask = taskRepository.findOne(taskId); + Scheduler sch = schedulerRepository.findOneByTask(scheduleTask); + if (sch != null) { + schedulerRepository.delete(sch.getId()); + } taskRepository.delete(taskId); } @@ -110,6 +128,110 @@ public class TaskService { } } + public void copyMainPart(Task newTask, Task task) { + newTask.setTitle(task.getTitle()); + newTask.setTags(tagService.saveOrCreate(task.getTags())); + newTask.setCreateDate(new Date()); + newTask.setStatus(Task.TaskStatus.LOADED_FROM_KIAS); + } + + public Task copyTaskWithNewDates(Task task) { + Task newTask = new Task(); + copyMainPart(newTask, task); + Calendar cal1 = DateUtils.getCalendar(newTask.getCreateDate()); + Calendar cal2 = DateUtils.getCalendar(task.getCreateDate()); + Integer interval = cal1.get(Calendar.DAY_OF_YEAR) - cal2.get(Calendar.DAY_OF_YEAR); + newTask.setDeadlines(newDatesDeadlines(task.getDeadlines(), interval)); + return newTask; + } + + private List newDatesDeadlines(List deadlines, Integer interval) { + return deadlines + .stream() + .map(deadline -> { + Deadline newDeadline = new Deadline(); + Date newDate = DateUtils.addDays(deadline.getDate(), interval); + newDeadline.setDescription(deadline.getDescription()); + newDeadline.setDate(newDate); + return deadlineService.create(newDeadline); + }).collect(Collectors.toList()); + } + + public Task copyTaskWithNewYear(Task task) { + Task newTask = new Task(); + copyMainPart(newTask, task); + newTask.setDeadlines(newYearDeadlines(task.getDeadlines())); + return newTask; + } + + private List newYearDeadlines(List deadlines) { + return deadlines + .stream() + .map(deadline -> { + Deadline newDeadline = new Deadline(); + newDeadline.setDescription(deadline.getDescription()); + newDeadline.setDate(DateUtils.addYears(deadline.getDate(), 1)); + return deadlineService.create(newDeadline); + }).collect(Collectors.toList()); + } + + private boolean equalsDate(Task task) { + Calendar taskDate = DateUtils.getCalendar(task.getCreateDate()); + Calendar nowDate = DateUtils.getCalendar(new Date()); + return (taskDate.get(Calendar.DAY_OF_MONTH) == nowDate.get(Calendar.DAY_OF_MONTH) && + taskDate.get(Calendar.MONTH) + 1 == nowDate.get(Calendar.MONTH) + 1 && + taskDate.get(Calendar.YEAR) + 1 == nowDate.get(Calendar.YEAR)); + } + + @Transactional + public void generateYearTasks() { + Set tags = checkRepeatingTags(false); + List tasks = new ArrayList<>(); + tags.forEach(tag -> { + Task singleTask = findTasksByTag(tag).get(0); + if (equalsDate(singleTask)) { + if (!tasks.contains(singleTask)) { + tasks.add(singleTask); + } + } + }); + if (tasks != null) { + tasks.forEach(task -> { + Task newTask = copyTaskWithNewYear(task); + taskRepository.save(newTask); + }); + } + } + + + @Transactional + public Set checkRepeatingTags(Boolean createPeriodTask) { //param: false = year task; true = period task + Map tagsCount = new TreeMap<>(); + List tags = tagService.getTags(); + List tasks = taskRepository.findAllYear(DateUtils.clearTime(DateUtils.addYears(new Date(), -1))); + tags.forEach(tag -> + tagsCount.put(tag, tasks + .stream() + .filter(task -> task.getTags().contains(tag)) + .count())); + if (!createPeriodTask) { + return tagsCount + .entrySet() + .stream() + .filter(tagLongEntry -> tagLongEntry.getValue() == 1) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)) + .keySet(); + } else { + return tagsCount + .entrySet() + .stream() + .filter(tagLongEntry -> tagLongEntry.getValue() >= 2) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)) + .keySet(); + } + + } + public List getTaskStatuses() { return Arrays.asList(Task.TaskStatus.values()); } @@ -118,4 +240,13 @@ public class TaskService { return tagService.getTags(); } + public List findTasksByTag(Tag tag) { + return taskRepository.findByTag(tag); + } + + @Transactional + public void createPeriodTask(Scheduler scheduler) { + Task newTask = copyTaskWithNewDates(scheduler.getTask()); + taskRepository.save(newTask); + } } diff --git a/src/main/java/ru/ulstu/tags/model/Tag.java b/src/main/java/ru/ulstu/tags/model/Tag.java index aed000f..e1c63d2 100644 --- a/src/main/java/ru/ulstu/tags/model/Tag.java +++ b/src/main/java/ru/ulstu/tags/model/Tag.java @@ -9,6 +9,7 @@ import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; import javax.validation.constraints.Size; +import java.util.Objects; @Entity @Table(name = "tag") @@ -41,4 +42,21 @@ public class Tag extends BaseEntity { public void setTagName(String tagName) { this.tagName = tagName; } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Tag tag = (Tag) o; + return tagName.equals(tag.tagName); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), tagName); + } } diff --git a/src/main/resources/db/changelog-20190505_000000-schema.xml b/src/main/resources/db/changelog-20190505_000000-schema.xml index ac8707a..ad56dac 100644 --- a/src/main/resources/db/changelog-20190505_000000-schema.xml +++ b/src/main/resources/db/changelog-20190505_000000-schema.xml @@ -2,6 +2,7 @@ + diff --git a/src/main/resources/db/changelog-20190505_000001-schema.xml b/src/main/resources/db/changelog-20190505_000001-schema.xml new file mode 100644 index 0000000..1148d3a --- /dev/null +++ b/src/main/resources/db/changelog-20190505_000001-schema.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/db/changelog-master.xml b/src/main/resources/db/changelog-master.xml index 98e3c17..18bd645 100644 --- a/src/main/resources/db/changelog-master.xml +++ b/src/main/resources/db/changelog-master.xml @@ -38,6 +38,7 @@ + diff --git a/src/main/resources/public/css/conference.css b/src/main/resources/public/css/conference.css index dc83057..60a866d 100644 --- a/src/main/resources/public/css/conference.css +++ b/src/main/resources/public/css/conference.css @@ -23,11 +23,17 @@ body { text-decoration: none; margin: 0; } - .conference-row .d-flex .text-decoration:nth-child(1) { margin-left: 5px; } +.conference-row .d-flex .text-decoration span.h6.float-left.m-2 { + max-width: 470px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + .conference-row .d-flex .icon-delete { width: 29px; height: 29px; diff --git a/src/main/resources/public/css/tasks.css b/src/main/resources/public/css/tasks.css index 1c190b5..936dd84 100644 --- a/src/main/resources/public/css/tasks.css +++ b/src/main/resources/public/css/tasks.css @@ -38,6 +38,29 @@ width: auto; max-width: inherit; } +.tag-info{ + font-size: 10px; + color: white; + padding: 5px 15px; + background-color: black; + display: none; + margin-left: 5px; + border-radius: 5px; + opacity: 0.8; + font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; +} + +.fa-question-circle{ + + font-size: 15px; + color: #212529; + cursor:pointer; +} + +.fa-question-circle:hover .tag-info{ + display:inline-block; + +} .task-row{ diff --git a/src/main/resources/public/js/tasks.js b/src/main/resources/public/js/tasks.js index 84b9567..f1cf868 100644 --- a/src/main/resources/public/js/tasks.js +++ b/src/main/resources/public/js/tasks.js @@ -19,8 +19,16 @@ $(document).ready(function () { $("#input-tag").keyup(function (event) { - if(event.keyCode == 13 || event.keyCode == 188) { + if(event.keyCode == 13) { var tagNumber = $("#tags .tag").length; + if(tagNumber > 0) { + tagNumber = $("#tags .tag").last() + .children('input') + .attr("name") + .split(']')[0] + .split('[')[1]; + tagNumber++; + } var tagName = $.trim($(this).val()); var addTag = true; // проверка, добавлен ли этот тег diff --git a/src/main/resources/public/js/users.js b/src/main/resources/public/js/users.js index 3f4af95..76bd41d 100644 --- a/src/main/resources/public/js/users.js +++ b/src/main/resources/public/js/users.js @@ -4,12 +4,12 @@ function changePassword() { confirmPassword = document.getElementById("confirmPassword").value if ([oldPassword.length, password.length, confirmPassword.length].includes(0)) { - alert("Заполните все поля"); + showFeedbackMessage("Заполните все поля", MessageTypesEnum.WARNING); return; } if (password != confirmPassword) { - alert("Повторный пароль введен неверно"); + showFeedbackMessage("Повторный пароль введен неверно", MessageTypesEnum.WARNING); return; } @@ -17,9 +17,9 @@ function changePassword() { url:"/api/1.0/users/changePassword", contentType: "application/json; charset=utf-8", data: JSON.stringify({ - "oldPassword": document.getElementById("oldPassword").value, - "password": document.getElementById("password").value, - "confirmPassword": document.getElementById("confirmPassword").value, + "oldPassword": oldPassword, + "password": password, + "confirmPassword": confirmPassword, }), method: "POST", success: function() { @@ -39,7 +39,7 @@ function inviteUser() { if (!re.test(email)) { - alert("Некорректный почтовый ящик") + showFeedbackMessage("Некорректный почтовый ящик", MessageTypesEnum.WARNING); return; } diff --git a/src/main/resources/templates/conferences/dashboard.html b/src/main/resources/templates/conferences/dashboard.html index 86be4f2..e8cfa49 100644 --- a/src/main/resources/templates/conferences/dashboard.html +++ b/src/main/resources/templates/conferences/dashboard.html @@ -24,24 +24,24 @@
- - + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/templates/students/task.html b/src/main/resources/templates/students/task.html index 968c7a0..3642221 100644 --- a/src/main/resources/templates/students/task.html +++ b/src/main/resources/templates/students/task.html @@ -52,7 +52,7 @@
- +
diff --git a/src/test/java/ru/ulstu/conference/service/ConferenceServiceTest.java b/src/test/java/ru/ulstu/conference/service/ConferenceServiceTest.java new file mode 100644 index 0000000..95f4820 --- /dev/null +++ b/src/test/java/ru/ulstu/conference/service/ConferenceServiceTest.java @@ -0,0 +1,289 @@ +package ru.ulstu.conference.service; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.data.domain.Sort; +import ru.ulstu.conference.model.Conference; +import ru.ulstu.conference.model.ConferenceDto; +import ru.ulstu.conference.model.ConferenceFilterDto; +import ru.ulstu.conference.model.ConferenceUser; +import ru.ulstu.conference.repository.ConferenceRepository; +import ru.ulstu.deadline.model.Deadline; +import ru.ulstu.deadline.service.DeadlineService; +import ru.ulstu.paper.model.Paper; +import ru.ulstu.paper.service.PaperService; +import ru.ulstu.ping.model.Ping; +import ru.ulstu.ping.service.PingService; +import ru.ulstu.timeline.service.EventService; +import ru.ulstu.user.model.User; +import ru.ulstu.user.service.UserService; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class ConferenceServiceTest { + + @Mock + ConferenceRepository conferenceRepository; + + @Mock + DeadlineService deadlineService; + + @Mock + ConferenceUserService conferenceUserService; + + @Mock + PaperService paperService; + + @Mock + UserService userService; + + @Mock + EventService eventService; + + @Mock + ConferenceNotificationService conferenceNotificationService; + + @Mock + PingService pingService; + + @InjectMocks + ConferenceService conferenceService; + + private final static Integer ID = 1; + private final static Integer INDEX = 0; + private final static String NAME = "Name"; + private final static String DESCRIPTION = "Desc"; + private final static boolean TRUE = true; + private final static Integer YEAR = 2019; + private final static Sort SORT = new Sort(Sort.Direction.DESC, "beginDate"); + + private List conferences; + private List deadlines; + private List papers; + private List conferenceUsers; + + private Conference conferenceWithId; + + private Paper paperWithId; + private Paper paperWithoutId; + + private ConferenceDto conferenceDto; + private User user; + private Deadline deadline; + + @Before + public void setUp() throws Exception { + conferences = new ArrayList<>(); + conferenceWithId = new Conference(); + + conferenceWithId.setId(ID); + conferenceWithId.setTitle(NAME); + conferenceWithId.setDescription(DESCRIPTION); + + paperWithId = new Paper(); + paperWithId.setId(1); + paperWithId.setTitle(NAME); + + paperWithoutId = new Paper(); + paperWithoutId.setTitle(NAME); + + papers = new ArrayList<>(); + papers.add(paperWithId); + papers.add(paperWithoutId); + + deadlines = new ArrayList<>(); + deadline = new Deadline(new Date(), DESCRIPTION); + deadline.setId(ID); + deadlines.add(deadline); + + ConferenceUser conferenceUser = new ConferenceUser(); + conferenceUser.setDeposit(ConferenceUser.Deposit.ARTICLE); + conferenceUser.setParticipation(ConferenceUser.Participation.INTRAMURAL); + user = new User(); + user.setFirstName(NAME); + conferenceUser.setUser(user); + + conferenceUsers = new ArrayList<>(); + conferenceUsers.add(conferenceUser); + + conferences.add(conferenceWithId); + conferenceDto = new ConferenceDto(conferenceWithId); + } + + @Test + public void getExistConferenceById() { + when(conferenceRepository.findOne(ID)).thenReturn(conferenceWithId); + when(paperService.findAllNotSelect(new ArrayList<>())).thenReturn(papers); + when(userService.getCurrentUser()).thenReturn(user); + + ConferenceDto newConferenceDto = new ConferenceDto(conferenceWithId); + newConferenceDto.setNotSelectedPapers(papers); + newConferenceDto.setDisabledTakePart(!TRUE); + ConferenceDto result = conferenceService.getExistConferenceById(ID); + + assertEquals(newConferenceDto.getId(), result.getId()); + assertEquals(newConferenceDto.getNotSelectedPapers(), result.getNotSelectedPapers()); + assertEquals(newConferenceDto.isDisabledTakePart(), result.isDisabledTakePart()); + } + + @Test + public void getNewConference() { + when(paperService.findAllNotSelect(new ArrayList<>())).thenReturn(papers); + + ConferenceDto newConferenceDto = new ConferenceDto(); + newConferenceDto.setNotSelectedPapers(papers); + ConferenceDto result = conferenceService.getNewConference(); + + assertEquals(newConferenceDto.getId(), result.getId()); + assertEquals(newConferenceDto.getNotSelectedPapers(), result.getNotSelectedPapers()); + assertEquals(newConferenceDto.isDisabledTakePart(), result.isDisabledTakePart()); + } + + @Test + public void findAll() { + when(conferenceRepository.findAll(SORT)).thenReturn(conferences); + + assertEquals(Collections.singletonList(conferenceWithId), conferenceService.findAll()); + } + + @Test + public void create() throws IOException { + when(paperService.findPaperById(ID)).thenReturn(paperWithId); + when(paperService.create(new Paper())).thenReturn(paperWithoutId); + when(deadlineService.saveOrCreate(new ArrayList<>())).thenReturn(deadlines); + when(conferenceUserService.saveOrCreate(new ArrayList<>())).thenReturn(conferenceUsers); + when(conferenceRepository.save(new Conference())).thenReturn(conferenceWithId); + + conferenceDto.setPapers(papers); + conferenceDto.setDeadlines(deadlines); + conferenceDto.setUsers(conferenceUsers); + conferenceDto.getPaperIds().add(ID); + + Conference newConference = new Conference(); + newConference.setId(ID); + newConference.setTitle(NAME); + newConference.setDescription(DESCRIPTION); + newConference.setPapers(papers); + newConference.getPapers().add(paperWithId); + newConference.setDeadlines(deadlines); + newConference.setUsers(conferenceUsers); + + assertEquals(newConference, conferenceService.create(conferenceDto)); + } + + @Test + public void delete() { + when(conferenceRepository.exists(ID)).thenReturn(true); + when(conferenceRepository.findOne(ID)).thenReturn(conferenceWithId); + assertTrue(conferenceService.delete(ID)); + } + + @Test + public void addDeadline() { + ConferenceDto newConferenceDto = new ConferenceDto(); + newConferenceDto.getDeadlines().add(new Deadline()); + conferenceDto.getDeadlines().clear(); + + assertEquals(newConferenceDto.getDeadlines().get(0), conferenceService.addDeadline(conferenceDto).getDeadlines().get(0)); + } + + @Test + public void removeDeadline() throws IOException { + ConferenceDto newConferenceDto = new ConferenceDto(); + newConferenceDto.getRemovedDeadlineIds().add(ID); + conferenceDto.getDeadlines().add(deadline); + ConferenceDto result = conferenceService.removeDeadline(conferenceDto, INDEX); + + assertEquals(newConferenceDto.getDeadlines(), result.getDeadlines()); + assertEquals(newConferenceDto.getRemovedDeadlineIds(), result.getRemovedDeadlineIds()); + } + + @Test + public void addPaper() { + when(userService.getCurrentUser()).thenReturn(user); + + ConferenceDto newConferenceDto = new ConferenceDto(); + newConferenceDto.getPapers().add(paperWithoutId); + conferenceDto.getPapers().clear(); + ConferenceDto result = conferenceService.addPaper(conferenceDto); + result.getPapers().get(INDEX).setTitle(NAME); // приходится вручную назначать название, т.е. название зависит от даты + + assertEquals(newConferenceDto.getPapers(), result.getPapers()); + } + + @Test + public void removePaper() throws IOException { + ConferenceDto newConferenceDto = new ConferenceDto(); + newConferenceDto.getNotSelectedPapers().add(paperWithId); + newConferenceDto.getPapers().add(paperWithoutId); + conferenceDto.getPapers().add(paperWithId); + conferenceDto.getPapers().add(paperWithoutId); + ConferenceDto result = conferenceService.removePaper(conferenceDto, INDEX); + + assertEquals(newConferenceDto.getPapers(), result.getPapers()); + assertEquals(newConferenceDto.getNotSelectedPapers(), result.getNotSelectedPapers()); + } + + @Test + public void takePart() throws IOException { + when(userService.getCurrentUser()).thenReturn(user); + + ConferenceDto newConferenceDto = new ConferenceDto(); + newConferenceDto.setUsers(conferenceUsers); + newConferenceDto.setDisabledTakePart(TRUE); + conferenceDto.getPapers().clear(); + ConferenceDto result = conferenceService.takePart(conferenceDto); + + assertEquals(newConferenceDto.getUsers(), result.getUsers()); + assertEquals(newConferenceDto.isDisabledTakePart(), result.isDisabledTakePart()); + } + + @Test + public void getAllUsers() { + List users = Collections.singletonList(user); + when(userService.findAll()).thenReturn(users); + assertEquals(users, conferenceService.getAllUsers()); + } + + @Test + public void filter() { + when(userService.findById(ID)).thenReturn(user); + when(conferenceRepository.findByUserAndYear(user, YEAR)).thenReturn(conferences); + + ConferenceFilterDto conferenceFilterDto = new ConferenceFilterDto(); + conferenceFilterDto.setFilterUserId(ID); + conferenceFilterDto.setYear(YEAR); + + assertEquals(Collections.singletonList(conferenceDto), conferenceService.filter(conferenceFilterDto)); + } + + @Test + public void isAttachedToConference() { + when(conferenceRepository.isPaperAttached(ID)).thenReturn(TRUE); + + assertTrue(conferenceService.isAttachedToConference(ID)); + } + + @Test + public void ping() throws IOException { + Ping ping = new Ping(); + when(conferenceRepository.findOne(ID)).thenReturn(conferenceWithId); + when(pingService.addPing(conferenceWithId)).thenReturn(ping); + when(conferenceRepository.updatePingConference(ID)).thenReturn(INDEX); + + assertEquals(ping, conferenceService.ping(conferenceDto)); + } +} \ No newline at end of file