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

[Refactor/#143] 어드민 API 요구사항 반영 및 오류 수정 #144

Merged
merged 14 commits into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,17 @@ class ProblemDao(
.let { ProblemIdsRecord(it) }
}

fun insertProblems(command: InsertProblemsCommand) {
dslContext.insertInto(Problem.PROBLEM)
.set(Problem.PROBLEM.ARTICLE_ID, command.articleId)
.set(Problem.PROBLEM.CREATOR_ID, command.createrId)
.set(Problem.PROBLEM.TITLE, command.title)
.set(Problem.PROBLEM.CONTENTS, JSON.valueOf(contentsJsonMapper.toJson(command.contents)))
.set(Problem.PROBLEM.ANSWER, command.answer)
.set(Problem.PROBLEM.EXPLANATION, command.explanation)
.execute()
fun insertProblems(command: List<InsertProblemsCommand>) {
dslContext.batch(
command.map {
dslContext.insertInto(Problem.PROBLEM)
.set(Problem.PROBLEM.ARTICLE_ID, it.articleId)
.set(Problem.PROBLEM.CREATOR_ID, it.createrId)
.set(Problem.PROBLEM.TITLE, it.title)
.set(Problem.PROBLEM.CONTENTS, JSON.valueOf(contentsJsonMapper.toJson(it.contents)))
.set(Problem.PROBLEM.ANSWER, it.answer)
.set(Problem.PROBLEM.EXPLANATION, it.explanation)
}
).execute()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ data class AddArticleUseCaseIn(
val title: String,
val category: String,
/** Article IFO */
val contentType: String,
val contentSource: String,
val problemData: ProblemDetail
val problems: List<ProblemDetail>

)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,36 @@ package com.few.api.domain.admin.document.usecase

import com.few.api.domain.admin.document.dto.AddArticleUseCaseIn
import com.few.api.domain.admin.document.dto.AddArticleUseCaseOut
import com.few.api.domain.admin.document.service.GetUrlService
import com.few.api.domain.admin.document.service.dto.GetUrlQuery
import com.few.api.domain.admin.document.utils.ObjectPathGenerator
import com.few.api.repo.dao.article.ArticleDao
import com.few.api.repo.dao.article.command.InsertFullArticleRecordCommand
import com.few.api.repo.dao.document.DocumentDao
import com.few.api.repo.dao.document.command.InsertDocumentIfoCommand
import com.few.api.repo.dao.member.MemberDao
import com.few.api.repo.dao.member.query.SelectMemberByEmailQuery
import com.few.api.repo.dao.problem.ProblemDao
import com.few.api.repo.dao.problem.command.InsertProblemsCommand
import com.few.api.repo.dao.problem.support.Content
import com.few.api.repo.dao.problem.support.Contents
import com.few.data.common.code.CategoryType
import com.few.storage.document.service.ConvertDocumentService
import com.few.storage.document.service.PutDocumentService
import org.springframework.stereotype.Component
import org.springframework.transaction.annotation.Transactional
import java.io.File
import java.util.*

@Component
class AddArticleUseCase(
private val articleDao: ArticleDao,
private val memberDao: MemberDao,
private val problemDao: ProblemDao
private val problemDao: ProblemDao,
private val documentDao: DocumentDao,
private val convertDocumentService: ConvertDocumentService,
private val putDocumentService: PutDocumentService,
private val getUrlService: GetUrlService
Comment on lines -21 to +34
Copy link
Member

Choose a reason for hiding this comment

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

서비스는 도메인 별로 하나만 두는걸로 변경 필요합니다(저희끼리 정했던 부분)
추가로 유즈케이스가 아티클쪽인데 member, problem은 DAO 바로 사용하시나요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

여기는 어드민으라서 바로 dao로 사용했습니다!

) {
@Transactional
fun execute(useCaseIn: AddArticleUseCaseIn): AddArticleUseCaseOut {
Expand All @@ -27,32 +40,78 @@ class AddArticleUseCase(
memberDao.selectMemberByEmail(it)
} ?: throw RuntimeException("writer not found")

/**
* - content type: "md"
* put origin document to object storage
* and convert to html source
* - content type: "html"
* save html source
*/
val htmlSource = when {
useCaseIn.contentType.lowercase(Locale.getDefault()) == "md" -> {
val mdSource = useCaseIn.contentSource
val htmlSource = convertDocumentService.mdToHtml(useCaseIn.contentSource)

val document = runCatching {
File.createTempFile("temp", ".md")
}.onSuccess {
it.writeText(mdSource)
}.getOrThrow()
val documentName = ObjectPathGenerator.documentPath("md")

putDocumentService.execute(documentName, document)?.let { res ->
val source = res.`object`
GetUrlQuery(source).let { query ->
getUrlService.execute(query)
}.let { url ->
InsertDocumentIfoCommand(
path = documentName,
url = url
).let { command ->
documentDao.insertDocumentIfo(command)
}
url
}
} ?: throw IllegalStateException("Failed to put document")

htmlSource
}
useCaseIn.contentType.lowercase(Locale.getDefault()) == "html" -> {
useCaseIn.contentSource
}
else -> {
throw IllegalArgumentException("content type is not supported")
}
}

/** insert article */
val articleMstId = InsertFullArticleRecordCommand(
writerId = writerId.memberId,
mainImageURL = useCaseIn.articleImageUrl,
title = useCaseIn.title,
category = CategoryType.convertToCode(useCaseIn.category),
content = useCaseIn.contentSource
content = htmlSource
).let { articleDao.insertFullArticleRecord(it) }

/** insert problems */
InsertProblemsCommand(
articleId = articleMstId,
createrId = 0L, // todo fix
title = useCaseIn.title,
contents = Contents(
useCaseIn.problemData.contents.map {
Content(
it.number,
it.content
)
}
),
answer = useCaseIn.problemData.answer,
explanation = useCaseIn.problemData.explanation
).let {
problemDao.insertProblems(it)
useCaseIn.problems.stream().map { problemDatum ->
InsertProblemsCommand(
articleId = articleMstId,
createrId = 0L, // todo fix
title = problemDatum.title,
contents = Contents(
problemDatum.contents.map { detail ->
Content(
detail.number,
detail.content
)
}
),
answer = problemDatum.answer,
explanation = problemDatum.explanation
)
}.toList().let { commands ->
problemDao.insertProblems(commands)
}

return AddArticleUseCaseOut(articleMstId)
Expand Down
2 changes: 1 addition & 1 deletion api/src/main/kotlin/com/few/api/web/config/WebConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer

@Configuration
@EnableWebMvc
@EnableWebMvc // todo refactor
class WebConfig : WebMvcConfigurer {
override fun addCorsMappings(registry: CorsRegistry) {
registry.addMapping("/**")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,18 +57,21 @@ class AdminController(
articleImageUrl = request.articleImageUrl,
title = request.title,
category = request.category,
contentType = request.contentType,
contentSource = request.contentSource,
problemData = ProblemDetail(
title = request.problemData.title,
contents = request.problemData.contents.map {
ProblemContentDetail(
number = it.number,
content = it.content
)
},
answer = request.problemData.answer,
explanation = request.problemData.explanation
)
problems = request.problemData.map { datum ->
ProblemDetail(
title = datum.title,
contents = datum.contents.map { detail ->
ProblemContentDetail(
number = detail.number,
content = detail.content
)
},
answer = datum.answer,
explanation = datum.explanation
)
}.toList()
).let { useCaseIn ->
addArticleUseCase.execute(useCaseIn)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ data class AddArticleRequest(
@field:NotBlank(message = "{category.notblank}")
val category: String,
/** Article IFO */
@NotBlank(message = "{content.type.notblank}")
val contentType: String,
@field:NotBlank(message = "{content.source.notblank}")
val contentSource: String,
val problemData: ProblemDto
val problemData: List<ProblemDto>
)

data class ProblemDto(
Expand Down
2 changes: 1 addition & 1 deletion api/src/main/resources/ValidationMessages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ image.url.notblank=Image URL must be blank
title.notblank=Title must not be blank
category.notblank=Category must not be blank
content.source.notblank=Content must not be blank
content.type.notblank=Content Type must not be blank
problem.title.notblank=Problem Title must not be blank
problem.content.notblank=Problem Content must not be blank
problem.answer.notblank=Problem Answer must not be blank
Expand All @@ -14,4 +15,3 @@ workbook.description.notblank=Workbook Description must not be blank
min.day=The Day field must be greater than or equal to 1
min.id=The ID field must be greater than or equal to 1
min.problem.number=The Problem Number field must be greater than or equal to 1
max.day=The Day field must be less than or equal to 7
Original file line number Diff line number Diff line change
Expand Up @@ -137,17 +137,31 @@ class AdminControllerTest : ControllerTestSpec() {
URL("http://localhost:8080"),
"title",
CategoryType.fromCode(0)!!.name,
"contentSource",
ProblemDto(
"title",
listOf(
ProblemContentDto(1L, "content1"),
ProblemContentDto(2L, "content2"),
ProblemContentDto(3L, "content3"),
ProblemContentDto(4L, "content4")
"md",
"content source",
listOf(
ProblemDto(
"title1",
listOf(
ProblemContentDto(1L, "content1"),
ProblemContentDto(2L, "content2"),
ProblemContentDto(3L, "content3"),
ProblemContentDto(4L, "content4")
),
"1",
"explanation"
),
"1",
"explanation"
ProblemDto(
"title2",
listOf(
ProblemContentDto(1L, "content1"),
ProblemContentDto(2L, "content2"),
ProblemContentDto(3L, "content3"),
ProblemContentDto(4L, "content4")
),
"2",
"explanation"
)
)
)
val body = objectMapper.writeValueAsString(request)
Expand All @@ -159,17 +173,31 @@ class AdminControllerTest : ControllerTestSpec() {
URL("http://localhost:8080"),
"title",
CategoryType.fromCode(0)!!.name,
"contentSource",
ProblemDetail(
"title",
listOf(
ProblemContentDetail(1L, "content1"),
ProblemContentDetail(2L, "content2"),
ProblemContentDetail(3L, "content3"),
ProblemContentDetail(4L, "content4")
"md",
"content source",
listOf(
ProblemDetail(
"title1",
listOf(
ProblemContentDetail(1L, "content1"),
ProblemContentDetail(2L, "content2"),
ProblemContentDetail(3L, "content3"),
ProblemContentDetail(4L, "content4")
),
"1",
"explanation"
),
"1",
"explanation"
ProblemDetail(
"title2",
listOf(
ProblemContentDetail(1L, "content1"),
ProblemContentDetail(2L, "content2"),
ProblemContentDetail(3L, "content3"),
ProblemContentDetail(4L, "content4")
),
"2",
"explanation"
)
)
)
)
Expand Down
16 changes: 5 additions & 11 deletions data/src/main/kotlin/com/few/data/common/code/CategoryType.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,11 @@ package com.few.data.common.code
* @see com.few.batch.data.common.code.BatchCategoryType
*/
enum class CategoryType(val code: Byte, val displayName: String) {
POLITICS(0, "정치"),
ECONOMY(10, "경제"),
SOCIETY(20, "사회"),
CULTURE(30, "문화"),
LIFE(40, "생활"),
IT(50, "IT"),
SCIENCE(60, "과학"),
ENTERTAINMENTS(70, "엔터테인먼트"),
SPORTS(80, "스포츠"),
GLOBAL(90, "국제"),
ETC(100, "기타");
ECONOMY(0, "경제"),
IT(10, "IT"),
MARKETING(20, "마케팅"),
CULTURE(30, "교양"),
SCIENCE(40, "과학");

companion object {
fun fromCode(code: Byte): CategoryType? {
Expand Down
Loading
Loading