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

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

@ -1,6 +1,6 @@
buildscript { buildscript {
ext { ext {
versionSpringBoot = '1.5.10.RELEASE' versionSpringBoot = '2.1.3.RELEASE'
} }
repositories { repositories {
@ -30,6 +30,10 @@ bootRun.dependsOn checkstyleMain
sourceCompatibility = 1.8 sourceCompatibility = 1.8
targetCompatibility = 1.8 targetCompatibility = 1.8
bootRun {
systemProperties = System.properties
}
checkstyle { checkstyle {
project.ext.checkstyleVersion = '8.8' 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-jetty'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa' compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-thymeleaf' 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.module', name: 'jackson-module-afterburner'
compile group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-hibernate5' 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: '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.apache.commons', name: 'commons-lang3', version: '3.7'
compile group: 'org.webjars', name: 'bootstrap', version: '4.1.0' 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.npm', name: 'jquery.easing', version: '1.4.1'
compile group: 'org.webjars', name: 'font-awesome', version: '4.7.0' 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-swagger2', version: '2.6.0'
compile group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.5.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.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 --> <!-- Checks for imports -->
<!-- See http://checkstyle.sf.net/config_import.html --> <!-- See http://checkstyle.sf.net/config_import.html -->
<!--<module name="AvoidStarImport"/>--> <module name="AvoidStarImport"/>
<module name="IllegalImport"/> <!-- defaults to sun.* packages --> <module name="IllegalImport"/> <!-- defaults to sun.* packages -->
<module name="RedundantImport"/> <module name="RedundantImport"/>
<!--module name="UnusedImports"> <!--module name="UnusedImports">
@ -136,7 +136,7 @@
<module name="AvoidNestedBlocks"/> <module name="AvoidNestedBlocks"/>
<module name="EmptyBlock"/> <module name="EmptyBlock"/>
<module name="LeftCurly"/> <module name="LeftCurly"/>
<!--<module name="NeedBraces"/>--> <module name="NeedBraces"/>
<module name="RightCurly"/> <module name="RightCurly"/>
<!-- Checks for common coding problems --> <!-- Checks for common coding problems -->

@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists 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.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; 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 org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import ru.ulstu.configuration.ApplicationProperties;
import ru.ulstu.core.repository.JpaDetachableRepositoryImpl; import ru.ulstu.core.repository.JpaDetachableRepositoryImpl;
@SpringBootApplication @SpringBootApplication
@EnableJpaRepositories(repositoryBaseClass = JpaDetachableRepositoryImpl.class) @EnableJpaRepositories(repositoryBaseClass = JpaDetachableRepositoryImpl.class)
public class NgTrackerApplication { public class NgTrackerApplication {
private final ApplicationProperties applicationProperties;
public NgTrackerApplication(ApplicationProperties applicationProperties) {
this.applicationProperties = applicationProperties;
}
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(NgTrackerApplication.class, 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; package ru.ulstu.configuration;
import org.hibernate.validator.constraints.NotBlank;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.NotBlank;
@Component @Component
@ConfigurationProperties(prefix = "ng-tracker") @ConfigurationProperties(prefix = "ng-tracker")
@Validated @Validated
public class ApplicationProperties { public class ApplicationProperties {
@NotBlank @NotBlank
private String baseUrl; private String baseUrl;
@NotBlank @NotBlank
private String undeadUserLogin; private String undeadUserLogin;
private boolean devMode; private boolean devMode;
private boolean useHttps; private boolean useHttps;
private boolean checkRun;
public boolean isUseHttps() { public boolean isUseHttps() {
return useHttps; return useHttps;
} }
@ -48,4 +53,12 @@ public class ApplicationProperties {
public void setDevMode(boolean devMode) { public void setDevMode(boolean devMode) {
this.devMode = 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.eclipse.jetty.server.ServerConnector;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer; import org.springframework.boot.web.embedded.jetty.JettyServerCustomizer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer; import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory; import org.springframework.boot.web.server.ConfigurableWebServerFactory;
import org.springframework.boot.context.embedded.jetty.JettyServerCustomizer; import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@Configuration @Configuration
public class HttpListenerConfiguration implements EmbeddedServletContainerCustomizer { public class HttpListenerConfiguration implements WebServerFactoryCustomizer<ConfigurableWebServerFactory> {
@Value("${server.http.port}") @Value("${server.http.port}")
private int httpPort; private int httpPort;
private void configureJetty(JettyEmbeddedServletContainerFactory jettyFactory) { private void configureJetty(JettyServletWebServerFactory jettyFactory) {
jettyFactory.addServerCustomizers((JettyServerCustomizer) server -> { jettyFactory.addServerCustomizers((JettyServerCustomizer) server -> {
ServerConnector serverConnector = new ServerConnector(server); ServerConnector serverConnector = new ServerConnector(server);
serverConnector.setPort(httpPort); serverConnector.setPort(httpPort);
@ -22,9 +22,9 @@ public class HttpListenerConfiguration implements EmbeddedServletContainerCustom
} }
@Override @Override
public void customize(ConfigurableEmbeddedServletContainer container) { public void customize(ConfigurableWebServerFactory factory) {
if (container instanceof JettyEmbeddedServletContainerFactory) { if (factory instanceof JettyServletWebServerFactory) {
configureJetty((JettyEmbeddedServletContainerFactory) container); configureJetty((JettyServletWebServerFactory) factory);
} }
} }
} }

@ -3,8 +3,8 @@ package ru.ulstu.configuration;
import nz.net.ultraq.thymeleaf.LayoutDialect; import nz.net.ultraq.thymeleaf.LayoutDialect;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.thymeleaf.extras.springsecurity4.dialect.SpringSecurityDialect; import org.thymeleaf.extras.springsecurity5.dialect.SpringSecurityDialect;
import org.thymeleaf.spring4.SpringTemplateEngine; import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver; import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
import org.thymeleaf.templateresolver.ITemplateResolver; import org.thymeleaf.templateresolver.ITemplateResolver;
@ -17,7 +17,6 @@ public class MailTemplateConfiguration {
final SpringTemplateEngine templateEngine = new SpringTemplateEngine(); final SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.addTemplateResolver(templateResolver); templateEngine.addTemplateResolver(templateResolver);
templateEngine.addTemplateResolver(emailTemplateResolver()); templateEngine.addTemplateResolver(emailTemplateResolver());
templateEngine.addTemplateResolver(mvcTemplateResolver());
templateEngine.addDialect(new LayoutDialect()); templateEngine.addDialect(new LayoutDialect());
templateEngine.addDialect(sec); templateEngine.addDialect(sec);
return templateEngine; return templateEngine;
@ -25,22 +24,10 @@ public class MailTemplateConfiguration {
public ClassLoaderTemplateResolver emailTemplateResolver() { public ClassLoaderTemplateResolver emailTemplateResolver() {
ClassLoaderTemplateResolver emailTemplateResolver = new ClassLoaderTemplateResolver(); ClassLoaderTemplateResolver emailTemplateResolver = new ClassLoaderTemplateResolver();
emailTemplateResolver.setPrefix("mail_templates/"); emailTemplateResolver.setPrefix("/mail_templates/");
emailTemplateResolver.setTemplateMode("HTML5"); emailTemplateResolver.setTemplateMode("HTML");
emailTemplateResolver.setSuffix(".html"); emailTemplateResolver.setSuffix(".html");
emailTemplateResolver.setOrder(1);
emailTemplateResolver.setCharacterEncoding(StandardCharsets.UTF_8.name()); emailTemplateResolver.setCharacterEncoding(StandardCharsets.UTF_8.name());
return emailTemplateResolver; 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.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; 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 @Configuration
public class MvcConfiguration extends WebMvcConfigurerAdapter { public class MvcConfiguration implements WebMvcConfigurer {
@Override @Override
public void addViewControllers(ViewControllerRegistry registry) { public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/{articlename:\\w+}"); registry.addViewController("/{articlename:\\w+}");
//registry.addViewController("/admin/{articlename:\\w+}"); registry.addViewController("/admin/{articlename:\\w+}");
registry.addViewController("/papers/{articlename:\\w+}"); registry.addViewController("/papers/{articlename:\\w+}");
registry.addViewController("/grants/{articlename:\\w+}"); registry.addViewController("/grants/{articlename:\\w+}");
registry.addViewController("/conferences/{articlename:\\w+}");
registry.addViewController("/students/{articlename:\\w+}");
registry.addRedirectViewController("/", "/index"); registry.addRedirectViewController("/", "/index");
registry.addRedirectViewController("/default", "/index"); registry.addRedirectViewController("/default", "/index");
} }

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

@ -1,100 +1,110 @@
package ru.ulstu.core.controller; package ru.ulstu.core.controller;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.validation.FieldError; import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.ModelAttribute;
import ru.ulstu.core.error.EntityIdIsNullException; import ru.ulstu.core.error.EntityIdIsNullException;
import ru.ulstu.core.model.ErrorConstants; import ru.ulstu.core.model.ErrorConstants;
import ru.ulstu.core.model.response.Response; import ru.ulstu.core.model.response.Response;
import ru.ulstu.core.model.response.ResponseExtended; import ru.ulstu.core.model.response.ResponseExtended;
import ru.ulstu.user.error.UserActivationError; import ru.ulstu.user.error.UserActivationError;
import ru.ulstu.user.error.UserEmailExistsException; import ru.ulstu.user.error.UserEmailExistsException;
import ru.ulstu.user.error.UserIdExistsException; import ru.ulstu.user.error.UserIdExistsException;
import ru.ulstu.user.error.UserIsUndeadException; import ru.ulstu.user.error.UserIsUndeadException;
import ru.ulstu.user.error.UserLoginExistsException; import ru.ulstu.user.error.UserLoginExistsException;
import ru.ulstu.user.error.UserNotActivatedException; import ru.ulstu.user.error.UserNotActivatedException;
import ru.ulstu.user.error.UserNotFoundException; import ru.ulstu.user.error.UserNotFoundException;
import ru.ulstu.user.error.UserPasswordsNotValidOrNotMatchException; import ru.ulstu.user.error.UserPasswordsNotValidOrNotMatchException;
import ru.ulstu.user.error.UserResetKeyError; import ru.ulstu.user.error.UserResetKeyError;
import ru.ulstu.user.service.UserService;
import java.util.Set;
import java.util.stream.Collectors; import java.util.Set;
import java.util.stream.Collectors;
@RestController
@ControllerAdvice @ControllerAdvice
public class AdviceController { public class AdviceController {
private final Logger log = LoggerFactory.getLogger(AdviceController.class); private final Logger log = LoggerFactory.getLogger(AdviceController.class);
private final UserService userService;
private Response<Void> handleException(ErrorConstants error) {
log.warn(error.toString()); public AdviceController(UserService userService) {
return new Response<>(error); this.userService = userService;
} }
private <E> ResponseExtended<E> handleException(ErrorConstants error, E errorData) { @ModelAttribute("currentUser")
log.warn(error.toString()); public String getCurrentUser() {
return new ResponseExtended<>(error, errorData); return userService.getCurrentUser().getUserAbbreviate();
} }
@ExceptionHandler(EntityIdIsNullException.class) private Response<Void> handleException(ErrorConstants error) {
public Response<Void> handleEntityIdIsNullException(Throwable e) { log.warn(error.toString());
return handleException(ErrorConstants.ID_IS_NULL); return new Response<>(error);
} }
@ExceptionHandler(MethodArgumentNotValidException.class) private <E> ResponseExtended<E> handleException(ErrorConstants error, E errorData) {
public ResponseExtended<Set<String>> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { log.warn(error.toString());
final Set<String> errors = e.getBindingResult().getAllErrors().stream() return new ResponseExtended<>(error, errorData);
.filter(error -> error instanceof FieldError) }
.map(error -> ((FieldError) error).getField())
.collect(Collectors.toSet()); @ExceptionHandler(EntityIdIsNullException.class)
return handleException(ErrorConstants.VALIDATION_ERROR, errors); public Response<Void> handleEntityIdIsNullException(Throwable e) {
} return handleException(ErrorConstants.ID_IS_NULL);
}
@ExceptionHandler(UserIdExistsException.class)
public Response<Void> handleUserIdExistsException(Throwable e) { @ExceptionHandler(MethodArgumentNotValidException.class)
return handleException(ErrorConstants.USER_ID_EXISTS); public ResponseExtended<Set<String>> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
} final Set<String> errors = e.getBindingResult().getAllErrors().stream()
.filter(error -> error instanceof FieldError)
@ExceptionHandler(UserActivationError.class) .map(error -> ((FieldError) error).getField())
public ResponseExtended<String> handleUserActivationError(Throwable e) { .collect(Collectors.toSet());
return handleException(ErrorConstants.USER_ACTIVATION_ERROR, e.getMessage()); return handleException(ErrorConstants.VALIDATION_ERROR, errors);
} }
@ExceptionHandler(UserLoginExistsException.class) @ExceptionHandler(UserIdExistsException.class)
public ResponseExtended<String> handleUserLoginExistsException(Throwable e) { public Response<Void> handleUserIdExistsException(Throwable e) {
return handleException(ErrorConstants.USER_LOGIN_EXISTS, e.getMessage()); return handleException(ErrorConstants.USER_ID_EXISTS);
} }
@ExceptionHandler(UserEmailExistsException.class) @ExceptionHandler(UserActivationError.class)
public ResponseExtended<String> handleUserEmailExistsException(Throwable e) { public ResponseExtended<String> handleUserActivationError(Throwable e) {
return handleException(ErrorConstants.USER_EMAIL_EXISTS, e.getMessage()); return handleException(ErrorConstants.USER_ACTIVATION_ERROR, e.getMessage());
} }
@ExceptionHandler(UserPasswordsNotValidOrNotMatchException.class) @ExceptionHandler(UserLoginExistsException.class)
public Response<Void> handleUserPasswordsNotValidOrNotMatchException(Throwable e) { public ResponseExtended<String> handleUserLoginExistsException(Throwable e) {
return handleException(ErrorConstants.USER_PASSWORDS_NOT_VALID_OR_NOT_MATCH); return handleException(ErrorConstants.USER_LOGIN_EXISTS, e.getMessage());
} }
@ExceptionHandler(UserNotFoundException.class) @ExceptionHandler(UserEmailExistsException.class)
public ResponseExtended<String> handleUserNotFoundException(Throwable e) { public ResponseExtended<String> handleUserEmailExistsException(Throwable e) {
return handleException(ErrorConstants.USER_NOT_FOUND, e.getMessage()); return handleException(ErrorConstants.USER_EMAIL_EXISTS, e.getMessage());
} }
@ExceptionHandler(UserNotActivatedException.class) @ExceptionHandler(UserPasswordsNotValidOrNotMatchException.class)
public Response<Void> handleUserNotActivatedException(Throwable e) { public Response<Void> handleUserPasswordsNotValidOrNotMatchException(Throwable e) {
return handleException(ErrorConstants.USER_NOT_ACTIVATED); return handleException(ErrorConstants.USER_PASSWORDS_NOT_VALID_OR_NOT_MATCH);
} }
@ExceptionHandler(UserResetKeyError.class) @ExceptionHandler(UserNotFoundException.class)
public ResponseExtended<String> handleUserResetKeyError(Throwable e) { public ResponseExtended<String> handleUserNotFoundException(Throwable e) {
return handleException(ErrorConstants.USER_RESET_ERROR, e.getMessage()); return handleException(ErrorConstants.USER_NOT_FOUND, e.getMessage());
} }
@ExceptionHandler(UserIsUndeadException.class) @ExceptionHandler(UserNotActivatedException.class)
public ResponseExtended<String> handleUserIsUndeadException(Throwable e) { public Response<Void> handleUserNotActivatedException(Throwable e) {
return handleException(ErrorConstants.USER_UNDEAD_ERROR, e.getMessage()); 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; import java.io.Serializable;
public class OffsetablePageRequest implements Pageable, Serializable { public class OffsetablePageRequest implements Pageable, Serializable {
private final int offset; private final long offset;
private final int count; private final int count;
private final Sort sort; private final Sort sort;
public OffsetablePageRequest(int offset, int count) { public OffsetablePageRequest(long offset, int count) {
this(offset, count, null); 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)); 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) { if (offset < 0) {
throw new IllegalArgumentException("Offset value must not be less than zero!"); throw new IllegalArgumentException("Offset value must not be less than zero!");
} }
@ -42,11 +42,11 @@ public class OffsetablePageRequest implements Pageable, Serializable {
@Override @Override
public int getPageNumber() { public int getPageNumber() {
return offset / count; return (int) (offset / count);
} }
@Override @Override
public int getOffset() { public long getOffset() {
return offset; return offset;
} }
@ -89,9 +89,9 @@ public class OffsetablePageRequest implements Pageable, Serializable {
@Override @Override
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
int result = 1; long result = 1;
result = prime * result + offset; result = prime * result + offset;
result = prime * result + count; result = prime * result + count;
return result; return (int) result;
} }
} }

@ -1,6 +1,10 @@
package ru.ulstu.core.model; 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; import java.io.Serializable;
@MappedSuperclass @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; 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.Arrays;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
@ -24,7 +29,7 @@ public class DateUtils {
return cal; return cal;
} }
public static List<Month> getMonths () { public static List<Month> getMonths() {
return Arrays.asList(Month.values()); return Arrays.asList(Month.values());
} }

@ -1,5 +1,8 @@
package ru.ulstu.deadline.model; 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 ru.ulstu.core.model.BaseEntity;
import javax.persistence.Entity; import javax.persistence.Entity;
@ -13,6 +16,7 @@ public class Deadline extends BaseEntity {
private String description; private String description;
@Temporal(value = TemporalType.TIMESTAMP) @Temporal(value = TemporalType.TIMESTAMP)
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date date; private Date date;
public Deadline() { public Deadline() {
@ -23,6 +27,15 @@ public class Deadline extends BaseEntity {
this.description = description; 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() { public String getDescription() {
return description; 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.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import ru.ulstu.deadline.model.Deadline; import ru.ulstu.deadline.model.Deadline;
import ru.ulstu.deadline.model.DeadlineDto;
import ru.ulstu.deadline.repository.DeadlineRepository; import ru.ulstu.deadline.repository.DeadlineRepository;
import java.util.List; import java.util.List;
@ -17,29 +16,34 @@ public class DeadlineService {
this.deadlineRepository = deadlineRepository; this.deadlineRepository = deadlineRepository;
} }
public List<Deadline> saveOrCreate(List<DeadlineDto> deadlines) { public List<Deadline> saveOrCreate(List<Deadline> deadlines) {
return deadlines.stream().map(deadlineDto -> { return deadlines
return deadlineDto.getId() != null ? update(deadlineDto) : create(deadlineDto); .stream()
}).collect(Collectors.toList()); .map(deadline -> {
return deadline.getId() != null ? update(deadline) : create(deadline);
}).collect(Collectors.toList());
} }
@Transactional @Transactional
public Deadline update(DeadlineDto deadlineDto) { public Deadline update(Deadline deadline) {
Deadline deadline = deadlineRepository.findOne(deadlineDto.getId()); Deadline updateDeadline = deadlineRepository.getOne(deadline.getId());
deadlineRepository.save(copyFromDto(deadline, deadlineDto)); updateDeadline.setDate(deadline.getDate());
return deadline; updateDeadline.setDescription(deadline.getDescription());
deadlineRepository.save(updateDeadline);
return updateDeadline;
} }
@Transactional @Transactional
public Deadline create(DeadlineDto deadlineDto) { public Deadline create(Deadline deadline) {
Deadline newDeadline = copyFromDto(new Deadline(), deadlineDto); Deadline newDeadline = new Deadline();
newDeadline.setDate(deadline.getDate());
newDeadline.setDescription(deadline.getDescription());
newDeadline = deadlineRepository.save(newDeadline); newDeadline = deadlineRepository.save(newDeadline);
return newDeadline; return newDeadline;
} }
private Deadline copyFromDto(Deadline deadline, DeadlineDto deadlineDto) { @Transactional
deadline.setDate(deadlineDto.getDate()); public void remove(Integer deadlineId) {
deadline.setDescription(deadlineDto.getDescription()); deadlineRepository.deleteById(deadlineId);
return deadline;
} }
} }

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

@ -19,6 +19,9 @@ public class FileData extends BaseEntity {
private byte[] data; private byte[] data;
@Column(name = "is_latex_attach")
private Boolean isLatexAttach;
public String getName() { public String getName() {
return name; return name;
} }
@ -50,4 +53,12 @@ public class FileData extends BaseEntity {
public void setData(byte[] data) { public void setData(byte[] data) {
this.data = 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; package ru.ulstu.file.service;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import ru.ulstu.file.model.FileData; import ru.ulstu.file.model.FileData;
import ru.ulstu.file.model.FileDataDto;
import ru.ulstu.file.repostory.FileRepository; 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.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Date; 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; import static java.nio.charset.StandardCharsets.UTF_8;
@ -29,13 +38,13 @@ public class FileService {
public FileData createFileFromTmp(String tmpFileName) throws IOException { public FileData createFileFromTmp(String tmpFileName) throws IOException {
FileData fileData = new FileData(); FileData fileData = new FileData();
fileData.setData(getTmpFile(tmpFileName)); fileData.setData(getTmpFile(tmpFileName));
fileData.setName(getTmpFileName(tmpFileName)); fileData.setSize(getTmpFileSize(tmpFileName));
fileData.setCreateDate(new Date()); fileData.setCreateDate(new Date());
return fileRepository.save(fileData); return fileRepository.save(fileData);
} }
public String uploadToTmpDir(MultipartFile multipartFile) throws IOException { 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()); Files.write(getTmpFilePath(tmpFileName), multipartFile.getBytes());
String meta = multipartFile.getOriginalFilename() + "\n" + multipartFile.getSize(); String meta = multipartFile.getOriginalFilename() + "\n" + multipartFile.getSize();
Files.write(getTmpFileMetaPath(tmpFileName), meta.getBytes(UTF_8)); Files.write(getTmpFileMetaPath(tmpFileName), meta.getBytes(UTF_8));
@ -60,7 +69,7 @@ public class FileService {
} }
public FileData getFile(Integer fileId) { public FileData getFile(Integer fileId) {
return fileRepository.findOne(fileId); return fileRepository.getOne(fileId);
} }
public void deleteTmpFile(String tmpFileName) throws IOException { public void deleteTmpFile(String tmpFileName) throws IOException {
@ -78,4 +87,63 @@ public class FileService {
public void deleteFile(FileData fileData) { public void deleteFile(FileData fileData) {
fileRepository.delete(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.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; 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.Grant;
import ru.ulstu.grant.model.GrantDto; import ru.ulstu.grant.model.GrantDto;
import ru.ulstu.grant.service.GrantService; import ru.ulstu.grant.service.GrantService;
import ru.ulstu.user.model.User;
import springfox.documentation.annotations.ApiIgnore;
import javax.validation.Valid; import javax.validation.Valid;
import java.io.IOException; import java.io.IOException;
@ -20,10 +22,14 @@ import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.springframework.util.StringUtils.isEmpty; 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() @Controller()
@RequestMapping(value = "/grants") @RequestMapping(value = "/grants")
@ApiIgnore
public class GrantController { public class GrantController {
private final GrantService grantService; private final GrantService grantService;
@ -51,41 +57,50 @@ public class GrantController {
} }
@PostMapping(value = "/grant", params = "save") @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); filterEmptyDeadlines(grantDto);
if (grantDto.getDeadlines().isEmpty()) { if (grantDto.getDeadlines().isEmpty()) {
errors.rejectValue("deadlines", "errorCode", "Не может быть пустым"); errors.rejectValue("deadlines", "errorCode", "Не может быть пусто");
}
if (grantDto.getLeaderId().equals(-1)) {
errors.rejectValue("leaderId", "errorCode", "Укажите руководителя");
} }
if (errors.hasErrors()) { if (errors.hasErrors()) {
return "/grants/grant"; return GRANT_PAGE;
} }
grantService.save(grantDto); 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") @PostMapping(value = "/grant", params = "addDeadline")
public String addDeadline(@Valid GrantDto grantDto, Errors errors) { public String addDeadline(@Valid GrantDto grantDto, Errors errors) {
filterEmptyDeadlines(grantDto); filterEmptyDeadlines(grantDto);
if (errors.hasErrors()) { if (errors.hasErrors()) {
return "/grants/grant"; return GRANT_PAGE;
} }
grantDto.getDeadlines().add(new DeadlineDto()); grantDto.getDeadlines().add(new Deadline());
return "/grants/grant"; return GRANT_PAGE;
} }
@PostMapping(value = "/grant", params = "createProject") @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()) { if (errors.hasErrors()) {
return "/grants/grant"; return GRANT_PAGE;
} }
grantService.createProject(grantDto); grantService.createProject(grantDto);
return "/grants/grant"; return GRANT_PAGE;
} }
@GetMapping("/delete/{grant-id}") @GetMapping("/delete/{grant-id}")
public String delete(@PathVariable("grant-id") Integer grantId) throws IOException { public String delete(@PathVariable("grant-id") Integer grantId) throws IOException {
grantService.delete(grantId); grantService.delete(grantId);
return "redirect:/grants/grants"; return String.format(REDIRECT_TO, GRANTS_PAGE);
} }
@ModelAttribute("allStatuses") @ModelAttribute("allStatuses")
@ -93,6 +108,11 @@ public class GrantController {
return grantService.getGrantStatuses(); return grantService.getGrantStatuses();
} }
@ModelAttribute("allAuthors")
public List<User> getAllAuthors(GrantDto grantDto) {
return grantService.getGrantAuthors(grantDto);
}
private void filterEmptyDeadlines(GrantDto grantDto) { private void filterEmptyDeadlines(GrantDto grantDto) {
grantDto.setDeadlines(grantDto.getDeadlines().stream() grantDto.setDeadlines(grantDto.getDeadlines().stream()
.filter(dto -> dto.getDate() != null || !isEmpty(dto.getDescription())) .filter(dto -> dto.getDate() != null || !isEmpty(dto.getDescription()))

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

@ -2,36 +2,54 @@ package ru.ulstu.grant.model;
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import org.hibernate.validator.constraints.NotEmpty; import org.apache.commons.lang3.StringUtils;
import ru.ulstu.deadline.model.DeadlineDto; import ru.ulstu.deadline.model.Deadline;
import ru.ulstu.project.model.ProjectDto; import ru.ulstu.project.model.ProjectDto;
import ru.ulstu.user.model.UserDto;
import javax.validation.constraints.NotEmpty;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import static ru.ulstu.core.util.StreamApiUtils.convert; import static ru.ulstu.core.util.StreamApiUtils.convert;
public class GrantDto { public class GrantDto {
private final static int MAX_AUTHORS_LENGTH = 60;
private Integer id; private Integer id;
@NotEmpty @NotEmpty
private String title; private String title;
private Grant.GrantStatus status; private Grant.GrantStatus status;
private List<DeadlineDto> deadlines = new ArrayList<>(); private List<Deadline> deadlines = new ArrayList<>();
private String comment; private String comment;
private String applicationFileName; private String applicationFileName;
private ProjectDto project; 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() { public GrantDto() {
deadlines.add(new DeadlineDto()); deadlines.add(new Deadline());
} }
@JsonCreator @JsonCreator
public GrantDto(@JsonProperty("id") Integer id, public GrantDto(@JsonProperty("id") Integer id,
@JsonProperty("title") String title, @JsonProperty("title") String title,
@JsonProperty("status") Grant.GrantStatus status, @JsonProperty("status") Grant.GrantStatus status,
@JsonProperty("deadlines") List<DeadlineDto> deadlines, @JsonProperty("deadlines") List<Deadline> deadlines,
@JsonProperty("comment") String comment, @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.id = id;
this.title = title; this.title = title;
this.status = status; this.status = status;
@ -39,16 +57,27 @@ public class GrantDto {
this.comment = comment; this.comment = comment;
this.applicationFileName = null; this.applicationFileName = null;
this.project = project; this.project = project;
this.authors = authors;
this.leaderId = leaderId;
this.wasLeader = wasLeader;
this.hasAge = hasAge;
this.hasDegree = hasDegree;
} }
public GrantDto(Grant grant) { public GrantDto(Grant grant) {
this.id = grant.getId(); this.id = grant.getId();
this.title = grant.getTitle(); this.title = grant.getTitle();
this.status = grant.getStatus(); this.status = grant.getStatus();
this.deadlines = convert(grant.getDeadlines(), DeadlineDto::new); this.deadlines = grant.getDeadlines();
this.comment = grant.getComment(); this.comment = grant.getComment();
this.project = grant.getProject() == null ? null : new ProjectDto(grant.getProject()); this.project = grant.getProject() == null ? null : new ProjectDto(grant.getProject());
this.applicationFileName = grant.getApplication() == null ? null : grant.getApplication().getName(); 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() { public Integer getId() {
@ -75,11 +104,11 @@ public class GrantDto {
this.status = status; this.status = status;
} }
public List<DeadlineDto> getDeadlines() { public List<Deadline> getDeadlines() {
return deadlines; return deadlines;
} }
public void setDeadlines(List<DeadlineDto> deadlines) { public void setDeadlines(List<Deadline> deadlines) {
this.deadlines = deadlines; this.deadlines = deadlines;
} }
@ -106,4 +135,59 @@ public class GrantDto {
public void setApplicationFileName(String applicationFileName) { public void setApplicationFileName(String applicationFileName) {
this.applicationFileName = 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 org.springframework.data.jpa.repository.JpaRepository;
import ru.ulstu.grant.model.Grant; import ru.ulstu.grant.model.Grant;
import java.util.List;
public interface GrantRepository extends JpaRepository<Grant, Integer> { 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.Project;
import ru.ulstu.project.model.ProjectDto; import ru.ulstu.project.model.ProjectDto;
import ru.ulstu.project.service.ProjectService; import ru.ulstu.project.service.ProjectService;
import ru.ulstu.user.model.User;
import ru.ulstu.user.service.UserService;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import static org.springframework.util.ObjectUtils.isEmpty; import static org.springframework.util.ObjectUtils.isEmpty;
import static ru.ulstu.core.util.StreamApiUtils.convert; import static ru.ulstu.core.util.StreamApiUtils.convert;
@ -30,15 +33,18 @@ public class GrantService {
private final ProjectService projectService; private final ProjectService projectService;
private final DeadlineService deadlineService; private final DeadlineService deadlineService;
private final FileService fileService; private final FileService fileService;
private final UserService userService;
public GrantService(GrantRepository grantRepository, public GrantService(GrantRepository grantRepository,
FileService fileService, FileService fileService,
DeadlineService deadlineService, DeadlineService deadlineService,
ProjectService projectService) { ProjectService projectService,
UserService userService) {
this.grantRepository = grantRepository; this.grantRepository = grantRepository;
this.projectService = projectService;
this.fileService = fileService; this.fileService = fileService;
this.deadlineService = deadlineService; this.deadlineService = deadlineService;
this.projectService = projectService;
this.userService = userService;
} }
public List<Grant> findAll() { public List<Grant> findAll() {
@ -52,7 +58,7 @@ public class GrantService {
} }
public GrantDto findOneDto(Integer id) { public GrantDto findOneDto(Integer id) {
return new GrantDto(grantRepository.findOne(id)); return new GrantDto(grantRepository.getOne(id));
} }
@Transactional @Transactional
@ -73,17 +79,24 @@ public class GrantService {
if (grantDto.getApplicationFileName() != null) { if (grantDto.getApplicationFileName() != null) {
grant.setApplication(fileService.createFileFromTmp(grantDto.getApplicationFileName())); 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; return grant;
} }
public void createProject(GrantDto grantDto) { public void createProject(GrantDto grantDto) throws IOException {
grantDto.setProject( grantDto.setProject(
new ProjectDto(projectService.save(new ProjectDto(grantDto.getTitle())))); new ProjectDto(projectService.save(new ProjectDto(grantDto.getTitle()))));
} }
@Transactional @Transactional
public Integer update(GrantDto grantDto) throws IOException { public Integer update(GrantDto grantDto) throws IOException {
Grant grant = grantRepository.findOne(grantDto.getId()); Grant grant = grantRepository.getOne(grantDto.getId());
Grant.GrantStatus oldStatus = grant.getStatus(); Grant.GrantStatus oldStatus = grant.getStatus();
if (grantDto.getApplicationFileName() != null && grant.getApplication() != null) { if (grantDto.getApplicationFileName() != null && grant.getApplication() != null) {
fileService.deleteFile(grant.getApplication()); fileService.deleteFile(grant.getApplication());
@ -94,11 +107,10 @@ public class GrantService {
@Transactional @Transactional
public void delete(Integer grantId) throws IOException { public void delete(Integer grantId) throws IOException {
Grant grant = grantRepository.findOne(grantId); Grant grant = grantRepository.getOne(grantId);
if (grant.getApplication() != null) { if (grant.getApplication() != null) {
fileService.deleteFile(grant.getApplication()); fileService.deleteFile(grant.getApplication());
} }
//возможно при удалении гранта будет удаляться и проект, к нему привязанный
grantRepository.delete(grant); grantRepository.delete(grant);
} }
@ -107,13 +119,15 @@ public class GrantService {
} }
@Transactional @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 grant = new Grant();
grant.setTitle(title); grant.setTitle(title);
grant.setComment("Комментарий к гранту 1"); grant.setComment("Комментарий к гранту 1");
grant.setProject(projectId); grant.setProject(projectId);
grant.setStatus(APPLICATION); grant.setStatus(APPLICATION);
grant.getDeadlines().add(new Deadline(deadlineDate, "первый дедлайн")); grant.getDeadlines().add(new Deadline(deadlineDate, "первый дедлайн"));
grant.getAuthors().add(user);
grant.setLeader(user);
grant = grantRepository.save(grant); grant = grantRepository.save(grant);
return grant; return grant;
} }
@ -125,4 +139,22 @@ public class GrantService {
update(grantDto); 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; package ru.ulstu.odin.model;
import com.fasterxml.jackson.annotation.JsonProperty; 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.core.error.OdinException;
import ru.ulstu.odin.model.annotation.OdinCaption; import ru.ulstu.odin.model.annotation.OdinCaption;
import ru.ulstu.odin.model.annotation.OdinReadOnly; import ru.ulstu.odin.model.annotation.OdinReadOnly;
import ru.ulstu.odin.model.annotation.OdinVisible; import ru.ulstu.odin.model.annotation.OdinVisible;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.lang.reflect.Field; import java.lang.reflect.Field;
@ -31,14 +31,13 @@ public abstract class OdinField implements Comparable {
return this.name().toLowerCase(); return this.name().toLowerCase();
} }
} }
private Field field;
protected final OdinFieldType fieldType; protected final OdinFieldType fieldType;
protected final String fieldName; protected final String fieldName;
protected final String caption; protected final String caption;
protected final OdinVisible.OdinVisibleType visible; protected final OdinVisible.OdinVisibleType visible;
protected final boolean readOnly; protected final boolean readOnly;
protected final boolean notEmpty; protected final boolean notEmpty;
private Field field;
public OdinField(Field field, OdinFieldType fieldType) { public OdinField(Field field, OdinFieldType fieldType) {
this.field = field; this.field = field;
@ -126,8 +125,12 @@ public abstract class OdinField implements Comparable {
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) return true; if (this == o) {
if (o == null || getClass() != o.getClass()) return false; return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
OdinField odinField = (OdinField) o; OdinField odinField = (OdinField) o;
return Objects.equals(fieldName, odinField.fieldName); return Objects.equals(fieldName, odinField.fieldName);
} }

@ -1,9 +1,9 @@
package ru.ulstu.odin.model; 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;
import ru.ulstu.odin.model.annotation.OdinString.OdinStringType; import ru.ulstu.odin.model.annotation.OdinString.OdinStringType;
import javax.validation.constraints.Email;
import javax.validation.constraints.Size; import javax.validation.constraints.Size;
import java.lang.reflect.Field; import java.lang.reflect.Field;

@ -1,5 +1,8 @@
package ru.ulstu.paper.controller; 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.stereotype.Controller;
import org.springframework.ui.ModelMap; import org.springframework.ui.ModelMap;
import org.springframework.validation.Errors; 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.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; 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.Paper;
import ru.ulstu.paper.model.PaperDto; import ru.ulstu.paper.model.PaperDto;
import ru.ulstu.paper.model.PaperFilterDto; import ru.ulstu.paper.model.PaperFilterDto;
import ru.ulstu.paper.service.LatexService;
import ru.ulstu.paper.service.PaperService; import ru.ulstu.paper.service.PaperService;
import ru.ulstu.user.model.User; import ru.ulstu.user.model.User;
import springfox.documentation.annotations.ApiIgnore;
import javax.validation.Valid; import javax.validation.Valid;
import java.io.IOException; import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.springframework.util.StringUtils.isEmpty; import static org.springframework.util.StringUtils.isEmpty;
@Controller() @Controller()
@RequestMapping(value = "/papers") @RequestMapping(value = "/papers")
@ApiIgnore
public class PaperController { public class PaperController {
private final PaperService paperService; private final PaperService paperService;
private final LatexService latexService;
public PaperController(PaperService paperService) { public PaperController(PaperService paperService, LatexService latexService) {
this.paperService = paperService; this.paperService = paperService;
this.latexService = latexService;
} }
@GetMapping("/papers") @GetMapping("/papers")
@ -49,7 +59,7 @@ public class PaperController {
@GetMapping("/dashboard") @GetMapping("/dashboard")
public void getDashboard(ModelMap modelMap) { public void getDashboard(ModelMap modelMap) {
modelMap.put("papers", paperService.findAllActive()); modelMap.put("papers", paperService.findAllActiveDto());
} }
@GetMapping("/paper") @GetMapping("/paper")
@ -80,7 +90,7 @@ public class PaperController {
if (errors.hasErrors()) { if (errors.hasErrors()) {
return "/papers/paper"; return "/papers/paper";
} }
paperDto.getDeadlines().add(new DeadlineDto()); paperDto.getDeadlines().add(new Deadline());
return "/papers/paper"; return "/papers/paper";
} }
@ -95,6 +105,11 @@ public class PaperController {
return paperService.getPaperStatuses(); return paperService.getPaperStatuses();
} }
@ModelAttribute("allTypes")
public List<Paper.PaperType> getPaperTypes() {
return paperService.getPaperTypes();
}
@ModelAttribute("allAuthors") @ModelAttribute("allAuthors")
public List<User> getAllAuthors() { public List<User> getAllAuthors() {
return paperService.getPaperAuthors(); return paperService.getPaperAuthors();
@ -109,6 +124,14 @@ public class PaperController {
return years; 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) { private void filterEmptyDeadlines(PaperDto paperDto) {
paperDto.setDeadlines(paperDto.getDeadlines().stream() paperDto.setDeadlines(paperDto.getDeadlines().stream()
.filter(dto -> dto.getDate() != null || !isEmpty(dto.getDescription())) .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 { public Response<List<PaperDto>> filter(@RequestBody @Valid PaperFilterDto paperFilterDto) throws IOException {
return new Response<>(paperService.filter(paperFilterDto)); 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.Fetch;
import org.hibernate.annotations.FetchMode; import org.hibernate.annotations.FetchMode;
import org.hibernate.validator.constraints.NotBlank;
import ru.ulstu.core.model.BaseEntity; import ru.ulstu.core.model.BaseEntity;
import ru.ulstu.core.model.UserContainer; import ru.ulstu.core.model.UserContainer;
import ru.ulstu.deadline.model.Deadline; import ru.ulstu.deadline.model.Deadline;
import ru.ulstu.file.model.FileData; import ru.ulstu.file.model.FileData;
import ru.ulstu.timeline.model.Event;
import ru.ulstu.user.model.User; import ru.ulstu.user.model.User;
import javax.persistence.CascadeType; import javax.persistence.CascadeType;
@ -17,11 +17,11 @@ import javax.persistence.Enumerated;
import javax.persistence.FetchType; import javax.persistence.FetchType;
import javax.persistence.JoinColumn; import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany; import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany; import javax.persistence.OneToMany;
import javax.persistence.OrderBy; import javax.persistence.OrderBy;
import javax.persistence.Temporal; import javax.persistence.Temporal;
import javax.persistence.TemporalType; import javax.persistence.TemporalType;
import javax.validation.constraints.NotBlank;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Comparator; import java.util.Comparator;
import java.util.Date; 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 @NotBlank
private String title; private String title;
@Enumerated(value = EnumType.STRING) @Enumerated(value = EnumType.STRING)
private PaperStatus status = PaperStatus.DRAFT; private PaperStatus status = PaperStatus.DRAFT;
@Enumerated(value = EnumType.STRING)
private PaperType type = PaperType.OTHER;
@Column(name = "create_date") @Column(name = "create_date")
@Temporal(TemporalType.TIMESTAMP) @Temporal(TemporalType.TIMESTAMP)
private Date createDate = new Date(); private Date createDate = new Date();
@ -75,15 +95,25 @@ public class Paper extends BaseEntity implements UserContainer {
private String comment; private String comment;
private String url;
private Boolean locked = false; private Boolean locked = false;
@ManyToOne @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "file_id") @JoinColumn(name = "paper_id")
private FileData fileData; 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) @ManyToMany(fetch = FetchType.EAGER)
private Set<User> authors = new HashSet<>(); private Set<User> authors = new HashSet<>();
@Column(name = "latex_text")
private String latexText;
public PaperStatus getStatus() { public PaperStatus getStatus() {
return status; return status;
} }
@ -92,6 +122,14 @@ public class Paper extends BaseEntity implements UserContainer {
this.status = status; this.status = status;
} }
public PaperType getType() {
return type;
}
public void setType(PaperType type) {
this.type = type;
}
public Date getCreateDate() { public Date getCreateDate() {
return createDate; return createDate;
} }
@ -132,12 +170,12 @@ public class Paper extends BaseEntity implements UserContainer {
this.locked = locked; this.locked = locked;
} }
public FileData getFileData() { public List<FileData> getFiles() {
return fileData; return files;
} }
public void setFileData(FileData fileData) { public void setFiles(List<FileData> files) {
this.fileData = fileData; this.files = files;
} }
public String getTitle() { public String getTitle() {
@ -156,6 +194,30 @@ public class Paper extends BaseEntity implements UserContainer {
this.authors = authors; this.authors = authors;
} }
public List<Event> getEvents() {
return events;
}
public void setEvents(List<Event> events) {
this.events = events;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getLatexText() {
return latexText;
}
public void setLatexText(String latexText) {
this.latexText = latexText;
}
@Override @Override
public Set<User> getUsers() { public Set<User> getUsers() {
return getAuthors(); return getAuthors();

@ -3,10 +3,11 @@ package ru.ulstu.paper.model;
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.hibernate.validator.constraints.NotEmpty; import ru.ulstu.deadline.model.Deadline;
import ru.ulstu.deadline.model.DeadlineDto; import ru.ulstu.file.model.FileDataDto;
import ru.ulstu.user.model.UserDto; import ru.ulstu.user.model.UserDto;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size; import javax.validation.constraints.Size;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
@ -24,48 +25,51 @@ public class PaperDto {
@Size(min = 3, max = 254) @Size(min = 3, max = 254)
private String title; private String title;
private Paper.PaperStatus status; private Paper.PaperStatus status;
private Paper.PaperType type;
private Date createDate; private Date createDate;
private Date updateDate; private Date updateDate;
@NotEmpty @NotEmpty
private List<DeadlineDto> deadlines = new ArrayList<>(); private List<Deadline> deadlines = new ArrayList<>();
private String comment; private String comment;
private String url;
private Boolean locked; private Boolean locked;
private String tmpFileName; private List<FileDataDto> files = new ArrayList<>();
private Integer fileId;
private String fileName;
private Date fileCreateDate;
private Set<Integer> authorIds; private Set<Integer> authorIds;
private Set<UserDto> authors; private Set<UserDto> authors;
private Integer filterAuthorId; private Integer filterAuthorId;
private String latexText;
public PaperDto() { public PaperDto() {
deadlines.add(new DeadlineDto()); deadlines.add(new Deadline());
} }
@JsonCreator @JsonCreator
public PaperDto(@JsonProperty("id") Integer id, public PaperDto(@JsonProperty("id") Integer id,
@JsonProperty("title") String title, @JsonProperty("title") String title,
@JsonProperty("status") Paper.PaperStatus status, @JsonProperty("status") Paper.PaperStatus status,
@JsonProperty("type") Paper.PaperType type,
@JsonProperty("createDate") Date createDate, @JsonProperty("createDate") Date createDate,
@JsonProperty("updateDate") Date updateDate, @JsonProperty("updateDate") Date updateDate,
@JsonProperty("deadlines") List<DeadlineDto> deadlines, @JsonProperty("deadlines") List<Deadline> deadlines,
@JsonProperty("comment") String comment, @JsonProperty("comment") String comment,
@JsonProperty("latex_text") String latexText,
@JsonProperty("url") String url,
@JsonProperty("locked") Boolean locked, @JsonProperty("locked") Boolean locked,
@JsonProperty("tmpFileName") String tmpFileName, @JsonProperty("files") List<FileDataDto> files,
@JsonProperty("authorIds") Set<Integer> authorIds, @JsonProperty("authorIds") Set<Integer> authorIds,
@JsonProperty("authors") Set<UserDto> authors) { @JsonProperty("authors") Set<UserDto> authors) {
this.id = id; this.id = id;
this.title = title; this.title = title;
this.status = status; this.status = status;
this.type = type;
this.createDate = createDate; this.createDate = createDate;
this.updateDate = updateDate; this.updateDate = updateDate;
this.deadlines = deadlines; this.deadlines = deadlines;
this.comment = comment; this.comment = comment;
this.url = url;
this.latexText = latexText;
this.locked = locked; this.locked = locked;
this.tmpFileName = tmpFileName; this.files = files;
this.fileId = null;
this.fileName = null;
this.fileCreateDate = null;
this.authors = authors; this.authors = authors;
} }
@ -73,15 +77,15 @@ public class PaperDto {
this.id = paper.getId(); this.id = paper.getId();
this.title = paper.getTitle(); this.title = paper.getTitle();
this.status = paper.getStatus(); this.status = paper.getStatus();
this.type = paper.getType();
this.createDate = paper.getCreateDate(); this.createDate = paper.getCreateDate();
this.updateDate = paper.getUpdateDate(); this.updateDate = paper.getUpdateDate();
this.deadlines = convert(paper.getDeadlines(), DeadlineDto::new); this.deadlines = paper.getDeadlines();
this.comment = paper.getComment(); this.comment = paper.getComment();
this.url = paper.getUrl();
this.latexText = paper.getLatexText();
this.locked = paper.getLocked(); this.locked = paper.getLocked();
this.tmpFileName = null; this.files = convert(paper.getFiles(), FileDataDto::new);
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.authorIds = convert(paper.getAuthors(), user -> user.getId()); this.authorIds = convert(paper.getAuthors(), user -> user.getId());
this.authors = convert(paper.getAuthors(), UserDto::new); this.authors = convert(paper.getAuthors(), UserDto::new);
} }
@ -110,6 +114,14 @@ public class PaperDto {
this.status = status; this.status = status;
} }
public Paper.PaperType getType() {
return type;
}
public void setType(Paper.PaperType type) {
this.type = type;
}
public Date getCreateDate() { public Date getCreateDate() {
return createDate; return createDate;
} }
@ -126,11 +138,11 @@ public class PaperDto {
this.updateDate = updateDate; this.updateDate = updateDate;
} }
public List<DeadlineDto> getDeadlines() { public List<Deadline> getDeadlines() {
return deadlines; return deadlines;
} }
public void setDeadlines(List<DeadlineDto> deadlines) { public void setDeadlines(List<Deadline> deadlines) {
this.deadlines = deadlines; this.deadlines = deadlines;
} }
@ -150,36 +162,12 @@ public class PaperDto {
this.locked = locked; this.locked = locked;
} }
public String getTmpFileName() { public List<FileDataDto> getFiles() {
return tmpFileName; return files;
}
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 void setFileName(String fileName) { public void setFiles(List<FileDataDto> files) {
this.fileName = fileName; this.files = files;
}
public Date getFileCreateDate() {
return fileCreateDate;
}
public void setFileCreateDate(Date fileCreateDate) {
this.fileCreateDate = fileCreateDate;
} }
public Set<UserDto> getAuthors() { public Set<UserDto> getAuthors() {
@ -198,6 +186,22 @@ public class PaperDto {
this.authorIds = authorIds; 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() { public String getAuthorsString() {
return StringUtils.abbreviate(authors return StringUtils.abbreviate(authors
.stream() .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)") @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> 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 org.springframework.transaction.annotation.Transactional;
import ru.ulstu.deadline.model.Deadline; import ru.ulstu.deadline.model.Deadline;
import ru.ulstu.deadline.service.DeadlineService; import ru.ulstu.deadline.service.DeadlineService;
import ru.ulstu.file.model.FileDataDto;
import ru.ulstu.file.service.FileService; import ru.ulstu.file.service.FileService;
import ru.ulstu.paper.model.Paper; import ru.ulstu.paper.model.Paper;
import ru.ulstu.paper.model.PaperDto; import ru.ulstu.paper.model.PaperDto;
import ru.ulstu.paper.model.PaperFilterDto; import ru.ulstu.paper.model.PaperFilterDto;
import ru.ulstu.paper.repository.PaperRepository; import ru.ulstu.paper.repository.PaperRepository;
import ru.ulstu.timeline.service.EventService;
import ru.ulstu.user.model.User; import ru.ulstu.user.model.User;
import ru.ulstu.user.service.UserService; import ru.ulstu.user.service.UserService;
@ -21,6 +23,7 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static java.util.stream.Collectors.toList;
import static org.springframework.util.ObjectUtils.isEmpty; import static org.springframework.util.ObjectUtils.isEmpty;
import static ru.ulstu.core.util.StreamApiUtils.convert; import static ru.ulstu.core.util.StreamApiUtils.convert;
import static ru.ulstu.paper.model.Paper.PaperStatus.ATTENTION; 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.DRAFT;
import static ru.ulstu.paper.model.Paper.PaperStatus.FAILED; 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.PaperStatus.ON_PREPARATION;
import static ru.ulstu.paper.model.Paper.PaperType.OTHER;
@Service @Service
public class PaperService { public class PaperService {
private final static int MAX_DISPLAY_SIZE = 40; private final static int MAX_DISPLAY_SIZE = 40;
private final static String PAPER_FORMATTED_TEMPLATE = "%s %s";
private final PaperNotificationService paperNotificationService; private final PaperNotificationService paperNotificationService;
private final PaperRepository paperRepository; private final PaperRepository paperRepository;
private final UserService userService; private final UserService userService;
private final DeadlineService deadlineService; private final DeadlineService deadlineService;
private final FileService fileService; private final FileService fileService;
private final EventService eventService;
public PaperService(PaperRepository paperRepository, public PaperService(PaperRepository paperRepository,
FileService fileService, FileService fileService,
PaperNotificationService paperNotificationService, PaperNotificationService paperNotificationService,
UserService userService, UserService userService,
DeadlineService deadlineService) { DeadlineService deadlineService,
EventService eventService) {
this.paperRepository = paperRepository; this.paperRepository = paperRepository;
this.fileService = fileService; this.fileService = fileService;
this.paperNotificationService = paperNotificationService; this.paperNotificationService = paperNotificationService;
this.userService = userService; this.userService = userService;
this.deadlineService = deadlineService; this.deadlineService = deadlineService;
this.eventService = eventService;
} }
public List<Paper> findAll() { public List<Paper> findAll() {
@ -61,15 +69,19 @@ public class PaperService {
return papers; return papers;
} }
public List<PaperDto> findAllActive() { public List<Paper> findAllActive() {
return findAllDto() return findAll()
.stream() .stream()
.filter(paper -> paper.getStatus() != COMPLETED && paper.getStatus() != FAILED) .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) { public PaperDto findOneDto(Integer id) {
return new PaperDto(paperRepository.findOne(id)); return new PaperDto(paperRepository.getOne(id));
} }
@Transactional @Transactional
@ -77,20 +89,24 @@ public class PaperService {
Paper newPaper = copyFromDto(new Paper(), paperDto); Paper newPaper = copyFromDto(new Paper(), paperDto);
newPaper = paperRepository.save(newPaper); newPaper = paperRepository.save(newPaper);
paperNotificationService.sendCreateNotification(newPaper); paperNotificationService.sendCreateNotification(newPaper);
eventService.createFromPaper(newPaper);
return newPaper.getId(); return newPaper.getId();
} }
private Paper copyFromDto(Paper paper, PaperDto paperDto) throws IOException { private Paper copyFromDto(Paper paper, PaperDto paperDto) throws IOException {
paper.setComment(paperDto.getComment()); paper.setComment(paperDto.getComment());
paper.setUrl(paperDto.getUrl());
paper.setLatexText(paperDto.getLatexText());
paper.setCreateDate(paper.getCreateDate() == null ? new Date() : paper.getCreateDate()); paper.setCreateDate(paper.getCreateDate() == null ? new Date() : paper.getCreateDate());
paper.setLocked(paperDto.getLocked()); paper.setLocked(paperDto.getLocked());
paper.setStatus(paperDto.getStatus() == null ? DRAFT : paperDto.getStatus()); paper.setStatus(paperDto.getStatus() == null ? DRAFT : paperDto.getStatus());
paper.setType(paperDto.getType() == null ? OTHER : paperDto.getType());
paper.setTitle(paperDto.getTitle()); paper.setTitle(paperDto.getTitle());
paper.setUpdateDate(new Date()); paper.setUpdateDate(new Date());
paper.setDeadlines(deadlineService.saveOrCreate(paperDto.getDeadlines())); paper.setDeadlines(deadlineService.saveOrCreate(paperDto.getDeadlines()));
if (paperDto.getTmpFileName() != null) { paper.setFiles(fileService.saveOrCreate(paperDto.getFiles().stream()
paper.setFileData(fileService.createFileFromTmp(paperDto.getTmpFileName())); .filter(f -> !f.isDeleted())
} .collect(toList())));
paper.getAuthors().clear(); paper.getAuthors().clear();
if (paperDto.getAuthorIds() != null && !paperDto.getAuthorIds().isEmpty()) { if (paperDto.getAuthorIds() != null && !paperDto.getAuthorIds().isEmpty()) {
paperDto.getAuthorIds().forEach(authorIds -> paper.getAuthors().add(userService.findById(authorIds))); paperDto.getAuthorIds().forEach(authorIds -> paper.getAuthors().add(userService.findById(authorIds)));
@ -100,13 +116,17 @@ public class PaperService {
@Transactional @Transactional
public Integer update(PaperDto paperDto) throws IOException { public Integer update(PaperDto paperDto) throws IOException {
Paper paper = paperRepository.findOne(paperDto.getId()); Paper paper = paperRepository.getOne(paperDto.getId());
Paper.PaperStatus oldStatus = paper.getStatus(); Paper.PaperStatus oldStatus = paper.getStatus();
Set<User> oldAuthors = new HashSet<>(paper.getAuthors()); 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)); paperRepository.save(copyFromDto(paper, paperDto));
eventService.updatePaperDeadlines(paper);
paper.getAuthors().forEach(author -> { paper.getAuthors().forEach(author -> {
if (!oldAuthors.contains(author)) { if (!oldAuthors.contains(author)) {
@ -123,10 +143,7 @@ public class PaperService {
@Transactional @Transactional
public void delete(Integer paperId) throws IOException { public void delete(Integer paperId) throws IOException {
Paper paper = paperRepository.findOne(paperId); Paper paper = paperRepository.getOne(paperId);
if (paper.getFileData() != null) {
fileService.deleteFile(paper.getFileData());
}
paperRepository.delete(paper); paperRepository.delete(paper);
} }
@ -134,6 +151,10 @@ public class PaperService {
return Arrays.asList(Paper.PaperStatus.values()); return Arrays.asList(Paper.PaperStatus.values());
} }
public List<Paper.PaperType> getPaperTypes() {
return Arrays.asList(Paper.PaperType.values());
}
@Transactional @Transactional
public Paper create(String title, User user, Date deadlineDate) { public Paper create(String title, User user, Date deadlineDate) {
Paper paper = new Paper(); Paper paper = new Paper();
@ -143,9 +164,11 @@ public class PaperService {
paper.setCreateDate(new Date()); paper.setCreateDate(new Date());
paper.setUpdateDate(new Date()); paper.setUpdateDate(new Date());
paper.setStatus(DRAFT); paper.setStatus(DRAFT);
paper.setType(OTHER);
paper = paperRepository.save(paper); paper = paperRepository.save(paper);
paperNotificationService.sendCreateNotification(paper); paperNotificationService.sendCreateNotification(paper);
eventService.createFromPaper(paper);
return paper; return paper;
} }
@ -165,7 +188,7 @@ public class PaperService {
return statusCompareResult; return statusCompareResult;
} }
return paper1.getTitle().compareTo(paper2.getTitle()); return paper1.getTitle().compareTo(paper2.getTitle());
}).collect(Collectors.toList()); }).collect(toList());
} }
public PaperDto findPaper(int id) { public PaperDto findPaper(int id) {
@ -179,7 +202,7 @@ public class PaperService {
&& (paper.getStatus() == ON_PREPARATION && (paper.getStatus() == ON_PREPARATION
|| paper.getStatus() == DRAFT || paper.getStatus() == DRAFT
|| paper.getStatus() == ATTENTION)) || paper.getStatus() == ATTENTION))
.collect(Collectors.toList()); .collect(toList());
papers.forEach(paper -> { papers.forEach(paper -> {
Paper.PaperStatus oldStatus = paper.getStatus(); Paper.PaperStatus oldStatus = paper.getStatus();
paper.setStatus(Paper.PaperStatus.FAILED); paper.setStatus(Paper.PaperStatus.FAILED);
@ -197,10 +220,44 @@ public class PaperService {
} }
public PaperDto findById(Integer paperId) { 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() { public List<User> getPaperAuthors() {
return userService.findAll(); 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; package ru.ulstu.project.model;
import org.hibernate.validator.constraints.NotBlank;
import ru.ulstu.core.model.BaseEntity; import ru.ulstu.core.model.BaseEntity;
import ru.ulstu.deadline.model.Deadline; 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.CascadeType;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.JoinColumn; import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany; import javax.persistence.OneToMany;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@Entity @Entity
public class Project extends BaseEntity { 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 @NotBlank
private String title; private String title;
@Enumerated(value = EnumType.STRING)
private ProjectStatus status = ProjectStatus.APPLICATION;
@NotNull
private String description;
@OneToMany(cascade = CascadeType.ALL) @OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "project_id") @JoinColumn(name = "project_id")
private List<Deadline> deadlines = new ArrayList<>(); 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() { public String getTitle() {
return title; return title;
} }
@ -29,6 +70,38 @@ public class Project extends BaseEntity {
this.title = title; 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() { public List<Deadline> getDeadlines() {
return deadlines; return deadlines;
} }
@ -36,4 +109,12 @@ public class Project extends BaseEntity {
public void setDeadlines(List<Deadline> deadlines) { public void setDeadlines(List<Deadline> deadlines) {
this.deadlines = 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.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import org.hibernate.validator.constraints.NotEmpty; import ru.ulstu.deadline.model.Deadline;
import ru.ulstu.deadline.model.DeadlineDto; import ru.ulstu.grant.model.GrantDto;
import javax.validation.constraints.NotEmpty;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static ru.ulstu.core.util.StreamApiUtils.convert;
public class ProjectDto { public class ProjectDto {
private Integer id; private Integer id;
@NotEmpty @NotEmpty
private String title; private String title;
private Project.ProjectStatus status;
private List<DeadlineDto> deadlines = new ArrayList<>(); private String description;
private List<Deadline> deadlines = new ArrayList<>();
private GrantDto grant;
private String repository;
private String applicationFileName;
public ProjectDto() { public ProjectDto() {
} }
@ -28,17 +31,31 @@ public class ProjectDto {
@JsonCreator @JsonCreator
public ProjectDto(@JsonProperty("id") Integer id, public ProjectDto(@JsonProperty("id") Integer id,
@JsonProperty("title") String title, @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.id = id;
this.title = title; this.title = title;
this.status = status;
this.description = description;
this.grant = grant;
this.repository = repository;
this.deadlines = deadlines; this.deadlines = deadlines;
this.applicationFileName = null;
} }
public ProjectDto(Project project) { public ProjectDto(Project project) {
this.id = project.getId(); this.id = project.getId();
this.title = project.getTitle(); 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() { public Integer getId() {
@ -57,11 +74,51 @@ public class ProjectDto {
this.title = title; 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; return deadlines;
} }
public void setDeadlines(List<DeadlineDto> deadlines) { public void setDeadlines(List<Deadline> deadlines) {
this.deadlines = 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.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.thymeleaf.util.StringUtils;
import ru.ulstu.deadline.service.DeadlineService; 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.Project;
import ru.ulstu.project.model.ProjectDto; import ru.ulstu.project.model.ProjectDto;
import ru.ulstu.project.repository.ProjectRepository; import ru.ulstu.project.repository.ProjectRepository;
import java.io.IOException;
import java.util.Arrays;
import java.util.List; import java.util.List;
import static org.springframework.util.ObjectUtils.isEmpty; 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 @Service
public class ProjectService { public class ProjectService {
private final static int MAX_DISPLAY_SIZE = 40;
private final ProjectRepository projectRepository; private final ProjectRepository projectRepository;
private final DeadlineService deadlineService; private final DeadlineService deadlineService;
private final GrantRepository grantRepository;
private final FileService fileService;
public ProjectService(ProjectRepository projectRepository, public ProjectService(ProjectRepository projectRepository,
DeadlineService deadlineService) { DeadlineService deadlineService,
GrantRepository grantRepository,
FileService fileService) {
this.projectRepository = projectRepository; this.projectRepository = projectRepository;
this.deadlineService = deadlineService; this.deadlineService = deadlineService;
this.grantRepository = grantRepository;
this.fileService = fileService;
} }
public List<Project> findAll() { public List<Project> findAll() {
return projectRepository.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 @Transactional
public Project create(ProjectDto projectDto) { public Project create(ProjectDto projectDto) throws IOException {
Project newProject = copyFromDto(new Project(), projectDto); Project newProject = copyFromDto(new Project(), projectDto);
newProject = projectRepository.save(newProject); newProject = projectRepository.save(newProject);
return 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()); 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())); project.setDeadlines(deadlineService.saveOrCreate(projectDto.getDeadlines()));
if (projectDto.getApplicationFileName() != null) {
project.setApplication(fileService.createFileFromTmp(projectDto.getApplicationFileName()));
}
return project; return project;
} }
public Project save(ProjectDto projectDto) { public Project save(ProjectDto projectDto) throws IOException {
if (isEmpty(projectDto.getId())) { if (isEmpty(projectDto.getId())) {
return create(projectDto); return create(projectDto);
} else { } else {
@ -53,7 +90,7 @@ public class ProjectService {
} }
public Project findById(Integer id) { 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; package ru.ulstu.timeline.model;
import org.hibernate.validator.constraints.NotBlank;
import ru.ulstu.core.model.BaseEntity; import ru.ulstu.core.model.BaseEntity;
import ru.ulstu.paper.model.Paper;
import ru.ulstu.user.model.User; import ru.ulstu.user.model.User;
import javax.persistence.CascadeType; import javax.persistence.CascadeType;
@ -16,6 +16,7 @@ import javax.persistence.ManyToOne;
import javax.persistence.OneToMany; import javax.persistence.OneToMany;
import javax.persistence.Temporal; import javax.persistence.Temporal;
import javax.persistence.TemporalType; import javax.persistence.TemporalType;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -71,6 +72,10 @@ public class Event extends BaseEntity {
@JoinColumn(name = "child_id") @JoinColumn(name = "child_id")
private List<Event> parents; private List<Event> parents;
@ManyToOne
@JoinColumn(name = "paper_id")
private Paper paper;
public String getTitle() { public String getTitle() {
return title; return title;
} }
@ -150,4 +155,12 @@ public class Event extends BaseEntity {
public void setParents(List<Event> parents) { public void setParents(List<Event> parents) {
this.parents = parents; this.parents = parents;
} }
public Paper getPaper() {
return paper;
}
public void setPaper(Paper paper) {
this.paper = paper;
}
} }

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

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

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

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

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

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

@ -1,18 +1,20 @@
package ru.ulstu.user.model; package ru.ulstu.user.model;
import org.hibernate.annotations.BatchSize; import org.hibernate.annotations.BatchSize;
import org.hibernate.validator.constraints.Email;
import ru.ulstu.configuration.Constants; import ru.ulstu.configuration.Constants;
import ru.ulstu.core.model.BaseEntity; import ru.ulstu.core.model.BaseEntity;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.JoinColumn; import javax.persistence.JoinColumn;
import javax.persistence.JoinTable; import javax.persistence.JoinTable;
import javax.persistence.ManyToMany; import javax.persistence.ManyToMany;
import javax.persistence.Table; import javax.persistence.Table;
import javax.persistence.Temporal; import javax.persistence.Temporal;
import javax.persistence.TemporalType; import javax.persistence.TemporalType;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern; import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size; import javax.validation.constraints.Size;
@ -24,6 +26,8 @@ import java.util.Set;
@Entity @Entity
@Table(name = "users") @Table(name = "users")
public class User extends BaseEntity { public class User extends BaseEntity {
private final static String USER_ABBREVIATE_TEMPLATE = "%s %s%s";
@NotNull @NotNull
@Pattern(regexp = Constants.LOGIN_REGEX) @Pattern(regexp = Constants.LOGIN_REGEX)
@Size(min = 1, max = 50) @Size(min = 1, max = 50)
@ -45,6 +49,10 @@ public class User extends BaseEntity {
@Column(name = "last_name", length = 50, nullable = false) @Column(name = "last_name", length = 50, nullable = false)
private String lastName; private String lastName;
@Size(max = 50)
@Column(name = "patronymic", length = 50)
private String patronymic;
@NotNull @NotNull
@Email @Email
@Size(min = 5, max = 100) @Size(min = 5, max = 100)
@ -79,6 +87,28 @@ public class User extends BaseEntity {
@BatchSize(size = 20) @BatchSize(size = 20)
private Set<UserRole> roles; 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() { public User() {
roles = new HashSet<>(); roles = new HashSet<>();
activated = false; activated = false;
@ -174,4 +204,35 @@ public class User extends BaseEntity {
this.roles.clear(); this.roles.clear();
this.roles.addAll(roles); 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; package ru.ulstu.user.model;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotBlank;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import ru.ulstu.configuration.Constants; import ru.ulstu.configuration.Constants;
import ru.ulstu.odin.model.OdinDto; 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.odin.model.annotation.OdinVisible;
import ru.ulstu.user.controller.UserController; 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.Pattern;
import javax.validation.constraints.Size; import javax.validation.constraints.Size;
import java.util.Collection; import java.util.Collection;
import java.util.Date;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
@ -70,6 +71,10 @@ public class UserDto implements OdinDto {
@Size(min = Constants.MIN_PASSWORD_LENGTH, max = 50) @Size(min = Constants.MIN_PASSWORD_LENGTH, max = 50)
private String passwordConfirm; private String passwordConfirm;
private Date birthDate;
private User.UserDegree degree;
public UserDto() { public UserDto() {
activated = false; activated = false;
roles = new LinkedHashSet<>(); roles = new LinkedHashSet<>();
@ -86,6 +91,8 @@ public class UserDto implements OdinDto {
this.roles.addAll(user.getRoles().stream() this.roles.addAll(user.getRoles().stream()
.map(UserRoleDto::new) .map(UserRoleDto::new)
.collect(Collectors.toList())); .collect(Collectors.toList()));
this.birthDate = user.getBirthDate();
this.degree = user.getDegree();
} }
public Integer getId() { public Integer getId() {
@ -163,6 +170,22 @@ public class UserDto implements OdinDto {
return passwordConfirm; 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 @JsonIgnore
public boolean isPasswordsValid() { public boolean isPasswordsValid() {
if (StringUtils.isEmpty(password) || StringUtils.isEmpty(passwordConfirm)) { if (StringUtils.isEmpty(password) || StringUtils.isEmpty(passwordConfirm)) {
@ -188,6 +211,8 @@ public class UserDto implements OdinDto {
", roles=" + roles + ", roles=" + roles +
", password='" + password + '\'' + ", password='" + password + '\'' +
", passwordConfirm='" + passwordConfirm + '\'' + ", passwordConfirm='" + passwordConfirm + '\'' +
", birthDate='" + birthDate + '\'' +
", degree='" + degree + '\'' +
'}'; '}';
} }
} }

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

@ -2,7 +2,13 @@ package ru.ulstu.user.model;
import ru.ulstu.core.model.BaseEntity; 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 javax.validation.constraints.NotNull;
import java.util.Date; 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.EntityGraph;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import ru.ulstu.user.model.User; import ru.ulstu.user.model.User;
import java.util.Date; import java.util.Date;
@ -25,4 +27,11 @@ public interface UserRepository extends JpaRepository<User, Integer> {
@EntityGraph(attributePaths = "roles") @EntityGraph(attributePaths = "roles")
User findOneWithRolesByLogin(String login); 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.scheduling.annotation.Async;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.thymeleaf.context.Context; import org.thymeleaf.context.Context;
import org.thymeleaf.spring4.SpringTemplateEngine; import org.thymeleaf.spring5.SpringTemplateEngine;
import ru.ulstu.configuration.ApplicationProperties; import ru.ulstu.configuration.ApplicationProperties;
import ru.ulstu.configuration.Constants; import ru.ulstu.configuration.Constants;
import ru.ulstu.user.model.User; import ru.ulstu.user.model.User;
@ -19,11 +19,9 @@ import java.util.Map;
@Service @Service
public class MailService { public class MailService {
private final Logger log = LoggerFactory.getLogger(MailService.class);
private static final String USER = "user"; private static final String USER = "user";
private static final String BASE_URL = "baseUrl"; private static final String BASE_URL = "baseUrl";
private final Logger log = LoggerFactory.getLogger(MailService.class);
private final JavaMailSender javaMailSender; private final JavaMailSender javaMailSender;
private final SpringTemplateEngine templateEngine; private final SpringTemplateEngine templateEngine;
private final MailProperties mailProperties; private final MailProperties mailProperties;

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

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

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

@ -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-20181111_000000-schema.xml"/>
<include file="db/changelog-20181208_000000-schema.xml"/> <include file="db/changelog-20181208_000000-schema.xml"/>
<include file="db/changelog-20181224_000000-schema.xml"/> <include file="db/changelog-20181224_000000-schema.xml"/>
<include file="db/changelog-20190318_000000-schema.xml"/>
<include file="db/changelog-20190318_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> </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