Merge branch '18-paper-timeline' into 'dev'

Resolve "Реализовать добавление в таймлайн событий по дедлайнам статей"

Closes #18

See merge request romanov73/ng-tracker!39
This commit is contained in:
Anton Romanov 2019-03-30 07:12:26 +00:00
commit 76d4c15db5
11 changed files with 125 additions and 4 deletions

View File

@ -7,6 +7,7 @@ import ru.ulstu.core.model.BaseEntity;
import ru.ulstu.core.model.UserContainer; import ru.ulstu.core.model.UserContainer;
import ru.ulstu.deadline.model.Deadline; import ru.ulstu.deadline.model.Deadline;
import ru.ulstu.file.model.FileData; import ru.ulstu.file.model.FileData;
import ru.ulstu.timeline.model.Event;
import ru.ulstu.user.model.User; import ru.ulstu.user.model.User;
import javax.persistence.CascadeType; import javax.persistence.CascadeType;
@ -78,6 +79,9 @@ public class Paper extends BaseEntity implements UserContainer {
private Boolean locked = false; private Boolean locked = false;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "paper_id")
private List<Event> events = new ArrayList<>();
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "paper_id", unique = true) @JoinColumn(name = "paper_id", unique = true)
@ -159,6 +163,14 @@ public class Paper extends BaseEntity implements UserContainer {
this.authors = authors; this.authors = authors;
} }
public List<Event> getEvents() {
return events;
}
public void setEvents(List<Event> events) {
this.events = events;
}
public String getUrl() { public String getUrl() {
return url; return url;
} }

View File

@ -11,6 +11,7 @@ import ru.ulstu.paper.model.Paper;
import ru.ulstu.paper.model.PaperDto; import ru.ulstu.paper.model.PaperDto;
import ru.ulstu.paper.model.PaperFilterDto; import ru.ulstu.paper.model.PaperFilterDto;
import ru.ulstu.paper.repository.PaperRepository; import ru.ulstu.paper.repository.PaperRepository;
import ru.ulstu.timeline.service.EventService;
import ru.ulstu.user.model.User; import ru.ulstu.user.model.User;
import ru.ulstu.user.service.UserService; import ru.ulstu.user.service.UserService;
@ -39,17 +40,20 @@ public class PaperService {
private final UserService userService; private final UserService userService;
private final DeadlineService deadlineService; private final DeadlineService deadlineService;
private final FileService fileService; private final FileService fileService;
private final EventService eventService;
public PaperService(PaperRepository paperRepository, public PaperService(PaperRepository paperRepository,
FileService fileService, FileService fileService,
PaperNotificationService paperNotificationService, PaperNotificationService paperNotificationService,
UserService userService, UserService userService,
DeadlineService deadlineService) { DeadlineService deadlineService,
EventService eventService) {
this.paperRepository = paperRepository; this.paperRepository = paperRepository;
this.fileService = fileService; this.fileService = fileService;
this.paperNotificationService = paperNotificationService; this.paperNotificationService = paperNotificationService;
this.userService = userService; this.userService = userService;
this.deadlineService = deadlineService; this.deadlineService = deadlineService;
this.eventService = eventService;
} }
public List<Paper> findAll() { public List<Paper> findAll() {
@ -78,6 +82,7 @@ public class PaperService {
Paper newPaper = copyFromDto(new Paper(), paperDto); Paper newPaper = copyFromDto(new Paper(), paperDto);
newPaper = paperRepository.save(newPaper); newPaper = paperRepository.save(newPaper);
paperNotificationService.sendCreateNotification(newPaper); paperNotificationService.sendCreateNotification(newPaper);
eventService.createFromPaper(newPaper);
return newPaper.getId(); return newPaper.getId();
} }
@ -112,6 +117,7 @@ public class PaperService {
fileService.delete(file.getId()); fileService.delete(file.getId());
} }
paperRepository.save(copyFromDto(paper, paperDto)); paperRepository.save(copyFromDto(paper, paperDto));
eventService.updatePaperDeadlines(paper);
paper.getAuthors().forEach(author -> { paper.getAuthors().forEach(author -> {
if (!oldAuthors.contains(author)) { if (!oldAuthors.contains(author)) {
@ -127,7 +133,7 @@ public class PaperService {
} }
@Transactional @Transactional
public void delete(Integer paperId) throws IOException { public void delete(Integer paperId) {
Paper paper = paperRepository.findOne(paperId); Paper paper = paperRepository.findOne(paperId);
paperRepository.delete(paper); paperRepository.delete(paper);
} }
@ -148,6 +154,7 @@ public class PaperService {
paper = paperRepository.save(paper); paper = paperRepository.save(paper);
paperNotificationService.sendCreateNotification(paper); paperNotificationService.sendCreateNotification(paper);
eventService.createFromPaper(paper);
return paper; return paper;
} }

View File

@ -2,6 +2,7 @@ package ru.ulstu.timeline.model;
import org.hibernate.validator.constraints.NotBlank; import org.hibernate.validator.constraints.NotBlank;
import ru.ulstu.core.model.BaseEntity; import ru.ulstu.core.model.BaseEntity;
import ru.ulstu.paper.model.Paper;
import ru.ulstu.user.model.User; import ru.ulstu.user.model.User;
import javax.persistence.CascadeType; import javax.persistence.CascadeType;
@ -71,6 +72,10 @@ public class Event extends BaseEntity {
@JoinColumn(name = "child_id") @JoinColumn(name = "child_id")
private List<Event> parents; private List<Event> parents;
@ManyToOne
@JoinColumn(name = "paper_id")
private Paper paper;
public String getTitle() { public String getTitle() {
return title; return title;
} }
@ -150,4 +155,12 @@ public class Event extends BaseEntity {
public void setParents(List<Event> parents) { public void setParents(List<Event> parents) {
this.parents = parents; this.parents = parents;
} }
public Paper getPaper() {
return paper;
}
public void setPaper(Paper paper) {
this.paper = paper;
}
} }

View File

@ -3,6 +3,7 @@ package ru.ulstu.timeline.model;
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import org.hibernate.validator.constraints.NotBlank; import org.hibernate.validator.constraints.NotBlank;
import ru.ulstu.paper.model.PaperDto;
import ru.ulstu.user.model.UserDto; import ru.ulstu.user.model.UserDto;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
@ -23,6 +24,7 @@ public class EventDto {
private final Date updateDate; private final Date updateDate;
private final String description; private final String description;
private final List<UserDto> recipients; private final List<UserDto> recipients;
private PaperDto paperDto;
@JsonCreator @JsonCreator
public EventDto(@JsonProperty("id") Integer id, public EventDto(@JsonProperty("id") Integer id,
@ -33,6 +35,7 @@ public class EventDto {
@JsonProperty("createDate") Date createDate, @JsonProperty("createDate") Date createDate,
@JsonProperty("updateDate") Date updateDate, @JsonProperty("updateDate") Date updateDate,
@JsonProperty("description") String description, @JsonProperty("description") String description,
@JsonProperty("paperDto") PaperDto paperDto,
@JsonProperty("recipients") List<UserDto> recipients) { @JsonProperty("recipients") List<UserDto> recipients) {
this.id = id; this.id = id;
this.title = title; this.title = title;
@ -43,6 +46,7 @@ public class EventDto {
this.updateDate = updateDate; this.updateDate = updateDate;
this.description = description; this.description = description;
this.recipients = recipients; this.recipients = recipients;
this.paperDto = paperDto;
} }
public EventDto(Event event) { public EventDto(Event event) {
@ -54,6 +58,7 @@ public class EventDto {
this.createDate = event.getCreateDate(); this.createDate = event.getCreateDate();
this.updateDate = event.getUpdateDate(); this.updateDate = event.getUpdateDate();
this.description = event.getDescription(); this.description = event.getDescription();
this.paperDto = new PaperDto(event.getPaper());
this.recipients = convert(event.getRecipients(), UserDto::new); this.recipients = convert(event.getRecipients(), UserDto::new);
} }
@ -92,4 +97,12 @@ public class EventDto {
public Date getExecuteDate() { public Date getExecuteDate() {
return executeDate; return executeDate;
} }
public PaperDto getPaperDto() {
return paperDto;
}
public void setPaperDto(PaperDto paperDto) {
this.paperDto = paperDto;
}
} }

View File

@ -6,6 +6,7 @@ import javax.persistence.CascadeType;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.JoinColumn; import javax.persistence.JoinColumn;
import javax.persistence.OneToMany; import javax.persistence.OneToMany;
import java.util.ArrayList;
import java.util.List; import java.util.List;
@Entity @Entity
@ -13,7 +14,7 @@ public class Timeline extends BaseEntity {
@OneToMany(cascade = CascadeType.ALL) @OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "timeline_id") @JoinColumn(name = "timeline_id")
private List<Event> events; private List<Event> events = new ArrayList<>();
public List<Event> getEvents() { public List<Event> getEvents() {
return events; return events;

View File

@ -2,6 +2,7 @@ package ru.ulstu.timeline.repository;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
import ru.ulstu.paper.model.Paper;
import ru.ulstu.timeline.model.Event; import ru.ulstu.timeline.model.Event;
import java.util.List; import java.util.List;
@ -12,4 +13,6 @@ public interface EventRepository extends JpaRepository<Event, Integer> {
@Query("SELECT e FROM Event e WHERE e.executeDate > CURRENT_DATE ORDER BY e.executeDate") @Query("SELECT e FROM Event e WHERE e.executeDate > CURRENT_DATE ORDER BY e.executeDate")
List<Event> findAllFuture(); List<Event> findAllFuture();
List<Event> findAllByPaper(Paper paper);
} }

View File

@ -34,6 +34,10 @@ public class EventScheduler {
Map<String, Object> variables = ImmutableMap.of("description", event.getDescription()); Map<String, Object> variables = ImmutableMap.of("description", event.getDescription());
event.getRecipients() event.getRecipients()
.forEach(recipient -> mailService.sendEmailFromTemplate(variables, recipient, "eventNotification", event.getTitle())); .forEach(recipient -> mailService.sendEmailFromTemplate(variables, recipient, "eventNotification", event.getTitle()));
if (event.getPeriod() == null) {
event.setStatus(Event.EventStatus.COMPLETED);
eventService.save(event);
}
}); });
} }

View File

@ -1,15 +1,22 @@
package ru.ulstu.timeline.service; package ru.ulstu.timeline.service;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import ru.ulstu.deadline.model.Deadline;
import ru.ulstu.paper.model.Paper;
import ru.ulstu.timeline.model.Event; import ru.ulstu.timeline.model.Event;
import ru.ulstu.timeline.model.EventDto; import ru.ulstu.timeline.model.EventDto;
import ru.ulstu.timeline.model.Timeline;
import ru.ulstu.timeline.repository.EventRepository; import ru.ulstu.timeline.repository.EventRepository;
import ru.ulstu.user.model.UserDto; import ru.ulstu.user.model.UserDto;
import ru.ulstu.user.service.UserService; import ru.ulstu.user.service.UserService;
import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import static ru.ulstu.core.util.StreamApiUtils.convert; import static ru.ulstu.core.util.StreamApiUtils.convert;
@ -17,11 +24,14 @@ import static ru.ulstu.core.util.StreamApiUtils.convert;
public class EventService { public class EventService {
private final EventRepository eventRepository; private final EventRepository eventRepository;
private final TimelineService timelineService;
private final UserService userService; private final UserService userService;
public EventService(EventRepository eventRepository, public EventService(EventRepository eventRepository,
@Lazy TimelineService timelineService,
UserService userService) { UserService userService) {
this.eventRepository = eventRepository; this.eventRepository = eventRepository;
this.timelineService = timelineService;
this.userService = userService; this.userService = userService;
} }
@ -56,6 +66,11 @@ public class EventService {
return eventRepository.save(copyFromDto(event, eventDto)).getId(); return eventRepository.save(copyFromDto(event, eventDto)).getId();
} }
@Transactional
public Event save(Event event) {
return eventRepository.save(event);
}
@Transactional @Transactional
public void delete(Integer eventId) { public void delete(Integer eventId) {
Event event = eventRepository.findOne(eventId); Event event = eventRepository.findOne(eventId);
@ -84,6 +99,36 @@ public class EventService {
eventRepository.save(parentEvent); eventRepository.save(parentEvent);
} }
public void createFromPaper(Paper newPaper) {
List<Timeline> timelines = timelineService.findAll();
Timeline timeline = timelines.isEmpty() ? new Timeline() : timelines.get(0);
for (Deadline deadline : newPaper.getDeadlines()
.stream()
.filter(d -> d.getDate().after(new Date()) || DateUtils.isSameDay(d.getDate(), new Date()))
.collect(Collectors.toList())) {
Event newEvent = new Event();
newEvent.setTitle("Дедлайн статьи");
newEvent.setStatus(Event.EventStatus.NEW);
newEvent.setExecuteDate(deadline.getDate());
newEvent.setCreateDate(new Date());
newEvent.setUpdateDate(new Date());
newEvent.setDescription("Дедлайн '" + deadline.getDescription() + "' cтатьи '" + newPaper.getTitle() + "'");
newEvent.setRecipients(new ArrayList(newPaper.getAuthors()));
newEvent.setPaper(newPaper);
eventRepository.save(newEvent);
timeline.getEvents().add(newEvent);
timelineService.save(timeline);
}
}
public void updatePaperDeadlines(Paper paper) {
eventRepository.delete(eventRepository.findAllByPaper(paper));
createFromPaper(paper);
}
public List<Event> findByCurrentDate() { public List<Event> findByCurrentDate() {
return eventRepository.findByCurrentDate(); return eventRepository.findByCurrentDate();
} }

View File

@ -23,15 +23,24 @@ public class TimelineService {
this.eventService = eventService; this.eventService = eventService;
} }
public List<TimelineDto> findAll() { public List<TimelineDto> findAllDto() {
return convert(timelineRepository.findAll(), TimelineDto::new); return convert(timelineRepository.findAll(), TimelineDto::new);
} }
public List<Timeline> findAll() {
return timelineRepository.findAll();
}
@Transactional @Transactional
public int create(TimelineDto timelineDto) { public int create(TimelineDto timelineDto) {
return timelineRepository.save(copyFromDto(new Timeline(), timelineDto)).getId(); return timelineRepository.save(copyFromDto(new Timeline(), timelineDto)).getId();
} }
@Transactional
public Timeline save(Timeline timeline) {
return timelineRepository.save(timeline);
}
private Timeline copyFromDto(Timeline timeline, TimelineDto timelineDto) { private Timeline copyFromDto(Timeline timeline, TimelineDto timelineDto) {
timeline.setEvents(eventService.findByIds(convert(timelineDto.getEvents(), EventDto::getId))); timeline.setEvents(eventService.findByIds(convert(timelineDto.getEvents(), EventDto::getId)));
return timeline; return timeline;

View File

@ -0,0 +1,13 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="masha" id="20190327_000000-1">
<addColumn tableName="event">
<column name="paper_id" type="integer"/>
</addColumn>
<addForeignKeyConstraint baseTableName="event" baseColumnNames="paper_id"
constraintName="fk_event_paper_id" referencedTableName="paper"
referencedColumnNames="id"/>
</changeSet>
</databaseChangeLog>

View File

@ -20,5 +20,6 @@
<include file="db/changelog-20181224_000000-schema.xml"/> <include file="db/changelog-20181224_000000-schema.xml"/>
<include file="db/changelog-20190318_000000-schema.xml"/> <include file="db/changelog-20190318_000000-schema.xml"/>
<include file="db/changelog-20190318_000001-schema.xml"/> <include file="db/changelog-20190318_000001-schema.xml"/>
<include file="db/changelog-20190327_000000-schema.xml"/>
<include file="db/common/changelog-20190312_130000-schema.xml"/> <include file="db/common/changelog-20190312_130000-schema.xml"/>
</databaseChangeLog> </databaseChangeLog>