-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: createSeminar, readSeminar, updateSeminar 추가
- Loading branch information
Showing
5 changed files
with
314 additions
and
0 deletions.
There are no files selected for viewing
36 changes: 36 additions & 0 deletions
36
src/main/kotlin/com/wafflestudio/csereal/core/seminar/api/SeminarController.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)) | ||
} | ||
} |
96 changes: 96 additions & 0 deletions
96
src/main/kotlin/com/wafflestudio/csereal/core/seminar/database/SeminarEntity.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} | ||
} |
65 changes: 65 additions & 0 deletions
65
src/main/kotlin/com/wafflestudio/csereal/core/seminar/database/SeminarRepository.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
|
||
} | ||
} |
64 changes: 64 additions & 0 deletions
64
src/main/kotlin/com/wafflestudio/csereal/core/seminar/dto/SeminarDto.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
) | ||
} | ||
|
||
} | ||
|
||
} |
53 changes: 53 additions & 0 deletions
53
src/main/kotlin/com/wafflestudio/csereal/core/seminar/service/SeminarService.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} | ||
} |