Skip to content

Commit

Permalink
Merge pull request #24 from HappyScrolls/feature/#22_duplicated_schedule
Browse files Browse the repository at this point in the history
#22 중복 체크
  • Loading branch information
chs98412 authored Oct 29, 2024
2 parents 8dbc47c + 4dde5e6 commit f7f4553
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 3 deletions.
19 changes: 19 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ plugins {
kotlin("jvm") version "1.9.24"
kotlin("plugin.spring") version "1.9.24"
kotlin("plugin.jpa") version "1.9.24"
kotlin("kapt") version "1.5.31"
}

group = "com.yedongsoon"
Expand Down Expand Up @@ -37,6 +38,24 @@ dependencies {
implementation("org.springdoc:springdoc-openapi-starter-webflux-ui:2.1.0")
implementation("org.springframework.boot:spring-boot-starter-data-redis-reactive")
implementation("io.projectreactor.kotlin:reactor-kotlin-extensions")
implementation("com.querydsl:querydsl-jpa:5.0.0:jakarta")
implementation("com.querydsl:querydsl-apt:5.0.0:jakarta")
kapt("com.querydsl:querydsl-apt:5.0.0:jakarta")

}

kapt {
arguments {
arg("querydsl.entityAccessors", "true")
arg("querydsl.useFields", "false") // 필드 대신 getter/setter를 사용하는 옵션
}
}

// QueryDSL로 생성된 QClass의 경로 설정
sourceSets {
main {
java.srcDir("build/generated/source/kapt/main")
}
}

tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ package com.yedongsoon.example_project.application.exception
import org.springframework.http.HttpStatus

class ScheduleNotFoundException(message: String) : AbstractException(HttpStatus.NOT_FOUND, message)
class ScheduleDuplicatedException(message: String) : AbstractException(HttpStatus.BAD_REQUEST, message)
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
package com.yedongsoon.example_project.domain.schedule

import com.yedongsoon.example_project.application.couple.CoupleQueryService
import com.yedongsoon.example_project.application.exception.ScheduleDuplicatedException
import com.yedongsoon.example_project.application.exception.ScheduleNotFoundException
import com.yedongsoon.example_project.domain.schedule.model.ScheduleCreateCommand
import org.springframework.data.repository.findByIdOrNull
import org.springframework.stereotype.Service

@Service
class ScheduleCommandService(
private val scheduleRepository: ScheduleRepository
private val scheduleRepository: ScheduleRepository,
private val coupleQueryService: CoupleQueryService,
) {
// 일정 등록
fun createSchedule(command: ScheduleCreateCommand) {
val partnerNo = coupleQueryService.getLover(command.accountNo).no
if (scheduleRepository.existsByDuplicateSchedule(command.scheduleStartAt, command.scheduleEndAt, command.accountNo, partnerNo)) {
throw ScheduleDuplicatedException("시간대에 겹치는 일정이 존재합니다")
}
scheduleRepository.save(Schedule.create(command))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package com.yedongsoon.example_project.domain.schedule
import org.springframework.data.jpa.repository.JpaRepository
import java.time.LocalDate

interface ScheduleRepository : JpaRepository<Schedule, Int> {
interface ScheduleRepository : JpaRepository<Schedule, Int>, ScheduleRepositoryCustom {
// 특정 일정 조회
fun findByAccountNoAndScheduleAtAndIsCommonIsFalse(accountNo: Int, scheduleAt: LocalDate): List<Schedule>
fun findByAccountNoInAndScheduleAtAndIsCommonIsTrue(accountNos: List<Int>, scheduleAt: LocalDate): List<Schedule>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.yedongsoon.example_project.domain.schedule

import java.time.LocalDateTime

interface ScheduleRepositoryCustom {

fun existsByDuplicateSchedule(
scheduleEndAt: LocalDateTime,
scheduleStartAt: LocalDateTime,
accountNo: Int,
partnerNo: Int,
): Boolean
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.yedongsoon.example_project.infrastructure.config

import com.querydsl.jpa.impl.JPAQueryFactory
import org.springframework.data.jpa.repository.support.Querydsl
import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport
import org.springframework.stereotype.Repository
import kotlin.properties.Delegates
import kotlin.reflect.KClass

@Repository
abstract class QuerydslSupport(clazz: Class<*>) : QuerydslRepositorySupport(clazz) {
private var queryFactory: JPAQueryFactory by Delegates.notNull()

constructor(kClass: KClass<*>) : this(kClass.java)


override fun getQuerydsl(): Querydsl {
return super.getQuerydsl() ?: throw IllegalStateException("Querydsl is null")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.yedongsoon.example_project.infrastructure.jpa

import com.querydsl.core.BooleanBuilder
import com.yedongsoon.example_project.domain.schedule.QSchedule
import com.yedongsoon.example_project.domain.schedule.ScheduleRepositoryCustom
import com.yedongsoon.example_project.infrastructure.config.QuerydslSupport
import org.springframework.stereotype.Repository
import java.time.LocalDateTime

@Repository
class ScheduleRepositoryImpl : QuerydslSupport(QSchedule::class.java), ScheduleRepositoryCustom {
override fun existsByDuplicateSchedule(scheduleEndAt: LocalDateTime, scheduleStartAt: LocalDateTime, accountNo: Int, partnerNo: Int): Boolean {
val schedule = QSchedule.schedule
val conditionBuilder = BooleanBuilder()
conditionBuilder.and(schedule.isDeleted.isFalse)
conditionBuilder.and(schedule.scheduleStartAt.loe(scheduleStartAt))
conditionBuilder.and(schedule.scheduleEndAt.goe(scheduleEndAt))
conditionBuilder.and(schedule.accountNo.eq(accountNo))

val partnerConditionBuilder = BooleanBuilder()
partnerConditionBuilder.and(schedule.isDeleted.isFalse)
partnerConditionBuilder.and(schedule.scheduleStartAt.loe(scheduleStartAt))
partnerConditionBuilder.and(schedule.scheduleEndAt.goe(scheduleEndAt))
partnerConditionBuilder.and(schedule.accountNo.eq(partnerNo))
partnerConditionBuilder.and(schedule.isCommon.isTrue)
val result = from(schedule)
.where(conditionBuilder.or(partnerConditionBuilder))
.fetchCount()
return result != 0L
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class ScheduleHandler(
@Operation(summary = "스케줄 생성", description = "새로운 스케줄을 생성합니다.")
@ApiResponses(value = [
ApiResponse(responseCode = "204", description = "스케줄 생성 성공"),
ApiResponse(responseCode = "400", description = "잘못된 요청 데이터")
ApiResponse(responseCode = "400", description = "중복된 요청 데이터")
])
suspend fun createSchedule(request: ServerRequest): ServerResponse = withContext(Dispatchers.IO) {
val memberHeader = request.extractMemberCodeHeader()
Expand Down

0 comments on commit f7f4553

Please sign in to comment.