Compare commits
No commits in common. "feature/groups" and "master" have entirely different histories.
feature/gr
...
master
@ -52,6 +52,11 @@
|
||||
<artifactId>postgresql</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.deepoove</groupId>
|
||||
<artifactId>poi-tl</artifactId>
|
||||
<version>1.12.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
@ -97,6 +102,15 @@
|
||||
<artifactId>commons-collections4</artifactId>
|
||||
<version>4.4</version>
|
||||
</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>
|
||||
|
||||
<build>
|
||||
|
||||
@ -5,13 +5,29 @@ import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@Entity
|
||||
@Table(name = "defense")
|
||||
@Getter
|
||||
@Setter
|
||||
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
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
@ -21,20 +37,34 @@ public class Defense {
|
||||
name = "defense_commission",
|
||||
joinColumns = @JoinColumn(name = "defense_id", referencedColumnName = "id"),
|
||||
inverseJoinColumns = @JoinColumn(name = "commission_member_data_id", referencedColumnName = "id"))
|
||||
private List<CommissionMemberData> commissionMembers;
|
||||
private Set<CommissionMemberData> commissionMembers;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
private Status status;
|
||||
|
||||
private LocalDate defenseDate;
|
||||
|
||||
@OneToMany(mappedBy = "defense")
|
||||
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;
|
||||
private Set<Group> groups;
|
||||
|
||||
@Embedded
|
||||
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,6 +22,10 @@ public class DirectionOfPreparation {
|
||||
@OneToMany(mappedBy = "directionOfPreparation")
|
||||
private List<DiplomaTopic> diplomaTopic;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "responsible_id")
|
||||
private TeacherData responsible;
|
||||
|
||||
@Embedded
|
||||
private AuditInfo auditInfo;
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ package ru.mskobaro.tdms.business.entity;
|
||||
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
@ -15,6 +16,7 @@ import java.util.List;
|
||||
@ToString
|
||||
@Entity
|
||||
@Table(name = "`group`")
|
||||
@EqualsAndHashCode(of = "id")
|
||||
public class Group {
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
|
||||
@ -0,0 +1,56 @@
|
||||
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;
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
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;
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
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,6 +2,7 @@ package ru.mskobaro.tdms.business.entity;
|
||||
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
@ -13,6 +14,7 @@ import ru.mskobaro.tdms.integration.database.TeacherDataRepository;
|
||||
@ToString(exclude = "group")
|
||||
@Entity
|
||||
@Table(name = "student_data")
|
||||
@EqualsAndHashCode(of = "id")
|
||||
public class StudentData {
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
@ -34,9 +36,33 @@ public class StudentData {
|
||||
private Integer protectionOrder;
|
||||
private Integer protectionDay;
|
||||
|
||||
private Integer markComment;
|
||||
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
|
||||
@JoinColumn(name = "curator_id")
|
||||
private TeacherData curator;
|
||||
@ -45,6 +71,13 @@ public class StudentData {
|
||||
@JoinColumn(name = "diploma_topic_id")
|
||||
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
|
||||
private AuditInfo auditInfo;
|
||||
}
|
||||
|
||||
@ -4,38 +4,59 @@ import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.hibernate.annotations.JdbcTypeCode;
|
||||
import org.hibernate.type.SqlTypes;
|
||||
import ru.mskobaro.tdms.business.taskfields.TaskFields;
|
||||
|
||||
@Entity
|
||||
@Table(name = "task")
|
||||
@NoArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
|
||||
@DiscriminatorColumn(name = "task_type", discriminatorType = DiscriminatorType.STRING)
|
||||
public class Task {
|
||||
public enum Type {
|
||||
DIPLOMA_TOPIC_AGREEMENT,
|
||||
}
|
||||
|
||||
public enum Status {
|
||||
WAIT_FOR_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 {
|
||||
TOPIC_AGREEMENT,
|
||||
TOPIC_PREPARATION,
|
||||
TASK_CREATING,
|
||||
TASK_ASSIGN,
|
||||
PRE_DIPLOMA_PRACTICE,
|
||||
TOPIC_FINALIZATION,
|
||||
MAIN_VKR_WORK,
|
||||
PRE_DEFENSE,
|
||||
NORMCONTROL_AND_ANTIPLAGIARISM,
|
||||
DEFENSE_PREPARATION,
|
||||
DEFENSE,
|
||||
}
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
private Status status;
|
||||
@Enumerated(EnumType.STRING)
|
||||
private Type type;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
private Status status;
|
||||
|
||||
@JdbcTypeCode(SqlTypes.JSON)
|
||||
private TaskFields fields;
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "defense_id")
|
||||
private Defense defense;
|
||||
|
||||
@Embedded
|
||||
private AuditInfo auditInfo;
|
||||
|
||||
private Long makerParticId;
|
||||
private Long checkerParticId;
|
||||
}
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
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;
|
||||
|
||||
import ru.mskobaro.tdms.presentation.controller.payload.ErrorDTO;
|
||||
import ru.mskobaro.tdms.integration.controller.payload.ErrorDTO;
|
||||
|
||||
public class AccessDeniedException extends BusinessException {
|
||||
public AccessDeniedException() {
|
||||
|
||||
@ -1,12 +1,16 @@
|
||||
package ru.mskobaro.tdms.business.exception;
|
||||
|
||||
import ru.mskobaro.tdms.presentation.controller.payload.ErrorDTO;
|
||||
import ru.mskobaro.tdms.integration.controller.payload.ErrorDTO;
|
||||
|
||||
public class BusinessException extends RuntimeException {
|
||||
public BusinessException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public BusinessException(String message, Exception cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public ErrorDTO.ErrorCode getErrorCode() {
|
||||
return ErrorDTO.ErrorCode.BUSINESS_ERROR;
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package ru.mskobaro.tdms.business.exception;
|
||||
|
||||
import ru.mskobaro.tdms.presentation.controller.payload.ErrorDTO;
|
||||
import ru.mskobaro.tdms.integration.controller.payload.ErrorDTO;
|
||||
|
||||
public class NotFoundException extends BusinessException {
|
||||
public NotFoundException(Class<?> entityClass, Object id) {
|
||||
|
||||
@ -1,20 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,347 @@
|
||||
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,5 +1,7 @@
|
||||
package ru.mskobaro.tdms.business.service;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
import jakarta.transaction.Transactional;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -9,7 +11,7 @@ import ru.mskobaro.tdms.business.entity.TeacherData;
|
||||
import ru.mskobaro.tdms.integration.database.DiplomaTopicRepository;
|
||||
import ru.mskobaro.tdms.integration.database.PreparationDirectionRepository;
|
||||
import ru.mskobaro.tdms.integration.database.TeacherDataRepository;
|
||||
import ru.mskobaro.tdms.presentation.controller.payload.DiplomaTopicDTO;
|
||||
import ru.mskobaro.tdms.integration.controller.payload.DiplomaTopicDTO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -22,6 +24,8 @@ public class DiplomaTopicService {
|
||||
private TeacherDataRepository teacherDataRepository;
|
||||
@Autowired
|
||||
private PreparationDirectionRepository preparationDirectionRepository;
|
||||
@PersistenceContext
|
||||
private EntityManager entityManager;
|
||||
|
||||
public List<DiplomaTopic> findAll() {
|
||||
return diplomaTopicRepository.findAll();
|
||||
@ -49,7 +53,16 @@ public class DiplomaTopicService {
|
||||
diplomaTopicRepository.save(diplomaTopic);
|
||||
}
|
||||
|
||||
public List<DiplomaTopic> findAllForStudent(Long studentId) {
|
||||
return diplomaTopicRepository.findAllForStudentId(studentId);
|
||||
public List<DiplomaTopic> findAllForStudentByParticId(Long particId) {
|
||||
return diplomaTopicRepository.findAllForStudentByParticId(particId);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,272 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,178 @@
|
||||
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.PreparationDirectionRepository;
|
||||
import ru.mskobaro.tdms.integration.database.StudentDataRepository;
|
||||
import ru.mskobaro.tdms.presentation.controller.payload.GroupDTO;
|
||||
import ru.mskobaro.tdms.presentation.controller.payload.StudentDataDTO;
|
||||
import ru.mskobaro.tdms.integration.controller.payload.GroupDTO;
|
||||
import ru.mskobaro.tdms.integration.controller.payload.StudentDataDTO;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@ -0,0 +1,59 @@
|
||||
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,9 +1,11 @@
|
||||
package ru.mskobaro.tdms.business.service;
|
||||
|
||||
import io.micrometer.common.util.StringUtils;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.collections4.ListUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -11,8 +13,8 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import ru.mskobaro.tdms.business.entity.*;
|
||||
import ru.mskobaro.tdms.business.exception.AccessDeniedException;
|
||||
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.presentation.controller.payload.ParticipantSaveDTO;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@ -41,6 +43,18 @@ public class ParticipantService {
|
||||
private AuthenticationService authenticationService;
|
||||
@Autowired
|
||||
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) {
|
||||
this.participantRepository = participantRepository;
|
||||
@ -68,30 +82,72 @@ public class ParticipantService {
|
||||
participant.setFirstName(participantSaveDTO.getFirstName());
|
||||
participant.setLastName(participantSaveDTO.getLastName());
|
||||
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.setEmail(participantSaveDTO.getEmail());
|
||||
|
||||
List<Role> roles = persistRoles(participantSaveDTO, existingParticipant, editMode, callerUser, participant);
|
||||
boolean credentialsChanged = persistUserData(participantSaveDTO, existingParticipant, editMode, participant);
|
||||
persistStudentData(participantSaveDTO, existingParticipant, editMode, roles, participant);
|
||||
StudentData studentData = persistStudentData(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);
|
||||
log.info("Participant saved: {}", saved.getFullName());
|
||||
|
||||
boolean credentialsChanged = persistUserData(participantSaveDTO, saved, editMode, participant);
|
||||
|
||||
if (credentialsChanged) {
|
||||
log.info("User {} changed credentials, logging out", 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) {
|
||||
boolean isAdmin = roleService.isParticInAuthority(callerUser.getParticipant(), RoleService.Authority.ADMIN);
|
||||
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
|
||||
&& existingParticipant.getUser().getId().equals(callerUser.getId());
|
||||
if (!isAdmin && !isSecretary && !isOwner)
|
||||
if (!isAdmin && !isSecretary && !isOwner && !isTeacher)
|
||||
throw new AccessDeniedException();
|
||||
if (participantSaveDTO.getAuthorities() != null && participantSaveDTO.getAuthorities().contains(RoleService.Authority.ADMIN) && !isAdmin)
|
||||
throw new AccessDeniedException("Недостаточно прав для назначения роли администратора");
|
||||
@ -169,11 +225,11 @@ public class ParticipantService {
|
||||
teacherData.setParticipant(participant);
|
||||
}
|
||||
|
||||
private void persistStudentData(ParticipantSaveDTO participantSaveDTO, Participant existingParticipant, boolean editMode, List<Role> roles, Participant participant) {
|
||||
private StudentData persistStudentData(ParticipantSaveDTO participantSaveDTO, Participant existingParticipant, boolean editMode, List<Role> roles, Participant participant) {
|
||||
boolean shouldPersistStudentData = participantSaveDTO.getStudentData() != null && roles != null
|
||||
&& CollectionUtils.containsAny(roles, roleService.getRoleByAuthority(RoleService.Authority.STUDENT));
|
||||
if (!shouldPersistStudentData) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
boolean alreadyExists = editMode && studentDataRepository.existsByParticipant_IdAndParticipant_DeletedFalse(existingParticipant.getId());
|
||||
@ -184,6 +240,21 @@ public class ParticipantService {
|
||||
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) {
|
||||
Group group = groupRepository.findByIdThrow(participantSaveDTO.getStudentData().getGroupId());
|
||||
studentData.setGroup(group);
|
||||
@ -205,8 +276,28 @@ public class ParticipantService {
|
||||
studentData.setCurator(null);
|
||||
}
|
||||
|
||||
studentData = studentDataRepository.save(studentData);
|
||||
studentData.setParticipant(participant);
|
||||
return studentData;
|
||||
}
|
||||
|
||||
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) {
|
||||
@ -217,4 +308,10 @@ public class ParticipantService {
|
||||
Participant partic = participantRepository.findByIdThrow(id);
|
||||
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,8 +4,10 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
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.presentation.controller.payload.PreparationDirectionDTO;
|
||||
import ru.mskobaro.tdms.integration.controller.payload.PreparationDirectionDTO;
|
||||
import ru.mskobaro.tdms.integration.database.TeacherDataRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -14,6 +16,8 @@ import java.util.List;
|
||||
public class PreparationDirectionService {
|
||||
@Autowired
|
||||
private PreparationDirectionRepository preparationDirectionRepository;
|
||||
@Autowired
|
||||
private TeacherDataRepository teacherDataRepository;
|
||||
|
||||
public List<DirectionOfPreparation> getAll() {
|
||||
return preparationDirectionRepository.findAll();
|
||||
@ -27,8 +31,15 @@ public class PreparationDirectionService {
|
||||
} else {
|
||||
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.setCode(preparationDirectionDTO.getCode());
|
||||
preparationDirection.setResponsible(teacherData);
|
||||
preparationDirectionRepository.save(preparationDirection);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,11 +1,14 @@
|
||||
package ru.mskobaro.tdms.business.service;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
import jakarta.transaction.Transactional;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.mskobaro.tdms.business.entity.Participant;
|
||||
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.UserRepository;
|
||||
|
||||
@ -18,6 +21,8 @@ import java.util.List;
|
||||
public class StudentDataService {
|
||||
@Autowired
|
||||
private StudentDataRepository studentDataRepository;
|
||||
@PersistenceContext
|
||||
private EntityManager entityManager;
|
||||
|
||||
public StudentData getStudentByParticIdThrow(Long particId) {
|
||||
return studentDataRepository.findStudentDataByParticipant_Id(particId);
|
||||
@ -26,4 +31,9 @@ public class StudentDataService {
|
||||
public Collection<StudentData> getAllStudentsWithoutGroup() {
|
||||
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,17 +1,18 @@
|
||||
package ru.mskobaro.tdms.business.service;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import ru.mskobaro.tdms.business.entity.StudentData;
|
||||
import ru.mskobaro.tdms.business.entity.Task;
|
||||
import ru.mskobaro.tdms.business.entity.User;
|
||||
import ru.mskobaro.tdms.business.taskfields.DiplomaTopicAgreementTaskFields;
|
||||
import ru.mskobaro.tdms.business.taskfields.TaskFields;
|
||||
import ru.mskobaro.tdms.integration.database.StudentDataRepository;
|
||||
import ru.mskobaro.tdms.integration.database.TaskRepository;
|
||||
import ru.mskobaro.tdms.presentation.controller.TaskController;
|
||||
import ru.mskobaro.tdms.business.entity.*;
|
||||
import ru.mskobaro.tdms.business.exception.BusinessException;
|
||||
import ru.mskobaro.tdms.integration.controller.TaskController;
|
||||
import ru.mskobaro.tdms.integration.controller.payload.DefenseDTO;
|
||||
import ru.mskobaro.tdms.integration.controller.payload.IdDTO;
|
||||
import ru.mskobaro.tdms.integration.database.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@ -23,41 +24,496 @@ public class TaskService {
|
||||
private UserService userService;
|
||||
@Autowired
|
||||
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 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() {
|
||||
public TopicAgreementTask findDiplomaTopicAgreementTaskMadeByCurrentUser() {
|
||||
User user = userService.getCallerUser();
|
||||
List<Task> diplomaTopicAgreementTaskByMakerId = taskRepository.findDiplomaTopicAgreementTaskByMakerId(
|
||||
user.getParticipant().getId(), Task.Type.DIPLOMA_TOPIC_AGREEMENT
|
||||
);
|
||||
if (diplomaTopicAgreementTaskByMakerId.isEmpty()) {
|
||||
try {
|
||||
return entityManager.createQuery("select t from TopicAgreementTask t where t.checkerParticId = :id or t.makerParticId = :id", TopicAgreementTask.class)
|
||||
.setParameter("id", user.getParticipant().getId())
|
||||
.setMaxResults(1)
|
||||
.getSingleResult();
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (diplomaTopicAgreementTaskByMakerId.size() > 1) {
|
||||
throw new IllegalStateException();
|
||||
private List<Task.Status> getNotShowStatuses() {
|
||||
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);
|
||||
}
|
||||
|
||||
return diplomaTopicAgreementTaskByMakerId.get(0);
|
||||
if (!roleService.isParticInAuthority(user.getParticipant(), RoleService.Authority.TEACHER)) {
|
||||
notShowStatuses.add(Task.Status.WAIT_FOR_TOPIC_AGREEMENT);
|
||||
}
|
||||
return notShowStatuses;
|
||||
}
|
||||
|
||||
public void createDiplomaAgreementTask(TaskController.DiplomaTopicAgreementDTO diplomaTopicAgreementDTO) {
|
||||
DiplomaTopicAgreementTaskFields taskFields = new DiplomaTopicAgreementTaskFields();
|
||||
User user = userService.getCallerUser();
|
||||
StudentData studentData = studentDataRepository.findStudentDataByParticipant_Id(user.getParticipant().getId());
|
||||
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();
|
||||
}
|
||||
|
||||
taskFields.setCheckerParticipantId(user.getParticipant().getId());
|
||||
taskFields.setDiplomaTopicId(diplomaTopicAgreementDTO.getDiplomaTopicId());
|
||||
taskFields.setDiplomaTopicName(diplomaTopicAgreementDTO.getDiplomaTopicName());
|
||||
taskFields.setCheckerParticipantId(studentData.getCurator().getId());
|
||||
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()));
|
||||
|
||||
createTask(Task.Type.DIPLOMA_TOPIC_AGREEMENT, Task.Status.WAIT_FOR_TOPIC_AGREEMENT, taskFields);
|
||||
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();
|
||||
}
|
||||
Long checkerId = topicAgreementTask.getCheckerParticId();
|
||||
StudentData student = studentDataRepository.findStudentDataByParticipant_Id(checkerId);
|
||||
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) {
|
||||
try {
|
||||
return entityManager.createQuery("select t from TopicAgreementTask t where t.makerParticId = :id", TopicAgreementTask.class)
|
||||
.setParameter("id", id)
|
||||
.setMaxResults(1)
|
||||
.getSingleResult();
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void checkAndCreateTopicPreparationTasksAndSendEmail(List<TeacherData> teachers, Defense defense) {
|
||||
for (TeacherData teacher : teachers) {
|
||||
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", teacher.getParticipant().getId())
|
||||
.setParameter("type", Task.Type.TOPIC_PREPARATION)
|
||||
.setParameter("defense", defense)
|
||||
.getSingleResult();
|
||||
|
||||
if (!exists) {
|
||||
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 ru.mskobaro.tdms.business.entity.User;
|
||||
import ru.mskobaro.tdms.integration.database.UserRepository;
|
||||
import ru.mskobaro.tdms.presentation.controller.payload.UserDTO;
|
||||
import ru.mskobaro.tdms.integration.controller.payload.UserDTO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
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;
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
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;
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
package ru.mskobaro.tdms.business.taskfields;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class MakerTaskFields extends TaskFields {
|
||||
private Long makerParticipantId;
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
package ru.mskobaro.tdms.business.taskfields;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Getter
|
||||
public class TaskFields {
|
||||
private LocalDateTime createdAt;
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,121 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
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,10 +1,10 @@
|
||||
package ru.mskobaro.tdms.presentation.controller;
|
||||
package ru.mskobaro.tdms.integration.controller;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import ru.mskobaro.tdms.business.service.GroupService;
|
||||
import ru.mskobaro.tdms.presentation.controller.payload.GroupDTO;
|
||||
import ru.mskobaro.tdms.integration.controller.payload.GroupDTO;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@ -0,0 +1,33 @@
|
||||
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,14 +1,16 @@
|
||||
package ru.mskobaro.tdms.presentation.controller;
|
||||
package ru.mskobaro.tdms.integration.controller;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import ru.mskobaro.tdms.business.service.ParticipantService;
|
||||
import ru.mskobaro.tdms.presentation.controller.payload.IdDto;
|
||||
import ru.mskobaro.tdms.presentation.controller.payload.ParticipantDTO;
|
||||
import ru.mskobaro.tdms.presentation.controller.payload.ParticipantSaveDTO;
|
||||
import ru.mskobaro.tdms.integration.controller.payload.IdDTO;
|
||||
import ru.mskobaro.tdms.integration.controller.payload.ParticipantDTO;
|
||||
import ru.mskobaro.tdms.integration.controller.payload.ParticipantSaveDTO;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/participant")
|
||||
@ -17,7 +19,7 @@ public class ParticipantController {
|
||||
private ParticipantService participantService;
|
||||
|
||||
@GetMapping("/get-all-participants")
|
||||
public Collection<ParticipantDTO> getAllParticipants() {
|
||||
public List<ParticipantDTO> getAllParticipants() {
|
||||
return participantService.getAllParticipants().stream()
|
||||
.map(ParticipantDTO::fromEntity)
|
||||
.toList();
|
||||
@ -29,7 +31,17 @@ public class ParticipantController {
|
||||
}
|
||||
|
||||
@PostMapping("/delete")
|
||||
public void deleteParticipant(@RequestBody IdDto id) {
|
||||
public void deleteParticipant(@RequestBody IdDTO id) {
|
||||
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.presentation.controller;
|
||||
package ru.mskobaro.tdms.integration.controller;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import ru.mskobaro.tdms.business.service.PreparationDirectionService;
|
||||
import ru.mskobaro.tdms.presentation.controller.payload.PreparationDirectionDTO;
|
||||
import ru.mskobaro.tdms.integration.controller.payload.PreparationDirectionDTO;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
@ -1,4 +1,4 @@
|
||||
package ru.mskobaro.tdms.presentation.controller;
|
||||
package ru.mskobaro.tdms.integration.controller;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@ -7,16 +7,19 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import ru.mskobaro.tdms.business.entity.StudentData;
|
||||
import ru.mskobaro.tdms.business.service.StudentDataService;
|
||||
import ru.mskobaro.tdms.presentation.controller.payload.GroupDTO;
|
||||
import ru.mskobaro.tdms.presentation.controller.payload.StudentDataDTO;
|
||||
import ru.mskobaro.tdms.integration.controller.payload.StudentDataDTO;
|
||||
import ru.mskobaro.tdms.integration.database.StudentDataRepository;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/student/")
|
||||
public class StudentController {
|
||||
@Autowired
|
||||
private StudentDataService studentDataService;
|
||||
@Autowired
|
||||
private StudentDataRepository studentDataRepository;
|
||||
|
||||
@GetMapping(value = "/by-partic-id")
|
||||
public StudentDataDTO getCurrentStudent(@RequestParam(value = "id") Long particId) {
|
||||
@ -30,4 +33,16 @@ public class StudentController {
|
||||
.map(sd -> StudentDataDTO.from(sd, true))
|
||||
.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.presentation.controller;
|
||||
package ru.mskobaro.tdms.integration.controller;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@ -0,0 +1,122 @@
|
||||
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,4 +1,4 @@
|
||||
package ru.mskobaro.tdms.presentation.controller;
|
||||
package ru.mskobaro.tdms.integration.controller;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
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.RestController;
|
||||
import ru.mskobaro.tdms.business.service.TeacherDataService;
|
||||
import ru.mskobaro.tdms.presentation.controller.payload.TeacherDataDTO;
|
||||
import ru.mskobaro.tdms.integration.controller.payload.TeacherDataDTO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package ru.mskobaro.tdms.presentation.controller;
|
||||
package ru.mskobaro.tdms.integration.controller;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
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.service.AuthenticationService;
|
||||
import ru.mskobaro.tdms.business.service.UserService;
|
||||
import ru.mskobaro.tdms.presentation.controller.payload.LoginDTO;
|
||||
import ru.mskobaro.tdms.presentation.controller.payload.UserDTO;
|
||||
import ru.mskobaro.tdms.integration.controller.payload.LoginDTO;
|
||||
import ru.mskobaro.tdms.integration.controller.payload.UserDTO;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/user")
|
||||
@ -1,4 +1,4 @@
|
||||
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||
package ru.mskobaro.tdms.integration.controller.payload;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
@ -0,0 +1,58 @@
|
||||
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,4 +1,4 @@
|
||||
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||
package ru.mskobaro.tdms.integration.controller.payload;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
@ -1,4 +1,4 @@
|
||||
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||
package ru.mskobaro.tdms.integration.controller.payload;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@ -1,4 +1,4 @@
|
||||
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||
package ru.mskobaro.tdms.integration.controller.payload;
|
||||
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
@ -30,9 +30,7 @@ public class GroupDTO {
|
||||
dto.setId(group.getId());
|
||||
dto.setName(group.getName());
|
||||
if (includeStudents && group.getStudents() != null) {
|
||||
dto.setStudents(
|
||||
group.getStudents()
|
||||
.stream()
|
||||
dto.setStudents(group.getStudents().stream()
|
||||
.filter(sd -> !sd.getParticipant().isDeleted())
|
||||
.map(sd -> StudentDataDTO.from(sd, false))
|
||||
.toList());
|
||||
@ -0,0 +1,20 @@
|
||||
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,4 +1,4 @@
|
||||
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||
package ru.mskobaro.tdms.integration.controller.payload;
|
||||
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
@ -1,20 +1,15 @@
|
||||
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||
package ru.mskobaro.tdms.integration.controller.payload;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
|
||||
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import ru.mskobaro.tdms.business.entity.Participant;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
|
||||
// @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
|
||||
public class ParticipantDTO {
|
||||
private Long id;
|
||||
private String firstName;
|
||||
@ -1,4 +1,4 @@
|
||||
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||
package ru.mskobaro.tdms.integration.controller.payload;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.*;
|
||||
@ -33,6 +33,8 @@ public class ParticipantSaveDTO {
|
||||
private StudentRegistrationDTO studentData;
|
||||
@Valid
|
||||
private TeacherRegistrationDTO teacherData;
|
||||
@Valid
|
||||
private CommMemDto commMemData;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
@ -51,6 +53,19 @@ public class ParticipantSaveDTO {
|
||||
private Long groupId;
|
||||
private Long curatorId;
|
||||
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
|
||||
@ -61,4 +76,11 @@ public class ParticipantSaveDTO {
|
||||
private String degree;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
public static class CommMemDto {
|
||||
private String workPlace;
|
||||
private String workPosition;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||
package ru.mskobaro.tdms.integration.controller.payload;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
@ -14,6 +14,7 @@ public class PreparationDirectionDTO {
|
||||
private Long id;
|
||||
private String name;
|
||||
private String code;
|
||||
private TeacherDataDTO responsible;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
@ -22,6 +23,9 @@ public class PreparationDirectionDTO {
|
||||
dto.setId(preparationDirection.getId());
|
||||
dto.setName(preparationDirection.getName());
|
||||
dto.setCode(preparationDirection.getCode());
|
||||
if (preparationDirection.getResponsible() != null) {
|
||||
dto.setResponsible(TeacherDataDTO.from(preparationDirection.getResponsible()));
|
||||
}
|
||||
dto.setCreatedAt(preparationDirection.getAuditInfo().getCreatedAt());
|
||||
dto.setUpdatedAt(preparationDirection.getAuditInfo().getUpdatedAt());
|
||||
return dto;
|
||||
@ -1,4 +1,4 @@
|
||||
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||
package ru.mskobaro.tdms.integration.controller.payload;
|
||||
|
||||
|
||||
import ru.mskobaro.tdms.business.entity.Participant;
|
||||
@ -0,0 +1,88 @@
|
||||
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,4 +1,4 @@
|
||||
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||
package ru.mskobaro.tdms.integration.controller.payload;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
@ -0,0 +1,39 @@
|
||||
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,4 +1,4 @@
|
||||
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||
package ru.mskobaro.tdms.integration.controller.payload;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
|
||||
@ -7,7 +7,6 @@ import lombok.Builder;
|
||||
import ru.mskobaro.tdms.business.entity.User;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
|
||||
@Builder
|
||||
@ -0,0 +1,17 @@
|
||||
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);
|
||||
}
|
||||
@ -1,25 +0,0 @@
|
||||
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);
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
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,8 +4,6 @@ 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.DiplomaTopic;
|
||||
import ru.mskobaro.tdms.business.entity.DirectionOfPreparation;
|
||||
import ru.mskobaro.tdms.business.entity.StudentData;
|
||||
import ru.mskobaro.tdms.business.exception.NotFoundException;
|
||||
|
||||
import java.util.List;
|
||||
@ -17,13 +15,9 @@ public interface DiplomaTopicRepository extends JpaRepository<DiplomaTopic, Long
|
||||
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 " +
|
||||
"inner join d.directionOfPreparation dp " +
|
||||
"inner join StudentData sd on sd.id = :studentIdwhere " +
|
||||
"where dp = sd.group.directionOfPreparation")
|
||||
List<DiplomaTopic> findAllForStudentId(Long studentId);
|
||||
"inner join StudentData sd on sd.participant.id = :particId " +
|
||||
"where dp = sd.group.directionOfPreparation and dp is not null and sd.curator = d.teacher and d.teacher is not null")
|
||||
List<DiplomaTopic> findAllForStudentByParticId(Long particId);
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
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,4 +24,6 @@ public interface ParticipantRepository extends JpaRepository<Participant, Long>
|
||||
@Override
|
||||
@Query("SELECT p from Participant p where p.deleted = false")
|
||||
List<Participant> findAll();
|
||||
|
||||
boolean existsByNumberPhoneOrEmail(String numberPhone, String email);
|
||||
}
|
||||
|
||||
@ -1,21 +1,13 @@
|
||||
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.Task;
|
||||
import ru.mskobaro.tdms.business.exception.NotFoundException;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface TaskRepository extends JpaRepository<Task, Long> {
|
||||
default Task findByIdThrow(Long 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);
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package ru.mskobaro.tdms.presentation.exception;
|
||||
package ru.mskobaro.tdms.integration.exception;
|
||||
|
||||
import jakarta.mail.SendFailedException;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.support.DefaultMessageSourceResolvable;
|
||||
@ -11,14 +12,15 @@ import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.servlet.resource.NoResourceFoundException;
|
||||
import ru.mskobaro.tdms.business.exception.AccessDeniedException;
|
||||
import ru.mskobaro.tdms.business.exception.BusinessException;
|
||||
import ru.mskobaro.tdms.presentation.controller.payload.ErrorDTO;
|
||||
import ru.mskobaro.tdms.integration.controller.payload.ErrorDTO;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.springframework.http.HttpStatus.*;
|
||||
import static org.springframework.http.HttpStatus.NOT_FOUND;
|
||||
import static ru.mskobaro.tdms.presentation.controller.payload.ErrorDTO.ErrorCode.*;
|
||||
import static org.springframework.http.HttpStatus.*;
|
||||
import static ru.mskobaro.tdms.integration.controller.payload.ErrorDTO.ErrorCode.*;
|
||||
|
||||
@RestControllerAdvice
|
||||
@Slf4j
|
||||
@ -35,7 +37,7 @@ public class ApplicationExceptionHandler {
|
||||
|
||||
@ExceptionHandler(BusinessException.class)
|
||||
public ErrorDTO handleBusinessException(BusinessException e, HttpServletResponse response) {
|
||||
log.warn("Business error: {}", e.getMessage());
|
||||
log.warn("Business error: ", e);
|
||||
response.setStatus(e.getErrorCode().getHttpStatus().value());
|
||||
return new ErrorDTO(e.getMessage(), e.getErrorCode());
|
||||
}
|
||||
@ -70,4 +72,18 @@ public class ApplicationExceptionHandler {
|
||||
log.error("Unexpected exception ({})", uuid, e);
|
||||
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,22 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
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,34 +0,0 @@
|
||||
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,39 +0,0 @@
|
||||
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,14 +0,0 @@
|
||||
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,31 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -1,33 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
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,8 +31,7 @@ import ru.mskobaro.tdms.system.web.LoggingRequestFilter;
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
|
||||
import static ru.mskobaro.tdms.business.service.RoleService.Authority.ADMIN;
|
||||
import static ru.mskobaro.tdms.business.service.RoleService.Authority.SECRETARY;
|
||||
import static ru.mskobaro.tdms.business.service.RoleService.Authority.*;
|
||||
|
||||
|
||||
@Slf4j
|
||||
@ -63,16 +62,14 @@ public class SecurityConfig {
|
||||
@Bean
|
||||
@Primary
|
||||
public CorsConfigurationSource corsConfiguration(
|
||||
@Value("${application.domain}") String domain,
|
||||
@Value("${application.port}") String port,
|
||||
@Value("${application.protocol}") String protocol
|
||||
@Value("${application.domain}") String domain
|
||||
) {
|
||||
CorsConfiguration corsConfiguration = new CorsConfiguration();
|
||||
corsConfiguration.setAllowedMethods(List.of(HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.OPTIONS.name()));
|
||||
corsConfiguration.setAllowedHeaders(List.of("Authorization", "Content-Type"));
|
||||
corsConfiguration.setAllowCredentials(true);
|
||||
corsConfiguration.setMaxAge(Duration.ofDays(1));
|
||||
corsConfiguration.addAllowedOrigin(StringUtils.join(protocol, "://", domain, ":", port));
|
||||
corsConfiguration.addAllowedOrigin(StringUtils.join("https", "://", domain));
|
||||
|
||||
if (environment.matchesProfiles("dev")) {
|
||||
corsConfiguration.addAllowedOrigin("http://localhost:8888");
|
||||
@ -115,6 +112,8 @@ public class SecurityConfig {
|
||||
// Сложная логика авторизации, так что проверяем явно в ParticipantService
|
||||
httpAuthorization.requestMatchers("/api/v1/participant/save").authenticated();
|
||||
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/save").hasAnyAuthority(ADMIN.getAuthority(), SECRETARY.getAuthority());
|
||||
@ -122,6 +121,8 @@ public class SecurityConfig {
|
||||
|
||||
httpAuthorization.requestMatchers("/api/v1/student/by-partic-id").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/by-partic-id").permitAll();
|
||||
@ -129,11 +130,39 @@ public class SecurityConfig {
|
||||
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/defence/all").permitAll();
|
||||
httpAuthorization.requestMatchers("/api/v1/defense/get-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-for-student").permitAll();
|
||||
httpAuthorization.requestMatchers("/api/v1/diploma-topic/save").hasAnyAuthority(ADMIN.getAuthority(), SECRETARY.getAuthority());
|
||||
httpAuthorization.requestMatchers("/api/v1/diploma-topic/by-id").permitAll();
|
||||
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();
|
||||
|
||||
|
||||
@ -11,10 +11,13 @@ import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Slf4j
|
||||
public class LoggingRequestFilter extends OncePerRequestFilter {
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
||||
UUID uuid = UUID.randomUUID();
|
||||
@ -22,6 +25,12 @@ public class LoggingRequestFilter extends OncePerRequestFilter {
|
||||
String username = SecurityContextHolder.getContext().getAuthentication() != null ?
|
||||
SecurityContextHolder.getContext().getAuthentication().getName() : "anonymousUser";
|
||||
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: {} [{}]",
|
||||
request.getMethod(), request.getRequestURI(), username,
|
||||
session == null ? "no" : session.getId(), request.getRemoteAddr(), uuid);
|
||||
|
||||
@ -49,5 +49,20 @@
|
||||
"name": "application.protocol",
|
||||
"type": "java.lang.String",
|
||||
"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,8 +8,13 @@ application:
|
||||
version: @version@
|
||||
type: production
|
||||
port: 443
|
||||
domain: tdms.tu-bryansk.ru
|
||||
domain: vkr.tu-bryansk.ru
|
||||
host: localhost
|
||||
protocol: https
|
||||
smtp:
|
||||
host: localhost
|
||||
port: 2525
|
||||
message-from: admin@vkr.tu-bryansk.ru
|
||||
|
||||
spring:
|
||||
application:
|
||||
@ -32,7 +37,7 @@ spring:
|
||||
location: banner.txt
|
||||
server:
|
||||
port: ${application.port}
|
||||
address: ${application.domain}
|
||||
address: ${application.host}
|
||||
compression:
|
||||
enabled: true
|
||||
management:
|
||||
|
||||
@ -1,15 +1,13 @@
|
||||
CREATE TABLE defense
|
||||
(
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
defense_date DATE,
|
||||
created_at TIMESTAMP WITHOUT TIME ZONE,
|
||||
updated_at TIMESTAMP WITHOUT TIME ZONE
|
||||
);
|
||||
|
||||
CREATE TABLE defense_best_student_works
|
||||
(
|
||||
defense_id BIGINT,
|
||||
student_data_id BIGINT
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
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,
|
||||
updated_at TIMESTAMP WITHOUT TIME ZONE
|
||||
);
|
||||
|
||||
CREATE TABLE defense_commission
|
||||
@ -30,11 +28,12 @@ CREATE TABLE diploma_topic
|
||||
|
||||
CREATE TABLE direction_of_preparation
|
||||
(
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
name TEXT,
|
||||
code TEXT,
|
||||
created_at TIMESTAMP WITHOUT TIME ZONE,
|
||||
updated_at TIMESTAMP WITHOUT TIME ZONE
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
name TEXT,
|
||||
code TEXT,
|
||||
responsible_id BIGINT,
|
||||
created_at TIMESTAMP WITHOUT TIME ZONE,
|
||||
updated_at TIMESTAMP WITHOUT TIME ZONE
|
||||
);
|
||||
|
||||
CREATE TABLE "group"
|
||||
@ -73,7 +72,6 @@ CREATE TABLE role
|
||||
authority TEXT
|
||||
);
|
||||
|
||||
/* todo */
|
||||
CREATE TABLE student_data
|
||||
(
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
@ -84,30 +82,42 @@ CREATE TABLE student_data
|
||||
protection_order INTEGER,
|
||||
protection_day INTEGER,
|
||||
|
||||
mark_comment INTEGER,
|
||||
mark_practice INTEGER,
|
||||
predefnese_mark INTEGER,
|
||||
oztiv_mark INTEGER,
|
||||
|
||||
|
||||
predefnese_comment TEXT,
|
||||
normal_control BOOLEAN,
|
||||
anti_plagiarism INTEGER,
|
||||
|
||||
record_book_returned BOOLEAN,
|
||||
|
||||
work TEXT,
|
||||
|
||||
diploma_topic_id BIGINT,
|
||||
adviser_teacher_partic_id BIGINT,
|
||||
group_id BIGINT,
|
||||
|
||||
marks_3 BIGINT,
|
||||
marks_4 BIGINT,
|
||||
marks_5 BIGINT,
|
||||
|
||||
commission_mark BIGINT,
|
||||
|
||||
estimated BOOLEAN,
|
||||
|
||||
diploma_with_honors BOOLEAN,
|
||||
vnedreniye BOOLEAN,
|
||||
|
||||
magistracy_recommendation BOOLEAN,
|
||||
magistracy_wanted BOOLEAN,
|
||||
|
||||
electronic BOOLEAN,
|
||||
|
||||
created_at TIMESTAMP WITHOUT TIME ZONE,
|
||||
updated_at TIMESTAMP WITHOUT TIME ZONE
|
||||
);
|
||||
|
||||
/* not implemented */
|
||||
create table questionnaire
|
||||
(
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
@ -125,7 +135,6 @@ create table study_form
|
||||
updated_at TIMESTAMP WITHOUT TIME ZONE
|
||||
);
|
||||
|
||||
/* todo */
|
||||
create table stud_comment
|
||||
(
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
@ -134,7 +143,6 @@ create table stud_comment
|
||||
updated_at TIMESTAMP WITHOUT TIME ZONE
|
||||
);
|
||||
|
||||
/* todo */
|
||||
create table student_data_comment
|
||||
(
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
@ -173,14 +181,34 @@ CREATE TABLE "user"
|
||||
updated_at TIMESTAMP WITHOUT TIME ZONE
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE task
|
||||
(
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
type TEXT,
|
||||
status TEXT,
|
||||
fields jsonb,
|
||||
created_at TIMESTAMP WITHOUT TIME ZONE,
|
||||
updated_at TIMESTAMP WITHOUT TIME ZONE
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
status TEXT,
|
||||
type TEXT,
|
||||
defense_id BIGINT,
|
||||
maker_partic_id BIGINT,
|
||||
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,
|
||||
updated_at TIMESTAMP WITHOUT TIME ZONE
|
||||
);
|
||||
|
||||
ALTER TABLE defense_commission
|
||||
@ -201,9 +229,6 @@ 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;
|
||||
|
||||
ALTER TABLE student_data
|
||||
ADD CONSTRAINT UC_STUDENT_DATA_PARTIC UNIQUE (partic_id);
|
||||
|
||||
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;
|
||||
|
||||
@ -252,12 +277,6 @@ ALTER TABLE direction_of_preparation
|
||||
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;
|
||||
|
||||
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
|
||||
ADD CONSTRAINT UC_STUD_COMMENT_COMMENT UNIQUE (comment);
|
||||
|
||||
@ -278,3 +297,18 @@ 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;
|
||||
|
||||
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;
|
||||
@ -0,0 +1,97 @@
|
||||
-- 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());
|
||||
@ -1,12 +0,0 @@
|
||||
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 'Дата защиты';
|
||||
@ -1,40 +0,0 @@
|
||||
INSERT INTO diploma_topic (name)
|
||||
VALUES ('Мобильное приложение для заказа автозапчастей на платформе ABCP'),
|
||||
('Подсистема уведомления пользователей для программного комплекса "РискПроф. Учебный центр"'),
|
||||
('Веб-приложение "Таск-менеджер"'),
|
||||
('Интернет-магазин электроники'),
|
||||
('Информационная система для студентов БГТУ в Telegram'),
|
||||
('Автоматизированная система тестирования сотрудников для определения их компетенций: модуль подготовки тестов и учета результатов'),
|
||||
('Инструментарий для разработки динамической экосистемы игрового пространства. Подсистема управления поведением внутриигровых агентов'),
|
||||
('Корпоративное веб-приложение по управлению задачами'),
|
||||
('Подсистемы визуализации и аналитики для онлайн-сервиса поддержки scrum-доски'),
|
||||
('Интерактивная система обучения приемам работы с криптовалютой'),
|
||||
('Автоматизированная система учета деятельности салона по продаже автомобилей'),
|
||||
('Обучающее мобильное android-приложение'),
|
||||
('Автоматизированная система учета зуботехнической CAD/CAM лаборатории'),
|
||||
('Автоматизированная система тестирования сотрудников для определения их компетенций: модуль регистрации и управления кабинетами'),
|
||||
('Система мониторинга успеваемости обучающихся и посещаемости занятий образовательного учреждения'),
|
||||
('Мобильное приложение для организации работы репетитора'),
|
||||
('Модуль "Редактор рисков" для программного комплекса управления профессиональными рисками "1С. ЕОС ПБ"'),
|
||||
('Онлайн-сервис по продаже товаров (на примере ООО «ЭПК-2»'),
|
||||
('Веб-сервис по обучению Microsoft Excel'),
|
||||
('Инструментарий для разработки динамической экосистемы игрового пространства. Подсистема генерации наполнения помещений'),
|
||||
('Подсистема интеграции с федеральной государственной информационной системой по охране труда для программного комплекса «РискПроф. Учебный центр»'),
|
||||
('Разработка приложения голосовой авторизации на основе нейросетевого подхода'),
|
||||
('Автоматизированная система учета деятельности спортивного клуба'),
|
||||
('Модуль "Специальная оценка условий труда" для программного комплекса управления профессиональными рисками "1С. ЕОС ПБ"'),
|
||||
('Интернет-магазин по продаже спортивной обуви'),
|
||||
('Приложение интерактивной исторической карты'),
|
||||
('Миграция системы учёта с 1С:УТ на 1С:КА'),
|
||||
('Программный комплекс для автоматизированного проведения опросов и тестирования пользователей'),
|
||||
('Автоматизированное тестирование программного комплекса «Федеральная государственная информационная система специальной оценки условий труда»'),
|
||||
('Модуль "Единая информационно-справочная подсистема" для федеральной государственной информационной системы по охране труда'),
|
||||
('Подсистема сопровождения обучения по охране труда для программного комплекса «РискПроф. Учебный центр»'),
|
||||
('Программное обеспечение системы обучения и тестирования в мессенджере Telegram'),
|
||||
('Онлайн-калькулятор индексов влияния в играх взвешенного голосования'),
|
||||
('Telegram-бот с функциями обработки изображений'),
|
||||
('Подсистема администрирования автоматизированной системы для проведения платежей и перевода денежных средств'),
|
||||
('Подсистема администрирования для программного комплекса распределения студентов по руководителям выпускных квалификационных работ'),
|
||||
('Библиотека контроля качества данных в базах и хранилищах данных для программного комплекса MetaControl'),
|
||||
('Инструментарий для разработки динамической экосистемы игрового пространства. Подсистема генерации карты помещений'),
|
||||
('Программная система решения транспортной задачи методом генетического алгоритма для торговой сети');
|
||||
@ -1,3 +0,0 @@
|
||||
INSERT INTO "group" (name, curator_teacher_id, created_at, updated_at)
|
||||
VALUES ('ИВТ-1', 40, now(), now()),
|
||||
('ИВТ-2', 40, now(), now());
|
||||
@ -1,98 +0,0 @@
|
||||
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
|
||||
$$;
|
||||
@ -1,82 +0,0 @@
|
||||
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());
|
||||
@ -1,58 +0,0 @@
|
||||
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.
BIN
server/src/main/resources/doc_templates/questions_template.docx
Normal file
BIN
server/src/main/resources/doc_templates/questions_template.docx
Normal file
Binary file not shown.
Binary file not shown.
143
server/src/main/resources/test-data.sql
Normal file
143
server/src/main/resources/test-data.sql
Normal file
@ -0,0 +1,143 @@
|
||||
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,6 +21,7 @@
|
||||
"mobx-react": "^9.1.1",
|
||||
"mobx-state-router": "^6.0.1",
|
||||
"react": "^18.2.0",
|
||||
"react-beautiful-dnd": "^13.1.1",
|
||||
"react-bootstrap": "^2.10.4",
|
||||
"react-dom": "^18.2.0",
|
||||
"uuid": "^11.0.5"
|
||||
@ -30,6 +31,7 @@
|
||||
"@babel/preset-env": "^7.25.8",
|
||||
"@babel/preset-react": "^7.25.7",
|
||||
"@types/react": "^18.2.0",
|
||||
"@types/react-beautiful-dnd": "^13.1.8",
|
||||
"@types/react-dom": "^18.2.0",
|
||||
"@types/webpack": "^5.28.5",
|
||||
"copy-webpack-plugin": "^13.0.0",
|
||||
@ -2082,6 +2084,16 @@
|
||||
"@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": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
|
||||
@ -2165,6 +2177,16 @@
|
||||
"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": {
|
||||
"version": "18.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz",
|
||||
@ -2174,6 +2196,18 @@
|
||||
"@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": {
|
||||
"version": "4.4.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.11.tgz",
|
||||
@ -3256,6 +3290,15 @@
|
||||
"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": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.2.tgz",
|
||||
@ -4130,6 +4173,15 @@
|
||||
"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": {
|
||||
"version": "2.1.6",
|
||||
"resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
|
||||
@ -4746,6 +4798,12 @@
|
||||
"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": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
|
||||
@ -5412,6 +5470,12 @@
|
||||
"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": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||
@ -5465,6 +5529,26 @@
|
||||
"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": {
|
||||
"version": "2.10.5",
|
||||
"resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.10.5.tgz",
|
||||
@ -5516,6 +5600,37 @@
|
||||
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
||||
"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": {
|
||||
"version": "4.4.5",
|
||||
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
|
||||
@ -5569,6 +5684,15 @@
|
||||
"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": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
|
||||
@ -6569,6 +6693,15 @@
|
||||
"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": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz",
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
"mobx-react": "^9.1.1",
|
||||
"mobx-state-router": "^6.0.1",
|
||||
"react": "^18.2.0",
|
||||
"react-beautiful-dnd": "^13.1.1",
|
||||
"react-bootstrap": "^2.10.4",
|
||||
"react-dom": "^18.2.0",
|
||||
"uuid": "^11.0.5"
|
||||
@ -29,6 +30,7 @@
|
||||
"@babel/preset-env": "^7.25.8",
|
||||
"@babel/preset-react": "^7.25.7",
|
||||
"@types/react": "^18.2.0",
|
||||
"@types/react-beautiful-dnd": "^13.1.8",
|
||||
"@types/react-dom": "^18.2.0",
|
||||
"@types/webpack": "^5.28.5",
|
||||
"copy-webpack-plugin": "^13.0.0",
|
||||
|
||||
@ -12,15 +12,21 @@ import {ParticipantListPage} from "./components/participant/ParticipantListPage"
|
||||
import {DefenceListPage} from "./components/defence/DefenceListPage";
|
||||
import {PreparationDirectionListPage} from "./components/dictionary/PreparationDirectionList";
|
||||
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 = {
|
||||
home: <Home/>,
|
||||
error: <Error/>,
|
||||
participantList: <ParticipantListPage/>,
|
||||
groupList: <GroupListPage/>,
|
||||
defenceList: <DefenceListPage/>,
|
||||
themeList: <DiplomaTopicListPage/>,
|
||||
preparationDirectionList: <PreparationDirectionListPage/>,
|
||||
error: <Error/>,
|
||||
defenceTopicAgreement: <DiplomaTopicAgreementPage/>,
|
||||
defenseEdit: <DefenceEditPage/>,
|
||||
notifications: <NotificationPage/>,
|
||||
}
|
||||
|
||||
const rootStore = initApp();
|
||||
|
||||
@ -9,7 +9,7 @@ import {
|
||||
observer
|
||||
} from "mobx-react";
|
||||
import {
|
||||
action,
|
||||
action, computed,
|
||||
makeObservable,
|
||||
observable,
|
||||
runInAction
|
||||
@ -41,6 +41,8 @@ import {
|
||||
import {
|
||||
ModalState
|
||||
} from "../../utils/modalState";
|
||||
import _ from "lodash";
|
||||
import {dateConverter, dateConverter2} from "../../utils/converters";
|
||||
|
||||
export interface ReactiveInputProps<T> {
|
||||
value: ReactiveValue<T>;
|
||||
@ -112,7 +114,7 @@ export class StringInput extends Component<ReactiveInputProps<string>> {
|
||||
return <div className={'mb-1 l-no-bg'}>
|
||||
<FloatingLabel label={this.props.label} className={`${this.props.className} mt-0 mb-0`}>
|
||||
<FormControl type='text' placeholder={this.props.label} disabled={this.props.disabled} onChange={this.onChange}
|
||||
value={this.props.value.value ?? ''} className={inputClassName}/>
|
||||
value={this.props.value.value ?? ''} className={inputClassName}/>
|
||||
</FloatingLabel>
|
||||
<FormText children={this.props.value.firstError} className={`text-danger mt-0 mb-0 d-block`}/>
|
||||
</div>
|
||||
@ -279,16 +281,27 @@ export class DropdownSelectInput extends Component<MultipleSelectInputProps> {
|
||||
if (this.props.value.value === undefined) {
|
||||
this.props.value.setAuto([]);
|
||||
}
|
||||
|
||||
this.initField(this.props);
|
||||
|
||||
runInAction(() => {
|
||||
this.options = props.possibleValues;
|
||||
});
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: Readonly<MultipleSelectInputProps>) {
|
||||
if (this.value != prevProps.value) {
|
||||
componentDidUpdate() {
|
||||
if (this.value != this.props.value) {
|
||||
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
|
||||
@ -341,24 +354,23 @@ export class DropdownSelectInput extends Component<MultipleSelectInputProps> {
|
||||
const inputDisabledBackgroundStyle = this.props.disabled ? {backgroundColor: 'rgb(233, 236, 239)'} : {};
|
||||
const inputDisabledColor = this.props.disabled ? '#000000' : 'rgb(33, 37, 41)';
|
||||
|
||||
return <div
|
||||
className={'mb-1 l-no-bg'}>
|
||||
{
|
||||
return (
|
||||
<div className={'mb-1 l-no-bg'}>
|
||||
<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`}
|
||||
variant={'outline-light'} style={{'cursor': 'default'}} disabled={this.props.disabled}>
|
||||
variant={'outline-light'} style={{'cursor': 'default'}} disabled={this.props.disabled}>
|
||||
<span style={{'fontSize': '1rem', 'color': inputDisabledColor}}>{this.value.field}</span>
|
||||
{
|
||||
this.value.value?.map(sel => {
|
||||
return <Badge bg={'dark'} className={'ms-2 d-inline-flex ps-2 pe-2'} key={sel.value} data-value={sel.value}>
|
||||
<span>{sel.label}</span>
|
||||
{
|
||||
!this.props.disabled &&
|
||||
<FontAwesomeIcon icon={'close'} onClick={this.onCloseClick} className={'ms-1'} style={{'cursor': 'pointer'}}/>
|
||||
}
|
||||
</Badge>
|
||||
})
|
||||
return <Badge bg={'dark'} className={'ms-2 d-inline-flex ps-2 pe-2'} key={sel.value} data-value={sel.value}>
|
||||
<span>{sel.label}</span>
|
||||
{
|
||||
!this.props.disabled &&
|
||||
<FontAwesomeIcon icon={'close'} onClick={this.onCloseClick} className={'ms-1'} style={{'cursor': 'pointer'}}/>
|
||||
}
|
||||
</Badge>
|
||||
})
|
||||
}
|
||||
</Button>
|
||||
|
||||
@ -386,11 +398,11 @@ export class DropdownSelectInput extends Component<MultipleSelectInputProps> {
|
||||
}
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
}
|
||||
<FormText
|
||||
children={this.props.value.firstError}
|
||||
className={'text-danger d-block mt-0 mb-0'}/>
|
||||
</div>
|
||||
<FormText
|
||||
children={this.props.value.firstError}
|
||||
className={'text-danger d-block mt-0 mb-0'}/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -449,3 +461,58 @@ export class TableInput<T> extends Component<TableInputProps<T>> {
|
||||
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 {TableDescriptor} from "../../utils/tables";
|
||||
import {observer} from "mobx-react";
|
||||
import {action, computed, makeObservable, observable, runInAction} from "mobx";
|
||||
import {action, computed, makeObservable, observable, reaction, runInAction} from "mobx";
|
||||
import {Button, ButtonGroup, FormSelect, FormText, Table} from "react-bootstrap";
|
||||
import _ from "lodash";
|
||||
import React, {ChangeEvent} from "react";
|
||||
@ -24,6 +24,15 @@ export class DataTable<R> extends ComponentContext<DataTableProps<R> & { classNa
|
||||
constructor(props: DataTableProps<R>) {
|
||||
super(props);
|
||||
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;
|
||||
@ -35,19 +44,6 @@ export class DataTable<R> extends ComponentContext<DataTableProps<R> & { classNa
|
||||
@observable className = this.props.className;
|
||||
@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
|
||||
get isFirstPage() {
|
||||
return this.descriptor.page === 0;
|
||||
@ -90,7 +86,7 @@ export class DataTable<R> extends ComponentContext<DataTableProps<R> & { classNa
|
||||
this.descriptor.pageSize = _.toNumber(e.target.value);
|
||||
}
|
||||
|
||||
// not computed, since we want to show initial data, when no sorts applied
|
||||
@computed
|
||||
get filteredData() {
|
||||
const filters = this.descriptor.filters.filter(filter => filter);
|
||||
return this.descriptor.data.filter(row => ((filters && filters.length) > 0 ? filters.every(filter => filter(row)) : true));
|
||||
@ -193,9 +189,8 @@ export class DataTable<R> extends ComponentContext<DataTableProps<R> & { classNa
|
||||
borderLeft: firstColumn ? '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'}>
|
||||
<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(() => {
|
||||
const other = this.descriptor.columns
|
||||
.filter(c => c.key !== column.key)
|
||||
@ -258,12 +253,10 @@ export class DataTable<R> extends ComponentContext<DataTableProps<R> & { classNa
|
||||
borderRight: lastColumn ? '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>
|
||||
{
|
||||
suffixElement &&
|
||||
<span className={'ms-2'}>{suffixElement}</span>
|
||||
suffixElement && <span className={'ms-2'}>{suffixElement}</span>
|
||||
}
|
||||
</td>
|
||||
})
|
||||
|
||||
294
web/src/components/defence/DayAndOrderChangeModal.tsx
Normal file
294
web/src/components/defence/DayAndOrderChangeModal.tsx
Normal file
@ -0,0 +1,294 @@
|
||||
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>
|
||||
}
|
||||
</>
|
||||
}
|
||||
}
|
||||
498
web/src/components/defence/DefenceEditPage.tsx
Normal file
498
web/src/components/defence/DefenceEditPage.tsx
Normal file
@ -0,0 +1,498 @@
|
||||
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,39 +7,54 @@ import React from "react";
|
||||
import {ThinkService} from "../../services/ThinkService";
|
||||
import {DataTable} from "../data-tables/DataTable";
|
||||
import {Column, TableDescriptor} from "../../utils/tables";
|
||||
import {Defence} from "../../models/defence";
|
||||
import {Defense} from "../../models/defense";
|
||||
import {Participant} from "../../models/participant";
|
||||
import {datetimeConverter} from "../../utils/converters";
|
||||
import {StudentData} from "../../models/studentData";
|
||||
import {Button} from "react-bootstrap";
|
||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
||||
import {DefenseInfoModal} from "./DefenseInfoModal";
|
||||
import {ModalState} from "../../utils/modalState";
|
||||
import _ from "lodash";
|
||||
|
||||
class DefenceListPageState {
|
||||
constructor() {
|
||||
makeObservable(this);
|
||||
this.updateDefences();
|
||||
reaction(() => this.defences, () => {
|
||||
this.tableDescriptor = new TableDescriptor<Defence>([
|
||||
new Column<Defence, Participant[]>('commissionMembers', 'ГЭК', p => p ? p.length : 0),
|
||||
new Column<Defence, Group[]>('groups', 'Группы', g => g && g.length ? g.map(g => g.name).join(', ') : 'Пусто'),
|
||||
new Column<Defence, Group[]>('groups', 'Студентов', g => {
|
||||
if (!g) return 'Пусто';
|
||||
const students: StudentData[] = [];
|
||||
g.forEach(group => group.students.forEach(student => students.push(student)));
|
||||
return students.length;
|
||||
this.tableDescriptor = new TableDescriptor<Defense>([
|
||||
new Column<Defense, number>('id', 'Идентификатор', (v) => v, (defense: Defense) => {
|
||||
return <FontAwesomeIcon icon={'file-pen'} style={{'cursor': 'pointer'}}
|
||||
data-value={defense.id} onClick={this.onIconClicked}/>;
|
||||
}),
|
||||
new Column<Defence, string>('createdAt', 'Дата создания', datetimeConverter),
|
||||
new Column<Defence, string>('updatedAt', 'Дата обновления', datetimeConverter),
|
||||
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 'Пусто';
|
||||
let studLen = 0;
|
||||
g.forEach(group => {
|
||||
studLen += group.students.length;
|
||||
});
|
||||
return studLen ? studLen : 'Пусто';
|
||||
}),
|
||||
new Column<Defense, string>('createdAt', 'Дата создания', datetimeConverter),
|
||||
new Column<Defense, string>('updatedAt', 'Дата обновления', datetimeConverter),
|
||||
], this.defences, true
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@observable defences: Defence[] = [];
|
||||
@observable tableDescriptor: TableDescriptor<Defence>;
|
||||
@observable defences: Defense[] = [];
|
||||
@observable tableDescriptor: TableDescriptor<Defense>;
|
||||
|
||||
@observable selectedDefense: Defense = undefined;
|
||||
|
||||
@observable editDefenseModalState = new ModalState();
|
||||
@observable newDefenseModalState = new ModalState();
|
||||
|
||||
@action.bound
|
||||
updateDefences() {
|
||||
ThinkService.think();
|
||||
get<Defence[]>('/defence/all').then((defences) => {
|
||||
get<Defense[]>('/defense/get-all').then((defences) => {
|
||||
runInAction(() => {
|
||||
this.defences = defences;
|
||||
});
|
||||
@ -47,6 +62,15 @@ class DefenceListPageState {
|
||||
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
|
||||
@ -62,13 +86,27 @@ export class DefenceListPage extends Page {
|
||||
get page() {
|
||||
return <>
|
||||
{
|
||||
<>
|
||||
{
|
||||
this.fields.tableDescriptor &&
|
||||
<DataTable tableDescriptor={this.fields.tableDescriptor} name={'Защиты'} />
|
||||
}
|
||||
</>
|
||||
this.fields.tableDescriptor &&
|
||||
<DataTable tableDescriptor={this.fields.tableDescriptor} name={'Защиты'}
|
||||
additionalButtons={<AdditionalButtons state={this.fields}/>}/>
|
||||
}
|
||||
{
|
||||
this.fields.selectedDefense &&
|
||||
<DefenseInfoModal modalState={this.fields.editDefenseModalState} defense={this.fields.selectedDefense} />
|
||||
}
|
||||
<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>
|
||||
);
|
||||
});
|
||||
291
web/src/components/defence/DefenseInfoModal.tsx
Normal file
291
web/src/components/defence/DefenseInfoModal.tsx
Normal file
@ -0,0 +1,291 @@
|
||||
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>
|
||||
)
|
||||
}
|
||||
}
|
||||
85
web/src/components/dictionary/DiplomaTopicFilterModal.tsx
Normal file
85
web/src/components/dictionary/DiplomaTopicFilterModal.tsx
Normal file
@ -0,0 +1,85 @@
|
||||
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