diff --git a/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/common/dto/PageResponse.kt b/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/common/dto/PageResponse.kt new file mode 100644 index 00000000..0ffa627e --- /dev/null +++ b/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/common/dto/PageResponse.kt @@ -0,0 +1,23 @@ +package com.bamyanggang.apimodule.common.dto + +import com.bamyanggang.domainmodule.common.pagination.PageDomain + +data class PageResponse( + val content: List, + val page: Int, + val size: Int, + val totalPage: Int, + val hasNext: Boolean +) { + companion object { + fun from(page: PageDomain): PageResponse { + return PageResponse( + content = page.content, + page = page.pageNumber, + size = page.pageSize, + totalPage = page.totalPage, + hasNext = page.hasNext + ) + } + } +} diff --git a/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/common/dto/SliceResponse.kt b/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/common/dto/SliceResponse.kt deleted file mode 100644 index 7d6404de..00000000 --- a/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/common/dto/SliceResponse.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.bamyanggang.apimodule.common.dto - -import com.bamyanggang.domainmodule.common.pagination.SliceDomain - -data class SliceResponse( - val content: List, - val page: Int, - val size: Int, - val hasNext: Boolean -) { - companion object { - fun from(slice: SliceDomain): SliceResponse { - return SliceResponse( - content = slice.content, - page = slice.pageNumber, - size = slice.pageSize, - hasNext = slice.hasNext - ) - } - } -} diff --git a/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/jobDescription/application/service/ApplyCreateService.kt b/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/jobDescription/application/service/ApplyCreateService.kt index 8a3e3d57..72fd1134 100644 --- a/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/jobDescription/application/service/ApplyCreateService.kt +++ b/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/jobDescription/application/service/ApplyCreateService.kt @@ -1,8 +1,11 @@ package com.bamyanggang.apimodule.domain.jobDescription.application.service import com.bamyanggang.apimodule.domain.jobDescription.application.dto.CreateApply +import com.bamyanggang.domainmodule.domain.jobDescription.enums.WriteStatus import com.bamyanggang.domainmodule.domain.jobDescription.service.ApplyAppender import com.bamyanggang.domainmodule.domain.jobDescription.service.ApplyContentAppender +import com.bamyanggang.domainmodule.domain.jobDescription.service.JobDescriptionModifier +import com.bamyanggang.domainmodule.domain.jobDescription.service.JobDescriptionReader import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional import java.util.* @@ -10,19 +13,22 @@ import java.util.* @Service class ApplyCreateService( private val applyAppender: ApplyAppender, - private val applyContentAppender: ApplyContentAppender + private val applyContentAppender: ApplyContentAppender, + private val jobDescriptionReader: JobDescriptionReader, + private val jobDescriptionModifier: JobDescriptionModifier ) { @Transactional fun createApply(request: CreateApply.Request, jobDescriptionId: UUID) { - applyAppender.appendApply( - jobDescriptionId = jobDescriptionId, - ).also { apply -> - request.contents.forEach { content -> - applyContentAppender.appendApplyContent( - applyId = apply.id, - question = content.question, - answer = content.answer - ) + jobDescriptionReader.readJobDescriptionById(jobDescriptionId).also { + jobDescriptionModifier.modifyWriteStatus(it, WriteStatus.WRITING) + applyAppender.appendApply(it.id).also { apply -> + request.contents.forEach { content -> + applyContentAppender.appendApplyContent( + applyId = apply.id, + question = content.question, + answer = content.answer + ) + } } } } diff --git a/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/jobDescription/application/service/JobDescriptionInfoGetService.kt b/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/jobDescription/application/service/JobDescriptionInfoGetService.kt index 7acadeb5..1a988b53 100644 --- a/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/jobDescription/application/service/JobDescriptionInfoGetService.kt +++ b/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/jobDescription/application/service/JobDescriptionInfoGetService.kt @@ -1,15 +1,13 @@ package com.bamyanggang.apimodule.domain.jobDescription.application.service -import com.bamyanggang.apimodule.common.dto.SliceResponse +import com.bamyanggang.apimodule.common.dto.PageResponse import com.bamyanggang.apimodule.common.getAuthenticationPrincipal import com.bamyanggang.apimodule.domain.jobDescription.application.dto.GetJobDescriptionInfo -import com.bamyanggang.domainmodule.common.pagination.SliceDomain +import com.bamyanggang.domainmodule.common.pagination.PageDomain import com.bamyanggang.domainmodule.domain.jobDescription.enums.SortType import com.bamyanggang.domainmodule.domain.jobDescription.enums.WriteStatus -import com.bamyanggang.domainmodule.domain.jobDescription.service.ApplyReader import com.bamyanggang.domainmodule.domain.jobDescription.service.JobDescriptionReader import org.springframework.data.domain.Pageable -import org.springframework.data.domain.SliceImpl import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -17,30 +15,29 @@ import org.springframework.transaction.annotation.Transactional @Service class JobDescriptionInfoGetService( private val jobDescriptionReader: JobDescriptionReader, - private val applyReader: ApplyReader ) { @Transactional(readOnly = true) - fun getJobDescriptionInfo(pageable: Pageable, writeStatus: WriteStatus?, sortType: SortType?): SliceResponse { + fun getJobDescriptionInfo(pageable: Pageable, writeStatus: WriteStatus?, sortType: SortType?): PageResponse { return getAuthenticationPrincipal().let{ userId -> - val jobDescriptions = jobDescriptionReader.readJobDescriptionByUserIdAndSortType(userId, pageable.pageNumber, pageable.pageSize, sortType) + val jobDescriptions = jobDescriptionReader.readJobDescriptionByUserIdAndSortType(userId, pageable.pageNumber, pageable.pageSize, sortType, writeStatus) val jobDescriptionInfoResponses = jobDescriptions.content.map{ jobDescription -> - val apply = applyReader.readApplyByJobDescriptionId(jobDescription.id) GetJobDescriptionInfo.Response( jobDescription.id, jobDescription.getRemainingDate(), jobDescription.enterpriseName, jobDescription.title, - apply?.writeStatus?: WriteStatus.NOT_APPLIED, + jobDescription.writeStatus, jobDescription.createdAt, jobDescription.startedAt, jobDescription.endedAt ) } - val jobDescriptionsSlice = SliceDomain(jobDescriptionInfoResponses, jobDescriptions.pageNumber, jobDescriptions.pageSize, jobDescriptions.hasNext) - SliceResponse.from(jobDescriptionsSlice) + val jobDescriptionsSlice = PageDomain(jobDescriptionInfoResponses, jobDescriptions.pageNumber, jobDescriptions.pageSize, jobDescriptions.totalPage, + jobDescriptions.hasNext) + PageResponse.from(jobDescriptionsSlice) } } diff --git a/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/jobDescription/presentation/JobDescriptionController.kt b/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/jobDescription/presentation/JobDescriptionController.kt index 50521e7c..1c35c3d7 100644 --- a/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/jobDescription/presentation/JobDescriptionController.kt +++ b/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/jobDescription/presentation/JobDescriptionController.kt @@ -1,6 +1,6 @@ package com.bamyanggang.apimodule.domain.jobDescription.presentation -import com.bamyanggang.apimodule.common.dto.SliceResponse +import com.bamyanggang.apimodule.common.dto.PageResponse import com.bamyanggang.apimodule.domain.jobDescription.application.dto.CreateApply import com.bamyanggang.apimodule.domain.jobDescription.application.dto.CreateJobDescription import com.bamyanggang.apimodule.domain.jobDescription.application.dto.GetJobDescriptionInfo @@ -41,7 +41,7 @@ class JobDescriptionController( pageable: Pageable, @RequestParam writeStatus: WriteStatus?, @RequestParam sortType: SortType? - ): SliceResponse { + ): PageResponse { return jobDescriptionInfoGetService.getJobDescriptionInfo(pageable, writeStatus, sortType) } diff --git a/Api-Module/src/test/kotlin/com/bamyanggang/apimodule/domain/jobDescription/application/ApplyCreateServiceTest.kt b/Api-Module/src/test/kotlin/com/bamyanggang/apimodule/domain/jobDescription/application/ApplyCreateServiceTest.kt index 8eb7a320..9bcbc5de 100644 --- a/Api-Module/src/test/kotlin/com/bamyanggang/apimodule/domain/jobDescription/application/ApplyCreateServiceTest.kt +++ b/Api-Module/src/test/kotlin/com/bamyanggang/apimodule/domain/jobDescription/application/ApplyCreateServiceTest.kt @@ -4,39 +4,69 @@ import com.bamyanggang.apimodule.domain.jobDescription.application.dto.CreateApp import com.bamyanggang.apimodule.domain.jobDescription.application.service.ApplyCreateService import com.bamyanggang.commonmodule.fixture.generateFixture import com.bamyanggang.domainmodule.domain.jobDescription.aggregate.Apply +import com.bamyanggang.domainmodule.domain.jobDescription.aggregate.JobDescription +import com.bamyanggang.domainmodule.domain.jobDescription.enums.WriteStatus import com.bamyanggang.domainmodule.domain.jobDescription.service.ApplyAppender import com.bamyanggang.domainmodule.domain.jobDescription.service.ApplyContentAppender +import com.bamyanggang.domainmodule.domain.jobDescription.service.JobDescriptionModifier +import com.bamyanggang.domainmodule.domain.jobDescription.service.JobDescriptionReader import io.kotest.core.spec.style.BehaviorSpec import io.mockk.every import io.mockk.mockk import io.mockk.verify +import java.time.LocalDateTime import java.util.* + class ApplyCreateServiceTest : BehaviorSpec({ val applyAppender = mockk() val applyContentAppender = mockk() - val applyCreateService = ApplyCreateService(applyAppender, applyContentAppender) + val jobDescriptionReader = mockk() + val jobDescriptionModifier = mockk() + val applyCreateService = ApplyCreateService(applyAppender, applyContentAppender, jobDescriptionReader, jobDescriptionModifier) + + Given("CreateApply.Request 와 jobDescriptionId이 들어온 경우") { + val request = generateFixture() + val jobDescriptionId = UUID.randomUUID() + val jobDescription : JobDescription = generateFixture{ + it.set("id", jobDescriptionId) + it.set("enterpriseName", "기업 이름") + it.set("title", "직무 공고 제목") + it.set("content", "직무 공고 내용") + it.set("link", "직무 공고 링크") + it.set("startedAt", LocalDateTime.now()) + it.set("endedAt", LocalDateTime.now().plusDays(1)) + } + val apply = generateFixture() - given("ApplyCreateService.createApply") { - `when`("request가 주어지면") { - val request: CreateApply.Request = generateFixture() - val jobDescriptionId: UUID = generateFixture() - val apply: Apply = generateFixture() - every { applyAppender.appendApply(any()) } returns apply - every { applyContentAppender.appendApplyContent(any(), any(), any()) } returns Unit + every { jobDescriptionReader.readJobDescriptionById(jobDescriptionId) } returns jobDescription + every { applyAppender.appendApply(jobDescriptionId) } returns apply + every { applyContentAppender.appendApplyContent(any(), any(), any()) } returns Unit + every { jobDescriptionModifier.modifyWriteStatus(any(), any()) } returns Unit + When("createApply가 호출된다") { applyCreateService.createApply(request, jobDescriptionId) - then("appendApply가 호출된다.") { - verify { applyAppender.appendApply( jobDescriptionId) } + Then("applyAppender.appendApply가 호출된다") { + verify { applyAppender.appendApply(jobDescriptionId) } } - then("appendApplyContent가 호출된다.") { + Then("applyContentAppender.appendApplyContent가 호출된다") { request.contents.forEach { content -> - verify { applyContentAppender.appendApplyContent(apply.id, content.question, content.answer) } + verify { + applyContentAppender.appendApplyContent( + applyId = apply.id, + question = content.question, + answer = content.answer + ) + } } } + + Then("jobDescriptionModifier.modifyWriteStatus 가 호출된다") { + verify { jobDescriptionModifier.modifyWriteStatus(jobDescription, WriteStatus.WRITING) } + } } } }) diff --git a/Api-Module/src/test/kotlin/com/bamyanggang/apimodule/domain/jobDescription/presentation/JobDescriptionControllerTest.kt b/Api-Module/src/test/kotlin/com/bamyanggang/apimodule/domain/jobDescription/presentation/JobDescriptionControllerTest.kt index d37e4c81..7be31f16 100644 --- a/Api-Module/src/test/kotlin/com/bamyanggang/apimodule/domain/jobDescription/presentation/JobDescriptionControllerTest.kt +++ b/Api-Module/src/test/kotlin/com/bamyanggang/apimodule/domain/jobDescription/presentation/JobDescriptionControllerTest.kt @@ -1,7 +1,7 @@ package com.bamyanggang.apimodule.domain.jobDescription.presentation import com.bamyanggang.apimodule.BaseRestDocsTest -import com.bamyanggang.apimodule.common.dto.SliceResponse +import com.bamyanggang.apimodule.common.dto.PageResponse import com.bamyanggang.apimodule.domain.jobDescription.application.dto.CreateApply import com.bamyanggang.apimodule.domain.jobDescription.application.dto.CreateApplyContent import com.bamyanggang.apimodule.domain.jobDescription.application.dto.CreateJobDescription @@ -11,10 +11,9 @@ import com.bamyanggang.apimodule.domain.jobDescription.application.service.JobDe import com.bamyanggang.apimodule.domain.jobDescription.application.service.JobDescriptionInfoGetService import com.bamyanggang.commonmodule.exception.ExceptionHandler import com.bamyanggang.commonmodule.fixture.generateFixture -import com.bamyanggang.domainmodule.common.pagination.SliceDomain +import com.bamyanggang.domainmodule.common.pagination.PageDomain import com.bamyanggang.domainmodule.domain.jobDescription.enums.SortType import com.bamyanggang.domainmodule.domain.jobDescription.enums.WriteStatus -import io.kotest.assertions.print.printWithType import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test import org.mockito.BDDMockito.given @@ -22,8 +21,6 @@ import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest import org.springframework.boot.test.mock.mockito.MockBean import org.springframework.context.annotation.Import import org.springframework.data.domain.PageRequest -import org.springframework.data.domain.Slice -import org.springframework.data.domain.SliceImpl import org.springframework.http.MediaType import org.springframework.restdocs.headers.HeaderDocumentation.headerWithName import org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders @@ -260,9 +257,9 @@ class JobDescriptionControllerTest : BaseRestDocsTest() { it.set("startedAt", LocalDateTime.now()) it.set("endedAt", LocalDateTime.now()) } - val slice = SliceDomain(listOf(getJobDescriptionInfoResponse), 0, 1, true) - val sliceResponse = SliceResponse.from(slice) - given(jobDescriptionInfoGetService.getJobDescriptionInfo(pageRequest, WriteStatus.WRITING, SortType.ENDED)).willReturn(sliceResponse) + val slice = PageDomain(listOf(getJobDescriptionInfoResponse), 0, 1, 5, true) + val pageResponse = PageResponse.from(slice) + given(jobDescriptionInfoGetService.getJobDescriptionInfo(pageRequest, WriteStatus.WRITING, SortType.ENDED)).willReturn(pageResponse) val request = RestDocumentationRequestBuilders.get(JobDescriptionApi.BASE_URL) @@ -302,6 +299,7 @@ class JobDescriptionControllerTest : BaseRestDocsTest() { fieldWithPath("content[].endedAt").description("종료일"), fieldWithPath("page").description("요청 페이지"), fieldWithPath("size").description("요청 사이즈"), + fieldWithPath("totalPage").description("전체 페이지 수"), fieldWithPath("hasNext").description("다음 데이터 존재 여부") ) ) diff --git a/Common-Module/src/testFixtures/kotlin/com/bamyanggang/commonmodule/fixture/FixtureMonkeyUtils.kt b/Common-Module/src/testFixtures/kotlin/com/bamyanggang/commonmodule/fixture/FixtureMonkeyUtils.kt index 724caca1..f2941cb1 100644 --- a/Common-Module/src/testFixtures/kotlin/com/bamyanggang/commonmodule/fixture/FixtureMonkeyUtils.kt +++ b/Common-Module/src/testFixtures/kotlin/com/bamyanggang/commonmodule/fixture/FixtureMonkeyUtils.kt @@ -18,11 +18,6 @@ inline fun generateFixture(propertyBuilder: (ArbitraryBuilder) -> // 특정 속성 없는 임의 객체 생성 inline fun generateFixture(): T { - return generateFixture { it } -} - -// 기본 타입의 임의의 객체 -inline fun generateBasicTypeFixture(length: Int): T { return FixtureMonkey.builder() .defaultNotNull(true) .plugin(KotlinPlugin()) @@ -30,3 +25,25 @@ inline fun generateBasicTypeFixture(length: Int): T { .giveMeBuilder() .sample() } + +// 기본 타입의 임의의 객체 +inline fun generateBasicTypeFixture(length: Int): T { + return if (T::class == String::class) { + FixtureMonkey.builder() + .defaultNotNull(true) + .plugin(KotlinPlugin()) + .build() + .giveMeBuilder() + .sample() + .toString() + .take(length) as T + } else { + FixtureMonkey.builder() + .defaultNotNull(true) + .plugin(KotlinPlugin()) + .build() + .giveMeBuilder() + .sample() + } + +} diff --git a/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/common/pagination/SliceDomain.kt b/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/common/pagination/PageDomain.kt similarity index 75% rename from Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/common/pagination/SliceDomain.kt rename to Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/common/pagination/PageDomain.kt index 228634d0..bc40b388 100644 --- a/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/common/pagination/SliceDomain.kt +++ b/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/common/pagination/PageDomain.kt @@ -1,8 +1,9 @@ package com.bamyanggang.domainmodule.common.pagination -data class SliceDomain( +data class PageDomain( val content: List, val pageNumber: Int, val pageSize: Int, + val totalPage: Int, val hasNext: Boolean ) diff --git a/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/domain/jobDescription/aggregate/Apply.kt b/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/domain/jobDescription/aggregate/Apply.kt index 1add666c..a25429d8 100644 --- a/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/domain/jobDescription/aggregate/Apply.kt +++ b/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/domain/jobDescription/aggregate/Apply.kt @@ -8,7 +8,6 @@ import java.util.UUID data class Apply( override val id : UUID = UuidCreator.create(), - val writeStatus: WriteStatus = WriteStatus.WRITING, val createdAt: LocalDateTime, val updatedAt: LocalDateTime, val jobDescriptionId: UUID, @@ -27,14 +26,12 @@ data class Apply( fun toDomain( id: UUID, - writeStatus: WriteStatus, createdAt: LocalDateTime, updatedAt: LocalDateTime, jobDescriptionId: UUID ): Apply { return Apply( id = id, - writeStatus = writeStatus, createdAt = createdAt, updatedAt = updatedAt, jobDescriptionId = jobDescriptionId diff --git a/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/domain/jobDescription/aggregate/JobDescription.kt b/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/domain/jobDescription/aggregate/JobDescription.kt index a704785a..5ccafaf9 100644 --- a/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/domain/jobDescription/aggregate/JobDescription.kt +++ b/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/domain/jobDescription/aggregate/JobDescription.kt @@ -1,6 +1,7 @@ package com.bamyanggang.domainmodule.domain.jobDescription.aggregate import com.bamyanggang.domainmodule.common.entity.AggregateRoot +import com.bamyanggang.domainmodule.domain.jobDescription.enums.WriteStatus import com.example.uuid.UuidCreator import java.time.LocalDateTime import java.util.* @@ -9,6 +10,7 @@ data class JobDescription( override val id: UUID = UuidCreator.create(), val enterpriseName: String, val title: String, + val writeStatus: WriteStatus, val content: String, val link: String, val createdAt: LocalDateTime, @@ -30,6 +32,10 @@ data class JobDescription( return LocalDateTime.now().until(endedAt, java.time.temporal.ChronoUnit.DAYS).toInt() } + fun changeWriteStatus(writeStatus: WriteStatus): JobDescription { + return copy(writeStatus = writeStatus) + } + companion object { fun create( enterpriseName: String, @@ -43,6 +49,7 @@ data class JobDescription( return JobDescription( enterpriseName = enterpriseName, title = title, + writeStatus = WriteStatus.NOT_APPLIED, content = content, link = link, createdAt = LocalDateTime.now(), @@ -52,32 +59,6 @@ data class JobDescription( userId = userId ) } - - fun toDomain( - id: UUID, - enterpriseName: String, - title: String, - content: String, - link: String, - createdAt: LocalDateTime, - updatedAt: LocalDateTime, - startedAt: LocalDateTime, - endedAt: LocalDateTime, - userId: UUID, - ): JobDescription { - return JobDescription( - id = id, - enterpriseName = enterpriseName, - title = title, - content = content, - link = link, - createdAt = createdAt, - updatedAt = updatedAt, - startedAt = startedAt, - endedAt = endedAt, - userId = userId, - ) - } } } diff --git a/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/domain/jobDescription/repository/JobDescriptionRepository.kt b/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/domain/jobDescription/repository/JobDescriptionRepository.kt index abd3e400..1618231a 100644 --- a/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/domain/jobDescription/repository/JobDescriptionRepository.kt +++ b/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/domain/jobDescription/repository/JobDescriptionRepository.kt @@ -1,15 +1,20 @@ package com.bamyanggang.domainmodule.domain.jobDescription.repository -import com.bamyanggang.domainmodule.common.pagination.SliceDomain +import com.bamyanggang.domainmodule.common.pagination.PageDomain import com.bamyanggang.domainmodule.domain.jobDescription.aggregate.JobDescription +import com.bamyanggang.domainmodule.domain.jobDescription.enums.WriteStatus import java.util.* interface JobDescriptionRepository { fun save(jobDescription: JobDescription) - fun findAllByUserIdAndSortByCreatedAt(userId: UUID, page: Int, size: Int): SliceDomain + fun findById(jobDescriptionId: UUID): JobDescription - fun findAllByUserId(userId: UUID, page: Int, size: Int): SliceDomain + fun findAllByUserIdAndSortByCreatedAt(userId: UUID, page: Int, size: Int, writeStatus: WriteStatus?): PageDomain + + fun findAllByUserIdAndSortByEndedAt(userId: UUID, page: Int, size: Int, writeStatus: WriteStatus?): PageDomain + + fun findAllByUserId(userId: UUID, page: Int, size: Int, writeStatus: WriteStatus?): PageDomain } diff --git a/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/domain/jobDescription/service/JobDescriptionAppender.kt b/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/domain/jobDescription/service/JobDescriptionAppender.kt index b356fcc1..9cfae981 100644 --- a/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/domain/jobDescription/service/JobDescriptionAppender.kt +++ b/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/domain/jobDescription/service/JobDescriptionAppender.kt @@ -1,6 +1,7 @@ package com.bamyanggang.domainmodule.domain.jobDescription.service import com.bamyanggang.domainmodule.domain.jobDescription.aggregate.JobDescription +import com.bamyanggang.domainmodule.domain.jobDescription.enums.WriteStatus import com.bamyanggang.domainmodule.domain.jobDescription.repository.JobDescriptionRepository import org.springframework.stereotype.Service import java.time.LocalDateTime diff --git a/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/domain/jobDescription/service/JobDescriptionModifier.kt b/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/domain/jobDescription/service/JobDescriptionModifier.kt new file mode 100644 index 00000000..e874452d --- /dev/null +++ b/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/domain/jobDescription/service/JobDescriptionModifier.kt @@ -0,0 +1,17 @@ +package com.bamyanggang.domainmodule.domain.jobDescription.service + +import com.bamyanggang.domainmodule.domain.jobDescription.aggregate.JobDescription +import com.bamyanggang.domainmodule.domain.jobDescription.enums.WriteStatus +import com.bamyanggang.domainmodule.domain.jobDescription.repository.JobDescriptionRepository +import org.springframework.stereotype.Service + +@Service +class JobDescriptionModifier( + private val jobDescriptionRepository: JobDescriptionRepository +) { + + fun modifyWriteStatus(jobDescription: JobDescription, writeStatus: WriteStatus) { + jobDescription.changeWriteStatus(writeStatus).also { jobDescriptionRepository.save(it) } + } + +} diff --git a/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/domain/jobDescription/service/JobDescriptionReader.kt b/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/domain/jobDescription/service/JobDescriptionReader.kt index 01bb6dd6..dd350d54 100644 --- a/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/domain/jobDescription/service/JobDescriptionReader.kt +++ b/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/domain/jobDescription/service/JobDescriptionReader.kt @@ -1,8 +1,9 @@ package com.bamyanggang.domainmodule.domain.jobDescription.service -import com.bamyanggang.domainmodule.common.pagination.SliceDomain +import com.bamyanggang.domainmodule.common.pagination.PageDomain import com.bamyanggang.domainmodule.domain.jobDescription.aggregate.JobDescription import com.bamyanggang.domainmodule.domain.jobDescription.enums.SortType +import com.bamyanggang.domainmodule.domain.jobDescription.enums.WriteStatus import com.bamyanggang.domainmodule.domain.jobDescription.repository.JobDescriptionRepository import org.springframework.stereotype.Service import java.util.* @@ -14,13 +15,16 @@ class JobDescriptionReader( /** * TODO: 마감순 필터링 추가 */ - fun readJobDescriptionByUserIdAndSortType(userId: UUID, page: Int, size: Int, sortType: SortType?): SliceDomain { + fun readJobDescriptionByUserIdAndSortType(userId: UUID, page: Int, size: Int, sortType: SortType?, writeStatus: WriteStatus?): PageDomain { return when(sortType) { - SortType.CREATED -> jobDescriptionRepository.findAllByUserIdAndSortByCreatedAt(userId, page, size) -// SortType.ENDED -> jobDescriptionRepository.findAllByUserIdWithApply(userId, pageable) - else -> jobDescriptionRepository.findAllByUserId(userId, page, size) + SortType.CREATED -> jobDescriptionRepository.findAllByUserIdAndSortByCreatedAt(userId, page, size, writeStatus) + SortType.ENDED -> jobDescriptionRepository.findAllByUserIdAndSortByEndedAt(userId, page, size, writeStatus) + else -> jobDescriptionRepository.findAllByUserId(userId, page, size, writeStatus) } } + fun readJobDescriptionById(jobDescriptionId: UUID): JobDescription { + return jobDescriptionRepository.findById(jobDescriptionId) + } } diff --git a/Domain-Module/src/test/kotlin/com/bamyanggang/domainmodule/jobDescription/aggregate/ApplyTest.kt b/Domain-Module/src/test/kotlin/com/bamyanggang/domainmodule/jobDescription/aggregate/ApplyTest.kt index 0dcb7aa6..4c250c8e 100644 --- a/Domain-Module/src/test/kotlin/com/bamyanggang/domainmodule/jobDescription/aggregate/ApplyTest.kt +++ b/Domain-Module/src/test/kotlin/com/bamyanggang/domainmodule/jobDescription/aggregate/ApplyTest.kt @@ -17,7 +17,6 @@ ApplyTest : FunSpec({ val apply = Apply.create(jobDescriptionId) apply.jobDescriptionId shouldBe jobDescriptionId - apply.writeStatus shouldBe WriteStatus.WRITING } }) diff --git a/Infrastructure-Module/persistence/src/main/java/com/bamyanggang/persistence/jobDescription/JobDescriptionRepositoryImpl.java b/Infrastructure-Module/persistence/src/main/java/com/bamyanggang/persistence/jobDescription/JobDescriptionRepositoryImpl.java index bd54c1d1..a1355c6d 100644 --- a/Infrastructure-Module/persistence/src/main/java/com/bamyanggang/persistence/jobDescription/JobDescriptionRepositoryImpl.java +++ b/Infrastructure-Module/persistence/src/main/java/com/bamyanggang/persistence/jobDescription/JobDescriptionRepositoryImpl.java @@ -1,15 +1,20 @@ package com.bamyanggang.persistence.jobDescription; -import com.bamyanggang.domainmodule.common.pagination.SliceDomain; +import com.bamyanggang.domainmodule.common.pagination.PageDomain; import com.bamyanggang.domainmodule.domain.jobDescription.aggregate.JobDescription; +import com.bamyanggang.domainmodule.domain.jobDescription.enums.WriteStatus; import com.bamyanggang.domainmodule.domain.jobDescription.repository.JobDescriptionRepository; +import com.bamyanggang.persistence.common.exception.PersistenceException; import com.bamyanggang.persistence.jobDescription.jpa.entity.JobDescriptionJpaEntity; import com.bamyanggang.persistence.jobDescription.jpa.repository.JobDescriptionJpaRepository; import com.bamyanggang.persistence.jobDescription.mapper.JobDescriptionMapper; +import java.time.LocalDateTime; import java.util.UUID; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Slice; +import org.springframework.data.domain.Sort; import org.springframework.stereotype.Repository; @Repository @@ -24,33 +29,38 @@ public void save(JobDescription jobDescription) { jobDescriptionJpaRepository.save(jobDescriptionJpaEntity); } + public JobDescription findById(UUID jobDescriptionId) { + return jobDescriptionJpaRepository.findById(jobDescriptionId) + .map(jobDescriptionMapper::toDomainEntity) + .orElseThrow(() -> new PersistenceException.NotFound()); + } + @Override - public SliceDomain findAllByUserIdAndSortByCreatedAt(UUID userId, int page, int size) { - Pageable pageable = Pageable.ofSize(size).withPage(page); - Slice jobDescriptionJpaEntitySlice = jobDescriptionJpaRepository.findAllByUserIdOrderByCreatedAtDesc(userId, pageable); - Slice jobDescriptionSlice = jobDescriptionJpaEntitySlice.map(jobDescriptionMapper::toDomainEntity); - return new SliceDomain<>(jobDescriptionSlice.getContent(), jobDescriptionSlice.getNumber(), jobDescriptionSlice.getSize(), jobDescriptionSlice.hasNext()); + public PageDomain findAllByUserIdAndSortByCreatedAt(UUID userId, int page, int size, WriteStatus writeStatus) { + Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Order.desc("createdAt"))); + Page jobDescriptionJpaEntities = jobDescriptionJpaRepository.findAllByUserIdAndWriteStatus(userId, writeStatus, pageable); + Page jobDescriptionSlice = jobDescriptionJpaEntities.map(jobDescriptionMapper::toDomainEntity); + return new PageDomain<>(jobDescriptionSlice.getContent(), jobDescriptionSlice.getNumber(), jobDescriptionSlice.getSize() + ,jobDescriptionSlice.getTotalPages(), jobDescriptionSlice.hasNext()); } @Override - public SliceDomain findAllByUserId(UUID userId, int page, int size) { - Pageable pageable = Pageable.ofSize(size).withPage(page); - Slice jobDescriptionJpaEntitySlice = jobDescriptionJpaRepository.findAllByUserIdOrderByCreatedAtDesc(userId, pageable); - Slice jobDescriptionSlice = jobDescriptionJpaEntitySlice.map(jobDescriptionMapper::toDomainEntity); - return new SliceDomain<>(jobDescriptionSlice.getContent(), jobDescriptionSlice.getNumber(), jobDescriptionSlice.getSize(), jobDescriptionSlice.hasNext()); + public PageDomain findAllByUserId(UUID userId, int page, int size, WriteStatus writeStatus) { + Pageable pageable = PageRequest.of(page, size); + Page jobDescriptionJpaEntities = jobDescriptionJpaRepository.findAllByUserIdAndWriteStatus(userId, writeStatus, pageable); + Page jobDescriptionSlice = jobDescriptionJpaEntities.map(jobDescriptionMapper::toDomainEntity); + return new PageDomain<>(jobDescriptionSlice.getContent(), jobDescriptionSlice.getNumber(), jobDescriptionSlice.getSize() + ,jobDescriptionSlice.getTotalPages(), jobDescriptionSlice.hasNext()); } -// @Override -// public Slice findAllByUserIdAndSortByCreatedAt(UUID userId, Integer page, Integer size) { -// Pageable pageable = Pageable.ofSize(size).withPage(page); -// Slice jobDescriptionJpaEntitySlice = jobDescriptionJpaRepository.findAllByUserIdOrderByCreatedAtDesc(userId, pageable); -// return jobDescriptionJpaEntitySlice.map(jobDescriptionMapper::toDomainEntity); -// } -// -// @Override -// public Slice findAllByUserIdAndSortType(UUID userId, Pageable pageable) { -// Slice jobDescriptionJpaEntitySlice = jobDescriptionJpaRepository.findAllByUserId(userId, pageable); -// return jobDescriptionJpaEntitySlice.map(jobDescriptionMapper::toDomainEntity); -// } + @Override + public PageDomain findAllByUserIdAndSortByEndedAt(UUID userId, int page, int size, WriteStatus writeStatus) { + Pageable pageable = PageRequest.of(page, size); + LocalDateTime now = LocalDateTime.now(); + Page jobDescriptionJpaEntities = jobDescriptionJpaRepository.findAllByUserIdAndWriteStatusAndTime(userId, writeStatus, now, pageable); + Page jobDescriptionSlice = jobDescriptionJpaEntities.map(jobDescriptionMapper::toDomainEntity); + return new PageDomain<>(jobDescriptionSlice.getContent(), jobDescriptionSlice.getNumber(), jobDescriptionSlice.getSize() + ,jobDescriptionSlice.getTotalPages(), jobDescriptionSlice.hasNext()); + } } diff --git a/Infrastructure-Module/persistence/src/main/java/com/bamyanggang/persistence/jobDescription/jpa/entity/ApplyJpaEntity.java b/Infrastructure-Module/persistence/src/main/java/com/bamyanggang/persistence/jobDescription/jpa/entity/ApplyJpaEntity.java index f093ab01..7865162a 100644 --- a/Infrastructure-Module/persistence/src/main/java/com/bamyanggang/persistence/jobDescription/jpa/entity/ApplyJpaEntity.java +++ b/Infrastructure-Module/persistence/src/main/java/com/bamyanggang/persistence/jobDescription/jpa/entity/ApplyJpaEntity.java @@ -26,9 +26,6 @@ public class ApplyJpaEntity { @Convert(converter = UUIDBinaryConverter.class) private UUID applyId; - @Enumerated(EnumType.STRING) - private WriteStatus writeStatus; - private LocalDateTime createdAt; private LocalDateTime updatedAt; @@ -37,9 +34,8 @@ public class ApplyJpaEntity { @Convert(converter = UUIDBinaryConverter.class) private UUID jobDescriptionId; - public ApplyJpaEntity(UUID applyId, WriteStatus writeStatus, LocalDateTime createdAt, LocalDateTime updatedAt, UUID jobDescriptionId) { + public ApplyJpaEntity(UUID applyId, LocalDateTime createdAt, LocalDateTime updatedAt, UUID jobDescriptionId) { this.applyId = applyId; - this.writeStatus = writeStatus; this.createdAt = createdAt; this.updatedAt = updatedAt; this.jobDescriptionId = jobDescriptionId; diff --git a/Infrastructure-Module/persistence/src/main/java/com/bamyanggang/persistence/jobDescription/jpa/entity/JobDescriptionJpaEntity.java b/Infrastructure-Module/persistence/src/main/java/com/bamyanggang/persistence/jobDescription/jpa/entity/JobDescriptionJpaEntity.java index 8d70eaae..e8b9e65d 100644 --- a/Infrastructure-Module/persistence/src/main/java/com/bamyanggang/persistence/jobDescription/jpa/entity/JobDescriptionJpaEntity.java +++ b/Infrastructure-Module/persistence/src/main/java/com/bamyanggang/persistence/jobDescription/jpa/entity/JobDescriptionJpaEntity.java @@ -1,9 +1,12 @@ package com.bamyanggang.persistence.jobDescription.jpa.entity; +import com.bamyanggang.domainmodule.domain.jobDescription.enums.WriteStatus; import com.bamyanggang.persistence.common.UUIDBinaryConverter; import jakarta.persistence.Column; import jakarta.persistence.Convert; import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; import jakarta.persistence.Id; import jakarta.persistence.Table; import java.time.LocalDateTime; @@ -27,6 +30,10 @@ public class JobDescriptionJpaEntity { private String title; + @Column(name = "write_status", columnDefinition = "VARCHAR(255)") + @Enumerated(EnumType.STRING) + private WriteStatus writeStatus; + @Column(columnDefinition = "VARCHAR(6000)") private String content; @@ -45,12 +52,13 @@ public class JobDescriptionJpaEntity { private UUID userId; - public JobDescriptionJpaEntity(UUID jobDescriptionId, String enterpriseName, String title, String content, - String link, LocalDateTime createdAt, LocalDateTime updatedAt, LocalDateTime startedAt, - LocalDateTime endedAt, UUID userId) { + public JobDescriptionJpaEntity(UUID jobDescriptionId, String enterpriseName, String title, WriteStatus writeStatus, + String content, String link, LocalDateTime createdAt, LocalDateTime updatedAt, + LocalDateTime startedAt, LocalDateTime endedAt, UUID userId) { this.jobDescriptionId = jobDescriptionId; this.enterpriseName = enterpriseName; this.title = title; + this.writeStatus = writeStatus; this.content = content; this.link = link; this.createdAt = createdAt; diff --git a/Infrastructure-Module/persistence/src/main/java/com/bamyanggang/persistence/jobDescription/jpa/repository/JobDescriptionJpaRepository.java b/Infrastructure-Module/persistence/src/main/java/com/bamyanggang/persistence/jobDescription/jpa/repository/JobDescriptionJpaRepository.java index 9949b75f..10b8ee7a 100644 --- a/Infrastructure-Module/persistence/src/main/java/com/bamyanggang/persistence/jobDescription/jpa/repository/JobDescriptionJpaRepository.java +++ b/Infrastructure-Module/persistence/src/main/java/com/bamyanggang/persistence/jobDescription/jpa/repository/JobDescriptionJpaRepository.java @@ -1,16 +1,22 @@ package com.bamyanggang.persistence.jobDescription.jpa.repository; +import com.bamyanggang.domainmodule.domain.jobDescription.enums.WriteStatus; import com.bamyanggang.persistence.jobDescription.jpa.entity.JobDescriptionJpaEntity; +import java.time.LocalDateTime; import java.util.UUID; +import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Slice; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; public interface JobDescriptionJpaRepository extends JpaRepository { - Slice findAllByUserId(UUID userId, Pageable pageable); - - Slice findAllByUserIdOrderByCreatedAtDesc(UUID userId, Pageable pageable); + @Query("SELECT j FROM JobDescriptionJpaEntity j WHERE j.userId = :userId AND (:writeStatus is null or j.writeStatus = :writeStatus)") + Page findAllByUserIdAndWriteStatus(@Param("userId") UUID userId, @Param("writeStatus") WriteStatus writeStatus, @Param("date") Pageable pageable); + @Query("SELECT j FROM JobDescriptionJpaEntity j WHERE j.userId = :userId AND (:writeStatus is null or j.writeStatus = :writeStatus) AND j.endedAt > :date ORDER BY j.endedAt ASC") + Page findAllByUserIdAndWriteStatusAndTime(@Param("userId") UUID userId, @Param("writeStatus") WriteStatus writeStatus, + @Param("date") LocalDateTime now, Pageable pageable); } diff --git a/Infrastructure-Module/persistence/src/main/java/com/bamyanggang/persistence/jobDescription/mapper/JobDescriptionMapper.java b/Infrastructure-Module/persistence/src/main/java/com/bamyanggang/persistence/jobDescription/mapper/JobDescriptionMapper.java index 3e464478..87699c01 100644 --- a/Infrastructure-Module/persistence/src/main/java/com/bamyanggang/persistence/jobDescription/mapper/JobDescriptionMapper.java +++ b/Infrastructure-Module/persistence/src/main/java/com/bamyanggang/persistence/jobDescription/mapper/JobDescriptionMapper.java @@ -16,6 +16,7 @@ public JobDescriptionJpaEntity toJpaEntity(JobDescription jobDescription) { jobDescription.getId(), jobDescription.getEnterpriseName(), jobDescription.getTitle(), + jobDescription.getWriteStatus(), jobDescription.getContent(), jobDescription.getLink(), jobDescription.getCreatedAt(), @@ -28,10 +29,11 @@ public JobDescriptionJpaEntity toJpaEntity(JobDescription jobDescription) { public JobDescription toDomainEntity(JobDescriptionJpaEntity jobDescriptionJpaEntity) { - return JobDescription.Companion.toDomain( + return new JobDescription( jobDescriptionJpaEntity.getJobDescriptionId(), jobDescriptionJpaEntity.getEnterpriseName(), jobDescriptionJpaEntity.getTitle(), + jobDescriptionJpaEntity.getWriteStatus(), jobDescriptionJpaEntity.getContent(), jobDescriptionJpaEntity.getLink(), jobDescriptionJpaEntity.getCreatedAt(), @@ -40,12 +42,12 @@ public JobDescription toDomainEntity(JobDescriptionJpaEntity jobDescriptionJpaEn jobDescriptionJpaEntity.getEndedAt(), jobDescriptionJpaEntity.getUserId() ); + } public ApplyJpaEntity toApplyJpaEntity(Apply apply) { return new ApplyJpaEntity( apply.getId(), - apply.getWriteStatus(), apply.getCreatedAt(), apply.getUpdatedAt(), apply.getJobDescriptionId() @@ -55,7 +57,6 @@ public ApplyJpaEntity toApplyJpaEntity(Apply apply) { public Apply toApplyDomainEntity(ApplyJpaEntity applyJpaEntity) { return Apply.Companion.toDomain( applyJpaEntity.getApplyId(), - applyJpaEntity.getWriteStatus(), applyJpaEntity.getCreatedAt(), applyJpaEntity.getUpdatedAt(), applyJpaEntity.getJobDescriptionId()