Skip to content

Commit

Permalink
Feat: Professor API 언어 통합 업데이트 (#304)
Browse files Browse the repository at this point in the history
* refactor: move member search controller to v1

* feat: make a bit more query efficient

* feat: change to language merged apis

* fix: ktlint issue

* fix: fix index columnlist
  • Loading branch information
huGgW authored Aug 11, 2024
1 parent 1f02726 commit 8f53fc6
Show file tree
Hide file tree
Showing 15 changed files with 338 additions and 124 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.wafflestudio.csereal.core.member.api.req

data class CreateProfessorLanguagesReqBody(
val ko: CreateProfessorReqBody,
val en: CreateProfessorReqBody
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import com.wafflestudio.csereal.core.member.database.ProfessorStatus
import java.time.LocalDate

data class CreateProfessorReqBody(
val language: String,
val name: String,
val status: ProfessorStatus,
val academicRank: String,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.wafflestudio.csereal.core.member.api.req

data class ModifyProfessorLanguagesReqBody(
val ko: ModifyProfessorReqBody,
val en: ModifyProfessorReqBody
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import com.wafflestudio.csereal.core.member.database.ProfessorStatus
import java.time.LocalDate

data class ModifyProfessorReqBody(
val language: String,
val name: String,
val status: ProfessorStatus,
val academicRank: String,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.wafflestudio.csereal.core.member.api
package com.wafflestudio.csereal.core.member.api.v1

import com.wafflestudio.csereal.common.enums.LanguageType
import com.wafflestudio.csereal.core.member.service.MemberSearchService
Expand All @@ -8,6 +8,7 @@ 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 kotlin.let

@RestController
@RequestMapping("/api/v1/member/search")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.wafflestudio.csereal.core.member.api.v1

import com.wafflestudio.csereal.core.member.dto.ProfessorDto
import com.wafflestudio.csereal.core.member.dto.ProfessorPageDto
import com.wafflestudio.csereal.core.member.dto.SimpleProfessorDto
import com.wafflestudio.csereal.core.member.service.ProfessorService
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*

@Deprecated(message = "Use V2 API")
@RequestMapping("/api/v1/professor")
@RestController("ProfessorControllerV1")
class ProfessorController(
private val professorService: ProfessorService
) {
@GetMapping("/{professorId}")
fun getProfessor(@PathVariable professorId: Long): ResponseEntity<ProfessorDto> {
return ResponseEntity.ok(professorService.getProfessor(professorId))
}

@GetMapping("/active")
fun getActiveProfessors(
@RequestParam(required = false, defaultValue = "ko") language: String
): ResponseEntity<ProfessorPageDto> {
return ResponseEntity.ok(professorService.getActiveProfessors(language))
}

@GetMapping("/inactive")
fun getInactiveProfessors(
@RequestParam(required = false, defaultValue = "ko") language: String
): ResponseEntity<List<SimpleProfessorDto>> {
return ResponseEntity.ok(professorService.getInactiveProfessors(language))
}
}
Original file line number Diff line number Diff line change
@@ -1,36 +1,29 @@
package com.wafflestudio.csereal.core.member.api
package com.wafflestudio.csereal.core.member.api.v2

import com.wafflestudio.csereal.common.aop.AuthenticatedStaff
import com.wafflestudio.csereal.core.member.api.req.CreateProfessorReqBody
import com.wafflestudio.csereal.core.member.api.req.ModifyProfessorReqBody
import com.wafflestudio.csereal.core.member.dto.ProfessorDto
import com.wafflestudio.csereal.core.member.api.req.CreateProfessorLanguagesReqBody
import com.wafflestudio.csereal.core.member.api.req.ModifyProfessorLanguagesReqBody
import com.wafflestudio.csereal.core.member.dto.ProfessorLanguagesDto
import com.wafflestudio.csereal.core.member.dto.ProfessorPageDto
import com.wafflestudio.csereal.core.member.dto.SimpleProfessorDto
import com.wafflestudio.csereal.core.member.service.ProfessorService
import io.swagger.v3.oas.annotations.Parameter
import jakarta.validation.constraints.Positive
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*
import org.springframework.web.multipart.MultipartFile

@RequestMapping("/api/v1/professor")
@RequestMapping("/api/v2/professor")
@RestController
class ProfessorController(
private val professorService: ProfessorService
) {

@AuthenticatedStaff
@PostMapping
fun createProfessor(
@RequestPart("request") createProfessorRequest: CreateProfessorReqBody,
@RequestPart("mainImage") mainImage: MultipartFile?
): ProfessorDto {
return professorService.createProfessor(createProfessorRequest, mainImage)
}

@GetMapping("/{professorId}")
fun getProfessor(@PathVariable professorId: Long): ResponseEntity<ProfessorDto> {
return ResponseEntity.ok(professorService.getProfessor(professorId))
}
fun getProfessor(
@PathVariable @Positive
professorId: Long
): ProfessorLanguagesDto =
professorService.getProfessorLanguages(professorId)

@GetMapping("/active")
fun getActiveProfessors(
Expand All @@ -47,24 +40,34 @@ class ProfessorController(
}

@AuthenticatedStaff
@PutMapping("/{professorId}")
@PostMapping(consumes = ["multipart/form-data"])
fun createProfessor(
@RequestPart("request") requestBody: CreateProfessorLanguagesReqBody,
@RequestPart("image") image: MultipartFile?
): ProfessorLanguagesDto =
professorService.createProfessorLanguages(requestBody, image)

@AuthenticatedStaff
@PutMapping("/{koProfessorId}/{enProfessorId}", consumes = ["multipart/form-data"])
fun updateProfessor(
@PathVariable professorId: Long,
@RequestPart("request") updateProfessorRequest: ModifyProfessorReqBody,
@PathVariable @Positive
koProfessorId: Long,
@PathVariable @Positive
enProfessorId: Long,
@RequestPart("request") requestBody: ModifyProfessorLanguagesReqBody,

@Parameter(description = "image 교체할 경우 업로드. Request Body의 removeImage 관계없이 변경됨.")
@RequestPart("newImage")
newImage: MultipartFile?
): ResponseEntity<ProfessorDto> {
return ResponseEntity.ok(
professorService.updateProfessor(professorId, updateProfessorRequest, newImage)
)
}
): ProfessorLanguagesDto =
professorService.updateProfessorLanguages(koProfessorId, enProfessorId, requestBody, newImage)

@AuthenticatedStaff
@DeleteMapping("/{professorId}")
fun deleteProfessor(@PathVariable professorId: Long): ResponseEntity<Any> {
professorService.deleteProfessor(professorId)
return ResponseEntity.ok().build()
}
@DeleteMapping("/{koProfessorId}/{enProfessorId}", consumes = ["multipart/form-data"])
fun deleteProfessor(
@PathVariable @Positive
koProfessorId: Long,
@PathVariable @Positive
enProfessorId: Long
) = professorService.deleteProfessorLanguages(koProfessorId, enProfessorId)
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ import com.wafflestudio.csereal.core.member.type.MemberType
import jakarta.persistence.*

@Entity(name = "member_language")
@Table(
indexes = [
Index(columnList = "type"),
Index(columnList = "korean_id"),
Index(columnList = "english_id")
]
)
class MemberLanguageEntity(
@Column(nullable = false)
@Enumerated(EnumType.STRING)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,69 @@
package com.wafflestudio.csereal.core.member.database

import com.querydsl.core.types.dsl.Expressions
import com.querydsl.jpa.JPAExpressions
import com.querydsl.jpa.impl.JPAQueryFactory
import com.wafflestudio.csereal.common.enums.LanguageType
import com.wafflestudio.csereal.core.member.database.QCareerEntity.careerEntity
import com.wafflestudio.csereal.core.member.database.QEducationEntity.educationEntity
import com.wafflestudio.csereal.core.member.database.QMemberLanguageEntity.memberLanguageEntity
import com.wafflestudio.csereal.core.member.database.QProfessorEntity.professorEntity
import com.wafflestudio.csereal.core.member.database.QResearchAreaEntity.researchAreaEntity
import com.wafflestudio.csereal.core.member.type.MemberType
import com.wafflestudio.csereal.core.research.database.QLabEntity.labEntity
import com.wafflestudio.csereal.core.resource.mainImage.database.QMainImageEntity.mainImageEntity
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository

interface ProfessorRepository : JpaRepository<ProfessorEntity, Long> {
interface ProfessorRepository : JpaRepository<ProfessorEntity, Long>, ProfessorRepositoryCustom {
fun findByLanguageAndStatus(
languageType: LanguageType,
status: ProfessorStatus
): List<ProfessorEntity>

fun findByLanguageAndStatusNot(
languageType: LanguageType,
status: ProfessorStatus
): List<ProfessorEntity>
}

interface ProfessorRepositoryCustom {
fun findProfessorAllLanguages(id: Long): Map<LanguageType, List<ProfessorEntity>>
}

@Repository
class ProfessorRepositoryCustomImpl(
private val queryFactory: JPAQueryFactory
) : ProfessorRepositoryCustom {
override fun findProfessorAllLanguages(id: Long): Map<LanguageType, List<ProfessorEntity>> {
val professors = queryFactory.selectFrom(professorEntity)
.where(
professorEntity.id.`in`(
JPAExpressions.select(
memberLanguageEntity.koreanId
).from(memberLanguageEntity)
.where(
memberLanguageEntity.englishId.eq(id),
memberLanguageEntity.type.eq(MemberType.PROFESSOR)
),
JPAExpressions.select(
memberLanguageEntity.englishId
).from(memberLanguageEntity)
.where(
memberLanguageEntity.koreanId.eq(id),
memberLanguageEntity.type.eq(MemberType.PROFESSOR)
),
Expressions.constant(id)
)
).leftJoin(mainImageEntity).fetchJoin()
.leftJoin(labEntity).fetchJoin()
.leftJoin(careerEntity).on(careerEntity.professor.eq(professorEntity))
.leftJoin(researchAreaEntity).on(researchAreaEntity.professor.eq(professorEntity))
.leftJoin(educationEntity).on(educationEntity.professor.eq(professorEntity))
.fetch()

return professors.groupBy {
it.language
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.querydsl.jpa.impl.JPAQueryFactory
import com.wafflestudio.csereal.common.enums.LanguageType
import com.wafflestudio.csereal.core.member.database.QMemberLanguageEntity.memberLanguageEntity
import com.wafflestudio.csereal.core.member.database.QStaffEntity.staffEntity
import com.wafflestudio.csereal.core.member.database.QTaskEntity.taskEntity
import com.wafflestudio.csereal.core.member.type.MemberType
import com.wafflestudio.csereal.core.resource.mainImage.database.QMainImageEntity.mainImageEntity
import org.springframework.data.jpa.repository.JpaRepository
Expand Down Expand Up @@ -37,7 +38,8 @@ class StaffRepositoryCustomImpl(
.where(memberLanguageEntity.koreanId.eq(id), memberLanguageEntity.type.eq(MemberType.STAFF)),
Expressions.constant(id)
)
).leftJoin(mainImageEntity).on(mainImageEntity.id.eq(staffEntity.id))
).leftJoin(mainImageEntity).fetchJoin()
.leftJoin(taskEntity).on(taskEntity.staff.eq(staffEntity))
.fetch()

return staffs.groupBy {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.wafflestudio.csereal.core.member.dto

data class ProfessorLanguagesDto(
val ko: ProfessorDto?,
val en: ProfessorDto?
)
Loading

0 comments on commit 8f53fc6

Please sign in to comment.