Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: JD 등록, 자소서 등록 API 구현(#56) #60

Merged
merged 23 commits into from
May 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
c9229ac
feat : JD 등록 API 스펙 정의(#56)
isprogrammingfun May 16, 2024
18070d4
feat : JD 등록 API 로직 구현(#56)
isprogrammingfun May 16, 2024
60d8749
test : JD 등록 API 관련 테스트 코드 작성, 문서 반영(#56)
isprogrammingfun May 16, 2024
de2b606
test : JD 등록 domain 계층 테스트 코드 작성(#56)
isprogrammingfun May 16, 2024
a81cd6e
test : JD 등록 application 계층 테스트 코드 작성(#56)
isprogrammingfun May 16, 2024
bed84c9
refactor : JD 등록 API 응답값 반환하도록 수정(#56)
isprogrammingfun May 16, 2024
4d9b884
test : JD 등록 API 수정에 의한 테스트 코드 수정 및 명세 반영, User API 명세 snippets 에러 수정…
isprogrammingfun May 16, 2024
047dfc0
refactor : JD와 Apply 관계 수정(#56)
isprogrammingfun May 17, 2024
c5aca3b
feat : 자소서 등록 API 스펙 정의(#56)
isprogrammingfun May 17, 2024
e64536c
feat : 자소서 등록 API 로직 구현(#56)
isprogrammingfun May 17, 2024
bc9b939
feat : UUID-BINARY 변환 Converter 생성 후, 적용(#56)
isprogrammingfun May 17, 2024
e6dac87
refactor : 500에러 발생 시, 로그 출력하도록 수정(#56)
isprogrammingfun May 17, 2024
1ccf561
test : 자소서 등록 API 테스트 코드 작성, 문서 반영(#56)
isprogrammingfun May 17, 2024
fde65f3
test : 자소서 등록 API domain, application 계층 테스트 코드 작성(#56)
isprogrammingfun May 17, 2024
4852fb5
fix : git 충돌 해결(#56)
isprogrammingfun May 17, 2024
eaa637e
chore: 개행 추가(#56)
isprogrammingfun May 17, 2024
a5d9a52
test : null 값 반환 수정(#56)
isprogrammingfun May 17, 2024
e2884d0
test : 헤더 정보 추가(#56)
isprogrammingfun May 17, 2024
e7a3991
test : UUID 생성 방식 수정(#56)
isprogrammingfun May 17, 2024
a9d27d3
fix : 깃 충돌 해결(#56)
isprogrammingfun May 17, 2024
d0540e3
test : ApplyContent 테스트 오류 수정(#56)
isprogrammingfun May 17, 2024
7ebfa26
chore : JobDescriptionCreateServiceTest 주석 처리, persistence 모듈 의존성 수정(…
isprogrammingfun May 17, 2024
f252cb4
test : UUID 생성 null 방지(#56)
isprogrammingfun May 17, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/CI-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,3 @@ jobs:
- name: Build With Gradle
run: |
./gradlew build
./gradlew bootJar
37 changes: 37 additions & 0 deletions Api-Module/src/docs/asciidoc/JobDescription.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[[Job-Description-API]]
== Job-Description-API

[[CREATE-JD]]
=== JD 등록

operation::JobDescriptionControllerTest/createJobDescription[snippets='http-request,request-headers,request-fields,http-response,response-fields']

[[CREATE-JD-EXCEPTION]]
==== JD 등록 시 예외 (빈 값, 또는 NULL이 들어올 경우)

operation::JobDescriptionControllerTest/createJobDescriptionWithEmptyValue[snippets='http-request,request-headers,http-response']

[[CREATE-JD-EXCEPTION-2]]
==== JD 등록 시 예외 (시작일이 종료일보다 늦을 경우)

operation::JobDescriptionControllerTest/createJobDescriptionWithInvalidDate[snippets='http-request,request-headers,http-response']

[[CREATE-APPLY]]
=== JD 자소서 등록

operation::JobDescriptionControllerTest/createApply[snippets='http-request,request-headers,request-fields,http-response']

[[CREATE-APPLY-EXCEPTION]]
==== JD 자소서 등록 시 예외 (제목이 비어있는 경우)

operation::JobDescriptionControllerTest/createApplyWithEmptyTitle[snippets='http-request,request-headers,http-response']

[[CREATE-APPLY-EXCEPTION-2]]
==== JD 자소서 등록 시 예외 (내용이 비어있는 경우)

operation::JobDescriptionControllerTest/createApplyWithEmptyContent[snippets='http-request,request-headers,http-response']





2 changes: 1 addition & 1 deletion Api-Module/src/docs/asciidoc/User.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ operation::UserControllerTest/register[snippets='http-request,request-fields,htt
[[GetProfileImageUrl]]
=== 기본 제공 프로필 이미지 URL 조회 API

operation::UserControllerTest/getProfileImages[snippets='http-request,snippets='http-response,response-fields']
operation::UserControllerTest/getProfileImages[snippets='http-request,http-response,response-fields']

[[GetUserInfo]]
=== 사용자 정보 조회 API
Expand Down
1 change: 1 addition & 0 deletions Api-Module/src/docs/asciidoc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ include::Auth.adoc[]
include::User.adoc[]
include::StrongPoint.adoc[]
include::Tag.adoc[]
include::JobDescription.adoc[]


Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.bamyanggang.apimodule.domain.jobDescription.application.dto

class CreateApply {

data class Request(
val title: String,
val contents : List<CreateApplyContent>
)

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.bamyanggang.apimodule.domain.jobDescription.application.dto

data class CreateApplyContent (
val question: String,
val answer: String
)
Comment on lines +3 to +6

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CreateApply랑 별도 파일로 작업하시는 이유가 있나요?!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분은 저 또한 분리할 이유가 없다 생각이 들어 리펙터링 할 때 로직을 합치려고 했습니다! 좋은 리뷰 감사합니다:)


Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.bamyanggang.apimodule.domain.jobDescription.application.dto

import java.time.LocalDateTime
import java.util.UUID

class CreateJobDescription {

data class Request(
val enterpriseName: String,
val title: String,
val content: String,
val link: String,
val startedAt: LocalDateTime,
val endedAt: LocalDateTime
)

data class Response(
val jobDescriptionId: UUID
)

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.bamyanggang.apimodule.domain.jobDescription.application.service

import com.bamyanggang.apimodule.domain.jobDescription.application.dto.CreateApply
import com.bamyanggang.domainmodule.domain.jobDescription.service.ApplyAppender
import com.bamyanggang.domainmodule.domain.jobDescription.service.ApplyContentAppender
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.util.*

@Service
class ApplyCreateService(
private val applyAppender: ApplyAppender,
private val applyContentAppender: ApplyContentAppender
) {
@Transactional
fun createApply(request: CreateApply.Request, jobDescriptionId: UUID) {
applyAppender.appendApply(
jobDescriptionId = jobDescriptionId,
title = request.title
).also { apply ->
request.contents.forEach { content ->
applyContentAppender.appendApplyContent(
applyId = apply.id,
question = content.question,
answer = content.answer
)
}
Comment on lines +21 to +27

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bulk 작업 처리 되면 좋을 것 같아요

}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.bamyanggang.apimodule.domain.jobDescription.application.service

import com.bamyanggang.apimodule.common.getAuthenticationPrincipal
import com.bamyanggang.apimodule.domain.jobDescription.application.dto.CreateJobDescription
import com.bamyanggang.domainmodule.domain.jobDescription.service.JobDescriptionAppender
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

@Service
class JobDescriptionCreateService(
private val jobDescriptionAppender: JobDescriptionAppender
) {

@Transactional
fun createJobDescription(request: CreateJobDescription.Request): CreateJobDescription.Response {
getAuthenticationPrincipal().run {
jobDescriptionAppender.appendJobDescription(
enterpriseName = request.enterpriseName,
title = request.title,
content = request.content,
link = request.link,
startedAt = request.startedAt,
endedAt = request.endedAt,
userId = this
)
}.also { return CreateJobDescription.Response(jobDescriptionId = it.id) }
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.bamyanggang.apimodule.domain.jobDescription.presentation

object JobDescriptionApi {
const val BASE_URL = "/api/job-description"
const val APPLY = "${BASE_URL}/apply/{jobDescriptionId}"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.bamyanggang.apimodule.domain.jobDescription.presentation

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.service.ApplyCreateService
import com.bamyanggang.apimodule.domain.jobDescription.application.service.JobDescriptionCreateService
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RestController
import java.util.UUID

@RestController
class JobDescriptionController(
private val jobDescriptionCreateService: JobDescriptionCreateService,
private val applyCreateService: ApplyCreateService
) {

@PostMapping(JobDescriptionApi.BASE_URL)
fun createJobDescription(
@RequestBody request: CreateJobDescription.Request
): CreateJobDescription.Response = jobDescriptionCreateService.createJobDescription(request)

@PostMapping(JobDescriptionApi.APPLY)
fun createApply(
@PathVariable("jobDescriptionId") jobDescriptionId: UUID,
@RequestBody request: CreateApply.Request
) = applyCreateService.createApply(request, jobDescriptionId)

}
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ private val jwtEntryPoint: JwtEntryPoint) {
}
return httpSecurity.build()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.bamyanggang.apimodule.domain.jobDescription.application

import com.bamyanggang.apimodule.domain.jobDescription.application.dto.CreateApply
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.service.ApplyAppender
import com.bamyanggang.domainmodule.domain.jobDescription.service.ApplyContentAppender
import io.kotest.core.spec.style.BehaviorSpec
import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
import java.util.*


class ApplyCreateServiceTest : BehaviorSpec({
val applyAppender = mockk<ApplyAppender>()
val applyContentAppender = mockk<ApplyContentAppender>()
val applyCreateService = ApplyCreateService(applyAppender, applyContentAppender)

given("ApplyCreateService.createApply") {
`when`("request가 주어지면") {
val request: CreateApply.Request = generateFixture()
val jobDescriptionId: UUID = generateFixture()
val apply: Apply = generateFixture()
every { applyAppender.appendApply(any(), any()) } returns apply
every { applyContentAppender.appendApplyContent(any(), any(), any()) } returns Unit

applyCreateService.createApply(request, jobDescriptionId)

then("appendApply가 호출된다.") {
verify { applyAppender.appendApply( request.title,jobDescriptionId) }
}

then("appendApplyContent가 호출된다.") {
request.contents.forEach { content ->
verify { applyContentAppender.appendApplyContent(apply.id, content.question, content.answer) }
}
}
}
}
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.bamyanggang.apimodule.domain.jobDescription.application

import com.bamyanggang.apimodule.domain.jobDescription.application.dto.CreateJobDescription
import com.bamyanggang.apimodule.domain.jobDescription.application.service.JobDescriptionCreateService
import com.bamyanggang.commonmodule.fixture.generateFixture
import com.bamyanggang.domainmodule.domain.jobDescription.service.JobDescriptionAppender
import io.kotest.core.spec.style.BehaviorSpec
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkStatic
import org.springframework.security.core.Authentication
import org.springframework.security.core.context.SecurityContext
import org.springframework.security.core.context.SecurityContextHolder
import io.mockk.verify
import java.time.LocalDateTime
import java.util.UUID

/**
* Todo: securityContext를 어떻게 처리하지?
*/
//class JobDescriptionCreateServiceTest : BehaviorSpec({
// val mockJobDescriptionAppender = mockk<JobDescriptionAppender>(relaxed = true)
// val service = JobDescriptionCreateService(mockJobDescriptionAppender)
// mockkStatic(SecurityContextHolder::class)
// val securityContext = mockk<SecurityContext>()
// val authentication = mockk<Authentication>()
//
// given("JobDescriptionCreateService.createJobDescription") {
// val request: CreateJobDescription.Request = generateFixture {
// it.set("enterpriseName", "기업 이름")
// it.set("title", "직무 공고 제목")
// it.set("content", "직무 공고 내용")
// it.set("link", "직무 공고 링크")
// it.set("startedAt", LocalDateTime.now())
// it.set("endedAt", LocalDateTime.now())
// }
// val userId : UUID = generateFixture()
// every { SecurityContextHolder.getContext() } returns securityContext
// every { securityContext.authentication } returns authentication
// every { authentication.principal } returns userId
//
// `when`("request가 주어지면") {
// service.createJobDescription(request)
//
// then("appendJobDescription이 호출된다.") {
// verify {
// mockJobDescriptionAppender.appendJobDescription(
// enterpriseName = request.enterpriseName,
// title = request.title,
// content = request.content,
// link = request.link,
// startedAt = request.startedAt,
// endedAt = request.endedAt,
// userId = userId
// )
// }
// }
// }
// }
//})
Loading
Loading