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/#93] MemberType 정의 및 구독시 멤버 저장 과정 추가 #103

Merged
merged 9 commits into from
Jun 24, 2024
3 changes: 3 additions & 0 deletions api-repo/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ sourceSets {
}

dependencies {
/** module */
api(project(":data"))

Comment on lines +25 to +27
Copy link
Member Author

Choose a reason for hiding this comment

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

api-repo 모듈에서 data 모듈 추가

/** spring starter */
api("org.springframework.boot:spring-boot-starter-data-jdbc")
implementation("com.mysql:mysql-connector-j")
Expand Down
29 changes: 29 additions & 0 deletions api-repo/src/main/kotlin/com/few/api/repo/dao/member/MemberDao.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package com.few.api.repo.dao.member

import com.few.api.repo.dao.member.command.InsertMemberCommand
import com.few.api.repo.dao.member.query.SelectMemberQuery
import com.few.api.repo.dao.member.query.SelectWriterQuery
import com.few.api.repo.dao.member.record.MemberRecord
import com.few.api.repo.dao.member.record.WriterRecord
import jooq.jooq_dsl.tables.Member
import org.jooq.DSLContext
Expand All @@ -27,4 +30,30 @@ class MemberDao(
.fetchOneInto(WriterRecord::class.java)
?: throw IllegalArgumentException("cannot find writer record by writerId: $writerId")
}

fun selectMember(query: SelectMemberQuery): MemberRecord {
hun-ca marked this conversation as resolved.
Show resolved Hide resolved
hun-ca marked this conversation as resolved.
Show resolved Hide resolved
val email = query.email

return dslContext.select(
Member.MEMBER.ID.`as`(MemberRecord::memberId.name),
DSL.jsonGetAttributeAsText(Member.MEMBER.DESCRIPTION, "name").`as`(MemberRecord::name.name),
DSL.jsonGetAttribute(Member.MEMBER.DESCRIPTION, "url").`as`(WriterRecord::url.name)
Copy link
Collaborator

Choose a reason for hiding this comment

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

추가로 일반 멤버에는 아마 name, url 키가 포함된 json이 아니라 {} 값만 들어갈 것 같아요!

Copy link
Member Author

Choose a reason for hiding this comment

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

일반 멤버는 디스크립트션이 없다?

)
.from(Member.MEMBER)
.where(Member.MEMBER.EMAIL.eq(email))
.and(Member.MEMBER.DELETED_AT.isNull)
.fetchOneInto(MemberRecord::class.java)
?: throw IllegalArgumentException("cannot find member record by email: $email")
}

fun insertMember(command: InsertMemberCommand): Long {
val result = dslContext.insertInto(Member.MEMBER)
.set(Member.MEMBER.EMAIL, command.email)
.set(Member.MEMBER.TYPE_CD, command.memberType.code)
.returning(Member.MEMBER.ID)
.fetchOne()

return result?.getValue(Member.MEMBER.ID)
?: throw RuntimeException("Member with email ${command.email} insertion fail") // TODO: 에러 표준화
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.few.api.repo.dao.member.command

import com.few.data.common.code.MemberType

data class InsertMemberCommand(
val email: String,
val memberType: MemberType
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.few.api.repo.dao.member.query

data class SelectMemberQuery(
val email: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.few.api.repo.dao.member.record

import java.net.URL

data class MemberRecord(
val memberId: Long,
val name: String,
val url: URL
)
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
package com.few.api.domain.subscription.service

import com.few.api.domain.subscription.service.dto.readMemberIdDto
import com.few.api.domain.subscription.service.dto.InsertMemberDto
import com.few.api.domain.subscription.service.dto.ReadMemberIdDto
import com.few.api.repo.dao.member.MemberDao
import com.few.api.repo.dao.member.command.InsertMemberCommand
import com.few.api.repo.dao.member.query.SelectMemberQuery
import org.springframework.stereotype.Service

@Service
class MemberService {
class MemberService(
private val memberDao: MemberDao
) {

fun readMemberId(dto: readMemberIdDto): Long {
return 1L // TODO: implemenets
fun readMemberId(dto: ReadMemberIdDto): Long? {
Copy link
Collaborator

Choose a reason for hiding this comment

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

여기 Dto는 api-repo에서 쓰는 query, command 때문에 dto로 하신거죠?
저는 service에도 query, command를 쓰기는 했는데 그럼 어색할까요?

Copy link
Member Author

Choose a reason for hiding this comment

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

제가 쭉 봤는데 지금 쿼리, 커맨드 usecase in/out 등등 저희끼리 명칭이 안맞는 부분이 좀 있어서 한번에 맞춰가는 리펙토링 하시죠(패키지명도)

return memberDao.selectMember(SelectMemberQuery(dto.email)).memberId
}

fun insertMember(dto: InsertMemberDto): Long {
return memberDao.insertMember(InsertMemberCommand(dto.email, dto.memberType))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.few.api.domain.subscription.service.dto

import com.few.data.common.code.MemberType

data class InsertMemberDto(
val email: String,
val memberType: MemberType
)
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package com.few.api.domain.subscription.service.dto

data class readMemberIdDto(
data class ReadMemberIdDto(
val email: String
)
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
package com.few.api.domain.subscription.usecase

import com.few.api.domain.subscription.service.MemberService
import com.few.api.domain.subscription.service.dto.InsertMemberDto
import com.few.api.domain.subscription.service.dto.ReadMemberIdDto
import com.few.api.repo.dao.subscription.SubscriptionDao
import com.few.api.repo.dao.subscription.command.InsertWorkbookSubscriptionCommand
import com.few.api.repo.dao.subscription.query.CountWorkbookSubscriptionQuery
import com.few.api.domain.subscription.usecase.`in`.SubscribeWorkbookUseCaseIn
import com.few.data.common.code.MemberType
import org.springframework.stereotype.Component
import org.springframework.transaction.annotation.Transactional

@Component
class SubscribeWorkbookUseCase(
private val subscriptionDao: SubscriptionDao
private val subscriptionDao: SubscriptionDao,
private val memberService: MemberService
) {

@Transactional
fun execute(useCaseIn: SubscribeWorkbookUseCaseIn) {
// TODO: request sending email

val memberId = memberService.readMemberId(ReadMemberIdDto(useCaseIn.email)) ?: memberService.insertMember(
InsertMemberDto(useCaseIn.email, MemberType.NORMAL_USER)
)
Copy link
Member Author

Choose a reason for hiding this comment

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

구독시 멤버가 존재하지 않을 경우(memberService.readMemberId = null 리턴) 멤버를 저장하는데, 기본적으로 NORMAL_USER로 저장함. writer 같은 유저는 이미 writer로서 디비에 있다고 가정했음. 어드민 유저일리는 없을거고.. 그래서 노말 유저로 설정

Copy link
Member Author

Choose a reason for hiding this comment

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

클래스는 Member인데 여긴 또 User라 해놨네요.. 이건 수정할게요


// 이미 구독중인지 확인
CountWorkbookSubscriptionQuery(memberId = useCaseIn.memberId, workbookId = useCaseIn.workbookId).let { query ->
CountWorkbookSubscriptionQuery(memberId = memberId, workbookId = useCaseIn.workbookId).let { query ->
subscriptionDao.selectCountWorkbookSubscription(query).let { cnt ->
if (cnt > 0) {
throw RuntimeException("Already subscribed")
Expand All @@ -26,7 +35,7 @@ class SubscribeWorkbookUseCase(
}

subscriptionDao.insertWorkbookSubscription(
InsertWorkbookSubscriptionCommand(memberId = useCaseIn.memberId, workbookId = useCaseIn.workbookId)
InsertWorkbookSubscriptionCommand(memberId = memberId, workbookId = useCaseIn.workbookId)
)
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.few.api.domain.subscription.usecase

import com.few.api.domain.subscription.service.MemberService
import com.few.api.domain.subscription.service.dto.readMemberIdDto
import com.few.api.domain.subscription.service.dto.ReadMemberIdDto
import com.few.api.domain.subscription.usecase.`in`.UnsubscribeAllUseCaseIn
import com.few.api.repo.dao.subscription.SubscriptionDao
import com.few.api.repo.dao.subscription.command.UpdateDeletedAtInAllSubscriptionCommand
Expand All @@ -18,7 +18,8 @@ class UnsubscribeAllUseCase(
fun execute(useCaseIn: UnsubscribeAllUseCaseIn) {
// TODO: request sending email

val memberId = memberService.readMemberId(readMemberIdDto(useCaseIn.email))
val memberId =
memberService.readMemberId(ReadMemberIdDto(useCaseIn.email)) ?: throw RuntimeException("Member Not Found")

subscriptionDao.updateDeletedAtInAllSubscription(
UpdateDeletedAtInAllSubscriptionCommand(memberId = memberId, opinion = useCaseIn.opinion)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.few.api.domain.subscription.usecase

import com.few.api.domain.subscription.service.MemberService
import com.few.api.domain.subscription.service.dto.readMemberIdDto
import com.few.api.domain.subscription.service.dto.ReadMemberIdDto
import com.few.api.repo.dao.subscription.SubscriptionDao
import com.few.api.repo.dao.subscription.command.UpdateDeletedAtInWorkbookSubscriptionCommand
import com.few.api.domain.subscription.usecase.`in`.UnsubscribeWorkbookUseCaseIn
Expand All @@ -18,7 +18,8 @@ class UnsubscribeWorkbookUseCase(
fun execute(useCaseIn: UnsubscribeWorkbookUseCaseIn) {
// TODO: request sending email

val memberId = memberService.readMemberId(readMemberIdDto(useCaseIn.email))
val memberId =
memberService.readMemberId(ReadMemberIdDto(useCaseIn.email)) ?: throw RuntimeException("Member Not Found")

subscriptionDao.updateDeletedAtInWorkbookSubscription(
UpdateDeletedAtInWorkbookSubscriptionCommand(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,5 @@ package com.few.api.domain.subscription.usecase.`in`

data class SubscribeWorkbookUseCaseIn(
val workbookId: Long,
val email: String,
val memberId: Long
val email: String
)
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class SubscriptionController(
@RequestBody body: SubscribeWorkbookRequest
): ApiResponse<ApiResponse.Success> {
subscribeWorkbookUseCase.execute(
SubscribeWorkbookUseCaseIn(workbookId = workbookId, email = body.email, memberId = 1L) // TODO: memberId
SubscribeWorkbookUseCaseIn(workbookId = workbookId, email = body.email) // TODO: memberId
Copy link
Collaborator

Choose a reason for hiding this comment

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

todo memberId는 추후에는 email이 아닌 memberId로 하면 좋겠다는 코멘트인거죠?

Copy link
Member Author

Choose a reason for hiding this comment

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

아 저거 주석 삭제해야됨

)

return ApiResponseGenerator.success(HttpStatus.OK)
Expand Down
2 changes: 2 additions & 0 deletions batch/src/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# DB schema migration path
**/*.sql
13 changes: 13 additions & 0 deletions data/src/main/kotlin/com/few/data/common/code/MemberType.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.few.data.common.code

enum class MemberType(val code: Byte, val displayName: String) {
NORMAL_USER(60, "일반유저"),
ADMIN_USER(0, "어드민유저"),
AUTHOR_USER(120, "작가유저");

companion object {
fun fromCode(code: Byte): MemberType? {
return values().find { it.code == code }
}
}
}
Copy link
Member Author

Choose a reason for hiding this comment

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

멤버 타입 정의한 코드인데 front에선 멤버를 저장하거나 할땐 타입으로 통신하는게 좋아보이고 소스코드 상에서 60, 120 같은 멤버 타입 코드 값을 직접 지정하거나 하는 등의 코드 작성하지 않도록 주의해야 합니다. 멤버코드를 가져오거나 조회하거나 등등은 모두 MemberType 내에서 fromCode를 통하도록 해주세요

Copy link
Member Author

Choose a reason for hiding this comment

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

즉, 60, 120 이런 숫자는 소스코드 상에서 MemberType에서만 보여야 함.

Loading