From 44043b618dd8d3c60a21c3084a442592e84725b3 Mon Sep 17 00:00:00 2001 From: yoonseo8167 Date: Wed, 23 Jul 2025 19:39:17 +0900 Subject: [PATCH 01/15] =?UTF-8?q?feat:=20#164=20term=20api=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gradle/wrapper/gradle-wrapper.properties | 2 +- .../damaba/damaba/application/term/Command.kt | 29 +++++++ .../damaba/application/term/TermService.kt | 39 +++++++++ .../damaba/damaba/controller/term/Request.kt | 32 ++++++++ .../damaba/damaba/controller/term/Response.kt | 17 ++++ .../damaba/controller/term/TermController.kt | 79 +++++++++++++++++++ .../com/damaba/damaba/domain/term/Term.kt | 11 +++ .../com/damaba/damaba/domain/term/TermType.kt | 23 ++++++ .../damaba/domain/term/TermValidator.kt | 26 ++++++ .../infrastructure/term/TermCoreRepository.kt | 15 ++++ .../infrastructure/term/TermJpaEntity.kt | 51 ++++++++++++ .../infrastructure/term/TermJpaRepository.kt | 5 ++ .../infrastructure/term/TermRepository.kt | 7 ++ src/main/resources/application-local.yml | 1 + src/main/resources/application.yml | 2 +- 15 files changed, 337 insertions(+), 2 deletions(-) create mode 100644 src/main/kotlin/com/damaba/damaba/application/term/Command.kt create mode 100644 src/main/kotlin/com/damaba/damaba/application/term/TermService.kt create mode 100644 src/main/kotlin/com/damaba/damaba/controller/term/Request.kt create mode 100644 src/main/kotlin/com/damaba/damaba/controller/term/Response.kt create mode 100644 src/main/kotlin/com/damaba/damaba/controller/term/TermController.kt create mode 100644 src/main/kotlin/com/damaba/damaba/domain/term/Term.kt create mode 100644 src/main/kotlin/com/damaba/damaba/domain/term/TermType.kt create mode 100644 src/main/kotlin/com/damaba/damaba/domain/term/TermValidator.kt create mode 100644 src/main/kotlin/com/damaba/damaba/infrastructure/term/TermCoreRepository.kt create mode 100644 src/main/kotlin/com/damaba/damaba/infrastructure/term/TermJpaEntity.kt create mode 100644 src/main/kotlin/com/damaba/damaba/infrastructure/term/TermJpaRepository.kt create mode 100644 src/main/kotlin/com/damaba/damaba/infrastructure/term/TermRepository.kt diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0aaefbca..1af9e093 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/src/main/kotlin/com/damaba/damaba/application/term/Command.kt b/src/main/kotlin/com/damaba/damaba/application/term/Command.kt new file mode 100644 index 00000000..fbe18008 --- /dev/null +++ b/src/main/kotlin/com/damaba/damaba/application/term/Command.kt @@ -0,0 +1,29 @@ +package com.damaba.damaba.application.term + +import com.damaba.damaba.domain.term.TermType +import com.damaba.damaba.domain.term.TermValidator + +data class TermItem( + val type: TermType, + val agreed: Boolean, +) + +data class AcceptUserTermsCommand( + val userId: Long, + val terms: List, +) { + init { + // TermValidator 에서 필수 약관 체크 + TermValidator.validateUserRequired(terms) + } +} + +data class AcceptPhotographerTermsCommand( + val userId: Long, + val terms: List, +) { + init { + // TermValidator 에서 유저+작가 필수 약관 체크 + TermValidator.validatePhotographerRequired(terms) + } +} diff --git a/src/main/kotlin/com/damaba/damaba/application/term/TermService.kt b/src/main/kotlin/com/damaba/damaba/application/term/TermService.kt new file mode 100644 index 00000000..db54076b --- /dev/null +++ b/src/main/kotlin/com/damaba/damaba/application/term/TermService.kt @@ -0,0 +1,39 @@ +package com.damaba.damaba.application.term + +import com.damaba.damaba.domain.term.Term +import com.damaba.damaba.infrastructure.term.TermRepository +import jakarta.transaction.Transactional +import org.springframework.stereotype.Service + +@Service +class TermService( + private val termRepo: TermRepository, +) { + // 일반 유저용 약관 동의 내역 저장 + @Transactional + fun acceptUserTerms(command: AcceptUserTermsCommand) { + val userTerms = command.terms.map { item -> + Term( + id = 0L, + userId = command.userId, + type = item.type, + agreed = item.agreed, + ) + } + termRepo.saveAll(userTerms) + } + + // 사진 작가용 약관 동의 내역 저장 + @Transactional + fun acceptPhotographerTerms(command: AcceptPhotographerTermsCommand) { + val photoTerm = command.terms.map { item -> + Term( + id = 0L, + userId = command.userId, + type = item.type, + agreed = item.agreed, + ) + } + termRepo.saveAll(photoTerm) + } +} diff --git a/src/main/kotlin/com/damaba/damaba/controller/term/Request.kt b/src/main/kotlin/com/damaba/damaba/controller/term/Request.kt new file mode 100644 index 00000000..099d25fe --- /dev/null +++ b/src/main/kotlin/com/damaba/damaba/controller/term/Request.kt @@ -0,0 +1,32 @@ +package com.damaba.damaba.controller.term + +import com.damaba.damaba.application.term.AcceptPhotographerTermsCommand +import com.damaba.damaba.application.term.AcceptUserTermsCommand +import com.damaba.damaba.application.term.TermItem +import com.damaba.damaba.domain.term.TermType +import io.swagger.v3.oas.annotations.media.Schema + +data class AgreementRequestItem( + @Schema(description = "약관 항목", example = "SERVICE_TERMS") + val type: TermType, + + @Schema(description = "사용자의 동의 여부") + val agreed: Boolean, +) + +data class UserTermRequest( + @Schema( + description = "사용자가 동의한 약관 항목들", + ) + val agreements: List, +) { + fun toUserCommand(userId: Long): AcceptUserTermsCommand = AcceptUserTermsCommand( + userId = userId, + terms = agreements.map { TermItem(it.type, it.agreed) }, + ) + + fun toPhotographerCommand(userId: Long): AcceptPhotographerTermsCommand = AcceptPhotographerTermsCommand( + userId = userId, + terms = agreements.map { TermItem(it.type, it.agreed) }, + ) +} diff --git a/src/main/kotlin/com/damaba/damaba/controller/term/Response.kt b/src/main/kotlin/com/damaba/damaba/controller/term/Response.kt new file mode 100644 index 00000000..62b7c8a8 --- /dev/null +++ b/src/main/kotlin/com/damaba/damaba/controller/term/Response.kt @@ -0,0 +1,17 @@ +@file:Suppress("ktlint:standard:filename") + +package com.damaba.damaba.controller.term + +import com.damaba.damaba.domain.term.TermType +import io.swagger.v3.oas.annotations.media.Schema + +data class TermMetadataResponse( + @Schema(description = "약관 항목", example = "SERVICE_TERMS") + val type: TermType, + + @Schema(description = "필수 약관 여부", example = "true") + val required: Boolean, + + @Schema(description = "약관 상세 내용 URL", example = "https://damabad.com") + val detailUrl: String, +) diff --git a/src/main/kotlin/com/damaba/damaba/controller/term/TermController.kt b/src/main/kotlin/com/damaba/damaba/controller/term/TermController.kt new file mode 100644 index 00000000..db6cbcda --- /dev/null +++ b/src/main/kotlin/com/damaba/damaba/controller/term/TermController.kt @@ -0,0 +1,79 @@ +package com.damaba.damaba.controller.term + +import com.damaba.damaba.application.term.TermService +import com.damaba.damaba.domain.term.TermType +import com.damaba.damaba.domain.user.User +import io.swagger.v3.oas.annotations.Operation +import io.swagger.v3.oas.annotations.media.Content +import io.swagger.v3.oas.annotations.responses.ApiResponse +import io.swagger.v3.oas.annotations.responses.ApiResponses +import io.swagger.v3.oas.annotations.security.SecurityRequirement +import io.swagger.v3.oas.annotations.tags.Tag +import org.springframework.http.ResponseEntity +import org.springframework.security.core.annotation.AuthenticationPrincipal +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RestController + +@Tag(name = "서비스 약관 동의 API") +@RestController +class TermController( + private val termService: TermService, +) { + + @Operation( + summary = "유저 서비스 약관 동의 제출", + description = "

일반 유저용 약관 3개 제출", + security = [SecurityRequirement(name = "access-token")], + ) + @ApiResponses( + ApiResponse(responseCode = "200"), + ApiResponse(responseCode = "404", description = "유저 정보를 찾을 수 없는 경우", content = [Content()]), + ) + @PostMapping("/api/v1/users/me/terms/agree") + fun acceptUserTerms( + @AuthenticationPrincipal requestUser: User, + @RequestBody request: UserTermRequest, + ): ResponseEntity { + termService.acceptUserTerms(request.toUserCommand(requestUser.id)) + return ResponseEntity.noContent().build() + } + + @Operation( + summary = "작가 서비스 약관 동의 제출", + description = "

사진 작가용 약관 4개 제출", + security = [SecurityRequirement(name = "access-token")], + ) + @ApiResponses( + ApiResponse(responseCode = "200"), + ApiResponse(responseCode = "404", description = "유저 정보를 찾을 수 없는 경우", content = [Content()]), + ) + @PostMapping("/api/v1/photographers/me/terms/agree") + fun acceptPhotographerTerms( + @AuthenticationPrincipal requestUser: User, + @RequestBody request: UserTermRequest, + ): ResponseEntity { + termService.acceptPhotographerTerms(request.toPhotographerCommand(requestUser.id)) + return ResponseEntity.noContent().build() + } + + @Operation( + summary = "약관 메타데이터 조회", + description = "모든 약관 종류(type), 필수 여부(required), 상세 URL(detailUrl)을 반환한다.", + ) + @ApiResponses( + ApiResponse(responseCode = "200"), + ) + @GetMapping("/api/v1/terms/metadata") + fun getTermMetadata(): ResponseEntity> { + val metadata = TermType.values().map { + TermMetadataResponse( + type = it, + required = it.required, + detailUrl = it.detailUrl, + ) + } + return ResponseEntity.ok(metadata) + } +} diff --git a/src/main/kotlin/com/damaba/damaba/domain/term/Term.kt b/src/main/kotlin/com/damaba/damaba/domain/term/Term.kt new file mode 100644 index 00000000..d92ab45e --- /dev/null +++ b/src/main/kotlin/com/damaba/damaba/domain/term/Term.kt @@ -0,0 +1,11 @@ +package com.damaba.damaba.domain.term + +class Term( + val id: Long?, + val userId: Long, + val type: TermType, + agreed: Boolean, +) { + var agreed: Boolean = agreed + protected set +} diff --git a/src/main/kotlin/com/damaba/damaba/domain/term/TermType.kt b/src/main/kotlin/com/damaba/damaba/domain/term/TermType.kt new file mode 100644 index 00000000..0429ca38 --- /dev/null +++ b/src/main/kotlin/com/damaba/damaba/domain/term/TermType.kt @@ -0,0 +1,23 @@ +package com.damaba.damaba.domain.term + +enum class TermType( + val required: Boolean, + val detailUrl: String, +) { + AGE_CONFIRMATION( + required = true, + detailUrl = "", + ), + SERVICE_TERMS( + required = true, + detailUrl = "https://obtainable-chocolate-d07.notion.site/1b53cdfe88408032b850cbba8f856532?source=copy_link", + ), + PRIVACY_TERMS( + required = true, + detailUrl = "https://www.notion.so/1b53cdfe884080ef94bcf7e9f55f0bcb", + ), + PHOTOGRAPHER_TERMS( + required = true, + detailUrl = "https://obtainable-chocolate-d07.notion.site/MVP-2343cdfe88408001ae94ce87fcc81ebb?source=copy_link", + ), +} diff --git a/src/main/kotlin/com/damaba/damaba/domain/term/TermValidator.kt b/src/main/kotlin/com/damaba/damaba/domain/term/TermValidator.kt new file mode 100644 index 00000000..8353554b --- /dev/null +++ b/src/main/kotlin/com/damaba/damaba/domain/term/TermValidator.kt @@ -0,0 +1,26 @@ +package com.damaba.damaba.domain.term + +import com.damaba.damaba.application.term.TermItem + +object TermValidator { + private val userRequired = setOf( + TermType.AGE_CONFIRMATION, + TermType.PRIVACY_TERMS, + TermType.SERVICE_TERMS, + ) + private val photographerRequired = userRequired + TermType.PHOTOGRAPHER_TERMS + + fun validateUserRequired(items: List) { + val agreedSet = items.filter { it.agreed }.map { it.type }.toSet() + if (!agreedSet.containsAll(userRequired)) { + throw IllegalArgumentException("(유저) 필수 약관에 모두 동의해야 합니다.") + } + } + + fun validatePhotographerRequired(items: List) { + val agreedSet = items.filter { it.agreed }.map { it.type }.toSet() + if (!agreedSet.containsAll(photographerRequired)) { + throw IllegalArgumentException("(작가) 필수 약관에 모두 동의해야 합니다.") + } + } +} diff --git a/src/main/kotlin/com/damaba/damaba/infrastructure/term/TermCoreRepository.kt b/src/main/kotlin/com/damaba/damaba/infrastructure/term/TermCoreRepository.kt new file mode 100644 index 00000000..81c1ccd0 --- /dev/null +++ b/src/main/kotlin/com/damaba/damaba/infrastructure/term/TermCoreRepository.kt @@ -0,0 +1,15 @@ +package com.damaba.damaba.infrastructure.term + +import com.damaba.damaba.domain.term.Term +import org.springframework.stereotype.Repository + +@Repository +class TermCoreRepository( + private val jpaRepository: TermJpaRepository, +) : TermRepository { + + override fun saveAll(terms: List): List { + val entities = terms.map { TermJpaEntity.fromTerm(it) } + return jpaRepository.saveAll(entities).map { it.toTerm() } + } +} diff --git a/src/main/kotlin/com/damaba/damaba/infrastructure/term/TermJpaEntity.kt b/src/main/kotlin/com/damaba/damaba/infrastructure/term/TermJpaEntity.kt new file mode 100644 index 00000000..a0335d8f --- /dev/null +++ b/src/main/kotlin/com/damaba/damaba/infrastructure/term/TermJpaEntity.kt @@ -0,0 +1,51 @@ +package com.damaba.damaba.infrastructure.term + +import com.damaba.damaba.domain.term.Term +import com.damaba.damaba.domain.term.TermType +import com.damaba.damaba.infrastructure.common.TimeTrackedJpaEntity +import jakarta.persistence.Column +import jakarta.persistence.Entity +import jakarta.persistence.EnumType +import jakarta.persistence.Enumerated +import jakarta.persistence.GeneratedValue +import jakarta.persistence.GenerationType +import jakarta.persistence.Id +import jakarta.persistence.Table + +@Entity +@Table(name = "term") +class TermJpaEntity( + @Column(name = "user_id", nullable = false) + val userId: Long, + + @Enumerated(EnumType.STRING) + @Column(name = "type", nullable = false) + val type: TermType, + + agreed: Boolean, +) : TimeTrackedJpaEntity() { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id", nullable = false) + var id: Long? = null + private set + + @Column(name = "agreed", nullable = false) + var agreed: Boolean = agreed + private set + + fun toTerm(): Term = Term( + id = this.id, + userId = this.userId, + type = this.type, + agreed = this.agreed, + ) + + companion object { + fun fromTerm(term: Term): TermJpaEntity = TermJpaEntity( + userId = term.userId, + type = term.type, + agreed = term.agreed, + ).apply { id = term.id.takeIf { it != 0L } } + } +} diff --git a/src/main/kotlin/com/damaba/damaba/infrastructure/term/TermJpaRepository.kt b/src/main/kotlin/com/damaba/damaba/infrastructure/term/TermJpaRepository.kt new file mode 100644 index 00000000..b87428d0 --- /dev/null +++ b/src/main/kotlin/com/damaba/damaba/infrastructure/term/TermJpaRepository.kt @@ -0,0 +1,5 @@ +package com.damaba.damaba.infrastructure.term + +import org.springframework.data.jpa.repository.JpaRepository + +interface TermJpaRepository : JpaRepository diff --git a/src/main/kotlin/com/damaba/damaba/infrastructure/term/TermRepository.kt b/src/main/kotlin/com/damaba/damaba/infrastructure/term/TermRepository.kt new file mode 100644 index 00000000..00f7fd13 --- /dev/null +++ b/src/main/kotlin/com/damaba/damaba/infrastructure/term/TermRepository.kt @@ -0,0 +1,7 @@ +package com.damaba.damaba.infrastructure.term + +import com.damaba.damaba.domain.term.Term + +interface TermRepository { + fun saveAll(terms: List): List +} diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml index fd3c642b..6b51674e 100644 --- a/src/main/resources/application-local.yml +++ b/src/main/resources/application-local.yml @@ -4,6 +4,7 @@ spring: jpa: properties: hibernate: + ddl-auto: update format_sql: true defer-datasource-initialization: false diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 48cbf451..26de4259 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -36,7 +36,7 @@ spring: jpa: hibernate: - ddl-auto: validate + ddl-auto: update open-in-view: false properties: hibernate: From b3c9ebebdcde98c1ae7ea91e2fac0576c01a2414 Mon Sep 17 00:00:00 2001 From: yoonseo8167 Date: Thu, 24 Jul 2025 00:08:29 +0900 Subject: [PATCH 02/15] =?UTF-8?q?refactor:=20#164=20application=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application-local.yml | 1 - src/main/resources/application.yml | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml index 6b51674e..fd3c642b 100644 --- a/src/main/resources/application-local.yml +++ b/src/main/resources/application-local.yml @@ -4,7 +4,6 @@ spring: jpa: properties: hibernate: - ddl-auto: update format_sql: true defer-datasource-initialization: false diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 26de4259..48cbf451 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -36,7 +36,7 @@ spring: jpa: hibernate: - ddl-auto: update + ddl-auto: validate open-in-view: false properties: hibernate: From 17c385b67bc9c576d2a2d048e488f9c4998f2051 Mon Sep 17 00:00:00 2001 From: yoonseo8167 Date: Thu, 24 Jul 2025 00:09:57 +0900 Subject: [PATCH 03/15] =?UTF-8?q?refactor:=20#164=20gradle-wrapper=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1af9e093..0aaefbca 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From 61193f430b8fc98abc2268f38e49508c36b21ad6 Mon Sep 17 00:00:00 2001 From: yoonseo8167 Date: Thu, 24 Jul 2025 00:59:24 +0900 Subject: [PATCH 04/15] =?UTF-8?q?refactor:=20#164=20schema.sql=20term=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/schema.sql | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index bd2c9883..de043b9f 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -11,6 +11,7 @@ DROP TABLE IF EXISTS promotion_image; DROP TABLE IF EXISTS promotion_active_region; DROP TABLE IF EXISTS promotion_hashtag; DROP TABLE IF EXISTS promotion_save; +DROP TABLE IF EXISTS term; CREATE TABLE `user` ( @@ -185,5 +186,15 @@ CREATE TABLE promotion_save updated_at TIMESTAMP NOT NULL, PRIMARY KEY (id) ); +CREATE TABLE term +( + id BIGINT NOT NULL AUTO_INCREMENT, + user_id BIGINT NOT NULL COMMENT '(FK) id of user', + type VARCHAR(255) NOT NULL, + agreed BOOLEAN NOT NULL, + created_at TIMESTAMP NOT NULL , + updated_at TIMESTAMP NOT NULL, + PRIMARY KEY (id) +); CREATE INDEX fk_idx__promotion_save__user_id ON promotion_save (user_id); CREATE INDEX fk_idx__promotion_save__promotion_id ON promotion_save (promotion_id); From 87a43e2f7b7b5a8ed20746f6e98916818d914776 Mon Sep 17 00:00:00 2001 From: yoonseo8167 Date: Fri, 25 Jul 2025 14:55:50 +0900 Subject: [PATCH 05/15] =?UTF-8?q?refactor:=20#164=20review=20=EB=B0=98?= =?UTF-8?q?=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../damaba/damaba/controller/term/Response.kt | 3 --- .../damaba/controller/term/TermController.kt | 1 - .../com/damaba/damaba/domain/term/Term.kt | 4 ++-- .../com/damaba/damaba/domain/term/TermType.kt | 21 ++++--------------- .../infrastructure/term/TermJpaEntity.kt | 5 ++--- 5 files changed, 8 insertions(+), 26 deletions(-) diff --git a/src/main/kotlin/com/damaba/damaba/controller/term/Response.kt b/src/main/kotlin/com/damaba/damaba/controller/term/Response.kt index 62b7c8a8..b446ab3b 100644 --- a/src/main/kotlin/com/damaba/damaba/controller/term/Response.kt +++ b/src/main/kotlin/com/damaba/damaba/controller/term/Response.kt @@ -11,7 +11,4 @@ data class TermMetadataResponse( @Schema(description = "필수 약관 여부", example = "true") val required: Boolean, - - @Schema(description = "약관 상세 내용 URL", example = "https://damabad.com") - val detailUrl: String, ) diff --git a/src/main/kotlin/com/damaba/damaba/controller/term/TermController.kt b/src/main/kotlin/com/damaba/damaba/controller/term/TermController.kt index db6cbcda..2f576cea 100644 --- a/src/main/kotlin/com/damaba/damaba/controller/term/TermController.kt +++ b/src/main/kotlin/com/damaba/damaba/controller/term/TermController.kt @@ -71,7 +71,6 @@ class TermController( TermMetadataResponse( type = it, required = it.required, - detailUrl = it.detailUrl, ) } return ResponseEntity.ok(metadata) diff --git a/src/main/kotlin/com/damaba/damaba/domain/term/Term.kt b/src/main/kotlin/com/damaba/damaba/domain/term/Term.kt index d92ab45e..6855e691 100644 --- a/src/main/kotlin/com/damaba/damaba/domain/term/Term.kt +++ b/src/main/kotlin/com/damaba/damaba/domain/term/Term.kt @@ -1,11 +1,11 @@ package com.damaba.damaba.domain.term class Term( - val id: Long?, + val id: Long, val userId: Long, val type: TermType, agreed: Boolean, ) { var agreed: Boolean = agreed - protected set + private set } diff --git a/src/main/kotlin/com/damaba/damaba/domain/term/TermType.kt b/src/main/kotlin/com/damaba/damaba/domain/term/TermType.kt index 0429ca38..b9ab1e3b 100644 --- a/src/main/kotlin/com/damaba/damaba/domain/term/TermType.kt +++ b/src/main/kotlin/com/damaba/damaba/domain/term/TermType.kt @@ -2,22 +2,9 @@ package com.damaba.damaba.domain.term enum class TermType( val required: Boolean, - val detailUrl: String, ) { - AGE_CONFIRMATION( - required = true, - detailUrl = "", - ), - SERVICE_TERMS( - required = true, - detailUrl = "https://obtainable-chocolate-d07.notion.site/1b53cdfe88408032b850cbba8f856532?source=copy_link", - ), - PRIVACY_TERMS( - required = true, - detailUrl = "https://www.notion.so/1b53cdfe884080ef94bcf7e9f55f0bcb", - ), - PHOTOGRAPHER_TERMS( - required = true, - detailUrl = "https://obtainable-chocolate-d07.notion.site/MVP-2343cdfe88408001ae94ce87fcc81ebb?source=copy_link", - ), + AGE_CONFIRMATION(required = true), + SERVICE_TERMS(required = true), + PRIVACY_TERMS(required = true), + PHOTOGRAPHER_TERMS(required = true), } diff --git a/src/main/kotlin/com/damaba/damaba/infrastructure/term/TermJpaEntity.kt b/src/main/kotlin/com/damaba/damaba/infrastructure/term/TermJpaEntity.kt index a0335d8f..7f746226 100644 --- a/src/main/kotlin/com/damaba/damaba/infrastructure/term/TermJpaEntity.kt +++ b/src/main/kotlin/com/damaba/damaba/infrastructure/term/TermJpaEntity.kt @@ -27,8 +27,7 @@ class TermJpaEntity( @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", nullable = false) - var id: Long? = null - private set + val id: Long = 0 @Column(name = "agreed", nullable = false) var agreed: Boolean = agreed @@ -46,6 +45,6 @@ class TermJpaEntity( userId = term.userId, type = term.type, agreed = term.agreed, - ).apply { id = term.id.takeIf { it != 0L } } + ) } } From 52c858e2cce4e29aee0b925a7f962afdb4a5cd4e Mon Sep 17 00:00:00 2001 From: yoonseo8167 Date: Wed, 6 Aug 2025 19:17:50 +0900 Subject: [PATCH 06/15] =?UTF-8?q?modify:=20#164=20register=EC=97=90=20?= =?UTF-8?q?=EC=95=BD=EA=B4=80=20=EB=8F=99=EC=9D=98=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../damaba/application/photographer/Command.kt | 4 ++++ .../photographer/PhotographerService.kt | 14 +++++++++++++- .../com/damaba/damaba/application/user/Command.kt | 4 ++++ .../damaba/damaba/application/user/UserService.kt | 15 ++++++++++++++- .../damaba/controller/photographer/Request.kt | 13 +++++++++++++ .../com/damaba/damaba/controller/user/Request.kt | 14 ++++++++++++++ 6 files changed, 62 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/com/damaba/damaba/application/photographer/Command.kt b/src/main/kotlin/com/damaba/damaba/application/photographer/Command.kt index 02e9c210..d6dd3613 100644 --- a/src/main/kotlin/com/damaba/damaba/application/photographer/Command.kt +++ b/src/main/kotlin/com/damaba/damaba/application/photographer/Command.kt @@ -1,10 +1,12 @@ package com.damaba.damaba.application.photographer +import com.damaba.damaba.application.term.TermItem import com.damaba.damaba.domain.common.Address import com.damaba.damaba.domain.common.constant.PhotographyType import com.damaba.damaba.domain.file.Image import com.damaba.damaba.domain.photographer.PhotographerValidator import com.damaba.damaba.domain.region.Region +import com.damaba.damaba.domain.term.TermValidator import com.damaba.damaba.domain.user.UserValidator import com.damaba.damaba.domain.user.constant.Gender @@ -16,12 +18,14 @@ data class RegisterPhotographerCommand( val profileImage: Image, val mainPhotographyTypes: Set, val activeRegions: Set, + val terms: List, ) { init { PhotographerValidator.validateNickname(nickname) if (instagramId != null) UserValidator.validateInstagramId(instagramId) PhotographerValidator.validateMainPhotographyTypes(mainPhotographyTypes) PhotographerValidator.validateActiveRegions(activeRegions) + TermValidator.validatePhotographerRequired(terms) } } diff --git a/src/main/kotlin/com/damaba/damaba/application/photographer/PhotographerService.kt b/src/main/kotlin/com/damaba/damaba/application/photographer/PhotographerService.kt index 5d9bf516..2cd5aec9 100644 --- a/src/main/kotlin/com/damaba/damaba/application/photographer/PhotographerService.kt +++ b/src/main/kotlin/com/damaba/damaba/application/photographer/PhotographerService.kt @@ -1,5 +1,7 @@ package com.damaba.damaba.application.photographer +import com.damaba.damaba.application.term.AcceptPhotographerTermsCommand +import com.damaba.damaba.application.term.TermService import com.damaba.damaba.domain.common.Pagination import com.damaba.damaba.domain.photographer.Photographer import com.damaba.damaba.domain.photographer.PhotographerListItem @@ -25,6 +27,7 @@ class PhotographerService( private val photographerSaveRepo: PhotographerSaveRepository, private val promotionRepo: PromotionRepository, private val promotionSaveRepo: PromotionSaveRepository, + private val termService: TermService, ) { @Transactional fun register(command: RegisterPhotographerCommand): Photographer { @@ -46,7 +49,16 @@ class PhotographerService( mainPhotographyTypes = command.mainPhotographyTypes, activeRegions = command.activeRegions, ) - return photographerRepo.createIfUserExists(photographer) + val saved = photographerRepo.createIfUserExists(photographer) + + termService.acceptPhotographerTerms( + AcceptPhotographerTermsCommand( + userId = saved.id, + terms = command.terms, + ), + ) + + return saved } @Transactional diff --git a/src/main/kotlin/com/damaba/damaba/application/user/Command.kt b/src/main/kotlin/com/damaba/damaba/application/user/Command.kt index 274f3eb4..6361b072 100644 --- a/src/main/kotlin/com/damaba/damaba/application/user/Command.kt +++ b/src/main/kotlin/com/damaba/damaba/application/user/Command.kt @@ -1,6 +1,8 @@ package com.damaba.damaba.application.user +import com.damaba.damaba.application.term.TermItem import com.damaba.damaba.domain.file.Image +import com.damaba.damaba.domain.term.TermValidator import com.damaba.damaba.domain.user.UserValidator import com.damaba.damaba.domain.user.constant.Gender @@ -9,10 +11,12 @@ data class RegisterUserCommand( val nickname: String, val gender: Gender, val instagramId: String?, + val terms: List, ) { init { UserValidator.validateNickname(nickname) if (instagramId != null) UserValidator.validateInstagramId(instagramId) + TermValidator.validateUserRequired(terms) } } diff --git a/src/main/kotlin/com/damaba/damaba/application/user/UserService.kt b/src/main/kotlin/com/damaba/damaba/application/user/UserService.kt index b3d952b5..27b0bd57 100644 --- a/src/main/kotlin/com/damaba/damaba/application/user/UserService.kt +++ b/src/main/kotlin/com/damaba/damaba/application/user/UserService.kt @@ -1,5 +1,8 @@ package com.damaba.damaba.application.user +import com.damaba.damaba.application.term.AcceptUserTermsCommand +import com.damaba.damaba.application.term.TermItem +import com.damaba.damaba.application.term.TermService import com.damaba.damaba.domain.user.User import com.damaba.damaba.domain.user.exception.NicknameAlreadyExistsException import com.damaba.damaba.domain.user.exception.UserAlreadyRegisteredException @@ -16,6 +19,7 @@ class UserService( private val userRepo: UserRepository, private val photographerSaveRepo: PhotographerSaveRepository, private val promotionSaveRepo: PromotionSaveRepository, + private val termService: TermService, ) { @Transactional(readOnly = true) fun getUser(userId: Long): User = userRepo.getById(userId) @@ -49,7 +53,16 @@ class UserService( gender = command.gender, instagramId = command.instagramId, ) - return userRepo.update(user) + val saved = userRepo.update(user) + + val termItems: List = command.terms + termService.acceptUserTerms( + AcceptUserTermsCommand( + userId = saved.id, + terms = termItems, + ), + ) + return saved } @Transactional diff --git a/src/main/kotlin/com/damaba/damaba/controller/photographer/Request.kt b/src/main/kotlin/com/damaba/damaba/controller/photographer/Request.kt index fe63f8be..50bf15e1 100644 --- a/src/main/kotlin/com/damaba/damaba/controller/photographer/Request.kt +++ b/src/main/kotlin/com/damaba/damaba/controller/photographer/Request.kt @@ -3,10 +3,13 @@ package com.damaba.damaba.controller.photographer import com.damaba.damaba.application.photographer.RegisterPhotographerCommand import com.damaba.damaba.application.photographer.UpdatePhotographerPageCommand import com.damaba.damaba.application.photographer.UpdatePhotographerProfileCommand +import com.damaba.damaba.application.term.TermItem import com.damaba.damaba.controller.common.AddressRequest import com.damaba.damaba.controller.common.ImageRequest import com.damaba.damaba.controller.region.RegionRequest +import com.damaba.damaba.controller.term.AgreementRequestItem import com.damaba.damaba.domain.common.constant.PhotographyType +import com.damaba.damaba.domain.term.TermType import com.damaba.damaba.domain.user.constant.Gender import com.damaba.damaba.mapper.AddressMapper import com.damaba.damaba.mapper.ImageMapper @@ -20,6 +23,7 @@ data class RegisterPhotographerRequest( val profileImage: ImageRequest, val mainPhotographyTypes: Set, val activeRegions: Set, + val agreements: List, ) { fun toCommand(requesterId: Long) = RegisterPhotographerCommand( userId = requesterId, @@ -29,6 +33,7 @@ data class RegisterPhotographerRequest( profileImage = ImageMapper.INSTANCE.toImage(profileImage), mainPhotographyTypes = mainPhotographyTypes, activeRegions = activeRegions.map { regionRequest -> RegionMapper.INSTANCE.toRegion(regionRequest) }.toSet(), + terms = agreements.map { TermItem(it.type, it.agreed) }, ) } @@ -69,4 +74,12 @@ data class UpdateMyPhotographerProfileRequest( mainPhotographyTypes = this.mainPhotographyTypes, activeRegions = this.activeRegions.map { RegionMapper.INSTANCE.toRegion(it) }.toSet(), ) + + data class AgreementRequestItem( + @Schema(description = "약관 종류", example = "SERVICE_TERMS") + val type: TermType, + + @Schema(description = "사용자 동의 여부", example = "ture") + val agreed: Boolean, + ) } diff --git a/src/main/kotlin/com/damaba/damaba/controller/user/Request.kt b/src/main/kotlin/com/damaba/damaba/controller/user/Request.kt index 3846d988..2650bd82 100644 --- a/src/main/kotlin/com/damaba/damaba/controller/user/Request.kt +++ b/src/main/kotlin/com/damaba/damaba/controller/user/Request.kt @@ -1,8 +1,10 @@ package com.damaba.damaba.controller.user +import com.damaba.damaba.application.term.TermItem import com.damaba.damaba.application.user.RegisterUserCommand import com.damaba.damaba.application.user.UpdateUserProfileCommand import com.damaba.damaba.controller.common.ImageRequest +import com.damaba.damaba.controller.term.AgreementRequestItem import com.damaba.damaba.domain.user.constant.Gender import com.damaba.damaba.mapper.ImageMapper import io.swagger.v3.oas.annotations.media.Schema @@ -16,12 +18,16 @@ data class RegisterUserRequest( @Schema(description = "인스타 아이디", example = "damaba.unofficial") val instagramId: String?, + + @Schema(description = "동의한 약관 목록") + val agreements: List, ) { fun toCommand(requestUserId: Long) = RegisterUserCommand( userId = requestUserId, nickname = nickname, gender = gender, instagramId = instagramId, + terms = agreements.map { TermItem(it.type, it.agreed) }, ) } @@ -42,3 +48,11 @@ data class UpdateMyProfileRequest( profileImage = profileImage?.let { ImageMapper.INSTANCE.toImage(it) }, ) } + +data class AgreementRequestItem( + @Schema(description = "약관 종류", example = "SERVICE_TERMS") + val type: String, + + @Schema(description = "사용자 동의 여부", example = "true") + val agreed: Boolean, +) From 658f79a38e192876af4977107a4fe9402120c855 Mon Sep 17 00:00:00 2001 From: yoonseo8167 Date: Wed, 6 Aug 2025 19:21:56 +0900 Subject: [PATCH 07/15] =?UTF-8?q?modify:=20#164=20TermController=20?= =?UTF-8?q?=EC=95=88=EC=93=B0=EB=8A=94=20api=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../damaba/controller/term/TermController.kt | 45 +------------------ 1 file changed, 1 insertion(+), 44 deletions(-) diff --git a/src/main/kotlin/com/damaba/damaba/controller/term/TermController.kt b/src/main/kotlin/com/damaba/damaba/controller/term/TermController.kt index 2f576cea..83fb9e37 100644 --- a/src/main/kotlin/com/damaba/damaba/controller/term/TermController.kt +++ b/src/main/kotlin/com/damaba/damaba/controller/term/TermController.kt @@ -2,18 +2,12 @@ package com.damaba.damaba.controller.term import com.damaba.damaba.application.term.TermService import com.damaba.damaba.domain.term.TermType -import com.damaba.damaba.domain.user.User import io.swagger.v3.oas.annotations.Operation -import io.swagger.v3.oas.annotations.media.Content import io.swagger.v3.oas.annotations.responses.ApiResponse import io.swagger.v3.oas.annotations.responses.ApiResponses -import io.swagger.v3.oas.annotations.security.SecurityRequirement import io.swagger.v3.oas.annotations.tags.Tag import org.springframework.http.ResponseEntity -import org.springframework.security.core.annotation.AuthenticationPrincipal import org.springframework.web.bind.annotation.GetMapping -import org.springframework.web.bind.annotation.PostMapping -import org.springframework.web.bind.annotation.RequestBody import org.springframework.web.bind.annotation.RestController @Tag(name = "서비스 약관 동의 API") @@ -21,46 +15,9 @@ import org.springframework.web.bind.annotation.RestController class TermController( private val termService: TermService, ) { - - @Operation( - summary = "유저 서비스 약관 동의 제출", - description = "

일반 유저용 약관 3개 제출", - security = [SecurityRequirement(name = "access-token")], - ) - @ApiResponses( - ApiResponse(responseCode = "200"), - ApiResponse(responseCode = "404", description = "유저 정보를 찾을 수 없는 경우", content = [Content()]), - ) - @PostMapping("/api/v1/users/me/terms/agree") - fun acceptUserTerms( - @AuthenticationPrincipal requestUser: User, - @RequestBody request: UserTermRequest, - ): ResponseEntity { - termService.acceptUserTerms(request.toUserCommand(requestUser.id)) - return ResponseEntity.noContent().build() - } - - @Operation( - summary = "작가 서비스 약관 동의 제출", - description = "

사진 작가용 약관 4개 제출", - security = [SecurityRequirement(name = "access-token")], - ) - @ApiResponses( - ApiResponse(responseCode = "200"), - ApiResponse(responseCode = "404", description = "유저 정보를 찾을 수 없는 경우", content = [Content()]), - ) - @PostMapping("/api/v1/photographers/me/terms/agree") - fun acceptPhotographerTerms( - @AuthenticationPrincipal requestUser: User, - @RequestBody request: UserTermRequest, - ): ResponseEntity { - termService.acceptPhotographerTerms(request.toPhotographerCommand(requestUser.id)) - return ResponseEntity.noContent().build() - } - @Operation( summary = "약관 메타데이터 조회", - description = "모든 약관 종류(type), 필수 여부(required), 상세 URL(detailUrl)을 반환한다.", + description = "모든 약관 종류(type), 필수 여부(required)를 반환한다.", ) @ApiResponses( ApiResponse(responseCode = "200"), From 57e90b6e7762afc2c4c5ad7151fac7e873240854 Mon Sep 17 00:00:00 2001 From: yoonseo8167 Date: Wed, 6 Aug 2025 19:32:09 +0900 Subject: [PATCH 08/15] =?UTF-8?q?docs:=20#164=20example=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/damaba/damaba/controller/user/Request.kt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/com/damaba/damaba/controller/user/Request.kt b/src/main/kotlin/com/damaba/damaba/controller/user/Request.kt index 2650bd82..87ca2a85 100644 --- a/src/main/kotlin/com/damaba/damaba/controller/user/Request.kt +++ b/src/main/kotlin/com/damaba/damaba/controller/user/Request.kt @@ -19,7 +19,16 @@ data class RegisterUserRequest( @Schema(description = "인스타 아이디", example = "damaba.unofficial") val instagramId: String?, - @Schema(description = "동의한 약관 목록") + @Schema( + description = "동의한 약관 목록", + example = """ + [ + { "type": "AGE_CONFIRMATION", "agreed": true }, + { "type": "SERVICE_TERMS", "agreed": true }, + { "type": "PRIVACY_TERMS", "agreed": true } + ] + """, + ) val agreements: List, ) { fun toCommand(requestUserId: Long) = RegisterUserCommand( From f67542c0c1f5073961924d34f62945f5bd586543 Mon Sep 17 00:00:00 2001 From: yoonseo8167 Date: Wed, 6 Aug 2025 19:32:35 +0900 Subject: [PATCH 09/15] =?UTF-8?q?refactor:=20#164=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=20dto=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../damaba/damaba/controller/term/Request.kt | 22 ++----------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/src/main/kotlin/com/damaba/damaba/controller/term/Request.kt b/src/main/kotlin/com/damaba/damaba/controller/term/Request.kt index 099d25fe..b50510db 100644 --- a/src/main/kotlin/com/damaba/damaba/controller/term/Request.kt +++ b/src/main/kotlin/com/damaba/damaba/controller/term/Request.kt @@ -1,8 +1,7 @@ +@file:Suppress("ktlint:standard:filename") + package com.damaba.damaba.controller.term -import com.damaba.damaba.application.term.AcceptPhotographerTermsCommand -import com.damaba.damaba.application.term.AcceptUserTermsCommand -import com.damaba.damaba.application.term.TermItem import com.damaba.damaba.domain.term.TermType import io.swagger.v3.oas.annotations.media.Schema @@ -13,20 +12,3 @@ data class AgreementRequestItem( @Schema(description = "사용자의 동의 여부") val agreed: Boolean, ) - -data class UserTermRequest( - @Schema( - description = "사용자가 동의한 약관 항목들", - ) - val agreements: List, -) { - fun toUserCommand(userId: Long): AcceptUserTermsCommand = AcceptUserTermsCommand( - userId = userId, - terms = agreements.map { TermItem(it.type, it.agreed) }, - ) - - fun toPhotographerCommand(userId: Long): AcceptPhotographerTermsCommand = AcceptPhotographerTermsCommand( - userId = userId, - terms = agreements.map { TermItem(it.type, it.agreed) }, - ) -} From e01bca554192cde3f66e8d044f7976350e966cd5 Mon Sep 17 00:00:00 2001 From: yoonseo8167 Date: Wed, 6 Aug 2025 19:56:40 +0900 Subject: [PATCH 10/15] =?UTF-8?q?feat:=20#164=20=EC=95=BD=EA=B4=80=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20api=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../damaba/controller/term/TermController.kt | 43 +++++++++++++------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/src/main/kotlin/com/damaba/damaba/controller/term/TermController.kt b/src/main/kotlin/com/damaba/damaba/controller/term/TermController.kt index 83fb9e37..0832c538 100644 --- a/src/main/kotlin/com/damaba/damaba/controller/term/TermController.kt +++ b/src/main/kotlin/com/damaba/damaba/controller/term/TermController.kt @@ -8,28 +8,47 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses import io.swagger.v3.oas.annotations.tags.Tag import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController -@Tag(name = "서비스 약관 동의 API") +@Tag(name = "서비스 약관 동의 관련 API") @RestController +@RequestMapping("/api/v1/terms") class TermController( private val termService: TermService, ) { + /** + * 일반 유저의 서비스 약관 동의 목록 조회 (type, required) + */ @Operation( - summary = "약관 메타데이터 조회", - description = "모든 약관 종류(type), 필수 여부(required)를 반환한다.", + summary = "회원용 약관 목록 조회", + description = "가입 시 일반 유저가 동의해야 하는 약관 동의 목록 조회", ) @ApiResponses( ApiResponse(responseCode = "200"), ) - @GetMapping("/api/v1/terms/metadata") - fun getTermMetadata(): ResponseEntity> { - val metadata = TermType.values().map { - TermMetadataResponse( - type = it, - required = it.required, - ) - } - return ResponseEntity.ok(metadata) + @GetMapping("/user") + fun getUserTerms(): ResponseEntity> { + val userTerms = TermType.values() + .filter { it != TermType.PHOTOGRAPHER_TERMS } + .map { TermMetadataResponse(type = it, required = it.required) } + return ResponseEntity.ok(userTerms) + } + + /** + * 사진 작가의 서비스 약관 동의 목록 조회 (type, required) + */ + @Operation( + summary = "작가용 약관 목록 조회", + description = "가입 시 작가가 동의해야 하는 약관 동의 목록 조회", + ) + @ApiResponses( + ApiResponse(responseCode = "200"), + ) + @GetMapping("/photographer") + fun getPhotographerTerms(): ResponseEntity> { + val photographerTerms = TermType.values() + .map { TermMetadataResponse(type = it, required = it.required) } + return ResponseEntity.ok(photographerTerms) } } From 9e84704c004644dcba98169c3fe5e44ec70839f0 Mon Sep 17 00:00:00 2001 From: yoonseo8167 Date: Fri, 8 Aug 2025 10:52:44 +0900 Subject: [PATCH 11/15] =?UTF-8?q?refactor:=20#164=20=EC=84=9C=EB=B9=84?= =?UTF-8?q?=EC=8A=A4=20=EC=B0=B8=EC=A1=B0=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../photographer/PhotographerService.kt | 24 ++++++++++++------- .../damaba/application/user/UserService.kt | 24 +++++++++++-------- .../com/damaba/damaba/domain/term/Term.kt | 2 +- 3 files changed, 30 insertions(+), 20 deletions(-) diff --git a/src/main/kotlin/com/damaba/damaba/application/photographer/PhotographerService.kt b/src/main/kotlin/com/damaba/damaba/application/photographer/PhotographerService.kt index 2cd5aec9..23fc4d75 100644 --- a/src/main/kotlin/com/damaba/damaba/application/photographer/PhotographerService.kt +++ b/src/main/kotlin/com/damaba/damaba/application/photographer/PhotographerService.kt @@ -1,13 +1,13 @@ package com.damaba.damaba.application.photographer -import com.damaba.damaba.application.term.AcceptPhotographerTermsCommand -import com.damaba.damaba.application.term.TermService +import com.damaba.damaba.application.term.TermItem import com.damaba.damaba.domain.common.Pagination import com.damaba.damaba.domain.photographer.Photographer import com.damaba.damaba.domain.photographer.PhotographerListItem import com.damaba.damaba.domain.photographer.PhotographerSave import com.damaba.damaba.domain.photographer.exception.AlreadyPhotographerSaveException import com.damaba.damaba.domain.photographer.exception.PhotographerSaveNotFoundException +import com.damaba.damaba.domain.term.Term import com.damaba.damaba.domain.user.User import com.damaba.damaba.domain.user.exception.NicknameAlreadyExistsException import com.damaba.damaba.domain.user.exception.UserAlreadyRegisteredException @@ -15,6 +15,7 @@ import com.damaba.damaba.infrastructure.photographer.PhotographerRepository import com.damaba.damaba.infrastructure.photographer.PhotographerSaveRepository import com.damaba.damaba.infrastructure.promotion.PromotionRepository import com.damaba.damaba.infrastructure.promotion.PromotionSaveRepository +import com.damaba.damaba.infrastructure.term.TermRepository import com.damaba.damaba.infrastructure.user.UserRepository import com.damaba.damaba.mapper.PhotographerMapper import org.springframework.stereotype.Service @@ -27,7 +28,7 @@ class PhotographerService( private val photographerSaveRepo: PhotographerSaveRepository, private val promotionRepo: PromotionRepository, private val promotionSaveRepo: PromotionSaveRepository, - private val termService: TermService, + private val termRepo: TermRepository, ) { @Transactional fun register(command: RegisterPhotographerCommand): Photographer { @@ -51,12 +52,17 @@ class PhotographerService( ) val saved = photographerRepo.createIfUserExists(photographer) - termService.acceptPhotographerTerms( - AcceptPhotographerTermsCommand( - userId = saved.id, - terms = command.terms, - ), - ) + if (command.terms.isNotEmpty()) { + val termList: List = command.terms.map { item: TermItem -> + Term( + id = null, + userId = saved.id, + type = item.type, + agreed = item.agreed, + ) + } + termRepo.saveAll(termList) + } return saved } diff --git a/src/main/kotlin/com/damaba/damaba/application/user/UserService.kt b/src/main/kotlin/com/damaba/damaba/application/user/UserService.kt index 27b0bd57..d510f5e0 100644 --- a/src/main/kotlin/com/damaba/damaba/application/user/UserService.kt +++ b/src/main/kotlin/com/damaba/damaba/application/user/UserService.kt @@ -1,14 +1,14 @@ package com.damaba.damaba.application.user -import com.damaba.damaba.application.term.AcceptUserTermsCommand import com.damaba.damaba.application.term.TermItem -import com.damaba.damaba.application.term.TermService +import com.damaba.damaba.domain.term.Term import com.damaba.damaba.domain.user.User import com.damaba.damaba.domain.user.exception.NicknameAlreadyExistsException import com.damaba.damaba.domain.user.exception.UserAlreadyRegisteredException import com.damaba.damaba.domain.user.exception.UserNotFoundException import com.damaba.damaba.infrastructure.photographer.PhotographerSaveRepository import com.damaba.damaba.infrastructure.promotion.PromotionSaveRepository +import com.damaba.damaba.infrastructure.term.TermRepository import com.damaba.damaba.infrastructure.user.UserRepository import com.damaba.damaba.mapper.UserMapper import org.springframework.stereotype.Service @@ -19,7 +19,7 @@ class UserService( private val userRepo: UserRepository, private val photographerSaveRepo: PhotographerSaveRepository, private val promotionSaveRepo: PromotionSaveRepository, - private val termService: TermService, + private val termRepo: TermRepository, ) { @Transactional(readOnly = true) fun getUser(userId: Long): User = userRepo.getById(userId) @@ -55,13 +55,17 @@ class UserService( ) val saved = userRepo.update(user) - val termItems: List = command.terms - termService.acceptUserTerms( - AcceptUserTermsCommand( - userId = saved.id, - terms = termItems, - ), - ) + if (command.terms.isNotEmpty()) { + val termList: List = command.terms.map { item: TermItem -> + Term( + id = null, + userId = saved.id, + type = item.type, + agreed = item.agreed, + ) + } + termRepo.saveAll(termList) + } return saved } diff --git a/src/main/kotlin/com/damaba/damaba/domain/term/Term.kt b/src/main/kotlin/com/damaba/damaba/domain/term/Term.kt index 6855e691..685117d6 100644 --- a/src/main/kotlin/com/damaba/damaba/domain/term/Term.kt +++ b/src/main/kotlin/com/damaba/damaba/domain/term/Term.kt @@ -1,7 +1,7 @@ package com.damaba.damaba.domain.term class Term( - val id: Long, + val id: Long?, val userId: Long, val type: TermType, agreed: Boolean, From 7ed4f36e9d54822eb5f85140579901de2140840a Mon Sep 17 00:00:00 2001 From: yoonseo8167 Date: Fri, 8 Aug 2025 13:38:33 +0900 Subject: [PATCH 12/15] rebase: #164 rebase develop --- gradle/wrapper/gradle-wrapper.properties | 2 +- src/main/resources/application-local.yml | 1 + src/main/resources/application.yml | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0aaefbca..1af9e093 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml index fd3c642b..6b51674e 100644 --- a/src/main/resources/application-local.yml +++ b/src/main/resources/application-local.yml @@ -4,6 +4,7 @@ spring: jpa: properties: hibernate: + ddl-auto: update format_sql: true defer-datasource-initialization: false diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 48cbf451..26de4259 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -36,7 +36,7 @@ spring: jpa: hibernate: - ddl-auto: validate + ddl-auto: update open-in-view: false properties: hibernate: From afc7169775478ae042f6ec909ed21d6e49653926 Mon Sep 17 00:00:00 2001 From: yoonseo8167 Date: Fri, 25 Jul 2025 14:55:50 +0900 Subject: [PATCH 13/15] =?UTF-8?q?refactor:=20#164=20review=20=EB=B0=98?= =?UTF-8?q?=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/com/damaba/damaba/domain/term/Term.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/com/damaba/damaba/domain/term/Term.kt b/src/main/kotlin/com/damaba/damaba/domain/term/Term.kt index 685117d6..6855e691 100644 --- a/src/main/kotlin/com/damaba/damaba/domain/term/Term.kt +++ b/src/main/kotlin/com/damaba/damaba/domain/term/Term.kt @@ -1,7 +1,7 @@ package com.damaba.damaba.domain.term class Term( - val id: Long?, + val id: Long, val userId: Long, val type: TermType, agreed: Boolean, From 1c1ad1f16034e184bd9729cc0abe406f63ebe52c Mon Sep 17 00:00:00 2001 From: yoonseo8167 Date: Fri, 8 Aug 2025 10:52:44 +0900 Subject: [PATCH 14/15] =?UTF-8?q?refactor:=20#164=20=EC=84=9C=EB=B9=84?= =?UTF-8?q?=EC=8A=A4=20=EC=B0=B8=EC=A1=B0=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/com/damaba/damaba/domain/term/Term.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/com/damaba/damaba/domain/term/Term.kt b/src/main/kotlin/com/damaba/damaba/domain/term/Term.kt index 6855e691..685117d6 100644 --- a/src/main/kotlin/com/damaba/damaba/domain/term/Term.kt +++ b/src/main/kotlin/com/damaba/damaba/domain/term/Term.kt @@ -1,7 +1,7 @@ package com.damaba.damaba.domain.term class Term( - val id: Long, + val id: Long?, val userId: Long, val type: TermType, agreed: Boolean, From 538bb45f373107f8c0ebda74a0439a3ccb2dce0c Mon Sep 17 00:00:00 2001 From: yoonseo8167 Date: Fri, 8 Aug 2025 13:35:10 +0900 Subject: [PATCH 15/15] =?UTF-8?q?refactor:=20#164=20not=20null=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/damaba/damaba/application/user/UserService.kt | 2 +- src/main/kotlin/com/damaba/damaba/domain/term/Term.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/com/damaba/damaba/application/user/UserService.kt b/src/main/kotlin/com/damaba/damaba/application/user/UserService.kt index d510f5e0..6c6bd436 100644 --- a/src/main/kotlin/com/damaba/damaba/application/user/UserService.kt +++ b/src/main/kotlin/com/damaba/damaba/application/user/UserService.kt @@ -58,7 +58,7 @@ class UserService( if (command.terms.isNotEmpty()) { val termList: List = command.terms.map { item: TermItem -> Term( - id = null, + id = 0L, userId = saved.id, type = item.type, agreed = item.agreed, diff --git a/src/main/kotlin/com/damaba/damaba/domain/term/Term.kt b/src/main/kotlin/com/damaba/damaba/domain/term/Term.kt index 685117d6..6855e691 100644 --- a/src/main/kotlin/com/damaba/damaba/domain/term/Term.kt +++ b/src/main/kotlin/com/damaba/damaba/domain/term/Term.kt @@ -1,7 +1,7 @@ package com.damaba.damaba.domain.term class Term( - val id: Long?, + val id: Long, val userId: Long, val type: TermType, agreed: Boolean,