-
Notifications
You must be signed in to change notification settings - Fork 0
[feat/#32] 온보딩 api #33
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| package com.hsLink.hslink.data.dto.request.onboarding | ||
|
|
||
| import com.hsLink.hslink.presentation.onboarding.model.JobType | ||
| import com.hsLink.hslink.presentation.onboarding.model.LinkType | ||
| import kotlinx.serialization.SerialName | ||
| import kotlinx.serialization.Serializable | ||
|
|
||
| @Serializable | ||
| data class CareerRequest( | ||
| @SerialName("companyName") | ||
| val companyName: String, | ||
| @SerialName("position") | ||
| val position: String, | ||
| @SerialName("jobType") | ||
| val jobType: JobType, | ||
| @SerialName("startYm") | ||
| val startYm: String, | ||
| @SerialName("endYm") | ||
| val endYm: String? = null, | ||
| @SerialName("employed") | ||
| val employed: Boolean | ||
| ) | ||
|
|
||
| @Serializable | ||
| data class LinkRequest( | ||
| @SerialName("type") | ||
| val type: LinkType, | ||
| @SerialName("url") | ||
| val url: String | ||
| ) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| package com.hsLink.hslink.data.dto.request.onboarding | ||
|
|
||
| import kotlinx.serialization.SerialName | ||
| import kotlinx.serialization.Serializable | ||
|
|
||
| @Serializable | ||
| data class OnboardingRequest ( | ||
| @SerialName("name") | ||
| val name: String, | ||
| @SerialName("major") | ||
| val major: String, | ||
| @SerialName("studentNumber") | ||
| val studentNumber: String, | ||
| @SerialName("jobSeeking") | ||
| val jobSeeking : Boolean, | ||
| @SerialName("mentor") | ||
| val mentor : Boolean, | ||
| @SerialName("email") | ||
| val email : String | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| package com.hsLink.hslink.data.dto.response.onboarding | ||
|
|
||
| import com.hsLink.hslink.domain.model.search.CareerItemEntity | ||
| import com.hsLink.hslink.domain.model.search.LinkItemEntity | ||
| import com.hsLink.hslink.presentation.onboarding.model.JobType | ||
| import com.hsLink.hslink.presentation.onboarding.model.LinkType | ||
|
Comment on lines
+5
to
+6
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Architecture violation: data layer depends on presentation layer. The DTO is importing Consider one of these solutions:
Apply this approach if moving enums to domain: -import com.hsLink.hslink.presentation.onboarding.model.JobType
-import com.hsLink.hslink.presentation.onboarding.model.LinkType
+import com.hsLink.hslink.domain.model.JobType
+import com.hsLink.hslink.domain.model.LinkTypeThen move the enum definitions from
🤖 Prompt for AI Agents |
||
| import kotlinx.serialization.SerialName | ||
| import kotlinx.serialization.Serializable | ||
|
|
||
| @Serializable | ||
| data class CareerResponse( | ||
| @SerialName("id") val id: Int, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chainVerify ID type inconsistency.
Run this script to check if there are API documentation or integration tests that confirm the ID types: Also applies to: 23-23 🏁 Script executed: #!/bin/bash
# Search for API endpoint definitions or documentation mentioning career and link IDs
rg -n -C3 -g '!*.kt' -e 'career.*id|link.*id' -iLength of output: 333 🏁 Script executed: #!/bin/bash
# Get full content of CareerResponse and LinkResponse DTOs
echo "=== CareerResponse.kt ==="
cat app/src/main/java/com/hsLink/hslink/data/dto/response/CareerResponse.kt
echo -e "\n=== LinkResponse.kt ==="
cat app/src/main/java/com/hsLink/hslink/data/dto/response/LinkResponse.ktLength of output: 1549 🏁 Script executed: #!/bin/bash
# Search for Retrofit API interface definitions
fd -e 'kt' -p '.*[Aa]pi.*' --type f | head -20Length of output: 0 🏁 Script executed: #!/bin/bash
# Search for where CareerResponse and LinkResponse are deserialized or used
rg -n -C2 'CareerResponse|LinkResponse' --type=kt -g '!test'Length of output: 26 🏁 Script executed: #!/bin/bash
# Search for CareerItemEntity and LinkItemEntity to see their ID types
rg -n 'data class CareerItemEntity|data class LinkItemEntity' --type rustLength of output: 148 🏁 Script executed: #!/bin/bash
# Search for API service interface definitions (alternative syntax for Kotlin)
fd 'Service\|Api\|Repository' -e 'kt' | head -20Length of output: 0 🏁 Script executed: #!/bin/bash
# Search for usages of CareerResponse and LinkResponse to understand context
rg -n -C3 'CareerResponse\|LinkResponse'Length of output: 0 🏁 Script executed: #!/bin/bash
# Look for test files or fixtures showing API response structure
fd -e 'json' -o -e 'kt' | xargs rg -l 'career.*id\|link.*id' -i | head -10Length of output: 116 🏁 Script executed: #!/bin/bash
# Simple search for entity classes without type filters
rg -n 'data class CareerItemEntity' --no-headingLength of output: 108 🏁 Script executed: #!/bin/bash
# Search for any API or Service Kotlin files
find . -name '*Api.kt' -o -name '*Service.kt' -o -name '*Repository.kt' 2>/dev/null | head -15Length of output: 933 🏁 Script executed: #!/bin/bash
# Look at CareerResponse file again and grep for imports/usages
grep -r 'CareerResponse\|LinkResponse' . --include='*.kt' 2>/dev/null | head -20Length of output: 2197 🏁 Script executed: #!/bin/bash
# Check build.gradle for serialization library and backend info
find . -name 'build.gradle*' -o -name 'settings.gradle*' | xargs grep -l 'serialization\|retrofit\|okhttp' 2>/dev/nullLength of output: 41 🏁 Script executed: #!/bin/bash
# Get CareerItemEntity and LinkItemEntity definitions
cat app/src/main/java/com/hsLink/hslink/domain/model/search/UserProfileEntity.ktLength of output: 1074 🏁 Script executed: #!/bin/bash
# Get OnboardingService API interface to see endpoint signatures
cat app/src/main/java/com/hsLink/hslink/data/service/onboarding/OnboardingService.ktLength of output: 764 🏁 Script executed: #!/bin/bash
# Check if there are any comments or documentation about ID types
grep -r 'id.*Int\|id.*Long' app/src/main/java/com/hsLink/hslink/domain/model/search/ --include='*.kt' -B2 -A2Length of output: 1923 Resolve inconsistency between CareerItemEntity and CareerEntity ID types. While CareerResponse.id (Int) and LinkResponse.id (Long) correctly map to their respective entity types, a domain-level inconsistency exists: 🤖 Prompt for AI Agents |
||
| @SerialName("companyName") val companyName: String, | ||
| @SerialName("position") val position: String, | ||
| @SerialName("jobType") val jobType: JobType, | ||
| @SerialName("employed") val employed: Boolean, | ||
| @SerialName("startYm") val startYm: String, | ||
| @SerialName("endYm") val endYm: String?, | ||
| ) | ||
|
|
||
| @Serializable | ||
| data class LinkResponse( | ||
| @SerialName("id") val id: Long, | ||
| @SerialName("type") val type: LinkType, | ||
| @SerialName("url") val url: String, | ||
| ) | ||
|
|
||
| typealias CareerListResponseDto = List<CareerResponse> | ||
|
|
||
| @Serializable | ||
| data class LinkListResponseDto( | ||
| @SerialName("links") val links: List<LinkResponse>, | ||
| ) | ||
|
|
||
| fun CareerResponse.toEntity(): CareerItemEntity = CareerItemEntity( | ||
| id = id, companyName = companyName, position = position, | ||
| jobType = jobType, employed = employed, startYm = startYm, endYm = endYm | ||
| ) | ||
|
|
||
| fun LinkResponse.toEntity(): LinkItemEntity = LinkItemEntity( | ||
| id = id, type = type, url = url | ||
| ) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| package com.hsLink.hslink.data.remote.datasource | ||
|
|
||
| import com.hsLink.hslink.core.network.BaseResponse | ||
| import com.hsLink.hslink.data.dto.request.onboarding.* | ||
| import com.hsLink.hslink.data.dto.response.onboarding.* | ||
|
|
||
| interface OnboardingDataSource { | ||
| suspend fun submitOnboarding(request: OnboardingRequest): BaseResponse<Unit> | ||
| suspend fun getCareers(): BaseResponse<List<CareerResponse>> | ||
| suspend fun submitCareer(request: CareerRequest): BaseResponse<CareerResponse> | ||
| suspend fun getLinks(): BaseResponse<LinkListResponseDto> | ||
| suspend fun submitLink(request: LinkRequest): LinkResponse | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| package com.hsLink.hslink.data.remote.datasourceimpl | ||
|
|
||
| import com.hsLink.hslink.core.network.BaseResponse | ||
| import com.hsLink.hslink.data.dto.request.onboarding.* | ||
| import com.hsLink.hslink.data.remote.datasource.OnboardingDataSource | ||
| import com.hsLink.hslink.data.service.onboarding.OnboardingService | ||
| import com.hsLink.hslink.data.dto.response.onboarding.* | ||
| import javax.inject.Inject | ||
|
|
||
| class OnboardingDataSourceImpl @Inject constructor( | ||
| private val onboardingService: OnboardingService | ||
| ) : OnboardingDataSource { | ||
| override suspend fun submitOnboarding(request: OnboardingRequest): BaseResponse<Unit> = | ||
| onboardingService.onboarding(request) | ||
|
|
||
| override suspend fun getCareers(): BaseResponse<List<CareerResponse>> = | ||
| onboardingService.getCareers() | ||
|
|
||
| override suspend fun submitCareer(request: CareerRequest): BaseResponse<CareerResponse> = | ||
| onboardingService.submitCareer(request) | ||
|
|
||
| override suspend fun getLinks(): BaseResponse<LinkListResponseDto> = | ||
| onboardingService.getLinks() | ||
|
|
||
| override suspend fun submitLink(request: LinkRequest): LinkResponse = | ||
| onboardingService.submitLink(request) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| package com.hsLink.hslink.data.repositoryimpl.onboarding | ||
|
|
||
| import com.hsLink.hslink.data.dto.request.onboarding.* | ||
| import com.hsLink.hslink.data.dto.response.onboarding.toEntity | ||
| import com.hsLink.hslink.data.remote.datasource.OnboardingDataSource | ||
| import com.hsLink.hslink.domain.model.search.* | ||
| import com.hsLink.hslink.domain.repository.onboarding.OnboardingRepository | ||
| import javax.inject.Inject | ||
|
|
||
| class OnboardingRepositoryImpl @Inject constructor( | ||
| private val onboardingDataSource: OnboardingDataSource, | ||
| ) : OnboardingRepository { | ||
| override suspend fun submitOnboarding(request: OnboardingRequest): Result<Unit> = runCatching { | ||
| val response = onboardingDataSource.submitOnboarding(request) | ||
| if (response.isSuccess) response.result | ||
| else throw Exception(response.message) | ||
| } | ||
|
|
||
| override suspend fun getCareers(): Result<List<CareerItemEntity>> = runCatching { | ||
| val response = onboardingDataSource.getCareers() | ||
| if (response.isSuccess && response.result != null) { | ||
| response.result.map { it.toEntity() } | ||
| } else throw Exception(response.message ?: "Failed to get careers") | ||
| } | ||
|
|
||
| override suspend fun submitCareer(request: CareerRequest): Result<CareerItemEntity> = runCatching { | ||
| val response = onboardingDataSource.submitCareer(request) | ||
| if (response.isSuccess && response.result != null) { | ||
| response.result.toEntity() | ||
| } else throw Exception(response.message ?: "Failed to submit career") | ||
| } | ||
|
|
||
| override suspend fun getLinks(): Result<List<LinkItemEntity>> = runCatching { | ||
| val response = onboardingDataSource.getLinks() | ||
| if (response.isSuccess && response.result != null) { | ||
| response.result.links.map { it.toEntity() } | ||
| } else throw Exception(response.message ?: "Failed to get links") | ||
| } | ||
|
|
||
| override suspend fun submitLink(request: LinkRequest): Result<LinkItemEntity> = runCatching { | ||
| onboardingDataSource.submitLink(request).toEntity() | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| package com.hsLink.hslink.data.service.onboarding | ||
|
|
||
| import com.hsLink.hslink.core.network.BaseResponse | ||
| import com.hsLink.hslink.data.dto.request.onboarding.* | ||
| import com.hsLink.hslink.data.dto.response.onboarding.* | ||
| import retrofit2.http.* | ||
|
|
||
| interface OnboardingService { | ||
| @POST("auth/onboarding") | ||
| suspend fun onboarding(@Body request: OnboardingRequest): BaseResponse<Unit> | ||
|
|
||
| @GET("careers/mycareers") | ||
| suspend fun getCareers(): BaseResponse<List<CareerResponse>> | ||
|
|
||
| @POST("careers") | ||
| suspend fun submitCareer(@Body request: CareerRequest): BaseResponse<CareerResponse> | ||
|
|
||
| @GET("links/mylinks") | ||
| suspend fun getLinks(): BaseResponse<LinkListResponseDto> | ||
|
|
||
| @POST("links") | ||
| suspend fun submitLink(@Body request: LinkRequest): LinkResponse | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,8 @@ | ||
| package com.hsLink.hslink.domain.model.search | ||
|
|
||
| import com.hsLink.hslink.presentation.onboarding.model.JobType | ||
| import com.hsLink.hslink.presentation.onboarding.model.LinkType | ||
|
Comment on lines
+3
to
+4
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix layering violation: Domain layer should not import presentation layer types. The domain layer is importing Move -import com.hsLink.hslink.presentation.onboarding.model.JobType
-import com.hsLink.hslink.presentation.onboarding.model.LinkType
+import com.hsLink.hslink.domain.model.onboarding.JobType
+import com.hsLink.hslink.domain.model.onboarding.LinkType
|
||
|
|
||
| data class UserProfileEntity( | ||
| val userId: Long, | ||
| val name: String, | ||
|
|
@@ -13,6 +16,16 @@ data class UserProfileEntity( | |
| val links: List<LinkEntity> | ||
| ) | ||
|
|
||
| data class CareerItemEntity( | ||
| val id: Int, | ||
| val companyName: String, | ||
| val position: String, | ||
| val jobType: JobType, | ||
| val employed: Boolean, | ||
| val startYm: String, | ||
| val endYm: String? | ||
| ) | ||
|
|
||
| data class CareerEntity( | ||
| val id: Long, | ||
| val companyName: String, | ||
|
|
@@ -27,4 +40,10 @@ data class LinkEntity( | |
| val id: Long, | ||
| val type: String, | ||
| val url: String | ||
| ) | ||
|
|
||
| data class LinkItemEntity( | ||
| val id: Long, | ||
| val type: LinkType, | ||
| val url: String | ||
| ) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| package com.hsLink.hslink.domain.repository.onboarding | ||
|
|
||
| import com.hsLink.hslink.data.dto.request.onboarding.CareerRequest | ||
| import com.hsLink.hslink.data.dto.request.onboarding.LinkRequest | ||
| import com.hsLink.hslink.data.dto.request.onboarding.OnboardingRequest | ||
| import com.hsLink.hslink.domain.model.search.CareerItemEntity | ||
| import com.hsLink.hslink.domain.model.search.LinkItemEntity | ||
|
|
||
| interface OnboardingRepository { | ||
| suspend fun submitOnboarding(request: OnboardingRequest): Result<Unit> | ||
| suspend fun getCareers(): Result<List<CareerItemEntity>> | ||
| suspend fun submitCareer(request: CareerRequest): Result<CareerItemEntity> | ||
| suspend fun getLinks(): Result<List<LinkItemEntity>> | ||
| suspend fun submitLink(request: LinkRequest): Result<LinkItemEntity> | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix layering violation: Data layer should not import presentation layer types.
The data layer (DTOs) is importing
JobTypeandLinkTypefrom the presentation layer (com.hsLink.hslink.presentation.onboarding.model). This violates clean architecture principles where data/domain layers should not depend on the presentation layer.Move
JobTypeandLinkTypeto the domain layer (e.g.,com.hsLink.hslink.domain.model.onboarding) so they can be shared across layers without creating circular dependencies or layering violations.🤖 Prompt for AI Agents