package ru.ulstu.activity.students.service; import org.springframework.data.domain.Page; import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import ru.ulstu.activity.common.service.ActivityService; import ru.ulstu.activity.deadline.model.Deadline; import ru.ulstu.activity.deadline.service.DeadlineService; import ru.ulstu.activity.ping.service.PingService; import ru.ulstu.activity.students.model.Scheduler; import ru.ulstu.activity.students.model.Task; import ru.ulstu.activity.students.model.TaskDashboardDto; import ru.ulstu.activity.students.model.TaskDto; import ru.ulstu.activity.students.model.TaskFilterDto; import ru.ulstu.activity.students.model.TaskListDto; import ru.ulstu.activity.tags.model.Tag; import ru.ulstu.activity.tags.service.TagService; import ru.ulstu.activity.timeline.model.Event; import ru.ulstu.activity.timeline.service.EventService; import ru.ulstu.core.jpa.OffsetablePageRequest; import ru.ulstu.core.model.response.PageableItems; import ru.ulstu.core.util.DateUtils; import javax.persistence.EntityNotFoundException; 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 ru.ulstu.activity.students.model.Task.TaskStatus.IN_WORK; import static ru.ulstu.core.util.StreamApiUtils.convert; import static ru.ulstu.core.util.StreamApiUtils.convertPageable; @Service public class TaskService extends ActivityService { private final TaskRepository taskRepository; private final TaskNotificationService taskNotificationService; private final SchedulerRepository schedulerRepository; private final DeadlineService deadlineService; private final TagService tagService; private final EventService eventService; private final PingService pingService; public TaskService(TaskRepository taskRepository, TaskNotificationService taskNotificationService, DeadlineService deadlineService, TagService tagService, SchedulerRepository schedulerRepository, EventService eventService, PingService pingService) { super(taskRepository, taskNotificationService, pingService, eventService); this.taskRepository = taskRepository; this.taskNotificationService = taskNotificationService; this.deadlineService = deadlineService; this.tagService = tagService; this.eventService = eventService; this.schedulerRepository = schedulerRepository; this.pingService = pingService; } public List findAll() { return taskRepository.findAll(new Sort(Sort.Direction.DESC, "createDate")); } public PageableItems findAll(int offset, int count) { final Page page = taskRepository.findAll(new OffsetablePageRequest(offset, count)); return new PageableItems<>(page.getTotalElements(), page.getContent()); } @Override protected TaskListDto getActivityListDto(Task entity) { return new TaskListDto(entity); } @Override protected Task getNewActivity() { return new Task(); } @Override protected TaskDto getNewActivityDto(Task entity) { return new TaskDto(entity); } public List filter(TaskFilterDto filterDto) { if (filterDto.getOrder().compareTo("new") == 0) { return convert(taskRepository.filterNew( filterDto.getStatus(), filterDto.getTag() == null ? null : tagService.findById(filterDto.getTag())), TaskDto::new); } else { return convert(taskRepository.filterOld( filterDto.getStatus(), filterDto.getTag() == null ? null : tagService.findById(filterDto.getTag())), TaskDto::new); } } protected Task copyFromDto(Task task, TaskDto taskDto) { task.setTitle(taskDto.getTitle()); task.setDescription(taskDto.getDescription()); task.setStatus(taskDto.getStatus() == null ? IN_WORK : taskDto.getStatus()); task.setDeadlines(deadlineService.saveOrCreate(taskDto.getDeadlines())); task.setCreateDate(task.getCreateDate() == null ? new Date() : task.getCreateDate()); task.setUpdateDate(new Date()); task.getTags().clear(); //task.setTags(tagService.saveOrCreate(taskDto.getTags())); return task; } @Override protected List getEvents(Task entity) { return eventService.findByTask(entity); } private 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); } private 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()); } private 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 List 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); }); return tasks; } return null; } @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()); } public List getTags() { return tagService.getTags(); } public List findTasksByTag(Tag tag) { return taskRepository.findByTag(tag); } @Transactional public Task createPeriodTask(Scheduler scheduler) { Task newTask = copyTaskWithNewDates(scheduler.getTask()); taskRepository.save(newTask); return newTask; } @Override public PageableItems findAllActiveDto(int offset, int count) { return convertPageable(findAllActive(offset, count), TaskDashboardDto::new); } @Override public PageableItems findAllActive(int offset, int count) { return findAll(offset, count); } public TaskDto findTaskById(Integer taskId) { return new TaskDto(findById(taskId)); } public Task findById(Integer taskId) { return taskRepository.findById(taskId) .orElseThrow(() -> new EntityNotFoundException("Paper with id=" + taskId + " not found")); } @Transactional public void ping(int taskId) { pingService.addPing(findById(taskId)); } }