Refactor: split loop/throws helpers; drop deprecated JSON accessors
This commit is contained in:
@@ -124,10 +124,22 @@ class DefenseService(
|
||||
studentId: UUID,
|
||||
code: String,
|
||||
): DefenseSession {
|
||||
val s = sessions.findByCode(code.trim()) ?: throw BadRequestException("Код не найден")
|
||||
if (s.studentId != studentId) throw ForbiddenException("Этот код выдан другому студенту")
|
||||
if (s.status != DefenseStatus.waiting.name) throw BadRequestException("Защита по этому коду уже начата")
|
||||
return s
|
||||
val session = findSessionByCode(code)
|
||||
requireOwnerAndWaiting(session, studentId)
|
||||
return session
|
||||
}
|
||||
|
||||
private fun findSessionByCode(code: String): DefenseSession =
|
||||
sessions.findByCode(code.trim()) ?: throw BadRequestException("Код не найден")
|
||||
|
||||
private fun requireOwnerAndWaiting(
|
||||
session: DefenseSession,
|
||||
studentId: UUID,
|
||||
) {
|
||||
if (session.studentId != studentId) throw ForbiddenException("Этот код выдан другому студенту")
|
||||
if (session.status != DefenseStatus.waiting.name) {
|
||||
throw BadRequestException("Защита по этому коду уже начата")
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
|
||||
@@ -20,6 +20,7 @@ import ru.ysu.lms.web.api.CreateStudentRequestDto
|
||||
import ru.ysu.lms.web.api.DistributeRequestPayload
|
||||
import ru.ysu.lms.web.api.GradeSetPayload
|
||||
import ru.ysu.lms.web.api.LabCreatePayload
|
||||
import ru.ysu.lms.web.api.LabSummaryDto
|
||||
import ru.ysu.lms.web.api.LabUpdatePayload
|
||||
import ru.ysu.lms.web.api.LevelAssignPayload
|
||||
import ru.ysu.lms.web.api.LevelPayload
|
||||
@@ -479,29 +480,13 @@ class AdminController(
|
||||
var count = 0
|
||||
var skipped = 0
|
||||
for ((idx, rawCols) in rows.withIndex()) {
|
||||
val cells = rawCols.map { it.trim() }
|
||||
if (cells.all { it.isBlank() }) continue
|
||||
if (idx == 0 && looksLikeHeader(cells)) continue
|
||||
var sid: String? = null
|
||||
var lid: String? = labId?.takeIf { it.isNotBlank() }
|
||||
var md: String? = null
|
||||
when {
|
||||
cells.size >= 3 -> {
|
||||
sid = studentByNo[cells[0]]
|
||||
lid = labByNumber[cells[1]]?.id ?: lid
|
||||
md = cells.drop(2).joinToString("; ")
|
||||
}
|
||||
cells.size == 2 -> {
|
||||
sid = studentByNo[cells[0]]
|
||||
md = cells[1]
|
||||
}
|
||||
}
|
||||
if (sid == null || lid.isNullOrBlank() || md.isNullOrBlank()) {
|
||||
val row = resolveDefenseRow(rawCols, idx, labId, studentByNo, labByNumber)
|
||||
if (row == null) {
|
||||
skipped++
|
||||
continue
|
||||
} else {
|
||||
api.assignDefense(t, row.studentId, row.labId, row.assignmentMd.replace("\\n", "\n"))
|
||||
count++
|
||||
}
|
||||
api.assignDefense(t, sid, lid, md.replace("\\n", "\n"))
|
||||
count++
|
||||
}
|
||||
val tail = if (skipped > 0) ", пропущено: $skipped" else ""
|
||||
redirect.addFlashAttribute("notice", "Импортировано заданий: $count$tail")
|
||||
@@ -511,6 +496,41 @@ class AdminController(
|
||||
redirectToGroup(groupId, labId)
|
||||
}
|
||||
|
||||
private data class DefenseRow(
|
||||
val studentId: String,
|
||||
val labId: String,
|
||||
val assignmentMd: String,
|
||||
)
|
||||
|
||||
/** Разбирает строку CSV с заданием на защиту; null — строку нужно пропустить. */
|
||||
private fun resolveDefenseRow(
|
||||
rawCols: List<String>,
|
||||
index: Int,
|
||||
defaultLabId: String?,
|
||||
studentByNo: Map<String, String>,
|
||||
labByNumber: Map<String, LabSummaryDto>,
|
||||
): DefenseRow? {
|
||||
val cells = rawCols.map { it.trim() }
|
||||
if (cells.all { it.isBlank() }) return null
|
||||
if (index == 0 && looksLikeHeader(cells)) return null
|
||||
var sid: String? = null
|
||||
var lid: String? = defaultLabId?.takeIf { it.isNotBlank() }
|
||||
var md: String? = null
|
||||
when {
|
||||
cells.size >= 3 -> {
|
||||
sid = studentByNo[cells[0]]
|
||||
lid = labByNumber[cells[1]]?.id ?: lid
|
||||
md = cells.drop(2).joinToString("; ")
|
||||
}
|
||||
cells.size == 2 -> {
|
||||
sid = studentByNo[cells[0]]
|
||||
md = cells[1]
|
||||
}
|
||||
}
|
||||
if (sid == null || lid.isNullOrBlank() || md.isNullOrBlank()) return null
|
||||
return DefenseRow(sid, lid, md)
|
||||
}
|
||||
|
||||
private fun looksLikeHeader(cells: List<String>): Boolean {
|
||||
val joined = cells.joinToString(" ").lowercase()
|
||||
return joined.contains("студент") ||
|
||||
@@ -1250,11 +1270,11 @@ class AdminController(
|
||||
val node = mapper.readTree(json)
|
||||
buildList {
|
||||
node.forEach { el ->
|
||||
val text = el.path("text").asText("").trim()
|
||||
val text = el.path("text").asString("").trim()
|
||||
if (text.isNotEmpty()) {
|
||||
add(
|
||||
ru.ysu.lms.web.api
|
||||
.CommentPayload(text, el.path("tone").asText("neutral")),
|
||||
.CommentPayload(text, el.path("tone").asString("neutral")),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user