Compare commits
No commits in common. "master" and "feature/groups" have entirely different histories.
master
...
feature/gr
@ -52,11 +52,6 @@
|
|||||||
<artifactId>postgresql</artifactId>
|
<artifactId>postgresql</artifactId>
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>com.deepoove</groupId>
|
|
||||||
<artifactId>poi-tl</artifactId>
|
|
||||||
<version>1.12.2</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
@ -102,15 +97,6 @@
|
|||||||
<artifactId>commons-collections4</artifactId>
|
<artifactId>commons-collections4</artifactId>
|
||||||
<version>4.4</version>
|
<version>4.4</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
|
||||||
<artifactId>jackson-datatype-jsr310</artifactId>
|
|
||||||
<version>2.17.2</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-mail</artifactId>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@ -5,29 +5,13 @@ import lombok.Getter;
|
|||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.Set;
|
import java.util.List;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "defense")
|
@Table(name = "defense")
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
public class Defense {
|
public class Defense {
|
||||||
public enum Status {
|
|
||||||
NOT_STARTED,
|
|
||||||
TOPIC_PREPARATION,
|
|
||||||
TOPIC_CHOOSING,
|
|
||||||
TASK_CREATING,
|
|
||||||
TASK_ASSIGNING,
|
|
||||||
PRE_DIPLOMA_PRACTICE,
|
|
||||||
TOPIC_FINALIZATION,
|
|
||||||
MAIN_VKR_WORK,
|
|
||||||
PRE_DEFENSE,
|
|
||||||
NORMCONTROL_ANTI_PLAGIARISM,
|
|
||||||
DEFENSE_PREPARATION,
|
|
||||||
DEFENSE,
|
|
||||||
FINISHED,
|
|
||||||
}
|
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
private Long id;
|
private Long id;
|
||||||
@ -37,34 +21,20 @@ public class Defense {
|
|||||||
name = "defense_commission",
|
name = "defense_commission",
|
||||||
joinColumns = @JoinColumn(name = "defense_id", referencedColumnName = "id"),
|
joinColumns = @JoinColumn(name = "defense_id", referencedColumnName = "id"),
|
||||||
inverseJoinColumns = @JoinColumn(name = "commission_member_data_id", referencedColumnName = "id"))
|
inverseJoinColumns = @JoinColumn(name = "commission_member_data_id", referencedColumnName = "id"))
|
||||||
private Set<CommissionMemberData> commissionMembers;
|
private List<CommissionMemberData> commissionMembers;
|
||||||
|
|
||||||
@Enumerated(EnumType.STRING)
|
|
||||||
private Status status;
|
|
||||||
|
|
||||||
private LocalDate defenseDate;
|
private LocalDate defenseDate;
|
||||||
|
|
||||||
@OneToMany(mappedBy = "defense")
|
@OneToMany(mappedBy = "defense")
|
||||||
private Set<Group> groups;
|
private List<Group> groups;
|
||||||
|
|
||||||
|
@ManyToMany
|
||||||
|
@JoinTable(
|
||||||
|
name = "defense_best_student_works",
|
||||||
|
joinColumns = @JoinColumn(name = "defense_id", referencedColumnName = "id"),
|
||||||
|
inverseJoinColumns = @JoinColumn(name = "student_data_id", referencedColumnName = "id"))
|
||||||
|
private List<StudentData> bestWorks;
|
||||||
|
|
||||||
@Embedded
|
@Embedded
|
||||||
private AuditInfo auditInfo;
|
private AuditInfo auditInfo;
|
||||||
|
|
||||||
@ManyToOne
|
|
||||||
@JoinColumn(name = "direction_of_preparation_id")
|
|
||||||
private DirectionOfPreparation directionOfPreparation;
|
|
||||||
|
|
||||||
@ManyToOne
|
|
||||||
@JoinColumn(name = "responsible_for_antiplagiarism_id")
|
|
||||||
private Participant responsibleForAntiplagiarism;
|
|
||||||
|
|
||||||
@ManyToOne
|
|
||||||
@JoinColumn(name = "responsible_for_normcontrol_id")
|
|
||||||
private Participant responsibleForNormcontrol;
|
|
||||||
|
|
||||||
|
|
||||||
@Transient
|
|
||||||
public boolean isStateShouldBeProcessed(Status status) {
|
|
||||||
return this.status.ordinal() >= status.ordinal();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,10 +22,6 @@ public class DirectionOfPreparation {
|
|||||||
@OneToMany(mappedBy = "directionOfPreparation")
|
@OneToMany(mappedBy = "directionOfPreparation")
|
||||||
private List<DiplomaTopic> diplomaTopic;
|
private List<DiplomaTopic> diplomaTopic;
|
||||||
|
|
||||||
@ManyToOne
|
|
||||||
@JoinColumn(name = "responsible_id")
|
|
||||||
private TeacherData responsible;
|
|
||||||
|
|
||||||
@Embedded
|
@Embedded
|
||||||
private AuditInfo auditInfo;
|
private AuditInfo auditInfo;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,6 @@ package ru.mskobaro.tdms.business.entity;
|
|||||||
|
|
||||||
|
|
||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
@ -16,7 +15,6 @@ import java.util.List;
|
|||||||
@ToString
|
@ToString
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "`group`")
|
@Table(name = "`group`")
|
||||||
@EqualsAndHashCode(of = "id")
|
|
||||||
public class Group {
|
public class Group {
|
||||||
@Id
|
@Id
|
||||||
@Column(name = "id")
|
@Column(name = "id")
|
||||||
|
|||||||
@ -1,56 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.business.entity;
|
|
||||||
|
|
||||||
import jakarta.persistence.*;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Table(name = "message_template")
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@NoArgsConstructor
|
|
||||||
public class MessageTemplate {
|
|
||||||
|
|
||||||
public enum MessageType {
|
|
||||||
TOPIC_LIST_PREPARE_START_FOR_TEACHER,
|
|
||||||
|
|
||||||
TOPIC_CHOOSE_FOR_STUDENT,
|
|
||||||
TOPIC_CHOOSE_FOR_TEACHER,
|
|
||||||
|
|
||||||
TASK_CREATE_FOR_TEACHER,
|
|
||||||
TASK_ASSIGN_FOR_TEACHER,
|
|
||||||
|
|
||||||
PRE_DIPLOMA_PRACTICE_START_FOR_TEACHER,
|
|
||||||
PRE_DIPLOMA_PRACTICE_START_FOR_STUDENT,
|
|
||||||
|
|
||||||
TOPIC_FINALIZATION_FOR_TEACHER,
|
|
||||||
|
|
||||||
PRE_DEFENSE_FOR_STUDENT,
|
|
||||||
|
|
||||||
ANTIPLAGIARISM_FOR_STUDENT,
|
|
||||||
|
|
||||||
DEFENSE_PREPARATION_FOR_STUDENT,
|
|
||||||
|
|
||||||
MAIN_VRK_WORK_START,
|
|
||||||
|
|
||||||
NORMCONTROL_AND_ANTIPLAGIARISM,
|
|
||||||
|
|
||||||
DEFENSE,
|
|
||||||
|
|
||||||
DEFENSE_PREPARATION_FOR_TEACHER,
|
|
||||||
}
|
|
||||||
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
@Enumerated(EnumType.STRING)
|
|
||||||
private MessageType messageType;
|
|
||||||
|
|
||||||
private String subjectTemplate;
|
|
||||||
private String messageTemplate;
|
|
||||||
|
|
||||||
@Embedded
|
|
||||||
private AuditInfo auditInfo;
|
|
||||||
}
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.business.entity;
|
|
||||||
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public class NormcontrolAndAntiplagiarismTask extends Task {
|
|
||||||
private Boolean normcontrolPassed;
|
|
||||||
private Long antiplagiarismPercent;
|
|
||||||
}
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.business.entity;
|
|
||||||
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public class PreDiplomaPracticeTask extends Task {
|
|
||||||
private Long practiceMark;
|
|
||||||
}
|
|
||||||
@ -2,7 +2,6 @@ package ru.mskobaro.tdms.business.entity;
|
|||||||
|
|
||||||
|
|
||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
@ -14,7 +13,6 @@ import ru.mskobaro.tdms.integration.database.TeacherDataRepository;
|
|||||||
@ToString(exclude = "group")
|
@ToString(exclude = "group")
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "student_data")
|
@Table(name = "student_data")
|
||||||
@EqualsAndHashCode(of = "id")
|
|
||||||
public class StudentData {
|
public class StudentData {
|
||||||
@Id
|
@Id
|
||||||
@Column(name = "id")
|
@Column(name = "id")
|
||||||
@ -36,33 +34,9 @@ public class StudentData {
|
|||||||
private Integer protectionOrder;
|
private Integer protectionOrder;
|
||||||
private Integer protectionDay;
|
private Integer protectionDay;
|
||||||
|
|
||||||
|
private Integer markComment;
|
||||||
private Integer markPractice;
|
private Integer markPractice;
|
||||||
|
|
||||||
@Column(name = "magistracy_wanted")
|
|
||||||
private Boolean magistracy;
|
|
||||||
private Boolean electronic;
|
|
||||||
|
|
||||||
@Column(name = "oztiv_mark")
|
|
||||||
private Integer otziv;
|
|
||||||
@Column(name = "predefnese_mark")
|
|
||||||
private Integer preDefenseMark;
|
|
||||||
|
|
||||||
@Column(name = "normal_control")
|
|
||||||
private Boolean normcontrol;
|
|
||||||
@Column(name = "anti_plagiarism")
|
|
||||||
private Integer antiplagiarism;
|
|
||||||
|
|
||||||
@Column(name = "record_book_returned")
|
|
||||||
private Boolean zachetka;
|
|
||||||
|
|
||||||
@Column(name = "work")
|
|
||||||
private String work;
|
|
||||||
|
|
||||||
@Column(name = "vnedreniye")
|
|
||||||
private Boolean vnedreniye;
|
|
||||||
@Column(name = "diploma_with_honors")
|
|
||||||
private Boolean otlichiye;
|
|
||||||
|
|
||||||
@ManyToOne
|
@ManyToOne
|
||||||
@JoinColumn(name = "curator_id")
|
@JoinColumn(name = "curator_id")
|
||||||
private TeacherData curator;
|
private TeacherData curator;
|
||||||
@ -71,13 +45,6 @@ public class StudentData {
|
|||||||
@JoinColumn(name = "diploma_topic_id")
|
@JoinColumn(name = "diploma_topic_id")
|
||||||
private DiplomaTopic diplomaTopic;
|
private DiplomaTopic diplomaTopic;
|
||||||
|
|
||||||
@Column(name = "marks_5")
|
|
||||||
private Long marks5;
|
|
||||||
@Column(name = "marks_4")
|
|
||||||
private Long marks4;
|
|
||||||
@Column(name = "marks_3")
|
|
||||||
private Long marks3;
|
|
||||||
|
|
||||||
@Embedded
|
@Embedded
|
||||||
private AuditInfo auditInfo;
|
private AuditInfo auditInfo;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,59 +4,38 @@ import jakarta.persistence.*;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
import org.hibernate.annotations.JdbcTypeCode;
|
||||||
|
import org.hibernate.type.SqlTypes;
|
||||||
|
import ru.mskobaro.tdms.business.taskfields.TaskFields;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "task")
|
@Table(name = "task")
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
|
|
||||||
@DiscriminatorColumn(name = "task_type", discriminatorType = DiscriminatorType.STRING)
|
|
||||||
public class Task {
|
public class Task {
|
||||||
public enum Status {
|
public enum Type {
|
||||||
WAIT_FOR_TOPIC_AGREEMENT,
|
DIPLOMA_TOPIC_AGREEMENT,
|
||||||
WAIT_FOR_STUDENT_EDIT,
|
|
||||||
WAIT_FOR_STUDENT_START,
|
|
||||||
|
|
||||||
WAIT_FOR_TOPIC_PREPARATION,
|
|
||||||
|
|
||||||
WAIT_FOR_STUDENT_PRE_DIPLOMA_PRACTICE_WORK_DONE,
|
|
||||||
WAIT_FOR_TEACHER_PRE_DIPLOMA_PRACTICE_MARK_SEND,
|
|
||||||
|
|
||||||
DONE,
|
|
||||||
CANCELED, WAIT_FOR_NORMOCONTROL_PASSED, WAIT_FOR_TEACHER_OTZIV, WAIT_FOR_ANTIPL_PASSED,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Type {
|
public enum Status {
|
||||||
TOPIC_AGREEMENT,
|
WAIT_FOR_TOPIC_AGREEMENT,
|
||||||
TOPIC_PREPARATION,
|
DONE,
|
||||||
TASK_CREATING,
|
|
||||||
TASK_ASSIGN,
|
|
||||||
PRE_DIPLOMA_PRACTICE,
|
|
||||||
TOPIC_FINALIZATION,
|
|
||||||
MAIN_VKR_WORK,
|
|
||||||
PRE_DEFENSE,
|
|
||||||
NORMCONTROL_AND_ANTIPLAGIARISM,
|
|
||||||
DEFENSE_PREPARATION,
|
|
||||||
DEFENSE,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@Enumerated(EnumType.STRING)
|
|
||||||
private Status status;
|
|
||||||
@Enumerated(EnumType.STRING)
|
@Enumerated(EnumType.STRING)
|
||||||
private Type type;
|
private Type type;
|
||||||
|
|
||||||
@ManyToOne
|
@Enumerated(EnumType.STRING)
|
||||||
@JoinColumn(name = "defense_id")
|
private Status status;
|
||||||
private Defense defense;
|
|
||||||
|
@JdbcTypeCode(SqlTypes.JSON)
|
||||||
|
private TaskFields fields;
|
||||||
|
|
||||||
@Embedded
|
@Embedded
|
||||||
private AuditInfo auditInfo;
|
private AuditInfo auditInfo;
|
||||||
|
|
||||||
private Long makerParticId;
|
|
||||||
private Long checkerParticId;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,16 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.business.entity;
|
|
||||||
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public class TopicAgreementTask extends Task {
|
|
||||||
private Long diplomaTopicId;
|
|
||||||
private String diplomaTopicName;
|
|
||||||
private LocalDateTime approvedAt;
|
|
||||||
}
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
package ru.mskobaro.tdms.business.exception;
|
package ru.mskobaro.tdms.business.exception;
|
||||||
|
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.ErrorDTO;
|
import ru.mskobaro.tdms.presentation.controller.payload.ErrorDTO;
|
||||||
|
|
||||||
public class AccessDeniedException extends BusinessException {
|
public class AccessDeniedException extends BusinessException {
|
||||||
public AccessDeniedException() {
|
public AccessDeniedException() {
|
||||||
|
|||||||
@ -1,16 +1,12 @@
|
|||||||
package ru.mskobaro.tdms.business.exception;
|
package ru.mskobaro.tdms.business.exception;
|
||||||
|
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.ErrorDTO;
|
import ru.mskobaro.tdms.presentation.controller.payload.ErrorDTO;
|
||||||
|
|
||||||
public class BusinessException extends RuntimeException {
|
public class BusinessException extends RuntimeException {
|
||||||
public BusinessException(String message) {
|
public BusinessException(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BusinessException(String message, Exception cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ErrorDTO.ErrorCode getErrorCode() {
|
public ErrorDTO.ErrorCode getErrorCode() {
|
||||||
return ErrorDTO.ErrorCode.BUSINESS_ERROR;
|
return ErrorDTO.ErrorCode.BUSINESS_ERROR;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
package ru.mskobaro.tdms.business.exception;
|
package ru.mskobaro.tdms.business.exception;
|
||||||
|
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.ErrorDTO;
|
import ru.mskobaro.tdms.presentation.controller.payload.ErrorDTO;
|
||||||
|
|
||||||
public class NotFoundException extends BusinessException {
|
public class NotFoundException extends BusinessException {
|
||||||
public NotFoundException(Class<?> entityClass, Object id) {
|
public NotFoundException(Class<?> entityClass, Object id) {
|
||||||
|
|||||||
@ -0,0 +1,20 @@
|
|||||||
|
package ru.mskobaro.tdms.business.service;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import ru.mskobaro.tdms.integration.database.DefenceRepository;
|
||||||
|
import ru.mskobaro.tdms.presentation.controller.payload.DefenceDTO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Transactional
|
||||||
|
public class DefenceService {
|
||||||
|
@Autowired
|
||||||
|
private DefenceRepository defenceRepository;
|
||||||
|
|
||||||
|
public List<DefenceDTO> getAllDefences() {
|
||||||
|
return defenceRepository.findAll().stream().map(DefenceDTO::from).toList();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,347 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.business.service;
|
|
||||||
|
|
||||||
import jakarta.persistence.EntityManager;
|
|
||||||
import jakarta.persistence.PersistenceContext;
|
|
||||||
import org.hibernate.Hibernate;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
import ru.mskobaro.tdms.business.entity.*;
|
|
||||||
import ru.mskobaro.tdms.business.exception.BusinessException;
|
|
||||||
import ru.mskobaro.tdms.integration.controller.DefenseController;
|
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.CommissionMemberDTO;
|
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.DefenseDTO;
|
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.GroupDTO;
|
|
||||||
import ru.mskobaro.tdms.integration.database.*;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@Transactional
|
|
||||||
public class DefenseService {
|
|
||||||
@Autowired
|
|
||||||
private DefenseRepository defenseRepository;
|
|
||||||
@Autowired
|
|
||||||
private CommissionMemberRepository commissionMemberRepository;
|
|
||||||
@Autowired
|
|
||||||
private GroupRepository groupRepository;
|
|
||||||
@PersistenceContext
|
|
||||||
private EntityManager entityManager;
|
|
||||||
@Autowired
|
|
||||||
private TaskService taskService;
|
|
||||||
@Autowired
|
|
||||||
private ParticipantRepository participantRepository;
|
|
||||||
@Autowired
|
|
||||||
private TeacherDataRepository teacherDataRepository;
|
|
||||||
@Autowired
|
|
||||||
private PreparationDirectionRepository preparationDirectionRepository;
|
|
||||||
|
|
||||||
public List<Defense> findAll() {
|
|
||||||
List<Defense> defenses = entityManager.createQuery("select d from Defense d left join fetch d.commissionMembers", Defense.class)
|
|
||||||
.getResultList();
|
|
||||||
|
|
||||||
defenses.forEach(defense -> defense.getGroups().forEach(group -> Hibernate.initialize(group.getStudents())));
|
|
||||||
return defenses;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Defense findById(Long id) {
|
|
||||||
return entityManager.createQuery(
|
|
||||||
"select d from Defense d " +
|
|
||||||
"left join fetch d.commissionMembers cm " +
|
|
||||||
"left join fetch cm.participant " +
|
|
||||||
"left join fetch d.groups g " +
|
|
||||||
"left join fetch g.students " +
|
|
||||||
"where d.id = :id "
|
|
||||||
, Defense.class)
|
|
||||||
.setParameter("id", id)
|
|
||||||
.getSingleResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void save(DefenseDTO defenseDTO) {
|
|
||||||
boolean editMode = defenseDTO.getId() != null;
|
|
||||||
|
|
||||||
Defense defense;
|
|
||||||
if (editMode) {
|
|
||||||
defense = defenseRepository.findByIdThrow(defenseDTO.getId());
|
|
||||||
} else {
|
|
||||||
defense = new Defense();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<CommissionMemberData> members = commissionMemberRepository.findAllById(
|
|
||||||
defenseDTO.getCommissionMembers().stream().map(CommissionMemberDTO::getId).collect(Collectors.toList())
|
|
||||||
);
|
|
||||||
defense.setCommissionMembers(new HashSet<>(members));
|
|
||||||
|
|
||||||
if (defenseDTO.getResponsibleForNorm() != null && defenseDTO.getResponsibleForNorm().getId() != null) {
|
|
||||||
Participant norm = participantRepository.findByIdThrow(defenseDTO.getResponsibleForNorm().getId());
|
|
||||||
defense.setResponsibleForNormcontrol(norm);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defenseDTO.getResponsibleForAntipl() != null && defenseDTO.getResponsibleForAntipl().getId() != null) {
|
|
||||||
Participant antipl = participantRepository.findByIdThrow(defenseDTO.getResponsibleForAntipl().getId());
|
|
||||||
defense.setResponsibleForAntiplagiarism(antipl);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defenseDTO.getPreparationDirection() != null && defenseDTO.getPreparationDirection().getId() != null) {
|
|
||||||
DirectionOfPreparation dirOfPrep = preparationDirectionRepository.findByIdThrow(defenseDTO.getPreparationDirection().getId());
|
|
||||||
defense.setDirectionOfPreparation(dirOfPrep);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!editMode) {
|
|
||||||
defense.setStatus(Defense.Status.NOT_STARTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defenseDTO.getDefenseDate() != null) {
|
|
||||||
defense.setDefenseDate(defenseDTO.getDefenseDate());
|
|
||||||
}
|
|
||||||
|
|
||||||
defense = defenseRepository.save(defense);
|
|
||||||
|
|
||||||
List<Group> groups = groupRepository.findAllById(
|
|
||||||
defenseDTO.getGroups().stream().map(GroupDTO::getId).collect(Collectors.toList()));
|
|
||||||
for (Group g : groups) {
|
|
||||||
g.setDefense(defense);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void handleNextStateRequest(Long id) {
|
|
||||||
Defense defense = defenseRepository.findByIdThrow(id);
|
|
||||||
toNextState(defense);
|
|
||||||
processState(defense, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void processState(Defense defense, Defense.Status status) {
|
|
||||||
List<StudentData> students = defense.getGroups().stream()
|
|
||||||
.flatMap(g -> g.getStudents().stream())
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
List<TeacherData> curators = students.stream()
|
|
||||||
.map(StudentData::getCurator)
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
if (status == null) {
|
|
||||||
status = defense.getStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status == Defense.Status.TOPIC_PREPARATION) {
|
|
||||||
List<TeacherData> all = teacherDataRepository.findAll();
|
|
||||||
taskService.checkAndCreateTopicPreparationTasksAndSendEmail(all, defense);
|
|
||||||
} else if (status == Defense.Status.TOPIC_CHOOSING) {
|
|
||||||
taskService.checkAndCreateTopicChoosingTasksAndSendEmail(students, defense);
|
|
||||||
} else if (status == Defense.Status.TASK_CREATING) {
|
|
||||||
taskService.checkAndCreateTaskCreatingTask(curators, defense);
|
|
||||||
} else if (status == Defense.Status.TASK_ASSIGNING) {
|
|
||||||
taskService.checkAndCreateTaskAssignTasks(curators, defense);
|
|
||||||
} else if (status == Defense.Status.PRE_DIPLOMA_PRACTICE) {
|
|
||||||
taskService.checkAndCreatePreDiplomaPracticeTask(students, defense);
|
|
||||||
} else if (status == Defense.Status.TOPIC_FINALIZATION) {
|
|
||||||
taskService.checkAndCreateTopicFinalizationTask(defense, curators);
|
|
||||||
} else if (status == Defense.Status.MAIN_VKR_WORK) {
|
|
||||||
taskService.checkAndCreateMainVkrWorkTask(defense, students);
|
|
||||||
} else if (status == Defense.Status.PRE_DEFENSE) {
|
|
||||||
taskService.checkAndCreatePreDefenseTask(defense, students);
|
|
||||||
} else if (status == Defense.Status.NORMCONTROL_ANTI_PLAGIARISM) {
|
|
||||||
taskService.checkAndCreateNormcontrolAndAntiplagiarismTask(defense, students);
|
|
||||||
} else if (status == Defense.Status.DEFENSE_PREPARATION)
|
|
||||||
taskService.checkAndCreateDefensePreparationTasks(defense, students);
|
|
||||||
else if (status == Defense.Status.DEFENSE) {
|
|
||||||
taskService.checkAndCreateDefenseTask(defense, students);
|
|
||||||
} else if (status == Defense.Status.FINISHED) {
|
|
||||||
taskService.clearAllTasksWithDefense(defense);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void toNextState(Defense defense) {
|
|
||||||
switch (defense.getStatus()) {
|
|
||||||
case NOT_STARTED ->
|
|
||||||
defense.setStatus(Defense.Status.TOPIC_PREPARATION);
|
|
||||||
case TOPIC_PREPARATION ->
|
|
||||||
defense.setStatus(Defense.Status.TOPIC_CHOOSING);
|
|
||||||
case TOPIC_CHOOSING ->
|
|
||||||
defense.setStatus(Defense.Status.TASK_CREATING);
|
|
||||||
case TASK_CREATING ->
|
|
||||||
defense.setStatus(Defense.Status.TASK_ASSIGNING);
|
|
||||||
case TASK_ASSIGNING ->
|
|
||||||
defense.setStatus(Defense.Status.PRE_DIPLOMA_PRACTICE);
|
|
||||||
case PRE_DIPLOMA_PRACTICE ->
|
|
||||||
defense.setStatus(Defense.Status.TOPIC_FINALIZATION);
|
|
||||||
case TOPIC_FINALIZATION ->
|
|
||||||
defense.setStatus(Defense.Status.MAIN_VKR_WORK);
|
|
||||||
case MAIN_VKR_WORK ->
|
|
||||||
defense.setStatus(Defense.Status.PRE_DEFENSE);
|
|
||||||
case PRE_DEFENSE ->
|
|
||||||
defense.setStatus(Defense.Status.NORMCONTROL_ANTI_PLAGIARISM);
|
|
||||||
case NORMCONTROL_ANTI_PLAGIARISM ->
|
|
||||||
defense.setStatus(Defense.Status.DEFENSE_PREPARATION);
|
|
||||||
case DEFENSE_PREPARATION ->
|
|
||||||
defense.setStatus(Defense.Status.DEFENSE);
|
|
||||||
case DEFENSE ->
|
|
||||||
defense.setStatus(Defense.Status.FINISHED);
|
|
||||||
case FINISHED ->
|
|
||||||
throw new BusinessException("Защита окончена");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public DefenseController.DefenseTableData tableDataByDefenseId(Long defenseId) {
|
|
||||||
List<StudentData> allDefenseStudents = entityManager.createQuery("""
|
|
||||||
select sd from StudentData sd
|
|
||||||
where sd.group.defense.id = :defenseId
|
|
||||||
""", StudentData.class
|
|
||||||
).setParameter("defenseId", defenseId)
|
|
||||||
.getResultList();
|
|
||||||
|
|
||||||
List<DefenseController.DefenseTableDataGroup> groupsData = new ArrayList<>();
|
|
||||||
for (StudentData student : allDefenseStudents) {
|
|
||||||
DefenseController.DefenseTableDataGroup groupData = new DefenseController.DefenseTableDataGroup();
|
|
||||||
groupData.setGroupId(student.getGroup().getId());
|
|
||||||
groupData.setGroupName(student.getGroup().getName());
|
|
||||||
groupData.setStudId(student.getId());
|
|
||||||
groupData.setFio(student.getParticipant().getFullName());
|
|
||||||
if (student.getMarkPractice() != null) {
|
|
||||||
groupData.setPdpMark(student.getMarkPractice());
|
|
||||||
}
|
|
||||||
if (student.getDiplomaTopic() != null) {
|
|
||||||
groupData.setTopic(student.getDiplomaTopic().getName());
|
|
||||||
}
|
|
||||||
if (student.getCurator() != null) {
|
|
||||||
groupData.setTeacherFio(student.getCurator().getParticipant().getFullName());
|
|
||||||
}
|
|
||||||
if (student.getProtectionDay() != null) {
|
|
||||||
groupData.setDayOfProt(student.getProtectionDay());
|
|
||||||
}
|
|
||||||
if (student.getProtectionDay() != null) {
|
|
||||||
groupData.setPlaceOfProt(student.getProtectionOrder());
|
|
||||||
}
|
|
||||||
groupData.setMagistracy(student.getMagistracy());
|
|
||||||
groupData.setElectronic(student.getElectronic());
|
|
||||||
groupData.setOtziv(student.getOtziv());
|
|
||||||
groupData.setDpedefenseMark(student.getPreDefenseMark());
|
|
||||||
groupData.setNormcontrol(student.getNormcontrol());
|
|
||||||
groupData.setAntipl(student.getAntiplagiarism());
|
|
||||||
groupData.setZachetka(student.getZachetka());
|
|
||||||
groupData.setWork(student.getWork());
|
|
||||||
groupData.setVnedreniye(student.getVnedreniye());
|
|
||||||
groupData.setOtlichiye(student.getOtlichiye());
|
|
||||||
groupsData.add(groupData);
|
|
||||||
}
|
|
||||||
|
|
||||||
DefenseController.DefenseTableData dto = new DefenseController.DefenseTableData();
|
|
||||||
dto.setDefenseId(defenseId);
|
|
||||||
dto.setGroups(groupsData);
|
|
||||||
return dto;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void tableDataSave(DefenseController.DefenseTableData defenseTableData) {
|
|
||||||
List<DefenseController.DefenseTableDataGroup> groups = defenseTableData.getGroups();
|
|
||||||
for (DefenseController.DefenseTableDataGroup groupData : groups) {
|
|
||||||
StudentData student = entityManager.createQuery("""
|
|
||||||
select sd from StudentData sd
|
|
||||||
where sd.group.defense.id = :defenseId
|
|
||||||
and sd.id = :id
|
|
||||||
""", StudentData.class
|
|
||||||
).setParameter("defenseId", defenseTableData.getDefenseId())
|
|
||||||
.setParameter("id", groupData.getStudId())
|
|
||||||
.getSingleResult();
|
|
||||||
|
|
||||||
|
|
||||||
if (groupData.getPdpMark() != null) {
|
|
||||||
student.setMarkPractice(groupData.getPdpMark());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (groupData.getMagistracy() != null) {
|
|
||||||
student.setMagistracy(groupData.getMagistracy());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (groupData.getElectronic() != null) {
|
|
||||||
student.setElectronic(groupData.getElectronic());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (groupData.getOtziv() != null) {
|
|
||||||
student.setOtziv(groupData.getOtziv());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (groupData.getDpedefenseMark() != null) {
|
|
||||||
student.setPreDefenseMark(groupData.getDpedefenseMark());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (groupData.getZachetka() != null) {
|
|
||||||
student.setZachetka(groupData.getZachetka());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (groupData.getWork() != null) {
|
|
||||||
student.setWork(groupData.getWork());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (groupData.getVnedreniye() != null) {
|
|
||||||
student.setVnedreniye(groupData.getVnedreniye());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (groupData.getOtlichiye() != null) {
|
|
||||||
student.setOtlichiye(groupData.getOtlichiye());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void recreateProtectionOrder(Long defenseId) {
|
|
||||||
Defense defense = defenseRepository.findByIdThrow(defenseId);
|
|
||||||
|
|
||||||
List<StudentData> students = defense.getGroups().stream()
|
|
||||||
.map(Group::getStudents)
|
|
||||||
.flatMap(List::stream)
|
|
||||||
.sorted(Comparator.comparing(student -> {
|
|
||||||
if (student.getCurator() != null && student.getCurator().getParticipant() != null)
|
|
||||||
return student.getCurator().getParticipant().getFullName();
|
|
||||||
return null;
|
|
||||||
}, Comparator.nullsLast(Comparator.naturalOrder())
|
|
||||||
))
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
int maxInDay = 16;
|
|
||||||
|
|
||||||
int size = students.size();
|
|
||||||
for (int i = 1; i < 10; i++) {
|
|
||||||
int inDay = size / i;
|
|
||||||
if (inDay <= maxInDay) {
|
|
||||||
maxInDay = inDay;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int currentDay = 1;
|
|
||||||
int currentOrder = 1;
|
|
||||||
for (StudentData student : students) {
|
|
||||||
if (currentOrder > maxInDay) {
|
|
||||||
currentOrder = 1;
|
|
||||||
currentDay += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
student.setProtectionDay(currentDay);
|
|
||||||
student.setProtectionOrder(currentOrder++);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateProtOrder(DefenseController.ProtOrDTO dto) {
|
|
||||||
Defense defense = defenseRepository.findByIdThrow(dto.getDefenseId());
|
|
||||||
Map<Long, StudentData> studentsById = defense.getGroups().stream()
|
|
||||||
.map(Group::getStudents)
|
|
||||||
.flatMap(Collection::stream)
|
|
||||||
.collect(Collectors.toMap(StudentData::getId, Function.identity()));
|
|
||||||
|
|
||||||
dto.getDays().forEach(day -> day.getStuds().forEach(student -> {
|
|
||||||
StudentData studentData = studentsById.get(student.getId());
|
|
||||||
if (studentData != null) {
|
|
||||||
studentData.setProtectionDay(day.getNumber());
|
|
||||||
studentData.setProtectionOrder(student.getOrder() + 1);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
dto.getUnassigned().forEach(unassigned -> {
|
|
||||||
StudentData studentData = studentsById.get(unassigned.getId());
|
|
||||||
if (studentData != null) {
|
|
||||||
studentData.setProtectionDay(null);
|
|
||||||
studentData.setProtectionOrder(null);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,7 +1,5 @@
|
|||||||
package ru.mskobaro.tdms.business.service;
|
package ru.mskobaro.tdms.business.service;
|
||||||
|
|
||||||
import jakarta.persistence.EntityManager;
|
|
||||||
import jakarta.persistence.PersistenceContext;
|
|
||||||
import jakarta.transaction.Transactional;
|
import jakarta.transaction.Transactional;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@ -11,7 +9,7 @@ import ru.mskobaro.tdms.business.entity.TeacherData;
|
|||||||
import ru.mskobaro.tdms.integration.database.DiplomaTopicRepository;
|
import ru.mskobaro.tdms.integration.database.DiplomaTopicRepository;
|
||||||
import ru.mskobaro.tdms.integration.database.PreparationDirectionRepository;
|
import ru.mskobaro.tdms.integration.database.PreparationDirectionRepository;
|
||||||
import ru.mskobaro.tdms.integration.database.TeacherDataRepository;
|
import ru.mskobaro.tdms.integration.database.TeacherDataRepository;
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.DiplomaTopicDTO;
|
import ru.mskobaro.tdms.presentation.controller.payload.DiplomaTopicDTO;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -24,8 +22,6 @@ public class DiplomaTopicService {
|
|||||||
private TeacherDataRepository teacherDataRepository;
|
private TeacherDataRepository teacherDataRepository;
|
||||||
@Autowired
|
@Autowired
|
||||||
private PreparationDirectionRepository preparationDirectionRepository;
|
private PreparationDirectionRepository preparationDirectionRepository;
|
||||||
@PersistenceContext
|
|
||||||
private EntityManager entityManager;
|
|
||||||
|
|
||||||
public List<DiplomaTopic> findAll() {
|
public List<DiplomaTopic> findAll() {
|
||||||
return diplomaTopicRepository.findAll();
|
return diplomaTopicRepository.findAll();
|
||||||
@ -53,16 +49,7 @@ public class DiplomaTopicService {
|
|||||||
diplomaTopicRepository.save(diplomaTopic);
|
diplomaTopicRepository.save(diplomaTopic);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<DiplomaTopic> findAllForStudentByParticId(Long particId) {
|
public List<DiplomaTopic> findAllForStudent(Long studentId) {
|
||||||
return diplomaTopicRepository.findAllForStudentByParticId(particId);
|
return diplomaTopicRepository.findAllForStudentId(studentId);
|
||||||
}
|
|
||||||
|
|
||||||
public List<DiplomaTopic> findByTeacherParticIdAndDirPrep(Long particId, Long dirPrepId) {
|
|
||||||
return entityManager.createQuery(
|
|
||||||
"select dt from DiplomaTopic dt where dt.directionOfPreparation.id = :dirPrepId and dt.teacher.participant.id = :particId",
|
|
||||||
DiplomaTopic.class
|
|
||||||
).setParameter("dirPrepId", dirPrepId)
|
|
||||||
.setParameter("particId", particId)
|
|
||||||
.getResultList();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,272 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.business.service;
|
|
||||||
|
|
||||||
import com.deepoove.poi.XWPFTemplate;
|
|
||||||
import com.deepoove.poi.data.*;
|
|
||||||
import com.deepoove.poi.data.style.CellStyle;
|
|
||||||
import com.deepoove.poi.data.style.ParagraphStyle;
|
|
||||||
import com.deepoove.poi.data.style.Style;
|
|
||||||
import com.deepoove.poi.data.style.TableStyle;
|
|
||||||
import com.deepoove.poi.util.UnitUtils;
|
|
||||||
import jakarta.persistence.EntityManager;
|
|
||||||
import jakarta.persistence.PersistenceContext;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
import ru.mskobaro.tdms.business.entity.*;
|
|
||||||
import ru.mskobaro.tdms.business.exception.BusinessException;
|
|
||||||
import ru.mskobaro.tdms.integration.database.DefenseRepository;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.time.LocalDate;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@Transactional
|
|
||||||
public class DocumentsService {
|
|
||||||
@Autowired
|
|
||||||
private DefenseRepository defenseRepository;
|
|
||||||
@PersistenceContext
|
|
||||||
private EntityManager entityManager;
|
|
||||||
|
|
||||||
public byte[] getQuestionsDocument(Long defenseId, String studyForm) {
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
class Data {
|
|
||||||
String day;
|
|
||||||
String month;
|
|
||||||
String year;
|
|
||||||
String studFio;
|
|
||||||
String prepDir;
|
|
||||||
String form;
|
|
||||||
String gekFio;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Data> data = new ArrayList<>();
|
|
||||||
Defense defense = defenseRepository.findByIdThrow(defenseId);
|
|
||||||
LocalDate defenseDate = defense.getDefenseDate();
|
|
||||||
String defDay;
|
|
||||||
String defMonth;
|
|
||||||
String defYear;
|
|
||||||
if (defenseDate != null) {
|
|
||||||
defDay = Integer.toString(defenseDate.getDayOfMonth());
|
|
||||||
defMonth = Integer.toString(defenseDate.getMonthValue());
|
|
||||||
defYear = Integer.toString(defenseDate.getYear() - 2000);
|
|
||||||
} else {
|
|
||||||
defDay = "";
|
|
||||||
defMonth = "";
|
|
||||||
defYear = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Participant> gek = defense.getCommissionMembers().stream().map(CommissionMemberData::getParticipant).toList();
|
|
||||||
List<StudentData> students = defense.getGroups().stream().map(Group::getStudents).flatMap(List::stream).toList();
|
|
||||||
for (StudentData stud : students) {
|
|
||||||
String day = null;
|
|
||||||
String month = null;
|
|
||||||
if (StringUtils.isNotBlank(defDay) && stud.getProtectionDay() != null) {
|
|
||||||
day = Integer.toString(Integer.parseInt(defDay) + stud.getProtectionDay() - 1);
|
|
||||||
}
|
|
||||||
if (StringUtils.isNotBlank(defMonth)) {
|
|
||||||
month = getMonthNameByValue(Integer.parseInt(defMonth));
|
|
||||||
}
|
|
||||||
for (Participant g : gek) {
|
|
||||||
Data d = new Data();
|
|
||||||
d.day = day;
|
|
||||||
d.month = month;
|
|
||||||
d.year = defYear;
|
|
||||||
d.studFio = stud.getParticipant().getShortName();
|
|
||||||
d.prepDir = stud.getGroup().getDirectionOfPreparation().getCode();
|
|
||||||
d.form = studyForm;
|
|
||||||
d.gekFio = g.getFullName();
|
|
||||||
data.add(d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return renderFileWith(Map.of("data", data), "doc_templates/questions_template.docx");
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getTopicList(Long id) {
|
|
||||||
Defense defense = defenseRepository.findByIdThrow(id);
|
|
||||||
DirectionOfPreparation prep = defense.getDirectionOfPreparation();
|
|
||||||
List<DiplomaTopic> topics = entityManager.createQuery("select dt from DiplomaTopic dt where dt.directionOfPreparation.id = :id", DiplomaTopic.class)
|
|
||||||
.setParameter("id", prep.getId())
|
|
||||||
.getResultList();
|
|
||||||
|
|
||||||
String prepCode = prep.getCode();
|
|
||||||
String prepName = prep.getName();
|
|
||||||
NumberingRenderData diplomaTopics = new NumberingRenderData(
|
|
||||||
NumberingFormat.DECIMAL,
|
|
||||||
topics.stream()
|
|
||||||
.map(DiplomaTopic::getName)
|
|
||||||
.map(n -> n + ".")
|
|
||||||
.map(n -> {
|
|
||||||
ParagraphRenderData paragraphRenderData = new ParagraphRenderData();
|
|
||||||
paragraphRenderData.setContents(Collections.singletonList(new TextRenderData(n)));
|
|
||||||
return paragraphRenderData;
|
|
||||||
}).toList()
|
|
||||||
);
|
|
||||||
|
|
||||||
return renderFileWith(Map.of(
|
|
||||||
"prep_code", prepCode,
|
|
||||||
"prep_name", prepName,
|
|
||||||
"diploma_topics", diplomaTopics
|
|
||||||
), "doc_templates/diploma_topic_list_template.docx");
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getStudList(Long id, String stepName) {
|
|
||||||
Defense defense = defenseRepository.findByIdThrow(id);
|
|
||||||
|
|
||||||
Map<Integer, List<StudentData>> studentByProtDay = new HashMap<>();
|
|
||||||
defense.getGroups().stream().map(Group::getStudents).flatMap(List::stream).forEach(student -> {
|
|
||||||
Integer protectionDay = student.getProtectionDay();
|
|
||||||
List<StudentData> array = studentByProtDay.computeIfAbsent(protectionDay, k -> new ArrayList<>());
|
|
||||||
array.add(student);
|
|
||||||
});
|
|
||||||
|
|
||||||
List<ProtDay> days = new ArrayList<>();
|
|
||||||
LocalDate defenseDate = defense.getDefenseDate();
|
|
||||||
int dayOfMonth = defenseDate.getDayOfMonth();
|
|
||||||
int month = defenseDate.getMonthValue();
|
|
||||||
int year = defenseDate.getYear();
|
|
||||||
DirectionOfPreparation directionOfPreparation = defense.getDirectionOfPreparation();
|
|
||||||
String prepCode = directionOfPreparation.getCode();
|
|
||||||
String prepName = directionOfPreparation.getName();
|
|
||||||
|
|
||||||
for (Map.Entry<Integer, List<StudentData>> entry : studentByProtDay.entrySet()) {
|
|
||||||
if (entry.getKey() == null) continue;
|
|
||||||
int protDay = entry.getKey() + dayOfMonth - 1;
|
|
||||||
ProtDay day = new ProtDay();
|
|
||||||
day.setDay(Integer.toString(protDay));
|
|
||||||
day.setMonth(getMonthNameByValue(month));
|
|
||||||
day.setYear(Integer.toString(year));
|
|
||||||
day.setStepName(stepName);
|
|
||||||
day.setPrepCode(prepCode);
|
|
||||||
day.setPrepName(prepName);
|
|
||||||
makeTable(day, entry);
|
|
||||||
days.add(day);
|
|
||||||
}
|
|
||||||
|
|
||||||
return renderFileWith(Map.of("prot_day", days), "doc_templates/student_list_template.docx");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void makeTable(ProtDay day, Map.Entry<Integer, List<StudentData>> entry) {
|
|
||||||
TableStyle tableStyle = new TableStyle();
|
|
||||||
tableStyle.setWidth("100%");
|
|
||||||
tableStyle.setColWidths(new int[]{
|
|
||||||
UnitUtils.cm2Twips(0.8), UnitUtils.cm2Twips(4.7), UnitUtils.cm2Twips(3.25), UnitUtils.cm2Twips(9.5),
|
|
||||||
UnitUtils.cm2Twips(1.75), UnitUtils.cm2Twips(2d), UnitUtils.cm2Twips(1d), UnitUtils.cm2Twips(1.5),
|
|
||||||
UnitUtils.cm2Twips(1.25), UnitUtils.cm2Twips(1.25), UnitUtils.cm2Twips(1.50)
|
|
||||||
});
|
|
||||||
|
|
||||||
List<RowRenderData> rows = new ArrayList<>();
|
|
||||||
rows.add(Rows.of(
|
|
||||||
"№", "ФИО\nстудента", "ФИО\nруководителя", "Тема", "Оценок\n5/4/3", "Коммен-\nтарий",
|
|
||||||
"Оц. рук.", "Оц. чл. ГЭК", "ИТОГ", "Дипл. с отл.", "Реком. магист."
|
|
||||||
).center().textBold().textFontSize(10).create());
|
|
||||||
int i = 1;
|
|
||||||
for (StudentData stud : entry.getValue()) {
|
|
||||||
Rows.RowBuilder row = Rows.of(
|
|
||||||
i++ + ".",
|
|
||||||
stud.getParticipant().getFullName(),
|
|
||||||
(stud.getCurator() == null ? "" : stud.getCurator().getParticipant().getShortName()),
|
|
||||||
(stud.getDiplomaTopic() == null ? "" : stud.getDiplomaTopic().getName()),
|
|
||||||
("%s/%s/%s".formatted(stud.getMarks5() == null ? "-" : stud.getMarks5(), stud.getMarks4() == null ? "-" : stud.getMarks4(), stud.getMarks3() == null ? "-" : stud.getMarks3())),
|
|
||||||
(stud.getVnedreniye() ? "Заявка, акт о внедр." : ""),
|
|
||||||
(stud.getOtziv() == null ? "" : Integer.toString(stud.getOtziv()))
|
|
||||||
, "", "",
|
|
||||||
stud.getOtlichiye() ? "да" : ""
|
|
||||||
).textFontSize(10).center();
|
|
||||||
row.addCell(Cells.of(stud.getMagistracy() ? "да" : "").center().create());
|
|
||||||
rows.add(row.create());
|
|
||||||
}
|
|
||||||
|
|
||||||
day.setProtDayTable(Tables.of(rows.toArray(RowRenderData[]::new)).create());
|
|
||||||
day.getProtDayTable().setTableStyle(tableStyle);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
private byte[] renderFileWith(Map<String, Object> tags, String filename) {
|
|
||||||
try {
|
|
||||||
XWPFTemplate template = XWPFTemplate
|
|
||||||
.compile(getClass().getClassLoader().getResource(filename).openStream())
|
|
||||||
.render(tags);
|
|
||||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
|
||||||
template.write(stream);
|
|
||||||
return stream.toByteArray();
|
|
||||||
} catch (
|
|
||||||
Exception e) {
|
|
||||||
throw new BusinessException("Ошибка формирования документа", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getMonthNameByValue(int month) {
|
|
||||||
return switch (month) {
|
|
||||||
case 1 -> "Января";
|
|
||||||
case 2 -> "Февраля";
|
|
||||||
case 3 -> "Марта";
|
|
||||||
case 4 -> "Апреля";
|
|
||||||
case 5 -> "Мая";
|
|
||||||
case 6 -> "Июня";
|
|
||||||
case 7 -> "Июля";
|
|
||||||
case 8 -> "Августа";
|
|
||||||
case 9 -> "Сентября";
|
|
||||||
case 10 -> "Октября";
|
|
||||||
case 11 -> "Ноября";
|
|
||||||
case 12 -> "Декабря";
|
|
||||||
default -> String.valueOf(month);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private CellRenderData createCell(String text) {
|
|
||||||
return createCell(text, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private CellRenderData createCell(String text, CellStyle cellStyle) {
|
|
||||||
CellRenderData cellRenderData = new CellRenderData();
|
|
||||||
if (cellStyle != null) {
|
|
||||||
cellRenderData.setCellStyle(cellStyle);
|
|
||||||
}
|
|
||||||
ParagraphRenderData paragraph = new ParagraphRenderData();
|
|
||||||
paragraph.setContents(Collections.singletonList(new TextRenderData(text)));
|
|
||||||
cellRenderData.setParagraphs(Collections.singletonList(paragraph));
|
|
||||||
return cellRenderData;
|
|
||||||
}
|
|
||||||
|
|
||||||
private CellStyle boldCenter() {
|
|
||||||
Style style = new Style();
|
|
||||||
style.setBold(true);
|
|
||||||
ParagraphStyle paragraphStyle = new ParagraphStyle();
|
|
||||||
paragraphStyle.setAlign(ParagraphAlignment.BOTH);
|
|
||||||
paragraphStyle.setGlyphStyle(style);
|
|
||||||
CellStyle boldStyle = new CellStyle();
|
|
||||||
boldStyle.setDefaultParagraphStyle(paragraphStyle);
|
|
||||||
return boldStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
private CellStyle normalCenter() {
|
|
||||||
Style style = new Style();
|
|
||||||
style.setBold(false);
|
|
||||||
ParagraphStyle paragraphStyle = new ParagraphStyle();
|
|
||||||
paragraphStyle.setAlign(ParagraphAlignment.BOTH);
|
|
||||||
paragraphStyle.setGlyphStyle(style);
|
|
||||||
CellStyle boldStyle = new CellStyle();
|
|
||||||
boldStyle.setDefaultParagraphStyle(paragraphStyle);
|
|
||||||
return boldStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
class ProtDay {
|
|
||||||
private String day;
|
|
||||||
private String month;
|
|
||||||
private String year;
|
|
||||||
private String stepName;
|
|
||||||
private String prepCode;
|
|
||||||
private String prepName;
|
|
||||||
private TableRenderData protDayTable = new TableRenderData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,178 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.business.service;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.mail.SimpleMailMessage;
|
|
||||||
import org.springframework.mail.javamail.JavaMailSender;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import ru.mskobaro.tdms.business.entity.MessageTemplate;
|
|
||||||
import ru.mskobaro.tdms.business.entity.StudentData;
|
|
||||||
import ru.mskobaro.tdms.business.entity.TeacherData;
|
|
||||||
import ru.mskobaro.tdms.integration.database.MessageTemplateRepository;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class EmailService {
|
|
||||||
@Autowired
|
|
||||||
private JavaMailSender mailSender;
|
|
||||||
@Autowired
|
|
||||||
private MessageTemplateRepository messageTemplateRepository;
|
|
||||||
@Value("${application.smtp.message-from}")
|
|
||||||
private String from;
|
|
||||||
|
|
||||||
public void sendEmail(String to, String subject, String text) {
|
|
||||||
SimpleMailMessage message = new SimpleMailMessage();
|
|
||||||
message.setFrom(from);
|
|
||||||
message.setTo(to);
|
|
||||||
message.setSubject(subject);
|
|
||||||
message.setText(text);
|
|
||||||
mailSender.send(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendTopicPreparationStartMessage(TeacherData curator) {
|
|
||||||
MessageTemplate messageTemplate = messageTemplateRepository.findByMessageType(
|
|
||||||
MessageTemplate.MessageType.TOPIC_LIST_PREPARE_START_FOR_TEACHER
|
|
||||||
);
|
|
||||||
|
|
||||||
String message = messageTemplate.getMessageTemplate();
|
|
||||||
String subject = messageTemplate.getSubjectTemplate();
|
|
||||||
message = message.replaceAll("\\$\\$\\{ФИО_НАУЧ_РУК}", curator.getParticipant().getFullName());
|
|
||||||
subject = subject.replaceAll("\\$\\$\\{ФИО_НАУЧ_РУК}", curator.getParticipant().getFullName());
|
|
||||||
sendEmail(curator.getParticipant().getEmail(), subject, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendTopicChoosingStartMessage(TeacherData curator, StudentData student) {
|
|
||||||
MessageTemplate messageTemplate = messageTemplateRepository.findByMessageType(
|
|
||||||
MessageTemplate.MessageType.TOPIC_CHOOSE_FOR_TEACHER
|
|
||||||
);
|
|
||||||
String message = messageTemplate.getMessageTemplate();
|
|
||||||
String subject = messageTemplate.getSubjectTemplate();
|
|
||||||
message = message.replaceAll("\\$\\$\\{ФИО_НАУЧ_РУК}", curator.getParticipant().getFullName());
|
|
||||||
subject = subject.replaceAll("\\$\\$\\{ФИО_НАУЧ_РУК}", curator.getParticipant().getFullName());
|
|
||||||
sendEmail(curator.getParticipant().getEmail(), subject, message);
|
|
||||||
|
|
||||||
messageTemplate = messageTemplateRepository.findByMessageType(
|
|
||||||
MessageTemplate.MessageType.TOPIC_CHOOSE_FOR_STUDENT
|
|
||||||
);
|
|
||||||
message = messageTemplate.getMessageTemplate();
|
|
||||||
subject = messageTemplate.getSubjectTemplate();
|
|
||||||
message = message.replaceAll("\\$\\$\\{ФИО_СТУД}", student.getParticipant().getFullName());
|
|
||||||
subject = subject.replaceAll("\\$\\$\\{ФИО_СТУД}", student.getParticipant().getFullName());
|
|
||||||
sendEmail(student.getParticipant().getEmail(), subject, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendTaskCreatingMessage(TeacherData curator) {
|
|
||||||
MessageTemplate messageTemplate = messageTemplateRepository.findByMessageType(
|
|
||||||
MessageTemplate.MessageType.TASK_CREATE_FOR_TEACHER
|
|
||||||
);
|
|
||||||
|
|
||||||
String message = messageTemplate.getMessageTemplate();
|
|
||||||
String subject = messageTemplate.getSubjectTemplate();
|
|
||||||
message = message.replaceAll("\\$\\$\\{ФИО_НАУЧ_РУК}", curator.getParticipant().getFullName());
|
|
||||||
subject = subject.replaceAll("\\$\\$\\{ФИО_НАУЧ_РУК}", curator.getParticipant().getFullName());
|
|
||||||
sendEmail(curator.getParticipant().getEmail(), subject, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendTaskAssigningMessage(TeacherData curator) {
|
|
||||||
MessageTemplate messageTemplate = messageTemplateRepository.findByMessageType(
|
|
||||||
MessageTemplate.MessageType.TASK_ASSIGN_FOR_TEACHER
|
|
||||||
);
|
|
||||||
|
|
||||||
String message = messageTemplate.getMessageTemplate();
|
|
||||||
String subject = messageTemplate.getSubjectTemplate();
|
|
||||||
message = message.replaceAll("\\$\\$\\{ФИО_НАУЧ_РУК}", curator.getParticipant().getFullName());
|
|
||||||
subject = subject.replaceAll("\\$\\$\\{ФИО_НАУЧ_РУК}", curator.getParticipant().getFullName());
|
|
||||||
sendEmail(curator.getParticipant().getEmail(), subject, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendPreDiplomaPracticeMessage(TeacherData curator, StudentData student) {
|
|
||||||
MessageTemplate messageTemplate = messageTemplateRepository.findByMessageType(
|
|
||||||
MessageTemplate.MessageType.PRE_DIPLOMA_PRACTICE_START_FOR_TEACHER
|
|
||||||
);
|
|
||||||
String message = messageTemplate.getMessageTemplate();
|
|
||||||
String subject = messageTemplate.getSubjectTemplate();
|
|
||||||
message = message.replaceAll("\\$\\$\\{ФИО_НАУЧ_РУК}", curator.getParticipant().getFullName());
|
|
||||||
subject = subject.replaceAll("\\$\\$\\{ФИО_НАУЧ_РУК}", curator.getParticipant().getFullName());
|
|
||||||
sendEmail(curator.getParticipant().getEmail(), subject, message);
|
|
||||||
|
|
||||||
messageTemplate = messageTemplateRepository.findByMessageType(
|
|
||||||
MessageTemplate.MessageType.PRE_DIPLOMA_PRACTICE_START_FOR_STUDENT
|
|
||||||
);
|
|
||||||
message = messageTemplate.getMessageTemplate();
|
|
||||||
subject = messageTemplate.getSubjectTemplate();
|
|
||||||
message = message.replaceAll("\\$\\$\\{ФИО_СТУД}", student.getParticipant().getFullName());
|
|
||||||
subject = subject.replaceAll("\\$\\$\\{ФИО_СТУД}", student.getParticipant().getFullName());
|
|
||||||
sendEmail(student.getParticipant().getEmail(), subject, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendTopicFinalizationMessage(TeacherData curator) {
|
|
||||||
MessageTemplate messageTemplate = messageTemplateRepository.findByMessageType(
|
|
||||||
MessageTemplate.MessageType.TOPIC_FINALIZATION_FOR_TEACHER
|
|
||||||
);
|
|
||||||
|
|
||||||
String message = messageTemplate.getMessageTemplate();
|
|
||||||
String subject = messageTemplate.getSubjectTemplate();
|
|
||||||
message = message.replaceAll("\\$\\$\\{ФИО_НАУЧ_РУК}", curator.getParticipant().getFullName());
|
|
||||||
subject = subject.replaceAll("\\$\\$\\{ФИО_НАУЧ_РУК}", curator.getParticipant().getFullName());
|
|
||||||
sendEmail(curator.getParticipant().getEmail(), subject, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendMainVrkWorkMessage(StudentData student) {
|
|
||||||
MessageTemplate messageTemplate = messageTemplateRepository.findByMessageType(
|
|
||||||
MessageTemplate.MessageType.MAIN_VRK_WORK_START
|
|
||||||
);
|
|
||||||
String message = messageTemplate.getMessageTemplate();
|
|
||||||
String subject = messageTemplate.getSubjectTemplate();
|
|
||||||
message = message.replaceAll("\\$\\$\\{ФИО_СТУД}", student.getParticipant().getFullName());
|
|
||||||
subject = subject.replaceAll("\\$\\$\\{ФИО_СТУД}", student.getParticipant().getFullName());
|
|
||||||
sendEmail(student.getParticipant().getEmail(), subject, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendPreDefenseStartMessage(StudentData student) {
|
|
||||||
MessageTemplate messageTemplate = messageTemplateRepository.findByMessageType(
|
|
||||||
MessageTemplate.MessageType.PRE_DEFENSE_FOR_STUDENT
|
|
||||||
);
|
|
||||||
String message = messageTemplate.getMessageTemplate();
|
|
||||||
String subject = messageTemplate.getSubjectTemplate();
|
|
||||||
message = message.replaceAll("\\$\\$\\{ФИО_СТУД}", student.getParticipant().getFullName());
|
|
||||||
subject = subject.replaceAll("\\$\\$\\{ФИО_СТУД}", student.getParticipant().getFullName());
|
|
||||||
sendEmail(student.getParticipant().getEmail(), subject, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendNormcontrolAndAntiplagiarismMessage(StudentData student) {
|
|
||||||
MessageTemplate messageTemplate = messageTemplateRepository.findByMessageType(
|
|
||||||
MessageTemplate.MessageType.NORMCONTROL_AND_ANTIPLAGIARISM
|
|
||||||
);
|
|
||||||
String message = messageTemplate.getMessageTemplate();
|
|
||||||
String subject = messageTemplate.getSubjectTemplate();
|
|
||||||
message = message.replaceAll("\\$\\$\\{ФИО_СТУД}", student.getParticipant().getFullName());
|
|
||||||
subject = subject.replaceAll("\\$\\$\\{ФИО_СТУД}", student.getParticipant().getFullName());
|
|
||||||
sendEmail(student.getParticipant().getEmail(), subject, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendDefensePreparationMessage(StudentData student) {
|
|
||||||
MessageTemplate messageTemplate = messageTemplateRepository.findByMessageType(MessageTemplate.MessageType.DEFENSE_PREPARATION_FOR_STUDENT);
|
|
||||||
String message = messageTemplate.getMessageTemplate();
|
|
||||||
String subject = messageTemplate.getSubjectTemplate();
|
|
||||||
message = message.replaceAll("\\$\\$\\{ФИО_СТУД}", student.getParticipant().getFullName());
|
|
||||||
subject = subject.replaceAll("\\$\\$\\{ФИО_СТУД}", student.getParticipant().getFullName());
|
|
||||||
sendEmail(student.getParticipant().getEmail(), subject, message);
|
|
||||||
|
|
||||||
messageTemplate = messageTemplateRepository.findByMessageType(MessageTemplate.MessageType.DEFENSE_PREPARATION_FOR_TEACHER);
|
|
||||||
message = messageTemplate.getMessageTemplate();
|
|
||||||
subject = messageTemplate.getSubjectTemplate();
|
|
||||||
message = message.replaceAll("\\$\\$\\{ФИО_НАУЧ_РУК}", student.getCurator().getParticipant().getFullName());
|
|
||||||
subject = subject.replaceAll("\\$\\$\\{ФИО_НАУЧ_РУК}", student.getCurator().getParticipant().getFullName());
|
|
||||||
sendEmail(student.getCurator().getParticipant().getEmail(), subject, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendDefenseMessage(StudentData student) {
|
|
||||||
MessageTemplate messageTemplate = messageTemplateRepository.findByMessageType(
|
|
||||||
MessageTemplate.MessageType.DEFENSE
|
|
||||||
);
|
|
||||||
String message = messageTemplate.getMessageTemplate();
|
|
||||||
String subject = messageTemplate.getSubjectTemplate();
|
|
||||||
message = message.replaceAll("\\$\\$\\{ФИО_СТУД}", student.getParticipant().getFullName());
|
|
||||||
subject = subject.replaceAll("\\$\\$\\{ФИО_СТУД}", student.getParticipant().getFullName());
|
|
||||||
sendEmail(student.getParticipant().getEmail(), subject, message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -13,8 +13,8 @@ import ru.mskobaro.tdms.business.exception.BusinessException;
|
|||||||
import ru.mskobaro.tdms.integration.database.GroupRepository;
|
import ru.mskobaro.tdms.integration.database.GroupRepository;
|
||||||
import ru.mskobaro.tdms.integration.database.PreparationDirectionRepository;
|
import ru.mskobaro.tdms.integration.database.PreparationDirectionRepository;
|
||||||
import ru.mskobaro.tdms.integration.database.StudentDataRepository;
|
import ru.mskobaro.tdms.integration.database.StudentDataRepository;
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.GroupDTO;
|
import ru.mskobaro.tdms.presentation.controller.payload.GroupDTO;
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.StudentDataDTO;
|
import ru.mskobaro.tdms.presentation.controller.payload.StudentDataDTO;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|||||||
@ -1,59 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.business.service;
|
|
||||||
|
|
||||||
import jakarta.persistence.EntityManager;
|
|
||||||
import jakarta.persistence.PersistenceContext;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import ru.mskobaro.tdms.business.entity.Defense;
|
|
||||||
import ru.mskobaro.tdms.business.entity.Group;
|
|
||||||
import ru.mskobaro.tdms.integration.controller.HomeInfoController;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class HomeInfoService {
|
|
||||||
@PersistenceContext
|
|
||||||
private EntityManager entityManager;
|
|
||||||
|
|
||||||
public HomeInfoController.DefaultInfo defaultInfo() {
|
|
||||||
HomeInfoController.DefaultInfo defaultInfo = new HomeInfoController.DefaultInfo();
|
|
||||||
|
|
||||||
Long userCount = entityManager
|
|
||||||
.createQuery("select count(*) from User u", Long.class)
|
|
||||||
.getSingleResult();
|
|
||||||
Long particCount = entityManager
|
|
||||||
.createQuery("select count(*) from Participant u", Long.class)
|
|
||||||
.getSingleResult();
|
|
||||||
defaultInfo.setParticCount(particCount);
|
|
||||||
defaultInfo.setUserCount(userCount);
|
|
||||||
|
|
||||||
Long teacherCount = entityManager
|
|
||||||
.createQuery("select count(*) from TeacherData td", Long.class)
|
|
||||||
.getSingleResult();
|
|
||||||
Long studentCount = entityManager
|
|
||||||
.createQuery("select count(*) from StudentData sd", Long.class)
|
|
||||||
.getSingleResult();
|
|
||||||
defaultInfo.setTeacherCount(teacherCount);
|
|
||||||
defaultInfo.setStudentCount(studentCount);
|
|
||||||
|
|
||||||
Long defenseCount = entityManager
|
|
||||||
.createQuery("select count(*) from Defense d", Long.class)
|
|
||||||
.getSingleResult();
|
|
||||||
defaultInfo.setDefenseCount(defenseCount);
|
|
||||||
|
|
||||||
Long currentDefenseCount = entityManager
|
|
||||||
.createQuery("select count(*) from Defense d where d.status not in :statuses", Long.class)
|
|
||||||
.setParameter("statuses", List.of(Defense.Status.FINISHED, Defense.Status.NOT_STARTED))
|
|
||||||
.getSingleResult();
|
|
||||||
defaultInfo.setCurrentDefenseCount(currentDefenseCount);
|
|
||||||
|
|
||||||
List<Group> currentDefenseGroups = entityManager
|
|
||||||
.createQuery("select d.groups from Defense d where d.status not in :statuses", Group.class)
|
|
||||||
.setParameter("statuses", List.of(Defense.Status.FINISHED, Defense.Status.NOT_STARTED))
|
|
||||||
.getResultList();
|
|
||||||
String currentDefenseGroupNames = currentDefenseGroups.stream().map(Group::getName).collect(Collectors.joining(", "));
|
|
||||||
defaultInfo.setCurrentDefenseGroupNames(currentDefenseGroupNames);
|
|
||||||
|
|
||||||
return defaultInfo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,11 +1,9 @@
|
|||||||
package ru.mskobaro.tdms.business.service;
|
package ru.mskobaro.tdms.business.service;
|
||||||
|
|
||||||
import jakarta.persistence.EntityManager;
|
import io.micrometer.common.util.StringUtils;
|
||||||
import jakarta.persistence.PersistenceContext;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.commons.collections4.ListUtils;
|
import org.apache.commons.collections4.ListUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@ -13,8 +11,8 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
import ru.mskobaro.tdms.business.entity.*;
|
import ru.mskobaro.tdms.business.entity.*;
|
||||||
import ru.mskobaro.tdms.business.exception.AccessDeniedException;
|
import ru.mskobaro.tdms.business.exception.AccessDeniedException;
|
||||||
import ru.mskobaro.tdms.business.exception.BusinessException;
|
import ru.mskobaro.tdms.business.exception.BusinessException;
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.ParticipantSaveDTO;
|
|
||||||
import ru.mskobaro.tdms.integration.database.*;
|
import ru.mskobaro.tdms.integration.database.*;
|
||||||
|
import ru.mskobaro.tdms.presentation.controller.payload.ParticipantSaveDTO;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -43,18 +41,6 @@ public class ParticipantService {
|
|||||||
private AuthenticationService authenticationService;
|
private AuthenticationService authenticationService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private TeacherDataRepository teacherDataRepository;
|
private TeacherDataRepository teacherDataRepository;
|
||||||
@Autowired
|
|
||||||
private CommissionMemberRepository commissionMemberRepository;
|
|
||||||
@PersistenceContext
|
|
||||||
private EntityManager entityManager;
|
|
||||||
@Autowired
|
|
||||||
private EmailService emailService;
|
|
||||||
@Autowired
|
|
||||||
private TaskService taskService;
|
|
||||||
@Autowired
|
|
||||||
private DefenseRepository defenseRepository;
|
|
||||||
@Autowired
|
|
||||||
private DefenseService defenseService;
|
|
||||||
|
|
||||||
public ParticipantService(ParticipantRepository participantRepository) {
|
public ParticipantService(ParticipantRepository participantRepository) {
|
||||||
this.participantRepository = participantRepository;
|
this.participantRepository = participantRepository;
|
||||||
@ -82,72 +68,30 @@ public class ParticipantService {
|
|||||||
participant.setFirstName(participantSaveDTO.getFirstName());
|
participant.setFirstName(participantSaveDTO.getFirstName());
|
||||||
participant.setLastName(participantSaveDTO.getLastName());
|
participant.setLastName(participantSaveDTO.getLastName());
|
||||||
participant.setMiddleName(participantSaveDTO.getMiddleName());
|
participant.setMiddleName(participantSaveDTO.getMiddleName());
|
||||||
|
|
||||||
if (!editMode
|
|
||||||
|| (!StringUtils.equals(participantSaveDTO.getEmail(), existingParticipant.getEmail())
|
|
||||||
|| !StringUtils.equals(participantSaveDTO.getNumberPhone(), existingParticipant.getNumberPhone()))) {
|
|
||||||
if (participantRepository.existsByNumberPhoneOrEmail(participantSaveDTO.getNumberPhone(), participantSaveDTO.getEmail())) {
|
|
||||||
throw new BusinessException("Номер телефона или Электронная почта уже используются");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
participant.setNumberPhone(participantSaveDTO.getNumberPhone());
|
participant.setNumberPhone(participantSaveDTO.getNumberPhone());
|
||||||
participant.setEmail(participantSaveDTO.getEmail());
|
participant.setEmail(participantSaveDTO.getEmail());
|
||||||
|
|
||||||
List<Role> roles = persistRoles(participantSaveDTO, existingParticipant, editMode, callerUser, participant);
|
List<Role> roles = persistRoles(participantSaveDTO, existingParticipant, editMode, callerUser, participant);
|
||||||
StudentData studentData = persistStudentData(participantSaveDTO, existingParticipant, editMode, roles, participant);
|
boolean credentialsChanged = persistUserData(participantSaveDTO, existingParticipant, editMode, participant);
|
||||||
|
persistStudentData(participantSaveDTO, existingParticipant, editMode, roles, participant);
|
||||||
persistTeacherData(participantSaveDTO, existingParticipant, editMode, roles, participant);
|
persistTeacherData(participantSaveDTO, existingParticipant, editMode, roles, participant);
|
||||||
persistCommissionData(participantSaveDTO, existingParticipant, editMode, roles, participant);
|
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: notification task
|
||||||
Participant saved = participantRepository.save(participant);
|
Participant saved = participantRepository.save(participant);
|
||||||
|
log.info("Participant saved: {}", saved.getFullName());
|
||||||
boolean credentialsChanged = persistUserData(participantSaveDTO, saved, editMode, participant);
|
|
||||||
|
|
||||||
if (credentialsChanged) {
|
if (credentialsChanged) {
|
||||||
log.info("User {} changed credentials, logging out", saved.getUser().getUsername());
|
log.info("User {} changed credentials, logging out", saved.getUser().getUsername());
|
||||||
authenticationService.logout(saved.getUser().getUsername());
|
authenticationService.logout(saved.getUser().getUsername());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!editMode && participantSaveDTO.getUserData() != null) {
|
|
||||||
emailService.sendEmail(saved.getEmail(), "Вам была создана учетная запись в системе поддержки ВКР", """
|
|
||||||
Уважаемый, %s,
|
|
||||||
Вам была создана учетная запись в системе подготовки и защиты ВКР.
|
|
||||||
Ниже представлены данные для входа в систему:
|
|
||||||
Логин: %s
|
|
||||||
Пароль: %s
|
|
||||||
|
|
||||||
С уважением, администрация.
|
|
||||||
""".formatted(participant.getFullName(), participant.getUser().getUsername(), participantSaveDTO.getUserData().getPassword()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (studentData != null) {
|
|
||||||
studentData.setParticipant(saved);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (studentData != null && studentData.getGroup() != null) {
|
|
||||||
List<Defense> defenses = entityManager.createQuery("select distinct d from Defense d inner join fetch d.groups g where g.id = :id", Defense.class)
|
|
||||||
.setParameter("id", studentData.getGroup().getId())
|
|
||||||
.getResultList();
|
|
||||||
Defense defense = null;
|
|
||||||
if (defenses != null && !defenses.isEmpty()) {
|
|
||||||
defense = defenses.get(0);
|
|
||||||
}
|
|
||||||
if (defense != null && defense.isStateShouldBeProcessed(Defense.Status.TOPIC_CHOOSING)) {
|
|
||||||
taskService.checkAndCreateTopicChoosingTasksAndSendEmail(Collections.singletonList(studentData), defense);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log.info("Participant saved: {}", saved.getFullName());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Role> persistRoles(ParticipantSaveDTO participantSaveDTO, Participant existingParticipant, boolean editMode, User callerUser, Participant participant) {
|
private List<Role> persistRoles(ParticipantSaveDTO participantSaveDTO, Participant existingParticipant, boolean editMode, User callerUser, Participant participant) {
|
||||||
boolean isAdmin = roleService.isParticInAuthority(callerUser.getParticipant(), RoleService.Authority.ADMIN);
|
boolean isAdmin = roleService.isParticInAuthority(callerUser.getParticipant(), RoleService.Authority.ADMIN);
|
||||||
boolean isSecretary = roleService.isParticInAuthority(callerUser.getParticipant(), RoleService.Authority.SECRETARY);
|
boolean isSecretary = roleService.isParticInAuthority(callerUser.getParticipant(), RoleService.Authority.SECRETARY);
|
||||||
boolean isTeacher = roleService.isParticInAuthority(callerUser.getParticipant(), RoleService.Authority.TEACHER);
|
|
||||||
boolean isOwner = existingParticipant != null && existingParticipant.getUser() != null
|
boolean isOwner = existingParticipant != null && existingParticipant.getUser() != null
|
||||||
&& existingParticipant.getUser().getId().equals(callerUser.getId());
|
&& existingParticipant.getUser().getId().equals(callerUser.getId());
|
||||||
if (!isAdmin && !isSecretary && !isOwner && !isTeacher)
|
if (!isAdmin && !isSecretary && !isOwner)
|
||||||
throw new AccessDeniedException();
|
throw new AccessDeniedException();
|
||||||
if (participantSaveDTO.getAuthorities() != null && participantSaveDTO.getAuthorities().contains(RoleService.Authority.ADMIN) && !isAdmin)
|
if (participantSaveDTO.getAuthorities() != null && participantSaveDTO.getAuthorities().contains(RoleService.Authority.ADMIN) && !isAdmin)
|
||||||
throw new AccessDeniedException("Недостаточно прав для назначения роли администратора");
|
throw new AccessDeniedException("Недостаточно прав для назначения роли администратора");
|
||||||
@ -225,11 +169,11 @@ public class ParticipantService {
|
|||||||
teacherData.setParticipant(participant);
|
teacherData.setParticipant(participant);
|
||||||
}
|
}
|
||||||
|
|
||||||
private StudentData persistStudentData(ParticipantSaveDTO participantSaveDTO, Participant existingParticipant, boolean editMode, List<Role> roles, Participant participant) {
|
private void persistStudentData(ParticipantSaveDTO participantSaveDTO, Participant existingParticipant, boolean editMode, List<Role> roles, Participant participant) {
|
||||||
boolean shouldPersistStudentData = participantSaveDTO.getStudentData() != null && roles != null
|
boolean shouldPersistStudentData = participantSaveDTO.getStudentData() != null && roles != null
|
||||||
&& CollectionUtils.containsAny(roles, roleService.getRoleByAuthority(RoleService.Authority.STUDENT));
|
&& CollectionUtils.containsAny(roles, roleService.getRoleByAuthority(RoleService.Authority.STUDENT));
|
||||||
if (!shouldPersistStudentData) {
|
if (!shouldPersistStudentData) {
|
||||||
return null;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean alreadyExists = editMode && studentDataRepository.existsByParticipant_IdAndParticipant_DeletedFalse(existingParticipant.getId());
|
boolean alreadyExists = editMode && studentDataRepository.existsByParticipant_IdAndParticipant_DeletedFalse(existingParticipant.getId());
|
||||||
@ -240,21 +184,6 @@ public class ParticipantService {
|
|||||||
studentData = new StudentData();
|
studentData = new StudentData();
|
||||||
}
|
}
|
||||||
|
|
||||||
studentData.setOtziv(participantSaveDTO.getStudentData().getOtziv());
|
|
||||||
studentData.setWork(participantSaveDTO.getStudentData().getWork());
|
|
||||||
studentData.setZachetka(participantSaveDTO.getStudentData().getZachetka());
|
|
||||||
studentData.setPreDefenseMark(participantSaveDTO.getStudentData().getPreDefenseMark());
|
|
||||||
studentData.setElectronic(participantSaveDTO.getStudentData().getElectronic());
|
|
||||||
studentData.setOtlichiye(participantSaveDTO.getStudentData().getOtlichiye());
|
|
||||||
studentData.setVnedreniye(participantSaveDTO.getStudentData().getVnedreniye());
|
|
||||||
studentData.setMagistracy(participantSaveDTO.getStudentData().getMagistracy());
|
|
||||||
|
|
||||||
studentData.setMarks5(participantSaveDTO.getStudentData().getMarks5());
|
|
||||||
studentData.setMarks4(participantSaveDTO.getStudentData().getMarks4());
|
|
||||||
studentData.setMarks3(participantSaveDTO.getStudentData().getMarks3());
|
|
||||||
|
|
||||||
studentData = studentDataRepository.save(studentData);
|
|
||||||
|
|
||||||
if (participantSaveDTO.getStudentData().getGroupId() != null) {
|
if (participantSaveDTO.getStudentData().getGroupId() != null) {
|
||||||
Group group = groupRepository.findByIdThrow(participantSaveDTO.getStudentData().getGroupId());
|
Group group = groupRepository.findByIdThrow(participantSaveDTO.getStudentData().getGroupId());
|
||||||
studentData.setGroup(group);
|
studentData.setGroup(group);
|
||||||
@ -276,28 +205,8 @@ public class ParticipantService {
|
|||||||
studentData.setCurator(null);
|
studentData.setCurator(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return studentData;
|
studentData = studentDataRepository.save(studentData);
|
||||||
}
|
studentData.setParticipant(participant);
|
||||||
|
|
||||||
private void persistCommissionData(ParticipantSaveDTO participantSaveDTO, Participant existingParticipant, boolean editMode, List<Role> roles, Participant participant) {
|
|
||||||
boolean shouldPersist = participantSaveDTO.getCommMemData() != null && roles != null
|
|
||||||
&& CollectionUtils.containsAny(roles, roleService.getRoleByAuthority(RoleService.Authority.COMM_MEMBER));
|
|
||||||
if (!shouldPersist) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean alreadyExists = editMode && commissionMemberRepository.existsByParticipant_Id(existingParticipant.getId());
|
|
||||||
CommissionMemberData commMemData;
|
|
||||||
if (alreadyExists) {
|
|
||||||
commMemData = commissionMemberRepository.findByParticipant_Id(existingParticipant.getId());
|
|
||||||
} else {
|
|
||||||
commMemData = new CommissionMemberData();
|
|
||||||
}
|
|
||||||
|
|
||||||
commMemData.setWorkPlace(participantSaveDTO.getCommMemData().getWorkPlace());
|
|
||||||
commMemData.setWorkPosition(participantSaveDTO.getCommMemData().getWorkPosition());
|
|
||||||
commMemData = commissionMemberRepository.save(commMemData);
|
|
||||||
commMemData.setParticipant(participant);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteParticipant(Long id) {
|
public void deleteParticipant(Long id) {
|
||||||
@ -308,10 +217,4 @@ public class ParticipantService {
|
|||||||
Participant partic = participantRepository.findByIdThrow(id);
|
Participant partic = participantRepository.findByIdThrow(id);
|
||||||
partic.setDeleted(true);
|
partic.setDeleted(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Participant> getAllAntipl() {
|
|
||||||
return entityManager.createQuery("select p from Participant p inner join p.roles r where r.authority = :auth", Participant.class)
|
|
||||||
.setParameter("auth", RoleService.Authority.PLAGIARISM_CHECKER.getAuthority())
|
|
||||||
.getResultList();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,10 +4,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import ru.mskobaro.tdms.business.entity.DirectionOfPreparation;
|
import ru.mskobaro.tdms.business.entity.DirectionOfPreparation;
|
||||||
import ru.mskobaro.tdms.business.entity.TeacherData;
|
|
||||||
import ru.mskobaro.tdms.integration.database.PreparationDirectionRepository;
|
import ru.mskobaro.tdms.integration.database.PreparationDirectionRepository;
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.PreparationDirectionDTO;
|
import ru.mskobaro.tdms.presentation.controller.payload.PreparationDirectionDTO;
|
||||||
import ru.mskobaro.tdms.integration.database.TeacherDataRepository;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -16,8 +14,6 @@ import java.util.List;
|
|||||||
public class PreparationDirectionService {
|
public class PreparationDirectionService {
|
||||||
@Autowired
|
@Autowired
|
||||||
private PreparationDirectionRepository preparationDirectionRepository;
|
private PreparationDirectionRepository preparationDirectionRepository;
|
||||||
@Autowired
|
|
||||||
private TeacherDataRepository teacherDataRepository;
|
|
||||||
|
|
||||||
public List<DirectionOfPreparation> getAll() {
|
public List<DirectionOfPreparation> getAll() {
|
||||||
return preparationDirectionRepository.findAll();
|
return preparationDirectionRepository.findAll();
|
||||||
@ -31,15 +27,8 @@ public class PreparationDirectionService {
|
|||||||
} else {
|
} else {
|
||||||
preparationDirection = new DirectionOfPreparation();
|
preparationDirection = new DirectionOfPreparation();
|
||||||
}
|
}
|
||||||
|
|
||||||
TeacherData teacherData = null;
|
|
||||||
if (preparationDirectionDTO.getResponsible() != null && preparationDirectionDTO.getResponsible().getId() != null) {
|
|
||||||
teacherData = teacherDataRepository.findByIdThrow(preparationDirectionDTO.getResponsible().getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
preparationDirection.setName(preparationDirectionDTO.getName());
|
preparationDirection.setName(preparationDirectionDTO.getName());
|
||||||
preparationDirection.setCode(preparationDirectionDTO.getCode());
|
preparationDirection.setCode(preparationDirectionDTO.getCode());
|
||||||
preparationDirection.setResponsible(teacherData);
|
|
||||||
preparationDirectionRepository.save(preparationDirection);
|
preparationDirectionRepository.save(preparationDirection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,11 @@
|
|||||||
package ru.mskobaro.tdms.business.service;
|
package ru.mskobaro.tdms.business.service;
|
||||||
|
|
||||||
import jakarta.persistence.EntityManager;
|
|
||||||
import jakarta.persistence.PersistenceContext;
|
|
||||||
import jakarta.transaction.Transactional;
|
import jakarta.transaction.Transactional;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import ru.mskobaro.tdms.business.entity.Participant;
|
import ru.mskobaro.tdms.business.entity.Participant;
|
||||||
import ru.mskobaro.tdms.business.entity.StudentData;
|
import ru.mskobaro.tdms.business.entity.StudentData;
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.StudentDataDTO;
|
|
||||||
import ru.mskobaro.tdms.integration.database.StudentDataRepository;
|
import ru.mskobaro.tdms.integration.database.StudentDataRepository;
|
||||||
import ru.mskobaro.tdms.integration.database.UserRepository;
|
import ru.mskobaro.tdms.integration.database.UserRepository;
|
||||||
|
|
||||||
@ -21,8 +18,6 @@ import java.util.List;
|
|||||||
public class StudentDataService {
|
public class StudentDataService {
|
||||||
@Autowired
|
@Autowired
|
||||||
private StudentDataRepository studentDataRepository;
|
private StudentDataRepository studentDataRepository;
|
||||||
@PersistenceContext
|
|
||||||
private EntityManager entityManager;
|
|
||||||
|
|
||||||
public StudentData getStudentByParticIdThrow(Long particId) {
|
public StudentData getStudentByParticIdThrow(Long particId) {
|
||||||
return studentDataRepository.findStudentDataByParticipant_Id(particId);
|
return studentDataRepository.findStudentDataByParticipant_Id(particId);
|
||||||
@ -31,9 +26,4 @@ public class StudentDataService {
|
|||||||
public Collection<StudentData> getAllStudentsWithoutGroup() {
|
public Collection<StudentData> getAllStudentsWithoutGroup() {
|
||||||
return studentDataRepository.findByGroupIsNull();
|
return studentDataRepository.findByGroupIsNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<StudentData> getByDefenseId(Long id) {
|
|
||||||
return entityManager.createQuery("select sd from StudentData sd where sd.group.defense.id = :id", StudentData.class)
|
|
||||||
.setParameter("id", id).getResultList();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,18 +1,17 @@
|
|||||||
package ru.mskobaro.tdms.business.service;
|
package ru.mskobaro.tdms.business.service;
|
||||||
|
|
||||||
import jakarta.persistence.EntityManager;
|
|
||||||
import jakarta.persistence.PersistenceContext;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import ru.mskobaro.tdms.business.entity.*;
|
import ru.mskobaro.tdms.business.entity.StudentData;
|
||||||
import ru.mskobaro.tdms.business.exception.BusinessException;
|
import ru.mskobaro.tdms.business.entity.Task;
|
||||||
import ru.mskobaro.tdms.integration.controller.TaskController;
|
import ru.mskobaro.tdms.business.entity.User;
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.DefenseDTO;
|
import ru.mskobaro.tdms.business.taskfields.DiplomaTopicAgreementTaskFields;
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.IdDTO;
|
import ru.mskobaro.tdms.business.taskfields.TaskFields;
|
||||||
import ru.mskobaro.tdms.integration.database.*;
|
import ru.mskobaro.tdms.integration.database.StudentDataRepository;
|
||||||
|
import ru.mskobaro.tdms.integration.database.TaskRepository;
|
||||||
|
import ru.mskobaro.tdms.presentation.controller.TaskController;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@ -24,496 +23,41 @@ public class TaskService {
|
|||||||
private UserService userService;
|
private UserService userService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private StudentDataRepository studentDataRepository;
|
private StudentDataRepository studentDataRepository;
|
||||||
@PersistenceContext
|
|
||||||
private EntityManager entityManager;
|
|
||||||
@Autowired
|
|
||||||
private ParticipantRepository participantRepository;
|
|
||||||
@Autowired
|
|
||||||
private DiplomaTopicRepository diplomaTopicRepository;
|
|
||||||
@Autowired
|
|
||||||
private TeacherDataRepository teacherDataRepository;
|
|
||||||
@Autowired
|
|
||||||
private RoleService roleService;
|
|
||||||
@Autowired
|
|
||||||
private EmailService emailService;
|
|
||||||
@Autowired
|
|
||||||
private DefenseRepository defenseRepository;
|
|
||||||
|
|
||||||
public TopicAgreementTask findDiplomaTopicAgreementTaskMadeByCurrentUser() {
|
public void createTask(Task.Type type, Task.Status status, TaskFields taskFields) {
|
||||||
|
Task task = new Task();
|
||||||
|
task.setType(type);
|
||||||
|
task.setStatus(status);
|
||||||
|
task.setFields(taskFields);
|
||||||
|
taskRepository.save(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task findDiplomaTopicAgreementTaskCallerMaker() {
|
||||||
User user = userService.getCallerUser();
|
User user = userService.getCallerUser();
|
||||||
try {
|
List<Task> diplomaTopicAgreementTaskByMakerId = taskRepository.findDiplomaTopicAgreementTaskByMakerId(
|
||||||
return entityManager.createQuery("select t from TopicAgreementTask t where t.checkerParticId = :id or t.makerParticId = :id", TopicAgreementTask.class)
|
user.getParticipant().getId(), Task.Type.DIPLOMA_TOPIC_AGREEMENT
|
||||||
.setParameter("id", user.getParticipant().getId())
|
);
|
||||||
.setMaxResults(1)
|
if (diplomaTopicAgreementTaskByMakerId.isEmpty()) {
|
||||||
.getSingleResult();
|
|
||||||
} catch (Exception e) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private List<Task.Status> getNotShowStatuses() {
|
if (diplomaTopicAgreementTaskByMakerId.size() > 1) {
|
||||||
User user = userService.getCallerUser();
|
|
||||||
List<Task.Status> notShowStatuses = new ArrayList<>(List.of(Task.Status.DONE, Task.Status.CANCELED));
|
|
||||||
|
|
||||||
if (!roleService.isParticInAuthority(user.getParticipant(), RoleService.Authority.STUDENT)) {
|
|
||||||
notShowStatuses.add(Task.Status.WAIT_FOR_STUDENT_EDIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!roleService.isParticInAuthority(user.getParticipant(), RoleService.Authority.TEACHER)) {
|
|
||||||
notShowStatuses.add(Task.Status.WAIT_FOR_TOPIC_AGREEMENT);
|
|
||||||
}
|
|
||||||
return notShowStatuses;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getCurrentUserNotificationCount() {
|
|
||||||
return entityManager.createQuery(
|
|
||||||
"""
|
|
||||||
select count(t) from Task t where t.checkerParticId = :id
|
|
||||||
and t.status not in (:statuses)
|
|
||||||
""", Long.class)
|
|
||||||
.setParameter("id", userService.getCallerUser().getParticipant().getId())
|
|
||||||
.setParameter("statuses", getNotShowStatuses())
|
|
||||||
.getSingleResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<TaskController.TaskDTO> getAllCurrentTasks() {
|
|
||||||
List<Task> tasks = entityManager.createQuery(
|
|
||||||
"""
|
|
||||||
select t from Task t
|
|
||||||
inner join fetch t.defense
|
|
||||||
where t.checkerParticId = :id
|
|
||||||
and t.status not in (:statuses)
|
|
||||||
""", Task.class)
|
|
||||||
.setParameter("id", userService.getCallerUser().getParticipant().getId())
|
|
||||||
.setParameter("statuses", getNotShowStatuses())
|
|
||||||
.getResultList();
|
|
||||||
return tasks.stream().map(t -> {
|
|
||||||
TaskController.TaskDTO dto = new TaskController.TaskDTO();
|
|
||||||
dto.setId(t.getId());
|
|
||||||
dto.setStatus(t.getStatus());
|
|
||||||
dto.setMessage(getTaskMessage(t));
|
|
||||||
dto.setCheckerId(t.getCheckerParticId());
|
|
||||||
dto.setMakerId(t.getMakerParticId());
|
|
||||||
dto.setType(t.getType());
|
|
||||||
dto.setDefense(DefenseDTO.from(t.getDefense()));
|
|
||||||
|
|
||||||
if (t instanceof TopicAgreementTask tat) {
|
|
||||||
dto.setInfo(IdDTO.fromId(tat.getMakerParticId()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return dto;
|
|
||||||
}).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getTaskMessage(Task t) {
|
|
||||||
switch (t.getStatus()) {
|
|
||||||
case WAIT_FOR_TOPIC_PREPARATION -> {
|
|
||||||
return "Требуется указать темы ВКР, которые смогут выбрать студенты";
|
|
||||||
}
|
|
||||||
case WAIT_FOR_TOPIC_AGREEMENT -> {
|
|
||||||
Participant studentPartic = participantRepository.findByIdThrow(t.getMakerParticId());
|
|
||||||
return "Согласование темы ВКР со студентом %s".formatted(studentPartic.getFullName());
|
|
||||||
}
|
|
||||||
case WAIT_FOR_STUDENT_START -> {
|
|
||||||
return "Требуется согласовать тему с научным руководителем";
|
|
||||||
}
|
|
||||||
case WAIT_FOR_STUDENT_EDIT -> {
|
|
||||||
return "Научный руководитель отправил тему на доработку";
|
|
||||||
}
|
|
||||||
case WAIT_FOR_ANTIPL_PASSED -> {
|
|
||||||
Participant studPartic = participantRepository.findByIdThrow(t.getMakerParticId());
|
|
||||||
return "После прохождения антиплагиата требуется пометить этап указать уникальность работы (%s)".formatted(studPartic.getFullName());
|
|
||||||
}
|
|
||||||
case WAIT_FOR_NORMOCONTROL_PASSED -> {
|
|
||||||
Participant studPartic = participantRepository.findByIdThrow(t.getMakerParticId());
|
|
||||||
return "После прохождения нормоконтроля требуется пометить этап как проеденный (%s)".formatted(studPartic.getFullName());
|
|
||||||
}
|
|
||||||
case WAIT_FOR_TEACHER_OTZIV -> {
|
|
||||||
Participant studPartic = participantRepository.findByIdThrow(t.getMakerParticId());
|
|
||||||
return "Требуется предоставить отзыв студенту (%s)".formatted(studPartic.getFullName());
|
|
||||||
}
|
|
||||||
default -> { return t.getStatus().toString(); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void agreementChangeRequest(TaskController.DiplomaTopicAgreementChangeRequestDTO changeRequest) {
|
|
||||||
TopicAgreementTask topicAgreementTask = entityManager.createQuery(
|
|
||||||
"select t from TopicAgreementTask t where t.id = :id", TopicAgreementTask.class)
|
|
||||||
.setParameter("id", changeRequest.getTaskId())
|
|
||||||
.getSingleResult();
|
|
||||||
|
|
||||||
switch (changeRequest.getType()) {
|
|
||||||
case STUDENT_REDO -> {
|
|
||||||
if (changeRequest.getDiplomaTopicId() != null) {
|
|
||||||
topicAgreementTask.setDiplomaTopicId(changeRequest.getDiplomaTopicId());
|
|
||||||
topicAgreementTask.setDiplomaTopicName(null);
|
|
||||||
} else if (changeRequest.getDiplomaTopicName() != null) {
|
|
||||||
topicAgreementTask.setDiplomaTopicName(changeRequest.getDiplomaTopicName());
|
|
||||||
topicAgreementTask.setDiplomaTopicId(null);
|
|
||||||
} else {
|
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
Long checkerId = topicAgreementTask.getCheckerParticId();
|
|
||||||
StudentData student = studentDataRepository.findStudentDataByParticipant_Id(checkerId);
|
return diplomaTopicAgreementTaskByMakerId.get(0);
|
||||||
topicAgreementTask.setCheckerParticId(student.getCurator().getParticipant().getId());
|
|
||||||
topicAgreementTask.setMakerParticId(checkerId);
|
|
||||||
topicAgreementTask.setStatus(Task.Status.WAIT_FOR_TOPIC_AGREEMENT);
|
|
||||||
}
|
|
||||||
case TEACHER_APPROVE -> {
|
|
||||||
StudentData student = studentDataRepository.findStudentDataByParticipant_Id(topicAgreementTask.getMakerParticId());
|
|
||||||
if (topicAgreementTask.getDiplomaTopicId() != null) {
|
|
||||||
DiplomaTopic topic = diplomaTopicRepository.findByIdThrow(topicAgreementTask.getDiplomaTopicId());
|
|
||||||
student.setDiplomaTopic(topic);
|
|
||||||
topicAgreementTask.setStatus(Task.Status.DONE);
|
|
||||||
} else if (topicAgreementTask.getDiplomaTopicName() != null) {
|
|
||||||
TeacherData teacherData = teacherDataRepository.findByParticipant_Id(topicAgreementTask.getCheckerParticId());
|
|
||||||
DiplomaTopic diplomaTopic = new DiplomaTopic();
|
|
||||||
diplomaTopic.setName(topicAgreementTask.getDiplomaTopicName());
|
|
||||||
diplomaTopic.setTeacher(teacherData);
|
|
||||||
diplomaTopic.setDirectionOfPreparation(student.getGroup().getDirectionOfPreparation());
|
|
||||||
topicAgreementTask.setStatus(Task.Status.DONE);
|
|
||||||
diplomaTopic = diplomaTopicRepository.save(diplomaTopic);
|
|
||||||
student.setDiplomaTopic(diplomaTopic);
|
|
||||||
} else {
|
|
||||||
throw new BusinessException("Должна быть указана тема");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case TEACHER_REJECT -> {
|
|
||||||
Long checkerId = topicAgreementTask.getCheckerParticId();
|
|
||||||
topicAgreementTask.setCheckerParticId(topicAgreementTask.getMakerParticId());
|
|
||||||
topicAgreementTask.setMakerParticId(checkerId);
|
|
||||||
topicAgreementTask.setStatus(Task.Status.WAIT_FOR_STUDENT_EDIT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TopicAgreementTask getTopicAgreementTaskByMakerId(Long id) {
|
public void createDiplomaAgreementTask(TaskController.DiplomaTopicAgreementDTO diplomaTopicAgreementDTO) {
|
||||||
try {
|
DiplomaTopicAgreementTaskFields taskFields = new DiplomaTopicAgreementTaskFields();
|
||||||
return entityManager.createQuery("select t from TopicAgreementTask t where t.makerParticId = :id", TopicAgreementTask.class)
|
User user = userService.getCallerUser();
|
||||||
.setParameter("id", id)
|
StudentData studentData = studentDataRepository.findStudentDataByParticipant_Id(user.getParticipant().getId());
|
||||||
.setMaxResults(1)
|
|
||||||
.getSingleResult();
|
|
||||||
} catch (Exception e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkAndCreateTopicPreparationTasksAndSendEmail(List<TeacherData> teachers, Defense defense) {
|
taskFields.setCheckerParticipantId(user.getParticipant().getId());
|
||||||
for (TeacherData teacher : teachers) {
|
taskFields.setDiplomaTopicId(diplomaTopicAgreementDTO.getDiplomaTopicId());
|
||||||
Boolean exists = entityManager.createQuery("select case when (count(t) > 0) then true else false end from Task t where t.checkerParticId = :id and t.type = :type and t.defense = :defense", Boolean.class)
|
taskFields.setDiplomaTopicName(diplomaTopicAgreementDTO.getDiplomaTopicName());
|
||||||
.setParameter("id", teacher.getParticipant().getId())
|
taskFields.setCheckerParticipantId(studentData.getCurator().getId());
|
||||||
.setParameter("type", Task.Type.TOPIC_PREPARATION)
|
|
||||||
.setParameter("defense", defense)
|
|
||||||
.getSingleResult();
|
|
||||||
|
|
||||||
if (!exists) {
|
createTask(Task.Type.DIPLOMA_TOPIC_AGREEMENT, Task.Status.WAIT_FOR_TOPIC_AGREEMENT, taskFields);
|
||||||
Task task = new Task();
|
|
||||||
task.setDefense(defense);
|
|
||||||
task.setCheckerParticId(teacher.getParticipant().getId());
|
|
||||||
task.setType(Task.Type.TOPIC_PREPARATION);
|
|
||||||
task.setStatus(Task.Status.WAIT_FOR_TOPIC_PREPARATION);
|
|
||||||
taskRepository.save(task);
|
|
||||||
emailService.sendTopicPreparationStartMessage(teacher);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkAndCreateTopicChoosingTasksAndSendEmail(List<StudentData> students, Defense defense) {
|
|
||||||
students.stream().filter(studentData -> studentData.getCurator() == null).forEach((sd) -> {
|
|
||||||
throw new BusinessException("Студенту %s не назначен научный руководитель".formatted(sd.getParticipant().getFullName()));
|
|
||||||
});
|
|
||||||
|
|
||||||
for (StudentData student : students) {
|
|
||||||
Boolean exists = entityManager.createQuery("""
|
|
||||||
select case when (count(t) > 0) then true else false end from Task t
|
|
||||||
where (t.checkerParticId = :id or t.makerParticId = :id)
|
|
||||||
and t.type = :type
|
|
||||||
and t.defense = :defense
|
|
||||||
""", Boolean.class)
|
|
||||||
.setParameter("id", student.getParticipant().getId())
|
|
||||||
.setParameter("type", Task.Type.TOPIC_AGREEMENT)
|
|
||||||
.setParameter("defense", defense)
|
|
||||||
.getSingleResult();
|
|
||||||
|
|
||||||
if (!exists) {
|
|
||||||
TopicAgreementTask topicAgreementTask = new TopicAgreementTask();
|
|
||||||
topicAgreementTask.setCheckerParticId(student.getParticipant().getId());
|
|
||||||
topicAgreementTask.setType(Task.Type.TOPIC_AGREEMENT);
|
|
||||||
topicAgreementTask.setStatus(Task.Status.WAIT_FOR_STUDENT_START);
|
|
||||||
topicAgreementTask.setDefense(defense);
|
|
||||||
taskRepository.save(topicAgreementTask);
|
|
||||||
emailService.sendTopicChoosingStartMessage(student.getCurator(), student);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkAndCreateTaskCreatingTask(List<TeacherData> curators, Defense defense) {
|
|
||||||
for (TeacherData curator : curators) {
|
|
||||||
Boolean exists = entityManager.createQuery("""
|
|
||||||
select case when (count(t) > 0) then true else false end from Task t
|
|
||||||
where t.checkerParticId = :id
|
|
||||||
and t.type = :type
|
|
||||||
and t.defense = :defense
|
|
||||||
""", Boolean.class)
|
|
||||||
.setParameter("id", curator.getParticipant().getId())
|
|
||||||
.setParameter("type", Task.Type.TASK_CREATING)
|
|
||||||
.setParameter("defense", defense)
|
|
||||||
.getSingleResult();
|
|
||||||
|
|
||||||
if (!exists) {
|
|
||||||
Task task = new Task();
|
|
||||||
task.setDefense(defense);
|
|
||||||
task.setCheckerParticId(curator.getParticipant().getId());
|
|
||||||
task.setType(Task.Type.TASK_CREATING);
|
|
||||||
task.setStatus(Task.Status.DONE);
|
|
||||||
taskRepository.save(task);
|
|
||||||
emailService.sendTaskCreatingMessage(curator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkAndCreateTaskAssignTasks(List<TeacherData> curators, Defense defense) {
|
|
||||||
for (TeacherData curator : curators) {
|
|
||||||
Boolean exists = entityManager.createQuery("""
|
|
||||||
select case when (count(t) > 0) then true else false end from Task t
|
|
||||||
where t.checkerParticId = :id
|
|
||||||
and t.type = :type
|
|
||||||
and t.defense = :defense
|
|
||||||
""", Boolean.class)
|
|
||||||
.setParameter("id", curator.getParticipant().getId())
|
|
||||||
.setParameter("type", Task.Type.TASK_ASSIGN)
|
|
||||||
.setParameter("defense", defense)
|
|
||||||
.getSingleResult();
|
|
||||||
|
|
||||||
if (!exists) {
|
|
||||||
Task task = new Task();
|
|
||||||
task.setDefense(defense);
|
|
||||||
task.setCheckerParticId(curator.getParticipant().getId());
|
|
||||||
task.setType(Task.Type.TASK_ASSIGN);
|
|
||||||
task.setStatus(Task.Status.DONE);
|
|
||||||
taskRepository.save(task);
|
|
||||||
emailService.sendTaskAssigningMessage(curator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkAndCreatePreDiplomaPracticeTask(List<StudentData> students, Defense defense) {
|
|
||||||
for (StudentData student : students) {
|
|
||||||
Boolean exists = entityManager.createQuery("""
|
|
||||||
select case when (count(t) > 0) then true else false end from Task t
|
|
||||||
where (t.checkerParticId = :id or t.makerParticId = :id)
|
|
||||||
and t.type = :type
|
|
||||||
and t.defense = :defense
|
|
||||||
""", Boolean.class)
|
|
||||||
.setParameter("id", student.getParticipant().getId())
|
|
||||||
.setParameter("type", Task.Type.PRE_DIPLOMA_PRACTICE)
|
|
||||||
.setParameter("defense", defense)
|
|
||||||
.getSingleResult();
|
|
||||||
|
|
||||||
if (!exists) {
|
|
||||||
PreDiplomaPracticeTask task = new PreDiplomaPracticeTask();
|
|
||||||
task.setDefense(defense);
|
|
||||||
task.setCheckerParticId(student.getParticipant().getId());
|
|
||||||
task.setType(Task.Type.PRE_DIPLOMA_PRACTICE);
|
|
||||||
task.setStatus(Task.Status.WAIT_FOR_STUDENT_PRE_DIPLOMA_PRACTICE_WORK_DONE);
|
|
||||||
taskRepository.save(task);
|
|
||||||
emailService.sendPreDiplomaPracticeMessage(student.getCurator(), student);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkAndCreateTopicFinalizationTask(Defense defense, List<TeacherData> curators) {
|
|
||||||
for (TeacherData curator : curators) {
|
|
||||||
Boolean exists = entityManager.createQuery("""
|
|
||||||
select case when (count(t) > 0) then true else false end from Task t
|
|
||||||
where t.checkerParticId = :id
|
|
||||||
and t.type = :type
|
|
||||||
and t.defense = :defense
|
|
||||||
""", Boolean.class)
|
|
||||||
.setParameter("id", curator.getParticipant().getId())
|
|
||||||
.setParameter("type", Task.Type.TOPIC_FINALIZATION)
|
|
||||||
.setParameter("defense", defense)
|
|
||||||
.getSingleResult();
|
|
||||||
|
|
||||||
if (!exists) {
|
|
||||||
Task task = new Task();
|
|
||||||
task.setDefense(defense);
|
|
||||||
task.setCheckerParticId(curator.getParticipant().getId());
|
|
||||||
task.setType(Task.Type.TOPIC_FINALIZATION);
|
|
||||||
task.setStatus(Task.Status.DONE);
|
|
||||||
taskRepository.save(task);
|
|
||||||
emailService.sendTopicFinalizationMessage(curator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkAndCreateMainVkrWorkTask(Defense defense, List<StudentData> students) {
|
|
||||||
for (StudentData student : students) {
|
|
||||||
Boolean exists = entityManager.createQuery("""
|
|
||||||
select case when (count(t) > 0) then true else false end from Task t
|
|
||||||
where t.checkerParticId = :id
|
|
||||||
and t.type = :type
|
|
||||||
and t.defense = :defense
|
|
||||||
""", Boolean.class)
|
|
||||||
.setParameter("id", student.getParticipant().getId())
|
|
||||||
.setParameter("type", Task.Type.TOPIC_FINALIZATION)
|
|
||||||
.setParameter("defense", defense)
|
|
||||||
.getSingleResult();
|
|
||||||
if (!exists) {
|
|
||||||
Task task = new Task();
|
|
||||||
task.setDefense(defense);
|
|
||||||
task.setCheckerParticId(student.getParticipant().getId());
|
|
||||||
task.setType(Task.Type.MAIN_VKR_WORK);
|
|
||||||
task.setStatus(Task.Status.DONE);
|
|
||||||
taskRepository.save(task);
|
|
||||||
emailService.sendMainVrkWorkMessage(student);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkAndCreatePreDefenseTask(Defense defense, List<StudentData> students) {
|
|
||||||
for (StudentData student : students) {
|
|
||||||
Boolean exists = entityManager.createQuery("""
|
|
||||||
select case when (count(t) > 0) then true else false end from Task t
|
|
||||||
where t.checkerParticId = :id
|
|
||||||
and t.type = :type
|
|
||||||
and t.defense = :defense
|
|
||||||
""", Boolean.class)
|
|
||||||
.setParameter("id", student.getParticipant().getId())
|
|
||||||
.setParameter("type", Task.Type.PRE_DEFENSE)
|
|
||||||
.setParameter("defense", defense)
|
|
||||||
.getSingleResult();
|
|
||||||
|
|
||||||
if (!exists) {
|
|
||||||
Task task = new Task();
|
|
||||||
task.setDefense(defense);
|
|
||||||
task.setCheckerParticId(student.getParticipant().getId());
|
|
||||||
task.setType(Task.Type.PRE_DEFENSE);
|
|
||||||
task.setStatus(Task.Status.DONE);
|
|
||||||
taskRepository.save(task);
|
|
||||||
emailService.sendPreDefenseStartMessage(student);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkAndCreateNormcontrolAndAntiplagiarismTask(Defense defense, List<StudentData> students) {
|
|
||||||
for (StudentData student : students) {
|
|
||||||
Boolean exists = entityManager.createQuery("""
|
|
||||||
select case when (count(t) > 0) then true else false end from Task t
|
|
||||||
where t.makerParticId = :id
|
|
||||||
and t.type = :type
|
|
||||||
and t.defense = :defense
|
|
||||||
""", Boolean.class)
|
|
||||||
.setParameter("id", student.getParticipant().getId())
|
|
||||||
.setParameter("type", Task.Type.NORMCONTROL_AND_ANTIPLAGIARISM)
|
|
||||||
.setParameter("defense", defense)
|
|
||||||
.getSingleResult();
|
|
||||||
|
|
||||||
if (!exists) {
|
|
||||||
NormcontrolAndAntiplagiarismTask task = new NormcontrolAndAntiplagiarismTask();
|
|
||||||
task.setDefense(defense);
|
|
||||||
task.setType(Task.Type.NORMCONTROL_AND_ANTIPLAGIARISM);
|
|
||||||
task.setStatus(Task.Status.WAIT_FOR_NORMOCONTROL_PASSED);
|
|
||||||
task.setCheckerParticId(defense.getResponsibleForNormcontrol().getId());
|
|
||||||
task.setMakerParticId(student.getParticipant().getId());
|
|
||||||
taskRepository.save(task);
|
|
||||||
emailService.sendNormcontrolAndAntiplagiarismMessage(student);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkAndCreateDefensePreparationTasks(Defense defense, List<StudentData> students) {
|
|
||||||
for (StudentData student : students) {
|
|
||||||
Boolean exists = entityManager.createQuery("""
|
|
||||||
select case when (count(t) > 0) then true else false end from Task t
|
|
||||||
where t.makerParticId = :id
|
|
||||||
and t.type = :type
|
|
||||||
and t.defense = :defense
|
|
||||||
""", Boolean.class)
|
|
||||||
.setParameter("id", student.getParticipant().getId())
|
|
||||||
.setParameter("type", Task.Type.DEFENSE_PREPARATION)
|
|
||||||
.setParameter("defense", defense)
|
|
||||||
.getSingleResult();
|
|
||||||
|
|
||||||
if (!exists) {
|
|
||||||
Task task = new Task();
|
|
||||||
task.setDefense(defense);
|
|
||||||
task.setType(Task.Type.DEFENSE_PREPARATION);
|
|
||||||
task.setStatus(Task.Status.WAIT_FOR_TEACHER_OTZIV);
|
|
||||||
task.setMakerParticId(student.getParticipant().getId());
|
|
||||||
task.setCheckerParticId(student.getCurator().getParticipant().getId());
|
|
||||||
taskRepository.save(task);
|
|
||||||
emailService.sendDefensePreparationMessage(student);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkAndCreateDefenseTask(Defense defense, List<StudentData> students) {
|
|
||||||
for (StudentData student : students) {
|
|
||||||
Boolean exists = entityManager.createQuery("""
|
|
||||||
select case when (count(t) > 0) then true else false end from Task t
|
|
||||||
where t.checkerParticId = :id
|
|
||||||
and t.type = :type
|
|
||||||
and t.defense = :defense
|
|
||||||
""", Boolean.class)
|
|
||||||
.setParameter("id", student.getParticipant().getId())
|
|
||||||
.setParameter("type", Task.Type.DEFENSE)
|
|
||||||
.setParameter("defense", defense)
|
|
||||||
.getSingleResult();
|
|
||||||
|
|
||||||
if (!exists) {
|
|
||||||
Task task = new Task();
|
|
||||||
task.setDefense(defense);
|
|
||||||
task.setType(Task.Type.DEFENSE);
|
|
||||||
task.setStatus(Task.Status.DONE);
|
|
||||||
task.setCheckerParticId(student.getParticipant().getId());
|
|
||||||
taskRepository.save(task);
|
|
||||||
emailService.sendDefenseMessage(student);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearAllTasksWithDefense(Defense defense) {
|
|
||||||
entityManager.createQuery("delete from Task t where t.defense = :defense")
|
|
||||||
.setParameter("defense", defense)
|
|
||||||
.executeUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void finishTopicPreparationTask(IdDTO defenseId) {
|
|
||||||
Defense defense = defenseRepository.findByIdThrow(defenseId.getId());
|
|
||||||
Task task = entityManager.createQuery("""
|
|
||||||
select t from Task t
|
|
||||||
where t.checkerParticId = :id
|
|
||||||
and t.type = :type
|
|
||||||
and t.defense = :defense
|
|
||||||
""", Task.class)
|
|
||||||
.setParameter("id", userService.getCallerUser().getParticipant().getId())
|
|
||||||
.setParameter("type", Task.Type.TOPIC_PREPARATION)
|
|
||||||
.setParameter("defense", defense)
|
|
||||||
.getSingleResult();
|
|
||||||
task.setStatus(Task.Status.DONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void finishDefPrepTask(TaskController.DefPrepFinishDTO dto) {
|
|
||||||
Task task = entityManager.createQuery("select t from Task t where t.id = :id", Task.class)
|
|
||||||
.setParameter("id", dto.getTaskId())
|
|
||||||
.getSingleResult();
|
|
||||||
Long studentParticId = task.getMakerParticId();
|
|
||||||
StudentData student = studentDataRepository.findStudentDataByParticipant_Id(studentParticId);
|
|
||||||
student.setOtziv(dto.getMark());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void finishNormAntipl(TaskController.NormAntiplFinishDTO dto) {
|
|
||||||
Task task = entityManager.createQuery("select t from Task t where t.id = :id", Task.class)
|
|
||||||
.setParameter("id", dto.getTaskId())
|
|
||||||
.getSingleResult();
|
|
||||||
StudentData student = studentDataRepository.findStudentDataByParticipant_Id(task.getMakerParticId());
|
|
||||||
if (task.getStatus() == Task.Status.WAIT_FOR_NORMOCONTROL_PASSED) {
|
|
||||||
student.setNormcontrol(true);
|
|
||||||
task.setStatus(Task.Status.WAIT_FOR_ANTIPL_PASSED);
|
|
||||||
} else if (task.getStatus() == Task.Status.WAIT_FOR_ANTIPL_PASSED) {
|
|
||||||
student.setAntiplagiarism(dto.getAntipl());
|
|
||||||
task.setStatus(Task.Status.DONE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import ru.mskobaro.tdms.business.entity.User;
|
import ru.mskobaro.tdms.business.entity.User;
|
||||||
import ru.mskobaro.tdms.integration.database.UserRepository;
|
import ru.mskobaro.tdms.integration.database.UserRepository;
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.UserDTO;
|
import ru.mskobaro.tdms.presentation.controller.payload.UserDTO;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,11 @@
|
|||||||
|
package ru.mskobaro.tdms.business.taskfields;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class DiplomaTopicAgreementTaskFields extends MakerCheckerTaskFields {
|
||||||
|
private String diplomaTopicName;
|
||||||
|
private Long diplomaTopicId;
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
package ru.mskobaro.tdms.business.taskfields;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class MakerCheckerTaskFields extends MakerTaskFields {
|
||||||
|
private Long checkerParticipantId;
|
||||||
|
private LocalDateTime approvedAt;
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
package ru.mskobaro.tdms.business.taskfields;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class MakerTaskFields extends TaskFields {
|
||||||
|
private Long makerParticipantId;
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
package ru.mskobaro.tdms.business.taskfields;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class TaskFields {
|
||||||
|
private LocalDateTime createdAt;
|
||||||
|
}
|
||||||
@ -1,33 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.integration.controller;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
import ru.mskobaro.tdms.business.entity.CommissionMemberData;
|
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.CommissionMemberDTO;
|
|
||||||
import ru.mskobaro.tdms.integration.database.CommissionMemberRepository;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("api/v1/commission-member")
|
|
||||||
public class CommissionMemberController {
|
|
||||||
@Autowired
|
|
||||||
private CommissionMemberRepository commissionMemberRepository;
|
|
||||||
|
|
||||||
@GetMapping("/get-all")
|
|
||||||
public List<CommissionMemberDTO> getAll() {
|
|
||||||
List<CommissionMemberData> all = commissionMemberRepository.findAll();
|
|
||||||
return all.stream().map(CommissionMemberDTO::from).collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/by-partic-id")
|
|
||||||
public CommissionMemberDTO getByParticId(@RequestParam("id") Long id) {
|
|
||||||
CommissionMemberData commissionMemberData = commissionMemberRepository.findByParticipant_Id(id);
|
|
||||||
return CommissionMemberDTO.from(commissionMemberData);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,121 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.integration.controller;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
import ru.mskobaro.tdms.business.service.DefenseService;
|
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.DefenseDTO;
|
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.IdDTO;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/api/v1/defense")
|
|
||||||
public class DefenseController {
|
|
||||||
@Autowired
|
|
||||||
private DefenseService defenseService;
|
|
||||||
|
|
||||||
@GetMapping("get-all")
|
|
||||||
public List<DefenseDTO> getAllDefenses() {
|
|
||||||
return defenseService.findAll().stream().map(DefenseDTO::from).collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("get-by-id")
|
|
||||||
public DefenseDTO getById(@RequestParam Long id) {
|
|
||||||
return DefenseDTO.from(defenseService.findById(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("save")
|
|
||||||
public void save(@RequestBody DefenseDTO defenseDTO) {
|
|
||||||
defenseService.save(defenseDTO);
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("to-next-state")
|
|
||||||
public void nextState(@RequestBody IdDTO idDto) {
|
|
||||||
defenseService.handleNextStateRequest(idDto.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("defense-table")
|
|
||||||
public DefenseTableData getDefenseTable(@RequestParam Long defenseId) {
|
|
||||||
return defenseService.tableDataByDefenseId(defenseId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("defense-table-save")
|
|
||||||
public void defenseTableSave(@RequestBody DefenseTableData defenseTableData) {
|
|
||||||
defenseService.tableDataSave(defenseTableData);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public static class DefenseTableData {
|
|
||||||
private Long defenseId;
|
|
||||||
private List<DefenseTableDataGroup> groups;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public static class DefenseTableDataGroup {
|
|
||||||
private Long groupId;
|
|
||||||
private Long studId;
|
|
||||||
private String groupName;
|
|
||||||
|
|
||||||
private String fio;
|
|
||||||
|
|
||||||
private Integer pdpMark;
|
|
||||||
private String topic;
|
|
||||||
|
|
||||||
private String teacherFio;
|
|
||||||
|
|
||||||
private Integer dayOfProt;
|
|
||||||
private Integer placeOfProt;
|
|
||||||
|
|
||||||
private Boolean magistracy;
|
|
||||||
private Boolean electronic;
|
|
||||||
|
|
||||||
private Integer otziv;
|
|
||||||
private Integer dpedefenseMark;
|
|
||||||
|
|
||||||
private Boolean normcontrol;
|
|
||||||
private Integer antipl;
|
|
||||||
|
|
||||||
private Boolean zachetka;
|
|
||||||
private String work;
|
|
||||||
|
|
||||||
private Boolean vnedreniye;
|
|
||||||
private Boolean otlichiye;
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("recreate-protection-order")
|
|
||||||
public void recreateProtectionOrder(@RequestBody IdDTO idDto) {
|
|
||||||
defenseService.recreateProtectionOrder(idDto.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("save-order")
|
|
||||||
public void updateProtectionOrder(@RequestBody ProtOrDTO dto) {
|
|
||||||
defenseService.updateProtOrder(dto);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public static class ProtOrDTO {
|
|
||||||
private Long defenseId;
|
|
||||||
private List<DrotOrGroupDTO> days;
|
|
||||||
private List<IdDTO> unassigned;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public static class DrotOrGroupDTO {
|
|
||||||
private Integer number;
|
|
||||||
private List<StudDTO> studs;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public static class StudDTO {
|
|
||||||
private Long id;
|
|
||||||
private Integer order;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,49 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.integration.controller;
|
|
||||||
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.validation.annotation.Validated;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
import ru.mskobaro.tdms.business.entity.DiplomaTopic;
|
|
||||||
import ru.mskobaro.tdms.business.service.DiplomaTopicService;
|
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.DiplomaTopicDTO;
|
|
||||||
import ru.mskobaro.tdms.integration.database.DiplomaTopicRepository;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/api/v1/diploma-topic/")
|
|
||||||
@Validated
|
|
||||||
public class DiplomaTopicController {
|
|
||||||
@Autowired
|
|
||||||
private DiplomaTopicService diplomaTopicService;
|
|
||||||
@Autowired
|
|
||||||
private DiplomaTopicRepository diplomaTopicRepository;
|
|
||||||
|
|
||||||
@GetMapping("/all")
|
|
||||||
public List<DiplomaTopicDTO> getAll() {
|
|
||||||
return diplomaTopicService.findAll().stream().map(DiplomaTopicDTO::from).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("/save")
|
|
||||||
public void save(@RequestBody DiplomaTopicDTO diplomaTopicDTO) {
|
|
||||||
diplomaTopicService.save(diplomaTopicDTO);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/all-for-student")
|
|
||||||
public List<DiplomaTopicDTO> getAllForStudent(@RequestParam Long id) {
|
|
||||||
return diplomaTopicService.findAllForStudentByParticId(id).stream().map(DiplomaTopicDTO::from).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/by-id")
|
|
||||||
public DiplomaTopicDTO getById(@RequestParam Long id) {
|
|
||||||
DiplomaTopic topic = diplomaTopicRepository.findByIdThrow(id);
|
|
||||||
return DiplomaTopicDTO.from(topic);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("matching-teacher-and-dir-prep")
|
|
||||||
public List<DiplomaTopicDTO> matchingTeacherAndDirPrep(@RequestParam Long particId, @RequestParam Long dirPrepId) {
|
|
||||||
return diplomaTopicService.findByTeacherParticIdAndDirPrep(particId, dirPrepId).stream().map(DiplomaTopicDTO::from).toList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,46 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.integration.controller;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.core.io.ByteArrayResource;
|
|
||||||
import org.springframework.http.HttpHeaders;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
import ru.mskobaro.tdms.business.service.DocumentsService;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("api/v1/doc")
|
|
||||||
public class DocumentsController {
|
|
||||||
@Autowired
|
|
||||||
private DocumentsService documentsService;
|
|
||||||
|
|
||||||
@GetMapping("stud-list")
|
|
||||||
public ResponseEntity<ByteArrayResource> getStudList(@RequestParam Long id) {
|
|
||||||
byte[] document = documentsService.getStudList(id, "бакалавр");
|
|
||||||
return returnFile(document, "SPISOK_ZASHISHAYUSHIHSYA.docx");
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("gek-questions")
|
|
||||||
public ResponseEntity<ByteArrayResource> getQuestions(@RequestParam Long id) {
|
|
||||||
byte[] document = documentsService.getQuestionsDocument(id, "Очная");
|
|
||||||
return returnFile(document, "BLANK_VOPROSOV_GEK.docx");
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("topic-list")
|
|
||||||
public ResponseEntity<ByteArrayResource> getTopicList(@RequestParam Long id) {
|
|
||||||
byte[] document = documentsService.getTopicList(id);
|
|
||||||
return returnFile(document, "FRAGMENT_PRIKAZA_TEMI_VKR.docx");
|
|
||||||
}
|
|
||||||
|
|
||||||
private ResponseEntity<ByteArrayResource> returnFile(byte[] document, String filename) {
|
|
||||||
ByteArrayResource resource = new ByteArrayResource(document);
|
|
||||||
return ResponseEntity.ok()
|
|
||||||
.contentType(MediaType.APPLICATION_OCTET_STREAM)
|
|
||||||
.contentLength(document.length)
|
|
||||||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + filename)
|
|
||||||
.body(resource);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.integration.controller;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
import ru.mskobaro.tdms.business.service.HomeInfoService;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/api/v1/home-page/")
|
|
||||||
public class HomeInfoController {
|
|
||||||
@Autowired
|
|
||||||
private HomeInfoService homeInfoService;
|
|
||||||
|
|
||||||
@GetMapping("default-info")
|
|
||||||
public DefaultInfo defaultInfo() {
|
|
||||||
return homeInfoService.defaultInfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public static class DefaultInfo {
|
|
||||||
private Long particCount;
|
|
||||||
private Long userCount;
|
|
||||||
private Long teacherCount;
|
|
||||||
private Long studentCount;
|
|
||||||
private Long defenseCount;
|
|
||||||
private Long currentDefenseCount;
|
|
||||||
private String currentDefenseGroupNames;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,122 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.integration.controller;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import lombok.Setter;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
import ru.mskobaro.tdms.business.entity.Task;
|
|
||||||
import ru.mskobaro.tdms.business.entity.TopicAgreementTask;
|
|
||||||
import ru.mskobaro.tdms.business.service.TaskService;
|
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.DefenseDTO;
|
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.IdDTO;
|
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.TopicAgreementDto;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/api/v1/task")
|
|
||||||
public class TaskController {
|
|
||||||
@Autowired
|
|
||||||
private TaskService taskService;
|
|
||||||
|
|
||||||
@GetMapping("/diploma-agreement-maker")
|
|
||||||
public TopicAgreementDto diplomaTopicAgreementMaker() {
|
|
||||||
TopicAgreementTask task = taskService.findDiplomaTopicAgreementTaskMadeByCurrentUser();
|
|
||||||
return task == null ? null : TopicAgreementDto.from(task);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/diploma-agreement-maker-by-partic-id")
|
|
||||||
public TopicAgreementDto diplomaTopicAgreementMakerId(@RequestParam Long id) {
|
|
||||||
TopicAgreementTask task = taskService.getTopicAgreementTaskByMakerId(id);
|
|
||||||
return task == null ? null : TopicAgreementDto.from(task);
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("/agreement-change")
|
|
||||||
public void agreementChange(@RequestBody DiplomaTopicAgreementChangeRequestDTO changeRequest) {
|
|
||||||
taskService.agreementChangeRequest(changeRequest);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/notif-count")
|
|
||||||
public NumberDTO getCurrentUserNotificationCount() {
|
|
||||||
NumberDTO dto = new NumberDTO();
|
|
||||||
Long number = taskService.getCurrentUserNotificationCount();
|
|
||||||
dto.setNumber(number);
|
|
||||||
return dto;
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/get-current-tasks")
|
|
||||||
public List<TaskDTO> getCurrentTasks() {
|
|
||||||
return taskService.getAllCurrentTasks();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public static class DiplomaTopicAgreementDTO {
|
|
||||||
private String diplomaTopicName;
|
|
||||||
private Long diplomaTopicId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public static class NumberDTO {
|
|
||||||
private Long number;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public static class TaskDTO {
|
|
||||||
private Long id;
|
|
||||||
private String message;
|
|
||||||
private Task.Status status;
|
|
||||||
private Task.Type type;
|
|
||||||
private Long makerId;
|
|
||||||
private Long checkerId;
|
|
||||||
private DefenseDTO defense;
|
|
||||||
private Object info;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public static class DiplomaTopicAgreementChangeRequestDTO {
|
|
||||||
public enum ChangeType {
|
|
||||||
STUDENT_REDO,
|
|
||||||
TEACHER_APPROVE,
|
|
||||||
TEACHER_REJECT,
|
|
||||||
}
|
|
||||||
|
|
||||||
private Long taskId;
|
|
||||||
private String diplomaTopicName;
|
|
||||||
private Long diplomaTopicId;
|
|
||||||
private ChangeType type;
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("topic-preparation-finish")
|
|
||||||
public void finishTopicPreparation(@RequestBody IdDTO idDTO) {
|
|
||||||
taskService.finishTopicPreparationTask(idDTO);
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("def-prep-finish")
|
|
||||||
public void finishDefPreparation(@RequestBody DefPrepFinishDTO defPrepFinishDTO) {
|
|
||||||
taskService.finishDefPrepTask(defPrepFinishDTO);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public static class DefPrepFinishDTO {
|
|
||||||
private Long taskId;
|
|
||||||
private Integer mark;
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("norm-antipl-finish")
|
|
||||||
public void finishNormAntiplFinish(@RequestBody NormAntiplFinishDTO antiplFinishDTO) {
|
|
||||||
taskService.finishNormAntipl(antiplFinishDTO);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public static class NormAntiplFinishDTO {
|
|
||||||
private Long taskId;
|
|
||||||
private Integer antipl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,58 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.integration.controller.payload;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
|
||||||
import ru.mskobaro.tdms.business.entity.Defense;
|
|
||||||
|
|
||||||
import java.time.LocalDate;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public class DefenseDTO {
|
|
||||||
private Long id;
|
|
||||||
private List<CommissionMemberDTO> commissionMembers;
|
|
||||||
private List<GroupDTO> groups;
|
|
||||||
private Defense.Status status;
|
|
||||||
private ParticipantDTO responsibleForAntipl;
|
|
||||||
private ParticipantDTO responsibleForNorm;
|
|
||||||
private PreparationDirectionDTO preparationDirection;
|
|
||||||
private LocalDate defenseDate;
|
|
||||||
private LocalDateTime createdAt;
|
|
||||||
private LocalDateTime updatedAt;
|
|
||||||
|
|
||||||
public static DefenseDTO from(Defense defense) {
|
|
||||||
DefenseDTO dto = new DefenseDTO();
|
|
||||||
dto.setId(defense.getId());
|
|
||||||
|
|
||||||
if (CollectionUtils.isNotEmpty(defense.getCommissionMembers())) {
|
|
||||||
dto.setCommissionMembers(
|
|
||||||
defense.getCommissionMembers().stream()
|
|
||||||
.map(CommissionMemberDTO::from)
|
|
||||||
.collect(Collectors.toList())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defense.getResponsibleForAntiplagiarism() != null) {
|
|
||||||
dto.setResponsibleForAntipl(ParticipantDTO.fromEntity(defense.getResponsibleForAntiplagiarism()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defense.getResponsibleForNormcontrol() != null) {
|
|
||||||
dto.setResponsibleForNorm(ParticipantDTO.fromEntity(defense.getResponsibleForNormcontrol()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defense.getDirectionOfPreparation() != null) {
|
|
||||||
dto.setPreparationDirection(PreparationDirectionDTO.from(defense.getDirectionOfPreparation()));
|
|
||||||
}
|
|
||||||
|
|
||||||
dto.setStatus(defense.getStatus());
|
|
||||||
dto.setGroups(defense.getGroups().stream().map(g -> GroupDTO.from(g, true)).toList());
|
|
||||||
dto.setDefenseDate(defense.getDefenseDate());
|
|
||||||
dto.setCreatedAt(defense.getAuditInfo().getCreatedAt());
|
|
||||||
dto.setUpdatedAt(defense.getAuditInfo().getUpdatedAt());
|
|
||||||
return dto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.integration.controller.payload;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.ToString;
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@ToString
|
|
||||||
public class IdDTO {
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
public static IdDTO fromId(Long id) {
|
|
||||||
IdDTO dto = new IdDTO();
|
|
||||||
dto.setId(id);
|
|
||||||
return dto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,88 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.integration.controller.payload;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import ru.mskobaro.tdms.business.entity.StudentData;
|
|
||||||
|
|
||||||
|
|
||||||
// @Column(name = "magistracy_wanted")
|
|
||||||
// private Boolean magistracy;
|
|
||||||
// private Boolean electronic;
|
|
||||||
//
|
|
||||||
// @Column(name = "oztiv_mark")
|
|
||||||
// private Integer otziv;
|
|
||||||
// @Column(name = "predefnese_mark")
|
|
||||||
// private Integer preDefenseMark;
|
|
||||||
//
|
|
||||||
// @Column(name = "normal_control")
|
|
||||||
// private Boolean normcontrol;
|
|
||||||
// @Column(name = "anti_plagiarism")
|
|
||||||
// private Integer antiplagiarism;
|
|
||||||
//
|
|
||||||
// @Column(name = "record_book_returned")
|
|
||||||
// private Boolean zachetka;
|
|
||||||
//
|
|
||||||
// @Column(name = "work")
|
|
||||||
// private String work;
|
|
||||||
//
|
|
||||||
// @Column(name = "vnedreniye")
|
|
||||||
// private Boolean vnedreniye;
|
|
||||||
// @Column(name = "diploma_with_honors")
|
|
||||||
// private Boolean otlichiye;
|
|
||||||
|
|
||||||
|
|
||||||
@Setter
|
|
||||||
@Getter
|
|
||||||
public class StudentDataDTO {
|
|
||||||
private Long id;
|
|
||||||
private GroupDTO group;
|
|
||||||
private ParticipantDTO participant;
|
|
||||||
private TeacherDataDTO curator;
|
|
||||||
private DiplomaTopicDTO diplomaTopic;
|
|
||||||
private Boolean magistracy;
|
|
||||||
private Boolean electronic;
|
|
||||||
private Integer otziv;
|
|
||||||
private Integer preDefenseMark;
|
|
||||||
private Boolean normcontrol;
|
|
||||||
private Integer antiplagiarism;
|
|
||||||
private Boolean zachetka;
|
|
||||||
private String work;
|
|
||||||
private Boolean vnedreniye;
|
|
||||||
private Boolean otlichiye;
|
|
||||||
private Integer protDay;
|
|
||||||
private Integer protOrder;
|
|
||||||
private Long marks5;
|
|
||||||
private Long marks4;
|
|
||||||
private Long marks3;
|
|
||||||
|
|
||||||
public static StudentDataDTO from(StudentData studentData, boolean includeGroup) {
|
|
||||||
StudentDataDTO dto = new StudentDataDTO();
|
|
||||||
dto.setId(studentData.getId());
|
|
||||||
if (includeGroup && studentData.getGroup() != null) {
|
|
||||||
dto.setGroup(GroupDTO.from(studentData.getGroup(), false));
|
|
||||||
}
|
|
||||||
dto.setParticipant(ParticipantDTO.fromEntity(studentData.getParticipant()));
|
|
||||||
if (studentData.getCurator() != null) {
|
|
||||||
dto.setCurator(TeacherDataDTO.from(studentData.getCurator()));
|
|
||||||
}
|
|
||||||
if (studentData.getDiplomaTopic() != null) {
|
|
||||||
dto.setDiplomaTopic(DiplomaTopicDTO.from(studentData.getDiplomaTopic()));
|
|
||||||
}
|
|
||||||
dto.setMagistracy(studentData.getMagistracy());
|
|
||||||
dto.setElectronic(studentData.getElectronic());
|
|
||||||
dto.setOtziv(studentData.getOtziv());
|
|
||||||
dto.setPreDefenseMark(studentData.getPreDefenseMark());
|
|
||||||
dto.setNormcontrol(studentData.getNormcontrol());
|
|
||||||
dto.setAntiplagiarism(studentData.getAntiplagiarism());
|
|
||||||
dto.setZachetka(studentData.getZachetka());
|
|
||||||
dto.setWork(studentData.getWork());
|
|
||||||
dto.setVnedreniye(studentData.getVnedreniye());
|
|
||||||
dto.setOtlichiye(studentData.getOtlichiye());
|
|
||||||
dto.setProtDay(studentData.getProtectionDay());
|
|
||||||
dto.setProtOrder(studentData.getProtectionOrder());
|
|
||||||
dto.setMarks5(studentData.getMarks5());
|
|
||||||
dto.setMarks4(studentData.getMarks4());
|
|
||||||
dto.setMarks3(studentData.getMarks3());
|
|
||||||
return dto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,39 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.integration.controller.payload;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import lombok.Setter;
|
|
||||||
import ru.mskobaro.tdms.business.entity.Task;
|
|
||||||
import ru.mskobaro.tdms.business.entity.TopicAgreementTask;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public class TopicAgreementDto {
|
|
||||||
private Long id;
|
|
||||||
private Task.Status status;
|
|
||||||
private Long makerParticId;
|
|
||||||
private Long checkerParticId;
|
|
||||||
private Long diplomaTopicId;
|
|
||||||
private String diplomaTopicName;
|
|
||||||
private LocalDateTime createdAt;
|
|
||||||
private LocalDateTime updatedAt;
|
|
||||||
private LocalDateTime approvedAt;
|
|
||||||
|
|
||||||
|
|
||||||
public static TopicAgreementDto from(TopicAgreementTask task) {
|
|
||||||
TopicAgreementDto dto = new TopicAgreementDto();
|
|
||||||
dto.setId(task.getId());
|
|
||||||
dto.setStatus(task.getStatus());
|
|
||||||
dto.setMakerParticId(task.getMakerParticId());
|
|
||||||
dto.setCheckerParticId(task.getCheckerParticId());
|
|
||||||
dto.setDiplomaTopicId(task.getDiplomaTopicId());
|
|
||||||
dto.setDiplomaTopicName(task.getDiplomaTopicName());
|
|
||||||
dto.setCreatedAt(task.getAuditInfo().getCreatedAt());
|
|
||||||
dto.setUpdatedAt(task.getAuditInfo().getUpdatedAt());
|
|
||||||
dto.setApprovedAt(task.getApprovedAt());
|
|
||||||
return dto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.integration.database;
|
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
import ru.mskobaro.tdms.business.entity.CommissionMemberData;
|
|
||||||
import ru.mskobaro.tdms.business.exception.NotFoundException;
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
public interface CommissionMemberRepository extends JpaRepository<CommissionMemberData, Long> {
|
|
||||||
default CommissionMemberData findByIdThrow(Long id) {
|
|
||||||
return findById(id).orElseThrow(() -> new NotFoundException(CommissionMemberData.class, id));
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean existsByParticipant_Id(Long id);
|
|
||||||
|
|
||||||
CommissionMemberData findByParticipant_Id(Long participantId);
|
|
||||||
}
|
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
package ru.mskobaro.tdms.integration.database;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
import ru.mskobaro.tdms.business.entity.Defense;
|
||||||
|
import ru.mskobaro.tdms.business.exception.NotFoundException;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface DefenceRepository extends JpaRepository<Defense, Long> {
|
||||||
|
default Defense findByIdThrow(Long id) {
|
||||||
|
return this.findById(id).orElseThrow(() -> new NotFoundException(Defense.class, id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Query("SELECT d from Defense d " +
|
||||||
|
"left join fetch d.bestWorks bw " +
|
||||||
|
"left join fetch d.commissionMembers cm " +
|
||||||
|
"where d.id = :id " +
|
||||||
|
"and bw.participant.deleted = false " +
|
||||||
|
"and cm.participant.deleted = false")
|
||||||
|
Optional<Defense> findById(Long id);
|
||||||
|
}
|
||||||
@ -1,13 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.integration.database;
|
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
import ru.mskobaro.tdms.business.entity.Defense;
|
|
||||||
import ru.mskobaro.tdms.business.exception.NotFoundException;
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
public interface DefenseRepository extends JpaRepository<Defense, Long> {
|
|
||||||
default Defense findByIdThrow(Long id) {
|
|
||||||
return this.findById(id).orElseThrow(() -> new NotFoundException(Defense.class, id));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -4,6 +4,8 @@ import org.springframework.data.jpa.repository.JpaRepository;
|
|||||||
import org.springframework.data.jpa.repository.Query;
|
import org.springframework.data.jpa.repository.Query;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
import ru.mskobaro.tdms.business.entity.DiplomaTopic;
|
import ru.mskobaro.tdms.business.entity.DiplomaTopic;
|
||||||
|
import ru.mskobaro.tdms.business.entity.DirectionOfPreparation;
|
||||||
|
import ru.mskobaro.tdms.business.entity.StudentData;
|
||||||
import ru.mskobaro.tdms.business.exception.NotFoundException;
|
import ru.mskobaro.tdms.business.exception.NotFoundException;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -15,9 +17,13 @@ public interface DiplomaTopicRepository extends JpaRepository<DiplomaTopic, Long
|
|||||||
return this.findById(id).orElseThrow(() -> new NotFoundException(DiplomaTopic.class, id));
|
return this.findById(id).orElseThrow(() -> new NotFoundException(DiplomaTopic.class, id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Query("SELECT d FROM DiplomaTopic d WHERE d.id = :id AND d.teacher.participant.deleted = false")
|
||||||
|
Optional<DiplomaTopic> findById(Long id);
|
||||||
|
|
||||||
@Query("SELECT d FROM DiplomaTopic d " +
|
@Query("SELECT d FROM DiplomaTopic d " +
|
||||||
"inner join d.directionOfPreparation dp " +
|
"inner join d.directionOfPreparation dp " +
|
||||||
"inner join StudentData sd on sd.participant.id = :particId " +
|
"inner join StudentData sd on sd.id = :studentIdwhere " +
|
||||||
"where dp = sd.group.directionOfPreparation and dp is not null and sd.curator = d.teacher and d.teacher is not null")
|
"where dp = sd.group.directionOfPreparation")
|
||||||
List<DiplomaTopic> findAllForStudentByParticId(Long particId);
|
List<DiplomaTopic> findAllForStudentId(Long studentId);
|
||||||
}
|
}
|
||||||
@ -1,15 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.integration.database;
|
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
import ru.mskobaro.tdms.business.entity.MessageTemplate;
|
|
||||||
import ru.mskobaro.tdms.business.exception.NotFoundException;
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
public interface MessageTemplateRepository extends JpaRepository<MessageTemplate, Long> {
|
|
||||||
default MessageTemplate findByIdThrow(Long id) {
|
|
||||||
return findById(id).orElseThrow(() -> new NotFoundException(MessageTemplate.class, id));
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageTemplate findByMessageType(MessageTemplate.MessageType messageType);
|
|
||||||
}
|
|
||||||
@ -24,6 +24,4 @@ public interface ParticipantRepository extends JpaRepository<Participant, Long>
|
|||||||
@Override
|
@Override
|
||||||
@Query("SELECT p from Participant p where p.deleted = false")
|
@Query("SELECT p from Participant p where p.deleted = false")
|
||||||
List<Participant> findAll();
|
List<Participant> findAll();
|
||||||
|
|
||||||
boolean existsByNumberPhoneOrEmail(String numberPhone, String email);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,21 @@
|
|||||||
package ru.mskobaro.tdms.integration.database;
|
package ru.mskobaro.tdms.integration.database;
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
import ru.mskobaro.tdms.business.entity.Task;
|
import ru.mskobaro.tdms.business.entity.Task;
|
||||||
import ru.mskobaro.tdms.business.exception.NotFoundException;
|
import ru.mskobaro.tdms.business.exception.NotFoundException;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface TaskRepository extends JpaRepository<Task, Long> {
|
public interface TaskRepository extends JpaRepository<Task, Long> {
|
||||||
default Task findByIdThrow(Long id) {
|
default Task findByIdThrow(Long id) {
|
||||||
return findById(id).orElseThrow(() -> new NotFoundException(Task.class, id));
|
return findById(id).orElseThrow(() -> new NotFoundException(Task.class, id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Query(value = "SELECT t FROM task t " +
|
||||||
|
"WHERE t.type = :type " +
|
||||||
|
"and t.fields->>'makerParticipantId' = :id", nativeQuery = true)
|
||||||
|
List<Task> findDiplomaTopicAgreementTaskByMakerId(Long id, Task.Type type);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,22 @@
|
|||||||
|
package ru.mskobaro.tdms.presentation.controller;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import ru.mskobaro.tdms.business.service.DefenceService;
|
||||||
|
import ru.mskobaro.tdms.presentation.controller.payload.DefenceDTO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/v1/defence")
|
||||||
|
public class DefenceController {
|
||||||
|
@Autowired
|
||||||
|
private DefenceService defenceService;
|
||||||
|
|
||||||
|
@GetMapping("/all")
|
||||||
|
public List<DefenceDTO> getAllDefences() {
|
||||||
|
return defenceService.getAllDefences();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
package ru.mskobaro.tdms.presentation.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import ru.mskobaro.tdms.business.service.DiplomaTopicService;
|
||||||
|
import ru.mskobaro.tdms.presentation.controller.payload.DiplomaTopicDTO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/v1/diploma-topic/")
|
||||||
|
@Validated
|
||||||
|
public class DiplomaTopicController {
|
||||||
|
@Autowired
|
||||||
|
private DiplomaTopicService diplomaTopicService;
|
||||||
|
|
||||||
|
@GetMapping("/all")
|
||||||
|
public List<DiplomaTopicDTO> getAll() {
|
||||||
|
return diplomaTopicService.findAll().stream().map(DiplomaTopicDTO::from).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/save")
|
||||||
|
public void save(@RequestBody DiplomaTopicDTO diplomaTopicDTO) {
|
||||||
|
diplomaTopicService.save(diplomaTopicDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/all-for-student")
|
||||||
|
public List<DiplomaTopicDTO> getAllForStudent(@RequestParam Long studentId) {
|
||||||
|
return diplomaTopicService.findAllForStudent(studentId).stream().map(DiplomaTopicDTO::from).toList();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,10 +1,10 @@
|
|||||||
package ru.mskobaro.tdms.integration.controller;
|
package ru.mskobaro.tdms.presentation.controller;
|
||||||
|
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import ru.mskobaro.tdms.business.service.GroupService;
|
import ru.mskobaro.tdms.business.service.GroupService;
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.GroupDTO;
|
import ru.mskobaro.tdms.presentation.controller.payload.GroupDTO;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
@ -1,16 +1,14 @@
|
|||||||
package ru.mskobaro.tdms.integration.controller;
|
package ru.mskobaro.tdms.presentation.controller;
|
||||||
|
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import ru.mskobaro.tdms.business.service.ParticipantService;
|
import ru.mskobaro.tdms.business.service.ParticipantService;
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.IdDTO;
|
import ru.mskobaro.tdms.presentation.controller.payload.IdDto;
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.ParticipantDTO;
|
import ru.mskobaro.tdms.presentation.controller.payload.ParticipantDTO;
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.ParticipantSaveDTO;
|
import ru.mskobaro.tdms.presentation.controller.payload.ParticipantSaveDTO;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1/participant")
|
@RequestMapping("/api/v1/participant")
|
||||||
@ -19,7 +17,7 @@ public class ParticipantController {
|
|||||||
private ParticipantService participantService;
|
private ParticipantService participantService;
|
||||||
|
|
||||||
@GetMapping("/get-all-participants")
|
@GetMapping("/get-all-participants")
|
||||||
public List<ParticipantDTO> getAllParticipants() {
|
public Collection<ParticipantDTO> getAllParticipants() {
|
||||||
return participantService.getAllParticipants().stream()
|
return participantService.getAllParticipants().stream()
|
||||||
.map(ParticipantDTO::fromEntity)
|
.map(ParticipantDTO::fromEntity)
|
||||||
.toList();
|
.toList();
|
||||||
@ -31,17 +29,7 @@ public class ParticipantController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/delete")
|
@PostMapping("/delete")
|
||||||
public void deleteParticipant(@RequestBody IdDTO id) {
|
public void deleteParticipant(@RequestBody IdDto id) {
|
||||||
participantService.deleteParticipant(id.getId());
|
participantService.deleteParticipant(id.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("get-all-antipl")
|
|
||||||
public List<ParticipantDTO> getAllAntipl() {
|
|
||||||
return participantService.getAllAntipl().stream().map(ParticipantDTO::fromEntity).collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("get-all-norm")
|
|
||||||
public List<ParticipantDTO> getAllNorm() {
|
|
||||||
return this.getAllParticipants();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -1,9 +1,9 @@
|
|||||||
package ru.mskobaro.tdms.integration.controller;
|
package ru.mskobaro.tdms.presentation.controller;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import ru.mskobaro.tdms.business.service.PreparationDirectionService;
|
import ru.mskobaro.tdms.business.service.PreparationDirectionService;
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.PreparationDirectionDTO;
|
import ru.mskobaro.tdms.presentation.controller.payload.PreparationDirectionDTO;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package ru.mskobaro.tdms.integration.controller;
|
package ru.mskobaro.tdms.presentation.controller;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
@ -7,19 +7,16 @@ import org.springframework.web.bind.annotation.RequestParam;
|
|||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import ru.mskobaro.tdms.business.entity.StudentData;
|
import ru.mskobaro.tdms.business.entity.StudentData;
|
||||||
import ru.mskobaro.tdms.business.service.StudentDataService;
|
import ru.mskobaro.tdms.business.service.StudentDataService;
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.StudentDataDTO;
|
import ru.mskobaro.tdms.presentation.controller.payload.GroupDTO;
|
||||||
import ru.mskobaro.tdms.integration.database.StudentDataRepository;
|
import ru.mskobaro.tdms.presentation.controller.payload.StudentDataDTO;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1/student/")
|
@RequestMapping("/api/v1/student/")
|
||||||
public class StudentController {
|
public class StudentController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private StudentDataService studentDataService;
|
private StudentDataService studentDataService;
|
||||||
@Autowired
|
|
||||||
private StudentDataRepository studentDataRepository;
|
|
||||||
|
|
||||||
@GetMapping(value = "/by-partic-id")
|
@GetMapping(value = "/by-partic-id")
|
||||||
public StudentDataDTO getCurrentStudent(@RequestParam(value = "id") Long particId) {
|
public StudentDataDTO getCurrentStudent(@RequestParam(value = "id") Long particId) {
|
||||||
@ -33,16 +30,4 @@ public class StudentController {
|
|||||||
.map(sd -> StudentDataDTO.from(sd, true))
|
.map(sd -> StudentDataDTO.from(sd, true))
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping(value = "by-id")
|
|
||||||
public StudentDataDTO getStudentById(@RequestParam(value = "id") Long id) {
|
|
||||||
return StudentDataDTO.from(studentDataRepository.findByIdThrow(id), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("by-defense-id")
|
|
||||||
public List<StudentDataDTO> getByDefenseId(@RequestParam(value = "id") Long id) {
|
|
||||||
return studentDataService.getByDefenseId(id).stream()
|
|
||||||
.map(studentData -> StudentDataDTO.from(studentData, true))
|
|
||||||
.toList();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package ru.mskobaro.tdms.integration.controller;
|
package ru.mskobaro.tdms.presentation.controller;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
package ru.mskobaro.tdms.presentation.controller;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import ru.mskobaro.tdms.business.service.TaskService;
|
||||||
|
import ru.mskobaro.tdms.presentation.controller.payload.TaskDto;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/v1/task")
|
||||||
|
public class TaskController {
|
||||||
|
@Autowired
|
||||||
|
private TaskService taskService;
|
||||||
|
|
||||||
|
@GetMapping("/diploma-agreement-maker")
|
||||||
|
public TaskDto diplomaTopicAgreementMaker() {
|
||||||
|
return TaskDto.from(taskService.findDiplomaTopicAgreementTaskCallerMaker());
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/create-topic-agreement")
|
||||||
|
public void createDiplomaTopicAgreement(@RequestBody DiplomaTopicAgreementDTO diplomaTopicAgreementDTO) {
|
||||||
|
taskService.createDiplomaAgreementTask(diplomaTopicAgreementDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public static class DiplomaTopicAgreementDTO {
|
||||||
|
private String diplomaTopicName;
|
||||||
|
private Long diplomaTopicId;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package ru.mskobaro.tdms.integration.controller;
|
package ru.mskobaro.tdms.presentation.controller;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
@ -6,7 +6,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import ru.mskobaro.tdms.business.service.TeacherDataService;
|
import ru.mskobaro.tdms.business.service.TeacherDataService;
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.TeacherDataDTO;
|
import ru.mskobaro.tdms.presentation.controller.payload.TeacherDataDTO;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package ru.mskobaro.tdms.integration.controller;
|
package ru.mskobaro.tdms.presentation.controller;
|
||||||
|
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -9,8 +9,8 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
import ru.mskobaro.tdms.business.entity.User;
|
import ru.mskobaro.tdms.business.entity.User;
|
||||||
import ru.mskobaro.tdms.business.service.AuthenticationService;
|
import ru.mskobaro.tdms.business.service.AuthenticationService;
|
||||||
import ru.mskobaro.tdms.business.service.UserService;
|
import ru.mskobaro.tdms.business.service.UserService;
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.LoginDTO;
|
import ru.mskobaro.tdms.presentation.controller.payload.LoginDTO;
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.UserDTO;
|
import ru.mskobaro.tdms.presentation.controller.payload.UserDTO;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1/user")
|
@RequestMapping("/api/v1/user")
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package ru.mskobaro.tdms.integration.controller.payload;
|
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
@ -0,0 +1,39 @@
|
|||||||
|
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import ru.mskobaro.tdms.business.entity.Defense;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class DefenceDTO {
|
||||||
|
private Long id;
|
||||||
|
private List<CommissionMemberDTO> commissionMembers;
|
||||||
|
private List<GroupDTO> groups;
|
||||||
|
|
||||||
|
private LocalDateTime createdAt;
|
||||||
|
private LocalDateTime updatedAt;
|
||||||
|
|
||||||
|
public static DefenceDTO from(Defense defense) {
|
||||||
|
DefenceDTO dto = new DefenceDTO();
|
||||||
|
dto.setId(defense.getId());
|
||||||
|
|
||||||
|
if (CollectionUtils.isNotEmpty(defense.getCommissionMembers())) {
|
||||||
|
dto.setCommissionMembers(
|
||||||
|
defense.getCommissionMembers().stream()
|
||||||
|
.map(CommissionMemberDTO::from)
|
||||||
|
.collect(Collectors.toList())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
dto.setGroups(defense.getGroups().stream().map(g -> GroupDTO.from(g, true)).toList());
|
||||||
|
dto.setCreatedAt(defense.getAuditInfo().getCreatedAt());
|
||||||
|
dto.setUpdatedAt(defense.getAuditInfo().getUpdatedAt());
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package ru.mskobaro.tdms.integration.controller.payload;
|
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package ru.mskobaro.tdms.integration.controller.payload;
|
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package ru.mskobaro.tdms.integration.controller.payload;
|
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotEmpty;
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
import jakarta.validation.constraints.Pattern;
|
import jakarta.validation.constraints.Pattern;
|
||||||
@ -30,7 +30,9 @@ public class GroupDTO {
|
|||||||
dto.setId(group.getId());
|
dto.setId(group.getId());
|
||||||
dto.setName(group.getName());
|
dto.setName(group.getName());
|
||||||
if (includeStudents && group.getStudents() != null) {
|
if (includeStudents && group.getStudents() != null) {
|
||||||
dto.setStudents(group.getStudents().stream()
|
dto.setStudents(
|
||||||
|
group.getStudents()
|
||||||
|
.stream()
|
||||||
.filter(sd -> !sd.getParticipant().isDeleted())
|
.filter(sd -> !sd.getParticipant().isDeleted())
|
||||||
.map(sd -> StudentDataDTO.from(sd, false))
|
.map(sd -> StudentDataDTO.from(sd, false))
|
||||||
.toList());
|
.toList());
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
public class IdDto {
|
||||||
|
private Long id;
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package ru.mskobaro.tdms.integration.controller.payload;
|
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotEmpty;
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
import jakarta.validation.constraints.Pattern;
|
import jakarta.validation.constraints.Pattern;
|
||||||
@ -1,15 +1,20 @@
|
|||||||
package ru.mskobaro.tdms.integration.controller.payload;
|
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
|
||||||
|
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
import ru.mskobaro.tdms.business.entity.Participant;
|
import ru.mskobaro.tdms.business.entity.Participant;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
// @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
|
@ToString
|
||||||
|
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
|
||||||
public class ParticipantDTO {
|
public class ParticipantDTO {
|
||||||
private Long id;
|
private Long id;
|
||||||
private String firstName;
|
private String firstName;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package ru.mskobaro.tdms.integration.controller.payload;
|
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||||
|
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import jakarta.validation.constraints.*;
|
import jakarta.validation.constraints.*;
|
||||||
@ -33,8 +33,6 @@ public class ParticipantSaveDTO {
|
|||||||
private StudentRegistrationDTO studentData;
|
private StudentRegistrationDTO studentData;
|
||||||
@Valid
|
@Valid
|
||||||
private TeacherRegistrationDTO teacherData;
|
private TeacherRegistrationDTO teacherData;
|
||||||
@Valid
|
|
||||||
private CommMemDto commMemData;
|
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@ToString
|
@ToString
|
||||||
@ -53,19 +51,6 @@ public class ParticipantSaveDTO {
|
|||||||
private Long groupId;
|
private Long groupId;
|
||||||
private Long curatorId;
|
private Long curatorId;
|
||||||
private Long diplomaTopicId;
|
private Long diplomaTopicId;
|
||||||
private Boolean electronic;
|
|
||||||
private Integer otziv;
|
|
||||||
private Integer preDefenseMark;
|
|
||||||
private Boolean normcontrol;
|
|
||||||
private Integer antiplagiarism;
|
|
||||||
private Boolean zachetka;
|
|
||||||
private String work;
|
|
||||||
private Boolean vnedreniye;
|
|
||||||
private Boolean otlichiye;
|
|
||||||
private Boolean magistracy;
|
|
||||||
private Long marks3;
|
|
||||||
private Long marks4;
|
|
||||||
private Long marks5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@ -76,11 +61,4 @@ public class ParticipantSaveDTO {
|
|||||||
private String degree;
|
private String degree;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Getter
|
|
||||||
@ToString
|
|
||||||
public static class CommMemDto {
|
|
||||||
private String workPlace;
|
|
||||||
private String workPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package ru.mskobaro.tdms.integration.controller.payload;
|
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
@ -14,7 +14,6 @@ public class PreparationDirectionDTO {
|
|||||||
private Long id;
|
private Long id;
|
||||||
private String name;
|
private String name;
|
||||||
private String code;
|
private String code;
|
||||||
private TeacherDataDTO responsible;
|
|
||||||
private LocalDateTime createdAt;
|
private LocalDateTime createdAt;
|
||||||
private LocalDateTime updatedAt;
|
private LocalDateTime updatedAt;
|
||||||
|
|
||||||
@ -23,9 +22,6 @@ public class PreparationDirectionDTO {
|
|||||||
dto.setId(preparationDirection.getId());
|
dto.setId(preparationDirection.getId());
|
||||||
dto.setName(preparationDirection.getName());
|
dto.setName(preparationDirection.getName());
|
||||||
dto.setCode(preparationDirection.getCode());
|
dto.setCode(preparationDirection.getCode());
|
||||||
if (preparationDirection.getResponsible() != null) {
|
|
||||||
dto.setResponsible(TeacherDataDTO.from(preparationDirection.getResponsible()));
|
|
||||||
}
|
|
||||||
dto.setCreatedAt(preparationDirection.getAuditInfo().getCreatedAt());
|
dto.setCreatedAt(preparationDirection.getAuditInfo().getCreatedAt());
|
||||||
dto.setUpdatedAt(preparationDirection.getAuditInfo().getUpdatedAt());
|
dto.setUpdatedAt(preparationDirection.getAuditInfo().getUpdatedAt());
|
||||||
return dto;
|
return dto;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package ru.mskobaro.tdms.integration.controller.payload;
|
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||||
|
|
||||||
|
|
||||||
import ru.mskobaro.tdms.business.entity.Participant;
|
import ru.mskobaro.tdms.business.entity.Participant;
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import ru.mskobaro.tdms.business.entity.StudentData;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
public class StudentDataDTO {
|
||||||
|
private Long id;
|
||||||
|
private GroupDTO group;
|
||||||
|
private ParticipantDTO participant;
|
||||||
|
private TeacherDataDTO curator;
|
||||||
|
private DiplomaTopicDTO diplomaTopic;
|
||||||
|
|
||||||
|
public static StudentDataDTO from(StudentData studentData, boolean includeGroup) {
|
||||||
|
StudentDataDTO dto = new StudentDataDTO();
|
||||||
|
dto.setId(studentData.getId());
|
||||||
|
if (includeGroup && studentData.getGroup() != null) {
|
||||||
|
dto.setGroup(GroupDTO.from(studentData.getGroup(), false));
|
||||||
|
}
|
||||||
|
dto.setParticipant(ParticipantDTO.fromEntity(studentData.getParticipant()));
|
||||||
|
if (studentData.getCurator() != null) {
|
||||||
|
dto.setCurator(TeacherDataDTO.from(studentData.getCurator()));
|
||||||
|
}
|
||||||
|
if (studentData.getDiplomaTopic() != null) {
|
||||||
|
dto.setDiplomaTopic(DiplomaTopicDTO.from(studentData.getDiplomaTopic()));
|
||||||
|
}
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import ru.mskobaro.tdms.business.entity.Task;
|
||||||
|
import ru.mskobaro.tdms.business.taskfields.TaskFields;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TaskDto {
|
||||||
|
private Long id;
|
||||||
|
private Task.Type type;
|
||||||
|
private Task.Status status;
|
||||||
|
private TaskFields fields;
|
||||||
|
private LocalDateTime createdAt;
|
||||||
|
private LocalDateTime updatedAt;
|
||||||
|
|
||||||
|
|
||||||
|
public static TaskDto from(Task task) {
|
||||||
|
TaskDto dto = new TaskDto();
|
||||||
|
dto.setId(task.getId());
|
||||||
|
dto.setType(task.getType());
|
||||||
|
dto.setStatus(task.getStatus());
|
||||||
|
dto.setFields(task.getFields());
|
||||||
|
dto.setCreatedAt(task.getAuditInfo().getCreatedAt());
|
||||||
|
dto.setUpdatedAt(task.getAuditInfo().getUpdatedAt());
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package ru.mskobaro.tdms.integration.controller.payload;
|
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package ru.mskobaro.tdms.integration.controller.payload;
|
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||||
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
|
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
|
||||||
@ -7,6 +7,7 @@ import lombok.Builder;
|
|||||||
import ru.mskobaro.tdms.business.entity.User;
|
import ru.mskobaro.tdms.business.entity.User;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
|
||||||
|
|
||||||
@Builder
|
@Builder
|
||||||
@ -1,6 +1,5 @@
|
|||||||
package ru.mskobaro.tdms.integration.exception;
|
package ru.mskobaro.tdms.presentation.exception;
|
||||||
|
|
||||||
import jakarta.mail.SendFailedException;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.context.support.DefaultMessageSourceResolvable;
|
import org.springframework.context.support.DefaultMessageSourceResolvable;
|
||||||
@ -12,15 +11,14 @@ import org.springframework.web.bind.annotation.RestControllerAdvice;
|
|||||||
import org.springframework.web.servlet.resource.NoResourceFoundException;
|
import org.springframework.web.servlet.resource.NoResourceFoundException;
|
||||||
import ru.mskobaro.tdms.business.exception.AccessDeniedException;
|
import ru.mskobaro.tdms.business.exception.AccessDeniedException;
|
||||||
import ru.mskobaro.tdms.business.exception.BusinessException;
|
import ru.mskobaro.tdms.business.exception.BusinessException;
|
||||||
import ru.mskobaro.tdms.integration.controller.payload.ErrorDTO;
|
import ru.mskobaro.tdms.presentation.controller.payload.ErrorDTO;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.springframework.http.HttpStatus.NOT_FOUND;
|
|
||||||
import static org.springframework.http.HttpStatus.*;
|
import static org.springframework.http.HttpStatus.*;
|
||||||
import static ru.mskobaro.tdms.integration.controller.payload.ErrorDTO.ErrorCode.*;
|
import static org.springframework.http.HttpStatus.NOT_FOUND;
|
||||||
|
import static ru.mskobaro.tdms.presentation.controller.payload.ErrorDTO.ErrorCode.*;
|
||||||
|
|
||||||
@RestControllerAdvice
|
@RestControllerAdvice
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -37,7 +35,7 @@ public class ApplicationExceptionHandler {
|
|||||||
|
|
||||||
@ExceptionHandler(BusinessException.class)
|
@ExceptionHandler(BusinessException.class)
|
||||||
public ErrorDTO handleBusinessException(BusinessException e, HttpServletResponse response) {
|
public ErrorDTO handleBusinessException(BusinessException e, HttpServletResponse response) {
|
||||||
log.warn("Business error: ", e);
|
log.warn("Business error: {}", e.getMessage());
|
||||||
response.setStatus(e.getErrorCode().getHttpStatus().value());
|
response.setStatus(e.getErrorCode().getHttpStatus().value());
|
||||||
return new ErrorDTO(e.getMessage(), e.getErrorCode());
|
return new ErrorDTO(e.getMessage(), e.getErrorCode());
|
||||||
}
|
}
|
||||||
@ -72,18 +70,4 @@ public class ApplicationExceptionHandler {
|
|||||||
log.error("Unexpected exception ({})", uuid, e);
|
log.error("Unexpected exception ({})", uuid, e);
|
||||||
return new ErrorDTO("Идентификатор ошибки: (" + uuid + ")\nПроизошла непредвиденная ошибка, обратитесь к администратору", INTERNAL_ERROR);
|
return new ErrorDTO("Идентификатор ошибки: (" + uuid + ")\nПроизошла непредвиденная ошибка, обратитесь к администратору", INTERNAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ExceptionHandler(SendFailedException.class)
|
|
||||||
@ResponseStatus(BAD_REQUEST)
|
|
||||||
public ErrorDTO handleSendFailedException(SendFailedException e) {
|
|
||||||
log.error("Send failed: {}", e.getMessage());
|
|
||||||
StringBuilder addresses = new StringBuilder();
|
|
||||||
Arrays.stream(e.getInvalidAddresses()).forEach(address -> {
|
|
||||||
if (!addresses.isEmpty()) {
|
|
||||||
addresses.append(", ");
|
|
||||||
}
|
|
||||||
addresses.append(address);
|
|
||||||
});
|
|
||||||
return new ErrorDTO("Ошибка отправки Email-сообщения (%s)".formatted(addresses), BUSINESS_ERROR);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -1,27 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.system.config;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.mail.javamail.JavaMailSender;
|
|
||||||
import org.springframework.mail.javamail.JavaMailSenderImpl;
|
|
||||||
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
public class MailConfig {
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public JavaMailSender getJavaMailSender(
|
|
||||||
@Value("${application.smtp.host}") String smtpHost,
|
|
||||||
@Value("${application.smtp.port}") String smtpPort
|
|
||||||
) {
|
|
||||||
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
|
|
||||||
mailSender.setHost(smtpHost);
|
|
||||||
mailSender.setPort(Integer.parseInt(smtpPort));
|
|
||||||
Properties props = mailSender.getJavaMailProperties();
|
|
||||||
props.put("mail.transport.protocol", "smtp");
|
|
||||||
props.put("mail.debug", "true");
|
|
||||||
return mailSender;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -31,7 +31,8 @@ import ru.mskobaro.tdms.system.web.LoggingRequestFilter;
|
|||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static ru.mskobaro.tdms.business.service.RoleService.Authority.*;
|
import static ru.mskobaro.tdms.business.service.RoleService.Authority.ADMIN;
|
||||||
|
import static ru.mskobaro.tdms.business.service.RoleService.Authority.SECRETARY;
|
||||||
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -62,14 +63,16 @@ public class SecurityConfig {
|
|||||||
@Bean
|
@Bean
|
||||||
@Primary
|
@Primary
|
||||||
public CorsConfigurationSource corsConfiguration(
|
public CorsConfigurationSource corsConfiguration(
|
||||||
@Value("${application.domain}") String domain
|
@Value("${application.domain}") String domain,
|
||||||
|
@Value("${application.port}") String port,
|
||||||
|
@Value("${application.protocol}") String protocol
|
||||||
) {
|
) {
|
||||||
CorsConfiguration corsConfiguration = new CorsConfiguration();
|
CorsConfiguration corsConfiguration = new CorsConfiguration();
|
||||||
corsConfiguration.setAllowedMethods(List.of(HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.OPTIONS.name()));
|
corsConfiguration.setAllowedMethods(List.of(HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.OPTIONS.name()));
|
||||||
corsConfiguration.setAllowedHeaders(List.of("Authorization", "Content-Type"));
|
corsConfiguration.setAllowedHeaders(List.of("Authorization", "Content-Type"));
|
||||||
corsConfiguration.setAllowCredentials(true);
|
corsConfiguration.setAllowCredentials(true);
|
||||||
corsConfiguration.setMaxAge(Duration.ofDays(1));
|
corsConfiguration.setMaxAge(Duration.ofDays(1));
|
||||||
corsConfiguration.addAllowedOrigin(StringUtils.join("https", "://", domain));
|
corsConfiguration.addAllowedOrigin(StringUtils.join(protocol, "://", domain, ":", port));
|
||||||
|
|
||||||
if (environment.matchesProfiles("dev")) {
|
if (environment.matchesProfiles("dev")) {
|
||||||
corsConfiguration.addAllowedOrigin("http://localhost:8888");
|
corsConfiguration.addAllowedOrigin("http://localhost:8888");
|
||||||
@ -112,8 +115,6 @@ public class SecurityConfig {
|
|||||||
// Сложная логика авторизации, так что проверяем явно в ParticipantService
|
// Сложная логика авторизации, так что проверяем явно в ParticipantService
|
||||||
httpAuthorization.requestMatchers("/api/v1/participant/save").authenticated();
|
httpAuthorization.requestMatchers("/api/v1/participant/save").authenticated();
|
||||||
httpAuthorization.requestMatchers("/api/v1/participant/delete").hasAuthority(ADMIN.getAuthority());
|
httpAuthorization.requestMatchers("/api/v1/participant/delete").hasAuthority(ADMIN.getAuthority());
|
||||||
httpAuthorization.requestMatchers("/api/v1/participant/get-all-antipl").permitAll();
|
|
||||||
httpAuthorization.requestMatchers("/api/v1/participant/get-all-norm").permitAll();
|
|
||||||
|
|
||||||
httpAuthorization.requestMatchers("/api/v1/group/get-all-groups").permitAll();
|
httpAuthorization.requestMatchers("/api/v1/group/get-all-groups").permitAll();
|
||||||
httpAuthorization.requestMatchers("/api/v1/group/save").hasAnyAuthority(ADMIN.getAuthority(), SECRETARY.getAuthority());
|
httpAuthorization.requestMatchers("/api/v1/group/save").hasAnyAuthority(ADMIN.getAuthority(), SECRETARY.getAuthority());
|
||||||
@ -121,8 +122,6 @@ public class SecurityConfig {
|
|||||||
|
|
||||||
httpAuthorization.requestMatchers("/api/v1/student/by-partic-id").permitAll();
|
httpAuthorization.requestMatchers("/api/v1/student/by-partic-id").permitAll();
|
||||||
httpAuthorization.requestMatchers("/api/v1/student/all-without-group").permitAll();
|
httpAuthorization.requestMatchers("/api/v1/student/all-without-group").permitAll();
|
||||||
httpAuthorization.requestMatchers("/api/v1/student/by-id").permitAll();
|
|
||||||
httpAuthorization.requestMatchers("/api/v1/student/by-defense-id").permitAll();
|
|
||||||
|
|
||||||
httpAuthorization.requestMatchers("/api/v1/teacher-data/get-all").permitAll();
|
httpAuthorization.requestMatchers("/api/v1/teacher-data/get-all").permitAll();
|
||||||
httpAuthorization.requestMatchers("/api/v1/teacher-data/by-partic-id").permitAll();
|
httpAuthorization.requestMatchers("/api/v1/teacher-data/by-partic-id").permitAll();
|
||||||
@ -130,39 +129,11 @@ public class SecurityConfig {
|
|||||||
httpAuthorization.requestMatchers("/api/v1/prep-direction/get-all").permitAll();
|
httpAuthorization.requestMatchers("/api/v1/prep-direction/get-all").permitAll();
|
||||||
httpAuthorization.requestMatchers("/api/v1/prep-direction/save").hasAnyAuthority(ADMIN.getAuthority(), SECRETARY.getAuthority());
|
httpAuthorization.requestMatchers("/api/v1/prep-direction/save").hasAnyAuthority(ADMIN.getAuthority(), SECRETARY.getAuthority());
|
||||||
|
|
||||||
httpAuthorization.requestMatchers("/api/v1/defense/get-all").permitAll();
|
httpAuthorization.requestMatchers("/api/v1/defence/all").permitAll();
|
||||||
httpAuthorization.requestMatchers("/api/v1/defense/get-by-id").permitAll();
|
|
||||||
httpAuthorization.requestMatchers("/api/v1/defense/save").permitAll();
|
|
||||||
httpAuthorization.requestMatchers("/api/v1/defense/defense-table").permitAll();
|
|
||||||
httpAuthorization.requestMatchers("/api/v1/defense/defense-table-save").hasAnyAuthority(ADMIN.getAuthority(), TEACHER.getAuthority());
|
|
||||||
httpAuthorization.requestMatchers("/api/v1/defense/to-next-state").hasAnyAuthority(ADMIN.getAuthority(), SECRETARY.getAuthority(), TEACHER.getAuthority());
|
|
||||||
httpAuthorization.requestMatchers("api/v1/defense/recreate-protection-order").hasAnyAuthority(ADMIN.getAuthority(), TEACHER.getAuthority());
|
|
||||||
httpAuthorization.requestMatchers("api/v1/defense/save-order").hasAnyAuthority(ADMIN.getAuthority(), TEACHER.getAuthority());
|
|
||||||
|
|
||||||
httpAuthorization.requestMatchers("/api/v1/task/create-topic-agreement").hasAuthority(STUDENT.getAuthority());
|
|
||||||
httpAuthorization.requestMatchers("/api/v1/task/diploma-agreement-maker").hasAuthority(STUDENT.getAuthority());
|
|
||||||
httpAuthorization.requestMatchers("/api/v1/task/notif-count").authenticated();
|
|
||||||
httpAuthorization.requestMatchers("/api/v1/task/get-current-tasks").authenticated();
|
|
||||||
httpAuthorization.requestMatchers("/api/v1/task/diploma-agreement-maker-by-partic-id").authenticated();
|
|
||||||
httpAuthorization.requestMatchers("/api/v1/task/topic-preparation-finish").hasAnyAuthority(TEACHER.getAuthority());
|
|
||||||
httpAuthorization.requestMatchers("/api/v1/task/agreement-change").hasAnyAuthority(STUDENT.getAuthority(), TEACHER.getAuthority());
|
|
||||||
httpAuthorization.requestMatchers("/api/v1/task/def-prep-finish").hasAnyAuthority(TEACHER.getAuthority());
|
|
||||||
httpAuthorization.requestMatchers("/api/v1/task/norm-antipl-finish").authenticated();
|
|
||||||
|
|
||||||
httpAuthorization.requestMatchers("/api/v1/diploma-topic/all").permitAll();
|
httpAuthorization.requestMatchers("/api/v1/diploma-topic/all").permitAll();
|
||||||
httpAuthorization.requestMatchers("/api/v1/diploma-topic/all-for-student").permitAll();
|
httpAuthorization.requestMatchers("/api/v1/diploma-topic/all-for-student").permitAll();
|
||||||
httpAuthorization.requestMatchers("/api/v1/diploma-topic/by-id").permitAll();
|
httpAuthorization.requestMatchers("/api/v1/diploma-topic/save").hasAnyAuthority(ADMIN.getAuthority(), SECRETARY.getAuthority());
|
||||||
httpAuthorization.requestMatchers("/api/v1/diploma-topic/save").hasAnyAuthority(ADMIN.getAuthority(), SECRETARY.getAuthority(), TEACHER.getAuthority());
|
|
||||||
httpAuthorization.requestMatchers("/api/v1/diploma-topic/matching-teacher-and-dir-prep").permitAll();
|
|
||||||
|
|
||||||
httpAuthorization.requestMatchers("/api/v1/home-page/default-info").permitAll();
|
|
||||||
|
|
||||||
httpAuthorization.requestMatchers("api/v1/commission-member/get-all").permitAll();
|
|
||||||
httpAuthorization.requestMatchers("api/v1/commission-member/by-partic-id").permitAll();
|
|
||||||
|
|
||||||
httpAuthorization.requestMatchers("api/v1/doc/gek-questions").permitAll();
|
|
||||||
httpAuthorization.requestMatchers("api/v1/doc/stud-list").permitAll();
|
|
||||||
httpAuthorization.requestMatchers("api/v1/doc/topic-list").permitAll();
|
|
||||||
|
|
||||||
httpAuthorization.requestMatchers("/api/**").denyAll();
|
httpAuthorization.requestMatchers("/api/**").denyAll();
|
||||||
|
|
||||||
|
|||||||
@ -11,13 +11,10 @@ import org.springframework.stereotype.Component;
|
|||||||
import org.springframework.web.filter.OncePerRequestFilter;
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class LoggingRequestFilter extends OncePerRequestFilter {
|
public class LoggingRequestFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
||||||
UUID uuid = UUID.randomUUID();
|
UUID uuid = UUID.randomUUID();
|
||||||
@ -25,12 +22,6 @@ public class LoggingRequestFilter extends OncePerRequestFilter {
|
|||||||
String username = SecurityContextHolder.getContext().getAuthentication() != null ?
|
String username = SecurityContextHolder.getContext().getAuthentication() != null ?
|
||||||
SecurityContextHolder.getContext().getAuthentication().getName() : "anonymousUser";
|
SecurityContextHolder.getContext().getAuthentication().getName() : "anonymousUser";
|
||||||
HttpSession session = request.getSession(false);
|
HttpSession session = request.getSession(false);
|
||||||
|
|
||||||
if (request.getRequestURI().contains("notif-count") || request.getRequestURI().contains("get-current-tasks")) {
|
|
||||||
filterChain.doFilter(request, response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
log.info("Request received: [{}] {} user: {}, session: {}, remote ip: {} [{}]",
|
log.info("Request received: [{}] {} user: {}, session: {}, remote ip: {} [{}]",
|
||||||
request.getMethod(), request.getRequestURI(), username,
|
request.getMethod(), request.getRequestURI(), username,
|
||||||
session == null ? "no" : session.getId(), request.getRemoteAddr(), uuid);
|
session == null ? "no" : session.getId(), request.getRemoteAddr(), uuid);
|
||||||
|
|||||||
@ -49,20 +49,5 @@
|
|||||||
"name": "application.protocol",
|
"name": "application.protocol",
|
||||||
"type": "java.lang.String",
|
"type": "java.lang.String",
|
||||||
"description": "Service protocol."
|
"description": "Service protocol."
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "application.smtp.host",
|
|
||||||
"type": "java.lang.String",
|
|
||||||
"description": "SMTP server host."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "application.smtp.port",
|
|
||||||
"type": "java.lang.String",
|
|
||||||
"description": "SMTP server port."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "application.smtp.message-from",
|
|
||||||
"type": "java.lang.String",
|
|
||||||
"description": "Sender email."
|
|
||||||
}
|
}
|
||||||
] }
|
] }
|
||||||
@ -8,13 +8,8 @@ application:
|
|||||||
version: @version@
|
version: @version@
|
||||||
type: production
|
type: production
|
||||||
port: 443
|
port: 443
|
||||||
domain: vkr.tu-bryansk.ru
|
domain: tdms.tu-bryansk.ru
|
||||||
host: localhost
|
|
||||||
protocol: https
|
protocol: https
|
||||||
smtp:
|
|
||||||
host: localhost
|
|
||||||
port: 2525
|
|
||||||
message-from: admin@vkr.tu-bryansk.ru
|
|
||||||
|
|
||||||
spring:
|
spring:
|
||||||
application:
|
application:
|
||||||
@ -37,7 +32,7 @@ spring:
|
|||||||
location: banner.txt
|
location: banner.txt
|
||||||
server:
|
server:
|
||||||
port: ${application.port}
|
port: ${application.port}
|
||||||
address: ${application.host}
|
address: ${application.domain}
|
||||||
compression:
|
compression:
|
||||||
enabled: true
|
enabled: true
|
||||||
management:
|
management:
|
||||||
|
|||||||
@ -2,14 +2,16 @@ CREATE TABLE defense
|
|||||||
(
|
(
|
||||||
id BIGSERIAL PRIMARY KEY,
|
id BIGSERIAL PRIMARY KEY,
|
||||||
defense_date DATE,
|
defense_date DATE,
|
||||||
status TEXT NOT NULL,
|
|
||||||
direction_of_preparation_id BIGINT,
|
|
||||||
responsible_for_antiplagiarism_id BIGINT,
|
|
||||||
responsible_for_normcontrol_id BIGINT,
|
|
||||||
created_at TIMESTAMP WITHOUT TIME ZONE,
|
created_at TIMESTAMP WITHOUT TIME ZONE,
|
||||||
updated_at TIMESTAMP WITHOUT TIME ZONE
|
updated_at TIMESTAMP WITHOUT TIME ZONE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE defense_best_student_works
|
||||||
|
(
|
||||||
|
defense_id BIGINT,
|
||||||
|
student_data_id BIGINT
|
||||||
|
);
|
||||||
|
|
||||||
CREATE TABLE defense_commission
|
CREATE TABLE defense_commission
|
||||||
(
|
(
|
||||||
defense_id BIGINT,
|
defense_id BIGINT,
|
||||||
@ -31,7 +33,6 @@ CREATE TABLE direction_of_preparation
|
|||||||
id BIGSERIAL PRIMARY KEY,
|
id BIGSERIAL PRIMARY KEY,
|
||||||
name TEXT,
|
name TEXT,
|
||||||
code TEXT,
|
code TEXT,
|
||||||
responsible_id BIGINT,
|
|
||||||
created_at TIMESTAMP WITHOUT TIME ZONE,
|
created_at TIMESTAMP WITHOUT TIME ZONE,
|
||||||
updated_at TIMESTAMP WITHOUT TIME ZONE
|
updated_at TIMESTAMP WITHOUT TIME ZONE
|
||||||
);
|
);
|
||||||
@ -72,6 +73,7 @@ CREATE TABLE role
|
|||||||
authority TEXT
|
authority TEXT
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/* todo */
|
||||||
CREATE TABLE student_data
|
CREATE TABLE student_data
|
||||||
(
|
(
|
||||||
id BIGSERIAL PRIMARY KEY,
|
id BIGSERIAL PRIMARY KEY,
|
||||||
@ -82,42 +84,30 @@ CREATE TABLE student_data
|
|||||||
protection_order INTEGER,
|
protection_order INTEGER,
|
||||||
protection_day INTEGER,
|
protection_day INTEGER,
|
||||||
|
|
||||||
|
mark_comment INTEGER,
|
||||||
mark_practice INTEGER,
|
mark_practice INTEGER,
|
||||||
predefnese_mark INTEGER,
|
|
||||||
oztiv_mark INTEGER,
|
|
||||||
|
|
||||||
|
|
||||||
|
predefnese_comment TEXT,
|
||||||
normal_control BOOLEAN,
|
normal_control BOOLEAN,
|
||||||
anti_plagiarism INTEGER,
|
anti_plagiarism INTEGER,
|
||||||
|
|
||||||
record_book_returned BOOLEAN,
|
record_book_returned BOOLEAN,
|
||||||
|
|
||||||
work TEXT,
|
work TEXT,
|
||||||
|
|
||||||
diploma_topic_id BIGINT,
|
diploma_topic_id BIGINT,
|
||||||
adviser_teacher_partic_id BIGINT,
|
adviser_teacher_partic_id BIGINT,
|
||||||
group_id BIGINT,
|
group_id BIGINT,
|
||||||
|
|
||||||
marks_3 BIGINT,
|
marks_3 BIGINT,
|
||||||
marks_4 BIGINT,
|
marks_4 BIGINT,
|
||||||
marks_5 BIGINT,
|
marks_5 BIGINT,
|
||||||
|
|
||||||
commission_mark BIGINT,
|
commission_mark BIGINT,
|
||||||
|
|
||||||
estimated BOOLEAN,
|
estimated BOOLEAN,
|
||||||
|
|
||||||
diploma_with_honors BOOLEAN,
|
diploma_with_honors BOOLEAN,
|
||||||
vnedreniye BOOLEAN,
|
|
||||||
|
|
||||||
magistracy_recommendation BOOLEAN,
|
magistracy_recommendation BOOLEAN,
|
||||||
magistracy_wanted BOOLEAN,
|
magistracy_wanted BOOLEAN,
|
||||||
|
|
||||||
electronic BOOLEAN,
|
|
||||||
|
|
||||||
created_at TIMESTAMP WITHOUT TIME ZONE,
|
created_at TIMESTAMP WITHOUT TIME ZONE,
|
||||||
updated_at TIMESTAMP WITHOUT TIME ZONE
|
updated_at TIMESTAMP WITHOUT TIME ZONE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/* not implemented */
|
||||||
create table questionnaire
|
create table questionnaire
|
||||||
(
|
(
|
||||||
id BIGSERIAL PRIMARY KEY,
|
id BIGSERIAL PRIMARY KEY,
|
||||||
@ -135,6 +125,7 @@ create table study_form
|
|||||||
updated_at TIMESTAMP WITHOUT TIME ZONE
|
updated_at TIMESTAMP WITHOUT TIME ZONE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/* todo */
|
||||||
create table stud_comment
|
create table stud_comment
|
||||||
(
|
(
|
||||||
id BIGSERIAL PRIMARY KEY,
|
id BIGSERIAL PRIMARY KEY,
|
||||||
@ -143,6 +134,7 @@ create table stud_comment
|
|||||||
updated_at TIMESTAMP WITHOUT TIME ZONE
|
updated_at TIMESTAMP WITHOUT TIME ZONE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/* todo */
|
||||||
create table student_data_comment
|
create table student_data_comment
|
||||||
(
|
(
|
||||||
id BIGSERIAL PRIMARY KEY,
|
id BIGSERIAL PRIMARY KEY,
|
||||||
@ -181,32 +173,12 @@ CREATE TABLE "user"
|
|||||||
updated_at TIMESTAMP WITHOUT TIME ZONE
|
updated_at TIMESTAMP WITHOUT TIME ZONE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE task
|
CREATE TABLE task
|
||||||
(
|
(
|
||||||
id BIGSERIAL PRIMARY KEY,
|
id BIGSERIAL PRIMARY KEY,
|
||||||
status TEXT,
|
|
||||||
type TEXT,
|
type TEXT,
|
||||||
defense_id BIGINT,
|
status TEXT,
|
||||||
maker_partic_id BIGINT,
|
fields jsonb,
|
||||||
checker_partic_id BIGINT,
|
|
||||||
task_type TEXT,
|
|
||||||
diploma_topic_id BIGINT,
|
|
||||||
diploma_topic_name TEXT,
|
|
||||||
practice_mark BIGINT,
|
|
||||||
antiplagiarism_percent BIGINT,
|
|
||||||
normcontrol_passed BOOLEAN,
|
|
||||||
approved_at TIMESTAMP WITHOUT TIME ZONE,
|
|
||||||
created_at TIMESTAMP WITHOUT TIME ZONE,
|
|
||||||
updated_at TIMESTAMP WITHOUT TIME ZONE
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE message_template
|
|
||||||
(
|
|
||||||
id BIGSERIAL PRIMARY KEY,
|
|
||||||
message_type TEXT,
|
|
||||||
subject_template TEXT,
|
|
||||||
message_template TEXT,
|
|
||||||
created_at TIMESTAMP WITHOUT TIME ZONE,
|
created_at TIMESTAMP WITHOUT TIME ZONE,
|
||||||
updated_at TIMESTAMP WITHOUT TIME ZONE
|
updated_at TIMESTAMP WITHOUT TIME ZONE
|
||||||
);
|
);
|
||||||
@ -229,6 +201,9 @@ ALTER TABLE participant_role
|
|||||||
ALTER TABLE participant_role
|
ALTER TABLE participant_role
|
||||||
ADD CONSTRAINT FK_PARROL_ON_ROLE FOREIGN KEY (role_id) REFERENCES role (id) ON DELETE CASCADE ON UPDATE CASCADE;
|
ADD CONSTRAINT FK_PARROL_ON_ROLE FOREIGN KEY (role_id) REFERENCES role (id) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE student_data
|
||||||
|
ADD CONSTRAINT UC_STUDENT_DATA_PARTIC UNIQUE (partic_id);
|
||||||
|
|
||||||
ALTER TABLE student_data
|
ALTER TABLE student_data
|
||||||
ADD CONSTRAINT FK_STUDENT_DATA_ON_ADVISER_TEACHER_PARTIC FOREIGN KEY (adviser_teacher_partic_id) REFERENCES participant (id) ON DELETE SET NULL ON UPDATE CASCADE;
|
ADD CONSTRAINT FK_STUDENT_DATA_ON_ADVISER_TEACHER_PARTIC FOREIGN KEY (adviser_teacher_partic_id) REFERENCES participant (id) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
@ -277,6 +252,12 @@ ALTER TABLE direction_of_preparation
|
|||||||
ALTER TABLE diploma_topic
|
ALTER TABLE diploma_topic
|
||||||
ADD CONSTRAINT UC_DIPLOMA_TOPIC_NAME FOREIGN KEY (direction_of_preparation_id) REFERENCES direction_of_preparation (id) ON DELETE SET NULL ON UPDATE CASCADE;
|
ADD CONSTRAINT UC_DIPLOMA_TOPIC_NAME FOREIGN KEY (direction_of_preparation_id) REFERENCES direction_of_preparation (id) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE defense_best_student_works
|
||||||
|
ADD CONSTRAINT FK_DEFENSE_BEST_STUDENT_WORKS_ON_DEFENSE FOREIGN KEY (defense_id) REFERENCES defense (id) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE defense_best_student_works
|
||||||
|
ADD CONSTRAINT FK_DEFENSE_BEST_STUDENT_WORKS_ON_STUDENT_DATA FOREIGN KEY (student_data_id) REFERENCES student_data (id) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
ALTER TABLE stud_comment
|
ALTER TABLE stud_comment
|
||||||
ADD CONSTRAINT UC_STUD_COMMENT_COMMENT UNIQUE (comment);
|
ADD CONSTRAINT UC_STUD_COMMENT_COMMENT UNIQUE (comment);
|
||||||
|
|
||||||
@ -297,18 +278,3 @@ alter table questionnaire
|
|||||||
|
|
||||||
alter table questionnaire
|
alter table questionnaire
|
||||||
add constraint FK_QUESTIONNAIRE_STUDENT_DATA foreign key (student_data_id) references student_data (id) on delete cascade on update cascade;
|
add constraint FK_QUESTIONNAIRE_STUDENT_DATA foreign key (student_data_id) references student_data (id) on delete cascade on update cascade;
|
||||||
|
|
||||||
alter table direction_of_preparation
|
|
||||||
add constraint FK_RESPONSIBLE FOREIGN KEY (responsible_id) REFERENCES teacher_data (id) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
alter table defense
|
|
||||||
add constraint FK_RESPONSIBLE_NORM FOREIGN KEY (responsible_for_normcontrol_id) REFERENCES participant (id) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
alter table defense
|
|
||||||
add constraint FK_RESPONSIBLE_ANTIPLAGIARISM FOREIGN KEY (responsible_for_antiplagiarism_id) REFERENCES participant (id) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
alter table task
|
|
||||||
add constraint FK_DEFENSE FOREIGN KEY (defense_id) REFERENCES defense (id) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
alter table defense
|
|
||||||
add constraint FK_DIR_OF_PRERP FOREIGN KEY (direction_of_preparation_id) REFERENCES direction_of_preparation (id) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
@ -1,97 +0,0 @@
|
|||||||
-- TOPIC_LIST_PREPARE_START_FOR_TEACHER,
|
|
||||||
--
|
|
||||||
-- TOPIC_CHOOSE_FOR_STUDENT,
|
|
||||||
-- TOPIC_CHOOSE_FOR_TEACHER,
|
|
||||||
--
|
|
||||||
-- TASK_CREATE_FOR_TEACHER,
|
|
||||||
-- TASK_ASSIGN_FOR_TEACHER,
|
|
||||||
--
|
|
||||||
-- PRE_DIPLOMA_PRACTICE_START_FOR_TEACHER,
|
|
||||||
-- PRE_DIPLOMA_PRACTICE_START_FOR_STUDENT,
|
|
||||||
--
|
|
||||||
-- TOPIC_FINALIZATION_FOR_TEACHER,
|
|
||||||
--
|
|
||||||
-- PRE_DEFENSE_FOR_STUDENT,
|
|
||||||
--
|
|
||||||
-- ANTIPLAGIARISM_FOR_STUDENT,
|
|
||||||
--
|
|
||||||
-- DEFENSE_PREPARATION_FOR_STUDENT,
|
|
||||||
--
|
|
||||||
-- MAIN_VRK_WORK_START,
|
|
||||||
--
|
|
||||||
-- NORMCONTROL_AND_ANTIPLAGIARISM,
|
|
||||||
--
|
|
||||||
-- DEFENSE,
|
|
||||||
--
|
|
||||||
-- DEFENSE_PREPARATION_FOR_TEACHER,
|
|
||||||
|
|
||||||
INSERT INTO message_template (message_type,
|
|
||||||
subject_template,
|
|
||||||
message_template,
|
|
||||||
created_at,
|
|
||||||
updated_at)
|
|
||||||
VALUES ('TOPIC_LIST_PREPARE_START_FOR_TEACHER',
|
|
||||||
'Подготовка списка тем для студентов',
|
|
||||||
E'Уважаемый $${ФИО_НАУЧ_РУК},\nпросим вас подготовить и отправить список тем для выбора студентами.\n\nС уважением, администрация.',
|
|
||||||
NOW(),
|
|
||||||
NOW()),
|
|
||||||
('TOPIC_CHOOSE_FOR_STUDENT',
|
|
||||||
'Выбор темы для работы',
|
|
||||||
E'Уважаемый $${ФИО_СТУД},\nПожалуйста, выберите тему вашей работы из предложенного списка до конца недели.\n\nС уважением, администрация.',
|
|
||||||
NOW(),
|
|
||||||
NOW()),
|
|
||||||
('TOPIC_CHOOSE_FOR_TEACHER',
|
|
||||||
'Утверждение выбора тем студентами',
|
|
||||||
E'Уважаемый $${ФИО_НАУЧ_РУК},\nСтуденты начали выбор тем.\nПросим вас утвердить.\n\nС уважением, администрация.',
|
|
||||||
NOW(),
|
|
||||||
NOW()),
|
|
||||||
('TASK_CREATE_FOR_TEACHER',
|
|
||||||
'Создание задания для студента',
|
|
||||||
E'Уважаемый $${ФИО_НАУЧ_РУК},\nПросим вас создать задание для студента $${ФИО_СТУД}.\n\nС уважением, администрация.',
|
|
||||||
NOW(),
|
|
||||||
NOW()),
|
|
||||||
('TASK_ASSIGN_FOR_TEACHER',
|
|
||||||
'Назначение задания студенту',
|
|
||||||
E'Уважаемый $${ФИО_НАУЧ_РУК},\nЗадание для студента $${ФИО_СТУД} назначено. Просим вас проконтролировать выполнение.\n\nС уважением, администрация.',
|
|
||||||
NOW(),
|
|
||||||
NOW()),
|
|
||||||
('PRE_DIPLOMA_PRACTICE_START_FOR_TEACHER',
|
|
||||||
'Начало преддипломной практики',
|
|
||||||
E'Уважаемый $${ФИО_НАУЧ_РУК},\nПреддипломная практика для студента $${ФИО_СТУД} начинается. Просим вас обеспечить руководство.\n\nС уважением, администрация.',
|
|
||||||
NOW(),
|
|
||||||
NOW()),
|
|
||||||
('PRE_DIPLOMA_PRACTICE_START_FOR_STUDENT',
|
|
||||||
'Начало преддипломной практики',
|
|
||||||
E'Уважаемый $${ФИО_СТУД}, ваша\nПреддипломная практика начинается. Свяжитесь с научным руководителем $${ФИО_НАУЧ_РУК} для получения инструкций.\n\nС уважением, администрация.',
|
|
||||||
NOW(),
|
|
||||||
NOW()),
|
|
||||||
('TOPIC_FINALIZATION_FOR_TEACHER',
|
|
||||||
'Окончательное утверждение темы',
|
|
||||||
E'Уважаемый $${ФИО_НАУЧ_РУК},\nПросим вас окончательно утвердить тему работы студента $${ФИО_СТУД} до указанного срока.\n\nС уважением, администрация.',
|
|
||||||
NOW(),
|
|
||||||
NOW()),
|
|
||||||
('PRE_DEFENSE_FOR_TEACHER',
|
|
||||||
'Подготовка к предзащите',
|
|
||||||
E'Уважаемый $${ФИО_НАУЧ_РУК},\nПредзащита работы студента $${ФИО_СТУД} назначена. Просим вас подготовить необходимые материалы.\n\nС уважением, администрация.',
|
|
||||||
NOW(),
|
|
||||||
NOW()),
|
|
||||||
('PRE_DEFENSE_FOR_STUDENT',
|
|
||||||
'Подготовка к предзащите',
|
|
||||||
E'Уважаемый $${ФИО_СТУД},\nВаша предзащита назначена. Подготовьте материалы и согласуйте с $${ФИО_НАУЧ_РУК}.\n\nС уважением, администрация.',
|
|
||||||
NOW(),
|
|
||||||
NOW()),
|
|
||||||
('ANTIPLAGIARISM_FOR_STUDENT',
|
|
||||||
'Проверка работы на антиплагиат',
|
|
||||||
E'Уважаемый $${ФИО_СТУД},\nЗагрузите вашу работу в систему антиплагиата до указанного срока. Обратитесь к $${ФИО_НАУЧ_РУК} при необходимости.\n\nС уважением, администрация.',
|
|
||||||
NOW(),
|
|
||||||
NOW()),
|
|
||||||
('DEFENSE_PREPARATION_FOR_STUDENT',
|
|
||||||
'Подготовка к защите',
|
|
||||||
E'Уважаемый $${ФИО_СТУД},\nЗащита вашей работы приближается. Подготовьте презентацию и согласуйте с $${ФИО_НАУЧ_РУК}.\n\nС уважением, администрация.',
|
|
||||||
NOW(),
|
|
||||||
NOW()),
|
|
||||||
('DEFENSE_PREPARATION_FOR_TEACHER',
|
|
||||||
'Подготовка к защите студента',
|
|
||||||
E'Уважаемый $${ФИО_НАУЧ_РУК},\nЗащита работы студента $${ФИО_СТУД} назначена. Просим вас проконтролировать подготовку и оставить отзыв по работе студента.\n\nС уважением, администрация.',
|
|
||||||
NOW(),
|
|
||||||
NOW());
|
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
create table defense
|
||||||
|
(
|
||||||
|
id bigserial primary key,
|
||||||
|
defence_date timestamptz,
|
||||||
|
|
||||||
|
created_at timestamptz not null,
|
||||||
|
updated_at timestamptz
|
||||||
|
);
|
||||||
|
|
||||||
|
-- COMMENTS
|
||||||
|
comment on table defense is 'Таблица для хранения данных о защитах';
|
||||||
|
comment on column defense.defence_date is 'Дата защиты';
|
||||||
40
server/src/main/resources/db/test-data/diploma_topic.sql
Normal file
40
server/src/main/resources/db/test-data/diploma_topic.sql
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
INSERT INTO diploma_topic (name)
|
||||||
|
VALUES ('Мобильное приложение для заказа автозапчастей на платформе ABCP'),
|
||||||
|
('Подсистема уведомления пользователей для программного комплекса "РискПроф. Учебный центр"'),
|
||||||
|
('Веб-приложение "Таск-менеджер"'),
|
||||||
|
('Интернет-магазин электроники'),
|
||||||
|
('Информационная система для студентов БГТУ в Telegram'),
|
||||||
|
('Автоматизированная система тестирования сотрудников для определения их компетенций: модуль подготовки тестов и учета результатов'),
|
||||||
|
('Инструментарий для разработки динамической экосистемы игрового пространства. Подсистема управления поведением внутриигровых агентов'),
|
||||||
|
('Корпоративное веб-приложение по управлению задачами'),
|
||||||
|
('Подсистемы визуализации и аналитики для онлайн-сервиса поддержки scrum-доски'),
|
||||||
|
('Интерактивная система обучения приемам работы с криптовалютой'),
|
||||||
|
('Автоматизированная система учета деятельности салона по продаже автомобилей'),
|
||||||
|
('Обучающее мобильное android-приложение'),
|
||||||
|
('Автоматизированная система учета зуботехнической CAD/CAM лаборатории'),
|
||||||
|
('Автоматизированная система тестирования сотрудников для определения их компетенций: модуль регистрации и управления кабинетами'),
|
||||||
|
('Система мониторинга успеваемости обучающихся и посещаемости занятий образовательного учреждения'),
|
||||||
|
('Мобильное приложение для организации работы репетитора'),
|
||||||
|
('Модуль "Редактор рисков" для программного комплекса управления профессиональными рисками "1С. ЕОС ПБ"'),
|
||||||
|
('Онлайн-сервис по продаже товаров (на примере ООО «ЭПК-2»'),
|
||||||
|
('Веб-сервис по обучению Microsoft Excel'),
|
||||||
|
('Инструментарий для разработки динамической экосистемы игрового пространства. Подсистема генерации наполнения помещений'),
|
||||||
|
('Подсистема интеграции с федеральной государственной информационной системой по охране труда для программного комплекса «РискПроф. Учебный центр»'),
|
||||||
|
('Разработка приложения голосовой авторизации на основе нейросетевого подхода'),
|
||||||
|
('Автоматизированная система учета деятельности спортивного клуба'),
|
||||||
|
('Модуль "Специальная оценка условий труда" для программного комплекса управления профессиональными рисками "1С. ЕОС ПБ"'),
|
||||||
|
('Интернет-магазин по продаже спортивной обуви'),
|
||||||
|
('Приложение интерактивной исторической карты'),
|
||||||
|
('Миграция системы учёта с 1С:УТ на 1С:КА'),
|
||||||
|
('Программный комплекс для автоматизированного проведения опросов и тестирования пользователей'),
|
||||||
|
('Автоматизированное тестирование программного комплекса «Федеральная государственная информационная система специальной оценки условий труда»'),
|
||||||
|
('Модуль "Единая информационно-справочная подсистема" для федеральной государственной информационной системы по охране труда'),
|
||||||
|
('Подсистема сопровождения обучения по охране труда для программного комплекса «РискПроф. Учебный центр»'),
|
||||||
|
('Программное обеспечение системы обучения и тестирования в мессенджере Telegram'),
|
||||||
|
('Онлайн-калькулятор индексов влияния в играх взвешенного голосования'),
|
||||||
|
('Telegram-бот с функциями обработки изображений'),
|
||||||
|
('Подсистема администрирования автоматизированной системы для проведения платежей и перевода денежных средств'),
|
||||||
|
('Подсистема администрирования для программного комплекса распределения студентов по руководителям выпускных квалификационных работ'),
|
||||||
|
('Библиотека контроля качества данных в базах и хранилищах данных для программного комплекса MetaControl'),
|
||||||
|
('Инструментарий для разработки динамической экосистемы игрового пространства. Подсистема генерации карты помещений'),
|
||||||
|
('Программная система решения транспортной задачи методом генетического алгоритма для торговой сети');
|
||||||
3
server/src/main/resources/db/test-data/group.sql
Normal file
3
server/src/main/resources/db/test-data/group.sql
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
INSERT INTO "group" (name, curator_teacher_id, created_at, updated_at)
|
||||||
|
VALUES ('ИВТ-1', 40, now(), now()),
|
||||||
|
('ИВТ-2', 40, now(), now());
|
||||||
98
server/src/main/resources/db/test-data/student.sql
Normal file
98
server/src/main/resources/db/test-data/student.sql
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
do
|
||||||
|
$$
|
||||||
|
begin
|
||||||
|
INSERT INTO studentData (form,
|
||||||
|
protection_order,
|
||||||
|
magistracy,
|
||||||
|
digital_format_present,
|
||||||
|
mark_comment,
|
||||||
|
mark_practice,
|
||||||
|
predefence_comment,
|
||||||
|
normal_control,
|
||||||
|
anti_plagiarism,
|
||||||
|
note,
|
||||||
|
record_book_returned,
|
||||||
|
work,
|
||||||
|
user_id,
|
||||||
|
diploma_topic_id,
|
||||||
|
mentor_user_id,
|
||||||
|
group_id,
|
||||||
|
created_at)
|
||||||
|
VALUES (true, 1100, 'ПРИ, ИВТ или другой вуз', true, 5, 5, 'ок', 'Подписано', 7862, 'Акт о внедрении', true,
|
||||||
|
'нет', 1, 1, 40, 3, now()),
|
||||||
|
(true, 1110, 'Да, но не уверен, в БГТУ ли', true, 5, 5, 'ок', 'Подписано', 8196,
|
||||||
|
'Заявка, Акт о внедрении', true, 'ООО "ЦИРОБЗ"', 2, 2, 40, 3, now()),
|
||||||
|
(true, 3500, 'Нет', true, 3, 3,
|
||||||
|
'Критически низкий уровень. Допущен под ответственность руководителя ВКР', 'Подписано', 7141, 'Иниц',
|
||||||
|
true, 'нет', 3, 3, 41, 3, now()),
|
||||||
|
(true, 1800, 'Да, но не уверен, в БГТУ ли', true, 4, 5, 'Усилить работу', 'Подписано', 5381, 'Иниц',
|
||||||
|
true, 'нет', 4, 4, 42, 3, now()),
|
||||||
|
(true, 2100, 'ИВТ, ПРИ', true, 5, 5, 'ок', 'Подписано', 8146, 'Заявка, Акт о внедрении', true, 'нет', 5,
|
||||||
|
5, 43, 3, now()),
|
||||||
|
(true, 1100, 'ИВТ, ПРИ', true, 5, 5, 'ок', 'Подписано', 7965, 'Иниц', true, 'нет', 6, 6, 41, 3, now()),
|
||||||
|
(true, 1200, 'нет', true, 5, 4, 'Усилить работу', 'Подписано', 8583, Null, true,
|
||||||
|
'Газ Энерго Комплект (ГЭК)', 7, 7, 44, 3, now()),
|
||||||
|
(true, 1700, 'Нет', true, 5, 5,
|
||||||
|
'Критически низкий уровень. Допущен под ответственность руководителя ВКР', 'Подписано', 6647, Null,
|
||||||
|
true, 'нет', 8, 8, 45, 3, now()),
|
||||||
|
(true, 3300, 'ИВТ, ПРИ или другой вуз', true, 5, 5, 'Усилить работу', 'Подписано', 6741,
|
||||||
|
'Заявка, Акт о внедрении', true, 'нет', 9, 9, 46, 3, now()),
|
||||||
|
(true, 1200, 'ИВТ', true, 5, 5, 'ок', 'Подписано', 7645, 'Заявка, Акт о внедрении', true, 'нет', 10, 10,
|
||||||
|
40, 3, now()),
|
||||||
|
(true, 3700, 'нет', true, 3, 3,
|
||||||
|
'Критически низкий уровень. Допущен под ответственность руководителя ВКР', '1', 3093, 'Иниц', true,
|
||||||
|
'нет', 11, 11, 45, 3, now()),
|
||||||
|
(true, 1900, 'Нет', true, 5, 5, 'ок', 'Подписано', 8175, 'Заявка, Акт о внедрении', true, 'нет', 12, 12,
|
||||||
|
42, 3, now()),
|
||||||
|
(true, 3200, 'ИВТ', true, 5, 5, 'Усилить работу', 'Подписано', 7805, 'Акт', true, 'нет', 13, 13, 46, 3,
|
||||||
|
now()),
|
||||||
|
(true, 1200, 'ИВТ, ПРИ', true, 4, 4, 'ок', 'рек', 7590, 'Иниц', true, 'нет', 14, 14, 45, 3, now()),
|
||||||
|
(true, 3900, 'нет', true, 5, 5, 'Усилить работу', 'Подписано', 6463, 'Заявка, Акт о внедрении', true,
|
||||||
|
'нет', 15, 15, 40, 3, now()),
|
||||||
|
(true, 2200, 'ИВТ', true, 5, 5, 'ок', 'Подписано', 7441, Null, true, 'ООО "ЦИРОБЗ"', 16, 16, 44, 3,
|
||||||
|
now()),
|
||||||
|
(true, 1130, 'Нет', true, 5, 4,
|
||||||
|
'Критически низкий уровень. Допущен под ответственность руководителя ВКР', 'Подписано', 7319,
|
||||||
|
'Заявка, Акт о внедрении', true, 'нет', 17, 17, 40, 3, now()),
|
||||||
|
(true, 2400, 'ИВТ', true, 4, 5, 'ок', 'Подписано', 6436, Null, true, 'нет', 18, 18, 45, 3, now()),
|
||||||
|
(true, 1600, 'ИВТ', true, 5, 5, 'Усилить работу', 'Подписано', 6227, 'Исслед', true, 'АО "БЭМЗ"', 19, 19,
|
||||||
|
47, 3, now()),
|
||||||
|
(true, 1400, 'Нет', true, 5, 5, 'ок', 'Подписано', 8935, 'Иниц', true, 'ООО "ЦИРОБЗ"', 20, 20, 44, 4,
|
||||||
|
now()),
|
||||||
|
(true, 2900, 'ИВТ', true, 5, 5, 'ок', 'Подписано', 7971, 'Заявка, Акт о внедрении', true, 'нет', 21, 21,
|
||||||
|
40, 4, now()),
|
||||||
|
(true, 2600, 'ИВТ, ПРИ', true, 3, 3, 'ок', 'Подписано', 7284, Null, true, 'нет', 22, 22, 48, 4, now()),
|
||||||
|
(true, 3100, 'ИВТ, ПРИ', true, 5, 5, 'Усилить работу', 'Подписано', 4966, 'Заявка, Акт о внедрении',
|
||||||
|
true, 'нет', 23, 23, 45, 4, now()),
|
||||||
|
(true, 3110, 'Нет', true, 5, 5, 'ок', 'Подписано', 7174, Null, true, 'нет', 24, 24, 40, 4, now()),
|
||||||
|
(true, 3800, 'Нет', true, 5, 5, 'ок', 'Подписано', 7233, Null, true, 'нет', 25, 25, 45, 4, now()),
|
||||||
|
(true, 3300, 'ИВТ', true, 5, 5, 'ок', 'Подписано', 7133, Null, true, 'нет', 26, 26, 43, 4, now()),
|
||||||
|
(true, 3130, 'ИВТ', true, 5, 5, 'ок', 'Подписано', 8083, 'Заявка, Акт о внедрении', true, 'нет', 27, 27,
|
||||||
|
49, 4, now()),
|
||||||
|
(true, 3400, 'Нет', true, 5, 4,
|
||||||
|
'Критически низкий уровень. Допущен под ответственность руководителя ВКР', 'Подписано', 7968, 'Иниц',
|
||||||
|
true, 'нет', 28, 28, 50, 4, now()),
|
||||||
|
(true, 3120, 'ИВТ или ПРИ', true, 5, 5, 'ок', 'Подписано', 7940, 'Исслед', true, 'ООО "ЦИРОБЗ"', 29, 29,
|
||||||
|
40, 4, now()),
|
||||||
|
(true, 2800, 'Нет (возможно)', true, 4, 4, 'Усилить работу', 'рек', 6775, 'Заявка, Акт о внедрении',
|
||||||
|
true, 'нет', 30, 30, 40, 4, now()),
|
||||||
|
(true, 2100, 'Нет (возможно)', true, 5, 5, 'ок', 'Подписано', 7637, 'Заявка, Акт о внедрении', true,
|
||||||
|
'нет', 31, 31, 40, 4, now()),
|
||||||
|
(true, 2700, 'ИВТ', true, 5, 5, 'ок', 'Подписано', 8544, 'Заявка, Акт о внедрении', true, 'нет', 32, 32,
|
||||||
|
45, 4, now()),
|
||||||
|
(true, 2130, 'ИВТ, ПРИ', true, 5, 5, 'ок', 'Подписано', 7166, 'Заявка, Акт о внедрении', true, 'нет', 33,
|
||||||
|
33, 51, 4, now()),
|
||||||
|
(true, 2110, 'ИВТ', true, 5, 5, 'ок', 'Подписано', 6075, 'Заявка, Акт о внедрении', true, 'нет', 34, 34,
|
||||||
|
52, 4, now()),
|
||||||
|
(true, 3100, 'ИВТ', true, 5, 5, 'ок', 'Подписано', 7057, 'Заявка, Акт о внедрении', true, 'нет', 35, 35,
|
||||||
|
50, 4, now()),
|
||||||
|
(true, 2120, 'В БГТУ на другой кафедре (38.04.01 Экономика или 27.04.05. Инноватика)', true, 5, 5, 'ок',
|
||||||
|
'Подписано', 7057, 'Заявка, Акт о внедрении', true, 'нет', 36, 36, 51, 4, now()),
|
||||||
|
(true, 2500, 'ИВТ', true, 5, 5, 'ок', 'Подписано', 6583, 'Заявка, Акт о внедрении', true, 'нет', 37, 37,
|
||||||
|
53, 4, now()),
|
||||||
|
(true, 1300, 'ИВТ, ПРИ', true, 5, 5, 'ок', 'Подписано', 8444, 'Заявка, Акт о внедрении', true, 'нет', 38,
|
||||||
|
38, 44, 4, now()),
|
||||||
|
(true, 3600, 'ИВТ', true, 5, 5, 'ок', 'Подписано', 7631, 'Заявка, Акт о внедрении', true, 'нет', 39, 39,
|
||||||
|
45, 4, now());
|
||||||
|
end
|
||||||
|
$$;
|
||||||
82
server/src/main/resources/db/test-data/user.sql
Normal file
82
server/src/main/resources/db/test-data/user.sql
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
INSERT INTO "user" (login, password, full_name, mail, number_phone, created_at)
|
||||||
|
VALUES ('akulenko_mikhail', '{noop}1', 'Акуленко Михаил Вячеславович', 'akulenko.mikhail@example.com',
|
||||||
|
'+79110000001', NOW()),
|
||||||
|
('borovikov_artem', '{noop}1', 'Боровиков Артём Викторович', 'borovikov.artem@example.com', '+79110000002',
|
||||||
|
NOW()),
|
||||||
|
('bykonya_alexey', '{noop}1', 'Быконя Алексей Николаевич', 'bykonya.alexey@example.com', '+79110000003',
|
||||||
|
NOW()),
|
||||||
|
('ermakov_alexander', '{noop}1', 'Ермаков Александр Сергеевич', 'ermakov.alexander@example.com',
|
||||||
|
'+79110000004', NOW()),
|
||||||
|
('zgursky_evgeny', '{noop}1', 'Згурский Евгений Олегович', 'zgursky.evgeny@example.com', '+79110000005',
|
||||||
|
NOW()),
|
||||||
|
('ibishov_tural', '{noop}1', 'Ибишов Турал Садай оглы', 'ibishov.tural@example.com', '+79110000006', NOW()),
|
||||||
|
('ignatenko_vladimir', '{noop}1', 'Игнатенко Владимир Алексеевич', 'ignatenko.vladimir@example.com',
|
||||||
|
'+79110000007', NOW()),
|
||||||
|
('lazukin_danila', '{noop}1', 'Лазукин Данила Дмитриевич', 'lazukin.danila@example.com', '+79110000008',
|
||||||
|
NOW()),
|
||||||
|
('mitiaev_danila', '{noop}1', 'Митяев Данила Алексеевич', 'mitiaev.danila@example.com', '+79110000009',
|
||||||
|
NOW()),
|
||||||
|
('neshkov_daniil', '{noop}1', 'Нешков Даниил Владимирович', 'neshkov.daniil@example.com', '+79110000010',
|
||||||
|
NOW()),
|
||||||
|
('petrov_pavel', '{noop}1', 'Петров Павел Сергеевич', 'petrov.pavel@example.com', '+79110000011', NOW()),
|
||||||
|
('sazonov_andrey', '{noop}1', 'Сазонов Андрей Андреевич', 'sazonov.andrey@example.com', '+79110000012',
|
||||||
|
NOW()),
|
||||||
|
('solokhin_maxim', '{noop}1', 'Солохин Максим Николаевич', 'solokhin.maxim@example.com', '+79110000013',
|
||||||
|
NOW()),
|
||||||
|
('sochinsky_artem', '{noop}1', 'Сочинский Артем Александрович', 'sochinsky.artem@example.com',
|
||||||
|
'+79110000014', NOW()),
|
||||||
|
('trisvyatsky_kirill', '{noop}1', 'Трисвятский Кирилл Андреевич', 'trisvyatsky.kirill@example.com',
|
||||||
|
'+79110000015', NOW()),
|
||||||
|
('turov_alexander', '{noop}1', 'Туров Александр Сергеевич', 'turov.alexander@example.com', '+79110000016',
|
||||||
|
NOW()),
|
||||||
|
('shevtsova_alexandra', '{noop}1', 'Шевцова Александра Валерьевна', 'shevtsova.alexandra@example.com',
|
||||||
|
'+79110000017', NOW()),
|
||||||
|
('kibalyuk_artem', '{noop}1', 'Кибалюк Артем Сергеевич', 'kibalyuk.artem@example.com', '+79110000018', NOW()),
|
||||||
|
('shulindin_artem', '{noop}1', 'Шулындин Артём Андреевич', 'shulindin.artem@example.com', '+79110000019',
|
||||||
|
NOW()),
|
||||||
|
('belyaev_egor', '{noop}1', 'Беляев Егор Андреевич', 'belyaev.egor@example.com', '+79110000020', NOW()),
|
||||||
|
('berezhnoy_igor', '{noop}1', 'Бережной Игорь Александрович', 'berezhnoy.igor@example.com', '+79110000021',
|
||||||
|
NOW()),
|
||||||
|
('bogun_pavel', '{noop}1', 'Богун Павел Сергеевич', 'bogun.pavel@example.com', '+79110000022', NOW()),
|
||||||
|
('vaseykin_nikita', '{noop}1', 'Васейкин Никита Павлович', 'vaseykin.nikita@example.com', '+79110000023',
|
||||||
|
NOW()),
|
||||||
|
('gomonov_nikita', '{noop}1', 'Гомонов Никита Алексеевич', 'gomonov.nikita@example.com', '+79110000024',
|
||||||
|
NOW()),
|
||||||
|
('druyan_oleg', '{noop}1', 'Друян Олег Викторович', 'druyan.oleg@example.com', '+79110000025', NOW()),
|
||||||
|
('ivanov_kirill', '{noop}1', 'Иванов Кирилл Эдуардович', 'ivanov.kirill@example.com', '+79110000026', NOW()),
|
||||||
|
('ivanova_veronika', '{noop}1', 'Иванова Вероника Евгеньевна', 'ivanova.veronika@example.com',
|
||||||
|
'+79110000027', NOW()),
|
||||||
|
('izotov_ivan', '{noop}1', 'Изотов Иван Алексеевич', 'izotov.ivan@example.com', '+79110000028', NOW()),
|
||||||
|
('isakov_zahar', '{noop}1', 'Исаков Захар Александрович', 'isakov.zahar@example.com', '+79110000029', NOW()),
|
||||||
|
('iskritsky_daniil', '{noop}1', 'Искрицкий Даниил Павлович', 'iskritsky.daniil@example.com', '+79110000030',
|
||||||
|
NOW()),
|
||||||
|
('linko_daria', '{noop}1', 'Линько Дарья Андреевна', 'linko.daria@example.com', '+79110000031', NOW()),
|
||||||
|
('logutov_kirill', '{noop}1', 'Логутов Кирилл Александрович', 'logutov.kirill@example.com', '+79110000032',
|
||||||
|
NOW()),
|
||||||
|
('nekrassov_sergey', '{noop}1', 'Некрасов Сергей Игоревич', 'nekrassov.sergey@example.com', '+79110000033',
|
||||||
|
NOW()),
|
||||||
|
('sinyagin_ilya', '{noop}1', 'Синягин Илья Александрович', 'sinyagin.ilya@example.com', '+79110000034',
|
||||||
|
NOW()),
|
||||||
|
('sopriko_daniil', '{noop}1', 'Соприко Даниил Сергеевич', 'sopriko.daniil@example.com', '+79110000035',
|
||||||
|
NOW()),
|
||||||
|
('turovsky_ivan', '{noop}1', 'Туровский Иван Алексеевич', 'turovsky.ivan@example.com', '+79110000036', NOW()),
|
||||||
|
('frantsev_sergey', '{noop}1', 'Францев Сергей Дмитриевич', 'frantsev.sergey@example.com', '+79110000037',
|
||||||
|
NOW()),
|
||||||
|
('chepurnoy_maxim', '{noop}1', 'Чепурной Максим Романович', 'chepurnoy.maxim@example.com', '+79110000038',
|
||||||
|
NOW()),
|
||||||
|
('schemelinin_dmitry', '{noop}1', 'Щемелинин Дмитрий Михайлович', 'schemelinin.dmitry@example.com',
|
||||||
|
'+79110000039', NOW()),
|
||||||
|
('bulatitsky_d_i_1', '{noop}1', 'Булатицкий Д. И.', 'bulatitsky.d.i.1@example.com', '+79110000040', NOW()),
|
||||||
|
('kopeliovich_d_i_1', '{noop}1', 'Копелиович Д. И.', 'kopeliovich.d.i.1@example.com', '+79110000041', NOW()),
|
||||||
|
('dergachev_k_v', '{noop}1', 'Дергачев К. В.', 'dergachev.k.v@example.com', '+79110000042', NOW()),
|
||||||
|
('trubakov_e_o', '{noop}1', 'Трубаков Е. О.', 'trubakov.e.o@example.com', '+79110000043', NOW()),
|
||||||
|
('radchenko_a_o', '{noop}1', 'Радченко А. О.', 'radchenko.a.o@example.com', '+79110000044', NOW()),
|
||||||
|
('zimin_s_n_1', '{noop}1', 'Зимин С. Н.', 'zimin.s.n.1@example.com', '+79110000045', NOW()),
|
||||||
|
('koptenok_e_v', '{noop}1', 'Коптенок Е. В.', 'koptenok.e.v@example.com', '+79110000046', NOW()),
|
||||||
|
('mikhaleva_o_a', '{noop}1', 'Михалева О. А.', 'mikhaleva.o.a@example.com', '+79110000047', NOW()),
|
||||||
|
('gulakov_k_v', '{noop}1', 'Гулаков К. В.', 'gulakov.k.v@example.com', '+79110000048', NOW()),
|
||||||
|
('titarev_d_v', '{noop}1', 'Титарёв Д. В.', 'titarev.d.v@example.com', '+79110000049', NOW()),
|
||||||
|
('izrailev_v_ya_1', '{noop}1', 'Израилев В. Я.', 'izrailev.v.ya.1@example.com', '+79110000050', NOW()),
|
||||||
|
('podvesovsky_a_g_1', '{noop}1', 'Подвесовский А. Г.', 'podvesovsky.a.g.1@example.com', '+79110000051', NOW()),
|
||||||
|
('trubakov_a_o', '{noop}1', 'Трубаков А. О.', 'trubakov.a.o@example.com', '+79110000059', NOW()),
|
||||||
|
('lageriev_d_g', '{noop}1', 'Лагерев Д. Г.', 'lageriev.d.g@example.com', '+79110000052', NOW());
|
||||||
58
server/src/main/resources/db/test-data/user_role.sql
Normal file
58
server/src/main/resources/db/test-data/user_role.sql
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
do
|
||||||
|
$$
|
||||||
|
declare
|
||||||
|
teacher_id bigint := 1;
|
||||||
|
student_id bigint := 2;
|
||||||
|
commission_member_id bigint := 3;
|
||||||
|
administrator_id bigint := 4;
|
||||||
|
secretary_id bigint := 5;
|
||||||
|
begin
|
||||||
|
INSERT INTO user_role (user_id, role_id)
|
||||||
|
VALUES (1, student_id),
|
||||||
|
(2, student_id),
|
||||||
|
(3, student_id),
|
||||||
|
(4, student_id),
|
||||||
|
(5, student_id),
|
||||||
|
(6, student_id),
|
||||||
|
(7, student_id),
|
||||||
|
(8, student_id),
|
||||||
|
(9, student_id),
|
||||||
|
(10, student_id),
|
||||||
|
(11, student_id),
|
||||||
|
(12, student_id),
|
||||||
|
(13, student_id),
|
||||||
|
(14, student_id),
|
||||||
|
(15, student_id),
|
||||||
|
(16, student_id),
|
||||||
|
(17, student_id),
|
||||||
|
(18, student_id),
|
||||||
|
(19, student_id),
|
||||||
|
(20, student_id),
|
||||||
|
(21, student_id),
|
||||||
|
(22, student_id),
|
||||||
|
(23, student_id),
|
||||||
|
(24, student_id),
|
||||||
|
(25, student_id),
|
||||||
|
(26, student_id),
|
||||||
|
(27, student_id),
|
||||||
|
(28, student_id),
|
||||||
|
(29, student_id),
|
||||||
|
(30, student_id),
|
||||||
|
(31, student_id),
|
||||||
|
(32, student_id),
|
||||||
|
(33, student_id),
|
||||||
|
(34, student_id),
|
||||||
|
(35, student_id),
|
||||||
|
(36, student_id),
|
||||||
|
(37, teacher_id),
|
||||||
|
(37, administrator_id),
|
||||||
|
(38, commission_member_id),
|
||||||
|
(39, teacher_id),
|
||||||
|
(40, teacher_id),
|
||||||
|
(41, teacher_id),
|
||||||
|
(42, teacher_id),
|
||||||
|
(43, teacher_id),
|
||||||
|
(44, secretary_id),
|
||||||
|
(45, secretary_id);
|
||||||
|
end
|
||||||
|
$$;
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,143 +0,0 @@
|
|||||||
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (2, 'Сергей', 'Иванов', 'Александрович', 'ivanov.s.a@yandex.ru', '+79991234567', false, '2025-06-23 03:30:29.770236', '2025-06-23 03:30:29.770243');
|
|
||||||
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (3, 'Анна', 'Петрова', 'Викторовна', 'petrova.anna@mail.ru', '+79992345678', false, '2025-06-23 03:30:51.070370', '2025-06-23 03:30:51.070383');
|
|
||||||
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (4, 'Михаил', 'Сидоров', 'Юрьевич', 'sidorov.mikhail@gmail.com', '+79993456789', false, '2025-06-23 03:34:04.812946', '2025-06-23 03:34:04.812950');
|
|
||||||
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (5, 'Екатерина', 'Козлова', 'Дмитриевна', 'kozlova.ekaterina@yandex.ru', '+79994567890', false, '2025-06-23 03:34:22.224929', '2025-06-23 03:34:22.224937');
|
|
||||||
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (6, 'Алексей', 'Смирнов', 'Игоревич', 'smirnov.alexey@mail.ru', '+79995678901', false, '2025-06-23 03:34:44.026899', '2025-06-23 03:34:44.026907');
|
|
||||||
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (7, 'Ольга', 'Васильева', 'Сергеевна', 'vasilieva.olga@gmail.com', '+79996789012', false, '2025-06-23 03:35:04.258782', '2025-06-23 03:35:04.258786');
|
|
||||||
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (8, 'Павел', 'Кузнецов', 'Андреевич', 'kuznetsov.pavel@yandex.ru', '+79997890123', false, '2025-06-23 03:35:23.594053', '2025-06-23 03:35:23.594057');
|
|
||||||
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (9, 'Светлана', 'Морозова', 'Николаевна', 'morozova.svetlana@mail.ru', '+79998901234', false, '2025-06-23 03:35:41.692339', '2025-06-23 03:35:41.692348');
|
|
||||||
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (10, 'Дмитрий', 'Попов', 'Евгеньевич', 'popov.dmitry@gmail.com', '+79999012345', false, '2025-06-23 03:35:57.449960', '2025-06-23 03:35:57.449967');
|
|
||||||
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (11, 'Мария', 'Лебедева', 'Алексеевна', 'lebedeva.maria@yandex.ru', '+79990123456', false, '2025-06-23 03:36:15.662888', '2025-06-23 03:36:15.662897');
|
|
||||||
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (12, 'Артём', 'Новиков', 'Вадимович', 'novikov.artem@mail.ru', '+79991235678', false, '2025-06-23 03:36:32.688934', '2025-06-23 03:36:32.688937');
|
|
||||||
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (13, 'Юлия', 'Фёдорова', 'Олеговна', 'fedorova.yulia@gmail.com', '+79992346789', false, '2025-06-23 03:36:56.836898', '2025-06-23 03:36:56.836906');
|
|
||||||
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (14, 'Игорь', 'Михайлов', 'Павлович', 'mikhaylov.igor@yandex.ru', '+79993457890', false, '2025-06-23 03:37:10.639420', '2025-06-23 03:37:10.639426');
|
|
||||||
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (15, 'Елена', 'Беляева', 'Викторовна', 'belyaeva.elena@mail.ru', '+79994568901', false, '2025-06-23 03:37:25.821122', '2025-06-23 03:37:25.821125');
|
|
||||||
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (16, 'Андрей', 'Григорьев', 'Сергеевич', 'grigoriev.andrey@gmail.com', '+79995679012', false, '2025-06-23 03:37:43.800145', '2025-06-23 03:37:43.800148');
|
|
||||||
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (17, 'Наталья', 'Орлова', 'Ивановна', 'orlova.natalia@yandex.ru', '+79996780123', false, '2025-06-23 03:37:59.523747', '2025-06-23 03:37:59.523750');
|
|
||||||
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (18, 'Виктор', 'Ковалёв', 'Дмитриевич', 'kovalev.viktor@mail.ru', '+79997891234', false, '2025-06-23 03:38:18.141073', '2025-06-23 03:38:18.141083');
|
|
||||||
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (19, 'Дарья', 'Соколова', 'Александровна', 'sokolova.darya@gmail.com', '+79998912345', false, '2025-06-23 03:38:33.493732', '2025-06-23 03:38:33.493738');
|
|
||||||
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (20, 'Евгений', 'Романов', 'Николаевич', 'romanov.evgeny@yandex.ru', '+79990124567', false, '2025-06-23 03:38:52.229061', '2025-06-23 03:38:52.229065');
|
|
||||||
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (21, 'Алина', 'Зайцева', 'Сергеевна', 'zaytseva.alina@mail.ru', '+79991236789', false, '2025-06-23 03:39:08.364108', '2025-06-23 03:39:08.364111');
|
|
||||||
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (24, 'Арсений', 'Баранов', 'Викторович', 'baranov.arseny@mail.ru', '+79994569012', false, '2025-06-23 03:40:11.579147', '2025-06-23 03:40:11.579149');
|
|
||||||
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (25, 'Ксения', 'Егорова', 'Павловна', 'egorova.ksenia@gmail.com', '+79995670123', false, '2025-06-23 03:40:55.806292', '2025-06-23 03:40:55.806297');
|
|
||||||
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (26, 'Никита', 'Лазарев', 'Андреевич', 'lazarev.nikita@yandex.ru', '+79996781234', false, '2025-06-23 03:41:27.952004', '2025-06-23 03:41:27.952007');
|
|
||||||
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (27, 'София', 'Тихонова', 'Дмитриевна', 'tikhonova.sofia@mail.ru', '+79997892345', false, '2025-06-23 03:41:56.458424', '2025-06-23 03:41:56.458431');
|
|
||||||
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (23, 'Валерия', 'Королёва', 'Игоревна', 'koroleva.valeria@yandex.ru', '+79993458901', false, '2025-06-23 03:42:42.283585', '2025-06-23 03:42:42.283594');
|
|
||||||
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (22, 'Максим', 'Волков', 'Олегович', 'volkov.maxim@gmail.com', '+79992347890', false, '2025-06-23 04:17:19.212758', '2025-06-23 04:17:19.212763');
|
|
||||||
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (29,'Георгий','Павлов','Максимович','pavlov.georgiy@mail.com','+79936652346',false,'2025-06-24 03:24:17.701799','2025-06-24 03:24:17.701811');
|
|
||||||
|
|
||||||
INSERT INTO public.teacher_data (id, participant_id, degree, created_at, updated_at) VALUES (1, 22, 'ктн., доц.', '2025-06-23 03:39:38.369701', '2025-06-23 03:39:38.369706');
|
|
||||||
INSERT INTO public.teacher_data (id, participant_id, degree, created_at, updated_at) VALUES (2, 23, 'ктн., доц.', '2025-06-23 03:39:55.268771', '2025-06-23 03:39:55.268774');
|
|
||||||
INSERT INTO public.teacher_data (id, participant_id, degree, created_at, updated_at) VALUES (3, 24, 'ктн., доц.', '2025-06-23 03:40:11.580333', '2025-06-23 03:40:11.580339');
|
|
||||||
|
|
||||||
INSERT INTO public.direction_of_preparation (id, name, code, responsible_id, created_at, updated_at) VALUES (1, 'Информатика и вычислительная техника', '09.03.01', 1, '2025-06-23 03:43:21.412709', '2025-06-23 03:43:21.412726');
|
|
||||||
|
|
||||||
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (1, 'Разработка системы рекомендаций фильмов с использованием машинного обучения', 1, 1, '2025-06-23 03:44:10.229018', '2025-06-23 03:44:10.229025');
|
|
||||||
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (2, 'Создание чат-бота для автоматизации клиентской поддержки', 1, 1, '2025-06-23 03:44:16.798881', '2025-06-23 03:44:16.798888');
|
|
||||||
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (3, 'Анализ производительности алгоритмов сортировки на больших данных', 1, 1, '2025-06-23 03:44:24.036407', '2025-06-23 03:44:24.036426');
|
|
||||||
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (4, 'Разработка мобильного приложения для управления личными финансами', 1, 1, '2025-06-23 03:44:30.806074', '2025-06-23 03:44:30.806082');
|
|
||||||
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (5, 'Исследование методов защиты данных в облачных хранилищах', 2, 1, '2025-06-23 03:44:40.138182', '2025-06-23 03:44:40.138194');
|
|
||||||
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (6, 'Создание системы мониторинга серверов с использованием Prometheus и Grafana', 2, 1, '2025-06-23 03:44:46.312549', '2025-06-23 03:44:46.312558');
|
|
||||||
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (7, 'Разработка веб-приложения для организации мероприятий с интерактивным интерфейсом', 2, 1, '2025-06-23 03:44:51.925603', '2025-06-23 03:44:51.925613');
|
|
||||||
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (8, 'Оптимизация алгоритмов компьютерного зрения для распознавания лиц', 2, 1, '2025-06-23 03:44:59.413613', '2025-06-23 03:44:59.413632');
|
|
||||||
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (9, 'Исследование применения блокчейн-технологий в логистике', 2, 1, '2025-06-23 03:45:05.727136', '2025-06-23 03:45:05.727146');
|
|
||||||
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (10, 'Разработка системы автоматического тестирования веб-приложений', 2, 1, '2025-06-23 03:45:12.096788', '2025-06-23 03:45:12.096792');
|
|
||||||
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (11, 'Создание платформы для онлайн-обучения с адаптивным тестированием', 2, 1, '2025-06-23 03:45:38.511004', '2025-06-23 03:45:38.511020');
|
|
||||||
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (12, 'Анализ уязвимостей веб-приложений и разработка защитных мер', 3, 1, '2025-06-23 03:45:44.511502', '2025-06-23 03:45:44.511509');
|
|
||||||
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (13, 'Разработка игры на Unity с использованием элементов дополненной реальности', 3, 1, '2025-06-23 03:45:51.828513', '2025-06-23 03:45:51.828524');
|
|
||||||
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (14, 'Исследование методов обработки естественного языка для анализа текстов', 3, 1, '2025-06-23 03:45:58.514002', '2025-06-23 03:45:58.514011');
|
|
||||||
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (15, 'Создание системы управления проектами с интеграцией Kanban-доски', 3, 1, '2025-06-23 03:46:05.569625', '2025-06-23 03:46:05.569632');
|
|
||||||
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (16, 'Создание системы управления проектами с интеграцией Kanban-доски', 3, 1, '2025-06-23 03:46:11.498443', '2025-06-23 03:46:11.498449');
|
|
||||||
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (17, 'Исследование кибератак на IoT-устройства и разработка защитного ПО', 1, 1, '2025-06-23 03:46:18.270926', '2025-06-23 03:46:18.270944');
|
|
||||||
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (18, 'Разработка прототипа социальной сети', 1, 1, '2025-06-23 03:46:18.270926', '2025-06-23 03:46:18.270944');
|
|
||||||
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (19, 'Разработка подсистемы интеграции с платежными системами', 1, 1, '2025-06-23 03:46:18.270926', '2025-06-23 03:46:18.270944');
|
|
||||||
|
|
||||||
INSERT INTO public.commission_member_data (id, partic_id, work_place, work_position, created_at, updated_at) VALUES (1, 25, 'ООО "ТехноСофт"', 'Программист Python', '2025-06-23 03:40:55.807387', '2025-06-23 03:40:55.807392');
|
|
||||||
INSERT INTO public.commission_member_data (id, partic_id, work_place, work_position, created_at, updated_at) VALUES (2, 26, 'АО "Инновации"', 'Системный администратор', '2025-06-23 03:41:27.952659', '2025-06-23 03:41:27.952663');
|
|
||||||
INSERT INTO public.commission_member_data (id, partic_id, work_place, work_position, created_at, updated_at) VALUES (3, 27, 'ООО "ДатаСистемс"', 'Аналитик данных', '2025-06-23 03:41:56.460124', '2025-06-23 03:41:56.460133');
|
|
||||||
INSERT INTO public.commission_member_data (id, partic_id, work_place, work_position, created_at, updated_at) VALUES (5, 23, 'БГТУ', 'доц.,ктн.,зав.кав.', '2025-06-23 03:42:42.288583', '2025-06-23 03:42:42.288590');
|
|
||||||
INSERT INTO public.commission_member_data (id, partic_id, work_place, work_position, created_at, updated_at) VALUES (4, 22, 'БГТУ', 'доц.,ктн.', '2025-06-23 03:42:37.300773', '2025-06-23 03:42:37.300777');
|
|
||||||
|
|
||||||
INSERT INTO public.defense (id, defense_date, status, direction_of_preparation_id, responsible_for_antiplagiarism_id, responsible_for_normcontrol_id, created_at, updated_at) VALUES (1, '2025-06-26', 'DEFENSE_PREPARATION', 1, 22, 22, '2025-06-23 04:09:15.118953', '2025-06-23 04:09:15.118975');
|
|
||||||
|
|
||||||
INSERT INTO public."group" (id, name, defense_id, direction_of_preparation_id, created_at, updated_at) VALUES (1, 'О-21-ИВТ-1-по-Б', 1, 1, '2025-06-23 03:50:49.095829', '2025-06-23 03:50:49.095835');
|
|
||||||
INSERT INTO public."group" (id, name, defense_id, direction_of_preparation_id, created_at, updated_at) VALUES (2, 'О-21-ИВТ-2-по-Б', 1, 1, '2025-06-23 03:50:49.096295', '2025-06-23 03:50:49.096299');
|
|
||||||
|
|
||||||
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (7, 8, null, 1, 7, 1, 5, 4, 4, true, 64, true, '',1, null, 1, 8, 24, 19, null, null, false, true, true, true, true, '2025-06-23 03:49:29.837457', '2025-06-23 03:49:29.837459');
|
|
||||||
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (2, 3, null, 1, 2, 1, 5, 5, 5, true, 85, true, '',2, null, 1, 10, 12, 28, null, null, false, true, false, false, true, '2025-06-23 03:49:29.836268', '2025-06-23 03:49:29.836271');
|
|
||||||
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (4, 5, null, 1, 4, 1, 4, 5, 5, true, 82, true, '',3, null, 1, 7, 18, 10, null, null, false, true, true, true, true, '2025-06-23 03:49:29.836800', '2025-06-23 03:49:29.836802');
|
|
||||||
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (10, 11, null, 2, 10, 1, 5, 4, 4, true, 67, true, '',4, null, 1, 4, 25, 19, null, null, false, false, false, false, true, '2025-06-23 03:49:29.837974', '2025-06-23 03:49:29.837976');
|
|
||||||
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (13, 14, null, 2, 3, 2, 5, 4, 4, true, 45, true, '',5, null, 2, 12, 20, 19, null, null, false, false, false, false, true, '2025-06-23 03:50:04.763207', '2025-06-23 03:50:04.763212');
|
|
||||||
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (6, 7, null, 1, 6, 1, 4, 4, 4, true, 65, true, '',6, null, 1, 4, 25, 21, null, null, false, false, false, false, true, '2025-06-23 03:49:29.837241', '2025-06-23 03:49:29.837243');
|
|
||||||
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (12, 13, null, 2, 2, 2, 5, 5, 5, true, 87, false, '',7, null, 2, 0, 21, 18, null, null, true, true, true, true, false, '2025-06-23 03:50:04.762603', '2025-06-23 03:50:04.762610');
|
|
||||||
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (20, 21, null, 3, 10, 2, 5, 5, 5, true, 65, true, '', 8, null, 2, 7, 9, 29, null, null, false, false, false, false, false, '2025-06-23 03:50:04.766515', '2025-06-23 03:50:04.766520');
|
|
||||||
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (17, 18, null, 3, 7, 2, 4, 4, 4, true, 66, true, '', 9, null, 2, 9, 23, 19, null, null, false, true, false, false, true, '2025-06-23 03:50:04.765268', '2025-06-23 03:50:04.765273');
|
|
||||||
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (14, 15, null, 2, 4, 2, 4, 5, 5, true, 87, true, '', 10, null, 2, 5, 19, 23, null, null, false, false, true, true, true, '2025-06-23 03:50:04.763769', '2025-06-23 03:50:04.763774');
|
|
||||||
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (16, 17, null, 3, 6, 2, 4, 5, 5, true, 76, true, '', 11, null, 2, 4, 1, 35, null, null, false, true, true, true, false, '2025-06-23 03:50:04.764825', '2025-06-23 03:50:04.764831');
|
|
||||||
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (5, 6, null, 1, 5, 1, 4, 5, 5, true, 76, true, '', 12, null, 1, 6, 23, 19, null, null, false, false, false, false, true, '2025-06-23 03:49:29.837008', '2025-06-23 03:49:29.837010');
|
|
||||||
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (1, 2, null, 1, 1, 1, 5, 5, 5, true, 81, true, '',13, null, 1, 10, 20, 20, null, null, false, true, false, false, true, '2025-06-23 03:49:29.835742', '2025-06-23 03:49:29.835746');
|
|
||||||
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (3, 4, null, 1, 3, 1, 5, 5, 5, true, 73, true, '', 14, null, 1, 8, 21, 10, null, null, false, false, true, true, false, '2025-06-23 03:49:29.836579', '2025-06-23 03:49:29.836581');
|
|
||||||
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (18, 19, null, 3, 8, 2, 5, 4, 4, true, 67, true, '', 15, null, 2, 12, 12, 21, null, null, false, false, true, true, true, '2025-06-23 03:50:04.765687', '2025-06-23 03:50:04.765692');
|
|
||||||
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (19, 20, null, 3, 9, 2, 3, 3, 3, true, 52, true, '', 16, null, 2, 5, 21, 12, null, null, false, true, true, true, true, '2025-06-23 03:50:04.766102', '2025-06-23 03:50:04.766107');
|
|
||||||
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (11, 12, null, 2, 1, 2, 5, 4, 4, true, 78, true, '', 17, null, 2, 21, 24, 17, null, null, false, false, false, false, true, '2025-06-23 03:50:04.761995', '2025-06-23 03:50:04.761999');
|
|
||||||
|
|
||||||
INSERT INTO public."user" (id, login, password, partic_id, created_at, updated_at) VALUES (2, 'Teacher001', '{bcrypt}$2a$10$.HTDUMHEv3cMjZfdJPyrtugku6guROyqo9bDz5V46705ix0E94Rmm', 22, '2025-06-23 04:17:19.213271', '2025-06-23 04:17:19.213274');
|
|
||||||
INSERT INTO public."user" (id, login, password, partic_id, created_at, updated_at) VALUES (4, 'Secretary001', '{bcrypt}$2a$10$H/uiV2i.KXBIfv/XtQTinO4Hx4UfkaXuc1BKHL2CX2xkLryOXPdru', 29, '2025-06-24 03:24:17.963794', '2025-06-24 03:24:17.963823');
|
|
||||||
|
|
||||||
INSERT INTO public.participant_role (partic_id, role_id) VALUES (2, 2);
|
|
||||||
INSERT INTO public.participant_role (partic_id, role_id) VALUES (22, 4);
|
|
||||||
INSERT INTO public.participant_role (partic_id, role_id) VALUES (3, 2);
|
|
||||||
INSERT INTO public.participant_role (partic_id, role_id) VALUES (4, 2);
|
|
||||||
INSERT INTO public.participant_role (partic_id, role_id) VALUES (5, 2);
|
|
||||||
INSERT INTO public.participant_role (partic_id, role_id) VALUES (6, 2);
|
|
||||||
INSERT INTO public.participant_role (partic_id, role_id) VALUES (7, 2);
|
|
||||||
INSERT INTO public.participant_role (partic_id, role_id) VALUES (8, 2);
|
|
||||||
INSERT INTO public.participant_role (partic_id, role_id) VALUES (9, 2);
|
|
||||||
INSERT INTO public.participant_role (partic_id, role_id) VALUES (10, 2);
|
|
||||||
INSERT INTO public.participant_role (partic_id, role_id) VALUES (11, 2);
|
|
||||||
INSERT INTO public.participant_role (partic_id, role_id) VALUES (12, 2);
|
|
||||||
INSERT INTO public.participant_role (partic_id, role_id) VALUES (13, 2);
|
|
||||||
INSERT INTO public.participant_role (partic_id, role_id) VALUES (14, 2);
|
|
||||||
INSERT INTO public.participant_role (partic_id, role_id) VALUES (15, 2);
|
|
||||||
INSERT INTO public.participant_role (partic_id, role_id) VALUES (16, 2);
|
|
||||||
INSERT INTO public.participant_role (partic_id, role_id) VALUES (17, 2);
|
|
||||||
INSERT INTO public.participant_role (partic_id, role_id) VALUES (18, 2);
|
|
||||||
INSERT INTO public.participant_role (partic_id, role_id) VALUES (19, 2);
|
|
||||||
INSERT INTO public.participant_role (partic_id, role_id) VALUES (20, 2);
|
|
||||||
INSERT INTO public.participant_role (partic_id, role_id) VALUES (21, 2);
|
|
||||||
INSERT INTO public.participant_role (partic_id, role_id) VALUES (24, 1);
|
|
||||||
INSERT INTO public.participant_role (partic_id, role_id) VALUES (25, 3);
|
|
||||||
INSERT INTO public.participant_role (partic_id, role_id) VALUES (26, 3);
|
|
||||||
INSERT INTO public.participant_role (partic_id, role_id) VALUES (27, 3);
|
|
||||||
INSERT INTO public.participant_role (partic_id, role_id) VALUES (23, 1);
|
|
||||||
INSERT INTO public.participant_role (partic_id, role_id) VALUES (23, 3);
|
|
||||||
INSERT INTO public.participant_role (partic_id, role_id) VALUES (22, 1);
|
|
||||||
INSERT INTO public.participant_role (partic_id, role_id) VALUES (22, 3);
|
|
||||||
INSERT INTO public.participant_role (partic_id, role_id) VALUES (22, 6);
|
|
||||||
INSERT INTO public.participant_role (partic_id, role_id) VALUES (29, 5);
|
|
||||||
|
|
||||||
INSERT INTO public.task (id, status, type, defense_id, maker_partic_id, checker_partic_id, task_type, diploma_topic_id, diploma_topic_name, practice_mark, antiplagiarism_percent, normcontrol_passed, approved_at, created_at, updated_at) VALUES (1, 'WAIT_FOR_TOPIC_PREPARATION', 'TOPIC_PREPARATION', 1, null, 22, 'Task', null, null, null, null, null, null, '2025-06-23 04:09:15.021775', '2025-06-23 04:09:15.021786');
|
|
||||||
INSERT INTO public.task (id, status, type, defense_id, maker_partic_id, checker_partic_id, task_type, diploma_topic_id, diploma_topic_name, practice_mark, antiplagiarism_percent, normcontrol_passed, approved_at, created_at, updated_at) VALUES (2, 'WAIT_FOR_TOPIC_PREPARATION', 'TOPIC_PREPARATION', 1, null, 23, 'Task', null, null, null, null, null, null, '2025-06-23 04:09:15.078322', '2025-06-23 04:09:15.078333');
|
|
||||||
INSERT INTO public.task (id, status, type, defense_id, maker_partic_id, checker_partic_id, task_type, diploma_topic_id, diploma_topic_name, practice_mark, antiplagiarism_percent, normcontrol_passed, approved_at, created_at, updated_at) VALUES (3, 'WAIT_FOR_TOPIC_PREPARATION', 'TOPIC_PREPARATION', 1, null, 24, 'Task', null, null, null, null, null, null, '2025-06-23 04:09:15.097449', '2025-06-23 04:09:15.097458');
|
|
||||||
|
|
||||||
INSERT INTO public.defense_commission (defense_id, commission_member_data_id) VALUES (1, 3);
|
|
||||||
INSERT INTO public.defense_commission (defense_id, commission_member_data_id) VALUES (1, 2);
|
|
||||||
INSERT INTO public.defense_commission (defense_id, commission_member_data_id) VALUES (1, 1);
|
|
||||||
INSERT INTO public.defense_commission (defense_id, commission_member_data_id) VALUES (1, 5);
|
|
||||||
INSERT INTO public.defense_commission (defense_id, commission_member_data_id) VALUES (1, 4);
|
|
||||||
|
|
||||||
SELECT setval('commission_member_data_id_seq', COALESCE((SELECT MAX(id) + 1 FROM commission_member_data), 1));
|
|
||||||
SELECT setval('defense_id_seq', COALESCE((SELECT MAX(id) + 1 FROM defense), 1));
|
|
||||||
SELECT setval('diploma_topic_id_seq', COALESCE((SELECT MAX(id) + 1 FROM diploma_topic), 1));
|
|
||||||
SELECT setval('direction_of_preparation_id_seq', COALESCE((SELECT MAX(id) + 1 FROM direction_of_preparation), 1));
|
|
||||||
SELECT setval('group_id_seq', COALESCE((SELECT MAX(id) + 1 FROM "group"), 1));
|
|
||||||
SELECT setval('message_template_id_seq', COALESCE((SELECT MAX(id) + 1 FROM message_template), 1));
|
|
||||||
SELECT setval('participant_id_seq', COALESCE((SELECT MAX(id) + 1 FROM participant), 1));
|
|
||||||
SELECT setval('questionnaire_id_seq', COALESCE((SELECT MAX(id) + 1 FROM questionnaire), 1));
|
|
||||||
SELECT setval('stud_comment_id_seq', COALESCE((SELECT MAX(id) + 1 FROM stud_comment), 1));
|
|
||||||
SELECT setval('student_data_comment_id_seq', COALESCE((SELECT MAX(id) + 1 FROM student_data_comment), 1));
|
|
||||||
SELECT setval('student_data_id_seq', COALESCE((SELECT MAX(id) + 1 FROM student_data), 1));
|
|
||||||
SELECT setval('study_form_id_seq', COALESCE((SELECT MAX(id) + 1 FROM study_form), 1));
|
|
||||||
SELECT setval('task_id_seq', COALESCE((SELECT MAX(id) + 1 FROM task), 1));
|
|
||||||
SELECT setval('teacher_data_id_seq', COALESCE((SELECT MAX(id) + 1 FROM teacher_data), 1));
|
|
||||||
SELECT setval('user_id_seq', COALESCE((SELECT MAX(id) + 1 FROM "user"), 1));
|
|
||||||
133
web/package-lock.json
generated
133
web/package-lock.json
generated
@ -21,7 +21,6 @@
|
|||||||
"mobx-react": "^9.1.1",
|
"mobx-react": "^9.1.1",
|
||||||
"mobx-state-router": "^6.0.1",
|
"mobx-state-router": "^6.0.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-beautiful-dnd": "^13.1.1",
|
|
||||||
"react-bootstrap": "^2.10.4",
|
"react-bootstrap": "^2.10.4",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"uuid": "^11.0.5"
|
"uuid": "^11.0.5"
|
||||||
@ -31,7 +30,6 @@
|
|||||||
"@babel/preset-env": "^7.25.8",
|
"@babel/preset-env": "^7.25.8",
|
||||||
"@babel/preset-react": "^7.25.7",
|
"@babel/preset-react": "^7.25.7",
|
||||||
"@types/react": "^18.2.0",
|
"@types/react": "^18.2.0",
|
||||||
"@types/react-beautiful-dnd": "^13.1.8",
|
|
||||||
"@types/react-dom": "^18.2.0",
|
"@types/react-dom": "^18.2.0",
|
||||||
"@types/webpack": "^5.28.5",
|
"@types/webpack": "^5.28.5",
|
||||||
"copy-webpack-plugin": "^13.0.0",
|
"copy-webpack-plugin": "^13.0.0",
|
||||||
@ -2084,16 +2082,6 @@
|
|||||||
"@types/send": "*"
|
"@types/send": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/hoist-non-react-statics": {
|
|
||||||
"version": "3.3.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.6.tgz",
|
|
||||||
"integrity": "sha512-lPByRJUer/iN/xa4qpyL0qmL11DqNW81iU/IG1S3uvRUq4oKagz8VCxZjiWkumgt66YT3vOdDgZ0o32sGKtCEw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/react": "*",
|
|
||||||
"hoist-non-react-statics": "^3.3.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@types/html-minifier-terser": {
|
"node_modules/@types/html-minifier-terser": {
|
||||||
"version": "6.1.0",
|
"version": "6.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
|
||||||
@ -2177,16 +2165,6 @@
|
|||||||
"csstype": "^3.0.2"
|
"csstype": "^3.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/react-beautiful-dnd": {
|
|
||||||
"version": "13.1.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.1.8.tgz",
|
|
||||||
"integrity": "sha512-E3TyFsro9pQuK4r8S/OL6G99eq7p8v29sX0PM7oT8Z+PJfZvSQTx4zTQbUJ+QZXioAF0e7TGBEcA1XhYhCweyQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/react": "*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@types/react-dom": {
|
"node_modules/@types/react-dom": {
|
||||||
"version": "18.3.1",
|
"version": "18.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz",
|
||||||
@ -2196,18 +2174,6 @@
|
|||||||
"@types/react": "*"
|
"@types/react": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/react-redux": {
|
|
||||||
"version": "7.1.34",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.34.tgz",
|
|
||||||
"integrity": "sha512-GdFaVjEbYv4Fthm2ZLvj1VSCedV7TqE5y1kNwnjSdBOTXuRSgowux6J8TAct15T3CKBr63UMk+2CO7ilRhyrAQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/hoist-non-react-statics": "^3.3.0",
|
|
||||||
"@types/react": "*",
|
|
||||||
"hoist-non-react-statics": "^3.3.0",
|
|
||||||
"redux": "^4.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@types/react-transition-group": {
|
"node_modules/@types/react-transition-group": {
|
||||||
"version": "4.4.11",
|
"version": "4.4.11",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.11.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.11.tgz",
|
||||||
@ -3290,15 +3256,6 @@
|
|||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/css-box-model": {
|
|
||||||
"version": "1.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz",
|
|
||||||
"integrity": "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"tiny-invariant": "^1.0.6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/css-loader": {
|
"node_modules/css-loader": {
|
||||||
"version": "7.1.2",
|
"version": "7.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.2.tgz",
|
||||||
@ -4173,15 +4130,6 @@
|
|||||||
"value-equal": "^1.0.1"
|
"value-equal": "^1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/hoist-non-react-statics": {
|
|
||||||
"version": "3.3.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
|
|
||||||
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
|
|
||||||
"license": "BSD-3-Clause",
|
|
||||||
"dependencies": {
|
|
||||||
"react-is": "^16.7.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/hpack.js": {
|
"node_modules/hpack.js": {
|
||||||
"version": "2.1.6",
|
"version": "2.1.6",
|
||||||
"resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
|
"resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
|
||||||
@ -4798,12 +4746,6 @@
|
|||||||
"url": "https://github.com/sponsors/streamich"
|
"url": "https://github.com/sponsors/streamich"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/memoize-one": {
|
|
||||||
"version": "5.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
|
|
||||||
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/merge-descriptors": {
|
"node_modules/merge-descriptors": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
|
||||||
@ -5470,12 +5412,6 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/raf-schd": {
|
|
||||||
"version": "4.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz",
|
|
||||||
"integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/randombytes": {
|
"node_modules/randombytes": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||||
@ -5529,26 +5465,6 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-beautiful-dnd": {
|
|
||||||
"version": "13.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.1.tgz",
|
|
||||||
"integrity": "sha512-0Lvs4tq2VcrEjEgDXHjT98r+63drkKEgqyxdA7qD3mvKwga6a5SscbdLPO2IExotU1jW8L0Ksdl0Cj2AF67nPQ==",
|
|
||||||
"deprecated": "react-beautiful-dnd is now deprecated. Context and options: https://github.com/atlassian/react-beautiful-dnd/issues/2672",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/runtime": "^7.9.2",
|
|
||||||
"css-box-model": "^1.2.0",
|
|
||||||
"memoize-one": "^5.1.1",
|
|
||||||
"raf-schd": "^4.0.2",
|
|
||||||
"react-redux": "^7.2.0",
|
|
||||||
"redux": "^4.0.4",
|
|
||||||
"use-memo-one": "^1.1.1"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"react": "^16.8.5 || ^17.0.0 || ^18.0.0",
|
|
||||||
"react-dom": "^16.8.5 || ^17.0.0 || ^18.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/react-bootstrap": {
|
"node_modules/react-bootstrap": {
|
||||||
"version": "2.10.5",
|
"version": "2.10.5",
|
||||||
"resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.10.5.tgz",
|
"resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.10.5.tgz",
|
||||||
@ -5600,37 +5516,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
||||||
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
||||||
},
|
},
|
||||||
"node_modules/react-redux": {
|
|
||||||
"version": "7.2.9",
|
|
||||||
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz",
|
|
||||||
"integrity": "sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/runtime": "^7.15.4",
|
|
||||||
"@types/react-redux": "^7.1.20",
|
|
||||||
"hoist-non-react-statics": "^3.3.2",
|
|
||||||
"loose-envify": "^1.4.0",
|
|
||||||
"prop-types": "^15.7.2",
|
|
||||||
"react-is": "^17.0.2"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"react": "^16.8.3 || ^17 || ^18"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"react-dom": {
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"react-native": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/react-redux/node_modules/react-is": {
|
|
||||||
"version": "17.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
|
||||||
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/react-transition-group": {
|
"node_modules/react-transition-group": {
|
||||||
"version": "4.4.5",
|
"version": "4.4.5",
|
||||||
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
|
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
|
||||||
@ -5684,15 +5569,6 @@
|
|||||||
"node": ">= 10.13.0"
|
"node": ">= 10.13.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/redux": {
|
|
||||||
"version": "4.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz",
|
|
||||||
"integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/runtime": "^7.9.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/regenerate": {
|
"node_modules/regenerate": {
|
||||||
"version": "1.4.2",
|
"version": "1.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
|
||||||
@ -6693,15 +6569,6 @@
|
|||||||
"punycode": "^2.1.0"
|
"punycode": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/use-memo-one": {
|
|
||||||
"version": "1.1.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.3.tgz",
|
|
||||||
"integrity": "sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peerDependencies": {
|
|
||||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/use-sync-external-store": {
|
"node_modules/use-sync-external-store": {
|
||||||
"version": "1.2.2",
|
"version": "1.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz",
|
||||||
|
|||||||
@ -20,7 +20,6 @@
|
|||||||
"mobx-react": "^9.1.1",
|
"mobx-react": "^9.1.1",
|
||||||
"mobx-state-router": "^6.0.1",
|
"mobx-state-router": "^6.0.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-beautiful-dnd": "^13.1.1",
|
|
||||||
"react-bootstrap": "^2.10.4",
|
"react-bootstrap": "^2.10.4",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"uuid": "^11.0.5"
|
"uuid": "^11.0.5"
|
||||||
@ -30,7 +29,6 @@
|
|||||||
"@babel/preset-env": "^7.25.8",
|
"@babel/preset-env": "^7.25.8",
|
||||||
"@babel/preset-react": "^7.25.7",
|
"@babel/preset-react": "^7.25.7",
|
||||||
"@types/react": "^18.2.0",
|
"@types/react": "^18.2.0",
|
||||||
"@types/react-beautiful-dnd": "^13.1.8",
|
|
||||||
"@types/react-dom": "^18.2.0",
|
"@types/react-dom": "^18.2.0",
|
||||||
"@types/webpack": "^5.28.5",
|
"@types/webpack": "^5.28.5",
|
||||||
"copy-webpack-plugin": "^13.0.0",
|
"copy-webpack-plugin": "^13.0.0",
|
||||||
|
|||||||
@ -12,21 +12,15 @@ import {ParticipantListPage} from "./components/participant/ParticipantListPage"
|
|||||||
import {DefenceListPage} from "./components/defence/DefenceListPage";
|
import {DefenceListPage} from "./components/defence/DefenceListPage";
|
||||||
import {PreparationDirectionListPage} from "./components/dictionary/PreparationDirectionList";
|
import {PreparationDirectionListPage} from "./components/dictionary/PreparationDirectionList";
|
||||||
import {DiplomaTopicListPage} from "./components/dictionary/DiplomaTopicList";
|
import {DiplomaTopicListPage} from "./components/dictionary/DiplomaTopicList";
|
||||||
import {DiplomaTopicAgreementPage} from "./components/tasks/DiplomaTopicAgreementPage";
|
|
||||||
import {DefenceEditPage} from "./components/defence/DefenceEditPage";
|
|
||||||
import {NotificationPage} from "./components/notification/NotificationPage";
|
|
||||||
|
|
||||||
const viewMap: ViewMap = {
|
const viewMap: ViewMap = {
|
||||||
home: <Home/>,
|
home: <Home/>,
|
||||||
error: <Error/>,
|
|
||||||
participantList: <ParticipantListPage/>,
|
participantList: <ParticipantListPage/>,
|
||||||
groupList: <GroupListPage/>,
|
groupList: <GroupListPage/>,
|
||||||
defenceList: <DefenceListPage/>,
|
defenceList: <DefenceListPage/>,
|
||||||
themeList: <DiplomaTopicListPage/>,
|
themeList: <DiplomaTopicListPage/>,
|
||||||
preparationDirectionList: <PreparationDirectionListPage/>,
|
preparationDirectionList: <PreparationDirectionListPage/>,
|
||||||
defenceTopicAgreement: <DiplomaTopicAgreementPage/>,
|
error: <Error/>,
|
||||||
defenseEdit: <DefenceEditPage/>,
|
|
||||||
notifications: <NotificationPage/>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const rootStore = initApp();
|
const rootStore = initApp();
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import {
|
|||||||
observer
|
observer
|
||||||
} from "mobx-react";
|
} from "mobx-react";
|
||||||
import {
|
import {
|
||||||
action, computed,
|
action,
|
||||||
makeObservable,
|
makeObservable,
|
||||||
observable,
|
observable,
|
||||||
runInAction
|
runInAction
|
||||||
@ -41,8 +41,6 @@ import {
|
|||||||
import {
|
import {
|
||||||
ModalState
|
ModalState
|
||||||
} from "../../utils/modalState";
|
} from "../../utils/modalState";
|
||||||
import _ from "lodash";
|
|
||||||
import {dateConverter, dateConverter2} from "../../utils/converters";
|
|
||||||
|
|
||||||
export interface ReactiveInputProps<T> {
|
export interface ReactiveInputProps<T> {
|
||||||
value: ReactiveValue<T>;
|
value: ReactiveValue<T>;
|
||||||
@ -281,27 +279,16 @@ export class DropdownSelectInput extends Component<MultipleSelectInputProps> {
|
|||||||
if (this.props.value.value === undefined) {
|
if (this.props.value.value === undefined) {
|
||||||
this.props.value.setAuto([]);
|
this.props.value.setAuto([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.initField(this.props);
|
this.initField(this.props);
|
||||||
|
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.options = props.possibleValues;
|
this.options = props.possibleValues;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate() {
|
componentDidUpdate(prevProps: Readonly<MultipleSelectInputProps>) {
|
||||||
if (this.value != this.props.value) {
|
if (this.value != prevProps.value) {
|
||||||
this.initField(this.props);
|
this.initField(this.props);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_.isEqual(this.options, this.props.possibleValues)) {
|
|
||||||
runInAction(() => {
|
|
||||||
this.options = this.props.possibleValues;
|
|
||||||
if (!this.props.disabled) {
|
|
||||||
this.value.setAuto([]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@action.bound
|
@action.bound
|
||||||
@ -354,8 +341,9 @@ export class DropdownSelectInput extends Component<MultipleSelectInputProps> {
|
|||||||
const inputDisabledBackgroundStyle = this.props.disabled ? {backgroundColor: 'rgb(233, 236, 239)'} : {};
|
const inputDisabledBackgroundStyle = this.props.disabled ? {backgroundColor: 'rgb(233, 236, 239)'} : {};
|
||||||
const inputDisabledColor = this.props.disabled ? '#000000' : 'rgb(33, 37, 41)';
|
const inputDisabledColor = this.props.disabled ? '#000000' : 'rgb(33, 37, 41)';
|
||||||
|
|
||||||
return (
|
return <div
|
||||||
<div className={'mb-1 l-no-bg'}>
|
className={'mb-1 l-no-bg'}>
|
||||||
|
{
|
||||||
<Dropdown as={ButtonGroup} className={'d-flex align-items-center border ' + inputClassName}
|
<Dropdown as={ButtonGroup} className={'d-flex align-items-center border ' + inputClassName}
|
||||||
drop={'end'} style={inputDisabledBackgroundStyle}>
|
drop={'end'} style={inputDisabledBackgroundStyle}>
|
||||||
<Button size={'lg'} className={`d-flex flex-wrap gap-1 align-items-baseline no-reaction`}
|
<Button size={'lg'} className={`d-flex flex-wrap gap-1 align-items-baseline no-reaction`}
|
||||||
@ -398,11 +386,11 @@ export class DropdownSelectInput extends Component<MultipleSelectInputProps> {
|
|||||||
}
|
}
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
|
}
|
||||||
<FormText
|
<FormText
|
||||||
children={this.props.value.firstError}
|
children={this.props.value.firstError}
|
||||||
className={'text-danger d-block mt-0 mb-0'}/>
|
className={'text-danger d-block mt-0 mb-0'}/>
|
||||||
</div>
|
</div>
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,58 +449,3 @@ export class TableInput<T> extends Component<TableInputProps<T>> {
|
|||||||
editable={!this.disabled} editableModalState={this.searchNewEntryModalState}/>
|
editable={!this.disabled} editableModalState={this.searchNewEntryModalState}/>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface InputDateProps extends ReactiveInputProps<Date> {
|
|
||||||
maxDate?: Date;
|
|
||||||
minDate: Date;
|
|
||||||
}
|
|
||||||
|
|
||||||
@observer
|
|
||||||
export class InputDate extends Component<InputDateProps> {
|
|
||||||
constructor(props: any) {
|
|
||||||
super(props);
|
|
||||||
makeObservable(this);
|
|
||||||
runInAction(() => {
|
|
||||||
this.myProps = props;
|
|
||||||
if (this.myProps.value.value === undefined) {
|
|
||||||
this.myProps.value.setAuto(new Date());
|
|
||||||
}
|
|
||||||
this.myProps.value.setField(this.myProps.label);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate() {
|
|
||||||
if (this.myProps.value.value !== this.props.value.value || this.myProps.disabled !== this.props.disabled) {
|
|
||||||
runInAction(() => {
|
|
||||||
this.myProps = this.props;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@observable myProps: InputDateProps;
|
|
||||||
|
|
||||||
@action.bound
|
|
||||||
onChange(event: React.ChangeEvent<HTMLInputElement>) {
|
|
||||||
this.myProps.value.set(new Date(event.target.value));
|
|
||||||
console.log('onChange', event.target.value);
|
|
||||||
console.log('onChange', this.myProps.value.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@computed
|
|
||||||
get dateConvert() {
|
|
||||||
if (!this.myProps.value.value) return '';
|
|
||||||
return this.myProps.value.value.toISOString().split('T')[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const inputClassName = `${this.myProps.validateless ? '' : this.myProps.value.invalid ? 'bg-danger' : this.myProps.value.touched ? 'bg-success' : ''} bg-opacity-10`;
|
|
||||||
|
|
||||||
return <div className={'mb-1 l-no-bg'}>
|
|
||||||
<FloatingLabel label={this.myProps.label} className={`${this.myProps.className} mt-0 mb-0`}>
|
|
||||||
<FormControl type='date' placeholder={this.myProps.label} disabled={this.myProps.disabled} onChange={this.onChange}
|
|
||||||
value={this.dateConvert} className={inputClassName}/>
|
|
||||||
</FloatingLabel>
|
|
||||||
<FormText children={this.myProps.value.firstError} className={`text-danger mt-0 mb-0 d-block`}/>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import {ComponentContext} from "../../utils/ComponentContext";
|
import {ComponentContext} from "../../utils/ComponentContext";
|
||||||
import {TableDescriptor} from "../../utils/tables";
|
import {TableDescriptor} from "../../utils/tables";
|
||||||
import {observer} from "mobx-react";
|
import {observer} from "mobx-react";
|
||||||
import {action, computed, makeObservable, observable, reaction, runInAction} from "mobx";
|
import {action, computed, makeObservable, observable, runInAction} from "mobx";
|
||||||
import {Button, ButtonGroup, FormSelect, FormText, Table} from "react-bootstrap";
|
import {Button, ButtonGroup, FormSelect, FormText, Table} from "react-bootstrap";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import React, {ChangeEvent} from "react";
|
import React, {ChangeEvent} from "react";
|
||||||
@ -24,15 +24,6 @@ export class DataTable<R> extends ComponentContext<DataTableProps<R> & { classNa
|
|||||||
constructor(props: DataTableProps<R>) {
|
constructor(props: DataTableProps<R>) {
|
||||||
super(props);
|
super(props);
|
||||||
makeObservable(this);
|
makeObservable(this);
|
||||||
|
|
||||||
reaction(() => this.descriptor.pageable, () => {
|
|
||||||
if (!this.descriptor.pageable) {
|
|
||||||
this.descriptor.pageSize = this.descriptor.data.length;
|
|
||||||
} else {
|
|
||||||
this.descriptor.page = 0;
|
|
||||||
this.descriptor.pageSize = _.toNumber(10);
|
|
||||||
}
|
|
||||||
}, {fireImmediately: true});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@observable descriptor = this.props.tableDescriptor;
|
@observable descriptor = this.props.tableDescriptor;
|
||||||
@ -44,6 +35,19 @@ export class DataTable<R> extends ComponentContext<DataTableProps<R> & { classNa
|
|||||||
@observable className = this.props.className;
|
@observable className = this.props.className;
|
||||||
@observable additionalButtons?: React.ReactNode = this.props.additionalButtons;
|
@observable additionalButtons?: React.ReactNode = this.props.additionalButtons;
|
||||||
|
|
||||||
|
componentDidUpdate() {
|
||||||
|
runInAction(() => {
|
||||||
|
this.descriptor = this.props.tableDescriptor;
|
||||||
|
this.name = this.props.name;
|
||||||
|
this.headless = this.props.headless;
|
||||||
|
this.filterModalState = this.props.filterModalState;
|
||||||
|
this.editable = this.props.editable;
|
||||||
|
this.editableModalState = this.props.editableModalState;
|
||||||
|
this.className = this.props.className;
|
||||||
|
this.additionalButtons = this.props.additionalButtons;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@computed
|
@computed
|
||||||
get isFirstPage() {
|
get isFirstPage() {
|
||||||
return this.descriptor.page === 0;
|
return this.descriptor.page === 0;
|
||||||
@ -86,7 +90,7 @@ export class DataTable<R> extends ComponentContext<DataTableProps<R> & { classNa
|
|||||||
this.descriptor.pageSize = _.toNumber(e.target.value);
|
this.descriptor.pageSize = _.toNumber(e.target.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed
|
// not computed, since we want to show initial data, when no sorts applied
|
||||||
get filteredData() {
|
get filteredData() {
|
||||||
const filters = this.descriptor.filters.filter(filter => filter);
|
const filters = this.descriptor.filters.filter(filter => filter);
|
||||||
return this.descriptor.data.filter(row => ((filters && filters.length) > 0 ? filters.every(filter => filter(row)) : true));
|
return this.descriptor.data.filter(row => ((filters && filters.length) > 0 ? filters.every(filter => filter(row)) : true));
|
||||||
@ -189,8 +193,9 @@ export class DataTable<R> extends ComponentContext<DataTableProps<R> & { classNa
|
|||||||
borderLeft: firstColumn ? 'none' : '1px solid var(--bs-table-border-color)',
|
borderLeft: firstColumn ? 'none' : '1px solid var(--bs-table-border-color)',
|
||||||
borderRight: lastColumn ? 'none' : '1px solid var(--bs-table-border-color)',
|
borderRight: lastColumn ? 'none' : '1px solid var(--bs-table-border-color)',
|
||||||
};
|
};
|
||||||
|
|
||||||
return <th key={column.renderKey} style={style} className={'_table-header'}>
|
return <th key={column.renderKey} style={style} className={'_table-header'}>
|
||||||
<div className={`d-flex align-items-center justify-content-center position-relative user-select-none`} style={{cursor: "pointer"}}
|
<div className={'d-flex align-items-center justify-content-center position-relative user-select-none'} style={{cursor: "pointer"}}
|
||||||
onClick={() => runInAction(() => {
|
onClick={() => runInAction(() => {
|
||||||
const other = this.descriptor.columns
|
const other = this.descriptor.columns
|
||||||
.filter(c => c.key !== column.key)
|
.filter(c => c.key !== column.key)
|
||||||
@ -253,10 +258,12 @@ export class DataTable<R> extends ComponentContext<DataTableProps<R> & { classNa
|
|||||||
borderRight: lastColumn ? 'none' : '1px solid var(--bs-table-border-color)',
|
borderRight: lastColumn ? 'none' : '1px solid var(--bs-table-border-color)',
|
||||||
borderBottom: lastRow && !this.editable ? 'none' : '1px solid var(--bs-table-border-color)',
|
borderBottom: lastRow && !this.editable ? 'none' : '1px solid var(--bs-table-border-color)',
|
||||||
}
|
}
|
||||||
return <td className={'text-center'} key={_.uniqueId(column.key)} style={style}>
|
return <td className={'text-center'} key={_.uniqueId(column.key)}
|
||||||
|
style={style}>
|
||||||
<span>{column.format(rowAny[column.key], row)}</span>
|
<span>{column.format(rowAny[column.key], row)}</span>
|
||||||
{
|
{
|
||||||
suffixElement && <span className={'ms-2'}>{suffixElement}</span>
|
suffixElement &&
|
||||||
|
<span className={'ms-2'}>{suffixElement}</span>
|
||||||
}
|
}
|
||||||
</td>
|
</td>
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,294 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
import {ModalState} from "../../utils/modalState";
|
|
||||||
import {observer} from "mobx-react";
|
|
||||||
import {action, makeObservable, observable, runInAction} from "mobx";
|
|
||||||
import {Button, Card, Col, Modal, ModalBody, ModalFooter, ModalHeader, ModalTitle, Row} from "react-bootstrap";
|
|
||||||
import {DragDropContext, Draggable, Droppable, DropResult} from 'react-beautiful-dnd';
|
|
||||||
import {Defense} from "../../models/defense";
|
|
||||||
import {fullName} from "../../models/participant";
|
|
||||||
import _ from "lodash";
|
|
||||||
import {get, post} from "../../utils/request";
|
|
||||||
import {StudentData} from "../../models/studentData";
|
|
||||||
import {NotificationService} from "../../services/NotificationService";
|
|
||||||
|
|
||||||
export interface DayAndOrderChangeModalProps {
|
|
||||||
modalState: ModalState;
|
|
||||||
defense: Defense;
|
|
||||||
}
|
|
||||||
|
|
||||||
const getAllStudByDefId = (id: number) => {
|
|
||||||
return get<StudentData[]>('student/by-defense-id', {id: id});
|
|
||||||
}
|
|
||||||
|
|
||||||
const getStudByStud = (students: StudentData[]): DGDStudent[] => {
|
|
||||||
return students.map(stud => { return {
|
|
||||||
day: stud.protDay,
|
|
||||||
id: _.toString(stud.id),
|
|
||||||
fullName: fullName(stud.participant),
|
|
||||||
curatorName: stud.curator ? fullName(stud.curator?.participant) : "Не назначен",
|
|
||||||
order: stud.protOrder,
|
|
||||||
topicName: stud.diplomaTopic ? stud.diplomaTopic.name : "Не выбрана",
|
|
||||||
} as DGDStudent});
|
|
||||||
}
|
|
||||||
|
|
||||||
const groupStudentsByDay = (students: DGDStudent[]): [DGDDay[], DGDStudent[]] => {
|
|
||||||
const daysMap: { [key: number]: DGDDay } = {};
|
|
||||||
const unassigned: DGDStudent[] = [];
|
|
||||||
students.forEach(student => {
|
|
||||||
if (student.day !== undefined && Number.isInteger(student.day)) {
|
|
||||||
const day = student.day;
|
|
||||||
if (!daysMap[day]) {
|
|
||||||
daysMap[day] = {
|
|
||||||
students: [student],
|
|
||||||
title: `День ${day}`,
|
|
||||||
id: day.toString(),
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
daysMap[day].students.push(student);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unassigned.push(student);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return [Object.values(daysMap), unassigned];
|
|
||||||
};
|
|
||||||
|
|
||||||
interface DGDStudent {
|
|
||||||
id: string;
|
|
||||||
fullName: string;
|
|
||||||
curatorName: string;
|
|
||||||
topicName: string;
|
|
||||||
day: number;
|
|
||||||
order: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface DGDDay {
|
|
||||||
id: string,
|
|
||||||
title: string,
|
|
||||||
students: DGDStudent[],
|
|
||||||
}
|
|
||||||
|
|
||||||
class Fields {
|
|
||||||
constructor(private props: DayAndOrderChangeModalProps) {
|
|
||||||
makeObservable(this);
|
|
||||||
getAllStudByDefId(props.defense.id).then((stud) => {
|
|
||||||
runInAction(() => {
|
|
||||||
this.modalState = props.modalState;
|
|
||||||
this.students = getStudByStud(stud);
|
|
||||||
let grouped = groupStudentsByDay(this.students);
|
|
||||||
this.days = grouped[0];
|
|
||||||
this.unassigned = grouped[1];
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@observable students: DGDStudent[] = [];
|
|
||||||
@observable unassigned: DGDStudent[] = [];
|
|
||||||
@observable days: DGDDay[] = [];
|
|
||||||
@observable modalState: ModalState;
|
|
||||||
|
|
||||||
@action.bound
|
|
||||||
onDragEnd(result: DropResult): void {
|
|
||||||
const { source, destination } = result;
|
|
||||||
if (!destination || (source.droppableId === destination.droppableId && source.index === destination.index)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
runInAction(() => {
|
|
||||||
const sourceId = source.droppableId;
|
|
||||||
const destId = destination.droppableId;
|
|
||||||
const getList = (id: string) => {
|
|
||||||
return id === 'unassigned'
|
|
||||||
? this.unassigned
|
|
||||||
: this.days.find(day => day.id === id)?.students || [];
|
|
||||||
};
|
|
||||||
const sourceList = getList(sourceId);
|
|
||||||
const destList = sourceId === destId ? sourceList : getList(destId);
|
|
||||||
const [movedItem] = sourceList.splice(source.index, 1);
|
|
||||||
destList.splice(destination.index, 0, movedItem);
|
|
||||||
movedItem.day = destId === 'unassigned' ? undefined : parseInt(destId);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@action.bound
|
|
||||||
addDay(): void {
|
|
||||||
runInAction(() => {
|
|
||||||
const maxId = this.days.length > 0 ? Math.max(...this.days.map(d => _.toNumber(d.id))) : 0;
|
|
||||||
const newDay: DGDDay = {
|
|
||||||
id: _.toString(maxId + 1),
|
|
||||||
title: `День ${this.days.length + 1}`,
|
|
||||||
students: [],
|
|
||||||
};
|
|
||||||
this.days = [...this.days, newDay];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@action.bound
|
|
||||||
removeDay(dayId: string): void {
|
|
||||||
runInAction(() => {
|
|
||||||
const day = this.days.find(d => d.id === dayId);
|
|
||||||
if (day) {
|
|
||||||
day.students.forEach(student => {
|
|
||||||
student.day = undefined;
|
|
||||||
student.order = undefined;
|
|
||||||
});
|
|
||||||
this.unassigned = [...this.unassigned, ...day.students];
|
|
||||||
this.days = this.days.filter(d => d.id !== dayId);
|
|
||||||
this.days.forEach((day: DGDDay, idx) => {
|
|
||||||
day.id = _.toString(idx + 1);
|
|
||||||
day.title = `День ${day.id}`;
|
|
||||||
})
|
|
||||||
this.students = [
|
|
||||||
...this.days.flatMap(d => d.students),
|
|
||||||
...this.unassigned,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@action.bound
|
|
||||||
save(): void {
|
|
||||||
let data = {
|
|
||||||
defenseId: this.props.defense.id,
|
|
||||||
days: this.days.map((d) => { return {
|
|
||||||
number: _.toNumber(d.id),
|
|
||||||
studs: d.students.map((student: DGDStudent, idx) => {
|
|
||||||
return {id: _.toNumber(student.id), order: idx}
|
|
||||||
}),
|
|
||||||
}}),
|
|
||||||
unassigned: this.unassigned.map((student: DGDStudent) => {
|
|
||||||
return {id: _.toNumber(student.id)}
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log(data);
|
|
||||||
post('defense/save-order', data).then(() => {
|
|
||||||
NotificationService.success("День и порядок защиты успешно обновлен");
|
|
||||||
setTimeout(() => {
|
|
||||||
window.location.reload();
|
|
||||||
}, 2000);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@observer
|
|
||||||
export class DayAndOrderChangeModal extends React.Component<DayAndOrderChangeModalProps> {
|
|
||||||
constructor(props: any) {
|
|
||||||
super(props);
|
|
||||||
makeObservable(this);
|
|
||||||
runInAction(() => {
|
|
||||||
this.fields = new Fields(props);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@observable fields: Fields;
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return <>
|
|
||||||
{ this.fields.modalState &&
|
|
||||||
<Modal show={this.fields.modalState.isOpen} size={'xl'}>
|
|
||||||
<ModalHeader><ModalTitle>Формирование дня и порядка защиты</ModalTitle></ModalHeader>
|
|
||||||
<ModalBody>
|
|
||||||
<DragDropContext onDragEnd={this.fields.onDragEnd}>
|
|
||||||
<Row>
|
|
||||||
{this.fields.days.map(day => (
|
|
||||||
<Col md={4} key={day.id} className="mb-3">
|
|
||||||
<Card>
|
|
||||||
<Card.Header className="d-flex justify-content-between align-items-center">
|
|
||||||
<span>{day.title}</span>
|
|
||||||
<Button variant="danger" size="sm" onClick={() => this.fields.removeDay(day.id)}>
|
|
||||||
Удалить
|
|
||||||
</Button>
|
|
||||||
</Card.Header>
|
|
||||||
<Droppable droppableId={day.id}>
|
|
||||||
{(provided) => (
|
|
||||||
<Card.Body
|
|
||||||
{...provided.droppableProps}
|
|
||||||
ref={provided.innerRef}
|
|
||||||
className="day-list"
|
|
||||||
>
|
|
||||||
{day.students.map((student, index) => (
|
|
||||||
<Draggable key={student.id} draggableId={student.id} index={index}>
|
|
||||||
{(providedInner) => (
|
|
||||||
<div
|
|
||||||
ref={providedInner.innerRef}
|
|
||||||
{...providedInner.draggableProps}
|
|
||||||
{...providedInner.dragHandleProps}
|
|
||||||
className="student-item mb-2"
|
|
||||||
>
|
|
||||||
<>
|
|
||||||
<div>{student.fullName} ({index + 1})</div>
|
|
||||||
{
|
|
||||||
!_.isEmpty(student.topicName) &&
|
|
||||||
<div>Тема ВКР: {student.topicName}</div>
|
|
||||||
}
|
|
||||||
{
|
|
||||||
!_.isEmpty(student.curatorName) &&
|
|
||||||
<div>Науч.Рук.: {student.curatorName}</div>
|
|
||||||
}
|
|
||||||
</>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</Draggable>
|
|
||||||
))}
|
|
||||||
{provided.placeholder}
|
|
||||||
</Card.Body>
|
|
||||||
)}
|
|
||||||
</Droppable>
|
|
||||||
</Card>
|
|
||||||
</Col>
|
|
||||||
))}
|
|
||||||
<Col md={4} className="mb-3">
|
|
||||||
<Card>
|
|
||||||
<Card.Header>Нераспределённые студенты</Card.Header>
|
|
||||||
<Droppable droppableId="unassigned">
|
|
||||||
{(provided) => (
|
|
||||||
<Card.Body
|
|
||||||
{...provided.droppableProps}
|
|
||||||
ref={provided.innerRef}
|
|
||||||
className="day-list"
|
|
||||||
>
|
|
||||||
{this.fields.unassigned.map((student, index) => (
|
|
||||||
<Draggable key={student.id} draggableId={student.id} index={index}>
|
|
||||||
{(providedInner) => (
|
|
||||||
<div
|
|
||||||
ref={providedInner.innerRef}
|
|
||||||
{...providedInner.draggableProps}
|
|
||||||
{...providedInner.dragHandleProps}
|
|
||||||
className="student-item mb-2"
|
|
||||||
>
|
|
||||||
<>
|
|
||||||
<div>{student.fullName}</div>
|
|
||||||
{
|
|
||||||
!_.isEmpty(student.topicName) &&
|
|
||||||
<div>Тема ВКР: {student.topicName}</div>
|
|
||||||
}
|
|
||||||
{
|
|
||||||
!_.isEmpty(student.curatorName) &&
|
|
||||||
<div>Науч.Рук.: {student.curatorName}</div>
|
|
||||||
}
|
|
||||||
</>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</Draggable>
|
|
||||||
))}
|
|
||||||
{provided.placeholder}
|
|
||||||
</Card.Body>
|
|
||||||
)}
|
|
||||||
</Droppable>
|
|
||||||
</Card>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</DragDropContext>
|
|
||||||
</ModalBody>
|
|
||||||
<ModalFooter>
|
|
||||||
<Button variant="outline-primary" onClick={this.fields.addDay}>Добавить день</Button>
|
|
||||||
<Button variant={'primary'} onClick={this.fields.save}>Сохранить</Button>
|
|
||||||
<Button variant={'outline-secondary'} onClick={() => this.fields.modalState.close()}>Закрыть</Button>
|
|
||||||
</ModalFooter>
|
|
||||||
</Modal>
|
|
||||||
}
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,498 +0,0 @@
|
|||||||
import {observer} from "mobx-react";
|
|
||||||
import {Page} from "../layout/Page";
|
|
||||||
import {action, makeObservable, observable, reaction, runInAction} from "mobx";
|
|
||||||
import React from "react";
|
|
||||||
import {RouterService} from "../../services/RouterService";
|
|
||||||
import {get, getFile, post} from "../../utils/request";
|
|
||||||
import {Defense, mapStatusName} from "../../models/defense";
|
|
||||||
import {Button, Col, Row, Tab, Tabs} from "react-bootstrap";
|
|
||||||
import {SelectInputValue} from "../controls/ReactiveControls";
|
|
||||||
import {ReactiveValue} from "../../utils/reactive/reactiveValue";
|
|
||||||
import {CommissionMember} from "../../models/commissionMember";
|
|
||||||
import {fullName, Participant} from "../../models/participant";
|
|
||||||
import _ from "lodash";
|
|
||||||
import {Group} from "../../models/group";
|
|
||||||
import {dateConverter} from "../../utils/converters";
|
|
||||||
import {NotificationService} from "../../services/NotificationService";
|
|
||||||
import {UserService} from "../../services/UserService";
|
|
||||||
import {Column, TableDescriptor} from "../../utils/tables";
|
|
||||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
|
||||||
import {StudentData} from "../../models/studentData";
|
|
||||||
import {ModalState} from "../../utils/modalState";
|
|
||||||
import {DataTable} from "../data-tables/DataTable";
|
|
||||||
import ParticipantProfileModal from "../participant/ParticipantProfileModal";
|
|
||||||
import {DayAndOrderChangeModal} from "./DayAndOrderChangeModal";
|
|
||||||
|
|
||||||
interface GroupItemData {
|
|
||||||
groupsId: number;
|
|
||||||
studId: number;
|
|
||||||
groupName: string;
|
|
||||||
number: number;
|
|
||||||
fio: string;
|
|
||||||
pdpMark: number;
|
|
||||||
topic: string;
|
|
||||||
teacherFio: string;
|
|
||||||
dayOfProt: number;
|
|
||||||
placeOfProt: number;
|
|
||||||
magistracy: boolean;
|
|
||||||
electronic: boolean;
|
|
||||||
otziv: number;
|
|
||||||
dpedefenseMark: number;
|
|
||||||
normcontrol: boolean;
|
|
||||||
antipl: number;
|
|
||||||
vnedreniye: boolean;
|
|
||||||
otlichiye: boolean;
|
|
||||||
zachetka: boolean;
|
|
||||||
work: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface DefenseTableData {
|
|
||||||
defenseId: number;
|
|
||||||
groups: GroupItemData[];
|
|
||||||
}
|
|
||||||
|
|
||||||
const getDefenseTable = (defenseId: number) => {
|
|
||||||
return get<DefenseTableData>('defense/defense-table', {defenseId: defenseId});
|
|
||||||
}
|
|
||||||
|
|
||||||
const getDefenseById = (defenseId: string) => {
|
|
||||||
return get<Defense>('defense/get-by-id', {id: defenseId});
|
|
||||||
}
|
|
||||||
|
|
||||||
const mapGek = (g: CommissionMember) => {
|
|
||||||
return {value: _.toString(g.id), label: fullName(g.participant)} as SelectInputValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const mapGroup = (g: Group) => {
|
|
||||||
return {value: _.toString(g.id), label: g.name} as SelectInputValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const getStudentById = (studentId: number) => {
|
|
||||||
return get<StudentData>('student/by-id', {id: studentId});
|
|
||||||
}
|
|
||||||
|
|
||||||
class Fields {
|
|
||||||
constructor() {
|
|
||||||
makeObservable(this);
|
|
||||||
|
|
||||||
reaction(() => {
|
|
||||||
return {td: this.defenseTableData, dtd: this.dayDefenseTableData}
|
|
||||||
}, () => {
|
|
||||||
if (!this.defenseTableData) return;
|
|
||||||
let descriptors: TableDescriptor<GroupItemData>[] = [];
|
|
||||||
this.defenseTableData.forEach((val) => {
|
|
||||||
descriptors.push(
|
|
||||||
new TableDescriptor<GroupItemData>([
|
|
||||||
new Column<GroupItemData, number>('number', '№', (v) => v ? v : '-'),
|
|
||||||
new Column<GroupItemData, string>('fio', 'ФИО студента', (v) => v ? v : '-', (gid: GroupItemData) => {
|
|
||||||
return <FontAwesomeIcon icon={'file-pen'} style={{'cursor': 'pointer'}}
|
|
||||||
data-value={gid.studId} onClick={this.onIconClicked}/>;
|
|
||||||
}),
|
|
||||||
new Column<GroupItemData, string>('topic', 'Тема', (v) => v ? v : '-'),
|
|
||||||
new Column<GroupItemData, string>('pdpMark', 'Преддипломная практика', (v) => v ? v : '-'),
|
|
||||||
new Column<GroupItemData, string>('teacherFio', 'Руководитель', (v) => v ? v : '-'),
|
|
||||||
new Column<GroupItemData, string>('dayOfProt', 'День защиты', (v) => v ? v : '-'),
|
|
||||||
new Column<GroupItemData, string>('placeOfProt', 'Порядок защиты', (v) => v ? v : '-'),
|
|
||||||
new Column<GroupItemData, boolean>('magistracy', 'Магистратура', (v) => v ? '+' : '-'),
|
|
||||||
new Column<GroupItemData, boolean>('electronic', 'Работа в эл. виде', (v) => v ? '+' : '-', undefined, undefined, "5"),
|
|
||||||
new Column<GroupItemData, number>('otziv', 'Отзыв', (v) => v ? v : '-'),
|
|
||||||
new Column<GroupItemData, number>('dpedefenseMark', 'Предзащита', (v) => v ? v : '-'),
|
|
||||||
new Column<GroupItemData, number>('normcontrol', 'Нормоконтроль', (v) => v ? '+' : '-'),
|
|
||||||
new Column<GroupItemData, number>('antipl', 'Антиплагиат', (v) => v ? `${v}%` : '-'),
|
|
||||||
new Column<GroupItemData, boolean>('vnedreniye', 'Примечания', (v, data) => {
|
|
||||||
let string = "";
|
|
||||||
if (data.vnedreniye) string += "Заявка и акт о внедрении";
|
|
||||||
if (data.otlichiye) {
|
|
||||||
if (string.length > 0) string += ",\n";
|
|
||||||
string += "Заявка на диплом с отличием";
|
|
||||||
}
|
|
||||||
return string;
|
|
||||||
}),
|
|
||||||
new Column<GroupItemData, string>('zachetka', 'Зачетка сдана', (v) => v ? '+' : '-'),
|
|
||||||
new Column<GroupItemData, number>('work', 'Работа', (v) => v ? v : '-'),
|
|
||||||
], val, false
|
|
||||||
)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
this.tableDescriptors = descriptors;
|
|
||||||
|
|
||||||
let dayDescriptors: TableDescriptor<GroupItemData>[] = [];
|
|
||||||
this.dayDefenseTableData.forEach((val) => {
|
|
||||||
dayDescriptors.push(
|
|
||||||
new TableDescriptor<GroupItemData>([
|
|
||||||
new Column<GroupItemData, number>('number', '№', (v) => v ? v : '-'),
|
|
||||||
new Column<GroupItemData, string>('fio', 'ФИО студента', (v) => v ? v : '-', (gid: GroupItemData) => {
|
|
||||||
return <FontAwesomeIcon icon={'file-pen'} style={{'cursor': 'pointer'}}
|
|
||||||
data-value={gid.studId} onClick={this.onIconClicked}/>;
|
|
||||||
}),
|
|
||||||
new Column<GroupItemData, string>('topic', 'Тема', (v) => v ? v : '-'),
|
|
||||||
new Column<GroupItemData, string>('pdpMark', 'Преддипломная практика', (v) => v ? v : '-'),
|
|
||||||
new Column<GroupItemData, string>('teacherFio', 'Руководитель', (v) => v ? v : '-'),
|
|
||||||
new Column<GroupItemData, string>('dayOfProt', 'День защиты', (v) => v ? v : '-'),
|
|
||||||
new Column<GroupItemData, string>('placeOfProt', 'Порядок защиты', (v) => v ? v : '-'),
|
|
||||||
new Column<GroupItemData, boolean>('magistracy', 'Магистратура', (v) => v ? '+' : '-'),
|
|
||||||
new Column<GroupItemData, boolean>('electronic', 'Работа в эл. виде', (v) => v ? '+' : '-', undefined, undefined, "5"),
|
|
||||||
new Column<GroupItemData, number>('otziv', 'Отзыв', (v) => v ? v : '-'),
|
|
||||||
new Column<GroupItemData, number>('dpedefenseMark', 'Предзащита', (v) => v ? v : '-'),
|
|
||||||
new Column<GroupItemData, number>('normcontrol', 'Нормоконтроль', (v) => v ? '+' : '-'),
|
|
||||||
new Column<GroupItemData, number>('antipl', 'Антиплагиат', (v) => v ? `${v}%` : '-'),
|
|
||||||
new Column<GroupItemData, boolean>('vnedreniye', 'Примечания', (v, data) => {
|
|
||||||
let string = "";
|
|
||||||
if (data.vnedreniye) string += "Заявка и акт о внедрении";
|
|
||||||
if (data.otlichiye) {
|
|
||||||
if (string.length > 0) string += ",\n";
|
|
||||||
string += "Заявка на диплом с отличием";
|
|
||||||
}
|
|
||||||
return string;
|
|
||||||
}),
|
|
||||||
new Column<GroupItemData, string>('zachetka', 'Зачетка сдана', (v) => v ? '+' : '-'),
|
|
||||||
new Column<GroupItemData, number>('work', 'Работа', (v) => v ? v : '-'),
|
|
||||||
], val, false
|
|
||||||
)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
this.dayTableDescriptors = dayDescriptors;
|
|
||||||
}, {fireImmediately: true});
|
|
||||||
|
|
||||||
reaction(() => {
|
|
||||||
return {user: UserService.user, def: this.defense}
|
|
||||||
}, () => {
|
|
||||||
this.canChangeDefense = UserService.isSecretary
|
|
||||||
|| UserService.isAdministrator
|
|
||||||
|| UserService.isDirOfPrepResponsible(this.defense?.preparationDirection);
|
|
||||||
}, {fireImmediately: true});
|
|
||||||
|
|
||||||
let routerOptions = RouterService.getOptions();
|
|
||||||
|
|
||||||
if (!routerOptions.defenseId) {
|
|
||||||
NotificationService.error('Не наедена защита');
|
|
||||||
} else {
|
|
||||||
getDefenseById(routerOptions.defenseId).then((defense: Defense) => {
|
|
||||||
runInAction(() => {
|
|
||||||
this.defense = defense;
|
|
||||||
if (defense.commissionMembers && !_.isEmpty(defense.commissionMembers)) {
|
|
||||||
this.allGek = defense.commissionMembers.map(mapGek);
|
|
||||||
this.selectedGek.setAuto(this.allGek);
|
|
||||||
}
|
|
||||||
if (defense.groups && !_.isEmpty(defense.groups)) {
|
|
||||||
this.allGroups = defense.groups.map(mapGroup);
|
|
||||||
this.selectedGroups.setAuto(this.allGroups);
|
|
||||||
}
|
|
||||||
this.defDate.setAuto(dateConverter(defense.defenseDate));
|
|
||||||
this.status.setAuto(mapStatusName(defense.status));
|
|
||||||
|
|
||||||
this.updateDefData();
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@observable defense: Defense;
|
|
||||||
|
|
||||||
@observable allGek: SelectInputValue[];
|
|
||||||
@observable selectedGek = new ReactiveValue<SelectInputValue[]>();
|
|
||||||
|
|
||||||
@observable allGroups: SelectInputValue[] = [];
|
|
||||||
@observable selectedGroups = new ReactiveValue<SelectInputValue[]>();
|
|
||||||
|
|
||||||
@observable defDate = new ReactiveValue<string>();
|
|
||||||
|
|
||||||
@observable status = new ReactiveValue<string>();
|
|
||||||
|
|
||||||
@observable canChangeDefense: boolean;
|
|
||||||
|
|
||||||
@observable defenseTableData: Map<string, GroupItemData[]>;
|
|
||||||
@observable tableDescriptors: TableDescriptor<GroupItemData>[] = [];
|
|
||||||
@observable dayDefenseTableData: Map<string, GroupItemData[]>;
|
|
||||||
@observable dayTableDescriptors: TableDescriptor<GroupItemData>[] = [];
|
|
||||||
|
|
||||||
@observable selectedPartic: Participant;
|
|
||||||
@observable participantModalState = new ModalState(false, this.updateDefData);
|
|
||||||
|
|
||||||
@observable changeDefDayModalState = new ModalState(false, this.updateDefData);
|
|
||||||
|
|
||||||
@action.bound
|
|
||||||
updateDefData() {
|
|
||||||
getDefenseTable(_.toNumber(this.defense.id)).then(dt => {
|
|
||||||
runInAction(() => {
|
|
||||||
let defTable = _.cloneDeep(dt);
|
|
||||||
const grouped = defTable.groups?.reduce((acc: Map<string, GroupItemData[]>, item: GroupItemData) => {
|
|
||||||
const group = acc.get(item.groupName) || [];
|
|
||||||
group.push(item);
|
|
||||||
acc.set(item.groupName, group);
|
|
||||||
return acc;
|
|
||||||
}, new Map<string, GroupItemData[]>());
|
|
||||||
let tableData = new Map(
|
|
||||||
Array.from(grouped.entries())
|
|
||||||
.sort((a, b) => a[0].localeCompare(b[0]))
|
|
||||||
.map(([key, items]) => [
|
|
||||||
key,
|
|
||||||
items.sort((a, b) => a.fio.localeCompare(b.fio)),
|
|
||||||
])
|
|
||||||
);
|
|
||||||
tableData.forEach((item: GroupItemData[]) => {
|
|
||||||
let number = 1;
|
|
||||||
item.forEach((item: GroupItemData) => {
|
|
||||||
item.number = number++;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
this.defenseTableData = tableData;
|
|
||||||
|
|
||||||
let dayDefTable = _.cloneDeep(dt);
|
|
||||||
const dayGrouped = dayDefTable.groups?.reduce((acc: Map<string, GroupItemData[]>, item: GroupItemData) => {
|
|
||||||
const defDay = acc.get(_.toString(item.dayOfProt)) || [];
|
|
||||||
defDay.push(item);
|
|
||||||
acc.set(_.toString(item.dayOfProt), defDay);
|
|
||||||
return acc;
|
|
||||||
}, new Map<string, GroupItemData[]>());
|
|
||||||
let dayTableData = new Map(
|
|
||||||
Array.from(dayGrouped.entries())
|
|
||||||
.sort((a, b) => _.toNumber(a[0]) - _.toNumber(b[0]))
|
|
||||||
.map(([key, items]) => [
|
|
||||||
key,
|
|
||||||
items.filter(v => v.dayOfProt && v.placeOfProt)
|
|
||||||
.sort((a, b) => a.placeOfProt - b.placeOfProt),
|
|
||||||
])
|
|
||||||
);
|
|
||||||
dayTableData.forEach((item: GroupItemData[]) => {
|
|
||||||
let number = 1;
|
|
||||||
item.forEach((item: GroupItemData) => {
|
|
||||||
item.number = number++;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
this.dayDefenseTableData = dayTableData;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@action.bound
|
|
||||||
openChangeDefDayModal() {
|
|
||||||
this.changeDefDayModalState.open();
|
|
||||||
}
|
|
||||||
|
|
||||||
@action.bound
|
|
||||||
requestToNextState() {
|
|
||||||
post(`defense/to-next-state`, {id: this.defense.id}).then(() => {
|
|
||||||
NotificationService.success("Защита успешно переведена на следующий этап");
|
|
||||||
setTimeout(() => {
|
|
||||||
window.location.reload();
|
|
||||||
}, 2000);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@action.bound
|
|
||||||
requestRecreateDefDay() {
|
|
||||||
post(`defense/recreate-protection-order`, {id: this.defense.id}).then(() => {
|
|
||||||
NotificationService.success("День и порядок защиты успешно сформированы");
|
|
||||||
setTimeout(() => {
|
|
||||||
window.location.reload();
|
|
||||||
}, 2000);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@action.bound
|
|
||||||
onIconClicked(event: React.MouseEvent<any>) {
|
|
||||||
let studId = _.toNumber(event.currentTarget.getAttribute('data-value'));
|
|
||||||
if (studId) {
|
|
||||||
getStudentById(studId).then(student => {
|
|
||||||
runInAction(() => {
|
|
||||||
this.selectedPartic = student.participant;
|
|
||||||
this.participantModalState.open();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@action.bound
|
|
||||||
downloadList() {
|
|
||||||
getFile('doc/stud-list', {id: this.defense.id}, "список_защищающихся.docx").then();
|
|
||||||
}
|
|
||||||
|
|
||||||
@action.bound
|
|
||||||
downloadBlank() {
|
|
||||||
getFile('doc/gek-questions', {id: this.defense.id}, "бланки_вопросов_для_ГЭК.docx").then();
|
|
||||||
}
|
|
||||||
|
|
||||||
@action.bound
|
|
||||||
downloadFragment() {
|
|
||||||
getFile('doc/topic-list', {id: this.defense.id}, "фрагмент_приказа_о_темах_вкр.docx").then();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@observer
|
|
||||||
export class DefenceEditPage extends Page {
|
|
||||||
constructor(props: any) {
|
|
||||||
super(props);
|
|
||||||
makeObservable(this);
|
|
||||||
runInAction(() => {
|
|
||||||
this.fields = new Fields();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@observable fields: Fields;
|
|
||||||
|
|
||||||
get page() {
|
|
||||||
return <>
|
|
||||||
<MainData fields={this.fields}/>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@observer
|
|
||||||
class MainData extends React.Component<{ fields: Fields }> {
|
|
||||||
constructor(props: any) {
|
|
||||||
super(props);
|
|
||||||
makeObservable(this);
|
|
||||||
runInAction(() => {
|
|
||||||
this.fields = props.fields;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
@observable fields: Fields;
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return <>
|
|
||||||
<h1 className={"text-center"}>Защита</h1>
|
|
||||||
<Tabs defaultActiveKey="default" id="def-tabs" className={'d-flex flex-row justify-content-end mb-4'}>
|
|
||||||
<Tab title={"Общие данные"} eventKey={"default"}>
|
|
||||||
<Row>
|
|
||||||
<Col>
|
|
||||||
<Groups fields={this.fields}/>
|
|
||||||
</Col>
|
|
||||||
<Col>
|
|
||||||
<Gek fields={this.fields}/>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
<DefDate fields={this.fields}/>
|
|
||||||
<DefStatus fields={this.fields}/>
|
|
||||||
{
|
|
||||||
this.fields.canChangeDefense &&
|
|
||||||
<div className={'d-flex flex-row justify-content-end'}>
|
|
||||||
<Button variant={'outline-primary'} onClick={this.fields.requestToNextState}>
|
|
||||||
Перевести на следующий этап
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</Tab>
|
|
||||||
<Tab title={"Сводная таблица"} eventKey={"table"}>
|
|
||||||
{
|
|
||||||
this.fields.selectedPartic &&
|
|
||||||
<ParticipantProfileModal modalState={this.fields.participantModalState} participant={this.fields.selectedPartic}/>
|
|
||||||
}
|
|
||||||
<Tabs defaultActiveKey={'tabl-main'} id={"def-tabl-tabs"} className={'d-flex flex-row justify-content-end mb-4'}>
|
|
||||||
<Tab title={"Общая"} eventKey={"tabl-main"}>
|
|
||||||
{
|
|
||||||
this.fields.tableDescriptors.map(td =>
|
|
||||||
td.data.length > 0
|
|
||||||
? <DataTable tableDescriptor={td} name={td.data[0].groupName} className={'mt-2'} key={_.toString(_.random(0, 10000000))} additionalButtons={<AdditionalButtonsTable key={_.toString(_.random(0, 10000000))} fields={this.fields}/>}/>
|
|
||||||
: <></>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</Tab>
|
|
||||||
{
|
|
||||||
this.fields.dayTableDescriptors && !_.isEmpty(this.fields.dayTableDescriptors) &&
|
|
||||||
Array.from(this.fields.dayDefenseTableData.entries()).map(([k, v], i) => {
|
|
||||||
return (
|
|
||||||
!_.isEmpty(v)
|
|
||||||
? <Tab title={`День ${k}`} key={`prot-day-${i}`} eventKey={`tabl-day-${i}`}>
|
|
||||||
<DataTable tableDescriptor={this.fields.dayTableDescriptors[i]} name={`День ${k}`} key={_.toString(_.random(0, 10000000))}/>
|
|
||||||
</Tab>
|
|
||||||
: null
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</Tabs>
|
|
||||||
{
|
|
||||||
this.fields.canChangeDefense &&
|
|
||||||
<div className={'d-flex flex-row justify-content-end mt-3'}>
|
|
||||||
<Button variant={'outline-primary me-3'} onClick={this.fields.openChangeDefDayModal}>
|
|
||||||
Редактировать дни и порядок защиты
|
|
||||||
</Button>
|
|
||||||
<Button variant={'outline-primary'} onClick={this.fields.requestRecreateDefDay}>
|
|
||||||
Автоматически сформировать дни и порядок защиты
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
{
|
|
||||||
this.fields.defense &&
|
|
||||||
<DayAndOrderChangeModal modalState={this.fields.changeDefDayModalState} defense={this.fields.defense}/>
|
|
||||||
}
|
|
||||||
</Tab>
|
|
||||||
{
|
|
||||||
this.fields.canChangeDefense &&
|
|
||||||
<Tab title={"Формирование документов"} eventKey={"doc_make"} className={'ps-5 pe-5'}>
|
|
||||||
<Button variant={'primary me-3'} onClick={this.fields.downloadList}>
|
|
||||||
Сформировать список защищающихся
|
|
||||||
</Button>
|
|
||||||
<Button variant={'primary me-3'} onClick={this.fields.downloadBlank}>
|
|
||||||
Сформировать бланк вопросов
|
|
||||||
</Button>
|
|
||||||
<Button variant={'primary'} onClick={this.fields.downloadFragment}>
|
|
||||||
Сформировать фрагмент приказа о темах ВКР
|
|
||||||
</Button>
|
|
||||||
</Tab>
|
|
||||||
}
|
|
||||||
</Tabs>
|
|
||||||
</>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const Groups = observer(({fields}: { fields: Fields }) => {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<div className={'h4 fw-bold'}>Защищающиеся группы:</div>
|
|
||||||
{
|
|
||||||
fields.selectedGroups.value &&
|
|
||||||
<div className={'h4'}>
|
|
||||||
{
|
|
||||||
fields.selectedGroups.value.map(g => <>{g.label}</>).reduce((prev, curr) => {
|
|
||||||
return <>{prev}<br/>{curr}</>
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const Gek = observer(({fields}: { fields: Fields }) => {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<div className={'h4 fw-bold'}>Члены ГЭК:</div>
|
|
||||||
{
|
|
||||||
fields.selectedGek.value &&
|
|
||||||
<div className={'h4'}>
|
|
||||||
{
|
|
||||||
fields.selectedGek.value.map(g => <>{g.label}</>).reduce((prev, curr) => {
|
|
||||||
return <>{prev}<br/>{curr}</>
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const DefDate = observer(({fields}: { fields: Fields }) => {
|
|
||||||
return (
|
|
||||||
<div className={'h4 mb-3'}>Дата начала защиты: {fields.defDate.value}</div>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const DefStatus = observer(({fields}: { fields: Fields }) => {
|
|
||||||
return (
|
|
||||||
<div className={'h4 mb-3'}>Этап защиты: <span className={'fw-bold'}>{fields.status.value}</span></div>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const AdditionalButtonsTable = observer(({fields}: { fields: Fields }) => {
|
|
||||||
return (
|
|
||||||
<div className={'d-flex'}>
|
|
||||||
<div>
|
|
||||||
<Button variant="outline-secondary" size="sm" className="me-2" onClick={fields.updateDefData}>
|
|
||||||
<FontAwesomeIcon icon={'rotate'} style={{'cursor': 'pointer'}}/>
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
@ -7,54 +7,39 @@ import React from "react";
|
|||||||
import {ThinkService} from "../../services/ThinkService";
|
import {ThinkService} from "../../services/ThinkService";
|
||||||
import {DataTable} from "../data-tables/DataTable";
|
import {DataTable} from "../data-tables/DataTable";
|
||||||
import {Column, TableDescriptor} from "../../utils/tables";
|
import {Column, TableDescriptor} from "../../utils/tables";
|
||||||
import {Defense} from "../../models/defense";
|
import {Defence} from "../../models/defence";
|
||||||
import {Participant} from "../../models/participant";
|
import {Participant} from "../../models/participant";
|
||||||
import {datetimeConverter} from "../../utils/converters";
|
import {datetimeConverter} from "../../utils/converters";
|
||||||
import {Button} from "react-bootstrap";
|
import {StudentData} from "../../models/studentData";
|
||||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
|
||||||
import {DefenseInfoModal} from "./DefenseInfoModal";
|
|
||||||
import {ModalState} from "../../utils/modalState";
|
|
||||||
import _ from "lodash";
|
|
||||||
|
|
||||||
class DefenceListPageState {
|
class DefenceListPageState {
|
||||||
constructor() {
|
constructor() {
|
||||||
makeObservable(this);
|
makeObservable(this);
|
||||||
this.updateDefences();
|
this.updateDefences();
|
||||||
reaction(() => this.defences, () => {
|
reaction(() => this.defences, () => {
|
||||||
this.tableDescriptor = new TableDescriptor<Defense>([
|
this.tableDescriptor = new TableDescriptor<Defence>([
|
||||||
new Column<Defense, number>('id', 'Идентификатор', (v) => v, (defense: Defense) => {
|
new Column<Defence, Participant[]>('commissionMembers', 'ГЭК', p => p ? p.length : 0),
|
||||||
return <FontAwesomeIcon icon={'file-pen'} style={{'cursor': 'pointer'}}
|
new Column<Defence, Group[]>('groups', 'Группы', g => g && g.length ? g.map(g => g.name).join(', ') : 'Пусто'),
|
||||||
data-value={defense.id} onClick={this.onIconClicked}/>;
|
new Column<Defence, Group[]>('groups', 'Студентов', g => {
|
||||||
}),
|
|
||||||
new Column<Defense, Participant[]>('commissionMembers', 'ГЭК', p => p ? p.length : 'Пусто'),
|
|
||||||
new Column<Defense, Group[]>('groups', 'Группы', g => g && g.length ? g.map(g => g.name).join(', ') : 'Пусто'),
|
|
||||||
new Column<Defense, Group[]>('groups', 'Студентов', g => {
|
|
||||||
if (!g) return 'Пусто';
|
if (!g) return 'Пусто';
|
||||||
let studLen = 0;
|
const students: StudentData[] = [];
|
||||||
g.forEach(group => {
|
g.forEach(group => group.students.forEach(student => students.push(student)));
|
||||||
studLen += group.students.length;
|
return students.length;
|
||||||
});
|
|
||||||
return studLen ? studLen : 'Пусто';
|
|
||||||
}),
|
}),
|
||||||
new Column<Defense, string>('createdAt', 'Дата создания', datetimeConverter),
|
new Column<Defence, string>('createdAt', 'Дата создания', datetimeConverter),
|
||||||
new Column<Defense, string>('updatedAt', 'Дата обновления', datetimeConverter),
|
new Column<Defence, string>('updatedAt', 'Дата обновления', datetimeConverter),
|
||||||
], this.defences, true
|
], this.defences, true
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@observable defences: Defense[] = [];
|
@observable defences: Defence[] = [];
|
||||||
@observable tableDescriptor: TableDescriptor<Defense>;
|
@observable tableDescriptor: TableDescriptor<Defence>;
|
||||||
|
|
||||||
@observable selectedDefense: Defense = undefined;
|
|
||||||
|
|
||||||
@observable editDefenseModalState = new ModalState();
|
|
||||||
@observable newDefenseModalState = new ModalState();
|
|
||||||
|
|
||||||
@action.bound
|
@action.bound
|
||||||
updateDefences() {
|
updateDefences() {
|
||||||
ThinkService.think();
|
ThinkService.think();
|
||||||
get<Defense[]>('/defense/get-all').then((defences) => {
|
get<Defence[]>('/defence/all').then((defences) => {
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.defences = defences;
|
this.defences = defences;
|
||||||
});
|
});
|
||||||
@ -62,15 +47,6 @@ class DefenceListPageState {
|
|||||||
ThinkService.completeAll();
|
ThinkService.completeAll();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@action.bound
|
|
||||||
onIconClicked(event: React.MouseEvent<any>) {
|
|
||||||
const d = this.defences.find(d => d.id === _.toNumber(event.currentTarget.getAttribute('data-value')));
|
|
||||||
if (d) {
|
|
||||||
this.selectedDefense = d;
|
|
||||||
this.editDefenseModalState.open();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
@ -86,27 +62,13 @@ export class DefenceListPage extends Page {
|
|||||||
get page() {
|
get page() {
|
||||||
return <>
|
return <>
|
||||||
{
|
{
|
||||||
this.fields.tableDescriptor &&
|
<>
|
||||||
<DataTable tableDescriptor={this.fields.tableDescriptor} name={'Защиты'}
|
|
||||||
additionalButtons={<AdditionalButtons state={this.fields}/>}/>
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
this.fields.selectedDefense &&
|
this.fields.tableDescriptor &&
|
||||||
<DefenseInfoModal modalState={this.fields.editDefenseModalState} defense={this.fields.selectedDefense} />
|
<DataTable tableDescriptor={this.fields.tableDescriptor} name={'Защиты'} />
|
||||||
|
}
|
||||||
|
</>
|
||||||
}
|
}
|
||||||
<DefenseInfoModal modalState={this.fields.newDefenseModalState} />
|
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const AdditionalButtons = observer(({state}: { state: DefenceListPageState }) => {
|
|
||||||
return (
|
|
||||||
<div className={'d-flex'}>
|
|
||||||
<div>
|
|
||||||
<Button variant="outline-secondary" size="sm" className="me-2" onClick={state.updateDefences}>
|
|
||||||
<FontAwesomeIcon icon={'rotate'} style={{'cursor': 'pointer'}}/>
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
@ -1,291 +0,0 @@
|
|||||||
import React, {Component} from "react";
|
|
||||||
import {ModalState} from "../../utils/modalState";
|
|
||||||
import {Defense, mapStatusName} from "../../models/defense";
|
|
||||||
import {observer} from "mobx-react";
|
|
||||||
import {action, computed, makeObservable, observable, reaction, runInAction} from "mobx";
|
|
||||||
import {Button, Modal} from "react-bootstrap";
|
|
||||||
import {DropdownSelectInput, InputDate, SelectInputValue, StringInput} from "../controls/ReactiveControls";
|
|
||||||
import {ReactiveValue} from "../../utils/reactive/reactiveValue";
|
|
||||||
import {required} from "../../utils/reactive/validators";
|
|
||||||
import _ from "lodash";
|
|
||||||
import {datetimeConverter} from "../../utils/converters";
|
|
||||||
import {Group} from "../../models/group";
|
|
||||||
import {fullName, Participant} from "../../models/participant";
|
|
||||||
import {UserService} from "../../services/UserService";
|
|
||||||
import {RouterService} from "../../services/RouterService";
|
|
||||||
import {CommissionMember} from "../../models/commissionMember";
|
|
||||||
import {get, post} from "../../utils/request";
|
|
||||||
import {NotificationService} from "../../services/NotificationService";
|
|
||||||
import {ThinkService} from "../../services/ThinkService";
|
|
||||||
import {PreparationDirection} from "../../models/preparationDirection";
|
|
||||||
|
|
||||||
const mapGroup = (g: Group) => {
|
|
||||||
return {value: _.toString(g.id), label: g.name} as SelectInputValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const mapGek = (g: CommissionMember) => {
|
|
||||||
return {value: _.toString(g.id), label: fullName(g.participant)} as SelectInputValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const getAllGroups = () => {
|
|
||||||
return get<Group[]>("group/get-all-groups");
|
|
||||||
}
|
|
||||||
|
|
||||||
const getAllGek = () => {
|
|
||||||
return get<CommissionMember[]>("commission-member/get-all");
|
|
||||||
}
|
|
||||||
|
|
||||||
const getAllNorm = () => {
|
|
||||||
return get<Participant[]>("participant/get-all-norm");
|
|
||||||
}
|
|
||||||
|
|
||||||
const getAllAntipl = () => {
|
|
||||||
return get<Participant[]>("participant/get-all-antipl");
|
|
||||||
}
|
|
||||||
|
|
||||||
const mapPartic = (p: Participant) => {
|
|
||||||
return {value: _.toString(p.id), label: fullName(p)} as SelectInputValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const getAllDirOrPrep = () => {
|
|
||||||
return get<PreparationDirection[]>('prep-direction/get-all');
|
|
||||||
}
|
|
||||||
|
|
||||||
const mapDirOfPrep = (dp: PreparationDirection) => {
|
|
||||||
return { value: _.toString(dp.id), label: dp.code } as SelectInputValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
class Fields {
|
|
||||||
constructor(state: ModalState, defense?: Defense) {
|
|
||||||
makeObservable(this);
|
|
||||||
runInAction(() => {
|
|
||||||
this.modalState = state;
|
|
||||||
|
|
||||||
getAllGroups().then(groups => {
|
|
||||||
runInAction(() => {
|
|
||||||
this.allGroups = groups;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
getAllGek().then(geks => {
|
|
||||||
runInAction(() => {
|
|
||||||
this.allGek = geks.map(mapGek);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
getAllNorm().then(norms => {
|
|
||||||
runInAction(() => {
|
|
||||||
this.allNorm = norms.map(mapPartic);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
getAllAntipl().then(norms => {
|
|
||||||
runInAction(() => {
|
|
||||||
this.allAntipl = norms.map(mapPartic);
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
getAllDirOrPrep().then(dp => {
|
|
||||||
runInAction(() => {
|
|
||||||
this.allDirOfPrep = dp.map(mapDirOfPrep);
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
reaction(() => this.dirOfPrep.value, () => {
|
|
||||||
if (this.dirOfPrep.value && this.dirOfPrep.value[0]) {
|
|
||||||
this.filteredGroups = this.allGroups
|
|
||||||
.filter(g => g.preparationDirection.id === _.toNumber(this.dirOfPrep.value[0].value))
|
|
||||||
.map(mapGroup);
|
|
||||||
} else {
|
|
||||||
this.filteredGroups = [];
|
|
||||||
}
|
|
||||||
}, {fireImmediately: true});
|
|
||||||
|
|
||||||
if (defense) {
|
|
||||||
this.editMode = false;
|
|
||||||
this.alreadyExists = true;
|
|
||||||
this.modalState = state;
|
|
||||||
this.defense = defense;
|
|
||||||
this.createdAt.setAuto(datetimeConverter(this.defense.createdAt));
|
|
||||||
this.updatedAt.setAuto(datetimeConverter(this.defense.updatedAt));
|
|
||||||
this.groups.setAuto(this.defense.groups?.map(mapGroup));
|
|
||||||
this.gek.setAuto(this.defense.commissionMembers?.map(mapGek));
|
|
||||||
if (defense.responsibleForNorm) this.selectedNorm.setAuto([mapPartic(this.defense.responsibleForNorm)]);
|
|
||||||
if (defense.responsibleForAntipl) this.selectedAntipl.setAuto([mapPartic(this.defense.responsibleForAntipl)]);
|
|
||||||
if (defense.preparationDirection) this.dirOfPrep.setAuto([mapDirOfPrep(this.defense.preparationDirection)]);
|
|
||||||
this.status.setAuto(mapStatusName(this.defense.status));
|
|
||||||
if (defense.defenseDate) this.startDate.setAuto(new Date(defense.defenseDate));
|
|
||||||
} else {
|
|
||||||
this.editMode = true;
|
|
||||||
this.status.setAuto(mapStatusName("NOT_STARTED"));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@observable editMode: boolean;
|
|
||||||
@observable alreadyExists = false;
|
|
||||||
|
|
||||||
@observable modalState: ModalState;
|
|
||||||
@observable defense: Defense;
|
|
||||||
|
|
||||||
@observable allGroups: Group[] = [];
|
|
||||||
@observable filteredGroups: SelectInputValue[] = [];
|
|
||||||
@observable groups = new ReactiveValue<SelectInputValue[]>().addValidator(required);
|
|
||||||
|
|
||||||
@observable allDirOfPrep: SelectInputValue[] = [];
|
|
||||||
@observable dirOfPrep = new ReactiveValue<SelectInputValue[]>().addValidator(required);
|
|
||||||
|
|
||||||
@observable allGek: SelectInputValue[] = [];
|
|
||||||
@observable gek = new ReactiveValue<SelectInputValue[]>().addValidator(required);
|
|
||||||
|
|
||||||
@observable allAntipl: SelectInputValue[] = [];
|
|
||||||
@observable selectedAntipl = new ReactiveValue<SelectInputValue[]>().addValidator(required);
|
|
||||||
|
|
||||||
@observable allNorm: SelectInputValue[] = [];
|
|
||||||
@observable selectedNorm = new ReactiveValue<SelectInputValue[]>().addValidator(required);
|
|
||||||
|
|
||||||
@observable status = new ReactiveValue<string>().addValidator(required).setAuto("");
|
|
||||||
|
|
||||||
@observable createdAt = new ReactiveValue<string>().setAuto("");
|
|
||||||
@observable updatedAt = new ReactiveValue<string>().setAuto("");
|
|
||||||
|
|
||||||
@observable startDate = new ReactiveValue<Date>().addValidator(required);
|
|
||||||
|
|
||||||
isAnyInvalid() {
|
|
||||||
let invalid = this.gek.invalid || this.groups.invalid || this.selectedAntipl.invalid || this.selectedNorm.invalid || this.dirOfPrep.invalid;
|
|
||||||
|
|
||||||
if (!this.alreadyExists) {
|
|
||||||
invalid = invalid || !this.gek.touched || !this.groups.touched || !this.selectedAntipl.touched || !this.selectedNorm.touched || !this.dirOfPrep.touched;
|
|
||||||
}
|
|
||||||
|
|
||||||
return invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
touchAll() {
|
|
||||||
this.gek.touch();
|
|
||||||
this.groups.touch();
|
|
||||||
this.selectedAntipl.touch();
|
|
||||||
this.selectedNorm.touch();
|
|
||||||
}
|
|
||||||
|
|
||||||
@action.bound
|
|
||||||
save() {
|
|
||||||
if (this.isAnyInvalid()) {
|
|
||||||
this.touchAll();
|
|
||||||
NotificationService.error("Исправьте ошибки на форме");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const data: Defense = {
|
|
||||||
id: this.defense ? this.defense.id : undefined,
|
|
||||||
groups: this.groups.value.map(g => {
|
|
||||||
return {id: _.toNumber(g.value)} as Group
|
|
||||||
}),
|
|
||||||
commissionMembers: this.gek.value.map(g => {
|
|
||||||
return {id: _.toNumber(g.value)} as CommissionMember
|
|
||||||
}),
|
|
||||||
responsibleForAntipl: this.selectedAntipl.value && this.selectedAntipl.value[0] ? { id: _.toNumber(this.selectedAntipl.value[0].value) } : undefined,
|
|
||||||
responsibleForNorm: this.selectedNorm.value && this.selectedNorm.value[0] ? { id: _.toNumber(this.selectedNorm.value[0].value) } : undefined,
|
|
||||||
preparationDirection: this.dirOfPrep.value && this.dirOfPrep.value[0] ? { id: _.toNumber(this.dirOfPrep.value[0].value) } : undefined,
|
|
||||||
defenseDate: this.startDate.value ? this.startDate.value.toISOString() : undefined,
|
|
||||||
};
|
|
||||||
|
|
||||||
ThinkService.think();
|
|
||||||
post("defense/save", data).then(() => {
|
|
||||||
if (this.defense)
|
|
||||||
NotificationService.success("Защита успешно сохранена");
|
|
||||||
else
|
|
||||||
NotificationService.success("Защита успешно изменена");
|
|
||||||
}).finally(() => {
|
|
||||||
ThinkService.completeAll();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.editMode = false;
|
|
||||||
this.modalState.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@observer
|
|
||||||
export class DefenseInfoModal extends Component<{ modalState: ModalState, defense?: Defense }> {
|
|
||||||
constructor(props: any) {
|
|
||||||
super(props);
|
|
||||||
makeObservable(this);
|
|
||||||
runInAction(() => {
|
|
||||||
this.fields = new Fields(this.props.modalState, this.props.defense);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate() {
|
|
||||||
if (this.fields.defense != this.props.defense) {
|
|
||||||
runInAction(() => {
|
|
||||||
this.fields = new Fields(this.props.modalState, this.props.defense);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@observable fields: Fields;
|
|
||||||
|
|
||||||
render() {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Modal show={this.fields.modalState.isOpen} centered size={"lg"}>
|
|
||||||
<Modal.Header>
|
|
||||||
<Modal.Title>
|
|
||||||
{this.fields.editMode
|
|
||||||
? "Редактирование защиты"
|
|
||||||
: "Защита"}
|
|
||||||
</Modal.Title>
|
|
||||||
</Modal.Header>
|
|
||||||
<Modal.Body>
|
|
||||||
<DropdownSelectInput possibleValues={this.fields.allDirOfPrep} label={"Направление подготовки"} filtering singleSelect
|
|
||||||
value={this.fields.dirOfPrep} disabled={!this.fields.editMode}/>
|
|
||||||
<DropdownSelectInput possibleValues={this.fields.filteredGroups} label={"Группы"} filtering
|
|
||||||
value={this.fields.groups} disabled={!this.fields.editMode}/>
|
|
||||||
<DropdownSelectInput possibleValues={this.fields.allGek} label={"Государственная экзаменационная комиссия"} filtering
|
|
||||||
value={this.fields.gek} disabled={!this.fields.editMode}/>
|
|
||||||
<DropdownSelectInput possibleValues={this.fields.allAntipl} label={"Ответственный за антиплагиат"} filtering singleSelect
|
|
||||||
value={this.fields.selectedAntipl} disabled={!this.fields.editMode}/>
|
|
||||||
<DropdownSelectInput possibleValues={this.fields.allNorm} label={"Ответственный за нормоконтроль"} filtering singleSelect
|
|
||||||
value={this.fields.selectedNorm} disabled={!this.fields.editMode}/>
|
|
||||||
<StringInput value={this.fields.status} label={"Этап защиты"} disabled/>
|
|
||||||
<InputDate label={"Дата начала защиты"} maxDate={(() => {
|
|
||||||
let date = new Date();
|
|
||||||
date.setFullYear(date.getFullYear() + 2);
|
|
||||||
return date;
|
|
||||||
})()} minDate={new Date()} value={this.fields.startDate} disabled={!this.fields.editMode}/>
|
|
||||||
<StringInput value={this.fields.createdAt} label={"Дата создания"} disabled/>
|
|
||||||
<StringInput value={this.fields.updatedAt} label={"Дата обновления"} disabled/>
|
|
||||||
</Modal.Body>
|
|
||||||
<Modal.Footer>
|
|
||||||
{
|
|
||||||
!this.fields.editMode &&
|
|
||||||
<Button onClick={() => {
|
|
||||||
RouterService.redirect("defenseEdit", {defenseId: _.toString(this.fields.defense.id)});
|
|
||||||
}} variant={'primary'}>Подробнее</Button>
|
|
||||||
}
|
|
||||||
{
|
|
||||||
(UserService.isAdministrator || UserService.isSecretary || UserService.isDirOfPrepResponsible(this.fields.defense?.preparationDirection)) && !this.fields.editMode &&
|
|
||||||
<Button onClick={() => {
|
|
||||||
runInAction(() => {
|
|
||||||
this.fields.editMode = true;
|
|
||||||
});
|
|
||||||
}} variant={'outline-secondary'}>Редактировать</Button>
|
|
||||||
}
|
|
||||||
{
|
|
||||||
(UserService.isAdministrator || UserService.isSecretary || UserService.isDirOfPrepResponsible(this.fields.defense?.preparationDirection)) && this.fields.editMode &&
|
|
||||||
<Button onClick={this.fields.save} variant={'primary'}>Сохранить</Button>
|
|
||||||
}
|
|
||||||
<Button onClick={() => {
|
|
||||||
runInAction(() => {
|
|
||||||
this.fields.modalState.close();
|
|
||||||
if (this.fields.defense)
|
|
||||||
this.fields.editMode = false;
|
|
||||||
})
|
|
||||||
}} variant={'outline-secondary'}>Закрыть</Button>
|
|
||||||
</Modal.Footer>
|
|
||||||
</Modal>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,85 +0,0 @@
|
|||||||
import {ModalState} from "../../utils/modalState";
|
|
||||||
import {Group} from "../../models/group";
|
|
||||||
import {observer} from "mobx-react";
|
|
||||||
import React, {Component} from "react";
|
|
||||||
import {action, makeObservable, observable, runInAction} from "mobx";
|
|
||||||
import {ReactiveValue} from "../../utils/reactive/reactiveValue";
|
|
||||||
import {Button, Modal, ModalBody, ModalFooter, ModalHeader, ModalTitle} from "react-bootstrap";
|
|
||||||
import {StringInput} from "../controls/ReactiveControls";
|
|
||||||
import {DiplomaTopic} from "../../models/diplomaTopic";
|
|
||||||
import {fullName} from "../../models/participant";
|
|
||||||
|
|
||||||
export interface DiplomaTopicFilterProps {
|
|
||||||
modalState: ModalState;
|
|
||||||
filters: ((group: DiplomaTopic) => boolean)[];
|
|
||||||
}
|
|
||||||
|
|
||||||
@observer
|
|
||||||
export class DiplomaTopicFilterModal extends Component<DiplomaTopicFilterProps> {
|
|
||||||
constructor(props: DiplomaTopicFilterProps) {
|
|
||||||
super(props);
|
|
||||||
makeObservable(this);
|
|
||||||
|
|
||||||
runInAction(() => {
|
|
||||||
this.filters.push(this.nameFilter);
|
|
||||||
this.filters.push(this.pdCodeFilter);
|
|
||||||
this.filters.push(this.pdNameFilter);
|
|
||||||
this.filters.push(this.teacherNameFilter);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@observable filters = this.props.filters;
|
|
||||||
@observable modalState = this.props.modalState;
|
|
||||||
|
|
||||||
@observable nameField = new ReactiveValue<string>().syncWithParam('name');
|
|
||||||
@observable prepDirNameField = new ReactiveValue<string>().syncWithParam('pdn');
|
|
||||||
@observable prepDirCodeField = new ReactiveValue<string>().syncWithParam('pdc');
|
|
||||||
@observable teacherNameField = new ReactiveValue<string>().syncWithParam('tn');
|
|
||||||
|
|
||||||
@observable nameFilter = (topic: DiplomaTopic) => {
|
|
||||||
if (!this.nameField.value) return true;
|
|
||||||
return topic.name?.includes(this.nameField.value)
|
|
||||||
};
|
|
||||||
|
|
||||||
@observable pdNameFilter = (topic: DiplomaTopic) => {
|
|
||||||
if (!this.prepDirNameField.value) return true;
|
|
||||||
return topic.preparationDirection.name?.includes(this.prepDirNameField.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
@observable pdCodeFilter = (topic: DiplomaTopic) => {
|
|
||||||
if (!this.prepDirCodeField.value) return true;
|
|
||||||
return topic.preparationDirection.code?.includes(this.prepDirCodeField.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
@observable teacherNameFilter = (topic: DiplomaTopic) => {
|
|
||||||
if (!this.teacherNameField.value) return true;
|
|
||||||
if (!topic.teacher || !topic.teacher.participant) return false;
|
|
||||||
return fullName(topic.teacher.participant).includes(this.teacherNameField.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@action.bound
|
|
||||||
reset() {
|
|
||||||
this.nameField.set("");
|
|
||||||
this.prepDirNameField.set("");
|
|
||||||
this.prepDirCodeField.set("");
|
|
||||||
this.teacherNameField.set("");
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return <Modal show={this.modalState.isOpen} centered>
|
|
||||||
<ModalHeader>
|
|
||||||
<ModalTitle>Фильтр</ModalTitle>
|
|
||||||
</ModalHeader>
|
|
||||||
<ModalBody>
|
|
||||||
<StringInput value={this.nameField} label={'Название'} validateless/>
|
|
||||||
<StringInput value={this.prepDirCodeField} label={'Код направления подготовки'} validateless/>
|
|
||||||
<StringInput value={this.prepDirNameField} label={'Название направления подготовки'} validateless/>
|
|
||||||
<StringInput value={this.teacherNameField} label={'ФИО Преподавателя'} validateless/>
|
|
||||||
</ModalBody>
|
|
||||||
<ModalFooter>
|
|
||||||
<Button onClick={this.reset} variant={'secondary'}>Сбросить</Button>
|
|
||||||
<Button onClick={this.modalState.close} variant={'outline-secondary'}>Закрыть</Button>
|
|
||||||
</ModalFooter>
|
|
||||||
</Modal>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user