Skip to content

Commit

Permalink
Merge branch 'develop' into feat/news_add_plain
Browse files Browse the repository at this point in the history
  • Loading branch information
huGgW authored Sep 8, 2023
2 parents ae0d7e1 + 8d5627c commit c307063
Show file tree
Hide file tree
Showing 13 changed files with 105 additions and 118 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class SubjectChangesDto(
val description: String,
) {
companion object {

fun of(entity: AcademicsEntity) = entity.run {
SubjectChangesDto(
time = this.time!!,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ import org.springframework.web.bind.annotation.RestController
class AdmissionsController(
private val admissionsService: AdmissionsService
) {
@PostMapping("/undergraduate")
@PostMapping("/undergraduate/{postType}")
fun createUndergraduateAdmissions(
@RequestParam postType: String,
@PathVariable postType: String,
@Valid @RequestBody request: AdmissionsDto
) : AdmissionsDto {
return admissionsService.createUndergraduateAdmissions(postType, request)
Expand All @@ -32,9 +32,9 @@ class AdmissionsController(
return admissionsService.createGraduateAdmissions(request)
}

@GetMapping("/undergraduate")
@GetMapping("/undergraduate/{postType}")
fun readUndergraduateAdmissions(
@RequestParam postType: String
@PathVariable postType: String
) : ResponseEntity<AdmissionsDto> {
return ResponseEntity.ok(admissionsService.readUndergraduateAdmissions(postType))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ import jakarta.persistence.Enumerated
class AdmissionsEntity(
@Enumerated(EnumType.STRING)
val postType: AdmissionsPostType,
val title: String,
val pageName: String,
val description: String,
): BaseTimeEntity() {
companion object {
fun of(postType: AdmissionsPostType, admissionsDto: AdmissionsDto) : AdmissionsEntity {
fun of(postType: AdmissionsPostType, pageName: String, admissionsDto: AdmissionsDto) : AdmissionsEntity {
return AdmissionsEntity(
postType = postType,
title = admissionsDto.title,
pageName = pageName,
description = admissionsDto.description,
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import java.time.LocalDateTime

data class AdmissionsDto(
val id: Long,
val title: String,
val description: String,
val createdAt: LocalDateTime?,
val modifiedAt: LocalDateTime?,
Expand All @@ -14,7 +13,6 @@ data class AdmissionsDto(
fun of(entity: AdmissionsEntity) : AdmissionsDto = entity.run {
AdmissionsDto(
id = this.id,
title = this.title,
description = this.description,
createdAt = this.createdAt,
modifiedAt = this.modifiedAt,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@ class AdmissionsServiceImpl(
override fun createUndergraduateAdmissions(postType: String, request: AdmissionsDto): AdmissionsDto {
val enumPostType = makeStringToAdmissionsPostType(postType)

val newAdmissions = AdmissionsEntity.of(enumPostType, request)
val pageName = when(enumPostType) {
AdmissionsPostType.UNDERGRADUATE_EARLY_ADMISSION -> "수시 모집"
AdmissionsPostType.UNDERGRADUATE_REGULAR_ADMISSION -> "정시 모집"
else -> throw CserealException.Csereal404("해당하는 페이지를 찾을 수 없습니다.")
}

val newAdmissions = AdmissionsEntity.of(enumPostType, pageName, request)

admissionsRepository.save(newAdmissions)

Expand All @@ -33,7 +39,7 @@ class AdmissionsServiceImpl(

@Transactional
override fun createGraduateAdmissions(request: AdmissionsDto): AdmissionsDto {
val newAdmissions: AdmissionsEntity = AdmissionsEntity.of(AdmissionsPostType.GRADUATE, request)
val newAdmissions: AdmissionsEntity = AdmissionsEntity.of(AdmissionsPostType.GRADUATE, "전기/후기 모집", request)

admissionsRepository.save(newAdmissions)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.wafflestudio.csereal.common.aop.AuthenticatedStaff
import com.wafflestudio.csereal.core.notice.dto.*
import com.wafflestudio.csereal.core.notice.service.NoticeService
import jakarta.validation.Valid
import org.springframework.data.domain.PageRequest
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*
Expand All @@ -18,18 +19,19 @@ class NoticeController(
fun searchNotice(
@RequestParam(required = false) tag: List<String>?,
@RequestParam(required = false) keyword: String?,
@RequestParam(required = false, defaultValue = "0") pageNum: Long
@RequestParam(required = false, defaultValue = "1") pageNum: Int,
@RequestParam(required = false, defaultValue = "false") usePageBtn: Boolean
): ResponseEntity<NoticeSearchResponse> {
return ResponseEntity.ok(noticeService.searchNotice(tag, keyword, pageNum))
val pageSize = 20
val pageRequest = PageRequest.of(pageNum - 1, pageSize)
return ResponseEntity.ok(noticeService.searchNotice(tag, keyword, pageRequest, usePageBtn))
}

@GetMapping("/{noticeId}")
fun readNotice(
@PathVariable noticeId: Long,
@RequestParam(required = false) tag: List<String>?,
@RequestParam(required = false) keyword: String?,
@PathVariable noticeId: Long
): ResponseEntity<NoticeDto> {
return ResponseEntity.ok(noticeService.readNotice(noticeId, tag, keyword))
return ResponseEntity.ok(noticeService.readNotice(noticeId))
}

@AuthenticatedStaff
Expand Down Expand Up @@ -63,6 +65,7 @@ class NoticeController(
) {
noticeService.unpinManyNotices(request.idList)
}

@DeleteMapping
fun deleteManyNotices(
@RequestBody request: NoticeIdListRequest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,42 @@ import com.wafflestudio.csereal.core.notice.database.QNoticeEntity.noticeEntity
import com.wafflestudio.csereal.core.notice.database.QNoticeTagEntity.noticeTagEntity
import com.wafflestudio.csereal.core.notice.dto.NoticeSearchDto
import com.wafflestudio.csereal.core.notice.dto.NoticeSearchResponse
import org.springframework.data.domain.PageRequest
import org.springframework.data.domain.Pageable
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Component
import java.time.LocalDateTime
import kotlin.math.ceil

interface NoticeRepository : JpaRepository<NoticeEntity, Long>, CustomNoticeRepository {
fun findAllByIsImportant(isImportant: Boolean): List<NoticeEntity>
fun findFirstByCreatedAtLessThanOrderByCreatedAtDesc(timestamp: LocalDateTime): NoticeEntity?
fun findFirstByCreatedAtGreaterThanOrderByCreatedAtAsc(timestamp: LocalDateTime): NoticeEntity?
}

interface CustomNoticeRepository {
fun searchNotice(tag: List<String>?, keyword: String?, pageNum: Long): NoticeSearchResponse
fun findPrevNextId(noticeId: Long, tag: List<String>?, keyword: String?): Array<NoticeEntity?>?
fun searchNotice(
tag: List<String>?,
keyword: String?,
pageable: Pageable,
usePageBtn: Boolean
): NoticeSearchResponse
}

@Component
class NoticeRepositoryImpl(
private val queryFactory: JPAQueryFactory,
) : CustomNoticeRepository {
override fun searchNotice(tag: List<String>?, keyword: String?, pageNum: Long): NoticeSearchResponse {
override fun searchNotice(
tag: List<String>?,
keyword: String?,
pageable: Pageable,
usePageBtn: Boolean
): NoticeSearchResponse {
val keywordBooleanBuilder = BooleanBuilder()
val tagsBooleanBuilder = BooleanBuilder()

if (!keyword.isNullOrEmpty()) {

val keywordList = keyword.split("[^a-zA-Z0-9가-힣]".toRegex())
keywordList.forEach {
if (it.length == 1) {
Expand All @@ -39,8 +53,8 @@ class NoticeRepositoryImpl(
.or(noticeEntity.description.contains(it))
)
}
}

}
}
if (!tag.isNullOrEmpty()) {
tag.forEach {
Expand All @@ -50,18 +64,27 @@ class NoticeRepositoryImpl(
}
}

val jpaQuery = queryFactory.select(noticeEntity).from(noticeEntity)
val jpaQuery = queryFactory.selectFrom(noticeEntity)
.leftJoin(noticeTagEntity).on(noticeTagEntity.notice.eq(noticeEntity))
.where(noticeEntity.isDeleted.eq(false), noticeEntity.isPublic.eq(true))
.where(keywordBooleanBuilder).where(tagsBooleanBuilder)
.where(keywordBooleanBuilder, tagsBooleanBuilder)

val countQuery = jpaQuery.clone()
val total = countQuery.select(noticeEntity.countDistinct()).fetchOne()
val total: Long
var pageRequest = pageable

if (usePageBtn) {
val countQuery = jpaQuery.clone()
total = countQuery.select(noticeEntity.countDistinct()).fetchOne()!!
pageRequest = exchangePageRequest(pageable, total)
} else {
total = (10 * pageable.pageSize).toLong() // 10개 페이지 고정
}

val noticeEntityList = jpaQuery.orderBy(noticeEntity.isPinned.desc())
val noticeEntityList = jpaQuery
.orderBy(noticeEntity.isPinned.desc())
.orderBy(noticeEntity.createdAt.desc())
.offset(20 * pageNum)
.limit(20)
.offset(pageRequest.offset)
.limit(pageRequest.pageSize.toLong())
.distinct()
.fetch()

Expand All @@ -77,62 +100,25 @@ class NoticeRepositoryImpl(
)
}

return NoticeSearchResponse(total!!, noticeSearchDtoList)
}

override fun findPrevNextId(noticeId: Long, tag: List<String>?, keyword: String?): Array<NoticeEntity?>? {
val keywordBooleanBuilder = BooleanBuilder()
val tagsBooleanBuilder = BooleanBuilder()
return NoticeSearchResponse(total, noticeSearchDtoList)

if (!keyword.isNullOrEmpty()) {
val keywordList = keyword.split("[^a-zA-Z0-9가-힣]".toRegex())
keywordList.forEach {
if (it.length == 1) {
throw CserealException.Csereal400("각각의 키워드는 한글자 이상이어야 합니다.")
} else {
keywordBooleanBuilder.and(
noticeEntity.title.contains(it)
.or(noticeEntity.description.contains(it))
)
}
}

}
}
if (!tag.isNullOrEmpty()) {
tag.forEach {
tagsBooleanBuilder.or(
noticeTagEntity.tag.name.eq(it)
)
}
}
private fun exchangePageRequest(pageable: Pageable, total: Long): Pageable {
/**
* 요청한 페이지 번호가 기존 데이터 사이즈 초과할 경우 마지막 페이지 데이터 반환
*/

val noticeSearchDtoList = queryFactory.select(noticeEntity).from(noticeEntity)
.leftJoin(noticeTagEntity).on(noticeTagEntity.notice.eq(noticeEntity))
.where(noticeEntity.isDeleted.eq(false), noticeEntity.isPublic.eq(true))
.where(keywordBooleanBuilder).where(tagsBooleanBuilder)
.orderBy(noticeEntity.isPinned.desc())
.orderBy(noticeEntity.createdAt.desc())
.distinct()
.fetch()
val pageNum = pageable.pageNumber
val pageSize = pageable.pageSize
val requestCount = (pageNum - 1) * pageSize

val findingId = noticeSearchDtoList.indexOfFirst { it.id == noticeId }

val prevNext: Array<NoticeEntity?>?
if (findingId == -1) {
prevNext = arrayOf(null, null)
} else if (findingId != 0 && findingId != noticeSearchDtoList.size - 1) {
prevNext = arrayOf(noticeSearchDtoList[findingId + 1], noticeSearchDtoList[findingId - 1])
} else if (findingId == 0) {
if (noticeSearchDtoList.size == 1) {
prevNext = arrayOf(null, null)
} else {
prevNext = arrayOf(noticeSearchDtoList[1], null)
}
} else {
prevNext = arrayOf(null, noticeSearchDtoList[noticeSearchDtoList.size - 2])
if (total > requestCount) {
return pageable
}

return prevNext
val requestPageNum = ceil(total.toDouble() / pageNum).toInt()
return PageRequest.of(requestPageNum, pageSize)

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ data class NoticeDto(
fun of(
entity: NoticeEntity,
attachmentResponses: List<AttachmentResponse>,
prevNext: Array<NoticeEntity?>?
prevNotice: NoticeEntity? = null,
nextNotice: NoticeEntity? = null
): NoticeDto = entity.run {
NoticeDto(
id = this.id,
Expand All @@ -39,10 +40,10 @@ data class NoticeDto(
isPublic = this.isPublic,
isPinned = this.isPinned,
isImportant = this.isImportant,
prevId = prevNext?.get(0)?.id,
prevTitle = prevNext?.get(0)?.title,
nextId = prevNext?.get(1)?.id,
nextTitle = prevNext?.get(1)?.title,
prevId = prevNotice?.id,
prevTitle = prevNotice?.title,
nextId = nextNotice?.id,
nextTitle = nextNotice?.title,
attachments = attachmentResponses,
)
}
Expand Down
Loading

0 comments on commit c307063

Please sign in to comment.