Publication per student: checkbox in lab column, partial state in eye, cursor on Variant
This commit is contained in:
@@ -168,3 +168,15 @@ data class SubmissionDto(
|
||||
val createdAt: String,
|
||||
val files: List<String>,
|
||||
)
|
||||
|
||||
/** Публикация оценок по (группа, лаба): либо всей группе, либо списку студентов. */
|
||||
data class PublicationState(
|
||||
val all: Boolean = false,
|
||||
val studentIds: List<String> = emptyList(),
|
||||
)
|
||||
|
||||
data class PublicationSetRequest(
|
||||
val groupId: String,
|
||||
val labId: String,
|
||||
val studentIds: List<String> = emptyList(),
|
||||
)
|
||||
|
||||
@@ -2,34 +2,45 @@ package ru.ysu.lms.progress
|
||||
|
||||
import org.springframework.stereotype.Service
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
import ru.ysu.lms.progress.domain.GradePublication
|
||||
import ru.ysu.lms.progress.domain.GradePublicationStudent
|
||||
import ru.ysu.lms.progress.repo.GradePublicationRepository
|
||||
import ru.ysu.lms.progress.repo.GradePublicationStudentRepository
|
||||
import java.util.UUID
|
||||
|
||||
@Service
|
||||
class GradePublicationService(
|
||||
private val repo: GradePublicationRepository,
|
||||
private val studentRepo: GradePublicationStudentRepository,
|
||||
) {
|
||||
@Transactional
|
||||
fun setPublished(
|
||||
/** Текущее состояние публикации по (группа, лаба): группа целиком или список студентов. */
|
||||
@Transactional(readOnly = true)
|
||||
fun state(
|
||||
groupId: UUID,
|
||||
labId: UUID,
|
||||
published: Boolean,
|
||||
): PublicationState {
|
||||
val all = repo.findByLabIdAndGroupId(labId, groupId) != null
|
||||
val students = studentRepo.findByGroupIdAndLabId(groupId, labId).map { it.studentId.toString() }
|
||||
return PublicationState(all, students)
|
||||
}
|
||||
|
||||
/** Устанавливает ровно указанный набор студентов; публикация «всей группе» при этом снимается. */
|
||||
@Transactional
|
||||
fun setStudents(
|
||||
groupId: UUID,
|
||||
labId: UUID,
|
||||
studentIds: Collection<UUID>,
|
||||
) {
|
||||
val existing = repo.findByLabIdAndGroupId(labId, groupId)
|
||||
if (published && existing == null) repo.save(GradePublication(groupId, labId))
|
||||
if (!published && existing != null) repo.delete(existing)
|
||||
repo.findByLabIdAndGroupId(labId, groupId)?.let { repo.delete(it) }
|
||||
studentRepo.deleteByGroupIdAndLabId(groupId, labId)
|
||||
studentIds.distinct().forEach { studentRepo.save(GradePublicationStudent(groupId, labId, it)) }
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
fun isPublished(
|
||||
groupId: UUID,
|
||||
labId: UUID,
|
||||
): Boolean = repo.findByLabIdAndGroupId(labId, groupId) != null
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
fun publishedGroupIdsForLab(labId: UUID): List<String> = repo.findByLabId(labId).map { it.groupId.toString() }
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
fun publishedLabIdsForGroup(groupId: UUID): List<String> = repo.findByGroupId(groupId).map { it.labId.toString() }
|
||||
studentId: UUID,
|
||||
): Boolean =
|
||||
repo.findByLabIdAndGroupId(labId, groupId) != null ||
|
||||
studentRepo.existsByGroupIdAndLabIdAndStudentId(groupId, labId, studentId)
|
||||
}
|
||||
|
||||
@@ -85,28 +85,24 @@ class ProgressController(
|
||||
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
|
||||
fun listGrades(): List<GradeResponse> = grades.listGrades()
|
||||
|
||||
@PostMapping("/grades/publish")
|
||||
@GetMapping("/grades/publication")
|
||||
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
|
||||
fun publishGrades(
|
||||
fun publicationState(
|
||||
@RequestParam groupId: java.util.UUID,
|
||||
@RequestParam labId: java.util.UUID,
|
||||
@RequestParam groupId: java.util.UUID,
|
||||
@RequestParam published: Boolean,
|
||||
) {
|
||||
publications.setPublished(groupId, labId, published)
|
||||
}
|
||||
): PublicationState = publications.state(groupId, labId)
|
||||
|
||||
@GetMapping("/grades/published")
|
||||
@PostMapping("/grades/publication")
|
||||
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
|
||||
fun gradesPublished(
|
||||
@RequestParam("labId") labId: java.util.UUID,
|
||||
@RequestParam groupId: java.util.UUID,
|
||||
): Boolean = publications.isPublished(groupId, labId)
|
||||
|
||||
@GetMapping("/grades/publications")
|
||||
@PreAuthorize("isAuthenticated()")
|
||||
fun groupPublications(
|
||||
@RequestParam groupId: java.util.UUID,
|
||||
): List<String> = publications.publishedLabIdsForGroup(groupId)
|
||||
fun setPublication(
|
||||
@RequestBody body: PublicationSetRequest,
|
||||
) {
|
||||
publications.setStudents(
|
||||
java.util.UUID.fromString(body.groupId),
|
||||
java.util.UUID.fromString(body.labId),
|
||||
body.studentIds.map { java.util.UUID.fromString(it) },
|
||||
)
|
||||
}
|
||||
|
||||
@GetMapping("/me/grades")
|
||||
fun myGrades(
|
||||
@@ -115,7 +111,8 @@ class ProgressController(
|
||||
): List<GradeResponse> {
|
||||
val all = grades.listGrades().filter { it.studentId == jwt.subject }
|
||||
if (groupId == null) return emptyList()
|
||||
return all.filter { publications.isPublished(groupId, java.util.UUID.fromString(it.labId)) }
|
||||
val studentId = java.util.UUID.fromString(jwt.subject)
|
||||
return all.filter { publications.isPublished(groupId, java.util.UUID.fromString(it.labId), studentId) }
|
||||
}
|
||||
|
||||
@GetMapping("/comment-templates")
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package ru.ysu.lms.progress.domain
|
||||
|
||||
import jakarta.persistence.Column
|
||||
import jakarta.persistence.Entity
|
||||
import jakarta.persistence.Id
|
||||
import jakarta.persistence.IdClass
|
||||
import jakarta.persistence.Table
|
||||
import java.io.Serializable
|
||||
import java.time.Instant
|
||||
import java.util.UUID
|
||||
|
||||
@Entity
|
||||
@Table(name = "grade_publication_students")
|
||||
@IdClass(GradePublicationStudentKey::class)
|
||||
class GradePublicationStudent(
|
||||
@Id @Column(name = "group_id", nullable = false) var groupId: UUID = UUID(0, 0),
|
||||
@Id @Column(name = "lab_id", nullable = false) var labId: UUID = UUID(0, 0),
|
||||
@Id @Column(name = "student_id", nullable = false) var studentId: UUID = UUID(0, 0),
|
||||
@Column(name = "published_at", nullable = false) var publishedAt: Instant = Instant.now(),
|
||||
)
|
||||
|
||||
data class GradePublicationStudentKey(
|
||||
val groupId: UUID = UUID(0, 0),
|
||||
val labId: UUID = UUID(0, 0),
|
||||
val studentId: UUID = UUID(0, 0),
|
||||
) : Serializable {
|
||||
companion object {
|
||||
private const val serialVersionUID: Long = 1L
|
||||
}
|
||||
}
|
||||
@@ -10,8 +10,4 @@ interface GradePublicationRepository : JpaRepository<GradePublication, GradePubl
|
||||
labId: UUID,
|
||||
groupId: UUID,
|
||||
): GradePublication?
|
||||
|
||||
fun findByLabId(labId: UUID): List<GradePublication>
|
||||
|
||||
fun findByGroupId(groupId: UUID): List<GradePublication>
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package ru.ysu.lms.progress.repo
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository
|
||||
import ru.ysu.lms.progress.domain.GradePublicationStudent
|
||||
import ru.ysu.lms.progress.domain.GradePublicationStudentKey
|
||||
import java.util.UUID
|
||||
|
||||
interface GradePublicationStudentRepository : JpaRepository<GradePublicationStudent, GradePublicationStudentKey> {
|
||||
fun findByGroupIdAndLabId(
|
||||
groupId: UUID,
|
||||
labId: UUID,
|
||||
): List<GradePublicationStudent>
|
||||
|
||||
fun deleteByGroupIdAndLabId(
|
||||
groupId: UUID,
|
||||
labId: UUID,
|
||||
)
|
||||
|
||||
fun existsByGroupIdAndLabIdAndStudentId(
|
||||
groupId: UUID,
|
||||
labId: UUID,
|
||||
studentId: UUID,
|
||||
): Boolean
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
-- Per-student grade publication: which students see the grade and comments for a lab.
|
||||
-- The older group-wide rows in grade_publications keep meaning "visible to everyone in the group".
|
||||
|
||||
CREATE TABLE grade_publication_students (
|
||||
group_id uuid NOT NULL,
|
||||
lab_id uuid NOT NULL,
|
||||
student_id uuid NOT NULL,
|
||||
published_at timestamptz NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (group_id, lab_id, student_id)
|
||||
);
|
||||
Reference in New Issue
Block a user