Compare commits

...

No commits in common. "master" and "feature/groups" have entirely different histories.

133 changed files with 1010 additions and 5633 deletions

View File

@ -52,11 +52,6 @@
<artifactId>postgresql</artifactId> <artifactId>postgresql</artifactId>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.12.2</version>
</dependency>
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
@ -102,15 +97,6 @@
<artifactId>commons-collections4</artifactId> <artifactId>commons-collections4</artifactId>
<version>4.4</version> <version>4.4</version>
</dependency> </dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.17.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -5,29 +5,13 @@ import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.Set; import java.util.List;
@Entity @Entity
@Table(name = "defense") @Table(name = "defense")
@Getter @Getter
@Setter @Setter
public class Defense { public class Defense {
public enum Status {
NOT_STARTED,
TOPIC_PREPARATION,
TOPIC_CHOOSING,
TASK_CREATING,
TASK_ASSIGNING,
PRE_DIPLOMA_PRACTICE,
TOPIC_FINALIZATION,
MAIN_VKR_WORK,
PRE_DEFENSE,
NORMCONTROL_ANTI_PLAGIARISM,
DEFENSE_PREPARATION,
DEFENSE,
FINISHED,
}
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; private Long id;
@ -37,34 +21,20 @@ public class Defense {
name = "defense_commission", name = "defense_commission",
joinColumns = @JoinColumn(name = "defense_id", referencedColumnName = "id"), joinColumns = @JoinColumn(name = "defense_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "commission_member_data_id", referencedColumnName = "id")) inverseJoinColumns = @JoinColumn(name = "commission_member_data_id", referencedColumnName = "id"))
private Set<CommissionMemberData> commissionMembers; private List<CommissionMemberData> commissionMembers;
@Enumerated(EnumType.STRING)
private Status status;
private LocalDate defenseDate; private LocalDate defenseDate;
@OneToMany(mappedBy = "defense") @OneToMany(mappedBy = "defense")
private Set<Group> groups; private List<Group> groups;
@ManyToMany
@JoinTable(
name = "defense_best_student_works",
joinColumns = @JoinColumn(name = "defense_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "student_data_id", referencedColumnName = "id"))
private List<StudentData> bestWorks;
@Embedded @Embedded
private AuditInfo auditInfo; private AuditInfo auditInfo;
@ManyToOne
@JoinColumn(name = "direction_of_preparation_id")
private DirectionOfPreparation directionOfPreparation;
@ManyToOne
@JoinColumn(name = "responsible_for_antiplagiarism_id")
private Participant responsibleForAntiplagiarism;
@ManyToOne
@JoinColumn(name = "responsible_for_normcontrol_id")
private Participant responsibleForNormcontrol;
@Transient
public boolean isStateShouldBeProcessed(Status status) {
return this.status.ordinal() >= status.ordinal();
}
} }

View File

@ -22,10 +22,6 @@ public class DirectionOfPreparation {
@OneToMany(mappedBy = "directionOfPreparation") @OneToMany(mappedBy = "directionOfPreparation")
private List<DiplomaTopic> diplomaTopic; private List<DiplomaTopic> diplomaTopic;
@ManyToOne
@JoinColumn(name = "responsible_id")
private TeacherData responsible;
@Embedded @Embedded
private AuditInfo auditInfo; private AuditInfo auditInfo;
} }

View File

@ -2,7 +2,6 @@ package ru.mskobaro.tdms.business.entity;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.EqualsAndHashCode;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.ToString; import lombok.ToString;
@ -16,7 +15,6 @@ import java.util.List;
@ToString @ToString
@Entity @Entity
@Table(name = "`group`") @Table(name = "`group`")
@EqualsAndHashCode(of = "id")
public class Group { public class Group {
@Id @Id
@Column(name = "id") @Column(name = "id")

View File

@ -1,56 +0,0 @@
package ru.mskobaro.tdms.business.entity;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Entity
@Table(name = "message_template")
@Getter
@Setter
@NoArgsConstructor
public class MessageTemplate {
public enum MessageType {
TOPIC_LIST_PREPARE_START_FOR_TEACHER,
TOPIC_CHOOSE_FOR_STUDENT,
TOPIC_CHOOSE_FOR_TEACHER,
TASK_CREATE_FOR_TEACHER,
TASK_ASSIGN_FOR_TEACHER,
PRE_DIPLOMA_PRACTICE_START_FOR_TEACHER,
PRE_DIPLOMA_PRACTICE_START_FOR_STUDENT,
TOPIC_FINALIZATION_FOR_TEACHER,
PRE_DEFENSE_FOR_STUDENT,
ANTIPLAGIARISM_FOR_STUDENT,
DEFENSE_PREPARATION_FOR_STUDENT,
MAIN_VRK_WORK_START,
NORMCONTROL_AND_ANTIPLAGIARISM,
DEFENSE,
DEFENSE_PREPARATION_FOR_TEACHER,
}
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Enumerated(EnumType.STRING)
private MessageType messageType;
private String subjectTemplate;
private String messageTemplate;
@Embedded
private AuditInfo auditInfo;
}

View File

@ -1,15 +0,0 @@
package ru.mskobaro.tdms.business.entity;
import jakarta.persistence.Entity;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;
@Entity
@Getter
@Setter
public class NormcontrolAndAntiplagiarismTask extends Task {
private Boolean normcontrolPassed;
private Long antiplagiarismPercent;
}

View File

@ -1,14 +0,0 @@
package ru.mskobaro.tdms.business.entity;
import jakarta.persistence.Entity;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;
@Entity
@Getter
@Setter
public class PreDiplomaPracticeTask extends Task {
private Long practiceMark;
}

View File

@ -2,7 +2,6 @@ package ru.mskobaro.tdms.business.entity;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.EqualsAndHashCode;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.ToString; import lombok.ToString;
@ -14,7 +13,6 @@ import ru.mskobaro.tdms.integration.database.TeacherDataRepository;
@ToString(exclude = "group") @ToString(exclude = "group")
@Entity @Entity
@Table(name = "student_data") @Table(name = "student_data")
@EqualsAndHashCode(of = "id")
public class StudentData { public class StudentData {
@Id @Id
@Column(name = "id") @Column(name = "id")
@ -36,33 +34,9 @@ public class StudentData {
private Integer protectionOrder; private Integer protectionOrder;
private Integer protectionDay; private Integer protectionDay;
private Integer markComment;
private Integer markPractice; private Integer markPractice;
@Column(name = "magistracy_wanted")
private Boolean magistracy;
private Boolean electronic;
@Column(name = "oztiv_mark")
private Integer otziv;
@Column(name = "predefnese_mark")
private Integer preDefenseMark;
@Column(name = "normal_control")
private Boolean normcontrol;
@Column(name = "anti_plagiarism")
private Integer antiplagiarism;
@Column(name = "record_book_returned")
private Boolean zachetka;
@Column(name = "work")
private String work;
@Column(name = "vnedreniye")
private Boolean vnedreniye;
@Column(name = "diploma_with_honors")
private Boolean otlichiye;
@ManyToOne @ManyToOne
@JoinColumn(name = "curator_id") @JoinColumn(name = "curator_id")
private TeacherData curator; private TeacherData curator;
@ -71,13 +45,6 @@ public class StudentData {
@JoinColumn(name = "diploma_topic_id") @JoinColumn(name = "diploma_topic_id")
private DiplomaTopic diplomaTopic; private DiplomaTopic diplomaTopic;
@Column(name = "marks_5")
private Long marks5;
@Column(name = "marks_4")
private Long marks4;
@Column(name = "marks_3")
private Long marks3;
@Embedded @Embedded
private AuditInfo auditInfo; private AuditInfo auditInfo;
} }

View File

@ -4,59 +4,38 @@ import jakarta.persistence.*;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.type.SqlTypes;
import ru.mskobaro.tdms.business.taskfields.TaskFields;
@Entity @Entity
@Table(name = "task") @Table(name = "task")
@NoArgsConstructor @NoArgsConstructor
@Getter @Getter
@Setter @Setter
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "task_type", discriminatorType = DiscriminatorType.STRING)
public class Task { public class Task {
public enum Status { public enum Type {
WAIT_FOR_TOPIC_AGREEMENT, DIPLOMA_TOPIC_AGREEMENT,
WAIT_FOR_STUDENT_EDIT,
WAIT_FOR_STUDENT_START,
WAIT_FOR_TOPIC_PREPARATION,
WAIT_FOR_STUDENT_PRE_DIPLOMA_PRACTICE_WORK_DONE,
WAIT_FOR_TEACHER_PRE_DIPLOMA_PRACTICE_MARK_SEND,
DONE,
CANCELED, WAIT_FOR_NORMOCONTROL_PASSED, WAIT_FOR_TEACHER_OTZIV, WAIT_FOR_ANTIPL_PASSED,
} }
public enum Type { public enum Status {
TOPIC_AGREEMENT, WAIT_FOR_TOPIC_AGREEMENT,
TOPIC_PREPARATION, DONE,
TASK_CREATING,
TASK_ASSIGN,
PRE_DIPLOMA_PRACTICE,
TOPIC_FINALIZATION,
MAIN_VKR_WORK,
PRE_DEFENSE,
NORMCONTROL_AND_ANTIPLAGIARISM,
DEFENSE_PREPARATION,
DEFENSE,
} }
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; private Long id;
@Enumerated(EnumType.STRING)
private Status status;
@Enumerated(EnumType.STRING) @Enumerated(EnumType.STRING)
private Type type; private Type type;
@ManyToOne @Enumerated(EnumType.STRING)
@JoinColumn(name = "defense_id") private Status status;
private Defense defense;
@JdbcTypeCode(SqlTypes.JSON)
private TaskFields fields;
@Embedded @Embedded
private AuditInfo auditInfo; private AuditInfo auditInfo;
private Long makerParticId;
private Long checkerParticId;
} }

View File

@ -1,16 +0,0 @@
package ru.mskobaro.tdms.business.entity;
import jakarta.persistence.Entity;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;
@Entity
@Getter
@Setter
public class TopicAgreementTask extends Task {
private Long diplomaTopicId;
private String diplomaTopicName;
private LocalDateTime approvedAt;
}

View File

@ -1,6 +1,6 @@
package ru.mskobaro.tdms.business.exception; package ru.mskobaro.tdms.business.exception;
import ru.mskobaro.tdms.integration.controller.payload.ErrorDTO; import ru.mskobaro.tdms.presentation.controller.payload.ErrorDTO;
public class AccessDeniedException extends BusinessException { public class AccessDeniedException extends BusinessException {
public AccessDeniedException() { public AccessDeniedException() {

View File

@ -1,16 +1,12 @@
package ru.mskobaro.tdms.business.exception; package ru.mskobaro.tdms.business.exception;
import ru.mskobaro.tdms.integration.controller.payload.ErrorDTO; import ru.mskobaro.tdms.presentation.controller.payload.ErrorDTO;
public class BusinessException extends RuntimeException { public class BusinessException extends RuntimeException {
public BusinessException(String message) { public BusinessException(String message) {
super(message); super(message);
} }
public BusinessException(String message, Exception cause) {
super(message, cause);
}
public ErrorDTO.ErrorCode getErrorCode() { public ErrorDTO.ErrorCode getErrorCode() {
return ErrorDTO.ErrorCode.BUSINESS_ERROR; return ErrorDTO.ErrorCode.BUSINESS_ERROR;
} }

View File

@ -1,6 +1,6 @@
package ru.mskobaro.tdms.business.exception; package ru.mskobaro.tdms.business.exception;
import ru.mskobaro.tdms.integration.controller.payload.ErrorDTO; import ru.mskobaro.tdms.presentation.controller.payload.ErrorDTO;
public class NotFoundException extends BusinessException { public class NotFoundException extends BusinessException {
public NotFoundException(Class<?> entityClass, Object id) { public NotFoundException(Class<?> entityClass, Object id) {

View File

@ -0,0 +1,20 @@
package ru.mskobaro.tdms.business.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ru.mskobaro.tdms.integration.database.DefenceRepository;
import ru.mskobaro.tdms.presentation.controller.payload.DefenceDTO;
import java.util.List;
@Service
@Transactional
public class DefenceService {
@Autowired
private DefenceRepository defenceRepository;
public List<DefenceDTO> getAllDefences() {
return defenceRepository.findAll().stream().map(DefenceDTO::from).toList();
}
}

View File

@ -1,347 +0,0 @@
package ru.mskobaro.tdms.business.service;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import org.hibernate.Hibernate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ru.mskobaro.tdms.business.entity.*;
import ru.mskobaro.tdms.business.exception.BusinessException;
import ru.mskobaro.tdms.integration.controller.DefenseController;
import ru.mskobaro.tdms.integration.controller.payload.CommissionMemberDTO;
import ru.mskobaro.tdms.integration.controller.payload.DefenseDTO;
import ru.mskobaro.tdms.integration.controller.payload.GroupDTO;
import ru.mskobaro.tdms.integration.database.*;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@Service
@Transactional
public class DefenseService {
@Autowired
private DefenseRepository defenseRepository;
@Autowired
private CommissionMemberRepository commissionMemberRepository;
@Autowired
private GroupRepository groupRepository;
@PersistenceContext
private EntityManager entityManager;
@Autowired
private TaskService taskService;
@Autowired
private ParticipantRepository participantRepository;
@Autowired
private TeacherDataRepository teacherDataRepository;
@Autowired
private PreparationDirectionRepository preparationDirectionRepository;
public List<Defense> findAll() {
List<Defense> defenses = entityManager.createQuery("select d from Defense d left join fetch d.commissionMembers", Defense.class)
.getResultList();
defenses.forEach(defense -> defense.getGroups().forEach(group -> Hibernate.initialize(group.getStudents())));
return defenses;
}
public Defense findById(Long id) {
return entityManager.createQuery(
"select d from Defense d " +
"left join fetch d.commissionMembers cm " +
"left join fetch cm.participant " +
"left join fetch d.groups g " +
"left join fetch g.students " +
"where d.id = :id "
, Defense.class)
.setParameter("id", id)
.getSingleResult();
}
public void save(DefenseDTO defenseDTO) {
boolean editMode = defenseDTO.getId() != null;
Defense defense;
if (editMode) {
defense = defenseRepository.findByIdThrow(defenseDTO.getId());
} else {
defense = new Defense();
}
List<CommissionMemberData> members = commissionMemberRepository.findAllById(
defenseDTO.getCommissionMembers().stream().map(CommissionMemberDTO::getId).collect(Collectors.toList())
);
defense.setCommissionMembers(new HashSet<>(members));
if (defenseDTO.getResponsibleForNorm() != null && defenseDTO.getResponsibleForNorm().getId() != null) {
Participant norm = participantRepository.findByIdThrow(defenseDTO.getResponsibleForNorm().getId());
defense.setResponsibleForNormcontrol(norm);
}
if (defenseDTO.getResponsibleForAntipl() != null && defenseDTO.getResponsibleForAntipl().getId() != null) {
Participant antipl = participantRepository.findByIdThrow(defenseDTO.getResponsibleForAntipl().getId());
defense.setResponsibleForAntiplagiarism(antipl);
}
if (defenseDTO.getPreparationDirection() != null && defenseDTO.getPreparationDirection().getId() != null) {
DirectionOfPreparation dirOfPrep = preparationDirectionRepository.findByIdThrow(defenseDTO.getPreparationDirection().getId());
defense.setDirectionOfPreparation(dirOfPrep);
}
if (!editMode) {
defense.setStatus(Defense.Status.NOT_STARTED);
}
if (defenseDTO.getDefenseDate() != null) {
defense.setDefenseDate(defenseDTO.getDefenseDate());
}
defense = defenseRepository.save(defense);
List<Group> groups = groupRepository.findAllById(
defenseDTO.getGroups().stream().map(GroupDTO::getId).collect(Collectors.toList()));
for (Group g : groups) {
g.setDefense(defense);
}
}
public void handleNextStateRequest(Long id) {
Defense defense = defenseRepository.findByIdThrow(id);
toNextState(defense);
processState(defense, null);
}
private void processState(Defense defense, Defense.Status status) {
List<StudentData> students = defense.getGroups().stream()
.flatMap(g -> g.getStudents().stream())
.toList();
List<TeacherData> curators = students.stream()
.map(StudentData::getCurator)
.toList();
if (status == null) {
status = defense.getStatus();
}
if (status == Defense.Status.TOPIC_PREPARATION) {
List<TeacherData> all = teacherDataRepository.findAll();
taskService.checkAndCreateTopicPreparationTasksAndSendEmail(all, defense);
} else if (status == Defense.Status.TOPIC_CHOOSING) {
taskService.checkAndCreateTopicChoosingTasksAndSendEmail(students, defense);
} else if (status == Defense.Status.TASK_CREATING) {
taskService.checkAndCreateTaskCreatingTask(curators, defense);
} else if (status == Defense.Status.TASK_ASSIGNING) {
taskService.checkAndCreateTaskAssignTasks(curators, defense);
} else if (status == Defense.Status.PRE_DIPLOMA_PRACTICE) {
taskService.checkAndCreatePreDiplomaPracticeTask(students, defense);
} else if (status == Defense.Status.TOPIC_FINALIZATION) {
taskService.checkAndCreateTopicFinalizationTask(defense, curators);
} else if (status == Defense.Status.MAIN_VKR_WORK) {
taskService.checkAndCreateMainVkrWorkTask(defense, students);
} else if (status == Defense.Status.PRE_DEFENSE) {
taskService.checkAndCreatePreDefenseTask(defense, students);
} else if (status == Defense.Status.NORMCONTROL_ANTI_PLAGIARISM) {
taskService.checkAndCreateNormcontrolAndAntiplagiarismTask(defense, students);
} else if (status == Defense.Status.DEFENSE_PREPARATION)
taskService.checkAndCreateDefensePreparationTasks(defense, students);
else if (status == Defense.Status.DEFENSE) {
taskService.checkAndCreateDefenseTask(defense, students);
} else if (status == Defense.Status.FINISHED) {
taskService.clearAllTasksWithDefense(defense);
}
}
private void toNextState(Defense defense) {
switch (defense.getStatus()) {
case NOT_STARTED ->
defense.setStatus(Defense.Status.TOPIC_PREPARATION);
case TOPIC_PREPARATION ->
defense.setStatus(Defense.Status.TOPIC_CHOOSING);
case TOPIC_CHOOSING ->
defense.setStatus(Defense.Status.TASK_CREATING);
case TASK_CREATING ->
defense.setStatus(Defense.Status.TASK_ASSIGNING);
case TASK_ASSIGNING ->
defense.setStatus(Defense.Status.PRE_DIPLOMA_PRACTICE);
case PRE_DIPLOMA_PRACTICE ->
defense.setStatus(Defense.Status.TOPIC_FINALIZATION);
case TOPIC_FINALIZATION ->
defense.setStatus(Defense.Status.MAIN_VKR_WORK);
case MAIN_VKR_WORK ->
defense.setStatus(Defense.Status.PRE_DEFENSE);
case PRE_DEFENSE ->
defense.setStatus(Defense.Status.NORMCONTROL_ANTI_PLAGIARISM);
case NORMCONTROL_ANTI_PLAGIARISM ->
defense.setStatus(Defense.Status.DEFENSE_PREPARATION);
case DEFENSE_PREPARATION ->
defense.setStatus(Defense.Status.DEFENSE);
case DEFENSE ->
defense.setStatus(Defense.Status.FINISHED);
case FINISHED ->
throw new BusinessException("Защита окончена");
}
}
public DefenseController.DefenseTableData tableDataByDefenseId(Long defenseId) {
List<StudentData> allDefenseStudents = entityManager.createQuery("""
select sd from StudentData sd
where sd.group.defense.id = :defenseId
""", StudentData.class
).setParameter("defenseId", defenseId)
.getResultList();
List<DefenseController.DefenseTableDataGroup> groupsData = new ArrayList<>();
for (StudentData student : allDefenseStudents) {
DefenseController.DefenseTableDataGroup groupData = new DefenseController.DefenseTableDataGroup();
groupData.setGroupId(student.getGroup().getId());
groupData.setGroupName(student.getGroup().getName());
groupData.setStudId(student.getId());
groupData.setFio(student.getParticipant().getFullName());
if (student.getMarkPractice() != null) {
groupData.setPdpMark(student.getMarkPractice());
}
if (student.getDiplomaTopic() != null) {
groupData.setTopic(student.getDiplomaTopic().getName());
}
if (student.getCurator() != null) {
groupData.setTeacherFio(student.getCurator().getParticipant().getFullName());
}
if (student.getProtectionDay() != null) {
groupData.setDayOfProt(student.getProtectionDay());
}
if (student.getProtectionDay() != null) {
groupData.setPlaceOfProt(student.getProtectionOrder());
}
groupData.setMagistracy(student.getMagistracy());
groupData.setElectronic(student.getElectronic());
groupData.setOtziv(student.getOtziv());
groupData.setDpedefenseMark(student.getPreDefenseMark());
groupData.setNormcontrol(student.getNormcontrol());
groupData.setAntipl(student.getAntiplagiarism());
groupData.setZachetka(student.getZachetka());
groupData.setWork(student.getWork());
groupData.setVnedreniye(student.getVnedreniye());
groupData.setOtlichiye(student.getOtlichiye());
groupsData.add(groupData);
}
DefenseController.DefenseTableData dto = new DefenseController.DefenseTableData();
dto.setDefenseId(defenseId);
dto.setGroups(groupsData);
return dto;
}
public void tableDataSave(DefenseController.DefenseTableData defenseTableData) {
List<DefenseController.DefenseTableDataGroup> groups = defenseTableData.getGroups();
for (DefenseController.DefenseTableDataGroup groupData : groups) {
StudentData student = entityManager.createQuery("""
select sd from StudentData sd
where sd.group.defense.id = :defenseId
and sd.id = :id
""", StudentData.class
).setParameter("defenseId", defenseTableData.getDefenseId())
.setParameter("id", groupData.getStudId())
.getSingleResult();
if (groupData.getPdpMark() != null) {
student.setMarkPractice(groupData.getPdpMark());
}
if (groupData.getMagistracy() != null) {
student.setMagistracy(groupData.getMagistracy());
}
if (groupData.getElectronic() != null) {
student.setElectronic(groupData.getElectronic());
}
if (groupData.getOtziv() != null) {
student.setOtziv(groupData.getOtziv());
}
if (groupData.getDpedefenseMark() != null) {
student.setPreDefenseMark(groupData.getDpedefenseMark());
}
if (groupData.getZachetka() != null) {
student.setZachetka(groupData.getZachetka());
}
if (groupData.getWork() != null) {
student.setWork(groupData.getWork());
}
if (groupData.getVnedreniye() != null) {
student.setVnedreniye(groupData.getVnedreniye());
}
if (groupData.getOtlichiye() != null) {
student.setOtlichiye(groupData.getOtlichiye());
}
}
}
public void recreateProtectionOrder(Long defenseId) {
Defense defense = defenseRepository.findByIdThrow(defenseId);
List<StudentData> students = defense.getGroups().stream()
.map(Group::getStudents)
.flatMap(List::stream)
.sorted(Comparator.comparing(student -> {
if (student.getCurator() != null && student.getCurator().getParticipant() != null)
return student.getCurator().getParticipant().getFullName();
return null;
}, Comparator.nullsLast(Comparator.naturalOrder())
))
.toList();
int maxInDay = 16;
int size = students.size();
for (int i = 1; i < 10; i++) {
int inDay = size / i;
if (inDay <= maxInDay) {
maxInDay = inDay;
break;
}
}
int currentDay = 1;
int currentOrder = 1;
for (StudentData student : students) {
if (currentOrder > maxInDay) {
currentOrder = 1;
currentDay += 1;
}
student.setProtectionDay(currentDay);
student.setProtectionOrder(currentOrder++);
}
}
public void updateProtOrder(DefenseController.ProtOrDTO dto) {
Defense defense = defenseRepository.findByIdThrow(dto.getDefenseId());
Map<Long, StudentData> studentsById = defense.getGroups().stream()
.map(Group::getStudents)
.flatMap(Collection::stream)
.collect(Collectors.toMap(StudentData::getId, Function.identity()));
dto.getDays().forEach(day -> day.getStuds().forEach(student -> {
StudentData studentData = studentsById.get(student.getId());
if (studentData != null) {
studentData.setProtectionDay(day.getNumber());
studentData.setProtectionOrder(student.getOrder() + 1);
}
}));
dto.getUnassigned().forEach(unassigned -> {
StudentData studentData = studentsById.get(unassigned.getId());
if (studentData != null) {
studentData.setProtectionDay(null);
studentData.setProtectionOrder(null);
}
});
}
}

View File

@ -1,7 +1,5 @@
package ru.mskobaro.tdms.business.service; package ru.mskobaro.tdms.business.service;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.transaction.Transactional; import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -11,7 +9,7 @@ import ru.mskobaro.tdms.business.entity.TeacherData;
import ru.mskobaro.tdms.integration.database.DiplomaTopicRepository; import ru.mskobaro.tdms.integration.database.DiplomaTopicRepository;
import ru.mskobaro.tdms.integration.database.PreparationDirectionRepository; import ru.mskobaro.tdms.integration.database.PreparationDirectionRepository;
import ru.mskobaro.tdms.integration.database.TeacherDataRepository; import ru.mskobaro.tdms.integration.database.TeacherDataRepository;
import ru.mskobaro.tdms.integration.controller.payload.DiplomaTopicDTO; import ru.mskobaro.tdms.presentation.controller.payload.DiplomaTopicDTO;
import java.util.List; import java.util.List;
@ -24,8 +22,6 @@ public class DiplomaTopicService {
private TeacherDataRepository teacherDataRepository; private TeacherDataRepository teacherDataRepository;
@Autowired @Autowired
private PreparationDirectionRepository preparationDirectionRepository; private PreparationDirectionRepository preparationDirectionRepository;
@PersistenceContext
private EntityManager entityManager;
public List<DiplomaTopic> findAll() { public List<DiplomaTopic> findAll() {
return diplomaTopicRepository.findAll(); return diplomaTopicRepository.findAll();
@ -53,16 +49,7 @@ public class DiplomaTopicService {
diplomaTopicRepository.save(diplomaTopic); diplomaTopicRepository.save(diplomaTopic);
} }
public List<DiplomaTopic> findAllForStudentByParticId(Long particId) { public List<DiplomaTopic> findAllForStudent(Long studentId) {
return diplomaTopicRepository.findAllForStudentByParticId(particId); return diplomaTopicRepository.findAllForStudentId(studentId);
}
public List<DiplomaTopic> findByTeacherParticIdAndDirPrep(Long particId, Long dirPrepId) {
return entityManager.createQuery(
"select dt from DiplomaTopic dt where dt.directionOfPreparation.id = :dirPrepId and dt.teacher.participant.id = :particId",
DiplomaTopic.class
).setParameter("dirPrepId", dirPrepId)
.setParameter("particId", particId)
.getResultList();
} }
} }

View File

@ -1,272 +0,0 @@
package ru.mskobaro.tdms.business.service;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.data.*;
import com.deepoove.poi.data.style.CellStyle;
import com.deepoove.poi.data.style.ParagraphStyle;
import com.deepoove.poi.data.style.Style;
import com.deepoove.poi.data.style.TableStyle;
import com.deepoove.poi.util.UnitUtils;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ru.mskobaro.tdms.business.entity.*;
import ru.mskobaro.tdms.business.exception.BusinessException;
import ru.mskobaro.tdms.integration.database.DefenseRepository;
import java.io.ByteArrayOutputStream;
import java.time.LocalDate;
import java.util.*;
@Service
@Transactional
public class DocumentsService {
@Autowired
private DefenseRepository defenseRepository;
@PersistenceContext
private EntityManager entityManager;
public byte[] getQuestionsDocument(Long defenseId, String studyForm) {
@Getter
@Setter
class Data {
String day;
String month;
String year;
String studFio;
String prepDir;
String form;
String gekFio;
}
List<Data> data = new ArrayList<>();
Defense defense = defenseRepository.findByIdThrow(defenseId);
LocalDate defenseDate = defense.getDefenseDate();
String defDay;
String defMonth;
String defYear;
if (defenseDate != null) {
defDay = Integer.toString(defenseDate.getDayOfMonth());
defMonth = Integer.toString(defenseDate.getMonthValue());
defYear = Integer.toString(defenseDate.getYear() - 2000);
} else {
defDay = "";
defMonth = "";
defYear = "";
}
List<Participant> gek = defense.getCommissionMembers().stream().map(CommissionMemberData::getParticipant).toList();
List<StudentData> students = defense.getGroups().stream().map(Group::getStudents).flatMap(List::stream).toList();
for (StudentData stud : students) {
String day = null;
String month = null;
if (StringUtils.isNotBlank(defDay) && stud.getProtectionDay() != null) {
day = Integer.toString(Integer.parseInt(defDay) + stud.getProtectionDay() - 1);
}
if (StringUtils.isNotBlank(defMonth)) {
month = getMonthNameByValue(Integer.parseInt(defMonth));
}
for (Participant g : gek) {
Data d = new Data();
d.day = day;
d.month = month;
d.year = defYear;
d.studFio = stud.getParticipant().getShortName();
d.prepDir = stud.getGroup().getDirectionOfPreparation().getCode();
d.form = studyForm;
d.gekFio = g.getFullName();
data.add(d);
}
}
return renderFileWith(Map.of("data", data), "doc_templates/questions_template.docx");
}
public byte[] getTopicList(Long id) {
Defense defense = defenseRepository.findByIdThrow(id);
DirectionOfPreparation prep = defense.getDirectionOfPreparation();
List<DiplomaTopic> topics = entityManager.createQuery("select dt from DiplomaTopic dt where dt.directionOfPreparation.id = :id", DiplomaTopic.class)
.setParameter("id", prep.getId())
.getResultList();
String prepCode = prep.getCode();
String prepName = prep.getName();
NumberingRenderData diplomaTopics = new NumberingRenderData(
NumberingFormat.DECIMAL,
topics.stream()
.map(DiplomaTopic::getName)
.map(n -> n + ".")
.map(n -> {
ParagraphRenderData paragraphRenderData = new ParagraphRenderData();
paragraphRenderData.setContents(Collections.singletonList(new TextRenderData(n)));
return paragraphRenderData;
}).toList()
);
return renderFileWith(Map.of(
"prep_code", prepCode,
"prep_name", prepName,
"diploma_topics", diplomaTopics
), "doc_templates/diploma_topic_list_template.docx");
}
public byte[] getStudList(Long id, String stepName) {
Defense defense = defenseRepository.findByIdThrow(id);
Map<Integer, List<StudentData>> studentByProtDay = new HashMap<>();
defense.getGroups().stream().map(Group::getStudents).flatMap(List::stream).forEach(student -> {
Integer protectionDay = student.getProtectionDay();
List<StudentData> array = studentByProtDay.computeIfAbsent(protectionDay, k -> new ArrayList<>());
array.add(student);
});
List<ProtDay> days = new ArrayList<>();
LocalDate defenseDate = defense.getDefenseDate();
int dayOfMonth = defenseDate.getDayOfMonth();
int month = defenseDate.getMonthValue();
int year = defenseDate.getYear();
DirectionOfPreparation directionOfPreparation = defense.getDirectionOfPreparation();
String prepCode = directionOfPreparation.getCode();
String prepName = directionOfPreparation.getName();
for (Map.Entry<Integer, List<StudentData>> entry : studentByProtDay.entrySet()) {
if (entry.getKey() == null) continue;
int protDay = entry.getKey() + dayOfMonth - 1;
ProtDay day = new ProtDay();
day.setDay(Integer.toString(protDay));
day.setMonth(getMonthNameByValue(month));
day.setYear(Integer.toString(year));
day.setStepName(stepName);
day.setPrepCode(prepCode);
day.setPrepName(prepName);
makeTable(day, entry);
days.add(day);
}
return renderFileWith(Map.of("prot_day", days), "doc_templates/student_list_template.docx");
}
private void makeTable(ProtDay day, Map.Entry<Integer, List<StudentData>> entry) {
TableStyle tableStyle = new TableStyle();
tableStyle.setWidth("100%");
tableStyle.setColWidths(new int[]{
UnitUtils.cm2Twips(0.8), UnitUtils.cm2Twips(4.7), UnitUtils.cm2Twips(3.25), UnitUtils.cm2Twips(9.5),
UnitUtils.cm2Twips(1.75), UnitUtils.cm2Twips(2d), UnitUtils.cm2Twips(1d), UnitUtils.cm2Twips(1.5),
UnitUtils.cm2Twips(1.25), UnitUtils.cm2Twips(1.25), UnitUtils.cm2Twips(1.50)
});
List<RowRenderData> rows = new ArrayList<>();
rows.add(Rows.of(
"", "ФИО\nстудента", "ФИО\nруководителя", "Тема", "Оценок\n5/4/3", "Коммен-\арий",
"Оц. рук.", "Оц. чл. ГЭК", "ИТОГ", "Дипл. с отл.", "Реком. магист."
).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();
}
}

View File

@ -1,178 +0,0 @@
package ru.mskobaro.tdms.business.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import ru.mskobaro.tdms.business.entity.MessageTemplate;
import ru.mskobaro.tdms.business.entity.StudentData;
import ru.mskobaro.tdms.business.entity.TeacherData;
import ru.mskobaro.tdms.integration.database.MessageTemplateRepository;
@Service
public class EmailService {
@Autowired
private JavaMailSender mailSender;
@Autowired
private MessageTemplateRepository messageTemplateRepository;
@Value("${application.smtp.message-from}")
private String from;
public void sendEmail(String to, String subject, String text) {
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(from);
message.setTo(to);
message.setSubject(subject);
message.setText(text);
mailSender.send(message);
}
public void sendTopicPreparationStartMessage(TeacherData curator) {
MessageTemplate messageTemplate = messageTemplateRepository.findByMessageType(
MessageTemplate.MessageType.TOPIC_LIST_PREPARE_START_FOR_TEACHER
);
String message = messageTemplate.getMessageTemplate();
String subject = messageTemplate.getSubjectTemplate();
message = message.replaceAll("\\$\\$\\{ФИО_НАУЧ_РУК}", curator.getParticipant().getFullName());
subject = subject.replaceAll("\\$\\$\\{ФИО_НАУЧ_РУК}", curator.getParticipant().getFullName());
sendEmail(curator.getParticipant().getEmail(), subject, message);
}
public void sendTopicChoosingStartMessage(TeacherData curator, StudentData student) {
MessageTemplate messageTemplate = messageTemplateRepository.findByMessageType(
MessageTemplate.MessageType.TOPIC_CHOOSE_FOR_TEACHER
);
String message = messageTemplate.getMessageTemplate();
String subject = messageTemplate.getSubjectTemplate();
message = message.replaceAll("\\$\\$\\{ФИО_НАУЧ_РУК}", curator.getParticipant().getFullName());
subject = subject.replaceAll("\\$\\$\\{ФИО_НАУЧ_РУК}", curator.getParticipant().getFullName());
sendEmail(curator.getParticipant().getEmail(), subject, message);
messageTemplate = messageTemplateRepository.findByMessageType(
MessageTemplate.MessageType.TOPIC_CHOOSE_FOR_STUDENT
);
message = messageTemplate.getMessageTemplate();
subject = messageTemplate.getSubjectTemplate();
message = message.replaceAll("\\$\\$\\{ФИО_СТУД}", student.getParticipant().getFullName());
subject = subject.replaceAll("\\$\\$\\{ФИО_СТУД}", student.getParticipant().getFullName());
sendEmail(student.getParticipant().getEmail(), subject, message);
}
public void sendTaskCreatingMessage(TeacherData curator) {
MessageTemplate messageTemplate = messageTemplateRepository.findByMessageType(
MessageTemplate.MessageType.TASK_CREATE_FOR_TEACHER
);
String message = messageTemplate.getMessageTemplate();
String subject = messageTemplate.getSubjectTemplate();
message = message.replaceAll("\\$\\$\\{ФИО_НАУЧ_РУК}", curator.getParticipant().getFullName());
subject = subject.replaceAll("\\$\\$\\{ФИО_НАУЧ_РУК}", curator.getParticipant().getFullName());
sendEmail(curator.getParticipant().getEmail(), subject, message);
}
public void sendTaskAssigningMessage(TeacherData curator) {
MessageTemplate messageTemplate = messageTemplateRepository.findByMessageType(
MessageTemplate.MessageType.TASK_ASSIGN_FOR_TEACHER
);
String message = messageTemplate.getMessageTemplate();
String subject = messageTemplate.getSubjectTemplate();
message = message.replaceAll("\\$\\$\\{ФИО_НАУЧ_РУК}", curator.getParticipant().getFullName());
subject = subject.replaceAll("\\$\\$\\{ФИО_НАУЧ_РУК}", curator.getParticipant().getFullName());
sendEmail(curator.getParticipant().getEmail(), subject, message);
}
public void sendPreDiplomaPracticeMessage(TeacherData curator, StudentData student) {
MessageTemplate messageTemplate = messageTemplateRepository.findByMessageType(
MessageTemplate.MessageType.PRE_DIPLOMA_PRACTICE_START_FOR_TEACHER
);
String message = messageTemplate.getMessageTemplate();
String subject = messageTemplate.getSubjectTemplate();
message = message.replaceAll("\\$\\$\\{ФИО_НАУЧ_РУК}", curator.getParticipant().getFullName());
subject = subject.replaceAll("\\$\\$\\{ФИО_НАУЧ_РУК}", curator.getParticipant().getFullName());
sendEmail(curator.getParticipant().getEmail(), subject, message);
messageTemplate = messageTemplateRepository.findByMessageType(
MessageTemplate.MessageType.PRE_DIPLOMA_PRACTICE_START_FOR_STUDENT
);
message = messageTemplate.getMessageTemplate();
subject = messageTemplate.getSubjectTemplate();
message = message.replaceAll("\\$\\$\\{ФИО_СТУД}", student.getParticipant().getFullName());
subject = subject.replaceAll("\\$\\$\\{ФИО_СТУД}", student.getParticipant().getFullName());
sendEmail(student.getParticipant().getEmail(), subject, message);
}
public void sendTopicFinalizationMessage(TeacherData curator) {
MessageTemplate messageTemplate = messageTemplateRepository.findByMessageType(
MessageTemplate.MessageType.TOPIC_FINALIZATION_FOR_TEACHER
);
String message = messageTemplate.getMessageTemplate();
String subject = messageTemplate.getSubjectTemplate();
message = message.replaceAll("\\$\\$\\{ФИО_НАУЧ_РУК}", curator.getParticipant().getFullName());
subject = subject.replaceAll("\\$\\$\\{ФИО_НАУЧ_РУК}", curator.getParticipant().getFullName());
sendEmail(curator.getParticipant().getEmail(), subject, message);
}
public void sendMainVrkWorkMessage(StudentData student) {
MessageTemplate messageTemplate = messageTemplateRepository.findByMessageType(
MessageTemplate.MessageType.MAIN_VRK_WORK_START
);
String message = messageTemplate.getMessageTemplate();
String subject = messageTemplate.getSubjectTemplate();
message = message.replaceAll("\\$\\$\\{ФИО_СТУД}", student.getParticipant().getFullName());
subject = subject.replaceAll("\\$\\$\\{ФИО_СТУД}", student.getParticipant().getFullName());
sendEmail(student.getParticipant().getEmail(), subject, message);
}
public void sendPreDefenseStartMessage(StudentData student) {
MessageTemplate messageTemplate = messageTemplateRepository.findByMessageType(
MessageTemplate.MessageType.PRE_DEFENSE_FOR_STUDENT
);
String message = messageTemplate.getMessageTemplate();
String subject = messageTemplate.getSubjectTemplate();
message = message.replaceAll("\\$\\$\\{ФИО_СТУД}", student.getParticipant().getFullName());
subject = subject.replaceAll("\\$\\$\\{ФИО_СТУД}", student.getParticipant().getFullName());
sendEmail(student.getParticipant().getEmail(), subject, message);
}
public void sendNormcontrolAndAntiplagiarismMessage(StudentData student) {
MessageTemplate messageTemplate = messageTemplateRepository.findByMessageType(
MessageTemplate.MessageType.NORMCONTROL_AND_ANTIPLAGIARISM
);
String message = messageTemplate.getMessageTemplate();
String subject = messageTemplate.getSubjectTemplate();
message = message.replaceAll("\\$\\$\\{ФИО_СТУД}", student.getParticipant().getFullName());
subject = subject.replaceAll("\\$\\$\\{ФИО_СТУД}", student.getParticipant().getFullName());
sendEmail(student.getParticipant().getEmail(), subject, message);
}
public void sendDefensePreparationMessage(StudentData student) {
MessageTemplate messageTemplate = messageTemplateRepository.findByMessageType(MessageTemplate.MessageType.DEFENSE_PREPARATION_FOR_STUDENT);
String message = messageTemplate.getMessageTemplate();
String subject = messageTemplate.getSubjectTemplate();
message = message.replaceAll("\\$\\$\\{ФИО_СТУД}", student.getParticipant().getFullName());
subject = subject.replaceAll("\\$\\$\\{ФИО_СТУД}", student.getParticipant().getFullName());
sendEmail(student.getParticipant().getEmail(), subject, message);
messageTemplate = messageTemplateRepository.findByMessageType(MessageTemplate.MessageType.DEFENSE_PREPARATION_FOR_TEACHER);
message = messageTemplate.getMessageTemplate();
subject = messageTemplate.getSubjectTemplate();
message = message.replaceAll("\\$\\$\\{ФИО_НАУЧ_РУК}", student.getCurator().getParticipant().getFullName());
subject = subject.replaceAll("\\$\\$\\{ФИО_НАУЧ_РУК}", student.getCurator().getParticipant().getFullName());
sendEmail(student.getCurator().getParticipant().getEmail(), subject, message);
}
public void sendDefenseMessage(StudentData student) {
MessageTemplate messageTemplate = messageTemplateRepository.findByMessageType(
MessageTemplate.MessageType.DEFENSE
);
String message = messageTemplate.getMessageTemplate();
String subject = messageTemplate.getSubjectTemplate();
message = message.replaceAll("\\$\\$\\{ФИО_СТУД}", student.getParticipant().getFullName());
subject = subject.replaceAll("\\$\\$\\{ФИО_СТУД}", student.getParticipant().getFullName());
sendEmail(student.getParticipant().getEmail(), subject, message);
}
}

View File

@ -13,8 +13,8 @@ import ru.mskobaro.tdms.business.exception.BusinessException;
import ru.mskobaro.tdms.integration.database.GroupRepository; import ru.mskobaro.tdms.integration.database.GroupRepository;
import ru.mskobaro.tdms.integration.database.PreparationDirectionRepository; import ru.mskobaro.tdms.integration.database.PreparationDirectionRepository;
import ru.mskobaro.tdms.integration.database.StudentDataRepository; import ru.mskobaro.tdms.integration.database.StudentDataRepository;
import ru.mskobaro.tdms.integration.controller.payload.GroupDTO; import ru.mskobaro.tdms.presentation.controller.payload.GroupDTO;
import ru.mskobaro.tdms.integration.controller.payload.StudentDataDTO; import ru.mskobaro.tdms.presentation.controller.payload.StudentDataDTO;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;

View File

@ -1,59 +0,0 @@
package ru.mskobaro.tdms.business.service;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import org.springframework.stereotype.Service;
import ru.mskobaro.tdms.business.entity.Defense;
import ru.mskobaro.tdms.business.entity.Group;
import ru.mskobaro.tdms.integration.controller.HomeInfoController;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class HomeInfoService {
@PersistenceContext
private EntityManager entityManager;
public HomeInfoController.DefaultInfo defaultInfo() {
HomeInfoController.DefaultInfo defaultInfo = new HomeInfoController.DefaultInfo();
Long userCount = entityManager
.createQuery("select count(*) from User u", Long.class)
.getSingleResult();
Long particCount = entityManager
.createQuery("select count(*) from Participant u", Long.class)
.getSingleResult();
defaultInfo.setParticCount(particCount);
defaultInfo.setUserCount(userCount);
Long teacherCount = entityManager
.createQuery("select count(*) from TeacherData td", Long.class)
.getSingleResult();
Long studentCount = entityManager
.createQuery("select count(*) from StudentData sd", Long.class)
.getSingleResult();
defaultInfo.setTeacherCount(teacherCount);
defaultInfo.setStudentCount(studentCount);
Long defenseCount = entityManager
.createQuery("select count(*) from Defense d", Long.class)
.getSingleResult();
defaultInfo.setDefenseCount(defenseCount);
Long currentDefenseCount = entityManager
.createQuery("select count(*) from Defense d where d.status not in :statuses", Long.class)
.setParameter("statuses", List.of(Defense.Status.FINISHED, Defense.Status.NOT_STARTED))
.getSingleResult();
defaultInfo.setCurrentDefenseCount(currentDefenseCount);
List<Group> currentDefenseGroups = entityManager
.createQuery("select d.groups from Defense d where d.status not in :statuses", Group.class)
.setParameter("statuses", List.of(Defense.Status.FINISHED, Defense.Status.NOT_STARTED))
.getResultList();
String currentDefenseGroupNames = currentDefenseGroups.stream().map(Group::getName).collect(Collectors.joining(", "));
defaultInfo.setCurrentDefenseGroupNames(currentDefenseGroupNames);
return defaultInfo;
}
}

View File

@ -1,11 +1,9 @@
package ru.mskobaro.tdms.business.service; package ru.mskobaro.tdms.business.service;
import jakarta.persistence.EntityManager; import io.micrometer.common.util.StringUtils;
import jakarta.persistence.PersistenceContext;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils; import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -13,8 +11,8 @@ import org.springframework.transaction.annotation.Transactional;
import ru.mskobaro.tdms.business.entity.*; import ru.mskobaro.tdms.business.entity.*;
import ru.mskobaro.tdms.business.exception.AccessDeniedException; import ru.mskobaro.tdms.business.exception.AccessDeniedException;
import ru.mskobaro.tdms.business.exception.BusinessException; import ru.mskobaro.tdms.business.exception.BusinessException;
import ru.mskobaro.tdms.integration.controller.payload.ParticipantSaveDTO;
import ru.mskobaro.tdms.integration.database.*; import ru.mskobaro.tdms.integration.database.*;
import ru.mskobaro.tdms.presentation.controller.payload.ParticipantSaveDTO;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -43,18 +41,6 @@ public class ParticipantService {
private AuthenticationService authenticationService; private AuthenticationService authenticationService;
@Autowired @Autowired
private TeacherDataRepository teacherDataRepository; private TeacherDataRepository teacherDataRepository;
@Autowired
private CommissionMemberRepository commissionMemberRepository;
@PersistenceContext
private EntityManager entityManager;
@Autowired
private EmailService emailService;
@Autowired
private TaskService taskService;
@Autowired
private DefenseRepository defenseRepository;
@Autowired
private DefenseService defenseService;
public ParticipantService(ParticipantRepository participantRepository) { public ParticipantService(ParticipantRepository participantRepository) {
this.participantRepository = participantRepository; this.participantRepository = participantRepository;
@ -82,72 +68,30 @@ public class ParticipantService {
participant.setFirstName(participantSaveDTO.getFirstName()); participant.setFirstName(participantSaveDTO.getFirstName());
participant.setLastName(participantSaveDTO.getLastName()); participant.setLastName(participantSaveDTO.getLastName());
participant.setMiddleName(participantSaveDTO.getMiddleName()); participant.setMiddleName(participantSaveDTO.getMiddleName());
if (!editMode
|| (!StringUtils.equals(participantSaveDTO.getEmail(), existingParticipant.getEmail())
|| !StringUtils.equals(participantSaveDTO.getNumberPhone(), existingParticipant.getNumberPhone()))) {
if (participantRepository.existsByNumberPhoneOrEmail(participantSaveDTO.getNumberPhone(), participantSaveDTO.getEmail())) {
throw new BusinessException("Номер телефона или Электронная почта уже используются");
}
}
participant.setNumberPhone(participantSaveDTO.getNumberPhone()); participant.setNumberPhone(participantSaveDTO.getNumberPhone());
participant.setEmail(participantSaveDTO.getEmail()); participant.setEmail(participantSaveDTO.getEmail());
List<Role> roles = persistRoles(participantSaveDTO, existingParticipant, editMode, callerUser, participant); List<Role> roles = persistRoles(participantSaveDTO, existingParticipant, editMode, callerUser, participant);
StudentData studentData = persistStudentData(participantSaveDTO, existingParticipant, editMode, roles, participant); boolean credentialsChanged = persistUserData(participantSaveDTO, existingParticipant, editMode, participant);
persistStudentData(participantSaveDTO, existingParticipant, editMode, roles, participant);
persistTeacherData(participantSaveDTO, existingParticipant, editMode, roles, participant); persistTeacherData(participantSaveDTO, existingParticipant, editMode, roles, participant);
persistCommissionData(participantSaveDTO, existingParticipant, editMode, roles, participant);
// TODO: notification task
Participant saved = participantRepository.save(participant); Participant saved = participantRepository.save(participant);
log.info("Participant saved: {}", saved.getFullName());
boolean credentialsChanged = persistUserData(participantSaveDTO, saved, editMode, participant);
if (credentialsChanged) { if (credentialsChanged) {
log.info("User {} changed credentials, logging out", saved.getUser().getUsername()); log.info("User {} changed credentials, logging out", saved.getUser().getUsername());
authenticationService.logout(saved.getUser().getUsername()); authenticationService.logout(saved.getUser().getUsername());
} }
if (!editMode && participantSaveDTO.getUserData() != null) {
emailService.sendEmail(saved.getEmail(), "Вам была создана учетная запись в системе поддержки ВКР", """
Уважаемый, %s,
Вам была создана учетная запись в системе подготовки и защиты ВКР.
Ниже представлены данные для входа в систему:
Логин: %s
Пароль: %s
С уважением, администрация.
""".formatted(participant.getFullName(), participant.getUser().getUsername(), participantSaveDTO.getUserData().getPassword()));
}
if (studentData != null) {
studentData.setParticipant(saved);
}
if (studentData != null && studentData.getGroup() != null) {
List<Defense> defenses = entityManager.createQuery("select distinct d from Defense d inner join fetch d.groups g where g.id = :id", Defense.class)
.setParameter("id", studentData.getGroup().getId())
.getResultList();
Defense defense = null;
if (defenses != null && !defenses.isEmpty()) {
defense = defenses.get(0);
}
if (defense != null && defense.isStateShouldBeProcessed(Defense.Status.TOPIC_CHOOSING)) {
taskService.checkAndCreateTopicChoosingTasksAndSendEmail(Collections.singletonList(studentData), defense);
}
}
log.info("Participant saved: {}", saved.getFullName());
} }
private List<Role> persistRoles(ParticipantSaveDTO participantSaveDTO, Participant existingParticipant, boolean editMode, User callerUser, Participant participant) { private List<Role> persistRoles(ParticipantSaveDTO participantSaveDTO, Participant existingParticipant, boolean editMode, User callerUser, Participant participant) {
boolean isAdmin = roleService.isParticInAuthority(callerUser.getParticipant(), RoleService.Authority.ADMIN); boolean isAdmin = roleService.isParticInAuthority(callerUser.getParticipant(), RoleService.Authority.ADMIN);
boolean isSecretary = roleService.isParticInAuthority(callerUser.getParticipant(), RoleService.Authority.SECRETARY); boolean isSecretary = roleService.isParticInAuthority(callerUser.getParticipant(), RoleService.Authority.SECRETARY);
boolean isTeacher = roleService.isParticInAuthority(callerUser.getParticipant(), RoleService.Authority.TEACHER);
boolean isOwner = existingParticipant != null && existingParticipant.getUser() != null boolean isOwner = existingParticipant != null && existingParticipant.getUser() != null
&& existingParticipant.getUser().getId().equals(callerUser.getId()); && existingParticipant.getUser().getId().equals(callerUser.getId());
if (!isAdmin && !isSecretary && !isOwner && !isTeacher) if (!isAdmin && !isSecretary && !isOwner)
throw new AccessDeniedException(); throw new AccessDeniedException();
if (participantSaveDTO.getAuthorities() != null && participantSaveDTO.getAuthorities().contains(RoleService.Authority.ADMIN) && !isAdmin) if (participantSaveDTO.getAuthorities() != null && participantSaveDTO.getAuthorities().contains(RoleService.Authority.ADMIN) && !isAdmin)
throw new AccessDeniedException("Недостаточно прав для назначения роли администратора"); throw new AccessDeniedException("Недостаточно прав для назначения роли администратора");
@ -225,11 +169,11 @@ public class ParticipantService {
teacherData.setParticipant(participant); teacherData.setParticipant(participant);
} }
private StudentData persistStudentData(ParticipantSaveDTO participantSaveDTO, Participant existingParticipant, boolean editMode, List<Role> roles, Participant participant) { private void persistStudentData(ParticipantSaveDTO participantSaveDTO, Participant existingParticipant, boolean editMode, List<Role> roles, Participant participant) {
boolean shouldPersistStudentData = participantSaveDTO.getStudentData() != null && roles != null boolean shouldPersistStudentData = participantSaveDTO.getStudentData() != null && roles != null
&& CollectionUtils.containsAny(roles, roleService.getRoleByAuthority(RoleService.Authority.STUDENT)); && CollectionUtils.containsAny(roles, roleService.getRoleByAuthority(RoleService.Authority.STUDENT));
if (!shouldPersistStudentData) { if (!shouldPersistStudentData) {
return null; return;
} }
boolean alreadyExists = editMode && studentDataRepository.existsByParticipant_IdAndParticipant_DeletedFalse(existingParticipant.getId()); boolean alreadyExists = editMode && studentDataRepository.existsByParticipant_IdAndParticipant_DeletedFalse(existingParticipant.getId());
@ -240,21 +184,6 @@ public class ParticipantService {
studentData = new StudentData(); studentData = new StudentData();
} }
studentData.setOtziv(participantSaveDTO.getStudentData().getOtziv());
studentData.setWork(participantSaveDTO.getStudentData().getWork());
studentData.setZachetka(participantSaveDTO.getStudentData().getZachetka());
studentData.setPreDefenseMark(participantSaveDTO.getStudentData().getPreDefenseMark());
studentData.setElectronic(participantSaveDTO.getStudentData().getElectronic());
studentData.setOtlichiye(participantSaveDTO.getStudentData().getOtlichiye());
studentData.setVnedreniye(participantSaveDTO.getStudentData().getVnedreniye());
studentData.setMagistracy(participantSaveDTO.getStudentData().getMagistracy());
studentData.setMarks5(participantSaveDTO.getStudentData().getMarks5());
studentData.setMarks4(participantSaveDTO.getStudentData().getMarks4());
studentData.setMarks3(participantSaveDTO.getStudentData().getMarks3());
studentData = studentDataRepository.save(studentData);
if (participantSaveDTO.getStudentData().getGroupId() != null) { if (participantSaveDTO.getStudentData().getGroupId() != null) {
Group group = groupRepository.findByIdThrow(participantSaveDTO.getStudentData().getGroupId()); Group group = groupRepository.findByIdThrow(participantSaveDTO.getStudentData().getGroupId());
studentData.setGroup(group); studentData.setGroup(group);
@ -276,28 +205,8 @@ public class ParticipantService {
studentData.setCurator(null); studentData.setCurator(null);
} }
return studentData; studentData = studentDataRepository.save(studentData);
} studentData.setParticipant(participant);
private void persistCommissionData(ParticipantSaveDTO participantSaveDTO, Participant existingParticipant, boolean editMode, List<Role> roles, Participant participant) {
boolean shouldPersist = participantSaveDTO.getCommMemData() != null && roles != null
&& CollectionUtils.containsAny(roles, roleService.getRoleByAuthority(RoleService.Authority.COMM_MEMBER));
if (!shouldPersist) {
return;
}
boolean alreadyExists = editMode && commissionMemberRepository.existsByParticipant_Id(existingParticipant.getId());
CommissionMemberData commMemData;
if (alreadyExists) {
commMemData = commissionMemberRepository.findByParticipant_Id(existingParticipant.getId());
} else {
commMemData = new CommissionMemberData();
}
commMemData.setWorkPlace(participantSaveDTO.getCommMemData().getWorkPlace());
commMemData.setWorkPosition(participantSaveDTO.getCommMemData().getWorkPosition());
commMemData = commissionMemberRepository.save(commMemData);
commMemData.setParticipant(participant);
} }
public void deleteParticipant(Long id) { public void deleteParticipant(Long id) {
@ -308,10 +217,4 @@ public class ParticipantService {
Participant partic = participantRepository.findByIdThrow(id); Participant partic = participantRepository.findByIdThrow(id);
partic.setDeleted(true); partic.setDeleted(true);
} }
public List<Participant> getAllAntipl() {
return entityManager.createQuery("select p from Participant p inner join p.roles r where r.authority = :auth", Participant.class)
.setParameter("auth", RoleService.Authority.PLAGIARISM_CHECKER.getAuthority())
.getResultList();
}
} }

View File

@ -4,10 +4,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import ru.mskobaro.tdms.business.entity.DirectionOfPreparation; import ru.mskobaro.tdms.business.entity.DirectionOfPreparation;
import ru.mskobaro.tdms.business.entity.TeacherData;
import ru.mskobaro.tdms.integration.database.PreparationDirectionRepository; import ru.mskobaro.tdms.integration.database.PreparationDirectionRepository;
import ru.mskobaro.tdms.integration.controller.payload.PreparationDirectionDTO; import ru.mskobaro.tdms.presentation.controller.payload.PreparationDirectionDTO;
import ru.mskobaro.tdms.integration.database.TeacherDataRepository;
import java.util.List; import java.util.List;
@ -16,8 +14,6 @@ import java.util.List;
public class PreparationDirectionService { public class PreparationDirectionService {
@Autowired @Autowired
private PreparationDirectionRepository preparationDirectionRepository; private PreparationDirectionRepository preparationDirectionRepository;
@Autowired
private TeacherDataRepository teacherDataRepository;
public List<DirectionOfPreparation> getAll() { public List<DirectionOfPreparation> getAll() {
return preparationDirectionRepository.findAll(); return preparationDirectionRepository.findAll();
@ -31,15 +27,8 @@ public class PreparationDirectionService {
} else { } else {
preparationDirection = new DirectionOfPreparation(); preparationDirection = new DirectionOfPreparation();
} }
TeacherData teacherData = null;
if (preparationDirectionDTO.getResponsible() != null && preparationDirectionDTO.getResponsible().getId() != null) {
teacherData = teacherDataRepository.findByIdThrow(preparationDirectionDTO.getResponsible().getId());
}
preparationDirection.setName(preparationDirectionDTO.getName()); preparationDirection.setName(preparationDirectionDTO.getName());
preparationDirection.setCode(preparationDirectionDTO.getCode()); preparationDirection.setCode(preparationDirectionDTO.getCode());
preparationDirection.setResponsible(teacherData);
preparationDirectionRepository.save(preparationDirection); preparationDirectionRepository.save(preparationDirection);
} }
} }

View File

@ -1,14 +1,11 @@
package ru.mskobaro.tdms.business.service; package ru.mskobaro.tdms.business.service;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.transaction.Transactional; import jakarta.transaction.Transactional;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ru.mskobaro.tdms.business.entity.Participant; import ru.mskobaro.tdms.business.entity.Participant;
import ru.mskobaro.tdms.business.entity.StudentData; import ru.mskobaro.tdms.business.entity.StudentData;
import ru.mskobaro.tdms.integration.controller.payload.StudentDataDTO;
import ru.mskobaro.tdms.integration.database.StudentDataRepository; import ru.mskobaro.tdms.integration.database.StudentDataRepository;
import ru.mskobaro.tdms.integration.database.UserRepository; import ru.mskobaro.tdms.integration.database.UserRepository;
@ -21,8 +18,6 @@ import java.util.List;
public class StudentDataService { public class StudentDataService {
@Autowired @Autowired
private StudentDataRepository studentDataRepository; private StudentDataRepository studentDataRepository;
@PersistenceContext
private EntityManager entityManager;
public StudentData getStudentByParticIdThrow(Long particId) { public StudentData getStudentByParticIdThrow(Long particId) {
return studentDataRepository.findStudentDataByParticipant_Id(particId); return studentDataRepository.findStudentDataByParticipant_Id(particId);
@ -31,9 +26,4 @@ public class StudentDataService {
public Collection<StudentData> getAllStudentsWithoutGroup() { public Collection<StudentData> getAllStudentsWithoutGroup() {
return studentDataRepository.findByGroupIsNull(); return studentDataRepository.findByGroupIsNull();
} }
public List<StudentData> getByDefenseId(Long id) {
return entityManager.createQuery("select sd from StudentData sd where sd.group.defense.id = :id", StudentData.class)
.setParameter("id", id).getResultList();
}
} }

View File

@ -1,18 +1,17 @@
package ru.mskobaro.tdms.business.service; package ru.mskobaro.tdms.business.service;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import ru.mskobaro.tdms.business.entity.*; import ru.mskobaro.tdms.business.entity.StudentData;
import ru.mskobaro.tdms.business.exception.BusinessException; import ru.mskobaro.tdms.business.entity.Task;
import ru.mskobaro.tdms.integration.controller.TaskController; import ru.mskobaro.tdms.business.entity.User;
import ru.mskobaro.tdms.integration.controller.payload.DefenseDTO; import ru.mskobaro.tdms.business.taskfields.DiplomaTopicAgreementTaskFields;
import ru.mskobaro.tdms.integration.controller.payload.IdDTO; import ru.mskobaro.tdms.business.taskfields.TaskFields;
import ru.mskobaro.tdms.integration.database.*; import ru.mskobaro.tdms.integration.database.StudentDataRepository;
import ru.mskobaro.tdms.integration.database.TaskRepository;
import ru.mskobaro.tdms.presentation.controller.TaskController;
import java.util.ArrayList;
import java.util.List; import java.util.List;
@Service @Service
@ -24,496 +23,41 @@ public class TaskService {
private UserService userService; private UserService userService;
@Autowired @Autowired
private StudentDataRepository studentDataRepository; private StudentDataRepository studentDataRepository;
@PersistenceContext
private EntityManager entityManager;
@Autowired
private ParticipantRepository participantRepository;
@Autowired
private DiplomaTopicRepository diplomaTopicRepository;
@Autowired
private TeacherDataRepository teacherDataRepository;
@Autowired
private RoleService roleService;
@Autowired
private EmailService emailService;
@Autowired
private DefenseRepository defenseRepository;
public TopicAgreementTask findDiplomaTopicAgreementTaskMadeByCurrentUser() { public void createTask(Task.Type type, Task.Status status, TaskFields taskFields) {
Task task = new Task();
task.setType(type);
task.setStatus(status);
task.setFields(taskFields);
taskRepository.save(task);
}
public Task findDiplomaTopicAgreementTaskCallerMaker() {
User user = userService.getCallerUser(); User user = userService.getCallerUser();
try { List<Task> diplomaTopicAgreementTaskByMakerId = taskRepository.findDiplomaTopicAgreementTaskByMakerId(
return entityManager.createQuery("select t from TopicAgreementTask t where t.checkerParticId = :id or t.makerParticId = :id", TopicAgreementTask.class) user.getParticipant().getId(), Task.Type.DIPLOMA_TOPIC_AGREEMENT
.setParameter("id", user.getParticipant().getId()) );
.setMaxResults(1) if (diplomaTopicAgreementTaskByMakerId.isEmpty()) {
.getSingleResult();
} catch (Exception e) {
return null; return null;
} }
if (diplomaTopicAgreementTaskByMakerId.size() > 1) {
throw new IllegalStateException();
}
return diplomaTopicAgreementTaskByMakerId.get(0);
} }
private List<Task.Status> getNotShowStatuses() { public void createDiplomaAgreementTask(TaskController.DiplomaTopicAgreementDTO diplomaTopicAgreementDTO) {
DiplomaTopicAgreementTaskFields taskFields = new DiplomaTopicAgreementTaskFields();
User user = userService.getCallerUser(); User user = userService.getCallerUser();
List<Task.Status> notShowStatuses = new ArrayList<>(List.of(Task.Status.DONE, Task.Status.CANCELED)); StudentData studentData = studentDataRepository.findStudentDataByParticipant_Id(user.getParticipant().getId());
if (!roleService.isParticInAuthority(user.getParticipant(), RoleService.Authority.STUDENT)) { taskFields.setCheckerParticipantId(user.getParticipant().getId());
notShowStatuses.add(Task.Status.WAIT_FOR_STUDENT_EDIT); taskFields.setDiplomaTopicId(diplomaTopicAgreementDTO.getDiplomaTopicId());
} taskFields.setDiplomaTopicName(diplomaTopicAgreementDTO.getDiplomaTopicName());
taskFields.setCheckerParticipantId(studentData.getCurator().getId());
if (!roleService.isParticInAuthority(user.getParticipant(), RoleService.Authority.TEACHER)) { createTask(Task.Type.DIPLOMA_TOPIC_AGREEMENT, Task.Status.WAIT_FOR_TOPIC_AGREEMENT, taskFields);
notShowStatuses.add(Task.Status.WAIT_FOR_TOPIC_AGREEMENT);
}
return notShowStatuses;
}
public Long getCurrentUserNotificationCount() {
return entityManager.createQuery(
"""
select count(t) from Task t where t.checkerParticId = :id
and t.status not in (:statuses)
""", Long.class)
.setParameter("id", userService.getCallerUser().getParticipant().getId())
.setParameter("statuses", getNotShowStatuses())
.getSingleResult();
}
public List<TaskController.TaskDTO> getAllCurrentTasks() {
List<Task> tasks = entityManager.createQuery(
"""
select t from Task t
inner join fetch t.defense
where t.checkerParticId = :id
and t.status not in (:statuses)
""", Task.class)
.setParameter("id", userService.getCallerUser().getParticipant().getId())
.setParameter("statuses", getNotShowStatuses())
.getResultList();
return tasks.stream().map(t -> {
TaskController.TaskDTO dto = new TaskController.TaskDTO();
dto.setId(t.getId());
dto.setStatus(t.getStatus());
dto.setMessage(getTaskMessage(t));
dto.setCheckerId(t.getCheckerParticId());
dto.setMakerId(t.getMakerParticId());
dto.setType(t.getType());
dto.setDefense(DefenseDTO.from(t.getDefense()));
if (t instanceof TopicAgreementTask tat) {
dto.setInfo(IdDTO.fromId(tat.getMakerParticId()));
}
return dto;
}).toList();
}
private String getTaskMessage(Task t) {
switch (t.getStatus()) {
case WAIT_FOR_TOPIC_PREPARATION -> {
return "Требуется указать темы ВКР, которые смогут выбрать студенты";
}
case WAIT_FOR_TOPIC_AGREEMENT -> {
Participant studentPartic = participantRepository.findByIdThrow(t.getMakerParticId());
return "Согласование темы ВКР со студентом %s".formatted(studentPartic.getFullName());
}
case WAIT_FOR_STUDENT_START -> {
return "Требуется согласовать тему с научным руководителем";
}
case WAIT_FOR_STUDENT_EDIT -> {
return "Научный руководитель отправил тему на доработку";
}
case WAIT_FOR_ANTIPL_PASSED -> {
Participant studPartic = participantRepository.findByIdThrow(t.getMakerParticId());
return "После прохождения антиплагиата требуется пометить этап указать уникальность работы (%s)".formatted(studPartic.getFullName());
}
case WAIT_FOR_NORMOCONTROL_PASSED -> {
Participant studPartic = participantRepository.findByIdThrow(t.getMakerParticId());
return "После прохождения нормоконтроля требуется пометить этап как проеденный (%s)".formatted(studPartic.getFullName());
}
case WAIT_FOR_TEACHER_OTZIV -> {
Participant studPartic = participantRepository.findByIdThrow(t.getMakerParticId());
return "Требуется предоставить отзыв студенту (%s)".formatted(studPartic.getFullName());
}
default -> { return t.getStatus().toString(); }
}
}
public void agreementChangeRequest(TaskController.DiplomaTopicAgreementChangeRequestDTO changeRequest) {
TopicAgreementTask topicAgreementTask = entityManager.createQuery(
"select t from TopicAgreementTask t where t.id = :id", TopicAgreementTask.class)
.setParameter("id", changeRequest.getTaskId())
.getSingleResult();
switch (changeRequest.getType()) {
case STUDENT_REDO -> {
if (changeRequest.getDiplomaTopicId() != null) {
topicAgreementTask.setDiplomaTopicId(changeRequest.getDiplomaTopicId());
topicAgreementTask.setDiplomaTopicName(null);
} else if (changeRequest.getDiplomaTopicName() != null) {
topicAgreementTask.setDiplomaTopicName(changeRequest.getDiplomaTopicName());
topicAgreementTask.setDiplomaTopicId(null);
} else {
throw new IllegalStateException();
}
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);
}
} }
} }

View File

@ -9,7 +9,7 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ru.mskobaro.tdms.business.entity.User; import ru.mskobaro.tdms.business.entity.User;
import ru.mskobaro.tdms.integration.database.UserRepository; import ru.mskobaro.tdms.integration.database.UserRepository;
import ru.mskobaro.tdms.integration.controller.payload.UserDTO; import ru.mskobaro.tdms.presentation.controller.payload.UserDTO;
import java.util.List; import java.util.List;

View File

@ -0,0 +1,11 @@
package ru.mskobaro.tdms.business.taskfields;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class DiplomaTopicAgreementTaskFields extends MakerCheckerTaskFields {
private String diplomaTopicName;
private Long diplomaTopicId;
}

View File

@ -0,0 +1,13 @@
package ru.mskobaro.tdms.business.taskfields;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;
@Getter
@Setter
public class MakerCheckerTaskFields extends MakerTaskFields {
private Long checkerParticipantId;
private LocalDateTime approvedAt;
}

View File

@ -0,0 +1,10 @@
package ru.mskobaro.tdms.business.taskfields;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class MakerTaskFields extends TaskFields {
private Long makerParticipantId;
}

View File

@ -0,0 +1,10 @@
package ru.mskobaro.tdms.business.taskfields;
import lombok.Getter;
import java.time.LocalDateTime;
@Getter
public class TaskFields {
private LocalDateTime createdAt;
}

View File

@ -1,33 +0,0 @@
package ru.mskobaro.tdms.integration.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import ru.mskobaro.tdms.business.entity.CommissionMemberData;
import ru.mskobaro.tdms.integration.controller.payload.CommissionMemberDTO;
import ru.mskobaro.tdms.integration.database.CommissionMemberRepository;
import java.util.List;
import java.util.stream.Collectors;
@RestController
@RequestMapping("api/v1/commission-member")
public class CommissionMemberController {
@Autowired
private CommissionMemberRepository commissionMemberRepository;
@GetMapping("/get-all")
public List<CommissionMemberDTO> getAll() {
List<CommissionMemberData> all = commissionMemberRepository.findAll();
return all.stream().map(CommissionMemberDTO::from).collect(Collectors.toList());
}
@GetMapping("/by-partic-id")
public CommissionMemberDTO getByParticId(@RequestParam("id") Long id) {
CommissionMemberData commissionMemberData = commissionMemberRepository.findByParticipant_Id(id);
return CommissionMemberDTO.from(commissionMemberData);
}
}

View File

@ -1,121 +0,0 @@
package ru.mskobaro.tdms.integration.controller;
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import ru.mskobaro.tdms.business.service.DefenseService;
import ru.mskobaro.tdms.integration.controller.payload.DefenseDTO;
import ru.mskobaro.tdms.integration.controller.payload.IdDTO;
import java.util.List;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/api/v1/defense")
public class DefenseController {
@Autowired
private DefenseService defenseService;
@GetMapping("get-all")
public List<DefenseDTO> getAllDefenses() {
return defenseService.findAll().stream().map(DefenseDTO::from).collect(Collectors.toList());
}
@GetMapping("get-by-id")
public DefenseDTO getById(@RequestParam Long id) {
return DefenseDTO.from(defenseService.findById(id));
}
@PostMapping("save")
public void save(@RequestBody DefenseDTO defenseDTO) {
defenseService.save(defenseDTO);
}
@PostMapping("to-next-state")
public void nextState(@RequestBody IdDTO idDto) {
defenseService.handleNextStateRequest(idDto.getId());
}
@GetMapping("defense-table")
public DefenseTableData getDefenseTable(@RequestParam Long defenseId) {
return defenseService.tableDataByDefenseId(defenseId);
}
@PostMapping("defense-table-save")
public void defenseTableSave(@RequestBody DefenseTableData defenseTableData) {
defenseService.tableDataSave(defenseTableData);
}
@Getter
@Setter
public static class DefenseTableData {
private Long defenseId;
private List<DefenseTableDataGroup> groups;
}
@Getter
@Setter
public static class DefenseTableDataGroup {
private Long groupId;
private Long studId;
private String groupName;
private String fio;
private Integer pdpMark;
private String topic;
private String teacherFio;
private Integer dayOfProt;
private Integer placeOfProt;
private Boolean magistracy;
private Boolean electronic;
private Integer otziv;
private Integer dpedefenseMark;
private Boolean normcontrol;
private Integer antipl;
private Boolean zachetka;
private String work;
private Boolean vnedreniye;
private Boolean otlichiye;
}
@PostMapping("recreate-protection-order")
public void recreateProtectionOrder(@RequestBody IdDTO idDto) {
defenseService.recreateProtectionOrder(idDto.getId());
}
@PostMapping("save-order")
public void updateProtectionOrder(@RequestBody ProtOrDTO dto) {
defenseService.updateProtOrder(dto);
}
@Getter
@Setter
public static class ProtOrDTO {
private Long defenseId;
private List<DrotOrGroupDTO> days;
private List<IdDTO> unassigned;
}
@Getter
@Setter
public static class DrotOrGroupDTO {
private Integer number;
private List<StudDTO> studs;
}
@Getter
@Setter
public static class StudDTO {
private Long id;
private Integer order;
}
}

View File

@ -1,49 +0,0 @@
package ru.mskobaro.tdms.integration.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import ru.mskobaro.tdms.business.entity.DiplomaTopic;
import ru.mskobaro.tdms.business.service.DiplomaTopicService;
import ru.mskobaro.tdms.integration.controller.payload.DiplomaTopicDTO;
import ru.mskobaro.tdms.integration.database.DiplomaTopicRepository;
import java.util.List;
@RestController
@RequestMapping("/api/v1/diploma-topic/")
@Validated
public class DiplomaTopicController {
@Autowired
private DiplomaTopicService diplomaTopicService;
@Autowired
private DiplomaTopicRepository diplomaTopicRepository;
@GetMapping("/all")
public List<DiplomaTopicDTO> getAll() {
return diplomaTopicService.findAll().stream().map(DiplomaTopicDTO::from).toList();
}
@PostMapping("/save")
public void save(@RequestBody DiplomaTopicDTO diplomaTopicDTO) {
diplomaTopicService.save(diplomaTopicDTO);
}
@GetMapping("/all-for-student")
public List<DiplomaTopicDTO> getAllForStudent(@RequestParam Long id) {
return diplomaTopicService.findAllForStudentByParticId(id).stream().map(DiplomaTopicDTO::from).toList();
}
@GetMapping("/by-id")
public DiplomaTopicDTO getById(@RequestParam Long id) {
DiplomaTopic topic = diplomaTopicRepository.findByIdThrow(id);
return DiplomaTopicDTO.from(topic);
}
@GetMapping("matching-teacher-and-dir-prep")
public List<DiplomaTopicDTO> matchingTeacherAndDirPrep(@RequestParam Long particId, @RequestParam Long dirPrepId) {
return diplomaTopicService.findByTeacherParticIdAndDirPrep(particId, dirPrepId).stream().map(DiplomaTopicDTO::from).toList();
}
}

View File

@ -1,46 +0,0 @@
package ru.mskobaro.tdms.integration.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import ru.mskobaro.tdms.business.service.DocumentsService;
@RestController
@RequestMapping("api/v1/doc")
public class DocumentsController {
@Autowired
private DocumentsService documentsService;
@GetMapping("stud-list")
public ResponseEntity<ByteArrayResource> getStudList(@RequestParam Long id) {
byte[] document = documentsService.getStudList(id, "бакалавр");
return returnFile(document, "SPISOK_ZASHISHAYUSHIHSYA.docx");
}
@GetMapping("gek-questions")
public ResponseEntity<ByteArrayResource> getQuestions(@RequestParam Long id) {
byte[] document = documentsService.getQuestionsDocument(id, "Очная");
return returnFile(document, "BLANK_VOPROSOV_GEK.docx");
}
@GetMapping("topic-list")
public ResponseEntity<ByteArrayResource> getTopicList(@RequestParam Long id) {
byte[] document = documentsService.getTopicList(id);
return returnFile(document, "FRAGMENT_PRIKAZA_TEMI_VKR.docx");
}
private ResponseEntity<ByteArrayResource> returnFile(byte[] document, String filename) {
ByteArrayResource resource = new ByteArrayResource(document);
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.contentLength(document.length)
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + filename)
.body(resource);
}
}

View File

@ -1,33 +0,0 @@
package ru.mskobaro.tdms.integration.controller;
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import ru.mskobaro.tdms.business.service.HomeInfoService;
@RestController
@RequestMapping("/api/v1/home-page/")
public class HomeInfoController {
@Autowired
private HomeInfoService homeInfoService;
@GetMapping("default-info")
public DefaultInfo defaultInfo() {
return homeInfoService.defaultInfo();
}
@Getter
@Setter
public static class DefaultInfo {
private Long particCount;
private Long userCount;
private Long teacherCount;
private Long studentCount;
private Long defenseCount;
private Long currentDefenseCount;
private String currentDefenseGroupNames;
}
}

View File

@ -1,122 +0,0 @@
package ru.mskobaro.tdms.integration.controller;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import ru.mskobaro.tdms.business.entity.Task;
import ru.mskobaro.tdms.business.entity.TopicAgreementTask;
import ru.mskobaro.tdms.business.service.TaskService;
import ru.mskobaro.tdms.integration.controller.payload.DefenseDTO;
import ru.mskobaro.tdms.integration.controller.payload.IdDTO;
import ru.mskobaro.tdms.integration.controller.payload.TopicAgreementDto;
import java.util.List;
@RestController
@RequestMapping("/api/v1/task")
public class TaskController {
@Autowired
private TaskService taskService;
@GetMapping("/diploma-agreement-maker")
public TopicAgreementDto diplomaTopicAgreementMaker() {
TopicAgreementTask task = taskService.findDiplomaTopicAgreementTaskMadeByCurrentUser();
return task == null ? null : TopicAgreementDto.from(task);
}
@GetMapping("/diploma-agreement-maker-by-partic-id")
public TopicAgreementDto diplomaTopicAgreementMakerId(@RequestParam Long id) {
TopicAgreementTask task = taskService.getTopicAgreementTaskByMakerId(id);
return task == null ? null : TopicAgreementDto.from(task);
}
@PostMapping("/agreement-change")
public void agreementChange(@RequestBody DiplomaTopicAgreementChangeRequestDTO changeRequest) {
taskService.agreementChangeRequest(changeRequest);
}
@GetMapping("/notif-count")
public NumberDTO getCurrentUserNotificationCount() {
NumberDTO dto = new NumberDTO();
Long number = taskService.getCurrentUserNotificationCount();
dto.setNumber(number);
return dto;
}
@GetMapping("/get-current-tasks")
public List<TaskDTO> getCurrentTasks() {
return taskService.getAllCurrentTasks();
}
@Getter
@Setter
public static class DiplomaTopicAgreementDTO {
private String diplomaTopicName;
private Long diplomaTopicId;
}
@Getter
@Setter
public static class NumberDTO {
private Long number;
}
@Getter
@Setter
public static class TaskDTO {
private Long id;
private String message;
private Task.Status status;
private Task.Type type;
private Long makerId;
private Long checkerId;
private DefenseDTO defense;
private Object info;
}
@Getter
@Setter
public static class DiplomaTopicAgreementChangeRequestDTO {
public enum ChangeType {
STUDENT_REDO,
TEACHER_APPROVE,
TEACHER_REJECT,
}
private Long taskId;
private String diplomaTopicName;
private Long diplomaTopicId;
private ChangeType type;
}
@PostMapping("topic-preparation-finish")
public void finishTopicPreparation(@RequestBody IdDTO idDTO) {
taskService.finishTopicPreparationTask(idDTO);
}
@PostMapping("def-prep-finish")
public void finishDefPreparation(@RequestBody DefPrepFinishDTO defPrepFinishDTO) {
taskService.finishDefPrepTask(defPrepFinishDTO);
}
@Getter
@Setter
public static class DefPrepFinishDTO {
private Long taskId;
private Integer mark;
}
@PostMapping("norm-antipl-finish")
public void finishNormAntiplFinish(@RequestBody NormAntiplFinishDTO antiplFinishDTO) {
taskService.finishNormAntipl(antiplFinishDTO);
}
@Getter
@Setter
public static class NormAntiplFinishDTO {
private Long taskId;
private Integer antipl;
}
}

View File

@ -1,58 +0,0 @@
package ru.mskobaro.tdms.integration.controller.payload;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.collections4.CollectionUtils;
import ru.mskobaro.tdms.business.entity.Defense;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;
@Getter
@Setter
public class DefenseDTO {
private Long id;
private List<CommissionMemberDTO> commissionMembers;
private List<GroupDTO> groups;
private Defense.Status status;
private ParticipantDTO responsibleForAntipl;
private ParticipantDTO responsibleForNorm;
private PreparationDirectionDTO preparationDirection;
private LocalDate defenseDate;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
public static DefenseDTO from(Defense defense) {
DefenseDTO dto = new DefenseDTO();
dto.setId(defense.getId());
if (CollectionUtils.isNotEmpty(defense.getCommissionMembers())) {
dto.setCommissionMembers(
defense.getCommissionMembers().stream()
.map(CommissionMemberDTO::from)
.collect(Collectors.toList())
);
}
if (defense.getResponsibleForAntiplagiarism() != null) {
dto.setResponsibleForAntipl(ParticipantDTO.fromEntity(defense.getResponsibleForAntiplagiarism()));
}
if (defense.getResponsibleForNormcontrol() != null) {
dto.setResponsibleForNorm(ParticipantDTO.fromEntity(defense.getResponsibleForNormcontrol()));
}
if (defense.getDirectionOfPreparation() != null) {
dto.setPreparationDirection(PreparationDirectionDTO.from(defense.getDirectionOfPreparation()));
}
dto.setStatus(defense.getStatus());
dto.setGroups(defense.getGroups().stream().map(g -> GroupDTO.from(g, true)).toList());
dto.setDefenseDate(defense.getDefenseDate());
dto.setCreatedAt(defense.getAuditInfo().getCreatedAt());
dto.setUpdatedAt(defense.getAuditInfo().getUpdatedAt());
return dto;
}
}

View File

@ -1,20 +0,0 @@
package ru.mskobaro.tdms.integration.controller.payload;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@NoArgsConstructor
@Getter
@Setter
@ToString
public class IdDTO {
private Long id;
public static IdDTO fromId(Long id) {
IdDTO dto = new IdDTO();
dto.setId(id);
return dto;
}
}

View File

@ -1,88 +0,0 @@
package ru.mskobaro.tdms.integration.controller.payload;
import lombok.Getter;
import lombok.Setter;
import ru.mskobaro.tdms.business.entity.StudentData;
// @Column(name = "magistracy_wanted")
// private Boolean magistracy;
// private Boolean electronic;
//
// @Column(name = "oztiv_mark")
// private Integer otziv;
// @Column(name = "predefnese_mark")
// private Integer preDefenseMark;
//
// @Column(name = "normal_control")
// private Boolean normcontrol;
// @Column(name = "anti_plagiarism")
// private Integer antiplagiarism;
//
// @Column(name = "record_book_returned")
// private Boolean zachetka;
//
// @Column(name = "work")
// private String work;
//
// @Column(name = "vnedreniye")
// private Boolean vnedreniye;
// @Column(name = "diploma_with_honors")
// private Boolean otlichiye;
@Setter
@Getter
public class StudentDataDTO {
private Long id;
private GroupDTO group;
private ParticipantDTO participant;
private TeacherDataDTO curator;
private DiplomaTopicDTO diplomaTopic;
private Boolean magistracy;
private Boolean electronic;
private Integer otziv;
private Integer preDefenseMark;
private Boolean normcontrol;
private Integer antiplagiarism;
private Boolean zachetka;
private String work;
private Boolean vnedreniye;
private Boolean otlichiye;
private Integer protDay;
private Integer protOrder;
private Long marks5;
private Long marks4;
private Long marks3;
public static StudentDataDTO from(StudentData studentData, boolean includeGroup) {
StudentDataDTO dto = new StudentDataDTO();
dto.setId(studentData.getId());
if (includeGroup && studentData.getGroup() != null) {
dto.setGroup(GroupDTO.from(studentData.getGroup(), false));
}
dto.setParticipant(ParticipantDTO.fromEntity(studentData.getParticipant()));
if (studentData.getCurator() != null) {
dto.setCurator(TeacherDataDTO.from(studentData.getCurator()));
}
if (studentData.getDiplomaTopic() != null) {
dto.setDiplomaTopic(DiplomaTopicDTO.from(studentData.getDiplomaTopic()));
}
dto.setMagistracy(studentData.getMagistracy());
dto.setElectronic(studentData.getElectronic());
dto.setOtziv(studentData.getOtziv());
dto.setPreDefenseMark(studentData.getPreDefenseMark());
dto.setNormcontrol(studentData.getNormcontrol());
dto.setAntiplagiarism(studentData.getAntiplagiarism());
dto.setZachetka(studentData.getZachetka());
dto.setWork(studentData.getWork());
dto.setVnedreniye(studentData.getVnedreniye());
dto.setOtlichiye(studentData.getOtlichiye());
dto.setProtDay(studentData.getProtectionDay());
dto.setProtOrder(studentData.getProtectionOrder());
dto.setMarks5(studentData.getMarks5());
dto.setMarks4(studentData.getMarks4());
dto.setMarks3(studentData.getMarks3());
return dto;
}
}

View File

@ -1,39 +0,0 @@
package ru.mskobaro.tdms.integration.controller.payload;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import ru.mskobaro.tdms.business.entity.Task;
import ru.mskobaro.tdms.business.entity.TopicAgreementTask;
import java.time.LocalDateTime;
@NoArgsConstructor
@Getter
@Setter
public class TopicAgreementDto {
private Long id;
private Task.Status status;
private Long makerParticId;
private Long checkerParticId;
private Long diplomaTopicId;
private String diplomaTopicName;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
private LocalDateTime approvedAt;
public static TopicAgreementDto from(TopicAgreementTask task) {
TopicAgreementDto dto = new TopicAgreementDto();
dto.setId(task.getId());
dto.setStatus(task.getStatus());
dto.setMakerParticId(task.getMakerParticId());
dto.setCheckerParticId(task.getCheckerParticId());
dto.setDiplomaTopicId(task.getDiplomaTopicId());
dto.setDiplomaTopicName(task.getDiplomaTopicName());
dto.setCreatedAt(task.getAuditInfo().getCreatedAt());
dto.setUpdatedAt(task.getAuditInfo().getUpdatedAt());
dto.setApprovedAt(task.getApprovedAt());
return dto;
}
}

View File

@ -1,17 +0,0 @@
package ru.mskobaro.tdms.integration.database;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import ru.mskobaro.tdms.business.entity.CommissionMemberData;
import ru.mskobaro.tdms.business.exception.NotFoundException;
@Repository
public interface CommissionMemberRepository extends JpaRepository<CommissionMemberData, Long> {
default CommissionMemberData findByIdThrow(Long id) {
return findById(id).orElseThrow(() -> new NotFoundException(CommissionMemberData.class, id));
}
boolean existsByParticipant_Id(Long id);
CommissionMemberData findByParticipant_Id(Long participantId);
}

View File

@ -0,0 +1,25 @@
package ru.mskobaro.tdms.integration.database;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import ru.mskobaro.tdms.business.entity.Defense;
import ru.mskobaro.tdms.business.exception.NotFoundException;
import java.util.Optional;
@Repository
public interface DefenceRepository extends JpaRepository<Defense, Long> {
default Defense findByIdThrow(Long id) {
return this.findById(id).orElseThrow(() -> new NotFoundException(Defense.class, id));
}
@Override
@Query("SELECT d from Defense d " +
"left join fetch d.bestWorks bw " +
"left join fetch d.commissionMembers cm " +
"where d.id = :id " +
"and bw.participant.deleted = false " +
"and cm.participant.deleted = false")
Optional<Defense> findById(Long id);
}

View File

@ -1,13 +0,0 @@
package ru.mskobaro.tdms.integration.database;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import ru.mskobaro.tdms.business.entity.Defense;
import ru.mskobaro.tdms.business.exception.NotFoundException;
@Repository
public interface DefenseRepository extends JpaRepository<Defense, Long> {
default Defense findByIdThrow(Long id) {
return this.findById(id).orElseThrow(() -> new NotFoundException(Defense.class, id));
}
}

View File

@ -4,6 +4,8 @@ import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import ru.mskobaro.tdms.business.entity.DiplomaTopic; import ru.mskobaro.tdms.business.entity.DiplomaTopic;
import ru.mskobaro.tdms.business.entity.DirectionOfPreparation;
import ru.mskobaro.tdms.business.entity.StudentData;
import ru.mskobaro.tdms.business.exception.NotFoundException; import ru.mskobaro.tdms.business.exception.NotFoundException;
import java.util.List; import java.util.List;
@ -15,9 +17,13 @@ public interface DiplomaTopicRepository extends JpaRepository<DiplomaTopic, Long
return this.findById(id).orElseThrow(() -> new NotFoundException(DiplomaTopic.class, id)); return this.findById(id).orElseThrow(() -> new NotFoundException(DiplomaTopic.class, id));
} }
@Override
@Query("SELECT d FROM DiplomaTopic d WHERE d.id = :id AND d.teacher.participant.deleted = false")
Optional<DiplomaTopic> findById(Long id);
@Query("SELECT d FROM DiplomaTopic d " + @Query("SELECT d FROM DiplomaTopic d " +
"inner join d.directionOfPreparation dp " + "inner join d.directionOfPreparation dp " +
"inner join StudentData sd on sd.participant.id = :particId " + "inner join StudentData sd on sd.id = :studentIdwhere " +
"where dp = sd.group.directionOfPreparation and dp is not null and sd.curator = d.teacher and d.teacher is not null") "where dp = sd.group.directionOfPreparation")
List<DiplomaTopic> findAllForStudentByParticId(Long particId); List<DiplomaTopic> findAllForStudentId(Long studentId);
} }

View File

@ -1,15 +0,0 @@
package ru.mskobaro.tdms.integration.database;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import ru.mskobaro.tdms.business.entity.MessageTemplate;
import ru.mskobaro.tdms.business.exception.NotFoundException;
@Repository
public interface MessageTemplateRepository extends JpaRepository<MessageTemplate, Long> {
default MessageTemplate findByIdThrow(Long id) {
return findById(id).orElseThrow(() -> new NotFoundException(MessageTemplate.class, id));
}
MessageTemplate findByMessageType(MessageTemplate.MessageType messageType);
}

View File

@ -24,6 +24,4 @@ public interface ParticipantRepository extends JpaRepository<Participant, Long>
@Override @Override
@Query("SELECT p from Participant p where p.deleted = false") @Query("SELECT p from Participant p where p.deleted = false")
List<Participant> findAll(); List<Participant> findAll();
boolean existsByNumberPhoneOrEmail(String numberPhone, String email);
} }

View File

@ -1,13 +1,21 @@
package ru.mskobaro.tdms.integration.database; package ru.mskobaro.tdms.integration.database;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import ru.mskobaro.tdms.business.entity.Task; import ru.mskobaro.tdms.business.entity.Task;
import ru.mskobaro.tdms.business.exception.NotFoundException; import ru.mskobaro.tdms.business.exception.NotFoundException;
import java.util.List;
@Repository @Repository
public interface TaskRepository extends JpaRepository<Task, Long> { public interface TaskRepository extends JpaRepository<Task, Long> {
default Task findByIdThrow(Long id) { default Task findByIdThrow(Long id) {
return findById(id).orElseThrow(() -> new NotFoundException(Task.class, id)); return findById(id).orElseThrow(() -> new NotFoundException(Task.class, id));
} }
@Query(value = "SELECT t FROM task t " +
"WHERE t.type = :type " +
"and t.fields->>'makerParticipantId' = :id", nativeQuery = true)
List<Task> findDiplomaTopicAgreementTaskByMakerId(Long id, Task.Type type);
} }

View File

@ -0,0 +1,22 @@
package ru.mskobaro.tdms.presentation.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import ru.mskobaro.tdms.business.service.DefenceService;
import ru.mskobaro.tdms.presentation.controller.payload.DefenceDTO;
import java.util.List;
@RestController
@RequestMapping("/api/v1/defence")
public class DefenceController {
@Autowired
private DefenceService defenceService;
@GetMapping("/all")
public List<DefenceDTO> getAllDefences() {
return defenceService.getAllDefences();
}
}

View File

@ -0,0 +1,34 @@
package ru.mskobaro.tdms.presentation.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import ru.mskobaro.tdms.business.service.DiplomaTopicService;
import ru.mskobaro.tdms.presentation.controller.payload.DiplomaTopicDTO;
import java.util.List;
@RestController
@RequestMapping("/api/v1/diploma-topic/")
@Validated
public class DiplomaTopicController {
@Autowired
private DiplomaTopicService diplomaTopicService;
@GetMapping("/all")
public List<DiplomaTopicDTO> getAll() {
return diplomaTopicService.findAll().stream().map(DiplomaTopicDTO::from).toList();
}
@PostMapping("/save")
public void save(@RequestBody DiplomaTopicDTO diplomaTopicDTO) {
diplomaTopicService.save(diplomaTopicDTO);
}
@GetMapping("/all-for-student")
public List<DiplomaTopicDTO> getAllForStudent(@RequestParam Long studentId) {
return diplomaTopicService.findAllForStudent(studentId).stream().map(DiplomaTopicDTO::from).toList();
}
}

View File

@ -1,10 +1,10 @@
package ru.mskobaro.tdms.integration.controller; package ru.mskobaro.tdms.presentation.controller;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import ru.mskobaro.tdms.business.service.GroupService; import ru.mskobaro.tdms.business.service.GroupService;
import ru.mskobaro.tdms.integration.controller.payload.GroupDTO; import ru.mskobaro.tdms.presentation.controller.payload.GroupDTO;
import java.util.Collection; import java.util.Collection;

View File

@ -1,16 +1,14 @@
package ru.mskobaro.tdms.integration.controller; package ru.mskobaro.tdms.presentation.controller;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import ru.mskobaro.tdms.business.service.ParticipantService; import ru.mskobaro.tdms.business.service.ParticipantService;
import ru.mskobaro.tdms.integration.controller.payload.IdDTO; import ru.mskobaro.tdms.presentation.controller.payload.IdDto;
import ru.mskobaro.tdms.integration.controller.payload.ParticipantDTO; import ru.mskobaro.tdms.presentation.controller.payload.ParticipantDTO;
import ru.mskobaro.tdms.integration.controller.payload.ParticipantSaveDTO; import ru.mskobaro.tdms.presentation.controller.payload.ParticipantSaveDTO;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
@RestController @RestController
@RequestMapping("/api/v1/participant") @RequestMapping("/api/v1/participant")
@ -19,7 +17,7 @@ public class ParticipantController {
private ParticipantService participantService; private ParticipantService participantService;
@GetMapping("/get-all-participants") @GetMapping("/get-all-participants")
public List<ParticipantDTO> getAllParticipants() { public Collection<ParticipantDTO> getAllParticipants() {
return participantService.getAllParticipants().stream() return participantService.getAllParticipants().stream()
.map(ParticipantDTO::fromEntity) .map(ParticipantDTO::fromEntity)
.toList(); .toList();
@ -31,17 +29,7 @@ public class ParticipantController {
} }
@PostMapping("/delete") @PostMapping("/delete")
public void deleteParticipant(@RequestBody IdDTO id) { public void deleteParticipant(@RequestBody IdDto id) {
participantService.deleteParticipant(id.getId()); participantService.deleteParticipant(id.getId());
} }
@GetMapping("get-all-antipl")
public List<ParticipantDTO> getAllAntipl() {
return participantService.getAllAntipl().stream().map(ParticipantDTO::fromEntity).collect(Collectors.toList());
}
@GetMapping("get-all-norm")
public List<ParticipantDTO> getAllNorm() {
return this.getAllParticipants();
}
} }

View File

@ -1,9 +1,9 @@
package ru.mskobaro.tdms.integration.controller; package ru.mskobaro.tdms.presentation.controller;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import ru.mskobaro.tdms.business.service.PreparationDirectionService; import ru.mskobaro.tdms.business.service.PreparationDirectionService;
import ru.mskobaro.tdms.integration.controller.payload.PreparationDirectionDTO; import ru.mskobaro.tdms.presentation.controller.payload.PreparationDirectionDTO;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;

View File

@ -1,4 +1,4 @@
package ru.mskobaro.tdms.integration.controller; package ru.mskobaro.tdms.presentation.controller;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
@ -7,19 +7,16 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import ru.mskobaro.tdms.business.entity.StudentData; import ru.mskobaro.tdms.business.entity.StudentData;
import ru.mskobaro.tdms.business.service.StudentDataService; import ru.mskobaro.tdms.business.service.StudentDataService;
import ru.mskobaro.tdms.integration.controller.payload.StudentDataDTO; import ru.mskobaro.tdms.presentation.controller.payload.GroupDTO;
import ru.mskobaro.tdms.integration.database.StudentDataRepository; import ru.mskobaro.tdms.presentation.controller.payload.StudentDataDTO;
import java.util.Collection; import java.util.Collection;
import java.util.List;
@RestController @RestController
@RequestMapping("/api/v1/student/") @RequestMapping("/api/v1/student/")
public class StudentController { public class StudentController {
@Autowired @Autowired
private StudentDataService studentDataService; private StudentDataService studentDataService;
@Autowired
private StudentDataRepository studentDataRepository;
@GetMapping(value = "/by-partic-id") @GetMapping(value = "/by-partic-id")
public StudentDataDTO getCurrentStudent(@RequestParam(value = "id") Long particId) { public StudentDataDTO getCurrentStudent(@RequestParam(value = "id") Long particId) {
@ -33,16 +30,4 @@ public class StudentController {
.map(sd -> StudentDataDTO.from(sd, true)) .map(sd -> StudentDataDTO.from(sd, true))
.toList(); .toList();
} }
@GetMapping(value = "by-id")
public StudentDataDTO getStudentById(@RequestParam(value = "id") Long id) {
return StudentDataDTO.from(studentDataRepository.findByIdThrow(id), true);
}
@GetMapping("by-defense-id")
public List<StudentDataDTO> getByDefenseId(@RequestParam(value = "id") Long id) {
return studentDataService.getByDefenseId(id).stream()
.map(studentData -> StudentDataDTO.from(studentData, true))
.toList();
}
} }

View File

@ -1,4 +1,4 @@
package ru.mskobaro.tdms.integration.controller; package ru.mskobaro.tdms.presentation.controller;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;

View File

@ -0,0 +1,34 @@
package ru.mskobaro.tdms.presentation.controller;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import ru.mskobaro.tdms.business.service.TaskService;
import ru.mskobaro.tdms.presentation.controller.payload.TaskDto;
@RestController
@RequestMapping("/api/v1/task")
public class TaskController {
@Autowired
private TaskService taskService;
@GetMapping("/diploma-agreement-maker")
public TaskDto diplomaTopicAgreementMaker() {
return TaskDto.from(taskService.findDiplomaTopicAgreementTaskCallerMaker());
}
@PostMapping("/create-topic-agreement")
public void createDiplomaTopicAgreement(@RequestBody DiplomaTopicAgreementDTO diplomaTopicAgreementDTO) {
taskService.createDiplomaAgreementTask(diplomaTopicAgreementDTO);
}
@NoArgsConstructor
@Getter
@Setter
public static class DiplomaTopicAgreementDTO {
private String diplomaTopicName;
private Long diplomaTopicId;
}
}

View File

@ -1,4 +1,4 @@
package ru.mskobaro.tdms.integration.controller; package ru.mskobaro.tdms.presentation.controller;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
@ -6,7 +6,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import ru.mskobaro.tdms.business.service.TeacherDataService; import ru.mskobaro.tdms.business.service.TeacherDataService;
import ru.mskobaro.tdms.integration.controller.payload.TeacherDataDTO; import ru.mskobaro.tdms.presentation.controller.payload.TeacherDataDTO;
import java.util.List; import java.util.List;

View File

@ -1,4 +1,4 @@
package ru.mskobaro.tdms.integration.controller; package ru.mskobaro.tdms.presentation.controller;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -9,8 +9,8 @@ import org.springframework.web.bind.annotation.*;
import ru.mskobaro.tdms.business.entity.User; import ru.mskobaro.tdms.business.entity.User;
import ru.mskobaro.tdms.business.service.AuthenticationService; import ru.mskobaro.tdms.business.service.AuthenticationService;
import ru.mskobaro.tdms.business.service.UserService; import ru.mskobaro.tdms.business.service.UserService;
import ru.mskobaro.tdms.integration.controller.payload.LoginDTO; import ru.mskobaro.tdms.presentation.controller.payload.LoginDTO;
import ru.mskobaro.tdms.integration.controller.payload.UserDTO; import ru.mskobaro.tdms.presentation.controller.payload.UserDTO;
@RestController @RestController
@RequestMapping("/api/v1/user") @RequestMapping("/api/v1/user")

View File

@ -1,4 +1,4 @@
package ru.mskobaro.tdms.integration.controller.payload; package ru.mskobaro.tdms.presentation.controller.payload;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;

View File

@ -0,0 +1,39 @@
package ru.mskobaro.tdms.presentation.controller.payload;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.collections4.CollectionUtils;
import ru.mskobaro.tdms.business.entity.Defense;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;
@Getter
@Setter
public class DefenceDTO {
private Long id;
private List<CommissionMemberDTO> commissionMembers;
private List<GroupDTO> groups;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
public static DefenceDTO from(Defense defense) {
DefenceDTO dto = new DefenceDTO();
dto.setId(defense.getId());
if (CollectionUtils.isNotEmpty(defense.getCommissionMembers())) {
dto.setCommissionMembers(
defense.getCommissionMembers().stream()
.map(CommissionMemberDTO::from)
.collect(Collectors.toList())
);
}
dto.setGroups(defense.getGroups().stream().map(g -> GroupDTO.from(g, true)).toList());
dto.setCreatedAt(defense.getAuditInfo().getCreatedAt());
dto.setUpdatedAt(defense.getAuditInfo().getUpdatedAt());
return dto;
}
}

View File

@ -1,4 +1,4 @@
package ru.mskobaro.tdms.integration.controller.payload; package ru.mskobaro.tdms.presentation.controller.payload;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;

View File

@ -1,4 +1,4 @@
package ru.mskobaro.tdms.integration.controller.payload; package ru.mskobaro.tdms.presentation.controller.payload;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;

View File

@ -1,4 +1,4 @@
package ru.mskobaro.tdms.integration.controller.payload; package ru.mskobaro.tdms.presentation.controller.payload;
import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Pattern; import jakarta.validation.constraints.Pattern;
@ -30,7 +30,9 @@ public class GroupDTO {
dto.setId(group.getId()); dto.setId(group.getId());
dto.setName(group.getName()); dto.setName(group.getName());
if (includeStudents && group.getStudents() != null) { if (includeStudents && group.getStudents() != null) {
dto.setStudents(group.getStudents().stream() dto.setStudents(
group.getStudents()
.stream()
.filter(sd -> !sd.getParticipant().isDeleted()) .filter(sd -> !sd.getParticipant().isDeleted())
.map(sd -> StudentDataDTO.from(sd, false)) .map(sd -> StudentDataDTO.from(sd, false))
.toList()); .toList());

View File

@ -0,0 +1,14 @@
package ru.mskobaro.tdms.presentation.controller.payload;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@NoArgsConstructor
@Getter
@Setter
@ToString
public class IdDto {
private Long id;
}

View File

@ -1,4 +1,4 @@
package ru.mskobaro.tdms.integration.controller.payload; package ru.mskobaro.tdms.presentation.controller.payload;
import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Pattern; import jakarta.validation.constraints.Pattern;

View File

@ -1,15 +1,20 @@
package ru.mskobaro.tdms.integration.controller.payload; package ru.mskobaro.tdms.presentation.controller.payload;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.ToString;
import ru.mskobaro.tdms.business.entity.Participant; import ru.mskobaro.tdms.business.entity.Participant;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.util.List; import java.util.List;
@Getter @Getter
@Setter @Setter
// @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") @ToString
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class ParticipantDTO { public class ParticipantDTO {
private Long id; private Long id;
private String firstName; private String firstName;

View File

@ -1,4 +1,4 @@
package ru.mskobaro.tdms.integration.controller.payload; package ru.mskobaro.tdms.presentation.controller.payload;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import jakarta.validation.constraints.*; import jakarta.validation.constraints.*;
@ -33,8 +33,6 @@ public class ParticipantSaveDTO {
private StudentRegistrationDTO studentData; private StudentRegistrationDTO studentData;
@Valid @Valid
private TeacherRegistrationDTO teacherData; private TeacherRegistrationDTO teacherData;
@Valid
private CommMemDto commMemData;
@Getter @Getter
@ToString @ToString
@ -53,19 +51,6 @@ public class ParticipantSaveDTO {
private Long groupId; private Long groupId;
private Long curatorId; private Long curatorId;
private Long diplomaTopicId; private Long diplomaTopicId;
private Boolean electronic;
private Integer otziv;
private Integer preDefenseMark;
private Boolean normcontrol;
private Integer antiplagiarism;
private Boolean zachetka;
private String work;
private Boolean vnedreniye;
private Boolean otlichiye;
private Boolean magistracy;
private Long marks3;
private Long marks4;
private Long marks5;
} }
@Getter @Getter
@ -76,11 +61,4 @@ public class ParticipantSaveDTO {
private String degree; private String degree;
} }
@Getter
@ToString
public static class CommMemDto {
private String workPlace;
private String workPosition;
}
} }

View File

@ -1,4 +1,4 @@
package ru.mskobaro.tdms.integration.controller.payload; package ru.mskobaro.tdms.presentation.controller.payload;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@ -14,7 +14,6 @@ public class PreparationDirectionDTO {
private Long id; private Long id;
private String name; private String name;
private String code; private String code;
private TeacherDataDTO responsible;
private LocalDateTime createdAt; private LocalDateTime createdAt;
private LocalDateTime updatedAt; private LocalDateTime updatedAt;
@ -23,9 +22,6 @@ public class PreparationDirectionDTO {
dto.setId(preparationDirection.getId()); dto.setId(preparationDirection.getId());
dto.setName(preparationDirection.getName()); dto.setName(preparationDirection.getName());
dto.setCode(preparationDirection.getCode()); dto.setCode(preparationDirection.getCode());
if (preparationDirection.getResponsible() != null) {
dto.setResponsible(TeacherDataDTO.from(preparationDirection.getResponsible()));
}
dto.setCreatedAt(preparationDirection.getAuditInfo().getCreatedAt()); dto.setCreatedAt(preparationDirection.getAuditInfo().getCreatedAt());
dto.setUpdatedAt(preparationDirection.getAuditInfo().getUpdatedAt()); dto.setUpdatedAt(preparationDirection.getAuditInfo().getUpdatedAt());
return dto; return dto;

View File

@ -1,4 +1,4 @@
package ru.mskobaro.tdms.integration.controller.payload; package ru.mskobaro.tdms.presentation.controller.payload;
import ru.mskobaro.tdms.business.entity.Participant; import ru.mskobaro.tdms.business.entity.Participant;

View File

@ -0,0 +1,31 @@
package ru.mskobaro.tdms.presentation.controller.payload;
import lombok.Getter;
import lombok.Setter;
import ru.mskobaro.tdms.business.entity.StudentData;
@Setter
@Getter
public class StudentDataDTO {
private Long id;
private GroupDTO group;
private ParticipantDTO participant;
private TeacherDataDTO curator;
private DiplomaTopicDTO diplomaTopic;
public static StudentDataDTO from(StudentData studentData, boolean includeGroup) {
StudentDataDTO dto = new StudentDataDTO();
dto.setId(studentData.getId());
if (includeGroup && studentData.getGroup() != null) {
dto.setGroup(GroupDTO.from(studentData.getGroup(), false));
}
dto.setParticipant(ParticipantDTO.fromEntity(studentData.getParticipant()));
if (studentData.getCurator() != null) {
dto.setCurator(TeacherDataDTO.from(studentData.getCurator()));
}
if (studentData.getDiplomaTopic() != null) {
dto.setDiplomaTopic(DiplomaTopicDTO.from(studentData.getDiplomaTopic()));
}
return dto;
}
}

View File

@ -0,0 +1,33 @@
package ru.mskobaro.tdms.presentation.controller.payload;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import ru.mskobaro.tdms.business.entity.Task;
import ru.mskobaro.tdms.business.taskfields.TaskFields;
import java.time.LocalDateTime;
@NoArgsConstructor
@Getter
@Setter
public class TaskDto {
private Long id;
private Task.Type type;
private Task.Status status;
private TaskFields fields;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
public static TaskDto from(Task task) {
TaskDto dto = new TaskDto();
dto.setId(task.getId());
dto.setType(task.getType());
dto.setStatus(task.getStatus());
dto.setFields(task.getFields());
dto.setCreatedAt(task.getAuditInfo().getCreatedAt());
dto.setUpdatedAt(task.getAuditInfo().getUpdatedAt());
return dto;
}
}

View File

@ -1,4 +1,4 @@
package ru.mskobaro.tdms.integration.controller.payload; package ru.mskobaro.tdms.presentation.controller.payload;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;

View File

@ -1,4 +1,4 @@
package ru.mskobaro.tdms.integration.controller.payload; package ru.mskobaro.tdms.presentation.controller.payload;
import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.JsonIdentityInfo;
@ -7,6 +7,7 @@ import lombok.Builder;
import ru.mskobaro.tdms.business.entity.User; import ru.mskobaro.tdms.business.entity.User;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.ZonedDateTime;
@Builder @Builder

View File

@ -1,6 +1,5 @@
package ru.mskobaro.tdms.integration.exception; package ru.mskobaro.tdms.presentation.exception;
import jakarta.mail.SendFailedException;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.DefaultMessageSourceResolvable; import org.springframework.context.support.DefaultMessageSourceResolvable;
@ -12,15 +11,14 @@ import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.resource.NoResourceFoundException; import org.springframework.web.servlet.resource.NoResourceFoundException;
import ru.mskobaro.tdms.business.exception.AccessDeniedException; import ru.mskobaro.tdms.business.exception.AccessDeniedException;
import ru.mskobaro.tdms.business.exception.BusinessException; import ru.mskobaro.tdms.business.exception.BusinessException;
import ru.mskobaro.tdms.integration.controller.payload.ErrorDTO; import ru.mskobaro.tdms.presentation.controller.payload.ErrorDTO;
import java.util.Arrays;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.springframework.http.HttpStatus.NOT_FOUND;
import static org.springframework.http.HttpStatus.*; import static org.springframework.http.HttpStatus.*;
import static ru.mskobaro.tdms.integration.controller.payload.ErrorDTO.ErrorCode.*; import static org.springframework.http.HttpStatus.NOT_FOUND;
import static ru.mskobaro.tdms.presentation.controller.payload.ErrorDTO.ErrorCode.*;
@RestControllerAdvice @RestControllerAdvice
@Slf4j @Slf4j
@ -37,7 +35,7 @@ public class ApplicationExceptionHandler {
@ExceptionHandler(BusinessException.class) @ExceptionHandler(BusinessException.class)
public ErrorDTO handleBusinessException(BusinessException e, HttpServletResponse response) { public ErrorDTO handleBusinessException(BusinessException e, HttpServletResponse response) {
log.warn("Business error: ", e); log.warn("Business error: {}", e.getMessage());
response.setStatus(e.getErrorCode().getHttpStatus().value()); response.setStatus(e.getErrorCode().getHttpStatus().value());
return new ErrorDTO(e.getMessage(), e.getErrorCode()); return new ErrorDTO(e.getMessage(), e.getErrorCode());
} }
@ -72,18 +70,4 @@ public class ApplicationExceptionHandler {
log.error("Unexpected exception ({})", uuid, e); log.error("Unexpected exception ({})", uuid, e);
return new ErrorDTO("Идентификатор ошибки: (" + uuid + ")\роизошла непредвиденная ошибка, обратитесь к администратору", INTERNAL_ERROR); return new ErrorDTO("Идентификатор ошибки: (" + uuid + ")\роизошла непредвиденная ошибка, обратитесь к администратору", 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);
}
} }

View File

@ -1,27 +0,0 @@
package ru.mskobaro.tdms.system.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import java.util.Properties;
@Configuration
public class MailConfig {
@Bean
public JavaMailSender getJavaMailSender(
@Value("${application.smtp.host}") String smtpHost,
@Value("${application.smtp.port}") String smtpPort
) {
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost(smtpHost);
mailSender.setPort(Integer.parseInt(smtpPort));
Properties props = mailSender.getJavaMailProperties();
props.put("mail.transport.protocol", "smtp");
props.put("mail.debug", "true");
return mailSender;
}
}

View File

@ -31,7 +31,8 @@ import ru.mskobaro.tdms.system.web.LoggingRequestFilter;
import java.time.Duration; import java.time.Duration;
import java.util.List; import java.util.List;
import static ru.mskobaro.tdms.business.service.RoleService.Authority.*; import static ru.mskobaro.tdms.business.service.RoleService.Authority.ADMIN;
import static ru.mskobaro.tdms.business.service.RoleService.Authority.SECRETARY;
@Slf4j @Slf4j
@ -62,14 +63,16 @@ public class SecurityConfig {
@Bean @Bean
@Primary @Primary
public CorsConfigurationSource corsConfiguration( public CorsConfigurationSource corsConfiguration(
@Value("${application.domain}") String domain @Value("${application.domain}") String domain,
@Value("${application.port}") String port,
@Value("${application.protocol}") String protocol
) { ) {
CorsConfiguration corsConfiguration = new CorsConfiguration(); CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowedMethods(List.of(HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.OPTIONS.name())); corsConfiguration.setAllowedMethods(List.of(HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.OPTIONS.name()));
corsConfiguration.setAllowedHeaders(List.of("Authorization", "Content-Type")); corsConfiguration.setAllowedHeaders(List.of("Authorization", "Content-Type"));
corsConfiguration.setAllowCredentials(true); corsConfiguration.setAllowCredentials(true);
corsConfiguration.setMaxAge(Duration.ofDays(1)); corsConfiguration.setMaxAge(Duration.ofDays(1));
corsConfiguration.addAllowedOrigin(StringUtils.join("https", "://", domain)); corsConfiguration.addAllowedOrigin(StringUtils.join(protocol, "://", domain, ":", port));
if (environment.matchesProfiles("dev")) { if (environment.matchesProfiles("dev")) {
corsConfiguration.addAllowedOrigin("http://localhost:8888"); corsConfiguration.addAllowedOrigin("http://localhost:8888");
@ -112,8 +115,6 @@ public class SecurityConfig {
// Сложная логика авторизации, так что проверяем явно в ParticipantService // Сложная логика авторизации, так что проверяем явно в ParticipantService
httpAuthorization.requestMatchers("/api/v1/participant/save").authenticated(); httpAuthorization.requestMatchers("/api/v1/participant/save").authenticated();
httpAuthorization.requestMatchers("/api/v1/participant/delete").hasAuthority(ADMIN.getAuthority()); httpAuthorization.requestMatchers("/api/v1/participant/delete").hasAuthority(ADMIN.getAuthority());
httpAuthorization.requestMatchers("/api/v1/participant/get-all-antipl").permitAll();
httpAuthorization.requestMatchers("/api/v1/participant/get-all-norm").permitAll();
httpAuthorization.requestMatchers("/api/v1/group/get-all-groups").permitAll(); httpAuthorization.requestMatchers("/api/v1/group/get-all-groups").permitAll();
httpAuthorization.requestMatchers("/api/v1/group/save").hasAnyAuthority(ADMIN.getAuthority(), SECRETARY.getAuthority()); httpAuthorization.requestMatchers("/api/v1/group/save").hasAnyAuthority(ADMIN.getAuthority(), SECRETARY.getAuthority());
@ -121,8 +122,6 @@ public class SecurityConfig {
httpAuthorization.requestMatchers("/api/v1/student/by-partic-id").permitAll(); httpAuthorization.requestMatchers("/api/v1/student/by-partic-id").permitAll();
httpAuthorization.requestMatchers("/api/v1/student/all-without-group").permitAll(); httpAuthorization.requestMatchers("/api/v1/student/all-without-group").permitAll();
httpAuthorization.requestMatchers("/api/v1/student/by-id").permitAll();
httpAuthorization.requestMatchers("/api/v1/student/by-defense-id").permitAll();
httpAuthorization.requestMatchers("/api/v1/teacher-data/get-all").permitAll(); httpAuthorization.requestMatchers("/api/v1/teacher-data/get-all").permitAll();
httpAuthorization.requestMatchers("/api/v1/teacher-data/by-partic-id").permitAll(); httpAuthorization.requestMatchers("/api/v1/teacher-data/by-partic-id").permitAll();
@ -130,39 +129,11 @@ public class SecurityConfig {
httpAuthorization.requestMatchers("/api/v1/prep-direction/get-all").permitAll(); httpAuthorization.requestMatchers("/api/v1/prep-direction/get-all").permitAll();
httpAuthorization.requestMatchers("/api/v1/prep-direction/save").hasAnyAuthority(ADMIN.getAuthority(), SECRETARY.getAuthority()); httpAuthorization.requestMatchers("/api/v1/prep-direction/save").hasAnyAuthority(ADMIN.getAuthority(), SECRETARY.getAuthority());
httpAuthorization.requestMatchers("/api/v1/defense/get-all").permitAll(); httpAuthorization.requestMatchers("/api/v1/defence/all").permitAll();
httpAuthorization.requestMatchers("/api/v1/defense/get-by-id").permitAll();
httpAuthorization.requestMatchers("/api/v1/defense/save").permitAll();
httpAuthorization.requestMatchers("/api/v1/defense/defense-table").permitAll();
httpAuthorization.requestMatchers("/api/v1/defense/defense-table-save").hasAnyAuthority(ADMIN.getAuthority(), TEACHER.getAuthority());
httpAuthorization.requestMatchers("/api/v1/defense/to-next-state").hasAnyAuthority(ADMIN.getAuthority(), SECRETARY.getAuthority(), TEACHER.getAuthority());
httpAuthorization.requestMatchers("api/v1/defense/recreate-protection-order").hasAnyAuthority(ADMIN.getAuthority(), TEACHER.getAuthority());
httpAuthorization.requestMatchers("api/v1/defense/save-order").hasAnyAuthority(ADMIN.getAuthority(), TEACHER.getAuthority());
httpAuthorization.requestMatchers("/api/v1/task/create-topic-agreement").hasAuthority(STUDENT.getAuthority());
httpAuthorization.requestMatchers("/api/v1/task/diploma-agreement-maker").hasAuthority(STUDENT.getAuthority());
httpAuthorization.requestMatchers("/api/v1/task/notif-count").authenticated();
httpAuthorization.requestMatchers("/api/v1/task/get-current-tasks").authenticated();
httpAuthorization.requestMatchers("/api/v1/task/diploma-agreement-maker-by-partic-id").authenticated();
httpAuthorization.requestMatchers("/api/v1/task/topic-preparation-finish").hasAnyAuthority(TEACHER.getAuthority());
httpAuthorization.requestMatchers("/api/v1/task/agreement-change").hasAnyAuthority(STUDENT.getAuthority(), TEACHER.getAuthority());
httpAuthorization.requestMatchers("/api/v1/task/def-prep-finish").hasAnyAuthority(TEACHER.getAuthority());
httpAuthorization.requestMatchers("/api/v1/task/norm-antipl-finish").authenticated();
httpAuthorization.requestMatchers("/api/v1/diploma-topic/all").permitAll(); httpAuthorization.requestMatchers("/api/v1/diploma-topic/all").permitAll();
httpAuthorization.requestMatchers("/api/v1/diploma-topic/all-for-student").permitAll(); httpAuthorization.requestMatchers("/api/v1/diploma-topic/all-for-student").permitAll();
httpAuthorization.requestMatchers("/api/v1/diploma-topic/by-id").permitAll(); httpAuthorization.requestMatchers("/api/v1/diploma-topic/save").hasAnyAuthority(ADMIN.getAuthority(), SECRETARY.getAuthority());
httpAuthorization.requestMatchers("/api/v1/diploma-topic/save").hasAnyAuthority(ADMIN.getAuthority(), SECRETARY.getAuthority(), TEACHER.getAuthority());
httpAuthorization.requestMatchers("/api/v1/diploma-topic/matching-teacher-and-dir-prep").permitAll();
httpAuthorization.requestMatchers("/api/v1/home-page/default-info").permitAll();
httpAuthorization.requestMatchers("api/v1/commission-member/get-all").permitAll();
httpAuthorization.requestMatchers("api/v1/commission-member/by-partic-id").permitAll();
httpAuthorization.requestMatchers("api/v1/doc/gek-questions").permitAll();
httpAuthorization.requestMatchers("api/v1/doc/stud-list").permitAll();
httpAuthorization.requestMatchers("api/v1/doc/topic-list").permitAll();
httpAuthorization.requestMatchers("/api/**").denyAll(); httpAuthorization.requestMatchers("/api/**").denyAll();

View File

@ -11,13 +11,10 @@ import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID; import java.util.UUID;
@Slf4j @Slf4j
public class LoggingRequestFilter extends OncePerRequestFilter { public class LoggingRequestFilter extends OncePerRequestFilter {
@Override @Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
UUID uuid = UUID.randomUUID(); UUID uuid = UUID.randomUUID();
@ -25,12 +22,6 @@ public class LoggingRequestFilter extends OncePerRequestFilter {
String username = SecurityContextHolder.getContext().getAuthentication() != null ? String username = SecurityContextHolder.getContext().getAuthentication() != null ?
SecurityContextHolder.getContext().getAuthentication().getName() : "anonymousUser"; SecurityContextHolder.getContext().getAuthentication().getName() : "anonymousUser";
HttpSession session = request.getSession(false); HttpSession session = request.getSession(false);
if (request.getRequestURI().contains("notif-count") || request.getRequestURI().contains("get-current-tasks")) {
filterChain.doFilter(request, response);
return;
}
log.info("Request received: [{}] {} user: {}, session: {}, remote ip: {} [{}]", log.info("Request received: [{}] {} user: {}, session: {}, remote ip: {} [{}]",
request.getMethod(), request.getRequestURI(), username, request.getMethod(), request.getRequestURI(), username,
session == null ? "no" : session.getId(), request.getRemoteAddr(), uuid); session == null ? "no" : session.getId(), request.getRemoteAddr(), uuid);

View File

@ -49,20 +49,5 @@
"name": "application.protocol", "name": "application.protocol",
"type": "java.lang.String", "type": "java.lang.String",
"description": "Service protocol." "description": "Service protocol."
},
{
"name": "application.smtp.host",
"type": "java.lang.String",
"description": "SMTP server host."
},
{
"name": "application.smtp.port",
"type": "java.lang.String",
"description": "SMTP server port."
},
{
"name": "application.smtp.message-from",
"type": "java.lang.String",
"description": "Sender email."
} }
] } ] }

View File

@ -8,13 +8,8 @@ application:
version: @version@ version: @version@
type: production type: production
port: 443 port: 443
domain: vkr.tu-bryansk.ru domain: tdms.tu-bryansk.ru
host: localhost
protocol: https protocol: https
smtp:
host: localhost
port: 2525
message-from: admin@vkr.tu-bryansk.ru
spring: spring:
application: application:
@ -37,7 +32,7 @@ spring:
location: banner.txt location: banner.txt
server: server:
port: ${application.port} port: ${application.port}
address: ${application.host} address: ${application.domain}
compression: compression:
enabled: true enabled: true
management: management:

View File

@ -1,13 +1,15 @@
CREATE TABLE defense CREATE TABLE defense
( (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
defense_date DATE, defense_date DATE,
status TEXT NOT NULL, created_at TIMESTAMP WITHOUT TIME ZONE,
direction_of_preparation_id BIGINT, updated_at TIMESTAMP WITHOUT TIME ZONE
responsible_for_antiplagiarism_id BIGINT, );
responsible_for_normcontrol_id BIGINT,
created_at TIMESTAMP WITHOUT TIME ZONE, CREATE TABLE defense_best_student_works
updated_at TIMESTAMP WITHOUT TIME ZONE (
defense_id BIGINT,
student_data_id BIGINT
); );
CREATE TABLE defense_commission CREATE TABLE defense_commission
@ -28,12 +30,11 @@ CREATE TABLE diploma_topic
CREATE TABLE direction_of_preparation CREATE TABLE direction_of_preparation
( (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
name TEXT, name TEXT,
code TEXT, code TEXT,
responsible_id BIGINT, created_at TIMESTAMP WITHOUT TIME ZONE,
created_at TIMESTAMP WITHOUT TIME ZONE, updated_at TIMESTAMP WITHOUT TIME ZONE
updated_at TIMESTAMP WITHOUT TIME ZONE
); );
CREATE TABLE "group" CREATE TABLE "group"
@ -72,6 +73,7 @@ CREATE TABLE role
authority TEXT authority TEXT
); );
/* todo */
CREATE TABLE student_data CREATE TABLE student_data
( (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
@ -82,42 +84,30 @@ CREATE TABLE student_data
protection_order INTEGER, protection_order INTEGER,
protection_day INTEGER, protection_day INTEGER,
mark_comment INTEGER,
mark_practice INTEGER, mark_practice INTEGER,
predefnese_mark INTEGER,
oztiv_mark INTEGER,
predefnese_comment TEXT,
normal_control BOOLEAN, normal_control BOOLEAN,
anti_plagiarism INTEGER, anti_plagiarism INTEGER,
record_book_returned BOOLEAN, record_book_returned BOOLEAN,
work TEXT, work TEXT,
diploma_topic_id BIGINT, diploma_topic_id BIGINT,
adviser_teacher_partic_id BIGINT, adviser_teacher_partic_id BIGINT,
group_id BIGINT, group_id BIGINT,
marks_3 BIGINT, marks_3 BIGINT,
marks_4 BIGINT, marks_4 BIGINT,
marks_5 BIGINT, marks_5 BIGINT,
commission_mark BIGINT, commission_mark BIGINT,
estimated BOOLEAN, estimated BOOLEAN,
diploma_with_honors BOOLEAN, diploma_with_honors BOOLEAN,
vnedreniye BOOLEAN,
magistracy_recommendation BOOLEAN, magistracy_recommendation BOOLEAN,
magistracy_wanted BOOLEAN, magistracy_wanted BOOLEAN,
electronic BOOLEAN,
created_at TIMESTAMP WITHOUT TIME ZONE, created_at TIMESTAMP WITHOUT TIME ZONE,
updated_at TIMESTAMP WITHOUT TIME ZONE updated_at TIMESTAMP WITHOUT TIME ZONE
); );
/* not implemented */
create table questionnaire create table questionnaire
( (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
@ -135,6 +125,7 @@ create table study_form
updated_at TIMESTAMP WITHOUT TIME ZONE updated_at TIMESTAMP WITHOUT TIME ZONE
); );
/* todo */
create table stud_comment create table stud_comment
( (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
@ -143,6 +134,7 @@ create table stud_comment
updated_at TIMESTAMP WITHOUT TIME ZONE updated_at TIMESTAMP WITHOUT TIME ZONE
); );
/* todo */
create table student_data_comment create table student_data_comment
( (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
@ -181,34 +173,14 @@ CREATE TABLE "user"
updated_at TIMESTAMP WITHOUT TIME ZONE updated_at TIMESTAMP WITHOUT TIME ZONE
); );
CREATE TABLE task CREATE TABLE task
( (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
status TEXT, type TEXT,
type TEXT, status TEXT,
defense_id BIGINT, fields jsonb,
maker_partic_id BIGINT, created_at TIMESTAMP WITHOUT TIME ZONE,
checker_partic_id BIGINT, updated_at TIMESTAMP WITHOUT TIME ZONE
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 ALTER TABLE defense_commission
@ -229,6 +201,9 @@ ALTER TABLE participant_role
ALTER TABLE participant_role ALTER TABLE participant_role
ADD CONSTRAINT FK_PARROL_ON_ROLE FOREIGN KEY (role_id) REFERENCES role (id) ON DELETE CASCADE ON UPDATE CASCADE; ADD CONSTRAINT FK_PARROL_ON_ROLE FOREIGN KEY (role_id) REFERENCES role (id) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE student_data
ADD CONSTRAINT UC_STUDENT_DATA_PARTIC UNIQUE (partic_id);
ALTER TABLE student_data ALTER TABLE student_data
ADD CONSTRAINT FK_STUDENT_DATA_ON_ADVISER_TEACHER_PARTIC FOREIGN KEY (adviser_teacher_partic_id) REFERENCES participant (id) ON DELETE SET NULL ON UPDATE CASCADE; ADD CONSTRAINT FK_STUDENT_DATA_ON_ADVISER_TEACHER_PARTIC FOREIGN KEY (adviser_teacher_partic_id) REFERENCES participant (id) ON DELETE SET NULL ON UPDATE CASCADE;
@ -277,6 +252,12 @@ ALTER TABLE direction_of_preparation
ALTER TABLE diploma_topic ALTER TABLE diploma_topic
ADD CONSTRAINT UC_DIPLOMA_TOPIC_NAME FOREIGN KEY (direction_of_preparation_id) REFERENCES direction_of_preparation (id) ON DELETE SET NULL ON UPDATE CASCADE; ADD CONSTRAINT UC_DIPLOMA_TOPIC_NAME FOREIGN KEY (direction_of_preparation_id) REFERENCES direction_of_preparation (id) ON DELETE SET NULL ON UPDATE CASCADE;
ALTER TABLE defense_best_student_works
ADD CONSTRAINT FK_DEFENSE_BEST_STUDENT_WORKS_ON_DEFENSE FOREIGN KEY (defense_id) REFERENCES defense (id) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE defense_best_student_works
ADD CONSTRAINT FK_DEFENSE_BEST_STUDENT_WORKS_ON_STUDENT_DATA FOREIGN KEY (student_data_id) REFERENCES student_data (id) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE stud_comment ALTER TABLE stud_comment
ADD CONSTRAINT UC_STUD_COMMENT_COMMENT UNIQUE (comment); ADD CONSTRAINT UC_STUD_COMMENT_COMMENT UNIQUE (comment);
@ -296,19 +277,4 @@ alter table questionnaire
add constraint UC_QUESTIONNAIRE_STUDENT_DATA_ID unique (student_data_id); add constraint UC_QUESTIONNAIRE_STUDENT_DATA_ID unique (student_data_id);
alter table questionnaire alter table questionnaire
add constraint FK_QUESTIONNAIRE_STUDENT_DATA foreign key (student_data_id) references student_data (id) on delete cascade on update cascade; add constraint FK_QUESTIONNAIRE_STUDENT_DATA foreign key (student_data_id) references student_data (id) on delete cascade on update cascade;
alter table direction_of_preparation
add constraint FK_RESPONSIBLE FOREIGN KEY (responsible_id) REFERENCES teacher_data (id) ON DELETE CASCADE ON UPDATE CASCADE;
alter table defense
add constraint FK_RESPONSIBLE_NORM FOREIGN KEY (responsible_for_normcontrol_id) REFERENCES participant (id) ON DELETE CASCADE ON UPDATE CASCADE;
alter table defense
add constraint FK_RESPONSIBLE_ANTIPLAGIARISM FOREIGN KEY (responsible_for_antiplagiarism_id) REFERENCES participant (id) ON DELETE CASCADE ON UPDATE CASCADE;
alter table task
add constraint FK_DEFENSE FOREIGN KEY (defense_id) REFERENCES defense (id) ON DELETE CASCADE ON UPDATE CASCADE;
alter table defense
add constraint FK_DIR_OF_PRERP FOREIGN KEY (direction_of_preparation_id) REFERENCES direction_of_preparation (id) ON DELETE CASCADE ON UPDATE CASCADE;

View File

@ -1,97 +0,0 @@
-- TOPIC_LIST_PREPARE_START_FOR_TEACHER,
--
-- TOPIC_CHOOSE_FOR_STUDENT,
-- TOPIC_CHOOSE_FOR_TEACHER,
--
-- TASK_CREATE_FOR_TEACHER,
-- TASK_ASSIGN_FOR_TEACHER,
--
-- PRE_DIPLOMA_PRACTICE_START_FOR_TEACHER,
-- PRE_DIPLOMA_PRACTICE_START_FOR_STUDENT,
--
-- TOPIC_FINALIZATION_FOR_TEACHER,
--
-- PRE_DEFENSE_FOR_STUDENT,
--
-- ANTIPLAGIARISM_FOR_STUDENT,
--
-- DEFENSE_PREPARATION_FOR_STUDENT,
--
-- MAIN_VRK_WORK_START,
--
-- NORMCONTROL_AND_ANTIPLAGIARISM,
--
-- DEFENSE,
--
-- DEFENSE_PREPARATION_FOR_TEACHER,
INSERT INTO message_template (message_type,
subject_template,
message_template,
created_at,
updated_at)
VALUES ('TOPIC_LIST_PREPARE_START_FOR_TEACHER',
'Подготовка списка тем для студентов',
E'Уважаемый $${ФИО_НАУЧ_РУК},\nпросим вас подготовить и отправить список тем для выбора студентами.\n\nС уважением, администрация.',
NOW(),
NOW()),
('TOPIC_CHOOSE_FOR_STUDENT',
'Выбор темы для работы',
E'Уважаемый $${ФИО_СТУД},\nПожалуйста, выберите тему вашей работы из предложенного списка до конца недели.\n\nС уважением, администрация.',
NOW(),
NOW()),
('TOPIC_CHOOSE_FOR_TEACHER',
'Утверждение выбора тем студентами',
E'Уважаемый $${ФИО_НАУЧ_РУК},\nСтуденты начали выбор тем.\nПросим вас утвердить.\n\nС уважением, администрация.',
NOW(),
NOW()),
('TASK_CREATE_FOR_TEACHER',
'Создание задания для студента',
E'Уважаемый $${ФИО_НАУЧ_РУК},\nПросим вас создать задание для студента $${ФИО_СТУД}.\n\nС уважением, администрация.',
NOW(),
NOW()),
('TASK_ASSIGN_FOR_TEACHER',
'Назначение задания студенту',
E'Уважаемый $${ФИО_НАУЧ_РУК},\nЗадание для студента $${ФИО_СТУД} назначено. Просим вас проконтролировать выполнение.\n\nС уважением, администрация.',
NOW(),
NOW()),
('PRE_DIPLOMA_PRACTICE_START_FOR_TEACHER',
'Начало преддипломной практики',
E'Уважаемый $${ФИО_НАУЧ_РУК},\nПреддипломная практика для студента $${ФИО_СТУД} начинается. Просим вас обеспечить руководство.\n\nС уважением, администрация.',
NOW(),
NOW()),
('PRE_DIPLOMA_PRACTICE_START_FOR_STUDENT',
'Начало преддипломной практики',
E'Уважаемый $${ФИО_СТУД}, ваша\nПреддипломная практика начинается. Свяжитесь с научным руководителем $${ФИО_НАУЧ_РУК} для получения инструкций.\n\nС уважением, администрация.',
NOW(),
NOW()),
('TOPIC_FINALIZATION_FOR_TEACHER',
'Окончательное утверждение темы',
E'Уважаемый $${ФИО_НАУЧ_РУК},\nПросим вас окончательно утвердить тему работы студента $${ФИО_СТУД} до указанного срока.\n\nС уважением, администрация.',
NOW(),
NOW()),
('PRE_DEFENSE_FOR_TEACHER',
'Подготовка к предзащите',
E'Уважаемый $${ФИО_НАУЧ_РУК},\nПредзащита работы студента $${ФИО_СТУД} назначена. Просим вас подготовить необходимые материалы.\n\nС уважением, администрация.',
NOW(),
NOW()),
('PRE_DEFENSE_FOR_STUDENT',
'Подготовка к предзащите',
E'Уважаемый $${ФИО_СТУД},\nВаша предзащита назначена. Подготовьте материалы и согласуйте с $${ФИО_НАУЧ_РУК}.\n\nС уважением, администрация.',
NOW(),
NOW()),
('ANTIPLAGIARISM_FOR_STUDENT',
'Проверка работы на антиплагиат',
E'Уважаемый $${ФИО_СТУД},\nЗагрузите вашу работу в систему антиплагиата до указанного срока. Обратитесь к $${ФИО_НАУЧ_РУК} при необходимости.\n\nС уважением, администрация.',
NOW(),
NOW()),
('DEFENSE_PREPARATION_FOR_STUDENT',
'Подготовка к защите',
E'Уважаемый $${ФИО_СТУД},\nЗащита вашей работы приближается. Подготовьте презентацию и согласуйте с $${ФИО_НАУЧ_РУК}.\n\nС уважением, администрация.',
NOW(),
NOW()),
('DEFENSE_PREPARATION_FOR_TEACHER',
'Подготовка к защите студента',
E'Уважаемый $${ФИО_НАУЧ_РУК},\nЗащита работы студента $${ФИО_СТУД} назначена. Просим вас проконтролировать подготовку и оставить отзыв по работе студента.\n\nС уважением, администрация.',
NOW(),
NOW());

View File

@ -0,0 +1,12 @@
create table defense
(
id bigserial primary key,
defence_date timestamptz,
created_at timestamptz not null,
updated_at timestamptz
);
-- COMMENTS
comment on table defense is 'Таблица для хранения данных о защитах';
comment on column defense.defence_date is 'Дата защиты';

View File

@ -0,0 +1,40 @@
INSERT INTO diploma_topic (name)
VALUES ('Мобильное приложение для заказа автозапчастей на платформе ABCP'),
('Подсистема уведомления пользователей для программного комплекса "РискПроф. Учебный центр"'),
('Веб-приложение "Таск-менеджер"'),
('Интернет-магазин электроники'),
('Информационная система для студентов БГТУ в Telegram'),
('Автоматизированная система тестирования сотрудников для определения их компетенций: модуль подготовки тестов и учета результатов'),
('Инструментарий для разработки динамической экосистемы игрового пространства. Подсистема управления поведением внутриигровых агентов'),
('Корпоративное веб-приложение по управлению задачами'),
('Подсистемы визуализации и аналитики для онлайн-сервиса поддержки scrum-доски'),
('Интерактивная система обучения приемам работы с криптовалютой'),
('Автоматизированная система учета деятельности салона по продаже автомобилей'),
('Обучающее мобильное android-приложение'),
('Автоматизированная система учета зуботехнической CAD/CAM лаборатории'),
('Автоматизированная система тестирования сотрудников для определения их компетенций: модуль регистрации и управления кабинетами'),
('Система мониторинга успеваемости обучающихся и посещаемости занятий образовательного учреждения'),
('Мобильное приложение для организации работы репетитора'),
('Модуль "Редактор рисков" для программного комплекса управления профессиональными рисками "1С. ЕОС ПБ"'),
('Онлайн-сервис по продаже товаров (на примере ООО «ЭПК-2»'),
('Веб-сервис по обучению Microsoft Excel'),
('Инструментарий для разработки динамической экосистемы игрового пространства. Подсистема генерации наполнения помещений'),
('Подсистема интеграции с федеральной государственной информационной системой по охране труда для программного комплекса «РискПроф. Учебный центр»'),
('Разработка приложения голосовой авторизации на основе нейросетевого подхода'),
('Автоматизированная система учета деятельности спортивного клуба'),
('Модуль "Специальная оценка условий труда" для программного комплекса управления профессиональными рисками "1С. ЕОС ПБ"'),
('Интернет-магазин по продаже спортивной обуви'),
('Приложение интерактивной исторической карты'),
('Миграция системы учёта с 1С:УТ на 1С:КА'),
('Программный комплекс для автоматизированного проведения опросов и тестирования пользователей'),
('Автоматизированное тестирование программного комплекса «Федеральная государственная информационная система специальной оценки условий труда»'),
('Модуль "Единая информационно-справочная подсистема" для федеральной государственной информационной системы по охране труда'),
('Подсистема сопровождения обучения по охране труда для программного комплекса «РискПроф. Учебный центр»'),
('Программное обеспечение системы обучения и тестирования в мессенджере Telegram'),
('Онлайн-калькулятор индексов влияния в играх взвешенного голосования'),
('Telegram-бот с функциями обработки изображений'),
('Подсистема администрирования автоматизированной системы для проведения платежей и перевода денежных средств'),
('Подсистема администрирования для программного комплекса распределения студентов по руководителям выпускных квалификационных работ'),
('Библиотека контроля качества данных в базах и хранилищах данных для программного комплекса MetaControl'),
('Инструментарий для разработки динамической экосистемы игрового пространства. Подсистема генерации карты помещений'),
('Программная система решения транспортной задачи методом генетического алгоритма для торговой сети');

View File

@ -0,0 +1,3 @@
INSERT INTO "group" (name, curator_teacher_id, created_at, updated_at)
VALUES ('ИВТ-1', 40, now(), now()),
('ИВТ-2', 40, now(), now());

View File

@ -0,0 +1,98 @@
do
$$
begin
INSERT INTO studentData (form,
protection_order,
magistracy,
digital_format_present,
mark_comment,
mark_practice,
predefence_comment,
normal_control,
anti_plagiarism,
note,
record_book_returned,
work,
user_id,
diploma_topic_id,
mentor_user_id,
group_id,
created_at)
VALUES (true, 1100, 'ПРИ, ИВТ или другой вуз', true, 5, 5, 'ок', 'Подписано', 7862, 'Акт о внедрении', true,
'нет', 1, 1, 40, 3, now()),
(true, 1110, 'Да, но не уверен, в БГТУ ли', true, 5, 5, 'ок', 'Подписано', 8196,
'Заявка, Акт о внедрении', true, 'ООО "ЦИРОБЗ"', 2, 2, 40, 3, now()),
(true, 3500, 'Нет', true, 3, 3,
'Критически низкий уровень. Допущен под ответственность руководителя ВКР', 'Подписано', 7141, 'Иниц',
true, 'нет', 3, 3, 41, 3, now()),
(true, 1800, 'Да, но не уверен, в БГТУ ли', true, 4, 5, 'Усилить работу', 'Подписано', 5381, 'Иниц',
true, 'нет', 4, 4, 42, 3, now()),
(true, 2100, 'ИВТ, ПРИ', true, 5, 5, 'ок', 'Подписано', 8146, 'Заявка, Акт о внедрении', true, 'нет', 5,
5, 43, 3, now()),
(true, 1100, 'ИВТ, ПРИ', true, 5, 5, 'ок', 'Подписано', 7965, 'Иниц', true, 'нет', 6, 6, 41, 3, now()),
(true, 1200, 'нет', true, 5, 4, 'Усилить работу', 'Подписано', 8583, Null, true,
'Газ Энерго Комплект (ГЭК)', 7, 7, 44, 3, now()),
(true, 1700, 'Нет', true, 5, 5,
'Критически низкий уровень. Допущен под ответственность руководителя ВКР', 'Подписано', 6647, Null,
true, 'нет', 8, 8, 45, 3, now()),
(true, 3300, 'ИВТ, ПРИ или другой вуз', true, 5, 5, 'Усилить работу', 'Подписано', 6741,
'Заявка, Акт о внедрении', true, 'нет', 9, 9, 46, 3, now()),
(true, 1200, 'ИВТ', true, 5, 5, 'ок', 'Подписано', 7645, 'Заявка, Акт о внедрении', true, 'нет', 10, 10,
40, 3, now()),
(true, 3700, 'нет', true, 3, 3,
'Критически низкий уровень. Допущен под ответственность руководителя ВКР', '1', 3093, 'Иниц', true,
'нет', 11, 11, 45, 3, now()),
(true, 1900, 'Нет', true, 5, 5, 'ок', 'Подписано', 8175, 'Заявка, Акт о внедрении', true, 'нет', 12, 12,
42, 3, now()),
(true, 3200, 'ИВТ', true, 5, 5, 'Усилить работу', 'Подписано', 7805, 'Акт', true, 'нет', 13, 13, 46, 3,
now()),
(true, 1200, 'ИВТ, ПРИ', true, 4, 4, 'ок', 'рек', 7590, 'Иниц', true, 'нет', 14, 14, 45, 3, now()),
(true, 3900, 'нет', true, 5, 5, 'Усилить работу', 'Подписано', 6463, 'Заявка, Акт о внедрении', true,
'нет', 15, 15, 40, 3, now()),
(true, 2200, 'ИВТ', true, 5, 5, 'ок', 'Подписано', 7441, Null, true, 'ООО "ЦИРОБЗ"', 16, 16, 44, 3,
now()),
(true, 1130, 'Нет', true, 5, 4,
'Критически низкий уровень. Допущен под ответственность руководителя ВКР', 'Подписано', 7319,
'Заявка, Акт о внедрении', true, 'нет', 17, 17, 40, 3, now()),
(true, 2400, 'ИВТ', true, 4, 5, 'ок', 'Подписано', 6436, Null, true, 'нет', 18, 18, 45, 3, now()),
(true, 1600, 'ИВТ', true, 5, 5, 'Усилить работу', 'Подписано', 6227, 'Исслед', true, 'АО "БЭМЗ"', 19, 19,
47, 3, now()),
(true, 1400, 'Нет', true, 5, 5, 'ок', 'Подписано', 8935, 'Иниц', true, 'ООО "ЦИРОБЗ"', 20, 20, 44, 4,
now()),
(true, 2900, 'ИВТ', true, 5, 5, 'ок', 'Подписано', 7971, 'Заявка, Акт о внедрении', true, 'нет', 21, 21,
40, 4, now()),
(true, 2600, 'ИВТ, ПРИ', true, 3, 3, 'ок', 'Подписано', 7284, Null, true, 'нет', 22, 22, 48, 4, now()),
(true, 3100, 'ИВТ, ПРИ', true, 5, 5, 'Усилить работу', 'Подписано', 4966, 'Заявка, Акт о внедрении',
true, 'нет', 23, 23, 45, 4, now()),
(true, 3110, 'Нет', true, 5, 5, 'ок', 'Подписано', 7174, Null, true, 'нет', 24, 24, 40, 4, now()),
(true, 3800, 'Нет', true, 5, 5, 'ок', 'Подписано', 7233, Null, true, 'нет', 25, 25, 45, 4, now()),
(true, 3300, 'ИВТ', true, 5, 5, 'ок', 'Подписано', 7133, Null, true, 'нет', 26, 26, 43, 4, now()),
(true, 3130, 'ИВТ', true, 5, 5, 'ок', 'Подписано', 8083, 'Заявка, Акт о внедрении', true, 'нет', 27, 27,
49, 4, now()),
(true, 3400, 'Нет', true, 5, 4,
'Критически низкий уровень. Допущен под ответственность руководителя ВКР', 'Подписано', 7968, 'Иниц',
true, 'нет', 28, 28, 50, 4, now()),
(true, 3120, 'ИВТ или ПРИ', true, 5, 5, 'ок', 'Подписано', 7940, 'Исслед', true, 'ООО "ЦИРОБЗ"', 29, 29,
40, 4, now()),
(true, 2800, 'Нет (возможно)', true, 4, 4, 'Усилить работу', 'рек', 6775, 'Заявка, Акт о внедрении',
true, 'нет', 30, 30, 40, 4, now()),
(true, 2100, 'Нет (возможно)', true, 5, 5, 'ок', 'Подписано', 7637, 'Заявка, Акт о внедрении', true,
'нет', 31, 31, 40, 4, now()),
(true, 2700, 'ИВТ', true, 5, 5, 'ок', 'Подписано', 8544, 'Заявка, Акт о внедрении', true, 'нет', 32, 32,
45, 4, now()),
(true, 2130, 'ИВТ, ПРИ', true, 5, 5, 'ок', 'Подписано', 7166, 'Заявка, Акт о внедрении', true, 'нет', 33,
33, 51, 4, now()),
(true, 2110, 'ИВТ', true, 5, 5, 'ок', 'Подписано', 6075, 'Заявка, Акт о внедрении', true, 'нет', 34, 34,
52, 4, now()),
(true, 3100, 'ИВТ', true, 5, 5, 'ок', 'Подписано', 7057, 'Заявка, Акт о внедрении', true, 'нет', 35, 35,
50, 4, now()),
(true, 2120, 'В БГТУ на другой кафедре (38.04.01 Экономика или 27.04.05. Инноватика)', true, 5, 5, 'ок',
'Подписано', 7057, 'Заявка, Акт о внедрении', true, 'нет', 36, 36, 51, 4, now()),
(true, 2500, 'ИВТ', true, 5, 5, 'ок', 'Подписано', 6583, 'Заявка, Акт о внедрении', true, 'нет', 37, 37,
53, 4, now()),
(true, 1300, 'ИВТ, ПРИ', true, 5, 5, 'ок', 'Подписано', 8444, 'Заявка, Акт о внедрении', true, 'нет', 38,
38, 44, 4, now()),
(true, 3600, 'ИВТ', true, 5, 5, 'ок', 'Подписано', 7631, 'Заявка, Акт о внедрении', true, 'нет', 39, 39,
45, 4, now());
end
$$;

View File

@ -0,0 +1,82 @@
INSERT INTO "user" (login, password, full_name, mail, number_phone, created_at)
VALUES ('akulenko_mikhail', '{noop}1', 'Акуленко Михаил Вячеславович', 'akulenko.mikhail@example.com',
'+79110000001', NOW()),
('borovikov_artem', '{noop}1', 'Боровиков Артём Викторович', 'borovikov.artem@example.com', '+79110000002',
NOW()),
('bykonya_alexey', '{noop}1', 'Быконя Алексей Николаевич', 'bykonya.alexey@example.com', '+79110000003',
NOW()),
('ermakov_alexander', '{noop}1', 'Ермаков Александр Сергеевич', 'ermakov.alexander@example.com',
'+79110000004', NOW()),
('zgursky_evgeny', '{noop}1', 'Згурский Евгений Олегович', 'zgursky.evgeny@example.com', '+79110000005',
NOW()),
('ibishov_tural', '{noop}1', 'Ибишов Турал Садай оглы', 'ibishov.tural@example.com', '+79110000006', NOW()),
('ignatenko_vladimir', '{noop}1', 'Игнатенко Владимир Алексеевич', 'ignatenko.vladimir@example.com',
'+79110000007', NOW()),
('lazukin_danila', '{noop}1', 'Лазукин Данила Дмитриевич', 'lazukin.danila@example.com', '+79110000008',
NOW()),
('mitiaev_danila', '{noop}1', 'Митяев Данила Алексеевич', 'mitiaev.danila@example.com', '+79110000009',
NOW()),
('neshkov_daniil', '{noop}1', 'Нешков Даниил Владимирович', 'neshkov.daniil@example.com', '+79110000010',
NOW()),
('petrov_pavel', '{noop}1', 'Петров Павел Сергеевич', 'petrov.pavel@example.com', '+79110000011', NOW()),
('sazonov_andrey', '{noop}1', 'Сазонов Андрей Андреевич', 'sazonov.andrey@example.com', '+79110000012',
NOW()),
('solokhin_maxim', '{noop}1', 'Солохин Максим Николаевич', 'solokhin.maxim@example.com', '+79110000013',
NOW()),
('sochinsky_artem', '{noop}1', 'Сочинский Артем Александрович', 'sochinsky.artem@example.com',
'+79110000014', NOW()),
('trisvyatsky_kirill', '{noop}1', 'Трисвятский Кирилл Андреевич', 'trisvyatsky.kirill@example.com',
'+79110000015', NOW()),
('turov_alexander', '{noop}1', 'Туров Александр Сергеевич', 'turov.alexander@example.com', '+79110000016',
NOW()),
('shevtsova_alexandra', '{noop}1', 'Шевцова Александра Валерьевна', 'shevtsova.alexandra@example.com',
'+79110000017', NOW()),
('kibalyuk_artem', '{noop}1', 'Кибалюк Артем Сергеевич', 'kibalyuk.artem@example.com', '+79110000018', NOW()),
('shulindin_artem', '{noop}1', 'Шулындин Артём Андреевич', 'shulindin.artem@example.com', '+79110000019',
NOW()),
('belyaev_egor', '{noop}1', 'Беляев Егор Андреевич', 'belyaev.egor@example.com', '+79110000020', NOW()),
('berezhnoy_igor', '{noop}1', 'Бережной Игорь Александрович', 'berezhnoy.igor@example.com', '+79110000021',
NOW()),
('bogun_pavel', '{noop}1', 'Богун Павел Сергеевич', 'bogun.pavel@example.com', '+79110000022', NOW()),
('vaseykin_nikita', '{noop}1', 'Васейкин Никита Павлович', 'vaseykin.nikita@example.com', '+79110000023',
NOW()),
('gomonov_nikita', '{noop}1', 'Гомонов Никита Алексеевич', 'gomonov.nikita@example.com', '+79110000024',
NOW()),
('druyan_oleg', '{noop}1', 'Друян Олег Викторович', 'druyan.oleg@example.com', '+79110000025', NOW()),
('ivanov_kirill', '{noop}1', 'Иванов Кирилл Эдуардович', 'ivanov.kirill@example.com', '+79110000026', NOW()),
('ivanova_veronika', '{noop}1', 'Иванова Вероника Евгеньевна', 'ivanova.veronika@example.com',
'+79110000027', NOW()),
('izotov_ivan', '{noop}1', 'Изотов Иван Алексеевич', 'izotov.ivan@example.com', '+79110000028', NOW()),
('isakov_zahar', '{noop}1', 'Исаков Захар Александрович', 'isakov.zahar@example.com', '+79110000029', NOW()),
('iskritsky_daniil', '{noop}1', 'Искрицкий Даниил Павлович', 'iskritsky.daniil@example.com', '+79110000030',
NOW()),
('linko_daria', '{noop}1', 'Линько Дарья Андреевна', 'linko.daria@example.com', '+79110000031', NOW()),
('logutov_kirill', '{noop}1', 'Логутов Кирилл Александрович', 'logutov.kirill@example.com', '+79110000032',
NOW()),
('nekrassov_sergey', '{noop}1', 'Некрасов Сергей Игоревич', 'nekrassov.sergey@example.com', '+79110000033',
NOW()),
('sinyagin_ilya', '{noop}1', 'Синягин Илья Александрович', 'sinyagin.ilya@example.com', '+79110000034',
NOW()),
('sopriko_daniil', '{noop}1', 'Соприко Даниил Сергеевич', 'sopriko.daniil@example.com', '+79110000035',
NOW()),
('turovsky_ivan', '{noop}1', 'Туровский Иван Алексеевич', 'turovsky.ivan@example.com', '+79110000036', NOW()),
('frantsev_sergey', '{noop}1', 'Францев Сергей Дмитриевич', 'frantsev.sergey@example.com', '+79110000037',
NOW()),
('chepurnoy_maxim', '{noop}1', 'Чепурной Максим Романович', 'chepurnoy.maxim@example.com', '+79110000038',
NOW()),
('schemelinin_dmitry', '{noop}1', 'Щемелинин Дмитрий Михайлович', 'schemelinin.dmitry@example.com',
'+79110000039', NOW()),
('bulatitsky_d_i_1', '{noop}1', 'Булатицкий Д. И.', 'bulatitsky.d.i.1@example.com', '+79110000040', NOW()),
('kopeliovich_d_i_1', '{noop}1', 'Копелиович Д. И.', 'kopeliovich.d.i.1@example.com', '+79110000041', NOW()),
('dergachev_k_v', '{noop}1', 'Дергачев К. В.', 'dergachev.k.v@example.com', '+79110000042', NOW()),
('trubakov_e_o', '{noop}1', 'Трубаков Е. О.', 'trubakov.e.o@example.com', '+79110000043', NOW()),
('radchenko_a_o', '{noop}1', 'Радченко А. О.', 'radchenko.a.o@example.com', '+79110000044', NOW()),
('zimin_s_n_1', '{noop}1', 'Зимин С. Н.', 'zimin.s.n.1@example.com', '+79110000045', NOW()),
('koptenok_e_v', '{noop}1', 'Коптенок Е. В.', 'koptenok.e.v@example.com', '+79110000046', NOW()),
('mikhaleva_o_a', '{noop}1', 'Михалева О. А.', 'mikhaleva.o.a@example.com', '+79110000047', NOW()),
('gulakov_k_v', '{noop}1', 'Гулаков К. В.', 'gulakov.k.v@example.com', '+79110000048', NOW()),
('titarev_d_v', '{noop}1', 'Титарёв Д. В.', 'titarev.d.v@example.com', '+79110000049', NOW()),
('izrailev_v_ya_1', '{noop}1', 'Израилев В. Я.', 'izrailev.v.ya.1@example.com', '+79110000050', NOW()),
('podvesovsky_a_g_1', '{noop}1', 'Подвесовский А. Г.', 'podvesovsky.a.g.1@example.com', '+79110000051', NOW()),
('trubakov_a_o', '{noop}1', 'Трубаков А. О.', 'trubakov.a.o@example.com', '+79110000059', NOW()),
('lageriev_d_g', '{noop}1', 'Лагерев Д. Г.', 'lageriev.d.g@example.com', '+79110000052', NOW());

View File

@ -0,0 +1,58 @@
do
$$
declare
teacher_id bigint := 1;
student_id bigint := 2;
commission_member_id bigint := 3;
administrator_id bigint := 4;
secretary_id bigint := 5;
begin
INSERT INTO user_role (user_id, role_id)
VALUES (1, student_id),
(2, student_id),
(3, student_id),
(4, student_id),
(5, student_id),
(6, student_id),
(7, student_id),
(8, student_id),
(9, student_id),
(10, student_id),
(11, student_id),
(12, student_id),
(13, student_id),
(14, student_id),
(15, student_id),
(16, student_id),
(17, student_id),
(18, student_id),
(19, student_id),
(20, student_id),
(21, student_id),
(22, student_id),
(23, student_id),
(24, student_id),
(25, student_id),
(26, student_id),
(27, student_id),
(28, student_id),
(29, student_id),
(30, student_id),
(31, student_id),
(32, student_id),
(33, student_id),
(34, student_id),
(35, student_id),
(36, student_id),
(37, teacher_id),
(37, administrator_id),
(38, commission_member_id),
(39, teacher_id),
(40, teacher_id),
(41, teacher_id),
(42, teacher_id),
(43, teacher_id),
(44, secretary_id),
(45, secretary_id);
end
$$;

View File

@ -1,143 +0,0 @@
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (2, 'Сергей', 'Иванов', 'Александрович', 'ivanov.s.a@yandex.ru', '+79991234567', false, '2025-06-23 03:30:29.770236', '2025-06-23 03:30:29.770243');
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (3, 'Анна', 'Петрова', 'Викторовна', 'petrova.anna@mail.ru', '+79992345678', false, '2025-06-23 03:30:51.070370', '2025-06-23 03:30:51.070383');
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (4, 'Михаил', 'Сидоров', 'Юрьевич', 'sidorov.mikhail@gmail.com', '+79993456789', false, '2025-06-23 03:34:04.812946', '2025-06-23 03:34:04.812950');
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (5, 'Екатерина', 'Козлова', 'Дмитриевна', 'kozlova.ekaterina@yandex.ru', '+79994567890', false, '2025-06-23 03:34:22.224929', '2025-06-23 03:34:22.224937');
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (6, 'Алексей', 'Смирнов', 'Игоревич', 'smirnov.alexey@mail.ru', '+79995678901', false, '2025-06-23 03:34:44.026899', '2025-06-23 03:34:44.026907');
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (7, 'Ольга', 'Васильева', 'Сергеевна', 'vasilieva.olga@gmail.com', '+79996789012', false, '2025-06-23 03:35:04.258782', '2025-06-23 03:35:04.258786');
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (8, 'Павел', 'Кузнецов', 'Андреевич', 'kuznetsov.pavel@yandex.ru', '+79997890123', false, '2025-06-23 03:35:23.594053', '2025-06-23 03:35:23.594057');
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (9, 'Светлана', 'Морозова', 'Николаевна', 'morozova.svetlana@mail.ru', '+79998901234', false, '2025-06-23 03:35:41.692339', '2025-06-23 03:35:41.692348');
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (10, 'Дмитрий', 'Попов', 'Евгеньевич', 'popov.dmitry@gmail.com', '+79999012345', false, '2025-06-23 03:35:57.449960', '2025-06-23 03:35:57.449967');
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (11, 'Мария', 'Лебедева', 'Алексеевна', 'lebedeva.maria@yandex.ru', '+79990123456', false, '2025-06-23 03:36:15.662888', '2025-06-23 03:36:15.662897');
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (12, 'Артём', 'Новиков', 'Вадимович', 'novikov.artem@mail.ru', '+79991235678', false, '2025-06-23 03:36:32.688934', '2025-06-23 03:36:32.688937');
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (13, 'Юлия', 'Фёдорова', 'Олеговна', 'fedorova.yulia@gmail.com', '+79992346789', false, '2025-06-23 03:36:56.836898', '2025-06-23 03:36:56.836906');
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (14, 'Игорь', 'Михайлов', 'Павлович', 'mikhaylov.igor@yandex.ru', '+79993457890', false, '2025-06-23 03:37:10.639420', '2025-06-23 03:37:10.639426');
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (15, 'Елена', 'Беляева', 'Викторовна', 'belyaeva.elena@mail.ru', '+79994568901', false, '2025-06-23 03:37:25.821122', '2025-06-23 03:37:25.821125');
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (16, 'Андрей', 'Григорьев', 'Сергеевич', 'grigoriev.andrey@gmail.com', '+79995679012', false, '2025-06-23 03:37:43.800145', '2025-06-23 03:37:43.800148');
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (17, 'Наталья', 'Орлова', 'Ивановна', 'orlova.natalia@yandex.ru', '+79996780123', false, '2025-06-23 03:37:59.523747', '2025-06-23 03:37:59.523750');
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (18, 'Виктор', 'Ковалёв', 'Дмитриевич', 'kovalev.viktor@mail.ru', '+79997891234', false, '2025-06-23 03:38:18.141073', '2025-06-23 03:38:18.141083');
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (19, 'Дарья', 'Соколова', 'Александровна', 'sokolova.darya@gmail.com', '+79998912345', false, '2025-06-23 03:38:33.493732', '2025-06-23 03:38:33.493738');
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (20, 'Евгений', 'Романов', 'Николаевич', 'romanov.evgeny@yandex.ru', '+79990124567', false, '2025-06-23 03:38:52.229061', '2025-06-23 03:38:52.229065');
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (21, 'Алина', 'Зайцева', 'Сергеевна', 'zaytseva.alina@mail.ru', '+79991236789', false, '2025-06-23 03:39:08.364108', '2025-06-23 03:39:08.364111');
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (24, 'Арсений', 'Баранов', 'Викторович', 'baranov.arseny@mail.ru', '+79994569012', false, '2025-06-23 03:40:11.579147', '2025-06-23 03:40:11.579149');
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (25, 'Ксения', 'Егорова', 'Павловна', 'egorova.ksenia@gmail.com', '+79995670123', false, '2025-06-23 03:40:55.806292', '2025-06-23 03:40:55.806297');
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (26, 'Никита', 'Лазарев', 'Андреевич', 'lazarev.nikita@yandex.ru', '+79996781234', false, '2025-06-23 03:41:27.952004', '2025-06-23 03:41:27.952007');
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (27, 'София', 'Тихонова', 'Дмитриевна', 'tikhonova.sofia@mail.ru', '+79997892345', false, '2025-06-23 03:41:56.458424', '2025-06-23 03:41:56.458431');
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (23, 'Валерия', 'Королёва', 'Игоревна', 'koroleva.valeria@yandex.ru', '+79993458901', false, '2025-06-23 03:42:42.283585', '2025-06-23 03:42:42.283594');
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (22, 'Максим', 'Волков', 'Олегович', 'volkov.maxim@gmail.com', '+79992347890', false, '2025-06-23 04:17:19.212758', '2025-06-23 04:17:19.212763');
INSERT INTO public.participant (id, first_name, last_name, middle_name, email, number_phone, deleted, created_at, updated_at) VALUES (29,'Георгий','Павлов','Максимович','pavlov.georgiy@mail.com','+79936652346',false,'2025-06-24 03:24:17.701799','2025-06-24 03:24:17.701811');
INSERT INTO public.teacher_data (id, participant_id, degree, created_at, updated_at) VALUES (1, 22, 'ктн., доц.', '2025-06-23 03:39:38.369701', '2025-06-23 03:39:38.369706');
INSERT INTO public.teacher_data (id, participant_id, degree, created_at, updated_at) VALUES (2, 23, 'ктн., доц.', '2025-06-23 03:39:55.268771', '2025-06-23 03:39:55.268774');
INSERT INTO public.teacher_data (id, participant_id, degree, created_at, updated_at) VALUES (3, 24, 'ктн., доц.', '2025-06-23 03:40:11.580333', '2025-06-23 03:40:11.580339');
INSERT INTO public.direction_of_preparation (id, name, code, responsible_id, created_at, updated_at) VALUES (1, 'Информатика и вычислительная техника', '09.03.01', 1, '2025-06-23 03:43:21.412709', '2025-06-23 03:43:21.412726');
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (1, 'Разработка системы рекомендаций фильмов с использованием машинного обучения', 1, 1, '2025-06-23 03:44:10.229018', '2025-06-23 03:44:10.229025');
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (2, 'Создание чат-бота для автоматизации клиентской поддержки', 1, 1, '2025-06-23 03:44:16.798881', '2025-06-23 03:44:16.798888');
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (3, 'Анализ производительности алгоритмов сортировки на больших данных', 1, 1, '2025-06-23 03:44:24.036407', '2025-06-23 03:44:24.036426');
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (4, 'Разработка мобильного приложения для управления личными финансами', 1, 1, '2025-06-23 03:44:30.806074', '2025-06-23 03:44:30.806082');
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (5, 'Исследование методов защиты данных в облачных хранилищах', 2, 1, '2025-06-23 03:44:40.138182', '2025-06-23 03:44:40.138194');
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (6, 'Создание системы мониторинга серверов с использованием Prometheus и Grafana', 2, 1, '2025-06-23 03:44:46.312549', '2025-06-23 03:44:46.312558');
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (7, 'Разработка веб-приложения для организации мероприятий с интерактивным интерфейсом', 2, 1, '2025-06-23 03:44:51.925603', '2025-06-23 03:44:51.925613');
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (8, 'Оптимизация алгоритмов компьютерного зрения для распознавания лиц', 2, 1, '2025-06-23 03:44:59.413613', '2025-06-23 03:44:59.413632');
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (9, 'Исследование применения блокчейн-технологий в логистике', 2, 1, '2025-06-23 03:45:05.727136', '2025-06-23 03:45:05.727146');
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (10, 'Разработка системы автоматического тестирования веб-приложений', 2, 1, '2025-06-23 03:45:12.096788', '2025-06-23 03:45:12.096792');
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (11, 'Создание платформы для онлайн-обучения с адаптивным тестированием', 2, 1, '2025-06-23 03:45:38.511004', '2025-06-23 03:45:38.511020');
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (12, 'Анализ уязвимостей веб-приложений и разработка защитных мер', 3, 1, '2025-06-23 03:45:44.511502', '2025-06-23 03:45:44.511509');
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (13, 'Разработка игры на Unity с использованием элементов дополненной реальности', 3, 1, '2025-06-23 03:45:51.828513', '2025-06-23 03:45:51.828524');
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (14, 'Исследование методов обработки естественного языка для анализа текстов', 3, 1, '2025-06-23 03:45:58.514002', '2025-06-23 03:45:58.514011');
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (15, 'Создание системы управления проектами с интеграцией Kanban-доски', 3, 1, '2025-06-23 03:46:05.569625', '2025-06-23 03:46:05.569632');
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (16, 'Создание системы управления проектами с интеграцией Kanban-доски', 3, 1, '2025-06-23 03:46:11.498443', '2025-06-23 03:46:11.498449');
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (17, 'Исследование кибератак на IoT-устройства и разработка защитного ПО', 1, 1, '2025-06-23 03:46:18.270926', '2025-06-23 03:46:18.270944');
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (18, 'Разработка прототипа социальной сети', 1, 1, '2025-06-23 03:46:18.270926', '2025-06-23 03:46:18.270944');
INSERT INTO public.diploma_topic (id, name, teacher_id, direction_of_preparation_id, created_at, updated_at) VALUES (19, 'Разработка подсистемы интеграции с платежными системами', 1, 1, '2025-06-23 03:46:18.270926', '2025-06-23 03:46:18.270944');
INSERT INTO public.commission_member_data (id, partic_id, work_place, work_position, created_at, updated_at) VALUES (1, 25, 'ООО "ТехноСофт"', 'Программист Python', '2025-06-23 03:40:55.807387', '2025-06-23 03:40:55.807392');
INSERT INTO public.commission_member_data (id, partic_id, work_place, work_position, created_at, updated_at) VALUES (2, 26, 'АО "Инновации"', 'Системный администратор', '2025-06-23 03:41:27.952659', '2025-06-23 03:41:27.952663');
INSERT INTO public.commission_member_data (id, partic_id, work_place, work_position, created_at, updated_at) VALUES (3, 27, 'ООО "ДатаСистемс"', 'Аналитик данных', '2025-06-23 03:41:56.460124', '2025-06-23 03:41:56.460133');
INSERT INTO public.commission_member_data (id, partic_id, work_place, work_position, created_at, updated_at) VALUES (5, 23, 'БГТУ', 'доц.,ктн.,зав.кав.', '2025-06-23 03:42:42.288583', '2025-06-23 03:42:42.288590');
INSERT INTO public.commission_member_data (id, partic_id, work_place, work_position, created_at, updated_at) VALUES (4, 22, 'БГТУ', 'доц.,ктн.', '2025-06-23 03:42:37.300773', '2025-06-23 03:42:37.300777');
INSERT INTO public.defense (id, defense_date, status, direction_of_preparation_id, responsible_for_antiplagiarism_id, responsible_for_normcontrol_id, created_at, updated_at) VALUES (1, '2025-06-26', 'DEFENSE_PREPARATION', 1, 22, 22, '2025-06-23 04:09:15.118953', '2025-06-23 04:09:15.118975');
INSERT INTO public."group" (id, name, defense_id, direction_of_preparation_id, created_at, updated_at) VALUES (1, 'О-21-ИВТ-1-по-Б', 1, 1, '2025-06-23 03:50:49.095829', '2025-06-23 03:50:49.095835');
INSERT INTO public."group" (id, name, defense_id, direction_of_preparation_id, created_at, updated_at) VALUES (2, 'О-21-ИВТ-2-по-Б', 1, 1, '2025-06-23 03:50:49.096295', '2025-06-23 03:50:49.096299');
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (7, 8, null, 1, 7, 1, 5, 4, 4, true, 64, true, '',1, null, 1, 8, 24, 19, null, null, false, true, true, true, true, '2025-06-23 03:49:29.837457', '2025-06-23 03:49:29.837459');
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (2, 3, null, 1, 2, 1, 5, 5, 5, true, 85, true, '',2, null, 1, 10, 12, 28, null, null, false, true, false, false, true, '2025-06-23 03:49:29.836268', '2025-06-23 03:49:29.836271');
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (4, 5, null, 1, 4, 1, 4, 5, 5, true, 82, true, '',3, null, 1, 7, 18, 10, null, null, false, true, true, true, true, '2025-06-23 03:49:29.836800', '2025-06-23 03:49:29.836802');
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (10, 11, null, 2, 10, 1, 5, 4, 4, true, 67, true, '',4, null, 1, 4, 25, 19, null, null, false, false, false, false, true, '2025-06-23 03:49:29.837974', '2025-06-23 03:49:29.837976');
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (13, 14, null, 2, 3, 2, 5, 4, 4, true, 45, true, '',5, null, 2, 12, 20, 19, null, null, false, false, false, false, true, '2025-06-23 03:50:04.763207', '2025-06-23 03:50:04.763212');
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (6, 7, null, 1, 6, 1, 4, 4, 4, true, 65, true, '',6, null, 1, 4, 25, 21, null, null, false, false, false, false, true, '2025-06-23 03:49:29.837241', '2025-06-23 03:49:29.837243');
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (12, 13, null, 2, 2, 2, 5, 5, 5, true, 87, false, '',7, null, 2, 0, 21, 18, null, null, true, true, true, true, false, '2025-06-23 03:50:04.762603', '2025-06-23 03:50:04.762610');
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (20, 21, null, 3, 10, 2, 5, 5, 5, true, 65, true, '', 8, null, 2, 7, 9, 29, null, null, false, false, false, false, false, '2025-06-23 03:50:04.766515', '2025-06-23 03:50:04.766520');
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (17, 18, null, 3, 7, 2, 4, 4, 4, true, 66, true, '', 9, null, 2, 9, 23, 19, null, null, false, true, false, false, true, '2025-06-23 03:50:04.765268', '2025-06-23 03:50:04.765273');
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (14, 15, null, 2, 4, 2, 4, 5, 5, true, 87, true, '', 10, null, 2, 5, 19, 23, null, null, false, false, true, true, true, '2025-06-23 03:50:04.763769', '2025-06-23 03:50:04.763774');
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (16, 17, null, 3, 6, 2, 4, 5, 5, true, 76, true, '', 11, null, 2, 4, 1, 35, null, null, false, true, true, true, false, '2025-06-23 03:50:04.764825', '2025-06-23 03:50:04.764831');
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (5, 6, null, 1, 5, 1, 4, 5, 5, true, 76, true, '', 12, null, 1, 6, 23, 19, null, null, false, false, false, false, true, '2025-06-23 03:49:29.837008', '2025-06-23 03:49:29.837010');
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (1, 2, null, 1, 1, 1, 5, 5, 5, true, 81, true, '',13, null, 1, 10, 20, 20, null, null, false, true, false, false, true, '2025-06-23 03:49:29.835742', '2025-06-23 03:49:29.835746');
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (3, 4, null, 1, 3, 1, 5, 5, 5, true, 73, true, '', 14, null, 1, 8, 21, 10, null, null, false, false, true, true, false, '2025-06-23 03:49:29.836579', '2025-06-23 03:49:29.836581');
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (18, 19, null, 3, 8, 2, 5, 4, 4, true, 67, true, '', 15, null, 2, 12, 12, 21, null, null, false, false, true, true, true, '2025-06-23 03:50:04.765687', '2025-06-23 03:50:04.765692');
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (19, 20, null, 3, 9, 2, 3, 3, 3, true, 52, true, '', 16, null, 2, 5, 21, 12, null, null, false, true, true, true, true, '2025-06-23 03:50:04.766102', '2025-06-23 03:50:04.766107');
INSERT INTO public.student_data (id, partic_id, study_form_id, curator_id, protection_order, protection_day, mark_practice, predefnese_mark, oztiv_mark, normal_control, anti_plagiarism, record_book_returned, work, diploma_topic_id, adviser_teacher_partic_id, group_id, marks_3, marks_4, marks_5, commission_mark, estimated, diploma_with_honors, vnedreniye, magistracy_recommendation, magistracy_wanted, electronic, created_at, updated_at) VALUES (11, 12, null, 2, 1, 2, 5, 4, 4, true, 78, true, '', 17, null, 2, 21, 24, 17, null, null, false, false, false, false, true, '2025-06-23 03:50:04.761995', '2025-06-23 03:50:04.761999');
INSERT INTO public."user" (id, login, password, partic_id, created_at, updated_at) VALUES (2, 'Teacher001', '{bcrypt}$2a$10$.HTDUMHEv3cMjZfdJPyrtugku6guROyqo9bDz5V46705ix0E94Rmm', 22, '2025-06-23 04:17:19.213271', '2025-06-23 04:17:19.213274');
INSERT INTO public."user" (id, login, password, partic_id, created_at, updated_at) VALUES (4, 'Secretary001', '{bcrypt}$2a$10$H/uiV2i.KXBIfv/XtQTinO4Hx4UfkaXuc1BKHL2CX2xkLryOXPdru', 29, '2025-06-24 03:24:17.963794', '2025-06-24 03:24:17.963823');
INSERT INTO public.participant_role (partic_id, role_id) VALUES (2, 2);
INSERT INTO public.participant_role (partic_id, role_id) VALUES (22, 4);
INSERT INTO public.participant_role (partic_id, role_id) VALUES (3, 2);
INSERT INTO public.participant_role (partic_id, role_id) VALUES (4, 2);
INSERT INTO public.participant_role (partic_id, role_id) VALUES (5, 2);
INSERT INTO public.participant_role (partic_id, role_id) VALUES (6, 2);
INSERT INTO public.participant_role (partic_id, role_id) VALUES (7, 2);
INSERT INTO public.participant_role (partic_id, role_id) VALUES (8, 2);
INSERT INTO public.participant_role (partic_id, role_id) VALUES (9, 2);
INSERT INTO public.participant_role (partic_id, role_id) VALUES (10, 2);
INSERT INTO public.participant_role (partic_id, role_id) VALUES (11, 2);
INSERT INTO public.participant_role (partic_id, role_id) VALUES (12, 2);
INSERT INTO public.participant_role (partic_id, role_id) VALUES (13, 2);
INSERT INTO public.participant_role (partic_id, role_id) VALUES (14, 2);
INSERT INTO public.participant_role (partic_id, role_id) VALUES (15, 2);
INSERT INTO public.participant_role (partic_id, role_id) VALUES (16, 2);
INSERT INTO public.participant_role (partic_id, role_id) VALUES (17, 2);
INSERT INTO public.participant_role (partic_id, role_id) VALUES (18, 2);
INSERT INTO public.participant_role (partic_id, role_id) VALUES (19, 2);
INSERT INTO public.participant_role (partic_id, role_id) VALUES (20, 2);
INSERT INTO public.participant_role (partic_id, role_id) VALUES (21, 2);
INSERT INTO public.participant_role (partic_id, role_id) VALUES (24, 1);
INSERT INTO public.participant_role (partic_id, role_id) VALUES (25, 3);
INSERT INTO public.participant_role (partic_id, role_id) VALUES (26, 3);
INSERT INTO public.participant_role (partic_id, role_id) VALUES (27, 3);
INSERT INTO public.participant_role (partic_id, role_id) VALUES (23, 1);
INSERT INTO public.participant_role (partic_id, role_id) VALUES (23, 3);
INSERT INTO public.participant_role (partic_id, role_id) VALUES (22, 1);
INSERT INTO public.participant_role (partic_id, role_id) VALUES (22, 3);
INSERT INTO public.participant_role (partic_id, role_id) VALUES (22, 6);
INSERT INTO public.participant_role (partic_id, role_id) VALUES (29, 5);
INSERT INTO public.task (id, status, type, defense_id, maker_partic_id, checker_partic_id, task_type, diploma_topic_id, diploma_topic_name, practice_mark, antiplagiarism_percent, normcontrol_passed, approved_at, created_at, updated_at) VALUES (1, 'WAIT_FOR_TOPIC_PREPARATION', 'TOPIC_PREPARATION', 1, null, 22, 'Task', null, null, null, null, null, null, '2025-06-23 04:09:15.021775', '2025-06-23 04:09:15.021786');
INSERT INTO public.task (id, status, type, defense_id, maker_partic_id, checker_partic_id, task_type, diploma_topic_id, diploma_topic_name, practice_mark, antiplagiarism_percent, normcontrol_passed, approved_at, created_at, updated_at) VALUES (2, 'WAIT_FOR_TOPIC_PREPARATION', 'TOPIC_PREPARATION', 1, null, 23, 'Task', null, null, null, null, null, null, '2025-06-23 04:09:15.078322', '2025-06-23 04:09:15.078333');
INSERT INTO public.task (id, status, type, defense_id, maker_partic_id, checker_partic_id, task_type, diploma_topic_id, diploma_topic_name, practice_mark, antiplagiarism_percent, normcontrol_passed, approved_at, created_at, updated_at) VALUES (3, 'WAIT_FOR_TOPIC_PREPARATION', 'TOPIC_PREPARATION', 1, null, 24, 'Task', null, null, null, null, null, null, '2025-06-23 04:09:15.097449', '2025-06-23 04:09:15.097458');
INSERT INTO public.defense_commission (defense_id, commission_member_data_id) VALUES (1, 3);
INSERT INTO public.defense_commission (defense_id, commission_member_data_id) VALUES (1, 2);
INSERT INTO public.defense_commission (defense_id, commission_member_data_id) VALUES (1, 1);
INSERT INTO public.defense_commission (defense_id, commission_member_data_id) VALUES (1, 5);
INSERT INTO public.defense_commission (defense_id, commission_member_data_id) VALUES (1, 4);
SELECT setval('commission_member_data_id_seq', COALESCE((SELECT MAX(id) + 1 FROM commission_member_data), 1));
SELECT setval('defense_id_seq', COALESCE((SELECT MAX(id) + 1 FROM defense), 1));
SELECT setval('diploma_topic_id_seq', COALESCE((SELECT MAX(id) + 1 FROM diploma_topic), 1));
SELECT setval('direction_of_preparation_id_seq', COALESCE((SELECT MAX(id) + 1 FROM direction_of_preparation), 1));
SELECT setval('group_id_seq', COALESCE((SELECT MAX(id) + 1 FROM "group"), 1));
SELECT setval('message_template_id_seq', COALESCE((SELECT MAX(id) + 1 FROM message_template), 1));
SELECT setval('participant_id_seq', COALESCE((SELECT MAX(id) + 1 FROM participant), 1));
SELECT setval('questionnaire_id_seq', COALESCE((SELECT MAX(id) + 1 FROM questionnaire), 1));
SELECT setval('stud_comment_id_seq', COALESCE((SELECT MAX(id) + 1 FROM stud_comment), 1));
SELECT setval('student_data_comment_id_seq', COALESCE((SELECT MAX(id) + 1 FROM student_data_comment), 1));
SELECT setval('student_data_id_seq', COALESCE((SELECT MAX(id) + 1 FROM student_data), 1));
SELECT setval('study_form_id_seq', COALESCE((SELECT MAX(id) + 1 FROM study_form), 1));
SELECT setval('task_id_seq', COALESCE((SELECT MAX(id) + 1 FROM task), 1));
SELECT setval('teacher_data_id_seq', COALESCE((SELECT MAX(id) + 1 FROM teacher_data), 1));
SELECT setval('user_id_seq', COALESCE((SELECT MAX(id) + 1 FROM "user"), 1));

133
web/package-lock.json generated
View File

@ -21,7 +21,6 @@
"mobx-react": "^9.1.1", "mobx-react": "^9.1.1",
"mobx-state-router": "^6.0.1", "mobx-state-router": "^6.0.1",
"react": "^18.2.0", "react": "^18.2.0",
"react-beautiful-dnd": "^13.1.1",
"react-bootstrap": "^2.10.4", "react-bootstrap": "^2.10.4",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"uuid": "^11.0.5" "uuid": "^11.0.5"
@ -31,7 +30,6 @@
"@babel/preset-env": "^7.25.8", "@babel/preset-env": "^7.25.8",
"@babel/preset-react": "^7.25.7", "@babel/preset-react": "^7.25.7",
"@types/react": "^18.2.0", "@types/react": "^18.2.0",
"@types/react-beautiful-dnd": "^13.1.8",
"@types/react-dom": "^18.2.0", "@types/react-dom": "^18.2.0",
"@types/webpack": "^5.28.5", "@types/webpack": "^5.28.5",
"copy-webpack-plugin": "^13.0.0", "copy-webpack-plugin": "^13.0.0",
@ -2084,16 +2082,6 @@
"@types/send": "*" "@types/send": "*"
} }
}, },
"node_modules/@types/hoist-non-react-statics": {
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.6.tgz",
"integrity": "sha512-lPByRJUer/iN/xa4qpyL0qmL11DqNW81iU/IG1S3uvRUq4oKagz8VCxZjiWkumgt66YT3vOdDgZ0o32sGKtCEw==",
"license": "MIT",
"dependencies": {
"@types/react": "*",
"hoist-non-react-statics": "^3.3.0"
}
},
"node_modules/@types/html-minifier-terser": { "node_modules/@types/html-minifier-terser": {
"version": "6.1.0", "version": "6.1.0",
"resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
@ -2177,16 +2165,6 @@
"csstype": "^3.0.2" "csstype": "^3.0.2"
} }
}, },
"node_modules/@types/react-beautiful-dnd": {
"version": "13.1.8",
"resolved": "https://registry.npmjs.org/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.1.8.tgz",
"integrity": "sha512-E3TyFsro9pQuK4r8S/OL6G99eq7p8v29sX0PM7oT8Z+PJfZvSQTx4zTQbUJ+QZXioAF0e7TGBEcA1XhYhCweyQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/react": "*"
}
},
"node_modules/@types/react-dom": { "node_modules/@types/react-dom": {
"version": "18.3.1", "version": "18.3.1",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz",
@ -2196,18 +2174,6 @@
"@types/react": "*" "@types/react": "*"
} }
}, },
"node_modules/@types/react-redux": {
"version": "7.1.34",
"resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.34.tgz",
"integrity": "sha512-GdFaVjEbYv4Fthm2ZLvj1VSCedV7TqE5y1kNwnjSdBOTXuRSgowux6J8TAct15T3CKBr63UMk+2CO7ilRhyrAQ==",
"license": "MIT",
"dependencies": {
"@types/hoist-non-react-statics": "^3.3.0",
"@types/react": "*",
"hoist-non-react-statics": "^3.3.0",
"redux": "^4.0.0"
}
},
"node_modules/@types/react-transition-group": { "node_modules/@types/react-transition-group": {
"version": "4.4.11", "version": "4.4.11",
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.11.tgz", "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.11.tgz",
@ -3290,15 +3256,6 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/css-box-model": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz",
"integrity": "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==",
"license": "MIT",
"dependencies": {
"tiny-invariant": "^1.0.6"
}
},
"node_modules/css-loader": { "node_modules/css-loader": {
"version": "7.1.2", "version": "7.1.2",
"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.2.tgz", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.2.tgz",
@ -4173,15 +4130,6 @@
"value-equal": "^1.0.1" "value-equal": "^1.0.1"
} }
}, },
"node_modules/hoist-non-react-statics": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
"license": "BSD-3-Clause",
"dependencies": {
"react-is": "^16.7.0"
}
},
"node_modules/hpack.js": { "node_modules/hpack.js": {
"version": "2.1.6", "version": "2.1.6",
"resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
@ -4798,12 +4746,6 @@
"url": "https://github.com/sponsors/streamich" "url": "https://github.com/sponsors/streamich"
} }
}, },
"node_modules/memoize-one": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==",
"license": "MIT"
},
"node_modules/merge-descriptors": { "node_modules/merge-descriptors": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
@ -5470,12 +5412,6 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/raf-schd": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz",
"integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==",
"license": "MIT"
},
"node_modules/randombytes": { "node_modules/randombytes": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
@ -5529,26 +5465,6 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/react-beautiful-dnd": {
"version": "13.1.1",
"resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.1.tgz",
"integrity": "sha512-0Lvs4tq2VcrEjEgDXHjT98r+63drkKEgqyxdA7qD3mvKwga6a5SscbdLPO2IExotU1jW8L0Ksdl0Cj2AF67nPQ==",
"deprecated": "react-beautiful-dnd is now deprecated. Context and options: https://github.com/atlassian/react-beautiful-dnd/issues/2672",
"license": "Apache-2.0",
"dependencies": {
"@babel/runtime": "^7.9.2",
"css-box-model": "^1.2.0",
"memoize-one": "^5.1.1",
"raf-schd": "^4.0.2",
"react-redux": "^7.2.0",
"redux": "^4.0.4",
"use-memo-one": "^1.1.1"
},
"peerDependencies": {
"react": "^16.8.5 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.8.5 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/react-bootstrap": { "node_modules/react-bootstrap": {
"version": "2.10.5", "version": "2.10.5",
"resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.10.5.tgz", "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.10.5.tgz",
@ -5600,37 +5516,6 @@
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
}, },
"node_modules/react-redux": {
"version": "7.2.9",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz",
"integrity": "sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.15.4",
"@types/react-redux": "^7.1.20",
"hoist-non-react-statics": "^3.3.2",
"loose-envify": "^1.4.0",
"prop-types": "^15.7.2",
"react-is": "^17.0.2"
},
"peerDependencies": {
"react": "^16.8.3 || ^17 || ^18"
},
"peerDependenciesMeta": {
"react-dom": {
"optional": true
},
"react-native": {
"optional": true
}
}
},
"node_modules/react-redux/node_modules/react-is": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
"license": "MIT"
},
"node_modules/react-transition-group": { "node_modules/react-transition-group": {
"version": "4.4.5", "version": "4.4.5",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
@ -5684,15 +5569,6 @@
"node": ">= 10.13.0" "node": ">= 10.13.0"
} }
}, },
"node_modules/redux": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz",
"integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.9.2"
}
},
"node_modules/regenerate": { "node_modules/regenerate": {
"version": "1.4.2", "version": "1.4.2",
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
@ -6693,15 +6569,6 @@
"punycode": "^2.1.0" "punycode": "^2.1.0"
} }
}, },
"node_modules/use-memo-one": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.3.tgz",
"integrity": "sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==",
"license": "MIT",
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/use-sync-external-store": { "node_modules/use-sync-external-store": {
"version": "1.2.2", "version": "1.2.2",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz",

View File

@ -20,7 +20,6 @@
"mobx-react": "^9.1.1", "mobx-react": "^9.1.1",
"mobx-state-router": "^6.0.1", "mobx-state-router": "^6.0.1",
"react": "^18.2.0", "react": "^18.2.0",
"react-beautiful-dnd": "^13.1.1",
"react-bootstrap": "^2.10.4", "react-bootstrap": "^2.10.4",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"uuid": "^11.0.5" "uuid": "^11.0.5"
@ -30,7 +29,6 @@
"@babel/preset-env": "^7.25.8", "@babel/preset-env": "^7.25.8",
"@babel/preset-react": "^7.25.7", "@babel/preset-react": "^7.25.7",
"@types/react": "^18.2.0", "@types/react": "^18.2.0",
"@types/react-beautiful-dnd": "^13.1.8",
"@types/react-dom": "^18.2.0", "@types/react-dom": "^18.2.0",
"@types/webpack": "^5.28.5", "@types/webpack": "^5.28.5",
"copy-webpack-plugin": "^13.0.0", "copy-webpack-plugin": "^13.0.0",

View File

@ -12,21 +12,15 @@ import {ParticipantListPage} from "./components/participant/ParticipantListPage"
import {DefenceListPage} from "./components/defence/DefenceListPage"; import {DefenceListPage} from "./components/defence/DefenceListPage";
import {PreparationDirectionListPage} from "./components/dictionary/PreparationDirectionList"; import {PreparationDirectionListPage} from "./components/dictionary/PreparationDirectionList";
import {DiplomaTopicListPage} from "./components/dictionary/DiplomaTopicList"; import {DiplomaTopicListPage} from "./components/dictionary/DiplomaTopicList";
import {DiplomaTopicAgreementPage} from "./components/tasks/DiplomaTopicAgreementPage";
import {DefenceEditPage} from "./components/defence/DefenceEditPage";
import {NotificationPage} from "./components/notification/NotificationPage";
const viewMap: ViewMap = { const viewMap: ViewMap = {
home: <Home/>, home: <Home/>,
error: <Error/>,
participantList: <ParticipantListPage/>, participantList: <ParticipantListPage/>,
groupList: <GroupListPage/>, groupList: <GroupListPage/>,
defenceList: <DefenceListPage/>, defenceList: <DefenceListPage/>,
themeList: <DiplomaTopicListPage/>, themeList: <DiplomaTopicListPage/>,
preparationDirectionList: <PreparationDirectionListPage/>, preparationDirectionList: <PreparationDirectionListPage/>,
defenceTopicAgreement: <DiplomaTopicAgreementPage/>, error: <Error/>,
defenseEdit: <DefenceEditPage/>,
notifications: <NotificationPage/>,
} }
const rootStore = initApp(); const rootStore = initApp();

View File

@ -9,7 +9,7 @@ import {
observer observer
} from "mobx-react"; } from "mobx-react";
import { import {
action, computed, action,
makeObservable, makeObservable,
observable, observable,
runInAction runInAction
@ -41,8 +41,6 @@ import {
import { import {
ModalState ModalState
} from "../../utils/modalState"; } from "../../utils/modalState";
import _ from "lodash";
import {dateConverter, dateConverter2} from "../../utils/converters";
export interface ReactiveInputProps<T> { export interface ReactiveInputProps<T> {
value: ReactiveValue<T>; value: ReactiveValue<T>;
@ -114,7 +112,7 @@ export class StringInput extends Component<ReactiveInputProps<string>> {
return <div className={'mb-1 l-no-bg'}> return <div className={'mb-1 l-no-bg'}>
<FloatingLabel label={this.props.label} className={`${this.props.className} mt-0 mb-0`}> <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} <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> </FloatingLabel>
<FormText children={this.props.value.firstError} className={`text-danger mt-0 mb-0 d-block`}/> <FormText children={this.props.value.firstError} className={`text-danger mt-0 mb-0 d-block`}/>
</div> </div>
@ -281,27 +279,16 @@ export class DropdownSelectInput extends Component<MultipleSelectInputProps> {
if (this.props.value.value === undefined) { if (this.props.value.value === undefined) {
this.props.value.setAuto([]); this.props.value.setAuto([]);
} }
this.initField(this.props); this.initField(this.props);
runInAction(() => { runInAction(() => {
this.options = props.possibleValues; this.options = props.possibleValues;
}); });
} }
componentDidUpdate() { componentDidUpdate(prevProps: Readonly<MultipleSelectInputProps>) {
if (this.value != this.props.value) { if (this.value != prevProps.value) {
this.initField(this.props); this.initField(this.props);
} }
if (!_.isEqual(this.options, this.props.possibleValues)) {
runInAction(() => {
this.options = this.props.possibleValues;
if (!this.props.disabled) {
this.value.setAuto([]);
}
});
}
} }
@action.bound @action.bound
@ -354,23 +341,24 @@ export class DropdownSelectInput extends Component<MultipleSelectInputProps> {
const inputDisabledBackgroundStyle = this.props.disabled ? {backgroundColor: 'rgb(233, 236, 239)'} : {}; const inputDisabledBackgroundStyle = this.props.disabled ? {backgroundColor: 'rgb(233, 236, 239)'} : {};
const inputDisabledColor = this.props.disabled ? '#000000' : 'rgb(33, 37, 41)'; const inputDisabledColor = this.props.disabled ? '#000000' : 'rgb(33, 37, 41)';
return ( return <div
<div className={'mb-1 l-no-bg'}> className={'mb-1 l-no-bg'}>
{
<Dropdown as={ButtonGroup} className={'d-flex align-items-center border ' + inputClassName} <Dropdown as={ButtonGroup} className={'d-flex align-items-center border ' + inputClassName}
drop={'end'} style={inputDisabledBackgroundStyle}> drop={'end'} style={inputDisabledBackgroundStyle}>
<Button size={'lg'} className={`d-flex flex-wrap gap-1 align-items-baseline no-reaction`} <Button size={'lg'} className={`d-flex flex-wrap gap-1 align-items-baseline no-reaction`}
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> <span style={{'fontSize': '1rem', 'color': inputDisabledColor}}>{this.value.field}</span>
{ {
this.value.value?.map(sel => { 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}> 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> <span>{sel.label}</span>
{ {
!this.props.disabled && !this.props.disabled &&
<FontAwesomeIcon icon={'close'} onClick={this.onCloseClick} className={'ms-1'} style={{'cursor': 'pointer'}}/> <FontAwesomeIcon icon={'close'} onClick={this.onCloseClick} className={'ms-1'} style={{'cursor': 'pointer'}}/>
} }
</Badge> </Badge>
}) })
} }
</Button> </Button>
@ -398,11 +386,11 @@ export class DropdownSelectInput extends Component<MultipleSelectInputProps> {
} }
</DropdownMenu> </DropdownMenu>
</Dropdown> </Dropdown>
<FormText }
children={this.props.value.firstError} <FormText
className={'text-danger d-block mt-0 mb-0'}/> children={this.props.value.firstError}
</div> className={'text-danger d-block mt-0 mb-0'}/>
) </div>
} }
} }
@ -461,58 +449,3 @@ export class TableInput<T> extends Component<TableInputProps<T>> {
editable={!this.disabled} editableModalState={this.searchNewEntryModalState}/> editable={!this.disabled} editableModalState={this.searchNewEntryModalState}/>
} }
} }
interface InputDateProps extends ReactiveInputProps<Date> {
maxDate?: Date;
minDate: Date;
}
@observer
export class InputDate extends Component<InputDateProps> {
constructor(props: any) {
super(props);
makeObservable(this);
runInAction(() => {
this.myProps = props;
if (this.myProps.value.value === undefined) {
this.myProps.value.setAuto(new Date());
}
this.myProps.value.setField(this.myProps.label);
})
}
componentDidUpdate() {
if (this.myProps.value.value !== this.props.value.value || this.myProps.disabled !== this.props.disabled) {
runInAction(() => {
this.myProps = this.props;
});
}
}
@observable myProps: InputDateProps;
@action.bound
onChange(event: React.ChangeEvent<HTMLInputElement>) {
this.myProps.value.set(new Date(event.target.value));
console.log('onChange', event.target.value);
console.log('onChange', this.myProps.value.value);
}
@computed
get dateConvert() {
if (!this.myProps.value.value) return '';
return this.myProps.value.value.toISOString().split('T')[0];
}
render() {
const inputClassName = `${this.myProps.validateless ? '' : this.myProps.value.invalid ? 'bg-danger' : this.myProps.value.touched ? 'bg-success' : ''} bg-opacity-10`;
return <div className={'mb-1 l-no-bg'}>
<FloatingLabel label={this.myProps.label} className={`${this.myProps.className} mt-0 mb-0`}>
<FormControl type='date' placeholder={this.myProps.label} disabled={this.myProps.disabled} onChange={this.onChange}
value={this.dateConvert} className={inputClassName}/>
</FloatingLabel>
<FormText children={this.myProps.value.firstError} className={`text-danger mt-0 mb-0 d-block`}/>
</div>
}
}

View File

@ -1,7 +1,7 @@
import {ComponentContext} from "../../utils/ComponentContext"; import {ComponentContext} from "../../utils/ComponentContext";
import {TableDescriptor} from "../../utils/tables"; import {TableDescriptor} from "../../utils/tables";
import {observer} from "mobx-react"; import {observer} from "mobx-react";
import {action, computed, makeObservable, observable, reaction, runInAction} from "mobx"; import {action, computed, makeObservable, observable, runInAction} from "mobx";
import {Button, ButtonGroup, FormSelect, FormText, Table} from "react-bootstrap"; import {Button, ButtonGroup, FormSelect, FormText, Table} from "react-bootstrap";
import _ from "lodash"; import _ from "lodash";
import React, {ChangeEvent} from "react"; import React, {ChangeEvent} from "react";
@ -24,15 +24,6 @@ export class DataTable<R> extends ComponentContext<DataTableProps<R> & { classNa
constructor(props: DataTableProps<R>) { constructor(props: DataTableProps<R>) {
super(props); super(props);
makeObservable(this); makeObservable(this);
reaction(() => this.descriptor.pageable, () => {
if (!this.descriptor.pageable) {
this.descriptor.pageSize = this.descriptor.data.length;
} else {
this.descriptor.page = 0;
this.descriptor.pageSize = _.toNumber(10);
}
}, {fireImmediately: true});
} }
@observable descriptor = this.props.tableDescriptor; @observable descriptor = this.props.tableDescriptor;
@ -44,6 +35,19 @@ export class DataTable<R> extends ComponentContext<DataTableProps<R> & { classNa
@observable className = this.props.className; @observable className = this.props.className;
@observable additionalButtons?: React.ReactNode = this.props.additionalButtons; @observable additionalButtons?: React.ReactNode = this.props.additionalButtons;
componentDidUpdate() {
runInAction(() => {
this.descriptor = this.props.tableDescriptor;
this.name = this.props.name;
this.headless = this.props.headless;
this.filterModalState = this.props.filterModalState;
this.editable = this.props.editable;
this.editableModalState = this.props.editableModalState;
this.className = this.props.className;
this.additionalButtons = this.props.additionalButtons;
});
}
@computed @computed
get isFirstPage() { get isFirstPage() {
return this.descriptor.page === 0; return this.descriptor.page === 0;
@ -86,7 +90,7 @@ export class DataTable<R> extends ComponentContext<DataTableProps<R> & { classNa
this.descriptor.pageSize = _.toNumber(e.target.value); this.descriptor.pageSize = _.toNumber(e.target.value);
} }
@computed // not computed, since we want to show initial data, when no sorts applied
get filteredData() { get filteredData() {
const filters = this.descriptor.filters.filter(filter => filter); const filters = this.descriptor.filters.filter(filter => filter);
return this.descriptor.data.filter(row => ((filters && filters.length) > 0 ? filters.every(filter => filter(row)) : true)); return this.descriptor.data.filter(row => ((filters && filters.length) > 0 ? filters.every(filter => filter(row)) : true));
@ -189,8 +193,9 @@ export class DataTable<R> extends ComponentContext<DataTableProps<R> & { classNa
borderLeft: firstColumn ? 'none' : '1px solid var(--bs-table-border-color)', borderLeft: firstColumn ? 'none' : '1px solid var(--bs-table-border-color)',
borderRight: lastColumn ? 'none' : '1px solid var(--bs-table-border-color)', borderRight: lastColumn ? 'none' : '1px solid var(--bs-table-border-color)',
}; };
return <th key={column.renderKey} style={style} className={'_table-header'}> return <th key={column.renderKey} style={style} className={'_table-header'}>
<div className={`d-flex align-items-center justify-content-center position-relative user-select-none`} style={{cursor: "pointer"}} <div className={'d-flex align-items-center justify-content-center position-relative user-select-none'} style={{cursor: "pointer"}}
onClick={() => runInAction(() => { onClick={() => runInAction(() => {
const other = this.descriptor.columns const other = this.descriptor.columns
.filter(c => c.key !== column.key) .filter(c => c.key !== column.key)
@ -253,10 +258,12 @@ export class DataTable<R> extends ComponentContext<DataTableProps<R> & { classNa
borderRight: lastColumn ? 'none' : '1px solid var(--bs-table-border-color)', borderRight: lastColumn ? 'none' : '1px solid var(--bs-table-border-color)',
borderBottom: lastRow && !this.editable ? 'none' : '1px solid var(--bs-table-border-color)', borderBottom: lastRow && !this.editable ? 'none' : '1px solid var(--bs-table-border-color)',
} }
return <td className={'text-center'} key={_.uniqueId(column.key)} style={style}> return <td className={'text-center'} key={_.uniqueId(column.key)}
style={style}>
<span>{column.format(rowAny[column.key], row)}</span> <span>{column.format(rowAny[column.key], row)}</span>
{ {
suffixElement && <span className={'ms-2'}>{suffixElement}</span> suffixElement &&
<span className={'ms-2'}>{suffixElement}</span>
} }
</td> </td>
}) })

View File

@ -1,294 +0,0 @@
import React from "react";
import {ModalState} from "../../utils/modalState";
import {observer} from "mobx-react";
import {action, makeObservable, observable, runInAction} from "mobx";
import {Button, Card, Col, Modal, ModalBody, ModalFooter, ModalHeader, ModalTitle, Row} from "react-bootstrap";
import {DragDropContext, Draggable, Droppable, DropResult} from 'react-beautiful-dnd';
import {Defense} from "../../models/defense";
import {fullName} from "../../models/participant";
import _ from "lodash";
import {get, post} from "../../utils/request";
import {StudentData} from "../../models/studentData";
import {NotificationService} from "../../services/NotificationService";
export interface DayAndOrderChangeModalProps {
modalState: ModalState;
defense: Defense;
}
const getAllStudByDefId = (id: number) => {
return get<StudentData[]>('student/by-defense-id', {id: id});
}
const getStudByStud = (students: StudentData[]): DGDStudent[] => {
return students.map(stud => { return {
day: stud.protDay,
id: _.toString(stud.id),
fullName: fullName(stud.participant),
curatorName: stud.curator ? fullName(stud.curator?.participant) : "Не назначен",
order: stud.protOrder,
topicName: stud.diplomaTopic ? stud.diplomaTopic.name : "Не выбрана",
} as DGDStudent});
}
const groupStudentsByDay = (students: DGDStudent[]): [DGDDay[], DGDStudent[]] => {
const daysMap: { [key: number]: DGDDay } = {};
const unassigned: DGDStudent[] = [];
students.forEach(student => {
if (student.day !== undefined && Number.isInteger(student.day)) {
const day = student.day;
if (!daysMap[day]) {
daysMap[day] = {
students: [student],
title: `День ${day}`,
id: day.toString(),
};
} else {
daysMap[day].students.push(student);
}
} else {
unassigned.push(student);
}
});
return [Object.values(daysMap), unassigned];
};
interface DGDStudent {
id: string;
fullName: string;
curatorName: string;
topicName: string;
day: number;
order: number;
}
interface DGDDay {
id: string,
title: string,
students: DGDStudent[],
}
class Fields {
constructor(private props: DayAndOrderChangeModalProps) {
makeObservable(this);
getAllStudByDefId(props.defense.id).then((stud) => {
runInAction(() => {
this.modalState = props.modalState;
this.students = getStudByStud(stud);
let grouped = groupStudentsByDay(this.students);
this.days = grouped[0];
this.unassigned = grouped[1];
});
});
}
@observable students: DGDStudent[] = [];
@observable unassigned: DGDStudent[] = [];
@observable days: DGDDay[] = [];
@observable modalState: ModalState;
@action.bound
onDragEnd(result: DropResult): void {
const { source, destination } = result;
if (!destination || (source.droppableId === destination.droppableId && source.index === destination.index)) {
return;
}
runInAction(() => {
const sourceId = source.droppableId;
const destId = destination.droppableId;
const getList = (id: string) => {
return id === 'unassigned'
? this.unassigned
: this.days.find(day => day.id === id)?.students || [];
};
const sourceList = getList(sourceId);
const destList = sourceId === destId ? sourceList : getList(destId);
const [movedItem] = sourceList.splice(source.index, 1);
destList.splice(destination.index, 0, movedItem);
movedItem.day = destId === 'unassigned' ? undefined : parseInt(destId);
});
}
@action.bound
addDay(): void {
runInAction(() => {
const maxId = this.days.length > 0 ? Math.max(...this.days.map(d => _.toNumber(d.id))) : 0;
const newDay: DGDDay = {
id: _.toString(maxId + 1),
title: `День ${this.days.length + 1}`,
students: [],
};
this.days = [...this.days, newDay];
});
}
@action.bound
removeDay(dayId: string): void {
runInAction(() => {
const day = this.days.find(d => d.id === dayId);
if (day) {
day.students.forEach(student => {
student.day = undefined;
student.order = undefined;
});
this.unassigned = [...this.unassigned, ...day.students];
this.days = this.days.filter(d => d.id !== dayId);
this.days.forEach((day: DGDDay, idx) => {
day.id = _.toString(idx + 1);
day.title = `День ${day.id}`;
})
this.students = [
...this.days.flatMap(d => d.students),
...this.unassigned,
];
}
});
}
@action.bound
save(): void {
let data = {
defenseId: this.props.defense.id,
days: this.days.map((d) => { return {
number: _.toNumber(d.id),
studs: d.students.map((student: DGDStudent, idx) => {
return {id: _.toNumber(student.id), order: idx}
}),
}}),
unassigned: this.unassigned.map((student: DGDStudent) => {
return {id: _.toNumber(student.id)}
}),
};
console.log(data);
post('defense/save-order', data).then(() => {
NotificationService.success("День и порядок защиты успешно обновлен");
setTimeout(() => {
window.location.reload();
}, 2000);
});
}
}
@observer
export class DayAndOrderChangeModal extends React.Component<DayAndOrderChangeModalProps> {
constructor(props: any) {
super(props);
makeObservable(this);
runInAction(() => {
this.fields = new Fields(props);
});
}
@observable fields: Fields;
render() {
return <>
{ this.fields.modalState &&
<Modal show={this.fields.modalState.isOpen} size={'xl'}>
<ModalHeader><ModalTitle>Формирование дня и порядка защиты</ModalTitle></ModalHeader>
<ModalBody>
<DragDropContext onDragEnd={this.fields.onDragEnd}>
<Row>
{this.fields.days.map(day => (
<Col md={4} key={day.id} className="mb-3">
<Card>
<Card.Header className="d-flex justify-content-between align-items-center">
<span>{day.title}</span>
<Button variant="danger" size="sm" onClick={() => this.fields.removeDay(day.id)}>
Удалить
</Button>
</Card.Header>
<Droppable droppableId={day.id}>
{(provided) => (
<Card.Body
{...provided.droppableProps}
ref={provided.innerRef}
className="day-list"
>
{day.students.map((student, index) => (
<Draggable key={student.id} draggableId={student.id} index={index}>
{(providedInner) => (
<div
ref={providedInner.innerRef}
{...providedInner.draggableProps}
{...providedInner.dragHandleProps}
className="student-item mb-2"
>
<>
<div>{student.fullName} ({index + 1})</div>
{
!_.isEmpty(student.topicName) &&
<div>Тема ВКР: {student.topicName}</div>
}
{
!_.isEmpty(student.curatorName) &&
<div>Науч.Рук.: {student.curatorName}</div>
}
</>
</div>
)}
</Draggable>
))}
{provided.placeholder}
</Card.Body>
)}
</Droppable>
</Card>
</Col>
))}
<Col md={4} className="mb-3">
<Card>
<Card.Header>Нераспределённые студенты</Card.Header>
<Droppable droppableId="unassigned">
{(provided) => (
<Card.Body
{...provided.droppableProps}
ref={provided.innerRef}
className="day-list"
>
{this.fields.unassigned.map((student, index) => (
<Draggable key={student.id} draggableId={student.id} index={index}>
{(providedInner) => (
<div
ref={providedInner.innerRef}
{...providedInner.draggableProps}
{...providedInner.dragHandleProps}
className="student-item mb-2"
>
<>
<div>{student.fullName}</div>
{
!_.isEmpty(student.topicName) &&
<div>Тема ВКР: {student.topicName}</div>
}
{
!_.isEmpty(student.curatorName) &&
<div>Науч.Рук.: {student.curatorName}</div>
}
</>
</div>
)}
</Draggable>
))}
{provided.placeholder}
</Card.Body>
)}
</Droppable>
</Card>
</Col>
</Row>
</DragDropContext>
</ModalBody>
<ModalFooter>
<Button variant="outline-primary" onClick={this.fields.addDay}>Добавить день</Button>
<Button variant={'primary'} onClick={this.fields.save}>Сохранить</Button>
<Button variant={'outline-secondary'} onClick={() => this.fields.modalState.close()}>Закрыть</Button>
</ModalFooter>
</Modal>
}
</>
}
}

View File

@ -1,498 +0,0 @@
import {observer} from "mobx-react";
import {Page} from "../layout/Page";
import {action, makeObservable, observable, reaction, runInAction} from "mobx";
import React from "react";
import {RouterService} from "../../services/RouterService";
import {get, getFile, post} from "../../utils/request";
import {Defense, mapStatusName} from "../../models/defense";
import {Button, Col, Row, Tab, Tabs} from "react-bootstrap";
import {SelectInputValue} from "../controls/ReactiveControls";
import {ReactiveValue} from "../../utils/reactive/reactiveValue";
import {CommissionMember} from "../../models/commissionMember";
import {fullName, Participant} from "../../models/participant";
import _ from "lodash";
import {Group} from "../../models/group";
import {dateConverter} from "../../utils/converters";
import {NotificationService} from "../../services/NotificationService";
import {UserService} from "../../services/UserService";
import {Column, TableDescriptor} from "../../utils/tables";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {StudentData} from "../../models/studentData";
import {ModalState} from "../../utils/modalState";
import {DataTable} from "../data-tables/DataTable";
import ParticipantProfileModal from "../participant/ParticipantProfileModal";
import {DayAndOrderChangeModal} from "./DayAndOrderChangeModal";
interface GroupItemData {
groupsId: number;
studId: number;
groupName: string;
number: number;
fio: string;
pdpMark: number;
topic: string;
teacherFio: string;
dayOfProt: number;
placeOfProt: number;
magistracy: boolean;
electronic: boolean;
otziv: number;
dpedefenseMark: number;
normcontrol: boolean;
antipl: number;
vnedreniye: boolean;
otlichiye: boolean;
zachetka: boolean;
work: string;
}
interface DefenseTableData {
defenseId: number;
groups: GroupItemData[];
}
const getDefenseTable = (defenseId: number) => {
return get<DefenseTableData>('defense/defense-table', {defenseId: defenseId});
}
const getDefenseById = (defenseId: string) => {
return get<Defense>('defense/get-by-id', {id: defenseId});
}
const mapGek = (g: CommissionMember) => {
return {value: _.toString(g.id), label: fullName(g.participant)} as SelectInputValue;
}
const mapGroup = (g: Group) => {
return {value: _.toString(g.id), label: g.name} as SelectInputValue;
}
const getStudentById = (studentId: number) => {
return get<StudentData>('student/by-id', {id: studentId});
}
class Fields {
constructor() {
makeObservable(this);
reaction(() => {
return {td: this.defenseTableData, dtd: this.dayDefenseTableData}
}, () => {
if (!this.defenseTableData) return;
let descriptors: TableDescriptor<GroupItemData>[] = [];
this.defenseTableData.forEach((val) => {
descriptors.push(
new TableDescriptor<GroupItemData>([
new Column<GroupItemData, number>('number', '№', (v) => v ? v : '-'),
new Column<GroupItemData, string>('fio', 'ФИО студента', (v) => v ? v : '-', (gid: GroupItemData) => {
return <FontAwesomeIcon icon={'file-pen'} style={{'cursor': 'pointer'}}
data-value={gid.studId} onClick={this.onIconClicked}/>;
}),
new Column<GroupItemData, string>('topic', 'Тема', (v) => v ? v : '-'),
new Column<GroupItemData, string>('pdpMark', 'Преддипломная практика', (v) => v ? v : '-'),
new Column<GroupItemData, string>('teacherFio', 'Руководитель', (v) => v ? v : '-'),
new Column<GroupItemData, string>('dayOfProt', 'День защиты', (v) => v ? v : '-'),
new Column<GroupItemData, string>('placeOfProt', 'Порядок защиты', (v) => v ? v : '-'),
new Column<GroupItemData, boolean>('magistracy', 'Магистратура', (v) => v ? '+' : '-'),
new Column<GroupItemData, boolean>('electronic', 'Работа в эл. виде', (v) => v ? '+' : '-', undefined, undefined, "5"),
new Column<GroupItemData, number>('otziv', 'Отзыв', (v) => v ? v : '-'),
new Column<GroupItemData, number>('dpedefenseMark', 'Предзащита', (v) => v ? v : '-'),
new Column<GroupItemData, number>('normcontrol', 'Нормоконтроль', (v) => v ? '+' : '-'),
new Column<GroupItemData, number>('antipl', 'Антиплагиат', (v) => v ? `${v}%` : '-'),
new Column<GroupItemData, boolean>('vnedreniye', 'Примечания', (v, data) => {
let string = "";
if (data.vnedreniye) string += "Заявка и акт о внедрении";
if (data.otlichiye) {
if (string.length > 0) string += ",\n";
string += "Заявка на диплом с отличием";
}
return string;
}),
new Column<GroupItemData, string>('zachetka', 'Зачетка сдана', (v) => v ? '+' : '-'),
new Column<GroupItemData, number>('work', 'Работа', (v) => v ? v : '-'),
], val, false
)
);
});
this.tableDescriptors = descriptors;
let dayDescriptors: TableDescriptor<GroupItemData>[] = [];
this.dayDefenseTableData.forEach((val) => {
dayDescriptors.push(
new TableDescriptor<GroupItemData>([
new Column<GroupItemData, number>('number', '№', (v) => v ? v : '-'),
new Column<GroupItemData, string>('fio', 'ФИО студента', (v) => v ? v : '-', (gid: GroupItemData) => {
return <FontAwesomeIcon icon={'file-pen'} style={{'cursor': 'pointer'}}
data-value={gid.studId} onClick={this.onIconClicked}/>;
}),
new Column<GroupItemData, string>('topic', 'Тема', (v) => v ? v : '-'),
new Column<GroupItemData, string>('pdpMark', 'Преддипломная практика', (v) => v ? v : '-'),
new Column<GroupItemData, string>('teacherFio', 'Руководитель', (v) => v ? v : '-'),
new Column<GroupItemData, string>('dayOfProt', 'День защиты', (v) => v ? v : '-'),
new Column<GroupItemData, string>('placeOfProt', 'Порядок защиты', (v) => v ? v : '-'),
new Column<GroupItemData, boolean>('magistracy', 'Магистратура', (v) => v ? '+' : '-'),
new Column<GroupItemData, boolean>('electronic', 'Работа в эл. виде', (v) => v ? '+' : '-', undefined, undefined, "5"),
new Column<GroupItemData, number>('otziv', 'Отзыв', (v) => v ? v : '-'),
new Column<GroupItemData, number>('dpedefenseMark', 'Предзащита', (v) => v ? v : '-'),
new Column<GroupItemData, number>('normcontrol', 'Нормоконтроль', (v) => v ? '+' : '-'),
new Column<GroupItemData, number>('antipl', 'Антиплагиат', (v) => v ? `${v}%` : '-'),
new Column<GroupItemData, boolean>('vnedreniye', 'Примечания', (v, data) => {
let string = "";
if (data.vnedreniye) string += "Заявка и акт о внедрении";
if (data.otlichiye) {
if (string.length > 0) string += ",\n";
string += "Заявка на диплом с отличием";
}
return string;
}),
new Column<GroupItemData, string>('zachetka', 'Зачетка сдана', (v) => v ? '+' : '-'),
new Column<GroupItemData, number>('work', 'Работа', (v) => v ? v : '-'),
], val, false
)
);
});
this.dayTableDescriptors = dayDescriptors;
}, {fireImmediately: true});
reaction(() => {
return {user: UserService.user, def: this.defense}
}, () => {
this.canChangeDefense = UserService.isSecretary
|| UserService.isAdministrator
|| UserService.isDirOfPrepResponsible(this.defense?.preparationDirection);
}, {fireImmediately: true});
let routerOptions = RouterService.getOptions();
if (!routerOptions.defenseId) {
NotificationService.error('Не наедена защита');
} else {
getDefenseById(routerOptions.defenseId).then((defense: Defense) => {
runInAction(() => {
this.defense = defense;
if (defense.commissionMembers && !_.isEmpty(defense.commissionMembers)) {
this.allGek = defense.commissionMembers.map(mapGek);
this.selectedGek.setAuto(this.allGek);
}
if (defense.groups && !_.isEmpty(defense.groups)) {
this.allGroups = defense.groups.map(mapGroup);
this.selectedGroups.setAuto(this.allGroups);
}
this.defDate.setAuto(dateConverter(defense.defenseDate));
this.status.setAuto(mapStatusName(defense.status));
this.updateDefData();
})
});
}
}
@observable defense: Defense;
@observable allGek: SelectInputValue[];
@observable selectedGek = new ReactiveValue<SelectInputValue[]>();
@observable allGroups: SelectInputValue[] = [];
@observable selectedGroups = new ReactiveValue<SelectInputValue[]>();
@observable defDate = new ReactiveValue<string>();
@observable status = new ReactiveValue<string>();
@observable canChangeDefense: boolean;
@observable defenseTableData: Map<string, GroupItemData[]>;
@observable tableDescriptors: TableDescriptor<GroupItemData>[] = [];
@observable dayDefenseTableData: Map<string, GroupItemData[]>;
@observable dayTableDescriptors: TableDescriptor<GroupItemData>[] = [];
@observable selectedPartic: Participant;
@observable participantModalState = new ModalState(false, this.updateDefData);
@observable changeDefDayModalState = new ModalState(false, this.updateDefData);
@action.bound
updateDefData() {
getDefenseTable(_.toNumber(this.defense.id)).then(dt => {
runInAction(() => {
let defTable = _.cloneDeep(dt);
const grouped = defTable.groups?.reduce((acc: Map<string, GroupItemData[]>, item: GroupItemData) => {
const group = acc.get(item.groupName) || [];
group.push(item);
acc.set(item.groupName, group);
return acc;
}, new Map<string, GroupItemData[]>());
let tableData = new Map(
Array.from(grouped.entries())
.sort((a, b) => a[0].localeCompare(b[0]))
.map(([key, items]) => [
key,
items.sort((a, b) => a.fio.localeCompare(b.fio)),
])
);
tableData.forEach((item: GroupItemData[]) => {
let number = 1;
item.forEach((item: GroupItemData) => {
item.number = number++;
});
});
this.defenseTableData = tableData;
let dayDefTable = _.cloneDeep(dt);
const dayGrouped = dayDefTable.groups?.reduce((acc: Map<string, GroupItemData[]>, item: GroupItemData) => {
const defDay = acc.get(_.toString(item.dayOfProt)) || [];
defDay.push(item);
acc.set(_.toString(item.dayOfProt), defDay);
return acc;
}, new Map<string, GroupItemData[]>());
let dayTableData = new Map(
Array.from(dayGrouped.entries())
.sort((a, b) => _.toNumber(a[0]) - _.toNumber(b[0]))
.map(([key, items]) => [
key,
items.filter(v => v.dayOfProt && v.placeOfProt)
.sort((a, b) => a.placeOfProt - b.placeOfProt),
])
);
dayTableData.forEach((item: GroupItemData[]) => {
let number = 1;
item.forEach((item: GroupItemData) => {
item.number = number++;
});
});
this.dayDefenseTableData = dayTableData;
});
});
}
@action.bound
openChangeDefDayModal() {
this.changeDefDayModalState.open();
}
@action.bound
requestToNextState() {
post(`defense/to-next-state`, {id: this.defense.id}).then(() => {
NotificationService.success("Защита успешно переведена на следующий этап");
setTimeout(() => {
window.location.reload();
}, 2000);
});
}
@action.bound
requestRecreateDefDay() {
post(`defense/recreate-protection-order`, {id: this.defense.id}).then(() => {
NotificationService.success("День и порядок защиты успешно сформированы");
setTimeout(() => {
window.location.reload();
}, 2000);
});
}
@action.bound
onIconClicked(event: React.MouseEvent<any>) {
let studId = _.toNumber(event.currentTarget.getAttribute('data-value'));
if (studId) {
getStudentById(studId).then(student => {
runInAction(() => {
this.selectedPartic = student.participant;
this.participantModalState.open();
});
});
}
}
@action.bound
downloadList() {
getFile('doc/stud-list', {id: this.defense.id}, "список_защищающихся.docx").then();
}
@action.bound
downloadBlank() {
getFile('doc/gek-questions', {id: this.defense.id}, "бланки_вопросов_для_ГЭК.docx").then();
}
@action.bound
downloadFragment() {
getFile('doc/topic-list', {id: this.defense.id}, рагмент_приказа_оемах_вкр.docx").then();
}
}
@observer
export class DefenceEditPage extends Page {
constructor(props: any) {
super(props);
makeObservable(this);
runInAction(() => {
this.fields = new Fields();
});
}
@observable fields: Fields;
get page() {
return <>
<MainData fields={this.fields}/>
</>
}
}
@observer
class MainData extends React.Component<{ fields: Fields }> {
constructor(props: any) {
super(props);
makeObservable(this);
runInAction(() => {
this.fields = props.fields;
})
}
@observable fields: Fields;
render() {
return <>
<h1 className={"text-center"}>Защита</h1>
<Tabs defaultActiveKey="default" id="def-tabs" className={'d-flex flex-row justify-content-end mb-4'}>
<Tab title={"Общие данные"} eventKey={"default"}>
<Row>
<Col>
<Groups fields={this.fields}/>
</Col>
<Col>
<Gek fields={this.fields}/>
</Col>
</Row>
<DefDate fields={this.fields}/>
<DefStatus fields={this.fields}/>
{
this.fields.canChangeDefense &&
<div className={'d-flex flex-row justify-content-end'}>
<Button variant={'outline-primary'} onClick={this.fields.requestToNextState}>
Перевести на следующий этап
</Button>
</div>
}
</Tab>
<Tab title={"Сводная таблица"} eventKey={"table"}>
{
this.fields.selectedPartic &&
<ParticipantProfileModal modalState={this.fields.participantModalState} participant={this.fields.selectedPartic}/>
}
<Tabs defaultActiveKey={'tabl-main'} id={"def-tabl-tabs"} className={'d-flex flex-row justify-content-end mb-4'}>
<Tab title={"Общая"} eventKey={"tabl-main"}>
{
this.fields.tableDescriptors.map(td =>
td.data.length > 0
? <DataTable tableDescriptor={td} name={td.data[0].groupName} className={'mt-2'} key={_.toString(_.random(0, 10000000))} additionalButtons={<AdditionalButtonsTable key={_.toString(_.random(0, 10000000))} fields={this.fields}/>}/>
: <></>
)
}
</Tab>
{
this.fields.dayTableDescriptors && !_.isEmpty(this.fields.dayTableDescriptors) &&
Array.from(this.fields.dayDefenseTableData.entries()).map(([k, v], i) => {
return (
!_.isEmpty(v)
? <Tab title={`День ${k}`} key={`prot-day-${i}`} eventKey={`tabl-day-${i}`}>
<DataTable tableDescriptor={this.fields.dayTableDescriptors[i]} name={`День ${k}`} key={_.toString(_.random(0, 10000000))}/>
</Tab>
: null
)
})
}
</Tabs>
{
this.fields.canChangeDefense &&
<div className={'d-flex flex-row justify-content-end mt-3'}>
<Button variant={'outline-primary me-3'} onClick={this.fields.openChangeDefDayModal}>
Редактировать дни и порядок защиты
</Button>
<Button variant={'outline-primary'} onClick={this.fields.requestRecreateDefDay}>
Автоматически сформировать дни и порядок защиты
</Button>
</div>
}
{
this.fields.defense &&
<DayAndOrderChangeModal modalState={this.fields.changeDefDayModalState} defense={this.fields.defense}/>
}
</Tab>
{
this.fields.canChangeDefense &&
<Tab title={"Формирование документов"} eventKey={"doc_make"} className={'ps-5 pe-5'}>
<Button variant={'primary me-3'} onClick={this.fields.downloadList}>
Сформировать список защищающихся
</Button>
<Button variant={'primary me-3'} onClick={this.fields.downloadBlank}>
Сформировать бланк вопросов
</Button>
<Button variant={'primary'} onClick={this.fields.downloadFragment}>
Сформировать фрагмент приказа о темах ВКР
</Button>
</Tab>
}
</Tabs>
</>;
}
}
const Groups = observer(({fields}: { fields: Fields }) => {
return (
<div>
<div className={'h4 fw-bold'}>Защищающиеся группы:</div>
{
fields.selectedGroups.value &&
<div className={'h4'}>
{
fields.selectedGroups.value.map(g => <>{g.label}</>).reduce((prev, curr) => {
return <>{prev}<br/>{curr}</>
})
}
</div>
}
</div>
);
});
const Gek = observer(({fields}: { fields: Fields }) => {
return (
<div>
<div className={'h4 fw-bold'}>Члены ГЭК:</div>
{
fields.selectedGek.value &&
<div className={'h4'}>
{
fields.selectedGek.value.map(g => <>{g.label}</>).reduce((prev, curr) => {
return <>{prev}<br/>{curr}</>
})
}
</div>
}
</div>
);
});
const DefDate = observer(({fields}: { fields: Fields }) => {
return (
<div className={'h4 mb-3'}>Дата начала защиты: {fields.defDate.value}</div>
);
});
const DefStatus = observer(({fields}: { fields: Fields }) => {
return (
<div className={'h4 mb-3'}>Этап защиты: <span className={'fw-bold'}>{fields.status.value}</span></div>
);
});
const AdditionalButtonsTable = observer(({fields}: { fields: Fields }) => {
return (
<div className={'d-flex'}>
<div>
<Button variant="outline-secondary" size="sm" className="me-2" onClick={fields.updateDefData}>
<FontAwesomeIcon icon={'rotate'} style={{'cursor': 'pointer'}}/>
</Button>
</div>
</div>
);
});

View File

@ -7,54 +7,39 @@ import React from "react";
import {ThinkService} from "../../services/ThinkService"; import {ThinkService} from "../../services/ThinkService";
import {DataTable} from "../data-tables/DataTable"; import {DataTable} from "../data-tables/DataTable";
import {Column, TableDescriptor} from "../../utils/tables"; import {Column, TableDescriptor} from "../../utils/tables";
import {Defense} from "../../models/defense"; import {Defence} from "../../models/defence";
import {Participant} from "../../models/participant"; import {Participant} from "../../models/participant";
import {datetimeConverter} from "../../utils/converters"; import {datetimeConverter} from "../../utils/converters";
import {Button} from "react-bootstrap"; import {StudentData} from "../../models/studentData";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {DefenseInfoModal} from "./DefenseInfoModal";
import {ModalState} from "../../utils/modalState";
import _ from "lodash";
class DefenceListPageState { class DefenceListPageState {
constructor() { constructor() {
makeObservable(this); makeObservable(this);
this.updateDefences(); this.updateDefences();
reaction(() => this.defences, () => { reaction(() => this.defences, () => {
this.tableDescriptor = new TableDescriptor<Defense>([ this.tableDescriptor = new TableDescriptor<Defence>([
new Column<Defense, number>('id', 'Идентификатор', (v) => v, (defense: Defense) => { new Column<Defence, Participant[]>('commissionMembers', 'ГЭК', p => p ? p.length : 0),
return <FontAwesomeIcon icon={'file-pen'} style={{'cursor': 'pointer'}} new Column<Defence, Group[]>('groups', 'Группы', g => g && g.length ? g.map(g => g.name).join(', ') : 'Пусто'),
data-value={defense.id} onClick={this.onIconClicked}/>; new Column<Defence, Group[]>('groups', 'Студентов', g => {
}),
new Column<Defense, Participant[]>('commissionMembers', 'ГЭК', p => p ? p.length : 'Пусто'),
new Column<Defense, Group[]>('groups', 'Группы', g => g && g.length ? g.map(g => g.name).join(', ') : 'Пусто'),
new Column<Defense, Group[]>('groups', 'Студентов', g => {
if (!g) return 'Пусто'; if (!g) return 'Пусто';
let studLen = 0; const students: StudentData[] = [];
g.forEach(group => { g.forEach(group => group.students.forEach(student => students.push(student)));
studLen += group.students.length; return students.length;
});
return studLen ? studLen : 'Пусто';
}), }),
new Column<Defense, string>('createdAt', 'Дата создания', datetimeConverter), new Column<Defence, string>('createdAt', 'Дата создания', datetimeConverter),
new Column<Defense, string>('updatedAt', 'Дата обновления', datetimeConverter), new Column<Defence, string>('updatedAt', 'Дата обновления', datetimeConverter),
], this.defences, true ], this.defences, true
); );
}); });
} }
@observable defences: Defense[] = []; @observable defences: Defence[] = [];
@observable tableDescriptor: TableDescriptor<Defense>; @observable tableDescriptor: TableDescriptor<Defence>;
@observable selectedDefense: Defense = undefined;
@observable editDefenseModalState = new ModalState();
@observable newDefenseModalState = new ModalState();
@action.bound @action.bound
updateDefences() { updateDefences() {
ThinkService.think(); ThinkService.think();
get<Defense[]>('/defense/get-all').then((defences) => { get<Defence[]>('/defence/all').then((defences) => {
runInAction(() => { runInAction(() => {
this.defences = defences; this.defences = defences;
}); });
@ -62,15 +47,6 @@ class DefenceListPageState {
ThinkService.completeAll(); ThinkService.completeAll();
}); });
} }
@action.bound
onIconClicked(event: React.MouseEvent<any>) {
const d = this.defences.find(d => d.id === _.toNumber(event.currentTarget.getAttribute('data-value')));
if (d) {
this.selectedDefense = d;
this.editDefenseModalState.open();
}
}
} }
@observer @observer
@ -86,27 +62,13 @@ export class DefenceListPage extends Page {
get page() { get page() {
return <> return <>
{ {
this.fields.tableDescriptor && <>
<DataTable tableDescriptor={this.fields.tableDescriptor} name={'Защиты'} {
additionalButtons={<AdditionalButtons state={this.fields}/>}/> this.fields.tableDescriptor &&
<DataTable tableDescriptor={this.fields.tableDescriptor} name={'Защиты'} />
}
</>
} }
{
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>
);
});

View File

@ -1,291 +0,0 @@
import React, {Component} from "react";
import {ModalState} from "../../utils/modalState";
import {Defense, mapStatusName} from "../../models/defense";
import {observer} from "mobx-react";
import {action, computed, makeObservable, observable, reaction, runInAction} from "mobx";
import {Button, Modal} from "react-bootstrap";
import {DropdownSelectInput, InputDate, SelectInputValue, StringInput} from "../controls/ReactiveControls";
import {ReactiveValue} from "../../utils/reactive/reactiveValue";
import {required} from "../../utils/reactive/validators";
import _ from "lodash";
import {datetimeConverter} from "../../utils/converters";
import {Group} from "../../models/group";
import {fullName, Participant} from "../../models/participant";
import {UserService} from "../../services/UserService";
import {RouterService} from "../../services/RouterService";
import {CommissionMember} from "../../models/commissionMember";
import {get, post} from "../../utils/request";
import {NotificationService} from "../../services/NotificationService";
import {ThinkService} from "../../services/ThinkService";
import {PreparationDirection} from "../../models/preparationDirection";
const mapGroup = (g: Group) => {
return {value: _.toString(g.id), label: g.name} as SelectInputValue;
}
const mapGek = (g: CommissionMember) => {
return {value: _.toString(g.id), label: fullName(g.participant)} as SelectInputValue;
}
const getAllGroups = () => {
return get<Group[]>("group/get-all-groups");
}
const getAllGek = () => {
return get<CommissionMember[]>("commission-member/get-all");
}
const getAllNorm = () => {
return get<Participant[]>("participant/get-all-norm");
}
const getAllAntipl = () => {
return get<Participant[]>("participant/get-all-antipl");
}
const mapPartic = (p: Participant) => {
return {value: _.toString(p.id), label: fullName(p)} as SelectInputValue;
}
const getAllDirOrPrep = () => {
return get<PreparationDirection[]>('prep-direction/get-all');
}
const mapDirOfPrep = (dp: PreparationDirection) => {
return { value: _.toString(dp.id), label: dp.code } as SelectInputValue;
}
class Fields {
constructor(state: ModalState, defense?: Defense) {
makeObservable(this);
runInAction(() => {
this.modalState = state;
getAllGroups().then(groups => {
runInAction(() => {
this.allGroups = groups;
});
});
getAllGek().then(geks => {
runInAction(() => {
this.allGek = geks.map(mapGek);
});
});
getAllNorm().then(norms => {
runInAction(() => {
this.allNorm = norms.map(mapPartic);
});
});
getAllAntipl().then(norms => {
runInAction(() => {
this.allAntipl = norms.map(mapPartic);
})
});
getAllDirOrPrep().then(dp => {
runInAction(() => {
this.allDirOfPrep = dp.map(mapDirOfPrep);
})
});
reaction(() => this.dirOfPrep.value, () => {
if (this.dirOfPrep.value && this.dirOfPrep.value[0]) {
this.filteredGroups = this.allGroups
.filter(g => g.preparationDirection.id === _.toNumber(this.dirOfPrep.value[0].value))
.map(mapGroup);
} else {
this.filteredGroups = [];
}
}, {fireImmediately: true});
if (defense) {
this.editMode = false;
this.alreadyExists = true;
this.modalState = state;
this.defense = defense;
this.createdAt.setAuto(datetimeConverter(this.defense.createdAt));
this.updatedAt.setAuto(datetimeConverter(this.defense.updatedAt));
this.groups.setAuto(this.defense.groups?.map(mapGroup));
this.gek.setAuto(this.defense.commissionMembers?.map(mapGek));
if (defense.responsibleForNorm) this.selectedNorm.setAuto([mapPartic(this.defense.responsibleForNorm)]);
if (defense.responsibleForAntipl) this.selectedAntipl.setAuto([mapPartic(this.defense.responsibleForAntipl)]);
if (defense.preparationDirection) this.dirOfPrep.setAuto([mapDirOfPrep(this.defense.preparationDirection)]);
this.status.setAuto(mapStatusName(this.defense.status));
if (defense.defenseDate) this.startDate.setAuto(new Date(defense.defenseDate));
} else {
this.editMode = true;
this.status.setAuto(mapStatusName("NOT_STARTED"));
}
});
}
@observable editMode: boolean;
@observable alreadyExists = false;
@observable modalState: ModalState;
@observable defense: Defense;
@observable allGroups: Group[] = [];
@observable filteredGroups: SelectInputValue[] = [];
@observable groups = new ReactiveValue<SelectInputValue[]>().addValidator(required);
@observable allDirOfPrep: SelectInputValue[] = [];
@observable dirOfPrep = new ReactiveValue<SelectInputValue[]>().addValidator(required);
@observable allGek: SelectInputValue[] = [];
@observable gek = new ReactiveValue<SelectInputValue[]>().addValidator(required);
@observable allAntipl: SelectInputValue[] = [];
@observable selectedAntipl = new ReactiveValue<SelectInputValue[]>().addValidator(required);
@observable allNorm: SelectInputValue[] = [];
@observable selectedNorm = new ReactiveValue<SelectInputValue[]>().addValidator(required);
@observable status = new ReactiveValue<string>().addValidator(required).setAuto("");
@observable createdAt = new ReactiveValue<string>().setAuto("");
@observable updatedAt = new ReactiveValue<string>().setAuto("");
@observable startDate = new ReactiveValue<Date>().addValidator(required);
isAnyInvalid() {
let invalid = this.gek.invalid || this.groups.invalid || this.selectedAntipl.invalid || this.selectedNorm.invalid || this.dirOfPrep.invalid;
if (!this.alreadyExists) {
invalid = invalid || !this.gek.touched || !this.groups.touched || !this.selectedAntipl.touched || !this.selectedNorm.touched || !this.dirOfPrep.touched;
}
return invalid;
}
touchAll() {
this.gek.touch();
this.groups.touch();
this.selectedAntipl.touch();
this.selectedNorm.touch();
}
@action.bound
save() {
if (this.isAnyInvalid()) {
this.touchAll();
NotificationService.error("Исправьте ошибки на форме");
return;
}
const data: Defense = {
id: this.defense ? this.defense.id : undefined,
groups: this.groups.value.map(g => {
return {id: _.toNumber(g.value)} as Group
}),
commissionMembers: this.gek.value.map(g => {
return {id: _.toNumber(g.value)} as CommissionMember
}),
responsibleForAntipl: this.selectedAntipl.value && this.selectedAntipl.value[0] ? { id: _.toNumber(this.selectedAntipl.value[0].value) } : undefined,
responsibleForNorm: this.selectedNorm.value && this.selectedNorm.value[0] ? { id: _.toNumber(this.selectedNorm.value[0].value) } : undefined,
preparationDirection: this.dirOfPrep.value && this.dirOfPrep.value[0] ? { id: _.toNumber(this.dirOfPrep.value[0].value) } : undefined,
defenseDate: this.startDate.value ? this.startDate.value.toISOString() : undefined,
};
ThinkService.think();
post("defense/save", data).then(() => {
if (this.defense)
NotificationService.success("Защита успешно сохранена");
else
NotificationService.success("Защита успешно изменена");
}).finally(() => {
ThinkService.completeAll();
});
this.editMode = false;
this.modalState.close();
}
}
@observer
export class DefenseInfoModal extends Component<{ modalState: ModalState, defense?: Defense }> {
constructor(props: any) {
super(props);
makeObservable(this);
runInAction(() => {
this.fields = new Fields(this.props.modalState, this.props.defense);
});
}
componentDidUpdate() {
if (this.fields.defense != this.props.defense) {
runInAction(() => {
this.fields = new Fields(this.props.modalState, this.props.defense);
});
}
}
@observable fields: Fields;
render() {
return (
<Modal show={this.fields.modalState.isOpen} centered size={"lg"}>
<Modal.Header>
<Modal.Title>
{this.fields.editMode
? "Редактирование защиты"
: "Защита"}
</Modal.Title>
</Modal.Header>
<Modal.Body>
<DropdownSelectInput possibleValues={this.fields.allDirOfPrep} label={"Направление подготовки"} filtering singleSelect
value={this.fields.dirOfPrep} disabled={!this.fields.editMode}/>
<DropdownSelectInput possibleValues={this.fields.filteredGroups} label={"Группы"} filtering
value={this.fields.groups} disabled={!this.fields.editMode}/>
<DropdownSelectInput possibleValues={this.fields.allGek} label={"Государственная экзаменационная комиссия"} filtering
value={this.fields.gek} disabled={!this.fields.editMode}/>
<DropdownSelectInput possibleValues={this.fields.allAntipl} label={"Ответственный за антиплагиат"} filtering singleSelect
value={this.fields.selectedAntipl} disabled={!this.fields.editMode}/>
<DropdownSelectInput possibleValues={this.fields.allNorm} label={"Ответственный за нормоконтроль"} filtering singleSelect
value={this.fields.selectedNorm} disabled={!this.fields.editMode}/>
<StringInput value={this.fields.status} label={"Этап защиты"} disabled/>
<InputDate label={"Дата начала защиты"} maxDate={(() => {
let date = new Date();
date.setFullYear(date.getFullYear() + 2);
return date;
})()} minDate={new Date()} value={this.fields.startDate} disabled={!this.fields.editMode}/>
<StringInput value={this.fields.createdAt} label={"Дата создания"} disabled/>
<StringInput value={this.fields.updatedAt} label={"Дата обновления"} disabled/>
</Modal.Body>
<Modal.Footer>
{
!this.fields.editMode &&
<Button onClick={() => {
RouterService.redirect("defenseEdit", {defenseId: _.toString(this.fields.defense.id)});
}} variant={'primary'}>Подробнее</Button>
}
{
(UserService.isAdministrator || UserService.isSecretary || UserService.isDirOfPrepResponsible(this.fields.defense?.preparationDirection)) && !this.fields.editMode &&
<Button onClick={() => {
runInAction(() => {
this.fields.editMode = true;
});
}} variant={'outline-secondary'}>Редактировать</Button>
}
{
(UserService.isAdministrator || UserService.isSecretary || UserService.isDirOfPrepResponsible(this.fields.defense?.preparationDirection)) && this.fields.editMode &&
<Button onClick={this.fields.save} variant={'primary'}>Сохранить</Button>
}
<Button onClick={() => {
runInAction(() => {
this.fields.modalState.close();
if (this.fields.defense)
this.fields.editMode = false;
})
}} variant={'outline-secondary'}>Закрыть</Button>
</Modal.Footer>
</Modal>
)
}
}

View File

@ -1,85 +0,0 @@
import {ModalState} from "../../utils/modalState";
import {Group} from "../../models/group";
import {observer} from "mobx-react";
import React, {Component} from "react";
import {action, makeObservable, observable, runInAction} from "mobx";
import {ReactiveValue} from "../../utils/reactive/reactiveValue";
import {Button, Modal, ModalBody, ModalFooter, ModalHeader, ModalTitle} from "react-bootstrap";
import {StringInput} from "../controls/ReactiveControls";
import {DiplomaTopic} from "../../models/diplomaTopic";
import {fullName} from "../../models/participant";
export interface DiplomaTopicFilterProps {
modalState: ModalState;
filters: ((group: DiplomaTopic) => boolean)[];
}
@observer
export class DiplomaTopicFilterModal extends Component<DiplomaTopicFilterProps> {
constructor(props: DiplomaTopicFilterProps) {
super(props);
makeObservable(this);
runInAction(() => {
this.filters.push(this.nameFilter);
this.filters.push(this.pdCodeFilter);
this.filters.push(this.pdNameFilter);
this.filters.push(this.teacherNameFilter);
});
}
@observable filters = this.props.filters;
@observable modalState = this.props.modalState;
@observable nameField = new ReactiveValue<string>().syncWithParam('name');
@observable prepDirNameField = new ReactiveValue<string>().syncWithParam('pdn');
@observable prepDirCodeField = new ReactiveValue<string>().syncWithParam('pdc');
@observable teacherNameField = new ReactiveValue<string>().syncWithParam('tn');
@observable nameFilter = (topic: DiplomaTopic) => {
if (!this.nameField.value) return true;
return topic.name?.includes(this.nameField.value)
};
@observable pdNameFilter = (topic: DiplomaTopic) => {
if (!this.prepDirNameField.value) return true;
return topic.preparationDirection.name?.includes(this.prepDirNameField.value)
}
@observable pdCodeFilter = (topic: DiplomaTopic) => {
if (!this.prepDirCodeField.value) return true;
return topic.preparationDirection.code?.includes(this.prepDirCodeField.value)
}
@observable teacherNameFilter = (topic: DiplomaTopic) => {
if (!this.teacherNameField.value) return true;
if (!topic.teacher || !topic.teacher.participant) return false;
return fullName(topic.teacher.participant).includes(this.teacherNameField.value);
}
@action.bound
reset() {
this.nameField.set("");
this.prepDirNameField.set("");
this.prepDirCodeField.set("");
this.teacherNameField.set("");
}
render() {
return <Modal show={this.modalState.isOpen} centered>
<ModalHeader>
<ModalTitle>Фильтр</ModalTitle>
</ModalHeader>
<ModalBody>
<StringInput value={this.nameField} label={'Название'} validateless/>
<StringInput value={this.prepDirCodeField} label={'Код направления подготовки'} validateless/>
<StringInput value={this.prepDirNameField} label={'Название направления подготовки'} validateless/>
<StringInput value={this.teacherNameField} label={'ФИО Преподавателя'} validateless/>
</ModalBody>
<ModalFooter>
<Button onClick={this.reset} variant={'secondary'}>Сбросить</Button>
<Button onClick={this.modalState.close} variant={'outline-secondary'}>Закрыть</Button>
</ModalFooter>
</Modal>
}
}

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