Skip to content

Commit 3a2f273

Browse files
authored
Merge pull request #387 from GSM-MSG/feature/386-teacher-grading-form
선생님 학생 채점 기능 개발
2 parents 31597cc + 1001c8a commit 3a2f273

25 files changed

+233
-18
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package team.msg.sms.domain.authentication.dto.req
2+
3+
import java.util.UUID
4+
5+
data class GradingRequestData(
6+
val setId: UUID,
7+
val score: Double?
8+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package team.msg.sms.domain.authentication.exception
2+
3+
import team.msg.sms.common.error.SmsException
4+
import team.msg.sms.domain.authentication.exception.error.AuthenticationErrorCode
5+
6+
object UserFormValueNotFoundException : SmsException(
7+
AuthenticationErrorCode.USER_FORM_VALUE_NOT_FOUND
8+
)

sms-core/src/main/kotlin/team/msg/sms/domain/authentication/exception/error/AuthenticationErrorCode.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ enum class AuthenticationErrorCode(
1515
INVALID_GRADE_CLASS(ErrorStatus.FORBIDDEN, "담임 선생님만 조회할 수 있습니다."),
1616
ALREADY_GIVEN_SCORE(ErrorStatus.CONFLICT, "이미 활동에 점수가 부여되었습니다."),
1717
NO_REQUESTED_ACTIVITY(ErrorStatus.CONFLICT, "활동이 아직 요청되지 않았습니다."),
18-
MARKING_BOARD_NOT_FOUND(ErrorStatus.NOT_FOUND, "학생이 제출한 폼이 조회되지 않습니다.")
18+
MARKING_BOARD_NOT_FOUND(ErrorStatus.NOT_FOUND, "학생이 제출한 폼이 조회되지 않습니다."),
19+
USER_FORM_VALUE_NOT_FOUND(ErrorStatus.NOT_FOUND, "채점 데이터의 존재하지 않는 폼 제출 데이터가 포함되어있습니다.")
1920
;
2021

2122
override fun status(): Int = status

sms-core/src/main/kotlin/team/msg/sms/domain/authentication/model/MarkingValue.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ import java.util.UUID
55

66
data class MarkingValue(
77
val id: UUID,
8-
val score: Double,
8+
val score: Double?,
99
val type: MarkingType,
10-
val fieldId: UUID,
11-
val groupId: UUID,
10+
val setId: UUID,
11+
val markingBoardId: UUID,
1212
val createdAt: LocalDateTime,
1313
val createdBy: UUID
14-
)
14+
)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package team.msg.sms.domain.authentication.service
2+
3+
import java.util.UUID
4+
5+
interface CheckUserFormValueService {
6+
fun checkUserFormValueBySetIds(setIds: List<UUID>): Boolean
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package team.msg.sms.domain.authentication.service
2+
3+
import team.msg.sms.domain.authentication.model.MarkingValue
4+
5+
interface CommandMarkingValueService {
6+
fun saveAll(markingValueList: List<MarkingValue>): List<MarkingValue>
7+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package team.msg.sms.domain.authentication.service
2+
3+
import team.msg.sms.domain.authentication.model.MarkingValue
4+
import java.util.UUID
5+
6+
interface GetMarkingValueService {
7+
fun findMarkingValueListByMarkingBoardId(markingBoardId: UUID): List<MarkingValue>
8+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package team.msg.sms.domain.authentication.service
2+
3+
import team.msg.sms.common.annotation.Service
4+
5+
@Service
6+
class MarkingValueService(
7+
commandMarkingService: CommandMarkingValueService,
8+
getMarkingValueService: GetMarkingValueService
9+
) : CommandMarkingValueService by commandMarkingService,
10+
GetMarkingValueService by getMarkingValueService

sms-core/src/main/kotlin/team/msg/sms/domain/authentication/service/UserFormValueService.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import team.msg.sms.common.annotation.Service
55
@Service
66
class UserFormValueService(
77
getUserFormValueService: GetUserFormValueService,
8-
commandUserFormValueService: CommandUserFormValueService
8+
commandUserFormValueService: CommandUserFormValueService,
9+
checkUserFormValueService: CheckUserFormValueService
910
) : GetUserFormValueService by getUserFormValueService,
10-
CommandUserFormValueService by commandUserFormValueService
11+
CommandUserFormValueService by commandUserFormValueService,
12+
CheckUserFormValueService by checkUserFormValueService
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package team.msg.sms.domain.authentication.service.impl
2+
3+
import team.msg.sms.common.annotation.Service
4+
import team.msg.sms.domain.authentication.service.CheckUserFormValueService
5+
import team.msg.sms.domain.authentication.spi.UserFormValuePort
6+
import java.util.*
7+
8+
@Service
9+
class CheckUserFormValueServiceImpl(
10+
private val userFormValuePort: UserFormValuePort
11+
) : CheckUserFormValueService{
12+
override fun checkUserFormValueBySetIds(setIds: List<UUID>): Boolean =
13+
userFormValuePort.existsUserFormValueBySetIds(setIds)
14+
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package team.msg.sms.domain.authentication.service.impl
2+
3+
import team.msg.sms.common.annotation.Service
4+
import team.msg.sms.domain.authentication.model.MarkingValue
5+
import team.msg.sms.domain.authentication.service.CommandMarkingValueService
6+
import team.msg.sms.domain.authentication.spi.MarkingValuePort
7+
8+
@Service
9+
class CommandMarkingServiceValueImpl(
10+
private val markingValuePort: MarkingValuePort
11+
) : CommandMarkingValueService {
12+
override fun saveAll(markingValueList: List<MarkingValue>): List<MarkingValue> =
13+
markingValuePort.saveAll(markingValueList)
14+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package team.msg.sms.domain.authentication.service.impl
2+
3+
import team.msg.sms.common.annotation.Service
4+
import team.msg.sms.domain.authentication.model.MarkingValue
5+
import team.msg.sms.domain.authentication.service.GetMarkingValueService
6+
import team.msg.sms.domain.authentication.spi.MarkingValuePort
7+
import java.util.*
8+
9+
@Service
10+
class GetMarkingValueServiceImpl(
11+
private val markingValuePort: MarkingValuePort
12+
) : GetMarkingValueService {
13+
override fun findMarkingValueListByMarkingBoardId(markingBoardId: UUID): List<MarkingValue> =
14+
markingValuePort.queryMarkingValueListByMarkingBoardId(markingBoardId = markingBoardId)
15+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package team.msg.sms.domain.authentication.spi
2+
3+
import team.msg.sms.domain.authentication.model.MarkingValue
4+
5+
interface CommandMarkingValuePort {
6+
fun saveAll(markingValueList: List<MarkingValue>): List<MarkingValue>
7+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package team.msg.sms.domain.authentication.spi
2+
3+
interface MarkingValuePort : CommandMarkingValuePort, QueryMarkingValuePort
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package team.msg.sms.domain.authentication.spi
2+
3+
import team.msg.sms.domain.authentication.model.MarkingValue
4+
import java.util.UUID
5+
6+
interface QueryMarkingValuePort {
7+
fun queryMarkingValueListByMarkingBoardId(markingBoardId: UUID): List<MarkingValue>
8+
}

sms-core/src/main/kotlin/team/msg/sms/domain/authentication/spi/QueryUserFormValuePort.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ import java.util.UUID
55

66
interface QueryUserFormValuePort {
77
fun queryUserFormValueListByFieldIdAndStudentId(fieldId: UUID, studentId: UUID): List<UserFormValue>
8+
fun existsUserFormValueBySetIds(setIds: List<UUID>): Boolean
89
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package team.msg.sms.domain.authentication.usecase
2+
3+
import team.msg.sms.common.annotation.UseCase
4+
import team.msg.sms.domain.authentication.dto.req.GradingRequestData
5+
import team.msg.sms.domain.authentication.exception.UserFormValueNotFoundException
6+
import team.msg.sms.domain.authentication.model.MarkingType
7+
import team.msg.sms.domain.authentication.model.MarkingValue
8+
import team.msg.sms.domain.authentication.service.MarkingBoardService
9+
import team.msg.sms.domain.authentication.service.MarkingValueService
10+
import team.msg.sms.domain.authentication.service.UserFormValueService
11+
import team.msg.sms.domain.teacher.service.TeacherService
12+
import java.time.LocalDateTime
13+
import java.util.UUID
14+
15+
@UseCase
16+
class GradingAuthenticationFormUseCase(
17+
private val markingValueService: MarkingValueService,
18+
private val markingBoardService: MarkingBoardService,
19+
private val userFormValueService: UserFormValueService,
20+
private val teacherService: TeacherService
21+
) {
22+
fun execute(markingBoardId: UUID, gradingDataList: List<GradingRequestData>) {
23+
//요청한 setId 들 중 실제 userFormValue 테이블에 없는 setId 일 경우 최종점수에 영향을 미칠 수 있어 예외처리
24+
if (!userFormValueService.checkUserFormValueBySetIds(gradingDataList.map { it.setId })) throw UserFormValueNotFoundException
25+
26+
val teacher = teacherService.currentTeacher()
27+
28+
val markingValueList = markingValueService.findMarkingValueListByMarkingBoardId(markingBoardId)
29+
30+
val markingValueMap = markingValueList.associateBy { it.setId }
31+
32+
val saveMarkingValueList = markingValueService.saveAll(
33+
gradingDataList.map { gradingData ->
34+
markingValueMap[gradingData.setId]?.copy(
35+
score = gradingData.score,
36+
createdAt = LocalDateTime.now(),
37+
createdBy = teacher.id,
38+
type = if (gradingData.score == null) MarkingType.REJECT else MarkingType.RESOLVE
39+
) ?: MarkingValue(
40+
id = UUID.randomUUID(),
41+
score = gradingData.score,
42+
createdAt = LocalDateTime.now(),
43+
createdBy = teacher.id,
44+
setId = gradingData.setId,
45+
markingBoardId = markingBoardId,
46+
type = if (gradingData.score == null) MarkingType.REJECT else MarkingType.RESOLVE
47+
)
48+
}
49+
)
50+
51+
val totalScore = saveMarkingValueList.sumOf { it.score ?: 0.0 }
52+
53+
markingBoardService.getMarkingBoardById(markingBoardId).let { markingBoard ->
54+
markingBoardService.save(
55+
markingBoard.copy(
56+
totalScore = totalScore
57+
)
58+
)
59+
}
60+
}
61+
}

sms-infrastructure/src/main/kotlin/team/msg/sms/global/security/SecurityConfig.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ class SecurityConfig(
102102
.antMatchers(HttpMethod.POST, "/authentication").hasAuthority(STUDENT)
103103
.antMatchers(HttpMethod.POST, "/authentication/submit/{uuid}").hasAuthority(STUDENT)
104104
.antMatchers(HttpMethod.POST, "/authentication/create").hasAuthority(TEACHER)
105+
.antMatchers(HttpMethod.POST, "/authentication/grading/{markingBoardId}").hasAuthority(TEACHER)
105106
.antMatchers(HttpMethod.PATCH, "/authentication/teacher/{uuid}/approve").hasAuthority(TEACHER)
106107
.antMatchers(HttpMethod.PATCH, "/authentication/teacher/{uuid}/reject").hasAuthority(TEACHER)
107108
.antMatchers(HttpMethod.PATCH, "/authentication/{uuid}").hasAuthority(STUDENT)
Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,20 @@
11
package team.msg.sms.persistence.authentication
22

33
import org.springframework.stereotype.Component
4+
import team.msg.sms.domain.authentication.model.MarkingValue
5+
import team.msg.sms.domain.authentication.spi.MarkingValuePort
6+
import team.msg.sms.persistence.authentication.mapper.toDomain
7+
import team.msg.sms.persistence.authentication.mapper.toEntity
8+
import team.msg.sms.persistence.authentication.repository.MarkingValueJpaRepository
9+
import java.util.*
410

511
@Component
6-
class MarkingValuePersistenceAdapter {
12+
class MarkingValuePersistenceAdapter(
13+
private val markingValueJpaRepository: MarkingValueJpaRepository
14+
) : MarkingValuePort {
15+
override fun saveAll(markingValueList: List<MarkingValue>): List<MarkingValue> =
16+
markingValueJpaRepository.saveAll(markingValueList.map { it.toEntity() }).map { it.toDomain() }
717

18+
override fun queryMarkingValueListByMarkingBoardId(markingBoardId: UUID): List<MarkingValue> =
19+
markingValueJpaRepository.findAllByMarkingBoardId(markingBoardId = markingBoardId).map { it.toDomain() }
820
}

sms-persistence/src/main/kotlin/team/msg/sms/persistence/authentication/UserFormValuePersistenceAdapter.kt

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,33 @@
11
package team.msg.sms.persistence.authentication
22

3+
import com.querydsl.jpa.impl.JPAQueryFactory
34
import org.springframework.stereotype.Component
45
import team.msg.sms.domain.authentication.model.UserFormValue
56
import team.msg.sms.domain.authentication.spi.UserFormValuePort
7+
import team.msg.sms.persistence.authentication.entity.QUserFormValueJpaEntity
68
import team.msg.sms.persistence.authentication.mapper.toDomain
79
import team.msg.sms.persistence.authentication.mapper.toEntity
810
import team.msg.sms.persistence.authentication.repository.UserFormValueRepository
911
import java.util.*
1012

1113
@Component
1214
class UserFormValuePersistenceAdapter(
13-
private val userFormValueRepository: UserFormValueRepository
15+
private val userFormValueRepository: UserFormValueRepository,
16+
private val jpaQueryFactory: JPAQueryFactory
1417
) : UserFormValuePort {
1518
override fun queryUserFormValueListByFieldIdAndStudentId(fieldId: UUID, studentId: UUID): List<UserFormValue> {
1619
return userFormValueRepository.findAllByAuthenticationFieldIdAndCreatedBy(fieldId, studentId).map { it.toDomain() }
1720
}
21+
override fun existsUserFormValueBySetIds(setIds: List<UUID>): Boolean {
22+
val qUserFormValue = QUserFormValueJpaEntity.userFormValueJpaEntity
23+
val userFormValueIds = jpaQueryFactory
24+
.select(qUserFormValue.setId)
25+
.from(qUserFormValue)
26+
.where(qUserFormValue.setId.`in`(setIds))
27+
.fetch()
28+
29+
return setIds.all { it in userFormValueIds }
30+
}
1831

1932
override fun saveAll(userFormValueList: List<UserFormValue>): List<UserFormValue> {
2033
return userFormValueRepository.saveAll(userFormValueList.map { it.toEntity() })

sms-persistence/src/main/kotlin/team/msg/sms/persistence/authentication/entity/MarkingValueJpaEntity.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,17 @@ import javax.persistence.Enumerated
1313
class MarkingValueJpaEntity(
1414
override val id: UUID,
1515

16-
val score: Double,
16+
val score: Double?,
1717

1818
@Enumerated(EnumType.STRING)
1919
val type : MarkingType,
2020

2121
@Column(columnDefinition = "BINARY(16)", nullable = false)
22-
val fieldId: UUID,
22+
val setId: UUID,
2323

2424
@Column(columnDefinition = "BINARY(16)", nullable = false)
25-
val groupId: UUID,
25+
val markingBoardId: UUID,
2626

27-
@Column(columnDefinition = "BINARY(16)", nullable = false)
2827
val createdAt: LocalDateTime,
2928

3029
@Column(columnDefinition = "BINARY(16)", nullable = false)

sms-persistence/src/main/kotlin/team/msg/sms/persistence/authentication/mapper/MarkingValueMapper.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ fun MarkingValueJpaEntity.toDomain() =
88
id = id,
99
score = score,
1010
type = type,
11-
fieldId = fieldId,
12-
groupId = groupId,
11+
setId = setId,
12+
markingBoardId = markingBoardId,
1313
createdAt = createdAt,
1414
createdBy = createdBy
1515
)
@@ -19,8 +19,8 @@ fun MarkingValue.toEntity() =
1919
id = id,
2020
score = score,
2121
type = type,
22-
fieldId = fieldId,
23-
groupId = groupId,
22+
setId = setId,
23+
markingBoardId = markingBoardId,
2424
createdAt = createdAt,
2525
createdBy = createdBy
2626
)

sms-persistence/src/main/kotlin/team/msg/sms/persistence/authentication/repository/MarkingValueJpaRepository.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ import team.msg.sms.persistence.authentication.entity.MarkingValueJpaEntity
55
import java.util.UUID
66

77
interface MarkingValueJpaRepository: JpaRepository<MarkingValueJpaEntity, UUID> {
8+
fun findAllByMarkingBoardId(markingBoardId: UUID): List<MarkingValueJpaEntity>
89
}

sms-presentation/src/main/kotlin/team/msg/sms/domain/authentication/AuthenticationWebAdapter.kt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ class AuthenticationWebAdapter(
3131
private val submitUserFormDataUseCase: SubmitUserFormDataUseCase,
3232
private val createAuthenticationFormUseCase: CreateAuthenticationFormUseCase,
3333
private val queryStudentFormListUseCase: QueryStudentFormListUseCase,
34-
private val queryStudentAuthenticationFormDetailUseCase: QueryStudentAuthenticationFormDetailUseCase
34+
private val queryStudentAuthenticationFormDetailUseCase: QueryStudentAuthenticationFormDetailUseCase,
35+
private val gradingAuthenticationFormUseCase: GradingAuthenticationFormUseCase
3536
) {
3637
@GetMapping("/form")
3738
fun queryAuthenticationForm(): ResponseEntity<QueryAuthenticationFormWebResponse> =
@@ -48,6 +49,14 @@ class AuthenticationWebAdapter(
4849
.let { ResponseEntity.ok(it.toResponse()) }
4950
}
5051

52+
@PostMapping("/grading/{markingBoardId}")
53+
fun gradingAuthenticationForm(
54+
@PathVariable markingBoardId: String,
55+
@RequestBody gradingRequest: GradingRequest
56+
): ResponseEntity<Unit> =
57+
gradingAuthenticationFormUseCase.execute(UUID.fromString(markingBoardId), gradingRequest.content)
58+
.let { ResponseEntity.ok().build() }
59+
5160
@GetMapping("/{uuid}/form")
5261
fun queryStudentDetail(
5362
@PathVariable uuid: String
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package team.msg.sms.domain.authentication.dto.req
2+
3+
data class GradingRequest(
4+
val content: List<GradingRequestData>
5+
)

0 commit comments

Comments
 (0)