Skip to content

Commit

Permalink
feat: createSeminar, readSeminar, updateSeminar 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
skfotakf committed Aug 10, 2023
1 parent 7e3ea8e commit 54ad2ff
Show file tree
Hide file tree
Showing 5 changed files with 314 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.wafflestudio.csereal.core.seminar.api

import com.wafflestudio.csereal.core.seminar.dto.SeminarDto
import com.wafflestudio.csereal.core.seminar.service.SeminarService
import jakarta.validation.Valid
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*

@RequestMapping("/seminar")
@RestController
class SeminarController (
private val seminarService: SeminarService,
) {
@PostMapping
fun createSeminar(
@Valid @RequestBody request: SeminarDto
) : ResponseEntity<SeminarDto> {
return ResponseEntity.ok(seminarService.createSeminar(request))
}

@GetMapping("/{seminarId}")
fun readSeminar(
@PathVariable seminarId: Long,
@RequestParam(required = false) keyword: String?,
) : ResponseEntity<SeminarDto> {
return ResponseEntity.ok(seminarService.readSeminar(seminarId, keyword))
}

@PatchMapping("/{seminarId}")
fun updateSeminar(
@PathVariable seminarId: Long,
@Valid @RequestBody request: SeminarDto,
) : ResponseEntity<SeminarDto> {
return ResponseEntity.ok(seminarService.updateSeminar(seminarId, request))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package com.wafflestudio.csereal.core.seminar.database

import com.wafflestudio.csereal.common.config.BaseTimeEntity
import com.wafflestudio.csereal.core.seminar.dto.SeminarDto
import jakarta.persistence.Column
import jakarta.persistence.Entity

@Entity(name = "seminar")
class SeminarEntity(

var isDeleted: Boolean = false,

var title: String,

@Column(columnDefinition = "text")
var description: String,

@Column(columnDefinition = "text")
var introduction: String,

var category: String,

// 연사 정보
var name: String,
var speakerUrl: String?,
var speakerTitle: String?,
var affiliation: String,
var affiliationUrl: String?,

var startDate: String?,
var startTime: String?,
var endDate: String?,
var endTime: String?,

var location: String,

var host: String?,

// var profileImage: File,

// var seminarFile: File,

var isPublic: Boolean,

var isSlide: Boolean,

var additionalNote: String?
): BaseTimeEntity() {

companion object {
fun of(seminarDto: SeminarDto): SeminarEntity {
return SeminarEntity(
title = seminarDto.title,
description = seminarDto.description,
introduction = seminarDto.introduction,
category = seminarDto.category,
name = seminarDto.name,
speakerUrl = seminarDto.speakerUrl,
speakerTitle = seminarDto.speakerTitle,
affiliation = seminarDto.affiliation,
affiliationUrl = seminarDto.affiliationUrl,
startDate = seminarDto.startDate,
startTime = seminarDto.startTime,
endDate = seminarDto.endDate,
endTime = seminarDto.endTime,
location = seminarDto.location,
host = seminarDto.host,
additionalNote = seminarDto.additionalNote,
isPublic = seminarDto.isPublic,
isSlide = seminarDto.isSlide
)
}

}

fun update(updateSeminarRequest: SeminarDto) {
title = updateSeminarRequest.title
description = updateSeminarRequest.description
introduction = updateSeminarRequest.introduction
category = updateSeminarRequest.category
name = updateSeminarRequest.name
speakerUrl = updateSeminarRequest.speakerUrl
speakerTitle = updateSeminarRequest.speakerTitle
affiliation = updateSeminarRequest.affiliation
affiliationUrl = updateSeminarRequest.affiliationUrl
startDate = updateSeminarRequest.startDate
startTime = updateSeminarRequest.startTime
endDate = updateSeminarRequest.endDate
endTime = updateSeminarRequest.endTime
location = updateSeminarRequest.location
host = updateSeminarRequest.host
additionalNote = updateSeminarRequest.additionalNote
isPublic = updateSeminarRequest.isPublic
isSlide = updateSeminarRequest.isSlide
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.wafflestudio.csereal.core.seminar.database

import com.querydsl.core.BooleanBuilder
import com.querydsl.jpa.impl.JPAQueryFactory
import com.wafflestudio.csereal.common.CserealException
import com.wafflestudio.csereal.core.seminar.database.QSeminarEntity.seminarEntity
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Component

interface SeminarRepository : JpaRepository<SeminarEntity, Long>, CustomSeminarRepository {
}

interface CustomSeminarRepository {
fun findPrevNextId(seminarId: Long, keyword: String?): Array<SeminarEntity?>?
}

@Component
class SeminarRepositoryImpl(
private val queryFactory: JPAQueryFactory,
) : CustomSeminarRepository {
override fun findPrevNextId(seminarId: Long, keyword: String?): Array<SeminarEntity?>? {
val keywordBooleanBuilder = BooleanBuilder()

if (!keyword.isNullOrEmpty()) {
val keywordList = keyword.split("[^a-zA-Z0-9가-힣]".toRegex())
keywordList.forEach {
if (it.length == 1) {
throw CserealException.Csereal400("각각의 키워드는 한글자 이상이어야 합니다.")
} else {
keywordBooleanBuilder.and(
seminarEntity.title.contains(it)
.or(seminarEntity.description.contains(it))
)
}
}
}
val seminarSearchDtoList = queryFactory.select(seminarEntity).from(seminarEntity)
.where(seminarEntity.isDeleted.eq(false), seminarEntity.isPublic.eq(true))
.where(keywordBooleanBuilder)
.orderBy(seminarEntity.createdAt.desc())
.distinct()
.fetch()

val findingId = seminarSearchDtoList.indexOfFirst { it.id == seminarId }

val prevNext: Array<SeminarEntity?>?

if (findingId == -1) {
return null
} else if (findingId != 0 && findingId != seminarSearchDtoList.size - 1) {
prevNext = arrayOf(seminarSearchDtoList[findingId + 1], seminarSearchDtoList[findingId - 1])
} else if (findingId == 0) {
if (seminarSearchDtoList.size == 1) {
prevNext = arrayOf(null, null)
} else {
prevNext = arrayOf(seminarSearchDtoList[1], null)
}
} else {
prevNext = arrayOf(null, seminarSearchDtoList[seminarSearchDtoList.size - 2])
}

return prevNext

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.wafflestudio.csereal.core.seminar.dto

import com.wafflestudio.csereal.core.seminar.database.SeminarEntity

data class SeminarDto(
val id: Long,
val title: String,
val description: String,
val introduction: String,
val category: String,
val name: String,
val speakerUrl: String?,
val speakerTitle: String?,
val affiliation: String,
val affiliationUrl: String?,
val startDate: String?,
val startTime: String?,
val endDate: String?,
val endTime: String?,
val location: String,
val host: String?,
// val profileImage: File,
// val seminarFile: File,
val additionalNote: String?,
val isPublic: Boolean,
val isSlide: Boolean,
val prevId: Long?,
val prevTitle: String?,
val nextId: Long?,
val nextTitle: String?
) {

companion object {
fun of(entity: SeminarEntity, prevNext: Array<SeminarEntity?>?): SeminarDto = entity.run {
SeminarDto(
id = this.id,
title = this.title,
description = this.description,
introduction = this.introduction,
category = this.category,
name = this.name,
speakerUrl = this.speakerUrl,
speakerTitle = this.speakerTitle,
affiliation = this.affiliation,
affiliationUrl = this.affiliationUrl,
startDate = this.startDate,
startTime = this.startTime,
endDate = this.endDate,
endTime = this.endTime,
location = this.location,
host = this.host,
additionalNote = this.additionalNote,
isPublic = this.isPublic,
isSlide = this.isSlide,
prevId = prevNext?.get(0)?.id,
prevTitle = prevNext?.get(0)?.title,
nextId = prevNext?.get(1)?.id,
nextTitle = prevNext?.get(1)?.title
)
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.wafflestudio.csereal.core.seminar.service

import com.wafflestudio.csereal.common.CserealException
import com.wafflestudio.csereal.core.seminar.database.SeminarEntity
import com.wafflestudio.csereal.core.seminar.database.SeminarRepository
import com.wafflestudio.csereal.core.seminar.dto.SeminarDto
import org.springframework.data.repository.findByIdOrNull
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

interface SeminarService {
fun createSeminar(request: SeminarDto): SeminarDto
fun readSeminar(seminarId: Long, keyword: String?): SeminarDto
fun updateSeminar(seminarId: Long, request: SeminarDto): SeminarDto
}

@Service
class SeminarServiceImpl(
private val seminarRepository: SeminarRepository
) : SeminarService {

@Transactional
override fun createSeminar(request: SeminarDto): SeminarDto {
val newSeminar = SeminarEntity.of(request)

seminarRepository.save(newSeminar)

return SeminarDto.of(newSeminar, null)
}

@Transactional(readOnly = true)
override fun readSeminar(seminarId: Long, keyword: String?): SeminarDto {
val seminar: SeminarEntity = seminarRepository.findByIdOrNull(seminarId)
?: throw CserealException.Csereal404("존재하지 않는 세미나입니다.(seminarId: $seminarId)")

if (seminar.isDeleted) throw CserealException.Csereal400("삭제된 세미나입니다. (seminarId: $seminarId)")

val prevNext = seminarRepository.findPrevNextId(seminarId, keyword)

return SeminarDto.of(seminar, prevNext)
}

@Transactional
override fun updateSeminar(seminarId: Long, request: SeminarDto): SeminarDto {
val seminar: SeminarEntity = seminarRepository.findByIdOrNull(seminarId)
?: throw CserealException.Csereal404("존재하지 않는 세미나입니다")
if(seminar.isDeleted) throw CserealException.Csereal404("삭제된 세미나입니다. (seminarId: $seminarId)")

seminar.update(request)

return SeminarDto.of(seminar, null)
}
}

0 comments on commit 54ad2ff

Please sign in to comment.