diff --git a/src/main/kotlin/com/sexysisters/tojserverv2/domain/student/StudentMapper.kt b/src/main/kotlin/com/sexysisters/tojserverv2/domain/student/StudentMapper.kt index 65ce472..de4fd39 100644 --- a/src/main/kotlin/com/sexysisters/tojserverv2/domain/student/StudentMapper.kt +++ b/src/main/kotlin/com/sexysisters/tojserverv2/domain/student/StudentMapper.kt @@ -16,8 +16,8 @@ interface StudentMapper { @Mappings( value = [ - Mapping(source = "user.profileImg", target = "profileImg"), - Mapping(source = "user.nickname", target = "nickname"), + Mapping(source = "user.image.value", target = "profileImg"), + Mapping(source = "user.nickname.value", target = "nickname"), Mapping(source = "grade.value", target = "grade"), Mapping(source = "classroom.value", target = "classroom"), Mapping(source = "number.value", target = "number"), diff --git a/src/main/kotlin/com/sexysisters/tojserverv2/domain/student/domain/Student.kt b/src/main/kotlin/com/sexysisters/tojserverv2/domain/student/domain/Student.kt index 310f9df..9608612 100644 --- a/src/main/kotlin/com/sexysisters/tojserverv2/domain/student/domain/Student.kt +++ b/src/main/kotlin/com/sexysisters/tojserverv2/domain/student/domain/Student.kt @@ -9,10 +9,10 @@ import javax.persistence.* @Entity @Table(name = "tbl_student") class Student( - @Embedded val grade: Grade, - @Embedded val classroom: Classroom, - @Embedded val number: Number, - @Embedded val age: Age, + @Embedded private val grade: Grade, + @Embedded private val classroom: Classroom, + @Embedded private val number: Number, + @Embedded private val age: Age, ) : BaseTimeEntity() { @Enumerated(EnumType.STRING) @@ -62,4 +62,6 @@ fun Student.waiting() { fun Student.engaged() { status = Status.ENGAGED -} \ No newline at end of file +} + +fun Student.isAttendSchool() = school != null \ No newline at end of file diff --git a/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/TeacherCommand.kt b/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/TeacherCommand.kt index 047cf17..156623d 100644 --- a/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/TeacherCommand.kt +++ b/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/TeacherCommand.kt @@ -8,4 +8,11 @@ class TeacherCommand { val nickname: String, val bio: String, ) + + data class Update( + val image: String, + val name: String, + val nickname: String, + val bio: String, + ) } \ No newline at end of file diff --git a/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/TeacherEntityMapper.kt b/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/TeacherEntityMapper.kt deleted file mode 100644 index d719f43..0000000 --- a/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/TeacherEntityMapper.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.sexysisters.tojserverv2.domain.teacher - -import com.sexysisters.tojserverv2.domain.teacher.domain.* -import org.springframework.stereotype.Component - -@Component -class TeacherEntityMapper { - fun of(command: TeacherCommand.Create) = Teacher( - Image.of(command.image), - Name.of(command.name), - Nickname.of(command.nickname), - Bio.of(command.bio), - ) -} \ No newline at end of file diff --git a/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/TeacherReader.kt b/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/TeacherReader.kt new file mode 100644 index 0000000..1476901 --- /dev/null +++ b/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/TeacherReader.kt @@ -0,0 +1,10 @@ +package com.sexysisters.tojserverv2.domain.teacher + +import com.sexysisters.tojserverv2.domain.school.domain.School +import com.sexysisters.tojserverv2.domain.teacher.domain.Teacher + +interface TeacherReader { + fun search(schoolCode: String): List + fun getTeacher(id: Long): Teacher + fun getTeacher(id: Long, school: School): Teacher +} \ No newline at end of file diff --git a/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/TeacherResponseMapper.kt b/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/TeacherResponseMapper.kt new file mode 100644 index 0000000..8b17178 --- /dev/null +++ b/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/TeacherResponseMapper.kt @@ -0,0 +1,10 @@ +package com.sexysisters.tojserverv2.domain.teacher + +import org.mapstruct.* + +@Mapper( + componentModel = "spring", + injectionStrategy = InjectionStrategy.CONSTRUCTOR, + unmappedTargetPolicy = ReportingPolicy.ERROR, +) +interface TeacherResponseMapper \ No newline at end of file diff --git a/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/TeacherStore.kt b/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/TeacherStore.kt index 6b75b9e..09a8ff1 100644 --- a/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/TeacherStore.kt +++ b/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/TeacherStore.kt @@ -4,4 +4,5 @@ import com.sexysisters.tojserverv2.domain.teacher.domain.Teacher interface TeacherStore { fun store(teacher: Teacher): Teacher + fun delete(teacher: Teacher) } \ No newline at end of file diff --git a/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/domain/Bio.kt b/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/domain/Bio.kt index 5202356..93ca016 100644 --- a/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/domain/Bio.kt +++ b/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/domain/Bio.kt @@ -6,21 +6,14 @@ import javax.persistence.Embeddable import javax.validation.constraints.NotNull @Embeddable -class Bio private constructor( +class Bio( @field:NotNull @Column(name = "bio") val value: String ) { - companion object { - private val REGEX = Regex("^{1,500}$") - - fun of(value: String): Bio { - validate(value) - return Bio(value) - } - - private fun validate(value: String) { - if (REGEX.matches(value)) throw TeacherException.TeacherNotValid() - } + init { + val MIN_LENGTH = 1 + val MAX_LENGTH = 500 + if (value.length !in MIN_LENGTH..MAX_LENGTH) throw TeacherException.TeacherNotValid() } } \ No newline at end of file diff --git a/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/domain/Image.kt b/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/domain/Image.kt index 72f2f52..89c09a5 100644 --- a/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/domain/Image.kt +++ b/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/domain/Image.kt @@ -7,20 +7,13 @@ import javax.persistence.Embeddable import javax.validation.constraints.NotNull @Embeddable -class Image private constructor ( +class Image( @URL @field:NotNull @Column(name = "image") val value: String ) { - companion object { - fun of(value: String): Image { - validate(value) - return Image(value) - } - - private fun validate(value: String) { - if (value.isBlank()) throw TeacherException.TeacherNotValid() - } + init { + if (value.isBlank()) throw TeacherException.TeacherNotValid() } } \ No newline at end of file diff --git a/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/domain/Name.kt b/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/domain/Name.kt index 466a37e..1f183b2 100644 --- a/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/domain/Name.kt +++ b/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/domain/Name.kt @@ -6,21 +6,14 @@ import javax.persistence.Embeddable import javax.validation.constraints.NotNull @Embeddable -class Name private constructor ( +class Name( @field:NotNull @Column(name = "name", unique = true) val value: String ) { - companion object { - private val REGEX = Regex("^{1,100}$") - - fun of(value: String): Name { - validate(value) - return Name(value) - } - - private fun validate(value: String) { - if (REGEX.matches(value)) throw TeacherException.TeacherNotValid() - } + init { + val MIN_LENGTH = 1 + val MAX_LENGTH = 50 + if (value.length !in MIN_LENGTH..MAX_LENGTH) throw TeacherException.TeacherNotValid() } } \ No newline at end of file diff --git a/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/domain/Nickname.kt b/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/domain/Nickname.kt index 01001b3..175030c 100644 --- a/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/domain/Nickname.kt +++ b/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/domain/Nickname.kt @@ -6,21 +6,14 @@ import javax.persistence.Embeddable import javax.validation.constraints.NotNull @Embeddable -class Nickname private constructor( +class Nickname( @field:NotNull @Column(name = "nickname") val value: String ) { - companion object { - private val REGEX = Regex("^{1,100}$") - - fun of(value: String): Nickname { - validate(value) - return Nickname(value) - } - - private fun validate(value: String) { - if (REGEX.matches(value)) throw TeacherException.TeacherNotValid() - } + init { + val MIN_LENGTH = 1 + val MAX_LENGTH = 50 + if (value.length !in MIN_LENGTH..MAX_LENGTH) throw TeacherException.TeacherNotValid() } } \ No newline at end of file diff --git a/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/domain/Teacher.kt b/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/domain/Teacher.kt index 3d87f52..9e0719f 100644 --- a/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/domain/Teacher.kt +++ b/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/domain/Teacher.kt @@ -8,13 +8,13 @@ import javax.persistence.* @Table(name = "tbl_teacher") class Teacher( @Embedded - val image: Image, + var image: Image, @Embedded - val name: Name, + var name: Name, @Embedded - val nickname: Nickname, + var nickname: Nickname, @Embedded - val bio: Bio, + var bio: Bio, ) : BaseTimeEntity() { @ManyToOne(fetch = FetchType.LAZY) @@ -23,4 +23,11 @@ class Teacher( @Id @GeneratedValue(strategy = GenerationType.IDENTITY) val id: Long = 0L + + fun update(image: String, name: String, nickname: String, bio: String) { + this.image = Image(image) + this.name = Name(name) + this.nickname = Nickname(nickname) + this.bio = Bio(bio) + } } \ No newline at end of file diff --git a/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/exception/TeacherErrorCode.kt b/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/exception/TeacherErrorCode.kt index f9a0d77..4b3781d 100644 --- a/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/exception/TeacherErrorCode.kt +++ b/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/exception/TeacherErrorCode.kt @@ -8,4 +8,5 @@ enum class TeacherErrorCode( TEACHER_NOT_VALID("Teacher domain is not valid"), DUPLICATE_NAME("Teacher name is duplicate"), DUPLICATE_NICKNAME("Teacher nickname is duplicate"), + TEACHER_NOT_FOUND("Teacher not found"), } \ No newline at end of file diff --git a/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/exception/TeacherException.kt b/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/exception/TeacherException.kt index 2384342..34221bd 100644 --- a/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/exception/TeacherException.kt +++ b/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/exception/TeacherException.kt @@ -6,4 +6,5 @@ class TeacherException { class TeacherNotValid : BaseException(TeacherErrorCode.TEACHER_NOT_VALID) class DuplicateTeacherName : BaseException(TeacherErrorCode.DUPLICATE_NAME) class DuplicateTeacherNickname : BaseException(TeacherErrorCode.DUPLICATE_NICKNAME) + class TeacherNotFound : BaseException(TeacherErrorCode.TEACHER_NOT_FOUND) } \ No newline at end of file diff --git a/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/service/TeacherService.kt b/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/service/TeacherService.kt index fdcf278..91aab04 100644 --- a/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/service/TeacherService.kt +++ b/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/service/TeacherService.kt @@ -1,7 +1,12 @@ package com.sexysisters.tojserverv2.domain.teacher.service import com.sexysisters.tojserverv2.domain.teacher.TeacherCommand +import com.sexysisters.tojserverv2.interfaces.teacher.dto.TeacherResponse interface TeacherService { - fun createTeacher(command: TeacherCommand.Create) + fun create(command: TeacherCommand.Create) + fun getTeachers(schoolCode: String): List + fun getTeacher(id: Long): TeacherResponse.Main + fun update(id: Long, request: TeacherCommand.Update) + fun delete(id: Long) } \ No newline at end of file diff --git a/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/service/TeacherServiceImpl.kt b/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/service/TeacherServiceImpl.kt index d30d9d8..9a5f491 100644 --- a/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/service/TeacherServiceImpl.kt +++ b/src/main/kotlin/com/sexysisters/tojserverv2/domain/teacher/service/TeacherServiceImpl.kt @@ -1,24 +1,69 @@ package com.sexysisters.tojserverv2.domain.teacher.service +import com.sexysisters.tojserverv2.domain.school.exception.SchoolException +import com.sexysisters.tojserverv2.domain.student.domain.Student +import com.sexysisters.tojserverv2.domain.student.domain.isAttendSchool import com.sexysisters.tojserverv2.domain.student.exception.StudentException import com.sexysisters.tojserverv2.domain.teacher.* +import com.sexysisters.tojserverv2.domain.teacher.domain.* import com.sexysisters.tojserverv2.domain.user.UserReader import com.sexysisters.tojserverv2.domain.user.hasStudent +import com.sexysisters.tojserverv2.interfaces.teacher.dto.TeacherDtoMapper +import com.sexysisters.tojserverv2.interfaces.teacher.dto.TeacherResponse import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @Service +@Transactional class TeacherServiceImpl( private val userReader: UserReader, private val teacherStore: TeacherStore, - private val teacherEntityMapper: TeacherEntityMapper, + private val teacherReader: TeacherReader, + private val teacherDtoMapper: TeacherDtoMapper, ) : TeacherService { - @Transactional - override fun createTeacher(command: TeacherCommand.Create) { + override fun create(command: TeacherCommand.Create) { + checkStudentIdentity() + val teacher = createTeacherEntity(command) + teacherStore.store(teacher) + } + + @Transactional(readOnly = true) + override fun getTeachers(schoolCode: String): List { + val teachers = teacherReader.search(schoolCode) + return teachers.map { teacherDtoMapper.of(it) } + } + + @Transactional(readOnly = true) + override fun getTeacher(id: Long): TeacherResponse.Main { + val teacher = teacherReader.getTeacher(id) + return teacherDtoMapper.of(teacher) + } + + override fun update(id: Long, request: TeacherCommand.Update) { + val student = checkStudentIdentity() + if (!student.isAttendSchool()) throw SchoolException.SchoolNotFound() + val teacher = teacherReader.getTeacher(id, student.school!!) + teacher.update(request.image, request.name, request.nickname, request.bio) + } + + override fun delete(id: Long) { + val student = checkStudentIdentity() + if (!student.isAttendSchool()) throw SchoolException.SchoolNotFound() + val teacher = teacherReader.getTeacher(id, student.school!!) + teacherStore.delete(teacher) + } + + private fun createTeacherEntity(command: TeacherCommand.Create) = Teacher( + Image(command.image), + Name(command.name), + Nickname(command.nickname), + Bio(command.bio), + ) + + private fun checkStudentIdentity(): Student { val user = userReader.getCurrentUser() if (!user.hasStudent()) throw StudentException.StudentNotFound() - val teacher = teacherEntityMapper.of(command) - teacherStore.store(teacher) + return user.student!! } } \ No newline at end of file diff --git a/src/main/kotlin/com/sexysisters/tojserverv2/domain/user/Email.kt b/src/main/kotlin/com/sexysisters/tojserverv2/domain/user/Email.kt new file mode 100644 index 0000000..b422942 --- /dev/null +++ b/src/main/kotlin/com/sexysisters/tojserverv2/domain/user/Email.kt @@ -0,0 +1,19 @@ +package com.sexysisters.tojserverv2.domain.user + +import com.sexysisters.tojserverv2.domain.user.exception.UserException +import javax.persistence.Column +import javax.persistence.Embeddable +import javax.validation.constraints.NotNull + +@Embeddable +class Email( + @field:NotNull + @Column(name = "email") + private val value: String, +) { + init { + val EMAIL_FORMAT = "@" + if (value.isBlank()) throw UserException.UserNotValid() + if (!value.contains(EMAIL_FORMAT)) throw UserException.UserNotValid() + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/sexysisters/tojserverv2/domain/user/Image.kt b/src/main/kotlin/com/sexysisters/tojserverv2/domain/user/Image.kt new file mode 100644 index 0000000..8ebdb5a --- /dev/null +++ b/src/main/kotlin/com/sexysisters/tojserverv2/domain/user/Image.kt @@ -0,0 +1,17 @@ +package com.sexysisters.tojserverv2.domain.user + +import com.sexysisters.tojserverv2.domain.user.exception.UserException +import javax.persistence.Column +import javax.persistence.Embeddable +import javax.validation.constraints.NotNull + +@Embeddable +class Image( + @field:NotNull + @Column(name = "image") + private val value: String, +) { + init { + if (value.isBlank()) throw UserException.UserNotValid() + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/sexysisters/tojserverv2/domain/user/Name.kt b/src/main/kotlin/com/sexysisters/tojserverv2/domain/user/Name.kt new file mode 100644 index 0000000..3795108 --- /dev/null +++ b/src/main/kotlin/com/sexysisters/tojserverv2/domain/user/Name.kt @@ -0,0 +1,19 @@ +package com.sexysisters.tojserverv2.domain.user + +import com.sexysisters.tojserverv2.domain.user.exception.UserException +import javax.persistence.Column +import javax.persistence.Embeddable +import javax.validation.constraints.NotNull + +@Embeddable +class Name( + @field:NotNull + @Column(name = "name") + private val value: String, +) { + init { + val MAX_LENGTH = 20 + if (value.isBlank()) throw UserException.UserNotValid() + if (value.length > MAX_LENGTH) throw UserException.UserNotValid() + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/sexysisters/tojserverv2/domain/user/Password.kt b/src/main/kotlin/com/sexysisters/tojserverv2/domain/user/Password.kt new file mode 100644 index 0000000..7278913 --- /dev/null +++ b/src/main/kotlin/com/sexysisters/tojserverv2/domain/user/Password.kt @@ -0,0 +1,19 @@ +package com.sexysisters.tojserverv2.domain.user + +import com.sexysisters.tojserverv2.domain.user.exception.UserException +import javax.persistence.Column +import javax.persistence.Embeddable +import javax.validation.constraints.NotNull + +@Embeddable +class Password( + @field:NotNull + @Column(name = "password") + private val value: String +) { + init { + val MAX_LENGTH = 20 + if (value.isBlank()) throw UserException.UserNotValid() + if (value.length > MAX_LENGTH) throw UserException.UserNotValid() + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/sexysisters/tojserverv2/domain/user/User.kt b/src/main/kotlin/com/sexysisters/tojserverv2/domain/user/User.kt index 2ea9c49..e325dce 100644 --- a/src/main/kotlin/com/sexysisters/tojserverv2/domain/user/User.kt +++ b/src/main/kotlin/com/sexysisters/tojserverv2/domain/user/User.kt @@ -2,49 +2,42 @@ package com.sexysisters.tojserverv2.domain.user import com.sexysisters.tojserverv2.domain.BaseTimeEntity import com.sexysisters.tojserverv2.domain.student.domain.Student -import com.sexysisters.tojserverv2.domain.user.exception.UserException import com.sexysisters.tojserverv2.domain.user.type.Authority +import com.sexysisters.tojserverv2.domain.user.type.Nickname import javax.persistence.* @Entity @Table(name = "tbl_user") class User( - val email: String, - var password: String, - var nickname: String, - var profileImg: String, - var name: String, + @Embedded val email: Email, + @Embedded var password: Password, + @Embedded var nickname: Nickname, + @Embedded var image: Image, + @Embedded var name: Name, ) : BaseTimeEntity() { @Enumerated(EnumType.STRING) var authority: Authority = Authority.USER - @OneToOne(mappedBy = "user") + @OneToOne(mappedBy = "user", fetch = FetchType.LAZY) var student: Student? = null - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) val id: Long = 0L - - init { - if (email.isBlank()) throw UserException.UserNotValid() - if (password.isBlank()) throw UserException.UserNotValid() - if (nickname.isBlank()) throw UserException.UserNotValid() - if (profileImg.isBlank()) throw UserException.UserNotValid() - if (name.isBlank()) throw UserException.UserNotValid() - } } fun User.updateInfo( nickname: String, name: String, ): User { - this.nickname = nickname - this.name = name + this.nickname = Nickname(nickname) + this.name = Name(name) return this } -fun User.updateProfileImg(profileImg: String) { - this.profileImg = profileImg +fun User.updateProfileImg(image: String) { + this.image = Image(image) } fun User.hasStudent() = student != null \ No newline at end of file diff --git a/src/main/kotlin/com/sexysisters/tojserverv2/domain/user/UserCommand.kt b/src/main/kotlin/com/sexysisters/tojserverv2/domain/user/UserCommand.kt index be29373..3a9199a 100644 --- a/src/main/kotlin/com/sexysisters/tojserverv2/domain/user/UserCommand.kt +++ b/src/main/kotlin/com/sexysisters/tojserverv2/domain/user/UserCommand.kt @@ -1,10 +1,10 @@ package com.sexysisters.tojserverv2.domain.user import com.sexysisters.tojserverv2.config.properties.S3Properties +import com.sexysisters.tojserverv2.domain.user.type.Nickname import org.springframework.security.crypto.password.PasswordEncoder class UserCommand { - class CreateRequest( val email: String, var password: String, @@ -21,12 +21,14 @@ class UserCommand { ) } +private val DEFAULT_NAME = "이름" + fun UserCommand.CreateRequest.toEntity() = User( - email = email, - password = password, - nickname = nickname, - profileImg = S3Properties.defaultProfileImg, - name = "이름", + email = Email(email), + password = Password(password), + nickname = Nickname(nickname), + image = Image(S3Properties.defaultProfileImg), + name = Name(DEFAULT_NAME), ) fun UserCommand.CreateRequest.setEncodedPassword(encoder: PasswordEncoder) { diff --git a/src/main/kotlin/com/sexysisters/tojserverv2/domain/user/type/Nickname.kt b/src/main/kotlin/com/sexysisters/tojserverv2/domain/user/type/Nickname.kt new file mode 100644 index 0000000..b22e1c2 --- /dev/null +++ b/src/main/kotlin/com/sexysisters/tojserverv2/domain/user/type/Nickname.kt @@ -0,0 +1,19 @@ +package com.sexysisters.tojserverv2.domain.user.type + +import com.sexysisters.tojserverv2.domain.user.exception.UserException +import javax.persistence.Column +import javax.persistence.Embeddable +import javax.validation.constraints.NotNull + +@Embeddable +class Nickname( + @field:NotNull + @Column(name = "nickname", unique = true) + private val value: String, +) { + init { + val MAX_LENGTH = 21 + if (value.isBlank()) throw UserException.UserNotValid() + if (value.length > MAX_LENGTH) throw UserException.UserNotValid() + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/sexysisters/tojserverv2/infrastructure/teacher/TeacherCustomRepository.kt b/src/main/kotlin/com/sexysisters/tojserverv2/infrastructure/teacher/TeacherCustomRepository.kt new file mode 100644 index 0000000..8ff0798 --- /dev/null +++ b/src/main/kotlin/com/sexysisters/tojserverv2/infrastructure/teacher/TeacherCustomRepository.kt @@ -0,0 +1,8 @@ +package com.sexysisters.tojserverv2.infrastructure.teacher + +import com.sexysisters.tojserverv2.domain.teacher.domain.Teacher + +interface TeacherCustomRepository { + fun getTeachersBySchoolCode(schoolCode: String): List + fun findByIdAndSchoolCode(id: Long, schoolCode: String): Teacher? +} \ No newline at end of file diff --git a/src/main/kotlin/com/sexysisters/tojserverv2/infrastructure/teacher/TeacherCustomRepositoryImpl.kt b/src/main/kotlin/com/sexysisters/tojserverv2/infrastructure/teacher/TeacherCustomRepositoryImpl.kt new file mode 100644 index 0000000..1ad5296 --- /dev/null +++ b/src/main/kotlin/com/sexysisters/tojserverv2/infrastructure/teacher/TeacherCustomRepositoryImpl.kt @@ -0,0 +1,30 @@ +package com.sexysisters.tojserverv2.infrastructure.teacher + +import com.querydsl.jpa.impl.JPAQueryFactory +import com.sexysisters.tojserverv2.domain.teacher.domain.Teacher +import com.sexysisters.tojserverv2.domain.teacher.domain.QTeacher.teacher +import org.springframework.stereotype.Component + +@Component +class TeacherCustomRepositoryImpl( + private val query: JPAQueryFactory +) : TeacherCustomRepository { + override fun getTeachersBySchoolCode(schoolCode: String): List { + return query + .selectFrom(teacher) + .where( + teacher.school.code.value.eq(schoolCode), + ) + .fetch() + } + + override fun findByIdAndSchoolCode(id: Long, schoolCode: String): Teacher? { + return query + .selectFrom(teacher) + .where( + teacher.id.eq(id), + teacher.school.code.value.eq(schoolCode) + ) + .fetchOne() + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/sexysisters/tojserverv2/infrastructure/teacher/TeacherReaderImpl.kt b/src/main/kotlin/com/sexysisters/tojserverv2/infrastructure/teacher/TeacherReaderImpl.kt new file mode 100644 index 0000000..f7dc65c --- /dev/null +++ b/src/main/kotlin/com/sexysisters/tojserverv2/infrastructure/teacher/TeacherReaderImpl.kt @@ -0,0 +1,21 @@ +package com.sexysisters.tojserverv2.infrastructure.teacher + +import com.sexysisters.tojserverv2.domain.school.domain.School +import com.sexysisters.tojserverv2.domain.teacher.TeacherReader +import com.sexysisters.tojserverv2.domain.teacher.exception.TeacherException +import org.springframework.data.repository.findByIdOrNull +import org.springframework.stereotype.Component + +@Component +class TeacherReaderImpl( + private val teacherCustomRepository: TeacherCustomRepository, + private val teacherRepository: TeacherRepository, +) : TeacherReader { + override fun search(schoolCode: String) = teacherCustomRepository.getTeachersBySchoolCode(schoolCode) + + override fun getTeacher(id: Long) = teacherRepository.findByIdOrNull(id) + ?: throw TeacherException.TeacherNotFound() + + override fun getTeacher(id: Long, school: School) = teacherCustomRepository.findByIdAndSchoolCode(id, school.codeValue()) + ?: throw TeacherException.TeacherNotFound() +} \ No newline at end of file diff --git a/src/main/kotlin/com/sexysisters/tojserverv2/infrastructure/teacher/TeacherStoreImpl.kt b/src/main/kotlin/com/sexysisters/tojserverv2/infrastructure/teacher/TeacherStoreImpl.kt index e92e406..6506ec9 100644 --- a/src/main/kotlin/com/sexysisters/tojserverv2/infrastructure/teacher/TeacherStoreImpl.kt +++ b/src/main/kotlin/com/sexysisters/tojserverv2/infrastructure/teacher/TeacherStoreImpl.kt @@ -14,6 +14,8 @@ class TeacherStoreImpl( return teacherRepository.save(teacher) } + override fun delete(teacher: Teacher) = teacherRepository.delete(teacher) + private fun validate(teacher: Teacher) { checkDuplicateName(teacher) checkDuplicateNickname(teacher) diff --git a/src/main/kotlin/com/sexysisters/tojserverv2/interfaces/teacher/TeacherApiController.kt b/src/main/kotlin/com/sexysisters/tojserverv2/interfaces/teacher/TeacherApiController.kt index 92faff1..1aa35a6 100644 --- a/src/main/kotlin/com/sexysisters/tojserverv2/interfaces/teacher/TeacherApiController.kt +++ b/src/main/kotlin/com/sexysisters/tojserverv2/interfaces/teacher/TeacherApiController.kt @@ -1,14 +1,21 @@ package com.sexysisters.tojserverv2.interfaces.teacher +import com.sexysisters.tojserverv2.common.response.CommonResponse import com.sexysisters.tojserverv2.domain.teacher.service.TeacherService import com.sexysisters.tojserverv2.interfaces.teacher.dto.TeacherDtoMapper import com.sexysisters.tojserverv2.interfaces.teacher.dto.TeacherRequest +import com.sexysisters.tojserverv2.interfaces.teacher.dto.TeacherResponse import io.swagger.annotations.Api import io.swagger.annotations.ApiOperation import org.springframework.http.HttpStatus +import org.springframework.web.bind.annotation.DeleteMapping +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PathVariable import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.PutMapping import org.springframework.web.bind.annotation.RequestBody import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RequestParam import org.springframework.web.bind.annotation.ResponseStatus import org.springframework.web.bind.annotation.RestController import javax.validation.Valid @@ -24,10 +31,38 @@ class TeacherApiController( @ApiOperation(value = "선생님 생성") @ResponseStatus(HttpStatus.CREATED) @PostMapping - fun createTeacher( - @RequestBody @Valid request: TeacherRequest.Create + fun create(@RequestBody @Valid request: TeacherRequest.Create) { + val teacherCommand = teacherDtoMapper.of(request) + teacherService.create(teacherCommand) + } + + @ApiOperation(value = "학교 코드로 선생님 목록 조회") + @GetMapping + fun getAll(@RequestParam("code") schoolCode: String): CommonResponse> { + val response = teacherService.getTeachers(schoolCode) + return CommonResponse.success(response) + } + + @ApiOperation(value = "선생님 단건 조회") + @GetMapping("/{id}") + fun getDetail(@PathVariable("id") id: Long): CommonResponse { + val response = teacherService.getTeacher(id) + return CommonResponse.success(response) + } + + @ApiOperation(value = "학교의 학생만 학교의 선생님 수정") + @PutMapping("/{id}") + fun update( + @PathVariable("id") id: Long, + @RequestBody request: TeacherRequest.Update ) { val teacherCommand = teacherDtoMapper.of(request) - teacherService.createTeacher(teacherCommand) + teacherService.update(id, teacherCommand) + } + + @ApiOperation(value = "학교의 학생만 학교의 선생님 삭제") + @DeleteMapping("/{id}") + fun delete(@PathVariable("id") id: Long) { + teacherService.delete(id) } } \ No newline at end of file diff --git a/src/main/kotlin/com/sexysisters/tojserverv2/interfaces/teacher/dto/TeacherDtoMapper.kt b/src/main/kotlin/com/sexysisters/tojserverv2/interfaces/teacher/dto/TeacherDtoMapper.kt index 5ff8a08..f6e7c36 100644 --- a/src/main/kotlin/com/sexysisters/tojserverv2/interfaces/teacher/dto/TeacherDtoMapper.kt +++ b/src/main/kotlin/com/sexysisters/tojserverv2/interfaces/teacher/dto/TeacherDtoMapper.kt @@ -1,9 +1,8 @@ package com.sexysisters.tojserverv2.interfaces.teacher.dto import com.sexysisters.tojserverv2.domain.teacher.TeacherCommand -import org.mapstruct.InjectionStrategy -import org.mapstruct.Mapper -import org.mapstruct.ReportingPolicy +import com.sexysisters.tojserverv2.domain.teacher.domain.Teacher +import org.mapstruct.* @Mapper( componentModel = "spring", @@ -13,4 +12,15 @@ import org.mapstruct.ReportingPolicy interface TeacherDtoMapper { fun of(request: TeacherRequest.Create): TeacherCommand.Create + fun of(request: TeacherRequest.Update): TeacherCommand.Update + + @Mappings( + value = [ + Mapping(source = "image.value", target = "image"), + Mapping(source = "name.value", target = "name"), + Mapping(source = "nickname.value", target = "nickname"), + Mapping(source = "bio.value", target = "bio"), + ] + ) + fun of(teacher: Teacher): TeacherResponse.Main } \ No newline at end of file diff --git a/src/main/kotlin/com/sexysisters/tojserverv2/interfaces/teacher/dto/TeacherRequest.kt b/src/main/kotlin/com/sexysisters/tojserverv2/interfaces/teacher/dto/TeacherRequest.kt index 4fcb10f..a1200c5 100644 --- a/src/main/kotlin/com/sexysisters/tojserverv2/interfaces/teacher/dto/TeacherRequest.kt +++ b/src/main/kotlin/com/sexysisters/tojserverv2/interfaces/teacher/dto/TeacherRequest.kt @@ -8,4 +8,11 @@ class TeacherRequest { val nickname: String, val bio: String ) + + data class Update( + val image: String, + val name: String, + val nickname: String, + val bio: String + ) } \ No newline at end of file diff --git a/src/main/kotlin/com/sexysisters/tojserverv2/interfaces/teacher/dto/TeacherResponse.kt b/src/main/kotlin/com/sexysisters/tojserverv2/interfaces/teacher/dto/TeacherResponse.kt new file mode 100644 index 0000000..1c512af --- /dev/null +++ b/src/main/kotlin/com/sexysisters/tojserverv2/interfaces/teacher/dto/TeacherResponse.kt @@ -0,0 +1,10 @@ +package com.sexysisters.tojserverv2.interfaces.teacher.dto + +class TeacherResponse { + data class Main( + val image: String, + val name: String, + val nickname: String, + val bio: String, + ) +} \ No newline at end of file