Merge remote-tracking branch 'origin/move-to-jdk11' into gl_87

gl_87
arefiev1997 5 years ago
commit a53a12fa55

@ -1,30 +1,28 @@
image: ubuntu:18.04
cache:
key: "$CI_PROJECT_ID"
paths:
- .gradle/
image: romanov73/is:ng-tracker-container-11
variables:
GRADLE_OPTS: "-Dorg.gradle.daemon=false"
before_script:
- 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
- apt-get install openjdk-8-jdk git -y
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- service postgresql stop
- service postgresql start
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- git log --pretty="%cn;%cd;%s" > src/main/resources/commits.log
build:
stage: build
script: ./gradlew assemble
cache:
key: "$CI_PROJECT_ID"
policy: push
paths:
- build
- .gradle
checkRun:
stage: test
script: ./gradlew bootRun -Dng-tracker.check-run=true
checkStyle:
stage: test
script: ./gradlew check -x test
deploy:
stage: deploy
@ -32,9 +30,6 @@ deploy:
- sh deploy/gdccloud/deploy.sh
only:
- dev
cache:
key: "$CI_PROJECT_ID"
policy: pull
paths:
- build
- .gradle
environment:
name: staging
url: http://193.110.3.124:8080

@ -0,0 +1,46 @@
## Краткое описание задачи
Что требуется сделать
## `Опционально` Список верстаемых страниц
Будут затронуты страницы:
* page1.html
* page2.html
* page3.html
## `Опционально` Список затрагиваемых модулей
При реализации задачи потребуется также реализовать методы контроллера
## `Опционально` Список реализуемых функций
После выполнения задачи станет доступным:
* просмотр `entity_name`
* редактирование `entity_name`
* валидация `entity_name`
## `Опционально` Сценарии работы
Сценарий просмотра:
1. Зайти на главную страницу приложения
2. Перейти в раздел `section_name`
3. Перейти к списку `entity_name`
4. Выбрать нужную `entity_name` и нажать на нее
Сценарий редактирования:
1. Зайти на главную страницу приложения
2. Перейти в раздел `section_name`
3. Перейти к списку `entity_name`
4. Выбрать нужную `entity_name` и нажать на нее
5. Внести нужные правки в поля и сохранить
## Описание конечного результата, дающего возможность проверки выполнения задачи: компоненты проекта, сценарии работы
* Сверстаны страницы page1.hml, page2.hml, page3.hml
* Реализован контроллер для обслуживания страниц
* Сохранение в БД еще не реализовано
* Валидация происходит по полям `field1, field2`
* Сценарий просмотра проверяется при ручном внечении записей в БД

@ -7,6 +7,7 @@
2. Создать новую функцию автоматизированной системы управления задчами - интеллектуальную постановку задач исполнителям.
3. Получить платформу для обкатки научных проектов магистрантов по созданию интеллектуальны систем.
4. Получить проект для обучения бакалавров современым технологиям разработки.
5. Создать систему хранения и трансляции опыта между участниками научной группы.
[Демо версия доступна здесь](http://193.110.3.124:8080)

@ -1,6 +1,6 @@
buildscript {
ext {
versionSpringBoot = '1.5.10.RELEASE'
versionSpringBoot = '2.1.3.RELEASE'
}
repositories {
@ -30,6 +30,10 @@ bootRun.dependsOn checkstyleMain
sourceCompatibility = 1.8
targetCompatibility = 1.8
bootRun {
systemProperties = System.properties
}
checkstyle {
project.ext.checkstyleVersion = '8.8'
@ -101,18 +105,16 @@ dependencies {
compile group: 'org.springframework.boot', name: 'spring-boot-starter-jetty'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-thymeleaf'
compile group: 'org.thymeleaf.extras', name: 'thymeleaf-extras-springsecurity4'
compile group: 'nz.net.ultraq.thymeleaf', name: 'thymeleaf-layout-dialect'
compile group: 'org.thymeleaf.extras', name: 'thymeleaf-extras-springsecurity5'
compile group: 'com.fasterxml.jackson.module', name: 'jackson-module-afterburner'
compile group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-hibernate5'
compile group: 'postgresql', name: 'postgresql', version: '9.1-901.jdbc4'
compile group: 'org.postgresql', name: 'postgresql', version: '42.2.5'
compile group: 'org.liquibase', name: 'liquibase-core', version: '3.5.3'
compile group: 'org.liquibase', name: 'liquibase-core', version: '3.6.3'
compile group: 'com.mattbertolini', name: 'liquibase-slf4j', version: '2.0.0'
compile group: 'org.apache.poi', name: 'poi', version: '3.9'
compile group: 'org.apache.poi', name: 'poi-ooxml', version: '3.9'
compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.7'
compile group: 'org.webjars', name: 'bootstrap', version: '4.1.0'
@ -121,8 +123,10 @@ dependencies {
compile group: 'org.webjars.npm', name: 'jquery.easing', version: '1.4.1'
compile group: 'org.webjars', name: 'font-awesome', version: '4.7.0'
compile group: 'io.springfox', name: 'springfox-swagger2', version: '2.5.0'
compile group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.5.0'
compile group: 'io.springfox', name: 'springfox-swagger2', version: '2.6.0'
compile group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.6.0'
testCompile group: 'org.springframework.boot', name: 'spring-boot-starter-test'
testCompile group: 'org.seleniumhq.selenium', name: 'selenium-java', version: '3.3.1'
}

@ -100,7 +100,7 @@
<!-- Checks for imports -->
<!-- See http://checkstyle.sf.net/config_import.html -->
<!--<module name="AvoidStarImport"/>-->
<module name="AvoidStarImport"/>
<module name="IllegalImport"/> <!-- defaults to sun.* packages -->
<module name="RedundantImport"/>
<!--module name="UnusedImports">
@ -136,7 +136,7 @@
<module name="AvoidNestedBlocks"/>
<module name="EmptyBlock"/>
<module name="LeftCurly"/>
<!--<module name="NeedBraces"/>-->
<module name="NeedBraces"/>
<module name="RightCurly"/>
<!-- Checks for common coding problems -->

@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.5.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-bin.zip

@ -2,13 +2,30 @@ package ru.ulstu;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import ru.ulstu.configuration.ApplicationProperties;
import ru.ulstu.core.repository.JpaDetachableRepositoryImpl;
@SpringBootApplication
@EnableJpaRepositories(repositoryBaseClass = JpaDetachableRepositoryImpl.class)
public class NgTrackerApplication {
private final ApplicationProperties applicationProperties;
public NgTrackerApplication(ApplicationProperties applicationProperties) {
this.applicationProperties = applicationProperties;
}
public static void main(String[] args) {
SpringApplication.run(NgTrackerApplication.class, args);
}
@EventListener(ApplicationReadyEvent.class)
public void doSomethingAfterStartup() {
System.out.println("hello world, I have just started up");
if (applicationProperties.isCheckRun()) {
System.exit(0);
}
}
}

@ -0,0 +1,156 @@
package ru.ulstu.conference.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import ru.ulstu.conference.model.ConferenceDto;
import ru.ulstu.conference.model.ConferenceFilterDto;
import ru.ulstu.conference.model.ConferenceUser;
import ru.ulstu.conference.service.ConferenceService;
import ru.ulstu.deadline.model.Deadline;
import ru.ulstu.user.model.User;
import springfox.documentation.annotations.ApiIgnore;
import javax.validation.Valid;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.stream.Collectors;
import static org.springframework.util.StringUtils.isEmpty;
import static ru.ulstu.core.controller.Navigation.CONFERENCES_PAGE;
import static ru.ulstu.core.controller.Navigation.CONFERENCE_PAGE;
import static ru.ulstu.core.controller.Navigation.REDIRECT_TO;
@Controller()
@RequestMapping(value = "/conferences")
@ApiIgnore
public class ConferenceController {
private final ConferenceService conferenceService;
public ConferenceController(ConferenceService conferenceService) {
this.conferenceService = conferenceService;
}
@GetMapping("/conferences")
public void getConferences(ModelMap modelMap) {
modelMap.put("filteredConferences", new ConferenceFilterDto(conferenceService.findAllDto()));
}
@PostMapping("/conferences")
public void filterConferences(@Valid ConferenceFilterDto conferenceFilterDto, ModelMap modelMap) {
modelMap.put("filteredConferences", new ConferenceFilterDto(conferenceService.filter(conferenceFilterDto),
conferenceFilterDto.getFilterUserId(),
conferenceFilterDto.getYear()));
}
@GetMapping("/dashboard")
public void getDashboard(ModelMap modelMap) {
modelMap.put("conferences", conferenceService.findAllActiveDto());
}
@GetMapping("/conference")
public void getConference(ModelMap modelMap, @RequestParam(value = "id") Integer id) {
if (id != null && id > 0) {
modelMap.put("conferenceDto", conferenceService.getExistConferenceById(id));
} else {
modelMap.put("conferenceDto", conferenceService.getNewConference());
}
}
@PostMapping(value = "/conference", params = "save")
public String save(@Valid ConferenceDto conferenceDto, Errors errors) throws IOException {
filterEmptyDeadlines(conferenceDto);
if (errors.hasErrors()) {
return CONFERENCE_PAGE;
}
conferenceService.save(conferenceDto);
return String.format(REDIRECT_TO, CONFERENCES_PAGE);
}
@GetMapping("/delete/{conference-id}")
public String delete(@PathVariable("conference-id") Integer conferenceId) throws IOException {
conferenceService.delete(conferenceId);
return String.format(REDIRECT_TO, CONFERENCES_PAGE);
}
@PostMapping(value = "/conference", params = "addDeadline")
public String addDeadline(@Valid ConferenceDto conferenceDto, Errors errors) {
filterEmptyDeadlines(conferenceDto);
if (errors.hasErrors()) {
return CONFERENCE_PAGE;
}
conferenceDto.getDeadlines().add(new Deadline());
return CONFERENCE_PAGE;
}
@PostMapping(value = "/conference", params = "removeDeadline")
public String removeDeadline(@Valid ConferenceDto conferenceDto, Errors errors,
@RequestParam(value = "removeDeadline") Integer deadlineIndex) throws IOException {
if (errors.hasErrors()) {
return CONFERENCE_PAGE;
}
conferenceService.removeDeadline(conferenceDto, deadlineIndex);
return CONFERENCE_PAGE;
}
@PostMapping(value = "/conference", params = "removePaper")
public String removePaper(@Valid ConferenceDto conferenceDto, Errors errors,
@RequestParam(value = "removePaper") Integer paperIndex) throws IOException {
if (errors.hasErrors()) {
return CONFERENCE_PAGE;
}
conferenceService.removePaper(conferenceDto, paperIndex);
return CONFERENCE_PAGE;
}
@PostMapping(value = "/conference", params = "takePart")
public String takePart(@Valid ConferenceDto conferenceDto, Errors errors) throws IOException {
if (errors.hasErrors()) {
return CONFERENCE_PAGE;
}
conferenceService.takePart(conferenceDto);
return CONFERENCE_PAGE;
}
@ModelAttribute("allParticipation")
public List<ConferenceUser.Participation> getAllParticipation() {
return conferenceService.getAllParticipations();
}
@ModelAttribute("allDeposit")
public List<ConferenceUser.Deposit> getAllDeposit() {
return conferenceService.getAllDeposit();
}
@ModelAttribute("allUsers")
public List<User> getAllUsers() {
return conferenceService.getAllUsers();
}
@ModelAttribute("allYears")
public List<Integer> getAllYears() {
List<Integer> years = new ArrayList<>();
for (int i = Calendar.getInstance().get(Calendar.YEAR); i > 2010; i--) {
years.add(i);
}
return years;
}
private void filterEmptyDeadlines(ConferenceDto conferenceDto) {
conferenceDto.setDeadlines(conferenceDto.getDeadlines().stream()
.filter(dto -> dto.getDate() != null || !isEmpty(dto.getDescription()))
.collect(Collectors.toList()));
}
}

@ -0,0 +1,138 @@
package ru.ulstu.conference.model;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.springframework.format.annotation.DateTimeFormat;
import ru.ulstu.core.model.BaseEntity;
import ru.ulstu.deadline.model.Deadline;
import ru.ulstu.paper.model.Paper;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotBlank;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Entity
@Table(name = "conference")
public class Conference extends BaseEntity {
@NotBlank
private String title;
private String description;
private String url;
private int ping;
@Column(name = "begin_date")
@Temporal(TemporalType.TIMESTAMP)
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date beginDate;
@Column(name = "end_date")
@Temporal(TemporalType.TIMESTAMP)
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date endDate;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "conference_id", unique = true)
@Fetch(FetchMode.SUBSELECT)
@OrderBy("date")
private List<Deadline> deadlines = new ArrayList<>();
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "paper_conference",
joinColumns = {@JoinColumn(name = "conference_id")},
inverseJoinColumns = {@JoinColumn(name = "paper_id")})
private List<Paper> papers = new ArrayList<>();
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "conference_id", unique = true)
@Fetch(FetchMode.SUBSELECT)
private List<ConferenceUser> users = new ArrayList<>();
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public int getPing() {
return ping;
}
public void setPing(int ping) {
this.ping = ping;
}
public Date getBeginDate() {
return beginDate;
}
public void setBeginDate(Date beginDate) {
this.beginDate = beginDate;
}
public Date getEndDate() {
return endDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public List<Deadline> getDeadlines() {
return deadlines;
}
public void setDeadlines(List<Deadline> deadlines) {
this.deadlines = deadlines;
}
public List<Paper> getPapers() {
return papers;
}
public void setPapers(List<Paper> papers) {
this.papers = papers;
}
public List<ConferenceUser> getUsers() {
return users;
}
public void setUsers(List<ConferenceUser> users) {
this.users = users;
}
}

@ -0,0 +1,222 @@
package ru.ulstu.conference.model;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.springframework.format.annotation.DateTimeFormat;
import ru.ulstu.core.model.BaseEntity;
import ru.ulstu.deadline.model.Deadline;
import ru.ulstu.paper.model.Paper;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import static ru.ulstu.core.util.StreamApiUtils.convert;
public class ConferenceDto {
private final static String BEGIN_DATE = "Начало: ";
private final static String END_DATE = "Конец: ";
private Integer id;
@NotEmpty
@Size(min = 2, max = 400)
private String title;
@Size(max = 500)
private String description = "";
@Size(max = 255)
private String url = "";
private int ping = 0;
@Temporal(TemporalType.TIMESTAMP)
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date beginDate = new Date();
@Temporal(TemporalType.TIMESTAMP)
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date endDate = new Date();
private List<Deadline> deadlines = new ArrayList<>();
private List<Integer> removedDeadlineIds = new ArrayList<>();
private List<Integer> userIds = new ArrayList<>();
private List<Integer> paperIds = new ArrayList<>();
private List<Paper> papers = new ArrayList<>();
private List<Paper> notSelectedPapers = new ArrayList<>();
private List<ConferenceUser> users = new ArrayList<>();
private boolean disabledTakePart = false;
public ConferenceDto() {
}
@JsonCreator
public ConferenceDto(@JsonProperty("id") Integer id,
@JsonProperty("title") String title,
@JsonProperty("description") String description,
@JsonProperty("url") String url,
@JsonProperty("ping") Integer ping,
@JsonProperty("beginDate") Date beginDate,
@JsonProperty("endDate") Date endDate,
@JsonProperty("deadlines") List<Deadline> deadlines,
@JsonProperty("userIds") List<Integer> userIds,
@JsonProperty("paperIds") List<Integer> paperIds,
@JsonProperty("users") List<ConferenceUser> users,
@JsonProperty("papers") List<Paper> papers,
@JsonProperty("notSelectedPapers") List<Paper> notSelectedPapers,
@JsonProperty("notSelectedPapers") Boolean disabledTakePart) {
this.id = id;
this.title = title;
this.description = description;
this.url = url;
this.ping = ping;
this.beginDate = beginDate;
this.endDate = endDate;
this.deadlines = deadlines;
this.userIds = userIds;
this.paperIds = paperIds;
this.users = users;
this.papers = papers;
this.notSelectedPapers = notSelectedPapers;
this.disabledTakePart = disabledTakePart;
}
public ConferenceDto(Conference conference) {
this.id = conference.getId();
this.title = conference.getTitle();
this.description = conference.getDescription();
this.url = conference.getUrl();
this.ping = conference.getPing();
this.beginDate = conference.getBeginDate();
this.endDate = conference.getEndDate();
this.deadlines = conference.getDeadlines();
this.userIds = convert(conference.getUsers(), BaseEntity::getId);
this.paperIds = convert(conference.getPapers(), BaseEntity::getId);
this.users = conference.getUsers();
this.papers = conference.getPapers();
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public int getPing() {
return ping;
}
public void setPing(int ping) {
this.ping = ping;
}
public Date getBeginDate() {
return beginDate;
}
public void setBeginDate(Date beginDate) {
this.beginDate = beginDate;
}
public Date getEndDate() {
return endDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public List<Deadline> getDeadlines() {
return deadlines;
}
public void setDeadlines(List<Deadline> deadlines) {
this.deadlines = deadlines;
}
public List<Integer> getUserIds() {
return userIds;
}
public void setUserIds(List<Integer> userIds) {
this.userIds = userIds;
}
public List<Integer> getPaperIds() {
return paperIds;
}
public void setPaperIds(List<Integer> paperIds) {
this.paperIds = paperIds;
}
public List<Paper> getPapers() {
return papers;
}
public void setPapers(List<Paper> papers) {
this.papers = papers;
}
public List<ConferenceUser> getUsers() {
return users;
}
public void setUsers(List<ConferenceUser> users) {
this.users = users;
}
public boolean isDisabledTakePart() {
return disabledTakePart;
}
public void setDisabledTakePart(boolean disabledTakePart) {
this.disabledTakePart = disabledTakePart;
}
public List<Integer> getRemovedDeadlineIds() {
return removedDeadlineIds;
}
public void setRemovedDeadlineIds(List<Integer> removedDeadlineIds) {
this.removedDeadlineIds = removedDeadlineIds;
}
public List<Paper> getNotSelectedPapers() {
return notSelectedPapers;
}
public void setNotSelectedPapers(List<Paper> notSelectedPapers) {
this.notSelectedPapers = notSelectedPapers;
}
public String getDatesString() {
return BEGIN_DATE + beginDate.toString().split(" ")[0] + " " + END_DATE + endDate.toString().split(" ")[0];
}
}

@ -0,0 +1,47 @@
package ru.ulstu.conference.model;
import java.util.List;
public class ConferenceFilterDto {
private List<ConferenceDto> conferences;
private Integer filterUserId;
private Integer year;
public ConferenceFilterDto() {
}
public ConferenceFilterDto(List<ConferenceDto> conferenceDtos, Integer filterUserId, Integer year) {
this.conferences = conferenceDtos;
this.filterUserId = filterUserId;
this.year = year;
}
public ConferenceFilterDto(List<ConferenceDto> conferenceDtos) {
this(conferenceDtos, null, null);
}
public List<ConferenceDto> getConferences() {
return conferences;
}
public void setConferences(List<ConferenceDto> conferences) {
this.conferences = conferences;
}
public Integer getFilterUserId() {
return filterUserId;
}
public void setFilterUserId(Integer filterUserId) {
this.filterUserId = filterUserId;
}
public Integer getYear() {
return year;
}
public void setYear(Integer year) {
this.year = year;
}
}

@ -0,0 +1,110 @@
package ru.ulstu.conference.model;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import ru.ulstu.core.model.BaseEntity;
import ru.ulstu.user.model.User;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
@Entity
@Table(name = "users_conference")
public class ConferenceUser extends BaseEntity {
public enum Participation {
INTRAMURAL("Очная"),
EXTRAMURAL("Заочная");
private String participationName;
Participation(String name) {
this.participationName = name;
}
public String getParticipation() {
return participationName;
}
}
public enum Deposit {
ARTICLE("Статья"),
REPORT("Доклад"),
PRESENTATION("Презентация");
private String depositName;
Deposit(String name) {
this.depositName = name;
}
public String getDeposit() {
return depositName;
}
}
@NotNull
@Column(name = "participation", nullable = false)
@Enumerated(value = EnumType.STRING)
private Participation participation = Participation.INTRAMURAL;
@NotNull
@Column(name = "deposit", nullable = false)
@Enumerated(value = EnumType.STRING)
private Deposit deposit = Deposit.ARTICLE;
@ManyToOne(optional = false)
@JoinColumn(name = "users_id")
private User user;
public ConferenceUser() {
}
public ConferenceUser(User user) {
this.user = user;
}
@JsonCreator
public ConferenceUser(@JsonProperty("id") Integer id,
@JsonProperty("deposit") Participation participation,
@JsonProperty("deposit") Deposit deposit,
@JsonProperty("user") User user) {
this.setId(id);
this.participation = participation;
this.deposit = deposit;
this.user = user;
}
public Participation getParticipation() {
return participation;
}
public void setParticipation(Participation participation) {
this.participation = participation;
}
public Deposit getDeposit() {
return deposit;
}
public void setDeposit(Deposit deposit) {
this.deposit = deposit;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}

@ -0,0 +1,19 @@
package ru.ulstu.conference.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import ru.ulstu.conference.model.Conference;
import ru.ulstu.user.model.User;
import java.util.Date;
import java.util.List;
public interface ConferenceRepository extends JpaRepository<Conference, Integer> {
@Query("SELECT c FROM Conference c LEFT JOIN c.users u WHERE (:user IS NULL OR u.user = :user) " +
"AND (YEAR(c.beginDate) = :year OR :year IS NULL) ORDER BY begin_date DESC")
List<Conference> findByUserAndYear(@Param("user") User user, @Param("year") Integer year);
@Query("SELECT c FROM Conference c WHERE c.beginDate > :date")
List<Conference> findAllActive(@Param("date") Date date);
}

@ -0,0 +1,7 @@
package ru.ulstu.conference.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import ru.ulstu.conference.model.ConferenceUser;
public interface ConferenceUserRepository extends JpaRepository<ConferenceUser, Integer> {
}

@ -0,0 +1,7 @@
package ru.ulstu.conference.service;
import org.springframework.stereotype.Service;
@Service
public class ConferenceNotificationService {
}

@ -0,0 +1,176 @@
package ru.ulstu.conference.service;
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.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.service.DeadlineService;
import ru.ulstu.paper.model.Paper;
import ru.ulstu.paper.service.PaperService;
import ru.ulstu.user.model.User;
import ru.ulstu.user.service.UserService;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import static org.springframework.util.ObjectUtils.isEmpty;
import static ru.ulstu.core.util.StreamApiUtils.convert;
@Service
public class ConferenceService {
private final static int MAX_DISPLAY_SIZE = 40;
private final ConferenceRepository conferenceRepository;
private final ConferenceUserService conferenceUserService;
private final DeadlineService deadlineService;
private final PaperService paperService;
private final UserService userService;
public ConferenceService(ConferenceRepository conferenceRepository,
ConferenceUserService conferenceUserService,
DeadlineService deadlineService,
PaperService paperService,
UserService userService) {
this.conferenceRepository = conferenceRepository;
this.conferenceUserService = conferenceUserService;
this.deadlineService = deadlineService;
this.paperService = paperService;
this.userService = userService;
}
public ConferenceDto getExistConferenceById(Integer id) {
ConferenceDto conferenceDto = findOneDto(id);
conferenceDto.setNotSelectedPapers(getNotSelectPapers(conferenceDto.getPaperIds()));
conferenceDto.setDisabledTakePart(isCurrentUserParticipant(conferenceDto.getUsers()));
return conferenceDto;
}
public ConferenceDto getNewConference() {
ConferenceDto conferenceDto = new ConferenceDto();
conferenceDto.setNotSelectedPapers(getNotSelectPapers(new ArrayList<Integer>()));
return conferenceDto;
}
public List<Conference> findAll() {
return conferenceRepository.findAll(new Sort(Sort.Direction.DESC, "beginDate"));
}
public List<ConferenceDto> findAllDto() {
List<ConferenceDto> conferences = convert(findAll(), ConferenceDto::new);
conferences.forEach(conferenceDto -> conferenceDto.setTitle(StringUtils.abbreviate(conferenceDto.getTitle(), MAX_DISPLAY_SIZE)));
return conferences;
}
public ConferenceDto findOneDto(Integer id) {
return new ConferenceDto(conferenceRepository.getOne(id));
}
public void save(ConferenceDto conferenceDto) throws IOException {
if (isEmpty(conferenceDto.getId())) {
create(conferenceDto);
} else {
update(conferenceDto);
}
}
@Transactional
public Integer create(ConferenceDto conferenceDto) throws IOException {
Conference newConference = copyFromDto(new Conference(), conferenceDto);
newConference = conferenceRepository.save(newConference);
return newConference.getId();
}
@Transactional
public Integer update(ConferenceDto conferenceDto) throws IOException {
Conference conference = conferenceRepository.getOne(conferenceDto.getId());
conferenceRepository.save(copyFromDto(conference, conferenceDto));
conferenceDto.getRemovedDeadlineIds().forEach(deadlineService::remove);
return conference.getId();
}
@Transactional
public void delete(Integer conferenceId) {
if (conferenceRepository.existsById(conferenceId)) {
conferenceRepository.deleteById(conferenceId);
}
}
public void 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);
}
public void removePaper(ConferenceDto conferenceDto, Integer paperIndex) throws IOException {
Paper removedPaper = conferenceDto.getPapers().remove((int) paperIndex);
conferenceDto.getNotSelectedPapers().add(removedPaper);
}
public void takePart(ConferenceDto conferenceDto) throws IOException {
conferenceDto.getUsers().add(new ConferenceUser(userService.getCurrentUser()));
conferenceDto.setDisabledTakePart(true);
}
public List<Paper> getNotSelectPapers(List<Integer> paperIds) {
return paperService.findAllNotSelect(paperIds);
}
public List<User> getAllUsers() {
return userService.findAll();
}
public List<ConferenceUser.Participation> getAllParticipations() {
return Arrays.asList(ConferenceUser.Participation.values());
}
public List<ConferenceUser.Deposit> getAllDeposit() {
return Arrays.asList(ConferenceUser.Deposit.values());
}
private Conference copyFromDto(Conference conference, ConferenceDto conferenceDto) throws IOException {
conference.setTitle(conferenceDto.getTitle());
conference.setDescription(conferenceDto.getDescription());
conference.setUrl(conferenceDto.getUrl());
conference.setPing(0);
conference.setBeginDate(conferenceDto.getBeginDate());
conference.setEndDate(conferenceDto.getEndDate());
conference.setPapers(conferenceDto.getPapers());
conference.setDeadlines(deadlineService.saveOrCreate(conferenceDto.getDeadlines()));
conference.setUsers(conferenceUserService.saveOrCreate(conferenceDto.getUsers()));
if (conferenceDto.getPaperIds() != null && !conferenceDto.getPaperIds().isEmpty()) {
conferenceDto.getPaperIds().forEach(paperId ->
conference.getPapers().add(paperService.findEntityById(paperId)));
}
return conference;
}
public boolean isCurrentUserParticipant(List<ConferenceUser> conferenceUsers) {
return conferenceUsers.stream().anyMatch(participant -> participant.getUser().equals(userService.getCurrentUser()));
}
public List<ConferenceDto> filter(ConferenceFilterDto conferenceFilterDto) {
return convert(conferenceRepository.findByUserAndYear(
conferenceFilterDto.getFilterUserId() == null ? null : userService.findById(conferenceFilterDto.getFilterUserId()),
conferenceFilterDto.getYear()), ConferenceDto::new);
}
public List<ConferenceDto> findAllActiveDto() {
return convert(findAllActive(), ConferenceDto::new);
}
public List<Conference> findAllActive() {
return conferenceRepository.findAllActive(new Date());
}
}

@ -0,0 +1,48 @@
package ru.ulstu.conference.service;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ru.ulstu.conference.model.ConferenceUser;
import ru.ulstu.conference.repository.ConferenceUserRepository;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class ConferenceUserService {
private final ConferenceUserRepository conferenceUserRepository;
public ConferenceUserService(ConferenceUserRepository conferenceUserRepository) {
this.conferenceUserRepository = conferenceUserRepository;
}
public List<ConferenceUser> saveOrCreate(List<ConferenceUser> users) {
return users
.stream()
.map(user -> {
return user.getId() != null ? update(user) : create(user);
}).collect(Collectors.toList());
}
@Transactional
public ConferenceUser update(ConferenceUser user) {
ConferenceUser updateUser = conferenceUserRepository.getOne(user.getId());
updateUser.setDeposit(user.getDeposit());
updateUser.setParticipation(user.getParticipation());
conferenceUserRepository.save(updateUser);
return updateUser;
}
@Transactional
public ConferenceUser create(ConferenceUser user) {
ConferenceUser newUser = new ConferenceUser();
newUser.setDeposit(user.getDeposit());
newUser.setParticipation(user.getParticipation());
newUser.setUser(user.getUser());
newUser = conferenceUserRepository.save(newUser);
return newUser;
}
}

@ -1,22 +1,27 @@
package ru.ulstu.configuration;
import org.hibernate.validator.constraints.NotBlank;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.NotBlank;
@Component
@ConfigurationProperties(prefix = "ng-tracker")
@Validated
public class ApplicationProperties {
@NotBlank
private String baseUrl;
@NotBlank
private String undeadUserLogin;
private boolean devMode;
private boolean useHttps;
private boolean checkRun;
public boolean isUseHttps() {
return useHttps;
}
@ -48,4 +53,12 @@ public class ApplicationProperties {
public void setDevMode(boolean devMode) {
this.devMode = devMode;
}
public boolean isCheckRun() {
return checkRun;
}
public void setCheckRun(boolean checkRun) {
this.checkRun = checkRun;
}
}

@ -2,18 +2,18 @@ package ru.ulstu.configuration;
import org.eclipse.jetty.server.ServerConnector;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.jetty.JettyServerCustomizer;
import org.springframework.boot.web.embedded.jetty.JettyServerCustomizer;
import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
import org.springframework.boot.web.server.ConfigurableWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Configuration;
@Configuration
public class HttpListenerConfiguration implements EmbeddedServletContainerCustomizer {
public class HttpListenerConfiguration implements WebServerFactoryCustomizer<ConfigurableWebServerFactory> {
@Value("${server.http.port}")
private int httpPort;
private void configureJetty(JettyEmbeddedServletContainerFactory jettyFactory) {
private void configureJetty(JettyServletWebServerFactory jettyFactory) {
jettyFactory.addServerCustomizers((JettyServerCustomizer) server -> {
ServerConnector serverConnector = new ServerConnector(server);
serverConnector.setPort(httpPort);
@ -22,9 +22,9 @@ public class HttpListenerConfiguration implements EmbeddedServletContainerCustom
}
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
if (container instanceof JettyEmbeddedServletContainerFactory) {
configureJetty((JettyEmbeddedServletContainerFactory) container);
public void customize(ConfigurableWebServerFactory factory) {
if (factory instanceof JettyServletWebServerFactory) {
configureJetty((JettyServletWebServerFactory) factory);
}
}
}

@ -3,8 +3,8 @@ package ru.ulstu.configuration;
import nz.net.ultraq.thymeleaf.LayoutDialect;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.thymeleaf.extras.springsecurity4.dialect.SpringSecurityDialect;
import org.thymeleaf.spring4.SpringTemplateEngine;
import org.thymeleaf.extras.springsecurity5.dialect.SpringSecurityDialect;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
import org.thymeleaf.templateresolver.ITemplateResolver;
@ -17,7 +17,6 @@ public class MailTemplateConfiguration {
final SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.addTemplateResolver(templateResolver);
templateEngine.addTemplateResolver(emailTemplateResolver());
templateEngine.addTemplateResolver(mvcTemplateResolver());
templateEngine.addDialect(new LayoutDialect());
templateEngine.addDialect(sec);
return templateEngine;
@ -25,22 +24,10 @@ public class MailTemplateConfiguration {
public ClassLoaderTemplateResolver emailTemplateResolver() {
ClassLoaderTemplateResolver emailTemplateResolver = new ClassLoaderTemplateResolver();
emailTemplateResolver.setPrefix("mail_templates/");
emailTemplateResolver.setTemplateMode("HTML5");
emailTemplateResolver.setPrefix("/mail_templates/");
emailTemplateResolver.setTemplateMode("HTML");
emailTemplateResolver.setSuffix(".html");
emailTemplateResolver.setOrder(1);
emailTemplateResolver.setCharacterEncoding(StandardCharsets.UTF_8.name());
return emailTemplateResolver;
}
public ClassLoaderTemplateResolver mvcTemplateResolver() {
ClassLoaderTemplateResolver emailTemplateResolver = new ClassLoaderTemplateResolver();
emailTemplateResolver.setPrefix("templates");
emailTemplateResolver.setTemplateMode("HTML5");
emailTemplateResolver.setSuffix(".html");
emailTemplateResolver.setOrder(2);
emailTemplateResolver.setCharacterEncoding(StandardCharsets.UTF_8.name());
return emailTemplateResolver;
}
}

@ -3,16 +3,18 @@ package ru.ulstu.configuration;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MvcConfiguration extends WebMvcConfigurerAdapter {
public class MvcConfiguration implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/{articlename:\\w+}");
//registry.addViewController("/admin/{articlename:\\w+}");
registry.addViewController("/admin/{articlename:\\w+}");
registry.addViewController("/papers/{articlename:\\w+}");
registry.addViewController("/grants/{articlename:\\w+}");
registry.addViewController("/conferences/{articlename:\\w+}");
registry.addViewController("/students/{articlename:\\w+}");
registry.addRedirectViewController("/", "/index");
registry.addRedirectViewController("/default", "/index");
}

@ -58,7 +58,7 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
.anyRequest()
.permitAll();
http.anonymous()
.principal("developer")
.principal("admin")
.authorities(UserRoleConstants.ADMIN);
} else {
log.debug("Security enabled");

@ -1,100 +1,110 @@
package ru.ulstu.core.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;
import ru.ulstu.core.error.EntityIdIsNullException;
import ru.ulstu.core.model.ErrorConstants;
import ru.ulstu.core.model.response.Response;
import ru.ulstu.core.model.response.ResponseExtended;
import ru.ulstu.user.error.UserActivationError;
import ru.ulstu.user.error.UserEmailExistsException;
import ru.ulstu.user.error.UserIdExistsException;
import ru.ulstu.user.error.UserIsUndeadException;
import ru.ulstu.user.error.UserLoginExistsException;
import ru.ulstu.user.error.UserNotActivatedException;
import ru.ulstu.user.error.UserNotFoundException;
import ru.ulstu.user.error.UserPasswordsNotValidOrNotMatchException;
import ru.ulstu.user.error.UserResetKeyError;
import java.util.Set;
import java.util.stream.Collectors;
@RestController
@ControllerAdvice
public class AdviceController {
private final Logger log = LoggerFactory.getLogger(AdviceController.class);
private Response<Void> handleException(ErrorConstants error) {
log.warn(error.toString());
return new Response<>(error);
}
private <E> ResponseExtended<E> handleException(ErrorConstants error, E errorData) {
log.warn(error.toString());
return new ResponseExtended<>(error, errorData);
}
@ExceptionHandler(EntityIdIsNullException.class)
public Response<Void> handleEntityIdIsNullException(Throwable e) {
return handleException(ErrorConstants.ID_IS_NULL);
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseExtended<Set<String>> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
final Set<String> errors = e.getBindingResult().getAllErrors().stream()
.filter(error -> error instanceof FieldError)
.map(error -> ((FieldError) error).getField())
.collect(Collectors.toSet());
return handleException(ErrorConstants.VALIDATION_ERROR, errors);
}
@ExceptionHandler(UserIdExistsException.class)
public Response<Void> handleUserIdExistsException(Throwable e) {
return handleException(ErrorConstants.USER_ID_EXISTS);
}
@ExceptionHandler(UserActivationError.class)
public ResponseExtended<String> handleUserActivationError(Throwable e) {
return handleException(ErrorConstants.USER_ACTIVATION_ERROR, e.getMessage());
}
@ExceptionHandler(UserLoginExistsException.class)
public ResponseExtended<String> handleUserLoginExistsException(Throwable e) {
return handleException(ErrorConstants.USER_LOGIN_EXISTS, e.getMessage());
}
@ExceptionHandler(UserEmailExistsException.class)
public ResponseExtended<String> handleUserEmailExistsException(Throwable e) {
return handleException(ErrorConstants.USER_EMAIL_EXISTS, e.getMessage());
}
@ExceptionHandler(UserPasswordsNotValidOrNotMatchException.class)
public Response<Void> handleUserPasswordsNotValidOrNotMatchException(Throwable e) {
return handleException(ErrorConstants.USER_PASSWORDS_NOT_VALID_OR_NOT_MATCH);
}
@ExceptionHandler(UserNotFoundException.class)
public ResponseExtended<String> handleUserNotFoundException(Throwable e) {
return handleException(ErrorConstants.USER_NOT_FOUND, e.getMessage());
}
@ExceptionHandler(UserNotActivatedException.class)
public Response<Void> handleUserNotActivatedException(Throwable e) {
return handleException(ErrorConstants.USER_NOT_ACTIVATED);
}
@ExceptionHandler(UserResetKeyError.class)
public ResponseExtended<String> handleUserResetKeyError(Throwable e) {
return handleException(ErrorConstants.USER_RESET_ERROR, e.getMessage());
}
@ExceptionHandler(UserIsUndeadException.class)
public ResponseExtended<String> handleUserIsUndeadException(Throwable e) {
return handleException(ErrorConstants.USER_UNDEAD_ERROR, e.getMessage());
}
}
package ru.ulstu.core.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ModelAttribute;
import ru.ulstu.core.error.EntityIdIsNullException;
import ru.ulstu.core.model.ErrorConstants;
import ru.ulstu.core.model.response.Response;
import ru.ulstu.core.model.response.ResponseExtended;
import ru.ulstu.user.error.UserActivationError;
import ru.ulstu.user.error.UserEmailExistsException;
import ru.ulstu.user.error.UserIdExistsException;
import ru.ulstu.user.error.UserIsUndeadException;
import ru.ulstu.user.error.UserLoginExistsException;
import ru.ulstu.user.error.UserNotActivatedException;
import ru.ulstu.user.error.UserNotFoundException;
import ru.ulstu.user.error.UserPasswordsNotValidOrNotMatchException;
import ru.ulstu.user.error.UserResetKeyError;
import ru.ulstu.user.service.UserService;
import java.util.Set;
import java.util.stream.Collectors;
@ControllerAdvice
public class AdviceController {
private final Logger log = LoggerFactory.getLogger(AdviceController.class);
private final UserService userService;
public AdviceController(UserService userService) {
this.userService = userService;
}
@ModelAttribute("currentUser")
public String getCurrentUser() {
return userService.getCurrentUser().getUserAbbreviate();
}
private Response<Void> handleException(ErrorConstants error) {
log.warn(error.toString());
return new Response<>(error);
}
private <E> ResponseExtended<E> handleException(ErrorConstants error, E errorData) {
log.warn(error.toString());
return new ResponseExtended<>(error, errorData);
}
@ExceptionHandler(EntityIdIsNullException.class)
public Response<Void> handleEntityIdIsNullException(Throwable e) {
return handleException(ErrorConstants.ID_IS_NULL);
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseExtended<Set<String>> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
final Set<String> errors = e.getBindingResult().getAllErrors().stream()
.filter(error -> error instanceof FieldError)
.map(error -> ((FieldError) error).getField())
.collect(Collectors.toSet());
return handleException(ErrorConstants.VALIDATION_ERROR, errors);
}
@ExceptionHandler(UserIdExistsException.class)
public Response<Void> handleUserIdExistsException(Throwable e) {
return handleException(ErrorConstants.USER_ID_EXISTS);
}
@ExceptionHandler(UserActivationError.class)
public ResponseExtended<String> handleUserActivationError(Throwable e) {
return handleException(ErrorConstants.USER_ACTIVATION_ERROR, e.getMessage());
}
@ExceptionHandler(UserLoginExistsException.class)
public ResponseExtended<String> handleUserLoginExistsException(Throwable e) {
return handleException(ErrorConstants.USER_LOGIN_EXISTS, e.getMessage());
}
@ExceptionHandler(UserEmailExistsException.class)
public ResponseExtended<String> handleUserEmailExistsException(Throwable e) {
return handleException(ErrorConstants.USER_EMAIL_EXISTS, e.getMessage());
}
@ExceptionHandler(UserPasswordsNotValidOrNotMatchException.class)
public Response<Void> handleUserPasswordsNotValidOrNotMatchException(Throwable e) {
return handleException(ErrorConstants.USER_PASSWORDS_NOT_VALID_OR_NOT_MATCH);
}
@ExceptionHandler(UserNotFoundException.class)
public ResponseExtended<String> handleUserNotFoundException(Throwable e) {
return handleException(ErrorConstants.USER_NOT_FOUND, e.getMessage());
}
@ExceptionHandler(UserNotActivatedException.class)
public Response<Void> handleUserNotActivatedException(Throwable e) {
return handleException(ErrorConstants.USER_NOT_ACTIVATED);
}
@ExceptionHandler(UserResetKeyError.class)
public ResponseExtended<String> handleUserResetKeyError(Throwable e) {
return handleException(ErrorConstants.USER_RESET_ERROR, e.getMessage());
}
@ExceptionHandler(UserIsUndeadException.class)
public ResponseExtended<String> handleUserIsUndeadException(Throwable e) {
return handleException(ErrorConstants.USER_UNDEAD_ERROR, e.getMessage());
}
}

@ -0,0 +1,19 @@
package ru.ulstu.core.controller;
import org.springframework.validation.Errors;
public class Navigation {
public static final String REDIRECT_TO = "redirect:%s";
public static final String GRANTS_PAGE = "/grants/grants";
public static final String GRANT_PAGE = "/grants/grant";
public static final String CONFERENCES_PAGE = "/conferences/conferences";
public static final String CONFERENCE_PAGE = "/conferences/conference";
public static String hasErrors(Errors errors, String page) {
if (errors.hasErrors()) {
return page;
}
return null;
}
}

@ -1,7 +0,0 @@
package ru.ulstu.core.error;
public class XlsLoadException extends Exception {
public XlsLoadException(String s) {
super(s);
}
}

@ -1,7 +0,0 @@
package ru.ulstu.core.error;
public class XlsParseException extends Exception {
public XlsParseException(String s) {
super(s);
}
}

@ -6,19 +6,19 @@ import org.springframework.data.domain.Sort;
import java.io.Serializable;
public class OffsetablePageRequest implements Pageable, Serializable {
private final int offset;
private final long offset;
private final int count;
private final Sort sort;
public OffsetablePageRequest(int offset, int count) {
public OffsetablePageRequest(long offset, int count) {
this(offset, count, null);
}
public OffsetablePageRequest(int offset, int count, Sort.Direction direction, String... properties) {
public OffsetablePageRequest(long offset, int count, Sort.Direction direction, String... properties) {
this(offset, count, new Sort(direction, properties));
}
public OffsetablePageRequest(int offset, int count, Sort sort) {
public OffsetablePageRequest(long offset, int count, Sort sort) {
if (offset < 0) {
throw new IllegalArgumentException("Offset value must not be less than zero!");
}
@ -42,11 +42,11 @@ public class OffsetablePageRequest implements Pageable, Serializable {
@Override
public int getPageNumber() {
return offset / count;
return (int) (offset / count);
}
@Override
public int getOffset() {
public long getOffset() {
return offset;
}
@ -89,9 +89,9 @@ public class OffsetablePageRequest implements Pageable, Serializable {
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
long result = 1;
result = prime * result + offset;
result = prime * result + count;
return result;
return (int) result;
}
}

@ -1,6 +1,10 @@
package ru.ulstu.core.model;
import javax.persistence.*;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Version;
import java.io.Serializable;
@MappedSuperclass

@ -1,31 +0,0 @@
package ru.ulstu.core.service;
import org.springframework.stereotype.Service;
import ru.ulstu.core.model.TreeDto;
import ru.ulstu.core.model.TreeEntity;
import java.util.List;
import java.util.function.Predicate;
@Service
public class TreeService<T extends TreeEntity> {
public TreeDto getTree(String rootName, List<T> rootItems) {
return addChildNode(new TreeDto(rootName), rootItems, element -> true);
}
public TreeDto getTree(String rootName, List<T> rootItems, Predicate<T> filterPredicate) {
return addChildNode(new TreeDto(rootName), rootItems, filterPredicate);
}
private TreeDto addChildNode(TreeDto currentRoot, List<T> children, Predicate<T> filterPredicate) {
if (children != null) {
children.stream()
.filter(filterPredicate)
.forEach(item -> {
TreeDto newNode = new TreeDto(item);
currentRoot.getChildren().add(addChildNode(newNode, item.getChildren(), filterPredicate));
});
}
return currentRoot;
}
}

@ -1,207 +0,0 @@
package ru.ulstu.core.service;
import org.apache.poi.POIXMLDocument;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import ru.ulstu.core.error.XlsParseException;
import java.io.*;
public class XlsDocumentBuilder {
private static final int DEFAULT_SHEET_NUM = 0;
private File documentFile;
private Workbook workBook;
private Sheet currentSheet;
/**
* Constructor for reading and writing data from/to *.[xls|xlsx] document
*
* @param file contains existing document for reading or new document to save
*/
public XlsDocumentBuilder(File file) throws IOException, XlsParseException {
this.documentFile = file;
if (file.exists()) {
workBook = getWorkBook(file);
currentSheet = workBook.getSheetAt(DEFAULT_SHEET_NUM);
} else {
workBook = new XSSFWorkbook();
currentSheet = workBook.createSheet();
}
}
private Workbook getWorkBook(File file) throws XlsParseException, IOException {
InputStream inputStream = new PushbackInputStream(new FileInputStream(file), 4096);
if (isXlsx(inputStream)) {
return new XSSFWorkbook(inputStream);
} else if (isExcel(inputStream)) {
return new HSSFWorkbook(inputStream);
}
throw new XlsParseException("Wrong document format");
}
/**
* Change active sheet to write or read data
*
* @param index index of sheet to activate
*/
public XlsDocumentBuilder setActiveSheet(int index) {
workBook.setActiveSheet(index);
currentSheet = workBook.getSheetAt(index);
return this;
}
/**
* Create new sheet in document and set it active
*
* @param sheetName
*/
public XlsDocumentBuilder insertNewSheet(String sheetName) {
currentSheet = workBook.createSheet(sheetName);
workBook.setActiveSheet(getSheetCount() - 1);
return this;
}
public XlsDocumentBuilder insertNewSheet(String sheetName, int order) {
insertNewSheet(sheetName);
workBook.setSheetOrder(sheetName, order);
return this;
}
/**
* Returns number of sheet in document
*
* @return sheets count
*/
public int getSheetCount() {
return workBook.getNumberOfSheets();
}
/**
* Returns number of rows in sheet
*
* @return rows count
*/
public int getRowCount() {
return currentSheet.getLastRowNum();
}
/**
* Returns number of columns in sheet
*
* @return columns count
*/
public int getColumnCount() {
Row row = currentSheet.getRow(getRowCount());
if (row == null) {
return 0;
}
return row.getLastCellNum() - 1;
}
/**
* Returns converted to string representation of cell value
*
* @param rowIndex row index of current sheet
* @param colIndex column index of current sheet
* @return string value of cell
*/
public String getCellAsString(int rowIndex, int colIndex) {
Cell cell = currentSheet.getRow(rowIndex).getCell(colIndex);
cell.setCellType(Cell.CELL_TYPE_STRING);
return cell.getStringCellValue();
}
/**
* Sets string cell value
*
* @param rowIndex row index of current sheet
* @param colIndex column index of current sheet
*/
public XlsDocumentBuilder setCellValue(int rowIndex, int colIndex, String value) {
if (currentSheet.getRow(rowIndex) == null) {
currentSheet.createRow(rowIndex);
}
if (currentSheet.getRow(rowIndex).getCell(colIndex) == null) {
currentSheet.getRow(rowIndex).createCell(colIndex);
}
Cell cell = currentSheet.getRow(rowIndex).getCell(colIndex);
cell.setCellValue(value);
setColumnAutosize(colIndex, colIndex);
return this;
}
public XlsDocumentBuilder setCellValue(int rowIndex, int colIndex, int value) {
return setCellValue(rowIndex, colIndex, String.valueOf(value));
}
public XlsDocumentBuilder setCellValue(int rowIndex, int colIndex, long value) {
return setCellValue(rowIndex, colIndex, String.valueOf(value));
}
/**
* Save current file
*/
public XlsDocumentBuilder save() throws IOException {
OutputStream out = new FileOutputStream(documentFile);
workBook.write(out);
return this;
}
private boolean isExcel(InputStream i) throws IOException {
return (POIFSFileSystem.hasPOIFSHeader(i) || POIXMLDocument.hasOOXMLHeader(i));
}
private boolean isXlsx(InputStream i) throws IOException {
return POIXMLDocument.hasOOXMLHeader(i);
}
public int getActiveSheetIndex() {
return workBook.getActiveSheetIndex();
}
public XlsDocumentBuilder mergeCells(int rowFrom, int rowTo, int colFrom, int colTo) {
currentSheet.addMergedRegion(new CellRangeAddress(rowFrom, rowTo, colFrom, colTo));
return this;
}
public void setRegionBorderWithMedium(int rowFrom, int rowTo, int colFrom, int colTo) {
for (int row = rowFrom; row < rowTo; row++) {
for (int col = colFrom; col <= colTo; col++) {
CellRangeAddress cellRangeAddress = new CellRangeAddress(row, row, col, col);
RegionUtil.setBorderBottom(CellStyle.BORDER_THIN, cellRangeAddress, currentSheet, workBook);
RegionUtil.setBorderLeft(CellStyle.BORDER_THIN, cellRangeAddress, currentSheet, workBook);
RegionUtil.setBorderRight(CellStyle.BORDER_THIN, cellRangeAddress, currentSheet, workBook);
RegionUtil.setBorderTop(CellStyle.BORDER_THIN, cellRangeAddress, currentSheet, workBook);
}
}
}
public XlsDocumentBuilder setColumnAutosize(int from, int to) {
for (int col = from; col <= to; col++) {
currentSheet.autoSizeColumn(col, true);
}
return this;
}
public XlsDocumentBuilder setRowAutosize(int from, int to) {
CellStyle style = workBook.createCellStyle();
style.setWrapText(true);
for (int row = from; row <= to; row++) {
for (int col = 0; col <= currentSheet.getRow(row).getLastCellNum(); col++) {
if (currentSheet.getRow(row).getCell(col) != null) {
currentSheet.getRow(row).getCell(col).setCellStyle(style);
}
}
}
return this;
}
public XlsDocumentBuilder deleteSheet(int index) {
workBook.removeSheetAt(index);
return this;
}
}

@ -1,6 +1,11 @@
package ru.ulstu.core.util;
import java.time.*;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Month;
import java.time.ZoneId;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
@ -24,7 +29,7 @@ public class DateUtils {
return cal;
}
public static List<Month> getMonths () {
public static List<Month> getMonths() {
return Arrays.asList(Month.values());
}

@ -1,5 +1,8 @@
package ru.ulstu.deadline.model;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.springframework.format.annotation.DateTimeFormat;
import ru.ulstu.core.model.BaseEntity;
import javax.persistence.Entity;
@ -13,6 +16,7 @@ public class Deadline extends BaseEntity {
private String description;
@Temporal(value = TemporalType.TIMESTAMP)
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date date;
public Deadline() {
@ -23,6 +27,15 @@ public class Deadline extends BaseEntity {
this.description = description;
}
@JsonCreator
public Deadline(@JsonProperty("id") Integer id,
@JsonProperty("description") String description,
@JsonProperty("date") Date date) {
this.setId(id);
this.description = description;
this.date = date;
}
public String getDescription() {
return description;
}

@ -1,58 +0,0 @@
package ru.ulstu.deadline.model;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
public class DeadlineDto {
private Integer id;
private String description;
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date date;
public DeadlineDto() {
}
@JsonCreator
public DeadlineDto(@JsonProperty("id") Integer id,
@JsonProperty("description") String description,
@JsonProperty("date") Date date) {
this.id = id;
this.description = description;
this.date = date;
}
public DeadlineDto(Deadline deadline) {
this.id = deadline.getId();
this.description = deadline.getDescription();
this.date = deadline.getDate();
}
public Integer getId() {
return id;
}
public String getDescription() {
return description;
}
public Date getDate() {
return date;
}
public void setId(Integer id) {
this.id = id;
}
public void setDescription(String description) {
this.description = description;
}
public void setDate(Date date) {
this.date = date;
}
}

@ -3,7 +3,6 @@ package ru.ulstu.deadline.service;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ru.ulstu.deadline.model.Deadline;
import ru.ulstu.deadline.model.DeadlineDto;
import ru.ulstu.deadline.repository.DeadlineRepository;
import java.util.List;
@ -17,29 +16,34 @@ public class DeadlineService {
this.deadlineRepository = deadlineRepository;
}
public List<Deadline> saveOrCreate(List<DeadlineDto> deadlines) {
return deadlines.stream().map(deadlineDto -> {
return deadlineDto.getId() != null ? update(deadlineDto) : create(deadlineDto);
}).collect(Collectors.toList());
public List<Deadline> saveOrCreate(List<Deadline> deadlines) {
return deadlines
.stream()
.map(deadline -> {
return deadline.getId() != null ? update(deadline) : create(deadline);
}).collect(Collectors.toList());
}
@Transactional
public Deadline update(DeadlineDto deadlineDto) {
Deadline deadline = deadlineRepository.findOne(deadlineDto.getId());
deadlineRepository.save(copyFromDto(deadline, deadlineDto));
return deadline;
public Deadline update(Deadline deadline) {
Deadline updateDeadline = deadlineRepository.getOne(deadline.getId());
updateDeadline.setDate(deadline.getDate());
updateDeadline.setDescription(deadline.getDescription());
deadlineRepository.save(updateDeadline);
return updateDeadline;
}
@Transactional
public Deadline create(DeadlineDto deadlineDto) {
Deadline newDeadline = copyFromDto(new Deadline(), deadlineDto);
public Deadline create(Deadline deadline) {
Deadline newDeadline = new Deadline();
newDeadline.setDate(deadline.getDate());
newDeadline.setDescription(deadline.getDescription());
newDeadline = deadlineRepository.save(newDeadline);
return newDeadline;
}
private Deadline copyFromDto(Deadline deadline, DeadlineDto deadlineDto) {
deadline.setDate(deadlineDto.getDate());
deadline.setDescription(deadlineDto.getDescription());
return deadline;
@Transactional
public void remove(Integer deadlineId) {
deadlineRepository.deleteById(deadlineId);
}
}

@ -13,6 +13,7 @@ import org.springframework.web.multipart.MultipartFile;
import ru.ulstu.configuration.Constants;
import ru.ulstu.core.model.response.Response;
import ru.ulstu.file.model.FileData;
import ru.ulstu.file.model.FileDataDto;
import ru.ulstu.file.service.FileService;
import java.io.IOException;
@ -51,7 +52,7 @@ public class FileController {
}
@PostMapping("/uploadTmpFile")
public Response<String> upload(@RequestParam("file") MultipartFile multipartFile) throws IOException {
return new Response(fileService.uploadToTmpDir(multipartFile));
public Response<FileDataDto> upload(@RequestParam("file") MultipartFile multipartFile) throws IOException {
return new Response(fileService.createFromMultipartFile(multipartFile));
}
}

@ -19,6 +19,9 @@ public class FileData extends BaseEntity {
private byte[] data;
@Column(name = "is_latex_attach")
private Boolean isLatexAttach;
public String getName() {
return name;
}
@ -50,4 +53,12 @@ public class FileData extends BaseEntity {
public void setData(byte[] data) {
this.data = data;
}
public Boolean isLatexAttach() {
return isLatexAttach;
}
public void setLatexAttach(Boolean latexAttach) {
isLatexAttach = latexAttach;
}
}

@ -0,0 +1,95 @@
package ru.ulstu.file.model;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
public class FileDataDto {
private Integer id;
private String name;
private String fileName;
private String tmpFileName;
private boolean deleted;
private Boolean isLatexAttach;
public FileDataDto() {
}
@JsonCreator
public FileDataDto(@JsonProperty("id") Integer id,
@JsonProperty("name") String name,
@JsonProperty("isLatexAttach") Boolean isLatexAttach,
@JsonProperty("fileName") String fileName,
@JsonProperty("tmpFileName") String tmpFileName) {
this.id = id;
this.name = name;
this.fileName = fileName;
this.tmpFileName = tmpFileName;
this.isLatexAttach = isLatexAttach;
}
public FileDataDto(FileData fileData) {
this.id = fileData.getId();
this.name = fileData.getName();
this.isLatexAttach = fileData.isLatexAttach();
}
public FileDataDto(String fileName, String tmpFileName) {
this.fileName = fileName;
this.tmpFileName = tmpFileName;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getTmpFileName() {
return tmpFileName;
}
public void setTmpFileName(String tmpFileName) {
this.tmpFileName = tmpFileName;
}
public boolean isDeleted() {
return deleted;
}
public void setDeleted(boolean deleted) {
this.deleted = deleted;
}
public Boolean isLatexAttach() {
return isLatexAttach;
}
public Boolean getIsLatexAttach() {
return isLatexAttach;
}
public void setLatexAttach(Boolean latexAttach) {
isLatexAttach = latexAttach;
}
public void setIsLatexAttach(Boolean latexAttach) {
isLatexAttach = latexAttach;
}
}

@ -1,15 +1,24 @@
package ru.ulstu.file.service;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import ru.ulstu.file.model.FileData;
import ru.ulstu.file.model.FileDataDto;
import ru.ulstu.file.repostory.FileRepository;
import ru.ulstu.paper.model.PaperDto;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import static java.nio.charset.StandardCharsets.UTF_8;
@ -29,13 +38,13 @@ public class FileService {
public FileData createFileFromTmp(String tmpFileName) throws IOException {
FileData fileData = new FileData();
fileData.setData(getTmpFile(tmpFileName));
fileData.setName(getTmpFileName(tmpFileName));
fileData.setSize(getTmpFileSize(tmpFileName));
fileData.setCreateDate(new Date());
return fileRepository.save(fileData);
}
public String uploadToTmpDir(MultipartFile multipartFile) throws IOException {
String tmpFileName = String.valueOf(System.currentTimeMillis());
String tmpFileName = String.valueOf(System.currentTimeMillis()) + UUID.randomUUID();
Files.write(getTmpFilePath(tmpFileName), multipartFile.getBytes());
String meta = multipartFile.getOriginalFilename() + "\n" + multipartFile.getSize();
Files.write(getTmpFileMetaPath(tmpFileName), meta.getBytes(UTF_8));
@ -60,7 +69,7 @@ public class FileService {
}
public FileData getFile(Integer fileId) {
return fileRepository.findOne(fileId);
return fileRepository.getOne(fileId);
}
public void deleteTmpFile(String tmpFileName) throws IOException {
@ -78,4 +87,63 @@ public class FileService {
public void deleteFile(FileData fileData) {
fileRepository.delete(fileData);
}
public List<FileData> saveOrCreate(List<FileDataDto> fileDtos) throws IOException {
List<FileData> files = new ArrayList<>();
for (FileDataDto file : fileDtos) {
files.add(file.getId() != null ? update(file) : create(file));
}
return files;
}
@Transactional
public FileData update(FileDataDto fileDataDto) {
FileData file = fileRepository.getOne(fileDataDto.getId());
return fileRepository.save(copyFromDto(file, fileDataDto));
}
@Transactional
public FileData create(FileDataDto fileDataDto) throws IOException {
FileData newFile = createFileFromTmp(fileDataDto.getTmpFileName());
copyFromDto(newFile, fileDataDto);
return fileRepository.save(newFile);
}
private FileData copyFromDto(FileData fileData, FileDataDto fileDataDto) {
fileData.setName(fileDataDto.getName());
fileData.setLatexAttach(fileDataDto.isLatexAttach());
return fileData;
}
@Transactional
public void delete(Integer fileId) {
fileRepository.delete(fileRepository.getOne(fileId));
}
public FileDataDto createFromMultipartFile(MultipartFile multipartFile) throws IOException {
return new FileDataDto(multipartFile.getOriginalFilename(), uploadToTmpDir(multipartFile));
}
public void createLatexAttachs(PaperDto paper) throws IOException {
for (FileDataDto fileDataDto : paper.getFiles()
.stream()
.filter(f -> (f.isLatexAttach() != null && f.isLatexAttach()) && !f.isDeleted())
.collect(Collectors.toList())) {
if (fileDataDto.getId() == null) {
File oldFile = getTmpFilePath(fileDataDto.getTmpFileName()).toFile();
File renamed = getTmpFilePath(fileDataDto.getName()).toFile();
oldFile.renameTo(renamed);
} else {
Files.write(getTmpFilePath(fileDataDto.getName()), fileRepository.getOne(fileDataDto.getId()).getData());
}
}
}
public File createLatexFile(PaperDto paper) throws IOException {
BufferedWriter writer = Files.newBufferedWriter(getTmpFilePath(paper.getTitle() + ".tex"));
writer.write(paper.getLatexText());
writer.close();
return getTmpFilePath(paper.getTitle() + ".tex").toFile();
}
}

@ -9,10 +9,12 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import ru.ulstu.deadline.model.DeadlineDto;
import ru.ulstu.deadline.model.Deadline;
import ru.ulstu.grant.model.Grant;
import ru.ulstu.grant.model.GrantDto;
import ru.ulstu.grant.service.GrantService;
import ru.ulstu.user.model.User;
import springfox.documentation.annotations.ApiIgnore;
import javax.validation.Valid;
import java.io.IOException;
@ -20,10 +22,14 @@ import java.util.List;
import java.util.stream.Collectors;
import static org.springframework.util.StringUtils.isEmpty;
import static ru.ulstu.core.controller.Navigation.GRANTS_PAGE;
import static ru.ulstu.core.controller.Navigation.GRANT_PAGE;
import static ru.ulstu.core.controller.Navigation.REDIRECT_TO;
@Controller()
@RequestMapping(value = "/grants")
@ApiIgnore
public class GrantController {
private final GrantService grantService;
@ -51,41 +57,50 @@ public class GrantController {
}
@PostMapping(value = "/grant", params = "save")
public String save(@Valid GrantDto grantDto, Errors errors) throws IOException {
public String save(@Valid GrantDto grantDto, Errors errors)
throws IOException {
filterEmptyDeadlines(grantDto);
if (grantDto.getDeadlines().isEmpty()) {
errors.rejectValue("deadlines", "errorCode", "Не может быть пустым");
errors.rejectValue("deadlines", "errorCode", "Не может быть пусто");
}
if (grantDto.getLeaderId().equals(-1)) {
errors.rejectValue("leaderId", "errorCode", "Укажите руководителя");
}
if (errors.hasErrors()) {
return "/grants/grant";
return GRANT_PAGE;
}
grantService.save(grantDto);
return "redirect:/grants/grants";
return String.format(REDIRECT_TO, GRANTS_PAGE);
}
@PostMapping(value = "/grant", params = "filterUsers")
public String filterUsers() {
return GRANT_PAGE;
}
@PostMapping(value = "/grant", params = "addDeadline")
public String addDeadline(@Valid GrantDto grantDto, Errors errors) {
filterEmptyDeadlines(grantDto);
if (errors.hasErrors()) {
return "/grants/grant";
return GRANT_PAGE;
}
grantDto.getDeadlines().add(new DeadlineDto());
return "/grants/grant";
grantDto.getDeadlines().add(new Deadline());
return GRANT_PAGE;
}
@PostMapping(value = "/grant", params = "createProject")
public String createProject(@Valid GrantDto grantDto, Errors errors) {
public String createProject(@Valid GrantDto grantDto, Errors errors) throws IOException {
if (errors.hasErrors()) {
return "/grants/grant";
return GRANT_PAGE;
}
grantService.createProject(grantDto);
return "/grants/grant";
return GRANT_PAGE;
}
@GetMapping("/delete/{grant-id}")
public String delete(@PathVariable("grant-id") Integer grantId) throws IOException {
grantService.delete(grantId);
return "redirect:/grants/grants";
return String.format(REDIRECT_TO, GRANTS_PAGE);
}
@ModelAttribute("allStatuses")
@ -93,6 +108,11 @@ public class GrantController {
return grantService.getGrantStatuses();
}
@ModelAttribute("allAuthors")
public List<User> getAllAuthors(GrantDto grantDto) {
return grantService.getGrantAuthors(grantDto);
}
private void filterEmptyDeadlines(GrantDto grantDto) {
grantDto.setDeadlines(grantDto.getDeadlines().stream()
.filter(dto -> dto.getDate() != null || !isEmpty(dto.getDescription()))

@ -1,36 +1,44 @@
package ru.ulstu.grant.model;
import org.hibernate.validator.constraints.NotBlank;
import ru.ulstu.core.model.BaseEntity;
import ru.ulstu.core.model.UserContainer;
import ru.ulstu.deadline.model.Deadline;
import ru.ulstu.file.model.FileData;
import ru.ulstu.project.model.Project;
import ru.ulstu.user.model.User;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
@Entity
@Table(name = "grants")
public class Grant extends BaseEntity {
public class Grant extends BaseEntity implements UserContainer {
public enum GrantStatus {
APPLICATION("Заявка"),
ON_COMPETITION("Отправлен на конкурс"),
SUCCESSFUL_PASSAGE("Успешное прохождение"),
IN_WORK("В работе"),
COMPLETED("Завершен"),
FAILED("Провалены сроки");
FAILED("Провалены сроки"),
LOADED_FROM_KIAS("Загружен автоматически");
private String statusName;
@ -51,6 +59,7 @@ public class Grant extends BaseEntity {
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "grant_id")
@OrderBy("date")
private List<Deadline> deadlines = new ArrayList<>();
//Описание гранта
@ -66,6 +75,14 @@ public class Grant extends BaseEntity {
@JoinColumn(name = "project_id")
private Project project;
@ManyToMany(fetch = FetchType.EAGER)
private Set<User> authors = new HashSet<>();
@NotNull
@ManyToOne
@JoinColumn(name = "leader_id")
private User leader;
public GrantStatus getStatus() {
return status;
}
@ -114,6 +131,27 @@ public class Grant extends BaseEntity {
this.project = project;
}
public Set<User> getAuthors() {
return authors;
}
public void setAuthors(Set<User> authors) {
this.authors = authors;
}
@Override
public Set<User> getUsers() {
return getAuthors();
}
public User getLeader() {
return leader;
}
public void setLeader(User leader) {
this.leader = leader;
}
public Optional<Deadline> getNextDeadline() {
return deadlines
.stream()

@ -2,36 +2,54 @@ package ru.ulstu.grant.model;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.hibernate.validator.constraints.NotEmpty;
import ru.ulstu.deadline.model.DeadlineDto;
import org.apache.commons.lang3.StringUtils;
import ru.ulstu.deadline.model.Deadline;
import ru.ulstu.project.model.ProjectDto;
import ru.ulstu.user.model.UserDto;
import javax.validation.constraints.NotEmpty;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import static ru.ulstu.core.util.StreamApiUtils.convert;
public class GrantDto {
private final static int MAX_AUTHORS_LENGTH = 60;
private Integer id;
@NotEmpty
private String title;
private Grant.GrantStatus status;
private List<DeadlineDto> deadlines = new ArrayList<>();
private List<Deadline> deadlines = new ArrayList<>();
private String comment;
private String applicationFileName;
private ProjectDto project;
private Set<Integer> authorIds;
private Set<UserDto> authors;
private Integer leaderId;
private boolean wasLeader;
private boolean hasAge;
private boolean hasDegree;
public GrantDto() {
deadlines.add(new DeadlineDto());
deadlines.add(new Deadline());
}
@JsonCreator
public GrantDto(@JsonProperty("id") Integer id,
@JsonProperty("title") String title,
@JsonProperty("status") Grant.GrantStatus status,
@JsonProperty("deadlines") List<DeadlineDto> deadlines,
@JsonProperty("deadlines") List<Deadline> deadlines,
@JsonProperty("comment") String comment,
@JsonProperty("project") ProjectDto project) {
@JsonProperty("project") ProjectDto project,
@JsonProperty("authorIds") Set<Integer> authorIds,
@JsonProperty("authors") Set<UserDto> authors,
@JsonProperty("leader") Integer leaderId,
@JsonProperty("wasLeader") boolean wasLeader,
@JsonProperty("hasAge") boolean hasAge,
@JsonProperty("hasDegree") boolean hasDegree) {
this.id = id;
this.title = title;
this.status = status;
@ -39,16 +57,27 @@ public class GrantDto {
this.comment = comment;
this.applicationFileName = null;
this.project = project;
this.authors = authors;
this.leaderId = leaderId;
this.wasLeader = wasLeader;
this.hasAge = hasAge;
this.hasDegree = hasDegree;
}
public GrantDto(Grant grant) {
this.id = grant.getId();
this.title = grant.getTitle();
this.status = grant.getStatus();
this.deadlines = convert(grant.getDeadlines(), DeadlineDto::new);
this.deadlines = grant.getDeadlines();
this.comment = grant.getComment();
this.project = grant.getProject() == null ? null : new ProjectDto(grant.getProject());
this.applicationFileName = grant.getApplication() == null ? null : grant.getApplication().getName();
this.authorIds = convert(grant.getAuthors(), user -> user.getId());
this.authors = convert(grant.getAuthors(), UserDto::new);
this.leaderId = grant.getLeader().getId();
this.wasLeader = false;
this.hasAge = false;
this.hasDegree = false;
}
public Integer getId() {
@ -75,11 +104,11 @@ public class GrantDto {
this.status = status;
}
public List<DeadlineDto> getDeadlines() {
public List<Deadline> getDeadlines() {
return deadlines;
}
public void setDeadlines(List<DeadlineDto> deadlines) {
public void setDeadlines(List<Deadline> deadlines) {
this.deadlines = deadlines;
}
@ -106,4 +135,59 @@ public class GrantDto {
public void setApplicationFileName(String applicationFileName) {
this.applicationFileName = applicationFileName;
}
public Set<Integer> getAuthorIds() {
return authorIds;
}
public void setAuthorIds(Set<Integer> authorIds) {
this.authorIds = authorIds;
}
public Set<UserDto> getAuthors() {
return authors;
}
public void setAuthors(Set<UserDto> authors) {
this.authors = authors;
}
public String getAuthorsString() {
return StringUtils.abbreviate(authors
.stream()
.map(author -> author.getLastName())
.collect(Collectors.joining(", ")), MAX_AUTHORS_LENGTH);
}
public Integer getLeaderId() {
return leaderId;
}
public void setLeaderId(Integer leaderId) {
this.leaderId = leaderId;
}
public boolean isWasLeader() {
return wasLeader;
}
public void setWasLeader(boolean wasLeader) {
this.wasLeader = wasLeader;
}
public boolean isHasAge() {
return hasAge;
}
public void setHasAge(boolean hasAge) {
this.hasAge = hasAge;
}
public boolean isHasDegree() {
return hasDegree;
}
public void setHasDegree(boolean hasDegree) {
this.hasDegree = hasDegree;
}
}

@ -1,19 +0,0 @@
package ru.ulstu.grant.model;
public class GrantStatusDto {
private final String id;
private final String name;
public GrantStatusDto(Grant.GrantStatus status) {
this.id = status.name();
this.name = status.getStatusName();
}
public String getId() {
return id;
}
public String getName() {
return name;
}
}

@ -3,6 +3,9 @@ package ru.ulstu.grant.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import ru.ulstu.grant.model.Grant;
import java.util.List;
public interface GrantRepository extends JpaRepository<Grant, Integer> {
List<Grant> findByStatus(Grant.GrantStatus status);
}

@ -12,11 +12,14 @@ import ru.ulstu.grant.repository.GrantRepository;
import ru.ulstu.project.model.Project;
import ru.ulstu.project.model.ProjectDto;
import ru.ulstu.project.service.ProjectService;
import ru.ulstu.user.model.User;
import ru.ulstu.user.service.UserService;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import static org.springframework.util.ObjectUtils.isEmpty;
import static ru.ulstu.core.util.StreamApiUtils.convert;
@ -30,15 +33,18 @@ public class GrantService {
private final ProjectService projectService;
private final DeadlineService deadlineService;
private final FileService fileService;
private final UserService userService;
public GrantService(GrantRepository grantRepository,
FileService fileService,
DeadlineService deadlineService,
ProjectService projectService) {
ProjectService projectService,
UserService userService) {
this.grantRepository = grantRepository;
this.projectService = projectService;
this.fileService = fileService;
this.deadlineService = deadlineService;
this.projectService = projectService;
this.userService = userService;
}
public List<Grant> findAll() {
@ -52,7 +58,7 @@ public class GrantService {
}
public GrantDto findOneDto(Integer id) {
return new GrantDto(grantRepository.findOne(id));
return new GrantDto(grantRepository.getOne(id));
}
@Transactional
@ -73,17 +79,24 @@ public class GrantService {
if (grantDto.getApplicationFileName() != null) {
grant.setApplication(fileService.createFileFromTmp(grantDto.getApplicationFileName()));
}
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()));
}
return grant;
}
public void createProject(GrantDto grantDto) {
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 = grantRepository.findOne(grantDto.getId());
Grant grant = grantRepository.getOne(grantDto.getId());
Grant.GrantStatus oldStatus = grant.getStatus();
if (grantDto.getApplicationFileName() != null && grant.getApplication() != null) {
fileService.deleteFile(grant.getApplication());
@ -94,11 +107,10 @@ public class GrantService {
@Transactional
public void delete(Integer grantId) throws IOException {
Grant grant = grantRepository.findOne(grantId);
Grant grant = grantRepository.getOne(grantId);
if (grant.getApplication() != null) {
fileService.deleteFile(grant.getApplication());
}
//возможно при удалении гранта будет удаляться и проект, к нему привязанный
grantRepository.delete(grant);
}
@ -107,13 +119,15 @@ public class GrantService {
}
@Transactional
public Grant create(String title, Project projectId, Date deadlineDate) {
public Grant create(String title, Project projectId, Date deadlineDate, User user) {
Grant grant = new Grant();
grant.setTitle(title);
grant.setComment("Комментарий к гранту 1");
grant.setProject(projectId);
grant.setStatus(APPLICATION);
grant.getDeadlines().add(new Deadline(deadlineDate, "первый дедлайн"));
grant.getAuthors().add(user);
grant.setLeader(user);
grant = grantRepository.save(grant);
return grant;
}
@ -125,4 +139,22 @@ public class GrantService {
update(grantDto);
}
}
public List<User> getGrantAuthors(GrantDto grantDto) {
List<User> filteredUsers = userService.filterByAgeAndDegree(grantDto.isHasAge(), grantDto.isHasDegree());
if (grantDto.isWasLeader()) {
filteredUsers = filteredUsers
.stream()
.filter(getCompletedGrantLeaders()::contains)
.collect(Collectors.toList());
}
return filteredUsers;
}
private List<User> getCompletedGrantLeaders() {
return grantRepository.findByStatus(Grant.GrantStatus.COMPLETED)
.stream()
.map(Grant::getLeader)
.collect(Collectors.toList());
}
}

@ -0,0 +1,23 @@
package ru.ulstu.index.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import ru.ulstu.core.controller.AdviceController;
import ru.ulstu.user.service.UserService;
import springfox.documentation.annotations.ApiIgnore;
@Controller()
@RequestMapping(value = "/index")
@ApiIgnore
public class IndexController extends AdviceController {
public IndexController(UserService userService) {
super(userService);
}
@GetMapping
public void currentUser(ModelMap modelMap) {
//нужен здесь для добавления параметров на стартовой странице
}
}

@ -1,13 +1,13 @@
package ru.ulstu.odin.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.hibernate.validator.constraints.NotBlank;
import org.hibernate.validator.constraints.NotEmpty;
import ru.ulstu.core.error.OdinException;
import ru.ulstu.odin.model.annotation.OdinCaption;
import ru.ulstu.odin.model.annotation.OdinReadOnly;
import ru.ulstu.odin.model.annotation.OdinVisible;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
@ -31,14 +31,13 @@ public abstract class OdinField implements Comparable {
return this.name().toLowerCase();
}
}
private Field field;
protected final OdinFieldType fieldType;
protected final String fieldName;
protected final String caption;
protected final OdinVisible.OdinVisibleType visible;
protected final boolean readOnly;
protected final boolean notEmpty;
private Field field;
public OdinField(Field field, OdinFieldType fieldType) {
this.field = field;
@ -126,8 +125,12 @@ public abstract class OdinField implements Comparable {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
OdinField odinField = (OdinField) o;
return Objects.equals(fieldName, odinField.fieldName);
}

@ -1,9 +1,9 @@
package ru.ulstu.odin.model;
import org.hibernate.validator.constraints.Email;
import ru.ulstu.odin.model.annotation.OdinString;
import ru.ulstu.odin.model.annotation.OdinString.OdinStringType;
import javax.validation.constraints.Email;
import javax.validation.constraints.Size;
import java.lang.reflect.Field;

@ -1,5 +1,8 @@
package ru.ulstu.paper.controller;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.Errors;
@ -9,30 +12,37 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import ru.ulstu.deadline.model.DeadlineDto;
import ru.ulstu.deadline.model.Deadline;
import ru.ulstu.paper.model.Paper;
import ru.ulstu.paper.model.PaperDto;
import ru.ulstu.paper.model.PaperFilterDto;
import ru.ulstu.paper.service.LatexService;
import ru.ulstu.paper.service.PaperService;
import ru.ulstu.user.model.User;
import springfox.documentation.annotations.ApiIgnore;
import javax.validation.Valid;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.stream.Collectors;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.springframework.util.StringUtils.isEmpty;
@Controller()
@RequestMapping(value = "/papers")
@ApiIgnore
public class PaperController {
private final PaperService paperService;
private final LatexService latexService;
public PaperController(PaperService paperService) {
public PaperController(PaperService paperService, LatexService latexService) {
this.paperService = paperService;
this.latexService = latexService;
}
@GetMapping("/papers")
@ -49,7 +59,7 @@ public class PaperController {
@GetMapping("/dashboard")
public void getDashboard(ModelMap modelMap) {
modelMap.put("papers", paperService.findAllActive());
modelMap.put("papers", paperService.findAllActiveDto());
}
@GetMapping("/paper")
@ -80,7 +90,7 @@ public class PaperController {
if (errors.hasErrors()) {
return "/papers/paper";
}
paperDto.getDeadlines().add(new DeadlineDto());
paperDto.getDeadlines().add(new Deadline());
return "/papers/paper";
}
@ -95,6 +105,11 @@ public class PaperController {
return paperService.getPaperStatuses();
}
@ModelAttribute("allTypes")
public List<Paper.PaperType> getPaperTypes() {
return paperService.getPaperTypes();
}
@ModelAttribute("allAuthors")
public List<User> getAllAuthors() {
return paperService.getPaperAuthors();
@ -109,6 +124,14 @@ public class PaperController {
return years;
}
@PostMapping("/generatePdf")
public ResponseEntity<byte[]> getPdfFile(PaperDto paper) throws IOException, InterruptedException {
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Disposition", "attachment; filename='" +
URLEncoder.encode(paper.getTitle() + ".pdf", UTF_8.toString()) + "'");
return new ResponseEntity<>(latexService.generatePdfFromLatexFile(paper), headers, HttpStatus.OK);
}
private void filterEmptyDeadlines(PaperDto paperDto) {
paperDto.setDeadlines(paperDto.getDeadlines().stream()
.filter(dto -> dto.getDate() != null || !isEmpty(dto.getDescription()))

@ -61,4 +61,9 @@ public class PaperRestController {
public Response<List<PaperDto>> filter(@RequestBody @Valid PaperFilterDto paperFilterDto) throws IOException {
return new Response<>(paperService.filter(paperFilterDto));
}
@GetMapping("formatted-list")
public Response<List<String>> getFormattedPaperList() {
return new Response<>(paperService.getFormattedPaperList());
}
}

@ -2,11 +2,11 @@ package ru.ulstu.paper.model;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.validator.constraints.NotBlank;
import ru.ulstu.core.model.BaseEntity;
import ru.ulstu.core.model.UserContainer;
import ru.ulstu.deadline.model.Deadline;
import ru.ulstu.file.model.FileData;
import ru.ulstu.timeline.model.Event;
import ru.ulstu.user.model.User;
import javax.persistence.CascadeType;
@ -17,11 +17,11 @@ import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotBlank;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
@ -53,12 +53,32 @@ public class Paper extends BaseEntity implements UserContainer {
}
}
public enum PaperType {
OTHER("Прочая публикация"),
VAK("ВАК"),
SCOPUS("Scopus"),
WEB_OF_SCIENCE("Web Of Science");
private String typeName;
PaperType(String name) {
this.typeName = name;
}
public String getTypeName() {
return typeName;
}
}
@NotBlank
private String title;
@Enumerated(value = EnumType.STRING)
private PaperStatus status = PaperStatus.DRAFT;
@Enumerated(value = EnumType.STRING)
private PaperType type = PaperType.OTHER;
@Column(name = "create_date")
@Temporal(TemporalType.TIMESTAMP)
private Date createDate = new Date();
@ -75,15 +95,25 @@ public class Paper extends BaseEntity implements UserContainer {
private String comment;
private String url;
private Boolean locked = false;
@ManyToOne
@JoinColumn(name = "file_id")
private FileData fileData;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "paper_id")
private List<Event> events = new ArrayList<>();
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "paper_id", unique = true)
@Fetch(FetchMode.SUBSELECT)
private List<FileData> files = new ArrayList<>();
@ManyToMany(fetch = FetchType.EAGER)
private Set<User> authors = new HashSet<>();
@Column(name = "latex_text")
private String latexText;
public PaperStatus getStatus() {
return status;
}
@ -92,6 +122,14 @@ public class Paper extends BaseEntity implements UserContainer {
this.status = status;
}
public PaperType getType() {
return type;
}
public void setType(PaperType type) {
this.type = type;
}
public Date getCreateDate() {
return createDate;
}
@ -132,12 +170,12 @@ public class Paper extends BaseEntity implements UserContainer {
this.locked = locked;
}
public FileData getFileData() {
return fileData;
public List<FileData> getFiles() {
return files;
}
public void setFileData(FileData fileData) {
this.fileData = fileData;
public void setFiles(List<FileData> files) {
this.files = files;
}
public String getTitle() {
@ -156,6 +194,30 @@ public class Paper extends BaseEntity implements UserContainer {
this.authors = authors;
}
public List<Event> getEvents() {
return events;
}
public void setEvents(List<Event> events) {
this.events = events;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getLatexText() {
return latexText;
}
public void setLatexText(String latexText) {
this.latexText = latexText;
}
@Override
public Set<User> getUsers() {
return getAuthors();

@ -3,10 +3,11 @@ package ru.ulstu.paper.model;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.validator.constraints.NotEmpty;
import ru.ulstu.deadline.model.DeadlineDto;
import ru.ulstu.deadline.model.Deadline;
import ru.ulstu.file.model.FileDataDto;
import ru.ulstu.user.model.UserDto;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;
import java.util.ArrayList;
import java.util.Date;
@ -24,48 +25,51 @@ public class PaperDto {
@Size(min = 3, max = 254)
private String title;
private Paper.PaperStatus status;
private Paper.PaperType type;
private Date createDate;
private Date updateDate;
@NotEmpty
private List<DeadlineDto> deadlines = new ArrayList<>();
private List<Deadline> deadlines = new ArrayList<>();
private String comment;
private String url;
private Boolean locked;
private String tmpFileName;
private Integer fileId;
private String fileName;
private Date fileCreateDate;
private List<FileDataDto> files = new ArrayList<>();
private Set<Integer> authorIds;
private Set<UserDto> authors;
private Integer filterAuthorId;
private String latexText;
public PaperDto() {
deadlines.add(new DeadlineDto());
deadlines.add(new Deadline());
}
@JsonCreator
public PaperDto(@JsonProperty("id") Integer id,
@JsonProperty("title") String title,
@JsonProperty("status") Paper.PaperStatus status,
@JsonProperty("type") Paper.PaperType type,
@JsonProperty("createDate") Date createDate,
@JsonProperty("updateDate") Date updateDate,
@JsonProperty("deadlines") List<DeadlineDto> deadlines,
@JsonProperty("deadlines") List<Deadline> deadlines,
@JsonProperty("comment") String comment,
@JsonProperty("latex_text") String latexText,
@JsonProperty("url") String url,
@JsonProperty("locked") Boolean locked,
@JsonProperty("tmpFileName") String tmpFileName,
@JsonProperty("files") List<FileDataDto> files,
@JsonProperty("authorIds") Set<Integer> authorIds,
@JsonProperty("authors") Set<UserDto> authors) {
this.id = id;
this.title = title;
this.status = status;
this.type = type;
this.createDate = createDate;
this.updateDate = updateDate;
this.deadlines = deadlines;
this.comment = comment;
this.url = url;
this.latexText = latexText;
this.locked = locked;
this.tmpFileName = tmpFileName;
this.fileId = null;
this.fileName = null;
this.fileCreateDate = null;
this.files = files;
this.authors = authors;
}
@ -73,15 +77,15 @@ public class PaperDto {
this.id = paper.getId();
this.title = paper.getTitle();
this.status = paper.getStatus();
this.type = paper.getType();
this.createDate = paper.getCreateDate();
this.updateDate = paper.getUpdateDate();
this.deadlines = convert(paper.getDeadlines(), DeadlineDto::new);
this.deadlines = paper.getDeadlines();
this.comment = paper.getComment();
this.url = paper.getUrl();
this.latexText = paper.getLatexText();
this.locked = paper.getLocked();
this.tmpFileName = null;
this.fileId = paper.getFileData() == null ? null : paper.getFileData().getId();
this.fileName = paper.getFileData() == null ? null : paper.getFileData().getName();
this.fileCreateDate = paper.getFileData() == null ? null : paper.getFileData().getCreateDate();
this.files = convert(paper.getFiles(), FileDataDto::new);
this.authorIds = convert(paper.getAuthors(), user -> user.getId());
this.authors = convert(paper.getAuthors(), UserDto::new);
}
@ -110,6 +114,14 @@ public class PaperDto {
this.status = status;
}
public Paper.PaperType getType() {
return type;
}
public void setType(Paper.PaperType type) {
this.type = type;
}
public Date getCreateDate() {
return createDate;
}
@ -126,11 +138,11 @@ public class PaperDto {
this.updateDate = updateDate;
}
public List<DeadlineDto> getDeadlines() {
public List<Deadline> getDeadlines() {
return deadlines;
}
public void setDeadlines(List<DeadlineDto> deadlines) {
public void setDeadlines(List<Deadline> deadlines) {
this.deadlines = deadlines;
}
@ -150,36 +162,12 @@ public class PaperDto {
this.locked = locked;
}
public String getTmpFileName() {
return tmpFileName;
}
public void setTmpFileName(String tmpFileName) {
this.tmpFileName = tmpFileName;
}
public Integer getFileId() {
return fileId;
}
public void setFileId(Integer fileId) {
this.fileId = fileId;
}
public String getFileName() {
return fileName;
public List<FileDataDto> getFiles() {
return files;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public Date getFileCreateDate() {
return fileCreateDate;
}
public void setFileCreateDate(Date fileCreateDate) {
this.fileCreateDate = fileCreateDate;
public void setFiles(List<FileDataDto> files) {
this.files = files;
}
public Set<UserDto> getAuthors() {
@ -198,6 +186,22 @@ public class PaperDto {
this.authorIds = authorIds;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getLatexText() {
return latexText;
}
public void setLatexText(String latexText) {
this.latexText = latexText;
}
public String getAuthorsString() {
return StringUtils.abbreviate(authors
.stream()

@ -12,4 +12,6 @@ public interface PaperRepository extends JpaRepository<Paper, Integer> {
@Query("SELECT p FROM Paper p WHERE (:author IS NULL OR :author MEMBER OF p.authors) AND (YEAR(p.createDate) = :year OR :year IS NULL)")
List<Paper> filter(@Param("author") User author, @Param("year") Integer year);
List<Paper> findByIdNotIn(List<Integer> paperIds);
}

@ -0,0 +1,76 @@
package ru.ulstu.paper.service;
import org.springframework.stereotype.Service;
import ru.ulstu.file.service.FileService;
import ru.ulstu.paper.model.PaperDto;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
@Service
public class LatexService {
private final String pdfLatexError = "Errors occurred while executing pdfLaTeX.";
private final String bibtexError = "Errors occurred while executing bibtex.";
private String errorMessage;
private File pdfFile;
private FileService fileService;
public LatexService(FileService fileService) {
this.fileService = fileService;
}
public byte[] generatePdfFromLatexFile(PaperDto paper) throws IOException, InterruptedException {
fileService.createLatexAttachs(paper);
File tex = fileService.createLatexFile(paper);
if (!generate(paper.getTitle(), tex.getParentFile())) {
throw new IOException(errorMessage);
}
return Files.readAllBytes(pdfFile.toPath());
}
private int startProcess(String[] args, File dir, String message) throws IOException, InterruptedException {
ProcessBuilder processBuilder = new ProcessBuilder(args);
processBuilder.redirectErrorStream(true);
processBuilder.directory(dir);
Process process = processBuilder.start();
InputStreamReader inputStreamReader = new InputStreamReader(process.getInputStream());
try (BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
while ((bufferedReader.readLine()) != null) {
//
}
}
int exitCode = process.waitFor();
if (exitCode != 0) {
errorMessage = message + " Exit value of the process: " + exitCode;
}
return exitCode;
}
private boolean generate(String filename, File dir) throws IOException, InterruptedException {
startProcess(new String[]{"pdflatex", filename, "--interaction=nonstopmode"}, dir, pdfLatexError);
startProcess(new String[]{"bibtex", filename}, dir, bibtexError);
if (startProcess(new String[]{"pdflatex", filename, "--interaction=nonstopmode"}, dir, pdfLatexError) != 0) {
return false;
}
return checkPdf(filename, dir);
}
private boolean checkPdf(String filename, File dir) {
pdfFile = new File(dir.getAbsolutePath() + File.separator + filename + ".pdf");
if (pdfFile.isFile()) {
return true;
} else {
errorMessage = "The pdf file could not be created.";
return false;
}
}
}

@ -5,11 +5,13 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
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.paper.model.Paper;
import ru.ulstu.paper.model.PaperDto;
import ru.ulstu.paper.model.PaperFilterDto;
import ru.ulstu.paper.repository.PaperRepository;
import ru.ulstu.timeline.service.EventService;
import ru.ulstu.user.model.User;
import ru.ulstu.user.service.UserService;
@ -21,6 +23,7 @@ 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.paper.model.Paper.PaperStatus.ATTENTION;
@ -28,27 +31,32 @@ import static ru.ulstu.paper.model.Paper.PaperStatus.COMPLETED;
import static ru.ulstu.paper.model.Paper.PaperStatus.DRAFT;
import static ru.ulstu.paper.model.Paper.PaperStatus.FAILED;
import static ru.ulstu.paper.model.Paper.PaperStatus.ON_PREPARATION;
import static ru.ulstu.paper.model.Paper.PaperType.OTHER;
@Service
public class PaperService {
private final static int MAX_DISPLAY_SIZE = 40;
private final static String PAPER_FORMATTED_TEMPLATE = "%s %s";
private final PaperNotificationService paperNotificationService;
private final PaperRepository paperRepository;
private final UserService userService;
private final DeadlineService deadlineService;
private final FileService fileService;
private final EventService eventService;
public PaperService(PaperRepository paperRepository,
FileService fileService,
PaperNotificationService paperNotificationService,
UserService userService,
DeadlineService deadlineService) {
DeadlineService deadlineService,
EventService eventService) {
this.paperRepository = paperRepository;
this.fileService = fileService;
this.paperNotificationService = paperNotificationService;
this.userService = userService;
this.deadlineService = deadlineService;
this.eventService = eventService;
}
public List<Paper> findAll() {
@ -61,15 +69,19 @@ public class PaperService {
return papers;
}
public List<PaperDto> findAllActive() {
return findAllDto()
public List<Paper> findAllActive() {
return findAll()
.stream()
.filter(paper -> paper.getStatus() != COMPLETED && paper.getStatus() != FAILED)
.collect(Collectors.toList());
.collect(toList());
}
public List<PaperDto> findAllActiveDto() {
return convert(findAllActive(), PaperDto::new);
}
public PaperDto findOneDto(Integer id) {
return new PaperDto(paperRepository.findOne(id));
return new PaperDto(paperRepository.getOne(id));
}
@Transactional
@ -77,20 +89,24 @@ public class PaperService {
Paper newPaper = copyFromDto(new Paper(), paperDto);
newPaper = paperRepository.save(newPaper);
paperNotificationService.sendCreateNotification(newPaper);
eventService.createFromPaper(newPaper);
return newPaper.getId();
}
private Paper copyFromDto(Paper paper, PaperDto paperDto) throws IOException {
paper.setComment(paperDto.getComment());
paper.setUrl(paperDto.getUrl());
paper.setLatexText(paperDto.getLatexText());
paper.setCreateDate(paper.getCreateDate() == null ? new Date() : paper.getCreateDate());
paper.setLocked(paperDto.getLocked());
paper.setStatus(paperDto.getStatus() == null ? DRAFT : paperDto.getStatus());
paper.setType(paperDto.getType() == null ? OTHER : paperDto.getType());
paper.setTitle(paperDto.getTitle());
paper.setUpdateDate(new Date());
paper.setDeadlines(deadlineService.saveOrCreate(paperDto.getDeadlines()));
if (paperDto.getTmpFileName() != null) {
paper.setFileData(fileService.createFileFromTmp(paperDto.getTmpFileName()));
}
paper.setFiles(fileService.saveOrCreate(paperDto.getFiles().stream()
.filter(f -> !f.isDeleted())
.collect(toList())));
paper.getAuthors().clear();
if (paperDto.getAuthorIds() != null && !paperDto.getAuthorIds().isEmpty()) {
paperDto.getAuthorIds().forEach(authorIds -> paper.getAuthors().add(userService.findById(authorIds)));
@ -100,13 +116,17 @@ public class PaperService {
@Transactional
public Integer update(PaperDto paperDto) throws IOException {
Paper paper = paperRepository.findOne(paperDto.getId());
Paper paper = paperRepository.getOne(paperDto.getId());
Paper.PaperStatus oldStatus = paper.getStatus();
Set<User> oldAuthors = new HashSet<>(paper.getAuthors());
if (paperDto.getTmpFileName() != null && paper.getFileData() != null) {
fileService.deleteFile(paper.getFileData());
for (FileDataDto file : paperDto.getFiles().stream()
.filter(f -> f.isDeleted() && f.getId() != null)
.collect(toList())) {
fileService.delete(file.getId());
}
paperRepository.save(copyFromDto(paper, paperDto));
eventService.updatePaperDeadlines(paper);
paper.getAuthors().forEach(author -> {
if (!oldAuthors.contains(author)) {
@ -123,10 +143,7 @@ public class PaperService {
@Transactional
public void delete(Integer paperId) throws IOException {
Paper paper = paperRepository.findOne(paperId);
if (paper.getFileData() != null) {
fileService.deleteFile(paper.getFileData());
}
Paper paper = paperRepository.getOne(paperId);
paperRepository.delete(paper);
}
@ -134,6 +151,10 @@ public class PaperService {
return Arrays.asList(Paper.PaperStatus.values());
}
public List<Paper.PaperType> getPaperTypes() {
return Arrays.asList(Paper.PaperType.values());
}
@Transactional
public Paper create(String title, User user, Date deadlineDate) {
Paper paper = new Paper();
@ -143,9 +164,11 @@ public class PaperService {
paper.setCreateDate(new Date());
paper.setUpdateDate(new Date());
paper.setStatus(DRAFT);
paper.setType(OTHER);
paper = paperRepository.save(paper);
paperNotificationService.sendCreateNotification(paper);
eventService.createFromPaper(paper);
return paper;
}
@ -165,7 +188,7 @@ public class PaperService {
return statusCompareResult;
}
return paper1.getTitle().compareTo(paper2.getTitle());
}).collect(Collectors.toList());
}).collect(toList());
}
public PaperDto findPaper(int id) {
@ -179,7 +202,7 @@ public class PaperService {
&& (paper.getStatus() == ON_PREPARATION
|| paper.getStatus() == DRAFT
|| paper.getStatus() == ATTENTION))
.collect(Collectors.toList());
.collect(toList());
papers.forEach(paper -> {
Paper.PaperStatus oldStatus = paper.getStatus();
paper.setStatus(Paper.PaperStatus.FAILED);
@ -197,10 +220,44 @@ public class PaperService {
}
public PaperDto findById(Integer paperId) {
return new PaperDto(paperRepository.findOne(paperId));
return new PaperDto(paperRepository.getOne(paperId));
}
public Paper findEntityById(Integer paperId) {
return paperRepository.getOne(paperId);
}
public List<Paper> findAllNotSelect(List<Integer> paperIds) {
if (!paperIds.isEmpty()) {
return sortPapers(paperRepository.findByIdNotIn(paperIds));
} else {
return sortPapers(paperRepository.findAll());
}
}
public List<User> getPaperAuthors() {
return userService.findAll();
}
public List<String> getFormattedPaperList() {
return findAllCompleted()
.stream()
.map(paper -> String.format(PAPER_FORMATTED_TEMPLATE, paper.getTitle(), getAuthors(paper)))
.collect(toList());
}
private List<Paper> findAllCompleted() {
return findAll()
.stream()
.filter(paper -> paper.getStatus() == COMPLETED)
.collect(toList());
}
private String getAuthors(Paper paper) {
return paper.getAuthors()
.stream()
.map(User::getUserAbbreviate)
.collect(Collectors.joining(", "));
}
}

@ -0,0 +1,86 @@
package ru.ulstu.project.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import ru.ulstu.deadline.model.Deadline;
import ru.ulstu.project.model.Project;
import ru.ulstu.project.model.ProjectDto;
import ru.ulstu.project.service.ProjectService;
import springfox.documentation.annotations.ApiIgnore;
import javax.validation.Valid;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;
import static org.springframework.util.StringUtils.isEmpty;
@Controller()
@RequestMapping(value = "/projects")
@ApiIgnore
public class ProjectController {
private final ProjectService projectService;
public ProjectController(ProjectService projectService) {
this.projectService = projectService;
}
@GetMapping("/dashboard")
public void getDashboard(ModelMap modelMap) {
modelMap.put("projects", projectService.findAllDto());
}
@GetMapping("/projects")
public void getProjects(ModelMap modelMap) {
modelMap.put("projects", projectService.findAllDto());
}
@GetMapping("/project")
public void getProject(ModelMap modelMap, @RequestParam(value = "id") Integer id) {
if (id != null && id > 0) {
modelMap.put("projectDto", projectService.findOneDto(id));
} else {
modelMap.put("projectDto", new ProjectDto());
}
}
@ModelAttribute("allStatuses")
public List<Project.ProjectStatus> getProjectStatuses() {
return projectService.getProjectStatuses();
}
@PostMapping(value = "/project", params = "save")
public String save(@Valid ProjectDto projectDto, Errors errors) throws IOException {
filterEmptyDeadlines(projectDto);
if (projectDto.getDeadlines().isEmpty()) {
errors.rejectValue("deadlines", "errorCode", "Не может быть пустым");
}
if (errors.hasErrors()) {
return "/projects/project";
}
projectService.save(projectDto);
return String.format("redirect:%s", "/projects/projects");
}
@PostMapping(value = "/project", params = "addDeadline")
public String addDeadline(@Valid ProjectDto projectDto, Errors errors) {
filterEmptyDeadlines(projectDto);
if (errors.hasErrors()) {
return "/projects/project";
}
projectDto.getDeadlines().add(new Deadline());
return "/projects/project";
}
private void filterEmptyDeadlines(ProjectDto projectDto) {
projectDto.setDeadlines(projectDto.getDeadlines().stream()
.filter(dto -> dto.getDate() != null || !isEmpty(dto.getDescription()))
.collect(Collectors.toList()));
}
}

@ -1,26 +1,67 @@
package ru.ulstu.project.model;
import org.hibernate.validator.constraints.NotBlank;
import ru.ulstu.core.model.BaseEntity;
import ru.ulstu.deadline.model.Deadline;
import ru.ulstu.file.model.FileData;
import ru.ulstu.grant.model.Grant;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;
@Entity
public class Project extends BaseEntity {
public enum ProjectStatus {
APPLICATION("Заявка"),
ON_COMPETITION("Отправлен на конкурс"),
SUCCESSFUL_PASSAGE("Успешное прохождение"),
IN_WORK("В работе"),
COMPLETED("Завершен"),
FAILED("Провалены сроки");
private String statusName;
ProjectStatus(String statusName) {
this.statusName = statusName;
}
public String getStatusName() {
return statusName;
}
}
@NotBlank
private String title;
@Enumerated(value = EnumType.STRING)
private ProjectStatus status = ProjectStatus.APPLICATION;
@NotNull
private String description;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "project_id")
private List<Deadline> deadlines = new ArrayList<>();
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "grant_id")
private Grant grant;
@NotNull
private String repository;
@ManyToOne
@JoinColumn(name = "file_id")
private FileData application;
public String getTitle() {
return title;
}
@ -29,6 +70,38 @@ public class Project extends BaseEntity {
this.title = title;
}
public ProjectStatus getStatus() {
return status;
}
public void setStatus(ProjectStatus status) {
this.status = status;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Grant getGrant() {
return grant;
}
public void setGrant(Grant grant) {
this.grant = grant;
}
public String getRepository() {
return repository;
}
public void setRepository(String repository) {
this.repository = repository;
}
public List<Deadline> getDeadlines() {
return deadlines;
}
@ -36,4 +109,12 @@ public class Project extends BaseEntity {
public void setDeadlines(List<Deadline> deadlines) {
this.deadlines = deadlines;
}
public FileData getApplication() {
return application;
}
public void setApplication(FileData application) {
this.application = application;
}
}

@ -2,21 +2,24 @@ package ru.ulstu.project.model;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.hibernate.validator.constraints.NotEmpty;
import ru.ulstu.deadline.model.DeadlineDto;
import ru.ulstu.deadline.model.Deadline;
import ru.ulstu.grant.model.GrantDto;
import javax.validation.constraints.NotEmpty;
import java.util.ArrayList;
import java.util.List;
import static ru.ulstu.core.util.StreamApiUtils.convert;
public class ProjectDto {
private Integer id;
@NotEmpty
private String title;
private List<DeadlineDto> deadlines = new ArrayList<>();
private Project.ProjectStatus status;
private String description;
private List<Deadline> deadlines = new ArrayList<>();
private GrantDto grant;
private String repository;
private String applicationFileName;
public ProjectDto() {
}
@ -28,17 +31,31 @@ public class ProjectDto {
@JsonCreator
public ProjectDto(@JsonProperty("id") Integer id,
@JsonProperty("title") String title,
@JsonProperty("deadlines") List<DeadlineDto> deadlines) {
@JsonProperty("status") Project.ProjectStatus status,
@JsonProperty("description") String description,
@JsonProperty("grant") GrantDto grant,
@JsonProperty("repository") String repository,
@JsonProperty("deadlines") List<Deadline> deadlines) {
this.id = id;
this.title = title;
this.status = status;
this.description = description;
this.grant = grant;
this.repository = repository;
this.deadlines = deadlines;
this.applicationFileName = null;
}
public ProjectDto(Project project) {
this.id = project.getId();
this.title = project.getTitle();
this.deadlines = convert(project.getDeadlines(), DeadlineDto::new);
this.status = project.getStatus();
this.description = project.getDescription();
this.applicationFileName = project.getApplication() == null ? null : project.getApplication().getName();
this.grant = project.getGrant() == null ? null : new GrantDto(project.getGrant());
this.repository = project.getRepository();
this.deadlines = project.getDeadlines();
}
public Integer getId() {
@ -57,11 +74,51 @@ public class ProjectDto {
this.title = title;
}
public List<DeadlineDto> getDeadlines() {
public Project.ProjectStatus getStatus() {
return status;
}
public void setStatus(Project.ProjectStatus status) {
this.status = status;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public GrantDto getGrant() {
return grant;
}
public void setGrant(GrantDto grant) {
this.grant = grant;
}
public String getRepository() {
return repository;
}
public void setRepository(String repository) {
this.repository = repository;
}
public List<Deadline> getDeadlines() {
return deadlines;
}
public void setDeadlines(List<DeadlineDto> deadlines) {
public void setDeadlines(List<Deadline> deadlines) {
this.deadlines = deadlines;
}
public String getApplicationFileName() {
return applicationFileName;
}
public void setApplicationFileName(String applicationFileName) {
this.applicationFileName = applicationFileName;
}
}

@ -2,45 +2,82 @@ package ru.ulstu.project.service;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.thymeleaf.util.StringUtils;
import ru.ulstu.deadline.service.DeadlineService;
import ru.ulstu.file.service.FileService;
import ru.ulstu.grant.repository.GrantRepository;
import ru.ulstu.project.model.Project;
import ru.ulstu.project.model.ProjectDto;
import ru.ulstu.project.repository.ProjectRepository;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import static org.springframework.util.ObjectUtils.isEmpty;
import static ru.ulstu.core.util.StreamApiUtils.convert;
import static ru.ulstu.project.model.Project.ProjectStatus.APPLICATION;
@Service
public class ProjectService {
private final static int MAX_DISPLAY_SIZE = 40;
private final ProjectRepository projectRepository;
private final DeadlineService deadlineService;
private final GrantRepository grantRepository;
private final FileService fileService;
public ProjectService(ProjectRepository projectRepository,
DeadlineService deadlineService) {
DeadlineService deadlineService,
GrantRepository grantRepository,
FileService fileService) {
this.projectRepository = projectRepository;
this.deadlineService = deadlineService;
this.grantRepository = grantRepository;
this.fileService = fileService;
}
public List<Project> findAll() {
return projectRepository.findAll();
}
public List<ProjectDto> findAllDto() {
List<ProjectDto> projects = convert(findAll(), ProjectDto::new);
projects.forEach(projectDto -> projectDto.setTitle(StringUtils.abbreviate(projectDto.getTitle(), MAX_DISPLAY_SIZE)));
return projects;
}
public ProjectDto findOneDto(Integer id) {
return new ProjectDto(projectRepository.getOne(id));
}
public List<Project.ProjectStatus> getProjectStatuses() {
return Arrays.asList(Project.ProjectStatus.values());
}
@Transactional
public Project create(ProjectDto projectDto) {
public Project create(ProjectDto projectDto) throws IOException {
Project newProject = copyFromDto(new Project(), projectDto);
newProject = projectRepository.save(newProject);
return newProject;
}
private Project copyFromDto(Project project, ProjectDto projectDto) {
private Project copyFromDto(Project project, ProjectDto projectDto) throws IOException {
project.setDescription(projectDto.getDescription());
project.setStatus(projectDto.getStatus() == null ? APPLICATION : projectDto.getStatus());
project.setTitle(projectDto.getTitle());
if (projectDto.getGrant() != null && projectDto.getGrant().getId() != null) {
project.setGrant(grantRepository.getOne(projectDto.getGrant().getId()));
}
project.setRepository(projectDto.getRepository());
project.setDeadlines(deadlineService.saveOrCreate(projectDto.getDeadlines()));
if (projectDto.getApplicationFileName() != null) {
project.setApplication(fileService.createFileFromTmp(projectDto.getApplicationFileName()));
}
return project;
}
public Project save(ProjectDto projectDto) {
public Project save(ProjectDto projectDto) throws IOException {
if (isEmpty(projectDto.getId())) {
return create(projectDto);
} else {
@ -53,7 +90,7 @@ public class ProjectService {
}
public Project findById(Integer id) {
return projectRepository.findOne(id);
return projectRepository.getOne(id);
}
}

@ -0,0 +1,16 @@
package ru.ulstu.students.controller;
import org.springframework.validation.Errors;
public class Navigation {
public static final String REDIRECT_TO = "redirect:%s";
public static final String TASKS_PAGE = "/students/tasks";
public static final String TASK_PAGE = "/students/task";
public static String hasErrors(Errors errors, String page) {
if (errors.hasErrors()) {
return page;
}
return null;
}
}

@ -0,0 +1,90 @@
package ru.ulstu.students.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import ru.ulstu.deadline.model.Deadline;
import ru.ulstu.students.model.Task;
import ru.ulstu.students.model.TaskDto;
import ru.ulstu.students.service.TaskService;
import springfox.documentation.annotations.ApiIgnore;
import javax.validation.Valid;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;
import static org.springframework.util.StringUtils.isEmpty;
import static ru.ulstu.students.controller.Navigation.REDIRECT_TO;
import static ru.ulstu.students.controller.Navigation.TASKS_PAGE;
import static ru.ulstu.students.controller.Navigation.TASK_PAGE;
@Controller()
@RequestMapping(value = "/students")
@ApiIgnore
public class TaskController {
private final TaskService taskService;
public TaskController(TaskService taskService) {
this.taskService = taskService;
}
@GetMapping("/tasks")
public void getTasks(ModelMap modelMap) {
modelMap.put("tasks", taskService.findAllDto());
}
@GetMapping("/dashboard")
public void getDashboard(ModelMap modelMap) {
modelMap.put("tasks", taskService.findAllDto());
}
@GetMapping("/task")
public void getTask(ModelMap modelMap, @RequestParam(value = "id") Integer id) {
if (id != null && id > 0) {
modelMap.put("taskDto", taskService.findOneDto(id));
} else {
modelMap.put("taskDto", new TaskDto());
}
}
@PostMapping(value = "/task", params = "save")
public String save(@Valid TaskDto taskDto, Errors errors) throws IOException {
filterEmptyDeadlines(taskDto);
if (taskDto.getDeadlines().isEmpty()) {
errors.rejectValue("deadlines", "errorCode", "Не может быть пустым");
}
if (errors.hasErrors()) {
return TASK_PAGE;
}
taskService.save(taskDto);
return String.format(REDIRECT_TO, TASKS_PAGE);
}
@PostMapping(value = "/task", params = "addDeadline")
public String addDeadline(@Valid TaskDto taskDto, Errors errors) {
filterEmptyDeadlines(taskDto);
if (errors.hasErrors()) {
return TASK_PAGE;
}
taskDto.getDeadlines().add(new Deadline());
return TASK_PAGE;
}
@ModelAttribute("allStatuses")
public List<Task.TaskStatus> getTaskStatuses() {
return taskService.getTaskStatuses();
}
private void filterEmptyDeadlines(TaskDto taskDto) {
taskDto.setDeadlines(taskDto.getDeadlines().stream()
.filter(dto -> dto.getDate() != null || !isEmpty(dto.getDescription()))
.collect(Collectors.toList()));
}
}

@ -0,0 +1,130 @@
package ru.ulstu.students.model;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import ru.ulstu.core.model.BaseEntity;
import ru.ulstu.deadline.model.Deadline;
import ru.ulstu.tags.model.Tag;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotBlank;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Entity
public class Task extends BaseEntity {
public enum TaskStatus {
IN_WORK("В работе"),
COMPLETED("Завершен"),
FAILED("Провалены сроки"),
LOADED_FROM_KIAS("Загружен автоматически");
private String statusName;
TaskStatus(String name) {
this.statusName = name;
}
public String getStatusName() {
return statusName;
}
}
@NotBlank
private String title;
private String description;
@Enumerated(value = EnumType.STRING)
private ru.ulstu.students.model.Task.TaskStatus status = TaskStatus.IN_WORK;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "task_id", unique = true)
@Fetch(FetchMode.SUBSELECT)
@OrderBy("date")
private List<Deadline> deadlines = new ArrayList<>();
@Column(name = "create_date")
@Temporal(TemporalType.TIMESTAMP)
private Date createDate = new Date();
@Column(name = "update_date")
@Temporal(TemporalType.TIMESTAMP)
private Date updateDate = new Date();
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "task_tags",
joinColumns = {@JoinColumn(name = "task_id")},
inverseJoinColumns = {@JoinColumn(name = "tag_id")})
private List<Tag> tags = new ArrayList<>();
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public TaskStatus getStatus() {
return status;
}
public void setStatus(TaskStatus status) {
this.status = status;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public List<Deadline> getDeadlines() {
return deadlines;
}
public void setDeadlines(List<Deadline> deadlines) {
this.deadlines = deadlines;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
public Date getUpdateDate() {
return updateDate;
}
public void setUpdateDate(Date updateDate) {
this.updateDate = updateDate;
}
public List<Tag> getTags() {
return tags;
}
public void setTags(List<Tag> tags) {
this.tags = tags;
}
}

@ -0,0 +1,144 @@
package ru.ulstu.students.model;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.apache.commons.lang3.StringUtils;
import ru.ulstu.deadline.model.Deadline;
import ru.ulstu.tags.model.Tag;
import javax.validation.constraints.NotEmpty;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class TaskDto {
private final static int MAX_TAGS_LENGTH = 50;
private Integer id;
@NotEmpty
private String title;
private String description;
private Task.TaskStatus status;
private List<Deadline> deadlines = new ArrayList<>();
private Date createDate;
private Date updateDate;
private Set<Integer> tagIds;
private List<Tag> tags;
public TaskDto() {
deadlines.add(new Deadline());
}
@JsonCreator
public TaskDto(@JsonProperty("id") Integer id,
@JsonProperty("title") String title,
@JsonProperty("description") String description,
@JsonProperty("createDate") Date createDate,
@JsonProperty("updateDate") Date updateDate,
@JsonProperty("status") Task.TaskStatus status,
@JsonProperty("deadlines") List<Deadline> deadlines,
@JsonProperty("tagIds") Set<Integer> tagIds,
@JsonProperty("tags") List<Tag> tags) {
this.id = id;
this.title = title;
this.status = status;
this.deadlines = deadlines;
this.createDate = createDate;
this.updateDate = updateDate;
this.description = description;
this.tags = tags;
}
public TaskDto(Task task) {
this.id = task.getId();
this.title = task.getTitle();
this.status = task.getStatus();
this.deadlines = task.getDeadlines();
this.createDate = task.getCreateDate();
this.updateDate = task.getUpdateDate();
this.description = task.getDescription();
this.tags = task.getTags();
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Task.TaskStatus getStatus() {
return status;
}
public void setStatus(Task.TaskStatus status) {
this.status = status;
}
public List<Deadline> getDeadlines() {
return deadlines;
}
public void setDeadlines(List<Deadline> deadlines) {
this.deadlines = deadlines;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
public Date getUpdateDate() {
return updateDate;
}
public void setUpdateDate(Date updateDate) {
this.updateDate = updateDate;
}
public Set<Integer> getTagIds() {
return tagIds;
}
public void setTagIds(Set<Integer> tagIds) {
this.tagIds = tagIds;
}
public List<Tag> getTags() {
return tags;
}
public void setTags(List<Tag> tags) {
this.tags = tags;
}
public String getTagsString() {
return StringUtils.abbreviate(tags
.stream()
.map(tag -> tag.getTagName())
.collect(Collectors.joining(", ")), MAX_TAGS_LENGTH);
}
}

@ -0,0 +1,7 @@
package ru.ulstu.students.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import ru.ulstu.students.model.Task;
public interface TaskRepository extends JpaRepository<Task, Integer> {
}

@ -0,0 +1,95 @@
package ru.ulstu.students.service;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ru.ulstu.deadline.service.DeadlineService;
import ru.ulstu.students.model.Task;
import ru.ulstu.students.model.TaskDto;
import ru.ulstu.students.repository.TaskRepository;
import ru.ulstu.tags.service.TagService;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import static org.springframework.util.ObjectUtils.isEmpty;
import static ru.ulstu.core.util.StreamApiUtils.convert;
import static ru.ulstu.students.model.Task.TaskStatus.IN_WORK;
@Service
public class TaskService {
private final static int MAX_DISPLAY_SIZE = 40;
private final TaskRepository taskRepository;
private final DeadlineService deadlineService;
private final TagService tagService;
public TaskService(TaskRepository grantRepository,
DeadlineService deadlineService, TagService tagService) {
this.taskRepository = grantRepository;
this.deadlineService = deadlineService;
this.tagService = tagService;
}
public List<Task> findAll() {
return taskRepository.findAll();
}
public List<TaskDto> findAllDto() {
List<TaskDto> tasks = convert(findAll(), TaskDto::new);
tasks.forEach(taskDto -> taskDto.setTitle(StringUtils.abbreviate(taskDto.getTitle(), MAX_DISPLAY_SIZE)));
return tasks;
}
public TaskDto findOneDto(Integer id) {
return new TaskDto(taskRepository.getOne(id));
}
@Transactional
public Integer create(TaskDto taskDto) throws IOException {
Task newTask = copyFromDto(new Task(), taskDto);
newTask = taskRepository.save(newTask);
return newTask.getId();
}
private Task copyFromDto(Task task, TaskDto taskDto) throws IOException {
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;
}
@Transactional
public Integer update(TaskDto taskDto) throws IOException {
Task task = taskRepository.getOne(taskDto.getId());
taskRepository.save(copyFromDto(task, taskDto));
return task.getId();
}
@Transactional
public void delete(Integer taskId) throws IOException {
Task task = taskRepository.getOne(taskId);
taskRepository.delete(task);
}
public void save(TaskDto taskDto) throws IOException {
if (isEmpty(taskDto.getId())) {
create(taskDto);
} else {
update(taskDto);
}
}
public List<Task.TaskStatus> getTaskStatuses() {
return Arrays.asList(Task.TaskStatus.values());
}
}

@ -0,0 +1,44 @@
package ru.ulstu.tags.model;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import ru.ulstu.core.model.BaseEntity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;
@Entity
@Table(name = "tag")
public class Tag extends BaseEntity {
@NotEmpty
@Size(max = 50)
@Column(name = "tag_name")
private String tagName;
public Tag() {
}
@JsonCreator
public Tag(@JsonProperty("id") Integer id,
@JsonProperty("tag_name") String tagName) {
this.setId(id);
this.tagName = tagName;
}
public Tag(String name) {
this.tagName = name;
}
public String getTagName() {
return tagName;
}
public void setTagName(String tagName) {
this.tagName = tagName;
}
}

@ -0,0 +1,12 @@
package ru.ulstu.tags.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import ru.ulstu.tags.model.Tag;
public interface TagRepository extends JpaRepository<Tag, Integer> {
@Query("SELECT t FROM Tag t WHERE (t.tagName = :tagName)")
Tag findByName(@Param("tagName") String tagName);
}

@ -0,0 +1,53 @@
package ru.ulstu.tags.service;
import org.springframework.stereotype.Service;
import ru.ulstu.tags.model.Tag;
import ru.ulstu.tags.repository.TagRepository;
import javax.transaction.Transactional;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class TagService {
private final TagRepository tagRepository;
public TagService(TagRepository tagRepository) {
this.tagRepository = tagRepository;
}
public List<Tag> saveOrCreate(List<Tag> tags) {
return tags
.stream()
.map(tag -> {
if (tag.getId() != null) {
return getExistById(tag);
} else {
Tag existTag = isExistByName(tag.getTagName());
return existTag != null ? existTag : create(tag);
}
}).collect(Collectors.toList());
}
@Transactional
public Tag getExistById(Tag tag) {
return tagRepository.getOne(tag.getId());
}
@Transactional
public Tag isExistByName(String tagName) {
return tagRepository.findByName(tagName);
}
@Transactional
public Tag create(Tag tag) {
Tag newTag = new Tag();
newTag.setTagName(tag.getTagName());
newTag = tagRepository.save(newTag);
return newTag;
}
}

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

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

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

@ -2,6 +2,7 @@ package ru.ulstu.timeline.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import ru.ulstu.paper.model.Paper;
import ru.ulstu.timeline.model.Event;
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")
List<Event> findAllFuture();
List<Event> findAllByPaper(Paper paper);
}

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

@ -1,15 +1,22 @@
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.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.EventDto;
import ru.ulstu.timeline.model.Timeline;
import ru.ulstu.timeline.repository.EventRepository;
import ru.ulstu.user.model.UserDto;
import ru.ulstu.user.service.UserService;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import static ru.ulstu.core.util.StreamApiUtils.convert;
@ -17,11 +24,14 @@ import static ru.ulstu.core.util.StreamApiUtils.convert;
public class EventService {
private final EventRepository eventRepository;
private final TimelineService timelineService;
private final UserService userService;
public EventService(EventRepository eventRepository,
@Lazy TimelineService timelineService,
UserService userService) {
this.eventRepository = eventRepository;
this.timelineService = timelineService;
this.userService = userService;
}
@ -52,19 +62,24 @@ public class EventService {
@Transactional
public Integer update(EventDto eventDto) {
Event event = eventRepository.findOne(eventDto.getId());
Event event = eventRepository.getOne(eventDto.getId());
return eventRepository.save(copyFromDto(event, eventDto)).getId();
}
@Transactional
public Event save(Event event) {
return eventRepository.save(event);
}
@Transactional
public void delete(Integer eventId) {
Event event = eventRepository.findOne(eventId);
Event event = eventRepository.getOne(eventId);
event.setParents(null);
eventRepository.delete(event);
}
public List<Event> findByIds(List<Integer> ids) {
return eventRepository.findAll(ids);
return eventRepository.findAllById(ids);
}
public void createBasedOn(Event event, Date executeDate) {
@ -79,11 +94,41 @@ public class EventService {
event = eventRepository.save(event);
//set child to parent
Event parentEvent = eventRepository.findOne(parentEventId);
Event parentEvent = eventRepository.getOne(parentEventId);
parentEvent.setChild(event);
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.deleteAll(eventRepository.findAllByPaper(paper));
createFromPaper(paper);
}
public List<Event> findByCurrentDate() {
return eventRepository.findByCurrentDate();
}

@ -23,15 +23,24 @@ public class TimelineService {
this.eventService = eventService;
}
public List<TimelineDto> findAll() {
public List<TimelineDto> findAllDto() {
return convert(timelineRepository.findAll(), TimelineDto::new);
}
public List<Timeline> findAll() {
return timelineRepository.findAll();
}
@Transactional
public int create(TimelineDto timelineDto) {
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) {
timeline.setEvents(eventService.findByIds(convert(timelineDto.getEvents(), EventDto::getId)));
return timeline;
@ -39,13 +48,13 @@ public class TimelineService {
@Transactional
public Integer update(TimelineDto timelineDto) {
Timeline timeline = timelineRepository.findOne(timelineDto.getId());
Timeline timeline = timelineRepository.getOne(timelineDto.getId());
return timelineRepository.save(copyFromDto(timeline, timelineDto)).getId();
}
@Transactional
public void delete(Integer timelineId) {
Timeline timeline = timelineRepository.findOne(timelineId);
Timeline timeline = timelineRepository.getOne(timelineId);
timelineRepository.delete(timeline);
}
}

@ -1,18 +1,20 @@
package ru.ulstu.user.model;
import org.hibernate.annotations.BatchSize;
import org.hibernate.validator.constraints.Email;
import ru.ulstu.configuration.Constants;
import ru.ulstu.core.model.BaseEntity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
@ -24,6 +26,8 @@ import java.util.Set;
@Entity
@Table(name = "users")
public class User extends BaseEntity {
private final static String USER_ABBREVIATE_TEMPLATE = "%s %s%s";
@NotNull
@Pattern(regexp = Constants.LOGIN_REGEX)
@Size(min = 1, max = 50)
@ -45,6 +49,10 @@ public class User extends BaseEntity {
@Column(name = "last_name", length = 50, nullable = false)
private String lastName;
@Size(max = 50)
@Column(name = "patronymic", length = 50)
private String patronymic;
@NotNull
@Email
@Size(min = 5, max = 100)
@ -79,6 +87,28 @@ public class User extends BaseEntity {
@BatchSize(size = 20)
private Set<UserRole> roles;
@Column(name = "birth_date")
@Temporal(TemporalType.TIMESTAMP)
private Date birthDate;
public enum UserDegree {
CANDIDATE("Кандидат технических наук"),
DOCTOR("Доктор технических наук");
private String degreeName;
UserDegree(String degreeName) {
this.degreeName = degreeName;
}
public String getDegreeName() {
return degreeName;
}
}
@Enumerated(value = EnumType.STRING)
private UserDegree degree;
public User() {
roles = new HashSet<>();
activated = false;
@ -174,4 +204,35 @@ public class User extends BaseEntity {
this.roles.clear();
this.roles.addAll(roles);
}
public String getPatronymic() {
return patronymic;
}
public void setPatronymic(String patronymic) {
this.patronymic = patronymic;
}
public Date getBirthDate() {
return birthDate;
}
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
public UserDegree getDegree() {
return degree;
}
public void setDegree(UserDegree degree) {
this.degree = degree;
}
public String getUserAbbreviate() {
return String.format(USER_ABBREVIATE_TEMPLATE,
lastName == null ? "" : lastName,
firstName == null ? "" : firstName.substring(0, 1) + ".",
patronymic == null ? "" : patronymic.substring(0, 1) + ".");
}
}

@ -1,8 +1,6 @@
package ru.ulstu.user.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotBlank;
import org.springframework.util.StringUtils;
import ru.ulstu.configuration.Constants;
import ru.ulstu.odin.model.OdinDto;
@ -12,9 +10,12 @@ import ru.ulstu.odin.model.annotation.OdinString;
import ru.ulstu.odin.model.annotation.OdinVisible;
import ru.ulstu.user.controller.UserController;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import java.util.Collection;
import java.util.Date;
import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Set;
@ -70,6 +71,10 @@ public class UserDto implements OdinDto {
@Size(min = Constants.MIN_PASSWORD_LENGTH, max = 50)
private String passwordConfirm;
private Date birthDate;
private User.UserDegree degree;
public UserDto() {
activated = false;
roles = new LinkedHashSet<>();
@ -86,6 +91,8 @@ public class UserDto implements OdinDto {
this.roles.addAll(user.getRoles().stream()
.map(UserRoleDto::new)
.collect(Collectors.toList()));
this.birthDate = user.getBirthDate();
this.degree = user.getDegree();
}
public Integer getId() {
@ -163,6 +170,22 @@ public class UserDto implements OdinDto {
return passwordConfirm;
}
public Date getBirthDate() {
return birthDate;
}
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
public User.UserDegree getDegree() {
return degree;
}
public void setDegree(User.UserDegree degree) {
this.degree = degree;
}
@JsonIgnore
public boolean isPasswordsValid() {
if (StringUtils.isEmpty(password) || StringUtils.isEmpty(passwordConfirm)) {
@ -188,6 +211,8 @@ public class UserDto implements OdinDto {
", roles=" + roles +
", password='" + password + '\'' +
", passwordConfirm='" + passwordConfirm + '\'' +
", birthDate='" + birthDate + '\'' +
", degree='" + degree + '\'' +
'}';
}
}

@ -1,8 +1,8 @@
package ru.ulstu.user.model;
import org.hibernate.validator.constraints.NotEmpty;
import ru.ulstu.configuration.Constants;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;
import java.util.Objects;

@ -2,7 +2,13 @@ package ru.ulstu.user.model;
import ru.ulstu.core.model.BaseEntity;
import javax.persistence.*;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotNull;
import java.util.Date;

@ -2,6 +2,8 @@ package ru.ulstu.user.repository;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import ru.ulstu.user.model.User;
import java.util.Date;
@ -25,4 +27,11 @@ public interface UserRepository extends JpaRepository<User, Integer> {
@EntityGraph(attributePaths = "roles")
User findOneWithRolesByLogin(String login);
@Query("SELECT u FROM User u " +
"WHERE (YEAR(CURRENT_DATE) - YEAR(u.birthDate) < 35 OR :hasAge = FALSE) " +
"AND (u.degree = 'CANDIDATE' OR :hasDegree = FALSE)" +
"ORDER BY u.lastName")
List<User> filterByAgeAndDegree(@Param("hasAge") boolean hasAge,
@Param("hasDegree") boolean hasDegree);
}

@ -8,7 +8,7 @@ import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring4.SpringTemplateEngine;
import org.thymeleaf.spring5.SpringTemplateEngine;
import ru.ulstu.configuration.ApplicationProperties;
import ru.ulstu.configuration.Constants;
import ru.ulstu.user.model.User;
@ -19,11 +19,9 @@ import java.util.Map;
@Service
public class MailService {
private final Logger log = LoggerFactory.getLogger(MailService.class);
private static final String USER = "user";
private static final String BASE_URL = "baseUrl";
private final Logger log = LoggerFactory.getLogger(MailService.class);
private final JavaMailSender javaMailSender;
private final SpringTemplateEngine templateEngine;
private final MailProperties mailProperties;

@ -26,7 +26,7 @@ public class UserMapper {
public Set<UserRole> rolesFromDto(Set<UserRoleDto> strings) {
return Optional.ofNullable(strings).orElse(Collections.emptySet()).stream()
.filter(Objects::nonNull)
.map(role -> userRoleRepository.findOne(role.getId().toString()))
.map(role -> userRoleRepository.getOne(role.getId().toString()))
.filter(Objects::nonNull)
.collect(Collectors.toSet());
}

@ -1,318 +1,332 @@
package ru.ulstu.user.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import ru.ulstu.configuration.ApplicationProperties;
import ru.ulstu.core.error.EntityIdIsNullException;
import ru.ulstu.core.jpa.OffsetablePageRequest;
import ru.ulstu.core.model.BaseEntity;
import ru.ulstu.core.model.response.PageableItems;
import ru.ulstu.user.error.UserActivationError;
import ru.ulstu.user.error.UserEmailExistsException;
import ru.ulstu.user.error.UserIdExistsException;
import ru.ulstu.user.error.UserIsUndeadException;
import ru.ulstu.user.error.UserLoginExistsException;
import ru.ulstu.user.error.UserNotActivatedException;
import ru.ulstu.user.error.UserNotFoundException;
import ru.ulstu.user.error.UserPasswordsNotValidOrNotMatchException;
import ru.ulstu.user.error.UserResetKeyError;
import ru.ulstu.user.model.User;
import ru.ulstu.user.model.UserDto;
import ru.ulstu.user.model.UserListDto;
import ru.ulstu.user.model.UserResetPasswordDto;
import ru.ulstu.user.model.UserRole;
import ru.ulstu.user.model.UserRoleConstants;
import ru.ulstu.user.model.UserRoleDto;
import ru.ulstu.user.repository.UserRepository;
import ru.ulstu.user.repository.UserRoleRepository;
import ru.ulstu.user.util.UserUtils;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@Service
@Transactional
public class UserService implements UserDetailsService {
private final Logger log = LoggerFactory.getLogger(UserService.class);
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
private final UserRoleRepository userRoleRepository;
private final UserMapper userMapper;
private final MailService mailService;
private final ApplicationProperties applicationProperties;
public UserService(UserRepository userRepository,
PasswordEncoder passwordEncoder,
UserRoleRepository userRoleRepository,
UserMapper userMapper,
MailService mailService,
ApplicationProperties applicationProperties) {
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
this.userRoleRepository = userRoleRepository;
this.userMapper = userMapper;
this.mailService = mailService;
this.applicationProperties = applicationProperties;
}
private User getUserByEmail(String email) {
return userRepository.findOneByEmailIgnoreCase(email);
}
private User getUserByActivationKey(String activationKey) {
return userRepository.findOneByActivationKey(activationKey);
}
public User getUserByLogin(String login) {
return userRepository.findOneByLoginIgnoreCase(login);
}
@Transactional(readOnly = true)
public UserDto getUserWithRolesById(Integer userId) {
final User userEntity = userRepository.findOneWithRolesById(userId);
if (userEntity == null) {
throw new UserNotFoundException(userId.toString());
}
return userMapper.userEntityToUserDto(userEntity);
}
@Transactional(readOnly = true)
public PageableItems<UserListDto> getAllUsers(int offset, int count) {
final Page<User> page = userRepository.findAll(new OffsetablePageRequest(offset, count, new Sort("id")));
return new PageableItems<>(page.getTotalElements(), userMapper.userEntitiesToUserListDtos(page.getContent()));
}
// TODO: read only active users
public List<User> findAll() {
return userRepository.findAll();
}
@Transactional(readOnly = true)
public PageableItems<UserRoleDto> getUserRoles() {
final List<UserRoleDto> roles = userRoleRepository.findAll().stream()
.map(UserRoleDto::new)
.sorted(Comparator.comparing(UserRoleDto::getViewValue))
.collect(Collectors.toList());
return new PageableItems<>(roles.size(), roles);
}
public UserDto createUser(UserDto userDto) {
if (userDto.getId() != null) {
throw new UserIdExistsException();
}
if (getUserByLogin(userDto.getLogin()) != null) {
throw new UserLoginExistsException(userDto.getLogin());
}
if (getUserByEmail(userDto.getEmail()) != null) {
throw new UserEmailExistsException(userDto.getEmail());
}
if (!userDto.isPasswordsValid()) {
throw new UserPasswordsNotValidOrNotMatchException();
}
User user = userMapper.userDtoToUserEntity(userDto);
user.setActivated(false);
user.setActivationKey(UserUtils.generateActivationKey());
user.setRoles(Collections.singleton(new UserRole(UserRoleConstants.USER)));
user.setPassword(passwordEncoder.encode(userDto.getPassword()));
user = userRepository.save(user);
mailService.sendActivationEmail(user);
log.debug("Created Information for User: {}", user.getLogin());
return userMapper.userEntityToUserDto(user);
}
public UserDto activateUser(String activationKey) {
final User user = getUserByActivationKey(activationKey);
if (user == null) {
throw new UserActivationError(activationKey);
}
user.setActivated(true);
user.setActivationKey(null);
user.setActivationDate(null);
log.debug("Activated user: {}", user.getLogin());
return userMapper.userEntityToUserDto(userRepository.save(user));
}
public UserDto updateUser(UserDto userDto) {
if (userDto.getId() == null) {
throw new EntityIdIsNullException();
}
if (!Objects.equals(
Optional.ofNullable(getUserByEmail(userDto.getEmail()))
.map(BaseEntity::getId).orElse(userDto.getId()),
userDto.getId())) {
throw new UserEmailExistsException(userDto.getEmail());
}
if (!Objects.equals(
Optional.ofNullable(getUserByLogin(userDto.getLogin()))
.map(BaseEntity::getId).orElse(userDto.getId()),
userDto.getId())) {
throw new UserLoginExistsException(userDto.getLogin());
}
User user = userRepository.findOne(userDto.getId());
if (user == null) {
throw new UserNotFoundException(userDto.getId().toString());
}
if (applicationProperties.getUndeadUserLogin().equalsIgnoreCase(user.getLogin())) {
userDto.setLogin(applicationProperties.getUndeadUserLogin());
userDto.setActivated(true);
userDto.setRoles(Collections.singletonList(new UserRoleDto(UserRoleConstants.ADMIN)));
}
user.setLogin(userDto.getLogin());
user.setFirstName(userDto.getFirstName());
user.setLastName(userDto.getLastName());
user.setEmail(userDto.getEmail());
if (userDto.isActivated() != user.getActivated()) {
if (userDto.isActivated()) {
user.setActivationKey(null);
user.setActivationDate(null);
} else {
user.setActivationKey(UserUtils.generateActivationKey());
user.setActivationDate(new Date());
}
}
user.setActivated(userDto.isActivated());
final Set<UserRole> roles = userMapper.rolesFromDto(userDto.getRoles());
user.setRoles(roles.isEmpty()
? Collections.singleton(new UserRole(UserRoleConstants.USER))
: roles);
if (!StringUtils.isEmpty(userDto.getOldPassword())) {
if (!userDto.isPasswordsValid() || !userDto.isOldPasswordValid()) {
throw new UserPasswordsNotValidOrNotMatchException();
}
if (!passwordEncoder.matches(userDto.getOldPassword(), user.getPassword())) {
throw new UserPasswordsNotValidOrNotMatchException();
}
user.setPassword(passwordEncoder.encode(userDto.getPassword()));
log.debug("Changed password for User: {}", user.getLogin());
}
user = userRepository.save(user);
log.debug("Changed Information for User: {}", user.getLogin());
return userMapper.userEntityToUserDto(user);
}
public UserDto updateUserInformation(UserDto userDto) {
if (userDto.getId() == null) {
throw new EntityIdIsNullException();
}
if (!Objects.equals(
Optional.ofNullable(getUserByEmail(userDto.getEmail()))
.map(BaseEntity::getId).orElse(userDto.getId()),
userDto.getId())) {
throw new UserEmailExistsException(userDto.getEmail());
}
User user = userRepository.findOne(userDto.getId());
if (user == null) {
throw new UserNotFoundException(userDto.getId().toString());
}
user.setFirstName(userDto.getFirstName());
user.setLastName(userDto.getLastName());
user.setEmail(userDto.getEmail());
user = userRepository.save(user);
log.debug("Updated Information for User: {}", user.getLogin());
return userMapper.userEntityToUserDto(user);
}
public UserDto changeUserPassword(UserDto userDto) {
if (userDto.getId() == null) {
throw new EntityIdIsNullException();
}
if (!userDto.isPasswordsValid() || !userDto.isOldPasswordValid()) {
throw new UserPasswordsNotValidOrNotMatchException();
}
final String login = UserUtils.getCurrentUserLogin();
final User user = userRepository.findOneByLoginIgnoreCase(login);
if (user == null) {
throw new UserNotFoundException(login);
}
if (!passwordEncoder.matches(userDto.getOldPassword(), user.getPassword())) {
throw new UserPasswordsNotValidOrNotMatchException();
}
user.setPassword(passwordEncoder.encode(userDto.getPassword()));
log.debug("Changed password for User: {}", user.getLogin());
return userMapper.userEntityToUserDto(userRepository.save(user));
}
public boolean requestUserPasswordReset(String email) {
User user = userRepository.findOneByEmailIgnoreCase(email);
if (user == null) {
throw new UserNotFoundException(email);
}
if (!user.getActivated()) {
throw new UserNotActivatedException();
}
user.setResetKey(UserUtils.generateResetKey());
user.setResetDate(new Date());
user = userRepository.save(user);
mailService.sendPasswordResetMail(user);
log.debug("Created Reset Password Request for User: {}", user.getLogin());
return true;
}
public boolean completeUserPasswordReset(String key, UserResetPasswordDto userResetPasswordDto) {
if (!userResetPasswordDto.isPasswordsValid()) {
throw new UserPasswordsNotValidOrNotMatchException();
}
User user = userRepository.findOneByResetKey(key);
if (user == null) {
throw new UserResetKeyError(key);
}
user.setPassword(passwordEncoder.encode(userResetPasswordDto.getPassword()));
user.setResetKey(null);
user.setResetDate(null);
user = userRepository.save(user);
log.debug("Reset Password for User: {}", user.getLogin());
return true;
}
public UserDto deleteUser(Integer userId) {
final User user = userRepository.findOne(userId);
if (user == null) {
throw new UserNotFoundException(userId.toString());
}
if (applicationProperties.getUndeadUserLogin().equalsIgnoreCase(user.getLogin())) {
throw new UserIsUndeadException(user.getLogin());
}
userRepository.delete(user);
log.debug("Deleted User: {}", user.getLogin());
return userMapper.userEntityToUserDto(user);
}
@Override
public UserDetails loadUserByUsername(String username) {
final User user = userRepository.findOneByLoginIgnoreCase(username);
if (user == null) {
throw new UserNotFoundException(username);
}
if (!user.getActivated()) {
throw new UserNotActivatedException();
}
return new org.springframework.security.core.userdetails.User(user.getLogin(),
user.getPassword(),
Optional.ofNullable(user.getRoles()).orElse(Collections.emptySet()).stream()
.map(role -> new SimpleGrantedAuthority(role.getName()))
.collect(Collectors.toList()));
}
public List<User> findByIds(List<Integer> ids) {
return userRepository.findAll(ids);
}
public User findById(Integer id) {
return userRepository.findOne(id);
}
}
package ru.ulstu.user.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import ru.ulstu.configuration.ApplicationProperties;
import ru.ulstu.core.error.EntityIdIsNullException;
import ru.ulstu.core.jpa.OffsetablePageRequest;
import ru.ulstu.core.model.BaseEntity;
import ru.ulstu.core.model.response.PageableItems;
import ru.ulstu.user.error.UserActivationError;
import ru.ulstu.user.error.UserEmailExistsException;
import ru.ulstu.user.error.UserIdExistsException;
import ru.ulstu.user.error.UserIsUndeadException;
import ru.ulstu.user.error.UserLoginExistsException;
import ru.ulstu.user.error.UserNotActivatedException;
import ru.ulstu.user.error.UserNotFoundException;
import ru.ulstu.user.error.UserPasswordsNotValidOrNotMatchException;
import ru.ulstu.user.error.UserResetKeyError;
import ru.ulstu.user.model.User;
import ru.ulstu.user.model.UserDto;
import ru.ulstu.user.model.UserListDto;
import ru.ulstu.user.model.UserResetPasswordDto;
import ru.ulstu.user.model.UserRole;
import ru.ulstu.user.model.UserRoleConstants;
import ru.ulstu.user.model.UserRoleDto;
import ru.ulstu.user.repository.UserRepository;
import ru.ulstu.user.repository.UserRoleRepository;
import ru.ulstu.user.util.UserUtils;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@Service
@Transactional
public class UserService implements UserDetailsService {
private final Logger log = LoggerFactory.getLogger(UserService.class);
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
private final UserRoleRepository userRoleRepository;
private final UserMapper userMapper;
private final MailService mailService;
private final ApplicationProperties applicationProperties;
public UserService(UserRepository userRepository,
PasswordEncoder passwordEncoder,
UserRoleRepository userRoleRepository,
UserMapper userMapper,
MailService mailService,
ApplicationProperties applicationProperties) {
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
this.userRoleRepository = userRoleRepository;
this.userMapper = userMapper;
this.mailService = mailService;
this.applicationProperties = applicationProperties;
}
private User getUserByEmail(String email) {
return userRepository.findOneByEmailIgnoreCase(email);
}
private User getUserByActivationKey(String activationKey) {
return userRepository.findOneByActivationKey(activationKey);
}
public User getUserByLogin(String login) {
return userRepository.findOneByLoginIgnoreCase(login);
}
@Transactional(readOnly = true)
public UserDto getUserWithRolesById(Integer userId) {
final User userEntity = userRepository.findOneWithRolesById(userId);
if (userEntity == null) {
throw new UserNotFoundException(userId.toString());
}
return userMapper.userEntityToUserDto(userEntity);
}
@Transactional(readOnly = true)
public PageableItems<UserListDto> getAllUsers(int offset, int count) {
final Page<User> page = userRepository.findAll(new OffsetablePageRequest(offset, count, Sort.by("id")));
return new PageableItems<>(page.getTotalElements(), userMapper.userEntitiesToUserListDtos(page.getContent()));
}
// TODO: read only active users
public List<User> findAll() {
return userRepository.findAll();
}
@Transactional(readOnly = true)
public PageableItems<UserRoleDto> getUserRoles() {
final List<UserRoleDto> roles = userRoleRepository.findAll().stream()
.map(UserRoleDto::new)
.sorted(Comparator.comparing(UserRoleDto::getViewValue))
.collect(Collectors.toList());
return new PageableItems<>(roles.size(), roles);
}
public UserDto createUser(UserDto userDto) {
if (userDto.getId() != null) {
throw new UserIdExistsException();
}
if (getUserByLogin(userDto.getLogin()) != null) {
throw new UserLoginExistsException(userDto.getLogin());
}
if (getUserByEmail(userDto.getEmail()) != null) {
throw new UserEmailExistsException(userDto.getEmail());
}
if (!userDto.isPasswordsValid()) {
throw new UserPasswordsNotValidOrNotMatchException();
}
User user = userMapper.userDtoToUserEntity(userDto);
user.setActivated(false);
user.setActivationKey(UserUtils.generateActivationKey());
user.setRoles(Collections.singleton(new UserRole(UserRoleConstants.USER)));
user.setPassword(passwordEncoder.encode(userDto.getPassword()));
user = userRepository.save(user);
mailService.sendActivationEmail(user);
log.debug("Created Information for User: {}", user.getLogin());
return userMapper.userEntityToUserDto(user);
}
public UserDto activateUser(String activationKey) {
final User user = getUserByActivationKey(activationKey);
if (user == null) {
throw new UserActivationError(activationKey);
}
user.setActivated(true);
user.setActivationKey(null);
user.setActivationDate(null);
log.debug("Activated user: {}", user.getLogin());
return userMapper.userEntityToUserDto(userRepository.save(user));
}
public UserDto updateUser(UserDto userDto) {
if (userDto.getId() == null) {
throw new EntityIdIsNullException();
}
if (!Objects.equals(
Optional.ofNullable(getUserByEmail(userDto.getEmail()))
.map(BaseEntity::getId).orElse(userDto.getId()),
userDto.getId())) {
throw new UserEmailExistsException(userDto.getEmail());
}
if (!Objects.equals(
Optional.ofNullable(getUserByLogin(userDto.getLogin()))
.map(BaseEntity::getId).orElse(userDto.getId()),
userDto.getId())) {
throw new UserLoginExistsException(userDto.getLogin());
}
User user = userRepository.getOne(userDto.getId());
if (user == null) {
throw new UserNotFoundException(userDto.getId().toString());
}
if (applicationProperties.getUndeadUserLogin().equalsIgnoreCase(user.getLogin())) {
userDto.setLogin(applicationProperties.getUndeadUserLogin());
userDto.setActivated(true);
userDto.setRoles(Collections.singletonList(new UserRoleDto(UserRoleConstants.ADMIN)));
}
user.setLogin(userDto.getLogin());
user.setFirstName(userDto.getFirstName());
user.setLastName(userDto.getLastName());
user.setEmail(userDto.getEmail());
if (userDto.isActivated() != user.getActivated()) {
if (userDto.isActivated()) {
user.setActivationKey(null);
user.setActivationDate(null);
} else {
user.setActivationKey(UserUtils.generateActivationKey());
user.setActivationDate(new Date());
}
}
user.setActivated(userDto.isActivated());
final Set<UserRole> roles = userMapper.rolesFromDto(userDto.getRoles());
user.setRoles(roles.isEmpty()
? Collections.singleton(new UserRole(UserRoleConstants.USER))
: roles);
if (!StringUtils.isEmpty(userDto.getOldPassword())) {
if (!userDto.isPasswordsValid() || !userDto.isOldPasswordValid()) {
throw new UserPasswordsNotValidOrNotMatchException();
}
if (!passwordEncoder.matches(userDto.getOldPassword(), user.getPassword())) {
throw new UserPasswordsNotValidOrNotMatchException();
}
user.setPassword(passwordEncoder.encode(userDto.getPassword()));
log.debug("Changed password for User: {}", user.getLogin());
}
user = userRepository.save(user);
log.debug("Changed Information for User: {}", user.getLogin());
return userMapper.userEntityToUserDto(user);
}
public UserDto updateUserInformation(UserDto userDto) {
if (userDto.getId() == null) {
throw new EntityIdIsNullException();
}
if (!Objects.equals(
Optional.ofNullable(getUserByEmail(userDto.getEmail()))
.map(BaseEntity::getId).orElse(userDto.getId()),
userDto.getId())) {
throw new UserEmailExistsException(userDto.getEmail());
}
User user = userRepository.getOne(userDto.getId());
if (user == null) {
throw new UserNotFoundException(userDto.getId().toString());
}
user.setFirstName(userDto.getFirstName());
user.setLastName(userDto.getLastName());
user.setEmail(userDto.getEmail());
user = userRepository.save(user);
log.debug("Updated Information for User: {}", user.getLogin());
return userMapper.userEntityToUserDto(user);
}
public UserDto changeUserPassword(UserDto userDto) {
if (userDto.getId() == null) {
throw new EntityIdIsNullException();
}
if (!userDto.isPasswordsValid() || !userDto.isOldPasswordValid()) {
throw new UserPasswordsNotValidOrNotMatchException();
}
final String login = UserUtils.getCurrentUserLogin(SecurityContextHolder.getContext());
final User user = userRepository.findOneByLoginIgnoreCase(login);
if (user == null) {
throw new UserNotFoundException(login);
}
if (!passwordEncoder.matches(userDto.getOldPassword(), user.getPassword())) {
throw new UserPasswordsNotValidOrNotMatchException();
}
user.setPassword(passwordEncoder.encode(userDto.getPassword()));
log.debug("Changed password for User: {}", user.getLogin());
return userMapper.userEntityToUserDto(userRepository.save(user));
}
public boolean requestUserPasswordReset(String email) {
User user = userRepository.findOneByEmailIgnoreCase(email);
if (user == null) {
throw new UserNotFoundException(email);
}
if (!user.getActivated()) {
throw new UserNotActivatedException();
}
user.setResetKey(UserUtils.generateResetKey());
user.setResetDate(new Date());
user = userRepository.save(user);
mailService.sendPasswordResetMail(user);
log.debug("Created Reset Password Request for User: {}", user.getLogin());
return true;
}
public boolean completeUserPasswordReset(String key, UserResetPasswordDto userResetPasswordDto) {
if (!userResetPasswordDto.isPasswordsValid()) {
throw new UserPasswordsNotValidOrNotMatchException();
}
User user = userRepository.findOneByResetKey(key);
if (user == null) {
throw new UserResetKeyError(key);
}
user.setPassword(passwordEncoder.encode(userResetPasswordDto.getPassword()));
user.setResetKey(null);
user.setResetDate(null);
user = userRepository.save(user);
log.debug("Reset Password for User: {}", user.getLogin());
return true;
}
public UserDto deleteUser(Integer userId) {
final User user = userRepository.getOne(userId);
if (user == null) {
throw new UserNotFoundException(userId.toString());
}
if (applicationProperties.getUndeadUserLogin().equalsIgnoreCase(user.getLogin())) {
throw new UserIsUndeadException(user.getLogin());
}
userRepository.delete(user);
log.debug("Deleted User: {}", user.getLogin());
return userMapper.userEntityToUserDto(user);
}
@Override
public UserDetails loadUserByUsername(String username) {
final User user = userRepository.findOneByLoginIgnoreCase(username);
if (user == null) {
throw new UserNotFoundException(username);
}
if (!user.getActivated()) {
throw new UserNotActivatedException();
}
return new org.springframework.security.core.userdetails.User(user.getLogin(),
user.getPassword(),
Optional.ofNullable(user.getRoles()).orElse(Collections.emptySet()).stream()
.map(role -> new SimpleGrantedAuthority(role.getName()))
.collect(Collectors.toList()));
}
public List<User> findByIds(List<Integer> ids) {
return userRepository.findAllById(ids);
}
public User findById(Integer id) {
return userRepository.getOne(id);
}
public User getCurrentUser() {
String login = UserUtils.getCurrentUserLogin(SecurityContextHolder.getContext());
User user = userRepository.findOneByLoginIgnoreCase(login);
if (user == null) {
throw new UserNotFoundException(login);
}
return user;
}
public List<User> filterByAgeAndDegree(boolean hasDegree, boolean hasAge) {
return userRepository.filterByAgeAndDegree(hasDegree, hasAge);
}
}

@ -17,12 +17,12 @@ public class UserUtils {
return RandomStringUtils.randomNumeric(DEF_COUNT);
}
public static String getCurrentUserLogin() {
final SecurityContext securityContext = SecurityContextHolder.getContext();
public static String getCurrentUserLogin(SecurityContext securityContext) {
if (securityContext == null) {
return null;
}
final Authentication authentication = securityContext.getAuthentication();
if (authentication.getPrincipal() instanceof UserDetails) {
final UserDetails springSecurityUser = (UserDetails) authentication.getPrincipal();
return springSecurityUser.getUsername();

@ -2,12 +2,11 @@
spring.main.banner-mode=off
server.port=8443
server.http.port=8080
spring.http.multipart.maxFileSize=20MB
spring.http.multipart.maxRequestSize=20MB
multipart.maxFileSize=20MB
multipart.maxRequestSize=20MB
# Thymeleaf Settings
spring.thymeleaf.cache=false
# SSL Settings
security.require-ssl=true
server.ssl.key-store=classpath:sample.jks
server.ssl.key-store-password=secret
server.ssl.key-password=password
@ -25,14 +24,15 @@ spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFact
spring.datasource.url=jdbc:postgresql://localhost:5432/ng-tracker
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.datasource.driverclassName=org.postgresql.Driver
spring.jpa.hibernate.ddl-auto=validate
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults = false
# Liquibase Settings
liquibase.drop-first=false
liquibase.enabled=true
liquibase.change-log=classpath:db/changelog-master.xml
spring.liquibase.change-log=classpath:db/changelog-master.xml
spring.liquibase.drop-first=false
spring.liquibase.enabled=true
# Application Settings
ng-tracker.base-url=http://127.0.0.1:8080
ng-tracker.undead-user-login=admin
ng-tracker.dev-mode=true
ng-tracker.use-https=false
ng-tracker.use-https=false
ng-tracker.check-run=false

@ -1,489 +1,298 @@
Anton Romanov;Thu Mar 15 11:10:34 2018 +0400;change to date time
romanov73;Thu Mar 15 11:03:19 2018 +0400;read commits in constructor
romanov73;Thu Mar 15 09:12:07 2018 +0400;add commits page
Romanov Anton;Wed Mar 14 20:26:54 2018 +0000;Update README.md
Romanov Anton;Wed Mar 14 20:16:53 2018 +0000;Update README.md
Romanov Anton;Wed Mar 14 20:08:09 2018 +0000;Update README.md
Romanov Anton;Wed Mar 14 20:00:58 2018 +0000;Update README.md
Romanov Anton;Wed Mar 14 19:50:22 2018 +0000;Update README.md
Romanov Anton;Wed Mar 14 19:34:17 2018 +0000;Update README.md
Romanov Anton;Wed Mar 14 19:20:42 2018 +0000;Update README.md
Romanov Anton;Wed Mar 14 18:59:18 2018 +0000;Update README.md
Romanov Anton;Wed Mar 14 18:47:17 2018 +0000;Update README.md
Romanov Anton;Wed Mar 14 18:35:37 2018 +0000;Update README.md
Romanov Anton;Wed Mar 14 18:33:54 2018 +0000;Update README.md
Romanov Anton;Wed Mar 14 18:29:27 2018 +0000;Update README.md
Romanov Anton;Wed Mar 14 18:21:18 2018 +0000;Update README.md
Romanov Anton;Wed Mar 14 18:19:27 2018 +0000;Update README.md
Romanov Anton;Wed Mar 14 18:16:06 2018 +0000;Update README.md
romanov73;Wed Mar 14 21:28:10 2018 +0400;fix using constant
Aleksey Filippov;Wed Mar 14 20:07:25 2018 +0400;some fixes after merge
Aleksey Filippov;Wed Mar 14 19:52:45 2018 +0400;Merge remote-tracking branch 'origin/36-rest' into odin-ui
Aleksey Filippov;Wed Mar 14 19:48:45 2018 +0400;refactoring of odin paginator
romanov73;Wed Mar 14 18:43:16 2018 +0400;Merge branch 'develop' into 36-rest
romanov73;Wed Mar 14 18:17:02 2018 +0400;Merge branch 'develop' into 36-rest
Aleksey Filippov;Wed Mar 14 18:11:00 2018 +0400;fix null value check in formatter
Aleksey Filippov;Wed Mar 14 18:06:16 2018 +0400;fix odin paginator style, fix odin negative file
romanov73;Wed Mar 14 18:04:47 2018 +0400;rename entities
Aleksey Filippov;Wed Mar 14 17:58:59 2018 +0400;improve odin table look
romanov73;Wed Mar 14 17:47:45 2018 +0400;fix db changelogs
romanov73;Wed Mar 14 17:47:20 2018 +0400;fix db changelogs
Gleb;Wed Mar 14 08:50:23 2018 +0000;Merge branch '48-' into 'develop'
funny73;Wed Mar 14 12:28:55 2018 +0400;Поправил отображение подразделения при редактировании смены
Aleksey Filippov;Wed Mar 14 00:02:24 2018 +0400;move navbar to the left, move odin css to separate file
Aleksey Filippov;Tue Mar 13 23:26:33 2018 +0400;some style fixes
Aleksey Filippov;Tue Mar 13 23:22:37 2018 +0400;move version panel to navbar
funny73;Tue Mar 13 20:41:41 2018 +0400;Поправил валидацию сменности
romanov73;Tue Mar 13 17:26:54 2018 +0400;fix offsetable page request
romanov73;Tue Mar 13 17:26:02 2018 +0400;fix table constructor
romanov73;Tue Mar 13 17:24:56 2018 +0400;fix checking empty value
Romanov Anton;Tue Mar 13 13:09:41 2018 +0000;Merge branch 'odin-ui' into '36-rest'
Aleksey Filippov;Tue Mar 13 16:59:27 2018 +0400;notes updated
Aleksey Filippov;Tue Mar 13 16:56:00 2018 +0400;odin refactoring
Aleksey Filippov;Tue Mar 13 16:53:38 2018 +0400;odin refactoring
romanov73;Tue Mar 13 15:27:17 2018 +0400;fix tool load calc
romanov73;Tue Mar 13 14:46:46 2018 +0400;fix area load calc
Aleksey Filippov;Tue Mar 13 13:38:23 2018 +0400;some fixes
romanov73;Tue Mar 13 13:33:25 2018 +0400;Merge remote-tracking branch 'origin/develop' into develop
romanov73;Tue Mar 13 13:33:07 2018 +0400;fix tools count calc
Aleksey Filippov;Tue Mar 13 13:12:09 2018 +0400;some odin refactoring
Aleksey Filippov;Tue Mar 13 13:11:41 2018 +0400;some offsetablepagerequest fix
Aleksey Filippov;Tue Mar 13 13:06:48 2018 +0400;add offsetablepagerequest
Aleksey Filippov;Tue Mar 13 07:27:12 2018 +0000;Merge branch '51-rest-points' into '36-rest'
romanov73;Tue Mar 13 11:22:02 2018 +0400;fix by comment: remove default version id
romanov73;Tue Mar 13 00:04:50 2018 +0400;fix path
romanov73;Mon Mar 12 23:55:05 2018 +0400;add tool square dictionary
romanov73;Mon Mar 12 23:36:49 2018 +0400;add dictionary pages
romanov73;Mon Mar 12 23:18:01 2018 +0400;sort second level menu items by name
romanov73;Mon Mar 12 23:11:22 2018 +0400;fix menu
romanov73;Mon Mar 12 22:52:15 2018 +0400;add stream api utils and converter for "map ... collect"
funny73;Mon Mar 12 20:01:47 2018 +0400;Добавил свойство базового изделия для изделия
romanov73;Mon Mar 12 19:46:52 2018 +0400;refactor units
romanov73;Mon Mar 12 19:36:57 2018 +0400;refactor tool types and work types
romanov73;Mon Mar 12 19:20:23 2018 +0400;refactor tools
romanov73;Mon Mar 12 19:07:09 2018 +0400;refactor stages
romanov73;Mon Mar 12 18:53:26 2018 +0400;refactor positions
romanov73;Mon Mar 12 18:27:36 2018 +0400;refactor employees
romanov73;Mon Mar 12 18:26:49 2018 +0400;refactor employees
romanov73;Mon Mar 12 18:09:38 2018 +0400;refactor categories
Aleksey Filippov;Mon Mar 12 17:32:06 2018 +0400;todo added
Aleksey Filippov;Mon Mar 12 17:29:51 2018 +0400;paginator added to odin
Aleksey Filippov;Mon Mar 12 17:29:06 2018 +0400;notes updated
funny73;Mon Mar 12 16:29:13 2018 +0400;Добавил сущность изделие без привязки к производственной программе
funny73;Mon Mar 12 15:16:35 2018 +0400;Переименовал сущность Product на ProductOnProgram Ещё немного переименования
funny73;Mon Mar 12 14:39:52 2018 +0400;Переименовал сущность Product на ProductOnProgram
Aleksey Filippov;Mon Mar 12 13:44:42 2018 +0400;add formatters and initial form support to odin
Aleksey Filippov;Mon Mar 12 13:44:16 2018 +0400;userlistdto refactoring
Aleksey Filippov;Mon Mar 12 13:43:59 2018 +0400;dateutils improvements
Aleksey Filippov;Mon Mar 12 13:43:43 2018 +0400;add support of localdatetime type to odin
Aleksey Filippov;Mon Mar 12 13:42:54 2018 +0400;odin backend example added
Aleksey Filippov;Mon Mar 12 13:42:12 2018 +0400;notes updated
funny73;Mon Mar 12 12:16:02 2018 +0400;Поправил всплывающие сообщения при работе с "Категориями"
Aleksey Filippov;Mon Mar 12 11:25:51 2018 +0400;some refactoring
Aleksey Filippov;Mon Mar 12 11:25:30 2018 +0400;odinid annotation added
Aleksey Filippov;Sun Mar 11 15:23:49 2018 +0400;notes updated
Aleksey Filippov;Sun Mar 11 15:18:45 2018 +0400;some fixes
Aleksey Filippov;Sun Mar 11 15:09:57 2018 +0400;simple table draw support added, some refactoring
Aleksey Filippov;Sun Mar 11 15:08:22 2018 +0400;add user id field to userlistdto
Aleksey Filippov;Sun Mar 11 14:32:50 2018 +0400;add jsonproperty annotation support
Aleksey Filippov;Sun Mar 11 13:38:45 2018 +0400;some template fixes
Aleksey Filippov;Sun Mar 11 13:33:09 2018 +0400;some balance page fixes
Aleksey Filippov;Sun Mar 11 13:25:58 2018 +0400;add jsonignore annotation support
Aleksey Filippov;Thu Mar 8 14:16:20 2018 +0400;some odin improvements
Aleksey Filippov;Wed Mar 7 16:03:04 2018 +0400;Merge remote-tracking branch 'origin/36-rest' into 36-rest
Aleksey Filippov;Wed Mar 7 16:01:21 2018 +0400;odin submodule for basic types added, some refactoring
romanov73;Tue Mar 6 22:52:02 2018 +0400;remove old packages
romanov73;Tue Mar 6 19:12:27 2018 +0400;add tool type crud
romanov73;Tue Mar 6 13:09:51 2018 +0400;add version crud
romanov73;Tue Mar 6 10:48:36 2018 +0400;add unit crud
romanov73;Mon Mar 5 16:58:37 2018 +0400;fix tree
romanov73;Mon Mar 5 16:38:37 2018 +0400;Merge remote-tracking branch 'origin/36-rest' into 36-rest
romanov73;Mon Mar 5 16:38:21 2018 +0400;employee crud
Aleksey Filippov;Mon Mar 5 15:43:49 2018 +0400;some fixes
Aleksey Filippov;Mon Mar 5 15:39:53 2018 +0400;Merge remote-tracking branch 'origin/36-rest' into 36-rest
Aleksey Filippov;Mon Mar 5 15:39:33 2018 +0400;user reset password function added, some refactoring
romanov73;Mon Mar 5 15:29:16 2018 +0400;fix delete category
Aleksey Filippov;Mon Mar 5 15:08:27 2018 +0400;user change password function added, some refactoring
romanov73;Mon Mar 5 15:08:17 2018 +0400;add category crud
romanov73;Mon Mar 5 14:07:10 2018 +0400;add tree component
Aleksey Filippov;Mon Mar 5 11:30:22 2018 +0400;user delete function added, some refactoring
Aleksey Filippov;Mon Mar 5 11:18:23 2018 +0400;user update function added
Aleksey Filippov;Mon Mar 5 11:18:06 2018 +0400;some refactoring
Aleksey Filippov;Mon Mar 5 10:06:04 2018 +0400;add user activation function
Aleksey Filippov;Mon Mar 5 09:48:22 2018 +0400;add scheduler for users
Aleksey Filippov;Mon Mar 5 09:48:07 2018 +0400;add activateddate field to userentity
Aleksey Filippov;Mon Mar 5 09:47:25 2018 +0400;notes file updated
Aleksey Filippov;Mon Mar 5 09:47:11 2018 +0400;some refactoring
Aleksey Filippov;Mon Mar 5 09:21:49 2018 +0400;thymeleaf cache settings added
Aleksey Filippov;Mon Mar 5 09:21:11 2018 +0400;notes file added
Aleksey Filippov;Mon Mar 5 09:20:57 2018 +0400;some refactoring
Aleksey Filippov;Mon Mar 5 08:37:01 2018 +0400;some refactoring
romanov73;Mon Mar 5 00:08:02 2018 +0400;add callbacks on version getters
romanov73;Mon Mar 5 00:07:34 2018 +0400;fix npe
romanov73;Sun Mar 4 01:13:57 2018 +0400;fix column style
romanov73;Sun Mar 4 01:06:38 2018 +0400;fix table style
romanov73;Sun Mar 4 00:27:14 2018 +0400;add balance dto + draw employee balance
romanov73;Sat Mar 3 22:43:06 2018 +0400;add balance services
romanov73;Sat Mar 3 16:31:19 2018 +0400;Merge remote-tracking branch 'origin/36-rest' into 36-rest
romanov73;Sat Mar 3 16:31:04 2018 +0400;add employee balance table
Aleksey Filippov;Sat Mar 3 15:54:23 2018 +0400;some user support improvements
Aleksey Filippov;Sat Mar 3 15:53:20 2018 +0400;edit migration files, need manual fix of databasechangelog table
Aleksey Filippov;Sat Mar 3 15:51:58 2018 +0400;add application properties handler
Aleksey Filippov;Sat Mar 3 15:51:19 2018 +0400;disable tests
Aleksey Filippov;Sat Mar 3 13:49:32 2018 +0400;some refactoring
romanov73;Fri Mar 2 18:10:23 2018 +0400;add balance page
Aleksey Filippov;Fri Mar 2 18:04:39 2018 +0400;some refactoring
Aleksey Filippov;Fri Mar 2 17:51:41 2018 +0400;Merge remote-tracking branch 'origin/36-rest' into 36-rest
Aleksey Filippov;Fri Mar 2 17:50:59 2018 +0400;advicecontroller improvements
Aleksey Filippov;Fri Mar 2 17:50:39 2018 +0400;some mvc improvements
romanov73;Fri Mar 2 15:15:46 2018 +0400;add dtos
romanov73;Fri Mar 2 15:02:38 2018 +0400;Merge remote-tracking branch 'origin/36-rest' into 36-rest
Aleksey Filippov;Fri Mar 2 14:54:33 2018 +0400;Merge remote-tracking branch 'origin/36-rest' into 36-rest
Aleksey Filippov;Fri Mar 2 14:53:39 2018 +0400;add migrations
Aleksey Filippov;Fri Mar 2 14:53:30 2018 +0400;some core improvements
Aleksey Filippov;Fri Mar 2 14:53:13 2018 +0400;some users improvements
romanov73;Fri Mar 2 12:42:54 2018 +0400;add category service
romanov73;Fri Mar 2 12:37:51 2018 +0400;fix unit service
romanov73;Fri Mar 2 11:24:11 2018 +0400;add unit controller
romanov73;Thu Mar 1 23:19:42 2018 +0400;fix versions panel
romanov73;Thu Mar 1 22:50:57 2018 +0400;Merge branch 'develop' into 36-rest
romanov73;Thu Mar 1 22:50:37 2018 +0400;Merge branch 'develop' into 36-rest
Romanov Anton;Thu Mar 1 18:31:03 2018 +0000;Merge branch '29-' into 'develop'
romanov73;Thu Mar 1 22:25:49 2018 +0400;change versions
romanov73;Thu Mar 1 20:14:22 2018 +0400;show version select
romanov73;Thu Mar 1 19:56:24 2018 +0400;add old models, add versions controller
romanov73;Thu Mar 1 19:55:59 2018 +0400;add old models, add versions controller
romanov73;Thu Mar 1 19:04:47 2018 +0400;save menu to session
romanov73;Thu Mar 1 18:50:00 2018 +0400;add favicon
funny73;Thu Mar 1 18:01:43 2018 +0400;1) Поправил имена колонок и таблицы для смен под постгрес 2) Исправил ошибку в имени переменной thidShift ->thirdShift
romanov73;Thu Mar 1 16:03:03 2018 +0400;add menu and restore changelogs
funny73;Thu Mar 1 15:33:36 2018 +0400;Добавил распорядок смен для каждого подразделения. Смена назначается на месяц. Есть возможность сохранить любой вариант комбинирования 1,2 и 3 смены. Например (1,3); (2); ()... Добавлен интерфейс для просмотра и редактирования распорядка смен по каждому подразделению. Добавлена валидация - для каждого месяца может быть только один распорядок смен.
Aleksey Filippov;Thu Mar 1 15:23:06 2018 +0400;migrate to webjars
Aleksey Filippov;Thu Mar 1 13:31:16 2018 +0400;Merge remote-tracking branch 'origin/36-rest' into 36-rest
Aleksey Filippov;Thu Mar 1 13:30:55 2018 +0400;create migrations for user models
Aleksey Filippov;Thu Mar 1 13:30:09 2018 +0400;old code refactoring
romanov73;Thu Mar 1 12:51:14 2018 +0400;add basic menu from rest
romanov73;Thu Mar 1 11:51:17 2018 +0400;Merge remote-tracking branch 'origin/36-rest' into 36-rest
romanov73;Thu Mar 1 11:50:59 2018 +0400;try to fix ci: 3 remove tests
Aleksey Filippov;Thu Mar 1 11:50:25 2018 +0400;Merge remote-tracking branch 'origin/36-rest' into 36-rest
Aleksey Filippov;Thu Mar 1 11:49:59 2018 +0400;moved to new database
romanov73;Thu Mar 1 11:45:40 2018 +0400;try to fix ci: 2 change image
romanov73;Thu Mar 1 11:44:42 2018 +0400;try to fix ci: 1
romanov73;Thu Mar 1 11:15:52 2018 +0400;fix csrf tokens
Aleksey Filippov;Thu Mar 1 00:25:43 2018 +0400;initial user management support added
romanov73;Wed Feb 28 22:26:00 2018 +0400;save current version in local storage
romanov73;Wed Feb 28 18:40:57 2018 +0400;add ajax datatable
romanov73;Wed Feb 28 18:01:23 2018 +0400;add static index page with menu
Romanov Anton;Tue Feb 27 16:53:04 2018 +0000;Merge branch '33-' into 'develop'
romanov73;Tue Feb 27 20:50:44 2018 +0400;calc area balance
romanov73;Tue Feb 27 17:36:31 2018 +0400;remove unused panel
Romanov Anton;Tue Feb 27 13:06:02 2018 +0000;Merge branch '32-' into 'develop'
romanov73;Tue Feb 27 17:02:35 2018 +0400;calc tool balance
romanov73;Tue Feb 27 15:45:39 2018 +0400;calc tool balance
romanov73;Tue Feb 27 12:16:41 2018 +0400;calc tool power
romanov73;Tue Feb 27 11:40:59 2018 +0400;use tool types in dto
romanov73;Tue Feb 27 11:29:05 2018 +0400;fix dtos
romanov73;Mon Feb 26 23:50:53 2018 +0400;inherit dtos
romanov73;Mon Feb 26 15:38:00 2018 +0400;fix services for balance calculation
Aleksey Filippov;Mon Feb 26 15:00:48 2018 +0400;move from maven to gradle, move from javaee to spring boot
romanov73;Thu Feb 22 18:03:35 2018 +0400;Add menu resource
Romanov Anton;Tue Feb 20 18:12:55 2018 +0000;Merge branch 'balance-different-dto' into 'develop'
romanov73;Tue Feb 20 22:09:33 2018 +0400;restore tests
romanov73;Tue Feb 20 21:46:45 2018 +0400;filter employees by stage
romanov73;Tue Feb 20 21:21:27 2018 +0400;filter employees by workload
romanov73;Tue Feb 20 20:58:23 2018 +0400;Merge branch 'develop' into balance-different-dto
funny73;Tue Feb 20 19:52:24 2018 +0400;Add shift unit model Add link to unit view
romanov73;Tue Feb 20 16:14:09 2018 +0400;Important fix using coefficient
romanov73;Mon Feb 19 19:00:07 2018 +0400;partially fix ajustment
romanov73;Mon Feb 19 18:24:10 2018 +0400;Modify dto for using with different periods and work types
Romanov Anton;Mon Feb 19 08:11:39 2018 +0000;Merge branch '30-' into 'develop'
romanov73;Mon Feb 19 12:09:05 2018 +0400;Add work type to position
Romanov Anton;Wed Feb 14 20:57:35 2018 +0000;Merge branch '34-' into 'develop'
romanov73;Thu Feb 15 00:51:24 2018 +0400;fixes by comments
romanov73;Thu Feb 15 00:47:21 2018 +0400;merge fields
romanov73;Wed Feb 14 23:42:35 2018 +0400;Merge branch 'develop' into 34-gleb
romanov73;Wed Feb 14 21:05:51 2018 +0400;add clock
Romanov Anton;Wed Feb 14 16:49:29 2018 +0000;Merge branch '45-balance-employee-recomendations' into 'develop'
romanov73;Wed Feb 14 20:46:59 2018 +0400;cleanup code
romanov73;Wed Feb 14 18:25:42 2018 +0400;reduce code
romanov73;Wed Feb 14 18:24:59 2018 +0400;adjust additional employees
romanov73;Wed Feb 14 17:22:10 2018 +0400;move employees from other units
romanov73;Tue Feb 13 23:59:09 2018 +0400;fix save product name
romanov73;Tue Feb 13 23:28:30 2018 +0400;add converter, fix UI and backing for add complex object
romanov73;Tue Feb 13 22:10:59 2018 +0400;Merge branch 'develop' into 34-gleb
funny73;Tue Feb 13 18:07:25 2018 +0400;Add stage to workload
funny73;Tue Feb 13 16:05:45 2018 +0400;Add stage to category
romanov73;Tue Feb 13 13:20:16 2018 +0400;add map of all units balances
romanov73;Tue Feb 13 11:24:50 2018 +0400;move method
romanov73;Tue Feb 13 00:35:30 2018 +0400;add dialog
romanov73;Mon Feb 12 22:59:49 2018 +0400;filter only workshops and manufactures
romanov73;Mon Feb 12 22:04:55 2018 +0400;rename employees
romanov73;Mon Feb 12 17:34:37 2018 +0400;fix font size
romanov73;Mon Feb 12 16:59:16 2018 +0400;fix versions panel width
Romanov Anton;Mon Feb 12 12:47:04 2018 +0000;Merge branch '41-' into 'develop'
romanov73;Mon Feb 12 16:43:06 2018 +0400;change to working hours
romanov73;Mon Feb 12 14:05:36 2018 +0400;remove constructor
romanov73;Mon Feb 12 14:05:13 2018 +0400;Merge remote-tracking branch 'origin/develop' into develop
romanov73;Mon Feb 12 14:04:57 2018 +0400;fix selects
Romanov Anton;Mon Feb 12 09:20:05 2018 +0000;Merge branch '39-work-type-code' into 'develop'
Aleksey Filippov;Mon Feb 12 13:16:36 2018 +0400;add migration for work type code
Aleksey Filippov;Mon Feb 12 13:16:28 2018 +0400;add work type code support to xhtml
Aleksey Filippov;Mon Feb 12 13:16:12 2018 +0400;add work type code
Romanov Anton;Mon Feb 12 08:25:47 2018 +0000;Update README.md
Romanov Anton;Mon Feb 12 08:25:35 2018 +0000;Update README.md
Romanov Anton;Mon Feb 12 08:07:30 2018 +0000;Update README.md
Romanov Anton;Mon Feb 12 07:10:38 2018 +0000;Merge branch '40-' into 'develop'
Aleksey Filippov;Mon Feb 12 11:08:13 2018 +0400;add migration for position type
Aleksey Filippov;Mon Feb 12 11:07:45 2018 +0400;add position type support to xhtml
Aleksey Filippov;Mon Feb 12 11:07:23 2018 +0400;move position converter from boundary to view
Aleksey Filippov;Mon Feb 12 11:06:55 2018 +0400;add position type converter
Aleksey Filippov;Mon Feb 12 11:06:35 2018 +0400;add position type to backing
Aleksey Filippov;Mon Feb 12 11:06:00 2018 +0400;add position type support to service
Aleksey Filippov;Mon Feb 12 11:05:44 2018 +0400;add position type to model
Romanov Anton;Mon Feb 12 07:02:32 2018 +0000;Merge branch '33-' into 'develop'
romanov73;Mon Feb 12 14:58:51 2018 +0400;refactor
romanov73;Mon Feb 12 14:58:33 2018 +0400;add human hours coefficient
romanov73;Mon Feb 12 14:56:43 2018 +0400;fix api name
romanov73;Mon Feb 12 00:58:15 2018 +0400;add balance button
romanov73;Sun Feb 11 01:36:15 2018 +0400;add tools balance prototype
romanov73;Sat Feb 10 23:09:33 2018 +0400;move enum
romanov73;Sat Feb 10 23:02:36 2018 +0400;refactor
romanov73;Sat Feb 10 22:54:28 2018 +0400;add quarter
romanov73;Sat Feb 10 22:42:14 2018 +0400;refactor
romanov73;Sat Feb 10 20:52:46 2018 +0400;Merge branch 'develop' into 33-balance-area
romanov73;Sat Feb 10 20:52:32 2018 +0400;Merge branch 'develop' into 33-balance-area
Romanov Anton;Sat Feb 10 16:14:26 2018 +0000;Merge branch '31-map-2-dto' into 'develop'
romanov73;Sat Feb 10 19:35:17 2018 +0400;fixes after Almaz consultation
romanov73;Sat Feb 10 14:25:00 2018 +0400;fix npe
romanov73;Sat Feb 10 13:50:21 2018 +0400;add filter by work type
romanov73;Sat Feb 10 13:08:56 2018 +0400;rename field
romanov73;Sat Feb 10 13:08:38 2018 +0400;filter by all children
Aleksey Filippov;Sat Feb 10 11:26:17 2018 +0400;some fixes
Aleksey Filippov;Sat Feb 10 11:26:06 2018 +0400;add dto for total balance
Aleksey Filippov;Sat Feb 10 11:11:58 2018 +0400;add dto for employee load by unit
Aleksey Filippov;Sat Feb 10 10:30:11 2018 +0400;getEmployeesByUnit method refactoring
romanov73;Sat Feb 10 00:22:37 2018 +0400;add other type of balance area
romanov73;Fri Feb 9 22:03:39 2018 +0400;add tools balance
romanov73;Fri Feb 9 19:50:21 2018 +0400;divide balance page
Aleksey Filippov;Fri Feb 9 16:37:18 2018 +0400;adapt backing and view to areas and employee experience dtos
Aleksey Filippov;Fri Feb 9 16:36:18 2018 +0400;add dto for employee experience
Aleksey Filippov;Fri Feb 9 16:35:51 2018 +0400;add dto for areas
Aleksey Filippov;Fri Feb 9 14:57:01 2018 +0400;some ui fixes
Aleksey Filippov;Fri Feb 9 14:55:36 2018 +0400;move db methods from getters to init
romanov73;Thu Feb 8 01:20:12 2018 +0400;add areas panel
romanov73;Thu Feb 8 01:19:13 2018 +0400;add areas panel
romanov73;Thu Feb 8 01:02:39 2018 +0400;add global preloader
romanov73;Thu Feb 8 00:57:46 2018 +0400;select default unit
romanov73;Thu Feb 8 00:57:23 2018 +0400;add preloader
romanov73;Wed Feb 7 22:46:44 2018 +0400;change id
Romanov Anton;Wed Feb 7 13:53:35 2018 +0000;Merge branch '23-' into 'develop'
Romanov Anton;Wed Feb 7 13:49:27 2018 +0000;Merge branch 'deploy-fixes' into 'develop'
funny73;Wed Feb 7 17:34:41 2018 +0400;UDP modify AirplaneKitCounter to double
Aleksey Filippov;Wed Feb 7 17:33:23 2018 +0400;some wildfly deploy fixes
funny73;Wed Feb 7 17:19:22 2018 +0400;Modify AirplaneKitCounter to double -> Workload.java
funny73;Wed Feb 7 17:00:10 2018 +0400;Add AirplaneKitCounter to balance view -> BalanceEmployeeService.java Modify Worckload total Value (Value * AirplaneKitCounter) -> BalanceService.java
funny73;Wed Feb 7 14:13:35 2018 +0400;Add AirplaneKitCounter to view
funny73;Wed Feb 7 14:13:15 2018 +0400;Add AirplaneKitCounter to model Workload
funny73;Wed Feb 7 14:12:15 2018 +0400;Changelog for airplainetKitCounter
Romanov Anton;Wed Feb 7 06:54:55 2018 +0000;Merge branch '22-' into 'develop'
romanov73;Wed Feb 7 14:47:34 2018 +0400;add unit types
Romanov Anton;Tue Feb 6 22:43:40 2018 +0000;Merge branch '25-' into 'develop'
romanov73;Wed Feb 7 02:41:34 2018 +0400;filter balance by unit
romanov73;Wed Feb 7 02:06:46 2018 +0400;filter balance by unit
romanov73;Wed Feb 7 02:05:10 2018 +0400;filter balance by unit
romanov73;Wed Feb 7 00:41:01 2018 +0400;add method get all unit children
romanov73;Tue Feb 6 23:26:18 2018 +0400;add filter by unit in balance results
romanov73;Tue Feb 6 21:26:45 2018 +0400;refactor work with tree of menu items
romanov73;Tue Feb 6 21:08:01 2018 +0400;refactor work with tree
romanov73;Tue Feb 6 21:07:22 2018 +0400;fix update after remove enum key
romanov73;Tue Feb 6 20:03:31 2018 +0400;rename method
Gleb;Tue Feb 6 15:07:04 2018 +0000;Merge branch '17-' into 'develop'
romanov73;Tue Feb 6 21:15:12 2018 +0400;fix inf.
funny73;Tue Feb 6 19:02:36 2018 +0400;Add changelog for units with unit_type == 'Корпус', unit_type='Цех'
funny73;Tue Feb 6 18:19:50 2018 +0400;Remove "Korpus" from "Tip podrazdeleniya"
Romanov Anton;Tue Feb 6 11:31:43 2018 +0000;Merge branch '24-' into 'develop'
romanov73;Tue Feb 6 19:01:21 2018 +0400;add user
Romanov Anton;Thu Feb 1 19:45:21 2018 +0000;Merge branch 'wildfly-deploy' into 'develop'
Aleksey Filippov;Thu Feb 1 23:24:34 2018 +0400;add wildfly-maven-plugin, remove maven-glassfish-plugin
romanov73;Thu Feb 1 19:51:24 2018 +0400;add todos
Romanov Anton;Wed Jan 31 15:03:39 2018 +0000;Merge branch 'master' into 'develop'
romanov73;Wed Jan 31 18:53:27 2018 +0400;fix round
romanov73;Wed Jan 31 18:43:33 2018 +0400;fix round
romanov73;Wed Jan 31 18:38:33 2018 +0400;add balance by employees
romanov73;Wed Jan 31 18:30:18 2018 +0400;add balance by employees
Romanov Anton;Wed Jan 31 13:02:52 2018 +0000;Merge branch 'develop' into 'master'
Romanov Anton;Wed Jan 31 12:58:00 2018 +0000;Merge branch '4-' into 'develop'
romanov73;Wed Jan 31 16:47:51 2018 +0400;add balance by employees
romanov73;Wed Jan 31 00:47:39 2018 +0400;add calculation employee loads
romanov73;Wed Jan 31 00:47:25 2018 +0400;add calculation employee loads
romanov73;Wed Jan 31 00:47:08 2018 +0400;add calculation employee loads
romanov73;Wed Jan 31 00:46:53 2018 +0400;add calculation employee loads
romanov73;Wed Jan 31 00:45:59 2018 +0400;add interface for edit additional fields
romanov73;Wed Jan 31 00:45:04 2018 +0400;add comparable for using in tree map
romanov73;Wed Jan 31 00:44:33 2018 +0400;add fields for production program
romanov73;Wed Jan 31 00:43:56 2018 +0400;move interface to base entity
romanov73;Wed Jan 31 00:43:21 2018 +0400;add database fields for production program
romanov73;Wed Jan 31 00:42:55 2018 +0400;add dynamic columns
romanov73;Tue Jan 30 15:11:12 2018 +0400;add work type for workload
romanov73;Tue Jan 30 14:55:56 2018 +0400;add comments
romanov73;Tue Jan 30 03:00:28 2018 +0400;show by production program
romanov73;Tue Jan 30 00:07:31 2018 +0400;add employee available capacity
romanov73;Mon Jan 29 23:42:06 2018 +0400;fix units hierarchy bypass
romanov73;Mon Jan 29 23:28:28 2018 +0400;divide logic
romanov73;Mon Jan 29 22:59:45 2018 +0400;add employee experience table
romanov73;Mon Jan 29 22:15:29 2018 +0400;fix calc areas
romanov73;Mon Jan 29 21:57:23 2018 +0400;fix calc employee experience
romanov73;Mon Jan 29 21:12:52 2018 +0400;calc employee experience by units
romanov73;Mon Jan 29 14:01:36 2018 +0400;add employee experience
Romanov Anton;Mon Jan 29 06:04:01 2018 +0000;Update README.md
Romanov Anton;Sun Jan 28 16:16:56 2018 +0000;Merge branch 'develop' into 'master'
Romanov Anton;Sun Jan 28 16:06:14 2018 +0000;Merge branch '3-' into 'develop'
romanov73;Sun Jan 28 19:53:21 2018 +0400;remove product work types edit
romanov73;Sun Jan 28 19:41:31 2018 +0400;fix months select
romanov73;Sun Jan 28 19:06:10 2018 +0400;fix year select
romanov73;Sun Jan 28 04:28:21 2018 +0400;fix program edit
romanov73;Sun Jan 28 04:27:55 2018 +0400;add product backend
romanov73;Sun Jan 28 04:26:53 2018 +0400;add table and fields
Romanov Anton;Sat Jan 27 08:11:15 2018 +0000;Merge branch '9-' into 'develop'
romanov73;Sat Jan 27 15:28:22 2018 +0400;sort menu items, change logo
Romanov Anton;Sat Jan 27 05:55:52 2018 +0000;Update README.md
romanov73;Sat Jan 20 00:12:44 2018 +0400;fix versions select
Romanov Anton;Fri Jan 19 04:27:48 2018 +0000;Merge branch 'tool-square-catalog' into 'master'
Aleksey Filippov;Fri Jan 19 01:11:50 2018 +0400;add tool square catalog migration
Aleksey Filippov;Thu Jan 18 02:20:48 2018 +0400;add tool square catalog
romanov73;Thu Jan 11 21:22:14 2018 +0400;fix rest path
romanov73;Tue Jan 9 03:44:10 2018 +0400;fixes
romanov73;Tue Jan 9 00:09:27 2018 +0400;fix unit name
romanov73;Tue Jan 9 00:07:47 2018 +0400;fix year
romanov73;Mon Jan 8 19:16:28 2018 +0400;add short view
romanov73;Mon Jan 8 11:55:30 2018 +0400;fix
romanov73;Mon Jan 8 01:24:37 2018 +0400;fill work type by tool name
romanov73;Mon Jan 8 00:23:00 2018 +0400;ui fixes
romanov73;Sun Jan 7 23:54:40 2018 +0400;fix units hierarchy, add unit type, calc areas balance
romanov73;Sat Jan 6 22:51:11 2018 +0400;remove versions
romanov73;Sat Jan 6 22:06:03 2018 +0400;fix edit program
romanov73;Sat Jan 6 21:40:11 2018 +0400;add title image
romanov73;Sat Jan 6 18:04:27 2018 +0400;add production program input
romanov73;Wed Jan 3 21:05:48 2018 +0400;change wizard to tabs
romanov73;Wed Jan 3 01:03:05 2018 +0400;add wizard
romanov73;Sat Dec 30 02:02:42 2017 +0400;fix tools loading
romanov73;Sat Dec 30 01:46:01 2017 +0400;fix tools loading
romanov73;Sat Dec 30 01:32:33 2017 +0400;fix tools loading
romanov73;Sat Dec 30 01:28:24 2017 +0400;fix tools loading
romanov73;Sat Dec 30 00:54:26 2017 +0400;fix employee loading
romanov73;Fri Dec 29 19:04:14 2017 +0400;fix unit select
romanov73;Fri Dec 29 17:19:10 2017 +0400;fix unit select
romanov73;Fri Dec 29 01:40:38 2017 +0400;add cache
romanov73;Fri Dec 29 01:27:18 2017 +0400;add cache
romanov73;Fri Dec 29 01:14:09 2017 +0400;add cache
romanov73;Fri Dec 29 01:12:17 2017 +0400;change color
romanov73;Fri Dec 29 00:50:57 2017 +0400;add ci
romanov73;Fri Dec 29 00:48:10 2017 +0400;add ci
romanov73;Fri Dec 29 00:34:36 2017 +0400;add ci
romanov73;Fri Dec 29 00:31:22 2017 +0400;add ci
romanov73;Fri Dec 29 00:18:51 2017 +0400;add ci
romanov73;Fri Dec 29 00:16:44 2017 +0400;add ci
romanov73;Fri Dec 29 00:13:33 2017 +0400;add ci
romanov73;Fri Dec 29 00:09:51 2017 +0400;fix menus
Romanov Anton;Thu Dec 28 19:47:02 2017 +0000;Merge branch 'balance-example' into 'master'
romanov73;Thu Dec 28 23:44:52 2017 +0400;add other dictionaries
romanov73;Sat Dec 23 10:40:41 2017 +0400;add tool and work types
romanov73;Sat Dec 23 09:12:38 2017 +0400;fix menu item
romanov73;Sat Dec 23 09:12:23 2017 +0400;fix employee load
romanov73;Sat Dec 23 08:51:18 2017 +0400;add employee category
romanov73;Sat Dec 23 08:22:10 2017 +0400;add categories dictionary
romanov73;Fri Dec 22 12:38:08 2017 +0400;add menu item
romanov73;Fri Dec 22 12:31:26 2017 +0400;add employee category
romanov73;Fri Dec 22 09:55:31 2017 +0400;fix calendar
romanov73;Fri Dec 22 09:33:56 2017 +0400;fix date
romanov73;Thu Dec 21 16:38:20 2017 +0400;fix for context path change
romanov73;Thu Dec 21 13:58:02 2017 +0400;fluid panel
romanov73;Wed Dec 20 20:50:17 2017 +0400;fix context path
romanov73;Wed Dec 20 17:12:19 2017 +0400;fix displaying position
romanov73;Wed Dec 20 17:10:14 2017 +0400;load employees from file
romanov73;Wed Dec 20 15:09:54 2017 +0400;fix tool loading
romanov73;Mon Dec 18 18:18:04 2017 +0400;add resource versions
romanov73;Mon Dec 18 17:36:50 2017 +0400;add resource
romanov73;Mon Dec 18 17:07:47 2017 +0400;add swagger
romanov73;Sat Dec 16 09:42:46 2017 +0400;add new version
romanov73;Fri Dec 15 19:50:46 2017 +0400;fix title
romanov73;Fri Dec 15 19:24:13 2017 +0400;fix title
romanov73;Fri Dec 15 11:57:18 2017 +0400;add menu items
romanov73;Fri Dec 15 11:52:01 2017 +0400;add positions dictionary
romanov73;Fri Dec 15 11:29:02 2017 +0400;fix select for employee
romanov73;Fri Dec 15 10:35:12 2017 +0400;add employee backing
romanov73;Fri Dec 15 09:36:33 2017 +0400;fix 500 error page
romanov73;Thu Dec 14 22:26:45 2017 +0400;fix mapping
romanov73;Thu Dec 14 22:49:44 2017 +0400;add employee
romanov73;Thu Dec 14 22:37:30 2017 +0400;add employee
romanov73;Thu Dec 14 14:12:03 2017 +0400;fix crud service
romanov73;Thu Dec 14 12:51:59 2017 +0400;fix table style
romanov73;Thu Dec 14 12:22:48 2017 +0400;remove border for grid
romanov73;Thu Dec 14 12:20:14 2017 +0400;add version_id for units
romanov73;Thu Dec 14 11:49:53 2017 +0400;fix font size
romanov73;Thu Dec 14 11:08:46 2017 +0400;add unit fields
romanov73;Thu Dec 14 10:23:01 2017 +0400;KISS units hierarchy
romanov73;Wed Dec 13 19:04:05 2017 +0400;refresh page
romanov73;Wed Dec 13 17:43:54 2017 +0400;add version
romanov73;Wed Dec 13 01:46:05 2017 +0400;body width
romanov73;Wed Dec 13 01:45:17 2017 +0400;add menu item
romanov73;Tue Dec 12 22:20:07 2017 +0400;fix tree
romanov73;Tue Dec 12 20:02:20 2017 +0400;fix login
romanov73;Tue Dec 12 19:29:03 2017 +0400;add unit tree
romanov73;Tue Dec 12 18:23:38 2017 +0400;add unit dictionary
romanov73;Tue Dec 12 16:18:03 2017 +0400;add filter
romanov73;Tue Dec 12 14:13:31 2017 +0400;fix menu session
romanov73;Tue Dec 12 00:10:47 2017 +0400;remove bootstrap
romanov73;Mon Dec 11 21:53:18 2017 +0400;add unit select
romanov73;Mon Dec 11 19:49:15 2017 +0400;add menu item and role
romanov73;Mon Dec 11 19:37:38 2017 +0400;fix permissions
romanov73;Mon Dec 11 17:08:39 2017 +0400;refactor and add tools dictionary backing
romanov73;Mon Dec 11 17:08:04 2017 +0400;refactor and add tools dictionary backing
romanov73;Mon Dec 11 17:07:27 2017 +0400;refactor and add tools dictionary backing
romanov73;Mon Dec 11 14:12:24 2017 +0400;add tools dictionary page
romanov73;Sat Dec 9 09:54:45 2017 +0400;add global exception hadler
romanov73;Sat Nov 25 13:52:33 2017 +0400;add monitoring
romanov73;Sat Nov 25 13:21:18 2017 +0400;fix xls and xlsx
romanov73;Sat Nov 25 12:39:45 2017 +0400;upload tools
romanov73;Fri Nov 24 22:16:27 2017 +0400;save tools
romanov73;Fri Nov 24 13:06:21 2017 +0400;fix message
romanov73;Fri Nov 24 12:11:43 2017 +0400;add loading from xlsx
romanov73;Fri Nov 17 19:43:35 2017 +0400;add message
romanov73;Fri Nov 17 15:11:22 2017 +0400;fix button
romanov73;Fri Nov 17 10:15:42 2017 +0400;add registration service
romanov73;Thu Nov 16 21:35:04 2017 +0400;add push script
romanov73;Thu Nov 16 20:54:49 2017 +0400;fix named query execution
romanov73;Sun Nov 12 22:19:03 2017 +0400;sort menu items
romanov73;Sat Nov 11 15:09:35 2017 +0400;fix title
romanov73;Sat Nov 11 14:54:25 2017 +0400;fix table
romanov73;Sat Nov 11 14:35:38 2017 +0400;fix style attribute
romanov73;Sat Nov 11 14:08:56 2017 +0400;show user sessions
romanov73;Sat Nov 11 13:51:34 2017 +0400;rename service
romanov73;Fri Nov 10 22:03:25 2017 +0400;fix update tree
romanov73;Fri Nov 10 14:29:25 2017 +0400;edit menu items
romanov73;Fri Nov 10 12:17:24 2017 +0400;set bootstrap theme for primefaces
romanov73;Thu Nov 9 23:40:40 2017 +0400;fix saving entitites
romanov73;Thu Nov 9 23:27:42 2017 +0400;fix saving entitites
romanov73;Thu Nov 9 20:51:19 2017 +0400;fix titles
romanov73;Thu Nov 9 18:00:45 2017 +0400;fix login page title
romanov73;Thu Nov 9 13:36:21 2017 +0400;commit log
romanov73;Thu Nov 9 07:31:37 2017 +0400;reverse sort commits
romanov73;Thu Nov 9 00:27:48 2017 +0400;sort commits
romanov73;Wed Nov 8 23:16:07 2017 +0400;extend commits log
romanov73;Wed Nov 8 21:42:16 2017 +0400;fix styles
romanov73;Wed Nov 8 19:17:08 2017 +0400;add logout
romanov73;Wed Nov 8 19:13:17 2017 +0400;add logout
romanov73;Wed Nov 8 20:18:35 2017 +0400;Merge branch 'master' of gitlab.com:romanov73/balance
romanov73;Wed Nov 8 20:17:55 2017 +0400;add database diagramm
Romanov Anton;Wed Nov 8 04:13:39 2017 +0000;Update README.md
Romanov Anton;Wed Nov 8 04:11:33 2017 +0000;Update README.md
romanov73;Wed Nov 8 07:48:13 2017 +0400;Merge remote-tracking branch 'origin/master'
Romanov Anton;Tue Nov 7 18:05:04 2017 +0000;Update README.md
romanov73;Tue Nov 7 22:01:50 2017 +0400;add example of permissions validation
romanov73;Tue Nov 7 20:56:31 2017 +0400;rename project
romanov73;Wed Oct 11 21:37:49 2017 +0400;reverse sort commits
romanov73;Wed Oct 11 21:32:19 2017 +0400;fix read resource as file
romanov73;Wed Oct 11 20:23:10 2017 +0400;Merge remote-tracking branch 'origin/master'
romanov73;Wed Oct 11 20:22:52 2017 +0400;add commits log
Romanov Anton;Tue Oct 10 20:47:29 2017 +0000;Update README.md
romanov73;Fri Oct 6 01:55:57 2017 +0400;add menu to platform
Anton Romanov;Thu Mar 28 14:59:35 2019 +0400;partially restored commits page
Anton Romanov;Wed Mar 27 13:27:49 2019 +0400;#33 small external link
Anton Romanov;Wed Mar 27 09:07:02 2019 +0000;Update README.md
Anton Romanov;Wed Mar 27 07:58:58 2019 +0000;Merge branch '33-paper-url' into 'dev'
Семенова Мария;Sat Mar 23 12:23:30 2019 +0400;#33 link in new tab
Семенова Мария;Sat Mar 23 12:04:51 2019 +0400;Merge branch 'dev' into 33-paper-url
Anton Romanov;Fri Mar 22 10:36:09 2019 +0000;Merge branch '13-paper-files' into 'dev'
Anton Romanov;Fri Mar 22 13:58:03 2019 +0400;#13 reduce of code
Anton Romanov;Fri Mar 22 13:52:06 2019 +0400;#13 fix condition
Семенова Мария;Fri Mar 22 13:21:32 2019 +0400;#13 streams refactoring
Семенова Мария;Fri Mar 22 09:32:21 2019 +0400;#13 rename 'deleted', move creating fileDto to service
Семенова Мария;Thu Mar 21 18:26:28 2019 +0400;#13 fileDataDto instead of Object[]
Семенова Мария;Tue Mar 19 17:59:19 2019 +0400;#13 some refactoring
Семенова Мария;Tue Mar 19 17:41:02 2019 +0400;Merge branch 'dev' into 13-paper-files
Семенова Мария;Mon Mar 18 23:31:33 2019 +0400;#33 url in paper
Anton Romanov;Mon Mar 18 22:35:01 2019 +0400;merge deploy environments
Anton Romanov;Mon Mar 18 22:25:28 2019 +0400;add environment
Семенова Мария;Mon Mar 18 21:02:26 2019 +0400;#13 download files
Семенова Мария;Mon Mar 18 19:17:28 2019 +0400;#13 add files to db
Семенова Мария;Mon Mar 18 18:39:15 2019 +0400;#13 addNewFile js function
Семенова Мария;Mon Mar 18 16:13:22 2019 +0400;Merge branch 'dev' into 13-paper-files
Семенова Мария;Mon Mar 18 16:02:55 2019 +0400;#13 file list on paper page
Anton Romanov;Mon Mar 18 11:08:15 2019 +0000;Merge branch '50-refactorForGrants' into 'dev'
T-Midnight;Mon Mar 18 14:27:54 2019 +0400;Delete DeadlineDTO and update usages
Семенова Мария;Mon Mar 18 13:00:34 2019 +0400;#13 add fileDataDto
Семенова Мария;Mon Mar 18 11:07:30 2019 +0400;#13 change model, schema
T-Midnight;Fri Mar 15 12:24:02 2019 +0400;Add new status for grant
T-Midnight;Fri Mar 15 12:19:25 2019 +0400;Rename title
T-Midnight;Fri Mar 15 12:19:01 2019 +0400;Create Navigation class to avoid "magic strings" and code duplication
Anton Romanov;Wed Mar 13 07:16:32 2019 +0000;Merge branch '72-link-to-timetable' into 'dev'
Anton Romanov;Tue Mar 12 14:44:11 2019 +0400;add patronymic
Anton Romanov;Tue Mar 12 13:40:48 2019 +0400;display user in filter
Anton Romanov;Tue Mar 12 12:51:59 2019 +0300;add service methods
Anton Romanov;Tue Mar 12 12:35:09 2019 +0300;add timetable link
Anton Romanov;Mon Mar 11 10:49:07 2019 +0000;Merge branch '54-view-conference' into 'dev'
Nightblade73;Mon Mar 11 14:43:32 2019 +0400;#54 deleted edit btn
Nightblade73;Mon Mar 11 12:58:40 2019 +0400;#54 add back link, css fixes
Nightblade73;Mon Mar 11 11:36:00 2019 +0400;#54 add custom paper-list
Nightblade73;Sun Mar 10 22:15:09 2019 +0400;#54 add custom deadline-list, add edit-button, add edit and delete icons
Nightblade73;Thu Mar 7 22:50:37 2019 +0400;#54 add member list
Nightblade73;Wed Mar 6 20:51:46 2019 +0400;#54 part of make-up
Nightblade73;Wed Mar 6 16:48:51 2019 +0400;#54 add transitions
Anton Romanov;Wed Mar 6 16:40:33 2019 +0400;fix login
Nightblade73;Wed Mar 6 16:27:25 2019 +0400;#50 creating html page, changing href
Anton Romanov;Wed Mar 6 12:25:34 2019 +0000;Merge branch '29-page-header' into 'dev'
Anton Romanov;Wed Mar 6 16:19:43 2019 +0400;fix css
Anton Romanov;Wed Mar 6 14:36:46 2019 +0300;fix props
Anton Romanov;Wed Mar 6 14:35:09 2019 +0300;fix props
user;Wed Mar 6 14:25:02 2019 +0300;header fix
Anton Romanov;Mon Mar 4 10:28:46 2019 +0400;fix code
Anton Romanov;Mon Mar 4 10:24:30 2019 +0400;fix code
Anton Romanov;Fri Mar 1 11:27:57 2019 +0400;fix branch
Anton Romanov;Fri Mar 1 11:22:25 2019 +0400;add links to papers
Anton Romanov;Fri Mar 1 11:21:25 2019 +0400;add links to papers
Anton Romanov;Sun Feb 3 14:54:02 2019 +0000;Update README.md
Anton Romanov;Thu Jan 17 01:01:26 2019 +0400;filter dashboard papers
Anton Romanov;Thu Jan 17 00:57:34 2019 +0400;fix failed conditions
Anton Romanov;Tue Jan 8 19:55:27 2019 +0000;Update README.md
Anton Romanov;Tue Jan 8 19:36:36 2019 +0000;Update README.md
Anton Romanov;Sat Jan 5 08:01:07 2019 +0400;fix notifications
Anton Romanov;Fri Jan 4 17:41:48 2019 +0400;fix notifications
Anton Romanov;Sun Dec 30 19:23:11 2018 +0400;some layout fix
Anton Romanov;Sun Dec 30 19:22:51 2018 +0400;sort deadlines
Anton Romanov;Sat Dec 29 09:58:37 2018 +0400;fix enum field name
Anton Romanov;Fri Dec 28 10:04:42 2018 +0000;Merge branch '35-' into 'master'
Anton Romanov;Fri Dec 28 14:00:09 2018 +0400;some refactor
Anton Romanov;Fri Dec 28 13:57:20 2018 +0400;some refactor
T-Midnight;Tue Dec 25 12:50:14 2018 +0400;Create model folder for grant
T-Midnight;Tue Dec 25 02:44:50 2018 +0400;Hide button "Add Project" when project already exists (not perfect)
T-Midnight;Tue Dec 25 00:14:38 2018 +0400;Made button "delete grant" visible
T-Midnight;Mon Dec 24 23:39:19 2018 +0400;Rename table grant to grants
T-Midnight;Mon Dec 24 15:20:57 2018 +0400;Update classes
T-Midnight;Mon Dec 24 15:18:52 2018 +0400;Add thymeleaf template
T-Midnight;Mon Dec 24 13:05:37 2018 +0400;Create service&repository for Project
T-Midnight;Mon Dec 24 11:07:02 2018 +0400;Create js for grants
T-Midnight;Mon Dec 24 11:03:03 2018 +0400;Create html fragments
T-Midnight;Sun Dec 23 02:22:41 2018 +0400;Create Controller&Service
T-Midnight;Sun Dec 23 02:22:31 2018 +0400;Update ProjectDto
T-Midnight;Sun Dec 23 02:22:24 2018 +0400;Add constructor
T-Midnight;Sun Dec 23 02:22:06 2018 +0400;Add function getNextDeadline()
T-Midnight;Sat Dec 22 18:03:18 2018 +0400;Create GrantRepository
T-Midnight;Sat Dec 22 03:31:43 2018 +0400;Create setters for GrantDto
Anton Romanov;Fri Dec 21 00:07:26 2018 +0400;fix display paper title
Anton Romanov;Thu Dec 20 23:30:25 2018 +0400;fix paper status template
Anton Romanov;Wed Dec 19 01:29:54 2018 +0400;try to fix template resolvers, step 4
Anton Romanov;Wed Dec 19 01:00:08 2018 +0400;try to fix template resolvers, step 3
Anton Romanov;Wed Dec 19 00:44:12 2018 +0400;try to fix template resolvers, step 2
Anton Romanov;Wed Dec 19 00:22:36 2018 +0400;try to fix template resolvers
Anton Romanov;Wed Dec 19 00:11:39 2018 +0400;Merge remote-tracking branch 'origin/master'
Anton Romanov;Wed Dec 19 00:09:07 2018 +0400;try to fix gradlew
Anton Romanov;Tue Dec 18 23:02:48 2018 +0400;sort filtered papers
Anton Romanov;Tue Dec 18 18:45:43 2018 +0000;Merge branch '47-statuses' into 'master'
Anton Romanov;Tue Dec 18 22:42:34 2018 +0400;add statuses
Anton Romanov;Tue Dec 18 18:18:25 2018 +0000;Merge branch '46-mvc' into 'master'
Anton Romanov;Tue Dec 18 22:15:21 2018 +0400;fix filer
Anton Romanov;Tue Dec 18 19:40:23 2018 +0400;fix scripts
Anton Romanov;Tue Dec 18 19:23:15 2018 +0400;show authors
Anton Romanov;Tue Dec 18 18:47:15 2018 +0400;confirm delete paper
Anton Romanov;Tue Dec 18 18:05:30 2018 +0400;add papers navigation
Anton Romanov;Mon Dec 17 17:56:48 2018 +0400;fix submit form
Anton Romanov;Mon Dec 17 17:29:06 2018 +0400;fix email notification
Anton Romanov;Mon Dec 17 17:28:52 2018 +0400;fix route
Anton Romanov;Mon Dec 17 13:46:08 2018 +0400;edit deadlines
Anton Romanov;Fri Dec 14 16:00:46 2018 +0400;Merge branch 'master' into 46-mvc
Anton Romanov;Fri Dec 14 16:00:33 2018 +0400;Merge branch 'master' into 46-mvc
Anton Romanov;Tue Dec 11 11:14:21 2018 +0000;Merge branch '36-' into 'master'
Anton Romanov;Tue Dec 11 15:08:35 2018 +0400;move classes, add deadline to entities, fix db changelogs
T-Midnight;Sat Dec 8 23:53:38 2018 +0400;Create model for grant, deadline and project
Anton Romanov;Wed Dec 5 18:08:47 2018 +0400;save authors
Anton Romanov;Wed Dec 5 17:36:53 2018 +0400;fix npe
Anton Romanov;Wed Dec 5 17:06:56 2018 +0400;format dates
Anton Romanov;Wed Dec 5 16:51:26 2018 +0400;fix create paper
Anton Romanov;Wed Dec 5 06:00:33 2018 +0000;add rest controller
Anton Romanov;Tue Dec 4 14:49:23 2018 +0400;fix js
Anton Romanov;Tue Dec 4 14:48:39 2018 +0400;show status
Anton Romanov;Tue Dec 4 14:13:01 2018 +0400;add validation
Anton Romanov;Tue Dec 4 11:35:51 2018 +0400;pass values for paper
Anton Romanov;Mon Nov 26 23:07:14 2018 +0400;load paper
Anton Romanov;Fri Nov 23 16:40:15 2018 +0000;Merge branch '14-filter-frontend' into 'master'
Anton Romanov;Fri Nov 23 20:37:24 2018 +0400;fix failed commit
Anton Romanov;Fri Nov 23 16:24:26 2018 +0000;Merge branch '10-savePaper' into 'master'
Anton Romanov;Fri Nov 23 16:45:40 2018 +0400;show paper list in mvc
Alyona;Fri Nov 23 14:17:16 2018 +0400;filter
Alyona;Fri Nov 23 14:12:37 2018 +0400;Merge branch 'master' into 14-filter-frontend
Alyona;Fri Nov 23 14:10:49 2018 +0400;Merge remote-tracking branch 'origin/master'
Alyona;Fri Nov 23 14:10:36 2018 +0400;Merge branch 'master' of C:\Users\катя\IdeaProjects\ng-tracker with conflicts.
Elena;Fri Nov 23 14:05:23 2018 +0400;задача 10(new)
Elena;Fri Nov 23 13:53:20 2018 +0400;задача 10
Elena;Fri Nov 23 12:39:36 2018 +0400;Merge branch 'master' into 10-savePaper
Anton Romanov;Thu Nov 22 21:48:36 2018 +0400;fix colors
Anton Romanov;Thu Nov 22 21:31:41 2018 +0400;fix colors
Anton Romanov;Thu Nov 22 21:06:58 2018 +0400;add paper status
Anton Romanov;Thu Nov 22 11:20:08 2018 +0400;Merge remote-tracking branch 'origin/master'
Anton Romanov;Thu Nov 22 11:19:50 2018 +0400;add mertica
Anton Romanov;Wed Nov 21 15:47:26 2018 +0400;remove empty page
Anton Romanov;Wed Nov 21 15:47:14 2018 +0400;add toolbar
Anton Romanov;Wed Nov 21 15:42:20 2018 +0400;Merge remote-tracking branch 'origin/master'
Anton Romanov;Wed Nov 21 11:42:47 2018 +0000;Merge branch '31-' into 'master'
Anton Romanov;Wed Nov 21 15:40:20 2018 +0400;close failed papers
T-Midnight;Wed Nov 21 15:28:41 2018 +0400;Create grant page
Anton Romanov;Wed Nov 21 08:51:11 2018 +0000;Merge branch '30-main-grants-page' into 'master'
Anton Romanov;Wed Nov 21 12:46:42 2018 +0400;Merge remote-tracking branch 'origin/master'
Anton Romanov;Wed Nov 21 12:46:27 2018 +0400;notify if paper deadline in future
T-Midnight;Mon Nov 19 12:16:39 2018 +0400;Update dashboard for grants
Anton Romanov;Mon Nov 19 08:21:22 2018 +0400;fix for remove event
Anton Romanov;Mon Nov 19 07:46:02 2018 +0400;fix event create conditions
Anton Romanov;Sun Nov 18 14:29:41 2018 +0400;fix delete button
Anton Romanov;Sat Nov 17 12:31:22 2018 +0400;fix delete button
Anton Romanov;Sat Nov 17 11:56:52 2018 +0400;show events
Anton Romanov;Wed Nov 14 17:14:56 2018 +0400;fix build script for netbeans
Anton Romanov;Wed Nov 14 17:04:40 2018 +0400;show toolbar buttons
Anton Romanov;Wed Nov 14 17:04:29 2018 +0400;show toolbar buttons
Anton Romanov;Wed Nov 14 17:04:13 2018 +0400;show paper status
Anton Romanov;Wed Nov 14 17:03:22 2018 +0400;fix code
Anton Romanov;Wed Nov 14 15:18:22 2018 +0400;fix code
Anton Romanov;Wed Nov 14 15:15:23 2018 +0400;read dashboard
Alyona;Wed Nov 14 08:55:46 2018 +0400;filter
Anton Romanov;Tue Nov 13 11:46:25 2018 +0000;Merge branch '14-DB-filter' into 'master'
Anton Romanov;Tue Nov 13 15:41:18 2018 +0400;filter papers
Anton Romanov;Sun Nov 11 14:28:51 2018 +0400;Merge remote-tracking branch 'origin/master'
Anton Romanov;Sun Nov 11 12:43:27 2018 +0400;move class
Anton Romanov;Sat Nov 10 21:44:36 2018 +0000;Merge branch '20-' into 'master'
Anton Romanov;Sun Nov 11 01:31:27 2018 +0400;fix scheduler
Anton Romanov;Sun Nov 11 01:29:06 2018 +0400;refactor and db changes
Anton Romanov;Sat Nov 10 23:15:35 2018 +0400;delete paper
T-Midnight;Sat Nov 10 21:55:09 2018 +0400;Create dashboard for grants
Anton Romanov;Sat Nov 10 21:43:52 2018 +0400;add route
Alyona;Sat Nov 10 20:28:17 2018 +0400;fix
Alyona;Fri Nov 9 15:43:42 2018 +0400;fix
Elena;Fri Nov 9 15:43:25 2018 +0400;Задача №10
Anton Romanov;Fri Nov 9 15:37:58 2018 +0400;remove styles from email template
Alyona;Fri Nov 9 15:29:48 2018 +0400;Merge remote-tracking branch 'origin/master'
Anton Romanov;Fri Nov 9 15:21:03 2018 +0400;move styles to body
Anton Romanov;Fri Nov 9 11:15:00 2018 +0000;Merge branch '21-Event-status' into 'master'
Anton Romanov;Fri Nov 9 15:08:10 2018 +0400;Merge branch 'master' into 21-Event-status
Anton Romanov;Fri Nov 9 15:05:39 2018 +0400;fix styles
Anton Romanov;Fri Nov 9 14:53:24 2018 +0400;add styles in email templates
Alyona;Fri Nov 9 14:51:19 2018 +0400;added period event
Alyona;Fri Nov 9 14:48:21 2018 +0400;added period event
Elena;Fri Nov 9 13:43:08 2018 +0400;Merge branch 'master' into 10-savePaper
Elena;Fri Nov 9 13:42:28 2018 +0400;Задача №10
Alyona;Fri Nov 9 13:30:31 2018 +0400;Merge remote-tracking branch 'origin/master'
Anton Romanov;Fri Nov 9 10:04:50 2018 +0400;add notification templates
Anton Romanov;Fri Nov 9 09:16:24 2018 +0400;move to notification service
Anton Romanov;Fri Nov 9 08:39:00 2018 +0400;fix scheduler code to use service
Anton Romanov;Thu Nov 8 21:58:10 2018 +0400;add toolbar
Anton Romanov;Thu Nov 8 20:34:09 2018 +0400;fix paths
Anton Romanov;Thu Nov 8 20:08:26 2018 +0400;add config parameter
Anton Romanov;Thu Nov 8 19:39:22 2018 +0400;Merge remote-tracking branch 'origin/master'
Anton Romanov;Thu Nov 8 19:36:50 2018 +0400;add paper create strategy
Anton Romanov;Tue Nov 6 10:39:25 2018 +0000;Update README.md
Anton Romanov;Tue Nov 6 14:10:00 2018 +0400;fix ci
Anton Romanov;Thu Nov 1 12:53:19 2018 +0400;fix imports
Alyona;Wed Oct 31 20:06:27 2018 +0400;changelog
Alyona;Wed Oct 31 19:35:23 2018 +0400;Merge branch 'master' into 21-Event-status
Alyona;Wed Oct 31 19:33:21 2018 +0400;Merge branch 'master' of C:\Users\катя\IdeaProjects\ng-tracker with conflicts.
Alyona;Tue Oct 30 23:59:42 2018 +0400;added event status
Anton Romanov;Tue Oct 30 19:32:00 2018 +0000;Merge branch '4-show-time-line' into 'master'
Anton Romanov;Tue Oct 30 23:29:18 2018 +0400;Merge branch 'master' into 4-show-time-line
Anton Romanov;Tue Oct 30 23:26:55 2018 +0400;fix db
Anton Romanov;Tue Oct 30 23:07:01 2018 +0400;Revert "remove liquibase"
Anton Romanov;Tue Oct 30 23:04:49 2018 +0400;Merge remote-tracking branch 'origin/4-show-time-line' into 4-show-time-line
Anton Romanov;Tue Oct 30 23:04:21 2018 +0400;Revert "remove liquibase"
Anton Romanov;Sat Oct 27 21:00:43 2018 +0000;Merge branch '11-Message-about-deadlines' into 'master'
Anton Romanov;Sat Oct 27 21:00:01 2018 +0000;Merge branch '12-' into 'master'
Alyona;Sun Oct 28 00:33:00 2018 +0400;fix
Alyona;Sun Oct 28 00:26:09 2018 +0400;fix
Alyona;Sun Oct 28 00:17:16 2018 +0400;fix
Alyona;Sun Oct 28 00:15:42 2018 +0400;fix
Alyona;Sat Oct 27 23:50:12 2018 +0400;fix
Alyona;Sat Oct 27 23:46:49 2018 +0400;fix
Anton Romanov;Sat Oct 27 23:25:27 2018 +0400;- make scheduler as a service - reformat code - fix cyrillic letter
Anton Romanov;Sat Oct 27 23:16:14 2018 +0400;add database column
Alyona;Sat Oct 27 23:11:07 2018 +0400;class for send messages about update paper
Alyona;Sat Oct 27 22:32:51 2018 +0400;add deadlineSсheduler
Alyona;Sat Oct 27 22:24:10 2018 +0400;add deadlineDate to models
Anton Romanov;Thu Oct 25 10:27:57 2018 +0400;some fix
Anton Romanov;Thu Oct 25 04:59:51 2018 +0000;Merge branch '8-' into 'master'
Alyona;Thu Oct 25 08:53:48 2018 +0400;finish deadline
Alyona;Thu Oct 25 08:53:29 2018 +0400;finish deadline
Alyona;Thu Oct 25 08:44:25 2018 +0400;Merge branch 'master' into 8-Deadline
Alyona;Thu Oct 25 08:41:37 2018 +0400;partially add deadline
Anton Romanov;Thu Oct 18 07:25:58 2018 +0000;Merge branch '7-dates-Matveeva' into 'master'
Anton Romanov;Thu Oct 18 11:21:26 2018 +0400;use html5 datetime pickers
Elena;Thu Oct 18 10:38:04 2018 +0400;Задача №7
Anton Romanov;Thu Oct 18 04:49:10 2018 +0000;Merge branch '6-authors-list-Matveeva' into 'master'
Anton Romanov;Thu Oct 11 19:49:16 2018 +0400;fix buttons size
Anton Romanov;Thu Oct 11 15:39:57 2018 +0400;fix styles
Anton Romanov;Thu Oct 11 10:03:44 2018 +0400;load paper statuses
Anton Romanov;Thu Oct 11 09:05:41 2018 +0400;fix progress background
Elena;Wed Oct 10 23:09:45 2018 +0400;Задача №6
Anton Romanov;Wed Oct 10 13:18:24 2018 +0000;Merge branch '5-' into 'master'
Anton Romanov;Wed Oct 10 17:05:54 2018 +0400;fix paper view
Elena;Wed Oct 10 15:30:47 2018 +0400;Задача №5 new
Elena;Wed Oct 10 10:09:07 2018 +0400;Merge branch 'master' into 5-Matveeva-Page
Elena;Thu Oct 4 10:39:27 2018 +0400;Задача №5
Anton Romanov;Tue Oct 2 07:46:40 2018 +0000;Merge branch '27-file-upload' into 'master'
Anton Romanov;Tue Oct 2 11:11:13 2018 +0400;Merge branch 'master' into 27-file-upload
Anton Romanov;Tue Oct 2 10:58:41 2018 +0400;add messages
Anton Romanov;Mon Oct 1 13:54:11 2018 +0400;add example for file uploading
Anton Romanov;Sat Sep 29 09:22:48 2018 +0400;minimize scripts
Anton Romanov;Thu Sep 27 21:32:16 2018 +0400;fix error pages
Anton Romanov;Thu Sep 27 16:01:02 2018 +0000;Merge branch 'refactor-ui' into 'master'
Anton Romanov;Thu Sep 27 12:11:25 2018 +0400;move pages
Anton Romanov;Thu Sep 27 10:35:22 2018 +0400;some refactor
Anton Romanov;Thu Sep 27 06:08:53 2018 +0000;Merge branch '3-ui' into 'master'
Anton Romanov;Thu Sep 27 10:03:00 2018 +0400;Merge branch 'master' into 3-ui
Anton Romanov;Thu Sep 27 10:02:49 2018 +0400;Merge branch 'master' into 3-ui
Alyona;Wed Sep 26 16:44:36 2018 +0400;Merge branch 'master' into 5-Page-of-paper
Alyona;Wed Sep 26 16:41:33 2018 +0400;Merge branch 'master' into 23-dashboard
Anton Romanov;Wed Sep 26 12:22:38 2018 +0000;Merge branch '23-dashboard' into 'master'
Alyona;Wed Sep 26 16:11:43 2018 +0400;Merge branch 'master' into 23-dashboard
Alyona;Wed Sep 26 16:11:19 2018 +0400;Merge branch 'master' into 23-dashboard
Alyona;Wed Sep 26 16:04:31 2018 +0400;add paper page
Anton Romanov;Wed Sep 26 11:55:20 2018 +0000;Merge branch '24-paper-page' into 'master'
Alyona;Tue Sep 25 17:13:01 2018 +0400;Alyona-Test
Elena;Tue Sep 25 16:45:01 2018 +0400;Тестовое задание
Anton Romanov;Sat Sep 22 06:56:33 2018 +0000;Update README.md
Anton Romanov;Sat Sep 8 10:19:21 2018 +0400;change ports
Anton Romanov;Sat Sep 8 10:07:21 2018 +0400;Merge remote-tracking branch 'origin/4-show-time-line' into 4-show-time-line
Anton Romanov;Sat Sep 8 09:54:14 2018 +0400;Merge branch 'master' into 4-show-time-line
Anton Romanov;Sat Sep 8 09:53:34 2018 +0400;path to timeline
Anton Romanov;Sat Sep 8 09:50:13 2018 +0400;fix papers font
Anton Romanov;Thu Sep 6 19:14:04 2018 +0000;Update README.md
Anton Romanov;Thu Sep 6 23:01:39 2018 +0400;add variable
Anton Romanov;Thu Sep 6 22:50:34 2018 +0400;deploy on vps
Anton Romanov;Wed Sep 5 21:58:04 2018 +0400;add timeline page
Anton Romanov;Wed Sep 5 14:50:49 2018 +0400;sort papers
Anton Romanov;Wed Sep 5 13:45:20 2018 +0400;fix paper colors
Anton Romanov;Wed Sep 5 13:31:51 2018 +0400;add method for create paper
Anton Romanov;Wed Sep 5 11:27:22 2018 +0400;get paper list
Anton Romanov;Sun Jun 10 13:43:40 2018 +0400;add timeline page
Anton Romanov;Sun Jun 10 01:53:32 2018 +0400;fix time
Anton Romanov;Sun Jun 10 01:49:38 2018 +0400;send notification
Anton Romanov;Sun Jun 10 01:12:28 2018 +0400;add event controller
Anton Romanov;Sat Jun 9 22:58:32 2018 +0400;remove liquibase
Anton Romanov;Sat Jun 9 22:41:00 2018 +0400;fix ports
Aleksey Filippov;Sun May 20 08:05:21 2018 +0200;delete orphaned files, migrate to webjars, some fixes and refactoring
Anton Romanov;Sat May 5 14:49:34 2018 +0400;add paper authors
Anton Romanov;Sat May 5 11:17:13 2018 +0400;add paper status
Anton Romanov;Sat May 5 11:14:37 2018 +0400;fix papers delete
Anton Romanov;Sat May 5 10:57:02 2018 +0400;fix papers crud
Anton Romanov;Sat May 5 00:39:18 2018 +0400;fix paper controller
Anton Romanov;Sat May 5 00:24:48 2018 +0400;add file uploading
Anton Romanov;Fri May 4 18:09:29 2018 +0400;add big logo
Anton Romanov;Fri May 4 18:04:09 2018 +0400;add paper controller
Anton Romanov;Fri May 4 17:54:46 2018 +0400;add ci
Anton Romanov;Fri May 4 17:23:22 2018 +0400;gitignore
Anton Romanov;Fri May 4 17:08:20 2018 +0400;add java code
Anton Romanov;Mon Apr 30 00:47:50 2018 +0400;add works
Anton Romanov;Sun Apr 29 20:48:05 2018 +0400;add paper page
Anton Romanov;Sun Apr 29 20:46:54 2018 +0400;add paper page
Anton Romanov;Sun Apr 29 20:44:47 2018 +0400;add paper page
Anton Romanov;Sun Apr 29 18:24:42 2018 +0400;add papers page
Anton Romanov;Sun Apr 29 17:09:58 2018 +0400;fix menu and sources
Anton Romanov;Sun Apr 29 00:49:37 2018 +0400;fix title page
Anton Romanov;Sat Apr 28 23:30:38 2018 +0400;fix title page
Anton Romanov;Sat Apr 28 22:50:26 2018 +0400;copy from landing

@ -0,0 +1,12 @@
<?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="20190318_000000-1">
<dropColumn columnName="file_id" tableName="paper"/>
<addColumn tableName="file">
<column name="paper_id" type="integer"/>
</addColumn>
</changeSet>
</databaseChangeLog>

@ -0,0 +1,10 @@
<?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="20190319_000001-1">
<addColumn tableName="paper">
<column name="url" type="varchar(255)"></column>
</addColumn>
</changeSet>
</databaseChangeLog>

@ -0,0 +1,14 @@
<?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="20190323_000000-1">
<addColumn tableName="paper">
<column name="latex_text" type="varchar"/>
</addColumn>
<addColumn tableName="file">
<column name="is_latex_attach" type="boolean"/>
</addColumn>
</changeSet>
</databaseChangeLog>

@ -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>

@ -0,0 +1,55 @@
<?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="nastya" id="20190331_000000-1">
<createTable tableName="tag">
<column name="id" type="integer">
<constraints nullable="false"/>
</column>
<column name="tagname" type="varchar(255)"/>
</createTable>
<addPrimaryKey columnNames="id" constraintName="pk_tag" tableName="tag"/>
</changeSet>
<changeSet author="nastya" id="20190331_000000-2">
<createTable tableName="task">
<column name="id" type="integer">
<constraints nullable="false"/>
</column>
<column name="user_id" type="integer"/>
<column name="title" type="varchar(255)"/>
<column name="description" type="varchar(255)"/>
<column name="status" type="varchar(255)"/>
<column name="deadline_date" type="timestamp"/>
<column name="create_date" type="timestamp"/>
<column name="update_date" type="timestamp"/>
</createTable>
<addPrimaryKey columnNames="id" constraintName="pk_task" tableName="task"/>
<addForeignKeyConstraint baseTableName="task" baseColumnNames="user_id"
constraintName="fk_user_task_id" referencedTableName="users"
referencedColumnNames="id"/>
</changeSet>
<changeSet author="nastya" id="20190331_000000-3">
<createTable tableName="task_tags">
<column name="task_id" type="integer"/>
<column name="tag_id" type="integer"/>
</createTable>
<addForeignKeyConstraint baseTableName="task_tags" baseColumnNames="task_id"
constraintName="fk_task_id" referencedTableName="task"
referencedColumnNames="id"/>
<addForeignKeyConstraint baseTableName="task_tags" baseColumnNames="tag_id"
constraintName="fk_tag_id" referencedTableName="tag"
referencedColumnNames="id"/>
</changeSet>
<changeSet author="nastya" id="20190331_000000-4">
<addColumn tableName="deadline">
<column name="task_id" type="integer"/>
</addColumn>
<addForeignKeyConstraint baseTableName="deadline" baseColumnNames="task_id"
constraintName="fk_deadlines_task" referencedTableName="task"
referencedColumnNames="id"/>
</changeSet>
</databaseChangeLog>

@ -0,0 +1,63 @@
<?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="vova" id="20190331_000010-1">
<createTable tableName="conference">
<column name="id" type="integer">
<constraints nullable="false"/>
</column>
<column name="title" type="varchar(300)"/>
<column name="description" type="varchar(500)"/>
<column name="url" type="varchar(255)"/>
<column name="ping" type="integer"/>
<column name="begin_date" type="timestamp"/>
<column name="end_date" type="timestamp"/>
</createTable>
<addPrimaryKey columnNames="id" constraintName="pk_conference" tableName="conference"/>
</changeSet>
<changeSet author="vova" id="20190331_000010-2">
<createTable tableName="paper_conference">
<column name="conference_id" type="integer"/>
<column name="paper_id" type="integer"/>
</createTable>
<addForeignKeyConstraint baseTableName="paper_conference" baseColumnNames="conference_id"
constraintName=" fk_paper_conference_conference" referencedTableName="conference"
referencedColumnNames="id"/>
<addForeignKeyConstraint baseTableName="paper_conference" baseColumnNames="paper_id"
constraintName="fk_paper_conference_paper" referencedTableName="paper"
referencedColumnNames="id"/>
</changeSet>
<changeSet author="vova" id="20190331_000010-3">
<createTable tableName="users_conference">
<column name="conference_id" type="integer"/>
<column name="users_id" type="integer"/>
<column name="participation" type="boolean"/>
<column name="deposit" type="varchar(255)"/>
</createTable>
<addForeignKeyConstraint baseTableName="users_conference" baseColumnNames="conference_id"
constraintName=" fk_users_conference_conference" referencedTableName="conference"
referencedColumnNames="id"/>
<addForeignKeyConstraint baseTableName="users_conference" baseColumnNames="users_id"
constraintName="fk_users_conference_users" referencedTableName="users"
referencedColumnNames="id"/>
</changeSet>
<changeSet author="vova" id="20190331_000010-4">
<addColumn tableName="deadline">
<column name="conference_id" type="integer"/>
</addColumn>
<addForeignKeyConstraint baseTableName="deadline" baseColumnNames="conference_id"
constraintName=" fk_deadlines_conference" referencedTableName="conference"
referencedColumnNames="id"/>
</changeSet>
<changeSet author="orion" id="20190331_000010-5">
<addColumn tableName="conference">
<column name="version" type="integer"/>
</addColumn>
</changeSet>
</databaseChangeLog>

@ -0,0 +1,26 @@
<?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="tanya" id="20190402_000000-1">
<addColumn tableName="grants">
<column name="leader_id" type="integer"></column>
</addColumn>
<addForeignKeyConstraint baseTableName="grants" baseColumnNames="leader_id"
constraintName="fk_grants_leader_id" referencedTableName="users"
referencedColumnNames="id"/>
</changeSet>
<changeSet author="tanya" id="20190402_000000-2">
<createTable tableName="grants_authors">
<column name="grant_id" type="integer"/>
<column name="authors_id" type="integer"/>
</createTable>
<addForeignKeyConstraint baseTableName="grants_authors" baseColumnNames="grant_id"
constraintName="fk_grants_grants_authors" referencedTableName="grants"
referencedColumnNames="id"/>
<addForeignKeyConstraint baseTableName="grants_authors" baseColumnNames="authors_id"
constraintName="fk_user_grants_authors" referencedTableName="users"
referencedColumnNames="id"/>
</changeSet>
</databaseChangeLog>

@ -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="tanya" id="20190404_000000-1">
<addColumn tableName="users">
<column name="birth_date" type="timestamp"></column>
</addColumn>
<addColumn tableName="users">
<column name="degree" type="varchar(255)"></column>
</addColumn>
</changeSet>
</databaseChangeLog>

@ -0,0 +1,17 @@
<?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="nastya" id="20190410_000000-1">
<addColumn tableName="tag">
<column name="version" type="integer"/>
</addColumn>
<renameColumn tableName="tag" oldColumnName="tagname" newColumnName="tag_name"/>
</changeSet>
<changeSet author="nastya" id="20190410_000000-2">
<addColumn tableName="task">
<column name="version" type="integer"/>
</addColumn>
</changeSet>
</databaseChangeLog>

@ -0,0 +1,14 @@
<?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="vova" id="20190417_000000-1">
<addColumn tableName="users_conference">
<column name="id" type="integer"></column>
<column name="version" type="integer"></column>
</addColumn>
<addPrimaryKey columnNames="id" constraintName="pk_users_conference" tableName="users_conference"/>
<modifyDataType tableName="users_conference" columnName="participation" newDataType="varchar(255)"/>
</changeSet>
</databaseChangeLog>

@ -0,0 +1,22 @@
<?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="anton" id="20190418_000000-1">
<addColumn tableName="project">
<column name="status" type="varchar(255)"/>
</addColumn>
<addColumn tableName="project">
<column name="description" type="varchar(255)"/>
</addColumn>
<addColumn tableName="project">
<column name="grant_id" type="integer"/>
</addColumn>
<addForeignKeyConstraint baseTableName="project" baseColumnNames="grant_id"
constraintName="fk_project_grant_id" referencedTableName="grants"
referencedColumnNames="id"/>
<addColumn tableName="project">
<column name="repository" type="varchar(255)"/>
</addColumn>
</changeSet>
</databaseChangeLog>

@ -0,0 +1,15 @@
<?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="20190421_000000-1">
<addColumn tableName="paper">
<column name="type" type="varchar(255)"/>
</addColumn>
</changeSet>
<changeSet author="masha" id="20190421_000000-2">
<update tableName="paper">
<column name="type" value="OTHER"/>
</update>
</changeSet>
</databaseChangeLog>

@ -0,0 +1,16 @@
<?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="anton" id="20190418_000000-1">
<addColumn tableName="project">
<column name="file_id" type="integer"/>
</addColumn>
<addForeignKeyConstraint baseTableName="project" baseColumnNames="file_id"
constraintName="fk_project_file_id" referencedTableName="file"
referencedColumnNames="id"/>
<addColumn tableName="project">
<column name="applicationFileName" type="varchar(255)"/>
</addColumn>
</changeSet>
</databaseChangeLog>

@ -18,4 +18,19 @@
<include file="db/changelog-20181111_000000-schema.xml"/>
<include file="db/changelog-20181208_000000-schema.xml"/>
<include file="db/changelog-20181224_000000-schema.xml"/>
<include file="db/changelog-20190318_000000-schema.xml"/>
<include file="db/changelog-20190318_000001-schema.xml"/>
<include file="db/changelog-20190327_000000-schema.xml"/>
<include file="db/changelog-20190331_000000-schema.xml"/>
<include file="db/changelog-20190331_000010-schema.xml"/>
<include file="db/changelog-20190410_000000-schema.xml"/>
<include file="db/changelog-20190417_000000-schema.xml"/>
<include file="db/changelog-20190418_000000-schema.xml"/>
<include file="db/changelog-20190323_000001-schema.xml"/>
<include file="db/common/changelog-20190312_130000-schema.xml"/>
<include file="db/changelog-20190402_000000-schema.xml"/>
<include file="db/changelog-20190404_000000-schema.xml"/>
<include file="db/changelog-20190421_000000-schema.xml"/>
<include file="db/changelog-20190422_000000-schema.xml"/>
<include file="db/common/changelog-20190423_100000-schema.xml"/>
</databaseChangeLog>

@ -0,0 +1,16 @@
<?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="orion" id="20190312_130000-1">
<addColumn tableName="users">
<column name="patronymic" type="varchar(255)"/>
</addColumn>
</changeSet>
<changeSet author="orion" id="20190312_130000-2">
<sql>
update users
set first_name = 'Антон', patronymic = 'Алексеевич', last_name = 'Романов' where id = 1;
</sql>
</changeSet>
</databaseChangeLog>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save