From 069dac206ee98e910e54f56f9491f835aec8c620 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Sat, 17 Feb 2024 11:21:05 +0900 Subject: [PATCH 001/174] Fix UserEntity to add columns --- .../withaeng/converter/UserRoleConverter.kt | 18 ++++++++++++++++ .../travel/withaeng/domain/user/SocialType.kt | 5 +++++ .../travel/withaeng/domain/user/UserEntity.kt | 21 +++++++++++++++---- .../travel/withaeng/domain/user/UserRole.kt | 8 +++++++ 4 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserRoleConverter.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/SocialType.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRole.kt diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserRoleConverter.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserRoleConverter.kt new file mode 100644 index 0000000..4d9b416 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserRoleConverter.kt @@ -0,0 +1,18 @@ +package com.travel.withaeng.converter + +import com.travel.withaeng.domain.user.UserRole +import jakarta.persistence.AttributeConverter + +class UserRoleConverter : AttributeConverter, String> { + override fun convertToDatabaseColumn(attribute: Set): String { + return attribute.joinToString(DELIMITER) { it.name } + } + + override fun convertToEntityAttribute(data: String): Set { + return data.split(DELIMITER).map { UserRole.valueOf(it.trim()) }.toSet() + } + + companion object { + private const val DELIMITER = "," + } +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/SocialType.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/SocialType.kt new file mode 100644 index 0000000..45ab907 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/SocialType.kt @@ -0,0 +1,5 @@ +package com.travel.withaeng.domain.user + +enum class SocialType { + NAVER, KAKAO, GOOGLE +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserEntity.kt index 369472b..cf91660 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserEntity.kt @@ -1,9 +1,8 @@ package com.travel.withaeng.domain.user +import com.travel.withaeng.converter.UserRoleConverter import com.travel.withaeng.domain.BaseEntity -import jakarta.persistence.Column -import jakarta.persistence.Entity -import jakarta.persistence.Table +import jakarta.persistence.* import java.time.LocalDate @Table(name = "users") @@ -12,6 +11,16 @@ class UserEntity( @Column(name = "nickname", nullable = false) val nickname: String, + @Column(name = "password", nullable = true) + val password: String? = null, + + @Enumerated(EnumType.STRING) + @Column(name = "social_type", nullable = true) + val socialType: SocialType? = null, + + @Column(name = "provider_unique_key", nullable = true) + val providerUniqueKey: String? = null, + @Column(name = "birth", nullable = false) val birth: LocalDate, @@ -22,5 +31,9 @@ class UserEntity( val profileImageUrl: String? = null, @Column(name = "bio") - val bio: String? = null + val bio: String? = null, + + @Convert(converter = UserRoleConverter::class) + @Column(name = "roles") + val roles: Set, ) : BaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRole.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRole.kt new file mode 100644 index 0000000..e4456f4 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRole.kt @@ -0,0 +1,8 @@ +package com.travel.withaeng.domain.user + +enum class UserRole( + val role: String +) { + USER("ROLE_USER"), + ADMIN("ROLE_ADMIN"), +} \ No newline at end of file From c77ae70d991ce5fc633656356c10778bce2dfd57 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Sat, 17 Feb 2024 11:47:01 +0900 Subject: [PATCH 002/174] Fix to configure project settings --- build.gradle.kts | 31 +++++++++++++++---------------- gradle.properties | 15 +++++++++++++++ settings.gradle.kts | 27 ++++++++++++++++++++++----- withaeng-api/build.gradle.kts | 4 ++-- withaeng-domain/build.gradle.kts | 13 +++++++++---- 5 files changed, 63 insertions(+), 27 deletions(-) create mode 100644 gradle.properties diff --git a/build.gradle.kts b/build.gradle.kts index 27bb2c2..eb947e6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,45 +1,44 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { - id("org.springframework.boot") version "3.2.2" - id("io.spring.dependency-management") version "1.1.4" - kotlin("jvm") version "1.9.22" - kotlin("plugin.spring") version "1.9.22" - kotlin("plugin.jpa") version "1.9.22" + kotlin("jvm") + kotlin("plugin.spring") apply false + kotlin("plugin.jpa") apply false + id("org.springframework.boot") apply false + id("io.spring.dependency-management") apply false } java { sourceCompatibility = JavaVersion.VERSION_17 } +val projectGroup: String by project +val applicationVersion: String by project allprojects { - group = "com.travel" - version = "0.0.1-SNAPSHOT" + group = projectGroup + version = applicationVersion repositories { mavenCentral() } } +val springMockkVersion: String by project.extra + subprojects { apply(plugin = "org.jetbrains.kotlin.jvm") apply(plugin = "org.jetbrains.kotlin.plugin.spring") + apply(plugin = "org.jetbrains.kotlin.plugin.jpa") apply(plugin = "org.springframework.boot") - apply(plugin = "kotlin") - apply(plugin = "java-library") - apply(plugin = "kotlin-jpa") apply(plugin = "io.spring.dependency-management") - apply(plugin = "kotlin-kapt") - apply(plugin = "application") dependencies { implementation("org.jetbrains.kotlin:kotlin-reflect") - developmentOnly("org.springframework.boot:spring-boot-devtools") implementation("com.fasterxml.jackson.module:jackson-module-kotlin") // SpringMockk testImplementation("org.springframework.boot:spring-boot-starter-test") - testImplementation("com.ninja-squad:springmockk:3.1.1") + testImplementation("com.ninja-squad:springmockk:$springMockkVersion") runtimeOnly("com.h2database:h2") } @@ -55,11 +54,11 @@ subprojects { useJUnitPlatform() } - tasks.bootJar { + tasks.getByName("bootJar") { enabled = false } - tasks.jar { + tasks.getByName("jar") { enabled = true } } \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..6779101 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,15 @@ +### Application version ### +applicationVersion=0.0.1 +### Project configs ### +projectGroup=com.travel +### Project dependency versions ### +kotlinVersion=1.9.22 +### Spring dependency versions ### +springBootVersion=3.2.2 +springDependencyManagementVersion=1.1.4 +### Spring mockk #### +springMockkVersion=3.1.1 +### Jasypt versions ### +jasyptVersion=3.0.5 +### Persistence versions ### +mysqlVersion=8.3.0 \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index e9481d9..74548cd 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,6 +1,23 @@ -plugins { - id("org.gradle.toolchains.foojay-resolver-convention") version "0.5.0" -} rootProject.name = "withaeng" -include("withaeng-api") -include("withaeng-domain") +include( + "withaeng-api", + "withaeng-domain" +) + +pluginManagement { + val kotlinVersion: String by settings + val springBootVersion: String by settings + val springDependencyManagementVersion: String by settings + + resolutionStrategy { + eachPlugin { + when (requested.id.id) { + "org.jetbrains.kotlin.jvm" -> useVersion(kotlinVersion) + "org.jetbrains.kotlin.plugin.spring" -> useVersion(kotlinVersion) + "org.jetbrains.kotlin.plugin.jpa" -> useVersion(kotlinVersion) + "org.springframework.boot" -> useVersion(springBootVersion) + "io.spring.dependency-management" -> useVersion(springDependencyManagementVersion) + } + } + } +} \ No newline at end of file diff --git a/withaeng-api/build.gradle.kts b/withaeng-api/build.gradle.kts index 76c63a2..0641370 100644 --- a/withaeng-api/build.gradle.kts +++ b/withaeng-api/build.gradle.kts @@ -1,8 +1,8 @@ -tasks.bootJar { +tasks.getByName("bootJar") { enabled = true } -tasks.jar { +tasks.getByName("jar") { enabled = false } diff --git a/withaeng-domain/build.gradle.kts b/withaeng-domain/build.gradle.kts index 357b4ff..ca4b2e8 100644 --- a/withaeng-domain/build.gradle.kts +++ b/withaeng-domain/build.gradle.kts @@ -1,9 +1,14 @@ -dependencies { - implementation("org.springframework.boot:spring-boot-starter-data-jpa") -} - allOpen { annotation("jakarta.persistence.Entity") annotation("jakarta.persistence.MappedSuperclass") annotation("jakarta.persistence.Embeddable") +} + +val jasyptVersion: String by project.extra +val mysqlVersion: String by project.extra +dependencies { + implementation("org.springframework.boot:spring-boot-starter-data-jpa") + runtimeOnly("com.mysql:mysql-connector-j:$mysqlVersion") + // jasypt + api("com.github.ulisesbocchio:jasypt-spring-boot-starter:$jasyptVersion") } \ No newline at end of file From 5d517f777256dcc13af546fc525b49dbcfe6a6b0 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Sat, 17 Feb 2024 12:11:59 +0900 Subject: [PATCH 003/174] Implement JasyptConfig --- .../travel/withaeng/config/JasyptConfig.kt | 8 ++++ .../withaeng/config/JasyptConfigTest.kt | 46 +++++++++++++++++++ .../withaeng/config/TestConfiguration.kt | 6 +++ 3 files changed, 60 insertions(+) create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/config/JasyptConfig.kt create mode 100644 withaeng-domain/src/test/kotlin/com/travel/withaeng/config/JasyptConfigTest.kt create mode 100644 withaeng-domain/src/test/kotlin/com/travel/withaeng/config/TestConfiguration.kt diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/config/JasyptConfig.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/config/JasyptConfig.kt new file mode 100644 index 0000000..6bf92d9 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/config/JasyptConfig.kt @@ -0,0 +1,8 @@ +package com.travel.withaeng.config + +import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties +import org.springframework.context.annotation.Configuration + +@EnableEncryptableProperties +@Configuration +class JasyptConfig \ No newline at end of file diff --git a/withaeng-domain/src/test/kotlin/com/travel/withaeng/config/JasyptConfigTest.kt b/withaeng-domain/src/test/kotlin/com/travel/withaeng/config/JasyptConfigTest.kt new file mode 100644 index 0000000..cbf2115 --- /dev/null +++ b/withaeng-domain/src/test/kotlin/com/travel/withaeng/config/JasyptConfigTest.kt @@ -0,0 +1,46 @@ +package com.travel.withaeng.config + +import com.ulisesbocchio.jasyptspringboot.encryptor.DefaultLazyEncryptor +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.annotation.Value +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.core.env.ConfigurableEnvironment +import org.springframework.test.context.junit.jupiter.SpringExtension + +@SpringBootTest +@ExtendWith(SpringExtension::class) +class JasyptConfigTest { + @Value("\${jasypt.encryptor.password}") + private lateinit var jasyptEncryptorPassword: String + + @Autowired + private lateinit var configurableEnvironment: ConfigurableEnvironment + private lateinit var encryptor: DefaultLazyEncryptor + + @BeforeEach + internal fun setUp() { + check(jasyptEncryptorPassword.isNotBlank()) { + "jasypt.encryptor.password must not be null, empty or blank. " + } + encryptor = DefaultLazyEncryptor(configurableEnvironment) + } + + @Test + fun testForEncryption() { + val source = "test" + println("source: $source") + println("encrypted: ${encryptor.encrypt(source)}") + } + + @Test + fun testForDecryption() { + val source = "test" + println("source: $source") + println("decrypted: ${encryptor.decrypt(source)}") + } +} \ No newline at end of file diff --git a/withaeng-domain/src/test/kotlin/com/travel/withaeng/config/TestConfiguration.kt b/withaeng-domain/src/test/kotlin/com/travel/withaeng/config/TestConfiguration.kt new file mode 100644 index 0000000..2a48f79 --- /dev/null +++ b/withaeng-domain/src/test/kotlin/com/travel/withaeng/config/TestConfiguration.kt @@ -0,0 +1,6 @@ +package com.travel.withaeng.config + +import org.springframework.boot.autoconfigure.SpringBootApplication + +@SpringBootApplication +class TestConfiguration \ No newline at end of file From 6c907276d279c7379248c4f5ec9bcad00d356617 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Sat, 17 Feb 2024 12:39:39 +0900 Subject: [PATCH 004/174] Configure application settings --- .../src/main/resources/application-local.yml | 4 ++++ .../src/main/resources/application.yml | 6 ++++++ .../resources/application-domain-local.yml | 12 ++++++++++++ .../src/main/resources/application-domain.yml | 18 ++++++++++++++++++ 4 files changed, 40 insertions(+) create mode 100644 withaeng-api/src/main/resources/application-local.yml create mode 100644 withaeng-api/src/main/resources/application.yml create mode 100644 withaeng-domain/src/main/resources/application-domain-local.yml create mode 100644 withaeng-domain/src/main/resources/application-domain.yml diff --git a/withaeng-api/src/main/resources/application-local.yml b/withaeng-api/src/main/resources/application-local.yml new file mode 100644 index 0000000..eb2416f --- /dev/null +++ b/withaeng-api/src/main/resources/application-local.yml @@ -0,0 +1,4 @@ +spring: + config: + activate: + on-profile: local \ No newline at end of file diff --git a/withaeng-api/src/main/resources/application.yml b/withaeng-api/src/main/resources/application.yml new file mode 100644 index 0000000..c95d6f0 --- /dev/null +++ b/withaeng-api/src/main/resources/application.yml @@ -0,0 +1,6 @@ +spring: + profiles: + default: local + config: + import: + - classpath:/application-domain.yml \ No newline at end of file diff --git a/withaeng-domain/src/main/resources/application-domain-local.yml b/withaeng-domain/src/main/resources/application-domain-local.yml new file mode 100644 index 0000000..3f5e62f --- /dev/null +++ b/withaeng-domain/src/main/resources/application-domain-local.yml @@ -0,0 +1,12 @@ +spring: + config: + activate: + on-profile: local + jpa: + hibernate: + ddl-auto: create + properties: + hibernate: + show_sql: true + format_sql: true + use_sql_comments: true \ No newline at end of file diff --git a/withaeng-domain/src/main/resources/application-domain.yml b/withaeng-domain/src/main/resources/application-domain.yml new file mode 100644 index 0000000..4ac5c1c --- /dev/null +++ b/withaeng-domain/src/main/resources/application-domain.yml @@ -0,0 +1,18 @@ +spring: + profiles: + default: local + + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: ENC(lFITsL+l7aOSMUY3hRT3aR4X0GV+yqIJfYMyXaMajbZZJSW+Lv5MTrbP5Cwa8XAUxGpH7A9GxRNAZtrDhf6V4yXkD6gf3RUYWsPp77Ieguo=) + username: ENC(s1UggVxVWnWC0WqrTpmXaLw+QCpZmkuj2kvSQp+zt2vwKLbRH6WDAZKYUR75DqsR) + password: ENC(HT2z+x9LrfoHTmTTCYLkx7cO0ru9Gcbh+YGnP/0MWC1BpBwQtPfWue+zQx5RPQg8) + + jpa: + hibernate: + ddl-auto: none + properties: + hibernate: + show_sql: false + format_sql: false + use_sql_comments: false \ No newline at end of file From f376468c86bef86811b3640260e3e8db975c4147 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Sat, 17 Feb 2024 13:00:08 +0900 Subject: [PATCH 005/174] Rename UserEntity to User --- .../com/travel/withaeng/domain/user/{UserEntity.kt => User.kt} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/{UserEntity.kt => User.kt} (98%) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt similarity index 98% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserEntity.kt rename to withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt index cf91660..03c6d5d 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt @@ -7,7 +7,7 @@ import java.time.LocalDate @Table(name = "users") @Entity -class UserEntity( +class User( @Column(name = "nickname", nullable = false) val nickname: String, From c11b4d3ba64acfc6eba0b4c64fdce0ec563a42e5 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Sat, 17 Feb 2024 13:00:31 +0900 Subject: [PATCH 006/174] Fix JasyptConfigTest disabled --- .../test/kotlin/com/travel/withaeng/config/JasyptConfigTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/withaeng-domain/src/test/kotlin/com/travel/withaeng/config/JasyptConfigTest.kt b/withaeng-domain/src/test/kotlin/com/travel/withaeng/config/JasyptConfigTest.kt index cbf2115..9d8ed5a 100644 --- a/withaeng-domain/src/test/kotlin/com/travel/withaeng/config/JasyptConfigTest.kt +++ b/withaeng-domain/src/test/kotlin/com/travel/withaeng/config/JasyptConfigTest.kt @@ -1,7 +1,6 @@ package com.travel.withaeng.config import com.ulisesbocchio.jasyptspringboot.encryptor.DefaultLazyEncryptor -import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test @@ -12,6 +11,7 @@ import org.springframework.boot.test.context.SpringBootTest import org.springframework.core.env.ConfigurableEnvironment import org.springframework.test.context.junit.jupiter.SpringExtension +@Disabled @SpringBootTest @ExtendWith(SpringExtension::class) class JasyptConfigTest { From 7a23d5db0a82bd351dce83f03f94eb9ac1d14316 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Sat, 17 Feb 2024 13:00:48 +0900 Subject: [PATCH 007/174] Add base repositories of entities --- .../src/main/kotlin/com/travel/withaeng/config/JpaConfig.kt | 5 +++++ .../com/travel/withaeng/domain/WithaengDomainModule.kt | 3 +++ .../travel/withaeng/domain/accompany/AccompanyRepository.kt | 5 +++++ .../withaeng/domain/accompanylike/AccompanyLikeRepository.kt | 5 +++++ .../domain/accompanyreply/AccompanyReplyRepository.kt | 5 +++++ .../accompanyreplylike/AccompanyReplyLikeRepository.kt | 5 +++++ .../kotlin/com/travel/withaeng/domain/user/UserRepository.kt | 5 +++++ 7 files changed, 33 insertions(+) create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/WithaengDomainModule.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeRepository.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRepository.kt diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/config/JpaConfig.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/config/JpaConfig.kt index ede6839..2f037cd 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/config/JpaConfig.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/config/JpaConfig.kt @@ -1,8 +1,13 @@ package com.travel.withaeng.config +import com.travel.withaeng.domain.WithaengDomainModule +import org.springframework.boot.autoconfigure.domain.EntityScan import org.springframework.context.annotation.Configuration import org.springframework.data.jpa.repository.config.EnableJpaAuditing +import org.springframework.data.jpa.repository.config.EnableJpaRepositories @EnableJpaAuditing @Configuration +@EntityScan(basePackageClasses = [WithaengDomainModule::class]) +@EnableJpaRepositories(basePackageClasses = [WithaengDomainModule::class]) class JpaConfig \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/WithaengDomainModule.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/WithaengDomainModule.kt new file mode 100644 index 0000000..509cc53 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/WithaengDomainModule.kt @@ -0,0 +1,3 @@ +package com.travel.withaeng.domain + +interface WithaengDomainModule \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt new file mode 100644 index 0000000..42cea7f --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt @@ -0,0 +1,5 @@ +package com.travel.withaeng.domain.accompany + +import org.springframework.data.jpa.repository.JpaRepository + +interface AccompanyRepository : JpaRepository \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeRepository.kt new file mode 100644 index 0000000..fc87030 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeRepository.kt @@ -0,0 +1,5 @@ +package com.travel.withaeng.domain.accompanylike + +import org.springframework.data.jpa.repository.JpaRepository + +interface AccompanyLikeRepository : JpaRepository \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt new file mode 100644 index 0000000..ba21cf8 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt @@ -0,0 +1,5 @@ +package com.travel.withaeng.domain.accompanyreply + +import org.springframework.data.jpa.repository.JpaRepository + +interface AccompanyReplyRepository : JpaRepository \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt new file mode 100644 index 0000000..3cd5280 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt @@ -0,0 +1,5 @@ +package com.travel.withaeng.domain.accompanyreplylike + +import org.springframework.data.jpa.repository.JpaRepository + +interface AccompanyReplyLikeRepository : JpaRepository \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRepository.kt new file mode 100644 index 0000000..e069c1d --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRepository.kt @@ -0,0 +1,5 @@ +package com.travel.withaeng.domain.user + +import org.springframework.data.jpa.repository.JpaRepository + +interface UserRepository : JpaRepository \ No newline at end of file From cf3d08716ebabf8910a36c045b257599d81e91be Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Sat, 17 Feb 2024 13:24:53 +0900 Subject: [PATCH 008/174] Add WithaengExceptions --- settings.gradle.kts | 3 +- withaeng-api/build.gradle.kts | 1 + withaeng-common/build.gradle.kts | 1 + .../common/exception/WithaengException.kt | 25 ++++++++++++++ .../common/exception/WithaengExceptionType.kt | 34 +++++++++++++++++++ withaeng-domain/build.gradle.kts | 1 + 6 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 withaeng-common/build.gradle.kts create mode 100644 withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/WithaengException.kt create mode 100644 withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/WithaengExceptionType.kt diff --git a/settings.gradle.kts b/settings.gradle.kts index 74548cd..96f5936 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,7 +1,8 @@ rootProject.name = "withaeng" include( "withaeng-api", - "withaeng-domain" + "withaeng-domain", + "withaeng-common" ) pluginManagement { diff --git a/withaeng-api/build.gradle.kts b/withaeng-api/build.gradle.kts index 0641370..80633c2 100644 --- a/withaeng-api/build.gradle.kts +++ b/withaeng-api/build.gradle.kts @@ -8,5 +8,6 @@ tasks.getByName("jar") { dependencies { implementation(project(":withaeng-domain")) + implementation(project(":withaeng-common")) implementation("org.springframework.boot:spring-boot-starter-web") } \ No newline at end of file diff --git a/withaeng-common/build.gradle.kts b/withaeng-common/build.gradle.kts new file mode 100644 index 0000000..405438b --- /dev/null +++ b/withaeng-common/build.gradle.kts @@ -0,0 +1 @@ +dependencies { } \ No newline at end of file diff --git a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/WithaengException.kt b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/WithaengException.kt new file mode 100644 index 0000000..267d2dd --- /dev/null +++ b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/WithaengException.kt @@ -0,0 +1,25 @@ +package com.travel.withaeng.common.exception + +class WithaengException( + val errorCode: String, + val httpStatusCode: Int, + override val message: String, +) : RuntimeException() { + companion object { + fun of(type: WithaengExceptionType): WithaengException { + return WithaengException( + errorCode = type.errorCode, + httpStatusCode = type.httpStatusCode, + message = type.message, + ) + } + + fun of(type: WithaengExceptionType, message: String): WithaengException { + return WithaengException( + errorCode = type.errorCode, + httpStatusCode = type.httpStatusCode, + message = message, + ) + } + } +} diff --git a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/WithaengExceptionType.kt b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/WithaengExceptionType.kt new file mode 100644 index 0000000..5ec50de --- /dev/null +++ b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/WithaengExceptionType.kt @@ -0,0 +1,34 @@ +package com.travel.withaeng.common.exception + +enum class WithaengExceptionType( + val message: String, + val errorCode: String, + val httpStatusCode: Int, +) { + // USER + AUTH_ERROR("유저 프로세스에서 오류가 발생했습니다.", "U000_AUTH_ERROR", 500), + EMPTY_AUTHORIZATION_HEADER("Not Exist Authorization Header", "U001_EMPTY_AUTHORIZATION_HEADER", 400), + INVALID_USER_AUTH_TOKEN("Invalid JWT Token", "U002_INVALID_TOKEN", 400), + INVALID_AUTH_PROVIDER( + "Invalid provider by auth0. Check social section of auth0", + "U003_INVALID_AUTH_PROVIDER", + 500 + ), + EMPTY_FCM_TOKEN("Not Exist FCM Token", "U004_EMPTY_FCM_TOKEN", 400), + + // COMMON + NOT_EXIST("존재하지 않습니다.", "C001_NOT_EXIST", 404), + SYSTEM_FAIL("Internal Server Error.", "C002_SYSTEM_FAIL", 500), + INVALID_ACCESS("Invalid Access", "C003_INVALID_ACCESS", 403), + ALREADY_EXIST("Already Exist", "C004_ALREADY_EXIST", 409), + INVALID_INPUT("Invalid Input", "C004_INVALID_INPUT", 400), + METHOD_ARGUMENT_TYPE_MISMATCH_VALUE("Request method argument type mismatch", "C005_TYPE_MISMATCH_VALUE", 400), + HTTP_REQUEST_METHOD_NOT_SUPPORTED("HTTP request method not supported", "C006_HTTP_METHOD_NOT_SUPPORTED", 400), + ACCESS_DENIED("Access denied. Check authentication.", "C007_ACCESS_DENIED", 403), + AUTHENTICATION_FAILURE("Authentication failed. Check login.", "C008_AUTHENTICATION_FAILURE", 401), + ARGUMENT_NOT_VALID("Method Argument Not Valid. Check argument validation.", "C009_ARGUMENT_NOT_VALID", 400), + + // NOTIFICATION + INVALID_NOTIFICATION_TYPE("Invalid Notification Type", "N001_INVALID_NOTIFICATION_TYPE", 500), + ; +} diff --git a/withaeng-domain/build.gradle.kts b/withaeng-domain/build.gradle.kts index ca4b2e8..7a98a52 100644 --- a/withaeng-domain/build.gradle.kts +++ b/withaeng-domain/build.gradle.kts @@ -7,6 +7,7 @@ allOpen { val jasyptVersion: String by project.extra val mysqlVersion: String by project.extra dependencies { + implementation(project(":withaeng-common")) implementation("org.springframework.boot:spring-boot-starter-data-jpa") runtimeOnly("com.mysql:mysql-connector-j:$mysqlVersion") // jasypt From b1ea42afafbc30a909c0ff6940697addd48a98fc Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Sat, 2 Mar 2024 03:10:05 +0900 Subject: [PATCH 009/174] Implement UserService --- .../com/travel/withaeng/domain/user/User.kt | 46 ++++++++++++++----- .../travel/withaeng/domain/user/UserDto.kt | 37 +++++++++++++++ .../withaeng/domain/user/UserRepository.kt | 4 +- .../withaeng/domain/user/UserService.kt | 29 ++++++++++++ 4 files changed, 103 insertions(+), 13 deletions(-) create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserDto.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt index 03c6d5d..7b0ccf8 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt @@ -11,21 +11,18 @@ class User( @Column(name = "nickname", nullable = false) val nickname: String, - @Column(name = "password", nullable = true) - val password: String? = null, - @Enumerated(EnumType.STRING) - @Column(name = "social_type", nullable = true) - val socialType: SocialType? = null, + @Column(name = "social_type", nullable = false) + val socialType: SocialType, - @Column(name = "provider_unique_key", nullable = true) - val providerUniqueKey: String? = null, + @Column(name = "provider_unique_key", nullable = false) + val providerUniqueKey: String, - @Column(name = "birth", nullable = false) - val birth: LocalDate, + @Column(name = "birth", nullable = true) + val birth: LocalDate? = null, - @Column(name = "is_male", nullable = false) - val isMale: Boolean, + @Column(name = "is_male", nullable = true) + val isMale: Boolean? = null, @Column(name = "profile_image_url") val profileImageUrl: String? = null, @@ -36,4 +33,29 @@ class User( @Convert(converter = UserRoleConverter::class) @Column(name = "roles") val roles: Set, -) : BaseEntity() \ No newline at end of file +) : BaseEntity() { + + companion object { + + fun create( + nickname: String, + socialType: SocialType, + providerUniqueKey: String, + birth: LocalDate? = null, + isMale: Boolean? = null, + profileImageUrl: String? = null, + bio: String? = null, + ): User { + return User( + nickname = nickname, + socialType = socialType, + profileImageUrl = profileImageUrl, + providerUniqueKey = providerUniqueKey, + birth = birth, + isMale = isMale, + bio = bio, + roles = setOf(UserRole.USER) + ) + } + } +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserDto.kt new file mode 100644 index 0000000..0274801 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserDto.kt @@ -0,0 +1,37 @@ +package com.travel.withaeng.domain.user + +import java.time.LocalDate + +data class UserDto( + val id: Long, + val nickname: String, + val socialType: SocialType, + val providerUniqueKey: String, + val birth: LocalDate? = null, + val isMale: Boolean? = null, + val profileImageUrl: String? = null, + val bio: String? = null, + val roles: Set +) + +fun User.toDto(): UserDto = UserDto( + id = id, + nickname = nickname, + socialType = socialType, + providerUniqueKey = providerUniqueKey, + birth = birth, + isMale = isMale, + profileImageUrl = profileImageUrl, + bio = bio, + roles = roles +) + +data class CreateUserDto( + val nickname: String, + val socialType: SocialType, + val providerUniqueKey: String, + val birth: LocalDate? = null, + val isMale: Boolean? = null, + val profileImageUrl: String? = null, + val bio: String? = null, +) \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRepository.kt index e069c1d..fb6bb7d 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRepository.kt @@ -2,4 +2,6 @@ package com.travel.withaeng.domain.user import org.springframework.data.jpa.repository.JpaRepository -interface UserRepository : JpaRepository \ No newline at end of file +interface UserRepository : JpaRepository { + fun findByProviderUniqueKey(providerUniqueKey: String): User? +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt new file mode 100644 index 0000000..5529010 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt @@ -0,0 +1,29 @@ +package com.travel.withaeng.domain.user + +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional + +@Service +@Transactional(readOnly = true) +class UserService(private val userRepository: UserRepository) { + + @Transactional + fun createUser(createUserDto: CreateUserDto): UserDto { + return userRepository.save( + User.create( + nickname = createUserDto.nickname, + socialType = createUserDto.socialType, + profileImageUrl = createUserDto.profileImageUrl, + providerUniqueKey = createUserDto.providerUniqueKey, + birth = createUserDto.birth, + isMale = createUserDto.isMale, + bio = createUserDto.bio + ) + ).toDto() + } + + fun findByProviderUniqueKeyOrNull(providerUniqueKey: String): UserDto? { + return userRepository.findByProviderUniqueKey(providerUniqueKey)?.toDto() + } + +} \ No newline at end of file From 897732444d6b907910505863afbea5bdc1dd0b91 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Sat, 23 Mar 2024 10:43:52 +0900 Subject: [PATCH 010/174] Fix User columns --- .../travel/withaeng/domain/user/SocialType.kt | 5 ---- .../com/travel/withaeng/domain/user/User.kt | 26 ++++++++++--------- .../travel/withaeng/domain/user/UserDto.kt | 12 ++++----- .../withaeng/domain/user/UserRepository.kt | 4 +-- .../withaeng/domain/user/UserService.kt | 9 ++----- 5 files changed, 23 insertions(+), 33 deletions(-) delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/SocialType.kt diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/SocialType.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/SocialType.kt deleted file mode 100644 index 45ab907..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/SocialType.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.travel.withaeng.domain.user - -enum class SocialType { - NAVER, KAKAO, GOOGLE -} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt index 7b0ccf8..510f880 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt @@ -2,21 +2,23 @@ package com.travel.withaeng.domain.user import com.travel.withaeng.converter.UserRoleConverter import com.travel.withaeng.domain.BaseEntity -import jakarta.persistence.* +import jakarta.persistence.Column +import jakarta.persistence.Convert +import jakarta.persistence.Entity +import jakarta.persistence.Table import java.time.LocalDate @Table(name = "users") @Entity class User( - @Column(name = "nickname", nullable = false) - val nickname: String, + @Column(name = "email", nullable = false) + val email: String, - @Enumerated(EnumType.STRING) - @Column(name = "social_type", nullable = false) - val socialType: SocialType, + @Column(name = "password", nullable = false) + val password: String, - @Column(name = "provider_unique_key", nullable = false) - val providerUniqueKey: String, + @Column(name = "nickname", nullable = false) + val nickname: String, @Column(name = "birth", nullable = true) val birth: LocalDate? = null, @@ -38,19 +40,19 @@ class User( companion object { fun create( + email: String, + password: String, nickname: String, - socialType: SocialType, - providerUniqueKey: String, birth: LocalDate? = null, isMale: Boolean? = null, profileImageUrl: String? = null, bio: String? = null, ): User { return User( + email = email, + password = password, nickname = nickname, - socialType = socialType, profileImageUrl = profileImageUrl, - providerUniqueKey = providerUniqueKey, birth = birth, isMale = isMale, bio = bio, diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserDto.kt index 0274801..dfc9c46 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserDto.kt @@ -4,9 +4,9 @@ import java.time.LocalDate data class UserDto( val id: Long, + val email: String, + val password: String, val nickname: String, - val socialType: SocialType, - val providerUniqueKey: String, val birth: LocalDate? = null, val isMale: Boolean? = null, val profileImageUrl: String? = null, @@ -16,9 +16,9 @@ data class UserDto( fun User.toDto(): UserDto = UserDto( id = id, + email = email, + password = password, nickname = nickname, - socialType = socialType, - providerUniqueKey = providerUniqueKey, birth = birth, isMale = isMale, profileImageUrl = profileImageUrl, @@ -27,9 +27,9 @@ fun User.toDto(): UserDto = UserDto( ) data class CreateUserDto( + val email: String, + val password: String, val nickname: String, - val socialType: SocialType, - val providerUniqueKey: String, val birth: LocalDate? = null, val isMale: Boolean? = null, val profileImageUrl: String? = null, diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRepository.kt index fb6bb7d..e069c1d 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRepository.kt @@ -2,6 +2,4 @@ package com.travel.withaeng.domain.user import org.springframework.data.jpa.repository.JpaRepository -interface UserRepository : JpaRepository { - fun findByProviderUniqueKey(providerUniqueKey: String): User? -} \ No newline at end of file +interface UserRepository : JpaRepository \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt index 5529010..03ecc0e 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt @@ -11,19 +11,14 @@ class UserService(private val userRepository: UserRepository) { fun createUser(createUserDto: CreateUserDto): UserDto { return userRepository.save( User.create( + email = createUserDto.email, + password = createUserDto.password, nickname = createUserDto.nickname, - socialType = createUserDto.socialType, profileImageUrl = createUserDto.profileImageUrl, - providerUniqueKey = createUserDto.providerUniqueKey, birth = createUserDto.birth, isMale = createUserDto.isMale, bio = createUserDto.bio ) ).toDto() } - - fun findByProviderUniqueKeyOrNull(providerUniqueKey: String): UserDto? { - return userRepository.findByProviderUniqueKey(providerUniqueKey)?.toDto() - } - } \ No newline at end of file From 6918405d84333005308cba8271aa3ccb2c278aff Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Sat, 23 Mar 2024 10:44:09 +0900 Subject: [PATCH 011/174] Implement ControllerExceptionAdvice --- .../common/ControllerExceptionAdvice.kt | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/common/ControllerExceptionAdvice.kt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ControllerExceptionAdvice.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ControllerExceptionAdvice.kt new file mode 100644 index 0000000..fe64f88 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ControllerExceptionAdvice.kt @@ -0,0 +1,96 @@ +package com.travel.withaeng.common + +import com.travel.withaeng.common.exception.WithaengException +import com.travel.withaeng.common.exception.WithaengExceptionType +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import org.springframework.http.HttpStatus +import org.springframework.http.ResponseEntity +import org.springframework.validation.BindException +import org.springframework.web.HttpRequestMethodNotSupportedException +import org.springframework.web.bind.MethodArgumentNotValidException +import org.springframework.web.bind.MissingServletRequestParameterException +import org.springframework.web.bind.annotation.ExceptionHandler +import org.springframework.web.bind.annotation.RestControllerAdvice +import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException + +@RestControllerAdvice +class ControllerExceptionAdvice { + + private val logger: Logger = LoggerFactory.getLogger(ControllerExceptionAdvice::class.java) + + @ExceptionHandler(Exception::class) + fun handleException(ex: Exception): ResponseEntity> { + logger.error("Exception handler", ex) + return errorResponse(WithaengExceptionType.SYSTEM_FAIL, ex.message) + } + + @ExceptionHandler(WithaengException::class) + fun handleMoitException(ex: WithaengException): ResponseEntity> { + logger.error("WitheangException handler", ex) + return errorResponse(ex.httpStatusCode, ex.toApiErrorResponse()) + } + + @ExceptionHandler(MissingServletRequestParameterException::class) + protected fun handleMissingServletRequestParameterException(ex: MissingServletRequestParameterException): ResponseEntity> { + logger.error("MissingServletRequestParameterException handler", ex) + return errorResponse(WithaengExceptionType.INVALID_INPUT, ex.message) + } + + @ExceptionHandler(BindException::class) + protected fun handleBindException(ex: BindException): ResponseEntity> { + logger.error("BindException handler", ex) + return errorResponse(WithaengExceptionType.INVALID_INPUT, ex.message) + } + + @ExceptionHandler(MethodArgumentTypeMismatchException::class) + protected fun handleMethodArgumentTypeMismatchException(ex: MethodArgumentTypeMismatchException): ResponseEntity> { + logger.error("MethodArgumentTypeMismatchException handler", ex) + return errorResponse(WithaengExceptionType.METHOD_ARGUMENT_TYPE_MISMATCH_VALUE, ex.message) + } + + @ExceptionHandler(HttpRequestMethodNotSupportedException::class) + protected fun handleHttpRequestMethodNotSupportedException(ex: HttpRequestMethodNotSupportedException): ResponseEntity> { + logger.error("HttpRequestMethodNotSupportedException handler", ex) + return errorResponse(WithaengExceptionType.HTTP_REQUEST_METHOD_NOT_SUPPORTED, ex.message) + } + + @ExceptionHandler(AccessDeniedException::class) + protected fun handleAccessDeniedException(ex: AccessDeniedException): ResponseEntity> { + logger.error("AccessDeniedException handler", ex) + return errorResponse(WithaengExceptionType.ACCESS_DENIED, ex.message) + } + + @ExceptionHandler(MethodArgumentNotValidException::class) + protected fun handleMethodArgumentNotValidException(e: MethodArgumentNotValidException): ResponseEntity> { + logger.error("MethodArgumentNotValidException handler", e) + val errorMessage = e.allErrors.joinToString(" ,") + return errorResponse(WithaengExceptionType.ARGUMENT_NOT_VALID, errorMessage) + } + + private fun WithaengException.toApiErrorResponse() = ApiErrorResponse( + code = errorCode, + message = message, + ) + + private fun errorResponse( + exceptionType: WithaengExceptionType, + message: String? + ) = errorResponse( + exceptionType.httpStatusCode, + ApiErrorResponse(exceptionType.name, message) + ) + + private fun errorResponse(status: Int, errorResponse: ApiErrorResponse) = + errorResponse(HttpStatus.valueOf(status), errorResponse) + + private fun errorResponse(status: HttpStatus, errorResponse: ApiErrorResponse): ResponseEntity> = + ResponseEntity.status(status) + .body( + ApiResponse( + success = false, + data = null, + error = errorResponse, + ) + ) +} \ No newline at end of file From c255f0040d703b8e9e2e35bb07d39f137754b3af Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Sat, 23 Mar 2024 10:44:30 +0900 Subject: [PATCH 012/174] Implement ApiResponse --- .../com/travel/withaeng/common/ApiResponse.kt | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/common/ApiResponse.kt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ApiResponse.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ApiResponse.kt new file mode 100644 index 0000000..60d91a9 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ApiResponse.kt @@ -0,0 +1,35 @@ +package com.travel.withaeng.common + +import com.travel.withaeng.common.exception.WithaengExceptionType + +data class ApiResponse( + val success: Boolean = true, + val data: T? = null, + val error: ApiErrorResponse? = null +) { + companion object { + fun success(): ApiResponse { + return ApiResponse(success = true, data = null) + } + + fun success(data: T): ApiResponse { + return ApiResponse(success = true, data = data) + } + + fun fail( + exceptionType: WithaengExceptionType, + message: String? + ): ApiResponse { + return ApiResponse( + success = false, + data = null, + error = ApiErrorResponse( + code = exceptionType.errorCode, + message = message ?: exceptionType.message + ) + ) + } + } +} + +data class ApiErrorResponse(val code: String, val message: String?) \ No newline at end of file From f603eb1bcabbcc5f8d92075a53c8d67334c754ed Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Sat, 23 Mar 2024 10:45:22 +0900 Subject: [PATCH 013/174] Implement providing jwt after sigining in --- gradle.properties | 4 +- withaeng-api/build.gradle.kts | 6 ++ .../withaeng/{api => }/WithaengApplication.kt | 2 +- .../com/travel/withaeng/common/Constants.kt | 8 +++ .../com/travel/withaeng/config/AuthConfig.kt | 21 +++++++ .../security/authentication/UserInfo.kt | 22 +++++++ .../travel/withaeng/security/jwt/AuthToken.kt | 3 + .../security/jwt/AuthTokenGenerator.kt | 27 +++++++++ .../withaeng/security/jwt/JwtProvider.kt | 60 +++++++++++++++++++ .../src/main/resources/application.yml | 6 +- 10 files changed, 156 insertions(+), 3 deletions(-) rename withaeng-api/src/main/kotlin/com/travel/withaeng/{api => }/WithaengApplication.kt (88%) create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/common/Constants.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/config/AuthConfig.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/security/authentication/UserInfo.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/AuthToken.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/AuthTokenGenerator.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtProvider.kt diff --git a/gradle.properties b/gradle.properties index 6779101..757ce6b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,4 +12,6 @@ springMockkVersion=3.1.1 ### Jasypt versions ### jasyptVersion=3.0.5 ### Persistence versions ### -mysqlVersion=8.3.0 \ No newline at end of file +mysqlVersion=8.3.0 +### jjwt version +jjwtVersion=0.11.5 \ No newline at end of file diff --git a/withaeng-api/build.gradle.kts b/withaeng-api/build.gradle.kts index 80633c2..4472b6b 100644 --- a/withaeng-api/build.gradle.kts +++ b/withaeng-api/build.gradle.kts @@ -6,8 +6,14 @@ tasks.getByName("jar") { enabled = false } +val jjwtVersion: String by project.extra dependencies { implementation(project(":withaeng-domain")) implementation(project(":withaeng-common")) implementation("org.springframework.boot:spring-boot-starter-web") + + // jwt + implementation("io.jsonwebtoken:jjwt-api:$jjwtVersion") + runtimeOnly("io.jsonwebtoken:jjwt-impl:$jjwtVersion") + runtimeOnly("io.jsonwebtoken:jjwt-jackson:$jjwtVersion") } \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/api/WithaengApplication.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/WithaengApplication.kt similarity index 88% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/api/WithaengApplication.kt rename to withaeng-api/src/main/kotlin/com/travel/withaeng/WithaengApplication.kt index 64368bf..49bde78 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/api/WithaengApplication.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/WithaengApplication.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.api +package com.travel.withaeng import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/Constants.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/Constants.kt new file mode 100644 index 0000000..09a0be2 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/Constants.kt @@ -0,0 +1,8 @@ +package com.travel.withaeng.common + +object Constants { + object Authentication { + const val BEARER_TYPE = "Bearer" + const val BEARER_TOKEN_PREFIX_WITH_WHITESPACE = "$BEARER_TYPE " + } +} \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/AuthConfig.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/config/AuthConfig.kt new file mode 100644 index 0000000..30cc439 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/config/AuthConfig.kt @@ -0,0 +1,21 @@ +package com.travel.withaeng.config + +import com.fasterxml.jackson.databind.ObjectMapper +import com.travel.withaeng.security.jwt.JwtProvider +import org.springframework.boot.context.properties.ConfigurationProperties +import org.springframework.boot.context.properties.EnableConfigurationProperties +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +@Configuration +@EnableConfigurationProperties(AuthProperty::class) +class AuthConfig { + + @Bean + fun jwtProvider(mapper: ObjectMapper, authProperty: AuthProperty): JwtProvider { + return JwtProvider(mapper, authProperty.jwtSecretKey) + } +} + +@ConfigurationProperties(prefix = "witheang.auth") +data class AuthProperty(val jwtSecretKey: String) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/authentication/UserInfo.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/authentication/UserInfo.kt new file mode 100644 index 0000000..8732c60 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/authentication/UserInfo.kt @@ -0,0 +1,22 @@ +package com.travel.withaeng.security.authentication + +import com.travel.withaeng.domain.user.UserDto +import com.travel.withaeng.domain.user.UserRole + +data class UserInfo( + val id: Long, + val email: String, + val nickname: String, + val roles: Set, +) { + companion object { + fun from(user: UserDto): UserInfo { + return UserInfo( + id = user.id, + email = user.email, + nickname = user.nickname, + roles = user.roles + ) + } + } +} diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/AuthToken.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/AuthToken.kt new file mode 100644 index 0000000..39c7177 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/AuthToken.kt @@ -0,0 +1,3 @@ +package com.travel.withaeng.security.jwt + +data class AuthToken(val accessToken: String, val refreshToken: String, val grantType: String, val expiresIn: Long) \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/AuthTokenGenerator.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/AuthTokenGenerator.kt new file mode 100644 index 0000000..19ea712 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/AuthTokenGenerator.kt @@ -0,0 +1,27 @@ +package com.travel.withaeng.security.jwt + +import com.travel.withaeng.common.Constants +import com.travel.withaeng.security.authentication.UserInfo +import org.springframework.stereotype.Component + +@Component +class AuthTokenGenerator(private val jwtProvider: JwtProvider) { + + fun generate(userInfo: UserInfo): AuthToken { + val accessToken = jwtProvider.createToken(userInfo, ACCESS_TOKEN_EXPIRE_TIME) + val refreshToken = jwtProvider.createToken(userInfo, REFRESH_TOKEN_EXPIRE_TIME) + + return AuthToken( + accessToken = accessToken, + refreshToken = refreshToken, + grantType = Constants.Authentication.BEARER_TYPE, + expiresIn = ACCESS_TOKEN_EXPIRE_TIME / 1000L + ) + } + + companion object { + // TODO: Change expire times after developing application + private const val ACCESS_TOKEN_EXPIRE_TIME = 1000 * 60 * 60 * 7L + private const val REFRESH_TOKEN_EXPIRE_TIME = 1000 * 60 * 60 * 30L + } +} \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtProvider.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtProvider.kt new file mode 100644 index 0000000..1271858 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtProvider.kt @@ -0,0 +1,60 @@ +package com.travel.withaeng.security.jwt + +import com.fasterxml.jackson.databind.ObjectMapper +import com.travel.withaeng.common.exception.WithaengException +import com.travel.withaeng.common.exception.WithaengExceptionType +import com.travel.withaeng.security.authentication.UserInfo +import io.jsonwebtoken.JwtParser +import io.jsonwebtoken.Jwts +import io.jsonwebtoken.security.Keys +import java.security.Key +import java.time.LocalDateTime +import java.time.ZoneId +import java.time.ZoneOffset +import java.time.temporal.ChronoUnit +import java.util.* + +class JwtProvider(private val mapper: ObjectMapper, key: String) { + + private val secretKey: Key + private val jwtParser: JwtParser + + init { + val encodedKey = Base64.getEncoder().encodeToString(key.toByteArray()) + secretKey = Keys.hmacShaKeyFor(encodedKey.toByteArray()) + jwtParser = Jwts.parserBuilder().setSigningKey(secretKey).build() + } + + fun createToken(userInfo: UserInfo, expireTime: Long? = null): String { + val issuerDateTime = LocalDateTime.now(ASIA_SEOUL_ZONE_ID) + val expiredDateTime = expireTime?.let { issuerDateTime.plus(it, ChronoUnit.MILLIS) } + ?: issuerDateTime.plusDays(TOKEN_EXPIRE_DAY) + return Jwts.builder() + .setHeaderParam("typ", "JWT") + .setSubject("jwt-user-${userInfo.nickname}") + .setAudience("${userInfo.email}|${userInfo.id}|${userInfo.nickname}") + .setIssuer("https://github.com/withaeng/withaeng-backend") + .setIssuedAt(issuerDateTime.convertToDate()) + .setExpiration(expiredDateTime.convertToDate()) + .claim(KEY_CLAIM_INFO, userInfo) + .signWith(secretKey) + .compact() + } + + fun extractUserInfoFromToken(token: String): UserInfo { + return jwtParser.parseClaimsJws(token).body?.let { claims -> + mapper.convertValue(claims[KEY_CLAIM_INFO], UserInfo::class.java) + } ?: throw WithaengException.of(WithaengExceptionType.INVALID_USER_AUTH_TOKEN) + } + + private fun LocalDateTime.convertToDate(): Date = Date.from(this.toInstant(ASIA_SEOUL_ZONE_OFFSET)) + + companion object { + private const val KEY_CLAIM_INFO = "info" + + private val ASIA_SEOUL_ZONE_ID = ZoneId.of("Asia/Seoul") + private val ASIA_SEOUL_ZONE_OFFSET = ZoneOffset.of("+09:00") + + private const val TOKEN_EXPIRE_DAY = 30L + } +} \ No newline at end of file diff --git a/withaeng-api/src/main/resources/application.yml b/withaeng-api/src/main/resources/application.yml index c95d6f0..89900f1 100644 --- a/withaeng-api/src/main/resources/application.yml +++ b/withaeng-api/src/main/resources/application.yml @@ -3,4 +3,8 @@ spring: default: local config: import: - - classpath:/application-domain.yml \ No newline at end of file + - classpath:/application-domain.yml + +witheang: + auth: + jwt-secret-key: ENC(i5HqamjyyaTwDSyiHXoAxJrP11XyQ8mArvAUI1RD15tteCbIEnzVVp+qcYB45xDkybBZmjY79HDp/Ci5YkkSyg==) \ No newline at end of file From 377ae12fee72c02ee9e73cc46e760db1f9f1d7f6 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Thu, 4 Apr 2024 20:00:13 +0900 Subject: [PATCH 014/174] Add extenral module --- settings.gradle.kts | 6 ++++-- withaeng-external/build.gradle.kts | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 withaeng-external/build.gradle.kts diff --git a/settings.gradle.kts b/settings.gradle.kts index 96f5936..d9a3ee8 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -2,7 +2,8 @@ rootProject.name = "withaeng" include( "withaeng-api", "withaeng-domain", - "withaeng-common" + "withaeng-common", + "withaeng-external" ) pluginManagement { @@ -21,4 +22,5 @@ pluginManagement { } } } -} \ No newline at end of file +} +include("withaeng-external") diff --git a/withaeng-external/build.gradle.kts b/withaeng-external/build.gradle.kts new file mode 100644 index 0000000..9671094 --- /dev/null +++ b/withaeng-external/build.gradle.kts @@ -0,0 +1,19 @@ +plugins { + id("java") +} + +group = "org.example" +version = "0.0.1" + +repositories { + mavenCentral() +} + +dependencies { + testImplementation(platform("org.junit:junit-bom:5.9.1")) + testImplementation("org.junit.jupiter:junit-jupiter") +} + +tasks.test { + useJUnitPlatform() +} \ No newline at end of file From 686a8ee8215739b7fe76c5a4941009d786b2f506 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Fri, 5 Apr 2024 18:01:24 +0900 Subject: [PATCH 015/174] Add ThymeleafTemplate Bean --- withaeng-external/build.gradle.kts | 18 +--------- .../external/ses/config/ThymeleafConfig.kt | 36 +++++++++++++++++++ 2 files changed, 37 insertions(+), 17 deletions(-) create mode 100644 withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/config/ThymeleafConfig.kt diff --git a/withaeng-external/build.gradle.kts b/withaeng-external/build.gradle.kts index 9671094..3885205 100644 --- a/withaeng-external/build.gradle.kts +++ b/withaeng-external/build.gradle.kts @@ -1,19 +1,3 @@ -plugins { - id("java") -} - -group = "org.example" -version = "0.0.1" - -repositories { - mavenCentral() -} - dependencies { - testImplementation(platform("org.junit:junit-bom:5.9.1")) - testImplementation("org.junit.jupiter:junit-jupiter") -} - -tasks.test { - useJUnitPlatform() + implementation("org.springframework.boot:spring-boot-starter-thymeleaf") } \ No newline at end of file diff --git a/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/config/ThymeleafConfig.kt b/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/config/ThymeleafConfig.kt new file mode 100644 index 0000000..79e0edd --- /dev/null +++ b/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/config/ThymeleafConfig.kt @@ -0,0 +1,36 @@ +package com.travel.withaeng.external.ses.config + +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.thymeleaf.TemplateEngine +import org.thymeleaf.spring6.SpringTemplateEngine +import org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver +import org.thymeleaf.templatemode.TemplateMode + +@Configuration +class ThymeleafConfig { + + @Bean + fun htmlTemplateEngine(springResourceTemplateResolver: SpringResourceTemplateResolver): TemplateEngine { + return SpringTemplateEngine().apply { + addTemplateResolver(springResourceTemplateResolver) + } + } + + @Bean + fun springResourceTemplateResolver(): SpringResourceTemplateResolver { + return SpringResourceTemplateResolver().apply { + prefix = TEMPLATE_PREFIX + characterEncoding = TEMPLATE_CHARACTER_ENCODING + suffix = TEMPLATE_SUFFIX + templateMode = TemplateMode.HTML + isCacheable = false + } + } + + companion object { + private const val TEMPLATE_PREFIX = "classpath:templates/" + private const val TEMPLATE_CHARACTER_ENCODING = "UTF-8" + private const val TEMPLATE_SUFFIX = ".html" + } +} \ No newline at end of file From 1f967354a692b431f34a576f05a7b631651580b4 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Fri, 5 Apr 2024 18:01:46 +0900 Subject: [PATCH 016/174] Implement MailSender by using AWS SES --- build.gradle.kts | 1 + withaeng-external/build.gradle.kts | 1 + .../withaeng/external/ses/MailSender.kt | 5 +++ .../withaeng/external/ses/MailSenderImpl.kt | 38 +++++++++++++++++++ .../withaeng/external/ses/config/SESConfig.kt | 33 ++++++++++++++++ .../resources/external-config/application.yml | 9 +++++ .../resources/templates/email-template.html | 10 +++++ 7 files changed, 97 insertions(+) create mode 100644 withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSender.kt create mode 100644 withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSenderImpl.kt create mode 100644 withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/config/SESConfig.kt create mode 100644 withaeng-external/src/main/resources/external-config/application.yml create mode 100644 withaeng-external/src/main/resources/templates/email-template.html diff --git a/build.gradle.kts b/build.gradle.kts index eb947e6..5af766d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -33,6 +33,7 @@ subprojects { apply(plugin = "io.spring.dependency-management") dependencies { + implementation("org.springframework.boot:spring-boot-starter-web") implementation("org.jetbrains.kotlin:kotlin-reflect") implementation("com.fasterxml.jackson.module:jackson-module-kotlin") diff --git a/withaeng-external/build.gradle.kts b/withaeng-external/build.gradle.kts index 3885205..a27e38d 100644 --- a/withaeng-external/build.gradle.kts +++ b/withaeng-external/build.gradle.kts @@ -1,3 +1,4 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-thymeleaf") + implementation("com.amazonaws:aws-java-sdk-ses:1.12.408") } \ No newline at end of file diff --git a/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSender.kt b/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSender.kt new file mode 100644 index 0000000..3240ce8 --- /dev/null +++ b/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSender.kt @@ -0,0 +1,5 @@ +package com.travel.withaeng.external.ses + +interface MailSender { + fun send(subject: String, variables: Map, vararg to: String) +} \ No newline at end of file diff --git a/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSenderImpl.kt b/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSenderImpl.kt new file mode 100644 index 0000000..4e3d531 --- /dev/null +++ b/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSenderImpl.kt @@ -0,0 +1,38 @@ +package com.travel.withaeng.external.ses + +import com.amazonaws.services.simpleemail.AmazonSimpleEmailService +import com.amazonaws.services.simpleemail.model.* +import org.springframework.beans.factory.annotation.Value +import org.springframework.stereotype.Service +import org.thymeleaf.TemplateEngine +import org.thymeleaf.context.Context +import java.nio.charset.StandardCharsets + +@Service +class MailSenderImpl(private val emailService: AmazonSimpleEmailService, private val templateEngine: TemplateEngine) : + MailSender { + + @Value("\${cloud.aws.ses.from}") + private lateinit var from: String + + override fun send(subject: String, variables: Map, vararg to: String) { + val content = templateEngine.process("email-template", createContext(variables)) + val request = createSendEmailRequest(subject, content, *to) + emailService.sendEmail(request) + } + + private fun createContext(variables: Map): Context { + return Context().apply { setVariables(variables) } + } + + private fun createSendEmailRequest(subject: String, content: String, vararg to: String): SendEmailRequest { + return SendEmailRequest() + .withDestination(Destination().withToAddresses(*to)) + .withSource(from) + .withMessage( + Message() + .withSubject(Content().withCharset(StandardCharsets.UTF_8.name()).withData(subject)) + .withBody(Body().withHtml(Content().withCharset(StandardCharsets.UTF_8.name()).withData(content))) + ) + } +} \ No newline at end of file diff --git a/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/config/SESConfig.kt b/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/config/SESConfig.kt new file mode 100644 index 0000000..65fc282 --- /dev/null +++ b/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/config/SESConfig.kt @@ -0,0 +1,33 @@ +package com.travel.withaeng.external.ses.config + +import com.amazonaws.auth.AWSStaticCredentialsProvider +import com.amazonaws.auth.BasicAWSCredentials +import com.amazonaws.regions.Regions +import com.amazonaws.services.simpleemail.AmazonSimpleEmailService +import com.amazonaws.services.simpleemail.AmazonSimpleEmailServiceClientBuilder +import org.springframework.beans.factory.annotation.Value +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +@Configuration +// TODO: Device SES Config from development environment (local or prod) +class SESConfig { + + @Value("\${cloud.aws.credentials.access-key}") + private lateinit var accessKey: String + + @Value("\${cloud.aws.credentials.secret-key}") + private lateinit var secretKey: String + + @Value("\${cloud.aws.region.static}") + private lateinit var regionName: String + + @Bean + fun amazonSimpleEmailService(): AmazonSimpleEmailService { + val credentials = BasicAWSCredentials(accessKey, secretKey) + return AmazonSimpleEmailServiceClientBuilder.standard() + .withRegion(Regions.fromName(regionName)) + .withCredentials(AWSStaticCredentialsProvider(credentials)) + .build() + } +} \ No newline at end of file diff --git a/withaeng-external/src/main/resources/external-config/application.yml b/withaeng-external/src/main/resources/external-config/application.yml new file mode 100644 index 0000000..3b89701 --- /dev/null +++ b/withaeng-external/src/main/resources/external-config/application.yml @@ -0,0 +1,9 @@ +cloud: + aws: + credentials: + access-key: ENC(ebs6pebbMa3L64Bj4JRaYm8mR4L+mXbKtwIslRT8D1/1qeGoqvu8NbjUxcU7vcL8) + secret-key: ENC(I7orBCvSQW/PqGYJZFOa8Uz9pz4nbCp7QzuU7PNbYDuABMXzar4thmcXPRvQ+I3o) + region: + static: ENC(1OX/+Td6WwTc/zbC8t/DVgDHX24lMOV+ZQbza/IstkTM8E3UKwloe8EaH97FKpzT) + ses: + from: ENC(S6WIEUO3m5JKHw7PrhpgkAvQjd1LzwwLRXEu2I9yUtzErtBEDk6EEt28Ltzypo8/fZi7Ua8VkHjWh9498FT5DA==) \ No newline at end of file diff --git a/withaeng-external/src/main/resources/templates/email-template.html b/withaeng-external/src/main/resources/templates/email-template.html new file mode 100644 index 0000000..ca18082 --- /dev/null +++ b/withaeng-external/src/main/resources/templates/email-template.html @@ -0,0 +1,10 @@ + + + + + 이메일 인증 + + +
+ + \ No newline at end of file From b93b01ecc302d279f0cccc236317c9b6772ff67b Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Mon, 8 Apr 2024 13:06:32 +0900 Subject: [PATCH 017/174] Implement JwtAgent --- .../com/travel/withaeng/config/AuthConfig.kt | 9 +- .../authentication/JwtAuthentication.kt | 28 ++++++ .../travel/withaeng/security/jwt/AuthToken.kt | 3 - .../security/jwt/AuthTokenGenerator.kt | 27 ------ .../travel/withaeng/security/jwt/JwtAgent.kt | 23 +++++ .../jwt/{JwtProvider.kt => JwtAgentImpl.kt} | 40 +++++---- .../travel/withaeng/security/jwt/JwtFilter.kt | 88 +++++++++++++++++++ .../src/main/resources/application.yml | 3 +- 8 files changed, 167 insertions(+), 54 deletions(-) create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/security/authentication/JwtAuthentication.kt delete mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/AuthToken.kt delete mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/AuthTokenGenerator.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtAgent.kt rename withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/{JwtProvider.kt => JwtAgentImpl.kt} (55%) create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtFilter.kt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/AuthConfig.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/config/AuthConfig.kt index 30cc439..5b00d39 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/AuthConfig.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/config/AuthConfig.kt @@ -1,7 +1,8 @@ package com.travel.withaeng.config import com.fasterxml.jackson.databind.ObjectMapper -import com.travel.withaeng.security.jwt.JwtProvider +import com.travel.withaeng.security.jwt.JwtAgent +import com.travel.withaeng.security.jwt.JwtAgentImpl import org.springframework.boot.context.properties.ConfigurationProperties import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.context.annotation.Bean @@ -12,10 +13,10 @@ import org.springframework.context.annotation.Configuration class AuthConfig { @Bean - fun jwtProvider(mapper: ObjectMapper, authProperty: AuthProperty): JwtProvider { - return JwtProvider(mapper, authProperty.jwtSecretKey) + fun jwtAgent(mapper: ObjectMapper, authProperty: AuthProperty): JwtAgent { + return JwtAgentImpl(mapper, authProperty.jwtSecretKey, authProperty.jwtIssuer) } } @ConfigurationProperties(prefix = "witheang.auth") -data class AuthProperty(val jwtSecretKey: String) +data class AuthProperty(val jwtSecretKey: String, val jwtIssuer: String) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/authentication/JwtAuthentication.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/authentication/JwtAuthentication.kt new file mode 100644 index 0000000..6563dca --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/authentication/JwtAuthentication.kt @@ -0,0 +1,28 @@ +package com.travel.withaeng.security.authentication + +import org.springframework.security.core.Authentication +import org.springframework.security.core.GrantedAuthority +import org.springframework.security.core.authority.SimpleGrantedAuthority + +class JwtAuthentication(private val userInfo: UserInfo) : Authentication { + + var isAuthenticated = true + + override fun getName(): String = userInfo.nickname + + override fun getAuthorities(): Collection = userInfo.roles + .map { userRole -> SimpleGrantedAuthority(userRole.role) } + + override fun getCredentials(): Any = userInfo.id + + override fun getDetails(): Any = userInfo.toDetails() + + override fun getPrincipal(): Any = userInfo + + override fun isAuthenticated(): Boolean = isAuthenticated + + override fun setAuthenticated(isAuthenticated: Boolean) { + this.isAuthenticated = isAuthenticated + } + +} \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/AuthToken.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/AuthToken.kt deleted file mode 100644 index 39c7177..0000000 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/AuthToken.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.travel.withaeng.security.jwt - -data class AuthToken(val accessToken: String, val refreshToken: String, val grantType: String, val expiresIn: Long) \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/AuthTokenGenerator.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/AuthTokenGenerator.kt deleted file mode 100644 index 19ea712..0000000 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/AuthTokenGenerator.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.travel.withaeng.security.jwt - -import com.travel.withaeng.common.Constants -import com.travel.withaeng.security.authentication.UserInfo -import org.springframework.stereotype.Component - -@Component -class AuthTokenGenerator(private val jwtProvider: JwtProvider) { - - fun generate(userInfo: UserInfo): AuthToken { - val accessToken = jwtProvider.createToken(userInfo, ACCESS_TOKEN_EXPIRE_TIME) - val refreshToken = jwtProvider.createToken(userInfo, REFRESH_TOKEN_EXPIRE_TIME) - - return AuthToken( - accessToken = accessToken, - refreshToken = refreshToken, - grantType = Constants.Authentication.BEARER_TYPE, - expiresIn = ACCESS_TOKEN_EXPIRE_TIME / 1000L - ) - } - - companion object { - // TODO: Change expire times after developing application - private const val ACCESS_TOKEN_EXPIRE_TIME = 1000 * 60 * 60 * 7L - private const val REFRESH_TOKEN_EXPIRE_TIME = 1000 * 60 * 60 * 30L - } -} \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtAgent.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtAgent.kt new file mode 100644 index 0000000..735db10 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtAgent.kt @@ -0,0 +1,23 @@ +package com.travel.withaeng.security.jwt + +import com.travel.withaeng.security.authentication.UserInfo + +interface JwtAgent { + + /** + * 사용자 정보를 토대로 Jwt Token을 생성합니다. + * JwtToken은 accessToken및 refreshToken을 포함합니다. + * + * @param userInfo UserInfo 로 유저의 정보를 담고 있습니다. + * @return JWT 를 반환합니다. + */ + fun provide(userInfo: UserInfo): String + + /** + * 사용자의 accessToken을 입력받아 UserInfo 객체를 반환합니다. + * + * @param token 사용자가 발급받은 JWT + * @return UserInfo 를 반환합니다. + */ + fun extractUserInfoFromToken(token: String): UserInfo? +} \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtProvider.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtAgentImpl.kt similarity index 55% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtProvider.kt rename to withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtAgentImpl.kt index 1271858..5e4192a 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtProvider.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtAgentImpl.kt @@ -6,34 +6,32 @@ import com.travel.withaeng.common.exception.WithaengExceptionType import com.travel.withaeng.security.authentication.UserInfo import io.jsonwebtoken.JwtParser import io.jsonwebtoken.Jwts +import io.jsonwebtoken.io.Decoders import io.jsonwebtoken.security.Keys +import org.springframework.beans.factory.annotation.Value import java.security.Key import java.time.LocalDateTime import java.time.ZoneId import java.time.ZoneOffset -import java.time.temporal.ChronoUnit import java.util.* -class JwtProvider(private val mapper: ObjectMapper, key: String) { +class JwtAgentImpl( + private val objectMapper: ObjectMapper, + @Value("\${jwt.issuer}") private val issuer: String, + @Value("\${jwt.secret-key}") key: String, +) : JwtAgent { - private val secretKey: Key - private val jwtParser: JwtParser + private val secretKey: Key = Keys.hmacShaKeyFor(Decoders.BASE64.decode(key)) + private val jwtParser: JwtParser = Jwts.parserBuilder().setSigningKey(secretKey).build() - init { - val encodedKey = Base64.getEncoder().encodeToString(key.toByteArray()) - secretKey = Keys.hmacShaKeyFor(encodedKey.toByteArray()) - jwtParser = Jwts.parserBuilder().setSigningKey(secretKey).build() - } - - fun createToken(userInfo: UserInfo, expireTime: Long? = null): String { + override fun provide(userInfo: UserInfo): String { val issuerDateTime = LocalDateTime.now(ASIA_SEOUL_ZONE_ID) - val expiredDateTime = expireTime?.let { issuerDateTime.plus(it, ChronoUnit.MILLIS) } - ?: issuerDateTime.plusDays(TOKEN_EXPIRE_DAY) + val expiredDateTime = issuerDateTime.plusDays(TOKEN_EXPIRE_DAY) return Jwts.builder() - .setHeaderParam("typ", "JWT") - .setSubject("jwt-user-${userInfo.nickname}") + .setHeaderParam(KEY_TOKEN_TYPE, TOKEN_TYPE_JWT) + .setSubject(createSubject(userInfo.nickname)) .setAudience("${userInfo.email}|${userInfo.id}|${userInfo.nickname}") - .setIssuer("https://github.com/withaeng/withaeng-backend") + .setIssuer(issuer) .setIssuedAt(issuerDateTime.convertToDate()) .setExpiration(expiredDateTime.convertToDate()) .claim(KEY_CLAIM_INFO, userInfo) @@ -41,20 +39,24 @@ class JwtProvider(private val mapper: ObjectMapper, key: String) { .compact() } - fun extractUserInfoFromToken(token: String): UserInfo { + override fun extractUserInfoFromToken(token: String): UserInfo { return jwtParser.parseClaimsJws(token).body?.let { claims -> - mapper.convertValue(claims[KEY_CLAIM_INFO], UserInfo::class.java) + objectMapper.convertValue(claims[KEY_CLAIM_INFO], UserInfo::class.java) } ?: throw WithaengException.of(WithaengExceptionType.INVALID_USER_AUTH_TOKEN) } private fun LocalDateTime.convertToDate(): Date = Date.from(this.toInstant(ASIA_SEOUL_ZONE_OFFSET)) + private fun createSubject(subject: String): String = "jwt-user-$subject" + companion object { private const val KEY_CLAIM_INFO = "info" + private const val KEY_TOKEN_TYPE = "typ" + private const val TOKEN_TYPE_JWT = "JWT" private val ASIA_SEOUL_ZONE_ID = ZoneId.of("Asia/Seoul") private val ASIA_SEOUL_ZONE_OFFSET = ZoneOffset.of("+09:00") - private const val TOKEN_EXPIRE_DAY = 30L + private const val TOKEN_EXPIRE_DAY = 7L // 임시 JWT 만료기간 } } \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtFilter.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtFilter.kt new file mode 100644 index 0000000..0cc91a0 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtFilter.kt @@ -0,0 +1,88 @@ +package com.travel.withaeng.security.jwt + +import com.fasterxml.jackson.databind.ObjectMapper +import com.travel.withaeng.common.ApiResponse +import com.travel.withaeng.common.Constants.Authentication.BEARER_TYPE +import com.travel.withaeng.common.exception.WithaengException +import com.travel.withaeng.common.exception.WithaengExceptionType +import com.travel.withaeng.security.authentication.JwtAuthentication +import jakarta.servlet.FilterChain +import jakarta.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletResponse +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import org.springframework.http.HttpHeaders +import org.springframework.http.HttpStatus +import org.springframework.http.MediaType +import org.springframework.security.authentication.BadCredentialsException +import org.springframework.security.core.context.SecurityContextHolder +import org.springframework.web.filter.OncePerRequestFilter + +class JwtFilter( + private val jwtAgent: JwtAgent, + private val objectMapper: ObjectMapper +) : OncePerRequestFilter() { + + private val log: Logger = LoggerFactory.getLogger(JwtFilter::class.java) + + override fun doFilterInternal( + request: HttpServletRequest, + response: HttpServletResponse, + filterChain: FilterChain + ) { + log.debug("JWT Filter doFilterInternal()") + runCatching { + setAuthenticationFromToken(request) + }.onFailure { exception -> + log.debug("Authentication Failed: Authorization value=${request.getAuthorization()}, Message=${exception.message}") + SecurityContextHolder.clearContext() + response.run { + status = HttpStatus.UNAUTHORIZED.value() + addHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + val failResponse = ApiResponse.fail(WithaengExceptionType.AUTHENTICATION_FAILURE, exception.message) + writer.write(objectMapper.writeValueAsString(failResponse)) + } + }.onSuccess { + filterChain.doFilter(request, response) + } + } + + private fun setAuthenticationFromToken(request: HttpServletRequest) { + if (!isNotCheckEndpoint(request)) { + val authorization = + request.getAuthorization() + ?: throw BadCredentialsException(WithaengExceptionType.AUTHENTICATION_FAILURE.message) + log.debug("Parsing token in header: $authorization - Request path: ${request.requestURI}") + getToken(authorization)?.let { token -> + jwtAgent.extractUserInfoFromToken(token)?.let { userInfo -> + SecurityContextHolder.getContext().authentication = JwtAuthentication(userInfo) + } + } ?: throw WithaengException.of(WithaengExceptionType.AUTHENTICATION_FAILURE) + } + } + + private fun getToken(authorization: String): String? { + val (provider, token) = authorization.split(AUTH_PROVIDER_SPLIT_DELIMITER) + if (provider.uppercase() != BEARER_TYPE.uppercase()) return null + return token + } + + private fun HttpServletRequest.getAuthorization(): String? = getHeader(HttpHeaders.AUTHORIZATION) + + private fun isNotCheckEndpoint(request: HttpServletRequest): Boolean { + return NOT_CHECK_ENDPOINTS.any { request.requestURI.startsWith(it) } + } + + companion object { + private const val AUTH_PROVIDER_SPLIT_DELIMITER: String = " " + private val NOT_CHECK_ENDPOINTS = listOf( + // Common + "/favicon.ico", + "/error", + // Swagger + "/api-docs", "/swagger-ui", "/swagger-resources", + // SignIn/SignUp Endpoints + "/v1/auth", + ) + } +} \ No newline at end of file diff --git a/withaeng-api/src/main/resources/application.yml b/withaeng-api/src/main/resources/application.yml index 89900f1..0ff78e1 100644 --- a/withaeng-api/src/main/resources/application.yml +++ b/withaeng-api/src/main/resources/application.yml @@ -7,4 +7,5 @@ spring: witheang: auth: - jwt-secret-key: ENC(i5HqamjyyaTwDSyiHXoAxJrP11XyQ8mArvAUI1RD15tteCbIEnzVVp+qcYB45xDkybBZmjY79HDp/Ci5YkkSyg==) \ No newline at end of file + jwt-secret-key: ENC(i5HqamjyyaTwDSyiHXoAxJrP11XyQ8mArvAUI1RD15tteCbIEnzVVp+qcYB45xDkybBZmjY79HDp/Ci5YkkSyg==) + jwt-issuer: https://github.com/withaeng/withaeng-backend \ No newline at end of file From ff4991ca8d3562fa80b5c819f61891164ee183ab Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Mon, 8 Apr 2024 13:06:49 +0900 Subject: [PATCH 018/174] Implement SecurityConfig --- withaeng-api/build.gradle.kts | 1 + .../travel/withaeng/config/SecurityConfig.kt | 76 +++++++++++++++++++ .../handler/HttpStatusAccessDeniedHandler.kt | 21 +++++ .../HttpStatusAuthenticationEntryPoint.kt | 21 +++++ 4 files changed, 119 insertions(+) create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/config/SecurityConfig.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/security/handler/HttpStatusAccessDeniedHandler.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/security/handler/HttpStatusAuthenticationEntryPoint.kt diff --git a/withaeng-api/build.gradle.kts b/withaeng-api/build.gradle.kts index 4472b6b..b437721 100644 --- a/withaeng-api/build.gradle.kts +++ b/withaeng-api/build.gradle.kts @@ -11,6 +11,7 @@ dependencies { implementation(project(":withaeng-domain")) implementation(project(":withaeng-common")) implementation("org.springframework.boot:spring-boot-starter-web") + implementation("org.springframework.boot:spring-boot-starter-security") // jwt implementation("io.jsonwebtoken:jjwt-api:$jjwtVersion") diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/SecurityConfig.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/config/SecurityConfig.kt new file mode 100644 index 0000000..cd285c6 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/config/SecurityConfig.kt @@ -0,0 +1,76 @@ +package com.travel.withaeng.config + +import com.fasterxml.jackson.databind.ObjectMapper +import com.travel.withaeng.security.handler.HttpStatusAccessDeniedHandler +import com.travel.withaeng.security.handler.HttpStatusAuthenticationEntryPoint +import com.travel.withaeng.security.jwt.JwtAgent +import com.travel.withaeng.security.jwt.JwtFilter +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.http.HttpHeaders +import org.springframework.security.config.annotation.web.builders.HttpSecurity +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity +import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer +import org.springframework.security.web.SecurityFilterChain +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter +import org.springframework.web.cors.CorsConfiguration +import org.springframework.web.cors.CorsConfigurationSource +import org.springframework.web.cors.UrlBasedCorsConfigurationSource + +@Configuration +@EnableWebSecurity +class SecurityConfig(private val jwtAgent: JwtAgent, private val objectMapper: ObjectMapper) { + + @Bean + fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { + return http + .cors { it.configurationSource(corsConfigurationSource()) } + .csrf { it.disable() } + .httpBasic { it.disable() } + .formLogin { it.disable() } + .authorizeHttpRequests { + it.anyRequest().permitAll() // TODO: 추후 인가 추가 + } + .addFilterBefore(JwtFilter(jwtAgent, objectMapper), UsernamePasswordAuthenticationFilter::class.java) + .exceptionHandling { + it.authenticationEntryPoint(HttpStatusAuthenticationEntryPoint()) + it.accessDeniedHandler(HttpStatusAccessDeniedHandler()) + } + .build() + } + + @Bean + fun webSecurityCustomizer(): WebSecurityCustomizer { + return WebSecurityCustomizer { + it.ignoring().requestMatchers(*WHITE_LIST.toTypedArray()) + } + } + + @Bean + fun corsConfigurationSource(): CorsConfigurationSource { + val configuration = CorsConfiguration().apply { + addAllowedOriginPattern("*") + addAllowedMethod("*") + addAllowedHeader("*") + exposedHeaders = listOf(HttpHeaders.AUTHORIZATION, HttpHeaders.CONTENT_TYPE) + maxAge = MAX_CORS_EXPIRE_SECONDS + } + + return UrlBasedCorsConfigurationSource().apply { + registerCorsConfiguration("/v1/**", configuration) + } + } + + companion object { + private const val MAX_CORS_EXPIRE_SECONDS = 3600L + + private val WHITE_LIST = listOf( + // swagger + "/api-docs/**", "/swagger-ui/**", "/swagger-resources/**", "/v3/api-docs/**", + // error page + "/error/**", + // Auth endpoints + "/v1/auth/**", + ) + } +} \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/handler/HttpStatusAccessDeniedHandler.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/handler/HttpStatusAccessDeniedHandler.kt new file mode 100644 index 0000000..05f9ac9 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/handler/HttpStatusAccessDeniedHandler.kt @@ -0,0 +1,21 @@ +package com.travel.withaeng.security.handler + +import jakarta.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletResponse +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import org.springframework.http.HttpStatus +import org.springframework.security.web.access.AccessDeniedHandler + +class HttpStatusAccessDeniedHandler : AccessDeniedHandler { + private val log: Logger = LoggerFactory.getLogger(HttpStatusAccessDeniedHandler::class.java) + + override fun handle( + request: HttpServletRequest?, + response: HttpServletResponse, + accessDeniedException: org.springframework.security.access.AccessDeniedException + ) { + log.debug("Access Denied: ${accessDeniedException.message}") + response.status = HttpStatus.FORBIDDEN.value() + } +} \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/handler/HttpStatusAuthenticationEntryPoint.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/handler/HttpStatusAuthenticationEntryPoint.kt new file mode 100644 index 0000000..7a21905 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/handler/HttpStatusAuthenticationEntryPoint.kt @@ -0,0 +1,21 @@ +package com.travel.withaeng.security.handler + +import jakarta.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletResponse +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import org.springframework.http.HttpStatus +import org.springframework.security.core.AuthenticationException +import org.springframework.security.web.AuthenticationEntryPoint + +class HttpStatusAuthenticationEntryPoint : AuthenticationEntryPoint { + private val log: Logger = LoggerFactory.getLogger(HttpStatusAuthenticationEntryPoint::class.java) + + override fun commence( + request: HttpServletRequest, response: HttpServletResponse, + authException: AuthenticationException + ) { + log.debug("Not Authenticated: ${authException.message}") + response.status = HttpStatus.UNAUTHORIZED.value() + } +} \ No newline at end of file From 029fb3c3b5a5778074b6eb796be1c5aadf688caf Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Fri, 3 May 2024 17:53:16 +0900 Subject: [PATCH 019/174] Fix aws secret access keys --- .../src/main/resources/external-config/application.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/withaeng-external/src/main/resources/external-config/application.yml b/withaeng-external/src/main/resources/external-config/application.yml index 3b89701..a03e0b5 100644 --- a/withaeng-external/src/main/resources/external-config/application.yml +++ b/withaeng-external/src/main/resources/external-config/application.yml @@ -1,8 +1,8 @@ cloud: aws: credentials: - access-key: ENC(ebs6pebbMa3L64Bj4JRaYm8mR4L+mXbKtwIslRT8D1/1qeGoqvu8NbjUxcU7vcL8) - secret-key: ENC(I7orBCvSQW/PqGYJZFOa8Uz9pz4nbCp7QzuU7PNbYDuABMXzar4thmcXPRvQ+I3o) + access-key: ENC(tje4pV1gRGOh5N5ig8TND1sc3NyDGe9KDIXHMiY5UgBospTEAk2pjcxphPMvoOiNshPej16XCkj/RDP8ywREdQ==) + secret-key: ENC(5RTBAVDrwVdRLBQ/vrQrrE2f9K/68acjDiHgg9hc9J/8K3TZoejmca7Nagyz1exQ8XEndRKXl4XgxyXljZvykgP/56Ab7eAKuXXplny0zoQ=) region: static: ENC(1OX/+Td6WwTc/zbC8t/DVgDHX24lMOV+ZQbza/IstkTM8E3UKwloe8EaH97FKpzT) ses: From 4017c0ad88d5147b8019951b37d7715e1975c023 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Tue, 7 May 2024 17:17:21 +0900 Subject: [PATCH 020/174] Add ValidatingEmailEntity --- .../domain/validateemail/ValidatingEmail.kt | 21 ++++++++++ .../validateemail/ValidatingEmailDto.kt | 17 ++++++++ .../ValidatingEmailRepository.kt | 14 +++++++ .../validateemail/ValidatingEmailService.kt | 40 +++++++++++++++++++ .../validateemail/ValidatingEmailStatus.kt | 5 +++ ...plication.yml => application-external.yml} | 0 6 files changed, 97 insertions(+) create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmail.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailDto.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailRepository.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailService.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailStatus.kt rename withaeng-external/src/main/resources/{external-config/application.yml => application-external.yml} (100%) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmail.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmail.kt new file mode 100644 index 0000000..c43779b --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmail.kt @@ -0,0 +1,21 @@ +package com.travel.withaeng.domain.validateemail + +import com.travel.withaeng.domain.BaseEntity +import jakarta.persistence.* + +@Table(name = "validating_emails") +@Entity +class ValidatingEmail( + @Column(name = "email", nullable = false) + val email: String, + + @Column(name = "user_id", nullable = false) + val userId: Long, + + @Column(name = "code", nullable = false) + val code: String, + + @Enumerated(EnumType.STRING) + @Column(name = "status", nullable = false) + val status: ValidatingEmailStatus = ValidatingEmailStatus.YET +): BaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailDto.kt new file mode 100644 index 0000000..29acbbb --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailDto.kt @@ -0,0 +1,17 @@ +package com.travel.withaeng.domain.validateemail + +data class ValidatingEmailDto( + val id: Long, + val email: String, + val userId: Long, + val code: String, + val status: ValidatingEmailStatus +) + +fun ValidatingEmail.toDto(): ValidatingEmailDto = ValidatingEmailDto( + id = id, + email = email, + userId = userId, + code = code, + status = status +) \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailRepository.kt new file mode 100644 index 0000000..1255990 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailRepository.kt @@ -0,0 +1,14 @@ +package com.travel.withaeng.domain.validateemail + +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.data.jpa.repository.Modifying +import org.springframework.data.jpa.repository.Query +import java.time.LocalDateTime + +interface ValidatingEmailRepository : JpaRepository { + fun findAllByStatusNot(status: ValidatingEmailStatus): List + + @Modifying + @Query("UPDATE ValidatingEmail v SET v.status = :status WHERE v.id in :ids") + fun updateStatusByIds(ids: Set, status: ValidatingEmailStatus) +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailService.kt new file mode 100644 index 0000000..deba547 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailService.kt @@ -0,0 +1,40 @@ +package com.travel.withaeng.domain.validateemail + +import com.travel.withaeng.common.exception.WithaengException +import com.travel.withaeng.common.exception.WithaengExceptionType +import com.travel.withaeng.domain.user.UserRepository +import org.springframework.data.repository.findByIdOrNull +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional + +@Service +@Transactional(readOnly = true) +class ValidatingEmailService( + private val userRepository: UserRepository, + private val validatingEmailRepository: ValidatingEmailRepository +) { + + @Transactional + fun create(email: String, userId: Long, code: String): ValidatingEmailDto { + userRepository.findByIdOrNull(userId) ?: throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = "$userId 에 해당하는 사용자를 찾을 수 없습니다." + ) + if (email.isBlank() || code.isBlank()) { + throw WithaengException.of( + type = WithaengExceptionType.ARGUMENT_NOT_VALID, + message = "이메일 인증을 진행하는데 올바르지 않은 입력입니다." + ) + } + return validatingEmailRepository.save(ValidatingEmail(email, userId, code)).toDto() + } + + fun findAllByStatusNot(status: ValidatingEmailStatus): List { + return validatingEmailRepository.findAllByStatusNot(status).map { it.toDto() } + } + + @Transactional + fun updateStatusByIds(ids: Set, status: ValidatingEmailStatus) { + validatingEmailRepository.updateStatusByIds(ids, status) + } +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailStatus.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailStatus.kt new file mode 100644 index 0000000..8aa598b --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailStatus.kt @@ -0,0 +1,5 @@ +package com.travel.withaeng.domain.validateemail + +enum class ValidatingEmailStatus { + YET, DONE, FAILED +} \ No newline at end of file diff --git a/withaeng-external/src/main/resources/external-config/application.yml b/withaeng-external/src/main/resources/application-external.yml similarity index 100% rename from withaeng-external/src/main/resources/external-config/application.yml rename to withaeng-external/src/main/resources/application-external.yml From 0836e36f1bb9a58921c96eddff256c30959047b0 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Tue, 7 May 2024 17:17:51 +0900 Subject: [PATCH 021/174] Fix to send email for SES logic --- .../travel/withaeng/external/ses/MailSender.kt | 3 ++- .../withaeng/external/ses/MailSenderImpl.kt | 18 ++++++++++++++---- .../resources/templates/email-template.html | 2 +- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSender.kt b/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSender.kt index 3240ce8..41d6aa3 100644 --- a/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSender.kt +++ b/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSender.kt @@ -1,5 +1,6 @@ package com.travel.withaeng.external.ses interface MailSender { - fun send(subject: String, variables: Map, vararg to: String) + + fun sendValidatingEmail(validatingEmailUrl: String, vararg to: String) } \ No newline at end of file diff --git a/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSenderImpl.kt b/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSenderImpl.kt index 4e3d531..cca831e 100644 --- a/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSenderImpl.kt +++ b/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSenderImpl.kt @@ -9,14 +9,20 @@ import org.thymeleaf.context.Context import java.nio.charset.StandardCharsets @Service -class MailSenderImpl(private val emailService: AmazonSimpleEmailService, private val templateEngine: TemplateEngine) : - MailSender { +class MailSenderImpl( + private val emailService: AmazonSimpleEmailService, + private val templateEngine: TemplateEngine +) : MailSender { @Value("\${cloud.aws.ses.from}") private lateinit var from: String - override fun send(subject: String, variables: Map, vararg to: String) { - val content = templateEngine.process("email-template", createContext(variables)) + override fun sendValidatingEmail(validatingEmailUrl: String, vararg to: String) { + send("email-template", VALIDATING_EMAIL_SUBJECT, mapOf("validatingEmailUrl" to validatingEmailUrl), *to) + } + + private fun send(template: String, subject: String, variables: Map, vararg to: String) { + val content = templateEngine.process(template, createContext(variables)) val request = createSendEmailRequest(subject, content, *to) emailService.sendEmail(request) } @@ -35,4 +41,8 @@ class MailSenderImpl(private val emailService: AmazonSimpleEmailService, private .withBody(Body().withHtml(Content().withCharset(StandardCharsets.UTF_8.name()).withData(content))) ) } + + companion object { + private const val VALIDATING_EMAIL_SUBJECT = "같이행 서비스 이메일 인증을 부탁드립니다." + } } \ No newline at end of file diff --git a/withaeng-external/src/main/resources/templates/email-template.html b/withaeng-external/src/main/resources/templates/email-template.html index ca18082..6eb45f9 100644 --- a/withaeng-external/src/main/resources/templates/email-template.html +++ b/withaeng-external/src/main/resources/templates/email-template.html @@ -5,6 +5,6 @@ 이메일 인증 -
+
\ No newline at end of file From 68392570d768d70f803e47a0d7fd5f9fb61db8ee Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Tue, 7 May 2024 17:18:09 +0900 Subject: [PATCH 022/174] Configuration about scheduler --- .../com/travel/withaeng/config/AsyncConfig.kt | 22 +++++++++++++++++++ .../travel/withaeng/config/SchedulerConfig.kt | 11 ++++++++++ 2 files changed, 33 insertions(+) create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/config/AsyncConfig.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/config/SchedulerConfig.kt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/AsyncConfig.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/config/AsyncConfig.kt new file mode 100644 index 0000000..24b527d --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/config/AsyncConfig.kt @@ -0,0 +1,22 @@ +package com.travel.withaeng.config + +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.scheduling.annotation.EnableAsync +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor +import java.util.concurrent.Executor + +@Configuration +@EnableAsync +class AsyncConfig { + @Bean(name = ["asyncSchedulerExecutor"]) + fun asyncSchedulerExecutor(): Executor { + return ThreadPoolTaskExecutor().apply { + corePoolSize = 5 + maxPoolSize = 5 + queueCapacity = 20 + setThreadNamePrefix("AsyncSchedulerThread-") + setWaitForTasksToCompleteOnShutdown(true) + } + } +} \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/SchedulerConfig.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/config/SchedulerConfig.kt new file mode 100644 index 0000000..b36be83 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/config/SchedulerConfig.kt @@ -0,0 +1,11 @@ +package com.travel.withaeng.config + +import com.travel.withaeng.scheduler.SchedulerBasePackage +import org.springframework.context.annotation.ComponentScan +import org.springframework.context.annotation.Configuration +import org.springframework.scheduling.annotation.EnableScheduling + +@Configuration +@EnableScheduling +@ComponentScan(basePackageClasses = [SchedulerBasePackage::class]) +class SchedulerConfig \ No newline at end of file From 289e26c21fb88163ae83a72c3d8bf947e86160bc Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Tue, 7 May 2024 17:18:22 +0900 Subject: [PATCH 023/174] Implement sending email scheduler --- .../scheduler/SchedulerBasePackage.kt | 3 ++ .../withaeng/scheduler/SendEmailScheduler.kt | 37 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/SchedulerBasePackage.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/SendEmailScheduler.kt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/SchedulerBasePackage.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/SchedulerBasePackage.kt new file mode 100644 index 0000000..896dd0b --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/SchedulerBasePackage.kt @@ -0,0 +1,3 @@ +package com.travel.withaeng.scheduler + +interface SchedulerBasePackage \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/SendEmailScheduler.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/SendEmailScheduler.kt new file mode 100644 index 0000000..de87ce4 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/SendEmailScheduler.kt @@ -0,0 +1,37 @@ +package com.travel.withaeng.scheduler + +import com.travel.withaeng.common.Constants.Url.VALIDATING_EMAIL_URL +import com.travel.withaeng.domain.validateemail.ValidatingEmailService +import com.travel.withaeng.domain.validateemail.ValidatingEmailStatus +import com.travel.withaeng.external.ses.MailSender +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import org.springframework.scheduling.annotation.Async +import org.springframework.scheduling.annotation.Scheduled +import org.springframework.stereotype.Component +import org.springframework.transaction.annotation.Transactional +import java.time.LocalDateTime + +@Component +class SendEmailScheduler( + private val validatingEmailService: ValidatingEmailService, + private val mailSender: MailSender +) { + + private val log: Logger = LoggerFactory.getLogger(SendEmailScheduler::class.java) + + @Scheduled(cron = "0 * * * * *") + @Async("asyncSchedulerExecutor") + @Transactional + fun sendEmail() { + val now = LocalDateTime.now() + log.info("Start sending emails at {}", now) + val willSendMails = validatingEmailService.findAllByStatusNot(ValidatingEmailStatus.DONE) + willSendMails.forEach { + mailSender.sendValidatingEmail(VALIDATING_EMAIL_URL, it.email) + } + if (willSendMails.isNotEmpty()) { + validatingEmailService.updateStatusByIds(willSendMails.map { it.id }.toSet(), ValidatingEmailStatus.DONE) + } + } +} \ No newline at end of file From 6530c88d1aa0f7e68bc1ae3e8ae014b757075b18 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Thu, 9 May 2024 00:58:37 +0900 Subject: [PATCH 024/174] Fix wrong logic from security config --- .../applicationservice/auth/dto/AuthApplicationDto.kt | 10 ++++++++++ .../applicationservice/auth/dto/AuthResponseDto.kt | 7 +++++++ .../security/authentication/JwtAuthentication.kt | 6 +++--- .../withaeng/security/authentication/UserInfo.kt | 2 -- .../com/travel/withaeng/security/jwt/JwtAgentImpl.kt | 4 ++-- .../com/travel/withaeng/security/jwt/JwtFilter.kt | 2 +- 6 files changed, 23 insertions(+), 8 deletions(-) create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthApplicationDto.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthResponseDto.kt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthApplicationDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthApplicationDto.kt new file mode 100644 index 0000000..4c709fb --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthApplicationDto.kt @@ -0,0 +1,10 @@ +package com.travel.withaeng.applicationservice.auth.dto + +import java.time.LocalDate + +data class SignUpServiceRequest( + val isMale: Boolean, + val birth: LocalDate, + val email: String, + val password: String +) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthResponseDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthResponseDto.kt new file mode 100644 index 0000000..44f95a8 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthResponseDto.kt @@ -0,0 +1,7 @@ +package com.travel.withaeng.applicationservice.auth.dto + +data class UserResponse( + val userId: Long, + val email: String, + val accessToken: String +) \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/authentication/JwtAuthentication.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/authentication/JwtAuthentication.kt index 6563dca..b3c8211 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/authentication/JwtAuthentication.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/authentication/JwtAuthentication.kt @@ -6,16 +6,16 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority class JwtAuthentication(private val userInfo: UserInfo) : Authentication { - var isAuthenticated = true + private var isAuthenticated = true - override fun getName(): String = userInfo.nickname + override fun getName(): String = userInfo.email override fun getAuthorities(): Collection = userInfo.roles .map { userRole -> SimpleGrantedAuthority(userRole.role) } override fun getCredentials(): Any = userInfo.id - override fun getDetails(): Any = userInfo.toDetails() + override fun getDetails(): Any = userInfo.toString() override fun getPrincipal(): Any = userInfo diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/authentication/UserInfo.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/authentication/UserInfo.kt index 8732c60..6998a8a 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/authentication/UserInfo.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/authentication/UserInfo.kt @@ -6,7 +6,6 @@ import com.travel.withaeng.domain.user.UserRole data class UserInfo( val id: Long, val email: String, - val nickname: String, val roles: Set, ) { companion object { @@ -14,7 +13,6 @@ data class UserInfo( return UserInfo( id = user.id, email = user.email, - nickname = user.nickname, roles = user.roles ) } diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtAgentImpl.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtAgentImpl.kt index 5e4192a..efd9f9a 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtAgentImpl.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtAgentImpl.kt @@ -29,8 +29,8 @@ class JwtAgentImpl( val expiredDateTime = issuerDateTime.plusDays(TOKEN_EXPIRE_DAY) return Jwts.builder() .setHeaderParam(KEY_TOKEN_TYPE, TOKEN_TYPE_JWT) - .setSubject(createSubject(userInfo.nickname)) - .setAudience("${userInfo.email}|${userInfo.id}|${userInfo.nickname}") + .setSubject(createSubject(userInfo.email)) + .setAudience("${userInfo.email}|${userInfo.id}") .setIssuer(issuer) .setIssuedAt(issuerDateTime.convertToDate()) .setExpiration(expiredDateTime.convertToDate()) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtFilter.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtFilter.kt index 0cc91a0..e36a813 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtFilter.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtFilter.kt @@ -82,7 +82,7 @@ class JwtFilter( // Swagger "/api-docs", "/swagger-ui", "/swagger-resources", // SignIn/SignUp Endpoints - "/v1/auth", + "/api/v1/auth", ) } } \ No newline at end of file From 3e167de51c5f37fbc7e7f56ccd06ddb041aaaca9 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Thu, 9 May 2024 00:59:00 +0900 Subject: [PATCH 025/174] Fix wrong jwt secret key --- withaeng-api/src/main/resources/application.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/withaeng-api/src/main/resources/application.yml b/withaeng-api/src/main/resources/application.yml index 0ff78e1..a67e12a 100644 --- a/withaeng-api/src/main/resources/application.yml +++ b/withaeng-api/src/main/resources/application.yml @@ -7,5 +7,5 @@ spring: witheang: auth: - jwt-secret-key: ENC(i5HqamjyyaTwDSyiHXoAxJrP11XyQ8mArvAUI1RD15tteCbIEnzVVp+qcYB45xDkybBZmjY79HDp/Ci5YkkSyg==) + jwt-secret-key: ENC(1t2RYsNu8JCGgZjC5HuE9t9690mWUiygMhKfUQIn3ZpVlSYI0WvRPnQswh3Uti3gBoDqJ4Zk3moN6wWswWQC7g+IFiEDUvqjTLzhfJrl9A0TIW0MOY0kd+vnVu0sernJ) jwt-issuer: https://github.com/withaeng/withaeng-backend \ No newline at end of file From df6c5770b1ef2a9a8066b12055c94ed15bf4929c Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Thu, 9 May 2024 01:09:08 +0900 Subject: [PATCH 026/174] Fix domain logic of User --- .../com/travel/withaeng/domain/user/User.kt | 24 +++++++------------ .../travel/withaeng/domain/user/UserDto.kt | 9 +++---- .../withaeng/domain/user/UserRepository.kt | 5 +++- .../travel/withaeng/domain/user/UserRole.kt | 1 + .../withaeng/domain/user/UserService.kt | 14 +++++++---- 5 files changed, 27 insertions(+), 26 deletions(-) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt index 510f880..94e7aa5 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt @@ -17,14 +17,14 @@ class User( @Column(name = "password", nullable = false) val password: String, - @Column(name = "nickname", nullable = false) - val nickname: String, + @Column(name = "nickname", nullable = true) + val nickname: String? = null, - @Column(name = "birth", nullable = true) - val birth: LocalDate? = null, + @Column(name = "birth", nullable = false) + val birth: LocalDate, - @Column(name = "is_male", nullable = true) - val isMale: Boolean? = null, + @Column(name = "is_male", nullable = false) + val isMale: Boolean, @Column(name = "profile_image_url") val profileImageUrl: String? = null, @@ -42,21 +42,15 @@ class User( fun create( email: String, password: String, - nickname: String, - birth: LocalDate? = null, - isMale: Boolean? = null, - profileImageUrl: String? = null, - bio: String? = null, + birth: LocalDate, + isMale: Boolean ): User { return User( email = email, password = password, - nickname = nickname, - profileImageUrl = profileImageUrl, birth = birth, isMale = isMale, - bio = bio, - roles = setOf(UserRole.USER) + roles = setOf(UserRole.NON_USER) ) } } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserDto.kt index dfc9c46..8bfe5cb 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserDto.kt @@ -6,7 +6,7 @@ data class UserDto( val id: Long, val email: String, val password: String, - val nickname: String, + val nickname: String? = null, val birth: LocalDate? = null, val isMale: Boolean? = null, val profileImageUrl: String? = null, @@ -29,9 +29,6 @@ fun User.toDto(): UserDto = UserDto( data class CreateUserDto( val email: String, val password: String, - val nickname: String, - val birth: LocalDate? = null, - val isMale: Boolean? = null, - val profileImageUrl: String? = null, - val bio: String? = null, + val birth: LocalDate, + val isMale: Boolean ) \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRepository.kt index e069c1d..e145117 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRepository.kt @@ -2,4 +2,7 @@ package com.travel.withaeng.domain.user import org.springframework.data.jpa.repository.JpaRepository -interface UserRepository : JpaRepository \ No newline at end of file +interface UserRepository : JpaRepository { + fun findByEmail(email: String): User? + fun deleteByEmail(email: String) +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRole.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRole.kt index e4456f4..1b7a6ce 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRole.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRole.kt @@ -3,6 +3,7 @@ package com.travel.withaeng.domain.user enum class UserRole( val role: String ) { + NON_USER("ROLE_NON_USER"), USER("ROLE_USER"), ADMIN("ROLE_ADMIN"), } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt index 03ecc0e..e94cd59 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt @@ -13,12 +13,18 @@ class UserService(private val userRepository: UserRepository) { User.create( email = createUserDto.email, password = createUserDto.password, - nickname = createUserDto.nickname, - profileImageUrl = createUserDto.profileImageUrl, birth = createUserDto.birth, - isMale = createUserDto.isMale, - bio = createUserDto.bio + isMale = createUserDto.isMale ) ).toDto() } + + fun findByEmailOrNull(email: String): UserDto? { + return userRepository.findByEmail(email)?.toDto() + } + + @Transactional + fun deleteByEmail(email: String) { + return userRepository.deleteByEmail(email) + } } \ No newline at end of file From 8ea3dd6d1c26419a3a47a134f4547370333876b1 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Thu, 9 May 2024 01:09:26 +0900 Subject: [PATCH 027/174] Implement Sign-up api --- withaeng-api/build.gradle.kts | 2 + .../auth/AuthApplicationService.kt | 40 +++++++++++++++++++ .../com/travel/withaeng/common/Constants.kt | 5 +++ .../com/travel/withaeng/config/AuthConfig.kt | 6 ++- .../controller/auth/AuthController.kt | 22 ++++++++++ .../controller/auth/dto/AuthRequestDto.kt | 18 +++++++++ .../src/main/resources/application.yml | 1 + 7 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/dto/AuthRequestDto.kt diff --git a/withaeng-api/build.gradle.kts b/withaeng-api/build.gradle.kts index b437721..82da003 100644 --- a/withaeng-api/build.gradle.kts +++ b/withaeng-api/build.gradle.kts @@ -10,8 +10,10 @@ val jjwtVersion: String by project.extra dependencies { implementation(project(":withaeng-domain")) implementation(project(":withaeng-common")) + implementation(project(":withaeng-external")) implementation("org.springframework.boot:spring-boot-starter-web") implementation("org.springframework.boot:spring-boot-starter-security") + api("org.springframework.boot:spring-boot-starter-data-jpa") // jwt implementation("io.jsonwebtoken:jjwt-api:$jjwtVersion") diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt new file mode 100644 index 0000000..ff4a152 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt @@ -0,0 +1,40 @@ +package com.travel.withaeng.applicationservice.auth + +import com.travel.withaeng.applicationservice.auth.dto.SignUpServiceRequest +import com.travel.withaeng.applicationservice.auth.dto.UserResponse +import com.travel.withaeng.domain.user.CreateUserDto +import com.travel.withaeng.domain.user.UserService +import com.travel.withaeng.domain.validateemail.ValidatingEmailService +import com.travel.withaeng.security.authentication.UserInfo +import com.travel.withaeng.security.jwt.JwtAgent +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional +import java.util.* + +@Service +@Transactional(readOnly = true) +class AuthApplicationService( + private val userService: UserService, + private val validatingEmailService: ValidatingEmailService, + private val jwtAgent: JwtAgent +) { + + @Transactional + fun signUp(request: SignUpServiceRequest): UserResponse { + val userEmail = request.email + val userDto = userService.findByEmailOrNull(request.email) + if (userDto != null) { + userService.deleteByEmail(userEmail) + } + val newUserDto = userService.createUser(request.toCreateUserDto()) + validatingEmailService.create(newUserDto.email, newUserDto.id, UUID.randomUUID().toString()) + return UserResponse(newUserDto.id, newUserDto.email, jwtAgent.provide(UserInfo.from(newUserDto))) + } + + private fun SignUpServiceRequest.toCreateUserDto(): CreateUserDto = CreateUserDto( + email = email, + password = password, + birth = birth, + isMale = isMale + ) +} \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/Constants.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/Constants.kt index 09a0be2..fd56c0a 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/Constants.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/Constants.kt @@ -5,4 +5,9 @@ object Constants { const val BEARER_TYPE = "Bearer" const val BEARER_TOKEN_PREFIX_WITH_WHITESPACE = "$BEARER_TYPE " } + + object Url { + const val BASE_URL = "localhost:3030/" + const val VALIDATING_EMAIL_URL = BASE_URL + "validate-email/" + } } \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/AuthConfig.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/config/AuthConfig.kt index 5b00d39..93eaa45 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/AuthConfig.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/config/AuthConfig.kt @@ -14,7 +14,11 @@ class AuthConfig { @Bean fun jwtAgent(mapper: ObjectMapper, authProperty: AuthProperty): JwtAgent { - return JwtAgentImpl(mapper, authProperty.jwtSecretKey, authProperty.jwtIssuer) + return JwtAgentImpl( + objectMapper = mapper, + issuer = authProperty.jwtIssuer, + key = authProperty.jwtSecretKey + ) } } diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt new file mode 100644 index 0000000..e077c70 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt @@ -0,0 +1,22 @@ +package com.travel.withaeng.controller.auth + +import com.travel.withaeng.applicationservice.auth.AuthApplicationService +import com.travel.withaeng.applicationservice.auth.dto.UserResponse +import com.travel.withaeng.common.ApiResponse +import com.travel.withaeng.controller.auth.dto.SignUpRequest +import com.travel.withaeng.controller.auth.dto.toServiceRequest +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController + +@RestController +@RequestMapping("api/v1/auth") +class AuthController(private val authApplicationService: AuthApplicationService) { + @PostMapping("/sign-up") + fun signUp(@RequestBody request: SignUpRequest): ApiResponse { + return ApiResponse.success( + authApplicationService.signUp(request.toServiceRequest()) + ) + } +} \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/dto/AuthRequestDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/dto/AuthRequestDto.kt new file mode 100644 index 0000000..5f4849d --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/dto/AuthRequestDto.kt @@ -0,0 +1,18 @@ +package com.travel.withaeng.controller.auth.dto + +import com.travel.withaeng.applicationservice.auth.dto.SignUpServiceRequest +import java.time.LocalDate + +data class SignUpRequest( + val isMale: Boolean, + val birth: LocalDate, + val email: String, + val password: String +) + +fun SignUpRequest.toServiceRequest(): SignUpServiceRequest = SignUpServiceRequest( + isMale = isMale, + birth = birth, + email = email, + password = password +) \ No newline at end of file diff --git a/withaeng-api/src/main/resources/application.yml b/withaeng-api/src/main/resources/application.yml index a67e12a..01daac1 100644 --- a/withaeng-api/src/main/resources/application.yml +++ b/withaeng-api/src/main/resources/application.yml @@ -4,6 +4,7 @@ spring: config: import: - classpath:/application-domain.yml + - classpath:/application-external.yml witheang: auth: From e9dd57d9a30c232305f2c5e2601d608be805850a Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Thu, 9 May 2024 01:26:48 +0900 Subject: [PATCH 028/174] Fix application profile configurations --- withaeng-api/src/main/resources/application-local.yml | 6 +++++- .../src/main/resources/application-domain-local.yml | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/withaeng-api/src/main/resources/application-local.yml b/withaeng-api/src/main/resources/application-local.yml index eb2416f..a1ee886 100644 --- a/withaeng-api/src/main/resources/application-local.yml +++ b/withaeng-api/src/main/resources/application-local.yml @@ -1,4 +1,8 @@ spring: config: activate: - on-profile: local \ No newline at end of file + on-profile: local + +logging: + level: + root: debug \ No newline at end of file diff --git a/withaeng-domain/src/main/resources/application-domain-local.yml b/withaeng-domain/src/main/resources/application-domain-local.yml index 3f5e62f..568caa7 100644 --- a/withaeng-domain/src/main/resources/application-domain-local.yml +++ b/withaeng-domain/src/main/resources/application-domain-local.yml @@ -4,7 +4,7 @@ spring: on-profile: local jpa: hibernate: - ddl-auto: create + ddl-auto: update properties: hibernate: show_sql: true From 7151072dd4eb7df944ba22fb58d47c9a758dcbe7 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Thu, 9 May 2024 01:27:12 +0900 Subject: [PATCH 029/174] Implement Sign-in api --- .../auth/AuthApplicationService.kt | 28 +++++++++++++++++-- .../auth/dto/AuthApplicationDto.kt | 5 ++++ .../travel/withaeng/config/SecurityConfig.kt | 7 +++++ .../controller/auth/AuthController.kt | 8 ++++++ .../controller/auth/dto/AuthRequestDto.kt | 11 ++++++++ 5 files changed, 57 insertions(+), 2 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt index ff4a152..d4826ab 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt @@ -1,12 +1,17 @@ package com.travel.withaeng.applicationservice.auth +import com.travel.withaeng.applicationservice.auth.dto.SignInServiceRequest import com.travel.withaeng.applicationservice.auth.dto.SignUpServiceRequest import com.travel.withaeng.applicationservice.auth.dto.UserResponse +import com.travel.withaeng.common.exception.WithaengException +import com.travel.withaeng.common.exception.WithaengExceptionType import com.travel.withaeng.domain.user.CreateUserDto +import com.travel.withaeng.domain.user.UserRole import com.travel.withaeng.domain.user.UserService import com.travel.withaeng.domain.validateemail.ValidatingEmailService import com.travel.withaeng.security.authentication.UserInfo import com.travel.withaeng.security.jwt.JwtAgent +import org.springframework.security.crypto.password.PasswordEncoder import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional import java.util.* @@ -16,14 +21,19 @@ import java.util.* class AuthApplicationService( private val userService: UserService, private val validatingEmailService: ValidatingEmailService, - private val jwtAgent: JwtAgent + private val jwtAgent: JwtAgent, + private val passwordEncoder: PasswordEncoder ) { @Transactional fun signUp(request: SignUpServiceRequest): UserResponse { val userEmail = request.email val userDto = userService.findByEmailOrNull(request.email) + val isValidUser = userDto?.roles?.any { it == UserRole.USER } if (userDto != null) { + if (isValidUser == true) { + throw WithaengException.of(WithaengExceptionType.ALREADY_EXIST, "이미 가입된 이메일입니다.") + } userService.deleteByEmail(userEmail) } val newUserDto = userService.createUser(request.toCreateUserDto()) @@ -31,9 +41,23 @@ class AuthApplicationService( return UserResponse(newUserDto.id, newUserDto.email, jwtAgent.provide(UserInfo.from(newUserDto))) } + @Transactional + fun signIn(request: SignInServiceRequest): UserResponse { + val userDto = userService.findByEmailOrNull(request.email) + ?: throw WithaengException.of(WithaengExceptionType.NOT_EXIST, "이메일에 해당하는 유저를 찾을 수 없습니다.") + checkValidUserPassword(request.password, userDto.password) + return UserResponse(userDto.id, userDto.email, jwtAgent.provide(UserInfo.from(userDto))) + } + + private fun checkValidUserPassword(source: String, encryptedPassword: String) { + if (!passwordEncoder.matches(source, encryptedPassword)) { + throw WithaengException.of(WithaengExceptionType.AUTHENTICATION_FAILURE) + } + } + private fun SignUpServiceRequest.toCreateUserDto(): CreateUserDto = CreateUserDto( email = email, - password = password, + password = passwordEncoder.encode(password), birth = birth, isMale = isMale ) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthApplicationDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthApplicationDto.kt index 4c709fb..690137d 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthApplicationDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthApplicationDto.kt @@ -8,3 +8,8 @@ data class SignUpServiceRequest( val email: String, val password: String ) + +data class SignInServiceRequest( + val email: String, + val password: String +) \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/SecurityConfig.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/config/SecurityConfig.kt index cd285c6..af61abe 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/SecurityConfig.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/config/SecurityConfig.kt @@ -11,6 +11,8 @@ import org.springframework.http.HttpHeaders import org.springframework.security.config.annotation.web.builders.HttpSecurity import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder +import org.springframework.security.crypto.password.PasswordEncoder import org.springframework.security.web.SecurityFilterChain import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter import org.springframework.web.cors.CorsConfiguration @@ -21,6 +23,11 @@ import org.springframework.web.cors.UrlBasedCorsConfigurationSource @EnableWebSecurity class SecurityConfig(private val jwtAgent: JwtAgent, private val objectMapper: ObjectMapper) { + @Bean + fun passwordEncoder(): PasswordEncoder { + return BCryptPasswordEncoder() + } + @Bean fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { return http diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt index e077c70..a55d702 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt @@ -3,6 +3,7 @@ package com.travel.withaeng.controller.auth import com.travel.withaeng.applicationservice.auth.AuthApplicationService import com.travel.withaeng.applicationservice.auth.dto.UserResponse import com.travel.withaeng.common.ApiResponse +import com.travel.withaeng.controller.auth.dto.SignInRequest import com.travel.withaeng.controller.auth.dto.SignUpRequest import com.travel.withaeng.controller.auth.dto.toServiceRequest import org.springframework.web.bind.annotation.PostMapping @@ -19,4 +20,11 @@ class AuthController(private val authApplicationService: AuthApplicationService) authApplicationService.signUp(request.toServiceRequest()) ) } + + @PostMapping("/sign-in") + fun signIn(@RequestBody request: SignInRequest): ApiResponse { + return ApiResponse.success( + authApplicationService.signIn(request.toServiceRequest()) + ) + } } \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/dto/AuthRequestDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/dto/AuthRequestDto.kt index 5f4849d..614a557 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/dto/AuthRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/dto/AuthRequestDto.kt @@ -1,5 +1,6 @@ package com.travel.withaeng.controller.auth.dto +import com.travel.withaeng.applicationservice.auth.dto.SignInServiceRequest import com.travel.withaeng.applicationservice.auth.dto.SignUpServiceRequest import java.time.LocalDate @@ -10,9 +11,19 @@ data class SignUpRequest( val password: String ) +data class SignInRequest( + val email: String, + val password: String +) + fun SignUpRequest.toServiceRequest(): SignUpServiceRequest = SignUpServiceRequest( isMale = isMale, birth = birth, email = email, password = password +) + +fun SignInRequest.toServiceRequest(): SignInServiceRequest = SignInServiceRequest( + email = email, + password = password ) \ No newline at end of file From 0d6ac95d4db8492c0e7daeeb56d7f1ed155366e7 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Thu, 9 May 2024 01:53:34 +0900 Subject: [PATCH 030/174] Implement validate-email api --- .../auth/AuthApplicationService.kt | 26 +++++++++++++++++-- .../auth/dto/AuthApplicationDto.kt | 5 ++++ .../controller/auth/AuthController.kt | 12 ++++++--- .../controller/auth/dto/AuthRequestDto.kt | 23 +++++++++++----- .../com/travel/withaeng/domain/user/User.kt | 2 +- .../withaeng/domain/user/UserService.kt | 11 ++++++++ .../ValidatingEmailRepository.kt | 5 +++- .../validateemail/ValidatingEmailService.kt | 18 +++++++++++++ .../resources/application-domain-local.yml | 2 +- 9 files changed, 89 insertions(+), 15 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt index d4826ab..bd0e010 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt @@ -3,9 +3,11 @@ package com.travel.withaeng.applicationservice.auth import com.travel.withaeng.applicationservice.auth.dto.SignInServiceRequest import com.travel.withaeng.applicationservice.auth.dto.SignUpServiceRequest import com.travel.withaeng.applicationservice.auth.dto.UserResponse +import com.travel.withaeng.applicationservice.auth.dto.ValidateEmailServiceRequest import com.travel.withaeng.common.exception.WithaengException import com.travel.withaeng.common.exception.WithaengExceptionType import com.travel.withaeng.domain.user.CreateUserDto +import com.travel.withaeng.domain.user.UserDto import com.travel.withaeng.domain.user.UserRole import com.travel.withaeng.domain.user.UserService import com.travel.withaeng.domain.validateemail.ValidatingEmailService @@ -29,12 +31,12 @@ class AuthApplicationService( fun signUp(request: SignUpServiceRequest): UserResponse { val userEmail = request.email val userDto = userService.findByEmailOrNull(request.email) - val isValidUser = userDto?.roles?.any { it == UserRole.USER } if (userDto != null) { - if (isValidUser == true) { + if (userDto.isValidUser()) { throw WithaengException.of(WithaengExceptionType.ALREADY_EXIST, "이미 가입된 이메일입니다.") } userService.deleteByEmail(userEmail) + validatingEmailService.deleteAllByUserId(userDto.id) } val newUserDto = userService.createUser(request.toCreateUserDto()) validatingEmailService.create(newUserDto.email, newUserDto.id, UUID.randomUUID().toString()) @@ -49,6 +51,26 @@ class AuthApplicationService( return UserResponse(userDto.id, userDto.email, jwtAgent.provide(UserInfo.from(userDto))) } + @Transactional + fun validateEmail(request: ValidateEmailServiceRequest) { + val requestedEmail = request.email + val userDto = userService.findByEmailOrNull(requestedEmail) + ?: throw WithaengException.of(WithaengExceptionType.NOT_EXIST, "이메일에 해당하는 유저를 찾을 수 없습니다.") + if (userDto.isValidUser()) { + throw WithaengException.of(WithaengExceptionType.INVALID_ACCESS, "이미 인증된 유저입니다.") + } + val validatingEmailDto = validatingEmailService.findByEmail(requestedEmail) + if (validatingEmailDto.userId != userDto.id || validatingEmailDto.code != request.code) { + throw WithaengException.of(WithaengExceptionType.INVALID_INPUT, "Code가 올바르지 않습니다.") + } + validatingEmailService.deleteById(validatingEmailDto.id) + userService.grantUserRole(userDto.id) + } + + private fun UserDto.isValidUser(): Boolean { + return roles.any { it == UserRole.USER } + } + private fun checkValidUserPassword(source: String, encryptedPassword: String) { if (!passwordEncoder.matches(source, encryptedPassword)) { throw WithaengException.of(WithaengExceptionType.AUTHENTICATION_FAILURE) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthApplicationDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthApplicationDto.kt index 690137d..04186a3 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthApplicationDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthApplicationDto.kt @@ -12,4 +12,9 @@ data class SignUpServiceRequest( data class SignInServiceRequest( val email: String, val password: String +) + +data class ValidateEmailServiceRequest( + val email: String, + val code: String ) \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt index a55d702..81b9724 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt @@ -5,11 +5,9 @@ import com.travel.withaeng.applicationservice.auth.dto.UserResponse import com.travel.withaeng.common.ApiResponse import com.travel.withaeng.controller.auth.dto.SignInRequest import com.travel.withaeng.controller.auth.dto.SignUpRequest +import com.travel.withaeng.controller.auth.dto.ValidateEmailRequest import com.travel.withaeng.controller.auth.dto.toServiceRequest -import org.springframework.web.bind.annotation.PostMapping -import org.springframework.web.bind.annotation.RequestBody -import org.springframework.web.bind.annotation.RequestMapping -import org.springframework.web.bind.annotation.RestController +import org.springframework.web.bind.annotation.* @RestController @RequestMapping("api/v1/auth") @@ -27,4 +25,10 @@ class AuthController(private val authApplicationService: AuthApplicationService) authApplicationService.signIn(request.toServiceRequest()) ) } + + @PutMapping("/validate-email") + fun validateEmail(@RequestBody request: ValidateEmailRequest): ApiResponse { + authApplicationService.validateEmail(request.toServiceRequest()) + return ApiResponse.success() + } } \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/dto/AuthRequestDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/dto/AuthRequestDto.kt index 614a557..f571256 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/dto/AuthRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/dto/AuthRequestDto.kt @@ -2,6 +2,7 @@ package com.travel.withaeng.controller.auth.dto import com.travel.withaeng.applicationservice.auth.dto.SignInServiceRequest import com.travel.withaeng.applicationservice.auth.dto.SignUpServiceRequest +import com.travel.withaeng.applicationservice.auth.dto.ValidateEmailServiceRequest import java.time.LocalDate data class SignUpRequest( @@ -11,11 +12,6 @@ data class SignUpRequest( val password: String ) -data class SignInRequest( - val email: String, - val password: String -) - fun SignUpRequest.toServiceRequest(): SignUpServiceRequest = SignUpServiceRequest( isMale = isMale, birth = birth, @@ -23,7 +19,22 @@ fun SignUpRequest.toServiceRequest(): SignUpServiceRequest = SignUpServiceReques password = password ) +data class SignInRequest( + val email: String, + val password: String +) + fun SignInRequest.toServiceRequest(): SignInServiceRequest = SignInServiceRequest( email = email, password = password -) \ No newline at end of file +) + +data class ValidateEmailRequest( + val email: String, + val code: String +) + +fun ValidateEmailRequest.toServiceRequest(): ValidateEmailServiceRequest = ValidateEmailServiceRequest( + email = email, + code = code +) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt index 94e7aa5..3056b1d 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt @@ -34,7 +34,7 @@ class User( @Convert(converter = UserRoleConverter::class) @Column(name = "roles") - val roles: Set, + var roles: Set, ) : BaseEntity() { companion object { diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt index e94cd59..04ef1ae 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt @@ -1,5 +1,8 @@ package com.travel.withaeng.domain.user +import com.travel.withaeng.common.exception.WithaengException +import com.travel.withaeng.common.exception.WithaengExceptionType +import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -23,6 +26,14 @@ class UserService(private val userRepository: UserRepository) { return userRepository.findByEmail(email)?.toDto() } + @Transactional + fun grantUserRole(id: Long) { + val user = userRepository.findByIdOrNull(id) + ?: throw WithaengException.of(WithaengExceptionType.SYSTEM_FAIL) + val newUserRoles = user.roles.filter { it != UserRole.NON_USER } + listOf(UserRole.USER) + user.roles = newUserRoles.toSet() + } + @Transactional fun deleteByEmail(email: String) { return userRepository.deleteByEmail(email) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailRepository.kt index 1255990..3bc4ce1 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailRepository.kt @@ -3,12 +3,15 @@ package com.travel.withaeng.domain.validateemail import org.springframework.data.jpa.repository.JpaRepository import org.springframework.data.jpa.repository.Modifying import org.springframework.data.jpa.repository.Query -import java.time.LocalDateTime interface ValidatingEmailRepository : JpaRepository { fun findAllByStatusNot(status: ValidatingEmailStatus): List + fun findByEmail(email: String): ValidatingEmail? + @Modifying @Query("UPDATE ValidatingEmail v SET v.status = :status WHERE v.id in :ids") fun updateStatusByIds(ids: Set, status: ValidatingEmailStatus) + + fun deleteAllByUserId(userId: Long) } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailService.kt index deba547..9665619 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailService.kt @@ -29,10 +29,28 @@ class ValidatingEmailService( return validatingEmailRepository.save(ValidatingEmail(email, userId, code)).toDto() } + fun findByEmail(email: String): ValidatingEmailDto { + return validatingEmailRepository.findByEmail(email)?.toDto() + ?: throw WithaengException.of( + WithaengExceptionType.NOT_EXIST, + "이메일에 해당하는 요청이 없습니다." + ) + } + fun findAllByStatusNot(status: ValidatingEmailStatus): List { return validatingEmailRepository.findAllByStatusNot(status).map { it.toDto() } } + @Transactional + fun deleteById(id: Long) { + validatingEmailRepository.deleteById(id) + } + + @Transactional + fun deleteAllByUserId(userId: Long) { + validatingEmailRepository.deleteAllByUserId(userId) + } + @Transactional fun updateStatusByIds(ids: Set, status: ValidatingEmailStatus) { validatingEmailRepository.updateStatusByIds(ids, status) diff --git a/withaeng-domain/src/main/resources/application-domain-local.yml b/withaeng-domain/src/main/resources/application-domain-local.yml index 568caa7..3f5e62f 100644 --- a/withaeng-domain/src/main/resources/application-domain-local.yml +++ b/withaeng-domain/src/main/resources/application-domain-local.yml @@ -4,7 +4,7 @@ spring: on-profile: local jpa: hibernate: - ddl-auto: update + ddl-auto: create properties: hibernate: show_sql: true From d196f4a06d4ae5727027c0400ecbdc4518df96c5 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Thu, 9 May 2024 02:09:15 +0900 Subject: [PATCH 031/174] Add swagger dependency --- gradle.properties | 4 +++- withaeng-api/build.gradle.kts | 5 +++++ .../com/travel/withaeng/config/SwaggerConfig.kt | 14 ++++++++++++++ withaeng-api/src/main/resources/application.yml | 9 +++++++++ 4 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/config/SwaggerConfig.kt diff --git a/gradle.properties b/gradle.properties index 757ce6b..adf22ee 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,4 +14,6 @@ jasyptVersion=3.0.5 ### Persistence versions ### mysqlVersion=8.3.0 ### jjwt version -jjwtVersion=0.11.5 \ No newline at end of file +jjwtVersion=0.11.5 +### Swagger Version +swaggerVersion=2.2.0 \ No newline at end of file diff --git a/withaeng-api/build.gradle.kts b/withaeng-api/build.gradle.kts index 82da003..e69cc74 100644 --- a/withaeng-api/build.gradle.kts +++ b/withaeng-api/build.gradle.kts @@ -7,6 +7,8 @@ tasks.getByName("jar") { } val jjwtVersion: String by project.extra +val swaggerVersion: String by project.extra + dependencies { implementation(project(":withaeng-domain")) implementation(project(":withaeng-common")) @@ -19,4 +21,7 @@ dependencies { implementation("io.jsonwebtoken:jjwt-api:$jjwtVersion") runtimeOnly("io.jsonwebtoken:jjwt-impl:$jjwtVersion") runtimeOnly("io.jsonwebtoken:jjwt-jackson:$jjwtVersion") + + // Swagger + implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:$swaggerVersion") } \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/SwaggerConfig.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/config/SwaggerConfig.kt new file mode 100644 index 0000000..5113cdc --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/config/SwaggerConfig.kt @@ -0,0 +1,14 @@ +package com.travel.withaeng.config + +import io.swagger.v3.oas.annotations.enums.SecuritySchemeType +import io.swagger.v3.oas.annotations.security.SecurityScheme +import org.springframework.context.annotation.Configuration + +@Configuration +@SecurityScheme( + name = "Authorization", + type = SecuritySchemeType.HTTP, + bearerFormat = "JWT", + scheme = "bearer" +) +class SwaggerConfig \ No newline at end of file diff --git a/withaeng-api/src/main/resources/application.yml b/withaeng-api/src/main/resources/application.yml index 01daac1..35af6a4 100644 --- a/withaeng-api/src/main/resources/application.yml +++ b/withaeng-api/src/main/resources/application.yml @@ -6,6 +6,15 @@ spring: - classpath:/application-domain.yml - classpath:/application-external.yml +# Swagger docs +springdoc: + swagger-ui: + path: /api-docs + operations-sorter: alpha + api-docs: + groups: + enabled: true + witheang: auth: jwt-secret-key: ENC(1t2RYsNu8JCGgZjC5HuE9t9690mWUiygMhKfUQIn3ZpVlSYI0WvRPnQswh3Uti3gBoDqJ4Zk3moN6wWswWQC7g+IFiEDUvqjTLzhfJrl9A0TIW0MOY0kd+vnVu0sernJ) From bae26fe2d4323b7917d4b8b07aca29b012443fdb Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Thu, 9 May 2024 02:09:27 +0900 Subject: [PATCH 032/174] Write swagger descriptions about auth api --- .../withaeng/controller/auth/AuthController.kt | 7 +++++++ .../controller/auth/dto/AuthRequestDto.kt | 17 +++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt index 81b9724..1a2b83b 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt @@ -7,11 +7,16 @@ import com.travel.withaeng.controller.auth.dto.SignInRequest import com.travel.withaeng.controller.auth.dto.SignUpRequest import com.travel.withaeng.controller.auth.dto.ValidateEmailRequest import com.travel.withaeng.controller.auth.dto.toServiceRequest +import io.swagger.v3.oas.annotations.Operation +import io.swagger.v3.oas.annotations.tags.Tag import org.springframework.web.bind.annotation.* +@Tag(name = "Auth", description = "Auth API") @RestController @RequestMapping("api/v1/auth") class AuthController(private val authApplicationService: AuthApplicationService) { + + @Operation(summary = "Sign Up API", description = "회원가입 API") @PostMapping("/sign-up") fun signUp(@RequestBody request: SignUpRequest): ApiResponse { return ApiResponse.success( @@ -19,6 +24,7 @@ class AuthController(private val authApplicationService: AuthApplicationService) ) } + @Operation(summary = "Sign In API", description = "로그인 API") @PostMapping("/sign-in") fun signIn(@RequestBody request: SignInRequest): ApiResponse { return ApiResponse.success( @@ -26,6 +32,7 @@ class AuthController(private val authApplicationService: AuthApplicationService) ) } + @Operation(summary = "Validating Email API", description = "이메일 인증 API") @PutMapping("/validate-email") fun validateEmail(@RequestBody request: ValidateEmailRequest): ApiResponse { authApplicationService.validateEmail(request.toServiceRequest()) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/dto/AuthRequestDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/dto/AuthRequestDto.kt index f571256..4be41f5 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/dto/AuthRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/dto/AuthRequestDto.kt @@ -3,12 +3,21 @@ package com.travel.withaeng.controller.auth.dto import com.travel.withaeng.applicationservice.auth.dto.SignInServiceRequest import com.travel.withaeng.applicationservice.auth.dto.SignUpServiceRequest import com.travel.withaeng.applicationservice.auth.dto.ValidateEmailServiceRequest +import io.swagger.v3.oas.annotations.media.Schema import java.time.LocalDate +@Schema(description = "[Request] 회원가입") data class SignUpRequest( + @Schema(description = "남/여 성별") val isMale: Boolean, + + @Schema(description = "생년월일 format:[2024-05-09]") val birth: LocalDate, + + @Schema(description = "회원가입 할 이메일") val email: String, + + @Schema(description = "회원가입 할 패스워드") val password: String ) @@ -19,8 +28,12 @@ fun SignUpRequest.toServiceRequest(): SignUpServiceRequest = SignUpServiceReques password = password ) +@Schema(description = "[Request] 로그인") data class SignInRequest( + @Schema(description = "로그인 할 이메일") val email: String, + + @Schema(description = "로그인 할 패스워드") val password: String ) @@ -29,8 +42,12 @@ fun SignInRequest.toServiceRequest(): SignInServiceRequest = SignInServiceReques password = password ) +@Schema(description = "[Request] 이메일 인증") data class ValidateEmailRequest( + @Schema(description = "이메일 인증 할 이메일") val email: String, + + @Schema(description = "이메일 인증으로 보낸 코드 (UUID 형태)") val code: String ) From eb1c87635f0c53e96d14d6d742a1c2b00f41e739 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Thu, 9 May 2024 03:01:09 +0900 Subject: [PATCH 033/174] Prevent accesing resources from unauthorized user --- .../com/travel/withaeng/common/WhiteList.kt | 24 +++++++++++++++++++ .../travel/withaeng/config/SecurityConfig.kt | 18 ++++++-------- .../travel/withaeng/security/jwt/JwtFilter.kt | 12 ++-------- .../travel/withaeng/domain/user/UserRole.kt | 6 ++++- .../resources/application-domain-local.yml | 2 +- 5 files changed, 39 insertions(+), 23 deletions(-) create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/common/WhiteList.kt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/WhiteList.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/WhiteList.kt new file mode 100644 index 0000000..d8d19fc --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/WhiteList.kt @@ -0,0 +1,24 @@ +package com.travel.withaeng.common + +object WhiteList { + + fun getWhiteListForSecurityConfig(): List = listOf( + // swagger + "/api-docs/**", "/swagger-ui/**", "/swagger-resources/**", "/v3/api-docs/**", + // error page + "/error/**", + // Auth endpoints + "/api/v1/auth/**", + ) + + fun getWhiteListForAuthenticationFilter(): List = listOf( + // Common + "/favicon.ico", + "/error", + // Swagger + "/api-docs", "/swagger-ui", "/swagger-resources", + // SignIn/SignUp Endpoints + "/api/v1/auth", + ) + +} \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/SecurityConfig.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/config/SecurityConfig.kt index af61abe..6abd758 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/SecurityConfig.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/config/SecurityConfig.kt @@ -1,6 +1,8 @@ package com.travel.withaeng.config import com.fasterxml.jackson.databind.ObjectMapper +import com.travel.withaeng.common.WhiteList.getWhiteListForSecurityConfig +import com.travel.withaeng.domain.user.UserRole import com.travel.withaeng.security.handler.HttpStatusAccessDeniedHandler import com.travel.withaeng.security.handler.HttpStatusAuthenticationEntryPoint import com.travel.withaeng.security.jwt.JwtAgent @@ -15,6 +17,7 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder import org.springframework.security.crypto.password.PasswordEncoder import org.springframework.security.web.SecurityFilterChain import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter +import org.springframework.security.web.util.matcher.AntPathRequestMatcher import org.springframework.web.cors.CorsConfiguration import org.springframework.web.cors.CorsConfigurationSource import org.springframework.web.cors.UrlBasedCorsConfigurationSource @@ -36,7 +39,9 @@ class SecurityConfig(private val jwtAgent: JwtAgent, private val objectMapper: O .httpBasic { it.disable() } .formLogin { it.disable() } .authorizeHttpRequests { - it.anyRequest().permitAll() // TODO: 추후 인가 추가 + it.requestMatchers(AntPathRequestMatcher("/**")) + .hasAnyRole(UserRole.USER.getActualRoleName(), UserRole.ADMIN.getActualRoleName()) + .anyRequest().permitAll() } .addFilterBefore(JwtFilter(jwtAgent, objectMapper), UsernamePasswordAuthenticationFilter::class.java) .exceptionHandling { @@ -49,7 +54,7 @@ class SecurityConfig(private val jwtAgent: JwtAgent, private val objectMapper: O @Bean fun webSecurityCustomizer(): WebSecurityCustomizer { return WebSecurityCustomizer { - it.ignoring().requestMatchers(*WHITE_LIST.toTypedArray()) + it.ignoring().requestMatchers(*getWhiteListForSecurityConfig().toTypedArray()) } } @@ -70,14 +75,5 @@ class SecurityConfig(private val jwtAgent: JwtAgent, private val objectMapper: O companion object { private const val MAX_CORS_EXPIRE_SECONDS = 3600L - - private val WHITE_LIST = listOf( - // swagger - "/api-docs/**", "/swagger-ui/**", "/swagger-resources/**", "/v3/api-docs/**", - // error page - "/error/**", - // Auth endpoints - "/v1/auth/**", - ) } } \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtFilter.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtFilter.kt index e36a813..5cf53bf 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtFilter.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtFilter.kt @@ -3,6 +3,7 @@ package com.travel.withaeng.security.jwt import com.fasterxml.jackson.databind.ObjectMapper import com.travel.withaeng.common.ApiResponse import com.travel.withaeng.common.Constants.Authentication.BEARER_TYPE +import com.travel.withaeng.common.WhiteList.getWhiteListForAuthenticationFilter import com.travel.withaeng.common.exception.WithaengException import com.travel.withaeng.common.exception.WithaengExceptionType import com.travel.withaeng.security.authentication.JwtAuthentication @@ -70,19 +71,10 @@ class JwtFilter( private fun HttpServletRequest.getAuthorization(): String? = getHeader(HttpHeaders.AUTHORIZATION) private fun isNotCheckEndpoint(request: HttpServletRequest): Boolean { - return NOT_CHECK_ENDPOINTS.any { request.requestURI.startsWith(it) } + return getWhiteListForAuthenticationFilter().any { request.requestURI.startsWith(it) } } companion object { private const val AUTH_PROVIDER_SPLIT_DELIMITER: String = " " - private val NOT_CHECK_ENDPOINTS = listOf( - // Common - "/favicon.ico", - "/error", - // Swagger - "/api-docs", "/swagger-ui", "/swagger-resources", - // SignIn/SignUp Endpoints - "/api/v1/auth", - ) } } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRole.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRole.kt index 1b7a6ce..2a6955f 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRole.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRole.kt @@ -5,5 +5,9 @@ enum class UserRole( ) { NON_USER("ROLE_NON_USER"), USER("ROLE_USER"), - ADMIN("ROLE_ADMIN"), + ADMIN("ROLE_ADMIN"); + + fun getActualRoleName(): String { + return role.split("_")[1] + } } \ No newline at end of file diff --git a/withaeng-domain/src/main/resources/application-domain-local.yml b/withaeng-domain/src/main/resources/application-domain-local.yml index 3f5e62f..77902b6 100644 --- a/withaeng-domain/src/main/resources/application-domain-local.yml +++ b/withaeng-domain/src/main/resources/application-domain-local.yml @@ -4,7 +4,7 @@ spring: on-profile: local jpa: hibernate: - ddl-auto: create + ddl-auto: none properties: hibernate: show_sql: true From faced6baf3056e0ff1fe2c6c07bf55ef9eeb92de Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Fri, 10 May 2024 02:20:05 +0900 Subject: [PATCH 034/174] Implement UserInfoArgumentResolver --- .../travel/withaeng/config/WebConfigurer.kt | 32 +++++++++++++++++ .../withaeng/security/resolver/GetAuth.kt | 8 +++++ .../resolver/UserInfoArgumentResolver.kt | 36 +++++++++++++++++++ 3 files changed, 76 insertions(+) create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/config/WebConfigurer.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/security/resolver/GetAuth.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/security/resolver/UserInfoArgumentResolver.kt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/WebConfigurer.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/config/WebConfigurer.kt new file mode 100644 index 0000000..4375465 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/config/WebConfigurer.kt @@ -0,0 +1,32 @@ +package com.travel.withaeng.config + +import com.travel.withaeng.security.resolver.UserInfoArgumentResolver +import org.springframework.context.annotation.Configuration +import org.springframework.http.converter.ByteArrayHttpMessageConverter +import org.springframework.http.converter.HttpMessageConverter +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter +import org.springframework.web.method.support.HandlerMethodArgumentResolver +import org.springframework.web.servlet.config.annotation.EnableWebMvc +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer + +@EnableWebMvc +@Configuration +class WebConfigurer( + private val jackson2ObjectMapperBuilder: Jackson2ObjectMapperBuilder, +) : WebMvcConfigurer { + + override fun addArgumentResolvers(resolvers: MutableList) { + resolvers.add(UserInfoArgumentResolver()) + } + + override fun configureMessageConverters(converters: MutableList>) { + converters.addAll( + listOf( + ByteArrayHttpMessageConverter(), + MappingJackson2HttpMessageConverter(jackson2ObjectMapperBuilder.build()), + ) + ) + } + +} \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/resolver/GetAuth.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/resolver/GetAuth.kt new file mode 100644 index 0000000..d7be26a --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/resolver/GetAuth.kt @@ -0,0 +1,8 @@ +package com.travel.withaeng.security.resolver + +import io.swagger.v3.oas.annotations.media.Schema + +@Retention(AnnotationRetention.RUNTIME) +@Target(AnnotationTarget.VALUE_PARAMETER) +@Schema(hidden = true) +annotation class GetAuth diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/resolver/UserInfoArgumentResolver.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/resolver/UserInfoArgumentResolver.kt new file mode 100644 index 0000000..3e9f9f7 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/resolver/UserInfoArgumentResolver.kt @@ -0,0 +1,36 @@ +package com.travel.withaeng.security.resolver + +import com.travel.withaeng.common.exception.WithaengException +import com.travel.withaeng.common.exception.WithaengExceptionType +import com.travel.withaeng.security.authentication.JwtAuthentication +import com.travel.withaeng.security.authentication.UserInfo +import org.springframework.core.MethodParameter +import org.springframework.security.core.context.SecurityContextHolder +import org.springframework.web.bind.support.WebDataBinderFactory +import org.springframework.web.context.request.NativeWebRequest +import org.springframework.web.method.support.HandlerMethodArgumentResolver +import org.springframework.web.method.support.ModelAndViewContainer + +class UserInfoArgumentResolver : HandlerMethodArgumentResolver { + + override fun supportsParameter(parameter: MethodParameter): Boolean { + return parameter.hasParameterAnnotation(GetAuth::class.java) + && parameter.parameter.type == UserInfo::class.java + } + + override fun resolveArgument( + parameter: MethodParameter, + mavContainer: ModelAndViewContainer?, + webRequest: NativeWebRequest, + binderFactory: WebDataBinderFactory? + ): Any { + return when (val authentication = SecurityContextHolder.getContext().authentication) { + null -> throw WithaengException.of(WithaengExceptionType.AUTH_ERROR) + is JwtAuthentication -> authentication.principal + else -> throw WithaengException.of( + type = WithaengExceptionType.AUTH_ERROR, + message = "The argument of GetAuth annotation is not of type UserInfo class." + ) + } + } +} \ No newline at end of file From e55058f0a0914e4993c77a69f345ab330715762a Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Fri, 10 May 2024 02:21:35 +0900 Subject: [PATCH 035/174] Configure body writer data type converter --- .../travel/withaeng/config/JacksonConfig.kt | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/config/JacksonConfig.kt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/JacksonConfig.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/config/JacksonConfig.kt new file mode 100644 index 0000000..f51de48 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/config/JacksonConfig.kt @@ -0,0 +1,27 @@ +package com.travel.withaeng.config + +import com.fasterxml.jackson.databind.DeserializationFeature +import com.fasterxml.jackson.databind.SerializationFeature +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer +import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.LocalTime +import java.time.format.DateTimeFormatter + +@Configuration +class JacksonConfig { + @Bean + fun jackson2ObjectMapperBuilder(): Jackson2ObjectMapperBuilder { + return Jackson2ObjectMapperBuilder() + .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) + .featuresToDisable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) + .serializerByType(LocalDateTime::class.java, LocalDateTimeSerializer(DateTimeFormatter.ISO_LOCAL_DATE_TIME)) + .serializerByType(LocalDate::class.java, LocalDateSerializer(DateTimeFormatter.ISO_LOCAL_DATE)) + .serializerByType(LocalTime::class.java, LocalTimeSerializer(DateTimeFormatter.ISO_LOCAL_TIME)) + } +} \ No newline at end of file From b778d326890eeeab6fdc1a203de8df5ec45d88c8 Mon Sep 17 00:00:00 2001 From: collenkim Date: Wed, 20 Mar 2024 07:22:21 -0700 Subject: [PATCH 036/174] =?UTF-8?q?1=EC=B0=A8=20=EA=B0=9C=EB=B0=9C?= =?UTF-8?q?=EA=B1=B4=20=EC=BB=A4=EB=B0=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/AccompanyController.kt | 25 +++++++ .../controller/AccompanyLikeController.kt | 4 + .../controller/AccompanyReplyController.kt | 4 + .../withaeng/common/cd/AccompanyStatusCd.kt | 12 +++ .../com/travel/withaeng/common/cd/CityCd.kt | 4 + .../travel/withaeng/common/cd/ContinentCd.kt | 14 ++++ .../travel/withaeng/common/cd/CountryCd.kt | 4 + withaeng-domain/build.gradle.kts | 5 +- .../com/travel/withaeng/domain/BaseEntity.kt | 5 -- .../accompany/AccompanyCategoryEntity.kt | 27 +++++++ .../withaeng/domain/accompany/AccompanyDto.kt | 75 ++++++++++++++----- .../{Accompany.kt => AccompanyEntity.kt} | 17 +++-- .../domain/accompany/AccompanyHistEntity.kt | 47 ++++++++++++ .../domain/accompany/AccompanyRepository.kt | 2 +- .../domain/accompany/AccompanyService.kt | 15 ++++ ...ccompanyLike.kt => AccompanyLikeEntity.kt} | 13 +++- .../accompanylike/AccompanyLikeRepository.kt | 2 +- .../accompanyreply/AccompanyReplyDto.kt | 63 ++++++++++++---- ...ompanyReply.kt => AccompanyReplyEntity.kt} | 25 ++++--- .../AccompanyReplyRepository.kt | 2 +- .../accompanyreplylike/AccompanyReplyLike.kt | 16 ---- .../AccompanyReplyLikeEntity.kt | 21 ++++++ .../AccompanyReplyLikeRepository.kt | 2 +- .../src/main/resources/application-domain.yml | 18 +++-- 24 files changed, 340 insertions(+), 82 deletions(-) create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/accompany/controller/AccompanyController.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyLike/controller/AccompanyLikeController.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReply/controller/AccompanyReplyController.kt create mode 100644 withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/AccompanyStatusCd.kt create mode 100644 withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CityCd.kt create mode 100644 withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/ContinentCd.kt create mode 100644 withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CountryCd.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyCategoryEntity.kt rename withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/{Accompany.kt => AccompanyEntity.kt} (66%) create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt rename withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/{AccompanyLike.kt => AccompanyLikeEntity.kt} (61%) rename withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/{AccompanyReply.kt => AccompanyReplyEntity.kt} (55%) delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLike.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeEntity.kt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompany/controller/AccompanyController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompany/controller/AccompanyController.kt new file mode 100644 index 0000000..ec31357 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompany/controller/AccompanyController.kt @@ -0,0 +1,25 @@ +package com.travel.withaeng.accompany.controller + +import com.travel.withaeng.domain.accompany.AccompanyDto +import com.travel.withaeng.domain.accompany.AccompanyService +import com.travel.withaeng.domain.accompany.CreateAccompanyDTO +import org.springframework.http.HttpStatus +import org.springframework.http.HttpStatusCode +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController + +@RestController +@RequestMapping("/api/v1/accompany") +class AccompanyController(private val accompanyService: AccompanyService) { + + @PostMapping("") + fun createAccompany(@RequestBody param : CreateAccompanyDTO) : ResponseEntity { + val accompanyId = accompanyService.createAccompany(param); + return ResponseEntity.status(HttpStatus.CREATED.value()).body(accompanyId); + } + + +} \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyLike/controller/AccompanyLikeController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyLike/controller/AccompanyLikeController.kt new file mode 100644 index 0000000..9a48871 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyLike/controller/AccompanyLikeController.kt @@ -0,0 +1,4 @@ +package com.travel.withaeng.accompanyLike.controller + +class AccompanyLikeController { +} \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReply/controller/AccompanyReplyController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReply/controller/AccompanyReplyController.kt new file mode 100644 index 0000000..0877dc5 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReply/controller/AccompanyReplyController.kt @@ -0,0 +1,4 @@ +package com.travel.withaeng.accompanyReply.controller + +class AccompanyReplyController { +} \ No newline at end of file diff --git a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/AccompanyStatusCd.kt b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/AccompanyStatusCd.kt new file mode 100644 index 0000000..c91f39b --- /dev/null +++ b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/AccompanyStatusCd.kt @@ -0,0 +1,12 @@ +package com.travel.withaeng.common.cd + +enum class AccompanyStatusCd ( + + val statusCd : String, + val statusNm : String + +) { + + ING("ING", "동행 구인중"), + COMPLETE("COMPLETE", "동행 모집 완료"), +} diff --git a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CityCd.kt b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CityCd.kt new file mode 100644 index 0000000..a0fb212 --- /dev/null +++ b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CityCd.kt @@ -0,0 +1,4 @@ +package com.travel.withaeng.common.cd + +enum class CityCd { +} \ No newline at end of file diff --git a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/ContinentCd.kt b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/ContinentCd.kt new file mode 100644 index 0000000..8082de8 --- /dev/null +++ b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/ContinentCd.kt @@ -0,0 +1,14 @@ +package com.travel.withaeng.common.cd + +enum class ContinentCd( + + val continentCd : String, + val continentNm : String + +) { + + EAST_ASIA("EAST_ASIA", "동아시아"), + SOUTHEAST_ASIA("SOUTHEAST_ASIA", "동남아시아"), + + +} \ No newline at end of file diff --git a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CountryCd.kt b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CountryCd.kt new file mode 100644 index 0000000..4a76672 --- /dev/null +++ b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CountryCd.kt @@ -0,0 +1,4 @@ +package com.travel.withaeng.common.cd + +enum class CountryCd { +} \ No newline at end of file diff --git a/withaeng-domain/build.gradle.kts b/withaeng-domain/build.gradle.kts index 7a98a52..18fe9b9 100644 --- a/withaeng-domain/build.gradle.kts +++ b/withaeng-domain/build.gradle.kts @@ -9,7 +9,10 @@ val mysqlVersion: String by project.extra dependencies { implementation(project(":withaeng-common")) implementation("org.springframework.boot:spring-boot-starter-data-jpa") - runtimeOnly("com.mysql:mysql-connector-j:$mysqlVersion") + implementation("org.projectlombok:lombok") + implementation("org.springframework.boot:spring-boot-starter-validation") + runtimeOnly("com.h2database:h2") + //runtimeOnly("com.mysql:mysql-connector-j:$mysqlVersion") // jasypt api("com.github.ulisesbocchio:jasypt-spring-boot-starter:$jasyptVersion") } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/BaseEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/BaseEntity.kt index 1d2586b..7917e5b 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/BaseEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/BaseEntity.kt @@ -10,11 +10,6 @@ import java.time.LocalDateTime @MappedSuperclass abstract class BaseEntity { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "id", nullable = false) - val id: Long = 0L - @CreatedDate @Column(name = "created_at", nullable = false, updatable = false) var createdAt: LocalDateTime = LocalDateTime.now() diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyCategoryEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyCategoryEntity.kt new file mode 100644 index 0000000..0a14bad --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyCategoryEntity.kt @@ -0,0 +1,27 @@ +package com.travel.withaeng.domain.accompany + +import com.travel.withaeng.domain.BaseEntity +import jakarta.persistence.* + +@Table(name = "accompany_category") +@Entity +class AccompanyCategoryEntity( + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "category_id", nullable = false) + val categoryId: Long, + + @Column(name = "accompany_id", nullable = false) + val accompanyId: Long, + + @Column(name = "continent", nullable = false) + val continent: String, + + @Column(name = "country", nullable = false) + val country : String, + + @Column(name = "city", nullable = false) + val city : String, + +) : BaseEntity() diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt index 7efbc8a..f1fa379 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt @@ -1,28 +1,69 @@ package com.travel.withaeng.domain.accompany +import com.travel.withaeng.common.cd.AccompanyStatusCd +import jakarta.validation.constraints.NotBlank +import lombok.Getter +import lombok.NoArgsConstructor +import lombok.Setter +import org.jetbrains.annotations.NotNull import java.time.LocalDate import java.time.LocalDateTime -data class AccompanyDto( +class AccompanyDto () + +@Setter +@Getter +class CreateAccompanyDTO( + + @NotNull val userId: Long, + + @NotBlank(message = "제목은 필수 값 입니다.") val title: String, + + @NotBlank(message = "내용은 필수 값 입니다.") val content: String, - val destination: Destination, + + @NotBlank(message = "대륙은 필수 값 입니다.") + val continent: String, + + val country : String, + + val city : String, + + @NotBlank val startTripDate: LocalDate, + + @NotBlank val endTripDate: LocalDate, + val bannerImageUrl: String?, - val viewCounts: Long, - val createdAt: LocalDateTime -) - -fun Accompany.toDto(): AccompanyDto = AccompanyDto( - userId = userId, - title = title, - content = content, - destination = destination, - startTripDate = startTripDate, - endTripDate = endTripDate, - bannerImageUrl = bannerImageUrl, - viewCounts = viewCounts, - createdAt = createdAt -) \ No newline at end of file + + @NotNull + val accompanyCnt : Long + +){ + fun toEntity(): AccompanyEntity { + return AccompanyEntity( + 0, + this.userId, + this.title, + this.content, + AccompanyStatusCd.ING.statusCd, + this.startTripDate, + this.endTripDate, + this.bannerImageUrl, + this.accompanyCnt + ) + } + + fun toCategoryEntity(accompanyId : Long) : AccompanyCategoryEntity { + return AccompanyCategoryEntity( + 0, + accompanyId, + this.content, + this.country, + this.city + ) + } +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyEntity.kt similarity index 66% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt rename to withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyEntity.kt index 835e1a8..f807c41 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyEntity.kt @@ -6,7 +6,13 @@ import java.time.LocalDate @Table(name = "accompany") @Entity -class Accompany( +class AccompanyEntity( + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id", nullable = false) + val id: Long, + @Column(name = "user_id", nullable = false) val userId: Long, @@ -17,8 +23,8 @@ class Accompany( @Column(name = "content", nullable = false) val content: String, - @Embedded - val destination: Destination, + @Column(name = "accompany_status_cd", nullable = false) + val accompanyStatusCd : String, @Column(name = "start_trip_date", nullable = false) val startTripDate: LocalDate, @@ -29,6 +35,7 @@ class Accompany( @Column(name = "banner_image_url") val bannerImageUrl: String?, - @Column(name = "view_counts", nullable = false) - val viewCounts: Long = 0L + @Column(name = "accompany_cnt", nullable = false) + val accompanyCnt: Long = 0L + ) : BaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt new file mode 100644 index 0000000..84cd90e --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt @@ -0,0 +1,47 @@ +package com.travel.withaeng.domain.accompany + +import com.travel.withaeng.domain.BaseEntity +import jakarta.persistence.* +import java.time.LocalDate + +@Table(name = "accompany_hist") +@Entity +class AccompanyHistEntity ( + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "hist_id", nullable = false) + val histId: Long, + + @Column(name = "accompany_id", nullable = false) + val accompanyId: Long, + + @Column(name = "user_id", nullable = false) + val userId: Long, + + @Column(name = "title", nullable = false) + val title: String, + + @Lob + @Column(name = "content", nullable = false) + val content: String, + + @Column(name = "accompany_status_cd", nullable = false) + val accompanyStatusCd : String, + + @Embedded + val destination: Destination, + + @Column(name = "start_trip_date", nullable = false) + val startTripDate: LocalDate, + + @Column(name = "end_trip_date", nullable = false) + val endTripDate: LocalDate, + + @Column(name = "banner_image_url") + val bannerImageUrl: String?, + + @Column(name = "accompany_cnt", nullable = false) + val accompanyCnt: Long = 0L + +) : BaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt index 42cea7f..e821c6f 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt @@ -2,4 +2,4 @@ package com.travel.withaeng.domain.accompany import org.springframework.data.jpa.repository.JpaRepository -interface AccompanyRepository : JpaRepository \ No newline at end of file +interface AccompanyRepository : JpaRepository \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt new file mode 100644 index 0000000..8f74c3c --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt @@ -0,0 +1,15 @@ +package com.travel.withaeng.domain.accompany + +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional + +@Service +@Transactional(readOnly = true) +class AccompanyService(private val accompanyRepository: AccompanyRepository) { + + fun createAccompany(param : CreateAccompanyDTO) : Long { + val accompanyEntity = param.toEntity(); + accompanyRepository.save(accompanyEntity); + return accompanyEntity.id; + } +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLike.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeEntity.kt similarity index 61% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLike.kt rename to withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeEntity.kt index 12792d2..9332fb2 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLike.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeEntity.kt @@ -1,16 +1,21 @@ package com.travel.withaeng.domain.accompanylike import com.travel.withaeng.domain.BaseEntity -import jakarta.persistence.Column -import jakarta.persistence.Entity -import jakarta.persistence.Table +import jakarta.persistence.* @Table(name = "accompany_like") @Entity -class AccompanyLike( +class AccompanyLikeEntity( + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "like_id", nullable = false) + val likeId: Long, + @Column(name = "user_id", nullable = false) val userId: Long, @Column(name = "accompany_id", nullable = false) val accompanyId: Long + ) : BaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeRepository.kt index fc87030..dfbbf7d 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeRepository.kt @@ -2,4 +2,4 @@ package com.travel.withaeng.domain.accompanylike import org.springframework.data.jpa.repository.JpaRepository -interface AccompanyLikeRepository : JpaRepository \ No newline at end of file +interface AccompanyLikeRepository : JpaRepository \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt index db7e4d5..5774740 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt @@ -1,17 +1,50 @@ package com.travel.withaeng.domain.accompanyreply -data class AccompanyReplyDto( - val accompanyId: Long, - val userId: Long, - val content: String, - val depth: Long, - val groupId: Long -) - -fun AccompanyReply.toDto(): AccompanyReplyDto = AccompanyReplyDto( - accompanyId = accompanyId, - userId = userId, - content = content, - depth = depth, - groupId = groupId -) \ No newline at end of file +import com.travel.withaeng.common.cd.AccompanyStatusCd +import com.travel.withaeng.domain.accompany.AccompanyEntity +import com.travel.withaeng.domain.accompany.Destination +import jakarta.persistence.Column +import jakarta.persistence.GeneratedValue +import jakarta.persistence.GenerationType +import jakarta.persistence.Id +import jakarta.validation.constraints.NotBlank +import lombok.Getter +import lombok.Setter +import org.jetbrains.annotations.NotNull +import java.time.LocalDate + +class AccompanyReplyDto { + + @Setter + @Getter + inner class ReqAdd( + + @NotNull + val accompanyId : Long, + + @NotNull + val parentId : Long, + + @NotNull + val depth : Long, + + @NotNull + val userId: Long, + + @NotBlank(message = "내용은 필수 값 입니다.") + val content: String, + + ) { + fun createEntity(): AccompanyReplyEntity { + return AccompanyReplyEntity( + 0, + this.accompanyId, + this.parentId, + this.depth, + this.userId, + this.content + ) + } + } + +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyEntity.kt similarity index 55% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt rename to withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyEntity.kt index 986d58d..e6b193f 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyEntity.kt @@ -1,15 +1,25 @@ package com.travel.withaeng.domain.accompanyreply import com.travel.withaeng.domain.BaseEntity -import jakarta.persistence.Column -import jakarta.persistence.Entity -import jakarta.persistence.Table +import jakarta.persistence.* @Table(name = "accompany_reply") @Entity -class AccompanyReply( +class AccompanyReplyEntity( + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "reply_id", nullable = false) + val replyId: Long, + @Column(name = "accompany_id", nullable = false) - val accompanyId: Long, + val accompanyId : Long, + + @Column(name = "parent_id", nullable = false) + val parentId : Long, + + @Column(name = "depth", nullable = false) + val depth : Long, @Column(name = "user_id", nullable = false) val userId: Long, @@ -17,9 +27,4 @@ class AccompanyReply( @Column(name = "content", nullable = false) val content: String, - @Column(name = "depth", nullable = false) - val depth: Long, - - @Column(name = "group_id", nullable = false) - val groupId: Long ) : BaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt index ba21cf8..df50163 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt @@ -2,4 +2,4 @@ package com.travel.withaeng.domain.accompanyreply import org.springframework.data.jpa.repository.JpaRepository -interface AccompanyReplyRepository : JpaRepository \ No newline at end of file +interface AccompanyReplyRepository : JpaRepository \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLike.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLike.kt deleted file mode 100644 index b42ed26..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLike.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.travel.withaeng.domain.accompanyreplylike - -import com.travel.withaeng.domain.BaseEntity -import jakarta.persistence.Column -import jakarta.persistence.Entity -import jakarta.persistence.Table - -@Table(name = "accompany_reply_like") -@Entity -class AccompanyReplyLike( - @Column(name = "accompany_reply_id", nullable = false) - val accompanyReplyId: Long, - - @Column(name = "user_id", nullable = false) - val userId: Long -) : BaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeEntity.kt new file mode 100644 index 0000000..3a3cd0b --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeEntity.kt @@ -0,0 +1,21 @@ +package com.travel.withaeng.domain.accompanyreplylike + +import com.travel.withaeng.domain.BaseEntity +import jakarta.persistence.* + +@Table(name = "accompany_reply_like") +@Entity +class AccompanyReplyLikeEntity( + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "reply_like_id", nullable = false) + val replyLikeId: Long, + + @Column(name = "reply_id", nullable = false) + val replyId: Long, + + @Column(name = "user_id", nullable = false) + val userId: Long + +) : BaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt index 3cd5280..8a52cdf 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt @@ -2,4 +2,4 @@ package com.travel.withaeng.domain.accompanyreplylike import org.springframework.data.jpa.repository.JpaRepository -interface AccompanyReplyLikeRepository : JpaRepository \ No newline at end of file +interface AccompanyReplyLikeRepository : JpaRepository \ No newline at end of file diff --git a/withaeng-domain/src/main/resources/application-domain.yml b/withaeng-domain/src/main/resources/application-domain.yml index 4ac5c1c..84818ed 100644 --- a/withaeng-domain/src/main/resources/application-domain.yml +++ b/withaeng-domain/src/main/resources/application-domain.yml @@ -3,10 +3,14 @@ spring: default: local datasource: - driver-class-name: com.mysql.cj.jdbc.Driver - url: ENC(lFITsL+l7aOSMUY3hRT3aR4X0GV+yqIJfYMyXaMajbZZJSW+Lv5MTrbP5Cwa8XAUxGpH7A9GxRNAZtrDhf6V4yXkD6gf3RUYWsPp77Ieguo=) - username: ENC(s1UggVxVWnWC0WqrTpmXaLw+QCpZmkuj2kvSQp+zt2vwKLbRH6WDAZKYUR75DqsR) - password: ENC(HT2z+x9LrfoHTmTTCYLkx7cO0ru9Gcbh+YGnP/0MWC1BpBwQtPfWue+zQx5RPQg8) + driver-class-name: org.h2.Driver + url: jdbc:h2:~/test + username: user + password: + #driver-class-name: com.mysql.cj.jdbc.Driver + #url: ENC(lFITsL+l7aOSMUY3hRT3aR4X0GV+yqIJfYMyXaMajbZZJSW+Lv5MTrbP5Cwa8XAUxGpH7A9GxRNAZtrDhf6V4yXkD6gf3RUYWsPp77Ieguo=) + #username: ENC(s1UggVxVWnWC0WqrTpmXaLw+QCpZmkuj2kvSQp+zt2vwKLbRH6WDAZKYUR75DqsR) + #password: ENC(HT2z+x9LrfoHTmTTCYLkx7cO0ru9Gcbh+YGnP/0MWC1BpBwQtPfWue+zQx5RPQg8) jpa: hibernate: @@ -15,4 +19,8 @@ spring: hibernate: show_sql: false format_sql: false - use_sql_comments: false \ No newline at end of file + use_sql_comments: false + h2: + console: + enabled: true + path: /h2-console \ No newline at end of file From d4b67719165ab68d57e49f3af7f77e80a2045823 Mon Sep 17 00:00:00 2001 From: collenkim Date: Thu, 21 Mar 2024 07:29:24 -0700 Subject: [PATCH 037/174] =?UTF-8?q?=EB=8F=99=ED=96=89=20=EB=93=B1=EB=A1=9D?= =?UTF-8?q?=20=EB=B0=8F=20=EB=8B=A8=EA=B1=B4=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B0=9C=EB=B0=9C=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 3 + .../controller/AccompanyController.kt | 27 +++-- .../travel/withaeng/common/cd/ContinentCd.kt | 12 +- .../travel/withaeng/common/cd/CountryCd.kt | 109 +++++++++++++++++- withaeng-domain/build.gradle.kts | 6 +- ...ntity.kt => AccompanyDestinationEntity.kt} | 16 +-- .../AccompanyDestinationRepository.kt | 7 ++ .../withaeng/domain/accompany/AccompanyDto.kt | 97 ++++++++++++++-- .../domain/accompany/AccompanyEntity.kt | 4 +- .../domain/accompany/AccompanyHistEntity.kt | 3 - .../accompany/AccompanyHistRepository.kt | 6 + .../domain/accompany/AccompanyRepository.kt | 6 +- .../domain/accompany/AccompanyService.kt | 35 +++++- .../withaeng/domain/accompany/Destination.kt | 16 --- .../accompanyreply/AccompanyReplyDto.kt | 8 -- 15 files changed, 294 insertions(+), 61 deletions(-) rename withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/{AccompanyCategoryEntity.kt => AccompanyDestinationEntity.kt} (55%) create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestinationRepository.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistRepository.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Destination.kt diff --git a/build.gradle.kts b/build.gradle.kts index 5af766d..4248591 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,6 +2,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { kotlin("jvm") + kotlin("kapt") version "1.9.10" kotlin("plugin.spring") apply false kotlin("plugin.jpa") apply false id("org.springframework.boot") apply false @@ -27,6 +28,7 @@ val springMockkVersion: String by project.extra subprojects { apply(plugin = "org.jetbrains.kotlin.jvm") + //apply(plugin = "org.jetbrains.kotlin.kapt") apply(plugin = "org.jetbrains.kotlin.plugin.spring") apply(plugin = "org.jetbrains.kotlin.plugin.jpa") apply(plugin = "org.springframework.boot") @@ -41,6 +43,7 @@ subprojects { testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("com.ninja-squad:springmockk:$springMockkVersion") + runtimeOnly("com.h2database:h2") } diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompany/controller/AccompanyController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompany/controller/AccompanyController.kt index ec31357..501be6a 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompany/controller/AccompanyController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompany/controller/AccompanyController.kt @@ -3,23 +3,36 @@ package com.travel.withaeng.accompany.controller import com.travel.withaeng.domain.accompany.AccompanyDto import com.travel.withaeng.domain.accompany.AccompanyService import com.travel.withaeng.domain.accompany.CreateAccompanyDTO +import com.travel.withaeng.domain.accompany.ReadAccompanyDTO import org.springframework.http.HttpStatus import org.springframework.http.HttpStatusCode import org.springframework.http.ResponseEntity -import org.springframework.web.bind.annotation.PostMapping -import org.springframework.web.bind.annotation.RequestBody -import org.springframework.web.bind.annotation.RequestMapping -import org.springframework.web.bind.annotation.RestController +import org.springframework.web.bind.annotation.* +import java.util.Objects @RestController @RequestMapping("/api/v1/accompany") class AccompanyController(private val accompanyService: AccompanyService) { @PostMapping("") - fun createAccompany(@RequestBody param : CreateAccompanyDTO) : ResponseEntity { - val accompanyId = accompanyService.createAccompany(param); - return ResponseEntity.status(HttpStatus.CREATED.value()).body(accompanyId); + fun create(@RequestBody param : CreateAccompanyDTO) : ResponseEntity { + return ResponseEntity.status(HttpStatus.CREATED).body(accompanyService.createAccompany(param)) } + /*@PutMapping("") + fun create(@RequestBody param : ModifyAccompanyDTO) : ResponseEntity { + val accompanyId = accompanyService.createAccompany(param) + return ResponseEntity.status(HttpStatus.CREATED).body(accompanyId) + }*/ + + @GetMapping("/{accompanyId}") + fun getOne(@PathVariable("accompanyId") accompanyId : Long) : ResponseEntity { + return ResponseEntity.status(HttpStatus.OK).body(accompanyService.getOne(accompanyId)) + } + + /*@GetMapping("/getList") + fun getList(@RequestBody param : SearchAccompanyDTO) : ResponseEntity> { + return ResponseEntity.status(HttpStatus.OK).body(accompanyService.getList(param)) + }*/ } \ No newline at end of file diff --git a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/ContinentCd.kt b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/ContinentCd.kt index 8082de8..ef376b4 100644 --- a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/ContinentCd.kt +++ b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/ContinentCd.kt @@ -7,8 +7,14 @@ enum class ContinentCd( ) { - EAST_ASIA("EAST_ASIA", "동아시아"), - SOUTHEAST_ASIA("SOUTHEAST_ASIA", "동남아시아"), - + EAST_ASIA("EA", "동아시아"), + SOUTHEAST_ASIA("SA", "동남아시아"), + CENTRAL_ASIA("CA", "중앙아시아"), + WESTERN_ASIA("WA", "서남아시아"), + EUROPE("EU", "유럽"), + OCEANIA("OC", "오세아니아"), + AFRICA("AF", "아프리카"), + NORTH_AMERICA("NA", "북아메리카"), + SOUTH_AMERICA("SA", "남아메리카") } \ No newline at end of file diff --git a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CountryCd.kt b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CountryCd.kt index 4a76672..8aaab26 100644 --- a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CountryCd.kt +++ b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CountryCd.kt @@ -1,4 +1,111 @@ package com.travel.withaeng.common.cd -enum class CountryCd { +enum class CountryCd ( + + val continentCd: String, + val countryCd : String, + val countryNm : String + +) { + + KOREA(ContinentCd.EAST_ASIA.continentCd,"KOREA", "한국"), + JAPAN(ContinentCd.EAST_ASIA.continentCd,"JAPAN", "일본"), + HONG_KONG(ContinentCd.EAST_ASIA.continentCd,"HONG_KONG", "홍콩"), + MACAO(ContinentCd.EAST_ASIA.continentCd,"MACAO", "마카오"), + TAIWAN(ContinentCd.EAST_ASIA.continentCd,"TAIWAN", "대만"), + CHINA(ContinentCd.EAST_ASIA.continentCd,"CHINA", "중국"), + MONGOLIA(ContinentCd.EAST_ASIA.continentCd,"MONGOLIA", "몽골"), + + SINGAPORE(ContinentCd.SOUTHEAST_ASIA.continentCd,"SINGAPORE","싱가포르"), + EAST_TIMOR(ContinentCd.SOUTHEAST_ASIA.continentCd,"EAST_TIMOR","동티모르"), + MYANMAR(ContinentCd.SOUTHEAST_ASIA.continentCd,"MYANMAR","미얀마"), + CAMBODIA(ContinentCd.SOUTHEAST_ASIA.continentCd,"CAMBODIA","캄보디아"), + LAOS(ContinentCd.SOUTHEAST_ASIA.continentCd,"LAOS","라오스"), + PHILIPPINES(ContinentCd.SOUTHEAST_ASIA.continentCd,"PHILIPPINES","필리핀"), + MALAYSIA(ContinentCd.SOUTHEAST_ASIA.continentCd,"MALAYSIA","말레이시아"), + INDONESIA(ContinentCd.SOUTHEAST_ASIA.continentCd,"INDONESIA","인도네시아"), + THAILAND(ContinentCd.SOUTHEAST_ASIA.continentCd,"THAILAND","태국"), + VIETNAM(ContinentCd.SOUTHEAST_ASIA.continentCd,"VIETNAM","베트남"), + BRUNEI(ContinentCd.SOUTHEAST_ASIA.continentCd,"BRUNEI","브루나이"), + + UZBEKISTAN(ContinentCd.CENTRAL_ASIA.continentCd,"UZBEKISTAN","우즈베키스탄"), + BANGLADESH(ContinentCd.CENTRAL_ASIA.continentCd,"BANGLADESH","방글라데시"), + AZERBAIJAN(ContinentCd.CENTRAL_ASIA.continentCd,"AZERBAIJAN","아제르바이잔"), + BUTANE(ContinentCd.CENTRAL_ASIA.continentCd,"BUTANE","부탄"), + AFGHANISTAN(ContinentCd.CENTRAL_ASIA.continentCd,"AFGHANISTAN","아프가니스탄"), + TAJIKISTAN(ContinentCd.CENTRAL_ASIA.continentCd,"TAJIKISTAN","타지키스탄"), + KYRGYZSTAN(ContinentCd.CENTRAL_ASIA.continentCd,"KYRGYZSTAN","키르기스스탄"), + KAZAKHSTAN(ContinentCd.CENTRAL_ASIA.continentCd,"KAZAKHSTAN","카자흐스탄"), + TURKMENISTAN(ContinentCd.CENTRAL_ASIA.continentCd,"TURKMENISTAN","투르크메니스탄"), + TIBET(ContinentCd.CENTRAL_ASIA.continentCd,"TIBET","티베트"), + + ARAB_EMIRATES(ContinentCd.WESTERN_ASIA.continentCd,"ARAB_EMIRATES","아랍에미리트"), + JORDAN(ContinentCd.WESTERN_ASIA.continentCd,"JORDAN","요르단"), + YEMEN(ContinentCd.WESTERN_ASIA.continentCd,"YEMEN","예멘"), + SYRIA(ContinentCd.WESTERN_ASIA.continentCd,"SYRIA","시리아"), + IRAN(ContinentCd.WESTERN_ASIA.continentCd,"IRAN","이란"), + PAKISTAN(ContinentCd.WESTERN_ASIA.continentCd,"PAKISTAN","파키스탄"), + CYPRUS(ContinentCd.WESTERN_ASIA.continentCd,"CYPRUS","키프로스"), + SRI_LANKA(ContinentCd.WESTERN_ASIA.continentCd,"SRI_LANKA","스리랑카"), + MALDIVE(ContinentCd.WESTERN_ASIA.continentCd,"MALDIVE","몰디브"), + BAHRAIN(ContinentCd.WESTERN_ASIA.continentCd,"BAHRAIN","바레인"), + LRAQ(ContinentCd.WESTERN_ASIA.continentCd,"LRAQ","이라크"), + PALESTINE(ContinentCd.WESTERN_ASIA.continentCd,"PALESTINE","팔레스타인"), + OMAN(ContinentCd.WESTERN_ASIA.continentCd,"OMAN","오만"), + INDIA(ContinentCd.WESTERN_ASIA.continentCd,"INDIA","인도"), + NEPAL(ContinentCd.WESTERN_ASIA.continentCd,"NEPAL","네팔"), + ISRAEL(ContinentCd.WESTERN_ASIA.continentCd,"ISRAEL","이스라엘"), + CATARRH(ContinentCd.WESTERN_ASIA.continentCd,"CATARRH","카타르"), + LEBANON(ContinentCd.WESTERN_ASIA.continentCd,"LEBANON","레바논"), + SAUDI_ARABIA(ContinentCd.WESTERN_ASIA.continentCd,"SAUDI_ARABIA","사우디아라비아"), + KUWAIT(ContinentCd.WESTERN_ASIA.continentCd,"KUWAIT","쿠웨이트"), + ARMENIA(ContinentCd.WESTERN_ASIA.continentCd,"ARMENIA","아르메니아"), + + GEORGIA(ContinentCd.EUROPE.continentCd,"GEORGIA","조지아"), + MALTA(ContinentCd.EUROPE.continentCd,"MALTA","몰타"), + MOLDOVA(ContinentCd.EUROPE.continentCd,"MOLDOVA","몰도바"), + MONTENEGRO(ContinentCd.EUROPE.continentCd,"MONTENEGRO","몬테네그로"), + MONACO(ContinentCd.EUROPE.continentCd,"MONACO","모나코"), + MACEDONIA(ContinentCd.EUROPE.continentCd,"MACEDONIA","마케도니아"), + LIECHTENSTEIN(ContinentCd.EUROPE.continentCd,"LIECHTENSTEIN","리히텐슈타인"), + LITHUANIA(ContinentCd.EUROPE.continentCd,"LITHUANIA","리투아니아"), + LUXEMBOURG(ContinentCd.EUROPE.continentCd,"LUXEMBOURG","룩셈부르크"), + ROMANIA(ContinentCd.EUROPE.continentCd,"ROMANIA","루마니아"), + VATICAN(ContinentCd.EUROPE.continentCd,"VATICAN","바티칸"), + BELARUS(ContinentCd.EUROPE.continentCd,"BELARUS","벨라루스"), + BOSNIA_HERCEGOVINA(ContinentCd.EUROPE.continentCd,"BOSNIA_HERCEGOVINA","보스니아헤르체코비나"), + CROATIA(ContinentCd.EUROPE.continentCd,"CROATIA","크로아티아"), + UKRAINE(ContinentCd.EUROPE.continentCd,"UKRAINE","우크라이나"), + ESTONIA(ContinentCd.EUROPE.continentCd,"ESTONIA","에스토니아"), + ALBANIA(ContinentCd.EUROPE.continentCd,"ALBANIA","알바니아"), + ANDORRA(ContinentCd.EUROPE.continentCd,"ANDORRA","안도라"), + SLOVAKIA(ContinentCd.EUROPE.continentCd,"SLOVAKIA","슬로바키아"), + SERBIA(ContinentCd.EUROPE.continentCd,"SERBIA","세르비아"), + SAN_MARINO(ContinentCd.EUROPE.continentCd,"SAN_MARINO","산마리노"), + BULGARIA(ContinentCd.EUROPE.continentCd,"BULGARIA","불가리아"), + LATVIA(ContinentCd.EUROPE.continentCd,"LATVIA","라트비아"), + SLOVENIA(ContinentCd.EUROPE.continentCd,"SLOVENIA","슬로베니아"), + PORTUGAL(ContinentCd.EUROPE.continentCd,"PORTUGAL","포르투갈"), + SWISS(ContinentCd.EUROPE.continentCd,"SWISS","스위스"), + GERMANY(ContinentCd.EUROPE.continentCd,"GERMANY","독일"), + NETHERLAND(ContinentCd.EUROPE.continentCd,"NETHERLAND","네덜란드"), + AUSTRIA(ContinentCd.EUROPE.continentCd,"AUSTRIA","오스트리아"), + ENGLAND(ContinentCd.EUROPE.continentCd,"ENGLAND","영국"), + SPAIN(ContinentCd.EUROPE.continentCd,"SPAIN","스페인"), + TURKIYE(ContinentCd.EUROPE.continentCd,"TURKIYE","터키"), + ITALY(ContinentCd.EUROPE.continentCd,"ITALY","이탈리아"), + POLAND(ContinentCd.EUROPE.continentCd,"POLAND","폴란드"), + ICELAND(ContinentCd.EUROPE.continentCd,"ICELAND","아이슬란드"), + FINLAND(ContinentCd.EUROPE.continentCd,"FINLAND","핀란드"), + CZECHIA(ContinentCd.EUROPE.continentCd,"CZECHIA","체코"), + BELGIUM(ContinentCd.EUROPE.continentCd,"BELGIUM","벨기에"), + HUNGARY(ContinentCd.EUROPE.continentCd,"HUNGARY","헝가리"), + IRELAND(ContinentCd.EUROPE.continentCd,"IRELAND","아일랜드"), + RUSSIA(ContinentCd.EUROPE.continentCd,"RUSSIA","러시아"), + GREECE(ContinentCd.EUROPE.continentCd,"GREECE","그리스"), + DENMARK(ContinentCd.EUROPE.continentCd,"DENMARK","덴마크"), + NORWAY(ContinentCd.EUROPE.continentCd,"NORWAY","노르웨이"), + SWEDEN(ContinentCd.EUROPE.continentCd,"SWEDEN","스웨덴"), + FRANCE(ContinentCd.EUROPE.continentCd,"FRANCE","프랑스"), + } \ No newline at end of file diff --git a/withaeng-domain/build.gradle.kts b/withaeng-domain/build.gradle.kts index 18fe9b9..5d5a0c3 100644 --- a/withaeng-domain/build.gradle.kts +++ b/withaeng-domain/build.gradle.kts @@ -11,8 +11,12 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-data-jpa") implementation("org.projectlombok:lombok") implementation("org.springframework.boot:spring-boot-starter-validation") + implementation("com.querydsl:querydsl-jpa") + runtimeOnly("com.h2database:h2") //runtimeOnly("com.mysql:mysql-connector-j:$mysqlVersion") // jasypt api("com.github.ulisesbocchio:jasypt-spring-boot-starter:$jasyptVersion") -} \ No newline at end of file +} + + diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyCategoryEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestinationEntity.kt similarity index 55% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyCategoryEntity.kt rename to withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestinationEntity.kt index 0a14bad..deaf49c 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyCategoryEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestinationEntity.kt @@ -3,14 +3,14 @@ package com.travel.withaeng.domain.accompany import com.travel.withaeng.domain.BaseEntity import jakarta.persistence.* -@Table(name = "accompany_category") +@Table(name = "accompany_destinaion") @Entity -class AccompanyCategoryEntity( +class AccompanyDestinationEntity( @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "category_id", nullable = false) - val categoryId: Long, + @Column(name = "destination_id", nullable = false) + val destinationId: Long, @Column(name = "accompany_id", nullable = false) val accompanyId: Long, @@ -18,10 +18,10 @@ class AccompanyCategoryEntity( @Column(name = "continent", nullable = false) val continent: String, - @Column(name = "country", nullable = false) - val country : String, + @Column(name = "country", nullable = true) + val country : String?, - @Column(name = "city", nullable = false) - val city : String, + @Column(name = "city", nullable = true) + val city : String?, ) : BaseEntity() diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestinationRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestinationRepository.kt new file mode 100644 index 0000000..094ef3a --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestinationRepository.kt @@ -0,0 +1,7 @@ +package com.travel.withaeng.domain.accompany + +import org.springframework.data.jpa.repository.JpaRepository + +interface AccompanyDestinationRepository : JpaRepository { + fun findByAccompanyId(accompanyId : Long) : AccompanyDestinationEntity +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt index f1fa379..d4f562e 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt @@ -7,7 +7,6 @@ import lombok.NoArgsConstructor import lombok.Setter import org.jetbrains.annotations.NotNull import java.time.LocalDate -import java.time.LocalDateTime class AccompanyDto () @@ -27,9 +26,9 @@ class CreateAccompanyDTO( @NotBlank(message = "대륙은 필수 값 입니다.") val continent: String, - val country : String, + private val country : String? = null, - val city : String, + private val city : String? = null, @NotBlank val startTripDate: LocalDate, @@ -37,7 +36,7 @@ class CreateAccompanyDTO( @NotBlank val endTripDate: LocalDate, - val bannerImageUrl: String?, + val bannerImageUrl: String? = null, @NotNull val accompanyCnt : Long @@ -57,13 +56,97 @@ class CreateAccompanyDTO( ) } - fun toCategoryEntity(accompanyId : Long) : AccompanyCategoryEntity { - return AccompanyCategoryEntity( + fun toHistEntity(entity: AccompanyEntity): AccompanyHistEntity { + return AccompanyHistEntity( + 0, + entity.accompanyId, + entity.userId, + entity.title, + entity.content, + entity.accompanyStatusCd, + entity.startTripDate, + entity.endTripDate, + entity.bannerImageUrl, + entity.accompanyCnt + ) + } + + fun toDestinationEntity(accompanyId : Long) : AccompanyDestinationEntity { + return AccompanyDestinationEntity( 0, accompanyId, - this.content, + this.continent, this.country, this.city ) } +} + +data class ReadAccompanyDTO( + + val accompanyId : Long, + val userId: Long, + val title: String, + val content: String, + val continent: String, + val country : String? = null, + val city : String? = null, + val startTripDate: LocalDate, + val endTripDate: LocalDate, + val bannerImageUrl: String? = null, + val accompanyCnt : Long + +){ + companion object { + @JvmStatic + fun toDto(accompanyEntity : AccompanyEntity, accompanyDestinationEntity: AccompanyDestinationEntity) : ReadAccompanyDTO { + return ReadAccompanyDTO( + accompanyId = accompanyEntity.accompanyId, + userId = accompanyEntity.userId, + title = accompanyEntity.title, + content = accompanyEntity.content, + continent = accompanyDestinationEntity.continent, + country = accompanyDestinationEntity.country, + city = accompanyDestinationEntity.city, + startTripDate = accompanyEntity.startTripDate, + endTripDate = accompanyEntity.endTripDate, + bannerImageUrl = accompanyEntity.bannerImageUrl, + accompanyCnt = accompanyEntity.accompanyCnt + ) + } + } +} + +@Setter +@Getter +class SearchAccompanyDTO( + + @NotNull + val userId: Long, + + @NotBlank(message = "제목은 필수 값 입니다.") + val title: String, + + @NotBlank(message = "내용은 필수 값 입니다.") + val content: String, + + @NotBlank(message = "대륙은 필수 값 입니다.") + val continent: String, + + private val country : String? = null, + + private val city : String? = null, + + @NotBlank + val startTripDate: LocalDate, + + @NotBlank + val endTripDate: LocalDate, + + val bannerImageUrl: String? = null, + + @NotNull + val accompanyCnt : Long +){ + } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyEntity.kt index f807c41..550a67f 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyEntity.kt @@ -10,8 +10,8 @@ class AccompanyEntity( @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "id", nullable = false) - val id: Long, + @Column(name = "accompany_id", nullable = false) + val accompanyId: Long, @Column(name = "user_id", nullable = false) val userId: Long, diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt index 84cd90e..3c2a4ff 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt @@ -29,9 +29,6 @@ class AccompanyHistEntity ( @Column(name = "accompany_status_cd", nullable = false) val accompanyStatusCd : String, - @Embedded - val destination: Destination, - @Column(name = "start_trip_date", nullable = false) val startTripDate: LocalDate, diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistRepository.kt new file mode 100644 index 0000000..dca16f2 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistRepository.kt @@ -0,0 +1,6 @@ +package com.travel.withaeng.domain.accompany + +import org.springframework.data.jpa.repository.JpaRepository + +interface AccompanyHistRepository : JpaRepository { +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt index e821c6f..7559fc3 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt @@ -2,4 +2,8 @@ package com.travel.withaeng.domain.accompany import org.springframework.data.jpa.repository.JpaRepository -interface AccompanyRepository : JpaRepository \ No newline at end of file +interface AccompanyRepository : JpaRepository { + + fun findByAccompanyId(accompanyId : Long) : AccompanyEntity + +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt index 8f74c3c..6adb04c 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt @@ -5,11 +5,38 @@ import org.springframework.transaction.annotation.Transactional @Service @Transactional(readOnly = true) -class AccompanyService(private val accompanyRepository: AccompanyRepository) { +class AccompanyService( + private val accompanyRepository: AccompanyRepository, + private val accompanyHistRepository : AccompanyHistRepository, + private val accompanyDestinationRepository : AccompanyDestinationRepository + +) { + + @Transactional fun createAccompany(param : CreateAccompanyDTO) : Long { - val accompanyEntity = param.toEntity(); - accompanyRepository.save(accompanyEntity); - return accompanyEntity.id; + val accompanyEntity = param.toEntity() + accompanyRepository.save(accompanyEntity) + + val accompanyHistEntity = param.toHistEntity(accompanyEntity) + val accompanyDestinationEntity = param.toDestinationEntity(accompanyEntity.accompanyId) + + accompanyHistRepository.save(accompanyHistEntity) + accompanyDestinationRepository.save(accompanyDestinationEntity) + + return accompanyEntity.accompanyId; } + + fun getOne(param : Long) : ReadAccompanyDTO { + val accompanyEntity = accompanyRepository.findByAccompanyId(param) + val accompanyDestinationEntity = accompanyDestinationRepository.findByAccompanyId(param) + return ReadAccompanyDTO.toDto(accompanyEntity, accompanyDestinationEntity) + } + + fun getList(param : Long) : ReadAccompanyDTO { + val accompanyEntity = accompanyRepository.findByAccompanyId(param) + val accompanyDestinationEntity = accompanyDestinationRepository.findByAccompanyId(param) + return ReadAccompanyDTO.toDto(accompanyEntity, accompanyDestinationEntity) + } + } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Destination.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Destination.kt deleted file mode 100644 index 0db3414..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Destination.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.travel.withaeng.domain.accompany - -import jakarta.persistence.Column -import jakarta.persistence.Embeddable - -@Embeddable -data class Destination( - @Column(name = "continent", nullable = false) - val continent: String, - - @Column(name = "country", nullable = false) - val country: String, - - @Column(name = "city", nullable = false) - val city: String -) \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt index 5774740..a7909f0 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt @@ -1,17 +1,9 @@ package com.travel.withaeng.domain.accompanyreply -import com.travel.withaeng.common.cd.AccompanyStatusCd -import com.travel.withaeng.domain.accompany.AccompanyEntity -import com.travel.withaeng.domain.accompany.Destination -import jakarta.persistence.Column -import jakarta.persistence.GeneratedValue -import jakarta.persistence.GenerationType -import jakarta.persistence.Id import jakarta.validation.constraints.NotBlank import lombok.Getter import lombok.Setter import org.jetbrains.annotations.NotNull -import java.time.LocalDate class AccompanyReplyDto { From 402655cfb41ecf1fb354343ddea81e80dcb93a7b Mon Sep 17 00:00:00 2001 From: collenkim Date: Fri, 22 Mar 2024 08:05:46 -0700 Subject: [PATCH 038/174] =?UTF-8?q?Transaction=20=EC=B2=98=EB=A6=AC=20?= =?UTF-8?q?=EB=B0=8F=20=EB=8F=99=ED=96=89=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=A2=8B=EC=95=84=EC=9A=94,=20=EC=A1=B0=ED=9A=8C=EC=88=98=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/AccompanyController.kt | 5 ++ .../controller/AccompanyLikeController.kt | 23 +++++- .../controller/AccompanyReplyController.kt | 19 ++++- .../destination/DestinationController.kt | 16 ++++ .../travel/withaeng/common/cd/CountryCd.kt | 4 + .../withaeng/domain/accompany/AccompanyDto.kt | 6 +- .../domain/accompany/AccompanyEntity.kt | 19 +++-- .../domain/accompany/AccompanyHistEntity.kt | 17 ++-- .../domain/accompany/AccompanyService.kt | 8 ++ .../domain/accompanylike/AccompanyLikeDto.kt | 77 +++++++++++++++++++ .../accompanylike/AccompanyLikeHistEntity.kt | 24 ++++++ .../AccompanyLikeHistRepository.kt | 5 ++ .../accompanylike/AccompanyLikeService.kt | 41 ++++++++++ .../accompanyreply/AccompanyReplyDto.kt | 51 ++++++------ .../accompanyreply/AccompanyReplyService.kt | 9 +++ .../domain/destination/DestinationDto.kt | 8 ++ .../domain/destination/DestinationService.kt | 4 + 17 files changed, 292 insertions(+), 44 deletions(-) create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/destination/DestinationController.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeDto.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistEntity.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistRepository.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationDto.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationService.kt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompany/controller/AccompanyController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompany/controller/AccompanyController.kt index 501be6a..b733830 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompany/controller/AccompanyController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompany/controller/AccompanyController.kt @@ -30,6 +30,11 @@ class AccompanyController(private val accompanyService: AccompanyService) { return ResponseEntity.status(HttpStatus.OK).body(accompanyService.getOne(accompanyId)) } + @PutMapping("/{accompanyId}/incr/viewCnt") + fun incrViewCnt(@PathVariable("accompanyId") accompanyId : Long) : ResponseEntity { + return ResponseEntity.status(HttpStatus.OK).body(accompanyService.incrViewCnt(accompanyId)) + } + /*@GetMapping("/getList") fun getList(@RequestBody param : SearchAccompanyDTO) : ResponseEntity> { return ResponseEntity.status(HttpStatus.OK).body(accompanyService.getList(param)) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyLike/controller/AccompanyLikeController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyLike/controller/AccompanyLikeController.kt index 9a48871..a43c04c 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyLike/controller/AccompanyLikeController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyLike/controller/AccompanyLikeController.kt @@ -1,4 +1,25 @@ package com.travel.withaeng.accompanyLike.controller -class AccompanyLikeController { +import com.travel.withaeng.domain.accompany.CreateAccompanyDTO +import com.travel.withaeng.domain.accompanylike.AccompanyLikeService +import com.travel.withaeng.domain.accompanylike.CreateAccompanyLikeDTO +import com.travel.withaeng.domain.accompanylike.DeleteAccompanyLikeDTO +import org.springframework.http.HttpStatus +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.* + +@RestController +@RequestMapping("/api/v1/accompany/{accompany}/like") +class AccompanyLikeController(private val accompanyLikeService: AccompanyLikeService) { + + @PostMapping("") + fun create(@RequestBody param : CreateAccompanyLikeDTO) : ResponseEntity { + return ResponseEntity.status(HttpStatus.CREATED).body(accompanyLikeService.createAccompanyLike(param)) + } + + @DeleteMapping("") + fun delete(@RequestBody param : DeleteAccompanyLikeDTO) : ResponseEntity{ + return ResponseEntity.status(HttpStatus.OK).body("") + } + } \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReply/controller/AccompanyReplyController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReply/controller/AccompanyReplyController.kt index 0877dc5..7d0766c 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReply/controller/AccompanyReplyController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReply/controller/AccompanyReplyController.kt @@ -1,4 +1,21 @@ package com.travel.withaeng.accompanyReply.controller -class AccompanyReplyController { +import com.travel.withaeng.domain.accompanyreply.AccompanyReplyService +import com.travel.withaeng.domain.accompanyreply.CreateAccompanyReplyDTO +import org.springframework.http.HttpStatus +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController + +@RestController +@RequestMapping("/api/v1/accompany{accompany}/reply") +class AccompanyReplyController(private val accompanyReplyService: AccompanyReplyService){ + + /*@PostMapping("") + fun create(@RequestBody param : CreateAccompanyReplyDTO) : ResponseEntity { + return ResponseEntity.status(HttpStatus.CREATED).body(accompanyReplyService.createAccompanyReply(param)) + }*/ + } \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/destination/DestinationController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/destination/DestinationController.kt new file mode 100644 index 0000000..c0b60a2 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/destination/DestinationController.kt @@ -0,0 +1,16 @@ +package com.travel.withaeng.destination + +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 + +@RestController +@RequestMapping("/api/v1/destination") +class DestinationController { + + /*@GetMapping("/getList") + fun getList() : ResponseEntity<>{ + + }*/ +} \ No newline at end of file diff --git a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CountryCd.kt b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CountryCd.kt index 8aaab26..60e0b9b 100644 --- a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CountryCd.kt +++ b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CountryCd.kt @@ -108,4 +108,8 @@ enum class CountryCd ( SWEDEN(ContinentCd.EUROPE.continentCd,"SWEDEN","스웨덴"), FRANCE(ContinentCd.EUROPE.continentCd,"FRANCE","프랑스"), + AUSTRALIA(ContinentCd.OCEANIA.continentCd,"AUSTRALIA","호주"), + PALAU(ContinentCd.OCEANIA.continentCd,"PALAU","팔라우"), + PAPUA_NEW_GUINEA(ContinentCd.OCEANIA.continentCd,"PAPUA_NEW_GUINEA","파푸아뉴기니"), + } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt index d4f562e..070fcac 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt @@ -94,7 +94,8 @@ data class ReadAccompanyDTO( val startTripDate: LocalDate, val endTripDate: LocalDate, val bannerImageUrl: String? = null, - val accompanyCnt : Long + val accompanyCnt : Long, + val viewCnt : Long ){ companion object { @@ -111,7 +112,8 @@ data class ReadAccompanyDTO( startTripDate = accompanyEntity.startTripDate, endTripDate = accompanyEntity.endTripDate, bannerImageUrl = accompanyEntity.bannerImageUrl, - accompanyCnt = accompanyEntity.accompanyCnt + accompanyCnt = accompanyEntity.accompanyCnt, + viewCnt = accompanyEntity.viewCnt ) } } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyEntity.kt index 550a67f..a810530 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyEntity.kt @@ -2,8 +2,10 @@ package com.travel.withaeng.domain.accompany import com.travel.withaeng.domain.BaseEntity import jakarta.persistence.* +import org.hibernate.annotations.DynamicUpdate import java.time.LocalDate +@DynamicUpdate @Table(name = "accompany") @Entity class AccompanyEntity( @@ -17,25 +19,28 @@ class AccompanyEntity( val userId: Long, @Column(name = "title", nullable = false) - val title: String, + var title: String, @Lob @Column(name = "content", nullable = false) - val content: String, + var content: String, @Column(name = "accompany_status_cd", nullable = false) - val accompanyStatusCd : String, + var accompanyStatusCd : String, @Column(name = "start_trip_date", nullable = false) - val startTripDate: LocalDate, + var startTripDate: LocalDate, @Column(name = "end_trip_date", nullable = false) - val endTripDate: LocalDate, + var endTripDate: LocalDate, @Column(name = "banner_image_url") - val bannerImageUrl: String?, + var bannerImageUrl: String?, @Column(name = "accompany_cnt", nullable = false) - val accompanyCnt: Long = 0L + var accompanyCnt: Long = 0L, + + @Column(name = "view_cnt", nullable = false) + var viewCnt: Long = 0L ) : BaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt index 3c2a4ff..bfbd516 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt @@ -20,25 +20,28 @@ class AccompanyHistEntity ( val userId: Long, @Column(name = "title", nullable = false) - val title: String, + var title: String, @Lob @Column(name = "content", nullable = false) - val content: String, + var content: String, @Column(name = "accompany_status_cd", nullable = false) - val accompanyStatusCd : String, + var accompanyStatusCd : String, @Column(name = "start_trip_date", nullable = false) - val startTripDate: LocalDate, + var startTripDate: LocalDate, @Column(name = "end_trip_date", nullable = false) - val endTripDate: LocalDate, + var endTripDate: LocalDate, @Column(name = "banner_image_url") - val bannerImageUrl: String?, + var bannerImageUrl: String?, @Column(name = "accompany_cnt", nullable = false) - val accompanyCnt: Long = 0L + var accompanyCnt: Long = 0L, + + @Column(name = "view_cnt", nullable = false) + var viewCnt: Long = 0L ) : BaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt index 6adb04c..4b5a9ee 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt @@ -39,4 +39,12 @@ class AccompanyService( return ReadAccompanyDTO.toDto(accompanyEntity, accompanyDestinationEntity) } + @Transactional + fun incrViewCnt(param : Long) : Long{ + val accompanyEntity = accompanyRepository.findByAccompanyId(param) + accompanyEntity.let { + it.viewCnt++ + } + return param + } } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeDto.kt new file mode 100644 index 0000000..cb26ff0 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeDto.kt @@ -0,0 +1,77 @@ +package com.travel.withaeng.domain.accompanylike + +import com.travel.withaeng.common.cd.AccompanyStatusCd +import com.travel.withaeng.domain.accompany.AccompanyDestinationEntity +import com.travel.withaeng.domain.accompany.AccompanyEntity +import com.travel.withaeng.domain.accompany.AccompanyHistEntity +import jakarta.validation.constraints.NotBlank +import lombok.Getter +import lombok.Setter +import org.jetbrains.annotations.NotNull +import java.time.LocalDate + +class AccompanyLikeDto { +} + +@Setter +@Getter +class CreateAccompanyLikeDTO( + + @NotNull + val userId: Long, + + @NotNull + val accompanyId: Long, + +){ + fun toEntity(): AccompanyLikeEntity { + return AccompanyLikeEntity( + 0, + this.userId, + this.accompanyId + ) + } + + fun toHistEntity(entity: AccompanyLikeEntity): AccompanyLikeHistEntity { + return AccompanyLikeHistEntity( + 0, + entity.likeId, + entity.userId, + entity.accompanyId + ) + } + +} + +@Setter +@Getter +class DeleteAccompanyLikeDTO( + + @NotNull + val likeId : Long, + + @NotNull + val userId: Long, + + @NotNull + val accompanyId: Long, + + ){ + fun toEntity(): AccompanyLikeEntity { + return AccompanyLikeEntity( + this.likeId, + this.userId, + this.accompanyId + ) + } + + fun toHistEntity(entity: AccompanyLikeEntity): AccompanyLikeHistEntity { + return AccompanyLikeHistEntity( + 0, + entity.likeId, + entity.userId, + entity.accompanyId + ) + } + +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistEntity.kt new file mode 100644 index 0000000..b575957 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistEntity.kt @@ -0,0 +1,24 @@ +package com.travel.withaeng.domain.accompanylike + +import com.travel.withaeng.domain.BaseEntity +import jakarta.persistence.* + +@Table(name = "accompany_like_hist") +@Entity +class AccompanyLikeHistEntity ( + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "hist_id", nullable = false) + val histId: Long, + + @Column(name = "like_id", nullable = false) + val likeId: Long, + + @Column(name = "user_id", nullable = false) + val userId: Long, + + @Column(name = "accompany_id", nullable = false) + val accompanyId: Long + +) : BaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistRepository.kt new file mode 100644 index 0000000..1285f9e --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistRepository.kt @@ -0,0 +1,5 @@ +package com.travel.withaeng.domain.accompanylike + +import org.springframework.data.jpa.repository.JpaRepository + +interface AccompanyLikeHistRepository : JpaRepository diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt new file mode 100644 index 0000000..b0d33bd --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt @@ -0,0 +1,41 @@ +package com.travel.withaeng.domain.accompanylike + +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional +import java.time.LocalDateTime + +@Service +@Transactional(readOnly = true) +class AccompanyLikeService( + + private val accompanyLikeRepository: AccompanyLikeRepository, + private val accompanyLikeHistRepository : AccompanyLikeHistRepository + +) { + + @Transactional + fun createAccompanyLike(param : CreateAccompanyLikeDTO) : Long { + + val accompanyLikeEntity = param.toEntity() + accompanyLikeRepository.save(accompanyLikeEntity) + + val accompanyLikeHistEntity = param.toHistEntity(accompanyLikeEntity) + accompanyLikeHistRepository.save(accompanyLikeHistEntity) + + return accompanyLikeEntity.likeId + } + + //TODO delete 성능이 안나올 경우 boolean 형으로 좋아요 제어 + @Transactional + fun deleteAccompanyLike(param : DeleteAccompanyLikeDTO){ + + val accompanyLikeEntity = param.toEntity() + accompanyLikeRepository.delete(accompanyLikeEntity) + + val accompanyLikeHistEntity = param.toHistEntity(accompanyLikeEntity) + accompanyLikeHistEntity.deletedAt = LocalDateTime.now() + accompanyLikeHistRepository.save(accompanyLikeHistEntity) + + } + +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt index a7909f0..d0bd503 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt @@ -1,42 +1,41 @@ package com.travel.withaeng.domain.accompanyreply +import com.travel.withaeng.domain.accompanylike.AccompanyLikeEntity +import com.travel.withaeng.domain.accompanylike.AccompanyLikeHistEntity import jakarta.validation.constraints.NotBlank import lombok.Getter import lombok.Setter import org.jetbrains.annotations.NotNull class AccompanyReplyDto { +} - @Setter - @Getter - inner class ReqAdd( +@Setter +@Getter +class CreateAccompanyReplyDTO( - @NotNull - val accompanyId : Long, + @NotNull + val userId: Long, - @NotNull - val parentId : Long, + @NotNull + val accompanyId: Long, - @NotNull - val depth : Long, - - @NotNull - val userId: Long, - - @NotBlank(message = "내용은 필수 값 입니다.") - val content: String, + ){ + fun toEntity(): AccompanyLikeEntity { + return AccompanyLikeEntity( + 0, + this.userId, + this.accompanyId + ) + } - ) { - fun createEntity(): AccompanyReplyEntity { - return AccompanyReplyEntity( - 0, - this.accompanyId, - this.parentId, - this.depth, - this.userId, - this.content - ) - } + fun toHistEntity(entity: AccompanyLikeEntity): AccompanyLikeHistEntity { + return AccompanyLikeHistEntity( + 0, + entity.likeId, + entity.userId, + entity.accompanyId + ) } } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt new file mode 100644 index 0000000..22db52c --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt @@ -0,0 +1,9 @@ +package com.travel.withaeng.domain.accompanyreply + +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional + +@Service +@Transactional(readOnly = true) +class AccompanyReplyService { +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationDto.kt new file mode 100644 index 0000000..e8d6d4b --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationDto.kt @@ -0,0 +1,8 @@ +package com.travel.withaeng.domain.destination + +import com.travel.withaeng.domain.accompany.AccompanyDestinationEntity +import com.travel.withaeng.domain.accompany.AccompanyEntity +import java.time.LocalDate + +class DestinationDto { +} diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationService.kt new file mode 100644 index 0000000..267c3c5 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationService.kt @@ -0,0 +1,4 @@ +package com.travel.withaeng.domain.destination + +class DestinationService { +} \ No newline at end of file From a7021c9fe6d051534699acc185c00e482a9b55a9 Mon Sep 17 00:00:00 2001 From: collenkim Date: Fri, 22 Mar 2024 19:03:47 -0700 Subject: [PATCH 039/174] =?UTF-8?q?=EB=8F=99=ED=96=89=20=EA=B2=8C=EC=8B=9C?= =?UTF-8?q?=EA=B8=80=20tag=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/AccompanyLikeController.kt | 2 +- .../controller/AccompanyReplyController.kt | 2 +- .../AccompanyReplyLikeController.kt | 9 +++++++++ .../withaeng/domain/accompany/AccompanyDto.kt | 18 +++++++++++++++++- .../domain/accompany/AccompanyService.kt | 8 +++++++- .../domain/accompany/AccompanyTagEntity.kt | 12 ++++++++++++ .../domain/accompany/AccompanyTagPk.kt | 16 ++++++++++++++++ .../domain/accompany/AccompanyTagRepository.kt | 9 +++++++++ 8 files changed, 72 insertions(+), 4 deletions(-) create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReplyLike/AccompanyReplyLikeController.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagEntity.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagPk.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagRepository.kt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyLike/controller/AccompanyLikeController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyLike/controller/AccompanyLikeController.kt index a43c04c..5eb3e74 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyLike/controller/AccompanyLikeController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyLike/controller/AccompanyLikeController.kt @@ -9,7 +9,7 @@ import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.* @RestController -@RequestMapping("/api/v1/accompany/{accompany}/like") +@RequestMapping("/api/v1/accompany/{accompanyId}/like") class AccompanyLikeController(private val accompanyLikeService: AccompanyLikeService) { @PostMapping("") diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReply/controller/AccompanyReplyController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReply/controller/AccompanyReplyController.kt index 7d0766c..87a9970 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReply/controller/AccompanyReplyController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReply/controller/AccompanyReplyController.kt @@ -10,7 +10,7 @@ import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController @RestController -@RequestMapping("/api/v1/accompany{accompany}/reply") +@RequestMapping("/api/v1/accompany{accompanyId}/reply") class AccompanyReplyController(private val accompanyReplyService: AccompanyReplyService){ /*@PostMapping("") diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReplyLike/AccompanyReplyLikeController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReplyLike/AccompanyReplyLikeController.kt new file mode 100644 index 0000000..4356f7d --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReplyLike/AccompanyReplyLikeController.kt @@ -0,0 +1,9 @@ +package com.travel.withaeng.accompanyReplyLike + +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController + +@RestController +@RequestMapping("/api/v1/accompany{accompanyId}/reply/{replyId}/like") +class AccompanyReplyLikeController { +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt index 070fcac..101bd4f 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt @@ -39,7 +39,9 @@ class CreateAccompanyDTO( val bannerImageUrl: String? = null, @NotNull - val accompanyCnt : Long + val accompanyCnt : Long, + + val tags : List? ){ fun toEntity(): AccompanyEntity { @@ -80,6 +82,20 @@ class CreateAccompanyDTO( this.city ) } + + fun toTagEntity(accompanyId : Long) : List? { + + if(tags == null){ + return null + } + + val tagList = mutableListOf() + for(tagNm in tags){ + tagList.add(AccompanyTagEntity(AccompanyTagPk(accompanyId, tagNm))) + } + + return tagList + } } data class ReadAccompanyDTO( diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt index 4b5a9ee..bb38518 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt @@ -9,7 +9,8 @@ class AccompanyService( private val accompanyRepository: AccompanyRepository, private val accompanyHistRepository : AccompanyHistRepository, - private val accompanyDestinationRepository : AccompanyDestinationRepository + private val accompanyDestinationRepository : AccompanyDestinationRepository, + private val accompanyTagRepository: AccompanyTagRepository ) { @@ -20,10 +21,15 @@ class AccompanyService( val accompanyHistEntity = param.toHistEntity(accompanyEntity) val accompanyDestinationEntity = param.toDestinationEntity(accompanyEntity.accompanyId) + val accompanyTagEntityList = param.toTagEntity(accompanyEntity.accompanyId) accompanyHistRepository.save(accompanyHistEntity) accompanyDestinationRepository.save(accompanyDestinationEntity) + if(accompanyTagEntityList != null){ + accompanyTagRepository.saveAll(accompanyTagEntityList) + } + return accompanyEntity.accompanyId; } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagEntity.kt new file mode 100644 index 0000000..312f6d6 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagEntity.kt @@ -0,0 +1,12 @@ +package com.travel.withaeng.domain.accompany + +import jakarta.persistence.* + +@Table(name = "accompany_tag") +@Entity +class AccompanyTagEntity ( + + @EmbeddedId + val accompanyTagPk: AccompanyTagPk, + +) \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagPk.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagPk.kt new file mode 100644 index 0000000..ee47654 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagPk.kt @@ -0,0 +1,16 @@ +package com.travel.withaeng.domain.accompany + +import jakarta.persistence.Column +import jakarta.persistence.Embeddable +import java.io.Serializable + +@Embeddable +data class AccompanyTagPk ( + + @Column(name = "accompany_id", nullable = false) + val accompanyId : Long, + + @Column(name = "tag_nm", nullable = false) + val tagNm : String + +) : Serializable \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagRepository.kt new file mode 100644 index 0000000..43d1eeb --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagRepository.kt @@ -0,0 +1,9 @@ +package com.travel.withaeng.domain.accompany + +import org.springframework.data.jpa.repository.JpaRepository + +interface AccompanyTagRepository : JpaRepository { + + fun findByAccompanyId(accompanyId : Long) : List? + +} \ No newline at end of file From e0516e54ace9a1b4793407cfeb5586bd2e1d1477 Mon Sep 17 00:00:00 2001 From: collenkim Date: Sat, 23 Mar 2024 07:38:46 -0700 Subject: [PATCH 040/174] =?UTF-8?q?=EB=8F=99=ED=96=89=20=EA=B2=8C=EC=8B=9C?= =?UTF-8?q?=EA=B8=80=20=EC=A1=B0=ED=9A=8C=EC=88=98=20=EA=B0=90=EC=86=8C=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=20=EC=B2=98=EB=A6=AC=20=ED=95=B8=EB=93=A4=EB=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 --- .../controller/AccompanyController.kt | 44 +++++----- .../common/ControllerExceptionAdvice.kt | 14 ++++ .../exception/InvalidAccessException.kt | 5 ++ .../common/exception/NotExistsException.kt | 5 ++ .../withaeng/domain/AccompanyBaseEntity.kt | 26 ++++++ .../com/travel/withaeng/domain/BaseEntity.kt | 5 ++ .../accompany/AccompanyDestinationEntity.kt | 16 ++-- .../domain/accompany/AccompanyDetailEntity.kt | 23 +++++ .../accompany/AccompanyDetailRepository.kt | 8 ++ .../withaeng/domain/accompany/AccompanyDto.kt | 74 +++++++++++++++-- .../domain/accompany/AccompanyEntity.kt | 7 +- .../domain/accompany/AccompanyHistEntity.kt | 4 +- .../domain/accompany/AccompanyRepository.kt | 2 +- .../domain/accompany/AccompanyService.kt | 83 ++++++++++++++++--- .../accompany/AccompanyTagRepository.kt | 3 +- .../accompanylike/AccompanyLikeEntity.kt | 10 +-- .../accompanylike/AccompanyLikeHistEntity.kt | 4 +- .../accompanylike/AccompanyLikeService.kt | 9 +- .../accompanyreply/AccompanyReplyEntity.kt | 4 +- .../AccompanyReplyLikeEntity.kt | 4 +- 20 files changed, 284 insertions(+), 66 deletions(-) create mode 100644 withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/InvalidAccessException.kt create mode 100644 withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/NotExistsException.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/AccompanyBaseEntity.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDetailEntity.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDetailRepository.kt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompany/controller/AccompanyController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompany/controller/AccompanyController.kt index b733830..0a02fbe 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompany/controller/AccompanyController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompany/controller/AccompanyController.kt @@ -1,43 +1,45 @@ package com.travel.withaeng.accompany.controller -import com.travel.withaeng.domain.accompany.AccompanyDto -import com.travel.withaeng.domain.accompany.AccompanyService -import com.travel.withaeng.domain.accompany.CreateAccompanyDTO -import com.travel.withaeng.domain.accompany.ReadAccompanyDTO +import com.travel.withaeng.common.ApiResponse +import com.travel.withaeng.domain.accompany.* import org.springframework.http.HttpStatus -import org.springframework.http.HttpStatusCode import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.* -import java.util.Objects @RestController @RequestMapping("/api/v1/accompany") class AccompanyController(private val accompanyService: AccompanyService) { @PostMapping("") - fun create(@RequestBody param : CreateAccompanyDTO) : ResponseEntity { - return ResponseEntity.status(HttpStatus.CREATED).body(accompanyService.createAccompany(param)) + fun create(@RequestBody param : CreateAccompanyDTO) : ResponseEntity> { + return ResponseEntity.status(HttpStatus.CREATED).body(ApiResponse(true, accompanyService.createAccompany(param), null)) } - /*@PutMapping("") - fun create(@RequestBody param : ModifyAccompanyDTO) : ResponseEntity { - val accompanyId = accompanyService.createAccompany(param) - return ResponseEntity.status(HttpStatus.CREATED).body(accompanyId) - }*/ + @PutMapping("") + fun modify(@RequestBody param : ModifyAccompanyDTO) : ResponseEntity> { + return ResponseEntity.status(HttpStatus.CREATED).body(ApiResponse(true, accompanyService.modifyAccompany(param), null)) + } @GetMapping("/{accompanyId}") - fun getOne(@PathVariable("accompanyId") accompanyId : Long) : ResponseEntity { - return ResponseEntity.status(HttpStatus.OK).body(accompanyService.getOne(accompanyId)) + fun getOne(@PathVariable("accompanyId") accompanyId : Long) : ResponseEntity> { + return ResponseEntity.status(HttpStatus.OK).body(ApiResponse(true, accompanyService.getOne(accompanyId), null)) } @PutMapping("/{accompanyId}/incr/viewCnt") - fun incrViewCnt(@PathVariable("accompanyId") accompanyId : Long) : ResponseEntity { - return ResponseEntity.status(HttpStatus.OK).body(accompanyService.incrViewCnt(accompanyId)) + fun incrViewCnt(@PathVariable("accompanyId") accompanyId : Long) : ResponseEntity> { + accompanyService.incrViewCnt(accompanyId) + return ResponseEntity.status(HttpStatus.OK).body(ApiResponse(true, null, null)) + } + + @PutMapping("/{accompanyId}/decr/viewCnt") + fun decrViewCnt(@PathVariable("accompanyId") accompanyId : Long) : ResponseEntity> { + accompanyService.decrViewCnt(accompanyId) + return ResponseEntity.status(HttpStatus.OK).body(ApiResponse(true, null, null)) } - /*@GetMapping("/getList") - fun getList(@RequestBody param : SearchAccompanyDTO) : ResponseEntity> { - return ResponseEntity.status(HttpStatus.OK).body(accompanyService.getList(param)) - }*/ + @GetMapping("/getList") + fun getList(@RequestBody param : SearchAccompanyDTO) : ResponseEntity> { + return ResponseEntity.status(HttpStatus.OK).body(ApiResponse(true, accompanyService.getList(param), null)) + } } \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ControllerExceptionAdvice.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ControllerExceptionAdvice.kt index fe64f88..74cb5af 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ControllerExceptionAdvice.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ControllerExceptionAdvice.kt @@ -1,5 +1,7 @@ package com.travel.withaeng.common +import com.travel.withaeng.common.exception.InvalidAccessException +import com.travel.withaeng.common.exception.NotExistsException import com.travel.withaeng.common.exception.WithaengException import com.travel.withaeng.common.exception.WithaengExceptionType import org.slf4j.Logger @@ -68,6 +70,18 @@ class ControllerExceptionAdvice { return errorResponse(WithaengExceptionType.ARGUMENT_NOT_VALID, errorMessage) } + @ExceptionHandler(NotExistsException::class) + protected fun notExistsException(e: NotExistsException) : ResponseEntity> { + logger.error("notExistsException", e) + return errorResponse(WithaengExceptionType.NOT_EXIST, e.message) + } + + @ExceptionHandler(InvalidAccessException::class) + protected fun invalidAccessException(e: InvalidAccessException) : ResponseEntity> { + logger.error("invalidAccessException", e) + return errorResponse(WithaengExceptionType.INVALID_ACCESS, e.message) + } + private fun WithaengException.toApiErrorResponse() = ApiErrorResponse( code = errorCode, message = message, diff --git a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/InvalidAccessException.kt b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/InvalidAccessException.kt new file mode 100644 index 0000000..8ce6e51 --- /dev/null +++ b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/InvalidAccessException.kt @@ -0,0 +1,5 @@ +package com.travel.withaeng.common.exception + +class InvalidAccessException ( + override val message: String, +) : RuntimeException() \ No newline at end of file diff --git a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/NotExistsException.kt b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/NotExistsException.kt new file mode 100644 index 0000000..df7fb65 --- /dev/null +++ b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/NotExistsException.kt @@ -0,0 +1,5 @@ +package com.travel.withaeng.common.exception + +class NotExistsException ( + override val message: String, +) : RuntimeException() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/AccompanyBaseEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/AccompanyBaseEntity.kt new file mode 100644 index 0000000..f96a3f5 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/AccompanyBaseEntity.kt @@ -0,0 +1,26 @@ +package com.travel.withaeng.domain + +import jakarta.persistence.Column +import jakarta.persistence.EntityListeners +import jakarta.persistence.MappedSuperclass +import org.springframework.data.annotation.CreatedDate +import org.springframework.data.annotation.LastModifiedDate +import org.springframework.data.jpa.domain.support.AuditingEntityListener +import java.time.LocalDateTime + +@EntityListeners(AuditingEntityListener::class) +@MappedSuperclass +abstract class AccompanyBaseEntity { + + @CreatedDate + @Column(name = "created_at", nullable = false, updatable = false) + var createdAt: LocalDateTime = LocalDateTime.now() + + @LastModifiedDate + @Column(name = "updated_at", nullable = false, updatable = true) + var updatedAt: LocalDateTime = LocalDateTime.now() + + @Column(name = "deleted_at", nullable = true, updatable = true) + var deletedAt: LocalDateTime? = null + +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/BaseEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/BaseEntity.kt index 7917e5b..1d2586b 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/BaseEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/BaseEntity.kt @@ -10,6 +10,11 @@ import java.time.LocalDateTime @MappedSuperclass abstract class BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id", nullable = false) + val id: Long = 0L + @CreatedDate @Column(name = "created_at", nullable = false, updatable = false) var createdAt: LocalDateTime = LocalDateTime.now() diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestinationEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestinationEntity.kt index deaf49c..dd7d6a0 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestinationEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestinationEntity.kt @@ -1,6 +1,6 @@ package com.travel.withaeng.domain.accompany -import com.travel.withaeng.domain.BaseEntity +import com.travel.withaeng.domain.AccompanyBaseEntity import jakarta.persistence.* @Table(name = "accompany_destinaion") @@ -15,13 +15,13 @@ class AccompanyDestinationEntity( @Column(name = "accompany_id", nullable = false) val accompanyId: Long, - @Column(name = "continent", nullable = false) - val continent: String, + @Column(name = "continent", nullable = false, updatable = true) + var continent: String, - @Column(name = "country", nullable = true) - val country : String?, + @Column(name = "country", nullable = true, updatable = true) + var country : String?, - @Column(name = "city", nullable = true) - val city : String?, + @Column(name = "city", nullable = true, updatable = true) + var city : String?, -) : BaseEntity() +) : AccompanyBaseEntity() diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDetailEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDetailEntity.kt new file mode 100644 index 0000000..f72298c --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDetailEntity.kt @@ -0,0 +1,23 @@ +package com.travel.withaeng.domain.accompany + +import com.travel.withaeng.domain.AccompanyBaseEntity +import jakarta.persistence.* +import org.hibernate.annotations.DynamicUpdate + +@DynamicUpdate +@Table(name = "accompany_detail") +@Entity +class AccompanyDetailEntity ( + + @Id + @Column(name = "accompany_id", nullable = false) + val accompanyId: Long, + + @Column(name = "view_cnt", nullable = false) + var viewCnt: Long = 0L, + + @Column(name = "like_cnt", nullable = false) + var likeCnt: Long = 0L + + +) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDetailRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDetailRepository.kt new file mode 100644 index 0000000..206ec91 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDetailRepository.kt @@ -0,0 +1,8 @@ +package com.travel.withaeng.domain.accompany + +import org.springframework.data.jpa.repository.JpaRepository + +interface AccompanyDetailRepository : JpaRepository { + fun findByAccompanyId(accompanyId : Long) : AccompanyDetailEntity + +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt index 101bd4f..a2f6e33 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt @@ -26,9 +26,9 @@ class CreateAccompanyDTO( @NotBlank(message = "대륙은 필수 값 입니다.") val continent: String, - private val country : String? = null, + val country : String? = null, - private val city : String? = null, + val city : String? = null, @NotBlank val startTripDate: LocalDate, @@ -83,6 +83,66 @@ class CreateAccompanyDTO( ) } + fun toDetailEntity(accompanyId : Long) : AccompanyDetailEntity { + return AccompanyDetailEntity( + accompanyId, + 0, + 0 + ) + } + + fun toTagEntity(accompanyId : Long) : List? { + + if(tags == null){ + return null + } + + val tagList = mutableListOf() + for(tagNm in tags){ + tagList.add(AccompanyTagEntity(AccompanyTagPk(accompanyId, tagNm))) + } + + return tagList + } +} + +@Setter +@Getter +class ModifyAccompanyDTO( + + @NotNull + val accompanyId : Long, + + @NotNull + val userId: Long, + + @NotBlank(message = "제목은 필수 값 입니다.") + val title: String, + + @NotBlank(message = "내용은 필수 값 입니다.") + val content: String, + + @NotBlank(message = "대륙은 필수 값 입니다.") + val continent: String, + + val country : String? = null, + + val city : String? = null, + + @NotBlank + val startTripDate: LocalDate, + + @NotBlank + val endTripDate: LocalDate, + + val bannerImageUrl: String? = null, + + @NotNull + val accompanyCnt : Long, + + val tags : List? + +){ fun toTagEntity(accompanyId : Long) : List? { if(tags == null){ @@ -111,12 +171,14 @@ data class ReadAccompanyDTO( val endTripDate: LocalDate, val bannerImageUrl: String? = null, val accompanyCnt : Long, - val viewCnt : Long + val viewCnt : Long, + val likeCnt : Long, + val tags : List? = null ){ companion object { @JvmStatic - fun toDto(accompanyEntity : AccompanyEntity, accompanyDestinationEntity: AccompanyDestinationEntity) : ReadAccompanyDTO { + fun toDto(accompanyEntity : AccompanyEntity, accompanyDestinationEntity: AccompanyDestinationEntity, accompanyDetailEntity: AccompanyDetailEntity, tagList : List?) : ReadAccompanyDTO { return ReadAccompanyDTO( accompanyId = accompanyEntity.accompanyId, userId = accompanyEntity.userId, @@ -129,7 +191,9 @@ data class ReadAccompanyDTO( endTripDate = accompanyEntity.endTripDate, bannerImageUrl = accompanyEntity.bannerImageUrl, accompanyCnt = accompanyEntity.accompanyCnt, - viewCnt = accompanyEntity.viewCnt + viewCnt = accompanyDetailEntity.viewCnt, + likeCnt = accompanyDetailEntity.likeCnt, + tags = tagList ) } } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyEntity.kt index a810530..410e384 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyEntity.kt @@ -1,6 +1,6 @@ package com.travel.withaeng.domain.accompany -import com.travel.withaeng.domain.BaseEntity +import com.travel.withaeng.domain.AccompanyBaseEntity import jakarta.persistence.* import org.hibernate.annotations.DynamicUpdate import java.time.LocalDate @@ -40,7 +40,4 @@ class AccompanyEntity( @Column(name = "accompany_cnt", nullable = false) var accompanyCnt: Long = 0L, - @Column(name = "view_cnt", nullable = false) - var viewCnt: Long = 0L - -) : BaseEntity() \ No newline at end of file +) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt index bfbd516..1639e7e 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt @@ -1,6 +1,6 @@ package com.travel.withaeng.domain.accompany -import com.travel.withaeng.domain.BaseEntity +import com.travel.withaeng.domain.AccompanyBaseEntity import jakarta.persistence.* import java.time.LocalDate @@ -44,4 +44,4 @@ class AccompanyHistEntity ( @Column(name = "view_cnt", nullable = false) var viewCnt: Long = 0L -) : BaseEntity() \ No newline at end of file +) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt index 7559fc3..6b7b9d9 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt @@ -4,6 +4,6 @@ import org.springframework.data.jpa.repository.JpaRepository interface AccompanyRepository : JpaRepository { - fun findByAccompanyId(accompanyId : Long) : AccompanyEntity + fun findByAccompanyId(accompanyId : Long) : AccompanyEntity? } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt index bb38518..c4e6b18 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt @@ -1,5 +1,7 @@ package com.travel.withaeng.domain.accompany +import com.travel.withaeng.common.exception.InvalidAccessException +import com.travel.withaeng.common.exception.NotExistsException import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -10,47 +12,106 @@ class AccompanyService( private val accompanyRepository: AccompanyRepository, private val accompanyHistRepository : AccompanyHistRepository, private val accompanyDestinationRepository : AccompanyDestinationRepository, + private val accompanyDetailRepository : AccompanyDetailRepository, private val accompanyTagRepository: AccompanyTagRepository ) { @Transactional - fun createAccompany(param : CreateAccompanyDTO) : Long { + fun createAccompany(param : CreateAccompanyDTO) : ReadAccompanyDTO { val accompanyEntity = param.toEntity() accompanyRepository.save(accompanyEntity) val accompanyHistEntity = param.toHistEntity(accompanyEntity) val accompanyDestinationEntity = param.toDestinationEntity(accompanyEntity.accompanyId) + val accompanyDetailEntity = param.toDetailEntity(accompanyEntity.accompanyId) val accompanyTagEntityList = param.toTagEntity(accompanyEntity.accompanyId) accompanyHistRepository.save(accompanyHistEntity) accompanyDestinationRepository.save(accompanyDestinationEntity) + accompanyDetailRepository.save(accompanyDetailEntity) if(accompanyTagEntityList != null){ accompanyTagRepository.saveAll(accompanyTagEntityList) } - return accompanyEntity.accompanyId; + return getOne(accompanyHistEntity.accompanyId) + } + + @Transactional + fun modifyAccompany(param : ModifyAccompanyDTO) : ReadAccompanyDTO { + + val accompanyEntity = accompanyRepository.findByAccompanyId(param.accompanyId) + + if(accompanyEntity != null){ + + if(accompanyEntity.userId != param.userId){ + throw InvalidAccessException("등록자와 수정자가 달라 수정 요청을 거부 합니다.") + } + + val accompanyDestinationEntity = accompanyDestinationRepository.findByAccompanyId(param.accompanyId) + val accompanyTagEntityList = param.toTagEntity(accompanyEntity.accompanyId) + + accompanyEntity.let { + it.title = param.title + it.content = param.content + it.startTripDate = param.startTripDate + it.endTripDate = param.endTripDate + it.bannerImageUrl = param.bannerImageUrl + it.accompanyCnt = param.accompanyCnt + } + + accompanyDestinationEntity.let { + it.continent = param.continent + it.country = param.country + it.city = param.city + } + + accompanyTagRepository.deleteByAccompanyId(accompanyEntity.accompanyId) + if(accompanyTagEntityList != null){ + accompanyTagRepository.saveAll(accompanyTagEntityList) + } + + } + + return getOne(param.accompanyId) } fun getOne(param : Long) : ReadAccompanyDTO { val accompanyEntity = accompanyRepository.findByAccompanyId(param) - val accompanyDestinationEntity = accompanyDestinationRepository.findByAccompanyId(param) - return ReadAccompanyDTO.toDto(accompanyEntity, accompanyDestinationEntity) + + if(accompanyEntity != null){ + val accompanyDestinationEntity = accompanyDestinationRepository.findByAccompanyId(param) + val accompanyDetailEntity = accompanyDetailRepository.findByAccompanyId(param) + val tagList:List? = accompanyTagRepository.findByAccompanyId(param)?.map{AccompanyTagEntity::accompanyTagPk.name} + return ReadAccompanyDTO.toDto(accompanyEntity, accompanyDestinationEntity, accompanyDetailEntity, tagList) + } + + throw NotExistsException("존재하지 않는 동행 게시글 조회 요청 입니다.") } - fun getList(param : Long) : ReadAccompanyDTO { + fun getList(param : SearchAccompanyDTO) : List { val accompanyEntity = accompanyRepository.findByAccompanyId(param) - val accompanyDestinationEntity = accompanyDestinationRepository.findByAccompanyId(param) - return ReadAccompanyDTO.toDto(accompanyEntity, accompanyDestinationEntity) + if(accompanyEntity != null){ + val accompanyDestinationEntity = accompanyDestinationRepository.findByAccompanyId(param) + val accompanyDetailEntity = accompanyDetailRepository.findByAccompanyId(param) + return ReadAccompanyDTO.toDto(accompanyEntity, accompanyDestinationEntity) + } } @Transactional - fun incrViewCnt(param : Long) : Long{ - val accompanyEntity = accompanyRepository.findByAccompanyId(param) - accompanyEntity.let { + fun incrViewCnt(param : Long) { + val accompanyDetailEntity = accompanyDetailRepository.findByAccompanyId(param) + accompanyDetailEntity.let { it.viewCnt++ } - return param + } + + @Transactional + fun decrViewCnt(param : Long){ + val accompanyDetailEntity = accompanyDetailRepository.findByAccompanyId(param) + accompanyDetailEntity.let { + it.viewCnt-- + } } } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagRepository.kt index 43d1eeb..1822809 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagRepository.kt @@ -2,8 +2,9 @@ package com.travel.withaeng.domain.accompany import org.springframework.data.jpa.repository.JpaRepository -interface AccompanyTagRepository : JpaRepository { +interface AccompanyTagRepository : JpaRepository { fun findByAccompanyId(accompanyId : Long) : List? + fun deleteByAccompanyId(accompanyId: Long) } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeEntity.kt index 9332fb2..cd25b78 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeEntity.kt @@ -1,6 +1,6 @@ package com.travel.withaeng.domain.accompanylike -import com.travel.withaeng.domain.BaseEntity +import com.travel.withaeng.domain.AccompanyBaseEntity import jakarta.persistence.* @Table(name = "accompany_like") @@ -12,10 +12,10 @@ class AccompanyLikeEntity( @Column(name = "like_id", nullable = false) val likeId: Long, + @Column(name = "accompany_id", nullable = false) + val accompanyId: Long, + @Column(name = "user_id", nullable = false) val userId: Long, - @Column(name = "accompany_id", nullable = false) - val accompanyId: Long - -) : BaseEntity() \ No newline at end of file +) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistEntity.kt index b575957..c16f0d2 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistEntity.kt @@ -1,6 +1,6 @@ package com.travel.withaeng.domain.accompanylike -import com.travel.withaeng.domain.BaseEntity +import com.travel.withaeng.domain.AccompanyBaseEntity import jakarta.persistence.* @Table(name = "accompany_like_hist") @@ -21,4 +21,4 @@ class AccompanyLikeHistEntity ( @Column(name = "accompany_id", nullable = false) val accompanyId: Long -) : BaseEntity() \ No newline at end of file +) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt index b0d33bd..828e959 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt @@ -1,5 +1,6 @@ package com.travel.withaeng.domain.accompanylike +import com.travel.withaeng.domain.accompany.AccompanyDetailRepository import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional import java.time.LocalDateTime @@ -9,7 +10,8 @@ import java.time.LocalDateTime class AccompanyLikeService( private val accompanyLikeRepository: AccompanyLikeRepository, - private val accompanyLikeHistRepository : AccompanyLikeHistRepository + private val accompanyLikeHistRepository : AccompanyLikeHistRepository, + private val accompanyDetailRepository: AccompanyDetailRepository ) { @@ -22,6 +24,11 @@ class AccompanyLikeService( val accompanyLikeHistEntity = param.toHistEntity(accompanyLikeEntity) accompanyLikeHistRepository.save(accompanyLikeHistEntity) + val accompanyDetailEntity = accompanyDetailRepository.findByAccompanyId(param.accompanyId) + accompanyDetailEntity.let { + it.likeCnt++ + } + return accompanyLikeEntity.likeId } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyEntity.kt index e6b193f..ca5977e 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyEntity.kt @@ -1,6 +1,6 @@ package com.travel.withaeng.domain.accompanyreply -import com.travel.withaeng.domain.BaseEntity +import com.travel.withaeng.domain.AccompanyBaseEntity import jakarta.persistence.* @Table(name = "accompany_reply") @@ -27,4 +27,4 @@ class AccompanyReplyEntity( @Column(name = "content", nullable = false) val content: String, -) : BaseEntity() \ No newline at end of file +) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeEntity.kt index 3a3cd0b..2296bbc 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeEntity.kt @@ -1,6 +1,6 @@ package com.travel.withaeng.domain.accompanyreplylike -import com.travel.withaeng.domain.BaseEntity +import com.travel.withaeng.domain.AccompanyBaseEntity import jakarta.persistence.* @Table(name = "accompany_reply_like") @@ -18,4 +18,4 @@ class AccompanyReplyLikeEntity( @Column(name = "user_id", nullable = false) val userId: Long -) : BaseEntity() \ No newline at end of file +) : AccompanyBaseEntity() \ No newline at end of file From 2c0c4af25e401fdf17fa3f6f5f1ceb3ce6984f0f Mon Sep 17 00:00:00 2001 From: collenkim Date: Mon, 1 Apr 2024 10:46:14 +0900 Subject: [PATCH 041/174] =?UTF-8?q?=EB=8C=93=EA=B8=80,=20=EB=8C=93?= =?UTF-8?q?=EA=B8=80=20=EC=A2=8B=EC=95=84=EC=9A=94=20API=20=EA=B0=9C?= =?UTF-8?q?=EB=B0=9C=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/AccompanyLikeController.kt | 8 +- .../controller/AccompanyReplyController.kt | 29 +++- .../AccompanyReplyLikeController.kt | 25 ++- .../com/travel/withaeng/common/cd/ExecCd.kt | 14 ++ .../withaeng/domain/accompany/AccompanyDto.kt | 38 ++--- .../domain/accompany/AccompanyHistEntity.kt | 4 +- .../domain/accompany/AccompanyService.kt | 7 +- .../domain/accompany/AccompanyTagEntity.kt | 11 +- .../domain/accompany/AccompanyTagPk.kt | 16 -- .../domain/accompanylike/AccompanyLikeDto.kt | 7 +- .../accompanylike/AccompanyLikeHistEntity.kt | 5 +- .../accompanylike/AccompanyLikeService.kt | 7 +- .../accompanyreply/AccompanyReplyDto.kt | 151 ++++++++++++++++-- .../accompanyreply/AccompanyReplyEntity.kt | 4 +- .../AccompanyReplyHistEntity.kt | 36 +++++ .../AccompanyReplyHistRepository.kt | 5 + .../AccompanyReplyRepository.kt | 7 +- .../accompanyreply/AccompanyReplyService.kt | 93 ++++++++++- .../AccompanyReplyLikeDto.kt | 77 +++++++++ .../AccompanyReplyLikeHistEntity.kt | 28 ++++ .../AccompanyReplyLikeHistRepository.kt | 5 + .../AccompanyReplyLikeService.kt | 48 ++++++ .../withaeng/config/JasyptConfigTest.kt | 16 +- 23 files changed, 550 insertions(+), 91 deletions(-) create mode 100644 withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/ExecCd.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagPk.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHistEntity.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHistRepository.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeDto.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHistEntity.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHistRepository.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyLike/controller/AccompanyLikeController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyLike/controller/AccompanyLikeController.kt index 5eb3e74..1f91452 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyLike/controller/AccompanyLikeController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyLike/controller/AccompanyLikeController.kt @@ -1,5 +1,6 @@ package com.travel.withaeng.accompanyLike.controller +import com.travel.withaeng.common.ApiResponse import com.travel.withaeng.domain.accompany.CreateAccompanyDTO import com.travel.withaeng.domain.accompanylike.AccompanyLikeService import com.travel.withaeng.domain.accompanylike.CreateAccompanyLikeDTO @@ -13,13 +14,14 @@ import org.springframework.web.bind.annotation.* class AccompanyLikeController(private val accompanyLikeService: AccompanyLikeService) { @PostMapping("") - fun create(@RequestBody param : CreateAccompanyLikeDTO) : ResponseEntity { - return ResponseEntity.status(HttpStatus.CREATED).body(accompanyLikeService.createAccompanyLike(param)) + fun create(@RequestBody param : CreateAccompanyLikeDTO) : ResponseEntity> { + return ResponseEntity.status(HttpStatus.CREATED).body( + ApiResponse(true, accompanyLikeService.createAccompanyLike(param), null)) } @DeleteMapping("") fun delete(@RequestBody param : DeleteAccompanyLikeDTO) : ResponseEntity{ - return ResponseEntity.status(HttpStatus.OK).body("") + return ResponseEntity.status(HttpStatus.OK).body(ApiResponse(true,accompanyLikeService.deleteAccompanyLike(param), null)) } } \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReply/controller/AccompanyReplyController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReply/controller/AccompanyReplyController.kt index 87a9970..02d1e06 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReply/controller/AccompanyReplyController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReply/controller/AccompanyReplyController.kt @@ -1,10 +1,16 @@ package com.travel.withaeng.accompanyReply.controller +import com.travel.withaeng.common.ApiResponse import com.travel.withaeng.domain.accompanyreply.AccompanyReplyService import com.travel.withaeng.domain.accompanyreply.CreateAccompanyReplyDTO +import com.travel.withaeng.domain.accompanyreply.DeleteAccompanyReplyDTO +import com.travel.withaeng.domain.accompanyreply.ModifyAccompanyReplyDTO import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.DeleteMapping +import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.PutMapping import org.springframework.web.bind.annotation.RequestBody import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController @@ -13,9 +19,24 @@ import org.springframework.web.bind.annotation.RestController @RequestMapping("/api/v1/accompany{accompanyId}/reply") class AccompanyReplyController(private val accompanyReplyService: AccompanyReplyService){ - /*@PostMapping("") - fun create(@RequestBody param : CreateAccompanyReplyDTO) : ResponseEntity { - return ResponseEntity.status(HttpStatus.CREATED).body(accompanyReplyService.createAccompanyReply(param)) - }*/ + @PostMapping("") + fun create(@RequestBody param : CreateAccompanyReplyDTO) : ResponseEntity> { + return ResponseEntity.status(HttpStatus.CREATED).body(ApiResponse(true, accompanyReplyService.createAccompanyReply(param), null)) + } + + @PutMapping("") + fun create(@RequestBody param : ModifyAccompanyReplyDTO) : ResponseEntity> { + return ResponseEntity.status(HttpStatus.OK).body(ApiResponse(true, accompanyReplyService.modifyAccompanyReply(param), null)) + } + + @DeleteMapping("") + fun create(@RequestBody param : DeleteAccompanyReplyDTO) : ResponseEntity> { + return ResponseEntity.status(HttpStatus.OK).body(ApiResponse(true, accompanyReplyService.deleteAccompanyReply(param), null)) + } + + @GetMapping("/getList") + fun create(@RequestBody param : Long) : ResponseEntity> { + return ResponseEntity.status(HttpStatus.OK).body(ApiResponse(true, accompanyReplyService.getList(param), null)) + } } \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReplyLike/AccompanyReplyLikeController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReplyLike/AccompanyReplyLikeController.kt index 4356f7d..1ebf4c8 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReplyLike/AccompanyReplyLikeController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReplyLike/AccompanyReplyLikeController.kt @@ -1,9 +1,28 @@ package com.travel.withaeng.accompanyReplyLike -import org.springframework.web.bind.annotation.RequestMapping -import org.springframework.web.bind.annotation.RestController +import com.travel.withaeng.common.ApiResponse +import com.travel.withaeng.domain.accompanylike.AccompanyLikeService +import com.travel.withaeng.domain.accompanylike.CreateAccompanyLikeDTO +import com.travel.withaeng.domain.accompanylike.DeleteAccompanyLikeDTO +import com.travel.withaeng.domain.accompanyreplylike.AccompanyReplyLikeService +import com.travel.withaeng.domain.accompanyreplylike.CreateAccompanyReplyLikeDTO +import com.travel.withaeng.domain.accompanyreplylike.DeleteAccompanyReplyLikeDTO +import org.springframework.http.HttpStatus +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.* @RestController @RequestMapping("/api/v1/accompany{accompanyId}/reply/{replyId}/like") -class AccompanyReplyLikeController { +class AccompanyReplyLikeController(private val accompanyReplyLikeService: AccompanyReplyLikeService) { + + @PostMapping("") + fun create(@RequestBody param : CreateAccompanyReplyLikeDTO) : ResponseEntity> { + return ResponseEntity.status(HttpStatus.CREATED).body(ApiResponse(true, accompanyReplyLikeService.createAccompanyReplyLike(param), null)) + } + + @DeleteMapping("") + fun delete(@RequestBody param : DeleteAccompanyReplyLikeDTO) : ResponseEntity> { + return ResponseEntity.status(HttpStatus.OK).body(ApiResponse(true, accompanyReplyLikeService.deleteAccompanyReplyLike(param), null)) + } + } \ No newline at end of file diff --git a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/ExecCd.kt b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/ExecCd.kt new file mode 100644 index 0000000..d021b6e --- /dev/null +++ b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/ExecCd.kt @@ -0,0 +1,14 @@ +package com.travel.withaeng.common.cd + +enum class ExecCd ( + + val execCd : String, + val execNm : String + +) { + + CREATE("CREATE", "등록"), + UPDATE("UPDATE", "수정"), + DELETE("DELETE", "삭제") + +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt index a2f6e33..bfa0143 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt @@ -1,6 +1,7 @@ package com.travel.withaeng.domain.accompany import com.travel.withaeng.common.cd.AccompanyStatusCd +import com.travel.withaeng.common.cd.ExecCd import jakarta.validation.constraints.NotBlank import lombok.Getter import lombok.NoArgsConstructor @@ -69,7 +70,8 @@ class CreateAccompanyDTO( entity.startTripDate, entity.endTripDate, entity.bannerImageUrl, - entity.accompanyCnt + entity.accompanyCnt, + ExecCd.CREATE.execCd ) } @@ -99,7 +101,7 @@ class CreateAccompanyDTO( val tagList = mutableListOf() for(tagNm in tags){ - tagList.add(AccompanyTagEntity(AccompanyTagPk(accompanyId, tagNm))) + tagList.add(AccompanyTagEntity(accompanyId, tagNm)) } return tagList @@ -151,7 +153,7 @@ class ModifyAccompanyDTO( val tagList = mutableListOf() for(tagNm in tags){ - tagList.add(AccompanyTagEntity(AccompanyTagPk(accompanyId, tagNm))) + tagList.add(AccompanyTagEntity(accompanyId, tagNm)) } return tagList @@ -203,32 +205,12 @@ data class ReadAccompanyDTO( @Getter class SearchAccompanyDTO( - @NotNull - val userId: Long, - - @NotBlank(message = "제목은 필수 값 입니다.") - val title: String, - - @NotBlank(message = "내용은 필수 값 입니다.") - val content: String, - - @NotBlank(message = "대륙은 필수 값 입니다.") - val continent: String, + val viewCntOrder: Boolean,//조회수 높은 순서 - private val country : String? = null, + val likeCntOrder: Boolean,//좋아요 높은 순서 - private val city : String? = null, + val startTripDate: LocalDate,//동행 모집 시작일시 - @NotBlank - val startTripDate: LocalDate, - - @NotBlank - val endTripDate: LocalDate, - - val bannerImageUrl: String? = null, - - @NotNull - val accompanyCnt : Long -){ + val endTripDate: LocalDate,//동행 모집 마감일시 -} \ No newline at end of file +) \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt index 1639e7e..418ef10 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt @@ -41,7 +41,7 @@ class AccompanyHistEntity ( @Column(name = "accompany_cnt", nullable = false) var accompanyCnt: Long = 0L, - @Column(name = "view_cnt", nullable = false) - var viewCnt: Long = 0L + @Column(name = "exec_cd", nullable = false) + val execCd : String ) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt index c4e6b18..71bb604 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt @@ -83,7 +83,7 @@ class AccompanyService( if(accompanyEntity != null){ val accompanyDestinationEntity = accompanyDestinationRepository.findByAccompanyId(param) val accompanyDetailEntity = accompanyDetailRepository.findByAccompanyId(param) - val tagList:List? = accompanyTagRepository.findByAccompanyId(param)?.map{AccompanyTagEntity::accompanyTagPk.name} + val tagList:List? = accompanyTagRepository.findByAccompanyId(param)?.map(AccompanyTagEntity::tagNm) return ReadAccompanyDTO.toDto(accompanyEntity, accompanyDestinationEntity, accompanyDetailEntity, tagList) } @@ -91,12 +91,13 @@ class AccompanyService( } fun getList(param : SearchAccompanyDTO) : List { - val accompanyEntity = accompanyRepository.findByAccompanyId(param) + /*val accompanyList = accompanyRepository.findAll(param) if(accompanyEntity != null){ val accompanyDestinationEntity = accompanyDestinationRepository.findByAccompanyId(param) val accompanyDetailEntity = accompanyDetailRepository.findByAccompanyId(param) return ReadAccompanyDTO.toDto(accompanyEntity, accompanyDestinationEntity) - } + }*/ + return ArrayList() } @Transactional diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagEntity.kt index 312f6d6..1da4c1b 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagEntity.kt @@ -1,12 +1,17 @@ package com.travel.withaeng.domain.accompany +import com.travel.withaeng.domain.AccompanyBaseEntity import jakarta.persistence.* @Table(name = "accompany_tag") @Entity class AccompanyTagEntity ( - @EmbeddedId - val accompanyTagPk: AccompanyTagPk, + @Id + @Column(name = "accompany_id", nullable = false) + val accompanyId : Long, -) \ No newline at end of file + @Column(name = "tag_nm", nullable = false) + val tagNm : String + +) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagPk.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagPk.kt deleted file mode 100644 index ee47654..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagPk.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.travel.withaeng.domain.accompany - -import jakarta.persistence.Column -import jakarta.persistence.Embeddable -import java.io.Serializable - -@Embeddable -data class AccompanyTagPk ( - - @Column(name = "accompany_id", nullable = false) - val accompanyId : Long, - - @Column(name = "tag_nm", nullable = false) - val tagNm : String - -) : Serializable \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeDto.kt index cb26ff0..d1a2be3 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeDto.kt @@ -1,6 +1,7 @@ package com.travel.withaeng.domain.accompanylike import com.travel.withaeng.common.cd.AccompanyStatusCd +import com.travel.withaeng.common.cd.ExecCd import com.travel.withaeng.domain.accompany.AccompanyDestinationEntity import com.travel.withaeng.domain.accompany.AccompanyEntity import com.travel.withaeng.domain.accompany.AccompanyHistEntity @@ -37,7 +38,8 @@ class CreateAccompanyLikeDTO( 0, entity.likeId, entity.userId, - entity.accompanyId + entity.accompanyId, + ExecCd.CREATE.execCd ) } @@ -70,7 +72,8 @@ class DeleteAccompanyLikeDTO( 0, entity.likeId, entity.userId, - entity.accompanyId + entity.accompanyId, + ExecCd.DELETE.execCd ) } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistEntity.kt index c16f0d2..a7580fb 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistEntity.kt @@ -19,6 +19,9 @@ class AccompanyLikeHistEntity ( val userId: Long, @Column(name = "accompany_id", nullable = false) - val accompanyId: Long + val accompanyId: Long, + + @Column(name = "exec_cd", nullable = false) + val execCd : String ) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt index 828e959..55b340d 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt @@ -16,7 +16,7 @@ class AccompanyLikeService( ) { @Transactional - fun createAccompanyLike(param : CreateAccompanyLikeDTO) : Long { + fun createAccompanyLike(param : CreateAccompanyLikeDTO) : CreateAccompanyLikeDTO { val accompanyLikeEntity = param.toEntity() accompanyLikeRepository.save(accompanyLikeEntity) @@ -29,12 +29,12 @@ class AccompanyLikeService( it.likeCnt++ } - return accompanyLikeEntity.likeId + return param } //TODO delete 성능이 안나올 경우 boolean 형으로 좋아요 제어 @Transactional - fun deleteAccompanyLike(param : DeleteAccompanyLikeDTO){ + fun deleteAccompanyLike(param : DeleteAccompanyLikeDTO) : DeleteAccompanyLikeDTO{ val accompanyLikeEntity = param.toEntity() accompanyLikeRepository.delete(accompanyLikeEntity) @@ -43,6 +43,7 @@ class AccompanyLikeService( accompanyLikeHistEntity.deletedAt = LocalDateTime.now() accompanyLikeHistRepository.save(accompanyLikeHistEntity) + return param } } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt index d0bd503..08261bd 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt @@ -1,11 +1,17 @@ package com.travel.withaeng.domain.accompanyreply +import com.travel.withaeng.common.cd.ExecCd +import com.travel.withaeng.domain.accompany.AccompanyDestinationEntity +import com.travel.withaeng.domain.accompany.AccompanyDetailEntity +import com.travel.withaeng.domain.accompany.AccompanyEntity import com.travel.withaeng.domain.accompanylike.AccompanyLikeEntity import com.travel.withaeng.domain.accompanylike.AccompanyLikeHistEntity +import jakarta.persistence.Column import jakarta.validation.constraints.NotBlank import lombok.Getter import lombok.Setter import org.jetbrains.annotations.NotNull +import java.time.LocalDate class AccompanyReplyDto { } @@ -20,22 +26,143 @@ class CreateAccompanyReplyDTO( @NotNull val accompanyId: Long, + @NotNull + val parentId : Long, + + @NotNull + val depth : Long, + + @NotBlank(message = "댓글 내용이 존재하지 않습니다.") + var content: String, + ){ - fun toEntity(): AccompanyLikeEntity { - return AccompanyLikeEntity( - 0, - this.userId, - this.accompanyId + fun toEntity(): AccompanyReplyEntity { + return AccompanyReplyEntity( + 0, + this.accompanyId, + this.parentId, + this.depth, + this.userId, + this.content ) } - fun toHistEntity(entity: AccompanyLikeEntity): AccompanyLikeHistEntity { - return AccompanyLikeHistEntity( - 0, - entity.likeId, - entity.userId, - entity.accompanyId + fun toHistEntity(entity: AccompanyReplyEntity): AccompanyReplyHistEntity { + return AccompanyReplyHistEntity( + 0, + entity.replyId, + entity.accompanyId, + entity.parentId, + entity.depth, + entity.userId, + entity.content, + ExecCd.CREATE.execCd ) } -} \ No newline at end of file +} + +@Setter +@Getter +class ModifyAccompanyReplyDTO( + + @NotNull + val replyId : Long, + + @NotNull + val userId: Long, + + @NotNull + val accompanyId: Long, + + @NotNull + val parentId : Long, + + @NotNull + val depth : Long, + + @NotBlank(message = "댓글 내용이 존재하지 않습니다.") + var content: String, + + ){ + fun toEntity(): AccompanyReplyEntity { + return AccompanyReplyEntity( + 0, + this.accompanyId, + this.parentId, + this.depth, + this.userId, + this.content + ) + } + + fun toHistEntity(entity: AccompanyReplyEntity): AccompanyReplyHistEntity { + return AccompanyReplyHistEntity( + 0, + entity.replyId, + entity.accompanyId, + entity.parentId, + entity.depth, + entity.userId, + entity.content, + ExecCd.UPDATE.execCd + ) + } + +} + +@Setter +@Getter +class DeleteAccompanyReplyDTO( + + @NotNull + val replyId : Long, + + @NotNull + val userId: Long, + + @NotNull + val accompanyId: Long + + ){ + + fun toHistEntity(entity: AccompanyReplyEntity): AccompanyReplyHistEntity { + return AccompanyReplyHistEntity( + 0, + entity.replyId, + entity.accompanyId, + entity.parentId, + entity.depth, + entity.userId, + entity.content, + ExecCd.DELETE.execCd + ) + } + +} + +data class ReadAccompanyReplyDTO( + + val replyId : Long, + val userId: Long, + val accompanyId: Long, + val parentId : Long, + val depth : Long, + var content: String, + +){ + companion object { + @JvmStatic + fun toDto(accompanyReplyEntity : AccompanyReplyEntity) : ReadAccompanyReplyDTO { + return ReadAccompanyReplyDTO( + replyId = accompanyReplyEntity.replyId, + userId = accompanyReplyEntity.userId, + accompanyId = accompanyReplyEntity.accompanyId, + parentId = accompanyReplyEntity.parentId, + depth = accompanyReplyEntity.depth, + content = accompanyReplyEntity.content + ) + } + } +} + diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyEntity.kt index ca5977e..39622d9 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyEntity.kt @@ -2,7 +2,9 @@ package com.travel.withaeng.domain.accompanyreply import com.travel.withaeng.domain.AccompanyBaseEntity import jakarta.persistence.* +import org.hibernate.annotations.DynamicUpdate +@DynamicUpdate @Table(name = "accompany_reply") @Entity class AccompanyReplyEntity( @@ -25,6 +27,6 @@ class AccompanyReplyEntity( val userId: Long, @Column(name = "content", nullable = false) - val content: String, + var content: String, ) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHistEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHistEntity.kt new file mode 100644 index 0000000..531d480 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHistEntity.kt @@ -0,0 +1,36 @@ +package com.travel.withaeng.domain.accompanyreply + +import com.travel.withaeng.domain.AccompanyBaseEntity +import jakarta.persistence.* + +@Table(name = "accompany_reply_hist") +@Entity +class AccompanyReplyHistEntity ( + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "hist_id", nullable = false) + val histId: Long, + + @Column(name = "reply_id", nullable = false) + val replyId: Long, + + @Column(name = "accompany_id", nullable = false) + val accompanyId : Long, + + @Column(name = "parent_id", nullable = false) + val parentId : Long, + + @Column(name = "depth", nullable = false) + val depth : Long, + + @Column(name = "user_id", nullable = false) + val userId: Long, + + @Column(name = "content", nullable = false) + val content: String, + + @Column(name = "exec_cd", nullable = false) + val execCd: String, + +) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHistRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHistRepository.kt new file mode 100644 index 0000000..e8cc3c9 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHistRepository.kt @@ -0,0 +1,5 @@ +package com.travel.withaeng.domain.accompanyreply + +import org.springframework.data.jpa.repository.JpaRepository + +interface AccompanyReplyHistRepository : JpaRepository \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt index df50163..107957e 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt @@ -2,4 +2,9 @@ package com.travel.withaeng.domain.accompanyreply import org.springframework.data.jpa.repository.JpaRepository -interface AccompanyReplyRepository : JpaRepository \ No newline at end of file +interface AccompanyReplyRepository : JpaRepository { + fun findByReplyId(replyId : Long) : AccompanyReplyEntity? + + fun findByAccompanyId(accompanyId : Long) : List? + +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt index 22db52c..86b2d57 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt @@ -1,9 +1,100 @@ package com.travel.withaeng.domain.accompanyreply +import com.travel.withaeng.common.exception.InvalidAccessException +import com.travel.withaeng.common.exception.NotExistsException +import com.travel.withaeng.domain.accompany.* +import jakarta.persistence.Column import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @Service @Transactional(readOnly = true) -class AccompanyReplyService { +class AccompanyReplyService ( + + private val accompanyReplyRepository: AccompanyReplyRepository, + private val accompanyReplyHistRepository : AccompanyReplyHistRepository + +) { + + @Transactional + fun createAccompanyReply(param : CreateAccompanyReplyDTO) : ReadAccompanyReplyDTO { + val accompanyReplyEntity = param.toEntity() + accompanyReplyRepository.save(accompanyReplyEntity) + + val accompanyReplyHistEntity = param.toHistEntity(accompanyReplyEntity) + + accompanyReplyHistRepository.save(accompanyReplyHistEntity) + + return getOne(accompanyReplyEntity.replyId) + } + + @Transactional + fun modifyAccompanyReply(param : ModifyAccompanyReplyDTO) : ReadAccompanyReplyDTO { + + val accompanyReplyEntity = accompanyReplyRepository.findByReplyId(param.replyId) + + if(accompanyReplyEntity != null){ + + if(accompanyReplyEntity.userId != param.userId){ + throw InvalidAccessException("등록자와 수정자가 달라 수정 요청을 거부 합니다.") + } + + accompanyReplyEntity.let { + it.content = param.content + } + + val accompanyReplyHistEntity = param.toHistEntity(accompanyReplyEntity) + accompanyReplyHistRepository.save(accompanyReplyHistEntity) + } + + return getOne(param.replyId) + } + + @Transactional + fun deleteAccompanyReply(param : DeleteAccompanyReplyDTO) : ReadAccompanyReplyDTO { + + val accompanyReplyEntity = accompanyReplyRepository.findByReplyId(param.replyId) + + if(accompanyReplyEntity != null){ + + if(accompanyReplyEntity.userId != param.userId){ + throw InvalidAccessException("등록자와 수정자가 달라 삭제 요청을 거부 합니다.") + } + + accompanyReplyRepository.delete(accompanyReplyEntity) + + val accompanyReplyHistEntity = param.toHistEntity(accompanyReplyEntity) + accompanyReplyHistRepository.save(accompanyReplyHistEntity) + } + + return getOne(param.accompanyId) + } + + fun getOne(param : Long) : ReadAccompanyReplyDTO { + + val accompanyReplyEntity = accompanyReplyRepository.findByReplyId(param) + + if(accompanyReplyEntity != null){ + return ReadAccompanyReplyDTO.toDto(accompanyReplyEntity) + } + + throw NotExistsException("존재하지 않는 동행 게시글 댓글 요청 입니다.") + } + + fun getList(param : Long) : List { + + val accompanyReplyList = accompanyReplyRepository.findByAccompanyId(param) + + if(accompanyReplyList != null){ + + val resultList: List = accompanyReplyList.map { + accompanyReply -> ReadAccompanyReplyDTO.toDto(accompanyReply) + } + + return resultList + } + + throw NotExistsException("존재하지 않는 동행 게시글 댓글 요청 입니다.") + } + } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeDto.kt new file mode 100644 index 0000000..1383dc3 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeDto.kt @@ -0,0 +1,77 @@ +package com.travel.withaeng.domain.accompanyreplylike + +import com.travel.withaeng.common.cd.ExecCd +import com.travel.withaeng.domain.accompanylike.AccompanyLikeEntity +import com.travel.withaeng.domain.accompanylike.AccompanyLikeHistEntity +import jakarta.persistence.Column +import lombok.Getter +import lombok.Setter +import org.jetbrains.annotations.NotNull + +class AccompanyReplyLikeDto { +} + +@Setter +@Getter +class CreateAccompanyReplyLikeDTO( + + @NotNull + val replyId: Long, + + @NotNull + val userId: Long, + + ){ + fun toEntity(): AccompanyReplyLikeEntity { + return AccompanyReplyLikeEntity( + 0, + this.replyId, + this.userId + ) + } + + fun toHistEntity(entity: AccompanyReplyLikeEntity): AccompanyReplyLikeHistEntity { + return AccompanyReplyLikeHistEntity( + 0, + entity.replyLikeId, + entity.replyId, + entity.userId, + ExecCd.CREATE.execCd + ) + } + +} + +@Setter +@Getter +class DeleteAccompanyReplyLikeDTO( + + @NotNull + val replyLikeId: Long, + + @NotNull + val replyId: Long, + + @NotNull + val userId: Long + + ){ + fun toEntity(): AccompanyReplyLikeEntity { + return AccompanyReplyLikeEntity( + this.replyLikeId, + this.replyId, + this.userId + ) + } + + fun toHistEntity(entity: AccompanyReplyLikeEntity): AccompanyReplyLikeHistEntity { + return AccompanyReplyLikeHistEntity( + 0, + entity.replyLikeId, + entity.replyId, + entity.userId, + ExecCd.DELETE.execCd + ) + } + +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHistEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHistEntity.kt new file mode 100644 index 0000000..7c769a7 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHistEntity.kt @@ -0,0 +1,28 @@ +package com.travel.withaeng.domain.accompanyreplylike + +import com.travel.withaeng.common.cd.ExecCd +import com.travel.withaeng.domain.AccompanyBaseEntity +import jakarta.persistence.* + +@Table(name = "accompany_reply_like_hist") +@Entity +class AccompanyReplyLikeHistEntity ( + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "hist_id", nullable = false) + val histId: Long, + + @Column(name = "reply_like_id", nullable = false) + val replyLikeId: Long, + + @Column(name = "reply_id", nullable = false) + val replyId: Long, + + @Column(name = "user_id", nullable = false) + val userId: Long, + + @Column(name = "exec_cd", nullable = false) + val execCd : String + +) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHistRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHistRepository.kt new file mode 100644 index 0000000..8e2056e --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHistRepository.kt @@ -0,0 +1,5 @@ +package com.travel.withaeng.domain.accompanyreplylike + +import org.springframework.data.jpa.repository.JpaRepository + +interface AccompanyReplyLikeHistRepository : JpaRepository \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt new file mode 100644 index 0000000..b253ce9 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt @@ -0,0 +1,48 @@ +package com.travel.withaeng.domain.accompanyreplylike + +import com.travel.withaeng.domain.accompany.AccompanyDetailRepository +import com.travel.withaeng.domain.accompanylike.AccompanyLikeHistRepository +import com.travel.withaeng.domain.accompanylike.AccompanyLikeRepository +import com.travel.withaeng.domain.accompanylike.CreateAccompanyLikeDTO +import com.travel.withaeng.domain.accompanylike.DeleteAccompanyLikeDTO +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional +import java.time.LocalDateTime + +@Service +@Transactional(readOnly = true) +class AccompanyReplyLikeService ( + + private val accompanyReplyLikeRepository: AccompanyReplyLikeRepository, + private val accompanyReplyLikeHistRepository : AccompanyReplyLikeHistRepository, + private val accompanyDetailRepository: AccompanyDetailRepository + +) { + + @Transactional + fun createAccompanyReplyLike(param : CreateAccompanyReplyLikeDTO) : CreateAccompanyReplyLikeDTO { + + val accompanyReplyLikeEntity = param.toEntity() + accompanyReplyLikeRepository.save(accompanyReplyLikeEntity) + + val accompanyReplyLikeHistEntity = param.toHistEntity(accompanyReplyLikeEntity) + accompanyReplyLikeHistRepository.save(accompanyReplyLikeHistEntity) + + return param + } + + //TODO delete 성능이 안나올 경우 boolean 형으로 좋아요 제어 + @Transactional + fun deleteAccompanyReplyLike(param : DeleteAccompanyReplyLikeDTO) : DeleteAccompanyReplyLikeDTO{ + + val accompanyReplyLikeEntity = param.toEntity() + accompanyReplyLikeRepository.delete(accompanyReplyLikeEntity) + + val accompanyReplyLikeHistEntity = param.toHistEntity(accompanyReplyLikeEntity) + accompanyReplyLikeHistEntity.deletedAt = LocalDateTime.now() + accompanyReplyLikeHistRepository.save(accompanyReplyLikeHistEntity) + + return param + } + +} \ No newline at end of file diff --git a/withaeng-domain/src/test/kotlin/com/travel/withaeng/config/JasyptConfigTest.kt b/withaeng-domain/src/test/kotlin/com/travel/withaeng/config/JasyptConfigTest.kt index 9d8ed5a..645ef8d 100644 --- a/withaeng-domain/src/test/kotlin/com/travel/withaeng/config/JasyptConfigTest.kt +++ b/withaeng-domain/src/test/kotlin/com/travel/withaeng/config/JasyptConfigTest.kt @@ -15,32 +15,32 @@ import org.springframework.test.context.junit.jupiter.SpringExtension @SpringBootTest @ExtendWith(SpringExtension::class) class JasyptConfigTest { - @Value("\${jasypt.encryptor.password}") - private lateinit var jasyptEncryptorPassword: String + //@Value("\${jasypt.encryptor.password}") + //private lateinit var jasyptEncryptorPassword: String @Autowired private lateinit var configurableEnvironment: ConfigurableEnvironment private lateinit var encryptor: DefaultLazyEncryptor - @BeforeEach + /*@BeforeEach internal fun setUp() { check(jasyptEncryptorPassword.isNotBlank()) { "jasypt.encryptor.password must not be null, empty or blank. " } encryptor = DefaultLazyEncryptor(configurableEnvironment) - } + }*/ - @Test + /*@Test fun testForEncryption() { val source = "test" println("source: $source") println("encrypted: ${encryptor.encrypt(source)}") - } + }*/ - @Test + /*@Test fun testForDecryption() { val source = "test" println("source: $source") println("decrypted: ${encryptor.decrypt(source)}") - } + }*/ } \ No newline at end of file From 3b21748f123520c4a0c91c015352dcfa546d9ab4 Mon Sep 17 00:00:00 2001 From: collenkim Date: Mon, 1 Apr 2024 15:30:22 +0900 Subject: [PATCH 042/174] =?UTF-8?q?=EB=8F=99=ED=96=89=20=EB=93=B1=EB=A1=9D?= =?UTF-8?q?,=20=EB=8B=A8=EA=B1=B4=20=EC=A1=B0=ED=9A=8C,=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20API=20=EA=B0=9C=EB=B0=9C=20=EC=99=84=EB=A3=8C=20Res?= =?UTF-8?q?ponse=20=EC=A0=95=EC=9D=98=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 1 - withaeng-api/build.gradle.kts | 2 ++ .../accompany/controller/AccompanyController.kt | 10 ++++++---- .../withaeng/domain/accompany/AccompanyDto.kt | 14 +++++++++----- .../travel/withaeng/config/JasyptConfigTest.kt | 16 ++++++++-------- 5 files changed, 25 insertions(+), 18 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 4248591..21648f7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -43,7 +43,6 @@ subprojects { testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("com.ninja-squad:springmockk:$springMockkVersion") - runtimeOnly("com.h2database:h2") } diff --git a/withaeng-api/build.gradle.kts b/withaeng-api/build.gradle.kts index e69cc74..0b3fc6d 100644 --- a/withaeng-api/build.gradle.kts +++ b/withaeng-api/build.gradle.kts @@ -15,6 +15,8 @@ dependencies { implementation(project(":withaeng-external")) implementation("org.springframework.boot:spring-boot-starter-web") implementation("org.springframework.boot:spring-boot-starter-security") + implementation("org.springframework.boot:spring-boot-starter-validation") + api("org.springframework.boot:spring-boot-starter-data-jpa") // jwt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompany/controller/AccompanyController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompany/controller/AccompanyController.kt index 0a02fbe..cc7adb3 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompany/controller/AccompanyController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompany/controller/AccompanyController.kt @@ -2,8 +2,10 @@ package com.travel.withaeng.accompany.controller import com.travel.withaeng.common.ApiResponse import com.travel.withaeng.domain.accompany.* +import jakarta.validation.Valid import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity +import org.springframework.validation.annotation.Validated import org.springframework.web.bind.annotation.* @RestController @@ -11,13 +13,13 @@ import org.springframework.web.bind.annotation.* class AccompanyController(private val accompanyService: AccompanyService) { @PostMapping("") - fun create(@RequestBody param : CreateAccompanyDTO) : ResponseEntity> { + fun create(@RequestBody @Valid param : CreateAccompanyDTO) : ResponseEntity> { return ResponseEntity.status(HttpStatus.CREATED).body(ApiResponse(true, accompanyService.createAccompany(param), null)) } - @PutMapping("") - fun modify(@RequestBody param : ModifyAccompanyDTO) : ResponseEntity> { - return ResponseEntity.status(HttpStatus.CREATED).body(ApiResponse(true, accompanyService.modifyAccompany(param), null)) + @PutMapping("/{accompanyId}") + fun modify(@RequestBody @Valid param : ModifyAccompanyDTO) : ResponseEntity> { + return ResponseEntity.status(HttpStatus.OK).body(ApiResponse(true, accompanyService.modifyAccompany(param), null)) } @GetMapping("/{accompanyId}") diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt index bfa0143..6c1953f 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt @@ -1,5 +1,6 @@ package com.travel.withaeng.domain.accompany +import com.fasterxml.jackson.annotation.JsonProperty import com.travel.withaeng.common.cd.AccompanyStatusCd import com.travel.withaeng.common.cd.ExecCd import jakarta.validation.constraints.NotBlank @@ -15,16 +16,19 @@ class AccompanyDto () @Getter class CreateAccompanyDTO( - @NotNull + @field:NotNull + @JsonProperty("userId") val userId: Long, - @NotBlank(message = "제목은 필수 값 입니다.") + @field:NotBlank(message = "제목은 필수 값 입니다.") + @JsonProperty("title") val title: String, - @NotBlank(message = "내용은 필수 값 입니다.") + @field:NotBlank(message = "내용은 필수 값 입니다.") + @JsonProperty("content") val content: String, - @NotBlank(message = "대륙은 필수 값 입니다.") + @field:NotBlank(message = "대륙은 필수 값 입니다.") val continent: String, val country : String? = null, @@ -39,7 +43,7 @@ class CreateAccompanyDTO( val bannerImageUrl: String? = null, - @NotNull + @field:NotNull val accompanyCnt : Long, val tags : List? diff --git a/withaeng-domain/src/test/kotlin/com/travel/withaeng/config/JasyptConfigTest.kt b/withaeng-domain/src/test/kotlin/com/travel/withaeng/config/JasyptConfigTest.kt index 645ef8d..9d8ed5a 100644 --- a/withaeng-domain/src/test/kotlin/com/travel/withaeng/config/JasyptConfigTest.kt +++ b/withaeng-domain/src/test/kotlin/com/travel/withaeng/config/JasyptConfigTest.kt @@ -15,32 +15,32 @@ import org.springframework.test.context.junit.jupiter.SpringExtension @SpringBootTest @ExtendWith(SpringExtension::class) class JasyptConfigTest { - //@Value("\${jasypt.encryptor.password}") - //private lateinit var jasyptEncryptorPassword: String + @Value("\${jasypt.encryptor.password}") + private lateinit var jasyptEncryptorPassword: String @Autowired private lateinit var configurableEnvironment: ConfigurableEnvironment private lateinit var encryptor: DefaultLazyEncryptor - /*@BeforeEach + @BeforeEach internal fun setUp() { check(jasyptEncryptorPassword.isNotBlank()) { "jasypt.encryptor.password must not be null, empty or blank. " } encryptor = DefaultLazyEncryptor(configurableEnvironment) - }*/ + } - /*@Test + @Test fun testForEncryption() { val source = "test" println("source: $source") println("encrypted: ${encryptor.encrypt(source)}") - }*/ + } - /*@Test + @Test fun testForDecryption() { val source = "test" println("source: $source") println("decrypted: ${encryptor.decrypt(source)}") - }*/ + } } \ No newline at end of file From 282aa07ea3eed403b25a07c165e6fe9e1e1694b7 Mon Sep 17 00:00:00 2001 From: collenkim Date: Thu, 4 Apr 2024 11:10:59 +0900 Subject: [PATCH 043/174] =?UTF-8?q?querydsl=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 2 +- withaeng-domain/build.gradle.kts | 4 +++- .../withaeng/domain/accompanyreply/AccompanyReplyDto.kt | 3 ++- .../withaeng/domain/accompanyreply/AccompanyReplyService.kt | 4 +++- .../accompanyreplylike/AccompanyReplyLikeRepository.kt | 5 ++++- .../domain/accompanyreplylike/AccompanyReplyLikeService.kt | 6 ++++-- 6 files changed, 17 insertions(+), 7 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 21648f7..9728a20 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -28,7 +28,7 @@ val springMockkVersion: String by project.extra subprojects { apply(plugin = "org.jetbrains.kotlin.jvm") - //apply(plugin = "org.jetbrains.kotlin.kapt") + apply(plugin = "org.jetbrains.kotlin.kapt") apply(plugin = "org.jetbrains.kotlin.plugin.spring") apply(plugin = "org.jetbrains.kotlin.plugin.jpa") apply(plugin = "org.springframework.boot") diff --git a/withaeng-domain/build.gradle.kts b/withaeng-domain/build.gradle.kts index 5d5a0c3..f90e92b 100644 --- a/withaeng-domain/build.gradle.kts +++ b/withaeng-domain/build.gradle.kts @@ -11,7 +11,9 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-data-jpa") implementation("org.projectlombok:lombok") implementation("org.springframework.boot:spring-boot-starter-validation") - implementation("com.querydsl:querydsl-jpa") + implementation("com.querydsl:querydsl-jpa:5.0.0:jakarta") + kapt("com.querydsl:querydsl-apt:5.0.0:jakarta") + kapt("org.springframework.boot:spring-boot-configuration-processor") runtimeOnly("com.h2database:h2") //runtimeOnly("com.mysql:mysql-connector-j:$mysqlVersion") diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt index 08261bd..d14ae4e 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt @@ -160,7 +160,8 @@ data class ReadAccompanyReplyDTO( accompanyId = accompanyReplyEntity.accompanyId, parentId = accompanyReplyEntity.parentId, depth = accompanyReplyEntity.depth, - content = accompanyReplyEntity.content + content = accompanyReplyEntity.content, + ) } } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt index 86b2d57..a4cf3e1 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt @@ -88,7 +88,9 @@ class AccompanyReplyService ( if(accompanyReplyList != null){ val resultList: List = accompanyReplyList.map { - accompanyReply -> ReadAccompanyReplyDTO.toDto(accompanyReply) + accompanyReply -> + + ReadAccompanyReplyDTO.toDto(accompanyReply) } return resultList diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt index 8a52cdf..8a711c1 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt @@ -2,4 +2,7 @@ package com.travel.withaeng.domain.accompanyreplylike import org.springframework.data.jpa.repository.JpaRepository -interface AccompanyReplyLikeRepository : JpaRepository \ No newline at end of file +interface AccompanyReplyLikeRepository : JpaRepository{ + + fun countByReplyId(replyId : Long) : Long +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt index b253ce9..39faba1 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt @@ -14,8 +14,7 @@ import java.time.LocalDateTime class AccompanyReplyLikeService ( private val accompanyReplyLikeRepository: AccompanyReplyLikeRepository, - private val accompanyReplyLikeHistRepository : AccompanyReplyLikeHistRepository, - private val accompanyDetailRepository: AccompanyDetailRepository + private val accompanyReplyLikeHistRepository : AccompanyReplyLikeHistRepository ) { @@ -45,4 +44,7 @@ class AccompanyReplyLikeService ( return param } + fun getAccompanyReplyLikeCnt(param : Long) : Long { + return accompanyReplyLikeRepository.countByReplyId(param) + } } \ No newline at end of file From c02c39827f547ee91057a8ce825204e1951d6601 Mon Sep 17 00:00:00 2001 From: collenkim Date: Thu, 4 Apr 2024 17:38:52 +0900 Subject: [PATCH 044/174] =?UTF-8?q?querydsl=20config=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../withaeng/config/JpaQueryDslConfig.kt | 19 +++++++++++++++++++ .../accompany/AccompanyRepositoryCustom.kt | 6 ++++++ .../AccompanyRepositoryCustomImpl.kt | 12 ++++++++++++ .../domain/accompany/AccompanyService.kt | 15 ++++++++------- 4 files changed, 45 insertions(+), 7 deletions(-) create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/config/JpaQueryDslConfig.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustom.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/config/JpaQueryDslConfig.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/config/JpaQueryDslConfig.kt new file mode 100644 index 0000000..e5d9b4d --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/config/JpaQueryDslConfig.kt @@ -0,0 +1,19 @@ +package com.travel.withaeng.config + +import com.querydsl.jpa.impl.JPAQueryFactory +import jakarta.persistence.EntityManager +import jakarta.persistence.PersistenceContext +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +@Configuration +class JpaQueryDslConfig { + + @PersistenceContext + lateinit var entityManager : EntityManager + + @Bean + fun jpaQueryFactory() : JPAQueryFactory{ + return JPAQueryFactory(entityManager) + } +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustom.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustom.kt new file mode 100644 index 0000000..a440f70 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustom.kt @@ -0,0 +1,6 @@ +package com.travel.withaeng.domain.accompany + +interface AccompanyRepositoryCustom { + fun getAccompanyList(param : SearchAccompanyDTO) : List? + +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt new file mode 100644 index 0000000..8b2381a --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt @@ -0,0 +1,12 @@ +package com.travel.withaeng.domain.accompany + +import com.querydsl.jpa.impl.JPAQueryFactory +import org.springframework.stereotype.Repository + +@Repository +class AccompanyRepositoryCustomImpl (val jpaQueryFactory: JPAQueryFactory) : AccompanyRepositoryCustom { + + override fun getAccompanyList(param : SearchAccompanyDTO): List? { + + } +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt index 71bb604..c8bea77 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt @@ -11,6 +11,7 @@ class AccompanyService( private val accompanyRepository: AccompanyRepository, private val accompanyHistRepository : AccompanyHistRepository, + private val accompanyRepositoryCustom: AccompanyRepositoryCustom, private val accompanyDestinationRepository : AccompanyDestinationRepository, private val accompanyDetailRepository : AccompanyDetailRepository, private val accompanyTagRepository: AccompanyTagRepository @@ -91,13 +92,13 @@ class AccompanyService( } fun getList(param : SearchAccompanyDTO) : List { - /*val accompanyList = accompanyRepository.findAll(param) - if(accompanyEntity != null){ - val accompanyDestinationEntity = accompanyDestinationRepository.findByAccompanyId(param) - val accompanyDetailEntity = accompanyDetailRepository.findByAccompanyId(param) - return ReadAccompanyDTO.toDto(accompanyEntity, accompanyDestinationEntity) - }*/ - return ArrayList() + + val accompanyList = accompanyRepositoryCustom.getAccompanyList(param) + if(accompanyList != null){ + return accompanyList + } + + throw NotExistsException("존재하지 않는 동행 게시글 조회 요청 입니다.") } @Transactional From 15b07c2b4721ab334d278cdf559002b01e2ef344 Mon Sep 17 00:00:00 2001 From: collenkim Date: Fri, 5 Apr 2024 09:45:42 +0900 Subject: [PATCH 045/174] =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=20=EA=B8=B0=EB=8A=A5=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../travel/withaeng/domain/accompany/AccompanyDto.kt | 2 ++ .../withaeng/domain/accompany/AccompanyRepository.kt | 1 + .../domain/accompany/AccompanyRepositoryCustom.kt | 1 - .../accompany/AccompanyRepositoryCustomImpl.kt | 5 ++--- .../withaeng/domain/accompany/AccompanyService.kt | 12 ++++++++---- 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt index 6c1953f..538cc41 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt @@ -217,4 +217,6 @@ class SearchAccompanyDTO( val endTripDate: LocalDate,//동행 모집 마감일시 + val page : Int, + val pageIndex ) \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt index 6b7b9d9..58c5ada 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt @@ -6,4 +6,5 @@ interface AccompanyRepository : JpaRepository { fun findByAccompanyId(accompanyId : Long) : AccompanyEntity? + fun getAccompanyList() : List? } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustom.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustom.kt index a440f70..cfdc105 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustom.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustom.kt @@ -1,6 +1,5 @@ package com.travel.withaeng.domain.accompany interface AccompanyRepositoryCustom { - fun getAccompanyList(param : SearchAccompanyDTO) : List? } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt index 8b2381a..7458511 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt @@ -1,12 +1,11 @@ package com.travel.withaeng.domain.accompany +import com.querydsl.core.types.Projections import com.querydsl.jpa.impl.JPAQueryFactory import org.springframework.stereotype.Repository +import java.time.LocalDate @Repository class AccompanyRepositoryCustomImpl (val jpaQueryFactory: JPAQueryFactory) : AccompanyRepositoryCustom { - override fun getAccompanyList(param : SearchAccompanyDTO): List? { - - } } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt index c8bea77..1806369 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt @@ -93,12 +93,16 @@ class AccompanyService( fun getList(param : SearchAccompanyDTO) : List { - val accompanyList = accompanyRepositoryCustom.getAccompanyList(param) - if(accompanyList != null){ - return accompanyList + var accompanyList; + + if(isDefaultSearch(param)){ + accompanyList = accompanyRepositoryCustom.getAccompanyList(param) + return + }else{ + accompanyList = accompanyDetailRepository.getAccompanyList(param) + return } - throw NotExistsException("존재하지 않는 동행 게시글 조회 요청 입니다.") } @Transactional From 2f03a4a15cfdf3b3f38b4a926d3a5fd9771bf23a Mon Sep 17 00:00:00 2001 From: collenkim Date: Fri, 5 Apr 2024 08:40:49 -0700 Subject: [PATCH 046/174] =?UTF-8?q?1=EC=B0=A8=EC=95=88=20=EA=B0=9C?= =?UTF-8?q?=EB=B0=9C=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../withaeng/domain/accompany/AccompanyDto.kt | 81 ++++++++----------- .../domain/accompany/AccompanyRepository.kt | 7 +- .../accompany/AccompanyRepositoryCustom.kt | 5 ++ .../AccompanyRepositoryCustomImpl.kt | 60 ++++++++++++++ .../domain/accompany/AccompanyService.kt | 32 +++----- .../accompanyreply/AccompanyReplyDto.kt | 40 +++++---- .../AccompanyReplyRepository.kt | 5 +- .../AccompanyReplyRepositoryCustom.kt | 9 +++ .../AccompanyReplyRepositoryCustomImpl.kt | 27 +++++++ .../accompanyreply/AccompanyReplyService.kt | 38 +++++---- .../AccompanyReplyLikeDto.kt | 8 +- .../AccompanyReplyLikeRepository.kt | 6 +- .../AccompanyReplyLikeRepositoryCustom.kt | 9 +++ .../AccompanyReplyLikeRepositoryCustomImpl.kt | 22 +++++ .../AccompanyReplyLikeService.kt | 6 +- 15 files changed, 246 insertions(+), 109 deletions(-) create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustom.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustomImpl.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepositoryCustom.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepositoryCustomImpl.kt diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt index 538cc41..6a36f0b 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt @@ -8,6 +8,8 @@ import lombok.Getter import lombok.NoArgsConstructor import lombok.Setter import org.jetbrains.annotations.NotNull +import org.springframework.data.domain.Page +import org.springframework.data.domain.Pageable import java.time.LocalDate class AccompanyDto () @@ -164,59 +166,42 @@ class ModifyAccompanyDTO( } } -data class ReadAccompanyDTO( +data class GetDTO ( - val accompanyId : Long, - val userId: Long, - val title: String, - val content: String, - val continent: String, - val country : String? = null, - val city : String? = null, - val startTripDate: LocalDate, - val endTripDate: LocalDate, - val bannerImageUrl: String? = null, - val accompanyCnt : Long, - val viewCnt : Long, - val likeCnt : Long, - val tags : List? = null + var accompanyId : Long, + var userId: Long, + var title: String, + var content: String, + var continent: String, + var country : String? = null, + var city : String? = null, + var startTripDate: LocalDate, + var endTripDate: LocalDate, + var bannerImageUrl: String? = null, + var accompanyCnt : Long, + var viewCnt : Long, + var likeCnt : Long, + var tags : List? = null -){ - companion object { - @JvmStatic - fun toDto(accompanyEntity : AccompanyEntity, accompanyDestinationEntity: AccompanyDestinationEntity, accompanyDetailEntity: AccompanyDetailEntity, tagList : List?) : ReadAccompanyDTO { - return ReadAccompanyDTO( - accompanyId = accompanyEntity.accompanyId, - userId = accompanyEntity.userId, - title = accompanyEntity.title, - content = accompanyEntity.content, - continent = accompanyDestinationEntity.continent, - country = accompanyDestinationEntity.country, - city = accompanyDestinationEntity.city, - startTripDate = accompanyEntity.startTripDate, - endTripDate = accompanyEntity.endTripDate, - bannerImageUrl = accompanyEntity.bannerImageUrl, - accompanyCnt = accompanyEntity.accompanyCnt, - viewCnt = accompanyDetailEntity.viewCnt, - likeCnt = accompanyDetailEntity.likeCnt, - tags = tagList - ) - } - } -} +) -@Setter -@Getter -class SearchAccompanyDTO( +data class SearchAccompanyDTO( - val viewCntOrder: Boolean,//조회수 높은 순서 + var viewCntOrder: Boolean,//조회수 높은 순서 - val likeCntOrder: Boolean,//좋아요 높은 순서 + var likeCntOrder: Boolean,//좋아요 높은 순서 - val startTripDate: LocalDate,//동행 모집 시작일시 + var startTripDate: LocalDate,//동행 모집 시작일시 - val endTripDate: LocalDate,//동행 모집 마감일시 + var endTripDate: LocalDate,//동행 모집 마감일시 + + var pageIndex : Long, + + var pageSize : Long + +){ + fun getCurrentPage() : Long{ + return pageIndex * pageSize + } - val page : Int, - val pageIndex -) \ No newline at end of file +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt index 58c5ada..6119829 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt @@ -1,10 +1,13 @@ package com.travel.withaeng.domain.accompany +import org.springframework.data.domain.Page +import org.springframework.data.domain.Pageable +import org.springframework.data.domain.Sort import org.springframework.data.jpa.repository.JpaRepository +import java.time.LocalDate -interface AccompanyRepository : JpaRepository { +interface AccompanyRepository : JpaRepository, AccompanyRepositoryCustom { fun findByAccompanyId(accompanyId : Long) : AccompanyEntity? - fun getAccompanyList() : List? } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustom.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustom.kt index cfdc105..ffff7b8 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustom.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustom.kt @@ -1,5 +1,10 @@ package com.travel.withaeng.domain.accompany +import org.springframework.data.querydsl.QuerydslPredicateExecutor + interface AccompanyRepositoryCustom { + fun getAccompany(accompanyId : Long) : GetDTO? + + fun getAccompanyList(param : SearchAccompanyDTO) : List } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt index 7458511..9e05c6c 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt @@ -1,11 +1,71 @@ package com.travel.withaeng.domain.accompany +import com.querydsl.core.types.OrderSpecifier import com.querydsl.core.types.Projections +import com.querydsl.core.types.dsl.BooleanExpression import com.querydsl.jpa.impl.JPAQueryFactory +import org.springframework.data.domain.Sort +import org.springframework.data.domain.Sort.Order import org.springframework.stereotype.Repository import java.time.LocalDate @Repository class AccompanyRepositoryCustomImpl (val jpaQueryFactory: JPAQueryFactory) : AccompanyRepositoryCustom { + override fun getAccompany(accompanyId : Long) : GetDTO? { + return jpaQueryFactory + .select(Projections.constructor(GetDTO::class.java, + QAccompanyEntity.accompanyEntity.accompanyId, + QAccompanyEntity.accompanyEntity.userId, + QAccompanyEntity.accompanyEntity.title, + QAccompanyEntity.accompanyEntity.content, + QAccompanyDestinationEntity.accompanyDestinationEntity.continent, + QAccompanyDestinationEntity.accompanyDestinationEntity.country, + QAccompanyDestinationEntity.accompanyDestinationEntity.city, + QAccompanyEntity.accompanyEntity.startTripDate, + QAccompanyEntity.accompanyEntity.endTripDate, + QAccompanyEntity.accompanyEntity.bannerImageUrl, + QAccompanyEntity.accompanyEntity.accompanyCnt, + QAccompanyDetailEntity.accompanyDetailEntity.viewCnt, + QAccompanyDetailEntity.accompanyDetailEntity.likeCnt, + )) + .from(QAccompanyEntity.accompanyEntity) + .innerJoin(QAccompanyDestinationEntity.accompanyDestinationEntity) + .on(QAccompanyDestinationEntity.accompanyDestinationEntity.accompanyId.eq(QAccompanyEntity.accompanyEntity.accompanyId)) + .innerJoin(QAccompanyDetailEntity.accompanyDetailEntity) + .on(QAccompanyDetailEntity.accompanyDetailEntity.accompanyId.eq(QAccompanyEntity.accompanyEntity.accompanyId)) + .where(QAccompanyEntity.accompanyEntity.accompanyId.eq(accompanyId)) + .fetchOne() + } + + override fun getAccompanyList(param : SearchAccompanyDTO) : List{ + + return jpaQueryFactory + .select(Projections.constructor(GetDTO::class.java, + QAccompanyEntity.accompanyEntity.accompanyId, + QAccompanyEntity.accompanyEntity.userId, + QAccompanyEntity.accompanyEntity.title, + QAccompanyEntity.accompanyEntity.content, + QAccompanyDestinationEntity.accompanyDestinationEntity.continent, + QAccompanyDestinationEntity.accompanyDestinationEntity.country, + QAccompanyDestinationEntity.accompanyDestinationEntity.city, + QAccompanyEntity.accompanyEntity.startTripDate, + QAccompanyEntity.accompanyEntity.endTripDate, + QAccompanyEntity.accompanyEntity.bannerImageUrl, + QAccompanyEntity.accompanyEntity.accompanyCnt, + QAccompanyDetailEntity.accompanyDetailEntity.viewCnt, + QAccompanyDetailEntity.accompanyDetailEntity.likeCnt, + )) + .from(QAccompanyEntity.accompanyEntity) + .innerJoin(QAccompanyDestinationEntity.accompanyDestinationEntity) + .on(QAccompanyDestinationEntity.accompanyDestinationEntity.accompanyId.eq(QAccompanyEntity.accompanyEntity.accompanyId)) + .innerJoin(QAccompanyDetailEntity.accompanyDetailEntity) + .on(QAccompanyDetailEntity.accompanyDetailEntity.accompanyId.eq(QAccompanyEntity.accompanyEntity.accompanyId)) + .where(QAccompanyEntity.accompanyEntity.startTripDate.after(param.startTripDate), QAccompanyEntity.accompanyEntity.endTripDate.before(param.endTripDate)) + .orderBy(QAccompanyEntity.accompanyEntity.updatedAt.desc()) + .offset(param.getCurrentPage()) + .limit(param.pageSize) + .fetch() + } + } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt index 1806369..d978d8d 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt @@ -2,6 +2,7 @@ package com.travel.withaeng.domain.accompany import com.travel.withaeng.common.exception.InvalidAccessException import com.travel.withaeng.common.exception.NotExistsException +import com.travel.withaeng.domain.accompany.QAccompanyEntity.accompanyEntity import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -11,7 +12,6 @@ class AccompanyService( private val accompanyRepository: AccompanyRepository, private val accompanyHistRepository : AccompanyHistRepository, - private val accompanyRepositoryCustom: AccompanyRepositoryCustom, private val accompanyDestinationRepository : AccompanyDestinationRepository, private val accompanyDetailRepository : AccompanyDetailRepository, private val accompanyTagRepository: AccompanyTagRepository @@ -19,7 +19,7 @@ class AccompanyService( ) { @Transactional - fun createAccompany(param : CreateAccompanyDTO) : ReadAccompanyDTO { + fun createAccompany(param : CreateAccompanyDTO) : GetDTO { val accompanyEntity = param.toEntity() accompanyRepository.save(accompanyEntity) @@ -40,7 +40,7 @@ class AccompanyService( } @Transactional - fun modifyAccompany(param : ModifyAccompanyDTO) : ReadAccompanyDTO { + fun modifyAccompany(param : ModifyAccompanyDTO) : GetDTO { val accompanyEntity = accompanyRepository.findByAccompanyId(param.accompanyId) @@ -78,31 +78,21 @@ class AccompanyService( return getOne(param.accompanyId) } - fun getOne(param : Long) : ReadAccompanyDTO { - val accompanyEntity = accompanyRepository.findByAccompanyId(param) + fun getOne(param : Long) : GetDTO { - if(accompanyEntity != null){ - val accompanyDestinationEntity = accompanyDestinationRepository.findByAccompanyId(param) - val accompanyDetailEntity = accompanyDetailRepository.findByAccompanyId(param) + val getAccompany = accompanyRepository.getAccompany(param) + + if(getAccompany != null){ val tagList:List? = accompanyTagRepository.findByAccompanyId(param)?.map(AccompanyTagEntity::tagNm) - return ReadAccompanyDTO.toDto(accompanyEntity, accompanyDestinationEntity, accompanyDetailEntity, tagList) + getAccompany.tags = tagList + return getAccompany } throw NotExistsException("존재하지 않는 동행 게시글 조회 요청 입니다.") } - fun getList(param : SearchAccompanyDTO) : List { - - var accompanyList; - - if(isDefaultSearch(param)){ - accompanyList = accompanyRepositoryCustom.getAccompanyList(param) - return - }else{ - accompanyList = accompanyDetailRepository.getAccompanyList(param) - return - } - + fun getList(param : SearchAccompanyDTO) : List { + return accompanyRepository.getAccompanyList(param) } @Transactional diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt index d14ae4e..aee7213 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt @@ -141,29 +141,35 @@ class DeleteAccompanyReplyDTO( } -data class ReadAccompanyReplyDTO( +data class GetReplyDTO( - val replyId : Long, - val userId: Long, - val accompanyId: Long, - val parentId : Long, - val depth : Long, + var replyId : Long, + var userId: Long, + var accompanyId: Long, + var parentId : Long, + var depth : Long, var content: String, - + var likeCnt : Long ){ + + fun addLikeCnt(cnt: Long){ + likeCnt = cnt + } + companion object { @JvmStatic - fun toDto(accompanyReplyEntity : AccompanyReplyEntity) : ReadAccompanyReplyDTO { - return ReadAccompanyReplyDTO( - replyId = accompanyReplyEntity.replyId, - userId = accompanyReplyEntity.userId, - accompanyId = accompanyReplyEntity.accompanyId, - parentId = accompanyReplyEntity.parentId, - depth = accompanyReplyEntity.depth, - content = accompanyReplyEntity.content, - - ) + fun toDto(accompanyReplyEntity : AccompanyReplyEntity, likeCnt : Long) : GetReplyDTO { + return GetReplyDTO( + replyId = accompanyReplyEntity.replyId, + userId = accompanyReplyEntity.userId, + accompanyId = accompanyReplyEntity.accompanyId, + parentId = accompanyReplyEntity.parentId, + depth = accompanyReplyEntity.depth, + content = accompanyReplyEntity.content, + likeCnt = likeCnt + ) } } + } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt index 107957e..929d188 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt @@ -1,10 +1,9 @@ package com.travel.withaeng.domain.accompanyreply +import org.springframework.data.domain.Sort import org.springframework.data.jpa.repository.JpaRepository -interface AccompanyReplyRepository : JpaRepository { +interface AccompanyReplyRepository : JpaRepository, AccompanyReplyRepositoryCustom { fun findByReplyId(replyId : Long) : AccompanyReplyEntity? - fun findByAccompanyId(accompanyId : Long) : List? - } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustom.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustom.kt new file mode 100644 index 0000000..1d609c8 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustom.kt @@ -0,0 +1,9 @@ +package com.travel.withaeng.domain.accompanyreply + +import org.springframework.data.domain.Sort + +interface AccompanyReplyRepositoryCustom { + + fun getAccompanyReplyList(accompanyId : Long) : List? + +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustomImpl.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustomImpl.kt new file mode 100644 index 0000000..ef83b5f --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustomImpl.kt @@ -0,0 +1,27 @@ +package com.travel.withaeng.domain.accompanyreply + +import com.querydsl.core.types.Projections +import com.querydsl.jpa.impl.JPAQueryFactory +import com.travel.withaeng.domain.accompany.* +import org.springframework.stereotype.Repository + +@Repository +class AccompanyReplyRepositoryCustomImpl (val jpaQueryFactory: JPAQueryFactory) : AccompanyReplyRepositoryCustom { + override fun getAccompanyReplyList(accompanyId: Long): List { + return jpaQueryFactory + .select( + Projections.constructor( + GetReplyDTO::class.java, + QAccompanyReplyEntity.accompanyReplyEntity.replyId, + QAccompanyReplyEntity.accompanyReplyEntity.userId, + QAccompanyReplyEntity.accompanyReplyEntity.accompanyId, + QAccompanyReplyEntity.accompanyReplyEntity.parentId, + QAccompanyReplyEntity.accompanyReplyEntity.depth, + QAccompanyReplyEntity.accompanyReplyEntity.content, + )) + .from(QAccompanyReplyEntity.accompanyReplyEntity) + .where(QAccompanyReplyEntity.accompanyReplyEntity.accompanyId.eq(accompanyId)) + .orderBy(QAccompanyReplyEntity.accompanyReplyEntity.parentId.desc(), QAccompanyReplyEntity.accompanyReplyEntity.depth.desc()) + .fetch() + } +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt index a4cf3e1..a6d2a30 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt @@ -3,7 +3,10 @@ package com.travel.withaeng.domain.accompanyreply import com.travel.withaeng.common.exception.InvalidAccessException import com.travel.withaeng.common.exception.NotExistsException import com.travel.withaeng.domain.accompany.* +import com.travel.withaeng.domain.accompanyreplylike.AccompanyReplyLikeRepository +import com.travel.withaeng.domain.accompanyreplylike.AccompanyReplyLikeService import jakarta.persistence.Column +import org.springframework.data.domain.Sort import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -12,12 +15,13 @@ import org.springframework.transaction.annotation.Transactional class AccompanyReplyService ( private val accompanyReplyRepository: AccompanyReplyRepository, - private val accompanyReplyHistRepository : AccompanyReplyHistRepository + private val accompanyReplyHistRepository : AccompanyReplyHistRepository, + private val accompanyReplyLikeService: AccompanyReplyLikeService ) { @Transactional - fun createAccompanyReply(param : CreateAccompanyReplyDTO) : ReadAccompanyReplyDTO { + fun createAccompanyReply(param : CreateAccompanyReplyDTO) : GetReplyDTO { val accompanyReplyEntity = param.toEntity() accompanyReplyRepository.save(accompanyReplyEntity) @@ -29,7 +33,7 @@ class AccompanyReplyService ( } @Transactional - fun modifyAccompanyReply(param : ModifyAccompanyReplyDTO) : ReadAccompanyReplyDTO { + fun modifyAccompanyReply(param : ModifyAccompanyReplyDTO) : GetReplyDTO { val accompanyReplyEntity = accompanyReplyRepository.findByReplyId(param.replyId) @@ -51,7 +55,7 @@ class AccompanyReplyService ( } @Transactional - fun deleteAccompanyReply(param : DeleteAccompanyReplyDTO) : ReadAccompanyReplyDTO { + fun deleteAccompanyReply(param : DeleteAccompanyReplyDTO) : DeleteAccompanyReplyDTO { val accompanyReplyEntity = accompanyReplyRepository.findByReplyId(param.replyId) @@ -67,36 +71,42 @@ class AccompanyReplyService ( accompanyReplyHistRepository.save(accompanyReplyHistEntity) } - return getOne(param.accompanyId) + return param } - fun getOne(param : Long) : ReadAccompanyReplyDTO { + fun getOne(param : Long) : GetReplyDTO { val accompanyReplyEntity = accompanyReplyRepository.findByReplyId(param) + val accompanyReplyLikeCnt = accompanyReplyLikeService.getAccompanyReplyLikeCnt(param) if(accompanyReplyEntity != null){ - return ReadAccompanyReplyDTO.toDto(accompanyReplyEntity) + return GetReplyDTO.toDto(accompanyReplyEntity, accompanyReplyLikeCnt) } throw NotExistsException("존재하지 않는 동행 게시글 댓글 요청 입니다.") } - fun getList(param : Long) : List { + fun getList(param : Long) : List? { - val accompanyReplyList = accompanyReplyRepository.findByAccompanyId(param) + val accompanyReplyList = accompanyReplyRepository.getAccompanyReplyList(param) if(accompanyReplyList != null){ - val resultList: List = accompanyReplyList.map { - accompanyReply -> + val replyIdList : List = accompanyReplyList.map {accompanyReplyEntity -> accompanyReplyEntity.replyId}.toList() + val accompanyReplyLikeList = accompanyReplyLikeService.getAccompanyReplyLikeList(replyIdList) - ReadAccompanyReplyDTO.toDto(accompanyReply) + for(reply in accompanyReplyList){ + for(like in accompanyReplyLikeList){ + if(reply.replyId == like.replyId){ + reply.likeCnt = like.likeCnt + } + } } - return resultList + return accompanyReplyList } - throw NotExistsException("존재하지 않는 동행 게시글 댓글 요청 입니다.") + return null } } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeDto.kt index 1383dc3..508b3ca 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeDto.kt @@ -74,4 +74,10 @@ class DeleteAccompanyReplyLikeDTO( ) } -} \ No newline at end of file +} + +data class GetReplyLikeDTO( + + var replyId : Long, + var likeCnt : Long +) \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt index 8a711c1..0850ce5 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt @@ -1,8 +1,10 @@ package com.travel.withaeng.domain.accompanyreplylike import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.data.jpa.repository.Query -interface AccompanyReplyLikeRepository : JpaRepository{ +interface AccompanyReplyLikeRepository : JpaRepository, AccompanyReplyLikeRepositoryCustom{ + + fun countByReplyId(replyId: Long) : Long - fun countByReplyId(replyId : Long) : Long } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepositoryCustom.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepositoryCustom.kt new file mode 100644 index 0000000..9371eb2 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepositoryCustom.kt @@ -0,0 +1,9 @@ +package com.travel.withaeng.domain.accompanyreplylike + +import com.travel.withaeng.domain.accompanyreply.GetReplyDTO + +interface AccompanyReplyLikeRepositoryCustom { + + fun getAccompanyReplyLikeList(replyIds : List) : List + +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepositoryCustomImpl.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepositoryCustomImpl.kt new file mode 100644 index 0000000..7513e8e --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepositoryCustomImpl.kt @@ -0,0 +1,22 @@ +package com.travel.withaeng.domain.accompanyreplylike + +import com.querydsl.core.types.Projections +import com.querydsl.jpa.impl.JPAQueryFactory +import org.springframework.stereotype.Repository + +@Repository +class AccompanyReplyLikeRepositoryCustomImpl(val jpaQueryFactory: JPAQueryFactory) : AccompanyReplyLikeRepositoryCustom { + override fun getAccompanyReplyLikeList(replyIds: List): List { + return jpaQueryFactory + .select( + Projections.constructor( + GetReplyLikeDTO::class.java, + QAccompanyReplyLikeEntity.accompanyReplyLikeEntity.replyId, + QAccompanyReplyLikeEntity.accompanyReplyLikeEntity.replyId.count() + )) + .from(QAccompanyReplyLikeEntity.accompanyReplyLikeEntity) + .where(QAccompanyReplyLikeEntity.accompanyReplyLikeEntity.replyId.`in`(replyIds)) + .groupBy(QAccompanyReplyLikeEntity.accompanyReplyLikeEntity.replyId) + .fetch() + } +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt index 39faba1..0cdcb9b 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt @@ -44,7 +44,11 @@ class AccompanyReplyLikeService ( return param } - fun getAccompanyReplyLikeCnt(param : Long) : Long { + fun getAccompanyReplyLikeCnt(param: Long) : Long{ return accompanyReplyLikeRepository.countByReplyId(param) } + + fun getAccompanyReplyLikeList(param : List) : List { + return accompanyReplyLikeRepository.getAccompanyReplyLikeList(param) + } } \ No newline at end of file From 43bbdf1644153cdde7f59dcdf297210cfa0702b4 Mon Sep 17 00:00:00 2001 From: collenkim Date: Fri, 5 Apr 2024 18:04:15 -0700 Subject: [PATCH 047/174] =?UTF-8?q?1=EC=B0=A8=EC=95=88=20=EA=B0=9C?= =?UTF-8?q?=EB=B0=9C=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/accompany/AccompanyDetailEntity.kt | 5 +++- .../withaeng/domain/accompany/AccompanyDto.kt | 28 ++++++++++++------- .../domain/accompany/AccompanyService.kt | 5 ++++ .../domain/accompany/AccompanyTagEntity.kt | 4 +++ 4 files changed, 31 insertions(+), 11 deletions(-) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDetailEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDetailEntity.kt index f72298c..123554b 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDetailEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDetailEntity.kt @@ -17,7 +17,10 @@ class AccompanyDetailEntity ( var viewCnt: Long = 0L, @Column(name = "like_cnt", nullable = false) - var likeCnt: Long = 0L + var likeCnt: Long = 0L, + + @Column(name = "open_kakao_url", nullable = false) + var openKakaoUrl : String ) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt index 6a36f0b..af32c8d 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt @@ -18,19 +18,19 @@ class AccompanyDto () @Getter class CreateAccompanyDTO( - @field:NotNull + @NotNull @JsonProperty("userId") val userId: Long, - @field:NotBlank(message = "제목은 필수 값 입니다.") + @NotBlank(message = "제목은 필수 값 입니다.") @JsonProperty("title") val title: String, - @field:NotBlank(message = "내용은 필수 값 입니다.") + @NotBlank(message = "내용은 필수 값 입니다.") @JsonProperty("content") val content: String, - @field:NotBlank(message = "대륙은 필수 값 입니다.") + @NotBlank(message = "대륙은 필수 값 입니다.") val continent: String, val country : String? = null, @@ -48,7 +48,10 @@ class CreateAccompanyDTO( @field:NotNull val accompanyCnt : Long, - val tags : List? + val tags : List?, + + @NotBlank(message = "카카오 오픈 채팅 URL은 필수 값 입니다.") + val openKakaoUrl : String ){ fun toEntity(): AccompanyEntity { @@ -95,7 +98,8 @@ class CreateAccompanyDTO( return AccompanyDetailEntity( accompanyId, 0, - 0 + 0, + this.openKakaoUrl ) } @@ -107,7 +111,7 @@ class CreateAccompanyDTO( val tagList = mutableListOf() for(tagNm in tags){ - tagList.add(AccompanyTagEntity(accompanyId, tagNm)) + tagList.add(AccompanyTagEntity(0, accompanyId, tagNm)) } return tagList @@ -148,7 +152,10 @@ class ModifyAccompanyDTO( @NotNull val accompanyCnt : Long, - val tags : List? + val tags : List?, + + @NotBlank(message = "카카오 오픈 채팅 URL은 필수 값 입니다.") + val openKakaoUrl : String ){ fun toTagEntity(accompanyId : Long) : List? { @@ -159,7 +166,7 @@ class ModifyAccompanyDTO( val tagList = mutableListOf() for(tagNm in tags){ - tagList.add(AccompanyTagEntity(accompanyId, tagNm)) + tagList.add(AccompanyTagEntity(0, accompanyId, tagNm)) } return tagList @@ -181,7 +188,8 @@ data class GetDTO ( var accompanyCnt : Long, var viewCnt : Long, var likeCnt : Long, - var tags : List? = null + var tags : List? = null, + var openKakaoUrl : String ) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt index d978d8d..41e3e8f 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt @@ -51,6 +51,7 @@ class AccompanyService( } val accompanyDestinationEntity = accompanyDestinationRepository.findByAccompanyId(param.accompanyId) + val accompanyDetailEntity = accompanyDetailRepository.findByAccompanyId(param.accompanyId) val accompanyTagEntityList = param.toTagEntity(accompanyEntity.accompanyId) accompanyEntity.let { @@ -62,6 +63,10 @@ class AccompanyService( it.accompanyCnt = param.accompanyCnt } + accompanyDetailEntity.let { + it.openKakaoUrl = param.openKakaoUrl + } + accompanyDestinationEntity.let { it.continent = param.continent it.country = param.country diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagEntity.kt index 1da4c1b..a59cbd5 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagEntity.kt @@ -8,6 +8,10 @@ import jakarta.persistence.* class AccompanyTagEntity ( @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "tag_id", nullable = false) + val tagId : Long, + @Column(name = "accompany_id", nullable = false) val accompanyId : Long, From fce671d1d40e7d8e2768195d7de22cf2854126bd Mon Sep 17 00:00:00 2001 From: collenkim Date: Fri, 5 Apr 2024 19:44:18 -0700 Subject: [PATCH 048/174] =?UTF-8?q?querydsl=20=EC=83=9D=EC=84=B1=EC=9E=90?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../withaeng/domain/accompany/AccompanyDto.kt | 7 ++++++- .../accompany/AccompanyRepositoryCustomImpl.kt | 18 +++++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt index af32c8d..b3d8c1a 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt @@ -191,7 +191,12 @@ data class GetDTO ( var tags : List? = null, var openKakaoUrl : String -) +){ + constructor(accompanyId : Long, userId : Long, title: String, content : String, + continent : String,country : String, city : String, startTripDate : LocalDate, endTripDate : LocalDate, + bannerImageUrl: String?, accompanyCnt: Long, viewCnt: Long, likeCnt: Long, openKakaoUrl: String) : + this(accompanyId, userId, title, content, continent, country, city, startTripDate, endTripDate, bannerImageUrl, accompanyCnt, viewCnt, likeCnt, null, openKakaoUrl) +} data class SearchAccompanyDTO( diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt index 9e05c6c..bb6dc6d 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt @@ -3,6 +3,7 @@ package com.travel.withaeng.domain.accompany import com.querydsl.core.types.OrderSpecifier import com.querydsl.core.types.Projections import com.querydsl.core.types.dsl.BooleanExpression +import com.querydsl.core.types.dsl.Expressions import com.querydsl.jpa.impl.JPAQueryFactory import org.springframework.data.domain.Sort import org.springframework.data.domain.Sort.Order @@ -28,6 +29,7 @@ class AccompanyRepositoryCustomImpl (val jpaQueryFactory: JPAQueryFactory) : Acc QAccompanyEntity.accompanyEntity.accompanyCnt, QAccompanyDetailEntity.accompanyDetailEntity.viewCnt, QAccompanyDetailEntity.accompanyDetailEntity.likeCnt, + QAccompanyDetailEntity.accompanyDetailEntity.openKakaoUrl )) .from(QAccompanyEntity.accompanyEntity) .innerJoin(QAccompanyDestinationEntity.accompanyDestinationEntity) @@ -55,17 +57,31 @@ class AccompanyRepositoryCustomImpl (val jpaQueryFactory: JPAQueryFactory) : Acc QAccompanyEntity.accompanyEntity.accompanyCnt, QAccompanyDetailEntity.accompanyDetailEntity.viewCnt, QAccompanyDetailEntity.accompanyDetailEntity.likeCnt, + QAccompanyDetailEntity.accompanyDetailEntity.openKakaoUrl )) .from(QAccompanyEntity.accompanyEntity) .innerJoin(QAccompanyDestinationEntity.accompanyDestinationEntity) .on(QAccompanyDestinationEntity.accompanyDestinationEntity.accompanyId.eq(QAccompanyEntity.accompanyEntity.accompanyId)) .innerJoin(QAccompanyDetailEntity.accompanyDetailEntity) .on(QAccompanyDetailEntity.accompanyDetailEntity.accompanyId.eq(QAccompanyEntity.accompanyEntity.accompanyId)) - .where(QAccompanyEntity.accompanyEntity.startTripDate.after(param.startTripDate), QAccompanyEntity.accompanyEntity.endTripDate.before(param.endTripDate)) + .where(listWhere(param, QAccompanyEntity.accompanyEntity)) .orderBy(QAccompanyEntity.accompanyEntity.updatedAt.desc()) .offset(param.getCurrentPage()) .limit(param.pageSize) .fetch() } + fun listWhere(param : SearchAccompanyDTO, accompanyEntity : QAccompanyEntity, ) : BooleanExpression { + + var predicate: BooleanExpression = Expressions.asBoolean(true).isTrue + + if (param.startTripDate != null && param.endTripDate != null) { + println(param.startTripDate) + predicate = predicate + .and(accompanyEntity.startTripDate.between(param.startTripDate, param.endTripDate) + .or(accompanyEntity.endTripDate.between(param.startTripDate, param.endTripDate))) + } + + return predicate + } } \ No newline at end of file From 944c89cfa9031af1097efd04dd106cf3e58ed163 Mon Sep 17 00:00:00 2001 From: collenkim Date: Fri, 5 Apr 2024 19:46:51 -0700 Subject: [PATCH 049/174] =?UTF-8?q?querydsl=20=EC=83=9D=EC=84=B1=EC=9E=90?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../withaeng/domain/accompanyreply/AccompanyReplyDto.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt index aee7213..30791c4 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt @@ -152,6 +152,10 @@ data class GetReplyDTO( var likeCnt : Long ){ + constructor(replyId : Long, userId : Long, accompanyId: Long, parentId : Long, + depth : Long,content : String) : + this(replyId, userId, accompanyId, parentId, depth, content, 0) + fun addLikeCnt(cnt: Long){ likeCnt = cnt } From f8d14ec00c892561b64103334af1f60f37b75ed7 Mon Sep 17 00:00:00 2001 From: collenkim Date: Tue, 9 Apr 2024 17:25:53 +0900 Subject: [PATCH 050/174] =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=20=EA=B8=B0=EB=8A=A5=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../withaeng/domain/accompany/AccompanyDto.kt | 21 +++++++++++++++-- .../AccompanyRepositoryCustomImpl.kt | 23 +++++++++++++------ .../domain/accompany/AccompanyService.kt | 4 +++- 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt index b3d8c1a..c0c533c 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt @@ -158,6 +158,22 @@ class ModifyAccompanyDTO( val openKakaoUrl : String ){ + fun toHistEntity(entity: AccompanyEntity): AccompanyHistEntity { + return AccompanyHistEntity( + 0, + entity.accompanyId, + entity.userId, + entity.title, + entity.content, + entity.accompanyStatusCd, + entity.startTripDate, + entity.endTripDate, + entity.bannerImageUrl, + entity.accompanyCnt, + ExecCd.UPDATE.execCd + ) + } + fun toTagEntity(accompanyId : Long) : List? { if(tags == null){ @@ -193,7 +209,8 @@ data class GetDTO ( ){ constructor(accompanyId : Long, userId : Long, title: String, content : String, - continent : String,country : String, city : String, startTripDate : LocalDate, endTripDate : LocalDate, + continent : String, country : String?, city : String?, + startTripDate : LocalDate, endTripDate : LocalDate, bannerImageUrl: String?, accompanyCnt: Long, viewCnt: Long, likeCnt: Long, openKakaoUrl: String) : this(accompanyId, userId, title, content, continent, country, city, startTripDate, endTripDate, bannerImageUrl, accompanyCnt, viewCnt, likeCnt, null, openKakaoUrl) } @@ -214,7 +231,7 @@ data class SearchAccompanyDTO( ){ fun getCurrentPage() : Long{ - return pageIndex * pageSize + return pageIndex -1 * pageSize } } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt index bb6dc6d..fe1f126 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt @@ -1,14 +1,14 @@ package com.travel.withaeng.domain.accompany +import com.querydsl.core.types.Order import com.querydsl.core.types.OrderSpecifier import com.querydsl.core.types.Projections import com.querydsl.core.types.dsl.BooleanExpression import com.querydsl.core.types.dsl.Expressions +import com.querydsl.jpa.impl.JPAQuery import com.querydsl.jpa.impl.JPAQueryFactory -import org.springframework.data.domain.Sort -import org.springframework.data.domain.Sort.Order +import jakarta.persistence.Entity import org.springframework.stereotype.Repository -import java.time.LocalDate @Repository class AccompanyRepositoryCustomImpl (val jpaQueryFactory: JPAQueryFactory) : AccompanyRepositoryCustom { @@ -64,9 +64,9 @@ class AccompanyRepositoryCustomImpl (val jpaQueryFactory: JPAQueryFactory) : Acc .on(QAccompanyDestinationEntity.accompanyDestinationEntity.accompanyId.eq(QAccompanyEntity.accompanyEntity.accompanyId)) .innerJoin(QAccompanyDetailEntity.accompanyDetailEntity) .on(QAccompanyDetailEntity.accompanyDetailEntity.accompanyId.eq(QAccompanyEntity.accompanyEntity.accompanyId)) - .where(listWhere(param, QAccompanyEntity.accompanyEntity)) - .orderBy(QAccompanyEntity.accompanyEntity.updatedAt.desc()) - .offset(param.getCurrentPage()) + //.where(listWhere(param, QAccompanyEntity.accompanyEntity)) + .orderBy(listOrder(param)) + .offset(1) .limit(param.pageSize) .fetch() } @@ -76,7 +76,6 @@ class AccompanyRepositoryCustomImpl (val jpaQueryFactory: JPAQueryFactory) : Acc var predicate: BooleanExpression = Expressions.asBoolean(true).isTrue if (param.startTripDate != null && param.endTripDate != null) { - println(param.startTripDate) predicate = predicate .and(accompanyEntity.startTripDate.between(param.startTripDate, param.endTripDate) .or(accompanyEntity.endTripDate.between(param.startTripDate, param.endTripDate))) @@ -84,4 +83,14 @@ class AccompanyRepositoryCustomImpl (val jpaQueryFactory: JPAQueryFactory) : Acc return predicate } + + fun listOrder(param : SearchAccompanyDTO) : OrderSpecifier<*> { + if (param.likeCntOrder) { + return OrderSpecifier(Order.DESC, QAccompanyDetailEntity.accompanyDetailEntity.likeCnt) + } else if(param.viewCntOrder) { + return OrderSpecifier(Order.DESC, QAccompanyDetailEntity.accompanyDetailEntity.viewCnt) + }else { + return OrderSpecifier(Order.DESC, QAccompanyEntity.accompanyEntity.updatedAt) + } + } } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt index 41e3e8f..f625afe 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt @@ -36,7 +36,7 @@ class AccompanyService( accompanyTagRepository.saveAll(accompanyTagEntityList) } - return getOne(accompanyHistEntity.accompanyId) + return getOne(accompanyEntity.accompanyId) } @Transactional @@ -50,6 +50,7 @@ class AccompanyService( throw InvalidAccessException("등록자와 수정자가 달라 수정 요청을 거부 합니다.") } + val accompanyHistEntity = param.toHistEntity(accompanyEntity) val accompanyDestinationEntity = accompanyDestinationRepository.findByAccompanyId(param.accompanyId) val accompanyDetailEntity = accompanyDetailRepository.findByAccompanyId(param.accompanyId) val accompanyTagEntityList = param.toTagEntity(accompanyEntity.accompanyId) @@ -73,6 +74,7 @@ class AccompanyService( it.city = param.city } + accompanyHistRepository.save(accompanyHistEntity) accompanyTagRepository.deleteByAccompanyId(accompanyEntity.accompanyId) if(accompanyTagEntityList != null){ accompanyTagRepository.saveAll(accompanyTagEntityList) From 52699e6ca405bcbbf342a1e379143b2fdb8b1ec3 Mon Sep 17 00:00:00 2001 From: collenkim Date: Thu, 11 Apr 2024 16:55:12 +0900 Subject: [PATCH 051/174] =?UTF-8?q?=EB=8F=99=ED=96=89=20=EA=B2=8C=EC=8B=9C?= =?UTF-8?q?=EA=B8=80=20=EC=A2=8B=EC=95=84=EC=9A=94=20=EA=B8=B0=EB=8A=A5=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 --- .../accompanyLike/controller/AccompanyLikeController.kt | 5 +++-- .../withaeng/domain/accompanylike/AccompanyLikeService.kt | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyLike/controller/AccompanyLikeController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyLike/controller/AccompanyLikeController.kt index 1f91452..e833e60 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyLike/controller/AccompanyLikeController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyLike/controller/AccompanyLikeController.kt @@ -5,6 +5,7 @@ import com.travel.withaeng.domain.accompany.CreateAccompanyDTO import com.travel.withaeng.domain.accompanylike.AccompanyLikeService import com.travel.withaeng.domain.accompanylike.CreateAccompanyLikeDTO import com.travel.withaeng.domain.accompanylike.DeleteAccompanyLikeDTO +import jakarta.validation.Valid import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.* @@ -14,13 +15,13 @@ import org.springframework.web.bind.annotation.* class AccompanyLikeController(private val accompanyLikeService: AccompanyLikeService) { @PostMapping("") - fun create(@RequestBody param : CreateAccompanyLikeDTO) : ResponseEntity> { + fun create(@RequestBody @Valid param : CreateAccompanyLikeDTO) : ResponseEntity> { return ResponseEntity.status(HttpStatus.CREATED).body( ApiResponse(true, accompanyLikeService.createAccompanyLike(param), null)) } @DeleteMapping("") - fun delete(@RequestBody param : DeleteAccompanyLikeDTO) : ResponseEntity{ + fun delete(@RequestBody @Valid param : DeleteAccompanyLikeDTO) : ResponseEntity{ return ResponseEntity.status(HttpStatus.OK).body(ApiResponse(true,accompanyLikeService.deleteAccompanyLike(param), null)) } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt index 55b340d..0a2d18f 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt @@ -43,6 +43,11 @@ class AccompanyLikeService( accompanyLikeHistEntity.deletedAt = LocalDateTime.now() accompanyLikeHistRepository.save(accompanyLikeHistEntity) + val accompanyDetailEntity = accompanyDetailRepository.findByAccompanyId(param.accompanyId) + accompanyDetailEntity.let { + it.likeCnt-- + } + return param } From af49df749f7dd46f84c5a9ce75dc9eafa348e4fe Mon Sep 17 00:00:00 2001 From: collenkim Date: Fri, 12 Apr 2024 14:54:50 +0900 Subject: [PATCH 052/174] =?UTF-8?q?localdate=20->=20localdatetime=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../withaeng/domain/accompany/AccompanyDto.kt | 16 +++++------ .../domain/accompany/AccompanyEntity.kt | 7 ++--- .../domain/accompany/AccompanyHistEntity.kt | 27 ++++++++++--------- .../AccompanyRepositoryCustomImpl.kt | 22 +++++++++------ .../domain/accompany/AccompanyService.kt | 6 +++-- 5 files changed, 43 insertions(+), 35 deletions(-) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt index c0c533c..7079874 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt @@ -11,6 +11,8 @@ import org.jetbrains.annotations.NotNull import org.springframework.data.domain.Page import org.springframework.data.domain.Pageable import java.time.LocalDate +import java.time.LocalDateTime +import java.time.LocalTime class AccompanyDto () @@ -37,10 +39,8 @@ class CreateAccompanyDTO( val city : String? = null, - @NotBlank val startTripDate: LocalDate, - @NotBlank val endTripDate: LocalDate, val bannerImageUrl: String? = null, @@ -61,8 +61,8 @@ class CreateAccompanyDTO( this.title, this.content, AccompanyStatusCd.ING.statusCd, - this.startTripDate, - this.endTripDate, + this.startTripDate.atTime(LocalTime.MIN), + this.endTripDate.atTime(LocalTime.MAX), this.bannerImageUrl, this.accompanyCnt ) @@ -141,10 +141,8 @@ class ModifyAccompanyDTO( val city : String? = null, - @NotBlank val startTripDate: LocalDate, - @NotBlank val endTripDate: LocalDate, val bannerImageUrl: String? = null, @@ -198,8 +196,8 @@ data class GetDTO ( var continent: String, var country : String? = null, var city : String? = null, - var startTripDate: LocalDate, - var endTripDate: LocalDate, + var startTripDate: LocalDateTime, + var endTripDate: LocalDateTime, var bannerImageUrl: String? = null, var accompanyCnt : Long, var viewCnt : Long, @@ -210,7 +208,7 @@ data class GetDTO ( ){ constructor(accompanyId : Long, userId : Long, title: String, content : String, continent : String, country : String?, city : String?, - startTripDate : LocalDate, endTripDate : LocalDate, + startTripDate : LocalDateTime, endTripDate : LocalDateTime, bannerImageUrl: String?, accompanyCnt: Long, viewCnt: Long, likeCnt: Long, openKakaoUrl: String) : this(accompanyId, userId, title, content, continent, country, city, startTripDate, endTripDate, bannerImageUrl, accompanyCnt, viewCnt, likeCnt, null, openKakaoUrl) } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyEntity.kt index 410e384..51ffede 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyEntity.kt @@ -4,6 +4,7 @@ import com.travel.withaeng.domain.AccompanyBaseEntity import jakarta.persistence.* import org.hibernate.annotations.DynamicUpdate import java.time.LocalDate +import java.time.LocalDateTime @DynamicUpdate @Table(name = "accompany") @@ -29,10 +30,10 @@ class AccompanyEntity( var accompanyStatusCd : String, @Column(name = "start_trip_date", nullable = false) - var startTripDate: LocalDate, + var startTripDate: LocalDateTime, @Column(name = "end_trip_date", nullable = false) - var endTripDate: LocalDate, + var endTripDate: LocalDateTime, @Column(name = "banner_image_url") var bannerImageUrl: String?, @@ -40,4 +41,4 @@ class AccompanyEntity( @Column(name = "accompany_cnt", nullable = false) var accompanyCnt: Long = 0L, -) : AccompanyBaseEntity() \ No newline at end of file + ) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt index 418ef10..cd8ff90 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt @@ -3,45 +3,46 @@ package com.travel.withaeng.domain.accompany import com.travel.withaeng.domain.AccompanyBaseEntity import jakarta.persistence.* import java.time.LocalDate +import java.time.LocalDateTime @Table(name = "accompany_hist") @Entity class AccompanyHistEntity ( - @Id + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "hist_id", nullable = false) val histId: Long, - @Column(name = "accompany_id", nullable = false) + @Column(name = "accompany_id", nullable = false) val accompanyId: Long, - @Column(name = "user_id", nullable = false) + @Column(name = "user_id", nullable = false) val userId: Long, - @Column(name = "title", nullable = false) + @Column(name = "title", nullable = false) var title: String, - @Lob + @Lob @Column(name = "content", nullable = false) var content: String, - @Column(name = "accompany_status_cd", nullable = false) + @Column(name = "accompany_status_cd", nullable = false) var accompanyStatusCd : String, - @Column(name = "start_trip_date", nullable = false) - var startTripDate: LocalDate, + @Column(name = "start_trip_date", nullable = false) + var startTripDate: LocalDateTime, - @Column(name = "end_trip_date", nullable = false) - var endTripDate: LocalDate, + @Column(name = "end_trip_date", nullable = false) + var endTripDate: LocalDateTime, - @Column(name = "banner_image_url") + @Column(name = "banner_image_url") var bannerImageUrl: String?, - @Column(name = "accompany_cnt", nullable = false) + @Column(name = "accompany_cnt", nullable = false) var accompanyCnt: Long = 0L, - @Column(name = "exec_cd", nullable = false) + @Column(name = "exec_cd", nullable = false) val execCd : String ) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt index fe1f126..2eee20c 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt @@ -9,6 +9,7 @@ import com.querydsl.jpa.impl.JPAQuery import com.querydsl.jpa.impl.JPAQueryFactory import jakarta.persistence.Entity import org.springframework.stereotype.Repository +import java.time.LocalTime @Repository class AccompanyRepositoryCustomImpl (val jpaQueryFactory: JPAQueryFactory) : AccompanyRepositoryCustom { @@ -64,22 +65,27 @@ class AccompanyRepositoryCustomImpl (val jpaQueryFactory: JPAQueryFactory) : Acc .on(QAccompanyDestinationEntity.accompanyDestinationEntity.accompanyId.eq(QAccompanyEntity.accompanyEntity.accompanyId)) .innerJoin(QAccompanyDetailEntity.accompanyDetailEntity) .on(QAccompanyDetailEntity.accompanyDetailEntity.accompanyId.eq(QAccompanyEntity.accompanyEntity.accompanyId)) - //.where(listWhere(param, QAccompanyEntity.accompanyEntity)) + .where(listWhere(param, QAccompanyEntity.accompanyEntity)) .orderBy(listOrder(param)) - .offset(1) + .offset(param.pageIndex) .limit(param.pageSize) .fetch() } - fun listWhere(param : SearchAccompanyDTO, accompanyEntity : QAccompanyEntity, ) : BooleanExpression { + fun listWhere(param : SearchAccompanyDTO, accompanyEntity : QAccompanyEntity) : BooleanExpression { var predicate: BooleanExpression = Expressions.asBoolean(true).isTrue + val searchStartDate = param.startTripDate.atTime(LocalTime.MIN) + val searchEndDate = param.endTripDate.atTime(LocalTime.MAX) - if (param.startTripDate != null && param.endTripDate != null) { - predicate = predicate - .and(accompanyEntity.startTripDate.between(param.startTripDate, param.endTripDate) - .or(accompanyEntity.endTripDate.between(param.startTripDate, param.endTripDate))) - } + predicate = predicate + .and( + accompanyEntity.startTripDate.between(searchStartDate, searchEndDate) + .or( + accompanyEntity.endTripDate.between(searchStartDate, searchEndDate) + ) + .or(Expressions.allOf(accompanyEntity.startTripDate.before(searchStartDate), accompanyEntity.endTripDate.after(searchEndDate))) + ) return predicate } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt index f625afe..00ed1b7 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt @@ -5,6 +5,8 @@ import com.travel.withaeng.common.exception.NotExistsException import com.travel.withaeng.domain.accompany.QAccompanyEntity.accompanyEntity import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional +import java.time.LocalDateTime +import java.time.LocalTime @Service @Transactional(readOnly = true) @@ -58,8 +60,8 @@ class AccompanyService( accompanyEntity.let { it.title = param.title it.content = param.content - it.startTripDate = param.startTripDate - it.endTripDate = param.endTripDate + it.startTripDate = param.startTripDate.atTime(LocalTime.MIN) + it.endTripDate = param.endTripDate.atTime(LocalTime.MAX) it.bannerImageUrl = param.bannerImageUrl it.accompanyCnt = param.accompanyCnt } From 303fd42683c6c52015f5096c2d6d8f042c29bb4a Mon Sep 17 00:00:00 2001 From: collenkim Date: Fri, 12 Apr 2024 15:23:56 +0900 Subject: [PATCH 053/174] =?UTF-8?q?=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EB=8C=93?= =?UTF-8?q?=EA=B8=80=20API=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/AccompanyReplyController.kt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReply/controller/AccompanyReplyController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReply/controller/AccompanyReplyController.kt index 02d1e06..6af3be7 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReply/controller/AccompanyReplyController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReply/controller/AccompanyReplyController.kt @@ -9,6 +9,7 @@ import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.DeleteMapping import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PathVariable import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.PutMapping import org.springframework.web.bind.annotation.RequestBody @@ -16,7 +17,7 @@ import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController @RestController -@RequestMapping("/api/v1/accompany{accompanyId}/reply") +@RequestMapping("/api/v1/accompany/{accompanyId}/reply") class AccompanyReplyController(private val accompanyReplyService: AccompanyReplyService){ @PostMapping("") @@ -24,18 +25,18 @@ class AccompanyReplyController(private val accompanyReplyService: AccompanyReply return ResponseEntity.status(HttpStatus.CREATED).body(ApiResponse(true, accompanyReplyService.createAccompanyReply(param), null)) } - @PutMapping("") + @PutMapping("/{replyId}") fun create(@RequestBody param : ModifyAccompanyReplyDTO) : ResponseEntity> { return ResponseEntity.status(HttpStatus.OK).body(ApiResponse(true, accompanyReplyService.modifyAccompanyReply(param), null)) } - @DeleteMapping("") + @DeleteMapping("/{replyId}") fun create(@RequestBody param : DeleteAccompanyReplyDTO) : ResponseEntity> { return ResponseEntity.status(HttpStatus.OK).body(ApiResponse(true, accompanyReplyService.deleteAccompanyReply(param), null)) } @GetMapping("/getList") - fun create(@RequestBody param : Long) : ResponseEntity> { + fun create(@PathVariable(name= "accompanyId") param : Long) : ResponseEntity> { return ResponseEntity.status(HttpStatus.OK).body(ApiResponse(true, accompanyReplyService.getList(param), null)) } From 8ca1371fa8b5279aecdc3eff35aa2861cce5ee52 Mon Sep 17 00:00:00 2001 From: collenkim Date: Fri, 12 Apr 2024 07:05:01 -0700 Subject: [PATCH 054/174] =?UTF-8?q?=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EB=8C=93?= =?UTF-8?q?=EA=B8=80=20=EC=A2=8B=EC=95=84=EC=9A=94=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B0=9C=EB=B0=9C=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../accompanyReplyLike/AccompanyReplyLikeController.kt | 2 +- .../accompanyreplylike/AccompanyReplyLikeRepository.kt | 1 + .../domain/accompanyreplylike/AccompanyReplyLikeService.kt | 6 ++++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReplyLike/AccompanyReplyLikeController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReplyLike/AccompanyReplyLikeController.kt index 1ebf4c8..ff64ce4 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReplyLike/AccompanyReplyLikeController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReplyLike/AccompanyReplyLikeController.kt @@ -12,7 +12,7 @@ import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.* @RestController -@RequestMapping("/api/v1/accompany{accompanyId}/reply/{replyId}/like") +@RequestMapping("/api/v1/accompany/{accompanyId}/reply/{replyId}/like") class AccompanyReplyLikeController(private val accompanyReplyLikeService: AccompanyReplyLikeService) { @PostMapping("") diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt index 0850ce5..86c7239 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt @@ -7,4 +7,5 @@ interface AccompanyReplyLikeRepository : JpaRepository Date: Fri, 12 Apr 2024 07:06:34 -0700 Subject: [PATCH 055/174] =?UTF-8?q?=EC=A3=BC=EC=84=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../withaeng/domain/accompanyreply/AccompanyReplyService.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt index a6d2a30..f640199 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt @@ -86,6 +86,7 @@ class AccompanyReplyService ( throw NotExistsException("존재하지 않는 동행 게시글 댓글 요청 입니다.") } + //TODO 댓글당 좋아요 누른 userId 목록을 추가로 조회하여 리턴은 추후 처리 fun getList(param : Long) : List? { val accompanyReplyList = accompanyReplyRepository.getAccompanyReplyList(param) From fe164adb51bf6f2774b398467bee544918538fad Mon Sep 17 00:00:00 2001 From: collenkim Date: Fri, 12 Apr 2024 07:51:21 -0700 Subject: [PATCH 056/174] =?UTF-8?q?paging=20=EC=B2=98=EB=A6=AC=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../withaeng/domain/accompany/AccompanyDto.kt | 2 +- .../AccompanyRepositoryCustomImpl.kt | 30 ++++++++----------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt index 7079874..d5ec7e9 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt @@ -229,7 +229,7 @@ data class SearchAccompanyDTO( ){ fun getCurrentPage() : Long{ - return pageIndex -1 * pageSize + return (this.pageIndex -1) * this.pageSize } } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt index 2eee20c..c731abd 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt @@ -1,14 +1,15 @@ package com.travel.withaeng.domain.accompany +import com.querydsl.core.BooleanBuilder import com.querydsl.core.types.Order import com.querydsl.core.types.OrderSpecifier import com.querydsl.core.types.Projections import com.querydsl.core.types.dsl.BooleanExpression +import com.querydsl.core.types.dsl.DateTimeExpression import com.querydsl.core.types.dsl.Expressions -import com.querydsl.jpa.impl.JPAQuery import com.querydsl.jpa.impl.JPAQueryFactory -import jakarta.persistence.Entity import org.springframework.stereotype.Repository +import java.time.LocalDateTime import java.time.LocalTime @Repository @@ -42,7 +43,7 @@ class AccompanyRepositoryCustomImpl (val jpaQueryFactory: JPAQueryFactory) : Acc } override fun getAccompanyList(param : SearchAccompanyDTO) : List{ - + println("currentPage:" + param.getCurrentPage()); return jpaQueryFactory .select(Projections.constructor(GetDTO::class.java, QAccompanyEntity.accompanyEntity.accompanyId, @@ -67,27 +68,22 @@ class AccompanyRepositoryCustomImpl (val jpaQueryFactory: JPAQueryFactory) : Acc .on(QAccompanyDetailEntity.accompanyDetailEntity.accompanyId.eq(QAccompanyEntity.accompanyEntity.accompanyId)) .where(listWhere(param, QAccompanyEntity.accompanyEntity)) .orderBy(listOrder(param)) - .offset(param.pageIndex) + .offset(param.getCurrentPage()) .limit(param.pageSize) .fetch() } - fun listWhere(param : SearchAccompanyDTO, accompanyEntity : QAccompanyEntity) : BooleanExpression { + fun listWhere(param : SearchAccompanyDTO, accompanyEntity : QAccompanyEntity) : BooleanBuilder { + + val builder = BooleanBuilder() - var predicate: BooleanExpression = Expressions.asBoolean(true).isTrue - val searchStartDate = param.startTripDate.atTime(LocalTime.MIN) - val searchEndDate = param.endTripDate.atTime(LocalTime.MAX) + val startDate = param.startTripDate.atStartOfDay() + val endDate = param.endTripDate.atTime(LocalTime.MAX) - predicate = predicate - .and( - accompanyEntity.startTripDate.between(searchStartDate, searchEndDate) - .or( - accompanyEntity.endTripDate.between(searchStartDate, searchEndDate) - ) - .or(Expressions.allOf(accompanyEntity.startTripDate.before(searchStartDate), accompanyEntity.endTripDate.after(searchEndDate))) - ) + builder.and(accompanyEntity.startTripDate.after(startDate)) + builder.and(accompanyEntity.endTripDate.before(endDate)) - return predicate + return builder } fun listOrder(param : SearchAccompanyDTO) : OrderSpecifier<*> { From f30ba7bf02b919f1dbf1439c1dc4cb2a3b8e3ead Mon Sep 17 00:00:00 2001 From: collenkim Date: Wed, 17 Apr 2024 13:55:10 +0900 Subject: [PATCH 057/174] =?UTF-8?q?=EB=8C=93=EA=B8=80=20=EC=A0=95=EB=A0=AC?= =?UTF-8?q?=20=EA=B8=B0=EB=8A=A5=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/accompanylike/AccompanyLikeDto.kt | 6 ----- .../accompanyreply/AccompanyReplyDto.kt | 17 +++++++++++-- .../accompanyreply/AccompanyReplyEntity.kt | 3 +++ .../AccompanyReplyHistEntity.kt | 3 +++ .../AccompanyReplyRepositoryCustomImpl.kt | 1 + .../accompanyreply/AccompanyReplyService.kt | 24 +++++++++++++++---- 6 files changed, 41 insertions(+), 13 deletions(-) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeDto.kt index d1a2be3..cc53b50 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeDto.kt @@ -1,15 +1,9 @@ package com.travel.withaeng.domain.accompanylike -import com.travel.withaeng.common.cd.AccompanyStatusCd import com.travel.withaeng.common.cd.ExecCd -import com.travel.withaeng.domain.accompany.AccompanyDestinationEntity -import com.travel.withaeng.domain.accompany.AccompanyEntity -import com.travel.withaeng.domain.accompany.AccompanyHistEntity -import jakarta.validation.constraints.NotBlank import lombok.Getter import lombok.Setter import org.jetbrains.annotations.NotNull -import java.time.LocalDate class AccompanyLikeDto { } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt index 30791c4..3290743 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt @@ -32,6 +32,9 @@ class CreateAccompanyReplyDTO( @NotNull val depth : Long, + @NotNull + val replyOrder : Long, + @NotBlank(message = "댓글 내용이 존재하지 않습니다.") var content: String, @@ -42,6 +45,7 @@ class CreateAccompanyReplyDTO( this.accompanyId, this.parentId, this.depth, + this.replyOrder, this.userId, this.content ) @@ -54,6 +58,7 @@ class CreateAccompanyReplyDTO( entity.accompanyId, entity.parentId, entity.depth, + entity.replyOrder, entity.userId, entity.content, ExecCd.CREATE.execCd @@ -81,6 +86,9 @@ class ModifyAccompanyReplyDTO( @NotNull val depth : Long, + @NotNull + val replyOrder : Long, + @NotBlank(message = "댓글 내용이 존재하지 않습니다.") var content: String, @@ -91,6 +99,7 @@ class ModifyAccompanyReplyDTO( this.accompanyId, this.parentId, this.depth, + this.replyOrder, this.userId, this.content ) @@ -103,6 +112,7 @@ class ModifyAccompanyReplyDTO( entity.accompanyId, entity.parentId, entity.depth, + entity.replyOrder, entity.userId, entity.content, ExecCd.UPDATE.execCd @@ -133,6 +143,7 @@ class DeleteAccompanyReplyDTO( entity.accompanyId, entity.parentId, entity.depth, + entity.replyOrder, entity.userId, entity.content, ExecCd.DELETE.execCd @@ -148,13 +159,14 @@ data class GetReplyDTO( var accompanyId: Long, var parentId : Long, var depth : Long, + var replyOrder : Long, var content: String, var likeCnt : Long ){ constructor(replyId : Long, userId : Long, accompanyId: Long, parentId : Long, - depth : Long,content : String) : - this(replyId, userId, accompanyId, parentId, depth, content, 0) + depth : Long, replyOrder : Long, content : String) : + this(replyId, userId, accompanyId, parentId, depth, replyOrder, content, 0) fun addLikeCnt(cnt: Long){ likeCnt = cnt @@ -169,6 +181,7 @@ data class GetReplyDTO( accompanyId = accompanyReplyEntity.accompanyId, parentId = accompanyReplyEntity.parentId, depth = accompanyReplyEntity.depth, + replyOrder = accompanyReplyEntity.replyOrder, content = accompanyReplyEntity.content, likeCnt = likeCnt ) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyEntity.kt index 39622d9..ff47a3a 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyEntity.kt @@ -23,6 +23,9 @@ class AccompanyReplyEntity( @Column(name = "depth", nullable = false) val depth : Long, + @Column(name = "reply_order", nullable = false) + val replyOrder : Long, + @Column(name = "user_id", nullable = false) val userId: Long, diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHistEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHistEntity.kt index 531d480..8cb5ed7 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHistEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHistEntity.kt @@ -24,6 +24,9 @@ class AccompanyReplyHistEntity ( @Column(name = "depth", nullable = false) val depth : Long, + @Column(name = "reply_order", nullable = false) + val replyOrder : Long, + @Column(name = "user_id", nullable = false) val userId: Long, diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustomImpl.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustomImpl.kt index ef83b5f..3fc296d 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustomImpl.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustomImpl.kt @@ -17,6 +17,7 @@ class AccompanyReplyRepositoryCustomImpl (val jpaQueryFactory: JPAQueryFactory) QAccompanyReplyEntity.accompanyReplyEntity.accompanyId, QAccompanyReplyEntity.accompanyReplyEntity.parentId, QAccompanyReplyEntity.accompanyReplyEntity.depth, + QAccompanyReplyEntity.accompanyReplyEntity.replyOrder, QAccompanyReplyEntity.accompanyReplyEntity.content, )) .from(QAccompanyReplyEntity.accompanyReplyEntity) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt index f640199..23007dd 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt @@ -2,11 +2,8 @@ package com.travel.withaeng.domain.accompanyreply import com.travel.withaeng.common.exception.InvalidAccessException import com.travel.withaeng.common.exception.NotExistsException -import com.travel.withaeng.domain.accompany.* -import com.travel.withaeng.domain.accompanyreplylike.AccompanyReplyLikeRepository +import com.travel.withaeng.domain.accompany.AccompanyTagEntity import com.travel.withaeng.domain.accompanyreplylike.AccompanyReplyLikeService -import jakarta.persistence.Column -import org.springframework.data.domain.Sort import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -104,7 +101,24 @@ class AccompanyReplyService ( } } - return accompanyReplyList + val parentList = accompanyReplyList.stream().filter{ + e-> e.parentId.equals(0L) + }.toList() + + val sortList = accompanyReplyList.sortedWith(compareBy({it.parentId},{it.depth}, {it.replyOrder})).toList() + val resultList = mutableListOf() + + parentList.stream().forEach{ + e-> + resultList.add(e) + sortList.forEach{a-> + if(e.replyId.equals(a.parentId)){ + resultList.add(a) + } + } + } + + return resultList } return null From 7836f655fb5a11185c8d138200884eca9c51880b Mon Sep 17 00:00:00 2001 From: collenkim Date: Sun, 5 May 2024 19:42:11 -0700 Subject: [PATCH 058/174] =?UTF-8?q?=EB=8F=99=ED=96=89=20=EB=AA=A9=EC=A0=81?= =?UTF-8?q?=EC=A7=80=20=ED=95=98=EB=93=9C=20=EC=BD=94=EB=94=A9=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../destination/DestinationController.kt | 12 +- .../com/travel/withaeng/common/cd/CityCd.kt | 179 +++++++++++++++++- .../travel/withaeng/common/cd/CountryCd.kt | 76 ++++++++ .../domain/destination/DestinationDto.kt | 52 ++++- .../domain/destination/DestinationService.kt | 41 ++++ 5 files changed, 351 insertions(+), 9 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/destination/DestinationController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/destination/DestinationController.kt index c0b60a2..341fedd 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/destination/DestinationController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/destination/DestinationController.kt @@ -1,5 +1,8 @@ package com.travel.withaeng.destination +import com.travel.withaeng.common.ApiResponse +import com.travel.withaeng.domain.destination.DestinationService +import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RequestMapping @@ -7,10 +10,11 @@ import org.springframework.web.bind.annotation.RestController @RestController @RequestMapping("/api/v1/destination") -class DestinationController { +class DestinationController(private val destinationService: DestinationService) { - /*@GetMapping("/getList") - fun getList() : ResponseEntity<>{ - }*/ + @GetMapping("/getList") + fun getList() : ResponseEntity>{ + return ResponseEntity.status(HttpStatus.OK).body(ApiResponse(true, destinationService.getDestinationList(), null)) + } } \ No newline at end of file diff --git a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CityCd.kt b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CityCd.kt index a0fb212..742cda6 100644 --- a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CityCd.kt +++ b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CityCd.kt @@ -1,4 +1,181 @@ package com.travel.withaeng.common.cd -enum class CityCd { +enum class CityCd ( + + val countryCd: String, + val cityCd : String, + val cityNm : String + +){ + + SEOUL(CountryCd.KOREA.countryCd, "SEOUL", "서울"), + BUSAN(CountryCd.KOREA.countryCd, "BUSAN", "부산"), + INCHEON(CountryCd.KOREA.countryCd, "INCHEON", "인천"), + DAEGU(CountryCd.KOREA.countryCd, "DAEGU", "대구"), + GWANGJU(CountryCd.KOREA.countryCd, "GWANGJU", "광주"), + DAEJEON(CountryCd.KOREA.countryCd, "DAEJEON", "대전"), + ULSAN(CountryCd.KOREA.countryCd, "ULSAN", "울산"), + SUWON(CountryCd.KOREA.countryCd, "SUWON", "수원"), + CHANGWON(CountryCd.KOREA.countryCd, "CHANGWON", "창원"), + JEJU(CountryCd.KOREA.countryCd, "JEJU", "제주"), + + // Japan + TOKYO(CountryCd.JAPAN.countryCd, "TOKYO", "도쿄"), + OSAKA(CountryCd.JAPAN.countryCd, "OSAKA", "오사카"), + KYOTO(CountryCd.JAPAN.countryCd, "KYOTO", "교토"), + SAPPORO(CountryCd.JAPAN.countryCd, "SAPPORO", "삿포로"), + FUKUOKA(CountryCd.JAPAN.countryCd, "FUKUOKA", "후쿠오카"), + HIROSHIMA(CountryCd.JAPAN.countryCd, "HIROSHIMA", "히로시마"), + NAGOYA(CountryCd.JAPAN.countryCd, "NAGOYA", "나고야"), + OKINAWA(CountryCd.JAPAN.countryCd, "OKINAWA", "오키나와"), + KANAZAWA(CountryCd.JAPAN.countryCd, "KANAZAWA", "가나자와"), + + // China + BEIJING(CountryCd.CHINA.countryCd, "BEIJING", "베이징"), + SHANGHAI(CountryCd.CHINA.countryCd, "SHANGHAI", "상하이"), + HONG_KONG(CountryCd.CHINA.countryCd, "HONG_KONG", "홍콩"), + MACAO(CountryCd.CHINA.countryCd, "MACAO", "마카오"), + GUANGZHOU(CountryCd.CHINA.countryCd, "GUANGZHOU", "광저우"), + SHENZHEN(CountryCd.CHINA.countryCd, "SHENZHEN", "선전"), + CHENGDU(CountryCd.CHINA.countryCd, "CHENGDU", "청두"), + XIAMEN(CountryCd.CHINA.countryCd, "XIAMEN", "샤먼"), + TIANJIN(CountryCd.CHINA.countryCd, "TIANJIN", "천진"), + + // United States + NEW_YORK(CountryCd.UNITED_STATES.countryCd, "NEW_YORK", "뉴욕"), + LOS_ANGELES(CountryCd.UNITED_STATES.countryCd, "LOS_ANGELES", "로스앤젤레스"), + CHICAGO(CountryCd.UNITED_STATES.countryCd, "CHICAGO", "시카고"), + LAS_VEGAS(CountryCd.UNITED_STATES.countryCd, "LAS_VEGAS", "라스베이거스"), + SAN_FRANCISCO(CountryCd.UNITED_STATES.countryCd, "SAN_FRANCISCO", "샌프란시스코"), + WASHINGTON_DC(CountryCd.UNITED_STATES.countryCd, "WASHINGTON_DC", "워싱턴 D.C."), + MIAMI(CountryCd.UNITED_STATES.countryCd, "MIAMI", "마이애미"), + ORLANDO(CountryCd.UNITED_STATES.countryCd, "ORLANDO", "올랜도"), + SEATTLE(CountryCd.UNITED_STATES.countryCd, "SEATTLE", "시애틀"), + + // United Kingdom + LONDON(CountryCd.ENGLAND.countryCd, "LONDON", "런던"), + EDINBURGH(CountryCd.ENGLAND.countryCd, "EDINBURGH", "에든버러"), + MANCHESTER(CountryCd.ENGLAND.countryCd, "MANCHESTER", "맨체스터"), + BIRMINGHAM(CountryCd.ENGLAND.countryCd, "BIRMINGHAM", "버밍엄"), + GLASGOW(CountryCd.ENGLAND.countryCd, "GLASGOW", "글래스고"), + LIVERPOOL(CountryCd.ENGLAND.countryCd, "LIVERPOOL", "리버풀"), + CAMBRIDGE(CountryCd.ENGLAND.countryCd, "CAMBRIDGE", "케임브리지"), + + // France + PARIS(CountryCd.FRANCE.countryCd, "PARIS", "파리"), + MARSEILLE(CountryCd.FRANCE.countryCd, "MARSEILLE", "마르세유"), + LYON(CountryCd.FRANCE.countryCd, "LYON", "리옹"), + NICE(CountryCd.FRANCE.countryCd, "NICE", "니스"), + BORDEAUX(CountryCd.FRANCE.countryCd, "BORDEAUX", "보르도"), + STRASBOURG(CountryCd.FRANCE.countryCd, "STRASBOURG", "스트라스부르"), + + // Germany + BERLIN(CountryCd.GERMANY.countryCd, "BERLIN", "베를린"), + MUNICH(CountryCd.GERMANY.countryCd, "MUNICH", "뮌헨"), + FRANKFURT(CountryCd.GERMANY.countryCd, "FRANKFURT", "프랑크푸르트"), + HAMBURG(CountryCd.GERMANY.countryCd, "HAMBURG", "함부르크"), + COLOGNE(CountryCd.GERMANY.countryCd, "COLOGNE", "쾰른"), + DUSSELDORF(CountryCd.GERMANY.countryCd, "DUSSELDORF", "뒤셀도르프"), + + // Italy + ROME(CountryCd.ITALY.countryCd, "ROME", "로마"), + MILAN(CountryCd.ITALY.countryCd, "MILAN", "밀라노"), + VENICE(CountryCd.ITALY.countryCd, "VENICE", "베네치아"), + FLORENCE(CountryCd.ITALY.countryCd, "FLORENCE", "피렌체"), + NAPLES(CountryCd.ITALY.countryCd, "NAPLES", "나폴리"), + TURIN(CountryCd.ITALY.countryCd, "TURIN", "투린"), + + // Spain + MADRID(CountryCd.SPAIN.countryCd, "MADRID", "마드리드"), + BARCELONA(CountryCd.SPAIN.countryCd, "BARCELONA", "바르셀로나"), + VALENCIA(CountryCd.SPAIN.countryCd, "VALENCIA", "발렌시아"), + SEVILLE(CountryCd.SPAIN.countryCd, "SEVILLE", "세비야"), + MALAGA(CountryCd.SPAIN.countryCd, "MALAGA", "말라가"), + BILBAO(CountryCd.SPAIN.countryCd, "BILBAO", "빌바오"), + + // Canada + TORONTO(CountryCd.CANADA.countryCd, "TORONTO", "토론토"), + VANCOUVER(CountryCd.CANADA.countryCd, "VANCOUVER", "밴쿠버"), + MONTREAL(CountryCd.CANADA.countryCd, "MONTREAL", "몬트리올"), + CALGARY(CountryCd.CANADA.countryCd, "CALGARY", "캘거리"), + OTTAWA(CountryCd.CANADA.countryCd, "OTTAWA", "오타와"), + QUEBEC_CITY(CountryCd.CANADA.countryCd, "QUEBEC_CITY", "퀘벡 시티"), + + // Australia + SYDNEY(CountryCd.AUSTRALIA.countryCd, "SYDNEY", "시드니"), + MELBOURNE(CountryCd.AUSTRALIA.countryCd, "MELBOURNE", "멜버른"), + BRISBANE(CountryCd.AUSTRALIA.countryCd, "BRISBANE", "브리즈번"), + PERTH(CountryCd.AUSTRALIA.countryCd, "PERTH", "퍼스"), + ADELAIDE(CountryCd.AUSTRALIA.countryCd, "ADELAIDE", "애들레이드"), + CANBERRA(CountryCd.AUSTRALIA.countryCd, "CANBERRA", "캔버라"), + + // Brazil + SAO_PAULO(CountryCd.BRAZIL.countryCd, "SAO_PAULO", "상파울로"), + RIO_DE_JANEIRO(CountryCd.BRAZIL.countryCd, "RIO_DE_JANEIRO", "리오 데 자네이로"), + BRASILIA(CountryCd.BRAZIL.countryCd, "BRASILIA", "브라질리아"), + SALVADOR(CountryCd.BRAZIL.countryCd, "SALVADOR", "살바도르"), + BELO_HORIZONTE(CountryCd.BRAZIL.countryCd, "BELO_HORIZONTE", "벨루 오리손티"), + + // India + MUMBAI(CountryCd.INDIA.countryCd, "MUMBAI", "뭄바이"), + NEW_DELHI(CountryCd.INDIA.countryCd, "NEW_DELHI", "뉴델리"), + BANGALORE(CountryCd.INDIA.countryCd, "BANGALORE", "방갈로르"), + CHENNAI(CountryCd.INDIA.countryCd, "CHENNAI", "첸나이"), + KOLKATA(CountryCd.INDIA.countryCd, "KOLKATA", "콜카타"), + HYDERABAD(CountryCd.INDIA.countryCd, "HYDERABAD", "하이데라바드"), + + MOSCOW(CountryCd.RUSSIA.countryCd, "MOSCOW", "모스크바"), + SAINT_PETERSBURG(CountryCd.RUSSIA.countryCd, "SAINT_PETERSBURG", "상트페테르부르크"), + NOVOSIBIRSK(CountryCd.RUSSIA.countryCd, "NOVOSIBIRSK", "노보시비르스크"), + EKATERINBURG(CountryCd.RUSSIA.countryCd, "EKATERINBURG", "예카테린부르크"), + KAZAN(CountryCd.RUSSIA.countryCd, "KAZAN", "카잔"), + NIZHNY_NOVGOROD(CountryCd.RUSSIA.countryCd, "NIZHNY_NOVGOROD", "니즈니 노브고로드"), + + // Turkey + ISTANBUL(CountryCd.TURKIYE.countryCd, "ISTANBUL", "이스탄불"), + ANKARA(CountryCd.TURKIYE.countryCd, "ANKARA", "앙카라"), + IZMIR(CountryCd.TURKIYE.countryCd, "IZMIR", "이즈미르"), + BURSA(CountryCd.TURKIYE.countryCd, "BURSA", "부르사"), + ANTALYA(CountryCd.TURKIYE.countryCd, "ANTALYA", "안탈리아"), + ADANA(CountryCd.TURKIYE.countryCd, "ADANA", "아다나"), + + // Argentina + BUENOS_AIRES(CountryCd.ARGENTINA.countryCd, "BUENOS_AIRES", "부에노스 아이레스"), + CORDOBA(CountryCd.ARGENTINA.countryCd, "CORDOBA", "코르도바"), + ROSARIO(CountryCd.ARGENTINA.countryCd, "ROSARIO", "로사리오"), + MENDOZA(CountryCd.ARGENTINA.countryCd, "MENDOZA", "멘도사"), + SALTA(CountryCd.ARGENTINA.countryCd, "SALTA", "살타"), + + // Egypt + CAIRO(CountryCd.EGYPT.countryCd, "CAIRO", "카이로"), + ALEXANDRIA(CountryCd.EGYPT.countryCd, "ALEXANDRIA", "알렉산드리아"), + LUXOR(CountryCd.EGYPT.countryCd, "LUXOR", "룩소르"), + SHARM_EL_SHEIKH(CountryCd.EGYPT.countryCd, "SHARM_EL_SHEIKH", "샤름 엘 쉬크"), + ASWAN(CountryCd.EGYPT.countryCd, "ASWAN", "아스완"), + HURGHADA(CountryCd.EGYPT.countryCd, "HURGHADA", "후르가다"), + + // Thailand + BANGKOK(CountryCd.THAILAND.countryCd, "BANGKOK", "방콕"), + PHUKET(CountryCd.THAILAND.countryCd, "PHUKET", "푸켓"), + CHIANG_MAI(CountryCd.THAILAND.countryCd, "CHIANG_MAI", "치앙마이"), + PATTAYA(CountryCd.THAILAND.countryCd, "PATTAYA", "파타야"), + KRABI(CountryCd.THAILAND.countryCd, "KRABI", "크라비"), + HUA_HIN(CountryCd.THAILAND.countryCd, "HUA_HIN", "후아힌"), + + // Mexico + MEXICO_CITY(CountryCd.MEXICO.countryCd, "MEXICO_CITY", "멕시코시티"), + CANCUN(CountryCd.MEXICO.countryCd, "CANCUN", "칸쿤"), + GUADALAJARA(CountryCd.MEXICO.countryCd, "GUADALAJARA", "과달라하라"), + MONTERREY(CountryCd.MEXICO.countryCd, "MONTERREY", "몬테레이"), + TULUM(CountryCd.MEXICO.countryCd, "TULUM", "툴룸"), + OAXACA(CountryCd.MEXICO.countryCd, "OAXACA", "오아하카"), + + // Indonesia + JAKARTA(CountryCd.INDONESIA.countryCd, "JAKARTA", "자카르타"), + BALI(CountryCd.INDONESIA.countryCd, "BALI", "발리"), + BANDUNG(CountryCd.INDONESIA.countryCd, "BANDUNG", "반둥"), + YOGYAKARTA(CountryCd.INDONESIA.countryCd, "YOGYAKARTA", "요가야카르타"), + SURABAYA(CountryCd.INDONESIA.countryCd, "SURABAYA", "수라바야"), + MAKASSAR(CountryCd.INDONESIA.countryCd, "MAKASSAR", "마카사르"); + } \ No newline at end of file diff --git a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CountryCd.kt b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CountryCd.kt index 60e0b9b..bb32d81 100644 --- a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CountryCd.kt +++ b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CountryCd.kt @@ -111,5 +111,81 @@ enum class CountryCd ( AUSTRALIA(ContinentCd.OCEANIA.continentCd,"AUSTRALIA","호주"), PALAU(ContinentCd.OCEANIA.continentCd,"PALAU","팔라우"), PAPUA_NEW_GUINEA(ContinentCd.OCEANIA.continentCd,"PAPUA_NEW_GUINEA","파푸아뉴기니"), + TONGA(ContinentCd.OCEANIA.continentCd, "TONGA", "퉁가"), + KIRIBATI(ContinentCd.OCEANIA.continentCd, "KIRIBATI", "키리바시"), + SOLOMON_ISLAND(ContinentCd.OCEANIA.continentCd, "SOLOMON_ISLAND", "솔로몬제도"), + SAMOA(ContinentCd.OCEANIA.continentCd, "SAMOA", "사모아"), + + TUNISIA(ContinentCd.AFRICA.continentCd, "TUNISIA", "튀니지"), + ANGOLA(ContinentCd.AFRICA.continentCd, "ANGOLA", "앙골라"), + ALGERIA(ContinentCd.AFRICA.continentCd, "ALGERIA", "알제리"), + SIERRA_LEONE(ContinentCd.AFRICA.continentCd, "SIERRA_LEONE", "시에라리온"), + SUDAN(ContinentCd.AFRICA.continentCd, "SUDAN", "수단"), + SOMALIA(ContinentCd.AFRICA.continentCd, "SOMALIA", "소말리아"), + SEYCHELLES(ContinentCd.AFRICA.continentCd, "SEYCHELLES", "세이셸"), + SENEGAL(ContinentCd.AFRICA.continentCd, "SENEGAL", "세네갈"), + UGANDA(ContinentCd.AFRICA.continentCd, "UGANDA", "우간다"), + ZAMBIA(ContinentCd.AFRICA.continentCd, "ZAMBIA", "잠비아"), + EQUATORIAL_GUINEA(ContinentCd.AFRICA.continentCd, "EQUATORIAL_GUINEA", "적도기니"), + TOGO(ContinentCd.AFRICA.continentCd, "TOGO", "토고"), + CONGO(ContinentCd.AFRICA.continentCd, "CONGO", "콩고"), + COTE_D_IVOIRE(ContinentCd.AFRICA.continentCd, "COTE_D_IVOIRE", "코트디부아르"), + COMOROS(ContinentCd.AFRICA.continentCd, "COMOROS", "코모로"), + ZIMBABWE(ContinentCd.AFRICA.continentCd, "ZIMBABWE", "짐바브웨"), + DJIBOUTI(ContinentCd.AFRICA.continentCd, "DJIBOUTI", "지부티"), + CENTRAL_AFRICAN_REPUBLIC(ContinentCd.AFRICA.continentCd, "CENTRAL_AFRICAN_REPUBLIC", "중앙아프리카공화국"), + BURUNDI(ContinentCd.AFRICA.continentCd, "BURUNDI", "부룬디"), + BURKINA_FASO(ContinentCd.AFRICA.continentCd, "BURKINA_FASO", "부르키나파소"), + GUINEA_BISSAU(ContinentCd.AFRICA.continentCd, "GUINEA_BISSAU", "기니비사우"), + BOTSWANA(ContinentCd.AFRICA.continentCd, "BOTSWANA", "보츠와나"), + GUINEA(ContinentCd.AFRICA.continentCd, "GUINEA", "기니"), + GAMBIA(ContinentCd.AFRICA.continentCd, "GAMBIA", "감비아"), + GABON(ContinentCd.AFRICA.continentCd, "GABON", "가봉"), + GHANA(ContinentCd.AFRICA.continentCd, "GHANA", "가나"), + MOROCCO(ContinentCd.AFRICA.continentCd, "MOROCCO", "모로코"), + NAMIBIA(ContinentCd.AFRICA.continentCd, "NAMIBIA", "나미비아"), + KENYA(ContinentCd.AFRICA.continentCd, "KENYA", "케냐"), + ETHIOPIA(ContinentCd.AFRICA.continentCd, "ETHIOPIA", "에티오피아"), + TANZANIA(ContinentCd.AFRICA.continentCd, "TANZANIA", "탄자니아"), + NIGERIA(ContinentCd.AFRICA.continentCd, "NIGERIA", "나이지리아"), + BENIN(ContinentCd.AFRICA.continentCd, "BENIN", "베넹"), + NIGER(ContinentCd.AFRICA.continentCd, "NIGER", "니제르"), + MOZAMBIQUE(ContinentCd.AFRICA.continentCd, "MOZAMBIQUE", "모잠비크"), + MAURITANIA(ContinentCd.AFRICA.continentCd, "MAURITANIA", "모리타니"), + MAURITIUS(ContinentCd.AFRICA.continentCd, "MAURITIUS", "모리셔스"), + MALI(ContinentCd.AFRICA.continentCd, "MALI", "말리"), + MALAWI(ContinentCd.AFRICA.continentCd, "MALAWI", "말라위"), + MADAGASCAR(ContinentCd.AFRICA.continentCd, "MADAGASCAR", "마다가스카르"), + LIBYA(ContinentCd.AFRICA.continentCd, "LIBYA", "리비아"), + RWANDA(ContinentCd.AFRICA.continentCd, "RWANDA", "르완다"), + LESOTHO(ContinentCd.AFRICA.continentCd, "LESOTHO", "레소토"), + LIBERIA(ContinentCd.AFRICA.continentCd, "LIBERIA", "라이베리아"), + EGYPT(ContinentCd.AFRICA.continentCd, "EGYPT", "이집트"), + + UNITED_STATES(ContinentCd.NORTH_AMERICA.continentCd, "UNITED_STATES", "미국"), + CANADA(ContinentCd.NORTH_AMERICA.continentCd,"CANADA", "캐나다"), + MEXICO(ContinentCd.NORTH_AMERICA.continentCd,"MEXICO","멕시코"), + ANTIGUA_AND_BARBUDA(ContinentCd.NORTH_AMERICA.continentCd, "ANTIGUA_AND_BARBUDA", "앤티가바부다"), + ARUBA(ContinentCd.NORTH_AMERICA.continentCd, "ARUBA", "아루바"), + ANGUILLA(ContinentCd.NORTH_AMERICA.continentCd, "ANGUILLA", "앵귈라"), + ANTARCTICA(ContinentCd.NORTH_AMERICA.continentCd, "ANTARCTICA", "남극"), + BAHAMAS(ContinentCd.NORTH_AMERICA.continentCd, "BAHAMAS", "바하마"), + BELIZE(ContinentCd.NORTH_AMERICA.continentCd, "BELIZE", "벨리즈"), + BARBADOS(ContinentCd.NORTH_AMERICA.continentCd, "BARBADOS", "바베이도스"), + BERMUDA(ContinentCd.NORTH_AMERICA.continentCd, "BERMUDA", "버뮤다"), + BOLIVIA(ContinentCd.NORTH_AMERICA.continentCd, "BOLIVIA", "볼리비아"), + BRAZIL(ContinentCd.NORTH_AMERICA.continentCd, "BRAZIL", "브라질"), + IRAQ(ContinentCd.NORTH_AMERICA.continentCd, "IRAQ", "이라크"), + QATAR(ContinentCd.NORTH_AMERICA.continentCd, "QATAR", "카타르"), + + ARGENTINA(ContinentCd.SOUTH_AMERICA.continentCd, "ARGENTINA", "아르헨티나"), + CHILE(ContinentCd.SOUTH_AMERICA.continentCd, "CHILE", "칠레"), + COLOMBIA(ContinentCd.SOUTH_AMERICA.continentCd, "COLOMBIA", "콜롬비아"), + ECUADOR(ContinentCd.SOUTH_AMERICA.continentCd, "ECUADOR", "에콰도르"), + PARAGUAY(ContinentCd.SOUTH_AMERICA.continentCd, "PARAGUAY", "파라과이"), + PERU(ContinentCd.SOUTH_AMERICA.continentCd, "PERU", "페루"), + SURINAME(ContinentCd.SOUTH_AMERICA.continentCd, "SURINAME", "수리남"), + URUGUAY(ContinentCd.SOUTH_AMERICA.continentCd, "URUGUAY", "우루과이"), + VENEZUELA(ContinentCd.SOUTH_AMERICA.continentCd, "VENEZUELA", "베네수엘라") } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationDto.kt index e8d6d4b..7a47e4b 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationDto.kt @@ -1,8 +1,52 @@ package com.travel.withaeng.domain.destination -import com.travel.withaeng.domain.accompany.AccompanyDestinationEntity -import com.travel.withaeng.domain.accompany.AccompanyEntity -import java.time.LocalDate -class DestinationDto { +import lombok.Getter +import lombok.NoArgsConstructor +import lombok.Setter + +@Setter +@Getter +class DestinationDto ( + + var continentList : List +) + +@Setter +@Getter +@NoArgsConstructor +class Continent( + + var continentCd : String, + var continentNm : String, + var countryList : List + +){ + constructor(continentCd : String, continentNm : String) : + this(continentCd, continentNm, mutableListOf()) + +} + +@Setter +@Getter +@NoArgsConstructor +class Country( + + var countryCd : String, + var countryNm : String, + var cityList : List +){ + + constructor(countryCd : String, countryNm : String) : + this(countryCd, countryNm, mutableListOf()) + + } + +@Setter +@Getter +class City( + + var cityCd : String, + var cityNm : String, +) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationService.kt index 267c3c5..fee981a 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationService.kt @@ -1,4 +1,45 @@ package com.travel.withaeng.domain.destination +import com.travel.withaeng.common.cd.CityCd +import com.travel.withaeng.common.cd.ContinentCd +import com.travel.withaeng.common.cd.CountryCd +import org.springframework.stereotype.Service + +@Service class DestinationService { + + fun getDestinationList() : DestinationDto{ + + val continentList = mutableListOf() + + for (continentCd in ContinentCd.entries) { + + // Create a continent object + val continent = Continent(continentCd.continentCd, continentCd.continentNm) + val countryList = mutableListOf() + + for(countryCd in CountryCd.entries){ + if(continentCd.continentCd.equals(countryCd.continentCd)){ + val country = Country(countryCd.countryCd, countryCd.countryNm) + + val cityList = mutableListOf() + for(cityCd in CityCd.entries){ + if(countryCd.countryCd.equals(cityCd.countryCd)){ + val city = City(cityCd.cityCd, cityCd.cityNm) + cityList.add(city) + } + } + country.cityList = cityList + countryList.add(country) + } + } + + continent.countryList = countryList; + // Add the continent to the list + continentList.add(continent) + } + + // Create and return DestinationDto + return DestinationDto(continentList) + } } \ No newline at end of file From 4a0fcf0e3d2e154438c068a4ce986370894c5265 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Thu, 9 May 2024 02:17:44 +0900 Subject: [PATCH 059/174] Refactor package architectures --- withaeng-api/build.gradle.kts | 2 +- .../accompany}/AccompanyController.kt | 3 +-- .../accompanylike}/AccompanyLikeController.kt | 3 +-- .../accompanyreply}/AccompanyReplyController.kt | 2 +- .../accompanyreplylike}/AccompanyReplyLikeController.kt | 5 +---- .../domain/accompanyreplylike/AccompanyReplyLikeDto.kt | 3 --- 6 files changed, 5 insertions(+), 13 deletions(-) rename withaeng-api/src/main/kotlin/com/travel/withaeng/{accompany/controller => controller/accompany}/AccompanyController.kt (94%) rename withaeng-api/src/main/kotlin/com/travel/withaeng/{accompanyLike/controller => controller/accompanylike}/AccompanyLikeController.kt (90%) rename withaeng-api/src/main/kotlin/com/travel/withaeng/{accompanyReply/controller => controller/accompanyreply}/AccompanyReplyController.kt (97%) rename withaeng-api/src/main/kotlin/com/travel/withaeng/{accompanyReplyLike => controller/accompanyreplylike}/AccompanyReplyLikeController.kt (81%) diff --git a/withaeng-api/build.gradle.kts b/withaeng-api/build.gradle.kts index 0b3fc6d..cf1a201 100644 --- a/withaeng-api/build.gradle.kts +++ b/withaeng-api/build.gradle.kts @@ -16,7 +16,7 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-web") implementation("org.springframework.boot:spring-boot-starter-security") implementation("org.springframework.boot:spring-boot-starter-validation") - + api("org.springframework.boot:spring-boot-starter-data-jpa") // jwt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompany/controller/AccompanyController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/AccompanyController.kt similarity index 94% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/accompany/controller/AccompanyController.kt rename to withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/AccompanyController.kt index cc7adb3..18eaf59 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompany/controller/AccompanyController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/AccompanyController.kt @@ -1,11 +1,10 @@ -package com.travel.withaeng.accompany.controller +package com.travel.withaeng.controller.accompany import com.travel.withaeng.common.ApiResponse import com.travel.withaeng.domain.accompany.* import jakarta.validation.Valid import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity -import org.springframework.validation.annotation.Validated import org.springframework.web.bind.annotation.* @RestController diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyLike/controller/AccompanyLikeController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanylike/AccompanyLikeController.kt similarity index 90% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyLike/controller/AccompanyLikeController.kt rename to withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanylike/AccompanyLikeController.kt index e833e60..41e1105 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyLike/controller/AccompanyLikeController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanylike/AccompanyLikeController.kt @@ -1,7 +1,6 @@ -package com.travel.withaeng.accompanyLike.controller +package com.travel.withaeng.controller.accompanylike import com.travel.withaeng.common.ApiResponse -import com.travel.withaeng.domain.accompany.CreateAccompanyDTO import com.travel.withaeng.domain.accompanylike.AccompanyLikeService import com.travel.withaeng.domain.accompanylike.CreateAccompanyLikeDTO import com.travel.withaeng.domain.accompanylike.DeleteAccompanyLikeDTO diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReply/controller/AccompanyReplyController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt similarity index 97% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReply/controller/AccompanyReplyController.kt rename to withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt index 6af3be7..fc721d0 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReply/controller/AccompanyReplyController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.accompanyReply.controller +package com.travel.withaeng.controller.accompanyreply import com.travel.withaeng.common.ApiResponse import com.travel.withaeng.domain.accompanyreply.AccompanyReplyService diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReplyLike/AccompanyReplyLikeController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreplylike/AccompanyReplyLikeController.kt similarity index 81% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReplyLike/AccompanyReplyLikeController.kt rename to withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreplylike/AccompanyReplyLikeController.kt index ff64ce4..3d1ad36 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/accompanyReplyLike/AccompanyReplyLikeController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreplylike/AccompanyReplyLikeController.kt @@ -1,9 +1,6 @@ -package com.travel.withaeng.accompanyReplyLike +package com.travel.withaeng.controller.accompanyreplylike import com.travel.withaeng.common.ApiResponse -import com.travel.withaeng.domain.accompanylike.AccompanyLikeService -import com.travel.withaeng.domain.accompanylike.CreateAccompanyLikeDTO -import com.travel.withaeng.domain.accompanylike.DeleteAccompanyLikeDTO import com.travel.withaeng.domain.accompanyreplylike.AccompanyReplyLikeService import com.travel.withaeng.domain.accompanyreplylike.CreateAccompanyReplyLikeDTO import com.travel.withaeng.domain.accompanyreplylike.DeleteAccompanyReplyLikeDTO diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeDto.kt index 508b3ca..bf5995f 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeDto.kt @@ -1,9 +1,6 @@ package com.travel.withaeng.domain.accompanyreplylike import com.travel.withaeng.common.cd.ExecCd -import com.travel.withaeng.domain.accompanylike.AccompanyLikeEntity -import com.travel.withaeng.domain.accompanylike.AccompanyLikeHistEntity -import jakarta.persistence.Column import lombok.Getter import lombok.Setter import org.jetbrains.annotations.NotNull From 226f616c577de4a23a7782db15c33272991fc1e0 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Thu, 9 May 2024 02:19:08 +0900 Subject: [PATCH 060/174] Reformat codes --- .../common/ControllerExceptionAdvice.kt | 4 +- .../accompany/AccompanyController.kt | 23 ++- .../accompanylike/AccompanyLikeController.kt | 10 +- .../AccompanyReplyController.kt | 28 ++- .../AccompanyReplyLikeController.kt | 10 +- .../destination/DestinationController.kt | 5 +- .../withaeng/config/JpaQueryDslConfig.kt | 4 +- .../accompany/AccompanyDestinationEntity.kt | 6 +- .../AccompanyDestinationRepository.kt | 2 +- .../domain/accompany/AccompanyDetailEntity.kt | 9 +- .../accompany/AccompanyDetailRepository.kt | 2 +- .../withaeng/domain/accompany/AccompanyDto.kt | 141 +++++++------- .../domain/accompany/AccompanyEntity.kt | 5 +- .../domain/accompany/AccompanyHistEntity.kt | 29 ++- .../accompany/AccompanyHistRepository.kt | 3 +- .../domain/accompany/AccompanyRepository.kt | 6 +- .../accompany/AccompanyRepositoryCustom.kt | 6 +- .../AccompanyRepositoryCustomImpl.kt | 106 +++++------ .../domain/accompany/AccompanyService.kt | 34 ++-- .../domain/accompany/AccompanyTagEntity.kt | 18 +- .../accompany/AccompanyTagRepository.kt | 2 +- .../domain/accompanylike/AccompanyLikeDto.kt | 9 +- .../accompanylike/AccompanyLikeEntity.kt | 2 +- .../accompanylike/AccompanyLikeHistEntity.kt | 4 +- .../accompanylike/AccompanyLikeService.kt | 6 +- .../accompanyreply/AccompanyReplyDto.kt | 176 +++++++++--------- .../accompanyreply/AccompanyReplyEntity.kt | 10 +- .../AccompanyReplyHistEntity.kt | 28 +-- .../AccompanyReplyRepository.kt | 3 +- .../AccompanyReplyRepositoryCustom.kt | 4 +- .../AccompanyReplyRepositoryCustomImpl.kt | 24 ++- .../accompanyreply/AccompanyReplyService.kt | 54 +++--- .../AccompanyReplyLikeDto.kt | 63 +++---- .../AccompanyReplyLikeHistEntity.kt | 27 ++- .../AccompanyReplyLikeRepository.kt | 8 +- .../AccompanyReplyLikeRepositoryCustom.kt | 4 +- .../AccompanyReplyLikeRepositoryCustomImpl.kt | 6 +- .../AccompanyReplyLikeService.kt | 21 +-- .../domain/destination/DestinationDto.kt | 28 +-- .../domain/destination/DestinationService.kt | 12 +- .../domain/validateemail/ValidatingEmail.kt | 4 +- 41 files changed, 474 insertions(+), 472 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ControllerExceptionAdvice.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ControllerExceptionAdvice.kt index 74cb5af..28aced3 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ControllerExceptionAdvice.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ControllerExceptionAdvice.kt @@ -71,13 +71,13 @@ class ControllerExceptionAdvice { } @ExceptionHandler(NotExistsException::class) - protected fun notExistsException(e: NotExistsException) : ResponseEntity> { + protected fun notExistsException(e: NotExistsException): ResponseEntity> { logger.error("notExistsException", e) return errorResponse(WithaengExceptionType.NOT_EXIST, e.message) } @ExceptionHandler(InvalidAccessException::class) - protected fun invalidAccessException(e: InvalidAccessException) : ResponseEntity> { + protected fun invalidAccessException(e: InvalidAccessException): ResponseEntity> { logger.error("invalidAccessException", e) return errorResponse(WithaengExceptionType.INVALID_ACCESS, e.message) } diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/AccompanyController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/AccompanyController.kt index 18eaf59..f5bc78a 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/AccompanyController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/AccompanyController.kt @@ -1,7 +1,10 @@ package com.travel.withaeng.controller.accompany import com.travel.withaeng.common.ApiResponse -import com.travel.withaeng.domain.accompany.* +import com.travel.withaeng.domain.accompany.AccompanyService +import com.travel.withaeng.domain.accompany.CreateAccompanyDTO +import com.travel.withaeng.domain.accompany.ModifyAccompanyDTO +import com.travel.withaeng.domain.accompany.SearchAccompanyDTO import jakarta.validation.Valid import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity @@ -12,34 +15,36 @@ import org.springframework.web.bind.annotation.* class AccompanyController(private val accompanyService: AccompanyService) { @PostMapping("") - fun create(@RequestBody @Valid param : CreateAccompanyDTO) : ResponseEntity> { - return ResponseEntity.status(HttpStatus.CREATED).body(ApiResponse(true, accompanyService.createAccompany(param), null)) + fun create(@RequestBody @Valid param: CreateAccompanyDTO): ResponseEntity> { + return ResponseEntity.status(HttpStatus.CREATED) + .body(ApiResponse(true, accompanyService.createAccompany(param), null)) } @PutMapping("/{accompanyId}") - fun modify(@RequestBody @Valid param : ModifyAccompanyDTO) : ResponseEntity> { - return ResponseEntity.status(HttpStatus.OK).body(ApiResponse(true, accompanyService.modifyAccompany(param), null)) + fun modify(@RequestBody @Valid param: ModifyAccompanyDTO): ResponseEntity> { + return ResponseEntity.status(HttpStatus.OK) + .body(ApiResponse(true, accompanyService.modifyAccompany(param), null)) } @GetMapping("/{accompanyId}") - fun getOne(@PathVariable("accompanyId") accompanyId : Long) : ResponseEntity> { + fun getOne(@PathVariable("accompanyId") accompanyId: Long): ResponseEntity> { return ResponseEntity.status(HttpStatus.OK).body(ApiResponse(true, accompanyService.getOne(accompanyId), null)) } @PutMapping("/{accompanyId}/incr/viewCnt") - fun incrViewCnt(@PathVariable("accompanyId") accompanyId : Long) : ResponseEntity> { + fun incrViewCnt(@PathVariable("accompanyId") accompanyId: Long): ResponseEntity> { accompanyService.incrViewCnt(accompanyId) return ResponseEntity.status(HttpStatus.OK).body(ApiResponse(true, null, null)) } @PutMapping("/{accompanyId}/decr/viewCnt") - fun decrViewCnt(@PathVariable("accompanyId") accompanyId : Long) : ResponseEntity> { + fun decrViewCnt(@PathVariable("accompanyId") accompanyId: Long): ResponseEntity> { accompanyService.decrViewCnt(accompanyId) return ResponseEntity.status(HttpStatus.OK).body(ApiResponse(true, null, null)) } @GetMapping("/getList") - fun getList(@RequestBody param : SearchAccompanyDTO) : ResponseEntity> { + fun getList(@RequestBody param: SearchAccompanyDTO): ResponseEntity> { return ResponseEntity.status(HttpStatus.OK).body(ApiResponse(true, accompanyService.getList(param), null)) } diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanylike/AccompanyLikeController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanylike/AccompanyLikeController.kt index 41e1105..0c42b17 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanylike/AccompanyLikeController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanylike/AccompanyLikeController.kt @@ -14,14 +14,16 @@ import org.springframework.web.bind.annotation.* class AccompanyLikeController(private val accompanyLikeService: AccompanyLikeService) { @PostMapping("") - fun create(@RequestBody @Valid param : CreateAccompanyLikeDTO) : ResponseEntity> { + fun create(@RequestBody @Valid param: CreateAccompanyLikeDTO): ResponseEntity> { return ResponseEntity.status(HttpStatus.CREATED).body( - ApiResponse(true, accompanyLikeService.createAccompanyLike(param), null)) + ApiResponse(true, accompanyLikeService.createAccompanyLike(param), null) + ) } @DeleteMapping("") - fun delete(@RequestBody @Valid param : DeleteAccompanyLikeDTO) : ResponseEntity{ - return ResponseEntity.status(HttpStatus.OK).body(ApiResponse(true,accompanyLikeService.deleteAccompanyLike(param), null)) + fun delete(@RequestBody @Valid param: DeleteAccompanyLikeDTO): ResponseEntity { + return ResponseEntity.status(HttpStatus.OK) + .body(ApiResponse(true, accompanyLikeService.deleteAccompanyLike(param), null)) } } \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt index fc721d0..61c69eb 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt @@ -7,36 +7,32 @@ import com.travel.withaeng.domain.accompanyreply.DeleteAccompanyReplyDTO import com.travel.withaeng.domain.accompanyreply.ModifyAccompanyReplyDTO import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity -import org.springframework.web.bind.annotation.DeleteMapping -import org.springframework.web.bind.annotation.GetMapping -import org.springframework.web.bind.annotation.PathVariable -import org.springframework.web.bind.annotation.PostMapping -import org.springframework.web.bind.annotation.PutMapping -import org.springframework.web.bind.annotation.RequestBody -import org.springframework.web.bind.annotation.RequestMapping -import org.springframework.web.bind.annotation.RestController +import org.springframework.web.bind.annotation.* @RestController @RequestMapping("/api/v1/accompany/{accompanyId}/reply") -class AccompanyReplyController(private val accompanyReplyService: AccompanyReplyService){ +class AccompanyReplyController(private val accompanyReplyService: AccompanyReplyService) { @PostMapping("") - fun create(@RequestBody param : CreateAccompanyReplyDTO) : ResponseEntity> { - return ResponseEntity.status(HttpStatus.CREATED).body(ApiResponse(true, accompanyReplyService.createAccompanyReply(param), null)) + fun create(@RequestBody param: CreateAccompanyReplyDTO): ResponseEntity> { + return ResponseEntity.status(HttpStatus.CREATED) + .body(ApiResponse(true, accompanyReplyService.createAccompanyReply(param), null)) } @PutMapping("/{replyId}") - fun create(@RequestBody param : ModifyAccompanyReplyDTO) : ResponseEntity> { - return ResponseEntity.status(HttpStatus.OK).body(ApiResponse(true, accompanyReplyService.modifyAccompanyReply(param), null)) + fun create(@RequestBody param: ModifyAccompanyReplyDTO): ResponseEntity> { + return ResponseEntity.status(HttpStatus.OK) + .body(ApiResponse(true, accompanyReplyService.modifyAccompanyReply(param), null)) } @DeleteMapping("/{replyId}") - fun create(@RequestBody param : DeleteAccompanyReplyDTO) : ResponseEntity> { - return ResponseEntity.status(HttpStatus.OK).body(ApiResponse(true, accompanyReplyService.deleteAccompanyReply(param), null)) + fun create(@RequestBody param: DeleteAccompanyReplyDTO): ResponseEntity> { + return ResponseEntity.status(HttpStatus.OK) + .body(ApiResponse(true, accompanyReplyService.deleteAccompanyReply(param), null)) } @GetMapping("/getList") - fun create(@PathVariable(name= "accompanyId") param : Long) : ResponseEntity> { + fun create(@PathVariable(name = "accompanyId") param: Long): ResponseEntity> { return ResponseEntity.status(HttpStatus.OK).body(ApiResponse(true, accompanyReplyService.getList(param), null)) } diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreplylike/AccompanyReplyLikeController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreplylike/AccompanyReplyLikeController.kt index 3d1ad36..8ef8328 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreplylike/AccompanyReplyLikeController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreplylike/AccompanyReplyLikeController.kt @@ -13,13 +13,15 @@ import org.springframework.web.bind.annotation.* class AccompanyReplyLikeController(private val accompanyReplyLikeService: AccompanyReplyLikeService) { @PostMapping("") - fun create(@RequestBody param : CreateAccompanyReplyLikeDTO) : ResponseEntity> { - return ResponseEntity.status(HttpStatus.CREATED).body(ApiResponse(true, accompanyReplyLikeService.createAccompanyReplyLike(param), null)) + fun create(@RequestBody param: CreateAccompanyReplyLikeDTO): ResponseEntity> { + return ResponseEntity.status(HttpStatus.CREATED) + .body(ApiResponse(true, accompanyReplyLikeService.createAccompanyReplyLike(param), null)) } @DeleteMapping("") - fun delete(@RequestBody param : DeleteAccompanyReplyLikeDTO) : ResponseEntity> { - return ResponseEntity.status(HttpStatus.OK).body(ApiResponse(true, accompanyReplyLikeService.deleteAccompanyReplyLike(param), null)) + fun delete(@RequestBody param: DeleteAccompanyReplyLikeDTO): ResponseEntity> { + return ResponseEntity.status(HttpStatus.OK) + .body(ApiResponse(true, accompanyReplyLikeService.deleteAccompanyReplyLike(param), null)) } } \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/destination/DestinationController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/destination/DestinationController.kt index 341fedd..f43404a 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/destination/DestinationController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/destination/DestinationController.kt @@ -14,7 +14,8 @@ class DestinationController(private val destinationService: DestinationService) @GetMapping("/getList") - fun getList() : ResponseEntity>{ - return ResponseEntity.status(HttpStatus.OK).body(ApiResponse(true, destinationService.getDestinationList(), null)) + fun getList(): ResponseEntity> { + return ResponseEntity.status(HttpStatus.OK) + .body(ApiResponse(true, destinationService.getDestinationList(), null)) } } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/config/JpaQueryDslConfig.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/config/JpaQueryDslConfig.kt index e5d9b4d..1d5203f 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/config/JpaQueryDslConfig.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/config/JpaQueryDslConfig.kt @@ -10,10 +10,10 @@ import org.springframework.context.annotation.Configuration class JpaQueryDslConfig { @PersistenceContext - lateinit var entityManager : EntityManager + lateinit var entityManager: EntityManager @Bean - fun jpaQueryFactory() : JPAQueryFactory{ + fun jpaQueryFactory(): JPAQueryFactory { return JPAQueryFactory(entityManager) } } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestinationEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestinationEntity.kt index dd7d6a0..472893c 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestinationEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestinationEntity.kt @@ -19,9 +19,9 @@ class AccompanyDestinationEntity( var continent: String, @Column(name = "country", nullable = true, updatable = true) - var country : String?, + var country: String?, @Column(name = "city", nullable = true, updatable = true) - var city : String?, + var city: String?, -) : AccompanyBaseEntity() + ) : AccompanyBaseEntity() diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestinationRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestinationRepository.kt index 094ef3a..bc71391 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestinationRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestinationRepository.kt @@ -3,5 +3,5 @@ package com.travel.withaeng.domain.accompany import org.springframework.data.jpa.repository.JpaRepository interface AccompanyDestinationRepository : JpaRepository { - fun findByAccompanyId(accompanyId : Long) : AccompanyDestinationEntity + fun findByAccompanyId(accompanyId: Long): AccompanyDestinationEntity } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDetailEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDetailEntity.kt index 123554b..161ac82 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDetailEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDetailEntity.kt @@ -1,13 +1,16 @@ package com.travel.withaeng.domain.accompany import com.travel.withaeng.domain.AccompanyBaseEntity -import jakarta.persistence.* +import jakarta.persistence.Column +import jakarta.persistence.Entity +import jakarta.persistence.Id +import jakarta.persistence.Table import org.hibernate.annotations.DynamicUpdate @DynamicUpdate @Table(name = "accompany_detail") @Entity -class AccompanyDetailEntity ( +class AccompanyDetailEntity( @Id @Column(name = "accompany_id", nullable = false) @@ -20,7 +23,7 @@ class AccompanyDetailEntity ( var likeCnt: Long = 0L, @Column(name = "open_kakao_url", nullable = false) - var openKakaoUrl : String + var openKakaoUrl: String ) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDetailRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDetailRepository.kt index 206ec91..139e9b9 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDetailRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDetailRepository.kt @@ -3,6 +3,6 @@ package com.travel.withaeng.domain.accompany import org.springframework.data.jpa.repository.JpaRepository interface AccompanyDetailRepository : JpaRepository { - fun findByAccompanyId(accompanyId : Long) : AccompanyDetailEntity + fun findByAccompanyId(accompanyId: Long): AccompanyDetailEntity } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt index d5ec7e9..b493e0b 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt @@ -5,16 +5,13 @@ import com.travel.withaeng.common.cd.AccompanyStatusCd import com.travel.withaeng.common.cd.ExecCd import jakarta.validation.constraints.NotBlank import lombok.Getter -import lombok.NoArgsConstructor import lombok.Setter import org.jetbrains.annotations.NotNull -import org.springframework.data.domain.Page -import org.springframework.data.domain.Pageable import java.time.LocalDate import java.time.LocalDateTime import java.time.LocalTime -class AccompanyDto () +class AccompanyDto @Setter @Getter @@ -35,9 +32,9 @@ class CreateAccompanyDTO( @NotBlank(message = "대륙은 필수 값 입니다.") val continent: String, - val country : String? = null, + val country: String? = null, - val city : String? = null, + val city: String? = null, val startTripDate: LocalDate, @@ -46,14 +43,14 @@ class CreateAccompanyDTO( val bannerImageUrl: String? = null, @field:NotNull - val accompanyCnt : Long, + val accompanyCnt: Long, - val tags : List?, + val tags: List?, @NotBlank(message = "카카오 오픈 채팅 URL은 필수 값 입니다.") - val openKakaoUrl : String + val openKakaoUrl: String -){ +) { fun toEntity(): AccompanyEntity { return AccompanyEntity( 0, @@ -84,17 +81,17 @@ class CreateAccompanyDTO( ) } - fun toDestinationEntity(accompanyId : Long) : AccompanyDestinationEntity { + fun toDestinationEntity(accompanyId: Long): AccompanyDestinationEntity { return AccompanyDestinationEntity( - 0, - accompanyId, - this.continent, - this.country, - this.city - ) + 0, + accompanyId, + this.continent, + this.country, + this.city + ) } - fun toDetailEntity(accompanyId : Long) : AccompanyDetailEntity { + fun toDetailEntity(accompanyId: Long): AccompanyDetailEntity { return AccompanyDetailEntity( accompanyId, 0, @@ -103,14 +100,14 @@ class CreateAccompanyDTO( ) } - fun toTagEntity(accompanyId : Long) : List? { + fun toTagEntity(accompanyId: Long): List? { - if(tags == null){ + if (tags == null) { return null } val tagList = mutableListOf() - for(tagNm in tags){ + for (tagNm in tags) { tagList.add(AccompanyTagEntity(0, accompanyId, tagNm)) } @@ -123,7 +120,7 @@ class CreateAccompanyDTO( class ModifyAccompanyDTO( @NotNull - val accompanyId : Long, + val accompanyId: Long, @NotNull val userId: Long, @@ -137,9 +134,9 @@ class ModifyAccompanyDTO( @NotBlank(message = "대륙은 필수 값 입니다.") val continent: String, - val country : String? = null, + val country: String? = null, - val city : String? = null, + val city: String? = null, val startTripDate: LocalDate, @@ -148,38 +145,38 @@ class ModifyAccompanyDTO( val bannerImageUrl: String? = null, @NotNull - val accompanyCnt : Long, + val accompanyCnt: Long, - val tags : List?, + val tags: List?, @NotBlank(message = "카카오 오픈 채팅 URL은 필수 값 입니다.") - val openKakaoUrl : String + val openKakaoUrl: String -){ +) { fun toHistEntity(entity: AccompanyEntity): AccompanyHistEntity { return AccompanyHistEntity( - 0, - entity.accompanyId, - entity.userId, - entity.title, - entity.content, - entity.accompanyStatusCd, - entity.startTripDate, - entity.endTripDate, - entity.bannerImageUrl, - entity.accompanyCnt, - ExecCd.UPDATE.execCd + 0, + entity.accompanyId, + entity.userId, + entity.title, + entity.content, + entity.accompanyStatusCd, + entity.startTripDate, + entity.endTripDate, + entity.bannerImageUrl, + entity.accompanyCnt, + ExecCd.UPDATE.execCd ) } - fun toTagEntity(accompanyId : Long) : List? { + fun toTagEntity(accompanyId: Long): List? { - if(tags == null){ + if (tags == null) { return null } val tagList = mutableListOf() - for(tagNm in tags){ + for (tagNm in tags) { tagList.add(AccompanyTagEntity(0, accompanyId, tagNm)) } @@ -187,30 +184,48 @@ class ModifyAccompanyDTO( } } -data class GetDTO ( +data class GetDTO( - var accompanyId : Long, + var accompanyId: Long, var userId: Long, var title: String, var content: String, var continent: String, - var country : String? = null, - var city : String? = null, + var country: String? = null, + var city: String? = null, var startTripDate: LocalDateTime, var endTripDate: LocalDateTime, var bannerImageUrl: String? = null, - var accompanyCnt : Long, - var viewCnt : Long, - var likeCnt : Long, - var tags : List? = null, - var openKakaoUrl : String - -){ - constructor(accompanyId : Long, userId : Long, title: String, content : String, - continent : String, country : String?, city : String?, - startTripDate : LocalDateTime, endTripDate : LocalDateTime, - bannerImageUrl: String?, accompanyCnt: Long, viewCnt: Long, likeCnt: Long, openKakaoUrl: String) : - this(accompanyId, userId, title, content, continent, country, city, startTripDate, endTripDate, bannerImageUrl, accompanyCnt, viewCnt, likeCnt, null, openKakaoUrl) + var accompanyCnt: Long, + var viewCnt: Long, + var likeCnt: Long, + var tags: List? = null, + var openKakaoUrl: String + +) { + constructor( + accompanyId: Long, userId: Long, title: String, content: String, + continent: String, country: String?, city: String?, + startTripDate: LocalDateTime, endTripDate: LocalDateTime, + bannerImageUrl: String?, accompanyCnt: Long, viewCnt: Long, likeCnt: Long, openKakaoUrl: String + ) : + this( + accompanyId, + userId, + title, + content, + continent, + country, + city, + startTripDate, + endTripDate, + bannerImageUrl, + accompanyCnt, + viewCnt, + likeCnt, + null, + openKakaoUrl + ) } data class SearchAccompanyDTO( @@ -223,13 +238,13 @@ data class SearchAccompanyDTO( var endTripDate: LocalDate,//동행 모집 마감일시 - var pageIndex : Long, + var pageIndex: Long, - var pageSize : Long + var pageSize: Long -){ - fun getCurrentPage() : Long{ - return (this.pageIndex -1) * this.pageSize +) { + fun getCurrentPage(): Long { + return (this.pageIndex - 1) * this.pageSize } } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyEntity.kt index 51ffede..84d6934 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyEntity.kt @@ -3,7 +3,6 @@ package com.travel.withaeng.domain.accompany import com.travel.withaeng.domain.AccompanyBaseEntity import jakarta.persistence.* import org.hibernate.annotations.DynamicUpdate -import java.time.LocalDate import java.time.LocalDateTime @DynamicUpdate @@ -27,7 +26,7 @@ class AccompanyEntity( var content: String, @Column(name = "accompany_status_cd", nullable = false) - var accompanyStatusCd : String, + var accompanyStatusCd: String, @Column(name = "start_trip_date", nullable = false) var startTripDate: LocalDateTime, @@ -41,4 +40,4 @@ class AccompanyEntity( @Column(name = "accompany_cnt", nullable = false) var accompanyCnt: Long = 0L, - ) : AccompanyBaseEntity() \ No newline at end of file + ) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt index cd8ff90..d2dca8d 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt @@ -2,47 +2,46 @@ package com.travel.withaeng.domain.accompany import com.travel.withaeng.domain.AccompanyBaseEntity import jakarta.persistence.* -import java.time.LocalDate import java.time.LocalDateTime @Table(name = "accompany_hist") @Entity -class AccompanyHistEntity ( +class AccompanyHistEntity( - @Id + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "hist_id", nullable = false) val histId: Long, - @Column(name = "accompany_id", nullable = false) + @Column(name = "accompany_id", nullable = false) val accompanyId: Long, - @Column(name = "user_id", nullable = false) + @Column(name = "user_id", nullable = false) val userId: Long, - @Column(name = "title", nullable = false) + @Column(name = "title", nullable = false) var title: String, - @Lob + @Lob @Column(name = "content", nullable = false) var content: String, - @Column(name = "accompany_status_cd", nullable = false) - var accompanyStatusCd : String, + @Column(name = "accompany_status_cd", nullable = false) + var accompanyStatusCd: String, - @Column(name = "start_trip_date", nullable = false) + @Column(name = "start_trip_date", nullable = false) var startTripDate: LocalDateTime, - @Column(name = "end_trip_date", nullable = false) + @Column(name = "end_trip_date", nullable = false) var endTripDate: LocalDateTime, - @Column(name = "banner_image_url") + @Column(name = "banner_image_url") var bannerImageUrl: String?, - @Column(name = "accompany_cnt", nullable = false) + @Column(name = "accompany_cnt", nullable = false) var accompanyCnt: Long = 0L, - @Column(name = "exec_cd", nullable = false) - val execCd : String + @Column(name = "exec_cd", nullable = false) + val execCd: String ) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistRepository.kt index dca16f2..e4b558b 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistRepository.kt @@ -2,5 +2,4 @@ package com.travel.withaeng.domain.accompany import org.springframework.data.jpa.repository.JpaRepository -interface AccompanyHistRepository : JpaRepository { -} \ No newline at end of file +interface AccompanyHistRepository : JpaRepository \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt index 6119829..7fa84bf 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt @@ -1,13 +1,9 @@ package com.travel.withaeng.domain.accompany -import org.springframework.data.domain.Page -import org.springframework.data.domain.Pageable -import org.springframework.data.domain.Sort import org.springframework.data.jpa.repository.JpaRepository -import java.time.LocalDate interface AccompanyRepository : JpaRepository, AccompanyRepositoryCustom { - fun findByAccompanyId(accompanyId : Long) : AccompanyEntity? + fun findByAccompanyId(accompanyId: Long): AccompanyEntity? } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustom.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustom.kt index ffff7b8..b931b1a 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustom.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustom.kt @@ -1,10 +1,8 @@ package com.travel.withaeng.domain.accompany -import org.springframework.data.querydsl.QuerydslPredicateExecutor - interface AccompanyRepositoryCustom { - fun getAccompany(accompanyId : Long) : GetDTO? + fun getAccompany(accompanyId: Long): GetDTO? - fun getAccompanyList(param : SearchAccompanyDTO) : List + fun getAccompanyList(param: SearchAccompanyDTO): List } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt index c731abd..fc16f17 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt @@ -4,68 +4,70 @@ import com.querydsl.core.BooleanBuilder import com.querydsl.core.types.Order import com.querydsl.core.types.OrderSpecifier import com.querydsl.core.types.Projections -import com.querydsl.core.types.dsl.BooleanExpression -import com.querydsl.core.types.dsl.DateTimeExpression -import com.querydsl.core.types.dsl.Expressions import com.querydsl.jpa.impl.JPAQueryFactory import org.springframework.stereotype.Repository -import java.time.LocalDateTime import java.time.LocalTime @Repository -class AccompanyRepositoryCustomImpl (val jpaQueryFactory: JPAQueryFactory) : AccompanyRepositoryCustom { +class AccompanyRepositoryCustomImpl(val jpaQueryFactory: JPAQueryFactory) : AccompanyRepositoryCustom { - override fun getAccompany(accompanyId : Long) : GetDTO? { + override fun getAccompany(accompanyId: Long): GetDTO? { return jpaQueryFactory - .select(Projections.constructor(GetDTO::class.java, - QAccompanyEntity.accompanyEntity.accompanyId, - QAccompanyEntity.accompanyEntity.userId, - QAccompanyEntity.accompanyEntity.title, - QAccompanyEntity.accompanyEntity.content, - QAccompanyDestinationEntity.accompanyDestinationEntity.continent, - QAccompanyDestinationEntity.accompanyDestinationEntity.country, - QAccompanyDestinationEntity.accompanyDestinationEntity.city, - QAccompanyEntity.accompanyEntity.startTripDate, - QAccompanyEntity.accompanyEntity.endTripDate, - QAccompanyEntity.accompanyEntity.bannerImageUrl, - QAccompanyEntity.accompanyEntity.accompanyCnt, - QAccompanyDetailEntity.accompanyDetailEntity.viewCnt, - QAccompanyDetailEntity.accompanyDetailEntity.likeCnt, - QAccompanyDetailEntity.accompanyDetailEntity.openKakaoUrl - )) + .select( + Projections.constructor( + GetDTO::class.java, + QAccompanyEntity.accompanyEntity.accompanyId, + QAccompanyEntity.accompanyEntity.userId, + QAccompanyEntity.accompanyEntity.title, + QAccompanyEntity.accompanyEntity.content, + QAccompanyDestinationEntity.accompanyDestinationEntity.continent, + QAccompanyDestinationEntity.accompanyDestinationEntity.country, + QAccompanyDestinationEntity.accompanyDestinationEntity.city, + QAccompanyEntity.accompanyEntity.startTripDate, + QAccompanyEntity.accompanyEntity.endTripDate, + QAccompanyEntity.accompanyEntity.bannerImageUrl, + QAccompanyEntity.accompanyEntity.accompanyCnt, + QAccompanyDetailEntity.accompanyDetailEntity.viewCnt, + QAccompanyDetailEntity.accompanyDetailEntity.likeCnt, + QAccompanyDetailEntity.accompanyDetailEntity.openKakaoUrl + ) + ) .from(QAccompanyEntity.accompanyEntity) - .innerJoin(QAccompanyDestinationEntity.accompanyDestinationEntity) - .on(QAccompanyDestinationEntity.accompanyDestinationEntity.accompanyId.eq(QAccompanyEntity.accompanyEntity.accompanyId)) - .innerJoin(QAccompanyDetailEntity.accompanyDetailEntity) - .on(QAccompanyDetailEntity.accompanyDetailEntity.accompanyId.eq(QAccompanyEntity.accompanyEntity.accompanyId)) + .innerJoin(QAccompanyDestinationEntity.accompanyDestinationEntity) + .on(QAccompanyDestinationEntity.accompanyDestinationEntity.accompanyId.eq(QAccompanyEntity.accompanyEntity.accompanyId)) + .innerJoin(QAccompanyDetailEntity.accompanyDetailEntity) + .on(QAccompanyDetailEntity.accompanyDetailEntity.accompanyId.eq(QAccompanyEntity.accompanyEntity.accompanyId)) .where(QAccompanyEntity.accompanyEntity.accompanyId.eq(accompanyId)) .fetchOne() } - override fun getAccompanyList(param : SearchAccompanyDTO) : List{ - println("currentPage:" + param.getCurrentPage()); + override fun getAccompanyList(param: SearchAccompanyDTO): List { + println("currentPage:" + param.getCurrentPage()) return jpaQueryFactory - .select(Projections.constructor(GetDTO::class.java, - QAccompanyEntity.accompanyEntity.accompanyId, - QAccompanyEntity.accompanyEntity.userId, - QAccompanyEntity.accompanyEntity.title, - QAccompanyEntity.accompanyEntity.content, - QAccompanyDestinationEntity.accompanyDestinationEntity.continent, - QAccompanyDestinationEntity.accompanyDestinationEntity.country, - QAccompanyDestinationEntity.accompanyDestinationEntity.city, - QAccompanyEntity.accompanyEntity.startTripDate, - QAccompanyEntity.accompanyEntity.endTripDate, - QAccompanyEntity.accompanyEntity.bannerImageUrl, - QAccompanyEntity.accompanyEntity.accompanyCnt, - QAccompanyDetailEntity.accompanyDetailEntity.viewCnt, - QAccompanyDetailEntity.accompanyDetailEntity.likeCnt, - QAccompanyDetailEntity.accompanyDetailEntity.openKakaoUrl - )) + .select( + Projections.constructor( + GetDTO::class.java, + QAccompanyEntity.accompanyEntity.accompanyId, + QAccompanyEntity.accompanyEntity.userId, + QAccompanyEntity.accompanyEntity.title, + QAccompanyEntity.accompanyEntity.content, + QAccompanyDestinationEntity.accompanyDestinationEntity.continent, + QAccompanyDestinationEntity.accompanyDestinationEntity.country, + QAccompanyDestinationEntity.accompanyDestinationEntity.city, + QAccompanyEntity.accompanyEntity.startTripDate, + QAccompanyEntity.accompanyEntity.endTripDate, + QAccompanyEntity.accompanyEntity.bannerImageUrl, + QAccompanyEntity.accompanyEntity.accompanyCnt, + QAccompanyDetailEntity.accompanyDetailEntity.viewCnt, + QAccompanyDetailEntity.accompanyDetailEntity.likeCnt, + QAccompanyDetailEntity.accompanyDetailEntity.openKakaoUrl + ) + ) .from(QAccompanyEntity.accompanyEntity) - .innerJoin(QAccompanyDestinationEntity.accompanyDestinationEntity) - .on(QAccompanyDestinationEntity.accompanyDestinationEntity.accompanyId.eq(QAccompanyEntity.accompanyEntity.accompanyId)) - .innerJoin(QAccompanyDetailEntity.accompanyDetailEntity) - .on(QAccompanyDetailEntity.accompanyDetailEntity.accompanyId.eq(QAccompanyEntity.accompanyEntity.accompanyId)) + .innerJoin(QAccompanyDestinationEntity.accompanyDestinationEntity) + .on(QAccompanyDestinationEntity.accompanyDestinationEntity.accompanyId.eq(QAccompanyEntity.accompanyEntity.accompanyId)) + .innerJoin(QAccompanyDetailEntity.accompanyDetailEntity) + .on(QAccompanyDetailEntity.accompanyDetailEntity.accompanyId.eq(QAccompanyEntity.accompanyEntity.accompanyId)) .where(listWhere(param, QAccompanyEntity.accompanyEntity)) .orderBy(listOrder(param)) .offset(param.getCurrentPage()) @@ -73,7 +75,7 @@ class AccompanyRepositoryCustomImpl (val jpaQueryFactory: JPAQueryFactory) : Acc .fetch() } - fun listWhere(param : SearchAccompanyDTO, accompanyEntity : QAccompanyEntity) : BooleanBuilder { + fun listWhere(param: SearchAccompanyDTO, accompanyEntity: QAccompanyEntity): BooleanBuilder { val builder = BooleanBuilder() @@ -86,12 +88,12 @@ class AccompanyRepositoryCustomImpl (val jpaQueryFactory: JPAQueryFactory) : Acc return builder } - fun listOrder(param : SearchAccompanyDTO) : OrderSpecifier<*> { + fun listOrder(param: SearchAccompanyDTO): OrderSpecifier<*> { if (param.likeCntOrder) { return OrderSpecifier(Order.DESC, QAccompanyDetailEntity.accompanyDetailEntity.likeCnt) - } else if(param.viewCntOrder) { + } else if (param.viewCntOrder) { return OrderSpecifier(Order.DESC, QAccompanyDetailEntity.accompanyDetailEntity.viewCnt) - }else { + } else { return OrderSpecifier(Order.DESC, QAccompanyEntity.accompanyEntity.updatedAt) } } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt index 00ed1b7..8ccc1a3 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt @@ -2,10 +2,8 @@ package com.travel.withaeng.domain.accompany import com.travel.withaeng.common.exception.InvalidAccessException import com.travel.withaeng.common.exception.NotExistsException -import com.travel.withaeng.domain.accompany.QAccompanyEntity.accompanyEntity import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional -import java.time.LocalDateTime import java.time.LocalTime @Service @@ -13,15 +11,15 @@ import java.time.LocalTime class AccompanyService( private val accompanyRepository: AccompanyRepository, - private val accompanyHistRepository : AccompanyHistRepository, - private val accompanyDestinationRepository : AccompanyDestinationRepository, - private val accompanyDetailRepository : AccompanyDetailRepository, + private val accompanyHistRepository: AccompanyHistRepository, + private val accompanyDestinationRepository: AccompanyDestinationRepository, + private val accompanyDetailRepository: AccompanyDetailRepository, private val accompanyTagRepository: AccompanyTagRepository ) { @Transactional - fun createAccompany(param : CreateAccompanyDTO) : GetDTO { + fun createAccompany(param: CreateAccompanyDTO): GetDTO { val accompanyEntity = param.toEntity() accompanyRepository.save(accompanyEntity) @@ -34,7 +32,7 @@ class AccompanyService( accompanyDestinationRepository.save(accompanyDestinationEntity) accompanyDetailRepository.save(accompanyDetailEntity) - if(accompanyTagEntityList != null){ + if (accompanyTagEntityList != null) { accompanyTagRepository.saveAll(accompanyTagEntityList) } @@ -42,13 +40,13 @@ class AccompanyService( } @Transactional - fun modifyAccompany(param : ModifyAccompanyDTO) : GetDTO { + fun modifyAccompany(param: ModifyAccompanyDTO): GetDTO { val accompanyEntity = accompanyRepository.findByAccompanyId(param.accompanyId) - if(accompanyEntity != null){ + if (accompanyEntity != null) { - if(accompanyEntity.userId != param.userId){ + if (accompanyEntity.userId != param.userId) { throw InvalidAccessException("등록자와 수정자가 달라 수정 요청을 거부 합니다.") } @@ -78,7 +76,7 @@ class AccompanyService( accompanyHistRepository.save(accompanyHistEntity) accompanyTagRepository.deleteByAccompanyId(accompanyEntity.accompanyId) - if(accompanyTagEntityList != null){ + if (accompanyTagEntityList != null) { accompanyTagRepository.saveAll(accompanyTagEntityList) } @@ -87,12 +85,12 @@ class AccompanyService( return getOne(param.accompanyId) } - fun getOne(param : Long) : GetDTO { + fun getOne(param: Long): GetDTO { val getAccompany = accompanyRepository.getAccompany(param) - if(getAccompany != null){ - val tagList:List? = accompanyTagRepository.findByAccompanyId(param)?.map(AccompanyTagEntity::tagNm) + if (getAccompany != null) { + val tagList: List? = accompanyTagRepository.findByAccompanyId(param)?.map(AccompanyTagEntity::tagNm) getAccompany.tags = tagList return getAccompany } @@ -100,12 +98,12 @@ class AccompanyService( throw NotExistsException("존재하지 않는 동행 게시글 조회 요청 입니다.") } - fun getList(param : SearchAccompanyDTO) : List { - return accompanyRepository.getAccompanyList(param) + fun getList(param: SearchAccompanyDTO): List { + return accompanyRepository.getAccompanyList(param) } @Transactional - fun incrViewCnt(param : Long) { + fun incrViewCnt(param: Long) { val accompanyDetailEntity = accompanyDetailRepository.findByAccompanyId(param) accompanyDetailEntity.let { it.viewCnt++ @@ -113,7 +111,7 @@ class AccompanyService( } @Transactional - fun decrViewCnt(param : Long){ + fun decrViewCnt(param: Long) { val accompanyDetailEntity = accompanyDetailRepository.findByAccompanyId(param) accompanyDetailEntity.let { it.viewCnt-- diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagEntity.kt index a59cbd5..9dcf775 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagEntity.kt @@ -5,17 +5,17 @@ import jakarta.persistence.* @Table(name = "accompany_tag") @Entity -class AccompanyTagEntity ( +class AccompanyTagEntity( - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "tag_id", nullable = false) - val tagId : Long, + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "tag_id", nullable = false) + val tagId: Long, - @Column(name = "accompany_id", nullable = false) - val accompanyId : Long, + @Column(name = "accompany_id", nullable = false) + val accompanyId: Long, - @Column(name = "tag_nm", nullable = false) - val tagNm : String + @Column(name = "tag_nm", nullable = false) + val tagNm: String ) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagRepository.kt index 1822809..101c07f 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagRepository.kt @@ -4,7 +4,7 @@ import org.springframework.data.jpa.repository.JpaRepository interface AccompanyTagRepository : JpaRepository { - fun findByAccompanyId(accompanyId : Long) : List? + fun findByAccompanyId(accompanyId: Long): List? fun deleteByAccompanyId(accompanyId: Long) } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeDto.kt index cc53b50..c01c9fc 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeDto.kt @@ -5,8 +5,7 @@ import lombok.Getter import lombok.Setter import org.jetbrains.annotations.NotNull -class AccompanyLikeDto { -} +class AccompanyLikeDto @Setter @Getter @@ -18,7 +17,7 @@ class CreateAccompanyLikeDTO( @NotNull val accompanyId: Long, -){ + ) { fun toEntity(): AccompanyLikeEntity { return AccompanyLikeEntity( 0, @@ -44,7 +43,7 @@ class CreateAccompanyLikeDTO( class DeleteAccompanyLikeDTO( @NotNull - val likeId : Long, + val likeId: Long, @NotNull val userId: Long, @@ -52,7 +51,7 @@ class DeleteAccompanyLikeDTO( @NotNull val accompanyId: Long, - ){ + ) { fun toEntity(): AccompanyLikeEntity { return AccompanyLikeEntity( this.likeId, diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeEntity.kt index cd25b78..4c51695 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeEntity.kt @@ -18,4 +18,4 @@ class AccompanyLikeEntity( @Column(name = "user_id", nullable = false) val userId: Long, -) : AccompanyBaseEntity() \ No newline at end of file + ) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistEntity.kt index a7580fb..5e43c5e 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistEntity.kt @@ -5,7 +5,7 @@ import jakarta.persistence.* @Table(name = "accompany_like_hist") @Entity -class AccompanyLikeHistEntity ( +class AccompanyLikeHistEntity( @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -22,6 +22,6 @@ class AccompanyLikeHistEntity ( val accompanyId: Long, @Column(name = "exec_cd", nullable = false) - val execCd : String + val execCd: String ) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt index 0a2d18f..40fee2d 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt @@ -10,13 +10,13 @@ import java.time.LocalDateTime class AccompanyLikeService( private val accompanyLikeRepository: AccompanyLikeRepository, - private val accompanyLikeHistRepository : AccompanyLikeHistRepository, + private val accompanyLikeHistRepository: AccompanyLikeHistRepository, private val accompanyDetailRepository: AccompanyDetailRepository ) { @Transactional - fun createAccompanyLike(param : CreateAccompanyLikeDTO) : CreateAccompanyLikeDTO { + fun createAccompanyLike(param: CreateAccompanyLikeDTO): CreateAccompanyLikeDTO { val accompanyLikeEntity = param.toEntity() accompanyLikeRepository.save(accompanyLikeEntity) @@ -34,7 +34,7 @@ class AccompanyLikeService( //TODO delete 성능이 안나올 경우 boolean 형으로 좋아요 제어 @Transactional - fun deleteAccompanyLike(param : DeleteAccompanyLikeDTO) : DeleteAccompanyLikeDTO{ + fun deleteAccompanyLike(param: DeleteAccompanyLikeDTO): DeleteAccompanyLikeDTO { val accompanyLikeEntity = param.toEntity() accompanyLikeRepository.delete(accompanyLikeEntity) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt index 3290743..cae9344 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt @@ -1,20 +1,12 @@ package com.travel.withaeng.domain.accompanyreply import com.travel.withaeng.common.cd.ExecCd -import com.travel.withaeng.domain.accompany.AccompanyDestinationEntity -import com.travel.withaeng.domain.accompany.AccompanyDetailEntity -import com.travel.withaeng.domain.accompany.AccompanyEntity -import com.travel.withaeng.domain.accompanylike.AccompanyLikeEntity -import com.travel.withaeng.domain.accompanylike.AccompanyLikeHistEntity -import jakarta.persistence.Column import jakarta.validation.constraints.NotBlank import lombok.Getter import lombok.Setter import org.jetbrains.annotations.NotNull -import java.time.LocalDate -class AccompanyReplyDto { -} +class AccompanyReplyDto @Setter @Getter @@ -27,41 +19,41 @@ class CreateAccompanyReplyDTO( val accompanyId: Long, @NotNull - val parentId : Long, + val parentId: Long, @NotNull - val depth : Long, + val depth: Long, @NotNull - val replyOrder : Long, + val replyOrder: Long, @NotBlank(message = "댓글 내용이 존재하지 않습니다.") var content: String, - ){ + ) { fun toEntity(): AccompanyReplyEntity { return AccompanyReplyEntity( - 0, - this.accompanyId, - this.parentId, - this.depth, - this.replyOrder, - this.userId, - this.content + 0, + this.accompanyId, + this.parentId, + this.depth, + this.replyOrder, + this.userId, + this.content ) } fun toHistEntity(entity: AccompanyReplyEntity): AccompanyReplyHistEntity { return AccompanyReplyHistEntity( - 0, - entity.replyId, - entity.accompanyId, - entity.parentId, - entity.depth, - entity.replyOrder, - entity.userId, - entity.content, - ExecCd.CREATE.execCd + 0, + entity.replyId, + entity.accompanyId, + entity.parentId, + entity.depth, + entity.replyOrder, + entity.userId, + entity.content, + ExecCd.CREATE.execCd ) } @@ -71,51 +63,51 @@ class CreateAccompanyReplyDTO( @Getter class ModifyAccompanyReplyDTO( - @NotNull - val replyId : Long, + @NotNull + val replyId: Long, - @NotNull - val userId: Long, + @NotNull + val userId: Long, - @NotNull - val accompanyId: Long, + @NotNull + val accompanyId: Long, - @NotNull - val parentId : Long, + @NotNull + val parentId: Long, - @NotNull - val depth : Long, + @NotNull + val depth: Long, - @NotNull - val replyOrder : Long, + @NotNull + val replyOrder: Long, - @NotBlank(message = "댓글 내용이 존재하지 않습니다.") - var content: String, + @NotBlank(message = "댓글 내용이 존재하지 않습니다.") + var content: String, - ){ + ) { fun toEntity(): AccompanyReplyEntity { return AccompanyReplyEntity( - 0, - this.accompanyId, - this.parentId, - this.depth, - this.replyOrder, - this.userId, - this.content + 0, + this.accompanyId, + this.parentId, + this.depth, + this.replyOrder, + this.userId, + this.content ) } fun toHistEntity(entity: AccompanyReplyEntity): AccompanyReplyHistEntity { return AccompanyReplyHistEntity( - 0, - entity.replyId, - entity.accompanyId, - entity.parentId, - entity.depth, - entity.replyOrder, - entity.userId, - entity.content, - ExecCd.UPDATE.execCd + 0, + entity.replyId, + entity.accompanyId, + entity.parentId, + entity.depth, + entity.replyOrder, + entity.userId, + entity.content, + ExecCd.UPDATE.execCd ) } @@ -125,28 +117,28 @@ class ModifyAccompanyReplyDTO( @Getter class DeleteAccompanyReplyDTO( - @NotNull - val replyId : Long, + @NotNull + val replyId: Long, - @NotNull - val userId: Long, + @NotNull + val userId: Long, - @NotNull - val accompanyId: Long + @NotNull + val accompanyId: Long - ){ +) { fun toHistEntity(entity: AccompanyReplyEntity): AccompanyReplyHistEntity { return AccompanyReplyHistEntity( - 0, - entity.replyId, - entity.accompanyId, - entity.parentId, - entity.depth, - entity.replyOrder, - entity.userId, - entity.content, - ExecCd.DELETE.execCd + 0, + entity.replyId, + entity.accompanyId, + entity.parentId, + entity.depth, + entity.replyOrder, + entity.userId, + entity.content, + ExecCd.DELETE.execCd ) } @@ -154,27 +146,29 @@ class DeleteAccompanyReplyDTO( data class GetReplyDTO( - var replyId : Long, - var userId: Long, - var accompanyId: Long, - var parentId : Long, - var depth : Long, - var replyOrder : Long, - var content: String, - var likeCnt : Long -){ - - constructor(replyId : Long, userId : Long, accompanyId: Long, parentId : Long, - depth : Long, replyOrder : Long, content : String) : + var replyId: Long, + var userId: Long, + var accompanyId: Long, + var parentId: Long, + var depth: Long, + var replyOrder: Long, + var content: String, + var likeCnt: Long +) { + + constructor( + replyId: Long, userId: Long, accompanyId: Long, parentId: Long, + depth: Long, replyOrder: Long, content: String + ) : this(replyId, userId, accompanyId, parentId, depth, replyOrder, content, 0) - fun addLikeCnt(cnt: Long){ + fun addLikeCnt(cnt: Long) { likeCnt = cnt } companion object { @JvmStatic - fun toDto(accompanyReplyEntity : AccompanyReplyEntity, likeCnt : Long) : GetReplyDTO { + fun toDto(accompanyReplyEntity: AccompanyReplyEntity, likeCnt: Long): GetReplyDTO { return GetReplyDTO( replyId = accompanyReplyEntity.replyId, userId = accompanyReplyEntity.userId, @@ -184,7 +178,7 @@ data class GetReplyDTO( replyOrder = accompanyReplyEntity.replyOrder, content = accompanyReplyEntity.content, likeCnt = likeCnt - ) + ) } } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyEntity.kt index ff47a3a..739cd4d 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyEntity.kt @@ -15,16 +15,16 @@ class AccompanyReplyEntity( val replyId: Long, @Column(name = "accompany_id", nullable = false) - val accompanyId : Long, + val accompanyId: Long, @Column(name = "parent_id", nullable = false) - val parentId : Long, + val parentId: Long, @Column(name = "depth", nullable = false) - val depth : Long, + val depth: Long, @Column(name = "reply_order", nullable = false) - val replyOrder : Long, + val replyOrder: Long, @Column(name = "user_id", nullable = false) val userId: Long, @@ -32,4 +32,4 @@ class AccompanyReplyEntity( @Column(name = "content", nullable = false) var content: String, -) : AccompanyBaseEntity() \ No newline at end of file + ) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHistEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHistEntity.kt index 8cb5ed7..94b56ce 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHistEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHistEntity.kt @@ -5,27 +5,27 @@ import jakarta.persistence.* @Table(name = "accompany_reply_hist") @Entity -class AccompanyReplyHistEntity ( +class AccompanyReplyHistEntity( - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "hist_id", nullable = false) - val histId: Long, + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "hist_id", nullable = false) + val histId: Long, - @Column(name = "reply_id", nullable = false) - val replyId: Long, + @Column(name = "reply_id", nullable = false) + val replyId: Long, @Column(name = "accompany_id", nullable = false) - val accompanyId : Long, + val accompanyId: Long, @Column(name = "parent_id", nullable = false) - val parentId : Long, + val parentId: Long, @Column(name = "depth", nullable = false) - val depth : Long, + val depth: Long, @Column(name = "reply_order", nullable = false) - val replyOrder : Long, + val replyOrder: Long, @Column(name = "user_id", nullable = false) val userId: Long, @@ -33,7 +33,7 @@ class AccompanyReplyHistEntity ( @Column(name = "content", nullable = false) val content: String, - @Column(name = "exec_cd", nullable = false) - val execCd: String, + @Column(name = "exec_cd", nullable = false) + val execCd: String, -) : AccompanyBaseEntity() \ No newline at end of file + ) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt index 929d188..54687bb 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt @@ -1,9 +1,8 @@ package com.travel.withaeng.domain.accompanyreply -import org.springframework.data.domain.Sort import org.springframework.data.jpa.repository.JpaRepository interface AccompanyReplyRepository : JpaRepository, AccompanyReplyRepositoryCustom { - fun findByReplyId(replyId : Long) : AccompanyReplyEntity? + fun findByReplyId(replyId: Long): AccompanyReplyEntity? } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustom.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustom.kt index 1d609c8..2d37d6b 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustom.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustom.kt @@ -1,9 +1,7 @@ package com.travel.withaeng.domain.accompanyreply -import org.springframework.data.domain.Sort - interface AccompanyReplyRepositoryCustom { - fun getAccompanyReplyList(accompanyId : Long) : List? + fun getAccompanyReplyList(accompanyId: Long): List? } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustomImpl.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustomImpl.kt index 3fc296d..cbdcd89 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustomImpl.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustomImpl.kt @@ -6,23 +6,27 @@ import com.travel.withaeng.domain.accompany.* import org.springframework.stereotype.Repository @Repository -class AccompanyReplyRepositoryCustomImpl (val jpaQueryFactory: JPAQueryFactory) : AccompanyReplyRepositoryCustom { +class AccompanyReplyRepositoryCustomImpl(val jpaQueryFactory: JPAQueryFactory) : AccompanyReplyRepositoryCustom { override fun getAccompanyReplyList(accompanyId: Long): List { return jpaQueryFactory .select( Projections.constructor( GetReplyDTO::class.java, - QAccompanyReplyEntity.accompanyReplyEntity.replyId, - QAccompanyReplyEntity.accompanyReplyEntity.userId, - QAccompanyReplyEntity.accompanyReplyEntity.accompanyId, - QAccompanyReplyEntity.accompanyReplyEntity.parentId, - QAccompanyReplyEntity.accompanyReplyEntity.depth, - QAccompanyReplyEntity.accompanyReplyEntity.replyOrder, - QAccompanyReplyEntity.accompanyReplyEntity.content, - )) + QAccompanyReplyEntity.accompanyReplyEntity.replyId, + QAccompanyReplyEntity.accompanyReplyEntity.userId, + QAccompanyReplyEntity.accompanyReplyEntity.accompanyId, + QAccompanyReplyEntity.accompanyReplyEntity.parentId, + QAccompanyReplyEntity.accompanyReplyEntity.depth, + QAccompanyReplyEntity.accompanyReplyEntity.replyOrder, + QAccompanyReplyEntity.accompanyReplyEntity.content, + ) + ) .from(QAccompanyReplyEntity.accompanyReplyEntity) .where(QAccompanyReplyEntity.accompanyReplyEntity.accompanyId.eq(accompanyId)) - .orderBy(QAccompanyReplyEntity.accompanyReplyEntity.parentId.desc(), QAccompanyReplyEntity.accompanyReplyEntity.depth.desc()) + .orderBy( + QAccompanyReplyEntity.accompanyReplyEntity.parentId.desc(), + QAccompanyReplyEntity.accompanyReplyEntity.depth.desc() + ) .fetch() } } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt index 23007dd..50ba7d1 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt @@ -2,23 +2,22 @@ package com.travel.withaeng.domain.accompanyreply import com.travel.withaeng.common.exception.InvalidAccessException import com.travel.withaeng.common.exception.NotExistsException -import com.travel.withaeng.domain.accompany.AccompanyTagEntity import com.travel.withaeng.domain.accompanyreplylike.AccompanyReplyLikeService import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @Service @Transactional(readOnly = true) -class AccompanyReplyService ( +class AccompanyReplyService( - private val accompanyReplyRepository: AccompanyReplyRepository, - private val accompanyReplyHistRepository : AccompanyReplyHistRepository, - private val accompanyReplyLikeService: AccompanyReplyLikeService + private val accompanyReplyRepository: AccompanyReplyRepository, + private val accompanyReplyHistRepository: AccompanyReplyHistRepository, + private val accompanyReplyLikeService: AccompanyReplyLikeService ) { @Transactional - fun createAccompanyReply(param : CreateAccompanyReplyDTO) : GetReplyDTO { + fun createAccompanyReply(param: CreateAccompanyReplyDTO): GetReplyDTO { val accompanyReplyEntity = param.toEntity() accompanyReplyRepository.save(accompanyReplyEntity) @@ -30,13 +29,13 @@ class AccompanyReplyService ( } @Transactional - fun modifyAccompanyReply(param : ModifyAccompanyReplyDTO) : GetReplyDTO { + fun modifyAccompanyReply(param: ModifyAccompanyReplyDTO): GetReplyDTO { val accompanyReplyEntity = accompanyReplyRepository.findByReplyId(param.replyId) - if(accompanyReplyEntity != null){ + if (accompanyReplyEntity != null) { - if(accompanyReplyEntity.userId != param.userId){ + if (accompanyReplyEntity.userId != param.userId) { throw InvalidAccessException("등록자와 수정자가 달라 수정 요청을 거부 합니다.") } @@ -52,13 +51,13 @@ class AccompanyReplyService ( } @Transactional - fun deleteAccompanyReply(param : DeleteAccompanyReplyDTO) : DeleteAccompanyReplyDTO { + fun deleteAccompanyReply(param: DeleteAccompanyReplyDTO): DeleteAccompanyReplyDTO { val accompanyReplyEntity = accompanyReplyRepository.findByReplyId(param.replyId) - if(accompanyReplyEntity != null){ + if (accompanyReplyEntity != null) { - if(accompanyReplyEntity.userId != param.userId){ + if (accompanyReplyEntity.userId != param.userId) { throw InvalidAccessException("등록자와 수정자가 달라 삭제 요청을 거부 합니다.") } @@ -71,12 +70,12 @@ class AccompanyReplyService ( return param } - fun getOne(param : Long) : GetReplyDTO { + fun getOne(param: Long): GetReplyDTO { val accompanyReplyEntity = accompanyReplyRepository.findByReplyId(param) val accompanyReplyLikeCnt = accompanyReplyLikeService.getAccompanyReplyLikeCnt(param) - if(accompanyReplyEntity != null){ + if (accompanyReplyEntity != null) { return GetReplyDTO.toDto(accompanyReplyEntity, accompanyReplyLikeCnt) } @@ -84,35 +83,36 @@ class AccompanyReplyService ( } //TODO 댓글당 좋아요 누른 userId 목록을 추가로 조회하여 리턴은 추후 처리 - fun getList(param : Long) : List? { + fun getList(param: Long): List? { val accompanyReplyList = accompanyReplyRepository.getAccompanyReplyList(param) - if(accompanyReplyList != null){ + if (accompanyReplyList != null) { - val replyIdList : List = accompanyReplyList.map {accompanyReplyEntity -> accompanyReplyEntity.replyId}.toList() + val replyIdList: List = + accompanyReplyList.map { accompanyReplyEntity -> accompanyReplyEntity.replyId }.toList() val accompanyReplyLikeList = accompanyReplyLikeService.getAccompanyReplyLikeList(replyIdList) - for(reply in accompanyReplyList){ - for(like in accompanyReplyLikeList){ - if(reply.replyId == like.replyId){ + for (reply in accompanyReplyList) { + for (like in accompanyReplyLikeList) { + if (reply.replyId == like.replyId) { reply.likeCnt = like.likeCnt } } } - val parentList = accompanyReplyList.stream().filter{ - e-> e.parentId.equals(0L) + val parentList = accompanyReplyList.stream().filter { e -> + e.parentId.equals(0L) }.toList() - val sortList = accompanyReplyList.sortedWith(compareBy({it.parentId},{it.depth}, {it.replyOrder})).toList() + val sortList = + accompanyReplyList.sortedWith(compareBy({ it.parentId }, { it.depth }, { it.replyOrder })).toList() val resultList = mutableListOf() - parentList.stream().forEach{ - e-> + parentList.stream().forEach { e -> resultList.add(e) - sortList.forEach{a-> - if(e.replyId.equals(a.parentId)){ + sortList.forEach { a -> + if (e.replyId.equals(a.parentId)) { resultList.add(a) } } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeDto.kt index bf5995f..993daf8 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeDto.kt @@ -5,35 +5,34 @@ import lombok.Getter import lombok.Setter import org.jetbrains.annotations.NotNull -class AccompanyReplyLikeDto { -} +class AccompanyReplyLikeDto @Setter @Getter class CreateAccompanyReplyLikeDTO( - @NotNull - val replyId: Long, + @NotNull + val replyId: Long, - @NotNull - val userId: Long, + @NotNull + val userId: Long, - ){ + ) { fun toEntity(): AccompanyReplyLikeEntity { return AccompanyReplyLikeEntity( - 0, - this.replyId, - this.userId + 0, + this.replyId, + this.userId ) } fun toHistEntity(entity: AccompanyReplyLikeEntity): AccompanyReplyLikeHistEntity { return AccompanyReplyLikeHistEntity( - 0, - entity.replyLikeId, - entity.replyId, - entity.userId, - ExecCd.CREATE.execCd + 0, + entity.replyLikeId, + entity.replyId, + entity.userId, + ExecCd.CREATE.execCd ) } @@ -43,31 +42,31 @@ class CreateAccompanyReplyLikeDTO( @Getter class DeleteAccompanyReplyLikeDTO( - @NotNull - val replyLikeId: Long, + @NotNull + val replyLikeId: Long, - @NotNull - val replyId: Long, + @NotNull + val replyId: Long, - @NotNull - val userId: Long + @NotNull + val userId: Long - ){ +) { fun toEntity(): AccompanyReplyLikeEntity { return AccompanyReplyLikeEntity( - this.replyLikeId, - this.replyId, - this.userId + this.replyLikeId, + this.replyId, + this.userId ) } fun toHistEntity(entity: AccompanyReplyLikeEntity): AccompanyReplyLikeHistEntity { return AccompanyReplyLikeHistEntity( - 0, - entity.replyLikeId, - entity.replyId, - entity.userId, - ExecCd.DELETE.execCd + 0, + entity.replyLikeId, + entity.replyId, + entity.userId, + ExecCd.DELETE.execCd ) } @@ -75,6 +74,6 @@ class DeleteAccompanyReplyLikeDTO( data class GetReplyLikeDTO( - var replyId : Long, - var likeCnt : Long + var replyId: Long, + var likeCnt: Long ) \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHistEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHistEntity.kt index 7c769a7..7c08dc0 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHistEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHistEntity.kt @@ -1,28 +1,27 @@ package com.travel.withaeng.domain.accompanyreplylike -import com.travel.withaeng.common.cd.ExecCd import com.travel.withaeng.domain.AccompanyBaseEntity import jakarta.persistence.* @Table(name = "accompany_reply_like_hist") @Entity -class AccompanyReplyLikeHistEntity ( +class AccompanyReplyLikeHistEntity( - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "hist_id", nullable = false) - val histId: Long, + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "hist_id", nullable = false) + val histId: Long, - @Column(name = "reply_like_id", nullable = false) - val replyLikeId: Long, + @Column(name = "reply_like_id", nullable = false) + val replyLikeId: Long, - @Column(name = "reply_id", nullable = false) - val replyId: Long, + @Column(name = "reply_id", nullable = false) + val replyId: Long, - @Column(name = "user_id", nullable = false) - val userId: Long, + @Column(name = "user_id", nullable = false) + val userId: Long, - @Column(name = "exec_cd", nullable = false) - val execCd : String + @Column(name = "exec_cd", nullable = false) + val execCd: String ) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt index 86c7239..4591797 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt @@ -1,11 +1,11 @@ package com.travel.withaeng.domain.accompanyreplylike import org.springframework.data.jpa.repository.JpaRepository -import org.springframework.data.jpa.repository.Query -interface AccompanyReplyLikeRepository : JpaRepository, AccompanyReplyLikeRepositoryCustom{ +interface AccompanyReplyLikeRepository : JpaRepository, + AccompanyReplyLikeRepositoryCustom { - fun countByReplyId(replyId: Long) : Long + fun countByReplyId(replyId: Long): Long - fun findByReplyIdAndUserId(replyId: Long, userId:Long) : AccompanyReplyLikeEntity? + fun findByReplyIdAndUserId(replyId: Long, userId: Long): AccompanyReplyLikeEntity? } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepositoryCustom.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepositoryCustom.kt index 9371eb2..9412acb 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepositoryCustom.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepositoryCustom.kt @@ -1,9 +1,7 @@ package com.travel.withaeng.domain.accompanyreplylike -import com.travel.withaeng.domain.accompanyreply.GetReplyDTO - interface AccompanyReplyLikeRepositoryCustom { - fun getAccompanyReplyLikeList(replyIds : List) : List + fun getAccompanyReplyLikeList(replyIds: List): List } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepositoryCustomImpl.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepositoryCustomImpl.kt index 7513e8e..8c2b9fe 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepositoryCustomImpl.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepositoryCustomImpl.kt @@ -5,7 +5,8 @@ import com.querydsl.jpa.impl.JPAQueryFactory import org.springframework.stereotype.Repository @Repository -class AccompanyReplyLikeRepositoryCustomImpl(val jpaQueryFactory: JPAQueryFactory) : AccompanyReplyLikeRepositoryCustom { +class AccompanyReplyLikeRepositoryCustomImpl(val jpaQueryFactory: JPAQueryFactory) : + AccompanyReplyLikeRepositoryCustom { override fun getAccompanyReplyLikeList(replyIds: List): List { return jpaQueryFactory .select( @@ -13,7 +14,8 @@ class AccompanyReplyLikeRepositoryCustomImpl(val jpaQueryFactory: JPAQueryFactor GetReplyLikeDTO::class.java, QAccompanyReplyLikeEntity.accompanyReplyLikeEntity.replyId, QAccompanyReplyLikeEntity.accompanyReplyLikeEntity.replyId.count() - )) + ) + ) .from(QAccompanyReplyLikeEntity.accompanyReplyLikeEntity) .where(QAccompanyReplyLikeEntity.accompanyReplyLikeEntity.replyId.`in`(replyIds)) .groupBy(QAccompanyReplyLikeEntity.accompanyReplyLikeEntity.replyId) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt index b71889d..cd04369 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt @@ -1,29 +1,24 @@ package com.travel.withaeng.domain.accompanyreplylike import com.travel.withaeng.common.exception.InvalidAccessException -import com.travel.withaeng.domain.accompany.AccompanyDetailRepository -import com.travel.withaeng.domain.accompanylike.AccompanyLikeHistRepository -import com.travel.withaeng.domain.accompanylike.AccompanyLikeRepository -import com.travel.withaeng.domain.accompanylike.CreateAccompanyLikeDTO -import com.travel.withaeng.domain.accompanylike.DeleteAccompanyLikeDTO import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional import java.time.LocalDateTime @Service @Transactional(readOnly = true) -class AccompanyReplyLikeService ( +class AccompanyReplyLikeService( - private val accompanyReplyLikeRepository: AccompanyReplyLikeRepository, - private val accompanyReplyLikeHistRepository : AccompanyReplyLikeHistRepository + private val accompanyReplyLikeRepository: AccompanyReplyLikeRepository, + private val accompanyReplyLikeHistRepository: AccompanyReplyLikeHistRepository ) { @Transactional - fun createAccompanyReplyLike(param : CreateAccompanyReplyLikeDTO) : CreateAccompanyReplyLikeDTO { + fun createAccompanyReplyLike(param: CreateAccompanyReplyLikeDTO): CreateAccompanyReplyLikeDTO { val replyLikeEntity = accompanyReplyLikeRepository.findByReplyIdAndUserId(param.replyId, param.userId) - if(replyLikeEntity != null){ + if (replyLikeEntity != null) { throw InvalidAccessException("이미 해당 댓글의 좋아요 등록이 되어 있습니다.") } @@ -38,7 +33,7 @@ class AccompanyReplyLikeService ( //TODO delete 성능이 안나올 경우 boolean 형으로 좋아요 제어 @Transactional - fun deleteAccompanyReplyLike(param : DeleteAccompanyReplyLikeDTO) : DeleteAccompanyReplyLikeDTO{ + fun deleteAccompanyReplyLike(param: DeleteAccompanyReplyLikeDTO): DeleteAccompanyReplyLikeDTO { val accompanyReplyLikeEntity = param.toEntity() accompanyReplyLikeRepository.delete(accompanyReplyLikeEntity) @@ -50,11 +45,11 @@ class AccompanyReplyLikeService ( return param } - fun getAccompanyReplyLikeCnt(param: Long) : Long{ + fun getAccompanyReplyLikeCnt(param: Long): Long { return accompanyReplyLikeRepository.countByReplyId(param) } - fun getAccompanyReplyLikeList(param : List) : List { + fun getAccompanyReplyLikeList(param: List): List { return accompanyReplyLikeRepository.getAccompanyReplyLikeList(param) } } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationDto.kt index 7a47e4b..de03eaa 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationDto.kt @@ -7,9 +7,9 @@ import lombok.Setter @Setter @Getter -class DestinationDto ( +class DestinationDto( - var continentList : List + var continentList: List ) @Setter @@ -17,12 +17,12 @@ class DestinationDto ( @NoArgsConstructor class Continent( - var continentCd : String, - var continentNm : String, - var countryList : List + var continentCd: String, + var continentNm: String, + var countryList: List -){ - constructor(continentCd : String, continentNm : String) : +) { + constructor(continentCd: String, continentNm: String) : this(continentCd, continentNm, mutableListOf()) } @@ -32,12 +32,12 @@ class Continent( @NoArgsConstructor class Country( - var countryCd : String, - var countryNm : String, - var cityList : List -){ + var countryCd: String, + var countryNm: String, + var cityList: List +) { - constructor(countryCd : String, countryNm : String) : + constructor(countryCd: String, countryNm: String) : this(countryCd, countryNm, mutableListOf()) @@ -47,6 +47,6 @@ class Country( @Getter class City( - var cityCd : String, - var cityNm : String, + var cityCd: String, + var cityNm: String, ) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationService.kt index fee981a..9baa835 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationService.kt @@ -8,7 +8,7 @@ import org.springframework.stereotype.Service @Service class DestinationService { - fun getDestinationList() : DestinationDto{ + fun getDestinationList(): DestinationDto { val continentList = mutableListOf() @@ -18,13 +18,13 @@ class DestinationService { val continent = Continent(continentCd.continentCd, continentCd.continentNm) val countryList = mutableListOf() - for(countryCd in CountryCd.entries){ - if(continentCd.continentCd.equals(countryCd.continentCd)){ + for (countryCd in CountryCd.entries) { + if (continentCd.continentCd.equals(countryCd.continentCd)) { val country = Country(countryCd.countryCd, countryCd.countryNm) val cityList = mutableListOf() - for(cityCd in CityCd.entries){ - if(countryCd.countryCd.equals(cityCd.countryCd)){ + for (cityCd in CityCd.entries) { + if (countryCd.countryCd.equals(cityCd.countryCd)) { val city = City(cityCd.cityCd, cityCd.cityNm) cityList.add(city) } @@ -34,7 +34,7 @@ class DestinationService { } } - continent.countryList = countryList; + continent.countryList = countryList // Add the continent to the list continentList.add(continent) } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmail.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmail.kt index c43779b..b315746 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmail.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmail.kt @@ -6,7 +6,7 @@ import jakarta.persistence.* @Table(name = "validating_emails") @Entity class ValidatingEmail( - @Column(name = "email", nullable = false) + @Column(name = "email", nullable = false) val email: String, @Column(name = "user_id", nullable = false) @@ -18,4 +18,4 @@ class ValidatingEmail( @Enumerated(EnumType.STRING) @Column(name = "status", nullable = false) val status: ValidatingEmailStatus = ValidatingEmailStatus.YET -): BaseEntity() \ No newline at end of file +) : BaseEntity() \ No newline at end of file From 24a5c5a9a66bee9cadf50a3f10b8bdc81106962a Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Thu, 9 May 2024 02:29:18 +0900 Subject: [PATCH 061/174] Fix broken codes --- withaeng-domain/build.gradle.kts | 7 ++++--- .../withaeng/domain/accompany/AccompanyDto.kt | 8 -------- .../domain/accompanylike/AccompanyLikeDto.kt | 8 -------- .../domain/accompanyreply/AccompanyReplyDto.kt | 10 ---------- .../AccompanyReplyLikeDto.kt | 6 ------ .../domain/destination/DestinationDto.kt | 14 -------------- .../src/main/resources/application-domain.yml | 18 +++++------------- 7 files changed, 9 insertions(+), 62 deletions(-) diff --git a/withaeng-domain/build.gradle.kts b/withaeng-domain/build.gradle.kts index f90e92b..4ab4b15 100644 --- a/withaeng-domain/build.gradle.kts +++ b/withaeng-domain/build.gradle.kts @@ -9,14 +9,15 @@ val mysqlVersion: String by project.extra dependencies { implementation(project(":withaeng-common")) implementation("org.springframework.boot:spring-boot-starter-data-jpa") - implementation("org.projectlombok:lombok") implementation("org.springframework.boot:spring-boot-starter-validation") + + // Query DSL implementation("com.querydsl:querydsl-jpa:5.0.0:jakarta") kapt("com.querydsl:querydsl-apt:5.0.0:jakarta") + kapt("org.springframework.boot:spring-boot-configuration-processor") + runtimeOnly("com.mysql:mysql-connector-j:$mysqlVersion") - runtimeOnly("com.h2database:h2") - //runtimeOnly("com.mysql:mysql-connector-j:$mysqlVersion") // jasypt api("com.github.ulisesbocchio:jasypt-spring-boot-starter:$jasyptVersion") } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt index b493e0b..bcf1997 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt @@ -4,17 +4,11 @@ import com.fasterxml.jackson.annotation.JsonProperty import com.travel.withaeng.common.cd.AccompanyStatusCd import com.travel.withaeng.common.cd.ExecCd import jakarta.validation.constraints.NotBlank -import lombok.Getter -import lombok.Setter import org.jetbrains.annotations.NotNull import java.time.LocalDate import java.time.LocalDateTime import java.time.LocalTime -class AccompanyDto - -@Setter -@Getter class CreateAccompanyDTO( @NotNull @@ -115,8 +109,6 @@ class CreateAccompanyDTO( } } -@Setter -@Getter class ModifyAccompanyDTO( @NotNull diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeDto.kt index c01c9fc..c02957b 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeDto.kt @@ -1,14 +1,8 @@ package com.travel.withaeng.domain.accompanylike import com.travel.withaeng.common.cd.ExecCd -import lombok.Getter -import lombok.Setter import org.jetbrains.annotations.NotNull -class AccompanyLikeDto - -@Setter -@Getter class CreateAccompanyLikeDTO( @NotNull @@ -38,8 +32,6 @@ class CreateAccompanyLikeDTO( } -@Setter -@Getter class DeleteAccompanyLikeDTO( @NotNull diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt index cae9344..fe386c3 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt @@ -2,14 +2,8 @@ package com.travel.withaeng.domain.accompanyreply import com.travel.withaeng.common.cd.ExecCd import jakarta.validation.constraints.NotBlank -import lombok.Getter -import lombok.Setter import org.jetbrains.annotations.NotNull -class AccompanyReplyDto - -@Setter -@Getter class CreateAccompanyReplyDTO( @NotNull @@ -59,8 +53,6 @@ class CreateAccompanyReplyDTO( } -@Setter -@Getter class ModifyAccompanyReplyDTO( @NotNull @@ -113,8 +105,6 @@ class ModifyAccompanyReplyDTO( } -@Setter -@Getter class DeleteAccompanyReplyDTO( @NotNull diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeDto.kt index 993daf8..c71e6a5 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeDto.kt @@ -1,14 +1,10 @@ package com.travel.withaeng.domain.accompanyreplylike import com.travel.withaeng.common.cd.ExecCd -import lombok.Getter -import lombok.Setter import org.jetbrains.annotations.NotNull class AccompanyReplyLikeDto -@Setter -@Getter class CreateAccompanyReplyLikeDTO( @NotNull @@ -38,8 +34,6 @@ class CreateAccompanyReplyLikeDTO( } -@Setter -@Getter class DeleteAccompanyReplyLikeDTO( @NotNull diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationDto.kt index de03eaa..abc64a7 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationDto.kt @@ -1,20 +1,11 @@ package com.travel.withaeng.domain.destination -import lombok.Getter -import lombok.NoArgsConstructor -import lombok.Setter - -@Setter -@Getter class DestinationDto( var continentList: List ) -@Setter -@Getter -@NoArgsConstructor class Continent( var continentCd: String, @@ -27,9 +18,6 @@ class Continent( } -@Setter -@Getter -@NoArgsConstructor class Country( var countryCd: String, @@ -43,8 +31,6 @@ class Country( } -@Setter -@Getter class City( var cityCd: String, diff --git a/withaeng-domain/src/main/resources/application-domain.yml b/withaeng-domain/src/main/resources/application-domain.yml index 84818ed..4ac5c1c 100644 --- a/withaeng-domain/src/main/resources/application-domain.yml +++ b/withaeng-domain/src/main/resources/application-domain.yml @@ -3,14 +3,10 @@ spring: default: local datasource: - driver-class-name: org.h2.Driver - url: jdbc:h2:~/test - username: user - password: - #driver-class-name: com.mysql.cj.jdbc.Driver - #url: ENC(lFITsL+l7aOSMUY3hRT3aR4X0GV+yqIJfYMyXaMajbZZJSW+Lv5MTrbP5Cwa8XAUxGpH7A9GxRNAZtrDhf6V4yXkD6gf3RUYWsPp77Ieguo=) - #username: ENC(s1UggVxVWnWC0WqrTpmXaLw+QCpZmkuj2kvSQp+zt2vwKLbRH6WDAZKYUR75DqsR) - #password: ENC(HT2z+x9LrfoHTmTTCYLkx7cO0ru9Gcbh+YGnP/0MWC1BpBwQtPfWue+zQx5RPQg8) + driver-class-name: com.mysql.cj.jdbc.Driver + url: ENC(lFITsL+l7aOSMUY3hRT3aR4X0GV+yqIJfYMyXaMajbZZJSW+Lv5MTrbP5Cwa8XAUxGpH7A9GxRNAZtrDhf6V4yXkD6gf3RUYWsPp77Ieguo=) + username: ENC(s1UggVxVWnWC0WqrTpmXaLw+QCpZmkuj2kvSQp+zt2vwKLbRH6WDAZKYUR75DqsR) + password: ENC(HT2z+x9LrfoHTmTTCYLkx7cO0ru9Gcbh+YGnP/0MWC1BpBwQtPfWue+zQx5RPQg8) jpa: hibernate: @@ -19,8 +15,4 @@ spring: hibernate: show_sql: false format_sql: false - use_sql_comments: false - h2: - console: - enabled: true - path: /h2-console \ No newline at end of file + use_sql_comments: false \ No newline at end of file From 49228e93f57716a53104cf2eef01f8f09c056d89 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Thu, 9 May 2024 02:37:52 +0900 Subject: [PATCH 062/174] Remove unnecessary exceptions --- .../auth/AuthApplicationService.kt | 20 +++++++++++++++---- .../common/ControllerExceptionAdvice.kt | 14 ------------- .../exception/InvalidAccessException.kt | 5 ----- .../common/exception/NotExistsException.kt | 5 ----- .../domain/accompany/AccompanyService.kt | 14 +++++++++---- .../accompanyreply/AccompanyReplyService.kt | 19 +++++++++++++----- .../AccompanyReplyLikeService.kt | 8 ++++++-- .../validateemail/ValidatingEmailService.kt | 4 ++-- 8 files changed, 48 insertions(+), 41 deletions(-) delete mode 100644 withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/InvalidAccessException.kt delete mode 100644 withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/NotExistsException.kt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt index bd0e010..3413ede 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt @@ -33,7 +33,10 @@ class AuthApplicationService( val userDto = userService.findByEmailOrNull(request.email) if (userDto != null) { if (userDto.isValidUser()) { - throw WithaengException.of(WithaengExceptionType.ALREADY_EXIST, "이미 가입된 이메일입니다.") + throw WithaengException.of( + type = WithaengExceptionType.ALREADY_EXIST, + message = "이미 가입된 이메일입니다." + ) } userService.deleteByEmail(userEmail) validatingEmailService.deleteAllByUserId(userDto.id) @@ -46,7 +49,10 @@ class AuthApplicationService( @Transactional fun signIn(request: SignInServiceRequest): UserResponse { val userDto = userService.findByEmailOrNull(request.email) - ?: throw WithaengException.of(WithaengExceptionType.NOT_EXIST, "이메일에 해당하는 유저를 찾을 수 없습니다.") + ?: throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = "이메일에 해당하는 유저를 찾을 수 없습니다." + ) checkValidUserPassword(request.password, userDto.password) return UserResponse(userDto.id, userDto.email, jwtAgent.provide(UserInfo.from(userDto))) } @@ -55,9 +61,15 @@ class AuthApplicationService( fun validateEmail(request: ValidateEmailServiceRequest) { val requestedEmail = request.email val userDto = userService.findByEmailOrNull(requestedEmail) - ?: throw WithaengException.of(WithaengExceptionType.NOT_EXIST, "이메일에 해당하는 유저를 찾을 수 없습니다.") + ?: throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = "이메일에 해당하는 유저를 찾을 수 없습니다." + ) if (userDto.isValidUser()) { - throw WithaengException.of(WithaengExceptionType.INVALID_ACCESS, "이미 인증된 유저입니다.") + throw WithaengException.of( + type = WithaengExceptionType.INVALID_ACCESS, + message = "이미 인증된 유저입니다." + ) } val validatingEmailDto = validatingEmailService.findByEmail(requestedEmail) if (validatingEmailDto.userId != userDto.id || validatingEmailDto.code != request.code) { diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ControllerExceptionAdvice.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ControllerExceptionAdvice.kt index 28aced3..fe64f88 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ControllerExceptionAdvice.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ControllerExceptionAdvice.kt @@ -1,7 +1,5 @@ package com.travel.withaeng.common -import com.travel.withaeng.common.exception.InvalidAccessException -import com.travel.withaeng.common.exception.NotExistsException import com.travel.withaeng.common.exception.WithaengException import com.travel.withaeng.common.exception.WithaengExceptionType import org.slf4j.Logger @@ -70,18 +68,6 @@ class ControllerExceptionAdvice { return errorResponse(WithaengExceptionType.ARGUMENT_NOT_VALID, errorMessage) } - @ExceptionHandler(NotExistsException::class) - protected fun notExistsException(e: NotExistsException): ResponseEntity> { - logger.error("notExistsException", e) - return errorResponse(WithaengExceptionType.NOT_EXIST, e.message) - } - - @ExceptionHandler(InvalidAccessException::class) - protected fun invalidAccessException(e: InvalidAccessException): ResponseEntity> { - logger.error("invalidAccessException", e) - return errorResponse(WithaengExceptionType.INVALID_ACCESS, e.message) - } - private fun WithaengException.toApiErrorResponse() = ApiErrorResponse( code = errorCode, message = message, diff --git a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/InvalidAccessException.kt b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/InvalidAccessException.kt deleted file mode 100644 index 8ce6e51..0000000 --- a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/InvalidAccessException.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.travel.withaeng.common.exception - -class InvalidAccessException ( - override val message: String, -) : RuntimeException() \ No newline at end of file diff --git a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/NotExistsException.kt b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/NotExistsException.kt deleted file mode 100644 index df7fb65..0000000 --- a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/NotExistsException.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.travel.withaeng.common.exception - -class NotExistsException ( - override val message: String, -) : RuntimeException() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt index 8ccc1a3..3b306ea 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt @@ -1,7 +1,7 @@ package com.travel.withaeng.domain.accompany -import com.travel.withaeng.common.exception.InvalidAccessException -import com.travel.withaeng.common.exception.NotExistsException +import com.travel.withaeng.common.exception.WithaengException +import com.travel.withaeng.common.exception.WithaengExceptionType import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional import java.time.LocalTime @@ -47,7 +47,10 @@ class AccompanyService( if (accompanyEntity != null) { if (accompanyEntity.userId != param.userId) { - throw InvalidAccessException("등록자와 수정자가 달라 수정 요청을 거부 합니다.") + throw WithaengException.of( + type = WithaengExceptionType.INVALID_ACCESS, + message = "등록자와 수정자가 달라 수정 요청을 거부 합니다." + ) } val accompanyHistEntity = param.toHistEntity(accompanyEntity) @@ -95,7 +98,10 @@ class AccompanyService( return getAccompany } - throw NotExistsException("존재하지 않는 동행 게시글 조회 요청 입니다.") + throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = "존재하지 않는 동행 게시글 조회 요청 입니다." + ) } fun getList(param: SearchAccompanyDTO): List { diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt index 50ba7d1..6f03305 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt @@ -1,7 +1,7 @@ package com.travel.withaeng.domain.accompanyreply -import com.travel.withaeng.common.exception.InvalidAccessException -import com.travel.withaeng.common.exception.NotExistsException +import com.travel.withaeng.common.exception.WithaengException +import com.travel.withaeng.common.exception.WithaengExceptionType import com.travel.withaeng.domain.accompanyreplylike.AccompanyReplyLikeService import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -36,7 +36,10 @@ class AccompanyReplyService( if (accompanyReplyEntity != null) { if (accompanyReplyEntity.userId != param.userId) { - throw InvalidAccessException("등록자와 수정자가 달라 수정 요청을 거부 합니다.") + throw WithaengException.of( + type = WithaengExceptionType.INVALID_ACCESS, + message = "등록자와 수정자가 달라 수정 요청을 거부 합니다." + ) } accompanyReplyEntity.let { @@ -58,7 +61,10 @@ class AccompanyReplyService( if (accompanyReplyEntity != null) { if (accompanyReplyEntity.userId != param.userId) { - throw InvalidAccessException("등록자와 수정자가 달라 삭제 요청을 거부 합니다.") + throw WithaengException.of( + type = WithaengExceptionType.INVALID_ACCESS, + message = "등록자와 수정자가 달라 삭제 요청을 거부 합니다." + ) } accompanyReplyRepository.delete(accompanyReplyEntity) @@ -79,7 +85,10 @@ class AccompanyReplyService( return GetReplyDTO.toDto(accompanyReplyEntity, accompanyReplyLikeCnt) } - throw NotExistsException("존재하지 않는 동행 게시글 댓글 요청 입니다.") + throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = "존재하지 않는 동행 게시글 댓글 요청 입니다." + ) } //TODO 댓글당 좋아요 누른 userId 목록을 추가로 조회하여 리턴은 추후 처리 diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt index cd04369..a58c08b 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt @@ -1,6 +1,7 @@ package com.travel.withaeng.domain.accompanyreplylike -import com.travel.withaeng.common.exception.InvalidAccessException +import com.travel.withaeng.common.exception.WithaengException +import com.travel.withaeng.common.exception.WithaengExceptionType import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional import java.time.LocalDateTime @@ -19,7 +20,10 @@ class AccompanyReplyLikeService( val replyLikeEntity = accompanyReplyLikeRepository.findByReplyIdAndUserId(param.replyId, param.userId) if (replyLikeEntity != null) { - throw InvalidAccessException("이미 해당 댓글의 좋아요 등록이 되어 있습니다.") + throw WithaengException.of( + type = WithaengExceptionType.INVALID_ACCESS, + message = "이미 해당 댓글의 좋아요 등록이 되어 있습니다." + ) } val accompanyReplyLikeEntity = param.toEntity() diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailService.kt index 9665619..d59228c 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailService.kt @@ -32,8 +32,8 @@ class ValidatingEmailService( fun findByEmail(email: String): ValidatingEmailDto { return validatingEmailRepository.findByEmail(email)?.toDto() ?: throw WithaengException.of( - WithaengExceptionType.NOT_EXIST, - "이메일에 해당하는 요청이 없습니다." + type = WithaengExceptionType.NOT_EXIST, + message = "이메일에 해당하는 요청이 없습니다." ) } From d50654d7ce31173cda195709b2a3514dd8e270d3 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Thu, 9 May 2024 02:38:08 +0900 Subject: [PATCH 063/174] Cleanup codes --- .../withaeng/common/cd/AccompanyStatusCd.kt | 8 +- .../com/travel/withaeng/common/cd/CityCd.kt | 8 +- .../travel/withaeng/common/cd/ContinentCd.kt | 6 +- .../travel/withaeng/common/cd/CountryCd.kt | 208 +++++++++--------- .../com/travel/withaeng/common/cd/ExecCd.kt | 8 +- withaeng-domain/build.gradle.kts | 4 +- 6 files changed, 116 insertions(+), 126 deletions(-) diff --git a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/AccompanyStatusCd.kt b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/AccompanyStatusCd.kt index c91f39b..dbb161e 100644 --- a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/AccompanyStatusCd.kt +++ b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/AccompanyStatusCd.kt @@ -1,10 +1,8 @@ package com.travel.withaeng.common.cd -enum class AccompanyStatusCd ( - - val statusCd : String, - val statusNm : String - +enum class AccompanyStatusCd( + val statusCd: String, + val statusNm: String ) { ING("ING", "동행 구인중"), diff --git a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CityCd.kt b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CityCd.kt index 742cda6..64f7410 100644 --- a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CityCd.kt +++ b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CityCd.kt @@ -1,12 +1,12 @@ package com.travel.withaeng.common.cd -enum class CityCd ( +enum class CityCd( val countryCd: String, - val cityCd : String, - val cityNm : String + val cityCd: String, + val cityNm: String -){ +) { SEOUL(CountryCd.KOREA.countryCd, "SEOUL", "서울"), BUSAN(CountryCd.KOREA.countryCd, "BUSAN", "부산"), diff --git a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/ContinentCd.kt b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/ContinentCd.kt index ef376b4..be1aaed 100644 --- a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/ContinentCd.kt +++ b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/ContinentCd.kt @@ -1,10 +1,8 @@ package com.travel.withaeng.common.cd enum class ContinentCd( - - val continentCd : String, - val continentNm : String - + val continentCd: String, + val continentNm: String ) { EAST_ASIA("EA", "동아시아"), diff --git a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CountryCd.kt b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CountryCd.kt index bb32d81..459fb3e 100644 --- a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CountryCd.kt +++ b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CountryCd.kt @@ -1,116 +1,114 @@ package com.travel.withaeng.common.cd -enum class CountryCd ( - +enum class CountryCd( val continentCd: String, - val countryCd : String, - val countryNm : String - + val countryCd: String, + val countryNm: String ) { - KOREA(ContinentCd.EAST_ASIA.continentCd,"KOREA", "한국"), - JAPAN(ContinentCd.EAST_ASIA.continentCd,"JAPAN", "일본"), - HONG_KONG(ContinentCd.EAST_ASIA.continentCd,"HONG_KONG", "홍콩"), - MACAO(ContinentCd.EAST_ASIA.continentCd,"MACAO", "마카오"), - TAIWAN(ContinentCd.EAST_ASIA.continentCd,"TAIWAN", "대만"), - CHINA(ContinentCd.EAST_ASIA.continentCd,"CHINA", "중국"), - MONGOLIA(ContinentCd.EAST_ASIA.continentCd,"MONGOLIA", "몽골"), + KOREA(ContinentCd.EAST_ASIA.continentCd, "KOREA", "한국"), + JAPAN(ContinentCd.EAST_ASIA.continentCd, "JAPAN", "일본"), + HONG_KONG(ContinentCd.EAST_ASIA.continentCd, "HONG_KONG", "홍콩"), + MACAO(ContinentCd.EAST_ASIA.continentCd, "MACAO", "마카오"), + TAIWAN(ContinentCd.EAST_ASIA.continentCd, "TAIWAN", "대만"), + CHINA(ContinentCd.EAST_ASIA.continentCd, "CHINA", "중국"), + MONGOLIA(ContinentCd.EAST_ASIA.continentCd, "MONGOLIA", "몽골"), - SINGAPORE(ContinentCd.SOUTHEAST_ASIA.continentCd,"SINGAPORE","싱가포르"), - EAST_TIMOR(ContinentCd.SOUTHEAST_ASIA.continentCd,"EAST_TIMOR","동티모르"), - MYANMAR(ContinentCd.SOUTHEAST_ASIA.continentCd,"MYANMAR","미얀마"), - CAMBODIA(ContinentCd.SOUTHEAST_ASIA.continentCd,"CAMBODIA","캄보디아"), - LAOS(ContinentCd.SOUTHEAST_ASIA.continentCd,"LAOS","라오스"), - PHILIPPINES(ContinentCd.SOUTHEAST_ASIA.continentCd,"PHILIPPINES","필리핀"), - MALAYSIA(ContinentCd.SOUTHEAST_ASIA.continentCd,"MALAYSIA","말레이시아"), - INDONESIA(ContinentCd.SOUTHEAST_ASIA.continentCd,"INDONESIA","인도네시아"), - THAILAND(ContinentCd.SOUTHEAST_ASIA.continentCd,"THAILAND","태국"), - VIETNAM(ContinentCd.SOUTHEAST_ASIA.continentCd,"VIETNAM","베트남"), - BRUNEI(ContinentCd.SOUTHEAST_ASIA.continentCd,"BRUNEI","브루나이"), + SINGAPORE(ContinentCd.SOUTHEAST_ASIA.continentCd, "SINGAPORE", "싱가포르"), + EAST_TIMOR(ContinentCd.SOUTHEAST_ASIA.continentCd, "EAST_TIMOR", "동티모르"), + MYANMAR(ContinentCd.SOUTHEAST_ASIA.continentCd, "MYANMAR", "미얀마"), + CAMBODIA(ContinentCd.SOUTHEAST_ASIA.continentCd, "CAMBODIA", "캄보디아"), + LAOS(ContinentCd.SOUTHEAST_ASIA.continentCd, "LAOS", "라오스"), + PHILIPPINES(ContinentCd.SOUTHEAST_ASIA.continentCd, "PHILIPPINES", "필리핀"), + MALAYSIA(ContinentCd.SOUTHEAST_ASIA.continentCd, "MALAYSIA", "말레이시아"), + INDONESIA(ContinentCd.SOUTHEAST_ASIA.continentCd, "INDONESIA", "인도네시아"), + THAILAND(ContinentCd.SOUTHEAST_ASIA.continentCd, "THAILAND", "태국"), + VIETNAM(ContinentCd.SOUTHEAST_ASIA.continentCd, "VIETNAM", "베트남"), + BRUNEI(ContinentCd.SOUTHEAST_ASIA.continentCd, "BRUNEI", "브루나이"), - UZBEKISTAN(ContinentCd.CENTRAL_ASIA.continentCd,"UZBEKISTAN","우즈베키스탄"), - BANGLADESH(ContinentCd.CENTRAL_ASIA.continentCd,"BANGLADESH","방글라데시"), - AZERBAIJAN(ContinentCd.CENTRAL_ASIA.continentCd,"AZERBAIJAN","아제르바이잔"), - BUTANE(ContinentCd.CENTRAL_ASIA.continentCd,"BUTANE","부탄"), - AFGHANISTAN(ContinentCd.CENTRAL_ASIA.continentCd,"AFGHANISTAN","아프가니스탄"), - TAJIKISTAN(ContinentCd.CENTRAL_ASIA.continentCd,"TAJIKISTAN","타지키스탄"), - KYRGYZSTAN(ContinentCd.CENTRAL_ASIA.continentCd,"KYRGYZSTAN","키르기스스탄"), - KAZAKHSTAN(ContinentCd.CENTRAL_ASIA.continentCd,"KAZAKHSTAN","카자흐스탄"), - TURKMENISTAN(ContinentCd.CENTRAL_ASIA.continentCd,"TURKMENISTAN","투르크메니스탄"), - TIBET(ContinentCd.CENTRAL_ASIA.continentCd,"TIBET","티베트"), + UZBEKISTAN(ContinentCd.CENTRAL_ASIA.continentCd, "UZBEKISTAN", "우즈베키스탄"), + BANGLADESH(ContinentCd.CENTRAL_ASIA.continentCd, "BANGLADESH", "방글라데시"), + AZERBAIJAN(ContinentCd.CENTRAL_ASIA.continentCd, "AZERBAIJAN", "아제르바이잔"), + BUTANE(ContinentCd.CENTRAL_ASIA.continentCd, "BUTANE", "부탄"), + AFGHANISTAN(ContinentCd.CENTRAL_ASIA.continentCd, "AFGHANISTAN", "아프가니스탄"), + TAJIKISTAN(ContinentCd.CENTRAL_ASIA.continentCd, "TAJIKISTAN", "타지키스탄"), + KYRGYZSTAN(ContinentCd.CENTRAL_ASIA.continentCd, "KYRGYZSTAN", "키르기스스탄"), + KAZAKHSTAN(ContinentCd.CENTRAL_ASIA.continentCd, "KAZAKHSTAN", "카자흐스탄"), + TURKMENISTAN(ContinentCd.CENTRAL_ASIA.continentCd, "TURKMENISTAN", "투르크메니스탄"), + TIBET(ContinentCd.CENTRAL_ASIA.continentCd, "TIBET", "티베트"), - ARAB_EMIRATES(ContinentCd.WESTERN_ASIA.continentCd,"ARAB_EMIRATES","아랍에미리트"), - JORDAN(ContinentCd.WESTERN_ASIA.continentCd,"JORDAN","요르단"), - YEMEN(ContinentCd.WESTERN_ASIA.continentCd,"YEMEN","예멘"), - SYRIA(ContinentCd.WESTERN_ASIA.continentCd,"SYRIA","시리아"), - IRAN(ContinentCd.WESTERN_ASIA.continentCd,"IRAN","이란"), - PAKISTAN(ContinentCd.WESTERN_ASIA.continentCd,"PAKISTAN","파키스탄"), - CYPRUS(ContinentCd.WESTERN_ASIA.continentCd,"CYPRUS","키프로스"), - SRI_LANKA(ContinentCd.WESTERN_ASIA.continentCd,"SRI_LANKA","스리랑카"), - MALDIVE(ContinentCd.WESTERN_ASIA.continentCd,"MALDIVE","몰디브"), - BAHRAIN(ContinentCd.WESTERN_ASIA.continentCd,"BAHRAIN","바레인"), - LRAQ(ContinentCd.WESTERN_ASIA.continentCd,"LRAQ","이라크"), - PALESTINE(ContinentCd.WESTERN_ASIA.continentCd,"PALESTINE","팔레스타인"), - OMAN(ContinentCd.WESTERN_ASIA.continentCd,"OMAN","오만"), - INDIA(ContinentCd.WESTERN_ASIA.continentCd,"INDIA","인도"), - NEPAL(ContinentCd.WESTERN_ASIA.continentCd,"NEPAL","네팔"), - ISRAEL(ContinentCd.WESTERN_ASIA.continentCd,"ISRAEL","이스라엘"), - CATARRH(ContinentCd.WESTERN_ASIA.continentCd,"CATARRH","카타르"), - LEBANON(ContinentCd.WESTERN_ASIA.continentCd,"LEBANON","레바논"), - SAUDI_ARABIA(ContinentCd.WESTERN_ASIA.continentCd,"SAUDI_ARABIA","사우디아라비아"), - KUWAIT(ContinentCd.WESTERN_ASIA.continentCd,"KUWAIT","쿠웨이트"), - ARMENIA(ContinentCd.WESTERN_ASIA.continentCd,"ARMENIA","아르메니아"), + ARAB_EMIRATES(ContinentCd.WESTERN_ASIA.continentCd, "ARAB_EMIRATES", "아랍에미리트"), + JORDAN(ContinentCd.WESTERN_ASIA.continentCd, "JORDAN", "요르단"), + YEMEN(ContinentCd.WESTERN_ASIA.continentCd, "YEMEN", "예멘"), + SYRIA(ContinentCd.WESTERN_ASIA.continentCd, "SYRIA", "시리아"), + IRAN(ContinentCd.WESTERN_ASIA.continentCd, "IRAN", "이란"), + PAKISTAN(ContinentCd.WESTERN_ASIA.continentCd, "PAKISTAN", "파키스탄"), + CYPRUS(ContinentCd.WESTERN_ASIA.continentCd, "CYPRUS", "키프로스"), + SRI_LANKA(ContinentCd.WESTERN_ASIA.continentCd, "SRI_LANKA", "스리랑카"), + MALDIVE(ContinentCd.WESTERN_ASIA.continentCd, "MALDIVE", "몰디브"), + BAHRAIN(ContinentCd.WESTERN_ASIA.continentCd, "BAHRAIN", "바레인"), + LRAQ(ContinentCd.WESTERN_ASIA.continentCd, "LRAQ", "이라크"), + PALESTINE(ContinentCd.WESTERN_ASIA.continentCd, "PALESTINE", "팔레스타인"), + OMAN(ContinentCd.WESTERN_ASIA.continentCd, "OMAN", "오만"), + INDIA(ContinentCd.WESTERN_ASIA.continentCd, "INDIA", "인도"), + NEPAL(ContinentCd.WESTERN_ASIA.continentCd, "NEPAL", "네팔"), + ISRAEL(ContinentCd.WESTERN_ASIA.continentCd, "ISRAEL", "이스라엘"), + CATARRH(ContinentCd.WESTERN_ASIA.continentCd, "CATARRH", "카타르"), + LEBANON(ContinentCd.WESTERN_ASIA.continentCd, "LEBANON", "레바논"), + SAUDI_ARABIA(ContinentCd.WESTERN_ASIA.continentCd, "SAUDI_ARABIA", "사우디아라비아"), + KUWAIT(ContinentCd.WESTERN_ASIA.continentCd, "KUWAIT", "쿠웨이트"), + ARMENIA(ContinentCd.WESTERN_ASIA.continentCd, "ARMENIA", "아르메니아"), - GEORGIA(ContinentCd.EUROPE.continentCd,"GEORGIA","조지아"), - MALTA(ContinentCd.EUROPE.continentCd,"MALTA","몰타"), - MOLDOVA(ContinentCd.EUROPE.continentCd,"MOLDOVA","몰도바"), - MONTENEGRO(ContinentCd.EUROPE.continentCd,"MONTENEGRO","몬테네그로"), - MONACO(ContinentCd.EUROPE.continentCd,"MONACO","모나코"), - MACEDONIA(ContinentCd.EUROPE.continentCd,"MACEDONIA","마케도니아"), - LIECHTENSTEIN(ContinentCd.EUROPE.continentCd,"LIECHTENSTEIN","리히텐슈타인"), - LITHUANIA(ContinentCd.EUROPE.continentCd,"LITHUANIA","리투아니아"), - LUXEMBOURG(ContinentCd.EUROPE.continentCd,"LUXEMBOURG","룩셈부르크"), - ROMANIA(ContinentCd.EUROPE.continentCd,"ROMANIA","루마니아"), - VATICAN(ContinentCd.EUROPE.continentCd,"VATICAN","바티칸"), - BELARUS(ContinentCd.EUROPE.continentCd,"BELARUS","벨라루스"), - BOSNIA_HERCEGOVINA(ContinentCd.EUROPE.continentCd,"BOSNIA_HERCEGOVINA","보스니아헤르체코비나"), - CROATIA(ContinentCd.EUROPE.continentCd,"CROATIA","크로아티아"), - UKRAINE(ContinentCd.EUROPE.continentCd,"UKRAINE","우크라이나"), - ESTONIA(ContinentCd.EUROPE.continentCd,"ESTONIA","에스토니아"), - ALBANIA(ContinentCd.EUROPE.continentCd,"ALBANIA","알바니아"), - ANDORRA(ContinentCd.EUROPE.continentCd,"ANDORRA","안도라"), - SLOVAKIA(ContinentCd.EUROPE.continentCd,"SLOVAKIA","슬로바키아"), - SERBIA(ContinentCd.EUROPE.continentCd,"SERBIA","세르비아"), - SAN_MARINO(ContinentCd.EUROPE.continentCd,"SAN_MARINO","산마리노"), - BULGARIA(ContinentCd.EUROPE.continentCd,"BULGARIA","불가리아"), - LATVIA(ContinentCd.EUROPE.continentCd,"LATVIA","라트비아"), - SLOVENIA(ContinentCd.EUROPE.continentCd,"SLOVENIA","슬로베니아"), - PORTUGAL(ContinentCd.EUROPE.continentCd,"PORTUGAL","포르투갈"), - SWISS(ContinentCd.EUROPE.continentCd,"SWISS","스위스"), - GERMANY(ContinentCd.EUROPE.continentCd,"GERMANY","독일"), - NETHERLAND(ContinentCd.EUROPE.continentCd,"NETHERLAND","네덜란드"), - AUSTRIA(ContinentCd.EUROPE.continentCd,"AUSTRIA","오스트리아"), - ENGLAND(ContinentCd.EUROPE.continentCd,"ENGLAND","영국"), - SPAIN(ContinentCd.EUROPE.continentCd,"SPAIN","스페인"), - TURKIYE(ContinentCd.EUROPE.continentCd,"TURKIYE","터키"), - ITALY(ContinentCd.EUROPE.continentCd,"ITALY","이탈리아"), - POLAND(ContinentCd.EUROPE.continentCd,"POLAND","폴란드"), - ICELAND(ContinentCd.EUROPE.continentCd,"ICELAND","아이슬란드"), - FINLAND(ContinentCd.EUROPE.continentCd,"FINLAND","핀란드"), - CZECHIA(ContinentCd.EUROPE.continentCd,"CZECHIA","체코"), - BELGIUM(ContinentCd.EUROPE.continentCd,"BELGIUM","벨기에"), - HUNGARY(ContinentCd.EUROPE.continentCd,"HUNGARY","헝가리"), - IRELAND(ContinentCd.EUROPE.continentCd,"IRELAND","아일랜드"), - RUSSIA(ContinentCd.EUROPE.continentCd,"RUSSIA","러시아"), - GREECE(ContinentCd.EUROPE.continentCd,"GREECE","그리스"), - DENMARK(ContinentCd.EUROPE.continentCd,"DENMARK","덴마크"), - NORWAY(ContinentCd.EUROPE.continentCd,"NORWAY","노르웨이"), - SWEDEN(ContinentCd.EUROPE.continentCd,"SWEDEN","스웨덴"), - FRANCE(ContinentCd.EUROPE.continentCd,"FRANCE","프랑스"), + GEORGIA(ContinentCd.EUROPE.continentCd, "GEORGIA", "조지아"), + MALTA(ContinentCd.EUROPE.continentCd, "MALTA", "몰타"), + MOLDOVA(ContinentCd.EUROPE.continentCd, "MOLDOVA", "몰도바"), + MONTENEGRO(ContinentCd.EUROPE.continentCd, "MONTENEGRO", "몬테네그로"), + MONACO(ContinentCd.EUROPE.continentCd, "MONACO", "모나코"), + MACEDONIA(ContinentCd.EUROPE.continentCd, "MACEDONIA", "마케도니아"), + LIECHTENSTEIN(ContinentCd.EUROPE.continentCd, "LIECHTENSTEIN", "리히텐슈타인"), + LITHUANIA(ContinentCd.EUROPE.continentCd, "LITHUANIA", "리투아니아"), + LUXEMBOURG(ContinentCd.EUROPE.continentCd, "LUXEMBOURG", "룩셈부르크"), + ROMANIA(ContinentCd.EUROPE.continentCd, "ROMANIA", "루마니아"), + VATICAN(ContinentCd.EUROPE.continentCd, "VATICAN", "바티칸"), + BELARUS(ContinentCd.EUROPE.continentCd, "BELARUS", "벨라루스"), + BOSNIA_HERCEGOVINA(ContinentCd.EUROPE.continentCd, "BOSNIA_HERCEGOVINA", "보스니아헤르체코비나"), + CROATIA(ContinentCd.EUROPE.continentCd, "CROATIA", "크로아티아"), + UKRAINE(ContinentCd.EUROPE.continentCd, "UKRAINE", "우크라이나"), + ESTONIA(ContinentCd.EUROPE.continentCd, "ESTONIA", "에스토니아"), + ALBANIA(ContinentCd.EUROPE.continentCd, "ALBANIA", "알바니아"), + ANDORRA(ContinentCd.EUROPE.continentCd, "ANDORRA", "안도라"), + SLOVAKIA(ContinentCd.EUROPE.continentCd, "SLOVAKIA", "슬로바키아"), + SERBIA(ContinentCd.EUROPE.continentCd, "SERBIA", "세르비아"), + SAN_MARINO(ContinentCd.EUROPE.continentCd, "SAN_MARINO", "산마리노"), + BULGARIA(ContinentCd.EUROPE.continentCd, "BULGARIA", "불가리아"), + LATVIA(ContinentCd.EUROPE.continentCd, "LATVIA", "라트비아"), + SLOVENIA(ContinentCd.EUROPE.continentCd, "SLOVENIA", "슬로베니아"), + PORTUGAL(ContinentCd.EUROPE.continentCd, "PORTUGAL", "포르투갈"), + SWISS(ContinentCd.EUROPE.continentCd, "SWISS", "스위스"), + GERMANY(ContinentCd.EUROPE.continentCd, "GERMANY", "독일"), + NETHERLAND(ContinentCd.EUROPE.continentCd, "NETHERLAND", "네덜란드"), + AUSTRIA(ContinentCd.EUROPE.continentCd, "AUSTRIA", "오스트리아"), + ENGLAND(ContinentCd.EUROPE.continentCd, "ENGLAND", "영국"), + SPAIN(ContinentCd.EUROPE.continentCd, "SPAIN", "스페인"), + TURKIYE(ContinentCd.EUROPE.continentCd, "TURKIYE", "터키"), + ITALY(ContinentCd.EUROPE.continentCd, "ITALY", "이탈리아"), + POLAND(ContinentCd.EUROPE.continentCd, "POLAND", "폴란드"), + ICELAND(ContinentCd.EUROPE.continentCd, "ICELAND", "아이슬란드"), + FINLAND(ContinentCd.EUROPE.continentCd, "FINLAND", "핀란드"), + CZECHIA(ContinentCd.EUROPE.continentCd, "CZECHIA", "체코"), + BELGIUM(ContinentCd.EUROPE.continentCd, "BELGIUM", "벨기에"), + HUNGARY(ContinentCd.EUROPE.continentCd, "HUNGARY", "헝가리"), + IRELAND(ContinentCd.EUROPE.continentCd, "IRELAND", "아일랜드"), + RUSSIA(ContinentCd.EUROPE.continentCd, "RUSSIA", "러시아"), + GREECE(ContinentCd.EUROPE.continentCd, "GREECE", "그리스"), + DENMARK(ContinentCd.EUROPE.continentCd, "DENMARK", "덴마크"), + NORWAY(ContinentCd.EUROPE.continentCd, "NORWAY", "노르웨이"), + SWEDEN(ContinentCd.EUROPE.continentCd, "SWEDEN", "스웨덴"), + FRANCE(ContinentCd.EUROPE.continentCd, "FRANCE", "프랑스"), - AUSTRALIA(ContinentCd.OCEANIA.continentCd,"AUSTRALIA","호주"), - PALAU(ContinentCd.OCEANIA.continentCd,"PALAU","팔라우"), - PAPUA_NEW_GUINEA(ContinentCd.OCEANIA.continentCd,"PAPUA_NEW_GUINEA","파푸아뉴기니"), + AUSTRALIA(ContinentCd.OCEANIA.continentCd, "AUSTRALIA", "호주"), + PALAU(ContinentCd.OCEANIA.continentCd, "PALAU", "팔라우"), + PAPUA_NEW_GUINEA(ContinentCd.OCEANIA.continentCd, "PAPUA_NEW_GUINEA", "파푸아뉴기니"), TONGA(ContinentCd.OCEANIA.continentCd, "TONGA", "퉁가"), KIRIBATI(ContinentCd.OCEANIA.continentCd, "KIRIBATI", "키리바시"), SOLOMON_ISLAND(ContinentCd.OCEANIA.continentCd, "SOLOMON_ISLAND", "솔로몬제도"), @@ -163,8 +161,8 @@ enum class CountryCd ( EGYPT(ContinentCd.AFRICA.continentCd, "EGYPT", "이집트"), UNITED_STATES(ContinentCd.NORTH_AMERICA.continentCd, "UNITED_STATES", "미국"), - CANADA(ContinentCd.NORTH_AMERICA.continentCd,"CANADA", "캐나다"), - MEXICO(ContinentCd.NORTH_AMERICA.continentCd,"MEXICO","멕시코"), + CANADA(ContinentCd.NORTH_AMERICA.continentCd, "CANADA", "캐나다"), + MEXICO(ContinentCd.NORTH_AMERICA.continentCd, "MEXICO", "멕시코"), ANTIGUA_AND_BARBUDA(ContinentCd.NORTH_AMERICA.continentCd, "ANTIGUA_AND_BARBUDA", "앤티가바부다"), ARUBA(ContinentCd.NORTH_AMERICA.continentCd, "ARUBA", "아루바"), ANGUILLA(ContinentCd.NORTH_AMERICA.continentCd, "ANGUILLA", "앵귈라"), diff --git a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/ExecCd.kt b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/ExecCd.kt index d021b6e..2ca9c14 100644 --- a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/ExecCd.kt +++ b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/ExecCd.kt @@ -1,10 +1,8 @@ package com.travel.withaeng.common.cd -enum class ExecCd ( - - val execCd : String, - val execNm : String - +enum class ExecCd( + val execCd: String, + val execNm: String ) { CREATE("CREATE", "등록"), diff --git a/withaeng-domain/build.gradle.kts b/withaeng-domain/build.gradle.kts index 4ab4b15..2b47018 100644 --- a/withaeng-domain/build.gradle.kts +++ b/withaeng-domain/build.gradle.kts @@ -20,6 +20,4 @@ dependencies { // jasypt api("com.github.ulisesbocchio:jasypt-spring-boot-starter:$jasyptVersion") -} - - +} \ No newline at end of file From 45df69989e6924c420d43218a9a029c9e84d73ca Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Fri, 10 May 2024 02:37:31 +0900 Subject: [PATCH 064/174] Remove unnecessary codes --- .../withaeng/domain/AccompanyBaseEntity.kt | 26 ----- .../accompany/AccompanyDestinationEntity.kt | 27 ----- .../AccompanyDestinationRepository.kt | 7 -- .../domain/accompany/AccompanyDetailEntity.kt | 29 ----- .../accompany/AccompanyDetailRepository.kt | 8 -- .../domain/accompany/AccompanyEntity.kt | 43 -------- .../domain/accompany/AccompanyHistEntity.kt | 47 -------- .../accompany/AccompanyHistRepository.kt | 5 - .../accompany/AccompanyRepositoryCustom.kt | 8 -- .../AccompanyRepositoryCustomImpl.kt | 100 ------------------ .../domain/accompany/AccompanyTagEntity.kt | 21 ---- .../accompany/AccompanyTagRepository.kt | 10 -- .../accompanylike/AccompanyLikeEntity.kt | 21 ---- .../accompanylike/AccompanyLikeHistEntity.kt | 27 ----- .../accompanyreply/AccompanyReplyEntity.kt | 35 ------ .../AccompanyReplyHistEntity.kt | 39 ------- .../AccompanyReplyLikeEntity.kt | 21 ---- .../AccompanyReplyLikeHistEntity.kt | 27 ----- 18 files changed, 501 deletions(-) delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/AccompanyBaseEntity.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestinationEntity.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestinationRepository.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDetailEntity.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDetailRepository.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyEntity.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistRepository.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustom.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagEntity.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagRepository.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeEntity.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistEntity.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyEntity.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHistEntity.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeEntity.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHistEntity.kt diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/AccompanyBaseEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/AccompanyBaseEntity.kt deleted file mode 100644 index f96a3f5..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/AccompanyBaseEntity.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.travel.withaeng.domain - -import jakarta.persistence.Column -import jakarta.persistence.EntityListeners -import jakarta.persistence.MappedSuperclass -import org.springframework.data.annotation.CreatedDate -import org.springframework.data.annotation.LastModifiedDate -import org.springframework.data.jpa.domain.support.AuditingEntityListener -import java.time.LocalDateTime - -@EntityListeners(AuditingEntityListener::class) -@MappedSuperclass -abstract class AccompanyBaseEntity { - - @CreatedDate - @Column(name = "created_at", nullable = false, updatable = false) - var createdAt: LocalDateTime = LocalDateTime.now() - - @LastModifiedDate - @Column(name = "updated_at", nullable = false, updatable = true) - var updatedAt: LocalDateTime = LocalDateTime.now() - - @Column(name = "deleted_at", nullable = true, updatable = true) - var deletedAt: LocalDateTime? = null - -} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestinationEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestinationEntity.kt deleted file mode 100644 index 472893c..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestinationEntity.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.travel.withaeng.domain.accompany - -import com.travel.withaeng.domain.AccompanyBaseEntity -import jakarta.persistence.* - -@Table(name = "accompany_destinaion") -@Entity -class AccompanyDestinationEntity( - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "destination_id", nullable = false) - val destinationId: Long, - - @Column(name = "accompany_id", nullable = false) - val accompanyId: Long, - - @Column(name = "continent", nullable = false, updatable = true) - var continent: String, - - @Column(name = "country", nullable = true, updatable = true) - var country: String?, - - @Column(name = "city", nullable = true, updatable = true) - var city: String?, - - ) : AccompanyBaseEntity() diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestinationRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestinationRepository.kt deleted file mode 100644 index bc71391..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestinationRepository.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.travel.withaeng.domain.accompany - -import org.springframework.data.jpa.repository.JpaRepository - -interface AccompanyDestinationRepository : JpaRepository { - fun findByAccompanyId(accompanyId: Long): AccompanyDestinationEntity -} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDetailEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDetailEntity.kt deleted file mode 100644 index 161ac82..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDetailEntity.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.travel.withaeng.domain.accompany - -import com.travel.withaeng.domain.AccompanyBaseEntity -import jakarta.persistence.Column -import jakarta.persistence.Entity -import jakarta.persistence.Id -import jakarta.persistence.Table -import org.hibernate.annotations.DynamicUpdate - -@DynamicUpdate -@Table(name = "accompany_detail") -@Entity -class AccompanyDetailEntity( - - @Id - @Column(name = "accompany_id", nullable = false) - val accompanyId: Long, - - @Column(name = "view_cnt", nullable = false) - var viewCnt: Long = 0L, - - @Column(name = "like_cnt", nullable = false) - var likeCnt: Long = 0L, - - @Column(name = "open_kakao_url", nullable = false) - var openKakaoUrl: String - - -) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDetailRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDetailRepository.kt deleted file mode 100644 index 139e9b9..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDetailRepository.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.travel.withaeng.domain.accompany - -import org.springframework.data.jpa.repository.JpaRepository - -interface AccompanyDetailRepository : JpaRepository { - fun findByAccompanyId(accompanyId: Long): AccompanyDetailEntity - -} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyEntity.kt deleted file mode 100644 index 84d6934..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyEntity.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.travel.withaeng.domain.accompany - -import com.travel.withaeng.domain.AccompanyBaseEntity -import jakarta.persistence.* -import org.hibernate.annotations.DynamicUpdate -import java.time.LocalDateTime - -@DynamicUpdate -@Table(name = "accompany") -@Entity -class AccompanyEntity( - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "accompany_id", nullable = false) - val accompanyId: Long, - - @Column(name = "user_id", nullable = false) - val userId: Long, - - @Column(name = "title", nullable = false) - var title: String, - - @Lob - @Column(name = "content", nullable = false) - var content: String, - - @Column(name = "accompany_status_cd", nullable = false) - var accompanyStatusCd: String, - - @Column(name = "start_trip_date", nullable = false) - var startTripDate: LocalDateTime, - - @Column(name = "end_trip_date", nullable = false) - var endTripDate: LocalDateTime, - - @Column(name = "banner_image_url") - var bannerImageUrl: String?, - - @Column(name = "accompany_cnt", nullable = false) - var accompanyCnt: Long = 0L, - - ) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt deleted file mode 100644 index d2dca8d..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistEntity.kt +++ /dev/null @@ -1,47 +0,0 @@ -package com.travel.withaeng.domain.accompany - -import com.travel.withaeng.domain.AccompanyBaseEntity -import jakarta.persistence.* -import java.time.LocalDateTime - -@Table(name = "accompany_hist") -@Entity -class AccompanyHistEntity( - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "hist_id", nullable = false) - val histId: Long, - - @Column(name = "accompany_id", nullable = false) - val accompanyId: Long, - - @Column(name = "user_id", nullable = false) - val userId: Long, - - @Column(name = "title", nullable = false) - var title: String, - - @Lob - @Column(name = "content", nullable = false) - var content: String, - - @Column(name = "accompany_status_cd", nullable = false) - var accompanyStatusCd: String, - - @Column(name = "start_trip_date", nullable = false) - var startTripDate: LocalDateTime, - - @Column(name = "end_trip_date", nullable = false) - var endTripDate: LocalDateTime, - - @Column(name = "banner_image_url") - var bannerImageUrl: String?, - - @Column(name = "accompany_cnt", nullable = false) - var accompanyCnt: Long = 0L, - - @Column(name = "exec_cd", nullable = false) - val execCd: String - -) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistRepository.kt deleted file mode 100644 index e4b558b..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyHistRepository.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.travel.withaeng.domain.accompany - -import org.springframework.data.jpa.repository.JpaRepository - -interface AccompanyHistRepository : JpaRepository \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustom.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustom.kt deleted file mode 100644 index b931b1a..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustom.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.travel.withaeng.domain.accompany - -interface AccompanyRepositoryCustom { - - fun getAccompany(accompanyId: Long): GetDTO? - - fun getAccompanyList(param: SearchAccompanyDTO): List -} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt deleted file mode 100644 index fc16f17..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustomImpl.kt +++ /dev/null @@ -1,100 +0,0 @@ -package com.travel.withaeng.domain.accompany - -import com.querydsl.core.BooleanBuilder -import com.querydsl.core.types.Order -import com.querydsl.core.types.OrderSpecifier -import com.querydsl.core.types.Projections -import com.querydsl.jpa.impl.JPAQueryFactory -import org.springframework.stereotype.Repository -import java.time.LocalTime - -@Repository -class AccompanyRepositoryCustomImpl(val jpaQueryFactory: JPAQueryFactory) : AccompanyRepositoryCustom { - - override fun getAccompany(accompanyId: Long): GetDTO? { - return jpaQueryFactory - .select( - Projections.constructor( - GetDTO::class.java, - QAccompanyEntity.accompanyEntity.accompanyId, - QAccompanyEntity.accompanyEntity.userId, - QAccompanyEntity.accompanyEntity.title, - QAccompanyEntity.accompanyEntity.content, - QAccompanyDestinationEntity.accompanyDestinationEntity.continent, - QAccompanyDestinationEntity.accompanyDestinationEntity.country, - QAccompanyDestinationEntity.accompanyDestinationEntity.city, - QAccompanyEntity.accompanyEntity.startTripDate, - QAccompanyEntity.accompanyEntity.endTripDate, - QAccompanyEntity.accompanyEntity.bannerImageUrl, - QAccompanyEntity.accompanyEntity.accompanyCnt, - QAccompanyDetailEntity.accompanyDetailEntity.viewCnt, - QAccompanyDetailEntity.accompanyDetailEntity.likeCnt, - QAccompanyDetailEntity.accompanyDetailEntity.openKakaoUrl - ) - ) - .from(QAccompanyEntity.accompanyEntity) - .innerJoin(QAccompanyDestinationEntity.accompanyDestinationEntity) - .on(QAccompanyDestinationEntity.accompanyDestinationEntity.accompanyId.eq(QAccompanyEntity.accompanyEntity.accompanyId)) - .innerJoin(QAccompanyDetailEntity.accompanyDetailEntity) - .on(QAccompanyDetailEntity.accompanyDetailEntity.accompanyId.eq(QAccompanyEntity.accompanyEntity.accompanyId)) - .where(QAccompanyEntity.accompanyEntity.accompanyId.eq(accompanyId)) - .fetchOne() - } - - override fun getAccompanyList(param: SearchAccompanyDTO): List { - println("currentPage:" + param.getCurrentPage()) - return jpaQueryFactory - .select( - Projections.constructor( - GetDTO::class.java, - QAccompanyEntity.accompanyEntity.accompanyId, - QAccompanyEntity.accompanyEntity.userId, - QAccompanyEntity.accompanyEntity.title, - QAccompanyEntity.accompanyEntity.content, - QAccompanyDestinationEntity.accompanyDestinationEntity.continent, - QAccompanyDestinationEntity.accompanyDestinationEntity.country, - QAccompanyDestinationEntity.accompanyDestinationEntity.city, - QAccompanyEntity.accompanyEntity.startTripDate, - QAccompanyEntity.accompanyEntity.endTripDate, - QAccompanyEntity.accompanyEntity.bannerImageUrl, - QAccompanyEntity.accompanyEntity.accompanyCnt, - QAccompanyDetailEntity.accompanyDetailEntity.viewCnt, - QAccompanyDetailEntity.accompanyDetailEntity.likeCnt, - QAccompanyDetailEntity.accompanyDetailEntity.openKakaoUrl - ) - ) - .from(QAccompanyEntity.accompanyEntity) - .innerJoin(QAccompanyDestinationEntity.accompanyDestinationEntity) - .on(QAccompanyDestinationEntity.accompanyDestinationEntity.accompanyId.eq(QAccompanyEntity.accompanyEntity.accompanyId)) - .innerJoin(QAccompanyDetailEntity.accompanyDetailEntity) - .on(QAccompanyDetailEntity.accompanyDetailEntity.accompanyId.eq(QAccompanyEntity.accompanyEntity.accompanyId)) - .where(listWhere(param, QAccompanyEntity.accompanyEntity)) - .orderBy(listOrder(param)) - .offset(param.getCurrentPage()) - .limit(param.pageSize) - .fetch() - } - - fun listWhere(param: SearchAccompanyDTO, accompanyEntity: QAccompanyEntity): BooleanBuilder { - - val builder = BooleanBuilder() - - val startDate = param.startTripDate.atStartOfDay() - val endDate = param.endTripDate.atTime(LocalTime.MAX) - - builder.and(accompanyEntity.startTripDate.after(startDate)) - builder.and(accompanyEntity.endTripDate.before(endDate)) - - return builder - } - - fun listOrder(param: SearchAccompanyDTO): OrderSpecifier<*> { - if (param.likeCntOrder) { - return OrderSpecifier(Order.DESC, QAccompanyDetailEntity.accompanyDetailEntity.likeCnt) - } else if (param.viewCntOrder) { - return OrderSpecifier(Order.DESC, QAccompanyDetailEntity.accompanyDetailEntity.viewCnt) - } else { - return OrderSpecifier(Order.DESC, QAccompanyEntity.accompanyEntity.updatedAt) - } - } -} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagEntity.kt deleted file mode 100644 index 9dcf775..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagEntity.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.travel.withaeng.domain.accompany - -import com.travel.withaeng.domain.AccompanyBaseEntity -import jakarta.persistence.* - -@Table(name = "accompany_tag") -@Entity -class AccompanyTagEntity( - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "tag_id", nullable = false) - val tagId: Long, - - @Column(name = "accompany_id", nullable = false) - val accompanyId: Long, - - @Column(name = "tag_nm", nullable = false) - val tagNm: String - -) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagRepository.kt deleted file mode 100644 index 101c07f..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyTagRepository.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.travel.withaeng.domain.accompany - -import org.springframework.data.jpa.repository.JpaRepository - -interface AccompanyTagRepository : JpaRepository { - - fun findByAccompanyId(accompanyId: Long): List? - - fun deleteByAccompanyId(accompanyId: Long) -} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeEntity.kt deleted file mode 100644 index 4c51695..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeEntity.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.travel.withaeng.domain.accompanylike - -import com.travel.withaeng.domain.AccompanyBaseEntity -import jakarta.persistence.* - -@Table(name = "accompany_like") -@Entity -class AccompanyLikeEntity( - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "like_id", nullable = false) - val likeId: Long, - - @Column(name = "accompany_id", nullable = false) - val accompanyId: Long, - - @Column(name = "user_id", nullable = false) - val userId: Long, - - ) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistEntity.kt deleted file mode 100644 index 5e43c5e..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistEntity.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.travel.withaeng.domain.accompanylike - -import com.travel.withaeng.domain.AccompanyBaseEntity -import jakarta.persistence.* - -@Table(name = "accompany_like_hist") -@Entity -class AccompanyLikeHistEntity( - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "hist_id", nullable = false) - val histId: Long, - - @Column(name = "like_id", nullable = false) - val likeId: Long, - - @Column(name = "user_id", nullable = false) - val userId: Long, - - @Column(name = "accompany_id", nullable = false) - val accompanyId: Long, - - @Column(name = "exec_cd", nullable = false) - val execCd: String - -) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyEntity.kt deleted file mode 100644 index 739cd4d..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyEntity.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.travel.withaeng.domain.accompanyreply - -import com.travel.withaeng.domain.AccompanyBaseEntity -import jakarta.persistence.* -import org.hibernate.annotations.DynamicUpdate - -@DynamicUpdate -@Table(name = "accompany_reply") -@Entity -class AccompanyReplyEntity( - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "reply_id", nullable = false) - val replyId: Long, - - @Column(name = "accompany_id", nullable = false) - val accompanyId: Long, - - @Column(name = "parent_id", nullable = false) - val parentId: Long, - - @Column(name = "depth", nullable = false) - val depth: Long, - - @Column(name = "reply_order", nullable = false) - val replyOrder: Long, - - @Column(name = "user_id", nullable = false) - val userId: Long, - - @Column(name = "content", nullable = false) - var content: String, - - ) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHistEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHistEntity.kt deleted file mode 100644 index 94b56ce..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHistEntity.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.travel.withaeng.domain.accompanyreply - -import com.travel.withaeng.domain.AccompanyBaseEntity -import jakarta.persistence.* - -@Table(name = "accompany_reply_hist") -@Entity -class AccompanyReplyHistEntity( - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "hist_id", nullable = false) - val histId: Long, - - @Column(name = "reply_id", nullable = false) - val replyId: Long, - - @Column(name = "accompany_id", nullable = false) - val accompanyId: Long, - - @Column(name = "parent_id", nullable = false) - val parentId: Long, - - @Column(name = "depth", nullable = false) - val depth: Long, - - @Column(name = "reply_order", nullable = false) - val replyOrder: Long, - - @Column(name = "user_id", nullable = false) - val userId: Long, - - @Column(name = "content", nullable = false) - val content: String, - - @Column(name = "exec_cd", nullable = false) - val execCd: String, - - ) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeEntity.kt deleted file mode 100644 index 2296bbc..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeEntity.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.travel.withaeng.domain.accompanyreplylike - -import com.travel.withaeng.domain.AccompanyBaseEntity -import jakarta.persistence.* - -@Table(name = "accompany_reply_like") -@Entity -class AccompanyReplyLikeEntity( - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "reply_like_id", nullable = false) - val replyLikeId: Long, - - @Column(name = "reply_id", nullable = false) - val replyId: Long, - - @Column(name = "user_id", nullable = false) - val userId: Long - -) : AccompanyBaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHistEntity.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHistEntity.kt deleted file mode 100644 index 7c08dc0..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHistEntity.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.travel.withaeng.domain.accompanyreplylike - -import com.travel.withaeng.domain.AccompanyBaseEntity -import jakarta.persistence.* - -@Table(name = "accompany_reply_like_hist") -@Entity -class AccompanyReplyLikeHistEntity( - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "hist_id", nullable = false) - val histId: Long, - - @Column(name = "reply_like_id", nullable = false) - val replyLikeId: Long, - - @Column(name = "reply_id", nullable = false) - val replyId: Long, - - @Column(name = "user_id", nullable = false) - val userId: Long, - - @Column(name = "exec_cd", nullable = false) - val execCd: String - -) : AccompanyBaseEntity() \ No newline at end of file From b8290068fe8796a8786a7502efd68602a8fc9536 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Fri, 10 May 2024 02:38:01 +0900 Subject: [PATCH 065/174] Refactor destination --- .../com/travel/withaeng/common/cd/CityCd.kt | 181 ----------------- .../travel/withaeng/common/cd/CountryCd.kt | 189 ------------------ .../domain/accompany/AccompanyDestination.kt | 21 ++ .../travel/withaeng/domain/accompany/City.kt | 179 +++++++++++++++++ .../withaeng/domain/accompany/Continent.kt | 8 +- .../withaeng/domain/accompany/Country.kt | 189 ++++++++++++++++++ 6 files changed, 393 insertions(+), 374 deletions(-) delete mode 100644 withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CityCd.kt delete mode 100644 withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CountryCd.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestination.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/City.kt rename withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/ContinentCd.kt => withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Continent.kt (73%) create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Country.kt diff --git a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CityCd.kt b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CityCd.kt deleted file mode 100644 index 64f7410..0000000 --- a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CityCd.kt +++ /dev/null @@ -1,181 +0,0 @@ -package com.travel.withaeng.common.cd - -enum class CityCd( - - val countryCd: String, - val cityCd: String, - val cityNm: String - -) { - - SEOUL(CountryCd.KOREA.countryCd, "SEOUL", "서울"), - BUSAN(CountryCd.KOREA.countryCd, "BUSAN", "부산"), - INCHEON(CountryCd.KOREA.countryCd, "INCHEON", "인천"), - DAEGU(CountryCd.KOREA.countryCd, "DAEGU", "대구"), - GWANGJU(CountryCd.KOREA.countryCd, "GWANGJU", "광주"), - DAEJEON(CountryCd.KOREA.countryCd, "DAEJEON", "대전"), - ULSAN(CountryCd.KOREA.countryCd, "ULSAN", "울산"), - SUWON(CountryCd.KOREA.countryCd, "SUWON", "수원"), - CHANGWON(CountryCd.KOREA.countryCd, "CHANGWON", "창원"), - JEJU(CountryCd.KOREA.countryCd, "JEJU", "제주"), - - // Japan - TOKYO(CountryCd.JAPAN.countryCd, "TOKYO", "도쿄"), - OSAKA(CountryCd.JAPAN.countryCd, "OSAKA", "오사카"), - KYOTO(CountryCd.JAPAN.countryCd, "KYOTO", "교토"), - SAPPORO(CountryCd.JAPAN.countryCd, "SAPPORO", "삿포로"), - FUKUOKA(CountryCd.JAPAN.countryCd, "FUKUOKA", "후쿠오카"), - HIROSHIMA(CountryCd.JAPAN.countryCd, "HIROSHIMA", "히로시마"), - NAGOYA(CountryCd.JAPAN.countryCd, "NAGOYA", "나고야"), - OKINAWA(CountryCd.JAPAN.countryCd, "OKINAWA", "오키나와"), - KANAZAWA(CountryCd.JAPAN.countryCd, "KANAZAWA", "가나자와"), - - // China - BEIJING(CountryCd.CHINA.countryCd, "BEIJING", "베이징"), - SHANGHAI(CountryCd.CHINA.countryCd, "SHANGHAI", "상하이"), - HONG_KONG(CountryCd.CHINA.countryCd, "HONG_KONG", "홍콩"), - MACAO(CountryCd.CHINA.countryCd, "MACAO", "마카오"), - GUANGZHOU(CountryCd.CHINA.countryCd, "GUANGZHOU", "광저우"), - SHENZHEN(CountryCd.CHINA.countryCd, "SHENZHEN", "선전"), - CHENGDU(CountryCd.CHINA.countryCd, "CHENGDU", "청두"), - XIAMEN(CountryCd.CHINA.countryCd, "XIAMEN", "샤먼"), - TIANJIN(CountryCd.CHINA.countryCd, "TIANJIN", "천진"), - - // United States - NEW_YORK(CountryCd.UNITED_STATES.countryCd, "NEW_YORK", "뉴욕"), - LOS_ANGELES(CountryCd.UNITED_STATES.countryCd, "LOS_ANGELES", "로스앤젤레스"), - CHICAGO(CountryCd.UNITED_STATES.countryCd, "CHICAGO", "시카고"), - LAS_VEGAS(CountryCd.UNITED_STATES.countryCd, "LAS_VEGAS", "라스베이거스"), - SAN_FRANCISCO(CountryCd.UNITED_STATES.countryCd, "SAN_FRANCISCO", "샌프란시스코"), - WASHINGTON_DC(CountryCd.UNITED_STATES.countryCd, "WASHINGTON_DC", "워싱턴 D.C."), - MIAMI(CountryCd.UNITED_STATES.countryCd, "MIAMI", "마이애미"), - ORLANDO(CountryCd.UNITED_STATES.countryCd, "ORLANDO", "올랜도"), - SEATTLE(CountryCd.UNITED_STATES.countryCd, "SEATTLE", "시애틀"), - - // United Kingdom - LONDON(CountryCd.ENGLAND.countryCd, "LONDON", "런던"), - EDINBURGH(CountryCd.ENGLAND.countryCd, "EDINBURGH", "에든버러"), - MANCHESTER(CountryCd.ENGLAND.countryCd, "MANCHESTER", "맨체스터"), - BIRMINGHAM(CountryCd.ENGLAND.countryCd, "BIRMINGHAM", "버밍엄"), - GLASGOW(CountryCd.ENGLAND.countryCd, "GLASGOW", "글래스고"), - LIVERPOOL(CountryCd.ENGLAND.countryCd, "LIVERPOOL", "리버풀"), - CAMBRIDGE(CountryCd.ENGLAND.countryCd, "CAMBRIDGE", "케임브리지"), - - // France - PARIS(CountryCd.FRANCE.countryCd, "PARIS", "파리"), - MARSEILLE(CountryCd.FRANCE.countryCd, "MARSEILLE", "마르세유"), - LYON(CountryCd.FRANCE.countryCd, "LYON", "리옹"), - NICE(CountryCd.FRANCE.countryCd, "NICE", "니스"), - BORDEAUX(CountryCd.FRANCE.countryCd, "BORDEAUX", "보르도"), - STRASBOURG(CountryCd.FRANCE.countryCd, "STRASBOURG", "스트라스부르"), - - // Germany - BERLIN(CountryCd.GERMANY.countryCd, "BERLIN", "베를린"), - MUNICH(CountryCd.GERMANY.countryCd, "MUNICH", "뮌헨"), - FRANKFURT(CountryCd.GERMANY.countryCd, "FRANKFURT", "프랑크푸르트"), - HAMBURG(CountryCd.GERMANY.countryCd, "HAMBURG", "함부르크"), - COLOGNE(CountryCd.GERMANY.countryCd, "COLOGNE", "쾰른"), - DUSSELDORF(CountryCd.GERMANY.countryCd, "DUSSELDORF", "뒤셀도르프"), - - // Italy - ROME(CountryCd.ITALY.countryCd, "ROME", "로마"), - MILAN(CountryCd.ITALY.countryCd, "MILAN", "밀라노"), - VENICE(CountryCd.ITALY.countryCd, "VENICE", "베네치아"), - FLORENCE(CountryCd.ITALY.countryCd, "FLORENCE", "피렌체"), - NAPLES(CountryCd.ITALY.countryCd, "NAPLES", "나폴리"), - TURIN(CountryCd.ITALY.countryCd, "TURIN", "투린"), - - // Spain - MADRID(CountryCd.SPAIN.countryCd, "MADRID", "마드리드"), - BARCELONA(CountryCd.SPAIN.countryCd, "BARCELONA", "바르셀로나"), - VALENCIA(CountryCd.SPAIN.countryCd, "VALENCIA", "발렌시아"), - SEVILLE(CountryCd.SPAIN.countryCd, "SEVILLE", "세비야"), - MALAGA(CountryCd.SPAIN.countryCd, "MALAGA", "말라가"), - BILBAO(CountryCd.SPAIN.countryCd, "BILBAO", "빌바오"), - - // Canada - TORONTO(CountryCd.CANADA.countryCd, "TORONTO", "토론토"), - VANCOUVER(CountryCd.CANADA.countryCd, "VANCOUVER", "밴쿠버"), - MONTREAL(CountryCd.CANADA.countryCd, "MONTREAL", "몬트리올"), - CALGARY(CountryCd.CANADA.countryCd, "CALGARY", "캘거리"), - OTTAWA(CountryCd.CANADA.countryCd, "OTTAWA", "오타와"), - QUEBEC_CITY(CountryCd.CANADA.countryCd, "QUEBEC_CITY", "퀘벡 시티"), - - // Australia - SYDNEY(CountryCd.AUSTRALIA.countryCd, "SYDNEY", "시드니"), - MELBOURNE(CountryCd.AUSTRALIA.countryCd, "MELBOURNE", "멜버른"), - BRISBANE(CountryCd.AUSTRALIA.countryCd, "BRISBANE", "브리즈번"), - PERTH(CountryCd.AUSTRALIA.countryCd, "PERTH", "퍼스"), - ADELAIDE(CountryCd.AUSTRALIA.countryCd, "ADELAIDE", "애들레이드"), - CANBERRA(CountryCd.AUSTRALIA.countryCd, "CANBERRA", "캔버라"), - - // Brazil - SAO_PAULO(CountryCd.BRAZIL.countryCd, "SAO_PAULO", "상파울로"), - RIO_DE_JANEIRO(CountryCd.BRAZIL.countryCd, "RIO_DE_JANEIRO", "리오 데 자네이로"), - BRASILIA(CountryCd.BRAZIL.countryCd, "BRASILIA", "브라질리아"), - SALVADOR(CountryCd.BRAZIL.countryCd, "SALVADOR", "살바도르"), - BELO_HORIZONTE(CountryCd.BRAZIL.countryCd, "BELO_HORIZONTE", "벨루 오리손티"), - - // India - MUMBAI(CountryCd.INDIA.countryCd, "MUMBAI", "뭄바이"), - NEW_DELHI(CountryCd.INDIA.countryCd, "NEW_DELHI", "뉴델리"), - BANGALORE(CountryCd.INDIA.countryCd, "BANGALORE", "방갈로르"), - CHENNAI(CountryCd.INDIA.countryCd, "CHENNAI", "첸나이"), - KOLKATA(CountryCd.INDIA.countryCd, "KOLKATA", "콜카타"), - HYDERABAD(CountryCd.INDIA.countryCd, "HYDERABAD", "하이데라바드"), - - MOSCOW(CountryCd.RUSSIA.countryCd, "MOSCOW", "모스크바"), - SAINT_PETERSBURG(CountryCd.RUSSIA.countryCd, "SAINT_PETERSBURG", "상트페테르부르크"), - NOVOSIBIRSK(CountryCd.RUSSIA.countryCd, "NOVOSIBIRSK", "노보시비르스크"), - EKATERINBURG(CountryCd.RUSSIA.countryCd, "EKATERINBURG", "예카테린부르크"), - KAZAN(CountryCd.RUSSIA.countryCd, "KAZAN", "카잔"), - NIZHNY_NOVGOROD(CountryCd.RUSSIA.countryCd, "NIZHNY_NOVGOROD", "니즈니 노브고로드"), - - // Turkey - ISTANBUL(CountryCd.TURKIYE.countryCd, "ISTANBUL", "이스탄불"), - ANKARA(CountryCd.TURKIYE.countryCd, "ANKARA", "앙카라"), - IZMIR(CountryCd.TURKIYE.countryCd, "IZMIR", "이즈미르"), - BURSA(CountryCd.TURKIYE.countryCd, "BURSA", "부르사"), - ANTALYA(CountryCd.TURKIYE.countryCd, "ANTALYA", "안탈리아"), - ADANA(CountryCd.TURKIYE.countryCd, "ADANA", "아다나"), - - // Argentina - BUENOS_AIRES(CountryCd.ARGENTINA.countryCd, "BUENOS_AIRES", "부에노스 아이레스"), - CORDOBA(CountryCd.ARGENTINA.countryCd, "CORDOBA", "코르도바"), - ROSARIO(CountryCd.ARGENTINA.countryCd, "ROSARIO", "로사리오"), - MENDOZA(CountryCd.ARGENTINA.countryCd, "MENDOZA", "멘도사"), - SALTA(CountryCd.ARGENTINA.countryCd, "SALTA", "살타"), - - // Egypt - CAIRO(CountryCd.EGYPT.countryCd, "CAIRO", "카이로"), - ALEXANDRIA(CountryCd.EGYPT.countryCd, "ALEXANDRIA", "알렉산드리아"), - LUXOR(CountryCd.EGYPT.countryCd, "LUXOR", "룩소르"), - SHARM_EL_SHEIKH(CountryCd.EGYPT.countryCd, "SHARM_EL_SHEIKH", "샤름 엘 쉬크"), - ASWAN(CountryCd.EGYPT.countryCd, "ASWAN", "아스완"), - HURGHADA(CountryCd.EGYPT.countryCd, "HURGHADA", "후르가다"), - - // Thailand - BANGKOK(CountryCd.THAILAND.countryCd, "BANGKOK", "방콕"), - PHUKET(CountryCd.THAILAND.countryCd, "PHUKET", "푸켓"), - CHIANG_MAI(CountryCd.THAILAND.countryCd, "CHIANG_MAI", "치앙마이"), - PATTAYA(CountryCd.THAILAND.countryCd, "PATTAYA", "파타야"), - KRABI(CountryCd.THAILAND.countryCd, "KRABI", "크라비"), - HUA_HIN(CountryCd.THAILAND.countryCd, "HUA_HIN", "후아힌"), - - // Mexico - MEXICO_CITY(CountryCd.MEXICO.countryCd, "MEXICO_CITY", "멕시코시티"), - CANCUN(CountryCd.MEXICO.countryCd, "CANCUN", "칸쿤"), - GUADALAJARA(CountryCd.MEXICO.countryCd, "GUADALAJARA", "과달라하라"), - MONTERREY(CountryCd.MEXICO.countryCd, "MONTERREY", "몬테레이"), - TULUM(CountryCd.MEXICO.countryCd, "TULUM", "툴룸"), - OAXACA(CountryCd.MEXICO.countryCd, "OAXACA", "오아하카"), - - // Indonesia - JAKARTA(CountryCd.INDONESIA.countryCd, "JAKARTA", "자카르타"), - BALI(CountryCd.INDONESIA.countryCd, "BALI", "발리"), - BANDUNG(CountryCd.INDONESIA.countryCd, "BANDUNG", "반둥"), - YOGYAKARTA(CountryCd.INDONESIA.countryCd, "YOGYAKARTA", "요가야카르타"), - SURABAYA(CountryCd.INDONESIA.countryCd, "SURABAYA", "수라바야"), - MAKASSAR(CountryCd.INDONESIA.countryCd, "MAKASSAR", "마카사르"); - -} \ No newline at end of file diff --git a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CountryCd.kt b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CountryCd.kt deleted file mode 100644 index 459fb3e..0000000 --- a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/CountryCd.kt +++ /dev/null @@ -1,189 +0,0 @@ -package com.travel.withaeng.common.cd - -enum class CountryCd( - val continentCd: String, - val countryCd: String, - val countryNm: String -) { - - KOREA(ContinentCd.EAST_ASIA.continentCd, "KOREA", "한국"), - JAPAN(ContinentCd.EAST_ASIA.continentCd, "JAPAN", "일본"), - HONG_KONG(ContinentCd.EAST_ASIA.continentCd, "HONG_KONG", "홍콩"), - MACAO(ContinentCd.EAST_ASIA.continentCd, "MACAO", "마카오"), - TAIWAN(ContinentCd.EAST_ASIA.continentCd, "TAIWAN", "대만"), - CHINA(ContinentCd.EAST_ASIA.continentCd, "CHINA", "중국"), - MONGOLIA(ContinentCd.EAST_ASIA.continentCd, "MONGOLIA", "몽골"), - - SINGAPORE(ContinentCd.SOUTHEAST_ASIA.continentCd, "SINGAPORE", "싱가포르"), - EAST_TIMOR(ContinentCd.SOUTHEAST_ASIA.continentCd, "EAST_TIMOR", "동티모르"), - MYANMAR(ContinentCd.SOUTHEAST_ASIA.continentCd, "MYANMAR", "미얀마"), - CAMBODIA(ContinentCd.SOUTHEAST_ASIA.continentCd, "CAMBODIA", "캄보디아"), - LAOS(ContinentCd.SOUTHEAST_ASIA.continentCd, "LAOS", "라오스"), - PHILIPPINES(ContinentCd.SOUTHEAST_ASIA.continentCd, "PHILIPPINES", "필리핀"), - MALAYSIA(ContinentCd.SOUTHEAST_ASIA.continentCd, "MALAYSIA", "말레이시아"), - INDONESIA(ContinentCd.SOUTHEAST_ASIA.continentCd, "INDONESIA", "인도네시아"), - THAILAND(ContinentCd.SOUTHEAST_ASIA.continentCd, "THAILAND", "태국"), - VIETNAM(ContinentCd.SOUTHEAST_ASIA.continentCd, "VIETNAM", "베트남"), - BRUNEI(ContinentCd.SOUTHEAST_ASIA.continentCd, "BRUNEI", "브루나이"), - - UZBEKISTAN(ContinentCd.CENTRAL_ASIA.continentCd, "UZBEKISTAN", "우즈베키스탄"), - BANGLADESH(ContinentCd.CENTRAL_ASIA.continentCd, "BANGLADESH", "방글라데시"), - AZERBAIJAN(ContinentCd.CENTRAL_ASIA.continentCd, "AZERBAIJAN", "아제르바이잔"), - BUTANE(ContinentCd.CENTRAL_ASIA.continentCd, "BUTANE", "부탄"), - AFGHANISTAN(ContinentCd.CENTRAL_ASIA.continentCd, "AFGHANISTAN", "아프가니스탄"), - TAJIKISTAN(ContinentCd.CENTRAL_ASIA.continentCd, "TAJIKISTAN", "타지키스탄"), - KYRGYZSTAN(ContinentCd.CENTRAL_ASIA.continentCd, "KYRGYZSTAN", "키르기스스탄"), - KAZAKHSTAN(ContinentCd.CENTRAL_ASIA.continentCd, "KAZAKHSTAN", "카자흐스탄"), - TURKMENISTAN(ContinentCd.CENTRAL_ASIA.continentCd, "TURKMENISTAN", "투르크메니스탄"), - TIBET(ContinentCd.CENTRAL_ASIA.continentCd, "TIBET", "티베트"), - - ARAB_EMIRATES(ContinentCd.WESTERN_ASIA.continentCd, "ARAB_EMIRATES", "아랍에미리트"), - JORDAN(ContinentCd.WESTERN_ASIA.continentCd, "JORDAN", "요르단"), - YEMEN(ContinentCd.WESTERN_ASIA.continentCd, "YEMEN", "예멘"), - SYRIA(ContinentCd.WESTERN_ASIA.continentCd, "SYRIA", "시리아"), - IRAN(ContinentCd.WESTERN_ASIA.continentCd, "IRAN", "이란"), - PAKISTAN(ContinentCd.WESTERN_ASIA.continentCd, "PAKISTAN", "파키스탄"), - CYPRUS(ContinentCd.WESTERN_ASIA.continentCd, "CYPRUS", "키프로스"), - SRI_LANKA(ContinentCd.WESTERN_ASIA.continentCd, "SRI_LANKA", "스리랑카"), - MALDIVE(ContinentCd.WESTERN_ASIA.continentCd, "MALDIVE", "몰디브"), - BAHRAIN(ContinentCd.WESTERN_ASIA.continentCd, "BAHRAIN", "바레인"), - LRAQ(ContinentCd.WESTERN_ASIA.continentCd, "LRAQ", "이라크"), - PALESTINE(ContinentCd.WESTERN_ASIA.continentCd, "PALESTINE", "팔레스타인"), - OMAN(ContinentCd.WESTERN_ASIA.continentCd, "OMAN", "오만"), - INDIA(ContinentCd.WESTERN_ASIA.continentCd, "INDIA", "인도"), - NEPAL(ContinentCd.WESTERN_ASIA.continentCd, "NEPAL", "네팔"), - ISRAEL(ContinentCd.WESTERN_ASIA.continentCd, "ISRAEL", "이스라엘"), - CATARRH(ContinentCd.WESTERN_ASIA.continentCd, "CATARRH", "카타르"), - LEBANON(ContinentCd.WESTERN_ASIA.continentCd, "LEBANON", "레바논"), - SAUDI_ARABIA(ContinentCd.WESTERN_ASIA.continentCd, "SAUDI_ARABIA", "사우디아라비아"), - KUWAIT(ContinentCd.WESTERN_ASIA.continentCd, "KUWAIT", "쿠웨이트"), - ARMENIA(ContinentCd.WESTERN_ASIA.continentCd, "ARMENIA", "아르메니아"), - - GEORGIA(ContinentCd.EUROPE.continentCd, "GEORGIA", "조지아"), - MALTA(ContinentCd.EUROPE.continentCd, "MALTA", "몰타"), - MOLDOVA(ContinentCd.EUROPE.continentCd, "MOLDOVA", "몰도바"), - MONTENEGRO(ContinentCd.EUROPE.continentCd, "MONTENEGRO", "몬테네그로"), - MONACO(ContinentCd.EUROPE.continentCd, "MONACO", "모나코"), - MACEDONIA(ContinentCd.EUROPE.continentCd, "MACEDONIA", "마케도니아"), - LIECHTENSTEIN(ContinentCd.EUROPE.continentCd, "LIECHTENSTEIN", "리히텐슈타인"), - LITHUANIA(ContinentCd.EUROPE.continentCd, "LITHUANIA", "리투아니아"), - LUXEMBOURG(ContinentCd.EUROPE.continentCd, "LUXEMBOURG", "룩셈부르크"), - ROMANIA(ContinentCd.EUROPE.continentCd, "ROMANIA", "루마니아"), - VATICAN(ContinentCd.EUROPE.continentCd, "VATICAN", "바티칸"), - BELARUS(ContinentCd.EUROPE.continentCd, "BELARUS", "벨라루스"), - BOSNIA_HERCEGOVINA(ContinentCd.EUROPE.continentCd, "BOSNIA_HERCEGOVINA", "보스니아헤르체코비나"), - CROATIA(ContinentCd.EUROPE.continentCd, "CROATIA", "크로아티아"), - UKRAINE(ContinentCd.EUROPE.continentCd, "UKRAINE", "우크라이나"), - ESTONIA(ContinentCd.EUROPE.continentCd, "ESTONIA", "에스토니아"), - ALBANIA(ContinentCd.EUROPE.continentCd, "ALBANIA", "알바니아"), - ANDORRA(ContinentCd.EUROPE.continentCd, "ANDORRA", "안도라"), - SLOVAKIA(ContinentCd.EUROPE.continentCd, "SLOVAKIA", "슬로바키아"), - SERBIA(ContinentCd.EUROPE.continentCd, "SERBIA", "세르비아"), - SAN_MARINO(ContinentCd.EUROPE.continentCd, "SAN_MARINO", "산마리노"), - BULGARIA(ContinentCd.EUROPE.continentCd, "BULGARIA", "불가리아"), - LATVIA(ContinentCd.EUROPE.continentCd, "LATVIA", "라트비아"), - SLOVENIA(ContinentCd.EUROPE.continentCd, "SLOVENIA", "슬로베니아"), - PORTUGAL(ContinentCd.EUROPE.continentCd, "PORTUGAL", "포르투갈"), - SWISS(ContinentCd.EUROPE.continentCd, "SWISS", "스위스"), - GERMANY(ContinentCd.EUROPE.continentCd, "GERMANY", "독일"), - NETHERLAND(ContinentCd.EUROPE.continentCd, "NETHERLAND", "네덜란드"), - AUSTRIA(ContinentCd.EUROPE.continentCd, "AUSTRIA", "오스트리아"), - ENGLAND(ContinentCd.EUROPE.continentCd, "ENGLAND", "영국"), - SPAIN(ContinentCd.EUROPE.continentCd, "SPAIN", "스페인"), - TURKIYE(ContinentCd.EUROPE.continentCd, "TURKIYE", "터키"), - ITALY(ContinentCd.EUROPE.continentCd, "ITALY", "이탈리아"), - POLAND(ContinentCd.EUROPE.continentCd, "POLAND", "폴란드"), - ICELAND(ContinentCd.EUROPE.continentCd, "ICELAND", "아이슬란드"), - FINLAND(ContinentCd.EUROPE.continentCd, "FINLAND", "핀란드"), - CZECHIA(ContinentCd.EUROPE.continentCd, "CZECHIA", "체코"), - BELGIUM(ContinentCd.EUROPE.continentCd, "BELGIUM", "벨기에"), - HUNGARY(ContinentCd.EUROPE.continentCd, "HUNGARY", "헝가리"), - IRELAND(ContinentCd.EUROPE.continentCd, "IRELAND", "아일랜드"), - RUSSIA(ContinentCd.EUROPE.continentCd, "RUSSIA", "러시아"), - GREECE(ContinentCd.EUROPE.continentCd, "GREECE", "그리스"), - DENMARK(ContinentCd.EUROPE.continentCd, "DENMARK", "덴마크"), - NORWAY(ContinentCd.EUROPE.continentCd, "NORWAY", "노르웨이"), - SWEDEN(ContinentCd.EUROPE.continentCd, "SWEDEN", "스웨덴"), - FRANCE(ContinentCd.EUROPE.continentCd, "FRANCE", "프랑스"), - - AUSTRALIA(ContinentCd.OCEANIA.continentCd, "AUSTRALIA", "호주"), - PALAU(ContinentCd.OCEANIA.continentCd, "PALAU", "팔라우"), - PAPUA_NEW_GUINEA(ContinentCd.OCEANIA.continentCd, "PAPUA_NEW_GUINEA", "파푸아뉴기니"), - TONGA(ContinentCd.OCEANIA.continentCd, "TONGA", "퉁가"), - KIRIBATI(ContinentCd.OCEANIA.continentCd, "KIRIBATI", "키리바시"), - SOLOMON_ISLAND(ContinentCd.OCEANIA.continentCd, "SOLOMON_ISLAND", "솔로몬제도"), - SAMOA(ContinentCd.OCEANIA.continentCd, "SAMOA", "사모아"), - - TUNISIA(ContinentCd.AFRICA.continentCd, "TUNISIA", "튀니지"), - ANGOLA(ContinentCd.AFRICA.continentCd, "ANGOLA", "앙골라"), - ALGERIA(ContinentCd.AFRICA.continentCd, "ALGERIA", "알제리"), - SIERRA_LEONE(ContinentCd.AFRICA.continentCd, "SIERRA_LEONE", "시에라리온"), - SUDAN(ContinentCd.AFRICA.continentCd, "SUDAN", "수단"), - SOMALIA(ContinentCd.AFRICA.continentCd, "SOMALIA", "소말리아"), - SEYCHELLES(ContinentCd.AFRICA.continentCd, "SEYCHELLES", "세이셸"), - SENEGAL(ContinentCd.AFRICA.continentCd, "SENEGAL", "세네갈"), - UGANDA(ContinentCd.AFRICA.continentCd, "UGANDA", "우간다"), - ZAMBIA(ContinentCd.AFRICA.continentCd, "ZAMBIA", "잠비아"), - EQUATORIAL_GUINEA(ContinentCd.AFRICA.continentCd, "EQUATORIAL_GUINEA", "적도기니"), - TOGO(ContinentCd.AFRICA.continentCd, "TOGO", "토고"), - CONGO(ContinentCd.AFRICA.continentCd, "CONGO", "콩고"), - COTE_D_IVOIRE(ContinentCd.AFRICA.continentCd, "COTE_D_IVOIRE", "코트디부아르"), - COMOROS(ContinentCd.AFRICA.continentCd, "COMOROS", "코모로"), - ZIMBABWE(ContinentCd.AFRICA.continentCd, "ZIMBABWE", "짐바브웨"), - DJIBOUTI(ContinentCd.AFRICA.continentCd, "DJIBOUTI", "지부티"), - CENTRAL_AFRICAN_REPUBLIC(ContinentCd.AFRICA.continentCd, "CENTRAL_AFRICAN_REPUBLIC", "중앙아프리카공화국"), - BURUNDI(ContinentCd.AFRICA.continentCd, "BURUNDI", "부룬디"), - BURKINA_FASO(ContinentCd.AFRICA.continentCd, "BURKINA_FASO", "부르키나파소"), - GUINEA_BISSAU(ContinentCd.AFRICA.continentCd, "GUINEA_BISSAU", "기니비사우"), - BOTSWANA(ContinentCd.AFRICA.continentCd, "BOTSWANA", "보츠와나"), - GUINEA(ContinentCd.AFRICA.continentCd, "GUINEA", "기니"), - GAMBIA(ContinentCd.AFRICA.continentCd, "GAMBIA", "감비아"), - GABON(ContinentCd.AFRICA.continentCd, "GABON", "가봉"), - GHANA(ContinentCd.AFRICA.continentCd, "GHANA", "가나"), - MOROCCO(ContinentCd.AFRICA.continentCd, "MOROCCO", "모로코"), - NAMIBIA(ContinentCd.AFRICA.continentCd, "NAMIBIA", "나미비아"), - KENYA(ContinentCd.AFRICA.continentCd, "KENYA", "케냐"), - ETHIOPIA(ContinentCd.AFRICA.continentCd, "ETHIOPIA", "에티오피아"), - TANZANIA(ContinentCd.AFRICA.continentCd, "TANZANIA", "탄자니아"), - NIGERIA(ContinentCd.AFRICA.continentCd, "NIGERIA", "나이지리아"), - BENIN(ContinentCd.AFRICA.continentCd, "BENIN", "베넹"), - NIGER(ContinentCd.AFRICA.continentCd, "NIGER", "니제르"), - MOZAMBIQUE(ContinentCd.AFRICA.continentCd, "MOZAMBIQUE", "모잠비크"), - MAURITANIA(ContinentCd.AFRICA.continentCd, "MAURITANIA", "모리타니"), - MAURITIUS(ContinentCd.AFRICA.continentCd, "MAURITIUS", "모리셔스"), - MALI(ContinentCd.AFRICA.continentCd, "MALI", "말리"), - MALAWI(ContinentCd.AFRICA.continentCd, "MALAWI", "말라위"), - MADAGASCAR(ContinentCd.AFRICA.continentCd, "MADAGASCAR", "마다가스카르"), - LIBYA(ContinentCd.AFRICA.continentCd, "LIBYA", "리비아"), - RWANDA(ContinentCd.AFRICA.continentCd, "RWANDA", "르완다"), - LESOTHO(ContinentCd.AFRICA.continentCd, "LESOTHO", "레소토"), - LIBERIA(ContinentCd.AFRICA.continentCd, "LIBERIA", "라이베리아"), - EGYPT(ContinentCd.AFRICA.continentCd, "EGYPT", "이집트"), - - UNITED_STATES(ContinentCd.NORTH_AMERICA.continentCd, "UNITED_STATES", "미국"), - CANADA(ContinentCd.NORTH_AMERICA.continentCd, "CANADA", "캐나다"), - MEXICO(ContinentCd.NORTH_AMERICA.continentCd, "MEXICO", "멕시코"), - ANTIGUA_AND_BARBUDA(ContinentCd.NORTH_AMERICA.continentCd, "ANTIGUA_AND_BARBUDA", "앤티가바부다"), - ARUBA(ContinentCd.NORTH_AMERICA.continentCd, "ARUBA", "아루바"), - ANGUILLA(ContinentCd.NORTH_AMERICA.continentCd, "ANGUILLA", "앵귈라"), - ANTARCTICA(ContinentCd.NORTH_AMERICA.continentCd, "ANTARCTICA", "남극"), - BAHAMAS(ContinentCd.NORTH_AMERICA.continentCd, "BAHAMAS", "바하마"), - BELIZE(ContinentCd.NORTH_AMERICA.continentCd, "BELIZE", "벨리즈"), - BARBADOS(ContinentCd.NORTH_AMERICA.continentCd, "BARBADOS", "바베이도스"), - BERMUDA(ContinentCd.NORTH_AMERICA.continentCd, "BERMUDA", "버뮤다"), - BOLIVIA(ContinentCd.NORTH_AMERICA.continentCd, "BOLIVIA", "볼리비아"), - BRAZIL(ContinentCd.NORTH_AMERICA.continentCd, "BRAZIL", "브라질"), - IRAQ(ContinentCd.NORTH_AMERICA.continentCd, "IRAQ", "이라크"), - QATAR(ContinentCd.NORTH_AMERICA.continentCd, "QATAR", "카타르"), - - ARGENTINA(ContinentCd.SOUTH_AMERICA.continentCd, "ARGENTINA", "아르헨티나"), - CHILE(ContinentCd.SOUTH_AMERICA.continentCd, "CHILE", "칠레"), - COLOMBIA(ContinentCd.SOUTH_AMERICA.continentCd, "COLOMBIA", "콜롬비아"), - ECUADOR(ContinentCd.SOUTH_AMERICA.continentCd, "ECUADOR", "에콰도르"), - PARAGUAY(ContinentCd.SOUTH_AMERICA.continentCd, "PARAGUAY", "파라과이"), - PERU(ContinentCd.SOUTH_AMERICA.continentCd, "PERU", "페루"), - SURINAME(ContinentCd.SOUTH_AMERICA.continentCd, "SURINAME", "수리남"), - URUGUAY(ContinentCd.SOUTH_AMERICA.continentCd, "URUGUAY", "우루과이"), - VENEZUELA(ContinentCd.SOUTH_AMERICA.continentCd, "VENEZUELA", "베네수엘라") - -} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestination.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestination.kt new file mode 100644 index 0000000..84725f7 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestination.kt @@ -0,0 +1,21 @@ +package com.travel.withaeng.domain.accompany + +import jakarta.persistence.Column +import jakarta.persistence.Embeddable +import jakarta.persistence.EnumType +import jakarta.persistence.Enumerated + +@Embeddable +data class AccompanyDestination( + @Enumerated(EnumType.STRING) + @Column(name = "continent") + val continent: Continent, + + @Enumerated(EnumType.STRING) + @Column(name = "country") + val country: Country, + + @Enumerated(EnumType.STRING) + @Column(name = "city") + val city: City +) \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/City.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/City.kt new file mode 100644 index 0000000..5a58c92 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/City.kt @@ -0,0 +1,179 @@ +package com.travel.withaeng.domain.accompany + +enum class City( + val countryCode: String, + val cityCode: String, + val cityName: String +) { + + SEOUL(Country.KOREA.countryCode, "SEOUL", "서울"), + BUSAN(Country.KOREA.countryCode, "BUSAN", "부산"), + INCHEON(Country.KOREA.countryCode, "INCHEON", "인천"), + DAEGU(Country.KOREA.countryCode, "DAEGU", "대구"), + GWANGJU(Country.KOREA.countryCode, "GWANGJU", "광주"), + DAEJEON(Country.KOREA.countryCode, "DAEJEON", "대전"), + ULSAN(Country.KOREA.countryCode, "ULSAN", "울산"), + SUWON(Country.KOREA.countryCode, "SUWON", "수원"), + CHANGWON(Country.KOREA.countryCode, "CHANGWON", "창원"), + JEJU(Country.KOREA.countryCode, "JEJU", "제주"), + + // Japan + TOKYO(Country.JAPAN.countryCode, "TOKYO", "도쿄"), + OSAKA(Country.JAPAN.countryCode, "OSAKA", "오사카"), + KYOTO(Country.JAPAN.countryCode, "KYOTO", "교토"), + SAPPORO(Country.JAPAN.countryCode, "SAPPORO", "삿포로"), + FUKUOKA(Country.JAPAN.countryCode, "FUKUOKA", "후쿠오카"), + HIROSHIMA(Country.JAPAN.countryCode, "HIROSHIMA", "히로시마"), + NAGOYA(Country.JAPAN.countryCode, "NAGOYA", "나고야"), + OKINAWA(Country.JAPAN.countryCode, "OKINAWA", "오키나와"), + KANAZAWA(Country.JAPAN.countryCode, "KANAZAWA", "가나자와"), + + // China + BEIJING(Country.CHINA.countryCode, "BEIJING", "베이징"), + SHANGHAI(Country.CHINA.countryCode, "SHANGHAI", "상하이"), + HONG_KONG(Country.CHINA.countryCode, "HONG_KONG", "홍콩"), + MACAO(Country.CHINA.countryCode, "MACAO", "마카오"), + GUANGZHOU(Country.CHINA.countryCode, "GUANGZHOU", "광저우"), + SHENZHEN(Country.CHINA.countryCode, "SHENZHEN", "선전"), + CHENGDU(Country.CHINA.countryCode, "CHENGDU", "청두"), + XIAMEN(Country.CHINA.countryCode, "XIAMEN", "샤먼"), + TIANJIN(Country.CHINA.countryCode, "TIANJIN", "천진"), + + // United States + NEW_YORK(Country.UNITED_STATES.countryCode, "NEW_YORK", "뉴욕"), + LOS_ANGELES(Country.UNITED_STATES.countryCode, "LOS_ANGELES", "로스앤젤레스"), + CHICAGO(Country.UNITED_STATES.countryCode, "CHICAGO", "시카고"), + LAS_VEGAS(Country.UNITED_STATES.countryCode, "LAS_VEGAS", "라스베이거스"), + SAN_FRANCISCO(Country.UNITED_STATES.countryCode, "SAN_FRANCISCO", "샌프란시스코"), + WASHINGTON_DC(Country.UNITED_STATES.countryCode, "WASHINGTON_DC", "워싱턴 D.C."), + MIAMI(Country.UNITED_STATES.countryCode, "MIAMI", "마이애미"), + ORLANDO(Country.UNITED_STATES.countryCode, "ORLANDO", "올랜도"), + SEATTLE(Country.UNITED_STATES.countryCode, "SEATTLE", "시애틀"), + + // United Kingdom + LONDON(Country.ENGLAND.countryCode, "LONDON", "런던"), + EDINBURGH(Country.ENGLAND.countryCode, "EDINBURGH", "에든버러"), + MANCHESTER(Country.ENGLAND.countryCode, "MANCHESTER", "맨체스터"), + BIRMINGHAM(Country.ENGLAND.countryCode, "BIRMINGHAM", "버밍엄"), + GLASGOW(Country.ENGLAND.countryCode, "GLASGOW", "글래스고"), + LIVERPOOL(Country.ENGLAND.countryCode, "LIVERPOOL", "리버풀"), + CAMBRIDGE(Country.ENGLAND.countryCode, "CAMBRIDGE", "케임브리지"), + + // France + PARIS(Country.FRANCE.countryCode, "PARIS", "파리"), + MARSEILLE(Country.FRANCE.countryCode, "MARSEILLE", "마르세유"), + LYON(Country.FRANCE.countryCode, "LYON", "리옹"), + NICE(Country.FRANCE.countryCode, "NICE", "니스"), + BORDEAUX(Country.FRANCE.countryCode, "BORDEAUX", "보르도"), + STRASBOURG(Country.FRANCE.countryCode, "STRASBOURG", "스트라스부르"), + + // Germany + BERLIN(Country.GERMANY.countryCode, "BERLIN", "베를린"), + MUNICH(Country.GERMANY.countryCode, "MUNICH", "뮌헨"), + FRANKFURT(Country.GERMANY.countryCode, "FRANKFURT", "프랑크푸르트"), + HAMBURG(Country.GERMANY.countryCode, "HAMBURG", "함부르크"), + COLOGNE(Country.GERMANY.countryCode, "COLOGNE", "쾰른"), + DUSSELDORF(Country.GERMANY.countryCode, "DUSSELDORF", "뒤셀도르프"), + + // Italy + ROME(Country.ITALY.countryCode, "ROME", "로마"), + MILAN(Country.ITALY.countryCode, "MILAN", "밀라노"), + VENICE(Country.ITALY.countryCode, "VENICE", "베네치아"), + FLORENCE(Country.ITALY.countryCode, "FLORENCE", "피렌체"), + NAPLES(Country.ITALY.countryCode, "NAPLES", "나폴리"), + TURIN(Country.ITALY.countryCode, "TURIN", "투린"), + + // Spain + MADRID(Country.SPAIN.countryCode, "MADRID", "마드리드"), + BARCELONA(Country.SPAIN.countryCode, "BARCELONA", "바르셀로나"), + VALENCIA(Country.SPAIN.countryCode, "VALENCIA", "발렌시아"), + SEVILLE(Country.SPAIN.countryCode, "SEVILLE", "세비야"), + MALAGA(Country.SPAIN.countryCode, "MALAGA", "말라가"), + BILBAO(Country.SPAIN.countryCode, "BILBAO", "빌바오"), + + // Canada + TORONTO(Country.CANADA.countryCode, "TORONTO", "토론토"), + VANCOUVER(Country.CANADA.countryCode, "VANCOUVER", "밴쿠버"), + MONTREAL(Country.CANADA.countryCode, "MONTREAL", "몬트리올"), + CALGARY(Country.CANADA.countryCode, "CALGARY", "캘거리"), + OTTAWA(Country.CANADA.countryCode, "OTTAWA", "오타와"), + QUEBEC_CITY(Country.CANADA.countryCode, "QUEBEC_CITY", "퀘벡 시티"), + + // Australia + SYDNEY(Country.AUSTRALIA.countryCode, "SYDNEY", "시드니"), + MELBOURNE(Country.AUSTRALIA.countryCode, "MELBOURNE", "멜버른"), + BRISBANE(Country.AUSTRALIA.countryCode, "BRISBANE", "브리즈번"), + PERTH(Country.AUSTRALIA.countryCode, "PERTH", "퍼스"), + ADELAIDE(Country.AUSTRALIA.countryCode, "ADELAIDE", "애들레이드"), + CANBERRA(Country.AUSTRALIA.countryCode, "CANBERRA", "캔버라"), + + // Brazil + SAO_PAULO(Country.BRAZIL.countryCode, "SAO_PAULO", "상파울로"), + RIO_DE_JANEIRO(Country.BRAZIL.countryCode, "RIO_DE_JANEIRO", "리오 데 자네이로"), + BRASILIA(Country.BRAZIL.countryCode, "BRASILIA", "브라질리아"), + SALVADOR(Country.BRAZIL.countryCode, "SALVADOR", "살바도르"), + BELO_HORIZONTE(Country.BRAZIL.countryCode, "BELO_HORIZONTE", "벨루 오리손티"), + + // India + MUMBAI(Country.INDIA.countryCode, "MUMBAI", "뭄바이"), + NEW_DELHI(Country.INDIA.countryCode, "NEW_DELHI", "뉴델리"), + BANGALORE(Country.INDIA.countryCode, "BANGALORE", "방갈로르"), + CHENNAI(Country.INDIA.countryCode, "CHENNAI", "첸나이"), + KOLKATA(Country.INDIA.countryCode, "KOLKATA", "콜카타"), + HYDERABAD(Country.INDIA.countryCode, "HYDERABAD", "하이데라바드"), + + MOSCOW(Country.RUSSIA.countryCode, "MOSCOW", "모스크바"), + SAINT_PETERSBURG(Country.RUSSIA.countryCode, "SAINT_PETERSBURG", "상트페테르부르크"), + NOVOSIBIRSK(Country.RUSSIA.countryCode, "NOVOSIBIRSK", "노보시비르스크"), + EKATERINBURG(Country.RUSSIA.countryCode, "EKATERINBURG", "예카테린부르크"), + KAZAN(Country.RUSSIA.countryCode, "KAZAN", "카잔"), + NIZHNY_NOVGOROD(Country.RUSSIA.countryCode, "NIZHNY_NOVGOROD", "니즈니 노브고로드"), + + // Turkey + ISTANBUL(Country.TURKIYE.countryCode, "ISTANBUL", "이스탄불"), + ANKARA(Country.TURKIYE.countryCode, "ANKARA", "앙카라"), + IZMIR(Country.TURKIYE.countryCode, "IZMIR", "이즈미르"), + BURSA(Country.TURKIYE.countryCode, "BURSA", "부르사"), + ANTALYA(Country.TURKIYE.countryCode, "ANTALYA", "안탈리아"), + ADANA(Country.TURKIYE.countryCode, "ADANA", "아다나"), + + // Argentina + BUENOS_AIRES(Country.ARGENTINA.countryCode, "BUENOS_AIRES", "부에노스 아이레스"), + CORDOBA(Country.ARGENTINA.countryCode, "CORDOBA", "코르도바"), + ROSARIO(Country.ARGENTINA.countryCode, "ROSARIO", "로사리오"), + MENDOZA(Country.ARGENTINA.countryCode, "MENDOZA", "멘도사"), + SALTA(Country.ARGENTINA.countryCode, "SALTA", "살타"), + + // Egypt + CAIRO(Country.EGYPT.countryCode, "CAIRO", "카이로"), + ALEXANDRIA(Country.EGYPT.countryCode, "ALEXANDRIA", "알렉산드리아"), + LUXOR(Country.EGYPT.countryCode, "LUXOR", "룩소르"), + SHARM_EL_SHEIKH(Country.EGYPT.countryCode, "SHARM_EL_SHEIKH", "샤름 엘 쉬크"), + ASWAN(Country.EGYPT.countryCode, "ASWAN", "아스완"), + HURGHADA(Country.EGYPT.countryCode, "HURGHADA", "후르가다"), + + // Thailand + BANGKOK(Country.THAILAND.countryCode, "BANGKOK", "방콕"), + PHUKET(Country.THAILAND.countryCode, "PHUKET", "푸켓"), + CHIANG_MAI(Country.THAILAND.countryCode, "CHIANG_MAI", "치앙마이"), + PATTAYA(Country.THAILAND.countryCode, "PATTAYA", "파타야"), + KRABI(Country.THAILAND.countryCode, "KRABI", "크라비"), + HUA_HIN(Country.THAILAND.countryCode, "HUA_HIN", "후아힌"), + + // Mexico + MEXICO_CITY(Country.MEXICO.countryCode, "MEXICO_CITY", "멕시코시티"), + CANCUN(Country.MEXICO.countryCode, "CANCUN", "칸쿤"), + GUADALAJARA(Country.MEXICO.countryCode, "GUADALAJARA", "과달라하라"), + MONTERREY(Country.MEXICO.countryCode, "MONTERREY", "몬테레이"), + TULUM(Country.MEXICO.countryCode, "TULUM", "툴룸"), + OAXACA(Country.MEXICO.countryCode, "OAXACA", "오아하카"), + + // Indonesia + JAKARTA(Country.INDONESIA.countryCode, "JAKARTA", "자카르타"), + BALI(Country.INDONESIA.countryCode, "BALI", "발리"), + BANDUNG(Country.INDONESIA.countryCode, "BANDUNG", "반둥"), + YOGYAKARTA(Country.INDONESIA.countryCode, "YOGYAKARTA", "요가야카르타"), + SURABAYA(Country.INDONESIA.countryCode, "SURABAYA", "수라바야"), + MAKASSAR(Country.INDONESIA.countryCode, "MAKASSAR", "마카사르"); + +} \ No newline at end of file diff --git a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/ContinentCd.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Continent.kt similarity index 73% rename from withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/ContinentCd.kt rename to withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Continent.kt index be1aaed..6773203 100644 --- a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/ContinentCd.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Continent.kt @@ -1,8 +1,8 @@ -package com.travel.withaeng.common.cd +package com.travel.withaeng.domain.accompany -enum class ContinentCd( - val continentCd: String, - val continentNm: String +enum class Continent( + val continentCode: String, + val continentName: String ) { EAST_ASIA("EA", "동아시아"), diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Country.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Country.kt new file mode 100644 index 0000000..d04471d --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Country.kt @@ -0,0 +1,189 @@ +package com.travel.withaeng.domain.accompany + +enum class Country( + val continentCode: String, + val countryCode: String, + val countryName: String +) { + + KOREA(Continent.EAST_ASIA.continentCode, "KOREA", "한국"), + JAPAN(Continent.EAST_ASIA.continentCode, "JAPAN", "일본"), + HONG_KONG(Continent.EAST_ASIA.continentCode, "HONG_KONG", "홍콩"), + MACAO(Continent.EAST_ASIA.continentCode, "MACAO", "마카오"), + TAIWAN(Continent.EAST_ASIA.continentCode, "TAIWAN", "대만"), + CHINA(Continent.EAST_ASIA.continentCode, "CHINA", "중국"), + MONGOLIA(Continent.EAST_ASIA.continentCode, "MONGOLIA", "몽골"), + + SINGAPORE(Continent.SOUTHEAST_ASIA.continentCode, "SINGAPORE", "싱가포르"), + EAST_TIMOR(Continent.SOUTHEAST_ASIA.continentCode, "EAST_TIMOR", "동티모르"), + MYANMAR(Continent.SOUTHEAST_ASIA.continentCode, "MYANMAR", "미얀마"), + CAMBODIA(Continent.SOUTHEAST_ASIA.continentCode, "CAMBODIA", "캄보디아"), + LAOS(Continent.SOUTHEAST_ASIA.continentCode, "LAOS", "라오스"), + PHILIPPINES(Continent.SOUTHEAST_ASIA.continentCode, "PHILIPPINES", "필리핀"), + MALAYSIA(Continent.SOUTHEAST_ASIA.continentCode, "MALAYSIA", "말레이시아"), + INDONESIA(Continent.SOUTHEAST_ASIA.continentCode, "INDONESIA", "인도네시아"), + THAILAND(Continent.SOUTHEAST_ASIA.continentCode, "THAILAND", "태국"), + VIETNAM(Continent.SOUTHEAST_ASIA.continentCode, "VIETNAM", "베트남"), + BRUNEI(Continent.SOUTHEAST_ASIA.continentCode, "BRUNEI", "브루나이"), + + UZBEKISTAN(Continent.CENTRAL_ASIA.continentCode, "UZBEKISTAN", "우즈베키스탄"), + BANGLADESH(Continent.CENTRAL_ASIA.continentCode, "BANGLADESH", "방글라데시"), + AZERBAIJAN(Continent.CENTRAL_ASIA.continentCode, "AZERBAIJAN", "아제르바이잔"), + BUTANE(Continent.CENTRAL_ASIA.continentCode, "BUTANE", "부탄"), + AFGHANISTAN(Continent.CENTRAL_ASIA.continentCode, "AFGHANISTAN", "아프가니스탄"), + TAJIKISTAN(Continent.CENTRAL_ASIA.continentCode, "TAJIKISTAN", "타지키스탄"), + KYRGYZSTAN(Continent.CENTRAL_ASIA.continentCode, "KYRGYZSTAN", "키르기스스탄"), + KAZAKHSTAN(Continent.CENTRAL_ASIA.continentCode, "KAZAKHSTAN", "카자흐스탄"), + TURKMENISTAN(Continent.CENTRAL_ASIA.continentCode, "TURKMENISTAN", "투르크메니스탄"), + TIBET(Continent.CENTRAL_ASIA.continentCode, "TIBET", "티베트"), + + ARAB_EMIRATES(Continent.WESTERN_ASIA.continentCode, "ARAB_EMIRATES", "아랍에미리트"), + JORDAN(Continent.WESTERN_ASIA.continentCode, "JORDAN", "요르단"), + YEMEN(Continent.WESTERN_ASIA.continentCode, "YEMEN", "예멘"), + SYRIA(Continent.WESTERN_ASIA.continentCode, "SYRIA", "시리아"), + IRAN(Continent.WESTERN_ASIA.continentCode, "IRAN", "이란"), + PAKISTAN(Continent.WESTERN_ASIA.continentCode, "PAKISTAN", "파키스탄"), + CYPRUS(Continent.WESTERN_ASIA.continentCode, "CYPRUS", "키프로스"), + SRI_LANKA(Continent.WESTERN_ASIA.continentCode, "SRI_LANKA", "스리랑카"), + MALDIVE(Continent.WESTERN_ASIA.continentCode, "MALDIVE", "몰디브"), + BAHRAIN(Continent.WESTERN_ASIA.continentCode, "BAHRAIN", "바레인"), + LRAQ(Continent.WESTERN_ASIA.continentCode, "LRAQ", "이라크"), + PALESTINE(Continent.WESTERN_ASIA.continentCode, "PALESTINE", "팔레스타인"), + OMAN(Continent.WESTERN_ASIA.continentCode, "OMAN", "오만"), + INDIA(Continent.WESTERN_ASIA.continentCode, "INDIA", "인도"), + NEPAL(Continent.WESTERN_ASIA.continentCode, "NEPAL", "네팔"), + ISRAEL(Continent.WESTERN_ASIA.continentCode, "ISRAEL", "이스라엘"), + CATARRH(Continent.WESTERN_ASIA.continentCode, "CATARRH", "카타르"), + LEBANON(Continent.WESTERN_ASIA.continentCode, "LEBANON", "레바논"), + SAUDI_ARABIA(Continent.WESTERN_ASIA.continentCode, "SAUDI_ARABIA", "사우디아라비아"), + KUWAIT(Continent.WESTERN_ASIA.continentCode, "KUWAIT", "쿠웨이트"), + ARMENIA(Continent.WESTERN_ASIA.continentCode, "ARMENIA", "아르메니아"), + + GEORGIA(Continent.EUROPE.continentCode, "GEORGIA", "조지아"), + MALTA(Continent.EUROPE.continentCode, "MALTA", "몰타"), + MOLDOVA(Continent.EUROPE.continentCode, "MOLDOVA", "몰도바"), + MONTENEGRO(Continent.EUROPE.continentCode, "MONTENEGRO", "몬테네그로"), + MONACO(Continent.EUROPE.continentCode, "MONACO", "모나코"), + MACEDONIA(Continent.EUROPE.continentCode, "MACEDONIA", "마케도니아"), + LIECHTENSTEIN(Continent.EUROPE.continentCode, "LIECHTENSTEIN", "리히텐슈타인"), + LITHUANIA(Continent.EUROPE.continentCode, "LITHUANIA", "리투아니아"), + LUXEMBOURG(Continent.EUROPE.continentCode, "LUXEMBOURG", "룩셈부르크"), + ROMANIA(Continent.EUROPE.continentCode, "ROMANIA", "루마니아"), + VATICAN(Continent.EUROPE.continentCode, "VATICAN", "바티칸"), + BELARUS(Continent.EUROPE.continentCode, "BELARUS", "벨라루스"), + BOSNIA_HERCEGOVINA(Continent.EUROPE.continentCode, "BOSNIA_HERCEGOVINA", "보스니아헤르체코비나"), + CROATIA(Continent.EUROPE.continentCode, "CROATIA", "크로아티아"), + UKRAINE(Continent.EUROPE.continentCode, "UKRAINE", "우크라이나"), + ESTONIA(Continent.EUROPE.continentCode, "ESTONIA", "에스토니아"), + ALBANIA(Continent.EUROPE.continentCode, "ALBANIA", "알바니아"), + ANDORRA(Continent.EUROPE.continentCode, "ANDORRA", "안도라"), + SLOVAKIA(Continent.EUROPE.continentCode, "SLOVAKIA", "슬로바키아"), + SERBIA(Continent.EUROPE.continentCode, "SERBIA", "세르비아"), + SAN_MARINO(Continent.EUROPE.continentCode, "SAN_MARINO", "산마리노"), + BULGARIA(Continent.EUROPE.continentCode, "BULGARIA", "불가리아"), + LATVIA(Continent.EUROPE.continentCode, "LATVIA", "라트비아"), + SLOVENIA(Continent.EUROPE.continentCode, "SLOVENIA", "슬로베니아"), + PORTUGAL(Continent.EUROPE.continentCode, "PORTUGAL", "포르투갈"), + SWISS(Continent.EUROPE.continentCode, "SWISS", "스위스"), + GERMANY(Continent.EUROPE.continentCode, "GERMANY", "독일"), + NETHERLAND(Continent.EUROPE.continentCode, "NETHERLAND", "네덜란드"), + AUSTRIA(Continent.EUROPE.continentCode, "AUSTRIA", "오스트리아"), + ENGLAND(Continent.EUROPE.continentCode, "ENGLAND", "영국"), + SPAIN(Continent.EUROPE.continentCode, "SPAIN", "스페인"), + TURKIYE(Continent.EUROPE.continentCode, "TURKIYE", "터키"), + ITALY(Continent.EUROPE.continentCode, "ITALY", "이탈리아"), + POLAND(Continent.EUROPE.continentCode, "POLAND", "폴란드"), + ICELAND(Continent.EUROPE.continentCode, "ICELAND", "아이슬란드"), + FINLAND(Continent.EUROPE.continentCode, "FINLAND", "핀란드"), + CZECHIA(Continent.EUROPE.continentCode, "CZECHIA", "체코"), + BELGIUM(Continent.EUROPE.continentCode, "BELGIUM", "벨기에"), + HUNGARY(Continent.EUROPE.continentCode, "HUNGARY", "헝가리"), + IRELAND(Continent.EUROPE.continentCode, "IRELAND", "아일랜드"), + RUSSIA(Continent.EUROPE.continentCode, "RUSSIA", "러시아"), + GREECE(Continent.EUROPE.continentCode, "GREECE", "그리스"), + DENMARK(Continent.EUROPE.continentCode, "DENMARK", "덴마크"), + NORWAY(Continent.EUROPE.continentCode, "NORWAY", "노르웨이"), + SWEDEN(Continent.EUROPE.continentCode, "SWEDEN", "스웨덴"), + FRANCE(Continent.EUROPE.continentCode, "FRANCE", "프랑스"), + + AUSTRALIA(Continent.OCEANIA.continentCode, "AUSTRALIA", "호주"), + PALAU(Continent.OCEANIA.continentCode, "PALAU", "팔라우"), + PAPUA_NEW_GUINEA(Continent.OCEANIA.continentCode, "PAPUA_NEW_GUINEA", "파푸아뉴기니"), + TONGA(Continent.OCEANIA.continentCode, "TONGA", "퉁가"), + KIRIBATI(Continent.OCEANIA.continentCode, "KIRIBATI", "키리바시"), + SOLOMON_ISLAND(Continent.OCEANIA.continentCode, "SOLOMON_ISLAND", "솔로몬제도"), + SAMOA(Continent.OCEANIA.continentCode, "SAMOA", "사모아"), + + TUNISIA(Continent.AFRICA.continentCode, "TUNISIA", "튀니지"), + ANGOLA(Continent.AFRICA.continentCode, "ANGOLA", "앙골라"), + ALGERIA(Continent.AFRICA.continentCode, "ALGERIA", "알제리"), + SIERRA_LEONE(Continent.AFRICA.continentCode, "SIERRA_LEONE", "시에라리온"), + SUDAN(Continent.AFRICA.continentCode, "SUDAN", "수단"), + SOMALIA(Continent.AFRICA.continentCode, "SOMALIA", "소말리아"), + SEYCHELLES(Continent.AFRICA.continentCode, "SEYCHELLES", "세이셸"), + SENEGAL(Continent.AFRICA.continentCode, "SENEGAL", "세네갈"), + UGANDA(Continent.AFRICA.continentCode, "UGANDA", "우간다"), + ZAMBIA(Continent.AFRICA.continentCode, "ZAMBIA", "잠비아"), + EQUATORIAL_GUINEA(Continent.AFRICA.continentCode, "EQUATORIAL_GUINEA", "적도기니"), + TOGO(Continent.AFRICA.continentCode, "TOGO", "토고"), + CONGO(Continent.AFRICA.continentCode, "CONGO", "콩고"), + COTE_D_IVOIRE(Continent.AFRICA.continentCode, "COTE_D_IVOIRE", "코트디부아르"), + COMOROS(Continent.AFRICA.continentCode, "COMOROS", "코모로"), + ZIMBABWE(Continent.AFRICA.continentCode, "ZIMBABWE", "짐바브웨"), + DJIBOUTI(Continent.AFRICA.continentCode, "DJIBOUTI", "지부티"), + CENTRAL_AFRICAN_REPUBLIC(Continent.AFRICA.continentCode, "CENTRAL_AFRICAN_REPUBLIC", "중앙아프리카공화국"), + BURUNDI(Continent.AFRICA.continentCode, "BURUNDI", "부룬디"), + BURKINA_FASO(Continent.AFRICA.continentCode, "BURKINA_FASO", "부르키나파소"), + GUINEA_BISSAU(Continent.AFRICA.continentCode, "GUINEA_BISSAU", "기니비사우"), + BOTSWANA(Continent.AFRICA.continentCode, "BOTSWANA", "보츠와나"), + GUINEA(Continent.AFRICA.continentCode, "GUINEA", "기니"), + GAMBIA(Continent.AFRICA.continentCode, "GAMBIA", "감비아"), + GABON(Continent.AFRICA.continentCode, "GABON", "가봉"), + GHANA(Continent.AFRICA.continentCode, "GHANA", "가나"), + MOROCCO(Continent.AFRICA.continentCode, "MOROCCO", "모로코"), + NAMIBIA(Continent.AFRICA.continentCode, "NAMIBIA", "나미비아"), + KENYA(Continent.AFRICA.continentCode, "KENYA", "케냐"), + ETHIOPIA(Continent.AFRICA.continentCode, "ETHIOPIA", "에티오피아"), + TANZANIA(Continent.AFRICA.continentCode, "TANZANIA", "탄자니아"), + NIGERIA(Continent.AFRICA.continentCode, "NIGERIA", "나이지리아"), + BENIN(Continent.AFRICA.continentCode, "BENIN", "베넹"), + NIGER(Continent.AFRICA.continentCode, "NIGER", "니제르"), + MOZAMBIQUE(Continent.AFRICA.continentCode, "MOZAMBIQUE", "모잠비크"), + MAURITANIA(Continent.AFRICA.continentCode, "MAURITANIA", "모리타니"), + MAURITIUS(Continent.AFRICA.continentCode, "MAURITIUS", "모리셔스"), + MALI(Continent.AFRICA.continentCode, "MALI", "말리"), + MALAWI(Continent.AFRICA.continentCode, "MALAWI", "말라위"), + MADAGASCAR(Continent.AFRICA.continentCode, "MADAGASCAR", "마다가스카르"), + LIBYA(Continent.AFRICA.continentCode, "LIBYA", "리비아"), + RWANDA(Continent.AFRICA.continentCode, "RWANDA", "르완다"), + LESOTHO(Continent.AFRICA.continentCode, "LESOTHO", "레소토"), + LIBERIA(Continent.AFRICA.continentCode, "LIBERIA", "라이베리아"), + EGYPT(Continent.AFRICA.continentCode, "EGYPT", "이집트"), + + UNITED_STATES(Continent.NORTH_AMERICA.continentCode, "UNITED_STATES", "미국"), + CANADA(Continent.NORTH_AMERICA.continentCode, "CANADA", "캐나다"), + MEXICO(Continent.NORTH_AMERICA.continentCode, "MEXICO", "멕시코"), + ANTIGUA_AND_BARBUDA(Continent.NORTH_AMERICA.continentCode, "ANTIGUA_AND_BARBUDA", "앤티가바부다"), + ARUBA(Continent.NORTH_AMERICA.continentCode, "ARUBA", "아루바"), + ANGUILLA(Continent.NORTH_AMERICA.continentCode, "ANGUILLA", "앵귈라"), + ANTARCTICA(Continent.NORTH_AMERICA.continentCode, "ANTARCTICA", "남극"), + BAHAMAS(Continent.NORTH_AMERICA.continentCode, "BAHAMAS", "바하마"), + BELIZE(Continent.NORTH_AMERICA.continentCode, "BELIZE", "벨리즈"), + BARBADOS(Continent.NORTH_AMERICA.continentCode, "BARBADOS", "바베이도스"), + BERMUDA(Continent.NORTH_AMERICA.continentCode, "BERMUDA", "버뮤다"), + BOLIVIA(Continent.NORTH_AMERICA.continentCode, "BOLIVIA", "볼리비아"), + BRAZIL(Continent.NORTH_AMERICA.continentCode, "BRAZIL", "브라질"), + IRAQ(Continent.NORTH_AMERICA.continentCode, "IRAQ", "이라크"), + QATAR(Continent.NORTH_AMERICA.continentCode, "QATAR", "카타르"), + + ARGENTINA(Continent.SOUTH_AMERICA.continentCode, "ARGENTINA", "아르헨티나"), + CHILE(Continent.SOUTH_AMERICA.continentCode, "CHILE", "칠레"), + COLOMBIA(Continent.SOUTH_AMERICA.continentCode, "COLOMBIA", "콜롬비아"), + ECUADOR(Continent.SOUTH_AMERICA.continentCode, "ECUADOR", "에콰도르"), + PARAGUAY(Continent.SOUTH_AMERICA.continentCode, "PARAGUAY", "파라과이"), + PERU(Continent.SOUTH_AMERICA.continentCode, "PERU", "페루"), + SURINAME(Continent.SOUTH_AMERICA.continentCode, "SURINAME", "수리남"), + URUGUAY(Continent.SOUTH_AMERICA.continentCode, "URUGUAY", "우루과이"), + VENEZUELA(Continent.SOUTH_AMERICA.continentCode, "VENEZUELA", "베네수엘라") + +} \ No newline at end of file From 77d7e88be31b68c18b7ad541f08e7859fa596001 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Fri, 10 May 2024 02:38:18 +0900 Subject: [PATCH 066/174] Implement Tag entity --- .../kotlin/com/travel/withaeng/domain/tag/Tag.kt | 13 +++++++++++++ .../com/travel/withaeng/domain/tag/TagRepository.kt | 5 +++++ 2 files changed, 18 insertions(+) create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/tag/Tag.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/tag/TagRepository.kt diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/tag/Tag.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/tag/Tag.kt new file mode 100644 index 0000000..2529a07 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/tag/Tag.kt @@ -0,0 +1,13 @@ +package com.travel.withaeng.domain.tag + +import com.travel.withaeng.domain.BaseEntity +import jakarta.persistence.Column +import jakarta.persistence.Entity +import jakarta.persistence.Table + +@Table(name = "tags") +@Entity +class Tag ( + @Column(name = "name", nullable = false) + val name: String +): BaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/tag/TagRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/tag/TagRepository.kt new file mode 100644 index 0000000..7d2260b --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/tag/TagRepository.kt @@ -0,0 +1,5 @@ +package com.travel.withaeng.domain.tag + +import org.springframework.data.jpa.repository.JpaRepository + +interface TagRepository : JpaRepository \ No newline at end of file From b9f5c17483b7ec1440e893e01f637d1c857e685b Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Fri, 10 May 2024 02:39:14 +0900 Subject: [PATCH 067/174] Fix member properties of Accompany entity --- .../withaeng/converter/TagIdsConverter.kt | 19 +++++ .../withaeng/domain/accompany/Accompany.kt | 73 +++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/TagIdsConverter.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/TagIdsConverter.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/TagIdsConverter.kt new file mode 100644 index 0000000..01d40fa --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/TagIdsConverter.kt @@ -0,0 +1,19 @@ +package com.travel.withaeng.converter + +import jakarta.persistence.AttributeConverter + +class TagIdsConverter : AttributeConverter, String> { + override fun convertToDatabaseColumn(attribute: Set): String { + return attribute.joinToString(DELIMITER) + } + + override fun convertToEntityAttribute(data: String): Set { + return data.split(DELIMITER).map { it.toLong() }.toSet() + + } + + companion object { + private const val DELIMITER = "," + } + +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt new file mode 100644 index 0000000..d9d7dad --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt @@ -0,0 +1,73 @@ +package com.travel.withaeng.domain.accompany + +import com.travel.withaeng.converter.TagIdsConverter +import com.travel.withaeng.domain.BaseEntity +import jakarta.persistence.* +import org.hibernate.annotations.DynamicUpdate +import java.time.LocalDate + +@DynamicUpdate +@Table(name = "accompany") +@Entity +class Accompany( + + @Column(name = "user_id", nullable = false) + val userId: Long, + + @Column(name = "title", nullable = false) + var title: String, + + @Lob + @Column(name = "content", nullable = false) + var content: String, + + @Enumerated(EnumType.STRING) + @Column(name = "accompany_status", nullable = false) + var accompanyStatus: AccompanyStatus = AccompanyStatus.ING, + + @Column(name = "start_trip_date", nullable = false) + var startTripDate: LocalDate, + + @Column(name = "end_trip_date", nullable = false) + var endTripDate: LocalDate, + + @Column(name = "banner_image_url") + var bannerImageUrl: String?, + + @Column(name = "member_count", nullable = false) + var memberCount: Long = 0L, + + @Column(name = "view_count", nullable = false) + var viewCount: Long = 0L, + + @Column(name = "open_kakao_url", nullable = false) + var openKakaoUrl: String, + + @Embedded + var accompanyDestination: AccompanyDestination, + + @Convert(converter = TagIdsConverter::class) + @Column(name = "tag_ids", nullable = false) + var tagIds: Set = setOf() + +) : BaseEntity() { + + companion object { + + fun create(params: CreateAccompanyDto): Accompany { + return Accompany( + userId = params.userId, + title = params.title, + content = params.content, + startTripDate = params.startTripDate, + endTripDate = params.endTripDate, + bannerImageUrl = params.bannerImageUrl, + memberCount = params.memberCount, + openKakaoUrl = params.openKakaoUrl, + accompanyDestination = params.destination, + tagIds = params.tagIds + ) + } + + } +} \ No newline at end of file From f7827de4f35da750b18dfd723a7b8f875354abb6 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Fri, 10 May 2024 02:39:40 +0900 Subject: [PATCH 068/174] Rename wrong class name --- .../withaeng/common/cd/AccompanyStatusCd.kt | 10 - .../com/travel/withaeng/common/cd/ExecCd.kt | 12 - .../withaeng/domain/accompany/AccompanyDto.kt | 240 +++--------------- .../domain/accompany/AccompanyRepository.kt | 6 +- .../domain/accompany/AccompanyService.kt | 129 +++------- .../domain/accompany/AccompanyStatus.kt | 6 + .../domain/accompanylike/AccompanyLike.kt | 18 ++ .../domain/accompanylike/AccompanyLikeHist.kt | 24 ++ .../AccompanyLikeHistRepository.kt | 2 +- .../accompanylike/AccompanyLikeRepository.kt | 5 +- .../accompanylike/AccompanyLikeService.kt | 22 +- .../domain/accompanyreply/AccompanyReply.kt | 32 +++ .../accompanyreply/AccompanyReplyHist.kt | 36 +++ .../AccompanyReplyHistRepository.kt | 2 +- .../AccompanyReplyRepository.kt | 4 +- .../accompanyreplylike/AccompanyReplyLike.kt | 18 ++ .../AccompanyReplyLikeHist.kt | 24 ++ .../AccompanyReplyLikeHistRepository.kt | 2 +- .../AccompanyReplyLikeRepository.kt | 4 +- .../domain/destination/DestinationService.kt | 22 +- 20 files changed, 257 insertions(+), 361 deletions(-) delete mode 100644 withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/AccompanyStatusCd.kt delete mode 100644 withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/ExecCd.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyStatus.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLike.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHist.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHist.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLike.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHist.kt diff --git a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/AccompanyStatusCd.kt b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/AccompanyStatusCd.kt deleted file mode 100644 index dbb161e..0000000 --- a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/AccompanyStatusCd.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.travel.withaeng.common.cd - -enum class AccompanyStatusCd( - val statusCd: String, - val statusNm: String -) { - - ING("ING", "동행 구인중"), - COMPLETE("COMPLETE", "동행 모집 완료"), -} diff --git a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/ExecCd.kt b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/ExecCd.kt deleted file mode 100644 index 2ca9c14..0000000 --- a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/cd/ExecCd.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.travel.withaeng.common.cd - -enum class ExecCd( - val execCd: String, - val execNm: String -) { - - CREATE("CREATE", "등록"), - UPDATE("UPDATE", "수정"), - DELETE("DELETE", "삭제") - -} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt index bcf1997..ee4d4cb 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt @@ -1,226 +1,62 @@ package com.travel.withaeng.domain.accompany -import com.fasterxml.jackson.annotation.JsonProperty -import com.travel.withaeng.common.cd.AccompanyStatusCd -import com.travel.withaeng.common.cd.ExecCd -import jakarta.validation.constraints.NotBlank -import org.jetbrains.annotations.NotNull import java.time.LocalDate -import java.time.LocalDateTime -import java.time.LocalTime -class CreateAccompanyDTO( - - @NotNull - @JsonProperty("userId") +data class CreateAccompanyDto( val userId: Long, - - @NotBlank(message = "제목은 필수 값 입니다.") - @JsonProperty("title") val title: String, - - @NotBlank(message = "내용은 필수 값 입니다.") - @JsonProperty("content") val content: String, - - @NotBlank(message = "대륙은 필수 값 입니다.") - val continent: String, - - val country: String? = null, - - val city: String? = null, - + val destination: AccompanyDestination, val startTripDate: LocalDate, - val endTripDate: LocalDate, - val bannerImageUrl: String? = null, - - @field:NotNull - val accompanyCnt: Long, - - val tags: List?, - - @NotBlank(message = "카카오 오픈 채팅 URL은 필수 값 입니다.") + val memberCount: Long, + val tagIds: Set = emptySet(), val openKakaoUrl: String +) -) { - fun toEntity(): AccompanyEntity { - return AccompanyEntity( - 0, - this.userId, - this.title, - this.content, - AccompanyStatusCd.ING.statusCd, - this.startTripDate.atTime(LocalTime.MIN), - this.endTripDate.atTime(LocalTime.MAX), - this.bannerImageUrl, - this.accompanyCnt - ) - } - - fun toHistEntity(entity: AccompanyEntity): AccompanyHistEntity { - return AccompanyHistEntity( - 0, - entity.accompanyId, - entity.userId, - entity.title, - entity.content, - entity.accompanyStatusCd, - entity.startTripDate, - entity.endTripDate, - entity.bannerImageUrl, - entity.accompanyCnt, - ExecCd.CREATE.execCd - ) - } - - fun toDestinationEntity(accompanyId: Long): AccompanyDestinationEntity { - return AccompanyDestinationEntity( - 0, - accompanyId, - this.continent, - this.country, - this.city - ) - } - - fun toDetailEntity(accompanyId: Long): AccompanyDetailEntity { - return AccompanyDetailEntity( - accompanyId, - 0, - 0, - this.openKakaoUrl - ) - } - - fun toTagEntity(accompanyId: Long): List? { - - if (tags == null) { - return null - } - - val tagList = mutableListOf() - for (tagNm in tags) { - tagList.add(AccompanyTagEntity(0, accompanyId, tagNm)) - } - - return tagList - } -} - -class ModifyAccompanyDTO( - - @NotNull +data class UpdateAccompanyDto( val accompanyId: Long, + val title: String? = null, + val content: String? = null, + val destination: AccompanyDestination? = null, + val startTripDate: LocalDate? = null, + val endTripDate: LocalDate? = null, + val bannerImageUrl: String? = null, + val memberCount: Long? = null, + val tagIds: Set? = null, + val openKakaoUrl: String? = null +) - @NotNull +data class AccompanyDto( + val id: Long, val userId: Long, - - @NotBlank(message = "제목은 필수 값 입니다.") val title: String, - - @NotBlank(message = "내용은 필수 값 입니다.") val content: String, - - @NotBlank(message = "대륙은 필수 값 입니다.") - val continent: String, - - val country: String? = null, - - val city: String? = null, - + val destination: AccompanyDestination, val startTripDate: LocalDate, - val endTripDate: LocalDate, - val bannerImageUrl: String? = null, - - @NotNull - val accompanyCnt: Long, - - val tags: List?, - - @NotBlank(message = "카카오 오픈 채팅 URL은 필수 값 입니다.") + val memberCount: Long, + val viewCount: Long, val openKakaoUrl: String - -) { - fun toHistEntity(entity: AccompanyEntity): AccompanyHistEntity { - return AccompanyHistEntity( - 0, - entity.accompanyId, - entity.userId, - entity.title, - entity.content, - entity.accompanyStatusCd, - entity.startTripDate, - entity.endTripDate, - entity.bannerImageUrl, - entity.accompanyCnt, - ExecCd.UPDATE.execCd - ) - } - - fun toTagEntity(accompanyId: Long): List? { - - if (tags == null) { - return null - } - - val tagList = mutableListOf() - for (tagNm in tags) { - tagList.add(AccompanyTagEntity(0, accompanyId, tagNm)) - } - - return tagList - } -} - -data class GetDTO( - - var accompanyId: Long, - var userId: Long, - var title: String, - var content: String, - var continent: String, - var country: String? = null, - var city: String? = null, - var startTripDate: LocalDateTime, - var endTripDate: LocalDateTime, - var bannerImageUrl: String? = null, - var accompanyCnt: Long, - var viewCnt: Long, - var likeCnt: Long, - var tags: List? = null, - var openKakaoUrl: String - -) { - constructor( - accompanyId: Long, userId: Long, title: String, content: String, - continent: String, country: String?, city: String?, - startTripDate: LocalDateTime, endTripDate: LocalDateTime, - bannerImageUrl: String?, accompanyCnt: Long, viewCnt: Long, likeCnt: Long, openKakaoUrl: String - ) : - this( - accompanyId, - userId, - title, - content, - continent, - country, - city, - startTripDate, - endTripDate, - bannerImageUrl, - accompanyCnt, - viewCnt, - likeCnt, - null, - openKakaoUrl - ) -} - -data class SearchAccompanyDTO( +) + +fun Accompany.toDto(): AccompanyDto = AccompanyDto( + id = id, + userId = userId, + title = title, + content = content, + destination = accompanyDestination, + startTripDate = startTripDate, + endTripDate = endTripDate, + bannerImageUrl = bannerImageUrl, + memberCount = memberCount, + viewCount = viewCount, + openKakaoUrl = openKakaoUrl +) + +data class SearchAccompanyDto( var viewCntOrder: Boolean,//조회수 높은 순서 diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt index 7fa84bf..42cea7f 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt @@ -2,8 +2,4 @@ package com.travel.withaeng.domain.accompany import org.springframework.data.jpa.repository.JpaRepository -interface AccompanyRepository : JpaRepository, AccompanyRepositoryCustom { - - fun findByAccompanyId(accompanyId: Long): AccompanyEntity? - -} \ No newline at end of file +interface AccompanyRepository : JpaRepository \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt index 3b306ea..8820823 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt @@ -2,125 +2,62 @@ package com.travel.withaeng.domain.accompany import com.travel.withaeng.common.exception.WithaengException import com.travel.withaeng.common.exception.WithaengExceptionType +import com.travel.withaeng.domain.tag.TagRepository +import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional -import java.time.LocalTime @Service @Transactional(readOnly = true) class AccompanyService( - private val accompanyRepository: AccompanyRepository, - private val accompanyHistRepository: AccompanyHistRepository, - private val accompanyDestinationRepository: AccompanyDestinationRepository, - private val accompanyDetailRepository: AccompanyDetailRepository, - private val accompanyTagRepository: AccompanyTagRepository - + private val tagRepository: TagRepository ) { @Transactional - fun createAccompany(param: CreateAccompanyDTO): GetDTO { - val accompanyEntity = param.toEntity() + fun create(params: CreateAccompanyDto): AccompanyDto { + val actualTagIds = filterValidTagIds(params.tagIds) + val actualParams = params.copy(tagIds = actualTagIds) + val accompanyEntity = Accompany.create(actualParams) accompanyRepository.save(accompanyEntity) - - val accompanyHistEntity = param.toHistEntity(accompanyEntity) - val accompanyDestinationEntity = param.toDestinationEntity(accompanyEntity.accompanyId) - val accompanyDetailEntity = param.toDetailEntity(accompanyEntity.accompanyId) - val accompanyTagEntityList = param.toTagEntity(accompanyEntity.accompanyId) - - accompanyHistRepository.save(accompanyHistEntity) - accompanyDestinationRepository.save(accompanyDestinationEntity) - accompanyDetailRepository.save(accompanyDetailEntity) - - if (accompanyTagEntityList != null) { - accompanyTagRepository.saveAll(accompanyTagEntityList) - } - - return getOne(accompanyEntity.accompanyId) + return accompanyEntity.toDto() } @Transactional - fun modifyAccompany(param: ModifyAccompanyDTO): GetDTO { - - val accompanyEntity = accompanyRepository.findByAccompanyId(param.accompanyId) - - if (accompanyEntity != null) { - - if (accompanyEntity.userId != param.userId) { - throw WithaengException.of( - type = WithaengExceptionType.INVALID_ACCESS, - message = "등록자와 수정자가 달라 수정 요청을 거부 합니다." - ) - } - - val accompanyHistEntity = param.toHistEntity(accompanyEntity) - val accompanyDestinationEntity = accompanyDestinationRepository.findByAccompanyId(param.accompanyId) - val accompanyDetailEntity = accompanyDetailRepository.findByAccompanyId(param.accompanyId) - val accompanyTagEntityList = param.toTagEntity(accompanyEntity.accompanyId) - - accompanyEntity.let { - it.title = param.title - it.content = param.content - it.startTripDate = param.startTripDate.atTime(LocalTime.MIN) - it.endTripDate = param.endTripDate.atTime(LocalTime.MAX) - it.bannerImageUrl = param.bannerImageUrl - it.accompanyCnt = param.accompanyCnt - } - - accompanyDetailEntity.let { - it.openKakaoUrl = param.openKakaoUrl - } - - accompanyDestinationEntity.let { - it.continent = param.continent - it.country = param.country - it.city = param.city - } - - accompanyHistRepository.save(accompanyHistEntity) - accompanyTagRepository.deleteByAccompanyId(accompanyEntity.accompanyId) - if (accompanyTagEntityList != null) { - accompanyTagRepository.saveAll(accompanyTagEntityList) - } - - } - - return getOne(param.accompanyId) + fun update(params: UpdateAccompanyDto): AccompanyDto { + val accompany = accompanyRepository.findByIdOrNull(params.accompanyId) ?: throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = NOT_EXIST_MESSAGE + ) + params.title?.let { accompany.title = it } + params.content?.let { accompany.content = it } + params.destination?.let { accompany.accompanyDestination = it } + params.startTripDate?.let { accompany.startTripDate = it } + params.endTripDate?.let { accompany.endTripDate = it } + params.bannerImageUrl?.let { accompany.bannerImageUrl = it } + params.memberCount?.let { accompany.memberCount = it } + params.tagIds?.let { accompany.tagIds = filterValidTagIds(it) } + params.openKakaoUrl?.let { accompany.openKakaoUrl = it } + + return accompany.toDto() } - fun getOne(param: Long): GetDTO { - - val getAccompany = accompanyRepository.getAccompany(param) - - if (getAccompany != null) { - val tagList: List? = accompanyTagRepository.findByAccompanyId(param)?.map(AccompanyTagEntity::tagNm) - getAccompany.tags = tagList - return getAccompany - } - - throw WithaengException.of( + fun findById(id: Long): AccompanyDto { + return accompanyRepository.findByIdOrNull(id)?.toDto() ?: throw WithaengException.of( type = WithaengExceptionType.NOT_EXIST, - message = "존재하지 않는 동행 게시글 조회 요청 입니다." + message = NOT_EXIST_MESSAGE ) } - fun getList(param: SearchAccompanyDTO): List { - return accompanyRepository.getAccompanyList(param) + fun findAll(): List { + return accompanyRepository.findAll().map { it.toDto() } } - @Transactional - fun incrViewCnt(param: Long) { - val accompanyDetailEntity = accompanyDetailRepository.findByAccompanyId(param) - accompanyDetailEntity.let { - it.viewCnt++ - } + private fun filterValidTagIds(tagIds: Iterable): Set { + return tagRepository.findAllById(tagIds).map { it.id }.toSet() } - @Transactional - fun decrViewCnt(param: Long) { - val accompanyDetailEntity = accompanyDetailRepository.findByAccompanyId(param) - accompanyDetailEntity.let { - it.viewCnt-- - } + companion object { + private const val NOT_EXIST_MESSAGE = "해당하는 동행을 찾을 수 없습니다." } } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyStatus.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyStatus.kt new file mode 100644 index 0000000..9fd4188 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyStatus.kt @@ -0,0 +1,6 @@ +package com.travel.withaeng.domain.accompany + +enum class AccompanyStatus(val statusDescription: String) { + ING("동행 구인중"), + COMPLETE("동행 모집 완료"), +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLike.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLike.kt new file mode 100644 index 0000000..f86d23d --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLike.kt @@ -0,0 +1,18 @@ +package com.travel.withaeng.domain.accompanylike + +import com.travel.withaeng.domain.BaseEntity +import jakarta.persistence.Column +import jakarta.persistence.Entity +import jakarta.persistence.Table + +@Table(name = "accompany_like") +@Entity +class AccompanyLike( + + @Column(name = "accompany_id", nullable = false) + val accompanyId: Long, + + @Column(name = "user_id", nullable = false) + val userId: Long + +) : BaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHist.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHist.kt new file mode 100644 index 0000000..392a0ee --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHist.kt @@ -0,0 +1,24 @@ +package com.travel.withaeng.domain.accompanylike + +import com.travel.withaeng.domain.BaseEntity +import jakarta.persistence.Column +import jakarta.persistence.Entity +import jakarta.persistence.Table + +@Table(name = "accompany_like_hist") +@Entity +class AccompanyLikeHist( + + @Column(name = "like_id", nullable = false) + val likeId: Long, + + @Column(name = "user_id", nullable = false) + val userId: Long, + + @Column(name = "accompany_id", nullable = false) + val accompanyId: Long, + + @Column(name = "exec_cd", nullable = false) + val execCd: String + +) : BaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistRepository.kt index 1285f9e..d674795 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistRepository.kt @@ -2,4 +2,4 @@ package com.travel.withaeng.domain.accompanylike import org.springframework.data.jpa.repository.JpaRepository -interface AccompanyLikeHistRepository : JpaRepository +interface AccompanyLikeHistRepository : JpaRepository diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeRepository.kt index dfbbf7d..dfec9ae 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeRepository.kt @@ -2,4 +2,7 @@ package com.travel.withaeng.domain.accompanylike import org.springframework.data.jpa.repository.JpaRepository -interface AccompanyLikeRepository : JpaRepository \ No newline at end of file +interface AccompanyLikeRepository : JpaRepository { + fun countByAccompanyId(accompanyId: Long): Long + fun countByAccompanyIdIsIn(accompanyIds: Set): Long +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt index 40fee2d..90fc337 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt @@ -1,18 +1,13 @@ package com.travel.withaeng.domain.accompanylike -import com.travel.withaeng.domain.accompany.AccompanyDetailRepository import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional -import java.time.LocalDateTime @Service @Transactional(readOnly = true) class AccompanyLikeService( - private val accompanyLikeRepository: AccompanyLikeRepository, - private val accompanyLikeHistRepository: AccompanyLikeHistRepository, - private val accompanyDetailRepository: AccompanyDetailRepository - + private val accompanyLikeHistRepository: AccompanyLikeHistRepository ) { @Transactional @@ -24,14 +19,13 @@ class AccompanyLikeService( val accompanyLikeHistEntity = param.toHistEntity(accompanyLikeEntity) accompanyLikeHistRepository.save(accompanyLikeHistEntity) - val accompanyDetailEntity = accompanyDetailRepository.findByAccompanyId(param.accompanyId) - accompanyDetailEntity.let { - it.likeCnt++ - } - return param } + fun countByAccompanyId(accompanyId: Long): Long { + return accompanyLikeRepository.countByAccompanyId(accompanyId) + } + //TODO delete 성능이 안나올 경우 boolean 형으로 좋아요 제어 @Transactional fun deleteAccompanyLike(param: DeleteAccompanyLikeDTO): DeleteAccompanyLikeDTO { @@ -40,14 +34,8 @@ class AccompanyLikeService( accompanyLikeRepository.delete(accompanyLikeEntity) val accompanyLikeHistEntity = param.toHistEntity(accompanyLikeEntity) - accompanyLikeHistEntity.deletedAt = LocalDateTime.now() accompanyLikeHistRepository.save(accompanyLikeHistEntity) - val accompanyDetailEntity = accompanyDetailRepository.findByAccompanyId(param.accompanyId) - accompanyDetailEntity.let { - it.likeCnt-- - } - return param } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt new file mode 100644 index 0000000..afc7b02 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt @@ -0,0 +1,32 @@ +package com.travel.withaeng.domain.accompanyreply + +import com.travel.withaeng.domain.BaseEntity +import jakarta.persistence.Column +import jakarta.persistence.Entity +import jakarta.persistence.Table +import org.hibernate.annotations.DynamicUpdate + +@DynamicUpdate +@Table(name = "accompany_reply") +@Entity +class AccompanyReply( + + @Column(name = "accompany_id", nullable = false) + val accompanyId: Long, + + @Column(name = "parent_id", nullable = false) + val parentId: Long, + + @Column(name = "depth", nullable = false) + val depth: Long, + + @Column(name = "reply_order", nullable = false) + val replyOrder: Long, + + @Column(name = "user_id", nullable = false) + val userId: Long, + + @Column(name = "content", nullable = false) + var content: String + +) : BaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHist.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHist.kt new file mode 100644 index 0000000..8ec7444 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHist.kt @@ -0,0 +1,36 @@ +package com.travel.withaeng.domain.accompanyreply + +import com.travel.withaeng.domain.BaseEntity +import jakarta.persistence.Column +import jakarta.persistence.Entity +import jakarta.persistence.Table + +@Table(name = "accompany_reply_hist") +@Entity +class AccompanyReplyHist( + + @Column(name = "reply_id", nullable = false) + val replyId: Long, + + @Column(name = "accompany_id", nullable = false) + val accompanyId: Long, + + @Column(name = "parent_id", nullable = false) + val parentId: Long, + + @Column(name = "depth", nullable = false) + val depth: Long, + + @Column(name = "reply_order", nullable = false) + val replyOrder: Long, + + @Column(name = "user_id", nullable = false) + val userId: Long, + + @Column(name = "content", nullable = false) + val content: String, + + @Column(name = "exec_cd", nullable = false) + val execCd: String + +) : BaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHistRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHistRepository.kt index e8cc3c9..22a8b7a 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHistRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHistRepository.kt @@ -2,4 +2,4 @@ package com.travel.withaeng.domain.accompanyreply import org.springframework.data.jpa.repository.JpaRepository -interface AccompanyReplyHistRepository : JpaRepository \ No newline at end of file +interface AccompanyReplyHistRepository : JpaRepository \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt index 54687bb..0f02f44 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt @@ -2,7 +2,7 @@ package com.travel.withaeng.domain.accompanyreply import org.springframework.data.jpa.repository.JpaRepository -interface AccompanyReplyRepository : JpaRepository, AccompanyReplyRepositoryCustom { - fun findByReplyId(replyId: Long): AccompanyReplyEntity? +interface AccompanyReplyRepository : JpaRepository, AccompanyReplyRepositoryCustom { + fun findByReplyId(replyId: Long): AccompanyReply? } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLike.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLike.kt new file mode 100644 index 0000000..204a78a --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLike.kt @@ -0,0 +1,18 @@ +package com.travel.withaeng.domain.accompanyreplylike + +import com.travel.withaeng.domain.BaseEntity +import jakarta.persistence.Column +import jakarta.persistence.Entity +import jakarta.persistence.Table + +@Table(name = "accompany_reply_like") +@Entity +class AccompanyReplyLike( + + @Column(name = "reply_id", nullable = false) + val replyId: Long, + + @Column(name = "user_id", nullable = false) + val userId: Long + +) : BaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHist.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHist.kt new file mode 100644 index 0000000..c168801 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHist.kt @@ -0,0 +1,24 @@ +package com.travel.withaeng.domain.accompanyreplylike + +import com.travel.withaeng.domain.BaseEntity +import jakarta.persistence.Column +import jakarta.persistence.Entity +import jakarta.persistence.Table + +@Table(name = "accompany_reply_like_hist") +@Entity +class AccompanyReplyLikeHist( + + @Column(name = "reply_like_id", nullable = false) + val replyLikeId: Long, + + @Column(name = "reply_id", nullable = false) + val replyId: Long, + + @Column(name = "user_id", nullable = false) + val userId: Long, + + @Column(name = "exec_cd", nullable = false) + val execCd: String + +) : BaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHistRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHistRepository.kt index 8e2056e..d5c9184 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHistRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHistRepository.kt @@ -2,4 +2,4 @@ package com.travel.withaeng.domain.accompanyreplylike import org.springframework.data.jpa.repository.JpaRepository -interface AccompanyReplyLikeHistRepository : JpaRepository \ No newline at end of file +interface AccompanyReplyLikeHistRepository : JpaRepository \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt index 4591797..bc6d1a4 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt @@ -2,10 +2,10 @@ package com.travel.withaeng.domain.accompanyreplylike import org.springframework.data.jpa.repository.JpaRepository -interface AccompanyReplyLikeRepository : JpaRepository, +interface AccompanyReplyLikeRepository : JpaRepository, AccompanyReplyLikeRepositoryCustom { fun countByReplyId(replyId: Long): Long - fun findByReplyIdAndUserId(replyId: Long, userId: Long): AccompanyReplyLikeEntity? + fun findByReplyIdAndUserId(replyId: Long, userId: Long): AccompanyReplyLike? } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationService.kt index 9baa835..f7dc586 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationService.kt @@ -1,8 +1,8 @@ package com.travel.withaeng.domain.destination -import com.travel.withaeng.common.cd.CityCd -import com.travel.withaeng.common.cd.ContinentCd -import com.travel.withaeng.common.cd.CountryCd +import com.travel.withaeng.domain.accompany.City +import com.travel.withaeng.domain.accompany.Continent +import com.travel.withaeng.domain.accompany.Country import org.springframework.stereotype.Service @Service @@ -12,20 +12,20 @@ class DestinationService { val continentList = mutableListOf() - for (continentCd in ContinentCd.entries) { + for (continentCd in Continent.entries) { // Create a continent object - val continent = Continent(continentCd.continentCd, continentCd.continentNm) + val continent = Continent(continentCd.continentCode, continentCd.continentName) val countryList = mutableListOf() - for (countryCd in CountryCd.entries) { - if (continentCd.continentCd.equals(countryCd.continentCd)) { - val country = Country(countryCd.countryCd, countryCd.countryNm) + for (countryCd in Country.entries) { + if (continentCd.continentCode.equals(countryCd.continentCode)) { + val country = Country(countryCd.countryCode, countryCd.countryName) val cityList = mutableListOf() - for (cityCd in CityCd.entries) { - if (countryCd.countryCd.equals(cityCd.countryCd)) { - val city = City(cityCd.cityCd, cityCd.cityNm) + for (cityCd in City.entries) { + if (countryCd.countryCode.equals(cityCd.countryCode)) { + val city = City(cityCd.cityCode, cityCd.cityName) cityList.add(city) } } From 77a61e0fe86cedf94393245e655920936a45be31 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Fri, 10 May 2024 02:39:50 +0900 Subject: [PATCH 069/174] Implement Accompany API --- .../accompany/AccompanyApplicationService.kt | 45 +++++++ .../accompany/dto/AccompanyResponseDto.kt | 36 ++++++ .../dto/AccompanyServiceRequestDto.kt | 83 +++++++++++++ .../accompany/AccompanyController.kt | 79 +++++++----- .../accompany/dto/AccompanyRequestDto.kt | 114 ++++++++++++++++++ 5 files changed, 327 insertions(+), 30 deletions(-) create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/AccompanyApplicationService.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyResponseDto.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/dto/AccompanyRequestDto.kt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/AccompanyApplicationService.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/AccompanyApplicationService.kt new file mode 100644 index 0000000..b261b83 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/AccompanyApplicationService.kt @@ -0,0 +1,45 @@ +package com.travel.withaeng.applicationservice.accompany + +import com.travel.withaeng.applicationservice.accompany.dto.* +import com.travel.withaeng.domain.accompany.AccompanyService +import com.travel.withaeng.domain.accompanylike.AccompanyLikeService +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional + +@Service +@Transactional(readOnly = true) +class AccompanyApplicationService( + private val accompanyService: AccompanyService, + private val accompanyLikeService: AccompanyLikeService +) { + + @Transactional + fun create(request: CreateAccompanyServiceRequest): AccompanyResponse { + return accompanyService.create(request.toDomainDto()).toAccompanyResponse(0L) + } + + @Transactional + fun update(request: UpdateAccompanyServiceRequest): AccompanyResponse { + val accompanyDto = accompanyService.update(request.toDomainDto()) + val likeCount = countAccompanyLikeByAccompanyId(request.accompanyId) + return accompanyDto.toAccompanyResponse(likeCount) + } + + fun retrieve(accompanyId: Long): AccompanyResponse { + val accompanyDto = accompanyService.findById(accompanyId) + val likeCount = countAccompanyLikeByAccompanyId(accompanyId) + return accompanyDto.toAccompanyResponse(likeCount) + } + + fun retrieveAll(): List { + val accompanyDtoList = accompanyService.findAll() + // TODO: Bulk로 가져오는 방법을 고안 + return accompanyDtoList.map { accompanyDto -> + accompanyDto.toAccompanyResponse(countAccompanyLikeByAccompanyId(accompanyDto.id)) + } + } + + private fun countAccompanyLikeByAccompanyId(accompanyId: Long): Long { + return accompanyLikeService.countByAccompanyId(accompanyId) + } +} \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyResponseDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyResponseDto.kt new file mode 100644 index 0000000..dcc005e --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyResponseDto.kt @@ -0,0 +1,36 @@ +package com.travel.withaeng.applicationservice.accompany.dto + +import com.travel.withaeng.domain.accompany.AccompanyDestination +import com.travel.withaeng.domain.accompany.AccompanyDto +import java.time.LocalDate + +data class AccompanyResponse( + val id: Long, + val userId: Long, + val title: String, + val content: String, + val destination: AccompanyDestination, + val startTripDate: LocalDate, + val endTripDate: LocalDate, + val bannerImageUrl: String? = null, + val memberCount: Long, + val viewCount: Long, + val likeCount: Long, + val tagIds: List? = null, + val openKakaoUrl: String? = null +) + +fun AccompanyDto.toAccompanyResponse(likeCount: Long): AccompanyResponse = AccompanyResponse( + id = id, + userId = userId, + title = title, + content = content, + destination = destination, + startTripDate = startTripDate, + endTripDate = endTripDate, + bannerImageUrl = bannerImageUrl, + memberCount = memberCount, + viewCount = viewCount, + likeCount = likeCount, + openKakaoUrl = openKakaoUrl +) \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt new file mode 100644 index 0000000..28c3b13 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt @@ -0,0 +1,83 @@ +package com.travel.withaeng.applicationservice.accompany.dto + +import com.travel.withaeng.domain.accompany.* +import java.time.LocalDate + +data class CreateAccompanyServiceRequest( + val userId: Long, + val title: String, + val content: String, + val continent: String, + val country: String, + val city: String, + val startTripDate: LocalDate, + val endTripDate: LocalDate, + val bannerImageUrl: String? = null, + val memberCount: Long, + val tagIds: List, + val openKakaoUrl: String +) + +fun CreateAccompanyServiceRequest.toDomainDto(): CreateAccompanyDto = CreateAccompanyDto( + userId = userId, + title = title, + content = content, + destination = AccompanyDestination( + continent = Continent.valueOf(continent), + country = Country.valueOf(country), + city = City.valueOf(city) + ), + startTripDate = startTripDate, + endTripDate = endTripDate, + bannerImageUrl = bannerImageUrl, + memberCount = memberCount, + tagIds = tagIds.toSet(), + openKakaoUrl = openKakaoUrl +) + +data class UpdateAccompanyServiceRequest( + val accompanyId: Long, + val userId: Long, + val title: String? = null, + val content: String? = null, + val continent: String? = null, + val country: String? = null, + val city: String? = null, + val startTripDate: LocalDate? = null, + val endTripDate: LocalDate? = null, + val bannerImageUrl: String? = null, + val memberCount: Long? = null, + val tagIds: List? = null, + val openKakaoUrl: String? = null +) + +fun UpdateAccompanyServiceRequest.toDomainDto(): UpdateAccompanyDto { + val destination = if (continent == null || country == null || city == null) { + null + } else { + AccompanyDestination( + continent = Continent.valueOf(continent), + country = Country.valueOf(country), + city = City.valueOf(city) + ) + } + return UpdateAccompanyDto( + accompanyId = accompanyId, + title = title, + content = content, + destination =destination, + startTripDate = startTripDate, + endTripDate = endTripDate, + bannerImageUrl = bannerImageUrl, + memberCount = memberCount, + tagIds = tagIds?.toSet(), + openKakaoUrl = openKakaoUrl + ) +} + +data class SearchAccompanyServiceRequest( + val orderBy: String, + val isDescending: Boolean, + val pageIndex: Long, + val pageSize: Long +) \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/AccompanyController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/AccompanyController.kt index f5bc78a..10f22d0 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/AccompanyController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/AccompanyController.kt @@ -1,51 +1,70 @@ package com.travel.withaeng.controller.accompany +import com.travel.withaeng.applicationservice.accompany.AccompanyApplicationService +import com.travel.withaeng.applicationservice.accompany.dto.AccompanyResponse import com.travel.withaeng.common.ApiResponse -import com.travel.withaeng.domain.accompany.AccompanyService -import com.travel.withaeng.domain.accompany.CreateAccompanyDTO -import com.travel.withaeng.domain.accompany.ModifyAccompanyDTO -import com.travel.withaeng.domain.accompany.SearchAccompanyDTO +import com.travel.withaeng.controller.accompany.dto.CreateAccompanyRequest +import com.travel.withaeng.controller.accompany.dto.UpdateAccompanyRequest +import com.travel.withaeng.controller.accompany.dto.toServiceRequest +import com.travel.withaeng.security.authentication.UserInfo +import com.travel.withaeng.security.resolver.GetAuth +import io.swagger.v3.oas.annotations.Operation +import io.swagger.v3.oas.annotations.security.SecurityRequirement +import io.swagger.v3.oas.annotations.tags.Tag import jakarta.validation.Valid import org.springframework.http.HttpStatus -import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.* +@Tag(name = "Accompany", description = "Accompany API") @RestController @RequestMapping("/api/v1/accompany") -class AccompanyController(private val accompanyService: AccompanyService) { +class AccompanyController(private val accompanyApplicationService: AccompanyApplicationService) { - @PostMapping("") - fun create(@RequestBody @Valid param: CreateAccompanyDTO): ResponseEntity> { - return ResponseEntity.status(HttpStatus.CREATED) - .body(ApiResponse(true, accompanyService.createAccompany(param), null)) + @Operation( + summary = "Create Accompany API", + description = "동행 게시글 생성 API", + security = [SecurityRequirement(name = "Authorization")] + ) + @ResponseStatus(HttpStatus.OK) + @PostMapping + fun create( + @GetAuth userInfo: UserInfo, + @RequestBody @Valid request: CreateAccompanyRequest + ): ApiResponse { + return ApiResponse.success(accompanyApplicationService.create(request.toServiceRequest(userInfo.id))) } + @Operation( + summary = "Update Accompany API", + description = "동행 게시글 수정 API", + security = [SecurityRequirement(name = "Authorization")] + ) @PutMapping("/{accompanyId}") - fun modify(@RequestBody @Valid param: ModifyAccompanyDTO): ResponseEntity> { - return ResponseEntity.status(HttpStatus.OK) - .body(ApiResponse(true, accompanyService.modifyAccompany(param), null)) + fun update( + @GetAuth userInfo: UserInfo, + @PathVariable accompanyId: Long, + @RequestBody @Valid param: UpdateAccompanyRequest + ): ApiResponse { + return ApiResponse.success( + accompanyApplicationService.update( + param.toServiceRequest( + accompanyId = accompanyId, + userId = userInfo.id + ) + ) + ) } + @Operation(summary = "Retrieve Accompany API", description = "동행 게시글 단건 조회 API") @GetMapping("/{accompanyId}") - fun getOne(@PathVariable("accompanyId") accompanyId: Long): ResponseEntity> { - return ResponseEntity.status(HttpStatus.OK).body(ApiResponse(true, accompanyService.getOne(accompanyId), null)) + fun retrieve(@PathVariable("accompanyId") accompanyId: Long): ApiResponse { + return ApiResponse.success(accompanyApplicationService.retrieve(accompanyId)) } - @PutMapping("/{accompanyId}/incr/viewCnt") - fun incrViewCnt(@PathVariable("accompanyId") accompanyId: Long): ResponseEntity> { - accompanyService.incrViewCnt(accompanyId) - return ResponseEntity.status(HttpStatus.OK).body(ApiResponse(true, null, null)) - } - - @PutMapping("/{accompanyId}/decr/viewCnt") - fun decrViewCnt(@PathVariable("accompanyId") accompanyId: Long): ResponseEntity> { - accompanyService.decrViewCnt(accompanyId) - return ResponseEntity.status(HttpStatus.OK).body(ApiResponse(true, null, null)) - } - - @GetMapping("/getList") - fun getList(@RequestBody param: SearchAccompanyDTO): ResponseEntity> { - return ResponseEntity.status(HttpStatus.OK).body(ApiResponse(true, accompanyService.getList(param), null)) + @Operation(summary = "Retrieve All Accompany API", description = "모든 동행 게시글 조회 API") + @GetMapping("/all") + fun retrieveAll(): ApiResponse> { + return ApiResponse.success(accompanyApplicationService.retrieveAll()) } } \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/dto/AccompanyRequestDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/dto/AccompanyRequestDto.kt new file mode 100644 index 0000000..44cd873 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/dto/AccompanyRequestDto.kt @@ -0,0 +1,114 @@ +package com.travel.withaeng.controller.accompany.dto + +import com.travel.withaeng.applicationservice.accompany.dto.CreateAccompanyServiceRequest +import com.travel.withaeng.applicationservice.accompany.dto.UpdateAccompanyServiceRequest +import io.swagger.v3.oas.annotations.media.Schema +import java.time.LocalDate + +@Schema(description = "[Request] 동행 게시글 생성") +data class CreateAccompanyRequest( + @Schema(description = "동행 게시글 제목") + val title: String, + + @Schema(description = "동행 게시글 내용") + val content: String, + + @Schema(description = "동행 목적지의 대륙") + val continent: String, + + @Schema(description = "동행 목적지의 나라") + val country: String, + + @Schema(description = "동행 목적지의 도시") + val city: String, + + @Schema(description = "동행 시작 날짜 (1999-01-01)") + val startTripDate: LocalDate, + + @Schema(description = "동행 종료 날짜 (1999-01-01)") + val endTripDate: LocalDate, + + @Schema(description = "동행 게시글 배너 이미지 URL") + val bannerImageUrl: String? = null, + + @Schema(description = "동행 멤버수") + val memberCount: Long, + + @Schema(description = "동행 게시글에 부착할 태그 아이디 리스트") + val tagIds: List, + + @Schema(description = "동행 게시글에 게시된 오픈 카카오톡 URL") + val openKakaoUrl: String +) + +@Schema(description = "[Request] 동행 게시글 수정") +fun CreateAccompanyRequest.toServiceRequest( + userId: Long +): CreateAccompanyServiceRequest = CreateAccompanyServiceRequest( + userId = userId, + title = title, + content = content, + continent = continent, + country = country, + city = city, + startTripDate = startTripDate, + endTripDate = endTripDate, + bannerImageUrl = bannerImageUrl, + memberCount = memberCount, + tagIds = tagIds, + openKakaoUrl = openKakaoUrl +) + +data class UpdateAccompanyRequest( + @Schema(description = "동행 게시글 제목") + val title: String? = null, + + @Schema(description = "동행 게시글 내용") + val content: String? = null, + + @Schema(description = "동행 목적지의 대륙") + val continent: String? = null, + + @Schema(description = "동행 목적지의 나라") + val country: String? = null, + + @Schema(description = "동행 목적지의 도시") + val city: String? = null, + + @Schema(description = "동행 시작 날짜 (1999-01-01)") + val startTripDate: LocalDate? = null, + + @Schema(description = "동행 종료 날짜 (1999-01-01)") + val endTripDate: LocalDate? = null, + + @Schema(description = "동행 게시글 배너 이미지 URL") + val bannerImageUrl: String? = null, + + @Schema(description = "동행 멤버수") + val memberCount: Long? = null, + + @Schema(description = "동행 게시글에 부착할 태그 아이디 리스트") + val tagIds: List? = null, + + @Schema(description = "동행 게시글에 게시된 오픈 카카오톡 URL") + val openKakaoUrl: String? = null +) + +fun UpdateAccompanyRequest.toServiceRequest( + accompanyId: Long, + userId: Long +): UpdateAccompanyServiceRequest = UpdateAccompanyServiceRequest( + accompanyId = accompanyId, + userId = userId, + title = title, + content = content, + continent = continent, + country = country, + city = city, + startTripDate = startTripDate, + endTripDate = endTripDate, + bannerImageUrl = bannerImageUrl, + memberCount = memberCount, + tagIds = tagIds, + openKakaoUrl = openKakaoUrl +) \ No newline at end of file From 9c076bf4529eff455b01a216360d02dc9b86ac0e Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Mon, 13 May 2024 11:21:15 +0900 Subject: [PATCH 070/174] Implement like accompany api --- .../AccompanyLikeApplicationService.kt | 21 ++++++ .../accompanylike/AccompanyLikeController.kt | 38 ++++++----- .../domain/accompanylike/AccompanyLike.kt | 9 ++- .../domain/accompanylike/AccompanyLikeDto.kt | 65 ------------------- .../domain/accompanylike/AccompanyLikeHist.kt | 24 ------- .../AccompanyLikeHistRepository.kt | 5 -- .../accompanylike/AccompanyLikeRepository.kt | 2 +- .../accompanylike/AccompanyLikeService.kt | 52 ++++++++------- 8 files changed, 82 insertions(+), 134 deletions(-) create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanylike/AccompanyLikeApplicationService.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeDto.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHist.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistRepository.kt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanylike/AccompanyLikeApplicationService.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanylike/AccompanyLikeApplicationService.kt new file mode 100644 index 0000000..091672e --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanylike/AccompanyLikeApplicationService.kt @@ -0,0 +1,21 @@ +package com.travel.withaeng.applicationservice.accompanylike + +import com.travel.withaeng.domain.accompanylike.AccompanyLikeService +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional + +@Transactional(readOnly = true) +@Service +class AccompanyLikeApplicationService(private val accompanyLikeService: AccompanyLikeService) { + + @Transactional + fun like(userId: Long, accompanyId: Long) { + accompanyLikeService.createAccompanyLike(userId, accompanyId) + } + + @Transactional + fun dislike(userId: Long, accompanyId: Long) { + accompanyLikeService.deleteAccompanyLike(userId, accompanyId) + } + +} \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanylike/AccompanyLikeController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanylike/AccompanyLikeController.kt index 0c42b17..c14d3ee 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanylike/AccompanyLikeController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanylike/AccompanyLikeController.kt @@ -1,29 +1,35 @@ package com.travel.withaeng.controller.accompanylike +import com.travel.withaeng.applicationservice.accompanylike.AccompanyLikeApplicationService import com.travel.withaeng.common.ApiResponse -import com.travel.withaeng.domain.accompanylike.AccompanyLikeService -import com.travel.withaeng.domain.accompanylike.CreateAccompanyLikeDTO -import com.travel.withaeng.domain.accompanylike.DeleteAccompanyLikeDTO -import jakarta.validation.Valid +import com.travel.withaeng.security.authentication.UserInfo +import com.travel.withaeng.security.resolver.GetAuth import org.springframework.http.HttpStatus -import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.* @RestController -@RequestMapping("/api/v1/accompany/{accompanyId}/like") -class AccompanyLikeController(private val accompanyLikeService: AccompanyLikeService) { +@RequestMapping("/api/v1/accompany") +class AccompanyLikeController( + private val accompanyLikeApplicationService: AccompanyLikeApplicationService +) { - @PostMapping("") - fun create(@RequestBody @Valid param: CreateAccompanyLikeDTO): ResponseEntity> { - return ResponseEntity.status(HttpStatus.CREATED).body( - ApiResponse(true, accompanyLikeService.createAccompanyLike(param), null) - ) + @PostMapping("/{accompanyId}/like") + @ResponseStatus(HttpStatus.CREATED) + fun like( + @GetAuth userInfo: UserInfo, + @PathVariable("accompanyId") accompanyId: Long + ): ApiResponse { + accompanyLikeApplicationService.like(userInfo.id, accompanyId) + return ApiResponse.success() } - @DeleteMapping("") - fun delete(@RequestBody @Valid param: DeleteAccompanyLikeDTO): ResponseEntity { - return ResponseEntity.status(HttpStatus.OK) - .body(ApiResponse(true, accompanyLikeService.deleteAccompanyLike(param), null)) + @DeleteMapping("/{accompanyId}/like") + fun dislike( + @GetAuth userInfo: UserInfo, + @PathVariable("accompanyId") accompanyId: Long + ): ApiResponse { + accompanyLikeApplicationService.dislike(userInfo.id, accompanyId) + return ApiResponse.success() } } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLike.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLike.kt index f86d23d..50e2157 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLike.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLike.kt @@ -15,4 +15,11 @@ class AccompanyLike( @Column(name = "user_id", nullable = false) val userId: Long -) : BaseEntity() \ No newline at end of file +) : BaseEntity() { + + companion object { + fun create(userId: Long, accompanyId: Long): AccompanyLike { + return AccompanyLike(accompanyId = accompanyId, userId = userId) + } + } +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeDto.kt deleted file mode 100644 index c02957b..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeDto.kt +++ /dev/null @@ -1,65 +0,0 @@ -package com.travel.withaeng.domain.accompanylike - -import com.travel.withaeng.common.cd.ExecCd -import org.jetbrains.annotations.NotNull - -class CreateAccompanyLikeDTO( - - @NotNull - val userId: Long, - - @NotNull - val accompanyId: Long, - - ) { - fun toEntity(): AccompanyLikeEntity { - return AccompanyLikeEntity( - 0, - this.userId, - this.accompanyId - ) - } - - fun toHistEntity(entity: AccompanyLikeEntity): AccompanyLikeHistEntity { - return AccompanyLikeHistEntity( - 0, - entity.likeId, - entity.userId, - entity.accompanyId, - ExecCd.CREATE.execCd - ) - } - -} - -class DeleteAccompanyLikeDTO( - - @NotNull - val likeId: Long, - - @NotNull - val userId: Long, - - @NotNull - val accompanyId: Long, - - ) { - fun toEntity(): AccompanyLikeEntity { - return AccompanyLikeEntity( - this.likeId, - this.userId, - this.accompanyId - ) - } - - fun toHistEntity(entity: AccompanyLikeEntity): AccompanyLikeHistEntity { - return AccompanyLikeHistEntity( - 0, - entity.likeId, - entity.userId, - entity.accompanyId, - ExecCd.DELETE.execCd - ) - } - -} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHist.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHist.kt deleted file mode 100644 index 392a0ee..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHist.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.travel.withaeng.domain.accompanylike - -import com.travel.withaeng.domain.BaseEntity -import jakarta.persistence.Column -import jakarta.persistence.Entity -import jakarta.persistence.Table - -@Table(name = "accompany_like_hist") -@Entity -class AccompanyLikeHist( - - @Column(name = "like_id", nullable = false) - val likeId: Long, - - @Column(name = "user_id", nullable = false) - val userId: Long, - - @Column(name = "accompany_id", nullable = false) - val accompanyId: Long, - - @Column(name = "exec_cd", nullable = false) - val execCd: String - -) : BaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistRepository.kt deleted file mode 100644 index d674795..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeHistRepository.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.travel.withaeng.domain.accompanylike - -import org.springframework.data.jpa.repository.JpaRepository - -interface AccompanyLikeHistRepository : JpaRepository diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeRepository.kt index dfec9ae..86c5b54 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeRepository.kt @@ -4,5 +4,5 @@ import org.springframework.data.jpa.repository.JpaRepository interface AccompanyLikeRepository : JpaRepository { fun countByAccompanyId(accompanyId: Long): Long - fun countByAccompanyIdIsIn(accompanyIds: Set): Long + fun findByUserIdAndAccompanyId(userId: Long, accompanyId: Long): AccompanyLike? } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt index 90fc337..a20a5f4 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt @@ -1,42 +1,50 @@ package com.travel.withaeng.domain.accompanylike +import com.travel.withaeng.common.exception.WithaengException +import com.travel.withaeng.common.exception.WithaengExceptionType +import com.travel.withaeng.domain.accompany.AccompanyRepository +import com.travel.withaeng.domain.user.UserRepository +import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @Service @Transactional(readOnly = true) class AccompanyLikeService( - private val accompanyLikeRepository: AccompanyLikeRepository, - private val accompanyLikeHistRepository: AccompanyLikeHistRepository + private val userRepository: UserRepository, + private val accompanyRepository: AccompanyRepository, + private val accompanyLikeRepository: AccompanyLikeRepository ) { @Transactional - fun createAccompanyLike(param: CreateAccompanyLikeDTO): CreateAccompanyLikeDTO { - - val accompanyLikeEntity = param.toEntity() - accompanyLikeRepository.save(accompanyLikeEntity) - - val accompanyLikeHistEntity = param.toHistEntity(accompanyLikeEntity) - accompanyLikeHistRepository.save(accompanyLikeHistEntity) - - return param + fun createAccompanyLike(userId: Long, accompanyId: Long): AccompanyLikeDto { + userRepository.findByIdOrNull(userId) ?: throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = "해당하는 유저를 찾을 수 없습니다." + ) + accompanyRepository.findByIdOrNull(accompanyId) ?: throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = "해당하는 동행을 찾을 수 없습니다." + ) + val prevAccompanyLike = accompanyLikeRepository.findByUserIdAndAccompanyId(userId, accompanyId) + if (prevAccompanyLike != null) { + return prevAccompanyLike.toDto() + } + val accompanyLike = AccompanyLike.create(userId = userId, accompanyId = accompanyId) + accompanyLikeRepository.save(accompanyLike) + return accompanyLike.toDto() } fun countByAccompanyId(accompanyId: Long): Long { return accompanyLikeRepository.countByAccompanyId(accompanyId) } - //TODO delete 성능이 안나올 경우 boolean 형으로 좋아요 제어 @Transactional - fun deleteAccompanyLike(param: DeleteAccompanyLikeDTO): DeleteAccompanyLikeDTO { - - val accompanyLikeEntity = param.toEntity() - accompanyLikeRepository.delete(accompanyLikeEntity) - - val accompanyLikeHistEntity = param.toHistEntity(accompanyLikeEntity) - accompanyLikeHistRepository.save(accompanyLikeHistEntity) - - return param + fun deleteAccompanyLike(userId: Long, accompanyId: Long) { + val accompanyLike = accompanyLikeRepository.findByUserIdAndAccompanyId( + userId = userId, + accompanyId = accompanyId + ) ?: return + accompanyLikeRepository.delete(accompanyLike) } - } \ No newline at end of file From aef0a7820090085bd3a54b24792886fa547bea43 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Tue, 14 May 2024 15:18:27 +0900 Subject: [PATCH 071/174] Remove unnecessary codes about AccompanyReply --- .../accompanyreply/AccompanyReplyHist.kt | 36 ------------------- .../AccompanyReplyHistRepository.kt | 5 --- .../AccompanyReplyRepositoryCustom.kt | 7 ---- .../AccompanyReplyRepositoryCustomImpl.kt | 32 ----------------- .../AccompanyReplyLikeHist.kt | 24 ------------- .../AccompanyReplyLikeHistRepository.kt | 5 --- .../AccompanyReplyLikeRepositoryCustom.kt | 7 ---- .../AccompanyReplyLikeRepositoryCustomImpl.kt | 24 ------------- 8 files changed, 140 deletions(-) delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHist.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHistRepository.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustom.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustomImpl.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHist.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHistRepository.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepositoryCustom.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepositoryCustomImpl.kt diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHist.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHist.kt deleted file mode 100644 index 8ec7444..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHist.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.travel.withaeng.domain.accompanyreply - -import com.travel.withaeng.domain.BaseEntity -import jakarta.persistence.Column -import jakarta.persistence.Entity -import jakarta.persistence.Table - -@Table(name = "accompany_reply_hist") -@Entity -class AccompanyReplyHist( - - @Column(name = "reply_id", nullable = false) - val replyId: Long, - - @Column(name = "accompany_id", nullable = false) - val accompanyId: Long, - - @Column(name = "parent_id", nullable = false) - val parentId: Long, - - @Column(name = "depth", nullable = false) - val depth: Long, - - @Column(name = "reply_order", nullable = false) - val replyOrder: Long, - - @Column(name = "user_id", nullable = false) - val userId: Long, - - @Column(name = "content", nullable = false) - val content: String, - - @Column(name = "exec_cd", nullable = false) - val execCd: String - -) : BaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHistRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHistRepository.kt deleted file mode 100644 index 22a8b7a..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyHistRepository.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.travel.withaeng.domain.accompanyreply - -import org.springframework.data.jpa.repository.JpaRepository - -interface AccompanyReplyHistRepository : JpaRepository \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustom.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustom.kt deleted file mode 100644 index 2d37d6b..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustom.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.travel.withaeng.domain.accompanyreply - -interface AccompanyReplyRepositoryCustom { - - fun getAccompanyReplyList(accompanyId: Long): List? - -} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustomImpl.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustomImpl.kt deleted file mode 100644 index cbdcd89..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustomImpl.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.travel.withaeng.domain.accompanyreply - -import com.querydsl.core.types.Projections -import com.querydsl.jpa.impl.JPAQueryFactory -import com.travel.withaeng.domain.accompany.* -import org.springframework.stereotype.Repository - -@Repository -class AccompanyReplyRepositoryCustomImpl(val jpaQueryFactory: JPAQueryFactory) : AccompanyReplyRepositoryCustom { - override fun getAccompanyReplyList(accompanyId: Long): List { - return jpaQueryFactory - .select( - Projections.constructor( - GetReplyDTO::class.java, - QAccompanyReplyEntity.accompanyReplyEntity.replyId, - QAccompanyReplyEntity.accompanyReplyEntity.userId, - QAccompanyReplyEntity.accompanyReplyEntity.accompanyId, - QAccompanyReplyEntity.accompanyReplyEntity.parentId, - QAccompanyReplyEntity.accompanyReplyEntity.depth, - QAccompanyReplyEntity.accompanyReplyEntity.replyOrder, - QAccompanyReplyEntity.accompanyReplyEntity.content, - ) - ) - .from(QAccompanyReplyEntity.accompanyReplyEntity) - .where(QAccompanyReplyEntity.accompanyReplyEntity.accompanyId.eq(accompanyId)) - .orderBy( - QAccompanyReplyEntity.accompanyReplyEntity.parentId.desc(), - QAccompanyReplyEntity.accompanyReplyEntity.depth.desc() - ) - .fetch() - } -} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHist.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHist.kt deleted file mode 100644 index c168801..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHist.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.travel.withaeng.domain.accompanyreplylike - -import com.travel.withaeng.domain.BaseEntity -import jakarta.persistence.Column -import jakarta.persistence.Entity -import jakarta.persistence.Table - -@Table(name = "accompany_reply_like_hist") -@Entity -class AccompanyReplyLikeHist( - - @Column(name = "reply_like_id", nullable = false) - val replyLikeId: Long, - - @Column(name = "reply_id", nullable = false) - val replyId: Long, - - @Column(name = "user_id", nullable = false) - val userId: Long, - - @Column(name = "exec_cd", nullable = false) - val execCd: String - -) : BaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHistRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHistRepository.kt deleted file mode 100644 index d5c9184..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeHistRepository.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.travel.withaeng.domain.accompanyreplylike - -import org.springframework.data.jpa.repository.JpaRepository - -interface AccompanyReplyLikeHistRepository : JpaRepository \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepositoryCustom.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepositoryCustom.kt deleted file mode 100644 index 9412acb..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepositoryCustom.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.travel.withaeng.domain.accompanyreplylike - -interface AccompanyReplyLikeRepositoryCustom { - - fun getAccompanyReplyLikeList(replyIds: List): List - -} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepositoryCustomImpl.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepositoryCustomImpl.kt deleted file mode 100644 index 8c2b9fe..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepositoryCustomImpl.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.travel.withaeng.domain.accompanyreplylike - -import com.querydsl.core.types.Projections -import com.querydsl.jpa.impl.JPAQueryFactory -import org.springframework.stereotype.Repository - -@Repository -class AccompanyReplyLikeRepositoryCustomImpl(val jpaQueryFactory: JPAQueryFactory) : - AccompanyReplyLikeRepositoryCustom { - override fun getAccompanyReplyLikeList(replyIds: List): List { - return jpaQueryFactory - .select( - Projections.constructor( - GetReplyLikeDTO::class.java, - QAccompanyReplyLikeEntity.accompanyReplyLikeEntity.replyId, - QAccompanyReplyLikeEntity.accompanyReplyLikeEntity.replyId.count() - ) - ) - .from(QAccompanyReplyLikeEntity.accompanyReplyLikeEntity) - .where(QAccompanyReplyLikeEntity.accompanyReplyLikeEntity.replyId.`in`(replyIds)) - .groupBy(QAccompanyReplyLikeEntity.accompanyReplyLikeEntity.replyId) - .fetch() - } -} \ No newline at end of file From ba8e78bf4d44397d6a9bb273b534c5e944a4d9a5 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Tue, 14 May 2024 15:18:40 +0900 Subject: [PATCH 072/174] Implement reply API --- .../AccompanyReplyApplicationService.kt | 71 +++++++ .../dto/AccompanyReplyResponseDto.kt | 23 +++ .../dto/AccompanyReplyServiceRequestDto.kt | 15 ++ .../AccompanyReplyController.kt | 94 ++++++--- .../dto/AccompanyReplyRequestDto.kt | 40 ++++ .../domain/accompanyreply/AccompanyReply.kt | 23 ++- .../accompanyreply/AccompanyReplyDto.kt | 185 ++---------------- .../AccompanyReplyRepository.kt | 5 +- .../accompanyreply/AccompanyReplyService.kt | 162 +++++---------- .../AccompanyReplyLikeRepository.kt | 6 +- .../AccompanyReplyLikeService.kt | 29 +-- 11 files changed, 306 insertions(+), 347 deletions(-) create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyServiceRequestDto.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/dto/AccompanyReplyRequestDto.kt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt new file mode 100644 index 0000000..c0b8ab7 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt @@ -0,0 +1,71 @@ +package com.travel.withaeng.applicationservice.accompanyreply + +import com.travel.withaeng.applicationservice.accompanyreply.dto.AccompanyReplyResponse +import com.travel.withaeng.applicationservice.accompanyreply.dto.CreateAccompanyReplyServiceRequest +import com.travel.withaeng.applicationservice.accompanyreply.dto.UpdateAccompanyReplyServiceRequest +import com.travel.withaeng.applicationservice.accompanyreply.dto.toResponse +import com.travel.withaeng.common.exception.WithaengException +import com.travel.withaeng.common.exception.WithaengExceptionType +import com.travel.withaeng.domain.accompanyreply.AccompanyReplyService +import com.travel.withaeng.domain.accompanyreplylike.AccompanyReplyLikeService +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional + +@Service +@Transactional(readOnly = true) +class AccompanyReplyApplicationService( + val accompanyReplyService: AccompanyReplyService, + val accompanyReplyLikeService: AccompanyReplyLikeService +) { + + @Transactional + fun create(request: CreateAccompanyReplyServiceRequest): AccompanyReplyResponse { + return accompanyReplyService.create( + accompanyId = request.accompanyId, + userId = request.userId, + content = request.content, + parentId = request.parentId + ).toResponse() + } + + fun findById(accompanyReplyId: Long): AccompanyReplyResponse { + val accompanyReplyDto = accompanyReplyService.findById(accompanyReplyId) + val likeCount = accompanyReplyLikeService.countAccompanyReplyLikeCount(accompanyReplyDto.id) + return accompanyReplyDto.toResponse(likeCount) + } + + fun findAll(accompanyId: Long): List { + val accompanyReplyDtoList = accompanyReplyService.findAllByAccompanyId(accompanyId) + // TODO: Fix getting like count logic for using bulk from single + return accompanyReplyDtoList.map { replyDto -> + val likeCount = accompanyReplyLikeService.countAccompanyReplyLikeCount(replyDto.id) + replyDto.toResponse(likeCount) + } + } + + @Transactional + fun update(request: UpdateAccompanyReplyServiceRequest): AccompanyReplyResponse { + val accompanyReplyDto = accompanyReplyService.findById(request.accompanyReplyId) + if (accompanyReplyDto.userId != request.userId) { + throw WithaengException.of( + type = WithaengExceptionType.ACCESS_DENIED, + message = "댓글 작성자가 아닌 사용자가 수정할 수 없습니다." + ) + } + val updated = accompanyReplyService.update(accompanyReplyDto.id, request.content) + val likeCount = accompanyReplyLikeService.countAccompanyReplyLikeCount(accompanyReplyDto.id) + return updated.toResponse(likeCount) + } + + @Transactional + fun delete(userId: Long, accompanyReplyId: Long) { + val accompanyReplyDto = accompanyReplyService.findById(accompanyReplyId) + if (accompanyReplyDto.userId != userId) { + throw WithaengException.of( + type = WithaengExceptionType.ACCESS_DENIED, + message = "댓글 작성자가 아닌 사용자가 삭제할 수 없습니다." + ) + } + accompanyReplyService.delete(accompanyReplyDto.id) + } +} \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt new file mode 100644 index 0000000..93ea294 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt @@ -0,0 +1,23 @@ +package com.travel.withaeng.applicationservice.accompanyreply.dto + +import com.travel.withaeng.domain.accompanyreply.AccompanyReplyDto + +data class AccompanyReplyResponse( + val id: Long, + val accompanyId: Long, + val parentId: Long? = null, + val userId: Long, + val content: String, + val likeCount: Long = 0L +) + +fun AccompanyReplyDto.toResponse(likeCount: Long = 0L): AccompanyReplyResponse { + return AccompanyReplyResponse( + id = id, + accompanyId = accompanyId, + parentId = parentId, + userId = userId, + content = content, + likeCount = likeCount + ) +} \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyServiceRequestDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyServiceRequestDto.kt new file mode 100644 index 0000000..006bbe6 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyServiceRequestDto.kt @@ -0,0 +1,15 @@ +package com.travel.withaeng.applicationservice.accompanyreply.dto + +data class CreateAccompanyReplyServiceRequest( + val userId: Long, + val accompanyId: Long, + val content: String, + val parentId: Long? = null +) + +data class UpdateAccompanyReplyServiceRequest( + val accompanyReplyId: Long, + val userId: Long, + val accompanyId: Long, + val content: String +) \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt index 61c69eb..9a2d5d3 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt @@ -1,39 +1,89 @@ package com.travel.withaeng.controller.accompanyreply +import com.travel.withaeng.applicationservice.accompanyreply.AccompanyReplyApplicationService +import com.travel.withaeng.applicationservice.accompanyreply.dto.AccompanyReplyResponse import com.travel.withaeng.common.ApiResponse -import com.travel.withaeng.domain.accompanyreply.AccompanyReplyService -import com.travel.withaeng.domain.accompanyreply.CreateAccompanyReplyDTO -import com.travel.withaeng.domain.accompanyreply.DeleteAccompanyReplyDTO -import com.travel.withaeng.domain.accompanyreply.ModifyAccompanyReplyDTO +import com.travel.withaeng.controller.accompanyreply.dto.CreateAccompanyReplyRequest +import com.travel.withaeng.controller.accompanyreply.dto.UpdateAccompanyReplyRequest +import com.travel.withaeng.controller.accompanyreply.dto.toServiceRequest +import com.travel.withaeng.security.authentication.UserInfo +import com.travel.withaeng.security.resolver.GetAuth import org.springframework.http.HttpStatus -import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.* @RestController -@RequestMapping("/api/v1/accompany/{accompanyId}/reply") -class AccompanyReplyController(private val accompanyReplyService: AccompanyReplyService) { +@RequestMapping("/api/v1/accompany") +class AccompanyReplyController(private val accompanyReplyApplicationService: AccompanyReplyApplicationService) { - @PostMapping("") - fun create(@RequestBody param: CreateAccompanyReplyDTO): ResponseEntity> { - return ResponseEntity.status(HttpStatus.CREATED) - .body(ApiResponse(true, accompanyReplyService.createAccompanyReply(param), null)) + @PostMapping("/{accompanyId}/reply") + @ResponseStatus(HttpStatus.CREATED) + fun create( + @GetAuth userInfo: UserInfo, + @PathVariable("accompanyId") accompanyId: Long, + @RequestBody request: CreateAccompanyReplyRequest + ): ApiResponse { + return ApiResponse.success( + accompanyReplyApplicationService.create( + request.toServiceRequest( + userId = userInfo.id, + accompanyId = accompanyId + ) + ) + ) } - @PutMapping("/{replyId}") - fun create(@RequestBody param: ModifyAccompanyReplyDTO): ResponseEntity> { - return ResponseEntity.status(HttpStatus.OK) - .body(ApiResponse(true, accompanyReplyService.modifyAccompanyReply(param), null)) + @PostMapping("/{accompanyId}/reply/{replyId}") + @ResponseStatus(HttpStatus.CREATED) + fun reply( + @GetAuth userInfo: UserInfo, + @PathVariable("accompanyId") accompanyId: Long, + @PathVariable("replyId") replyId: Long, + @RequestBody request: CreateAccompanyReplyRequest + ): ApiResponse { + return ApiResponse.success( + accompanyReplyApplicationService.create( + request.toServiceRequest( + userId = userInfo.id, + accompanyId = accompanyId, + parentId = replyId + ) + ) + ) } - @DeleteMapping("/{replyId}") - fun create(@RequestBody param: DeleteAccompanyReplyDTO): ResponseEntity> { - return ResponseEntity.status(HttpStatus.OK) - .body(ApiResponse(true, accompanyReplyService.deleteAccompanyReply(param), null)) + @PutMapping("/{accompanyId}/reply/{replyId}") + fun update( + @GetAuth userInfo: UserInfo, + @PathVariable("accompanyId") accompanyId: Long, + @PathVariable("replyId") replyId: Long, + @RequestBody request: UpdateAccompanyReplyRequest + ): ApiResponse { + return ApiResponse.success( + accompanyReplyApplicationService.update( + request.toServiceRequest( + userId = userInfo.id, + accompanyId = accompanyId, + accompanyReplyId = replyId + ) + ) + ) } - @GetMapping("/getList") - fun create(@PathVariable(name = "accompanyId") param: Long): ResponseEntity> { - return ResponseEntity.status(HttpStatus.OK).body(ApiResponse(true, accompanyReplyService.getList(param), null)) + @DeleteMapping("/{accompanyId}/reply/{replyId}") + fun delete( + @GetAuth userInfo: UserInfo, + @PathVariable("replyId") replyId: Long + ): ApiResponse { + return ApiResponse.success( + accompanyReplyApplicationService.delete(userId = userInfo.id, accompanyReplyId = replyId) + ) + } + + @GetMapping("/{accompanyId}/reply/all") + fun findAll(@PathVariable(name = "accompanyId") accompanyId: Long): ApiResponse> { + return ApiResponse.success( + accompanyReplyApplicationService.findAll(accompanyId = accompanyId) + ) } } \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/dto/AccompanyReplyRequestDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/dto/AccompanyReplyRequestDto.kt new file mode 100644 index 0000000..6210164 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/dto/AccompanyReplyRequestDto.kt @@ -0,0 +1,40 @@ +package com.travel.withaeng.controller.accompanyreply.dto + +import com.travel.withaeng.applicationservice.accompanyreply.dto.CreateAccompanyReplyServiceRequest +import com.travel.withaeng.applicationservice.accompanyreply.dto.UpdateAccompanyReplyServiceRequest +import io.swagger.v3.oas.annotations.media.Schema + +@Schema(description = "[Request] 동행 댓글 생성") +data class CreateAccompanyReplyRequest( + @Schema(description = "동행 댓글 내용") + val content: String +) + +fun CreateAccompanyReplyRequest.toServiceRequest( + userId: Long, + accompanyId: Long, + parentId: Long? = null +): CreateAccompanyReplyServiceRequest = CreateAccompanyReplyServiceRequest( + userId = userId, + accompanyId = accompanyId, + content = content, + parentId = parentId +) + + +@Schema(description = "[Request] 동행 댓글 수정") +data class UpdateAccompanyReplyRequest( + @Schema(description = "동행 댓글 내용") + val content: String +) + +fun UpdateAccompanyReplyRequest.toServiceRequest( + userId: Long, + accompanyId: Long, + accompanyReplyId: Long +): UpdateAccompanyReplyServiceRequest = UpdateAccompanyReplyServiceRequest( + accompanyReplyId = accompanyReplyId, + userId = userId, + accompanyId = accompanyId, + content = content +) \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt index afc7b02..bbbdbf6 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt @@ -14,14 +14,8 @@ class AccompanyReply( @Column(name = "accompany_id", nullable = false) val accompanyId: Long, - @Column(name = "parent_id", nullable = false) - val parentId: Long, - - @Column(name = "depth", nullable = false) - val depth: Long, - - @Column(name = "reply_order", nullable = false) - val replyOrder: Long, + @Column(name = "parent_id", nullable = true) + val parentId: Long? = null, @Column(name = "user_id", nullable = false) val userId: Long, @@ -29,4 +23,15 @@ class AccompanyReply( @Column(name = "content", nullable = false) var content: String -) : BaseEntity() \ No newline at end of file +) : BaseEntity() { + companion object { + fun create(accompanyId: Long, userId: Long, content: String, parentId: Long? = null): AccompanyReply { + return AccompanyReply( + accompanyId = accompanyId, + userId = userId, + content = content, + parentId = parentId + ) + } + } +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt index fe386c3..1a1c4d8 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt @@ -1,176 +1,17 @@ package com.travel.withaeng.domain.accompanyreply -import com.travel.withaeng.common.cd.ExecCd -import jakarta.validation.constraints.NotBlank -import org.jetbrains.annotations.NotNull - -class CreateAccompanyReplyDTO( - - @NotNull +data class AccompanyReplyDto( + val id: Long, val userId: Long, - - @NotNull val accompanyId: Long, - - @NotNull - val parentId: Long, - - @NotNull - val depth: Long, - - @NotNull - val replyOrder: Long, - - @NotBlank(message = "댓글 내용이 존재하지 않습니다.") - var content: String, - - ) { - fun toEntity(): AccompanyReplyEntity { - return AccompanyReplyEntity( - 0, - this.accompanyId, - this.parentId, - this.depth, - this.replyOrder, - this.userId, - this.content - ) - } - - fun toHistEntity(entity: AccompanyReplyEntity): AccompanyReplyHistEntity { - return AccompanyReplyHistEntity( - 0, - entity.replyId, - entity.accompanyId, - entity.parentId, - entity.depth, - entity.replyOrder, - entity.userId, - entity.content, - ExecCd.CREATE.execCd - ) - } - -} - -class ModifyAccompanyReplyDTO( - - @NotNull - val replyId: Long, - - @NotNull - val userId: Long, - - @NotNull - val accompanyId: Long, - - @NotNull - val parentId: Long, - - @NotNull - val depth: Long, - - @NotNull - val replyOrder: Long, - - @NotBlank(message = "댓글 내용이 존재하지 않습니다.") - var content: String, - - ) { - fun toEntity(): AccompanyReplyEntity { - return AccompanyReplyEntity( - 0, - this.accompanyId, - this.parentId, - this.depth, - this.replyOrder, - this.userId, - this.content - ) - } - - fun toHistEntity(entity: AccompanyReplyEntity): AccompanyReplyHistEntity { - return AccompanyReplyHistEntity( - 0, - entity.replyId, - entity.accompanyId, - entity.parentId, - entity.depth, - entity.replyOrder, - entity.userId, - entity.content, - ExecCd.UPDATE.execCd - ) - } - -} - -class DeleteAccompanyReplyDTO( - - @NotNull - val replyId: Long, - - @NotNull - val userId: Long, - - @NotNull - val accompanyId: Long - -) { - - fun toHistEntity(entity: AccompanyReplyEntity): AccompanyReplyHistEntity { - return AccompanyReplyHistEntity( - 0, - entity.replyId, - entity.accompanyId, - entity.parentId, - entity.depth, - entity.replyOrder, - entity.userId, - entity.content, - ExecCd.DELETE.execCd - ) - } - -} - -data class GetReplyDTO( - - var replyId: Long, - var userId: Long, - var accompanyId: Long, - var parentId: Long, - var depth: Long, - var replyOrder: Long, - var content: String, - var likeCnt: Long -) { - - constructor( - replyId: Long, userId: Long, accompanyId: Long, parentId: Long, - depth: Long, replyOrder: Long, content: String - ) : - this(replyId, userId, accompanyId, parentId, depth, replyOrder, content, 0) - - fun addLikeCnt(cnt: Long) { - likeCnt = cnt - } - - companion object { - @JvmStatic - fun toDto(accompanyReplyEntity: AccompanyReplyEntity, likeCnt: Long): GetReplyDTO { - return GetReplyDTO( - replyId = accompanyReplyEntity.replyId, - userId = accompanyReplyEntity.userId, - accompanyId = accompanyReplyEntity.accompanyId, - parentId = accompanyReplyEntity.parentId, - depth = accompanyReplyEntity.depth, - replyOrder = accompanyReplyEntity.replyOrder, - content = accompanyReplyEntity.content, - likeCnt = likeCnt - ) - } - } - -} - + val parentId: Long? = null, + val content: String +) + +fun AccompanyReply.toDto(): AccompanyReplyDto = AccompanyReplyDto( + id = id, + userId = userId, + accompanyId = accompanyId, + parentId = parentId, + content = content +) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt index 0f02f44..4341eb5 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt @@ -2,7 +2,6 @@ package com.travel.withaeng.domain.accompanyreply import org.springframework.data.jpa.repository.JpaRepository -interface AccompanyReplyRepository : JpaRepository, AccompanyReplyRepositoryCustom { - fun findByReplyId(replyId: Long): AccompanyReply? - +interface AccompanyReplyRepository : JpaRepository { + fun findAllByAccompanyId(accompanyId: Long): List } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt index 6f03305..1daa554 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt @@ -2,135 +2,75 @@ package com.travel.withaeng.domain.accompanyreply import com.travel.withaeng.common.exception.WithaengException import com.travel.withaeng.common.exception.WithaengExceptionType -import com.travel.withaeng.domain.accompanyreplylike.AccompanyReplyLikeService +import com.travel.withaeng.domain.accompany.AccompanyRepository +import com.travel.withaeng.domain.user.UserRepository +import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @Service @Transactional(readOnly = true) class AccompanyReplyService( - - private val accompanyReplyRepository: AccompanyReplyRepository, - private val accompanyReplyHistRepository: AccompanyReplyHistRepository, - private val accompanyReplyLikeService: AccompanyReplyLikeService - + private val userRepository: UserRepository, + private val accompanyRepository: AccompanyRepository, + private val accompanyReplyRepository: AccompanyReplyRepository ) { @Transactional - fun createAccompanyReply(param: CreateAccompanyReplyDTO): GetReplyDTO { - val accompanyReplyEntity = param.toEntity() - accompanyReplyRepository.save(accompanyReplyEntity) - - val accompanyReplyHistEntity = param.toHistEntity(accompanyReplyEntity) - - accompanyReplyHistRepository.save(accompanyReplyHistEntity) - - return getOne(accompanyReplyEntity.replyId) - } - - @Transactional - fun modifyAccompanyReply(param: ModifyAccompanyReplyDTO): GetReplyDTO { - - val accompanyReplyEntity = accompanyReplyRepository.findByReplyId(param.replyId) - - if (accompanyReplyEntity != null) { - - if (accompanyReplyEntity.userId != param.userId) { - throw WithaengException.of( - type = WithaengExceptionType.INVALID_ACCESS, - message = "등록자와 수정자가 달라 수정 요청을 거부 합니다." - ) - } - - accompanyReplyEntity.let { - it.content = param.content - } - - val accompanyReplyHistEntity = param.toHistEntity(accompanyReplyEntity) - accompanyReplyHistRepository.save(accompanyReplyHistEntity) + fun create(accompanyId: Long, userId: Long, content: String, parentId: Long? = null): AccompanyReplyDto { + userRepository.findByIdOrNull(userId) ?: throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = "해당하는 유저를 찾을 수 없습니다." + ) + accompanyRepository.findByIdOrNull(accompanyId) ?: throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = "해당하는 동행을 찾을 수 없습니다." + ) + if (parentId != null) { + accompanyReplyRepository.findByIdOrNull(parentId) ?: throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = "해당하는 댓글을 찾을 수 없습니다." + ) } - - return getOne(param.replyId) + val accompanyReply = AccompanyReply.create( + accompanyId = accompanyId, + userId = userId, + content = content, + parentId = parentId + ) + accompanyReplyRepository.save(accompanyReply) + return accompanyReply.toDto() } - @Transactional - fun deleteAccompanyReply(param: DeleteAccompanyReplyDTO): DeleteAccompanyReplyDTO { - - val accompanyReplyEntity = accompanyReplyRepository.findByReplyId(param.replyId) - - if (accompanyReplyEntity != null) { - - if (accompanyReplyEntity.userId != param.userId) { - throw WithaengException.of( - type = WithaengExceptionType.INVALID_ACCESS, - message = "등록자와 수정자가 달라 삭제 요청을 거부 합니다." - ) - } - - accompanyReplyRepository.delete(accompanyReplyEntity) - - val accompanyReplyHistEntity = param.toHistEntity(accompanyReplyEntity) - accompanyReplyHistRepository.save(accompanyReplyHistEntity) - } - - return param + fun findById(replyId: Long): AccompanyReplyDto { + val accompanyReply = accompanyReplyRepository.findByIdOrNull(replyId) ?: throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = "해당하는 댓글을 찾을 수 없습니다." + ) + return accompanyReply.toDto() } - fun getOne(param: Long): GetReplyDTO { - - val accompanyReplyEntity = accompanyReplyRepository.findByReplyId(param) - val accompanyReplyLikeCnt = accompanyReplyLikeService.getAccompanyReplyLikeCnt(param) - - if (accompanyReplyEntity != null) { - return GetReplyDTO.toDto(accompanyReplyEntity, accompanyReplyLikeCnt) - } + fun findAllByAccompanyId(accompanyId: Long): List { + return accompanyReplyRepository.findAllByAccompanyId(accompanyId) + .map { it.toDto() } + } - throw WithaengException.of( + @Transactional + fun update(replyId: Long, content: String): AccompanyReplyDto { + val accompanyReply = accompanyReplyRepository.findByIdOrNull(replyId) ?: throw WithaengException.of( type = WithaengExceptionType.NOT_EXIST, - message = "존재하지 않는 동행 게시글 댓글 요청 입니다." + message = "해당하는 댓글을 찾을 수 없습니다." ) + accompanyReply.content = content + return accompanyReply.toDto() } - //TODO 댓글당 좋아요 누른 userId 목록을 추가로 조회하여 리턴은 추후 처리 - fun getList(param: Long): List? { - - val accompanyReplyList = accompanyReplyRepository.getAccompanyReplyList(param) - - if (accompanyReplyList != null) { - - val replyIdList: List = - accompanyReplyList.map { accompanyReplyEntity -> accompanyReplyEntity.replyId }.toList() - val accompanyReplyLikeList = accompanyReplyLikeService.getAccompanyReplyLikeList(replyIdList) - - for (reply in accompanyReplyList) { - for (like in accompanyReplyLikeList) { - if (reply.replyId == like.replyId) { - reply.likeCnt = like.likeCnt - } - } - } - - val parentList = accompanyReplyList.stream().filter { e -> - e.parentId.equals(0L) - }.toList() - - val sortList = - accompanyReplyList.sortedWith(compareBy({ it.parentId }, { it.depth }, { it.replyOrder })).toList() - val resultList = mutableListOf() - - parentList.stream().forEach { e -> - resultList.add(e) - sortList.forEach { a -> - if (e.replyId.equals(a.parentId)) { - resultList.add(a) - } - } - } - - return resultList - } - - return null + @Transactional + fun delete(replyId: Long) { + val accompanyReply = accompanyReplyRepository.findByIdOrNull(replyId) ?: throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = "해당하는 댓글을 찾을 수 없습니다." + ) + accompanyReplyRepository.delete(accompanyReply) } - } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt index bc6d1a4..3e26722 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt @@ -2,10 +2,6 @@ package com.travel.withaeng.domain.accompanyreplylike import org.springframework.data.jpa.repository.JpaRepository -interface AccompanyReplyLikeRepository : JpaRepository, - AccompanyReplyLikeRepositoryCustom { - +interface AccompanyReplyLikeRepository : JpaRepository { fun countByReplyId(replyId: Long): Long - - fun findByReplyIdAndUserId(replyId: Long, userId: Long): AccompanyReplyLike? } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt index a58c08b..fcbc829 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt @@ -9,30 +9,17 @@ import java.time.LocalDateTime @Service @Transactional(readOnly = true) class AccompanyReplyLikeService( - private val accompanyReplyLikeRepository: AccompanyReplyLikeRepository, private val accompanyReplyLikeHistRepository: AccompanyReplyLikeHistRepository - ) { @Transactional - fun createAccompanyReplyLike(param: CreateAccompanyReplyLikeDTO): CreateAccompanyReplyLikeDTO { + fun likeAccompanyReply(userId: Long, accompanyReplyId: Long) { - val replyLikeEntity = accompanyReplyLikeRepository.findByReplyIdAndUserId(param.replyId, param.userId) - if (replyLikeEntity != null) { - throw WithaengException.of( - type = WithaengExceptionType.INVALID_ACCESS, - message = "이미 해당 댓글의 좋아요 등록이 되어 있습니다." - ) - } - - val accompanyReplyLikeEntity = param.toEntity() - accompanyReplyLikeRepository.save(accompanyReplyLikeEntity) - - val accompanyReplyLikeHistEntity = param.toHistEntity(accompanyReplyLikeEntity) - accompanyReplyLikeHistRepository.save(accompanyReplyLikeHistEntity) + } - return param + fun countAccompanyReplyLikeCount(accompanyReplyId: Long): Long { + return accompanyReplyLikeRepository.countByReplyId(accompanyReplyId) } //TODO delete 성능이 안나올 경우 boolean 형으로 좋아요 제어 @@ -48,12 +35,4 @@ class AccompanyReplyLikeService( return param } - - fun getAccompanyReplyLikeCnt(param: Long): Long { - return accompanyReplyLikeRepository.countByReplyId(param) - } - - fun getAccompanyReplyLikeList(param: List): List { - return accompanyReplyLikeRepository.getAccompanyReplyLikeList(param) - } } \ No newline at end of file From 253104c75b25408d1ca318e9d97a4edb47a1083b Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Tue, 14 May 2024 15:34:18 +0900 Subject: [PATCH 073/174] Implement like accompany reply API --- .../AccompanyReplyLikeApplicationService.kt | 20 +++++ .../AccompanyReplyLikeController.kt | 42 +++++++---- .../accompanylike/AccompanyLikeService.kt | 7 +- .../AccompanyReplyLikeDto.kt | 73 ------------------- .../AccompanyReplyLikeRepository.kt | 1 + .../AccompanyReplyLikeService.kt | 42 +++++++---- 6 files changed, 77 insertions(+), 108 deletions(-) create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreplylike/AccompanyReplyLikeApplicationService.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeDto.kt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreplylike/AccompanyReplyLikeApplicationService.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreplylike/AccompanyReplyLikeApplicationService.kt new file mode 100644 index 0000000..99d7692 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreplylike/AccompanyReplyLikeApplicationService.kt @@ -0,0 +1,20 @@ +package com.travel.withaeng.applicationservice.accompanyreplylike + +import com.travel.withaeng.domain.accompanyreplylike.AccompanyReplyLikeService +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional + +@Service +@Transactional(readOnly = true) +class AccompanyReplyLikeApplicationService(private val accompanyReplyLikeService: AccompanyReplyLikeService) { + + @Transactional + fun like(userId: Long, accompanyReplyId: Long) { + accompanyReplyLikeService.createAccompanyReplyLike(userId, accompanyReplyId) + } + + @Transactional + fun dislike(userId: Long, accompanyReplyId: Long) { + accompanyReplyLikeService.deleteAccompanyReplyLike(userId, accompanyReplyId) + } +} \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreplylike/AccompanyReplyLikeController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreplylike/AccompanyReplyLikeController.kt index 8ef8328..fbe1f9f 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreplylike/AccompanyReplyLikeController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreplylike/AccompanyReplyLikeController.kt @@ -1,27 +1,39 @@ package com.travel.withaeng.controller.accompanyreplylike +import com.travel.withaeng.applicationservice.accompanyreplylike.AccompanyReplyLikeApplicationService import com.travel.withaeng.common.ApiResponse -import com.travel.withaeng.domain.accompanyreplylike.AccompanyReplyLikeService -import com.travel.withaeng.domain.accompanyreplylike.CreateAccompanyReplyLikeDTO -import com.travel.withaeng.domain.accompanyreplylike.DeleteAccompanyReplyLikeDTO -import org.springframework.http.HttpStatus -import org.springframework.http.ResponseEntity +import com.travel.withaeng.security.authentication.UserInfo +import com.travel.withaeng.security.resolver.GetAuth import org.springframework.web.bind.annotation.* @RestController -@RequestMapping("/api/v1/accompany/{accompanyId}/reply/{replyId}/like") -class AccompanyReplyLikeController(private val accompanyReplyLikeService: AccompanyReplyLikeService) { +@RequestMapping("/api/v1/accompany") +class AccompanyReplyLikeController( + private val accompanyReplyLikeApplicationService: AccompanyReplyLikeApplicationService +) { - @PostMapping("") - fun create(@RequestBody param: CreateAccompanyReplyLikeDTO): ResponseEntity> { - return ResponseEntity.status(HttpStatus.CREATED) - .body(ApiResponse(true, accompanyReplyLikeService.createAccompanyReplyLike(param), null)) + @PostMapping("/{accompanyId}/reply/{replyId}/like") + fun create( + @GetAuth userInfo: UserInfo, + @PathVariable("replyId") replyId: Long + ): ApiResponse { + accompanyReplyLikeApplicationService.like( + userId = userInfo.id, + accompanyReplyId = replyId + ) + return ApiResponse.success() } - @DeleteMapping("") - fun delete(@RequestBody param: DeleteAccompanyReplyLikeDTO): ResponseEntity> { - return ResponseEntity.status(HttpStatus.OK) - .body(ApiResponse(true, accompanyReplyLikeService.deleteAccompanyReplyLike(param), null)) + @DeleteMapping("/{accompanyId}/reply/{replyId}/dislike") + fun delete( + @GetAuth userInfo: UserInfo, + @PathVariable("replyId") replyId: Long + ): ApiResponse { + accompanyReplyLikeApplicationService.dislike( + userId = userInfo.id, + accompanyReplyId = replyId + ) + return ApiResponse.success() } } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt index a20a5f4..2d70d8e 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt @@ -17,7 +17,7 @@ class AccompanyLikeService( ) { @Transactional - fun createAccompanyLike(userId: Long, accompanyId: Long): AccompanyLikeDto { + fun createAccompanyLike(userId: Long, accompanyId: Long) { userRepository.findByIdOrNull(userId) ?: throw WithaengException.of( type = WithaengExceptionType.NOT_EXIST, message = "해당하는 유저를 찾을 수 없습니다." @@ -27,12 +27,9 @@ class AccompanyLikeService( message = "해당하는 동행을 찾을 수 없습니다." ) val prevAccompanyLike = accompanyLikeRepository.findByUserIdAndAccompanyId(userId, accompanyId) - if (prevAccompanyLike != null) { - return prevAccompanyLike.toDto() - } + if (prevAccompanyLike != null) return val accompanyLike = AccompanyLike.create(userId = userId, accompanyId = accompanyId) accompanyLikeRepository.save(accompanyLike) - return accompanyLike.toDto() } fun countByAccompanyId(accompanyId: Long): Long { diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeDto.kt deleted file mode 100644 index c71e6a5..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeDto.kt +++ /dev/null @@ -1,73 +0,0 @@ -package com.travel.withaeng.domain.accompanyreplylike - -import com.travel.withaeng.common.cd.ExecCd -import org.jetbrains.annotations.NotNull - -class AccompanyReplyLikeDto - -class CreateAccompanyReplyLikeDTO( - - @NotNull - val replyId: Long, - - @NotNull - val userId: Long, - - ) { - fun toEntity(): AccompanyReplyLikeEntity { - return AccompanyReplyLikeEntity( - 0, - this.replyId, - this.userId - ) - } - - fun toHistEntity(entity: AccompanyReplyLikeEntity): AccompanyReplyLikeHistEntity { - return AccompanyReplyLikeHistEntity( - 0, - entity.replyLikeId, - entity.replyId, - entity.userId, - ExecCd.CREATE.execCd - ) - } - -} - -class DeleteAccompanyReplyLikeDTO( - - @NotNull - val replyLikeId: Long, - - @NotNull - val replyId: Long, - - @NotNull - val userId: Long - -) { - fun toEntity(): AccompanyReplyLikeEntity { - return AccompanyReplyLikeEntity( - this.replyLikeId, - this.replyId, - this.userId - ) - } - - fun toHistEntity(entity: AccompanyReplyLikeEntity): AccompanyReplyLikeHistEntity { - return AccompanyReplyLikeHistEntity( - 0, - entity.replyLikeId, - entity.replyId, - entity.userId, - ExecCd.DELETE.execCd - ) - } - -} - -data class GetReplyLikeDTO( - - var replyId: Long, - var likeCnt: Long -) \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt index 3e26722..661577b 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt @@ -4,4 +4,5 @@ import org.springframework.data.jpa.repository.JpaRepository interface AccompanyReplyLikeRepository : JpaRepository { fun countByReplyId(replyId: Long): Long + fun findByUserIdAndReplyId(userId: Long, replyId: Long): AccompanyReplyLike? } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt index fcbc829..f026686 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt @@ -2,37 +2,49 @@ package com.travel.withaeng.domain.accompanyreplylike import com.travel.withaeng.common.exception.WithaengException import com.travel.withaeng.common.exception.WithaengExceptionType +import com.travel.withaeng.domain.accompanyreply.AccompanyReplyRepository +import com.travel.withaeng.domain.user.UserRepository +import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional -import java.time.LocalDateTime @Service @Transactional(readOnly = true) class AccompanyReplyLikeService( + private val userRepository: UserRepository, + private val accompanyReplyRepository: AccompanyReplyRepository, private val accompanyReplyLikeRepository: AccompanyReplyLikeRepository, - private val accompanyReplyLikeHistRepository: AccompanyReplyLikeHistRepository ) { @Transactional - fun likeAccompanyReply(userId: Long, accompanyReplyId: Long) { - + fun createAccompanyReplyLike(userId: Long, accompanyReplyId: Long) { + userRepository.findByIdOrNull(userId) ?: throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = "해당하는 유저가 없습니다." + ) + accompanyReplyRepository.findByIdOrNull(accompanyReplyId) ?: throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = "해당하는 댓글이 없습니다." + ) + if (accompanyReplyLikeRepository.findByUserIdAndReplyId(userId, accompanyReplyId) != null) return + accompanyReplyLikeRepository.save( + AccompanyReplyLike( + replyId = accompanyReplyId, + userId = userId + ) + ) } fun countAccompanyReplyLikeCount(accompanyReplyId: Long): Long { return accompanyReplyLikeRepository.countByReplyId(accompanyReplyId) } - //TODO delete 성능이 안나올 경우 boolean 형으로 좋아요 제어 @Transactional - fun deleteAccompanyReplyLike(param: DeleteAccompanyReplyLikeDTO): DeleteAccompanyReplyLikeDTO { - - val accompanyReplyLikeEntity = param.toEntity() - accompanyReplyLikeRepository.delete(accompanyReplyLikeEntity) - - val accompanyReplyLikeHistEntity = param.toHistEntity(accompanyReplyLikeEntity) - accompanyReplyLikeHistEntity.deletedAt = LocalDateTime.now() - accompanyReplyLikeHistRepository.save(accompanyReplyLikeHistEntity) - - return param + fun deleteAccompanyReplyLike(userId: Long, accompanyReplyId: Long) { + val accompanyReplyLike = accompanyReplyLikeRepository.findByUserIdAndReplyId( + userId = userId, + replyId = accompanyReplyId + ) ?: return + accompanyReplyLikeRepository.delete(accompanyReplyLike) } } \ No newline at end of file From ebc3145b42e6f62b483a0bc0f2a75da1830b230a Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Tue, 14 May 2024 15:38:44 +0900 Subject: [PATCH 074/174] Remove unnecessary codes --- .../destination/DestinationController.kt | 21 --------- .../domain/destination/DestinationDto.kt | 38 ---------------- .../domain/destination/DestinationService.kt | 45 ------------------- 3 files changed, 104 deletions(-) delete mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/destination/DestinationController.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationDto.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationService.kt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/destination/DestinationController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/destination/DestinationController.kt deleted file mode 100644 index f43404a..0000000 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/destination/DestinationController.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.travel.withaeng.destination - -import com.travel.withaeng.common.ApiResponse -import com.travel.withaeng.domain.destination.DestinationService -import org.springframework.http.HttpStatus -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 - -@RestController -@RequestMapping("/api/v1/destination") -class DestinationController(private val destinationService: DestinationService) { - - - @GetMapping("/getList") - fun getList(): ResponseEntity> { - return ResponseEntity.status(HttpStatus.OK) - .body(ApiResponse(true, destinationService.getDestinationList(), null)) - } -} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationDto.kt deleted file mode 100644 index abc64a7..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationDto.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.travel.withaeng.domain.destination - - -class DestinationDto( - - var continentList: List -) - -class Continent( - - var continentCd: String, - var continentNm: String, - var countryList: List - -) { - constructor(continentCd: String, continentNm: String) : - this(continentCd, continentNm, mutableListOf()) - -} - -class Country( - - var countryCd: String, - var countryNm: String, - var cityList: List -) { - - constructor(countryCd: String, countryNm: String) : - this(countryCd, countryNm, mutableListOf()) - - -} - -class City( - - var cityCd: String, - var cityNm: String, -) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationService.kt deleted file mode 100644 index f7dc586..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/destination/DestinationService.kt +++ /dev/null @@ -1,45 +0,0 @@ -package com.travel.withaeng.domain.destination - -import com.travel.withaeng.domain.accompany.City -import com.travel.withaeng.domain.accompany.Continent -import com.travel.withaeng.domain.accompany.Country -import org.springframework.stereotype.Service - -@Service -class DestinationService { - - fun getDestinationList(): DestinationDto { - - val continentList = mutableListOf() - - for (continentCd in Continent.entries) { - - // Create a continent object - val continent = Continent(continentCd.continentCode, continentCd.continentName) - val countryList = mutableListOf() - - for (countryCd in Country.entries) { - if (continentCd.continentCode.equals(countryCd.continentCode)) { - val country = Country(countryCd.countryCode, countryCd.countryName) - - val cityList = mutableListOf() - for (cityCd in City.entries) { - if (countryCd.countryCode.equals(cityCd.countryCode)) { - val city = City(cityCd.cityCode, cityCd.cityName) - cityList.add(city) - } - } - country.cityList = cityList - countryList.add(country) - } - } - - continent.countryList = countryList - // Add the continent to the list - continentList.add(continent) - } - - // Create and return DestinationDto - return DestinationDto(continentList) - } -} \ No newline at end of file From 0595bf60d9ca93244b083002717fad5bc025a9e5 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Tue, 14 May 2024 15:52:15 +0900 Subject: [PATCH 075/174] Write swagger descriptions --- .../accompany/AccompanyController.kt | 27 ++++++------- .../accompanylike/AccompanyLikeController.kt | 14 +++++++ .../AccompanyReplyController.kt | 40 +++++++++++++++---- .../AccompanyReplyLikeController.kt | 14 +++++++ .../controller/auth/AuthController.kt | 2 +- 5 files changed, 74 insertions(+), 23 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/AccompanyController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/AccompanyController.kt index 10f22d0..f8f61d5 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/AccompanyController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/AccompanyController.kt @@ -15,7 +15,7 @@ import jakarta.validation.Valid import org.springframework.http.HttpStatus import org.springframework.web.bind.annotation.* -@Tag(name = "Accompany", description = "Accompany API") +@Tag(name = "Accompany", description = "동행 API") @RestController @RequestMapping("/api/v1/accompany") class AccompanyController(private val accompanyApplicationService: AccompanyApplicationService) { @@ -34,6 +34,18 @@ class AccompanyController(private val accompanyApplicationService: AccompanyAppl return ApiResponse.success(accompanyApplicationService.create(request.toServiceRequest(userInfo.id))) } + @Operation(summary = "Retrieve Accompany API", description = "동행 게시글 단건 조회 API") + @GetMapping("/{accompanyId}") + fun retrieve(@PathVariable("accompanyId") accompanyId: Long): ApiResponse { + return ApiResponse.success(accompanyApplicationService.retrieve(accompanyId)) + } + + @Operation(summary = "Retrieve All Accompany API", description = "모든 동행 게시글 조회 API") + @GetMapping("/all") + fun retrieveAll(): ApiResponse> { + return ApiResponse.success(accompanyApplicationService.retrieveAll()) + } + @Operation( summary = "Update Accompany API", description = "동행 게시글 수정 API", @@ -54,17 +66,4 @@ class AccompanyController(private val accompanyApplicationService: AccompanyAppl ) ) } - - @Operation(summary = "Retrieve Accompany API", description = "동행 게시글 단건 조회 API") - @GetMapping("/{accompanyId}") - fun retrieve(@PathVariable("accompanyId") accompanyId: Long): ApiResponse { - return ApiResponse.success(accompanyApplicationService.retrieve(accompanyId)) - } - - @Operation(summary = "Retrieve All Accompany API", description = "모든 동행 게시글 조회 API") - @GetMapping("/all") - fun retrieveAll(): ApiResponse> { - return ApiResponse.success(accompanyApplicationService.retrieveAll()) - } - } \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanylike/AccompanyLikeController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanylike/AccompanyLikeController.kt index c14d3ee..c65a30c 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanylike/AccompanyLikeController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanylike/AccompanyLikeController.kt @@ -4,15 +4,24 @@ import com.travel.withaeng.applicationservice.accompanylike.AccompanyLikeApplica import com.travel.withaeng.common.ApiResponse import com.travel.withaeng.security.authentication.UserInfo import com.travel.withaeng.security.resolver.GetAuth +import io.swagger.v3.oas.annotations.Operation +import io.swagger.v3.oas.annotations.security.SecurityRequirement +import io.swagger.v3.oas.annotations.tags.Tag import org.springframework.http.HttpStatus import org.springframework.web.bind.annotation.* +@Tag(name = "Like/Dislike Accompany", description = "동행 좋아요 API") @RestController @RequestMapping("/api/v1/accompany") class AccompanyLikeController( private val accompanyLikeApplicationService: AccompanyLikeApplicationService ) { + @Operation( + summary = "Like Accompany API", + description = "동행 게시글 좋아요 API", + security = [SecurityRequirement(name = "Authorization")] + ) @PostMapping("/{accompanyId}/like") @ResponseStatus(HttpStatus.CREATED) fun like( @@ -23,6 +32,11 @@ class AccompanyLikeController( return ApiResponse.success() } + @Operation( + summary = "Dislike Accompany API", + description = "동행 게시글 좋아요 취소 API", + security = [SecurityRequirement(name = "Authorization")] + ) @DeleteMapping("/{accompanyId}/like") fun dislike( @GetAuth userInfo: UserInfo, diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt index 9a2d5d3..ca3f1a4 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt @@ -8,13 +8,22 @@ import com.travel.withaeng.controller.accompanyreply.dto.UpdateAccompanyReplyReq import com.travel.withaeng.controller.accompanyreply.dto.toServiceRequest import com.travel.withaeng.security.authentication.UserInfo import com.travel.withaeng.security.resolver.GetAuth +import io.swagger.v3.oas.annotations.Operation +import io.swagger.v3.oas.annotations.security.SecurityRequirement +import io.swagger.v3.oas.annotations.tags.Tag import org.springframework.http.HttpStatus import org.springframework.web.bind.annotation.* +@Tag(name = "Accompany Reply", description = "동행 댓글 API") @RestController @RequestMapping("/api/v1/accompany") class AccompanyReplyController(private val accompanyReplyApplicationService: AccompanyReplyApplicationService) { + @Operation( + summary = "Create Accompany Reply API", + description = "동행 댓글 생성 API", + security = [SecurityRequirement(name = "Authorization")] + ) @PostMapping("/{accompanyId}/reply") @ResponseStatus(HttpStatus.CREATED) fun create( @@ -32,6 +41,11 @@ class AccompanyReplyController(private val accompanyReplyApplicationService: Acc ) } + @Operation( + summary = "Reply Accompany Reply API", + description = "동행 댓글의 댓글 생성 API", + security = [SecurityRequirement(name = "Authorization")] + ) @PostMapping("/{accompanyId}/reply/{replyId}") @ResponseStatus(HttpStatus.CREATED) fun reply( @@ -51,6 +65,19 @@ class AccompanyReplyController(private val accompanyReplyApplicationService: Acc ) } + @Operation(summary = "Retrieve All Accompany Replies API", description = "동행 댓글 조회 API") + @GetMapping("/{accompanyId}/reply/all") + fun findAll(@PathVariable(name = "accompanyId") accompanyId: Long): ApiResponse> { + return ApiResponse.success( + accompanyReplyApplicationService.findAll(accompanyId = accompanyId) + ) + } + + @Operation( + summary = "Update Accompany Reply API", + description = "동행 댓글 수정 API", + security = [SecurityRequirement(name = "Authorization")] + ) @PutMapping("/{accompanyId}/reply/{replyId}") fun update( @GetAuth userInfo: UserInfo, @@ -69,6 +96,11 @@ class AccompanyReplyController(private val accompanyReplyApplicationService: Acc ) } + @Operation( + summary = "Delete Accompany Reply API", + description = "동행 댓글 삭제 API", + security = [SecurityRequirement(name = "Authorization")] + ) @DeleteMapping("/{accompanyId}/reply/{replyId}") fun delete( @GetAuth userInfo: UserInfo, @@ -78,12 +110,4 @@ class AccompanyReplyController(private val accompanyReplyApplicationService: Acc accompanyReplyApplicationService.delete(userId = userInfo.id, accompanyReplyId = replyId) ) } - - @GetMapping("/{accompanyId}/reply/all") - fun findAll(@PathVariable(name = "accompanyId") accompanyId: Long): ApiResponse> { - return ApiResponse.success( - accompanyReplyApplicationService.findAll(accompanyId = accompanyId) - ) - } - } \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreplylike/AccompanyReplyLikeController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreplylike/AccompanyReplyLikeController.kt index fbe1f9f..727f40a 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreplylike/AccompanyReplyLikeController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreplylike/AccompanyReplyLikeController.kt @@ -4,14 +4,23 @@ import com.travel.withaeng.applicationservice.accompanyreplylike.AccompanyReplyL import com.travel.withaeng.common.ApiResponse import com.travel.withaeng.security.authentication.UserInfo import com.travel.withaeng.security.resolver.GetAuth +import io.swagger.v3.oas.annotations.Operation +import io.swagger.v3.oas.annotations.security.SecurityRequirement +import io.swagger.v3.oas.annotations.tags.Tag import org.springframework.web.bind.annotation.* +@Tag(name = "Accompany Reply Like", description = "동행 댓글 좋아요 API") @RestController @RequestMapping("/api/v1/accompany") class AccompanyReplyLikeController( private val accompanyReplyLikeApplicationService: AccompanyReplyLikeApplicationService ) { + @Operation( + summary = "Like Accompany Reply API", + description = "동행 댓글 좋아요 API", + security = [SecurityRequirement(name = "Authorization")] + ) @PostMapping("/{accompanyId}/reply/{replyId}/like") fun create( @GetAuth userInfo: UserInfo, @@ -24,6 +33,11 @@ class AccompanyReplyLikeController( return ApiResponse.success() } + @Operation( + summary = "Dislike Accompany Reply API", + description = "동행 댓글 좋아요 취소 API", + security = [SecurityRequirement(name = "Authorization")] + ) @DeleteMapping("/{accompanyId}/reply/{replyId}/dislike") fun delete( @GetAuth userInfo: UserInfo, diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt index 1a2b83b..b572d6f 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt @@ -11,7 +11,7 @@ import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.tags.Tag import org.springframework.web.bind.annotation.* -@Tag(name = "Auth", description = "Auth API") +@Tag(name = "Auth", description = "인증 API") @RestController @RequestMapping("api/v1/auth") class AuthController(private val authApplicationService: AuthApplicationService) { From c305cbbc9bb3c12cf2f4116fae97a26da163297d Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Tue, 14 May 2024 19:56:03 +0900 Subject: [PATCH 076/174] Fix config of security --- .../com/travel/withaeng/common/WhiteList.kt | 11 -------- .../travel/withaeng/config/SecurityConfig.kt | 8 +++--- .../travel/withaeng/security/jwt/JwtFilter.kt | 26 +++++++------------ 3 files changed, 14 insertions(+), 31 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/WhiteList.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/WhiteList.kt index d8d19fc..9252ce7 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/WhiteList.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/WhiteList.kt @@ -10,15 +10,4 @@ object WhiteList { // Auth endpoints "/api/v1/auth/**", ) - - fun getWhiteListForAuthenticationFilter(): List = listOf( - // Common - "/favicon.ico", - "/error", - // Swagger - "/api-docs", "/swagger-ui", "/swagger-resources", - // SignIn/SignUp Endpoints - "/api/v1/auth", - ) - } \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/SecurityConfig.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/config/SecurityConfig.kt index 6abd758..45a944f 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/SecurityConfig.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/config/SecurityConfig.kt @@ -10,6 +10,7 @@ import com.travel.withaeng.security.jwt.JwtFilter import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.http.HttpHeaders +import org.springframework.http.HttpMethod import org.springframework.security.config.annotation.web.builders.HttpSecurity import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer @@ -39,9 +40,7 @@ class SecurityConfig(private val jwtAgent: JwtAgent, private val objectMapper: O .httpBasic { it.disable() } .formLogin { it.disable() } .authorizeHttpRequests { - it.requestMatchers(AntPathRequestMatcher("/**")) - .hasAnyRole(UserRole.USER.getActualRoleName(), UserRole.ADMIN.getActualRoleName()) - .anyRequest().permitAll() + it.anyRequest().hasAnyRole(UserRole.USER.getActualRoleName(), UserRole.ADMIN.getActualRoleName()) } .addFilterBefore(JwtFilter(jwtAgent, objectMapper), UsernamePasswordAuthenticationFilter::class.java) .exceptionHandling { @@ -55,6 +54,7 @@ class SecurityConfig(private val jwtAgent: JwtAgent, private val objectMapper: O fun webSecurityCustomizer(): WebSecurityCustomizer { return WebSecurityCustomizer { it.ignoring().requestMatchers(*getWhiteListForSecurityConfig().toTypedArray()) + .requestMatchers(AntPathRequestMatcher("/api/v1/**", HttpMethod.GET.name())) } } @@ -69,7 +69,7 @@ class SecurityConfig(private val jwtAgent: JwtAgent, private val objectMapper: O } return UrlBasedCorsConfigurationSource().apply { - registerCorsConfiguration("/v1/**", configuration) + registerCorsConfiguration("api/v1/**", configuration) } } diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtFilter.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtFilter.kt index 5cf53bf..ca54d4d 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtFilter.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtFilter.kt @@ -3,7 +3,6 @@ package com.travel.withaeng.security.jwt import com.fasterxml.jackson.databind.ObjectMapper import com.travel.withaeng.common.ApiResponse import com.travel.withaeng.common.Constants.Authentication.BEARER_TYPE -import com.travel.withaeng.common.WhiteList.getWhiteListForAuthenticationFilter import com.travel.withaeng.common.exception.WithaengException import com.travel.withaeng.common.exception.WithaengExceptionType import com.travel.withaeng.security.authentication.JwtAuthentication @@ -49,17 +48,16 @@ class JwtFilter( } private fun setAuthenticationFromToken(request: HttpServletRequest) { - if (!isNotCheckEndpoint(request)) { - val authorization = - request.getAuthorization() - ?: throw BadCredentialsException(WithaengExceptionType.AUTHENTICATION_FAILURE.message) - log.debug("Parsing token in header: $authorization - Request path: ${request.requestURI}") - getToken(authorization)?.let { token -> - jwtAgent.extractUserInfoFromToken(token)?.let { userInfo -> - SecurityContextHolder.getContext().authentication = JwtAuthentication(userInfo) - } - } ?: throw WithaengException.of(WithaengExceptionType.AUTHENTICATION_FAILURE) - } + val authorization = request.getAuthorization() + ?: throw BadCredentialsException(WithaengExceptionType.AUTHENTICATION_FAILURE.message) + log.debug("Parsing token in header: $authorization - Request path: ${request.requestURI}") + getToken(authorization)?.let { token -> + jwtAgent.extractUserInfoFromToken(token)?.let { userInfo -> + log.debug("userInfo: $userInfo") + SecurityContextHolder.getContext().authentication = JwtAuthentication(userInfo) + } + } ?: throw WithaengException.of(WithaengExceptionType.AUTHENTICATION_FAILURE) + } private fun getToken(authorization: String): String? { @@ -70,10 +68,6 @@ class JwtFilter( private fun HttpServletRequest.getAuthorization(): String? = getHeader(HttpHeaders.AUTHORIZATION) - private fun isNotCheckEndpoint(request: HttpServletRequest): Boolean { - return getWhiteListForAuthenticationFilter().any { request.requestURI.startsWith(it) } - } - companion object { private const val AUTH_PROVIDER_SPLIT_DELIMITER: String = " " } From dbba6cb54b77a4ccf6a7c28c0e940ce58c1eb144 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Tue, 14 May 2024 19:56:26 +0900 Subject: [PATCH 077/174] Fix tagIds to nullable in AccompanyService --- .../accompany/dto/AccompanyServiceRequestDto.kt | 4 ++-- .../withaeng/controller/accompany/dto/AccompanyRequestDto.kt | 2 +- .../kotlin/com/travel/withaeng/converter/TagIdsConverter.kt | 3 ++- .../kotlin/com/travel/withaeng/domain/accompany/Accompany.kt | 2 +- .../com/travel/withaeng/domain/accompany/AccompanyDto.kt | 2 +- .../com/travel/withaeng/domain/accompany/AccompanyService.kt | 3 ++- 6 files changed, 9 insertions(+), 7 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt index 28c3b13..279ebf5 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt @@ -14,7 +14,7 @@ data class CreateAccompanyServiceRequest( val endTripDate: LocalDate, val bannerImageUrl: String? = null, val memberCount: Long, - val tagIds: List, + val tagIds: List? = null, val openKakaoUrl: String ) @@ -31,7 +31,7 @@ fun CreateAccompanyServiceRequest.toDomainDto(): CreateAccompanyDto = CreateAcco endTripDate = endTripDate, bannerImageUrl = bannerImageUrl, memberCount = memberCount, - tagIds = tagIds.toSet(), + tagIds = tagIds?.toSet(), openKakaoUrl = openKakaoUrl ) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/dto/AccompanyRequestDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/dto/AccompanyRequestDto.kt index 44cd873..b81ba87 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/dto/AccompanyRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/dto/AccompanyRequestDto.kt @@ -35,7 +35,7 @@ data class CreateAccompanyRequest( val memberCount: Long, @Schema(description = "동행 게시글에 부착할 태그 아이디 리스트") - val tagIds: List, + val tagIds: List? = null, @Schema(description = "동행 게시글에 게시된 오픈 카카오톡 URL") val openKakaoUrl: String diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/TagIdsConverter.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/TagIdsConverter.kt index 01d40fa..272039e 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/TagIdsConverter.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/TagIdsConverter.kt @@ -8,7 +8,8 @@ class TagIdsConverter : AttributeConverter, String> { } override fun convertToEntityAttribute(data: String): Set { - return data.split(DELIMITER).map { it.toLong() }.toSet() + if (data.isBlank()) return setOf() + else return data.split(DELIMITER).map { it.toLong() }.toSet() } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt index d9d7dad..0c11af6 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt @@ -65,7 +65,7 @@ class Accompany( memberCount = params.memberCount, openKakaoUrl = params.openKakaoUrl, accompanyDestination = params.destination, - tagIds = params.tagIds + tagIds = params.tagIds ?: setOf() ) } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt index ee4d4cb..a3fa4e9 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt @@ -11,7 +11,7 @@ data class CreateAccompanyDto( val endTripDate: LocalDate, val bannerImageUrl: String? = null, val memberCount: Long, - val tagIds: Set = emptySet(), + val tagIds: Set? = emptySet(), val openKakaoUrl: String ) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt index 8820823..0c329a6 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt @@ -53,7 +53,8 @@ class AccompanyService( return accompanyRepository.findAll().map { it.toDto() } } - private fun filterValidTagIds(tagIds: Iterable): Set { + private fun filterValidTagIds(tagIds: Iterable?): Set { + if (tagIds == null) return setOf() return tagRepository.findAllById(tagIds).map { it.id }.toSet() } From 0c549930618eabd8fcca8f610d4d07e9f4449b54 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Wed, 15 May 2024 01:10:45 +0900 Subject: [PATCH 078/174] Implemen test api --- .../test/TestApplicationService.kt | 24 +++++++++++++++ .../com/travel/withaeng/common/WhiteList.kt | 2 ++ .../controller/test/TestController.kt | 30 +++++++++++++++++++ .../withaeng/domain/user/UserService.kt | 7 +++++ 4 files changed, 63 insertions(+) create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/test/TestApplicationService.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/controller/test/TestController.kt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/test/TestApplicationService.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/test/TestApplicationService.kt new file mode 100644 index 0000000..3502224 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/test/TestApplicationService.kt @@ -0,0 +1,24 @@ +package com.travel.withaeng.applicationservice.test + +import com.travel.withaeng.domain.user.UserService +import com.travel.withaeng.security.authentication.UserInfo +import com.travel.withaeng.security.jwt.JwtAgent +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional + +@Transactional(readOnly = true) +@Service +class TestApplicationService( + private val jwtAgent: JwtAgent, + private val userService: UserService +) { + + fun provideUserToken(userId: Long): String { + return jwtAgent.provide(UserInfo.from(userService.findById(userId))) + } + + @Transactional + fun confirmUser(userId: Long) { + userService.grantUserRole(userId) + } +} \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/WhiteList.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/WhiteList.kt index 9252ce7..8bd280f 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/WhiteList.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/WhiteList.kt @@ -9,5 +9,7 @@ object WhiteList { "/error/**", // Auth endpoints "/api/v1/auth/**", + // Test endpoints + "/api/v1/test/**" ) } \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/test/TestController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/test/TestController.kt new file mode 100644 index 0000000..1d14f07 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/test/TestController.kt @@ -0,0 +1,30 @@ +package com.travel.withaeng.controller.test + +import com.travel.withaeng.applicationservice.test.TestApplicationService +import com.travel.withaeng.common.ApiResponse +import io.swagger.v3.oas.annotations.Operation +import io.swagger.v3.oas.annotations.tags.Tag +import org.springframework.web.bind.annotation.* + +@Tag(name = "Test", description = "테스트를 위한 API") +@RequestMapping("/api/v1/test") +@RestController +class TestController( + private val testApplicationService: TestApplicationService +) { + + @Operation(summary = "Provide Test Access Token", description = "테스트 토큰 발급") + @GetMapping("/token/{userId}") + fun getToken(@PathVariable userId: Long): ApiResponse { + return ApiResponse.success(testApplicationService.provideUserToken(userId)) + } + + @Operation(summary = "Grant User Role", description = "사용자 인증 처리") + @PostMapping("/user/{userId}/confirm") + fun confirmUser(@PathVariable userId: Long): ApiResponse { + testApplicationService.confirmUser(userId) + return ApiResponse.success() + } + + +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt index 04ef1ae..0d11560 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt @@ -22,6 +22,13 @@ class UserService(private val userRepository: UserRepository) { ).toDto() } + fun findById(id: Long): UserDto { + return userRepository.findByIdOrNull(id)?.toDto() ?: throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = "해당하는 유저를 찾을 수 없습니다." + ) + } + fun findByEmailOrNull(email: String): UserDto? { return userRepository.findByEmail(email)?.toDto() } From 170cb18e543a4398fdf8e0f11d1a53ea66a5cc16 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Wed, 15 May 2024 02:11:38 +0900 Subject: [PATCH 079/174] Add application-domain-dev.yml --- .../src/main/resources/application-domain-dev.yml | 12 ++++++++++++ .../src/main/resources/application-domain-local.yml | 5 +++++ .../src/main/resources/application-domain.yml | 12 +++++------- 3 files changed, 22 insertions(+), 7 deletions(-) create mode 100644 withaeng-domain/src/main/resources/application-domain-dev.yml diff --git a/withaeng-domain/src/main/resources/application-domain-dev.yml b/withaeng-domain/src/main/resources/application-domain-dev.yml new file mode 100644 index 0000000..41eac20 --- /dev/null +++ b/withaeng-domain/src/main/resources/application-domain-dev.yml @@ -0,0 +1,12 @@ +spring: + config: + activate: + on-profile: dev + jpa: + hibernate: + ddl-auto: create + properties: + hibernate: + show_sql: false + format_sql: false + use_sql_comments: false \ No newline at end of file diff --git a/withaeng-domain/src/main/resources/application-domain-local.yml b/withaeng-domain/src/main/resources/application-domain-local.yml index 77902b6..1e2b26a 100644 --- a/withaeng-domain/src/main/resources/application-domain-local.yml +++ b/withaeng-domain/src/main/resources/application-domain-local.yml @@ -2,6 +2,11 @@ spring: config: activate: on-profile: local + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: ENC(lFITsL+l7aOSMUY3hRT3aR4X0GV+yqIJfYMyXaMajbZZJSW+Lv5MTrbP5Cwa8XAUxGpH7A9GxRNAZtrDhf6V4yXkD6gf3RUYWsPp77Ieguo=) + username: ENC(s1UggVxVWnWC0WqrTpmXaLw+QCpZmkuj2kvSQp+zt2vwKLbRH6WDAZKYUR75DqsR) + password: ENC(HT2z+x9LrfoHTmTTCYLkx7cO0ru9Gcbh+YGnP/0MWC1BpBwQtPfWue+zQx5RPQg8) jpa: hibernate: ddl-auto: none diff --git a/withaeng-domain/src/main/resources/application-domain.yml b/withaeng-domain/src/main/resources/application-domain.yml index 4ac5c1c..36c51bf 100644 --- a/withaeng-domain/src/main/resources/application-domain.yml +++ b/withaeng-domain/src/main/resources/application-domain.yml @@ -1,16 +1,14 @@ spring: profiles: - default: local - + default: dev datasource: driver-class-name: com.mysql.cj.jdbc.Driver - url: ENC(lFITsL+l7aOSMUY3hRT3aR4X0GV+yqIJfYMyXaMajbZZJSW+Lv5MTrbP5Cwa8XAUxGpH7A9GxRNAZtrDhf6V4yXkD6gf3RUYWsPp77Ieguo=) - username: ENC(s1UggVxVWnWC0WqrTpmXaLw+QCpZmkuj2kvSQp+zt2vwKLbRH6WDAZKYUR75DqsR) - password: ENC(HT2z+x9LrfoHTmTTCYLkx7cO0ru9Gcbh+YGnP/0MWC1BpBwQtPfWue+zQx5RPQg8) - + url: ENC(hrN+eQ4p84E3NW0vTIIRfhlAvKoNxPvYFvCAN2O9CyD7UZpSDS2dI9fEsBaHp6gftj+l4UOIBo5BHRIo2BQiC403lDFKj8I5ySiIxdvhY0Pp7fheX5J9DvJD5elcnAthagf+7EFdQVuQ0xdSODL7LceQs5DCSwESYThyL9HLPVM=) + username: ENC(FTbbdqVBbcTrUysSwbf/BwFbE0HhgdyXT+Z0uC0xZfLyuftv/9ceA4wQdOp70vMT) + password: ENC(7+z+f1IVvS1HcBCtH8hYpUMbEM6mcHVBw93co3jNIhp8EuXicXkee/MlqY1DkJq2) jpa: hibernate: - ddl-auto: none + ddl-auto: create properties: hibernate: show_sql: false From d064f4f70a1a5e7c2e36ce703d9662b66201a578 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Wed, 15 May 2024 02:11:55 +0900 Subject: [PATCH 080/174] Fix default spring profile --- withaeng-api/src/main/resources/application.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/withaeng-api/src/main/resources/application.yml b/withaeng-api/src/main/resources/application.yml index 35af6a4..f3288c0 100644 --- a/withaeng-api/src/main/resources/application.yml +++ b/withaeng-api/src/main/resources/application.yml @@ -1,6 +1,6 @@ spring: profiles: - default: local + default: dev config: import: - classpath:/application-domain.yml From ec16fdc3ebf0fe5fc6b76a98ead516e5999848a9 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Wed, 15 May 2024 02:18:52 +0900 Subject: [PATCH 081/174] Fix default jpa hibernate ddl-auto option --- withaeng-domain/src/main/resources/application-domain-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/withaeng-domain/src/main/resources/application-domain-dev.yml b/withaeng-domain/src/main/resources/application-domain-dev.yml index 41eac20..9d5fc86 100644 --- a/withaeng-domain/src/main/resources/application-domain-dev.yml +++ b/withaeng-domain/src/main/resources/application-domain-dev.yml @@ -4,7 +4,7 @@ spring: on-profile: dev jpa: hibernate: - ddl-auto: create + ddl-auto: none properties: hibernate: show_sql: false From 98177dd4f340409e83a4eb978f728c011a400930 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Tue, 28 May 2024 16:23:51 +0900 Subject: [PATCH 082/174] Add user columns --- .../withaeng/converter/TagIdsConverter.kt | 5 +-- .../converter/UserFoodRestrictionConverter.kt | 18 ++++++++ .../UserPreferTravelThemeConverter.kt | 18 ++++++++ .../com/travel/withaeng/domain/user/User.kt | 43 ++++++++++++++++--- .../withaeng/domain/user/UserConsumeStyle.kt | 5 +++ .../withaeng/domain/user/UserDrinkingType.kt | 5 +++ .../domain/user/UserFoodRestriction.kt | 6 +++ .../travel/withaeng/domain/user/UserMbti.kt | 6 +++ .../domain/user/UserPreferAccompanyGender.kt | 5 +++ .../domain/user/UserPreferTravelTheme.kt | 6 +++ .../domain/user/UserPreferTravelType.kt | 5 +++ .../withaeng/domain/user/UserSmokingType.kt | 5 +++ 12 files changed, 118 insertions(+), 9 deletions(-) create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserFoodRestrictionConverter.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserPreferTravelThemeConverter.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserConsumeStyle.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserDrinkingType.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserFoodRestriction.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserMbti.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserPreferAccompanyGender.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserPreferTravelTheme.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserPreferTravelType.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserSmokingType.kt diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/TagIdsConverter.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/TagIdsConverter.kt index 272039e..92a64ed 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/TagIdsConverter.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/TagIdsConverter.kt @@ -8,9 +8,8 @@ class TagIdsConverter : AttributeConverter, String> { } override fun convertToEntityAttribute(data: String): Set { - if (data.isBlank()) return setOf() - else return data.split(DELIMITER).map { it.toLong() }.toSet() - + return if (data.isBlank()) setOf() + else data.split(DELIMITER).map { it.toLong() }.toSet() } companion object { diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserFoodRestrictionConverter.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserFoodRestrictionConverter.kt new file mode 100644 index 0000000..d90a4be --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserFoodRestrictionConverter.kt @@ -0,0 +1,18 @@ +package com.travel.withaeng.converter + +import com.travel.withaeng.domain.user.UserFoodRestriction +import jakarta.persistence.AttributeConverter + +class UserFoodRestrictionConverter : AttributeConverter, String> { + override fun convertToDatabaseColumn(attribute: Set): String { + return attribute.joinToString(DELIMITER) + } + + override fun convertToEntityAttribute(data: String): Set { + return data.split(DELIMITER).map { UserFoodRestriction.valueOf(it.trim()) }.toSet() + } + + companion object { + private const val DELIMITER = "," + } +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserPreferTravelThemeConverter.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserPreferTravelThemeConverter.kt new file mode 100644 index 0000000..9153f53 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserPreferTravelThemeConverter.kt @@ -0,0 +1,18 @@ +package com.travel.withaeng.converter + +import com.travel.withaeng.domain.user.UserPreferTravelTheme +import jakarta.persistence.AttributeConverter + +class UserPreferTravelThemeConverter: AttributeConverter, String> { + override fun convertToDatabaseColumn(attribute: Set): String { + return attribute.joinToString(DELIMITER) { it.name } + } + + override fun convertToEntityAttribute(data: String): Set { + return data.split(DELIMITER).map { UserPreferTravelTheme.valueOf(it.trim()) }.toSet() + } + + companion object { + private const val DELIMITER = "," + } +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt index 3056b1d..8f52095 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt @@ -1,11 +1,10 @@ package com.travel.withaeng.domain.user +import com.travel.withaeng.converter.UserFoodRestrictionConverter +import com.travel.withaeng.converter.UserPreferTravelThemeConverter import com.travel.withaeng.converter.UserRoleConverter import com.travel.withaeng.domain.BaseEntity -import jakarta.persistence.Column -import jakarta.persistence.Convert -import jakarta.persistence.Entity -import jakarta.persistence.Table +import jakarta.persistence.* import java.time.LocalDate @Table(name = "users") @@ -26,12 +25,44 @@ class User( @Column(name = "is_male", nullable = false) val isMale: Boolean, - @Column(name = "profile_image_url") + @Column(name = "profile_image_url", nullable = true) val profileImageUrl: String? = null, - @Column(name = "bio") + @Column(name = "bio", nullable = true) val bio: String? = null, + @Enumerated(EnumType.STRING) + @Column(name = "mbti", nullable = true) + val mbti: UserMbti? = null, + + @Enumerated(EnumType.STRING) + @Column(name = "prefer_travel_type", nullable = true) + val preferTravelType: UserPreferTravelType? = null, + + @Convert(converter = UserPreferTravelThemeConverter::class) + @Column(name = "prefer_travel_theme", nullable = false) + val preferTravelThemes: List = emptyList(), + + @Enumerated(EnumType.STRING) + @Column(name = "consume_style", nullable = true) + val consumeStyle: UserConsumeStyle? = null, + + @Convert(converter = UserFoodRestrictionConverter::class) + @Column(name = "food_restriction", nullable = false) + val foodRestrictions: List = emptyList(), + + @Enumerated(EnumType.STRING) + @Column(name = "prefer_accompany_gender", nullable = true) + val preferAccompanyGender: UserPreferAccompanyGender? = null, + + @Enumerated(EnumType.STRING) + @Column(name = "smoking_type", nullable = true) + val smockingType: UserSmokingType? = null, + + @Enumerated(EnumType.STRING) + @Column(name = "drinking_type", nullable = true) + val drinkingType: UserDrinkingType? = null, + @Convert(converter = UserRoleConverter::class) @Column(name = "roles") var roles: Set, diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserConsumeStyle.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserConsumeStyle.kt new file mode 100644 index 0000000..f89837c --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserConsumeStyle.kt @@ -0,0 +1,5 @@ +package com.travel.withaeng.domain.user + +enum class UserConsumeStyle { + BUDGET_FRIENDLY, SPLURGE, LUXURY +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserDrinkingType.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserDrinkingType.kt new file mode 100644 index 0000000..5c9222b --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserDrinkingType.kt @@ -0,0 +1,5 @@ +package com.travel.withaeng.domain.user + +enum class UserDrinkingType { + FREQUENT_DRINKER, OCCASIONAL_DRINKER, ABSTAINER, NON_DRINKER +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserFoodRestriction.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserFoodRestriction.kt new file mode 100644 index 0000000..23db736 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserFoodRestriction.kt @@ -0,0 +1,6 @@ +package com.travel.withaeng.domain.user + +enum class UserFoodRestriction { + SHELLFISH, SEAFOOD, SPICY_FOOD, MEAT, STRONGLY_FLAVORED, + DAIRY, RAW_FOOD, GREASY_FOOD, NOODLES, GLUTEN, CARBONATED_DRINKS +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserMbti.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserMbti.kt new file mode 100644 index 0000000..1e94e34 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserMbti.kt @@ -0,0 +1,6 @@ +package com.travel.withaeng.domain.user + +enum class UserMbti { + ISTJ, ISTP, ISFJ, ISFP, INFJ, INTP, INFP, INTJ, + ESTJ, ESTP, ESFJ, ESFP, ENFJ, ENTP, ENFP, ENTJ +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserPreferAccompanyGender.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserPreferAccompanyGender.kt new file mode 100644 index 0000000..24f781a --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserPreferAccompanyGender.kt @@ -0,0 +1,5 @@ +package com.travel.withaeng.domain.user + +enum class UserPreferAccompanyGender { + MALE, FEMALE, NO_PREFERENCE +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserPreferTravelTheme.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserPreferTravelTheme.kt new file mode 100644 index 0000000..140a481 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserPreferTravelTheme.kt @@ -0,0 +1,6 @@ +package com.travel.withaeng.domain.user + +enum class UserPreferTravelTheme { + PICTURE, FOOD, TOURIST_ATTRACTION, NATURE, CAFE, MUSEUM, + EXHIBITION_HALL, ART_MUSEUM, LOCAL_FESTIVAL, HOTEL_VACATION +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserPreferTravelType.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserPreferTravelType.kt new file mode 100644 index 0000000..ef8b8c8 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserPreferTravelType.kt @@ -0,0 +1,5 @@ +package com.travel.withaeng.domain.user + +enum class UserPreferTravelType { + DOMESTIC, INTERNATIONAL +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserSmokingType.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserSmokingType.kt new file mode 100644 index 0000000..b71903a --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserSmokingType.kt @@ -0,0 +1,5 @@ +package com.travel.withaeng.domain.user + +enum class UserSmokingType { + FREQUENT_SMOKER, OCCASIONAL_SMOKER, QUITTING_SMOKER, NON_SMOKER +} \ No newline at end of file From 270bce9d97d537a10d9860c72a42e0a11d237551 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Thu, 30 May 2024 20:28:58 +0900 Subject: [PATCH 083/174] Implement searching accompany replies with paging API --- gradle.properties | 1 + .../AccompanyReplyApplicationService.kt | 16 ++++---- .../dto/AccompanyReplyResponseDto.kt | 11 ++++++ .../common/PagingResponse.kt | 20 ++++++++++ .../com/travel/withaeng/common/ApiResponse.kt | 10 ++++- .../AccompanyReplyController.kt | 10 +++-- withaeng-domain/build.gradle.kts | 5 ++- .../accompanyreply/AccompanyReplyDto.kt | 4 +- .../AccompanyReplyRepository.kt | 4 +- .../AccompanyReplyRepositoryCustom.kt | 8 ++++ .../AccompanyReplyRepositoryImpl.kt | 39 +++++++++++++++++++ .../accompanyreply/AccompanyReplyService.kt | 7 ++-- 12 files changed, 115 insertions(+), 20 deletions(-) create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/common/PagingResponse.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustom.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryImpl.kt diff --git a/gradle.properties b/gradle.properties index adf22ee..3fa1429 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,6 +13,7 @@ springMockkVersion=3.1.1 jasyptVersion=3.0.5 ### Persistence versions ### mysqlVersion=8.3.0 +queryDslVersion=5.1.0:jakarta ### jjwt version jjwtVersion=0.11.5 ### Swagger Version diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt index c0b8ab7..4dbe082 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt @@ -1,13 +1,13 @@ package com.travel.withaeng.applicationservice.accompanyreply -import com.travel.withaeng.applicationservice.accompanyreply.dto.AccompanyReplyResponse -import com.travel.withaeng.applicationservice.accompanyreply.dto.CreateAccompanyReplyServiceRequest -import com.travel.withaeng.applicationservice.accompanyreply.dto.UpdateAccompanyReplyServiceRequest -import com.travel.withaeng.applicationservice.accompanyreply.dto.toResponse +import com.travel.withaeng.applicationservice.accompanyreply.dto.* +import com.travel.withaeng.applicationservice.common.PagingResponse +import com.travel.withaeng.applicationservice.common.toPaging import com.travel.withaeng.common.exception.WithaengException import com.travel.withaeng.common.exception.WithaengExceptionType import com.travel.withaeng.domain.accompanyreply.AccompanyReplyService import com.travel.withaeng.domain.accompanyreplylike.AccompanyReplyLikeService +import org.springframework.data.domain.Pageable import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -34,13 +34,15 @@ class AccompanyReplyApplicationService( return accompanyReplyDto.toResponse(likeCount) } - fun findAll(accompanyId: Long): List { - val accompanyReplyDtoList = accompanyReplyService.findAllByAccompanyId(accompanyId) + fun search(accompanyId: Long, pageable: Pageable): PagingResponse> { + val accompanyReplyPage = accompanyReplyService.search(accompanyId, pageable) + val contents = accompanyReplyPage.content // TODO: Fix getting like count logic for using bulk from single - return accompanyReplyDtoList.map { replyDto -> + val accompanyReplyResponseList = contents.map { replyDto -> val likeCount = accompanyReplyLikeService.countAccompanyReplyLikeCount(replyDto.id) replyDto.toResponse(likeCount) } + return PagingAccompanyReplyResponse(accompanyReplyResponseList, accompanyReplyPage.toPaging()) } @Transactional diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt index 93ea294..db03137 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt @@ -1,5 +1,7 @@ package com.travel.withaeng.applicationservice.accompanyreply.dto +import com.travel.withaeng.applicationservice.common.Paging +import com.travel.withaeng.applicationservice.common.PagingResponse import com.travel.withaeng.domain.accompanyreply.AccompanyReplyDto data class AccompanyReplyResponse( @@ -11,6 +13,15 @@ data class AccompanyReplyResponse( val likeCount: Long = 0L ) +class PagingAccompanyReplyResponse( + private val content: List, + private val paging: Paging +) : PagingResponse> { + override fun getPaging(): Paging = paging + + override fun getContent(): List = content +} + fun AccompanyReplyDto.toResponse(likeCount: Long = 0L): AccompanyReplyResponse { return AccompanyReplyResponse( id = id, diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/common/PagingResponse.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/common/PagingResponse.kt new file mode 100644 index 0000000..79cb3dd --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/common/PagingResponse.kt @@ -0,0 +1,20 @@ +package com.travel.withaeng.applicationservice.common + +import org.springframework.data.domain.Page + +data class Paging( + val totalCount: Long, + val page: Int, + val offset: Long +) + +fun Page<*>.toPaging(): Paging = Paging( + totalCount = totalElements, + page = pageable.pageNumber, + offset = pageable.offset +) + +interface PagingResponse { + fun getPaging(): Paging + fun getContent(): T +} \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ApiResponse.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ApiResponse.kt index 60d91a9..37841cc 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ApiResponse.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ApiResponse.kt @@ -1,13 +1,17 @@ package com.travel.withaeng.common +import com.travel.withaeng.applicationservice.common.Paging +import com.travel.withaeng.applicationservice.common.PagingResponse import com.travel.withaeng.common.exception.WithaengExceptionType data class ApiResponse( val success: Boolean = true, val data: T? = null, - val error: ApiErrorResponse? = null + val error: ApiErrorResponse? = null, + val paging: Paging? = null ) { companion object { + fun success(): ApiResponse { return ApiResponse(success = true, data = null) } @@ -16,6 +20,10 @@ data class ApiResponse( return ApiResponse(success = true, data = data) } + fun success(data: PagingResponse): ApiResponse { + return ApiResponse(success = true, data = data.getContent(), paging = data.getPaging()) + } + fun fail( exceptionType: WithaengExceptionType, message: String? diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt index ca3f1a4..5ee6242 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt @@ -11,6 +11,7 @@ import com.travel.withaeng.security.resolver.GetAuth import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.security.SecurityRequirement import io.swagger.v3.oas.annotations.tags.Tag +import org.springframework.data.domain.Pageable import org.springframework.http.HttpStatus import org.springframework.web.bind.annotation.* @@ -66,10 +67,13 @@ class AccompanyReplyController(private val accompanyReplyApplicationService: Acc } @Operation(summary = "Retrieve All Accompany Replies API", description = "동행 댓글 조회 API") - @GetMapping("/{accompanyId}/reply/all") - fun findAll(@PathVariable(name = "accompanyId") accompanyId: Long): ApiResponse> { + @GetMapping("/{accompanyId}/reply/search") + fun search( + @PathVariable(name = "accompanyId") accompanyId: Long, + pageable: Pageable + ): ApiResponse> { return ApiResponse.success( - accompanyReplyApplicationService.findAll(accompanyId = accompanyId) + accompanyReplyApplicationService.search(accompanyId = accompanyId, pageable = pageable) ) } diff --git a/withaeng-domain/build.gradle.kts b/withaeng-domain/build.gradle.kts index 2b47018..cee68b8 100644 --- a/withaeng-domain/build.gradle.kts +++ b/withaeng-domain/build.gradle.kts @@ -6,14 +6,15 @@ allOpen { val jasyptVersion: String by project.extra val mysqlVersion: String by project.extra +val queryDslVersion: String by project.extra dependencies { implementation(project(":withaeng-common")) implementation("org.springframework.boot:spring-boot-starter-data-jpa") implementation("org.springframework.boot:spring-boot-starter-validation") // Query DSL - implementation("com.querydsl:querydsl-jpa:5.0.0:jakarta") - kapt("com.querydsl:querydsl-apt:5.0.0:jakarta") + implementation("com.querydsl:querydsl-jpa:$queryDslVersion") + kapt("com.querydsl:querydsl-apt:$queryDslVersion") kapt("org.springframework.boot:spring-boot-configuration-processor") runtimeOnly("com.mysql:mysql-connector-j:$mysqlVersion") diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt index 1a1c4d8..417a55e 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt @@ -1,6 +1,8 @@ package com.travel.withaeng.domain.accompanyreply -data class AccompanyReplyDto( +import com.querydsl.core.annotations.QueryProjection + +data class AccompanyReplyDto @QueryProjection constructor( val id: Long, val userId: Long, val accompanyId: Long, diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt index 4341eb5..e7479cd 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt @@ -2,6 +2,4 @@ package com.travel.withaeng.domain.accompanyreply import org.springframework.data.jpa.repository.JpaRepository -interface AccompanyReplyRepository : JpaRepository { - fun findAllByAccompanyId(accompanyId: Long): List -} \ No newline at end of file +interface AccompanyReplyRepository : JpaRepository, AccompanyReplyRepositoryCustom \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustom.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustom.kt new file mode 100644 index 0000000..0566d43 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustom.kt @@ -0,0 +1,8 @@ +package com.travel.withaeng.domain.accompanyreply + +import org.springframework.data.domain.Page +import org.springframework.data.domain.Pageable + +interface AccompanyReplyRepositoryCustom { + fun search(accompanyId: Long, pageable: Pageable): Page +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryImpl.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryImpl.kt new file mode 100644 index 0000000..ad8b127 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryImpl.kt @@ -0,0 +1,39 @@ +package com.travel.withaeng.domain.accompanyreply + +import com.querydsl.core.types.dsl.BooleanExpression +import com.querydsl.jpa.impl.JPAQueryFactory +import com.travel.withaeng.domain.accompanyreply.QAccompanyReply.accompanyReply +import org.springframework.data.domain.Page +import org.springframework.data.domain.Pageable +import org.springframework.data.support.PageableExecutionUtils + +class AccompanyReplyRepositoryImpl( + private val queryFactory: JPAQueryFactory +) : AccompanyReplyRepositoryCustom { + override fun search(accompanyId: Long, pageable: Pageable): Page { + val contents = queryFactory + .select( + QAccompanyReplyDto( + accompanyReply.id, + accompanyReply.userId, + accompanyReply.accompanyId, + accompanyReply.parentId, + accompanyReply.content + ) + ) + .from(accompanyReply) + .where(accompanyIdEq(accompanyId)) + .fetch() + + val countQuery = queryFactory + .select(accompanyReply.count()) + .from(accompanyReply) + .where(accompanyIdEq(accompanyId)) + + return PageableExecutionUtils.getPage(contents, pageable) { countQuery.fetchOne() ?: 0L } + } + + private fun accompanyIdEq(accompanyId: Long): BooleanExpression? { + return accompanyReply.accompanyId.eq(accompanyId) + } +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt index 1daa554..2686a03 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt @@ -4,6 +4,8 @@ import com.travel.withaeng.common.exception.WithaengException import com.travel.withaeng.common.exception.WithaengExceptionType import com.travel.withaeng.domain.accompany.AccompanyRepository import com.travel.withaeng.domain.user.UserRepository +import org.springframework.data.domain.Page +import org.springframework.data.domain.Pageable import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -50,9 +52,8 @@ class AccompanyReplyService( return accompanyReply.toDto() } - fun findAllByAccompanyId(accompanyId: Long): List { - return accompanyReplyRepository.findAllByAccompanyId(accompanyId) - .map { it.toDto() } + fun search(accompanyId: Long, pageable: Pageable): Page { + return accompanyReplyRepository.search(accompanyId, pageable) } @Transactional From 6a498a2f0b41bb44e0d658ea9d2ec61b9216970b Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Thu, 13 Jun 2024 16:45:15 +0900 Subject: [PATCH 084/174] Fix user columns' converters --- .../withaeng/converter/UserFoodRestrictionConverter.kt | 5 +++-- .../withaeng/converter/UserPreferTravelThemeConverter.kt | 5 +++-- .../com/travel/withaeng/converter/UserRoleConverter.kt | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserFoodRestrictionConverter.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserFoodRestrictionConverter.kt index d90a4be..38ee0aa 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserFoodRestrictionConverter.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserFoodRestrictionConverter.kt @@ -9,10 +9,11 @@ class UserFoodRestrictionConverter : AttributeConverter } override fun convertToEntityAttribute(data: String): Set { - return data.split(DELIMITER).map { UserFoodRestriction.valueOf(it.trim()) }.toSet() + return if (data.isBlank()) emptySet() + else data.split(DELIMITER).map { UserFoodRestriction.valueOf(it.trim()) }.toSet() } companion object { private const val DELIMITER = "," } -} \ No newline at end of file +} diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserPreferTravelThemeConverter.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserPreferTravelThemeConverter.kt index 9153f53..cf342d8 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserPreferTravelThemeConverter.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserPreferTravelThemeConverter.kt @@ -9,10 +9,11 @@ class UserPreferTravelThemeConverter: AttributeConverter { - return data.split(DELIMITER).map { UserPreferTravelTheme.valueOf(it.trim()) }.toSet() + return if (data.isBlank()) return emptySet() + else data.split(DELIMITER).map { UserPreferTravelTheme.valueOf(it.trim()) }.toSet() } companion object { private const val DELIMITER = "," } -} \ No newline at end of file +} diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserRoleConverter.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserRoleConverter.kt index 4d9b416..6bbb507 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserRoleConverter.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserRoleConverter.kt @@ -9,10 +9,11 @@ class UserRoleConverter : AttributeConverter, String> { } override fun convertToEntityAttribute(data: String): Set { - return data.split(DELIMITER).map { UserRole.valueOf(it.trim()) }.toSet() + return if (data.isBlank()) return emptySet() + else data.split(DELIMITER).map { UserRole.valueOf(it.trim()) }.toSet() } companion object { private const val DELIMITER = "," } -} \ No newline at end of file +} From 4a33298b3e1322a842914277efd5eebe628584ec Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Thu, 13 Jun 2024 16:47:00 +0900 Subject: [PATCH 085/174] Add custom module of Jackson for adding user column's enum class into DTO --- .../travel/withaeng/config/JacksonConfig.kt | 14 +++++++++-- .../com/travel/withaeng/jackson/EnumModule.kt | 24 +++++++++++++++++++ .../deserializer/SimpleEnumDeserializer.kt | 15 ++++++++++++ 3 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/jackson/EnumModule.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/jackson/deserializer/SimpleEnumDeserializer.kt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/JacksonConfig.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/config/JacksonConfig.kt index f51de48..45a47dd 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/JacksonConfig.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/config/JacksonConfig.kt @@ -1,10 +1,13 @@ package com.travel.withaeng.config import com.fasterxml.jackson.databind.DeserializationFeature +import com.fasterxml.jackson.databind.Module import com.fasterxml.jackson.databind.SerializationFeature import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer +import com.travel.withaeng.jackson.EnumModule +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder @@ -16,12 +19,19 @@ import java.time.format.DateTimeFormatter @Configuration class JacksonConfig { @Bean - fun jackson2ObjectMapperBuilder(): Jackson2ObjectMapperBuilder { - return Jackson2ObjectMapperBuilder() + fun jackson2ObjectMapperBuilder(customizers: List): Jackson2ObjectMapperBuilder { + val builder = Jackson2ObjectMapperBuilder() .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) .featuresToDisable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) .serializerByType(LocalDateTime::class.java, LocalDateTimeSerializer(DateTimeFormatter.ISO_LOCAL_DATE_TIME)) .serializerByType(LocalDate::class.java, LocalDateSerializer(DateTimeFormatter.ISO_LOCAL_DATE)) .serializerByType(LocalTime::class.java, LocalTimeSerializer(DateTimeFormatter.ISO_LOCAL_TIME)) + customizers.forEach { customizer -> customizer.customize(builder) } + return builder + } + + @Bean + fun enumModule(): Module { + return EnumModule() } } \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/jackson/EnumModule.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/jackson/EnumModule.kt new file mode 100644 index 0000000..c36061b --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/jackson/EnumModule.kt @@ -0,0 +1,24 @@ +package com.travel.withaeng.jackson + +import com.fasterxml.jackson.databind.module.SimpleModule +import com.travel.withaeng.domain.user.* +import com.travel.withaeng.jackson.deserializer.SimpleEnumDeserializer + +class EnumModule : SimpleModule() { + + init { + // User + addSimpleEnumDeserializer() + addSimpleEnumDeserializer() + addSimpleEnumDeserializer() + addSimpleEnumDeserializer() + addSimpleEnumDeserializer() + addSimpleEnumDeserializer() + addSimpleEnumDeserializer() + addSimpleEnumDeserializer() + } + + private inline fun > addSimpleEnumDeserializer() { + addDeserializer(T::class.java, object: SimpleEnumDeserializer(T::class.java){}) + } +} diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/jackson/deserializer/SimpleEnumDeserializer.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/jackson/deserializer/SimpleEnumDeserializer.kt new file mode 100644 index 0000000..b1f8a1c --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/jackson/deserializer/SimpleEnumDeserializer.kt @@ -0,0 +1,15 @@ +package com.travel.withaeng.jackson.deserializer + +import com.fasterxml.jackson.core.JsonParser +import com.fasterxml.jackson.databind.DeserializationContext +import com.fasterxml.jackson.databind.JsonDeserializer + +open class SimpleEnumDeserializer>( + private val enumType: Class +) : JsonDeserializer(){ + + override fun deserialize(parser: JsonParser, ctxt: DeserializationContext): T { + val node = parser.text + return java.lang.Enum.valueOf(enumType, node.uppercase()) + } +} \ No newline at end of file From 22cff054e3173f70fba2519e9f5660fd152fe683 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Thu, 13 Jun 2024 16:47:35 +0900 Subject: [PATCH 086/174] Implement adding user details into User domain service --- .../auth/AuthApplicationService.kt | 8 +- .../security/authentication/UserInfo.kt | 4 +- .../com/travel/withaeng/domain/user/User.kt | 22 ++--- .../travel/withaeng/domain/user/UserDto.kt | 34 -------- .../withaeng/domain/user/UserService.kt | 39 ++++++--- .../withaeng/domain/user/UserSimpleDto.kt | 86 +++++++++++++++++++ 6 files changed, 132 insertions(+), 61 deletions(-) delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserDto.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserSimpleDto.kt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt index 3413ede..634fed1 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt @@ -7,9 +7,9 @@ import com.travel.withaeng.applicationservice.auth.dto.ValidateEmailServiceReque import com.travel.withaeng.common.exception.WithaengException import com.travel.withaeng.common.exception.WithaengExceptionType import com.travel.withaeng.domain.user.CreateUserDto -import com.travel.withaeng.domain.user.UserDto import com.travel.withaeng.domain.user.UserRole import com.travel.withaeng.domain.user.UserService +import com.travel.withaeng.domain.user.UserSimpleDto import com.travel.withaeng.domain.validateemail.ValidatingEmailService import com.travel.withaeng.security.authentication.UserInfo import com.travel.withaeng.security.jwt.JwtAgent @@ -41,7 +41,7 @@ class AuthApplicationService( userService.deleteByEmail(userEmail) validatingEmailService.deleteAllByUserId(userDto.id) } - val newUserDto = userService.createUser(request.toCreateUserDto()) + val newUserDto = userService.create(request.toCreateUserDto()) validatingEmailService.create(newUserDto.email, newUserDto.id, UUID.randomUUID().toString()) return UserResponse(newUserDto.id, newUserDto.email, jwtAgent.provide(UserInfo.from(newUserDto))) } @@ -79,7 +79,7 @@ class AuthApplicationService( userService.grantUserRole(userDto.id) } - private fun UserDto.isValidUser(): Boolean { + private fun UserSimpleDto.isValidUser(): Boolean { return roles.any { it == UserRole.USER } } @@ -95,4 +95,4 @@ class AuthApplicationService( birth = birth, isMale = isMale ) -} \ No newline at end of file +} diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/authentication/UserInfo.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/authentication/UserInfo.kt index 6998a8a..89ad30b 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/authentication/UserInfo.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/authentication/UserInfo.kt @@ -1,7 +1,7 @@ package com.travel.withaeng.security.authentication -import com.travel.withaeng.domain.user.UserDto import com.travel.withaeng.domain.user.UserRole +import com.travel.withaeng.domain.user.UserSimpleDto data class UserInfo( val id: Long, @@ -9,7 +9,7 @@ data class UserInfo( val roles: Set, ) { companion object { - fun from(user: UserDto): UserInfo { + fun from(user: UserSimpleDto): UserInfo { return UserInfo( id = user.id, email = user.email, diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt index 8f52095..b4fb0c1 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt @@ -26,42 +26,42 @@ class User( val isMale: Boolean, @Column(name = "profile_image_url", nullable = true) - val profileImageUrl: String? = null, + var profileImageUrl: String? = null, @Column(name = "bio", nullable = true) - val bio: String? = null, + var bio: String? = null, @Enumerated(EnumType.STRING) @Column(name = "mbti", nullable = true) - val mbti: UserMbti? = null, + var mbti: UserMbti? = null, @Enumerated(EnumType.STRING) @Column(name = "prefer_travel_type", nullable = true) - val preferTravelType: UserPreferTravelType? = null, + var preferTravelType: UserPreferTravelType? = null, @Convert(converter = UserPreferTravelThemeConverter::class) @Column(name = "prefer_travel_theme", nullable = false) - val preferTravelThemes: List = emptyList(), + var preferTravelThemes: Set = emptySet(), @Enumerated(EnumType.STRING) @Column(name = "consume_style", nullable = true) - val consumeStyle: UserConsumeStyle? = null, + var consumeStyle: UserConsumeStyle? = null, @Convert(converter = UserFoodRestrictionConverter::class) @Column(name = "food_restriction", nullable = false) - val foodRestrictions: List = emptyList(), + var foodRestrictions: Set = emptySet(), @Enumerated(EnumType.STRING) @Column(name = "prefer_accompany_gender", nullable = true) - val preferAccompanyGender: UserPreferAccompanyGender? = null, + var preferAccompanyGender: UserPreferAccompanyGender? = null, @Enumerated(EnumType.STRING) @Column(name = "smoking_type", nullable = true) - val smockingType: UserSmokingType? = null, + var smokingType: UserSmokingType? = null, @Enumerated(EnumType.STRING) @Column(name = "drinking_type", nullable = true) - val drinkingType: UserDrinkingType? = null, + var drinkingType: UserDrinkingType? = null, @Convert(converter = UserRoleConverter::class) @Column(name = "roles") @@ -85,4 +85,4 @@ class User( ) } } -} \ No newline at end of file +} diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserDto.kt deleted file mode 100644 index 8bfe5cb..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserDto.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.travel.withaeng.domain.user - -import java.time.LocalDate - -data class UserDto( - val id: Long, - val email: String, - val password: String, - val nickname: String? = null, - val birth: LocalDate? = null, - val isMale: Boolean? = null, - val profileImageUrl: String? = null, - val bio: String? = null, - val roles: Set -) - -fun User.toDto(): UserDto = UserDto( - id = id, - email = email, - password = password, - nickname = nickname, - birth = birth, - isMale = isMale, - profileImageUrl = profileImageUrl, - bio = bio, - roles = roles -) - -data class CreateUserDto( - val email: String, - val password: String, - val birth: LocalDate, - val isMale: Boolean -) \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt index 0d11560..b0cde5d 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt @@ -11,7 +11,7 @@ import org.springframework.transaction.annotation.Transactional class UserService(private val userRepository: UserRepository) { @Transactional - fun createUser(createUserDto: CreateUserDto): UserDto { + fun create(createUserDto: CreateUserDto): UserSimpleDto { return userRepository.save( User.create( email = createUserDto.email, @@ -19,18 +19,29 @@ class UserService(private val userRepository: UserRepository) { birth = createUserDto.birth, isMale = createUserDto.isMale ) - ).toDto() + ).toSimpleDto() } - fun findById(id: Long): UserDto { - return userRepository.findByIdOrNull(id)?.toDto() ?: throw WithaengException.of( - type = WithaengExceptionType.NOT_EXIST, - message = "해당하는 유저를 찾을 수 없습니다." - ) + fun findById(id: Long): UserSimpleDto { + return userRepository.findByIdOrNull(id).getOrThrow().toSimpleDto() } - fun findByEmailOrNull(email: String): UserDto? { - return userRepository.findByEmail(email)?.toDto() + fun findByEmailOrNull(email: String): UserSimpleDto? { + return userRepository.findByEmail(email)?.toSimpleDto() + } + + @Transactional + fun addDetails(userId: Long, addDetailsUserDto: AddDetailsUserDto): UserDetailsDto { + val user = userRepository.findByIdOrNull(userId).getOrThrow() + addDetailsUserDto.mbti?.let { user.mbti = it } + addDetailsUserDto.preferTravelType?.let { user.preferTravelType = it } + addDetailsUserDto.preferTravelThemes?.let { user.preferTravelThemes = it.toSet() } + addDetailsUserDto.consumeStyle?.let { user.consumeStyle = it } + addDetailsUserDto.foodRestrictions?.let { user.foodRestrictions = it.toSet() } + addDetailsUserDto.preferAccompanyGender?.let { user.preferAccompanyGender = it } + addDetailsUserDto.smokingType?.let { user.smokingType = it } + addDetailsUserDto.drinkingType?.let { user.drinkingType = it } + return user.toDetailsDto() } @Transactional @@ -45,4 +56,12 @@ class UserService(private val userRepository: UserRepository) { fun deleteByEmail(email: String) { return userRepository.deleteByEmail(email) } -} \ No newline at end of file + + private fun User?.getOrThrow(): User { + this ?: throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = "해당하는 유저를 찾을 수 없습니다." + ) + return this + } +} diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserSimpleDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserSimpleDto.kt new file mode 100644 index 0000000..f590107 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserSimpleDto.kt @@ -0,0 +1,86 @@ +package com.travel.withaeng.domain.user + +import java.time.LocalDate + +data class UserSimpleDto( + val id: Long, + val email: String, + val password: String, + val nickname: String? = null, + val birth: LocalDate, + val isMale: Boolean, + val profileImageUrl: String? = null, + val bio: String? = null, + val roles: Set +) + +data class UserDetailsDto( + val id: Long, + val email: String, + val password: String, + val nickname: String? = null, + val birth: LocalDate, + val isMale: Boolean, + val profileImageUrl: String? = null, + val bio: String? = null, + val mbti: UserMbti? = null, + val preferTravelType: UserPreferTravelType? = null, + val preferTravelThemes: Set = emptySet(), + val consumeStyle: UserConsumeStyle? = null, + val foodRestrictions: Set = emptySet(), + val preferAccompanyGender: UserPreferAccompanyGender? = null, + val smokingType: UserSmokingType? = null, + val drinkingType: UserDrinkingType? = null, + val roles: Set +) + +fun User.toSimpleDto(): UserSimpleDto = UserSimpleDto( + id = id, + email = email, + password = password, + nickname = nickname, + birth = birth, + isMale = isMale, + profileImageUrl = profileImageUrl, + bio = bio, + roles = roles +) + +fun User.toDetailsDto(): UserDetailsDto = UserDetailsDto( + id = id, + email = email, + password = password, + nickname = nickname, + birth = birth, + isMale = isMale, + profileImageUrl = profileImageUrl, + bio = bio, + mbti = mbti, + preferTravelType = preferTravelType, + preferTravelThemes = preferTravelThemes, + consumeStyle = consumeStyle, + foodRestrictions = foodRestrictions, + preferAccompanyGender = preferAccompanyGender, + smokingType = smokingType, + drinkingType = drinkingType, + roles = roles +) + +data class CreateUserDto( + val email: String, + val password: String, + val birth: LocalDate, + val isMale: Boolean +) + +data class AddDetailsUserDto( + val nickname: String? = null, + val mbti: UserMbti? = null, + val preferTravelType: UserPreferTravelType? = null, + val preferTravelThemes: List? = null, + val consumeStyle: UserConsumeStyle? = null, + val foodRestrictions: List? = null, + val preferAccompanyGender: UserPreferAccompanyGender? = null, + val smokingType: UserSmokingType? = null, + val drinkingType: UserDrinkingType? = null +) From d644802e13fa5c5a159efb8e3a4b101403d5d919 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Thu, 13 Jun 2024 16:47:43 +0900 Subject: [PATCH 087/174] Implement adding user details api --- .../user/UserApplicationService.kt | 21 ++++++++ .../user/dto/UserResponseDto.kt | 41 ++++++++++++++++ .../user/dto/UserServiceRequestDto.kt | 28 +++++++++++ .../controller/auth/AuthController.kt | 2 +- .../controller/user/UserController.kt | 39 +++++++++++++++ .../controller/user/dto/UserRequestDto.kt | 49 +++++++++++++++++++ 6 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/UserApplicationService.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/dto/UserResponseDto.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/dto/UserServiceRequestDto.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/controller/user/UserController.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/controller/user/dto/UserRequestDto.kt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/UserApplicationService.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/UserApplicationService.kt new file mode 100644 index 0000000..9566a06 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/UserApplicationService.kt @@ -0,0 +1,21 @@ +package com.travel.withaeng.applicationservice.user + +import com.travel.withaeng.applicationservice.user.dto.AddUserDetailsServerRequest +import com.travel.withaeng.applicationservice.user.dto.UserDetailsResponse +import com.travel.withaeng.applicationservice.user.dto.toDomainDto +import com.travel.withaeng.domain.user.UserService +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional + +@Transactional(readOnly = true) +@Service +class UserApplicationService(private val userService: UserService) { + + @Transactional + fun addDetails(addUserDetailsServerRequest: AddUserDetailsServerRequest): UserDetailsResponse { + val userId = addUserDetailsServerRequest.userId + val userDetailsDto = userService.addDetails(userId, addUserDetailsServerRequest.toDomainDto()) + return UserDetailsResponse.from(userDetailsDto) + } + +} diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/dto/UserResponseDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/dto/UserResponseDto.kt new file mode 100644 index 0000000..66a768f --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/dto/UserResponseDto.kt @@ -0,0 +1,41 @@ +package com.travel.withaeng.applicationservice.user.dto + +import com.travel.withaeng.domain.user.* +import java.time.LocalDate + +data class UserDetailsResponse( + val id: Long, + val email: String, + val nickname: String? = null, + val isMale: Boolean, + val birth: LocalDate, + val mbti: UserMbti? = null, + val preferTravelType: UserPreferTravelType? = null, + val preferTravelThemes: Set = emptySet(), + val consumeStyle: UserConsumeStyle? = null, + val foodRestrictions: Set = emptySet(), + val preferAccompanyGender: UserPreferAccompanyGender? = null, + val smokingType: UserSmokingType? = null, + val drinkingType: UserDrinkingType? = null +) { + companion object { + fun from(userDetailsDto: UserDetailsDto): UserDetailsResponse { + return UserDetailsResponse( + id = userDetailsDto.id, + email = userDetailsDto.email, + nickname = userDetailsDto.nickname, + isMale = userDetailsDto.isMale, + birth = userDetailsDto.birth, + mbti = userDetailsDto.mbti, + preferTravelType = userDetailsDto.preferTravelType, + preferTravelThemes = userDetailsDto.preferTravelThemes, + consumeStyle = userDetailsDto.consumeStyle, + foodRestrictions = userDetailsDto.foodRestrictions, + preferAccompanyGender = userDetailsDto.preferAccompanyGender, + smokingType = userDetailsDto.smokingType, + drinkingType = userDetailsDto.drinkingType + ) + } + } +} + diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/dto/UserServiceRequestDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/dto/UserServiceRequestDto.kt new file mode 100644 index 0000000..9559d43 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/dto/UserServiceRequestDto.kt @@ -0,0 +1,28 @@ +package com.travel.withaeng.applicationservice.user.dto + +import com.travel.withaeng.domain.user.* + +data class AddUserDetailsServerRequest ( + val userId: Long, + val nickname: String? = null, + val mbti: UserMbti? = null, + val preferTravelType: UserPreferTravelType? = null, + val preferTravelThemes: List? = null, + val consumeStyle: UserConsumeStyle? = null, + val foodRestrictions: List? = null, + val preferAccompanyGender: UserPreferAccompanyGender? = null, + val smokingType: UserSmokingType? = null, + val drinkingType: UserDrinkingType? = null +) + +fun AddUserDetailsServerRequest.toDomainDto(): AddDetailsUserDto = AddDetailsUserDto( + nickname = nickname, + mbti = mbti, + preferTravelType = preferTravelType, + preferTravelThemes = preferTravelThemes, + consumeStyle = consumeStyle, + foodRestrictions = foodRestrictions, + preferAccompanyGender = preferAccompanyGender, + smokingType = smokingType, + drinkingType = drinkingType +) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt index b572d6f..4128f5a 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt @@ -13,7 +13,7 @@ import org.springframework.web.bind.annotation.* @Tag(name = "Auth", description = "인증 API") @RestController -@RequestMapping("api/v1/auth") +@RequestMapping("/api/v1/auth") class AuthController(private val authApplicationService: AuthApplicationService) { @Operation(summary = "Sign Up API", description = "회원가입 API") diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/user/UserController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/user/UserController.kt new file mode 100644 index 0000000..948043f --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/user/UserController.kt @@ -0,0 +1,39 @@ +package com.travel.withaeng.controller.user + +import com.travel.withaeng.applicationservice.user.UserApplicationService +import com.travel.withaeng.applicationservice.user.dto.UserDetailsResponse +import com.travel.withaeng.common.ApiResponse +import com.travel.withaeng.controller.user.dto.AddUserDetailsRequest +import com.travel.withaeng.controller.user.dto.toServiceRequest +import com.travel.withaeng.security.authentication.UserInfo +import com.travel.withaeng.security.resolver.GetAuth +import io.swagger.v3.oas.annotations.Operation +import io.swagger.v3.oas.annotations.security.SecurityRequirement +import io.swagger.v3.oas.annotations.tags.Tag +import jakarta.validation.Valid +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController + +@Tag(name = "User", description = "유저 정보 관리 API") +@RestController +@RequestMapping("/api/v1/user") +class UserController(private val userApplicationService: UserApplicationService) { + + @Operation( + summary = "Add Details", + description = "유저 관련 정보 수정 API", + security = [SecurityRequirement(name = "Authorization")] + ) + @PostMapping("/add-details") + fun addDetails( + @GetAuth userInfo: UserInfo, + @RequestBody @Valid request: AddUserDetailsRequest + ): ApiResponse { + return ApiResponse.success( + userApplicationService.addDetails(request.toServiceRequest(userInfo.id)) + ) + } + +} diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/user/dto/UserRequestDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/user/dto/UserRequestDto.kt new file mode 100644 index 0000000..cbc8616 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/user/dto/UserRequestDto.kt @@ -0,0 +1,49 @@ +package com.travel.withaeng.controller.user.dto + +import com.travel.withaeng.applicationservice.user.dto.AddUserDetailsServerRequest +import com.travel.withaeng.domain.user.* +import io.swagger.v3.oas.annotations.media.Schema +import org.hibernate.validator.constraints.Length + +@Schema(description = "[Request] User 정보를 추가합니다") +data class AddUserDetailsRequest( + @Schema(description = "유저 닉네임") + @field:Length(min = 2, max = 10, message = "닉네임은 2 ~ 10자리 문자열로 입력해야 합니다.") + val nickname: String? = null, + + @Schema(description = "유저 MBTI") + val mbti: UserMbti? = null, + + @Schema(description = "여행 선호 지역 (국내 / 해외)") + val preferTravelType: UserPreferTravelType? = null, + + @Schema(description = "여행 관심사 (사진, 음식 등)") + val preferTravelThemes: List? = null, + + @Schema(description = "여행 소비 스타일 (가성비, 쓸 때 쓰는 타입 등)") + val consumeStyle: UserConsumeStyle? = null, + + @Schema(description = "못 먹는 음식 (갑각류, 해산물 등)") + val foodRestrictions: List? = null, + + @Schema(description = "원하는 동행자의 성별") + val preferAccompanyGender: UserPreferAccompanyGender? = null, + + @Schema(description = "흡연 타입") + val smokingType: UserSmokingType? = null, + + @Schema(description = "음주 타입") + val drinkingType: UserDrinkingType? = null +) + +fun AddUserDetailsRequest.toServiceRequest(userId: Long): AddUserDetailsServerRequest = AddUserDetailsServerRequest( + userId = userId, + nickname = nickname, + mbti = mbti, + preferTravelType = preferTravelType, + preferTravelThemes = preferTravelThemes, + consumeStyle = consumeStyle, + foodRestrictions = foodRestrictions, + preferAccompanyGender = preferAccompanyGender, + smokingType = smokingType +) From 263fd25b29f5f9eabe6cd878fca86e9b8babb9d8 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Thu, 13 Jun 2024 17:56:56 +0900 Subject: [PATCH 088/174] Fix validating email template's style --- .../resources/templates/email-template.html | 41 +++++++++++++++---- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/withaeng-external/src/main/resources/templates/email-template.html b/withaeng-external/src/main/resources/templates/email-template.html index 6eb45f9..39298f7 100644 --- a/withaeng-external/src/main/resources/templates/email-template.html +++ b/withaeng-external/src/main/resources/templates/email-template.html @@ -1,10 +1,37 @@ - - + + - - 이메일 인증 + + + + 같이행(Withaeng) - 이메일 인증 - -
+ +
+
+
+
+

비밀번호 재설정

+

+ 안녕하세요.
+ 같이행 서비스 이용을 위해 이메일 주소 인증을 요청하셨습니다.
+ 아래 버튼을 클릭하여 서비스를 이용할 수 있습니다. +

+
+
+
+

인증은 5분 이내로 완료해주세요.

+
+ +
+
+
- \ No newline at end of file + From 627c42dd6df0faf094a8990c43eb49dfb90641fc Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Thu, 13 Jun 2024 17:57:19 +0900 Subject: [PATCH 089/174] Fix sending email for validating user logic --- .../com/travel/withaeng/common/Constants.kt | 4 +-- .../withaeng/scheduler/SendEmailScheduler.kt | 8 +++--- .../withaeng/external/ses/MailSender.kt | 4 +-- .../withaeng/external/ses/MailSenderImpl.kt | 25 +++++++++++++------ .../main/resources/application-external.yml | 10 +++++++- 5 files changed, 36 insertions(+), 15 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/Constants.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/Constants.kt index fd56c0a..dcefe4f 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/Constants.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/Constants.kt @@ -8,6 +8,6 @@ object Constants { object Url { const val BASE_URL = "localhost:3030/" - const val VALIDATING_EMAIL_URL = BASE_URL + "validate-email/" + const val VALIDATING_EMAIL_URL = BASE_URL + "validate-email" } -} \ No newline at end of file +} diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/SendEmailScheduler.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/SendEmailScheduler.kt index de87ce4..aa18484 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/SendEmailScheduler.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/SendEmailScheduler.kt @@ -27,11 +27,13 @@ class SendEmailScheduler( val now = LocalDateTime.now() log.info("Start sending emails at {}", now) val willSendMails = validatingEmailService.findAllByStatusNot(ValidatingEmailStatus.DONE) - willSendMails.forEach { - mailSender.sendValidatingEmail(VALIDATING_EMAIL_URL, it.email) + willSendMails.forEach { emailDto -> + val to = emailDto.email + val validatingEmailUrl = "$VALIDATING_EMAIL_URL?code=${emailDto.code}&email=${to}" + mailSender.sendValidatingEmail(validatingEmailUrl, to) } if (willSendMails.isNotEmpty()) { validatingEmailService.updateStatusByIds(willSendMails.map { it.id }.toSet(), ValidatingEmailStatus.DONE) } } -} \ No newline at end of file +} diff --git a/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSender.kt b/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSender.kt index 41d6aa3..e0fdaed 100644 --- a/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSender.kt +++ b/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSender.kt @@ -2,5 +2,5 @@ package com.travel.withaeng.external.ses interface MailSender { - fun sendValidatingEmail(validatingEmailUrl: String, vararg to: String) -} \ No newline at end of file + fun sendValidatingEmail(validatingEmailUrl: String, to: String) +} diff --git a/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSenderImpl.kt b/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSenderImpl.kt index cca831e..1320c39 100644 --- a/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSenderImpl.kt +++ b/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSenderImpl.kt @@ -17,13 +17,21 @@ class MailSenderImpl( @Value("\${cloud.aws.ses.from}") private lateinit var from: String - override fun sendValidatingEmail(validatingEmailUrl: String, vararg to: String) { - send("email-template", VALIDATING_EMAIL_SUBJECT, mapOf("validatingEmailUrl" to validatingEmailUrl), *to) + override fun sendValidatingEmail(validatingEmailUrl: String, to: String) { + send( + template = "email-template", + subject = VALIDATING_EMAIL_SUBJECT, + variables = mapOf( + VARIABLE_THYMELEAF_VALIDATING_EMAIL_URL to validatingEmailUrl, + VARIABLE_THYMELEAF_EMAIL to to + ), + to = to + ) } - private fun send(template: String, subject: String, variables: Map, vararg to: String) { + private fun send(template: String, subject: String, variables: Map, to: String) { val content = templateEngine.process(template, createContext(variables)) - val request = createSendEmailRequest(subject, content, *to) + val request = createSendEmailRequest(subject, content, to) emailService.sendEmail(request) } @@ -31,9 +39,9 @@ class MailSenderImpl( return Context().apply { setVariables(variables) } } - private fun createSendEmailRequest(subject: String, content: String, vararg to: String): SendEmailRequest { + private fun createSendEmailRequest(subject: String, content: String, to: String): SendEmailRequest { return SendEmailRequest() - .withDestination(Destination().withToAddresses(*to)) + .withDestination(Destination().withToAddresses(to)) .withSource(from) .withMessage( Message() @@ -44,5 +52,8 @@ class MailSenderImpl( companion object { private const val VALIDATING_EMAIL_SUBJECT = "같이행 서비스 이메일 인증을 부탁드립니다." + + private const val VARIABLE_THYMELEAF_VALIDATING_EMAIL_URL = "validatingEmailUrl" + private const val VARIABLE_THYMELEAF_EMAIL = "email" } -} \ No newline at end of file +} diff --git a/withaeng-external/src/main/resources/application-external.yml b/withaeng-external/src/main/resources/application-external.yml index a03e0b5..d951f5e 100644 --- a/withaeng-external/src/main/resources/application-external.yml +++ b/withaeng-external/src/main/resources/application-external.yml @@ -1,3 +1,11 @@ +spring: + thymeleaf: + prefix: classpath:/templates/ + suffix: .html + mode: HTML + encoding: UTF-8 + content-type: text/html + cache: false cloud: aws: credentials: @@ -6,4 +14,4 @@ cloud: region: static: ENC(1OX/+Td6WwTc/zbC8t/DVgDHX24lMOV+ZQbza/IstkTM8E3UKwloe8EaH97FKpzT) ses: - from: ENC(S6WIEUO3m5JKHw7PrhpgkAvQjd1LzwwLRXEu2I9yUtzErtBEDk6EEt28Ltzypo8/fZi7Ua8VkHjWh9498FT5DA==) \ No newline at end of file + from: ENC(S6WIEUO3m5JKHw7PrhpgkAvQjd1LzwwLRXEu2I9yUtzErtBEDk6EEt28Ltzypo8/fZi7Ua8VkHjWh9498FT5DA==) From e86a8abbf95a2a42da22e7cb4c39877f0a9e15cd Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Fri, 14 Jun 2024 17:49:53 +0900 Subject: [PATCH 090/174] Implement changing password api --- .../auth/AuthApplicationService.kt | 28 +++++++++++++--- ...icationDto.kt => AuthServiceRequestDto.kt} | 12 ++++++- .../controller/auth/AuthController.kt | 21 +++++++++--- .../controller/auth/dto/AuthRequestDto.kt | 32 +++++++++++++++++-- .../com/travel/withaeng/domain/user/User.kt | 2 +- .../withaeng/domain/user/UserService.kt | 7 ++++ 6 files changed, 88 insertions(+), 14 deletions(-) rename withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/{AuthApplicationDto.kt => AuthServiceRequestDto.kt} (66%) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt index 634fed1..6976568 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt @@ -1,9 +1,6 @@ package com.travel.withaeng.applicationservice.auth -import com.travel.withaeng.applicationservice.auth.dto.SignInServiceRequest -import com.travel.withaeng.applicationservice.auth.dto.SignUpServiceRequest -import com.travel.withaeng.applicationservice.auth.dto.UserResponse -import com.travel.withaeng.applicationservice.auth.dto.ValidateEmailServiceRequest +import com.travel.withaeng.applicationservice.auth.dto.* import com.travel.withaeng.common.exception.WithaengException import com.travel.withaeng.common.exception.WithaengExceptionType import com.travel.withaeng.domain.user.CreateUserDto @@ -79,6 +76,29 @@ class AuthApplicationService( userService.grantUserRole(userDto.id) } + @Transactional + fun sendEmailForChangeEmail(request: SendEmailForChangePasswordServiceRequest) { + val userDto = userService.findByEmailOrNull(request.email) ?: throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = "이메일에 해당하는 유저를 찾을 수 없습니다." + ) + validatingEmailService.create(userDto.email, userDto.id, UUID.randomUUID().toString()) + } + + @Transactional + fun changePassword(request: ChangePasswordServiceRequest) { + val userDto = userService.findByEmailOrNull(request.email) ?: throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = "이메일에 해당하는 유저를 찾을 수 없습니다." + ) + val validatingEmailDto = validatingEmailService.findByEmail(request.email) + if (validatingEmailDto.userId != userDto.id || validatingEmailDto.code != request.code) { + throw WithaengException.of(WithaengExceptionType.INVALID_INPUT, "Code가 올바르지 않습니다.") + } + validatingEmailService.deleteById(validatingEmailDto.id) + userService.updatePassword(userDto.id, passwordEncoder.encode(request.password)) + } + private fun UserSimpleDto.isValidUser(): Boolean { return roles.any { it == UserRole.USER } } diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthApplicationDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthServiceRequestDto.kt similarity index 66% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthApplicationDto.kt rename to withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthServiceRequestDto.kt index 04186a3..ce3a604 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthApplicationDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthServiceRequestDto.kt @@ -17,4 +17,14 @@ data class SignInServiceRequest( data class ValidateEmailServiceRequest( val email: String, val code: String -) \ No newline at end of file +) + +data class SendEmailForChangePasswordServiceRequest( + val email: String +) + +data class ChangePasswordServiceRequest( + val email: String, + val code: String, + val password: String +) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt index 4128f5a..d2eb908 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt @@ -3,10 +3,7 @@ package com.travel.withaeng.controller.auth import com.travel.withaeng.applicationservice.auth.AuthApplicationService import com.travel.withaeng.applicationservice.auth.dto.UserResponse import com.travel.withaeng.common.ApiResponse -import com.travel.withaeng.controller.auth.dto.SignInRequest -import com.travel.withaeng.controller.auth.dto.SignUpRequest -import com.travel.withaeng.controller.auth.dto.ValidateEmailRequest -import com.travel.withaeng.controller.auth.dto.toServiceRequest +import com.travel.withaeng.controller.auth.dto.* import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.tags.Tag import org.springframework.web.bind.annotation.* @@ -38,4 +35,18 @@ class AuthController(private val authApplicationService: AuthApplicationService) authApplicationService.validateEmail(request.toServiceRequest()) return ApiResponse.success() } -} \ No newline at end of file + + @Operation(summary = "Send Mail For Changing Password API", description = "비밀번호 변경을 위한 이메일 전송") + @PostMapping("/send-email-for-change-password") + fun sendEmailForChangingPassword(@RequestBody request: SendEmailForChangePasswordRequest): ApiResponse { + authApplicationService.sendEmailForChangeEmail(request.toServiceRequest()) + return ApiResponse.success() + } + + @Operation(summary = "Change Password API", description = "비밀번호 변경 API") + @PutMapping("/change-password") + fun changePassword(@RequestBody request: ChangePasswordRequest): ApiResponse { + authApplicationService.changePassword(request.toServiceRequest()) + return ApiResponse.success() + } +} diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/dto/AuthRequestDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/dto/AuthRequestDto.kt index 4be41f5..22bb877 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/dto/AuthRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/dto/AuthRequestDto.kt @@ -1,8 +1,6 @@ package com.travel.withaeng.controller.auth.dto -import com.travel.withaeng.applicationservice.auth.dto.SignInServiceRequest -import com.travel.withaeng.applicationservice.auth.dto.SignUpServiceRequest -import com.travel.withaeng.applicationservice.auth.dto.ValidateEmailServiceRequest +import com.travel.withaeng.applicationservice.auth.dto.* import io.swagger.v3.oas.annotations.media.Schema import java.time.LocalDate @@ -55,3 +53,31 @@ fun ValidateEmailRequest.toServiceRequest(): ValidateEmailServiceRequest = Valid email = email, code = code ) + + +@Schema(description = "[Request] 비밀번호 재설정을 위한 이메일 전송") +data class SendEmailForChangePasswordRequest( + @Schema(description = "이메일 인증 할 이메일") + val email: String +) + +fun SendEmailForChangePasswordRequest.toServiceRequest(): SendEmailForChangePasswordServiceRequest = + SendEmailForChangePasswordServiceRequest(email) + +@Schema(description = "[Request] 비밀번호 재설정") +data class ChangePasswordRequest( + @Schema(description = "이메일 인증 한 이메일") + val email: String, + + @Schema(description = "이메일 인증으로 받은 코드 (UUID 형태)") + val code: String, + + @Schema(description = "새로운 패스워드") + val password: String +) + +fun ChangePasswordRequest.toServiceRequest(): ChangePasswordServiceRequest = ChangePasswordServiceRequest( + email = email, + code = code, + password = password +) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt index b4fb0c1..34571a8 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt @@ -14,7 +14,7 @@ class User( val email: String, @Column(name = "password", nullable = false) - val password: String, + var password: String, @Column(name = "nickname", nullable = true) val nickname: String? = null, diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt index b0cde5d..1fa682b 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt @@ -44,6 +44,13 @@ class UserService(private val userRepository: UserRepository) { return user.toDetailsDto() } + @Transactional + fun updatePassword(userId: Long, password: String): UserSimpleDto { + val user = userRepository.findByIdOrNull(userId).getOrThrow() + user.password = password + return user.toSimpleDto() + } + @Transactional fun grantUserRole(id: Long) { val user = userRepository.findByIdOrNull(id) From 5b8f50c7aeeeb08854ad3778d5c052c004fa42b0 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Fri, 14 Jun 2024 18:18:03 +0900 Subject: [PATCH 091/174] Implement deleting outdated validating emails scheduler --- .../auth/AuthApplicationService.kt | 27 ++++++++----- .../DeleteValidatingEmailScheduler.kt | 39 +++++++++++++++++++ .../validateemail/ValidatingEmailDto.kt | 10 +++-- .../validateemail/ValidatingEmailService.kt | 7 +++- 4 files changed, 70 insertions(+), 13 deletions(-) create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/DeleteValidatingEmailScheduler.kt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt index 6976568..8be9756 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt @@ -68,11 +68,11 @@ class AuthApplicationService( message = "이미 인증된 유저입니다." ) } - val validatingEmailDto = validatingEmailService.findByEmail(requestedEmail) - if (validatingEmailDto.userId != userDto.id || validatingEmailDto.code != request.code) { - throw WithaengException.of(WithaengExceptionType.INVALID_INPUT, "Code가 올바르지 않습니다.") - } - validatingEmailService.deleteById(validatingEmailDto.id) + validateEmailCode( + email = requestedEmail, + userId = userDto.id, + code = request.code + ) userService.grantUserRole(userDto.id) } @@ -87,16 +87,25 @@ class AuthApplicationService( @Transactional fun changePassword(request: ChangePasswordServiceRequest) { - val userDto = userService.findByEmailOrNull(request.email) ?: throw WithaengException.of( + val email = request.email + val userDto = userService.findByEmailOrNull(email) ?: throw WithaengException.of( type = WithaengExceptionType.NOT_EXIST, message = "이메일에 해당하는 유저를 찾을 수 없습니다." ) - val validatingEmailDto = validatingEmailService.findByEmail(request.email) - if (validatingEmailDto.userId != userDto.id || validatingEmailDto.code != request.code) { + validateEmailCode( + email = email, + userId = userDto.id, + code = request.code + ) + userService.updatePassword(userDto.id, passwordEncoder.encode(request.password)) + } + + private fun validateEmailCode(email: String, userId: Long, code: String) { + val validatingEmailDto = validatingEmailService.findByEmail(email) + if (validatingEmailDto.userId != userId || validatingEmailDto.code != code) { throw WithaengException.of(WithaengExceptionType.INVALID_INPUT, "Code가 올바르지 않습니다.") } validatingEmailService.deleteById(validatingEmailDto.id) - userService.updatePassword(userDto.id, passwordEncoder.encode(request.password)) } private fun UserSimpleDto.isValidUser(): Boolean { diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/DeleteValidatingEmailScheduler.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/DeleteValidatingEmailScheduler.kt new file mode 100644 index 0000000..404b542 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/DeleteValidatingEmailScheduler.kt @@ -0,0 +1,39 @@ +package com.travel.withaeng.scheduler + +import com.travel.withaeng.domain.validateemail.ValidatingEmailService +import com.travel.withaeng.domain.validateemail.ValidatingEmailStatus +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import org.springframework.scheduling.annotation.Async +import org.springframework.scheduling.annotation.Scheduled +import org.springframework.stereotype.Component +import org.springframework.transaction.annotation.Transactional +import java.time.LocalDateTime + +@Component +class DeleteValidatingEmailScheduler( + private val validatingEmailService: ValidatingEmailService +) { + + private val log: Logger = LoggerFactory.getLogger(DeleteValidatingEmailScheduler::class.java) + + @Scheduled(cron = "0 * * * * *") + @Async("asyncSchedulerExecutor") + @Transactional + fun sendEmail() { + val now = LocalDateTime.now() + log.info("Start deleting validating emails at {}", now) + val willDeleteEmails = validatingEmailService.findAllByStatusNot(ValidatingEmailStatus.YET) + .filter { emailDto -> emailDto.createdAt.plusMinutes(VALIDATING_MAIL_EXPIRED_MINUTES) < now } + .map { emailDto -> emailDto.id } + .toSet() + if (willDeleteEmails.isNotEmpty()) { + validatingEmailService.deleteAllById(willDeleteEmails) + log.info("End deleteing {} validating emails at {}", willDeleteEmails.size, LocalDateTime.now()) + } + } + + companion object { + private const val VALIDATING_MAIL_EXPIRED_MINUTES = 5L + } +} diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailDto.kt index 29acbbb..c63c2c7 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailDto.kt @@ -1,11 +1,14 @@ package com.travel.withaeng.domain.validateemail +import java.time.LocalDateTime + data class ValidatingEmailDto( val id: Long, val email: String, val userId: Long, val code: String, - val status: ValidatingEmailStatus + val status: ValidatingEmailStatus, + val createdAt: LocalDateTime ) fun ValidatingEmail.toDto(): ValidatingEmailDto = ValidatingEmailDto( @@ -13,5 +16,6 @@ fun ValidatingEmail.toDto(): ValidatingEmailDto = ValidatingEmailDto( email = email, userId = userId, code = code, - status = status -) \ No newline at end of file + status = status, + createdAt = createdAt +) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailService.kt index d59228c..c939d4b 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailService.kt @@ -46,6 +46,11 @@ class ValidatingEmailService( validatingEmailRepository.deleteById(id) } + @Transactional + fun deleteAllById(ids: Set) { + validatingEmailRepository.deleteAllById(ids) + } + @Transactional fun deleteAllByUserId(userId: Long) { validatingEmailRepository.deleteAllByUserId(userId) @@ -55,4 +60,4 @@ class ValidatingEmailService( fun updateStatusByIds(ids: Set, status: ValidatingEmailStatus) { validatingEmailRepository.updateStatusByIds(ids, status) } -} \ No newline at end of file +} From 9294ea0cb6e42fe79e359d440c109006b0e7ac58 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Fri, 14 Jun 2024 18:57:06 +0900 Subject: [PATCH 092/174] Fix email templates by dividing email types --- .../auth/AuthApplicationService.kt | 15 +++++++- .../com/travel/withaeng/common/Constants.kt | 1 + .../withaeng/scheduler/SendEmailScheduler.kt | 22 +++++++++-- .../domain/validateemail/ValidatingEmail.kt | 8 +++- .../validateemail/ValidatingEmailDto.kt | 2 + .../ValidatingEmailRepository.kt | 4 +- .../validateemail/ValidatingEmailService.kt | 15 ++++++-- .../validateemail/ValidatingEmailType.kt | 5 +++ .../withaeng/external/ses/MailSender.kt | 2 +- .../withaeng/external/ses/MailSenderImpl.kt | 19 +++++----- .../travel/withaeng/external/ses/MailType.kt | 6 +++ .../templates/change-password-template.html | 37 +++++++++++++++++++ ...late.html => validate-email-template.html} | 4 +- 13 files changed, 115 insertions(+), 25 deletions(-) create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailType.kt create mode 100644 withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailType.kt create mode 100644 withaeng-external/src/main/resources/templates/change-password-template.html rename withaeng-external/src/main/resources/templates/{email-template.html => validate-email-template.html} (93%) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt index 8be9756..fb26077 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt @@ -8,6 +8,7 @@ import com.travel.withaeng.domain.user.UserRole import com.travel.withaeng.domain.user.UserService import com.travel.withaeng.domain.user.UserSimpleDto import com.travel.withaeng.domain.validateemail.ValidatingEmailService +import com.travel.withaeng.domain.validateemail.ValidatingEmailType import com.travel.withaeng.security.authentication.UserInfo import com.travel.withaeng.security.jwt.JwtAgent import org.springframework.security.crypto.password.PasswordEncoder @@ -39,7 +40,12 @@ class AuthApplicationService( validatingEmailService.deleteAllByUserId(userDto.id) } val newUserDto = userService.create(request.toCreateUserDto()) - validatingEmailService.create(newUserDto.email, newUserDto.id, UUID.randomUUID().toString()) + validatingEmailService.create( + email = newUserDto.email, + userId = newUserDto.id, + code = UUID.randomUUID().toString(), + type = ValidatingEmailType.VALIDATE_EMAIL + ) return UserResponse(newUserDto.id, newUserDto.email, jwtAgent.provide(UserInfo.from(newUserDto))) } @@ -82,7 +88,12 @@ class AuthApplicationService( type = WithaengExceptionType.NOT_EXIST, message = "이메일에 해당하는 유저를 찾을 수 없습니다." ) - validatingEmailService.create(userDto.email, userDto.id, UUID.randomUUID().toString()) + validatingEmailService.create( + email = userDto.email, + userId = userDto.id, + code = UUID.randomUUID().toString(), + type = ValidatingEmailType.CHANGE_PASSWORD + ) } @Transactional diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/Constants.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/Constants.kt index dcefe4f..9ded966 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/Constants.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/Constants.kt @@ -9,5 +9,6 @@ object Constants { object Url { const val BASE_URL = "localhost:3030/" const val VALIDATING_EMAIL_URL = BASE_URL + "validate-email" + const val CHANGING_PASSWORD_EMAIL_URL = BASE_URL + "change-password" } } diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/SendEmailScheduler.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/SendEmailScheduler.kt index aa18484..a985f89 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/SendEmailScheduler.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/SendEmailScheduler.kt @@ -1,9 +1,12 @@ package com.travel.withaeng.scheduler +import com.travel.withaeng.common.Constants.Url.CHANGING_PASSWORD_EMAIL_URL import com.travel.withaeng.common.Constants.Url.VALIDATING_EMAIL_URL import com.travel.withaeng.domain.validateemail.ValidatingEmailService import com.travel.withaeng.domain.validateemail.ValidatingEmailStatus +import com.travel.withaeng.domain.validateemail.ValidatingEmailType import com.travel.withaeng.external.ses.MailSender +import com.travel.withaeng.external.ses.MailType import org.slf4j.Logger import org.slf4j.LoggerFactory import org.springframework.scheduling.annotation.Async @@ -29,11 +32,24 @@ class SendEmailScheduler( val willSendMails = validatingEmailService.findAllByStatusNot(ValidatingEmailStatus.DONE) willSendMails.forEach { emailDto -> val to = emailDto.email - val validatingEmailUrl = "$VALIDATING_EMAIL_URL?code=${emailDto.code}&email=${to}" - mailSender.sendValidatingEmail(validatingEmailUrl, to) + val code = emailDto.code + val type = emailDto.type + val redirectUrl = "${type.toValidatingUrl()}?code=$code&email=$to" + mailSender.send(redirectUrl, to, emailDto.type.toMailType()) } if (willSendMails.isNotEmpty()) { - validatingEmailService.updateStatusByIds(willSendMails.map { it.id }.toSet(), ValidatingEmailStatus.DONE) + val updateCount = validatingEmailService.updateStatusByIds( + willSendMails.map { it.id }.toSet(), + ValidatingEmailStatus.DONE + ) + log.info("End sending {} emails at {}", updateCount, now) } } + + private fun ValidatingEmailType.toMailType(): MailType = + if (this == ValidatingEmailType.CHANGE_PASSWORD) MailType.CHANGE_PASSWORD + else MailType.VALIDATE_EMAIL + + private fun ValidatingEmailType.toValidatingUrl(): String = + if (this == ValidatingEmailType.CHANGE_PASSWORD) CHANGING_PASSWORD_EMAIL_URL else VALIDATING_EMAIL_URL } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmail.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmail.kt index b315746..9e032fd 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmail.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmail.kt @@ -15,7 +15,11 @@ class ValidatingEmail( @Column(name = "code", nullable = false) val code: String, + @Enumerated(EnumType.STRING) + @Column(name = "type", nullable = false) + val type: ValidatingEmailType = ValidatingEmailType.VALIDATE_EMAIL, + @Enumerated(EnumType.STRING) @Column(name = "status", nullable = false) - val status: ValidatingEmailStatus = ValidatingEmailStatus.YET -) : BaseEntity() \ No newline at end of file + val status: ValidatingEmailStatus = ValidatingEmailStatus.YET, +) : BaseEntity() diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailDto.kt index c63c2c7..54669e6 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailDto.kt @@ -8,6 +8,7 @@ data class ValidatingEmailDto( val userId: Long, val code: String, val status: ValidatingEmailStatus, + val type: ValidatingEmailType, val createdAt: LocalDateTime ) @@ -17,5 +18,6 @@ fun ValidatingEmail.toDto(): ValidatingEmailDto = ValidatingEmailDto( userId = userId, code = code, status = status, + type = type, createdAt = createdAt ) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailRepository.kt index 3bc4ce1..87786cb 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailRepository.kt @@ -11,7 +11,7 @@ interface ValidatingEmailRepository : JpaRepository { @Modifying @Query("UPDATE ValidatingEmail v SET v.status = :status WHERE v.id in :ids") - fun updateStatusByIds(ids: Set, status: ValidatingEmailStatus) + fun updateStatusByIds(ids: Set, status: ValidatingEmailStatus): Int fun deleteAllByUserId(userId: Long) -} \ No newline at end of file +} diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailService.kt index c939d4b..08476c4 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailService.kt @@ -15,7 +15,7 @@ class ValidatingEmailService( ) { @Transactional - fun create(email: String, userId: Long, code: String): ValidatingEmailDto { + fun create(email: String, userId: Long, code: String, type: ValidatingEmailType): ValidatingEmailDto { userRepository.findByIdOrNull(userId) ?: throw WithaengException.of( type = WithaengExceptionType.NOT_EXIST, message = "$userId 에 해당하는 사용자를 찾을 수 없습니다." @@ -26,7 +26,14 @@ class ValidatingEmailService( message = "이메일 인증을 진행하는데 올바르지 않은 입력입니다." ) } - return validatingEmailRepository.save(ValidatingEmail(email, userId, code)).toDto() + return validatingEmailRepository.save( + ValidatingEmail( + email = email, + userId = userId, + code = code, + type = type + ) + ).toDto() } fun findByEmail(email: String): ValidatingEmailDto { @@ -57,7 +64,7 @@ class ValidatingEmailService( } @Transactional - fun updateStatusByIds(ids: Set, status: ValidatingEmailStatus) { - validatingEmailRepository.updateStatusByIds(ids, status) + fun updateStatusByIds(ids: Set, status: ValidatingEmailStatus): Int { + return validatingEmailRepository.updateStatusByIds(ids, status) } } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailType.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailType.kt new file mode 100644 index 0000000..6b2a362 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailType.kt @@ -0,0 +1,5 @@ +package com.travel.withaeng.domain.validateemail + +enum class ValidatingEmailType { + VALIDATE_EMAIL, CHANGE_PASSWORD +} diff --git a/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSender.kt b/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSender.kt index e0fdaed..f5dea80 100644 --- a/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSender.kt +++ b/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSender.kt @@ -2,5 +2,5 @@ package com.travel.withaeng.external.ses interface MailSender { - fun sendValidatingEmail(validatingEmailUrl: String, to: String) + fun send(redirectUrl: String, to: String, type: MailType) } diff --git a/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSenderImpl.kt b/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSenderImpl.kt index 1320c39..c3bfe37 100644 --- a/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSenderImpl.kt +++ b/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSenderImpl.kt @@ -17,21 +17,20 @@ class MailSenderImpl( @Value("\${cloud.aws.ses.from}") private lateinit var from: String - override fun sendValidatingEmail(validatingEmailUrl: String, to: String) { + override fun send(redirectUrl: String, to: String, type: MailType) { send( - template = "email-template", - subject = VALIDATING_EMAIL_SUBJECT, + template = type.templateName, variables = mapOf( - VARIABLE_THYMELEAF_VALIDATING_EMAIL_URL to validatingEmailUrl, + VARIABLE_THYMELEAF_REDIRECT_URL to redirectUrl, VARIABLE_THYMELEAF_EMAIL to to ), to = to ) } - private fun send(template: String, subject: String, variables: Map, to: String) { + private fun send(template: String, variables: Map, to: String) { val content = templateEngine.process(template, createContext(variables)) - val request = createSendEmailRequest(subject, content, to) + val request = createSendEmailRequest(content, to) emailService.sendEmail(request) } @@ -39,13 +38,15 @@ class MailSenderImpl( return Context().apply { setVariables(variables) } } - private fun createSendEmailRequest(subject: String, content: String, to: String): SendEmailRequest { + private fun createSendEmailRequest(content: String, to: String): SendEmailRequest { return SendEmailRequest() .withDestination(Destination().withToAddresses(to)) .withSource(from) .withMessage( Message() - .withSubject(Content().withCharset(StandardCharsets.UTF_8.name()).withData(subject)) + .withSubject( + Content().withCharset(StandardCharsets.UTF_8.name()).withData(VALIDATING_EMAIL_SUBJECT) + ) .withBody(Body().withHtml(Content().withCharset(StandardCharsets.UTF_8.name()).withData(content))) ) } @@ -53,7 +54,7 @@ class MailSenderImpl( companion object { private const val VALIDATING_EMAIL_SUBJECT = "같이행 서비스 이메일 인증을 부탁드립니다." - private const val VARIABLE_THYMELEAF_VALIDATING_EMAIL_URL = "validatingEmailUrl" + private const val VARIABLE_THYMELEAF_REDIRECT_URL = "redirectUrl" private const val VARIABLE_THYMELEAF_EMAIL = "email" } } diff --git a/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailType.kt b/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailType.kt new file mode 100644 index 0000000..ec02404 --- /dev/null +++ b/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailType.kt @@ -0,0 +1,6 @@ +package com.travel.withaeng.external.ses + +enum class MailType(val templateName: String) { + VALIDATE_EMAIL("validate-email-template"), + CHANGE_PASSWORD("change-password-template") +} diff --git a/withaeng-external/src/main/resources/templates/change-password-template.html b/withaeng-external/src/main/resources/templates/change-password-template.html new file mode 100644 index 0000000..982f6ce --- /dev/null +++ b/withaeng-external/src/main/resources/templates/change-password-template.html @@ -0,0 +1,37 @@ + + + + + + + 같이행(Withaeng) - 이메일 인증 + + +
+
+
+
+

비밀번호 재설정

+

+ 안녕하세요.
+ 비밀번호 재설정을 위해 이메일 주소 인증을 요청하셨습니다.
+ 아래 버튼을 클릭하여 서비스를 이용할 수 있습니다. +

+
+
+
+

인증은 5분 이내로 완료해주세요.

+
+ +
+
+
+ + diff --git a/withaeng-external/src/main/resources/templates/email-template.html b/withaeng-external/src/main/resources/templates/validate-email-template.html similarity index 93% rename from withaeng-external/src/main/resources/templates/email-template.html rename to withaeng-external/src/main/resources/templates/validate-email-template.html index 39298f7..0022852 100644 --- a/withaeng-external/src/main/resources/templates/email-template.html +++ b/withaeng-external/src/main/resources/templates/validate-email-template.html @@ -16,7 +16,7 @@
-

비밀번호 재설정

+

이메일 주소 인증 메일

안녕하세요.
같이행 서비스 이용을 위해 이메일 주소 인증을 요청하셨습니다.
@@ -28,7 +28,7 @@

비밀번호

인증은 5분 이내로 완료해주세요.

From c9543ccd90af7868771dd6400f074024205faf74 Mon Sep 17 00:00:00 2001 From: Sujin Shin <67135103+ssj5037@users.noreply.github.com> Date: Fri, 14 Jun 2024 19:01:21 +0900 Subject: [PATCH 093/174] =?UTF-8?q?fix:=20=EB=B9=84=EB=B0=80=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=9E=AC=EC=84=A4=EC=A0=95=20html?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../templates/change-password-template.html | 138 ++++++++++++++---- 1 file changed, 110 insertions(+), 28 deletions(-) diff --git a/withaeng-external/src/main/resources/templates/change-password-template.html b/withaeng-external/src/main/resources/templates/change-password-template.html index 982f6ce..38c72d1 100644 --- a/withaeng-external/src/main/resources/templates/change-password-template.html +++ b/withaeng-external/src/main/resources/templates/change-password-template.html @@ -1,37 +1,119 @@ - + 같이행(Withaeng) - 이메일 인증 - - -
-
-
-
-

비밀번호 재설정

-

- 안녕하세요.
- 비밀번호 재설정을 위해 이메일 주소 인증을 요청하셨습니다.
- 아래 버튼을 클릭하여 서비스를 이용할 수 있습니다. -

-
-
-
-

인증은 5분 이내로 완료해주세요.

-
- + + +
+
+
+ +
+
+
+
+

+ 비밀번호 재설정 +

+

+ 안녕하세요.
+ 같이행 서비스 이용을 위해 이메일 주소 인증을 요청하셨습니다.
+ 아래 버튼을 클릭하여 서비스를 이용할 수 있습니다. +

+
+
+
+

+ 인증은 5분 이내로 완료해주세요. +

+
+
-
-
- +
+
+ From f3cd4e338bcb6bde5543f1021dc9ad5d774b3542 Mon Sep 17 00:00:00 2001 From: Sujin Shin <67135103+ssj5037@users.noreply.github.com> Date: Fri, 14 Jun 2024 19:02:02 +0900 Subject: [PATCH 094/174] =?UTF-8?q?feat:=20=EA=B0=99=EC=9D=B4=ED=96=89=20l?= =?UTF-8?q?ogo=20png=20image=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/resources/templates/withaeng-logo.png | Bin 0 -> 2960 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 withaeng-external/src/main/resources/templates/withaeng-logo.png diff --git a/withaeng-external/src/main/resources/templates/withaeng-logo.png b/withaeng-external/src/main/resources/templates/withaeng-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..939fd78040dfc4c4bcff801263b4fd4e3dd39b45 GIT binary patch literal 2960 zcmV;B3vcv^P)0015c1^@s6s}B_@00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yPvTZpnRL^E_(XuK=kR7#13J~%Zt)giSrjk^A}jzmKMvjlL;-v zGAUiObS!1lqiEfew5$M|03AOCxoB4Ymf_BLgfR*09Ozs%$<$=Npf{Ti2k z9n%lBee%s4)c?GJ`(4LDH0*8iJKb>`vqJ^S(H=3C@v}o2TI1XFF?K!5DK`mRlfCE;)5}Nd*_I<%U6l7Fmcw988D72 zmwq$#L7G1n%f!78iOm~)>tBcC^Y7Drd{j>rsmVX1n{>f~`|OYaF)V8U;XWJ zvrK-bI`yu8zCx6*$IdfF&(&#?zGCwP`ZhL4l=A?DBD zDbcXs;kVj{N!I~FDN4>PW}GZM)+;7jWag=)(MIz7J9HQZU^WAf#_)vZn&yHMS_N3l zYm@*e{@#<8`O90VA~OI(1|c|uvp6`nN)rG`jPT2*9_rZpB>GX0)|Nv$85lqj1K6NR z;?V|d1#{3Y+CQKf1bL;cl-cE@2GzKv0&FL2YI{4$Vxv6j18j(`0&H~fy#ddj<^>Dd zwBt6k=E}x4zORhzQJ?mCQ>*!KyN8&IaBdr)Q_=BJ_??bd>@@MamS((xG0VKKxUt%C zvoaY?VKUqp_HZ67h%GenthT(MAq~S)j7S)k!#Gb!{Tt>Fh2-MG?{zI$HE*=JBbgQR z^jFFHoGnv-Ib3b_5PE&3TLkD;cQj-o(8=ooO_`iScO>*>d~I}eD7_S6ruiRDs?$Y(67WkQ6XiH^pYq zp4>Ch-U;T^$J|;FR_Sz3SJk$#4nAxceMxI>yaMbkoNMFy-KqT(8@7L9Thgapyb$+b zL+LHlr()+BbPfQA47T?LKb zY+@5)KK$V-JYbvGo1wQ=-d_H>4xk-rQltP~qI!3zE(aw`b9CJuv(PF6w1!L&`qFe0 zRS)$AVZ%J48xt+aB*!ax+jp^t_G4QXi1+CXQMyRLFg8Nfk*7;z&&{iNvu0!*^%1xv z&z8A&k)j&7m!vqgvq0$RENN31_fO`|KBsX1o>p+6biwT2OG#*gI*p zyAdl!1}7C9pkw+iTM4V4^P2v8tQhfgYm~_~Xf`R*We96%dJs8RkLeB6Q^dr4;3oO( zdql@xo#a&=m@46uF;c#r)?TC^@?5rJyg*U))wB?g2$|@PeFU zyE2l~mI%WIx^fcsYNo$N{bP8Up5+9Gju*5Zu|U~gSf2%e-pfh$ns~U@syud*$^b{a z0zX#I6wAXx(o3-C2fWUxD?4G&Kfd*y$OGksRiXrYiNXovwcfQ8(UaAw)dUNb*qL6e zZQPd4kGJ&b(PlCLX=xWZU{`rPEtFAUsAubsJ7OLeR{^#rueZDOc}6_oC>OLI(1zr3 z*aktp3i_p~^v$a-e%vFthgUtb-Esmz1<+9slT$BNjA(W!ot%%JN_Y{+11blT3!JKEi${`i5Up5c3*2Vh(m)~nxedKh*!LE|hN>00QY=$NC z^cOB9Ee3VjeAZumaNJ&Hs-l znSb#2mig1SoA_2zTxYxyhqz%{zw8i&DzVpE+=Gx%Saf_{LHRM05|l|H51XsSi}R=K_CP0Z*vBWcXZ>!W3CF9q4FP9*~Iuv<5Tc1+jABi-!~MC!bg0*|y0u z>oI*ZfEV=22*2=tN=hSq3rT&vjS6_3USm;i%>WQ~iE!k>8p?^0dd03*%0@Y}c|<^5 zq0?MYKqgge8y-)+E?uHXfrc?xDVX>A+CTMhu8;}>u!9`99JO;c0Le!&k_B1mUsEs0 z4v0g)%eQ;+YIZQ(rR)jl0|x64?`J%$6N5|4ct`x*-Pe7qQ!VDXd`+}FG`mQ6D~8S> z2gF0)q?bejg_Gp<@-mcV9Ut_}C||9R9Yb4ndRlnIJoA|Vlw!o}eFGrO-Bs_$K1gOG z5q4jAhq!*bYxchd{XX<%X$}As5c>357awlPs~Ed5i04V^4B`QD>|ENs@P&)pI4rA1 zUAz=GL+A6D2Vn^Yy4={EmJUqufRIeK0S5c7dcILEsDL_7)@K9#-WGYDQ7@=<4!;QR z*P*zVh$X$caxtXh3*BsLQ1vFr+_{*i>!n+fdlaWNQ*!tURw8btTf?1OvbYcHy06@G z2mNhQkS5CDN=Bc>b-bKbuq>D~AKtWk@!OxG5CP9;S4LzrL5FYuZ-27>KZFxJ2=IX& z{{EATfA}V)R~^Q3kuOh<(|Iu^z)hrROGmF%=rSZo6WQ%^b?xt2N1l!ZtWnN$Dgfd-Ws@9I{j za!40pIcYP5+fr3Sm06|p3a6N>jNR=+^N6hc1a|Il+IA=|wvkn@^6DpVrqbVg6I4we z`kzkKcO4p07zqmcfNM$n=p41N6WI6GA-lCmfVhH(vNiGw^V~=6`?@h;jZW#6uIgT) zO3>p3HV_m8Hk+%{m)7tCPdNfZ8=$6NJCFFS;+6r!uU`JM7Vr@^Up)ySx zuiF7MK4lAu?Z|lTIP4z5{XoC=XukAD?y0m~dI0XN6cK9*y#7h5%FgT+p`U~PKj*6i zXB3@~fqEF5C;3Qv&*S;d(---3l&4^kz8nG^&5Pja+@G!rfiWIp%*{(7o|F1BiZPyz7zsH{#xmZRMYgAB}#e%K;a%kf3mA6Y6aIB!?-R z1ppT^len;3r1@nfxG{GDz=g~tns1ubn literal 0 HcmV?d00001 From 219536020bebf604a1367cedbd3f68198f9c3cb5 Mon Sep 17 00:00:00 2001 From: Sujin Shin <67135103+ssj5037@users.noreply.github.com> Date: Fri, 14 Jun 2024 19:04:09 +0900 Subject: [PATCH 095/174] =?UTF-8?q?fix:=20=EC=9D=B4=EB=A9=94=EC=9D=BC=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20html?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../templates/validate-email-template.html | 138 ++++++++++++++---- 1 file changed, 110 insertions(+), 28 deletions(-) diff --git a/withaeng-external/src/main/resources/templates/validate-email-template.html b/withaeng-external/src/main/resources/templates/validate-email-template.html index 0022852..df3248f 100644 --- a/withaeng-external/src/main/resources/templates/validate-email-template.html +++ b/withaeng-external/src/main/resources/templates/validate-email-template.html @@ -1,37 +1,119 @@ - + 같이행(Withaeng) - 이메일 인증 - - -
-
-
-
-

이메일 주소 인증 메일

-

- 안녕하세요.
- 같이행 서비스 이용을 위해 이메일 주소 인증을 요청하셨습니다.
- 아래 버튼을 클릭하여 서비스를 이용할 수 있습니다. -

-
-
-
-

인증은 5분 이내로 완료해주세요.

-
- + + +
+
+
+ +
+
+
+
+

+ 이메일 주소 인증 메일 +

+

+ 안녕하세요.
+ 같이행 서비스 이용을 위해 이메일 주소 인증을 요청하셨습니다.
+ 아래 버튼을 클릭하여 서비스를 이용할 수 있습니다. +

+
+
+
+

+ 인증은 5분 이내로 완료해주세요. +

+
+
-
-
- +
+
+ From f679f7b942b89144f19e35e9eaaf34deacf5e095 Mon Sep 17 00:00:00 2001 From: Sujin Shin <67135103+ssj5037@users.noreply.github.com> Date: Fri, 14 Jun 2024 19:04:40 +0900 Subject: [PATCH 096/174] =?UTF-8?q?fix:=20=EB=B9=84=EB=B0=80=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=9E=AC=EC=84=A4=EC=A0=95=20title=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/templates/change-password-template.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/withaeng-external/src/main/resources/templates/change-password-template.html b/withaeng-external/src/main/resources/templates/change-password-template.html index 38c72d1..c9d75fa 100644 --- a/withaeng-external/src/main/resources/templates/change-password-template.html +++ b/withaeng-external/src/main/resources/templates/change-password-template.html @@ -9,7 +9,7 @@ crossorigin href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/static/pretendard.min.css" /> - 같이행(Withaeng) - 이메일 인증 + 같이행(Withaeng) - 비밀번호 재설정 Date: Fri, 14 Jun 2024 19:26:09 +0900 Subject: [PATCH 097/174] Fix email tamplate logo image --- .../templates/change-password-template.html | 53 +++++++++++++++++- .../templates/validate-email-template.html | 53 +++++++++++++++++- .../resources/templates/withaeng-logo.png | Bin 2960 -> 0 bytes 3 files changed, 104 insertions(+), 2 deletions(-) delete mode 100644 withaeng-external/src/main/resources/templates/withaeng-logo.png diff --git a/withaeng-external/src/main/resources/templates/change-password-template.html b/withaeng-external/src/main/resources/templates/change-password-template.html index c9d75fa..2cabfc8 100644 --- a/withaeng-external/src/main/resources/templates/change-password-template.html +++ b/withaeng-external/src/main/resources/templates/change-password-template.html @@ -41,7 +41,58 @@ " >
- +
diff --git a/withaeng-external/src/main/resources/templates/validate-email-template.html b/withaeng-external/src/main/resources/templates/validate-email-template.html index df3248f..98534d4 100644 --- a/withaeng-external/src/main/resources/templates/validate-email-template.html +++ b/withaeng-external/src/main/resources/templates/validate-email-template.html @@ -41,7 +41,58 @@ " >
- +
diff --git a/withaeng-external/src/main/resources/templates/withaeng-logo.png b/withaeng-external/src/main/resources/templates/withaeng-logo.png deleted file mode 100644 index 939fd78040dfc4c4bcff801263b4fd4e3dd39b45..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2960 zcmV;B3vcv^P)0015c1^@s6s}B_@00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yPvTZpnRL^E_(XuK=kR7#13J~%Zt)giSrjk^A}jzmKMvjlL;-v zGAUiObS!1lqiEfew5$M|03AOCxoB4Ymf_BLgfR*09Ozs%$<$=Npf{Ti2k z9n%lBee%s4)c?GJ`(4LDH0*8iJKb>`vqJ^S(H=3C@v}o2TI1XFF?K!5DK`mRlfCE;)5}Nd*_I<%U6l7Fmcw988D72 zmwq$#L7G1n%f!78iOm~)>tBcC^Y7Drd{j>rsmVX1n{>f~`|OYaF)V8U;XWJ zvrK-bI`yu8zCx6*$IdfF&(&#?zGCwP`ZhL4l=A?DBD zDbcXs;kVj{N!I~FDN4>PW}GZM)+;7jWag=)(MIz7J9HQZU^WAf#_)vZn&yHMS_N3l zYm@*e{@#<8`O90VA~OI(1|c|uvp6`nN)rG`jPT2*9_rZpB>GX0)|Nv$85lqj1K6NR z;?V|d1#{3Y+CQKf1bL;cl-cE@2GzKv0&FL2YI{4$Vxv6j18j(`0&H~fy#ddj<^>Dd zwBt6k=E}x4zORhzQJ?mCQ>*!KyN8&IaBdr)Q_=BJ_??bd>@@MamS((xG0VKKxUt%C zvoaY?VKUqp_HZ67h%GenthT(MAq~S)j7S)k!#Gb!{Tt>Fh2-MG?{zI$HE*=JBbgQR z^jFFHoGnv-Ib3b_5PE&3TLkD;cQj-o(8=ooO_`iScO>*>d~I}eD7_S6ruiRDs?$Y(67WkQ6XiH^pYq zp4>Ch-U;T^$J|;FR_Sz3SJk$#4nAxceMxI>yaMbkoNMFy-KqT(8@7L9Thgapyb$+b zL+LHlr()+BbPfQA47T?LKb zY+@5)KK$V-JYbvGo1wQ=-d_H>4xk-rQltP~qI!3zE(aw`b9CJuv(PF6w1!L&`qFe0 zRS)$AVZ%J48xt+aB*!ax+jp^t_G4QXi1+CXQMyRLFg8Nfk*7;z&&{iNvu0!*^%1xv z&z8A&k)j&7m!vqgvq0$RENN31_fO`|KBsX1o>p+6biwT2OG#*gI*p zyAdl!1}7C9pkw+iTM4V4^P2v8tQhfgYm~_~Xf`R*We96%dJs8RkLeB6Q^dr4;3oO( zdql@xo#a&=m@46uF;c#r)?TC^@?5rJyg*U))wB?g2$|@PeFU zyE2l~mI%WIx^fcsYNo$N{bP8Up5+9Gju*5Zu|U~gSf2%e-pfh$ns~U@syud*$^b{a z0zX#I6wAXx(o3-C2fWUxD?4G&Kfd*y$OGksRiXrYiNXovwcfQ8(UaAw)dUNb*qL6e zZQPd4kGJ&b(PlCLX=xWZU{`rPEtFAUsAubsJ7OLeR{^#rueZDOc}6_oC>OLI(1zr3 z*aktp3i_p~^v$a-e%vFthgUtb-Esmz1<+9slT$BNjA(W!ot%%JN_Y{+11blT3!JKEi${`i5Up5c3*2Vh(m)~nxedKh*!LE|hN>00QY=$NC z^cOB9Ee3VjeAZumaNJ&Hs-l znSb#2mig1SoA_2zTxYxyhqz%{zw8i&DzVpE+=Gx%Saf_{LHRM05|l|H51XsSi}R=K_CP0Z*vBWcXZ>!W3CF9q4FP9*~Iuv<5Tc1+jABi-!~MC!bg0*|y0u z>oI*ZfEV=22*2=tN=hSq3rT&vjS6_3USm;i%>WQ~iE!k>8p?^0dd03*%0@Y}c|<^5 zq0?MYKqgge8y-)+E?uHXfrc?xDVX>A+CTMhu8;}>u!9`99JO;c0Le!&k_B1mUsEs0 z4v0g)%eQ;+YIZQ(rR)jl0|x64?`J%$6N5|4ct`x*-Pe7qQ!VDXd`+}FG`mQ6D~8S> z2gF0)q?bejg_Gp<@-mcV9Ut_}C||9R9Yb4ndRlnIJoA|Vlw!o}eFGrO-Bs_$K1gOG z5q4jAhq!*bYxchd{XX<%X$}As5c>357awlPs~Ed5i04V^4B`QD>|ENs@P&)pI4rA1 zUAz=GL+A6D2Vn^Yy4={EmJUqufRIeK0S5c7dcILEsDL_7)@K9#-WGYDQ7@=<4!;QR z*P*zVh$X$caxtXh3*BsLQ1vFr+_{*i>!n+fdlaWNQ*!tURw8btTf?1OvbYcHy06@G z2mNhQkS5CDN=Bc>b-bKbuq>D~AKtWk@!OxG5CP9;S4LzrL5FYuZ-27>KZFxJ2=IX& z{{EATfA}V)R~^Q3kuOh<(|Iu^z)hrROGmF%=rSZo6WQ%^b?xt2N1l!ZtWnN$Dgfd-Ws@9I{j za!40pIcYP5+fr3Sm06|p3a6N>jNR=+^N6hc1a|Il+IA=|wvkn@^6DpVrqbVg6I4we z`kzkKcO4p07zqmcfNM$n=p41N6WI6GA-lCmfVhH(vNiGw^V~=6`?@h;jZW#6uIgT) zO3>p3HV_m8Hk+%{m)7tCPdNfZ8=$6NJCFFS;+6r!uU`JM7Vr@^Up)ySx zuiF7MK4lAu?Z|lTIP4z5{XoC=XukAD?y0m~dI0XN6cK9*y#7h5%FgT+p`U~PKj*6i zXB3@~fqEF5C;3Qv&*S;d(---3l&4^kz8nG^&5Pja+@G!rfiWIp%*{(7o|F1BiZPyz7zsH{#xmZRMYgAB}#e%K;a%kf3mA6Y6aIB!?-R z1ppT^len;3r1@nfxG{GDz=g~tns1ubn From 574af0526748a89db3ae76d808bf1bd443efdd5f Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Fri, 21 Jun 2024 14:59:48 +0900 Subject: [PATCH 098/174] Add prefer travel themes --- .../travel/withaeng/domain/user/UserPreferTravelTheme.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserPreferTravelTheme.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserPreferTravelTheme.kt index 140a481..4413eb2 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserPreferTravelTheme.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserPreferTravelTheme.kt @@ -1,6 +1,6 @@ package com.travel.withaeng.domain.user enum class UserPreferTravelTheme { - PICTURE, FOOD, TOURIST_ATTRACTION, NATURE, CAFE, MUSEUM, - EXHIBITION_HALL, ART_MUSEUM, LOCAL_FESTIVAL, HOTEL_VACATION -} \ No newline at end of file + PICTURE, FOOD, TOURIST_ATTRACTION, NATURE, CAFE, MUSEUM, EXHIBITION_HALL, + ART_MUSEUM, LOCAL_FESTIVAL, HEALING_CARE, SHOPPING, HOTEL_VACATION +} From 2064ed5e4d79618c29b66d9bee3eb19489b43131 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Fri, 21 Jun 2024 16:17:12 +0900 Subject: [PATCH 099/174] Add github workflow for ci on pull requests --- .github/workflows/pr.yml | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 .github/workflows/pr.yml diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml new file mode 100644 index 0000000..f2d48ba --- /dev/null +++ b/.github/workflows/pr.yml @@ -0,0 +1,39 @@ +name: Pull request workflow (build check) + +on: + pull_request: + branches: + - main + - develop + +env: + JASYPT_ENCRYPTOR_PASSWORD: ${{ secrets.JASYPT_ENCRYPTOR_PASSWORD }} + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: 17 + distribution: adopt + + - name: Get CurrentTime + uses: 1466587594/get-current-time@v2 + id: current-time + with: + format: YYYY-MM-DDTHH-mm-ss + utcOffset: "+09:00" + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Build with Gradle + run: ./gradlew build -x test + + - name: Test with Gradle + run: SPRING_PROFILES_ACTIVE=[test] ./gradlew test From b8ae2aea63327b84b5f544bb9be351a99cdf5a73 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Fri, 21 Jun 2024 16:17:39 +0900 Subject: [PATCH 100/174] Add github workflow for delivering application on push develop branch --- .github/workflows/cd.yml | 57 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 .github/workflows/cd.yml diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml new file mode 100644 index 0000000..8bc27ab --- /dev/null +++ b/.github/workflows/cd.yml @@ -0,0 +1,57 @@ +name: Withaeng CD with Gradle, Github Actions + +on: + push: + branches: [ "develop" ] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: 체크아웃 + uses: actions/checkout@v3 + + - name: Gradle 캐싱 + uses: actions/cache@v3 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- + + - name: JDK 17 설치 + uses: actions/setup-java@v3 + with: + java-version: 17 + distribution: adopt + + - name: 빌드 권한 부여 + run: chmod +x ./gradlew + shell: bash + + - name: 프로젝트 빌드 + run: ./gradlew clean build + shell: bash + + - name: Jar 파일 생성 + run: ./gradlew bootJar + + - name: API 빌드 파일 복사 + uses: appleboy/scp-action@master + with: + host: ${{ secrets.EC2_HOST }} + username: ${{ secrets.EC2_USERNAME }} + key: ${{ secrets.EC2_KEY }} + source: "withaeng-api/build/libs/*.jar" + target: "/home/ubuntu/remote" + + - name: API EC2 인스턴스 접속 및 애플리케이션 실행 + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.EC2_HOST }} + username: ${{ secrets.EC2_USERNAME }} + key: ${{ secrets.EC2_KEY }} + script: | + sudo /home/ubuntu/remote/deploy.sh From d1baaf92f028d011095cfcfe8f48cdeb289bfba7 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Tue, 16 Jul 2024 17:25:30 +0900 Subject: [PATCH 101/174] Implement resending email API --- .../auth/AuthApplicationService.kt | 34 +++++++++++++++++-- .../auth/dto/AuthServiceRequestDto.kt | 4 +++ .../controller/auth/AuthController.kt | 24 +++++++++++-- .../controller/auth/dto/AuthRequestDto.kt | 17 +++++++++- .../DeleteValidatingEmailScheduler.kt | 2 +- .../ValidatingEmailRepository.kt | 2 ++ .../validateemail/ValidatingEmailService.kt | 5 +++ 7 files changed, 80 insertions(+), 8 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt index fb26077..b35220b 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt @@ -1,6 +1,12 @@ package com.travel.withaeng.applicationservice.auth -import com.travel.withaeng.applicationservice.auth.dto.* +import com.travel.withaeng.applicationservice.auth.dto.ChangePasswordServiceRequest +import com.travel.withaeng.applicationservice.auth.dto.ResendEmailServiceRequest +import com.travel.withaeng.applicationservice.auth.dto.SendEmailForChangePasswordServiceRequest +import com.travel.withaeng.applicationservice.auth.dto.SignInServiceRequest +import com.travel.withaeng.applicationservice.auth.dto.SignUpServiceRequest +import com.travel.withaeng.applicationservice.auth.dto.UserResponse +import com.travel.withaeng.applicationservice.auth.dto.ValidateEmailServiceRequest import com.travel.withaeng.common.exception.WithaengException import com.travel.withaeng.common.exception.WithaengExceptionType import com.travel.withaeng.domain.user.CreateUserDto @@ -14,7 +20,7 @@ import com.travel.withaeng.security.jwt.JwtAgent import org.springframework.security.crypto.password.PasswordEncoder import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional -import java.util.* +import java.util.UUID @Service @Transactional(readOnly = true) @@ -60,6 +66,27 @@ class AuthApplicationService( return UserResponse(userDto.id, userDto.email, jwtAgent.provide(UserInfo.from(userDto))) } + @Transactional + fun resendEmail(request: ResendEmailServiceRequest) { + val userDto = userService.findByEmailOrNull(request.email) ?: throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = "이메일에 해당하는 유저를 찾을 수 없습니다." + ) + if (userDto.isValidUser()) { + throw WithaengException.of( + type = WithaengExceptionType.INVALID_ACCESS, + message = "이미 인증된 유저입니다." + ) + } + validatingEmailService.deleteAllByUserIdAndEmailType(userDto.id, ValidatingEmailType.VALIDATE_EMAIL) + validatingEmailService.create( + email = userDto.email, + userId = userDto.id, + code = UUID.randomUUID().toString(), + type = ValidatingEmailType.VALIDATE_EMAIL + ) + } + @Transactional fun validateEmail(request: ValidateEmailServiceRequest) { val requestedEmail = request.email @@ -83,11 +110,12 @@ class AuthApplicationService( } @Transactional - fun sendEmailForChangeEmail(request: SendEmailForChangePasswordServiceRequest) { + fun sendEmailForChangingPassword(request: SendEmailForChangePasswordServiceRequest) { val userDto = userService.findByEmailOrNull(request.email) ?: throw WithaengException.of( type = WithaengExceptionType.NOT_EXIST, message = "이메일에 해당하는 유저를 찾을 수 없습니다." ) + validatingEmailService.deleteAllByUserIdAndEmailType(userDto.id, ValidatingEmailType.CHANGE_PASSWORD) validatingEmailService.create( email = userDto.email, userId = userDto.id, diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthServiceRequestDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthServiceRequestDto.kt index ce3a604..7963c23 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthServiceRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthServiceRequestDto.kt @@ -14,6 +14,10 @@ data class SignInServiceRequest( val password: String ) +data class ResendEmailServiceRequest( + val email: String +) + data class ValidateEmailServiceRequest( val email: String, val code: String diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt index d2eb908..cbd3a23 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt @@ -3,10 +3,20 @@ package com.travel.withaeng.controller.auth import com.travel.withaeng.applicationservice.auth.AuthApplicationService import com.travel.withaeng.applicationservice.auth.dto.UserResponse import com.travel.withaeng.common.ApiResponse -import com.travel.withaeng.controller.auth.dto.* +import com.travel.withaeng.controller.auth.dto.ChangePasswordRequest +import com.travel.withaeng.controller.auth.dto.ResendEmailRequest +import com.travel.withaeng.controller.auth.dto.SendEmailForChangePasswordRequest +import com.travel.withaeng.controller.auth.dto.SignInRequest +import com.travel.withaeng.controller.auth.dto.SignUpRequest +import com.travel.withaeng.controller.auth.dto.ValidateEmailRequest +import com.travel.withaeng.controller.auth.dto.toServiceRequest import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.tags.Tag -import org.springframework.web.bind.annotation.* +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.PutMapping +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController @Tag(name = "Auth", description = "인증 API") @RestController @@ -29,6 +39,14 @@ class AuthController(private val authApplicationService: AuthApplicationService) ) } + @Operation(summary = "Re-sending Email API", description = "이메일 재전송 API") + @PostMapping("/re-send") + fun resendEmail(@RequestBody request: ResendEmailRequest): ApiResponse { + return ApiResponse.success( + authApplicationService.resendEmail(request.toServiceRequest()) + ) + } + @Operation(summary = "Validating Email API", description = "이메일 인증 API") @PutMapping("/validate-email") fun validateEmail(@RequestBody request: ValidateEmailRequest): ApiResponse { @@ -39,7 +57,7 @@ class AuthController(private val authApplicationService: AuthApplicationService) @Operation(summary = "Send Mail For Changing Password API", description = "비밀번호 변경을 위한 이메일 전송") @PostMapping("/send-email-for-change-password") fun sendEmailForChangingPassword(@RequestBody request: SendEmailForChangePasswordRequest): ApiResponse { - authApplicationService.sendEmailForChangeEmail(request.toServiceRequest()) + authApplicationService.sendEmailForChangingPassword(request.toServiceRequest()) return ApiResponse.success() } diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/dto/AuthRequestDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/dto/AuthRequestDto.kt index 22bb877..f7c15df 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/dto/AuthRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/dto/AuthRequestDto.kt @@ -1,6 +1,11 @@ package com.travel.withaeng.controller.auth.dto -import com.travel.withaeng.applicationservice.auth.dto.* +import com.travel.withaeng.applicationservice.auth.dto.ChangePasswordServiceRequest +import com.travel.withaeng.applicationservice.auth.dto.ResendEmailServiceRequest +import com.travel.withaeng.applicationservice.auth.dto.SendEmailForChangePasswordServiceRequest +import com.travel.withaeng.applicationservice.auth.dto.SignInServiceRequest +import com.travel.withaeng.applicationservice.auth.dto.SignUpServiceRequest +import com.travel.withaeng.applicationservice.auth.dto.ValidateEmailServiceRequest import io.swagger.v3.oas.annotations.media.Schema import java.time.LocalDate @@ -40,6 +45,16 @@ fun SignInRequest.toServiceRequest(): SignInServiceRequest = SignInServiceReques password = password ) +@Schema(description = "[Request] 이메일 재전송") +data class ResendEmailRequest( + @Schema(description = "재전송 할 이메일") + val email: String +) + +fun ResendEmailRequest.toServiceRequest(): ResendEmailServiceRequest = ResendEmailServiceRequest( + email = email +) + @Schema(description = "[Request] 이메일 인증") data class ValidateEmailRequest( @Schema(description = "이메일 인증 할 이메일") diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/DeleteValidatingEmailScheduler.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/DeleteValidatingEmailScheduler.kt index 404b542..e81fc76 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/DeleteValidatingEmailScheduler.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/DeleteValidatingEmailScheduler.kt @@ -20,7 +20,7 @@ class DeleteValidatingEmailScheduler( @Scheduled(cron = "0 * * * * *") @Async("asyncSchedulerExecutor") @Transactional - fun sendEmail() { + fun deleteEmails() { val now = LocalDateTime.now() log.info("Start deleting validating emails at {}", now) val willDeleteEmails = validatingEmailService.findAllByStatusNot(ValidatingEmailStatus.YET) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailRepository.kt index 87786cb..70d369d 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailRepository.kt @@ -14,4 +14,6 @@ interface ValidatingEmailRepository : JpaRepository { fun updateStatusByIds(ids: Set, status: ValidatingEmailStatus): Int fun deleteAllByUserId(userId: Long) + + fun deleteAllByUserIdAndType(id: Long, status: ValidatingEmailType) } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailService.kt index 08476c4..52cb896 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailService.kt @@ -63,6 +63,11 @@ class ValidatingEmailService( validatingEmailRepository.deleteAllByUserId(userId) } + @Transactional + fun deleteAllByUserIdAndEmailType(userId: Long, emailType: ValidatingEmailType) { + validatingEmailRepository.deleteAllByUserIdAndType(userId, emailType) + } + @Transactional fun updateStatusByIds(ids: Set, status: ValidatingEmailStatus): Int { return validatingEmailRepository.updateStatusByIds(ids, status) From 4c28783fde8ec0f368efbe88a2377e30b4908e71 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Fri, 2 Aug 2024 22:13:10 +0900 Subject: [PATCH 102/174] Generate temporary nickname when creating user --- .../auth/AuthApplicationService.kt | 5 +++-- .../auth/UserNicknameUtils.kt | 14 ++++++++++++ .../user/dto/UserResponseDto.kt | 12 ++++++++-- .../user/dto/UserServiceRequestDto.kt | 10 ++++++++- .../user/UserNicknameUtilsTest.kt | 22 +++++++++++++++++++ .../com/travel/withaeng/domain/user/User.kt | 6 +++-- .../withaeng/domain/user/UserService.kt | 2 ++ .../withaeng/domain/user/UserSimpleDto.kt | 3 ++- 8 files changed, 66 insertions(+), 8 deletions(-) create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/UserNicknameUtils.kt create mode 100644 withaeng-api/src/test/kotlin/com/travel/withaeng/applicationservice/user/UserNicknameUtilsTest.kt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt index b35220b..7fe4ff0 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt @@ -45,7 +45,7 @@ class AuthApplicationService( userService.deleteByEmail(userEmail) validatingEmailService.deleteAllByUserId(userDto.id) } - val newUserDto = userService.create(request.toCreateUserDto()) + val newUserDto = userService.create(request.toCreateUserDto(UserNicknameUtils.createTemporaryNickname())) validatingEmailService.create( email = newUserDto.email, userId = newUserDto.id, @@ -157,8 +157,9 @@ class AuthApplicationService( } } - private fun SignUpServiceRequest.toCreateUserDto(): CreateUserDto = CreateUserDto( + private fun SignUpServiceRequest.toCreateUserDto(temporaryNickname: String): CreateUserDto = CreateUserDto( email = email, + nickname = temporaryNickname, password = passwordEncoder.encode(password), birth = birth, isMale = isMale diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/UserNicknameUtils.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/UserNicknameUtils.kt new file mode 100644 index 0000000..0c9c95a --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/UserNicknameUtils.kt @@ -0,0 +1,14 @@ +package com.travel.withaeng.applicationservice.auth + +import java.util.UUID + +object UserNicknameUtils { + + private const val TEMPORARY_NICKNAME_PREFIX = "user-" + private const val TEMPORARY_NICKNAME_SUFFIX_COUNT = 10 + + fun createTemporaryNickname(): String { + val suffix = UUID.randomUUID().toString().replace("-", "").take(TEMPORARY_NICKNAME_SUFFIX_COUNT) + return TEMPORARY_NICKNAME_PREFIX + suffix + } +} diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/dto/UserResponseDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/dto/UserResponseDto.kt index 66a768f..6edd954 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/dto/UserResponseDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/dto/UserResponseDto.kt @@ -1,12 +1,20 @@ package com.travel.withaeng.applicationservice.user.dto -import com.travel.withaeng.domain.user.* +import com.travel.withaeng.domain.user.UserConsumeStyle +import com.travel.withaeng.domain.user.UserDetailsDto +import com.travel.withaeng.domain.user.UserDrinkingType +import com.travel.withaeng.domain.user.UserFoodRestriction +import com.travel.withaeng.domain.user.UserMbti +import com.travel.withaeng.domain.user.UserPreferAccompanyGender +import com.travel.withaeng.domain.user.UserPreferTravelTheme +import com.travel.withaeng.domain.user.UserPreferTravelType +import com.travel.withaeng.domain.user.UserSmokingType import java.time.LocalDate data class UserDetailsResponse( val id: Long, val email: String, - val nickname: String? = null, + val nickname: String, val isMale: Boolean, val birth: LocalDate, val mbti: UserMbti? = null, diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/dto/UserServiceRequestDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/dto/UserServiceRequestDto.kt index 9559d43..576e098 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/dto/UserServiceRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/dto/UserServiceRequestDto.kt @@ -1,6 +1,14 @@ package com.travel.withaeng.applicationservice.user.dto -import com.travel.withaeng.domain.user.* +import com.travel.withaeng.domain.user.AddDetailsUserDto +import com.travel.withaeng.domain.user.UserConsumeStyle +import com.travel.withaeng.domain.user.UserDrinkingType +import com.travel.withaeng.domain.user.UserFoodRestriction +import com.travel.withaeng.domain.user.UserMbti +import com.travel.withaeng.domain.user.UserPreferAccompanyGender +import com.travel.withaeng.domain.user.UserPreferTravelTheme +import com.travel.withaeng.domain.user.UserPreferTravelType +import com.travel.withaeng.domain.user.UserSmokingType data class AddUserDetailsServerRequest ( val userId: Long, diff --git a/withaeng-api/src/test/kotlin/com/travel/withaeng/applicationservice/user/UserNicknameUtilsTest.kt b/withaeng-api/src/test/kotlin/com/travel/withaeng/applicationservice/user/UserNicknameUtilsTest.kt new file mode 100644 index 0000000..b2ef8cf --- /dev/null +++ b/withaeng-api/src/test/kotlin/com/travel/withaeng/applicationservice/user/UserNicknameUtilsTest.kt @@ -0,0 +1,22 @@ +package com.travel.withaeng.applicationservice.user + +import com.travel.withaeng.applicationservice.auth.UserNicknameUtils +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +class UserNicknameUtilsTest { + + @Test + fun createNickname() { + // given + val hyphen = '-' + + // when + val nickname = UserNicknameUtils.createTemporaryNickname() + + // then + assertThat(nickname.contains(hyphen)).isTrue() + assertThat(nickname.count { char -> char == hyphen }).isEqualTo(1) + } + +} diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt index 34571a8..91d9d22 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt @@ -16,8 +16,8 @@ class User( @Column(name = "password", nullable = false) var password: String, - @Column(name = "nickname", nullable = true) - val nickname: String? = null, + @Column(name = "nickname", nullable = false) + var nickname: String, @Column(name = "birth", nullable = false) val birth: LocalDate, @@ -72,12 +72,14 @@ class User( fun create( email: String, + nickname: String, password: String, birth: LocalDate, isMale: Boolean ): User { return User( email = email, + nickname = nickname, password = password, birth = birth, isMale = isMale, diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt index 1fa682b..974f8d5 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt @@ -15,6 +15,7 @@ class UserService(private val userRepository: UserRepository) { return userRepository.save( User.create( email = createUserDto.email, + nickname = createUserDto.nickname, password = createUserDto.password, birth = createUserDto.birth, isMale = createUserDto.isMale @@ -33,6 +34,7 @@ class UserService(private val userRepository: UserRepository) { @Transactional fun addDetails(userId: Long, addDetailsUserDto: AddDetailsUserDto): UserDetailsDto { val user = userRepository.findByIdOrNull(userId).getOrThrow() + addDetailsUserDto.nickname?.let { user.nickname = it } addDetailsUserDto.mbti?.let { user.mbti = it } addDetailsUserDto.preferTravelType?.let { user.preferTravelType = it } addDetailsUserDto.preferTravelThemes?.let { user.preferTravelThemes = it.toSet() } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserSimpleDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserSimpleDto.kt index f590107..eca21da 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserSimpleDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserSimpleDto.kt @@ -18,7 +18,7 @@ data class UserDetailsDto( val id: Long, val email: String, val password: String, - val nickname: String? = null, + val nickname: String, val birth: LocalDate, val isMale: Boolean, val profileImageUrl: String? = null, @@ -68,6 +68,7 @@ fun User.toDetailsDto(): UserDetailsDto = UserDetailsDto( data class CreateUserDto( val email: String, + val nickname: String, val password: String, val birth: LocalDate, val isMale: Boolean From 2c89a1619bc76c391066d7d042220b2df33b67d5 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Fri, 2 Aug 2024 22:26:13 +0900 Subject: [PATCH 103/174] Fix returning accompany reply response fields --- .../AccompanyReplyApplicationService.kt | 27 ++++++++++--------- .../dto/AccompanyReplyResponseDto.kt | 18 ++++++++----- .../user/dto/UserResponseDto.kt | 12 +++++++++ .../accompanyreply/AccompanyReplyDto.kt | 7 +++-- .../AccompanyReplyRepositoryImpl.kt | 5 ++-- .../withaeng/domain/user/UserSimpleDto.kt | 2 +- 6 files changed, 48 insertions(+), 23 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt index 4dbe082..ddf104c 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt @@ -1,12 +1,17 @@ package com.travel.withaeng.applicationservice.accompanyreply -import com.travel.withaeng.applicationservice.accompanyreply.dto.* +import com.travel.withaeng.applicationservice.accompanyreply.dto.AccompanyReplyResponse +import com.travel.withaeng.applicationservice.accompanyreply.dto.CreateAccompanyReplyServiceRequest +import com.travel.withaeng.applicationservice.accompanyreply.dto.PagingAccompanyReplyResponse +import com.travel.withaeng.applicationservice.accompanyreply.dto.UpdateAccompanyReplyServiceRequest +import com.travel.withaeng.applicationservice.accompanyreply.dto.toResponse import com.travel.withaeng.applicationservice.common.PagingResponse import com.travel.withaeng.applicationservice.common.toPaging import com.travel.withaeng.common.exception.WithaengException import com.travel.withaeng.common.exception.WithaengExceptionType import com.travel.withaeng.domain.accompanyreply.AccompanyReplyService import com.travel.withaeng.domain.accompanyreplylike.AccompanyReplyLikeService +import com.travel.withaeng.domain.user.UserService import org.springframework.data.domain.Pageable import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -14,33 +19,30 @@ import org.springframework.transaction.annotation.Transactional @Service @Transactional(readOnly = true) class AccompanyReplyApplicationService( + val userService: UserService, val accompanyReplyService: AccompanyReplyService, val accompanyReplyLikeService: AccompanyReplyLikeService ) { @Transactional fun create(request: CreateAccompanyReplyServiceRequest): AccompanyReplyResponse { + val userSimpleDto = userService.findById(request.userId) return accompanyReplyService.create( accompanyId = request.accompanyId, userId = request.userId, content = request.content, parentId = request.parentId - ).toResponse() - } - - fun findById(accompanyReplyId: Long): AccompanyReplyResponse { - val accompanyReplyDto = accompanyReplyService.findById(accompanyReplyId) - val likeCount = accompanyReplyLikeService.countAccompanyReplyLikeCount(accompanyReplyDto.id) - return accompanyReplyDto.toResponse(likeCount) + ).toResponse(userSimpleDto) } fun search(accompanyId: Long, pageable: Pageable): PagingResponse> { val accompanyReplyPage = accompanyReplyService.search(accompanyId, pageable) val contents = accompanyReplyPage.content - // TODO: Fix getting like count logic for using bulk from single + // TODO: Fix getting like count & user logic for using bulk from single val accompanyReplyResponseList = contents.map { replyDto -> val likeCount = accompanyReplyLikeService.countAccompanyReplyLikeCount(replyDto.id) - replyDto.toResponse(likeCount) + val userSimpleDto = userService.findById(replyDto.userId) + replyDto.toResponse(userSimpleDto, likeCount) } return PagingAccompanyReplyResponse(accompanyReplyResponseList, accompanyReplyPage.toPaging()) } @@ -54,9 +56,10 @@ class AccompanyReplyApplicationService( message = "댓글 작성자가 아닌 사용자가 수정할 수 없습니다." ) } + val userSimpleDto = userService.findById(request.userId) val updated = accompanyReplyService.update(accompanyReplyDto.id, request.content) val likeCount = accompanyReplyLikeService.countAccompanyReplyLikeCount(accompanyReplyDto.id) - return updated.toResponse(likeCount) + return updated.toResponse(userSimpleDto, likeCount) } @Transactional @@ -70,4 +73,4 @@ class AccompanyReplyApplicationService( } accompanyReplyService.delete(accompanyReplyDto.id) } -} \ No newline at end of file +} diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt index db03137..9bae766 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt @@ -2,15 +2,20 @@ package com.travel.withaeng.applicationservice.accompanyreply.dto import com.travel.withaeng.applicationservice.common.Paging import com.travel.withaeng.applicationservice.common.PagingResponse +import com.travel.withaeng.applicationservice.user.dto.UserSimpleResponse +import com.travel.withaeng.applicationservice.user.dto.toSimpleResponse import com.travel.withaeng.domain.accompanyreply.AccompanyReplyDto +import com.travel.withaeng.domain.user.UserSimpleDto +import java.time.LocalDateTime data class AccompanyReplyResponse( val id: Long, + val author: UserSimpleResponse, val accompanyId: Long, val parentId: Long? = null, - val userId: Long, val content: String, - val likeCount: Long = 0L + val likeCount: Long = 0L, + val createdAt: LocalDateTime ) class PagingAccompanyReplyResponse( @@ -22,13 +27,14 @@ class PagingAccompanyReplyResponse( override fun getContent(): List = content } -fun AccompanyReplyDto.toResponse(likeCount: Long = 0L): AccompanyReplyResponse { +fun AccompanyReplyDto.toResponse(userSimpleDto: UserSimpleDto, likeCount: Long = 0L): AccompanyReplyResponse { return AccompanyReplyResponse( id = id, accompanyId = accompanyId, parentId = parentId, - userId = userId, + author = userSimpleDto.toSimpleResponse(), content = content, - likeCount = likeCount + likeCount = likeCount, + createdAt = createdAt ) -} \ No newline at end of file +} diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/dto/UserResponseDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/dto/UserResponseDto.kt index 6edd954..ec79c59 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/dto/UserResponseDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/dto/UserResponseDto.kt @@ -8,6 +8,7 @@ import com.travel.withaeng.domain.user.UserMbti import com.travel.withaeng.domain.user.UserPreferAccompanyGender import com.travel.withaeng.domain.user.UserPreferTravelTheme import com.travel.withaeng.domain.user.UserPreferTravelType +import com.travel.withaeng.domain.user.UserSimpleDto import com.travel.withaeng.domain.user.UserSmokingType import java.time.LocalDate @@ -47,3 +48,14 @@ data class UserDetailsResponse( } } +data class UserSimpleResponse( + val id: Long, + val email: String, + val nickname: String +) + +fun UserSimpleDto.toSimpleResponse(): UserSimpleResponse = UserSimpleResponse( + id = id, + email = email, + nickname = nickname +) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt index 417a55e..0fd8a4d 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt @@ -1,13 +1,15 @@ package com.travel.withaeng.domain.accompanyreply import com.querydsl.core.annotations.QueryProjection +import java.time.LocalDateTime data class AccompanyReplyDto @QueryProjection constructor( val id: Long, val userId: Long, val accompanyId: Long, val parentId: Long? = null, - val content: String + val content: String, + val createdAt: LocalDateTime ) fun AccompanyReply.toDto(): AccompanyReplyDto = AccompanyReplyDto( @@ -15,5 +17,6 @@ fun AccompanyReply.toDto(): AccompanyReplyDto = AccompanyReplyDto( userId = userId, accompanyId = accompanyId, parentId = parentId, - content = content + content = content, + createdAt = createdAt ) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryImpl.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryImpl.kt index ad8b127..f732efd 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryImpl.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryImpl.kt @@ -18,7 +18,8 @@ class AccompanyReplyRepositoryImpl( accompanyReply.userId, accompanyReply.accompanyId, accompanyReply.parentId, - accompanyReply.content + accompanyReply.content, + accompanyReply.createdAt ) ) .from(accompanyReply) @@ -36,4 +37,4 @@ class AccompanyReplyRepositoryImpl( private fun accompanyIdEq(accompanyId: Long): BooleanExpression? { return accompanyReply.accompanyId.eq(accompanyId) } -} \ No newline at end of file +} diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserSimpleDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserSimpleDto.kt index eca21da..238e48d 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserSimpleDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserSimpleDto.kt @@ -6,7 +6,7 @@ data class UserSimpleDto( val id: Long, val email: String, val password: String, - val nickname: String? = null, + val nickname: String, val birth: LocalDate, val isMale: Boolean, val profileImageUrl: String? = null, From 43c8aa272fdd4a21ab7e80111dd1faa81376e4ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Wed, 7 Aug 2024 17:11:09 +0900 Subject: [PATCH 104/174] =?UTF-8?q?Feature:=20=EB=8F=99=ED=96=89=20?= =?UTF-8?q?=EB=8C=80=EB=8C=93=EA=B8=80=20=EC=88=98=EC=A0=95=20API=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AccompanyReplyApplicationService.kt | 39 ++++++---- .../dto/AccompanyReplyServiceRequestDto.kt | 3 +- .../AccompanyReplyController.kt | 78 +++++++++++++------ .../dto/AccompanyReplyRequestDto.kt | 6 +- .../domain/accompanyreply/AccompanyReply.kt | 6 ++ .../accompanyreply/AccompanyReplyService.kt | 22 +++++- 6 files changed, 110 insertions(+), 44 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt index ddf104c..3ddecce 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt @@ -1,10 +1,6 @@ package com.travel.withaeng.applicationservice.accompanyreply -import com.travel.withaeng.applicationservice.accompanyreply.dto.AccompanyReplyResponse -import com.travel.withaeng.applicationservice.accompanyreply.dto.CreateAccompanyReplyServiceRequest -import com.travel.withaeng.applicationservice.accompanyreply.dto.PagingAccompanyReplyResponse -import com.travel.withaeng.applicationservice.accompanyreply.dto.UpdateAccompanyReplyServiceRequest -import com.travel.withaeng.applicationservice.accompanyreply.dto.toResponse +import com.travel.withaeng.applicationservice.accompanyreply.dto.* import com.travel.withaeng.applicationservice.common.PagingResponse import com.travel.withaeng.applicationservice.common.toPaging import com.travel.withaeng.common.exception.WithaengException @@ -40,7 +36,7 @@ class AccompanyReplyApplicationService( val contents = accompanyReplyPage.content // TODO: Fix getting like count & user logic for using bulk from single val accompanyReplyResponseList = contents.map { replyDto -> - val likeCount = accompanyReplyLikeService.countAccompanyReplyLikeCount(replyDto.id) + val likeCount = countAccompanyReplyLikeCount(replyDto.id) val userSimpleDto = userService.findById(replyDto.userId) replyDto.toResponse(userSimpleDto, likeCount) } @@ -50,13 +46,8 @@ class AccompanyReplyApplicationService( @Transactional fun update(request: UpdateAccompanyReplyServiceRequest): AccompanyReplyResponse { val accompanyReplyDto = accompanyReplyService.findById(request.accompanyReplyId) - if (accompanyReplyDto.userId != request.userId) { - throw WithaengException.of( - type = WithaengExceptionType.ACCESS_DENIED, - message = "댓글 작성자가 아닌 사용자가 수정할 수 없습니다." - ) - } val userSimpleDto = userService.findById(request.userId) + validateCreator(accompanyReplyDto.userId, request.userId) val updated = accompanyReplyService.update(accompanyReplyDto.id, request.content) val likeCount = accompanyReplyLikeService.countAccompanyReplyLikeCount(accompanyReplyDto.id) return updated.toResponse(userSimpleDto, likeCount) @@ -65,12 +56,30 @@ class AccompanyReplyApplicationService( @Transactional fun delete(userId: Long, accompanyReplyId: Long) { val accompanyReplyDto = accompanyReplyService.findById(accompanyReplyId) - if (accompanyReplyDto.userId != userId) { + validateCreator(accompanyReplyDto.userId, userId) + accompanyReplyService.delete(accompanyReplyDto.id) + } + + @Transactional + fun updateSubReply(request: UpdateAccompanyReplyServiceRequest): AccompanyReplyResponse { + val accompanyReplyDto = accompanyReplyService.findById(request.accompanyReplyId) + validateCreator(accompanyReplyDto.userId, request.userId) + val updated = + accompanyReplyService.updateSubReply(accompanyReplyDto.id, accompanyReplyDto.parentId!!, request.content) + val likeCount = countAccompanyReplyLikeCount(accompanyReplyDto.id) + val userSimpleDto = userService.findById(request.userId) + return updated.toResponse(userSimpleDto, likeCount) + } + + private fun countAccompanyReplyLikeCount(replyId: Long) = + accompanyReplyLikeService.countAccompanyReplyLikeCount(replyId) + + private fun validateCreator(requestUserId: Long, createUserId: Long) { + if (requestUserId != createUserId) { throw WithaengException.of( type = WithaengExceptionType.ACCESS_DENIED, - message = "댓글 작성자가 아닌 사용자가 삭제할 수 없습니다." + message = "댓글 작성자가 아닌 사용자가 수정할 수 없습니다." ) } - accompanyReplyService.delete(accompanyReplyDto.id) } } diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyServiceRequestDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyServiceRequestDto.kt index 006bbe6..5b91385 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyServiceRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyServiceRequestDto.kt @@ -11,5 +11,6 @@ data class UpdateAccompanyReplyServiceRequest( val accompanyReplyId: Long, val userId: Long, val accompanyId: Long, - val content: String + val content: String, + val parentId: Long? = null ) \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt index 5ee6242..7a36bc3 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt @@ -18,7 +18,9 @@ import org.springframework.web.bind.annotation.* @Tag(name = "Accompany Reply", description = "동행 댓글 API") @RestController @RequestMapping("/api/v1/accompany") -class AccompanyReplyController(private val accompanyReplyApplicationService: AccompanyReplyApplicationService) { +class AccompanyReplyController( + private val accompanyReplyApplicationService: AccompanyReplyApplicationService +) { @Operation( summary = "Create Accompany Reply API", @@ -42,30 +44,6 @@ class AccompanyReplyController(private val accompanyReplyApplicationService: Acc ) } - @Operation( - summary = "Reply Accompany Reply API", - description = "동행 댓글의 댓글 생성 API", - security = [SecurityRequirement(name = "Authorization")] - ) - @PostMapping("/{accompanyId}/reply/{replyId}") - @ResponseStatus(HttpStatus.CREATED) - fun reply( - @GetAuth userInfo: UserInfo, - @PathVariable("accompanyId") accompanyId: Long, - @PathVariable("replyId") replyId: Long, - @RequestBody request: CreateAccompanyReplyRequest - ): ApiResponse { - return ApiResponse.success( - accompanyReplyApplicationService.create( - request.toServiceRequest( - userId = userInfo.id, - accompanyId = accompanyId, - parentId = replyId - ) - ) - ) - } - @Operation(summary = "Retrieve All Accompany Replies API", description = "동행 댓글 조회 API") @GetMapping("/{accompanyId}/reply/search") fun search( @@ -114,4 +92,54 @@ class AccompanyReplyController(private val accompanyReplyApplicationService: Acc accompanyReplyApplicationService.delete(userId = userInfo.id, accompanyReplyId = replyId) ) } + + @Operation( + summary = "Create Accompany Sub Reply API", + description = "동행 댓글의 댓글 생성 API", + security = [SecurityRequirement(name = "Authorization")] + ) + @PostMapping("/{accompanyId}/reply/{replyId}") + @ResponseStatus(HttpStatus.CREATED) + fun createSubReply( + @GetAuth userInfo: UserInfo, + @PathVariable("accompanyId") accompanyId: Long, + @PathVariable("replyId") replyId: Long, + @RequestBody request: CreateAccompanyReplyRequest + ): ApiResponse { + return ApiResponse.success( + accompanyReplyApplicationService.create( + request.toServiceRequest( + userId = userInfo.id, + accompanyId = accompanyId, + parentId = replyId + ) + ) + ) + } + + @Operation( + summary = "Update Accompany Sub Reply API", + description = "동행 댓글의 댓글 수정 API", + security = [SecurityRequirement(name = "Authorization")] + ) + @PutMapping("/{accompanyId}/reply/{replyId}/{subReplyId}") + fun updateSubReply( + @GetAuth userInfo: UserInfo, + @PathVariable("accompanyId") accompanyId: Long, + @PathVariable("replyId") replyId: Long, + @PathVariable("subReplyId") subReplyId: Long, + @RequestBody request: UpdateAccompanyReplyRequest + ): ApiResponse { + return ApiResponse.success( + accompanyReplyApplicationService.updateSubReply( + request.toServiceRequest( + userId = userInfo.id, + accompanyId = accompanyId, + accompanyReplyId = subReplyId, + parentId = replyId, + ) + ) + ) + } + } \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/dto/AccompanyReplyRequestDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/dto/AccompanyReplyRequestDto.kt index 6210164..5712d32 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/dto/AccompanyReplyRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/dto/AccompanyReplyRequestDto.kt @@ -31,10 +31,12 @@ data class UpdateAccompanyReplyRequest( fun UpdateAccompanyReplyRequest.toServiceRequest( userId: Long, accompanyId: Long, - accompanyReplyId: Long + accompanyReplyId: Long, + parentId: Long? = null ): UpdateAccompanyReplyServiceRequest = UpdateAccompanyReplyServiceRequest( accompanyReplyId = accompanyReplyId, userId = userId, accompanyId = accompanyId, - content = content + content = content, + parentId = parentId, ) \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt index bbbdbf6..9780bd1 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt @@ -34,4 +34,10 @@ class AccompanyReply( ) } } + + fun updateAccompanyReply( + newContent: String + ) { + this.content = newContent + } } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt index 2686a03..caa0422 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt @@ -62,7 +62,7 @@ class AccompanyReplyService( type = WithaengExceptionType.NOT_EXIST, message = "해당하는 댓글을 찾을 수 없습니다." ) - accompanyReply.content = content + accompanyReply.updateAccompanyReply(content) return accompanyReply.toDto() } @@ -74,4 +74,24 @@ class AccompanyReplyService( ) accompanyReplyRepository.delete(accompanyReply) } + + @Transactional + fun updateSubReply(replyId: Long, parentId: Long, content: String, ): AccompanyReplyDto { + val accompanySubReply = accompanyReplyRepository.findByIdOrNull(replyId) ?: throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = "해당하는 댓글을 찾을 수 없습니다." + ) + validateSubReply(accompanySubReply, parentId) + accompanySubReply.updateAccompanyReply(content) + return accompanySubReply.toDto() + } + + private fun validateSubReply(accompanyReply: AccompanyReply, parentId: Long) { + if (accompanyReply.parentId != parentId) { + throw WithaengException.of( + type = WithaengExceptionType.INVALID_INPUT, + message = "해당 댓글에 대한 대댓글이 아닙니다." + ) + } + } } \ No newline at end of file From c0603a04c250ddd7663ef48a13abe32a2c6e8248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Tue, 13 Aug 2024 17:35:05 +0900 Subject: [PATCH 105/174] =?UTF-8?q?Refactor:=20#32=20=EB=A6=AC=EB=B7=B0=20?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AccompanyReplyApplicationService.kt | 50 ++++++++++++------- .../AccompanyReplyController.kt | 2 +- .../accompanyreply/AccompanyReplyService.kt | 19 ------- 3 files changed, 34 insertions(+), 37 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt index 3ddecce..748e027 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt @@ -5,6 +5,7 @@ import com.travel.withaeng.applicationservice.common.PagingResponse import com.travel.withaeng.applicationservice.common.toPaging import com.travel.withaeng.common.exception.WithaengException import com.travel.withaeng.common.exception.WithaengExceptionType +import com.travel.withaeng.domain.accompanyreply.AccompanyReplyDto import com.travel.withaeng.domain.accompanyreply.AccompanyReplyService import com.travel.withaeng.domain.accompanyreplylike.AccompanyReplyLikeService import com.travel.withaeng.domain.user.UserService @@ -36,7 +37,7 @@ class AccompanyReplyApplicationService( val contents = accompanyReplyPage.content // TODO: Fix getting like count & user logic for using bulk from single val accompanyReplyResponseList = contents.map { replyDto -> - val likeCount = countAccompanyReplyLikeCount(replyDto.id) + val likeCount = accompanyReplyLikeService.countAccompanyReplyLikeCount(replyDto.id) val userSimpleDto = userService.findById(replyDto.userId) replyDto.toResponse(userSimpleDto, likeCount) } @@ -47,8 +48,11 @@ class AccompanyReplyApplicationService( fun update(request: UpdateAccompanyReplyServiceRequest): AccompanyReplyResponse { val accompanyReplyDto = accompanyReplyService.findById(request.accompanyReplyId) val userSimpleDto = userService.findById(request.userId) - validateCreator(accompanyReplyDto.userId, request.userId) - val updated = accompanyReplyService.update(accompanyReplyDto.id, request.content) + validateUpdate(request, accompanyReplyDto) + val updated = accompanyReplyService.update( + replyId = accompanyReplyDto.id, + content = request.content, + ) val likeCount = accompanyReplyLikeService.countAccompanyReplyLikeCount(accompanyReplyDto.id) return updated.toResponse(userSimpleDto, likeCount) } @@ -60,26 +64,38 @@ class AccompanyReplyApplicationService( accompanyReplyService.delete(accompanyReplyDto.id) } - @Transactional - fun updateSubReply(request: UpdateAccompanyReplyServiceRequest): AccompanyReplyResponse { - val accompanyReplyDto = accompanyReplyService.findById(request.accompanyReplyId) + private fun validateUpdate(request: UpdateAccompanyReplyServiceRequest, accompanyReplyDto: AccompanyReplyDto) { validateCreator(accompanyReplyDto.userId, request.userId) - val updated = - accompanyReplyService.updateSubReply(accompanyReplyDto.id, accompanyReplyDto.parentId!!, request.content) - val likeCount = countAccompanyReplyLikeCount(accompanyReplyDto.id) - val userSimpleDto = userService.findById(request.userId) - return updated.toResponse(userSimpleDto, likeCount) + validateSubReply(accompanyReplyDto.parentId, request.parentId) + if (request.parentId != null) { + validateParentId(request.parentId, accompanyReplyDto.parentId) + } } - private fun countAccompanyReplyLikeCount(replyId: Long) = - accompanyReplyLikeService.countAccompanyReplyLikeCount(replyId) - - private fun validateCreator(requestUserId: Long, createUserId: Long) { - if (requestUserId != createUserId) { + private fun validateCreator(createUserId: Long, requestUserId: Long) { + if (createUserId != requestUserId) { throw WithaengException.of( type = WithaengExceptionType.ACCESS_DENIED, - message = "댓글 작성자가 아닌 사용자가 수정할 수 없습니다." ) } } + + private fun validateSubReply(parentId: Long?, requestParentId: Long?) { + if (requestParentId == null && parentId != null) { + throw WithaengException.of( + type = WithaengExceptionType.INVALID_INPUT, + message = "댓글이 아닙니다." + ) + } + } + + private fun validateParentId(parentId: Long, requestParentId: Long?) { + if (parentId != requestParentId) { + throw WithaengException.of( + type = WithaengExceptionType.INVALID_INPUT, + message = "해당 댓글에 대한 대댓글이 아닙니다." + ) + } + } + } diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt index 7a36bc3..8031042 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt @@ -131,7 +131,7 @@ class AccompanyReplyController( @RequestBody request: UpdateAccompanyReplyRequest ): ApiResponse { return ApiResponse.success( - accompanyReplyApplicationService.updateSubReply( + accompanyReplyApplicationService.update( request.toServiceRequest( userId = userInfo.id, accompanyId = accompanyId, diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt index caa0422..c884211 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt @@ -75,23 +75,4 @@ class AccompanyReplyService( accompanyReplyRepository.delete(accompanyReply) } - @Transactional - fun updateSubReply(replyId: Long, parentId: Long, content: String, ): AccompanyReplyDto { - val accompanySubReply = accompanyReplyRepository.findByIdOrNull(replyId) ?: throw WithaengException.of( - type = WithaengExceptionType.NOT_EXIST, - message = "해당하는 댓글을 찾을 수 없습니다." - ) - validateSubReply(accompanySubReply, parentId) - accompanySubReply.updateAccompanyReply(content) - return accompanySubReply.toDto() - } - - private fun validateSubReply(accompanyReply: AccompanyReply, parentId: Long) { - if (accompanyReply.parentId != parentId) { - throw WithaengException.of( - type = WithaengExceptionType.INVALID_INPUT, - message = "해당 댓글에 대한 대댓글이 아닙니다." - ) - } - } } \ No newline at end of file From 9ccbc00f3071fcea4ca7778f568f400c6dbbc62a Mon Sep 17 00:00:00 2001 From: LEE-YOONSEON Date: Tue, 13 Aug 2024 17:44:51 +0900 Subject: [PATCH 106/174] Docs: Create pull_request_template.md --- .github/pull_request_template.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..cffa1e5 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,24 @@ +### 요약 + +### 변경한 부분 + +### 질문 + +### 변경한 결과 + + + +--- + +## PR 유형 + +어떤 변경 사항이 있나요? + +- [ ] 새로운 기능 추가 +- [ ] 버그 수정 +- [ ] 코드에 영향을 주지 않는 변경사항(오타 수정, 탭 사이즈 변경, 변수명 변경, 주석 변경) +- [ ] 코드 리팩토링 +- [ ] 문서 수정 +- [ ] 테스트 추가, 테스트 리팩토링 +- [ ] 파일 혹은 폴더명 수정, 삭제 +- [ ] 배포 관련 From 0ff3c2039c8c6471679b77bd6c4f13454b58c09b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Wed, 14 Aug 2024 02:19:11 +0900 Subject: [PATCH 107/174] =?UTF-8?q?Feature:=20=EB=8F=99=ED=96=89=20?= =?UTF-8?q?=EB=8C=80=EB=8C=93=EA=B8=80=20=EC=82=AD=EC=A0=9C=20API=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AccompanyReplyApplicationService.kt | 25 +++++++++++++++--- .../AccompanyReplyController.kt | 26 ++++++++++++++++++- .../domain/accompanyreply/AccompanyReply.kt | 21 ++++++++++----- .../accompanyreply/AccompanyReplyDto.kt | 6 +++-- .../AccompanyReplyRepositoryImpl.kt | 3 ++- .../accompanyreply/AccompanyReplyService.kt | 2 +- .../accompanyreply/AccompanyReplyStatus.kt | 5 ++++ 7 files changed, 74 insertions(+), 14 deletions(-) create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyStatus.kt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt index 748e027..f76ab37 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt @@ -7,6 +7,7 @@ import com.travel.withaeng.common.exception.WithaengException import com.travel.withaeng.common.exception.WithaengExceptionType import com.travel.withaeng.domain.accompanyreply.AccompanyReplyDto import com.travel.withaeng.domain.accompanyreply.AccompanyReplyService +import com.travel.withaeng.domain.accompanyreply.AccompanyReplyStatus import com.travel.withaeng.domain.accompanyreplylike.AccompanyReplyLikeService import com.travel.withaeng.domain.user.UserService import org.springframework.data.domain.Pageable @@ -58,12 +59,30 @@ class AccompanyReplyApplicationService( } @Transactional - fun delete(userId: Long, accompanyReplyId: Long) { + fun delete(userId: Long, accompanyReplyId: Long, parentId: Long? = null) { val accompanyReplyDto = accompanyReplyService.findById(accompanyReplyId) - validateCreator(accompanyReplyDto.userId, userId) + validateDelete(userId, parentId, accompanyReplyDto) accompanyReplyService.delete(accompanyReplyDto.id) } + private fun validateDelete(requestUserId: Long, requestParentId: Long?, accompanyReplyDto: AccompanyReplyDto) { + validateCreator(accompanyReplyDto.userId, requestUserId) + validateDeletionStatus(accompanyReplyDto.status) + validateSubReply(accompanyReplyDto.parentId, requestParentId) + if (requestParentId != null) { + validateParentId(requestParentId, accompanyReplyDto.parentId) + } + } + + private fun validateDeletionStatus(status: AccompanyReplyStatus) { + if (status == AccompanyReplyStatus.DELETED) { + throw WithaengException.of( + type = WithaengExceptionType.INVALID_INPUT, + message = "삭제된 댓글 입니다." + ) + } + } + private fun validateUpdate(request: UpdateAccompanyReplyServiceRequest, accompanyReplyDto: AccompanyReplyDto) { validateCreator(accompanyReplyDto.userId, request.userId) validateSubReply(accompanyReplyDto.parentId, request.parentId) @@ -81,7 +100,7 @@ class AccompanyReplyApplicationService( } private fun validateSubReply(parentId: Long?, requestParentId: Long?) { - if (requestParentId == null && parentId != null) { + if (parentId != null && requestParentId == null) { throw WithaengException.of( type = WithaengExceptionType.INVALID_INPUT, message = "댓글이 아닙니다." diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt index 8031042..e35c841 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt @@ -89,7 +89,10 @@ class AccompanyReplyController( @PathVariable("replyId") replyId: Long ): ApiResponse { return ApiResponse.success( - accompanyReplyApplicationService.delete(userId = userInfo.id, accompanyReplyId = replyId) + accompanyReplyApplicationService.delete( + userId = userInfo.id, + accompanyReplyId = replyId + ) ) } @@ -142,4 +145,25 @@ class AccompanyReplyController( ) } + @Operation( + summary = "Update Accompany Sub Reply API", + description = "동행 댓글의 댓글 삭제 API", + security = [SecurityRequirement(name = "Authorization")] + ) + @DeleteMapping("/{accompanyId}/reply/{replyId}/{subReplyId}") + fun deleteSubReply( + @GetAuth userInfo: UserInfo, + @PathVariable("accompanyId") accompanyId: Long, + @PathVariable("replyId") replyId: Long, + @PathVariable("subReplyId") subReplyId: Long, + ): ApiResponse { + return ApiResponse.success( + accompanyReplyApplicationService.delete( + userId = userInfo.id, + accompanyReplyId = subReplyId, + parentId = replyId, + ) + ) + } + } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt index 9780bd1..420c570 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt @@ -1,10 +1,9 @@ package com.travel.withaeng.domain.accompanyreply import com.travel.withaeng.domain.BaseEntity -import jakarta.persistence.Column -import jakarta.persistence.Entity -import jakarta.persistence.Table +import jakarta.persistence.* import org.hibernate.annotations.DynamicUpdate +import java.time.LocalDateTime @DynamicUpdate @Table(name = "accompany_reply") @@ -21,16 +20,20 @@ class AccompanyReply( val userId: Long, @Column(name = "content", nullable = false) - var content: String + var content: String, -) : BaseEntity() { + @Enumerated(EnumType.STRING) + var status: AccompanyReplyStatus, + + ) : BaseEntity() { companion object { fun create(accompanyId: Long, userId: Long, content: String, parentId: Long? = null): AccompanyReply { return AccompanyReply( accompanyId = accompanyId, userId = userId, content = content, - parentId = parentId + parentId = parentId, + status = AccompanyReplyStatus.ACTIVE ) } } @@ -40,4 +43,10 @@ class AccompanyReply( ) { this.content = newContent } + + fun delete() { + this.deletedAt = LocalDateTime.now() + this.status = AccompanyReplyStatus.DELETED + } + } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt index 0fd8a4d..c1cda2f 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt @@ -9,7 +9,8 @@ data class AccompanyReplyDto @QueryProjection constructor( val accompanyId: Long, val parentId: Long? = null, val content: String, - val createdAt: LocalDateTime + val createdAt: LocalDateTime, + val status: AccompanyReplyStatus, ) fun AccompanyReply.toDto(): AccompanyReplyDto = AccompanyReplyDto( @@ -18,5 +19,6 @@ fun AccompanyReply.toDto(): AccompanyReplyDto = AccompanyReplyDto( accompanyId = accompanyId, parentId = parentId, content = content, - createdAt = createdAt + createdAt = createdAt, + status = status, ) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryImpl.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryImpl.kt index f732efd..7cd824d 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryImpl.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryImpl.kt @@ -19,7 +19,8 @@ class AccompanyReplyRepositoryImpl( accompanyReply.accompanyId, accompanyReply.parentId, accompanyReply.content, - accompanyReply.createdAt + accompanyReply.createdAt, + accompanyReply.status, ) ) .from(accompanyReply) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt index c884211..4ae9a35 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt @@ -72,7 +72,7 @@ class AccompanyReplyService( type = WithaengExceptionType.NOT_EXIST, message = "해당하는 댓글을 찾을 수 없습니다." ) - accompanyReplyRepository.delete(accompanyReply) + accompanyReply.delete() } } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyStatus.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyStatus.kt new file mode 100644 index 0000000..8e42d87 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyStatus.kt @@ -0,0 +1,5 @@ +package com.travel.withaeng.domain.accompanyreply + +enum class AccompanyReplyStatus { + ACTIVE, DELETED +} \ No newline at end of file From e6a65ed6b0a811bd3c085f645685e034297b7680 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Wed, 14 Aug 2024 02:20:23 +0900 Subject: [PATCH 108/174] =?UTF-8?q?Chore:=20=EB=8F=99=ED=96=89=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=20update=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt | 2 +- .../withaeng/domain/accompanyreply/AccompanyReplyService.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt index 420c570..d02e3f1 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt @@ -38,7 +38,7 @@ class AccompanyReply( } } - fun updateAccompanyReply( + fun update( newContent: String ) { this.content = newContent diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt index 4ae9a35..54ece88 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt @@ -62,7 +62,7 @@ class AccompanyReplyService( type = WithaengExceptionType.NOT_EXIST, message = "해당하는 댓글을 찾을 수 없습니다." ) - accompanyReply.updateAccompanyReply(content) + accompanyReply.update(content) return accompanyReply.toDto() } From 1bf24f82a5018c114a1eb0fc2e5bacc5df206016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Wed, 14 Aug 2024 02:51:50 +0900 Subject: [PATCH 109/174] =?UTF-8?q?Feature:=20=EB=8F=99=ED=96=89=20?= =?UTF-8?q?=EC=97=94=ED=8B=B0=ED=8B=B0=20status=20=ED=95=84=EB=93=9C=20non?= =?UTF-8?q?-nullable=20=EC=A1=B0=EA=B1=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt index d02e3f1..0a55ebb 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt @@ -23,6 +23,7 @@ class AccompanyReply( var content: String, @Enumerated(EnumType.STRING) + @Column(name = "status", nullable = false) var status: AccompanyReplyStatus, ) : BaseEntity() { From 902a09525b8e317623f054b983bfb18150e4518d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Wed, 21 Aug 2024 03:22:45 +0900 Subject: [PATCH 110/174] =?UTF-8?q?Chore:=20=EB=8F=99=ED=96=89=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=20@Comment=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../travel/withaeng/domain/accompany/Accompany.kt | 14 +++++++++++++- .../domain/accompany/AccompanyDestination.kt | 4 ++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt index 0c11af6..423fdef 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt @@ -3,51 +3,63 @@ package com.travel.withaeng.domain.accompany import com.travel.withaeng.converter.TagIdsConverter import com.travel.withaeng.domain.BaseEntity import jakarta.persistence.* +import org.hibernate.annotations.Comment import org.hibernate.annotations.DynamicUpdate import java.time.LocalDate @DynamicUpdate -@Table(name = "accompany") @Entity +@Table(name = "accompany") class Accompany( @Column(name = "user_id", nullable = false) val userId: Long, @Column(name = "title", nullable = false) + @Comment("동행 제목") var title: String, @Lob @Column(name = "content", nullable = false) + @Comment("동행 내용") var content: String, @Enumerated(EnumType.STRING) @Column(name = "accompany_status", nullable = false) + @Comment("동행 모집 상태") var accompanyStatus: AccompanyStatus = AccompanyStatus.ING, @Column(name = "start_trip_date", nullable = false) + @Comment("여행 시작 일자") var startTripDate: LocalDate, @Column(name = "end_trip_date", nullable = false) + @Comment("여행 종료 일자") var endTripDate: LocalDate, @Column(name = "banner_image_url") + @Comment("베너 이미지 URI") var bannerImageUrl: String?, @Column(name = "member_count", nullable = false) + @Comment("모집 인원") var memberCount: Long = 0L, @Column(name = "view_count", nullable = false) + @Comment("조회수") var viewCount: Long = 0L, @Column(name = "open_kakao_url", nullable = false) + @Comment("오픈 카카오 채팅 URI") var openKakaoUrl: String, @Embedded + @Comment("동행 장소 정보") var accompanyDestination: AccompanyDestination, @Convert(converter = TagIdsConverter::class) @Column(name = "tag_ids", nullable = false) + @Comment("태그 목록") var tagIds: Set = setOf() ) : BaseEntity() { diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestination.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestination.kt index 84725f7..dddc1fc 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestination.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestination.kt @@ -4,18 +4,22 @@ import jakarta.persistence.Column import jakarta.persistence.Embeddable import jakarta.persistence.EnumType import jakarta.persistence.Enumerated +import org.hibernate.annotations.Comment @Embeddable data class AccompanyDestination( @Enumerated(EnumType.STRING) @Column(name = "continent") + @Comment("대륙") val continent: Continent, @Enumerated(EnumType.STRING) @Column(name = "country") + @Comment("국가") val country: Country, @Enumerated(EnumType.STRING) @Column(name = "city") + @Comment("도시") val city: City ) \ No newline at end of file From aa272c2a21b11b74e00443222a961f4b760964bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Wed, 21 Aug 2024 17:37:11 +0900 Subject: [PATCH 111/174] =?UTF-8?q?Feature:=20=EB=8F=99=ED=96=89=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D,=20=EC=83=81=EC=84=B8=EC=A1=B0=ED=9A=8C=20'?= =?UTF-8?q?=EB=8F=99=ED=96=89=20=EC=97=B0=EB=A0=B9'=20=ED=95=84=EB=93=9C?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../accompany/dto/AccompanyResponseDto.kt | 8 +++- .../dto/AccompanyServiceRequestDto.kt | 10 +++-- .../common/ControllerExceptionAdvice.kt | 17 ++++++++ .../accompany/dto/AccompanyRequestDto.kt | 17 +++++++- .../common/exception/WithaengExceptionType.kt | 5 +++ .../withaeng/domain/accompany/Accompany.kt | 10 +++++ .../withaeng/domain/accompany/AccompanyAge.kt | 40 +++++++++++++++++++ .../withaeng/domain/accompany/AccompanyDto.kt | 12 ++++-- 8 files changed, 109 insertions(+), 10 deletions(-) create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyAge.kt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyResponseDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyResponseDto.kt index dcc005e..f78abac 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyResponseDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyResponseDto.kt @@ -17,7 +17,9 @@ data class AccompanyResponse( val viewCount: Long, val likeCount: Long, val tagIds: List? = null, - val openKakaoUrl: String? = null + val openKakaoUrl: String? = null, + val startAccompanyAge: Int, + val endAccompanyAge: Int, ) fun AccompanyDto.toAccompanyResponse(likeCount: Long): AccompanyResponse = AccompanyResponse( @@ -32,5 +34,7 @@ fun AccompanyDto.toAccompanyResponse(likeCount: Long): AccompanyResponse = Accom memberCount = memberCount, viewCount = viewCount, likeCount = likeCount, - openKakaoUrl = openKakaoUrl + openKakaoUrl = openKakaoUrl, + startAccompanyAge = startAccompanyAge.value, + endAccompanyAge = endAccompanyAge.value, ) \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt index 279ebf5..d629b75 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt @@ -15,7 +15,9 @@ data class CreateAccompanyServiceRequest( val bannerImageUrl: String? = null, val memberCount: Long, val tagIds: List? = null, - val openKakaoUrl: String + val openKakaoUrl: String, + val startAccompanyAge: AccompanyAge, + val endAccompanyAge: AccompanyAge, ) fun CreateAccompanyServiceRequest.toDomainDto(): CreateAccompanyDto = CreateAccompanyDto( @@ -32,7 +34,9 @@ fun CreateAccompanyServiceRequest.toDomainDto(): CreateAccompanyDto = CreateAcco bannerImageUrl = bannerImageUrl, memberCount = memberCount, tagIds = tagIds?.toSet(), - openKakaoUrl = openKakaoUrl + openKakaoUrl = openKakaoUrl, + startAccompanyAge = startAccompanyAge, + endAccompanyAge = endAccompanyAge, ) data class UpdateAccompanyServiceRequest( @@ -65,7 +69,7 @@ fun UpdateAccompanyServiceRequest.toDomainDto(): UpdateAccompanyDto { accompanyId = accompanyId, title = title, content = content, - destination =destination, + destination = destination, startTripDate = startTripDate, endTripDate = endTripDate, bannerImageUrl = bannerImageUrl, diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ControllerExceptionAdvice.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ControllerExceptionAdvice.kt index fe64f88..e688510 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ControllerExceptionAdvice.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ControllerExceptionAdvice.kt @@ -1,11 +1,13 @@ package com.travel.withaeng.common +import com.fasterxml.jackson.databind.JsonMappingException import com.travel.withaeng.common.exception.WithaengException import com.travel.withaeng.common.exception.WithaengExceptionType import org.slf4j.Logger import org.slf4j.LoggerFactory import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity +import org.springframework.http.converter.HttpMessageNotReadableException import org.springframework.validation.BindException import org.springframework.web.HttpRequestMethodNotSupportedException import org.springframework.web.bind.MethodArgumentNotValidException @@ -68,6 +70,21 @@ class ControllerExceptionAdvice { return errorResponse(WithaengExceptionType.ARGUMENT_NOT_VALID, errorMessage) } + @ExceptionHandler(HttpMessageNotReadableException::class) + protected fun handleHttpMessageNotReadableException(e: HttpMessageNotReadableException): ResponseEntity> { + logger.error("HttpMessageNotReadableException handler", e) + + if (e.cause is JsonMappingException) { + val jsonMappingException = e.cause as JsonMappingException + val fieldName = jsonMappingException.path.getOrNull(0)?.fieldName + return errorResponse( + WithaengExceptionType.INVALID_JSON_FIELD, + "${fieldName} 필드 값이 잘못되었습니다." + ) + } + return errorResponse(WithaengExceptionType.JSON_PARSE_ERROR, "잘못된 데이터가 요청되었습니다.") + } + private fun WithaengException.toApiErrorResponse() = ApiErrorResponse( code = errorCode, message = message, diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/dto/AccompanyRequestDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/dto/AccompanyRequestDto.kt index b81ba87..29ce7f4 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/dto/AccompanyRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/dto/AccompanyRequestDto.kt @@ -1,7 +1,10 @@ package com.travel.withaeng.controller.accompany.dto +import com.fasterxml.jackson.databind.annotation.JsonDeserialize import com.travel.withaeng.applicationservice.accompany.dto.CreateAccompanyServiceRequest import com.travel.withaeng.applicationservice.accompany.dto.UpdateAccompanyServiceRequest +import com.travel.withaeng.domain.accompany.AccompanyAge +import com.travel.withaeng.domain.accompany.AccompanyAgeDeserializer import io.swagger.v3.oas.annotations.media.Schema import java.time.LocalDate @@ -38,7 +41,15 @@ data class CreateAccompanyRequest( val tagIds: List? = null, @Schema(description = "동행 게시글에 게시된 오픈 카카오톡 URL") - val openKakaoUrl: String + val openKakaoUrl: String, + + @Schema(description = "동행 시작 연령(누구나 가능의 경우 0)") + @JsonDeserialize(using = AccompanyAgeDeserializer::class) + val startAccompanyAge: AccompanyAge, + + @Schema(description = "동행 시작 연령(누구나 가능의 경우 99)") + @JsonDeserialize(using = AccompanyAgeDeserializer::class) + val endAccompanyAge: AccompanyAge, ) @Schema(description = "[Request] 동행 게시글 수정") @@ -56,7 +67,9 @@ fun CreateAccompanyRequest.toServiceRequest( bannerImageUrl = bannerImageUrl, memberCount = memberCount, tagIds = tagIds, - openKakaoUrl = openKakaoUrl + openKakaoUrl = openKakaoUrl, + startAccompanyAge = startAccompanyAge, + endAccompanyAge = endAccompanyAge, ) data class UpdateAccompanyRequest( diff --git a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/WithaengExceptionType.kt b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/WithaengExceptionType.kt index 5ec50de..3e6abf7 100644 --- a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/WithaengExceptionType.kt +++ b/withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/WithaengExceptionType.kt @@ -27,6 +27,11 @@ enum class WithaengExceptionType( ACCESS_DENIED("Access denied. Check authentication.", "C007_ACCESS_DENIED", 403), AUTHENTICATION_FAILURE("Authentication failed. Check login.", "C008_AUTHENTICATION_FAILURE", 401), ARGUMENT_NOT_VALID("Method Argument Not Valid. Check argument validation.", "C009_ARGUMENT_NOT_VALID", 400), + JSON_PARSE_ERROR("Request JSON parsing error", "C010_JSON_PARSE_ERROR", 400), + INVALID_JSON_FIELD("Invalid JSON field value", "C011_INVALID_JSON_FIELD", 400), + + // ACCOMPANY + INVALID_ACCOMPANY_AGE_VALUE("Invalid accompany age value", "A001_INVALID_ACCOMPANY_AGE_VALUE", 400), // NOTIFICATION INVALID_NOTIFICATION_TYPE("Invalid Notification Type", "N001_INVALID_NOTIFICATION_TYPE", 500), diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt index 423fdef..1355e01 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt @@ -57,6 +57,14 @@ class Accompany( @Comment("동행 장소 정보") var accompanyDestination: AccompanyDestination, + @Column(name = "start_accompany_age", nullable = false) + @Comment("동행 시작 연령") + var startAccompanyAge: Int, + + @Column(name = "end_accompany_age", nullable = false) + @Comment("동행 종료 연령") + var endAccompanyAge: Int, + @Convert(converter = TagIdsConverter::class) @Column(name = "tag_ids", nullable = false) @Comment("태그 목록") @@ -77,6 +85,8 @@ class Accompany( memberCount = params.memberCount, openKakaoUrl = params.openKakaoUrl, accompanyDestination = params.destination, + startAccompanyAge = params.startAccompanyAge.value, + endAccompanyAge = params.endAccompanyAge.value, tagIds = params.tagIds ?: setOf() ) } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyAge.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyAge.kt new file mode 100644 index 0000000..57b2e70 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyAge.kt @@ -0,0 +1,40 @@ +package com.travel.withaeng.domain.accompany + +import com.fasterxml.jackson.core.JsonParser +import com.fasterxml.jackson.databind.DeserializationContext +import com.fasterxml.jackson.databind.JsonDeserializer +import com.travel.withaeng.common.exception.WithaengException +import com.travel.withaeng.common.exception.WithaengExceptionType + +enum class AccompanyAge( + val code: String, + val value: Int, +) { + MIN("MIN", 0), + TWENTY("TWENTY", 20), + TWENTY_FIVE("TWENTYFIVE", 25), + THIRTY("THIRTY", 30), + THIRTY_FIVE("THIRTYFIVE", 35), + FORTY("FORTY", 40), + FORTY_FIVE("FORTYFIVE", 45), + OVER_FIFTY("FIFTY", 50), + MAX("MAX", 99) + ; + + companion object { + fun fromValue(value: Int): AccompanyAge { + return AccompanyAge.values().find { it.value == value } + ?: throw WithaengException.of( + type = WithaengExceptionType.INVALID_ACCOMPANY_AGE_VALUE, + message = "$value is not a valid value for $this" + ) + } + } +} + +class AccompanyAgeDeserializer : JsonDeserializer() { + override fun deserialize(p: JsonParser, ctxt: DeserializationContext): AccompanyAge { + val value = p.intValue + return AccompanyAge.fromValue(value) + } +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt index a3fa4e9..50f9d3e 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt @@ -12,7 +12,9 @@ data class CreateAccompanyDto( val bannerImageUrl: String? = null, val memberCount: Long, val tagIds: Set? = emptySet(), - val openKakaoUrl: String + val openKakaoUrl: String, + val startAccompanyAge: AccompanyAge, + val endAccompanyAge: AccompanyAge, ) data class UpdateAccompanyDto( @@ -39,7 +41,9 @@ data class AccompanyDto( val bannerImageUrl: String? = null, val memberCount: Long, val viewCount: Long, - val openKakaoUrl: String + val openKakaoUrl: String, + val startAccompanyAge: AccompanyAge, + val endAccompanyAge: AccompanyAge, ) fun Accompany.toDto(): AccompanyDto = AccompanyDto( @@ -53,7 +57,9 @@ fun Accompany.toDto(): AccompanyDto = AccompanyDto( bannerImageUrl = bannerImageUrl, memberCount = memberCount, viewCount = viewCount, - openKakaoUrl = openKakaoUrl + openKakaoUrl = openKakaoUrl, + startAccompanyAge = AccompanyAge.fromValue(startAccompanyAge), + endAccompanyAge = AccompanyAge.fromValue(endAccompanyAge), ) data class SearchAccompanyDto( From 0275c7d440da870e0425191787c24f70926cd024 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Wed, 21 Aug 2024 21:16:51 +0900 Subject: [PATCH 112/174] =?UTF-8?q?Feature:=20=EB=8F=99=ED=96=89=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D,=20=EC=83=81=EC=84=B8=EC=A1=B0=ED=9A=8C=20'?= =?UTF-8?q?=EB=8F=99=ED=96=89=20=EC=84=A0=ED=98=B8=20=EC=84=B1=EB=B3=84'?= =?UTF-8?q?=20=ED=95=84=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../accompany/dto/AccompanyResponseDto.kt | 3 +++ .../accompany/dto/AccompanyServiceRequestDto.kt | 3 +++ .../controller/accompany/dto/AccompanyRequestDto.kt | 5 +++++ .../com/travel/withaeng/domain/accompany/Accompany.kt | 6 ++++++ .../com/travel/withaeng/domain/accompany/AccompanyDto.kt | 4 ++++ 5 files changed, 21 insertions(+) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyResponseDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyResponseDto.kt index f78abac..1debaa0 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyResponseDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyResponseDto.kt @@ -2,6 +2,7 @@ package com.travel.withaeng.applicationservice.accompany.dto import com.travel.withaeng.domain.accompany.AccompanyDestination import com.travel.withaeng.domain.accompany.AccompanyDto +import com.travel.withaeng.domain.user.UserPreferAccompanyGender import java.time.LocalDate data class AccompanyResponse( @@ -20,6 +21,7 @@ data class AccompanyResponse( val openKakaoUrl: String? = null, val startAccompanyAge: Int, val endAccompanyAge: Int, + val preferGender: UserPreferAccompanyGender, ) fun AccompanyDto.toAccompanyResponse(likeCount: Long): AccompanyResponse = AccompanyResponse( @@ -37,4 +39,5 @@ fun AccompanyDto.toAccompanyResponse(likeCount: Long): AccompanyResponse = Accom openKakaoUrl = openKakaoUrl, startAccompanyAge = startAccompanyAge.value, endAccompanyAge = endAccompanyAge.value, + preferGender = preferGender, ) \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt index d629b75..db0ba66 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt @@ -1,6 +1,7 @@ package com.travel.withaeng.applicationservice.accompany.dto import com.travel.withaeng.domain.accompany.* +import com.travel.withaeng.domain.user.UserPreferAccompanyGender import java.time.LocalDate data class CreateAccompanyServiceRequest( @@ -18,6 +19,7 @@ data class CreateAccompanyServiceRequest( val openKakaoUrl: String, val startAccompanyAge: AccompanyAge, val endAccompanyAge: AccompanyAge, + val preferGender: UserPreferAccompanyGender, ) fun CreateAccompanyServiceRequest.toDomainDto(): CreateAccompanyDto = CreateAccompanyDto( @@ -37,6 +39,7 @@ fun CreateAccompanyServiceRequest.toDomainDto(): CreateAccompanyDto = CreateAcco openKakaoUrl = openKakaoUrl, startAccompanyAge = startAccompanyAge, endAccompanyAge = endAccompanyAge, + preferGender = preferGender, ) data class UpdateAccompanyServiceRequest( diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/dto/AccompanyRequestDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/dto/AccompanyRequestDto.kt index 29ce7f4..dd0a10d 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/dto/AccompanyRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/dto/AccompanyRequestDto.kt @@ -5,6 +5,7 @@ import com.travel.withaeng.applicationservice.accompany.dto.CreateAccompanyServi import com.travel.withaeng.applicationservice.accompany.dto.UpdateAccompanyServiceRequest import com.travel.withaeng.domain.accompany.AccompanyAge import com.travel.withaeng.domain.accompany.AccompanyAgeDeserializer +import com.travel.withaeng.domain.user.UserPreferAccompanyGender import io.swagger.v3.oas.annotations.media.Schema import java.time.LocalDate @@ -50,6 +51,9 @@ data class CreateAccompanyRequest( @Schema(description = "동행 시작 연령(누구나 가능의 경우 99)") @JsonDeserialize(using = AccompanyAgeDeserializer::class) val endAccompanyAge: AccompanyAge, + + @Schema(description = "동행 선호 성별") + val preferGender: UserPreferAccompanyGender, ) @Schema(description = "[Request] 동행 게시글 수정") @@ -70,6 +74,7 @@ fun CreateAccompanyRequest.toServiceRequest( openKakaoUrl = openKakaoUrl, startAccompanyAge = startAccompanyAge, endAccompanyAge = endAccompanyAge, + preferGender = preferGender, ) data class UpdateAccompanyRequest( diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt index 1355e01..9bd8c42 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt @@ -2,6 +2,7 @@ package com.travel.withaeng.domain.accompany import com.travel.withaeng.converter.TagIdsConverter import com.travel.withaeng.domain.BaseEntity +import com.travel.withaeng.domain.user.UserPreferAccompanyGender import jakarta.persistence.* import org.hibernate.annotations.Comment import org.hibernate.annotations.DynamicUpdate @@ -65,6 +66,10 @@ class Accompany( @Comment("동행 종료 연령") var endAccompanyAge: Int, + @Column(name = "prefer_gender", nullable = false) + @Comment("동행 희망 성별") + var preferGender: UserPreferAccompanyGender, + @Convert(converter = TagIdsConverter::class) @Column(name = "tag_ids", nullable = false) @Comment("태그 목록") @@ -87,6 +92,7 @@ class Accompany( accompanyDestination = params.destination, startAccompanyAge = params.startAccompanyAge.value, endAccompanyAge = params.endAccompanyAge.value, + preferGender = params.preferGender, tagIds = params.tagIds ?: setOf() ) } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt index 50f9d3e..5cb2d47 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt @@ -1,5 +1,6 @@ package com.travel.withaeng.domain.accompany +import com.travel.withaeng.domain.user.UserPreferAccompanyGender import java.time.LocalDate data class CreateAccompanyDto( @@ -15,6 +16,7 @@ data class CreateAccompanyDto( val openKakaoUrl: String, val startAccompanyAge: AccompanyAge, val endAccompanyAge: AccompanyAge, + val preferGender: UserPreferAccompanyGender, ) data class UpdateAccompanyDto( @@ -44,6 +46,7 @@ data class AccompanyDto( val openKakaoUrl: String, val startAccompanyAge: AccompanyAge, val endAccompanyAge: AccompanyAge, + val preferGender: UserPreferAccompanyGender, ) fun Accompany.toDto(): AccompanyDto = AccompanyDto( @@ -60,6 +63,7 @@ fun Accompany.toDto(): AccompanyDto = AccompanyDto( openKakaoUrl = openKakaoUrl, startAccompanyAge = AccompanyAge.fromValue(startAccompanyAge), endAccompanyAge = AccompanyAge.fromValue(endAccompanyAge), + preferGender = preferGender ) data class SearchAccompanyDto( From 5ee0da31d5eff5c5eb57b9f53db32aaf8cc1038f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Thu, 22 Aug 2024 00:54:31 +0900 Subject: [PATCH 113/174] =?UTF-8?q?Fix:=20=EB=8F=99=ED=96=89=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EB=88=84=EB=9D=BD=20=EC=BB=AC=EB=9F=BC=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 --- .../accompany/dto/AccompanyResponseDto.kt | 3 +- .../dto/AccompanyServiceRequestDto.kt | 14 +++++--- .../accompany/AccompanyController.kt | 4 ++- .../accompany/dto/AccompanyRequestDto.kt | 22 ++++++++++--- .../withaeng/domain/accompany/Accompany.kt | 32 +++++++++++++++++-- .../withaeng/domain/accompany/AccompanyDto.kt | 25 +++++++-------- .../domain/accompany/AccompanyService.kt | 28 +++++++++------- 7 files changed, 90 insertions(+), 38 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyResponseDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyResponseDto.kt index 1debaa0..257a85e 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyResponseDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyResponseDto.kt @@ -17,7 +17,7 @@ data class AccompanyResponse( val memberCount: Long, val viewCount: Long, val likeCount: Long, - val tagIds: List? = null, + val tagIds: Set? = null, val openKakaoUrl: String? = null, val startAccompanyAge: Int, val endAccompanyAge: Int, @@ -40,4 +40,5 @@ fun AccompanyDto.toAccompanyResponse(likeCount: Long): AccompanyResponse = Accom startAccompanyAge = startAccompanyAge.value, endAccompanyAge = endAccompanyAge.value, preferGender = preferGender, + tagIds = tagIds, ) \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt index db0ba66..fd837bb 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt @@ -15,7 +15,7 @@ data class CreateAccompanyServiceRequest( val endTripDate: LocalDate, val bannerImageUrl: String? = null, val memberCount: Long, - val tagIds: List? = null, + val tagIds: Set? = emptySet(), val openKakaoUrl: String, val startAccompanyAge: AccompanyAge, val endAccompanyAge: AccompanyAge, @@ -54,8 +54,11 @@ data class UpdateAccompanyServiceRequest( val endTripDate: LocalDate? = null, val bannerImageUrl: String? = null, val memberCount: Long? = null, - val tagIds: List? = null, - val openKakaoUrl: String? = null + val tagIds: Set? = null, + val openKakaoUrl: String? = null, + val startAccompanyAge: AccompanyAge? = null, + val endAccompanyAge: AccompanyAge? = null, + val preferGender: UserPreferAccompanyGender? = null, ) fun UpdateAccompanyServiceRequest.toDomainDto(): UpdateAccompanyDto { @@ -78,7 +81,10 @@ fun UpdateAccompanyServiceRequest.toDomainDto(): UpdateAccompanyDto { bannerImageUrl = bannerImageUrl, memberCount = memberCount, tagIds = tagIds?.toSet(), - openKakaoUrl = openKakaoUrl + openKakaoUrl = openKakaoUrl, + startAccompanyAge = startAccompanyAge, + endAccompanyAge = endAccompanyAge, + preferGender = preferGender, ) } diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/AccompanyController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/AccompanyController.kt index f8f61d5..be19338 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/AccompanyController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/AccompanyController.kt @@ -18,7 +18,9 @@ import org.springframework.web.bind.annotation.* @Tag(name = "Accompany", description = "동행 API") @RestController @RequestMapping("/api/v1/accompany") -class AccompanyController(private val accompanyApplicationService: AccompanyApplicationService) { +class AccompanyController( + private val accompanyApplicationService: AccompanyApplicationService +) { @Operation( summary = "Create Accompany API", diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/dto/AccompanyRequestDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/dto/AccompanyRequestDto.kt index dd0a10d..6462457 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/dto/AccompanyRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/dto/AccompanyRequestDto.kt @@ -39,7 +39,7 @@ data class CreateAccompanyRequest( val memberCount: Long, @Schema(description = "동행 게시글에 부착할 태그 아이디 리스트") - val tagIds: List? = null, + val tagIds: Set? = emptySet(), @Schema(description = "동행 게시글에 게시된 오픈 카카오톡 URL") val openKakaoUrl: String, @@ -106,10 +106,21 @@ data class UpdateAccompanyRequest( val memberCount: Long? = null, @Schema(description = "동행 게시글에 부착할 태그 아이디 리스트") - val tagIds: List? = null, + val tagIds: Set? = null, @Schema(description = "동행 게시글에 게시된 오픈 카카오톡 URL") - val openKakaoUrl: String? = null + val openKakaoUrl: String? = null, + + @Schema(description = "동행 시작 연령(누구나 가능의 경우 0)") + @JsonDeserialize(using = AccompanyAgeDeserializer::class) + val startAccompanyAge: AccompanyAge? = null, + + @Schema(description = "동행 시작 연령(누구나 가능의 경우 99)") + @JsonDeserialize(using = AccompanyAgeDeserializer::class) + val endAccompanyAge: AccompanyAge? = null, + + @Schema(description = "동행 선호 성별") + val preferGender: UserPreferAccompanyGender? = null, ) fun UpdateAccompanyRequest.toServiceRequest( @@ -128,5 +139,8 @@ fun UpdateAccompanyRequest.toServiceRequest( bannerImageUrl = bannerImageUrl, memberCount = memberCount, tagIds = tagIds, - openKakaoUrl = openKakaoUrl + openKakaoUrl = openKakaoUrl, + startAccompanyAge = startAccompanyAge, + endAccompanyAge = endAccompanyAge, + preferGender = preferGender, ) \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt index 9bd8c42..1af2dcf 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt @@ -67,7 +67,7 @@ class Accompany( var endAccompanyAge: Int, @Column(name = "prefer_gender", nullable = false) - @Comment("동행 희망 성별") + @Comment("동행 선호 성별") var preferGender: UserPreferAccompanyGender, @Convert(converter = TagIdsConverter::class) @@ -77,8 +77,35 @@ class Accompany( ) : BaseEntity() { - companion object { + fun update( + title: String?, + content: String?, + startTripDate: LocalDate?, + endTripDate: LocalDate?, + bannerImageUrl: String?, + memberCount: Long?, + openKakaoUrl: String?, + accompanyDestination: AccompanyDestination?, + startAccompanyAge: Int?, + endAccompanyAge: Int?, + preferGender: UserPreferAccompanyGender?, + tagIds: Set? + ) { + this.title = title ?: this.title + this.content = content ?: this.content + this.startTripDate = startTripDate ?: this.startTripDate + this.endTripDate = endTripDate ?: this.endTripDate + this.bannerImageUrl = bannerImageUrl ?: this.bannerImageUrl + this.memberCount = memberCount ?: this.memberCount + this.openKakaoUrl = openKakaoUrl ?: this.openKakaoUrl + this.accompanyDestination = accompanyDestination ?: this.accompanyDestination + this.startAccompanyAge = startAccompanyAge ?: this.startAccompanyAge + this.endAccompanyAge = endAccompanyAge ?: this.endAccompanyAge + this.preferGender = preferGender ?: this.preferGender + this.tagIds = tagIds ?: this.tagIds + } + companion object { fun create(params: CreateAccompanyDto): Accompany { return Accompany( userId = params.userId, @@ -96,6 +123,5 @@ class Accompany( tagIds = params.tagIds ?: setOf() ) } - } } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt index 5cb2d47..d39b15e 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt @@ -29,7 +29,10 @@ data class UpdateAccompanyDto( val bannerImageUrl: String? = null, val memberCount: Long? = null, val tagIds: Set? = null, - val openKakaoUrl: String? = null + val openKakaoUrl: String? = null, + val startAccompanyAge: AccompanyAge? = null, + val endAccompanyAge: AccompanyAge? = null, + val preferGender: UserPreferAccompanyGender? = null, ) data class AccompanyDto( @@ -47,6 +50,7 @@ data class AccompanyDto( val startAccompanyAge: AccompanyAge, val endAccompanyAge: AccompanyAge, val preferGender: UserPreferAccompanyGender, + val tagIds: Set? = null, ) fun Accompany.toDto(): AccompanyDto = AccompanyDto( @@ -63,26 +67,19 @@ fun Accompany.toDto(): AccompanyDto = AccompanyDto( openKakaoUrl = openKakaoUrl, startAccompanyAge = AccompanyAge.fromValue(startAccompanyAge), endAccompanyAge = AccompanyAge.fromValue(endAccompanyAge), - preferGender = preferGender + preferGender = preferGender, + tagIds = tagIds, ) data class SearchAccompanyDto( - - var viewCntOrder: Boolean,//조회수 높은 순서 - - var likeCntOrder: Boolean,//좋아요 높은 순서 - - var startTripDate: LocalDate,//동행 모집 시작일시 - - var endTripDate: LocalDate,//동행 모집 마감일시 - + var viewCntOrder: Boolean, // 조회수 높은 순서 + var likeCntOrder: Boolean, // 좋아요 높은 순서 + var startTripDate: LocalDate, // 동행 모집 시작일시 + var endTripDate: LocalDate, // 동행 모집 마감일시 var pageIndex: Long, - var pageSize: Long - ) { fun getCurrentPage(): Long { return (this.pageIndex - 1) * this.pageSize } - } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt index 0c329a6..dcf548e 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt @@ -29,15 +29,21 @@ class AccompanyService( type = WithaengExceptionType.NOT_EXIST, message = NOT_EXIST_MESSAGE ) - params.title?.let { accompany.title = it } - params.content?.let { accompany.content = it } - params.destination?.let { accompany.accompanyDestination = it } - params.startTripDate?.let { accompany.startTripDate = it } - params.endTripDate?.let { accompany.endTripDate = it } - params.bannerImageUrl?.let { accompany.bannerImageUrl = it } - params.memberCount?.let { accompany.memberCount = it } - params.tagIds?.let { accompany.tagIds = filterValidTagIds(it) } - params.openKakaoUrl?.let { accompany.openKakaoUrl = it } + + accompany.update( + title = params.title, + content = params.content, + startTripDate = params.startTripDate, + endTripDate = params.endTripDate, + bannerImageUrl = params.bannerImageUrl, + memberCount = params.memberCount, + openKakaoUrl = params.openKakaoUrl, + accompanyDestination = params.destination, + startAccompanyAge = params.startAccompanyAge?.value, + endAccompanyAge = params.endAccompanyAge?.value, + preferGender = params.preferGender, + tagIds = params.tagIds, + ) return accompany.toDto() } @@ -53,8 +59,8 @@ class AccompanyService( return accompanyRepository.findAll().map { it.toDto() } } - private fun filterValidTagIds(tagIds: Iterable?): Set { - if (tagIds == null) return setOf() + private fun filterValidTagIds(tagIds: Set?): Set { + if (tagIds == null) return emptySet() return tagRepository.findAllById(tagIds).map { it.id }.toSet() } From c14312862a2eb0ac3b5c93b0143466950f9e2028 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Mon, 26 Aug 2024 03:15:59 +0900 Subject: [PATCH 114/174] =?UTF-8?q?Feature:=20=EB=8F=99=ED=96=89=20?= =?UTF-8?q?=EB=8C=93=EA=B8=80=20=EC=A1=B0=ED=9A=8C=20status=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5=20=ED=95=AD=EB=AA=A9=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../accompanyreply/dto/AccompanyReplyResponseDto.kt | 9 ++++++--- .../withaeng/domain/accompanyreply/AccompanyReplyDto.kt | 6 ++++-- .../domain/accompanyreply/AccompanyReplyService.kt | 7 ++++++- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt index 9bae766..5efbc07 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt @@ -5,6 +5,7 @@ import com.travel.withaeng.applicationservice.common.PagingResponse import com.travel.withaeng.applicationservice.user.dto.UserSimpleResponse import com.travel.withaeng.applicationservice.user.dto.toSimpleResponse import com.travel.withaeng.domain.accompanyreply.AccompanyReplyDto +import com.travel.withaeng.domain.accompanyreply.AccompanyReplyStatus import com.travel.withaeng.domain.user.UserSimpleDto import java.time.LocalDateTime @@ -13,9 +14,10 @@ data class AccompanyReplyResponse( val author: UserSimpleResponse, val accompanyId: Long, val parentId: Long? = null, - val content: String, + val content: String?, val likeCount: Long = 0L, - val createdAt: LocalDateTime + val createdAt: LocalDateTime?, + val status: AccompanyReplyStatus, ) class PagingAccompanyReplyResponse( @@ -35,6 +37,7 @@ fun AccompanyReplyDto.toResponse(userSimpleDto: UserSimpleDto, likeCount: Long = author = userSimpleDto.toSimpleResponse(), content = content, likeCount = likeCount, - createdAt = createdAt + createdAt = createdAt, + status = status, ) } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt index c1cda2f..f330315 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt @@ -8,9 +8,10 @@ data class AccompanyReplyDto @QueryProjection constructor( val userId: Long, val accompanyId: Long, val parentId: Long? = null, - val content: String, - val createdAt: LocalDateTime, + val content: String?, + val createdAt: LocalDateTime?, val status: AccompanyReplyStatus, + val count: Long, ) fun AccompanyReply.toDto(): AccompanyReplyDto = AccompanyReplyDto( @@ -21,4 +22,5 @@ fun AccompanyReply.toDto(): AccompanyReplyDto = AccompanyReplyDto( content = content, createdAt = createdAt, status = status, + count = 0 ) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt index 54ece88..b0abc0e 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt @@ -53,7 +53,12 @@ class AccompanyReplyService( } fun search(accompanyId: Long, pageable: Pageable): Page { - return accompanyReplyRepository.search(accompanyId, pageable) + return accompanyReplyRepository.search(accompanyId, pageable).map { + it.takeIf { it.status == AccompanyReplyStatus.DELETED }?.copy( + content = null, + createdAt = null, + ) ?: it + } } @Transactional From 3a744ad45e52ede4f7baf8b0fc3a0218c3a8b4ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Mon, 26 Aug 2024 05:53:34 +0900 Subject: [PATCH 115/174] =?UTF-8?q?Refactor:=20=EB=8F=99=ED=96=89=20?= =?UTF-8?q?=EB=8C=93=EA=B8=80=20=EC=A1=B0=ED=9A=8C=20=EB=B0=8F=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=95=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AccompanyReplyApplicationService.kt | 17 ++++---- .../dto/AccompanyReplyResponseDto.kt | 11 ----- .../dto/FindAccompanyReplyResponse.kt | 30 +++++++++++++ .../common/PagingResponse.kt | 8 ++-- .../com/travel/withaeng/common/ApiResponse.kt | 2 +- .../travel/withaeng/common/PageInfoRequest.kt | 33 +++++++++++++++ .../AccompanyReplyController.kt | 12 ++++-- .../AccompanyReplyRepositoryCustom.kt | 2 +- .../AccompanyReplyRepositoryImpl.kt | 42 +++++++++++++++---- .../accompanyreply/AccompanyReplyService.kt | 4 +- .../accompanyreply/FindAccompanyReplyDto.kt | 16 +++++++ .../withaeng/domain/user/UserBasicInfoDto.kt | 10 +++++ 12 files changed, 146 insertions(+), 41 deletions(-) create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/FindAccompanyReplyResponse.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/common/PageInfoRequest.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/FindAccompanyReplyDto.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserBasicInfoDto.kt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt index f76ab37..20deaea 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt @@ -33,16 +33,13 @@ class AccompanyReplyApplicationService( ).toResponse(userSimpleDto) } - fun search(accompanyId: Long, pageable: Pageable): PagingResponse> { - val accompanyReplyPage = accompanyReplyService.search(accompanyId, pageable) - val contents = accompanyReplyPage.content - // TODO: Fix getting like count & user logic for using bulk from single - val accompanyReplyResponseList = contents.map { replyDto -> - val likeCount = accompanyReplyLikeService.countAccompanyReplyLikeCount(replyDto.id) - val userSimpleDto = userService.findById(replyDto.userId) - replyDto.toResponse(userSimpleDto, likeCount) - } - return PagingAccompanyReplyResponse(accompanyReplyResponseList, accompanyReplyPage.toPaging()) + fun getList(accompanyId: Long, pageable: Pageable): PagingResponse> { + val accompanyReplyPage = accompanyReplyService.getList(accompanyId, pageable) + val accompanyReplyResponseList = accompanyReplyPage + .map { it.toResponse() } + .toList() + + return PagingResponse(accompanyReplyResponseList, accompanyReplyPage.toPaging()) } @Transactional diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt index 5efbc07..dec8794 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt @@ -1,7 +1,5 @@ package com.travel.withaeng.applicationservice.accompanyreply.dto -import com.travel.withaeng.applicationservice.common.Paging -import com.travel.withaeng.applicationservice.common.PagingResponse import com.travel.withaeng.applicationservice.user.dto.UserSimpleResponse import com.travel.withaeng.applicationservice.user.dto.toSimpleResponse import com.travel.withaeng.domain.accompanyreply.AccompanyReplyDto @@ -20,15 +18,6 @@ data class AccompanyReplyResponse( val status: AccompanyReplyStatus, ) -class PagingAccompanyReplyResponse( - private val content: List, - private val paging: Paging -) : PagingResponse> { - override fun getPaging(): Paging = paging - - override fun getContent(): List = content -} - fun AccompanyReplyDto.toResponse(userSimpleDto: UserSimpleDto, likeCount: Long = 0L): AccompanyReplyResponse { return AccompanyReplyResponse( id = id, diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/FindAccompanyReplyResponse.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/FindAccompanyReplyResponse.kt new file mode 100644 index 0000000..8bffd79 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/FindAccompanyReplyResponse.kt @@ -0,0 +1,30 @@ +package com.travel.withaeng.applicationservice.accompanyreply.dto + +import com.travel.withaeng.domain.accompanyreply.AccompanyReplyStatus +import com.travel.withaeng.domain.accompanyreply.FindAccompanyReplyDto +import com.travel.withaeng.domain.user.UserBasicInfoDto +import java.time.LocalDateTime + +data class FindAccompanyReplyResponse( + val id: Long, + val author: UserBasicInfoDto, + val accompanyId: Long, + val parentId: Long? = null, + val content: String?, + val likeCount: Long = 0L, + val createdAt: LocalDateTime?, + val status: AccompanyReplyStatus, +) + +fun FindAccompanyReplyDto.toResponse(): FindAccompanyReplyResponse { + return FindAccompanyReplyResponse( + id = id, + accompanyId = accompanyId, + parentId = parentId, + author = author, + content = content, + likeCount = likeCount, + createdAt = createdAt, + status = status, + ) +} \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/common/PagingResponse.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/common/PagingResponse.kt index 79cb3dd..c552d80 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/common/PagingResponse.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/common/PagingResponse.kt @@ -14,7 +14,7 @@ fun Page<*>.toPaging(): Paging = Paging( offset = pageable.offset ) -interface PagingResponse { - fun getPaging(): Paging - fun getContent(): T -} \ No newline at end of file +class PagingResponse( + val content: T, + val paging: Paging +) \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ApiResponse.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ApiResponse.kt index 37841cc..4a35116 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ApiResponse.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ApiResponse.kt @@ -21,7 +21,7 @@ data class ApiResponse( } fun success(data: PagingResponse): ApiResponse { - return ApiResponse(success = true, data = data.getContent(), paging = data.getPaging()) + return ApiResponse(success = true, data = data.content, paging = data.paging) } fun fail( diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/PageInfoRequest.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/PageInfoRequest.kt new file mode 100644 index 0000000..461dcda --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/PageInfoRequest.kt @@ -0,0 +1,33 @@ +package com.travel.withaeng.common + +import io.swagger.v3.oas.annotations.media.Schema +import org.springframework.data.domain.PageRequest + +@Schema(description = "[Request] 페이지 정보") +data class PageInfoRequest( + @Schema(description = "요청할 페이지 번호 (0부터 시작)") + private val page: String = "0", + @Schema(description = "페이지당 데이터 개수") + private val size: String = "5", +) { + + private val pageAsInt = initPage(getIntegerValue(page)) + private val sizeAsInt = initSize(getIntegerValue(size)) + + fun toPageRequest() = PageRequest.of(pageAsInt, sizeAsInt) + + private fun getIntegerValue(value: String?) = value?.toIntOrNull() + + private fun initPage(page: Int?): Int { + val defaultPage = 0 + val minimumPage = 0 + return page?.takeIf { it >= minimumPage } ?: defaultPage + } + + private fun initSize(size: Int?): Int { + val defaultSize = 5 + val minimumSize = 1 + return size?.takeIf { it >= minimumSize } ?: defaultSize + } + +} \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt index e35c841..4837fd6 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt @@ -2,7 +2,9 @@ package com.travel.withaeng.controller.accompanyreply import com.travel.withaeng.applicationservice.accompanyreply.AccompanyReplyApplicationService import com.travel.withaeng.applicationservice.accompanyreply.dto.AccompanyReplyResponse +import com.travel.withaeng.applicationservice.accompanyreply.dto.FindAccompanyReplyResponse import com.travel.withaeng.common.ApiResponse +import com.travel.withaeng.common.PageInfoRequest import com.travel.withaeng.controller.accompanyreply.dto.CreateAccompanyReplyRequest import com.travel.withaeng.controller.accompanyreply.dto.UpdateAccompanyReplyRequest import com.travel.withaeng.controller.accompanyreply.dto.toServiceRequest @@ -11,7 +13,6 @@ import com.travel.withaeng.security.resolver.GetAuth import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.security.SecurityRequirement import io.swagger.v3.oas.annotations.tags.Tag -import org.springframework.data.domain.Pageable import org.springframework.http.HttpStatus import org.springframework.web.bind.annotation.* @@ -48,10 +49,13 @@ class AccompanyReplyController( @GetMapping("/{accompanyId}/reply/search") fun search( @PathVariable(name = "accompanyId") accompanyId: Long, - pageable: Pageable - ): ApiResponse> { + @ModelAttribute pageInfoRequest: PageInfoRequest, + ): ApiResponse> { return ApiResponse.success( - accompanyReplyApplicationService.search(accompanyId = accompanyId, pageable = pageable) + accompanyReplyApplicationService.getList( + accompanyId, + pageInfoRequest.toPageRequest() + ) ) } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustom.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustom.kt index 0566d43..43d6e6f 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustom.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustom.kt @@ -4,5 +4,5 @@ import org.springframework.data.domain.Page import org.springframework.data.domain.Pageable interface AccompanyReplyRepositoryCustom { - fun search(accompanyId: Long, pageable: Pageable): Page + fun findAccompanyReplyList(accompanyId: Long, pageable: Pageable): Page } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryImpl.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryImpl.kt index 7cd824d..d9a957b 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryImpl.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryImpl.kt @@ -3,36 +3,62 @@ package com.travel.withaeng.domain.accompanyreply import com.querydsl.core.types.dsl.BooleanExpression import com.querydsl.jpa.impl.JPAQueryFactory import com.travel.withaeng.domain.accompanyreply.QAccompanyReply.accompanyReply +import com.travel.withaeng.domain.accompanyreplylike.QAccompanyReplyLike.accompanyReplyLike +import com.travel.withaeng.domain.user.QUser.user +import com.travel.withaeng.domain.user.QUserBasicInfoDto import org.springframework.data.domain.Page import org.springframework.data.domain.Pageable import org.springframework.data.support.PageableExecutionUtils class AccompanyReplyRepositoryImpl( + private val queryFactory: JPAQueryFactory + ) : AccompanyReplyRepositoryCustom { - override fun search(accompanyId: Long, pageable: Pageable): Page { + + override fun findAccompanyReplyList( + accompanyId: Long, + pageable: Pageable, + ): Page { + val contents = queryFactory .select( - QAccompanyReplyDto( + QFindAccompanyReplyDto( accompanyReply.id, - accompanyReply.userId, accompanyReply.accompanyId, accompanyReply.parentId, accompanyReply.content, - accompanyReply.createdAt, accompanyReply.status, + accompanyReplyLike.count(), + accompanyReply.createdAt, + QUserBasicInfoDto( + user.id, + user.email, + user.nickname, + ) ) ) .from(accompanyReply) - .where(accompanyIdEq(accompanyId)) + .leftJoin(accompanyReplyLike) + .on(accompanyReply.id.eq(accompanyReplyLike.replyId)) + .innerJoin(user) + .on(accompanyReply.userId.eq(user.id)) + .where( + accompanyIdEq(accompanyId) + ) + .groupBy(accompanyReply.id) + .offset(pageable.offset) + .limit(pageable.pageSize.toLong()) .fetch() - val countQuery = queryFactory + val totalCount = queryFactory .select(accompanyReply.count()) .from(accompanyReply) - .where(accompanyIdEq(accompanyId)) + .where( + accompanyIdEq(accompanyId) + ) - return PageableExecutionUtils.getPage(contents, pageable) { countQuery.fetchOne() ?: 0L } + return PageableExecutionUtils.getPage(contents, pageable) { totalCount.fetchOne() ?: 0L } } private fun accompanyIdEq(accompanyId: Long): BooleanExpression? { diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt index b0abc0e..d2d8b2c 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt @@ -52,8 +52,8 @@ class AccompanyReplyService( return accompanyReply.toDto() } - fun search(accompanyId: Long, pageable: Pageable): Page { - return accompanyReplyRepository.search(accompanyId, pageable).map { + fun getList(accompanyId: Long, pageable: Pageable): Page { + return accompanyReplyRepository.findAccompanyReplyList(accompanyId, pageable).map { it.takeIf { it.status == AccompanyReplyStatus.DELETED }?.copy( content = null, createdAt = null, diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/FindAccompanyReplyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/FindAccompanyReplyDto.kt new file mode 100644 index 0000000..724169f --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/FindAccompanyReplyDto.kt @@ -0,0 +1,16 @@ +package com.travel.withaeng.domain.accompanyreply + +import com.querydsl.core.annotations.QueryProjection +import com.travel.withaeng.domain.user.UserBasicInfoDto +import java.time.LocalDateTime + +data class FindAccompanyReplyDto @QueryProjection constructor( + val id: Long, + val accompanyId: Long, + val parentId: Long? = null, + val content: String?, + val status: AccompanyReplyStatus, + val likeCount: Long = 0, + val createdAt: LocalDateTime?, + val author: UserBasicInfoDto, +) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserBasicInfoDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserBasicInfoDto.kt new file mode 100644 index 0000000..4f2b731 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserBasicInfoDto.kt @@ -0,0 +1,10 @@ +package com.travel.withaeng.domain.user + +import com.querydsl.core.annotations.QueryProjection + +data class UserBasicInfoDto @QueryProjection constructor( + val id: Long, + val email: String, + val nickname: String, +) + From 4d39c2a7683019a7d568ebe19bcbda48e958823b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Mon, 26 Aug 2024 17:27:31 +0900 Subject: [PATCH 116/174] =?UTF-8?q?Refactor:=20=EB=8F=99=ED=96=89=20?= =?UTF-8?q?=EB=8C=93=EA=B8=80=20=EC=83=9D=EC=84=B1=20validate=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AccompanyReplyApplicationService.kt | 6 +-- .../accompanyreply/AccompanyReplyService.kt | 46 ++++++++++++++----- 2 files changed, 37 insertions(+), 15 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt index 20deaea..e3a3738 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt @@ -17,9 +17,9 @@ import org.springframework.transaction.annotation.Transactional @Service @Transactional(readOnly = true) class AccompanyReplyApplicationService( - val userService: UserService, - val accompanyReplyService: AccompanyReplyService, - val accompanyReplyLikeService: AccompanyReplyLikeService + private val userService: UserService, + private val accompanyReplyService: AccompanyReplyService, + private val accompanyReplyLikeService: AccompanyReplyLikeService, ) { @Transactional diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt index d2d8b2c..bf3d742 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt @@ -20,19 +20,9 @@ class AccompanyReplyService( @Transactional fun create(accompanyId: Long, userId: Long, content: String, parentId: Long? = null): AccompanyReplyDto { - userRepository.findByIdOrNull(userId) ?: throw WithaengException.of( - type = WithaengExceptionType.NOT_EXIST, - message = "해당하는 유저를 찾을 수 없습니다." - ) - accompanyRepository.findByIdOrNull(accompanyId) ?: throw WithaengException.of( - type = WithaengExceptionType.NOT_EXIST, - message = "해당하는 동행을 찾을 수 없습니다." - ) + validateCreateAccompanyReply(accompanyId, userId) if (parentId != null) { - accompanyReplyRepository.findByIdOrNull(parentId) ?: throw WithaengException.of( - type = WithaengExceptionType.NOT_EXIST, - message = "해당하는 댓글을 찾을 수 없습니다." - ) + validateNotExistsParentId(parentId) } val accompanyReply = AccompanyReply.create( accompanyId = accompanyId, @@ -80,4 +70,36 @@ class AccompanyReplyService( accompanyReply.delete() } + private fun validateCreateAccompanyReply(accompanyId: Long, userId: Long) { + validateExistsUser(userId) + validateExistsAccompany(accompanyId) + } + + private fun validateExistsAccompany(accompanyId: Long) { + if (!accompanyRepository.existsById(accompanyId)) { + throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = "해당하는 동행을 찾을 수 없습니다." + ) + } + } + + private fun validateExistsUser(userId: Long) { + if (!userRepository.existsById(userId)) { + throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = "해당하는 유저를 찾을 수 없습니다." + ) + } + } + + private fun validateNotExistsParentId(parentId: Long) { + if (accompanyReplyRepository.existsById(parentId)) { + throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = "해당하는 댓글을 찾을 수 없습니다." + ) + } + } + } \ No newline at end of file From 40ccf62fb12e9d1f6bd9c39d8f10d6f14585e590 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Mon, 26 Aug 2024 18:17:39 +0900 Subject: [PATCH 117/174] =?UTF-8?q?Fix:=20=ED=8E=98=EC=9D=B4=EC=A7=95=20ma?= =?UTF-8?q?xSize=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/kotlin/com/travel/withaeng/common/PageInfoRequest.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/PageInfoRequest.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/PageInfoRequest.kt index 461dcda..a0fd0f2 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/PageInfoRequest.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/PageInfoRequest.kt @@ -27,7 +27,8 @@ data class PageInfoRequest( private fun initSize(size: Int?): Int { val defaultSize = 5 val minimumSize = 1 - return size?.takeIf { it >= minimumSize } ?: defaultSize + val maxSize = 20 + return size?.takeIf { it in minimumSize..maxSize } ?: defaultSize } } \ No newline at end of file From d7426730b5c77bedbf6adcb5af9144463cc66cf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Mon, 26 Aug 2024 18:57:31 +0900 Subject: [PATCH 118/174] =?UTF-8?q?Fix:=20=EB=8F=99=ED=96=89=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=ED=95=AD=EB=AA=A9=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/AccompanyServiceRequestDto.kt | 25 ------------ .../accompany/dto/AccompanyRequestDto.kt | 38 ------------------- .../withaeng/domain/accompany/Accompany.kt | 14 ------- .../withaeng/domain/accompany/AccompanyDto.kt | 7 ---- .../domain/accompany/AccompanyService.kt | 7 ---- 5 files changed, 91 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt index fd837bb..1b8cef8 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt @@ -47,44 +47,19 @@ data class UpdateAccompanyServiceRequest( val userId: Long, val title: String? = null, val content: String? = null, - val continent: String? = null, - val country: String? = null, - val city: String? = null, - val startTripDate: LocalDate? = null, - val endTripDate: LocalDate? = null, val bannerImageUrl: String? = null, - val memberCount: Long? = null, val tagIds: Set? = null, val openKakaoUrl: String? = null, - val startAccompanyAge: AccompanyAge? = null, - val endAccompanyAge: AccompanyAge? = null, - val preferGender: UserPreferAccompanyGender? = null, ) fun UpdateAccompanyServiceRequest.toDomainDto(): UpdateAccompanyDto { - val destination = if (continent == null || country == null || city == null) { - null - } else { - AccompanyDestination( - continent = Continent.valueOf(continent), - country = Country.valueOf(country), - city = City.valueOf(city) - ) - } return UpdateAccompanyDto( accompanyId = accompanyId, title = title, content = content, - destination = destination, - startTripDate = startTripDate, - endTripDate = endTripDate, bannerImageUrl = bannerImageUrl, - memberCount = memberCount, tagIds = tagIds?.toSet(), openKakaoUrl = openKakaoUrl, - startAccompanyAge = startAccompanyAge, - endAccompanyAge = endAccompanyAge, - preferGender = preferGender, ) } diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/dto/AccompanyRequestDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/dto/AccompanyRequestDto.kt index 6462457..38d2950 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/dto/AccompanyRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/dto/AccompanyRequestDto.kt @@ -84,43 +84,14 @@ data class UpdateAccompanyRequest( @Schema(description = "동행 게시글 내용") val content: String? = null, - @Schema(description = "동행 목적지의 대륙") - val continent: String? = null, - - @Schema(description = "동행 목적지의 나라") - val country: String? = null, - - @Schema(description = "동행 목적지의 도시") - val city: String? = null, - - @Schema(description = "동행 시작 날짜 (1999-01-01)") - val startTripDate: LocalDate? = null, - - @Schema(description = "동행 종료 날짜 (1999-01-01)") - val endTripDate: LocalDate? = null, - @Schema(description = "동행 게시글 배너 이미지 URL") val bannerImageUrl: String? = null, - @Schema(description = "동행 멤버수") - val memberCount: Long? = null, - @Schema(description = "동행 게시글에 부착할 태그 아이디 리스트") val tagIds: Set? = null, @Schema(description = "동행 게시글에 게시된 오픈 카카오톡 URL") val openKakaoUrl: String? = null, - - @Schema(description = "동행 시작 연령(누구나 가능의 경우 0)") - @JsonDeserialize(using = AccompanyAgeDeserializer::class) - val startAccompanyAge: AccompanyAge? = null, - - @Schema(description = "동행 시작 연령(누구나 가능의 경우 99)") - @JsonDeserialize(using = AccompanyAgeDeserializer::class) - val endAccompanyAge: AccompanyAge? = null, - - @Schema(description = "동행 선호 성별") - val preferGender: UserPreferAccompanyGender? = null, ) fun UpdateAccompanyRequest.toServiceRequest( @@ -131,16 +102,7 @@ fun UpdateAccompanyRequest.toServiceRequest( userId = userId, title = title, content = content, - continent = continent, - country = country, - city = city, - startTripDate = startTripDate, - endTripDate = endTripDate, bannerImageUrl = bannerImageUrl, - memberCount = memberCount, tagIds = tagIds, openKakaoUrl = openKakaoUrl, - startAccompanyAge = startAccompanyAge, - endAccompanyAge = endAccompanyAge, - preferGender = preferGender, ) \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt index 1af2dcf..5eb1e35 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt @@ -80,28 +80,14 @@ class Accompany( fun update( title: String?, content: String?, - startTripDate: LocalDate?, - endTripDate: LocalDate?, bannerImageUrl: String?, - memberCount: Long?, openKakaoUrl: String?, - accompanyDestination: AccompanyDestination?, - startAccompanyAge: Int?, - endAccompanyAge: Int?, - preferGender: UserPreferAccompanyGender?, tagIds: Set? ) { this.title = title ?: this.title this.content = content ?: this.content - this.startTripDate = startTripDate ?: this.startTripDate - this.endTripDate = endTripDate ?: this.endTripDate this.bannerImageUrl = bannerImageUrl ?: this.bannerImageUrl - this.memberCount = memberCount ?: this.memberCount this.openKakaoUrl = openKakaoUrl ?: this.openKakaoUrl - this.accompanyDestination = accompanyDestination ?: this.accompanyDestination - this.startAccompanyAge = startAccompanyAge ?: this.startAccompanyAge - this.endAccompanyAge = endAccompanyAge ?: this.endAccompanyAge - this.preferGender = preferGender ?: this.preferGender this.tagIds = tagIds ?: this.tagIds } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt index d39b15e..2ecbbb5 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt @@ -23,16 +23,9 @@ data class UpdateAccompanyDto( val accompanyId: Long, val title: String? = null, val content: String? = null, - val destination: AccompanyDestination? = null, - val startTripDate: LocalDate? = null, - val endTripDate: LocalDate? = null, val bannerImageUrl: String? = null, - val memberCount: Long? = null, val tagIds: Set? = null, val openKakaoUrl: String? = null, - val startAccompanyAge: AccompanyAge? = null, - val endAccompanyAge: AccompanyAge? = null, - val preferGender: UserPreferAccompanyGender? = null, ) data class AccompanyDto( diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt index dcf548e..97d7eff 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt @@ -33,15 +33,8 @@ class AccompanyService( accompany.update( title = params.title, content = params.content, - startTripDate = params.startTripDate, - endTripDate = params.endTripDate, bannerImageUrl = params.bannerImageUrl, - memberCount = params.memberCount, openKakaoUrl = params.openKakaoUrl, - accompanyDestination = params.destination, - startAccompanyAge = params.startAccompanyAge?.value, - endAccompanyAge = params.endAccompanyAge?.value, - preferGender = params.preferGender, tagIds = params.tagIds, ) From 9491acaa0c16ebd93a46d2a9da635cf7b744a63b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Mon, 26 Aug 2024 20:59:06 +0900 Subject: [PATCH 119/174] =?UTF-8?q?Refactor:=20=EB=8F=99=ED=96=89=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../accompany/AccompanyApplicationService.kt | 18 ++++-- .../accompany/dto/FindAccompanyResponseDto.kt | 48 +++++++++++++++ .../accompany/AccompanyController.kt | 18 ++++-- .../resolver/UserInfoArgumentResolver.kt | 4 +- .../domain/accompany/AccompanyRepository.kt | 2 +- .../accompany/AccompanyRepositoryCustom.kt | 5 ++ .../accompany/AccompanyRepositoryImpl.kt | 59 +++++++++++++++++++ .../domain/accompany/AccompanyService.kt | 11 ++-- .../domain/accompany/FindAccompanyDto.kt | 25 ++++++++ .../accompany/FindAccompanyUserInfoDto.kt | 15 +++++ 10 files changed, 188 insertions(+), 17 deletions(-) create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/FindAccompanyResponseDto.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustom.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryImpl.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/FindAccompanyDto.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/FindAccompanyUserInfoDto.kt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/AccompanyApplicationService.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/AccompanyApplicationService.kt index b261b83..426f56d 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/AccompanyApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/AccompanyApplicationService.kt @@ -10,7 +10,7 @@ import org.springframework.transaction.annotation.Transactional @Transactional(readOnly = true) class AccompanyApplicationService( private val accompanyService: AccompanyService, - private val accompanyLikeService: AccompanyLikeService + private val accompanyLikeService: AccompanyLikeService, ) { @Transactional @@ -25,12 +25,20 @@ class AccompanyApplicationService( return accompanyDto.toAccompanyResponse(likeCount) } - fun retrieve(accompanyId: Long): AccompanyResponse { - val accompanyDto = accompanyService.findById(accompanyId) - val likeCount = countAccompanyLikeByAccompanyId(accompanyId) - return accompanyDto.toAccompanyResponse(likeCount) + fun detail(accompanyId: Long, userId: Long?): FindAccompanyResponse { + val accompanyDto = accompanyService.getDetail(accompanyId) + .toAccompanyResponse() + + if (isHost(userId, accompanyDto.userId)) { + // TODO : Host인 경우 승인보류 유저 목록 추가 필요 + } + + return accompanyDto } + private fun isHost(loginUserId: Long?, userId: Long) = + loginUserId == userId + fun retrieveAll(): List { val accompanyDtoList = accompanyService.findAll() // TODO: Bulk로 가져오는 방법을 고안 diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/FindAccompanyResponseDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/FindAccompanyResponseDto.kt new file mode 100644 index 0000000..f5cb782 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/FindAccompanyResponseDto.kt @@ -0,0 +1,48 @@ +package com.travel.withaeng.applicationservice.accompany.dto + +import com.travel.withaeng.domain.accompany.AccompanyDestination +import com.travel.withaeng.domain.accompany.FindAccompanyDto +import com.travel.withaeng.domain.accompany.FindAccompanyUserInfoDto +import com.travel.withaeng.domain.user.UserPreferAccompanyGender +import java.time.LocalDate + +data class FindAccompanyResponse( + val id: Long, + val userId: Long, + val title: String, + val content: String, + val destination: AccompanyDestination, + val startTripDate: LocalDate, + val endTripDate: LocalDate, + val bannerImageUrl: String? = null, + val memberCount: Long, + val viewCount: Long, + val openKakaoUrl: String, + val startAccompanyAge: Int, + val endAccompanyAge: Int, + val preferGender: UserPreferAccompanyGender, + val tagIds: Set? = emptySet(), + val likeCount: Long = 0, + val author: FindAccompanyUserInfoDto, + val approvalPendingUsers: Set? = null, +) + +fun FindAccompanyDto.toAccompanyResponse() = FindAccompanyResponse( + id = id, + userId = userId, + title = title, + content = content, + destination = destination, + startTripDate = startTripDate, + endTripDate = endTripDate, + bannerImageUrl = bannerImageUrl, + memberCount = memberCount, + viewCount = viewCount, + likeCount = likeCount, + openKakaoUrl = openKakaoUrl, + startAccompanyAge = startAccompanyAge, + endAccompanyAge = endAccompanyAge, + preferGender = preferGender, + tagIds = tagIds, + author = author, +) \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/AccompanyController.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/AccompanyController.kt index be19338..68f1361 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/AccompanyController.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/AccompanyController.kt @@ -2,6 +2,7 @@ package com.travel.withaeng.controller.accompany import com.travel.withaeng.applicationservice.accompany.AccompanyApplicationService import com.travel.withaeng.applicationservice.accompany.dto.AccompanyResponse +import com.travel.withaeng.applicationservice.accompany.dto.FindAccompanyResponse import com.travel.withaeng.common.ApiResponse import com.travel.withaeng.controller.accompany.dto.CreateAccompanyRequest import com.travel.withaeng.controller.accompany.dto.UpdateAccompanyRequest @@ -33,19 +34,28 @@ class AccompanyController( @GetAuth userInfo: UserInfo, @RequestBody @Valid request: CreateAccompanyRequest ): ApiResponse { - return ApiResponse.success(accompanyApplicationService.create(request.toServiceRequest(userInfo.id))) + return ApiResponse.success( + accompanyApplicationService.create(request.toServiceRequest(userInfo.id)) + ) } @Operation(summary = "Retrieve Accompany API", description = "동행 게시글 단건 조회 API") @GetMapping("/{accompanyId}") - fun retrieve(@PathVariable("accompanyId") accompanyId: Long): ApiResponse { - return ApiResponse.success(accompanyApplicationService.retrieve(accompanyId)) + fun retrieve( + @GetAuth userInfo: UserInfo?, + @PathVariable("accompanyId") accompanyId: Long + ): ApiResponse { + return ApiResponse.success( + accompanyApplicationService.detail(accompanyId, userInfo?.id) + ) } @Operation(summary = "Retrieve All Accompany API", description = "모든 동행 게시글 조회 API") @GetMapping("/all") fun retrieveAll(): ApiResponse> { - return ApiResponse.success(accompanyApplicationService.retrieveAll()) + return ApiResponse.success( + accompanyApplicationService.retrieveAll() + ) } @Operation( diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/resolver/UserInfoArgumentResolver.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/resolver/UserInfoArgumentResolver.kt index 3e9f9f7..83d33ce 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/resolver/UserInfoArgumentResolver.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/security/resolver/UserInfoArgumentResolver.kt @@ -23,9 +23,9 @@ class UserInfoArgumentResolver : HandlerMethodArgumentResolver { mavContainer: ModelAndViewContainer?, webRequest: NativeWebRequest, binderFactory: WebDataBinderFactory? - ): Any { + ): Any? { return when (val authentication = SecurityContextHolder.getContext().authentication) { - null -> throw WithaengException.of(WithaengExceptionType.AUTH_ERROR) + null -> null is JwtAuthentication -> authentication.principal else -> throw WithaengException.of( type = WithaengExceptionType.AUTH_ERROR, diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt index 42cea7f..3179722 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt @@ -2,4 +2,4 @@ package com.travel.withaeng.domain.accompany import org.springframework.data.jpa.repository.JpaRepository -interface AccompanyRepository : JpaRepository \ No newline at end of file +interface AccompanyRepository : JpaRepository, AccompanyRepositoryCustom \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustom.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustom.kt new file mode 100644 index 0000000..6119d2a --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustom.kt @@ -0,0 +1,5 @@ +package com.travel.withaeng.domain.accompany + +interface AccompanyRepositoryCustom { + fun findAccompanyDetail(accompanyId: Long): FindAccompanyDto? +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryImpl.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryImpl.kt new file mode 100644 index 0000000..df95df1 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryImpl.kt @@ -0,0 +1,59 @@ +package com.travel.withaeng.domain.accompany + +import com.querydsl.core.types.dsl.BooleanExpression +import com.querydsl.jpa.impl.JPAQueryFactory +import com.travel.withaeng.domain.accompany.QAccompany.accompany +import com.travel.withaeng.domain.accompanylike.QAccompanyLike.accompanyLike +import com.travel.withaeng.domain.user.QUser.user + +class AccompanyRepositoryImpl( + + private val queryFactory: JPAQueryFactory + +) : AccompanyRepositoryCustom { + + override fun findAccompanyDetail(accompanyId: Long): FindAccompanyDto? { + return queryFactory + .select( + QFindAccompanyDto( + accompany.id, + accompany.userId, + accompany.title, + accompany.content, + accompany.accompanyDestination, + accompany.startTripDate, + accompany.endTripDate, + accompany.bannerImageUrl, + accompany.memberCount, + accompany.viewCount, + accompany.openKakaoUrl, + accompany.startAccompanyAge, + accompany.endAccompanyAge, + accompany.preferGender, + accompany.tagIds, + accompanyLike.count(), + QFindAccompanyUserInfoDto( + user.nickname, + user.profileImageUrl, + user.isMale, + user.bio, + user.createdAt, + ), + ) + ) + .from(accompany) + .leftJoin(accompanyLike) + .on(accompany.id.eq(accompanyLike.accompanyId)) + .innerJoin(user) + .on(accompany.userId.eq(user.id)) + .where( + accompanyIdEq(accompanyId) + ) + .groupBy(accompanyLike.accompanyId) + .fetchOne() + } + + private fun accompanyIdEq(accompanyId: Long): BooleanExpression? { + return accompany.id.eq(accompanyId) + } +} diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt index 97d7eff..5472058 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt @@ -41,11 +41,12 @@ class AccompanyService( return accompany.toDto() } - fun findById(id: Long): AccompanyDto { - return accompanyRepository.findByIdOrNull(id)?.toDto() ?: throw WithaengException.of( - type = WithaengExceptionType.NOT_EXIST, - message = NOT_EXIST_MESSAGE - ) + fun getDetail(accompanyId: Long): FindAccompanyDto { + return accompanyRepository.findAccompanyDetail(accompanyId) + ?: throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = NOT_EXIST_MESSAGE + ) } fun findAll(): List { diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/FindAccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/FindAccompanyDto.kt new file mode 100644 index 0000000..98e87c1 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/FindAccompanyDto.kt @@ -0,0 +1,25 @@ +package com.travel.withaeng.domain.accompany + +import com.querydsl.core.annotations.QueryProjection +import com.travel.withaeng.domain.user.UserPreferAccompanyGender +import java.time.LocalDate + +data class FindAccompanyDto @QueryProjection constructor( + val id: Long, + val userId: Long, + val title: String, + val content: String, + val destination: AccompanyDestination, + val startTripDate: LocalDate, + val endTripDate: LocalDate, + val bannerImageUrl: String? = null, + val memberCount: Long, + val viewCount: Long, + val openKakaoUrl: String, + val startAccompanyAge: Int, + val endAccompanyAge: Int, + val preferGender: UserPreferAccompanyGender, + val tagIds: Set? = emptySet(), + val likeCount: Long = 0, + val author: FindAccompanyUserInfoDto, +) \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/FindAccompanyUserInfoDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/FindAccompanyUserInfoDto.kt new file mode 100644 index 0000000..4bb89c6 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/FindAccompanyUserInfoDto.kt @@ -0,0 +1,15 @@ +package com.travel.withaeng.domain.accompany + +import com.querydsl.core.annotations.QueryProjection +import java.time.LocalDateTime + +data class FindAccompanyUserInfoDto @QueryProjection constructor( + val nickname: String, + val profileImageUrl: String?, + val isMale: Boolean, + val bio: String?, + val joinDate: LocalDateTime, + // TODO : 여행 관심사 Set 추가 필요 + // TODO : 온도 추가 필요 + // TODO : 연령대 추가 필요 +) \ No newline at end of file From 329aa2e898c5de981eb8b2ff5db0d541e9fd505b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Mon, 26 Aug 2024 21:05:26 +0900 Subject: [PATCH 120/174] =?UTF-8?q?Fix:=20=EB=8F=99=ED=96=89=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20=EC=9C=A0=EC=A0=80=20DTO=EB=AA=85,=20=EA=B2=BD?= =?UTF-8?q?=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../accompanyreply/dto/FindAccompanyReplyResponse.kt | 4 ++-- .../domain/accompanyreply/AccompanyReplyRepositoryImpl.kt | 3 +-- .../withaeng/domain/accompanyreply/FindAccompanyReplyDto.kt | 3 +-- .../FindAccompanyReplyUserInfoDto.kt} | 4 ++-- 4 files changed, 6 insertions(+), 8 deletions(-) rename withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/{user/UserBasicInfoDto.kt => accompanyreply/FindAccompanyReplyUserInfoDto.kt} (50%) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/FindAccompanyReplyResponse.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/FindAccompanyReplyResponse.kt index 8bffd79..eba38bf 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/FindAccompanyReplyResponse.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/FindAccompanyReplyResponse.kt @@ -2,12 +2,12 @@ package com.travel.withaeng.applicationservice.accompanyreply.dto import com.travel.withaeng.domain.accompanyreply.AccompanyReplyStatus import com.travel.withaeng.domain.accompanyreply.FindAccompanyReplyDto -import com.travel.withaeng.domain.user.UserBasicInfoDto +import com.travel.withaeng.domain.accompanyreply.FindAccompanyReplyUserInfoDto import java.time.LocalDateTime data class FindAccompanyReplyResponse( val id: Long, - val author: UserBasicInfoDto, + val author: FindAccompanyReplyUserInfoDto, val accompanyId: Long, val parentId: Long? = null, val content: String?, diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryImpl.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryImpl.kt index d9a957b..35fdcf1 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryImpl.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryImpl.kt @@ -5,7 +5,6 @@ import com.querydsl.jpa.impl.JPAQueryFactory import com.travel.withaeng.domain.accompanyreply.QAccompanyReply.accompanyReply import com.travel.withaeng.domain.accompanyreplylike.QAccompanyReplyLike.accompanyReplyLike import com.travel.withaeng.domain.user.QUser.user -import com.travel.withaeng.domain.user.QUserBasicInfoDto import org.springframework.data.domain.Page import org.springframework.data.domain.Pageable import org.springframework.data.support.PageableExecutionUtils @@ -31,7 +30,7 @@ class AccompanyReplyRepositoryImpl( accompanyReply.status, accompanyReplyLike.count(), accompanyReply.createdAt, - QUserBasicInfoDto( + QFindAccompanyReplyUserInfoDto( user.id, user.email, user.nickname, diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/FindAccompanyReplyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/FindAccompanyReplyDto.kt index 724169f..4371e61 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/FindAccompanyReplyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/FindAccompanyReplyDto.kt @@ -1,7 +1,6 @@ package com.travel.withaeng.domain.accompanyreply import com.querydsl.core.annotations.QueryProjection -import com.travel.withaeng.domain.user.UserBasicInfoDto import java.time.LocalDateTime data class FindAccompanyReplyDto @QueryProjection constructor( @@ -12,5 +11,5 @@ data class FindAccompanyReplyDto @QueryProjection constructor( val status: AccompanyReplyStatus, val likeCount: Long = 0, val createdAt: LocalDateTime?, - val author: UserBasicInfoDto, + val author: FindAccompanyReplyUserInfoDto, ) diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserBasicInfoDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/FindAccompanyReplyUserInfoDto.kt similarity index 50% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserBasicInfoDto.kt rename to withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/FindAccompanyReplyUserInfoDto.kt index 4f2b731..e090800 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserBasicInfoDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/FindAccompanyReplyUserInfoDto.kt @@ -1,8 +1,8 @@ -package com.travel.withaeng.domain.user +package com.travel.withaeng.domain.accompanyreply import com.querydsl.core.annotations.QueryProjection -data class UserBasicInfoDto @QueryProjection constructor( +data class FindAccompanyReplyUserInfoDto @QueryProjection constructor( val id: Long, val email: String, val nickname: String, From aed52d85fad15328d38fa449fd6d46debfba95c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Tue, 27 Aug 2024 01:18:39 +0900 Subject: [PATCH 121/174] =?UTF-8?q?Feature:=20=EB=8F=99=ED=96=89=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20=EC=A1=B0=ED=9A=8C=EC=88=98=20=EC=A6=9D?= =?UTF-8?q?=EA=B0=80=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../accompany/AccompanyApplicationService.kt | 12 ++++++-- .../accompany/AccompanyEventListener.kt | 20 +++++++++++++ .../com/travel/withaeng/common/Events.kt | 15 ++++++++++ .../com/travel/withaeng/config/EventConfig.kt | 21 ++++++++++++++ .../withaeng/domain/accompany/Accompany.kt | 22 +++++++++------ .../withaeng/domain/accompany/AccompanyDto.kt | 2 +- .../AccompanyIncrementViewCountEvent.kt | 5 ++++ .../accompany/AccompanyRepositoryImpl.kt | 5 +++- .../domain/accompany/AccompanyService.kt | 20 +++++++++---- .../AccompanyStatistics.kt | 28 +++++++++++++++++++ 10 files changed, 132 insertions(+), 18 deletions(-) create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/AccompanyEventListener.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/common/Events.kt create mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/config/EventConfig.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyIncrementViewCountEvent.kt create mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanystatistics/AccompanyStatistics.kt diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/AccompanyApplicationService.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/AccompanyApplicationService.kt index 426f56d..d404bc5 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/AccompanyApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/AccompanyApplicationService.kt @@ -1,6 +1,8 @@ package com.travel.withaeng.applicationservice.accompany import com.travel.withaeng.applicationservice.accompany.dto.* +import com.travel.withaeng.common.Events +import com.travel.withaeng.domain.accompany.AccompanyIncrementViewCountEvent import com.travel.withaeng.domain.accompany.AccompanyService import com.travel.withaeng.domain.accompanylike.AccompanyLikeService import org.springframework.stereotype.Service @@ -15,7 +17,8 @@ class AccompanyApplicationService( @Transactional fun create(request: CreateAccompanyServiceRequest): AccompanyResponse { - return accompanyService.create(request.toDomainDto()).toAccompanyResponse(0L) + return accompanyService.create(request.toDomainDto()) + .toAccompanyResponse(0L) } @Transactional @@ -26,7 +29,8 @@ class AccompanyApplicationService( } fun detail(accompanyId: Long, userId: Long?): FindAccompanyResponse { - val accompanyDto = accompanyService.getDetail(accompanyId) + increaseViewCount(accompanyId) + val accompanyDto = accompanyService.detail(accompanyId) .toAccompanyResponse() if (isHost(userId, accompanyDto.userId)) { @@ -36,6 +40,10 @@ class AccompanyApplicationService( return accompanyDto } + private fun increaseViewCount(accompanyId: Long) { + Events.raise(AccompanyIncrementViewCountEvent(accompanyId)) + } + private fun isHost(loginUserId: Long?, userId: Long) = loginUserId == userId diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/AccompanyEventListener.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/AccompanyEventListener.kt new file mode 100644 index 0000000..8cb1ad7 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/AccompanyEventListener.kt @@ -0,0 +1,20 @@ +package com.travel.withaeng.applicationservice.accompany + +import com.travel.withaeng.domain.accompany.AccompanyIncrementViewCountEvent +import com.travel.withaeng.domain.accompany.AccompanyService +import org.springframework.context.event.EventListener +import org.springframework.scheduling.annotation.Async +import org.springframework.stereotype.Component +import org.springframework.transaction.annotation.Transactional + +@Component +class AccompanyEventListener( + private val accompanyService: AccompanyService +) { + @EventListener + @Async + @Transactional + fun incrementViewCountEventListener(event: AccompanyIncrementViewCountEvent) { + event.accompanyId?.let { accompanyService.increaseViewCount(it) } + } +} \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/Events.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/Events.kt new file mode 100644 index 0000000..cf65cc3 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/common/Events.kt @@ -0,0 +1,15 @@ +package com.travel.withaeng.common + +import org.springframework.context.ApplicationEventPublisher + +object Events { + private var eventPublisher: ApplicationEventPublisher? = null + + fun setPublisher(applicationEventPublisher: ApplicationEventPublisher) { + eventPublisher = applicationEventPublisher + } + + fun raise(event: Any) { + eventPublisher?.publishEvent(event) + } +} \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/EventConfig.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/config/EventConfig.kt new file mode 100644 index 0000000..4d06045 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/config/EventConfig.kt @@ -0,0 +1,21 @@ +package com.travel.withaeng.config + +import com.travel.withaeng.common.Events +import org.springframework.beans.factory.InitializingBean +import org.springframework.context.ApplicationEventPublisher +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +@Configuration +class EventConfig( + private val publisher: ApplicationEventPublisher +) { + + @Bean + fun eventInitializer(): InitializingBean { + return InitializingBean { + Events.setPublisher(publisher) + } + } + +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt index 5eb1e35..cafbd61 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt @@ -2,6 +2,7 @@ package com.travel.withaeng.domain.accompany import com.travel.withaeng.converter.TagIdsConverter import com.travel.withaeng.domain.BaseEntity +import com.travel.withaeng.domain.accompanystatistics.AccompanyStatistics import com.travel.withaeng.domain.user.UserPreferAccompanyGender import jakarta.persistence.* import org.hibernate.annotations.Comment @@ -46,10 +47,6 @@ class Accompany( @Comment("모집 인원") var memberCount: Long = 0L, - @Column(name = "view_count", nullable = false) - @Comment("조회수") - var viewCount: Long = 0L, - @Column(name = "open_kakao_url", nullable = false) @Comment("오픈 카카오 채팅 URI") var openKakaoUrl: String, @@ -73,9 +70,16 @@ class Accompany( @Convert(converter = TagIdsConverter::class) @Column(name = "tag_ids", nullable = false) @Comment("태그 목록") - var tagIds: Set = setOf() + var tagIds: Set = setOf(), + + @OneToOne(mappedBy = "accompany", cascade = [CascadeType.ALL], orphanRemoval = true) + var accompanyStatistics: AccompanyStatistics? = null, -) : BaseEntity() { + ) : BaseEntity() { + + fun increaseViewCount() { + this.accompanyStatistics?.increaseViewCount() + } fun update( title: String?, @@ -93,7 +97,7 @@ class Accompany( companion object { fun create(params: CreateAccompanyDto): Accompany { - return Accompany( + val accompany = Accompany( userId = params.userId, title = params.title, content = params.content, @@ -106,8 +110,10 @@ class Accompany( startAccompanyAge = params.startAccompanyAge.value, endAccompanyAge = params.endAccompanyAge.value, preferGender = params.preferGender, - tagIds = params.tagIds ?: setOf() + tagIds = params.tagIds ?: setOf(), ) + accompany.accompanyStatistics = AccompanyStatistics(accompany = accompany) + return accompany } } } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt index 2ecbbb5..8974043 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt @@ -56,7 +56,7 @@ fun Accompany.toDto(): AccompanyDto = AccompanyDto( endTripDate = endTripDate, bannerImageUrl = bannerImageUrl, memberCount = memberCount, - viewCount = viewCount, + viewCount = accompanyStatistics?.viewCount ?: 0, openKakaoUrl = openKakaoUrl, startAccompanyAge = AccompanyAge.fromValue(startAccompanyAge), endAccompanyAge = AccompanyAge.fromValue(endAccompanyAge), diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyIncrementViewCountEvent.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyIncrementViewCountEvent.kt new file mode 100644 index 0000000..eb7aabe --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyIncrementViewCountEvent.kt @@ -0,0 +1,5 @@ +package com.travel.withaeng.domain.accompany + +class AccompanyIncrementViewCountEvent( + val accompanyId: Long? = null +) \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryImpl.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryImpl.kt index df95df1..44359a6 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryImpl.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryImpl.kt @@ -4,6 +4,7 @@ import com.querydsl.core.types.dsl.BooleanExpression import com.querydsl.jpa.impl.JPAQueryFactory import com.travel.withaeng.domain.accompany.QAccompany.accompany import com.travel.withaeng.domain.accompanylike.QAccompanyLike.accompanyLike +import com.travel.withaeng.domain.accompanystatistics.QAccompanyStatistics.accompanyStatistics import com.travel.withaeng.domain.user.QUser.user class AccompanyRepositoryImpl( @@ -25,7 +26,7 @@ class AccompanyRepositoryImpl( accompany.endTripDate, accompany.bannerImageUrl, accompany.memberCount, - accompany.viewCount, + accompanyStatistics.viewCount, accompany.openKakaoUrl, accompany.startAccompanyAge, accompany.endAccompanyAge, @@ -44,6 +45,8 @@ class AccompanyRepositoryImpl( .from(accompany) .leftJoin(accompanyLike) .on(accompany.id.eq(accompanyLike.accompanyId)) + .innerJoin(accompanyStatistics) + .on(accompany.id.eq(accompanyStatistics.accompany.id)) .innerJoin(user) .on(accompany.userId.eq(user.id)) .where( diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt index 5472058..9d0d2c4 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt @@ -25,11 +25,7 @@ class AccompanyService( @Transactional fun update(params: UpdateAccompanyDto): AccompanyDto { - val accompany = accompanyRepository.findByIdOrNull(params.accompanyId) ?: throw WithaengException.of( - type = WithaengExceptionType.NOT_EXIST, - message = NOT_EXIST_MESSAGE - ) - + val accompany = findById(params.accompanyId) accompany.update( title = params.title, content = params.content, @@ -41,7 +37,7 @@ class AccompanyService( return accompany.toDto() } - fun getDetail(accompanyId: Long): FindAccompanyDto { + fun detail(accompanyId: Long): FindAccompanyDto { return accompanyRepository.findAccompanyDetail(accompanyId) ?: throw WithaengException.of( type = WithaengExceptionType.NOT_EXIST, @@ -49,6 +45,18 @@ class AccompanyService( ) } + @Transactional + fun increaseViewCount(accompanyId: Long) { + val accompany = findById(accompanyId) + accompany.increaseViewCount() + } + + private fun findById(accompanyId: Long) = + accompanyRepository.findByIdOrNull(accompanyId) ?: throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = NOT_EXIST_MESSAGE + ) + fun findAll(): List { return accompanyRepository.findAll().map { it.toDto() } } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanystatistics/AccompanyStatistics.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanystatistics/AccompanyStatistics.kt new file mode 100644 index 0000000..a73f093 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanystatistics/AccompanyStatistics.kt @@ -0,0 +1,28 @@ +package com.travel.withaeng.domain.accompanystatistics + +import com.travel.withaeng.domain.accompany.Accompany +import jakarta.persistence.* +import org.hibernate.annotations.Comment + +@Entity +@Table(name = "accompany_statistics") +class AccompanyStatistics( + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id", nullable = false) + val id: Long = 0L, + + @OneToOne + @JoinColumn(name = "accompany_id", nullable = false) + val accompany: Accompany, + + @Column(name = "view_count", nullable = false) + @Comment("조회수") + var viewCount: Long = 0L, +) { + + fun increaseViewCount() { + this.viewCount++ + } + +} \ No newline at end of file From f2742c2ecb8caec9f5239ffb715bab411bfa58e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Tue, 27 Aug 2024 14:17:22 +0900 Subject: [PATCH 122/174] =?UTF-8?q?Fix:=20=EB=8F=99=ED=96=89=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=ED=95=AD=EB=AA=A9=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../accompany/dto/AccompanyServiceRequestDto.kt | 6 ------ .../controller/accompany/dto/AccompanyRequestDto.kt | 12 ------------ .../travel/withaeng/domain/accompany/Accompany.kt | 6 ------ .../travel/withaeng/domain/accompany/AccompanyDto.kt | 3 --- .../withaeng/domain/accompany/AccompanyService.kt | 3 --- 5 files changed, 30 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt index 1b8cef8..38db38d 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt @@ -45,21 +45,15 @@ fun CreateAccompanyServiceRequest.toDomainDto(): CreateAccompanyDto = CreateAcco data class UpdateAccompanyServiceRequest( val accompanyId: Long, val userId: Long, - val title: String? = null, val content: String? = null, - val bannerImageUrl: String? = null, val tagIds: Set? = null, - val openKakaoUrl: String? = null, ) fun UpdateAccompanyServiceRequest.toDomainDto(): UpdateAccompanyDto { return UpdateAccompanyDto( accompanyId = accompanyId, - title = title, content = content, - bannerImageUrl = bannerImageUrl, tagIds = tagIds?.toSet(), - openKakaoUrl = openKakaoUrl, ) } diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/dto/AccompanyRequestDto.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/dto/AccompanyRequestDto.kt index 38d2950..b30dcb9 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/dto/AccompanyRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/dto/AccompanyRequestDto.kt @@ -78,20 +78,11 @@ fun CreateAccompanyRequest.toServiceRequest( ) data class UpdateAccompanyRequest( - @Schema(description = "동행 게시글 제목") - val title: String? = null, - @Schema(description = "동행 게시글 내용") val content: String? = null, - @Schema(description = "동행 게시글 배너 이미지 URL") - val bannerImageUrl: String? = null, - @Schema(description = "동행 게시글에 부착할 태그 아이디 리스트") val tagIds: Set? = null, - - @Schema(description = "동행 게시글에 게시된 오픈 카카오톡 URL") - val openKakaoUrl: String? = null, ) fun UpdateAccompanyRequest.toServiceRequest( @@ -100,9 +91,6 @@ fun UpdateAccompanyRequest.toServiceRequest( ): UpdateAccompanyServiceRequest = UpdateAccompanyServiceRequest( accompanyId = accompanyId, userId = userId, - title = title, content = content, - bannerImageUrl = bannerImageUrl, tagIds = tagIds, - openKakaoUrl = openKakaoUrl, ) \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt index cafbd61..e3a4638 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt @@ -82,16 +82,10 @@ class Accompany( } fun update( - title: String?, content: String?, - bannerImageUrl: String?, - openKakaoUrl: String?, tagIds: Set? ) { - this.title = title ?: this.title this.content = content ?: this.content - this.bannerImageUrl = bannerImageUrl ?: this.bannerImageUrl - this.openKakaoUrl = openKakaoUrl ?: this.openKakaoUrl this.tagIds = tagIds ?: this.tagIds } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt index 8974043..0e02c1f 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt @@ -21,11 +21,8 @@ data class CreateAccompanyDto( data class UpdateAccompanyDto( val accompanyId: Long, - val title: String? = null, val content: String? = null, - val bannerImageUrl: String? = null, val tagIds: Set? = null, - val openKakaoUrl: String? = null, ) data class AccompanyDto( diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt index 9d0d2c4..9688075 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt +++ b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt @@ -27,10 +27,7 @@ class AccompanyService( fun update(params: UpdateAccompanyDto): AccompanyDto { val accompany = findById(params.accompanyId) accompany.update( - title = params.title, content = params.content, - bannerImageUrl = params.bannerImageUrl, - openKakaoUrl = params.openKakaoUrl, tagIds = params.tagIds, ) From 30aa144d17475e28dedfd83f52fe9527002d8a57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Fri, 30 Aug 2024 22:32:03 +0900 Subject: [PATCH 123/174] Chore: update artifact and group names --- gradle.properties | 2 +- settings.gradle.kts | 3 +- .../scheduler/SchedulerBasePackage.kt | 3 -- .../withaeng/WithaengApplication.kt | 2 +- .../accompany/AccompanyApplicationService.kt | 12 +++---- .../accompany/AccompanyEventListener.kt | 6 ++-- .../accompany/dto/AccompanyResponseDto.kt | 8 ++--- .../dto/AccompanyServiceRequestDto.kt | 6 ++-- .../accompany/dto/FindAccompanyResponseDto.kt | 10 +++--- .../AccompanyLikeApplicationService.kt | 8 +++-- .../AccompanyReplyApplicationService.kt | 35 ++++++++----------- .../dto/AccompanyReplyResponseDto.kt | 12 +++---- .../dto/AccompanyReplyServiceRequestDto.kt | 2 +- .../dto/FindAccompanyReplyResponse.kt | 8 ++--- .../AccompanyReplyLikeApplicationService.kt | 8 +++-- .../auth/AuthApplicationService.kt | 32 +++++++---------- .../auth/UserNicknameUtils.kt | 2 +- .../auth/dto/AuthResponseDto.kt | 2 +- .../auth/dto/AuthServiceRequestDto.kt | 2 +- .../common/PagingResponse.kt | 2 +- .../test/TestApplicationService.kt | 8 ++--- .../user/UserApplicationService.kt | 14 ++++---- .../user/dto/UserResponseDto.kt | 22 ++++++------ .../user/dto/UserServiceRequestDto.kt | 22 ++++++------ .../api}/common/ApiResponse.kt | 8 ++--- .../api}/common/Constants.kt | 2 +- .../api}/common/ControllerExceptionAdvice.kt | 6 ++-- .../api}/common/Events.kt | 2 +- .../api}/common/PageInfoRequest.kt | 2 +- .../api}/common/WhiteList.kt | 2 +- .../api}/config/AsyncConfig.kt | 2 +- .../api}/config/AuthConfig.kt | 7 ++-- .../api}/config/EventConfig.kt | 4 +-- .../api}/config/JacksonConfig.kt | 4 +-- .../api}/config/SchedulerConfig.kt | 4 +-- .../api}/config/SecurityConfig.kt | 14 ++++---- .../api}/config/SwaggerConfig.kt | 2 +- .../api}/config/WebConfigurer.kt | 4 +-- .../accompany/AccompanyController.kt | 20 +++++------ .../accompany/dto/AccompanyRequestDto.kt | 12 +++---- .../accompanylike/AccompanyLikeController.kt | 10 +++--- .../AccompanyReplyController.kt | 22 ++++++------ .../dto/AccompanyReplyRequestDto.kt | 6 ++-- .../AccompanyReplyLikeController.kt | 10 +++--- .../api}/controller/auth/AuthController.kt | 27 +++++--------- .../controller/auth/dto/AuthRequestDto.kt | 11 ++---- .../api}/controller/test/TestController.kt | 6 ++-- .../api}/controller/user/UserController.kt | 16 ++++----- .../controller/user/dto/UserRequestDto.kt | 6 ++-- .../api}/jackson/EnumModule.kt | 11 +++--- .../deserializer/SimpleEnumDeserializer.kt | 6 ++-- .../DeleteValidatingEmailScheduler.kt | 7 ++-- .../api/scheduler/SchedulerBasePackage.kt | 3 ++ .../api}/scheduler/SendEmailScheduler.kt | 16 ++++----- .../authentication/JwtAuthentication.kt | 2 +- .../api}/security/authentication/UserInfo.kt | 6 ++-- .../handler/HttpStatusAccessDeniedHandler.kt | 2 +- .../HttpStatusAuthenticationEntryPoint.kt | 2 +- .../api}/security/jwt/JwtAgent.kt | 4 +-- .../api}/security/jwt/JwtAgentImpl.kt | 8 ++--- .../api}/security/jwt/JwtFilter.kt | 12 +++---- .../api}/security/resolver/GetAuth.kt | 2 +- .../resolver/UserInfoArgumentResolver.kt | 10 +++--- .../user/UserNicknameUtilsTest.kt | 4 +-- .../common/exception/WithaengException.kt | 2 +- .../common/exception/WithaengExceptionType.kt | 2 +- .../withaeng/domain/WithaengDomainModule.kt | 3 -- .../withaeng/domain/BaseEntity.kt | 2 +- .../withaeng/domain/WithaengDomainModule.kt | 3 ++ .../withaeng/domain/accompany/Accompany.kt | 12 +++---- .../withaeng/domain/accompany/AccompanyAge.kt | 6 ++-- .../domain/accompany/AccompanyDestination.kt | 2 +- .../withaeng/domain/accompany/AccompanyDto.kt | 4 +-- .../AccompanyIncrementViewCountEvent.kt | 2 +- .../domain/accompany/AccompanyRepository.kt | 2 +- .../accompany/AccompanyRepositoryCustom.kt | 2 +- .../accompany/AccompanyRepositoryImpl.kt | 12 +++---- .../domain/accompany/AccompanyService.kt | 12 ++++--- .../domain/accompany/AccompanyStatus.kt | 2 +- .../withaeng/domain/accompany/City.kt | 2 +- .../withaeng/domain/accompany/Continent.kt | 2 +- .../withaeng/domain/accompany/Country.kt | 2 +- .../domain/accompany/FindAccompanyDto.kt | 4 +-- .../accompany/FindAccompanyUserInfoDto.kt | 2 +- .../domain/accompanylike/AccompanyLike.kt | 4 +-- .../accompanylike/AccompanyLikeRepository.kt | 2 +- .../accompanylike/AccompanyLikeService.kt | 10 +++--- .../domain/accompanyreply/AccompanyReply.kt | 4 +-- .../accompanyreply/AccompanyReplyDto.kt | 2 +- .../AccompanyReplyRepository.kt | 2 +- .../AccompanyReplyRepositoryCustom.kt | 2 +- .../AccompanyReplyRepositoryImpl.kt | 8 ++--- .../accompanyreply/AccompanyReplyService.kt | 33 +++++++---------- .../accompanyreply/AccompanyReplyStatus.kt | 2 +- .../accompanyreply/FindAccompanyReplyDto.kt | 2 +- .../FindAccompanyReplyUserInfoDto.kt | 2 +- .../accompanyreplylike/AccompanyReplyLike.kt | 4 +-- .../AccompanyReplyLikeRepository.kt | 2 +- .../AccompanyReplyLikeService.kt | 10 +++--- .../AccompanyStatistics.kt | 4 +-- .../domain}/config/JasyptConfig.kt | 2 +- .../domain}/config/JpaConfig.kt | 4 +-- .../domain}/config/JpaQueryDslConfig.kt | 2 +- .../domain}/converter/TagIdsConverter.kt | 2 +- .../converter/UserFoodRestrictionConverter.kt | 4 +-- .../UserPreferTravelThemeConverter.kt | 6 ++-- .../domain}/converter/UserRoleConverter.kt | 4 +-- .../{travel => }/withaeng/domain/tag/Tag.kt | 8 ++--- .../withaeng/domain/tag/TagRepository.kt | 2 +- .../{travel => }/withaeng/domain/user/User.kt | 10 +++--- .../withaeng/domain/user/UserConsumeStyle.kt | 2 +- .../withaeng/domain/user/UserDrinkingType.kt | 2 +- .../domain/user/UserFoodRestriction.kt | 2 +- .../withaeng/domain/user/UserMbti.kt | 2 +- .../domain/user/UserPreferAccompanyGender.kt | 2 +- .../domain/user/UserPreferTravelTheme.kt | 2 +- .../domain/user/UserPreferTravelType.kt | 2 +- .../withaeng/domain/user/UserRepository.kt | 2 +- .../withaeng/domain/user/UserRole.kt | 2 +- .../withaeng/domain/user/UserService.kt | 6 ++-- .../withaeng/domain/user/UserSimpleDto.kt | 2 +- .../withaeng/domain/user/UserSmokingType.kt | 2 +- .../domain/validateemail/ValidatingEmail.kt | 4 +-- .../validateemail/ValidatingEmailDto.kt | 2 +- .../ValidatingEmailRepository.kt | 2 +- .../validateemail/ValidatingEmailService.kt | 8 ++--- .../validateemail/ValidatingEmailStatus.kt | 2 +- .../validateemail/ValidatingEmailType.kt | 2 +- .../api}/config/JasyptConfigTest.kt | 2 +- .../api}/config/TestConfiguration.kt | 2 +- .../withaeng/external/ses/MailSender.kt | 2 +- .../withaeng/external/ses/MailSenderImpl.kt | 2 +- .../withaeng/external/ses/MailType.kt | 2 +- .../withaeng/external/ses/config/SESConfig.kt | 2 +- .../external/ses/config/ThymeleafConfig.kt | 2 +- 135 files changed, 392 insertions(+), 422 deletions(-) delete mode 100644 withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/SchedulerBasePackage.kt rename withaeng-api/src/main/kotlin/com/{travel => }/withaeng/WithaengApplication.kt (89%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/applicationservice/accompany/AccompanyApplicationService.kt (83%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/applicationservice/accompany/AccompanyEventListener.kt (73%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/applicationservice/accompany/dto/AccompanyResponseDto.kt (82%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt (90%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/applicationservice/accompany/dto/FindAccompanyResponseDto.kt (79%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/applicationservice/accompanylike/AccompanyLikeApplicationService.kt (66%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt (75%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt (63%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/applicationservice/accompanyreply/dto/AccompanyReplyServiceRequestDto.kt (83%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/applicationservice/accompanyreply/dto/FindAccompanyReplyResponse.kt (69%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/applicationservice/accompanyreplylike/AccompanyReplyLikeApplicationService.kt (65%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/applicationservice/auth/AuthApplicationService.kt (83%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/applicationservice/auth/UserNicknameUtils.kt (87%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/applicationservice/auth/dto/AuthResponseDto.kt (64%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/applicationservice/auth/dto/AuthServiceRequestDto.kt (91%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/applicationservice/common/PagingResponse.kt (86%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/applicationservice/test/TestApplicationService.kt (70%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/applicationservice/user/UserApplicationService.kt (55%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/applicationservice/user/dto/UserResponseDto.kt (73%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/applicationservice/user/dto/UserServiceRequestDto.kt (59%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/common/ApiResponse.kt (82%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/common/Constants.kt (91%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/common/ControllerExceptionAdvice.kt (96%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/common/Events.kt (91%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/common/PageInfoRequest.kt (96%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/common/WhiteList.kt (90%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/config/AsyncConfig.kt (95%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/config/AuthConfig.kt (85%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/config/EventConfig.kt (86%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/config/JacksonConfig.kt (95%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/config/SchedulerConfig.kt (76%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/config/SecurityConfig.kt (88%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/config/SwaggerConfig.kt (90%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/config/WebConfigurer.kt (91%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/controller/accompany/AccompanyController.kt (78%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/controller/accompany/dto/AccompanyRequestDto.kt (87%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/controller/accompanylike/AccompanyLikeController.kt (83%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/controller/accompanyreply/AccompanyReplyController.kt (87%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/controller/accompanyreply/dto/AccompanyReplyRequestDto.kt (80%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/controller/accompanyreplylike/AccompanyReplyLikeController.kt (83%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/controller/auth/AuthController.kt (67%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/controller/auth/dto/AuthRequestDto.kt (82%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/controller/test/TestController.kt (84%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/controller/user/UserController.kt (70%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/controller/user/dto/UserRequestDto.kt (90%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/jackson/EnumModule.kt (64%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/jackson/deserializer/SimpleEnumDeserializer.kt (75%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/scheduler/DeleteValidatingEmailScheduler.kt (88%) create mode 100644 withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/SchedulerBasePackage.kt rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/scheduler/SendEmailScheduler.kt (78%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/security/authentication/JwtAuthentication.kt (94%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/security/authentication/UserInfo.kt (68%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/security/handler/HttpStatusAccessDeniedHandler.kt (94%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/security/handler/HttpStatusAuthenticationEntryPoint.kt (94%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/security/jwt/JwtAgent.kt (85%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/security/jwt/JwtAgentImpl.kt (90%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/security/jwt/JwtFilter.kt (89%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/security/resolver/GetAuth.kt (79%) rename withaeng-api/src/main/kotlin/com/{travel/withaeng => withaeng/api}/security/resolver/UserInfoArgumentResolver.kt (81%) rename withaeng-api/src/test/kotlin/com/{travel/withaeng => withaeng/api}/applicationservice/user/UserNicknameUtilsTest.kt (78%) rename withaeng-common/src/main/kotlin/com/{travel => }/withaeng/common/exception/WithaengException.kt (94%) rename withaeng-common/src/main/kotlin/com/{travel => }/withaeng/common/exception/WithaengExceptionType.kt (97%) delete mode 100644 withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/WithaengDomainModule.kt rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/BaseEntity.kt (96%) create mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/WithaengDomainModule.kt rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/accompany/Accompany.kt (92%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/accompany/AccompanyAge.kt (86%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/accompany/AccompanyDestination.kt (92%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/accompany/AccompanyDto.kt (95%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/accompany/AccompanyIncrementViewCountEvent.kt (62%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/accompany/AccompanyRepository.kt (77%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/accompany/AccompanyRepositoryCustom.kt (70%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/accompany/AccompanyRepositoryImpl.kt (85%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/accompany/AccompanyService.kt (87%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/accompany/AccompanyStatus.kt (74%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/accompany/City.kt (99%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/accompany/Continent.kt (90%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/accompany/Country.kt (99%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/accompany/FindAccompanyDto.kt (86%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/accompany/FindAccompanyUserInfoDto.kt (90%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/accompanylike/AccompanyLike.kt (84%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/accompanylike/AccompanyLikeRepository.kt (84%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/accompanylike/AccompanyLikeService.kt (85%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/accompanyreply/AccompanyReply.kt (92%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/accompanyreply/AccompanyReplyDto.kt (92%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt (76%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustom.kt (82%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/accompanyreply/AccompanyReplyRepositoryImpl.kt (88%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/accompanyreply/AccompanyReplyService.kt (69%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/accompanyreply/AccompanyReplyStatus.kt (52%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/accompanyreply/FindAccompanyReplyDto.kt (88%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/accompanyreply/FindAccompanyReplyUserInfoDto.kt (79%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/accompanyreplylike/AccompanyReplyLike.kt (77%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt (83%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt (84%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/accompanystatistics/AccompanyStatistics.kt (83%) rename withaeng-domain/src/main/kotlin/com/{travel/withaeng => withaeng/domain}/config/JasyptConfig.kt (85%) rename withaeng-domain/src/main/kotlin/com/{travel/withaeng => withaeng/domain}/config/JpaConfig.kt (83%) rename withaeng-domain/src/main/kotlin/com/{travel/withaeng => withaeng/domain}/config/JpaQueryDslConfig.kt (93%) rename withaeng-domain/src/main/kotlin/com/{travel/withaeng => withaeng/domain}/converter/TagIdsConverter.kt (92%) rename withaeng-domain/src/main/kotlin/com/{travel/withaeng => withaeng/domain}/converter/UserFoodRestrictionConverter.kt (85%) rename withaeng-domain/src/main/kotlin/com/{travel/withaeng => withaeng/domain}/converter/UserPreferTravelThemeConverter.kt (72%) rename withaeng-domain/src/main/kotlin/com/{travel/withaeng => withaeng/domain}/converter/UserRoleConverter.kt (86%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/tag/Tag.kt (64%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/tag/TagRepository.kt (74%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/user/User.kt (90%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/user/UserConsumeStyle.kt (63%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/user/UserDrinkingType.kt (70%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/user/UserFoodRestriction.kt (80%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/user/UserMbti.kt (76%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/user/UserPreferAccompanyGender.kt (64%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/user/UserPreferTravelTheme.kt (82%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/user/UserPreferTravelType.kt (61%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/user/UserRepository.kt (83%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/user/UserRole.kt (83%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/user/UserService.kt (94%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/user/UserSimpleDto.kt (98%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/user/UserSmokingType.kt (71%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/validateemail/ValidatingEmail.kt (86%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/validateemail/ValidatingEmailDto.kt (90%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/validateemail/ValidatingEmailRepository.kt (93%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/validateemail/ValidatingEmailService.kt (91%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/validateemail/ValidatingEmailStatus.kt (54%) rename withaeng-domain/src/main/kotlin/com/{travel => }/withaeng/domain/validateemail/ValidatingEmailType.kt (59%) rename withaeng-domain/src/test/kotlin/com/{travel/withaeng => withaeng/api}/config/JasyptConfigTest.kt (97%) rename withaeng-domain/src/test/kotlin/com/{travel/withaeng => withaeng/api}/config/TestConfiguration.kt (76%) rename withaeng-external/src/main/kotlin/com/{travel => }/withaeng/external/ses/MailSender.kt (68%) rename withaeng-external/src/main/kotlin/com/{travel => }/withaeng/external/ses/MailSenderImpl.kt (98%) rename withaeng-external/src/main/kotlin/com/{travel => }/withaeng/external/ses/MailType.kt (78%) rename withaeng-external/src/main/kotlin/com/{travel => }/withaeng/external/ses/config/SESConfig.kt (96%) rename withaeng-external/src/main/kotlin/com/{travel => }/withaeng/external/ses/config/ThymeleafConfig.kt (96%) diff --git a/gradle.properties b/gradle.properties index 3fa1429..7b3047d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ ### Application version ### applicationVersion=0.0.1 ### Project configs ### -projectGroup=com.travel +projectGroup=com.withaeng ### Project dependency versions ### kotlinVersion=1.9.22 ### Spring dependency versions ### diff --git a/settings.gradle.kts b/settings.gradle.kts index d9a3ee8..eea101c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -22,5 +22,4 @@ pluginManagement { } } } -} -include("withaeng-external") +} \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/SchedulerBasePackage.kt b/withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/SchedulerBasePackage.kt deleted file mode 100644 index 896dd0b..0000000 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/SchedulerBasePackage.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.travel.withaeng.scheduler - -interface SchedulerBasePackage \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/WithaengApplication.kt b/withaeng-api/src/main/kotlin/com/withaeng/WithaengApplication.kt similarity index 89% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/WithaengApplication.kt rename to withaeng-api/src/main/kotlin/com/withaeng/WithaengApplication.kt index 49bde78..c6722b7 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/WithaengApplication.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/WithaengApplication.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng +package com.withaeng import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/AccompanyApplicationService.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt similarity index 83% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/AccompanyApplicationService.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt index d404bc5..587cff3 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/AccompanyApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt @@ -1,10 +1,10 @@ -package com.travel.withaeng.applicationservice.accompany +package com.withaeng.api.applicationservice.accompany -import com.travel.withaeng.applicationservice.accompany.dto.* -import com.travel.withaeng.common.Events -import com.travel.withaeng.domain.accompany.AccompanyIncrementViewCountEvent -import com.travel.withaeng.domain.accompany.AccompanyService -import com.travel.withaeng.domain.accompanylike.AccompanyLikeService +import com.withaeng.api.applicationservice.accompany.dto.* +import com.withaeng.api.common.Events +import com.withaeng.domain.accompany.AccompanyIncrementViewCountEvent +import com.withaeng.domain.accompany.AccompanyService +import com.withaeng.domain.accompanylike.AccompanyLikeService import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/AccompanyEventListener.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyEventListener.kt similarity index 73% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/AccompanyEventListener.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyEventListener.kt index 8cb1ad7..20377c5 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/AccompanyEventListener.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyEventListener.kt @@ -1,7 +1,7 @@ -package com.travel.withaeng.applicationservice.accompany +package com.withaeng.api.applicationservice.accompany -import com.travel.withaeng.domain.accompany.AccompanyIncrementViewCountEvent -import com.travel.withaeng.domain.accompany.AccompanyService +import com.withaeng.domain.accompany.AccompanyIncrementViewCountEvent +import com.withaeng.domain.accompany.AccompanyService import org.springframework.context.event.EventListener import org.springframework.scheduling.annotation.Async import org.springframework.stereotype.Component diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyResponseDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyResponseDto.kt similarity index 82% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyResponseDto.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyResponseDto.kt index 257a85e..95d1406 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyResponseDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyResponseDto.kt @@ -1,8 +1,8 @@ -package com.travel.withaeng.applicationservice.accompany.dto +package com.withaeng.api.applicationservice.accompany.dto -import com.travel.withaeng.domain.accompany.AccompanyDestination -import com.travel.withaeng.domain.accompany.AccompanyDto -import com.travel.withaeng.domain.user.UserPreferAccompanyGender +import com.withaeng.domain.accompany.AccompanyDestination +import com.withaeng.domain.accompany.AccompanyDto +import com.withaeng.domain.user.UserPreferAccompanyGender import java.time.LocalDate data class AccompanyResponse( diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt similarity index 90% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt index 38db38d..ebe9710 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt @@ -1,7 +1,7 @@ -package com.travel.withaeng.applicationservice.accompany.dto +package com.withaeng.api.applicationservice.accompany.dto -import com.travel.withaeng.domain.accompany.* -import com.travel.withaeng.domain.user.UserPreferAccompanyGender +import com.withaeng.domain.accompany.* +import com.withaeng.domain.user.UserPreferAccompanyGender import java.time.LocalDate data class CreateAccompanyServiceRequest( diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/FindAccompanyResponseDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/FindAccompanyResponseDto.kt similarity index 79% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/FindAccompanyResponseDto.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/FindAccompanyResponseDto.kt index f5cb782..6c509b5 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompany/dto/FindAccompanyResponseDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/FindAccompanyResponseDto.kt @@ -1,9 +1,9 @@ -package com.travel.withaeng.applicationservice.accompany.dto +package com.withaeng.api.applicationservice.accompany.dto -import com.travel.withaeng.domain.accompany.AccompanyDestination -import com.travel.withaeng.domain.accompany.FindAccompanyDto -import com.travel.withaeng.domain.accompany.FindAccompanyUserInfoDto -import com.travel.withaeng.domain.user.UserPreferAccompanyGender +import com.withaeng.domain.accompany.AccompanyDestination +import com.withaeng.domain.accompany.FindAccompanyDto +import com.withaeng.domain.accompany.FindAccompanyUserInfoDto +import com.withaeng.domain.user.UserPreferAccompanyGender import java.time.LocalDate data class FindAccompanyResponse( diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanylike/AccompanyLikeApplicationService.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanylike/AccompanyLikeApplicationService.kt similarity index 66% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanylike/AccompanyLikeApplicationService.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanylike/AccompanyLikeApplicationService.kt index 091672e..38b6443 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanylike/AccompanyLikeApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanylike/AccompanyLikeApplicationService.kt @@ -1,12 +1,14 @@ -package com.travel.withaeng.applicationservice.accompanylike +package com.withaeng.api.applicationservice.accompanylike -import com.travel.withaeng.domain.accompanylike.AccompanyLikeService +import com.withaeng.domain.accompanylike.AccompanyLikeService import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @Transactional(readOnly = true) @Service -class AccompanyLikeApplicationService(private val accompanyLikeService: AccompanyLikeService) { +class AccompanyLikeApplicationService( + private val accompanyLikeService: AccompanyLikeService +) { @Transactional fun like(userId: Long, accompanyId: Long) { diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt similarity index 75% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt index e3a3738..95e1539 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt @@ -1,15 +1,15 @@ -package com.travel.withaeng.applicationservice.accompanyreply +package com.withaeng.api.applicationservice.accompanyreply -import com.travel.withaeng.applicationservice.accompanyreply.dto.* -import com.travel.withaeng.applicationservice.common.PagingResponse -import com.travel.withaeng.applicationservice.common.toPaging -import com.travel.withaeng.common.exception.WithaengException -import com.travel.withaeng.common.exception.WithaengExceptionType -import com.travel.withaeng.domain.accompanyreply.AccompanyReplyDto -import com.travel.withaeng.domain.accompanyreply.AccompanyReplyService -import com.travel.withaeng.domain.accompanyreply.AccompanyReplyStatus -import com.travel.withaeng.domain.accompanyreplylike.AccompanyReplyLikeService -import com.travel.withaeng.domain.user.UserService +import com.withaeng.api.applicationservice.accompanyreply.dto.* +import com.withaeng.api.applicationservice.common.PagingResponse +import com.withaeng.api.applicationservice.common.toPaging +import com.withaeng.common.exception.WithaengException +import com.withaeng.common.exception.WithaengExceptionType +import com.withaeng.domain.accompanyreply.AccompanyReplyDto +import com.withaeng.domain.accompanyreply.AccompanyReplyService +import com.withaeng.domain.accompanyreply.AccompanyReplyStatus +import com.withaeng.domain.accompanyreplylike.AccompanyReplyLikeService +import com.withaeng.domain.user.UserService import org.springframework.data.domain.Pageable import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -35,9 +35,7 @@ class AccompanyReplyApplicationService( fun getList(accompanyId: Long, pageable: Pageable): PagingResponse> { val accompanyReplyPage = accompanyReplyService.getList(accompanyId, pageable) - val accompanyReplyResponseList = accompanyReplyPage - .map { it.toResponse() } - .toList() + val accompanyReplyResponseList = accompanyReplyPage.map { it.toResponse() }.toList() return PagingResponse(accompanyReplyResponseList, accompanyReplyPage.toPaging()) } @@ -74,8 +72,7 @@ class AccompanyReplyApplicationService( private fun validateDeletionStatus(status: AccompanyReplyStatus) { if (status == AccompanyReplyStatus.DELETED) { throw WithaengException.of( - type = WithaengExceptionType.INVALID_INPUT, - message = "삭제된 댓글 입니다." + type = WithaengExceptionType.INVALID_INPUT, message = "삭제된 댓글 입니다." ) } } @@ -99,8 +96,7 @@ class AccompanyReplyApplicationService( private fun validateSubReply(parentId: Long?, requestParentId: Long?) { if (parentId != null && requestParentId == null) { throw WithaengException.of( - type = WithaengExceptionType.INVALID_INPUT, - message = "댓글이 아닙니다." + type = WithaengExceptionType.INVALID_INPUT, message = "댓글이 아닙니다." ) } } @@ -108,8 +104,7 @@ class AccompanyReplyApplicationService( private fun validateParentId(parentId: Long, requestParentId: Long?) { if (parentId != requestParentId) { throw WithaengException.of( - type = WithaengExceptionType.INVALID_INPUT, - message = "해당 댓글에 대한 대댓글이 아닙니다." + type = WithaengExceptionType.INVALID_INPUT, message = "해당 댓글에 대한 대댓글이 아닙니다." ) } } diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt similarity index 63% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt index dec8794..03241be 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt @@ -1,10 +1,10 @@ -package com.travel.withaeng.applicationservice.accompanyreply.dto +package com.withaeng.api.applicationservice.accompanyreply.dto -import com.travel.withaeng.applicationservice.user.dto.UserSimpleResponse -import com.travel.withaeng.applicationservice.user.dto.toSimpleResponse -import com.travel.withaeng.domain.accompanyreply.AccompanyReplyDto -import com.travel.withaeng.domain.accompanyreply.AccompanyReplyStatus -import com.travel.withaeng.domain.user.UserSimpleDto +import com.withaeng.api.applicationservice.user.dto.UserSimpleResponse +import com.withaeng.api.applicationservice.user.dto.toSimpleResponse +import com.withaeng.domain.accompanyreply.AccompanyReplyDto +import com.withaeng.domain.accompanyreply.AccompanyReplyStatus +import com.withaeng.domain.user.UserSimpleDto import java.time.LocalDateTime data class AccompanyReplyResponse( diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyServiceRequestDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanyreply/dto/AccompanyReplyServiceRequestDto.kt similarity index 83% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyServiceRequestDto.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanyreply/dto/AccompanyReplyServiceRequestDto.kt index 5b91385..3d6e4cd 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/AccompanyReplyServiceRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanyreply/dto/AccompanyReplyServiceRequestDto.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.applicationservice.accompanyreply.dto +package com.withaeng.api.applicationservice.accompanyreply.dto data class CreateAccompanyReplyServiceRequest( val userId: Long, diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/FindAccompanyReplyResponse.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanyreply/dto/FindAccompanyReplyResponse.kt similarity index 69% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/FindAccompanyReplyResponse.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanyreply/dto/FindAccompanyReplyResponse.kt index eba38bf..1876623 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreply/dto/FindAccompanyReplyResponse.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanyreply/dto/FindAccompanyReplyResponse.kt @@ -1,8 +1,8 @@ -package com.travel.withaeng.applicationservice.accompanyreply.dto +package com.withaeng.api.applicationservice.accompanyreply.dto -import com.travel.withaeng.domain.accompanyreply.AccompanyReplyStatus -import com.travel.withaeng.domain.accompanyreply.FindAccompanyReplyDto -import com.travel.withaeng.domain.accompanyreply.FindAccompanyReplyUserInfoDto +import com.withaeng.domain.accompanyreply.AccompanyReplyStatus +import com.withaeng.domain.accompanyreply.FindAccompanyReplyDto +import com.withaeng.domain.accompanyreply.FindAccompanyReplyUserInfoDto import java.time.LocalDateTime data class FindAccompanyReplyResponse( diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreplylike/AccompanyReplyLikeApplicationService.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanyreplylike/AccompanyReplyLikeApplicationService.kt similarity index 65% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreplylike/AccompanyReplyLikeApplicationService.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanyreplylike/AccompanyReplyLikeApplicationService.kt index 99d7692..130e7be 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/accompanyreplylike/AccompanyReplyLikeApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanyreplylike/AccompanyReplyLikeApplicationService.kt @@ -1,12 +1,14 @@ -package com.travel.withaeng.applicationservice.accompanyreplylike +package com.withaeng.api.applicationservice.accompanyreplylike -import com.travel.withaeng.domain.accompanyreplylike.AccompanyReplyLikeService +import com.withaeng.domain.accompanyreplylike.AccompanyReplyLikeService import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @Service @Transactional(readOnly = true) -class AccompanyReplyLikeApplicationService(private val accompanyReplyLikeService: AccompanyReplyLikeService) { +class AccompanyReplyLikeApplicationService( + private val accompanyReplyLikeService: AccompanyReplyLikeService +) { @Transactional fun like(userId: Long, accompanyReplyId: Long) { diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/AuthApplicationService.kt similarity index 83% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/AuthApplicationService.kt index 7fe4ff0..7432250 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/AuthApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/AuthApplicationService.kt @@ -1,26 +1,20 @@ -package com.travel.withaeng.applicationservice.auth +package com.withaeng.api.applicationservice.auth -import com.travel.withaeng.applicationservice.auth.dto.ChangePasswordServiceRequest -import com.travel.withaeng.applicationservice.auth.dto.ResendEmailServiceRequest -import com.travel.withaeng.applicationservice.auth.dto.SendEmailForChangePasswordServiceRequest -import com.travel.withaeng.applicationservice.auth.dto.SignInServiceRequest -import com.travel.withaeng.applicationservice.auth.dto.SignUpServiceRequest -import com.travel.withaeng.applicationservice.auth.dto.UserResponse -import com.travel.withaeng.applicationservice.auth.dto.ValidateEmailServiceRequest -import com.travel.withaeng.common.exception.WithaengException -import com.travel.withaeng.common.exception.WithaengExceptionType -import com.travel.withaeng.domain.user.CreateUserDto -import com.travel.withaeng.domain.user.UserRole -import com.travel.withaeng.domain.user.UserService -import com.travel.withaeng.domain.user.UserSimpleDto -import com.travel.withaeng.domain.validateemail.ValidatingEmailService -import com.travel.withaeng.domain.validateemail.ValidatingEmailType -import com.travel.withaeng.security.authentication.UserInfo -import com.travel.withaeng.security.jwt.JwtAgent +import com.withaeng.api.applicationservice.auth.dto.* +import com.withaeng.api.security.authentication.UserInfo +import com.withaeng.api.security.jwt.JwtAgent +import com.withaeng.common.exception.WithaengException +import com.withaeng.common.exception.WithaengExceptionType +import com.withaeng.domain.user.CreateUserDto +import com.withaeng.domain.user.UserRole +import com.withaeng.domain.user.UserService +import com.withaeng.domain.user.UserSimpleDto +import com.withaeng.domain.validateemail.ValidatingEmailService +import com.withaeng.domain.validateemail.ValidatingEmailType import org.springframework.security.crypto.password.PasswordEncoder import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional -import java.util.UUID +import java.util.* @Service @Transactional(readOnly = true) diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/UserNicknameUtils.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/UserNicknameUtils.kt similarity index 87% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/UserNicknameUtils.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/UserNicknameUtils.kt index 0c9c95a..ff4722e 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/UserNicknameUtils.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/UserNicknameUtils.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.applicationservice.auth +package com.withaeng.api.applicationservice.auth import java.util.UUID diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthResponseDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/dto/AuthResponseDto.kt similarity index 64% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthResponseDto.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/dto/AuthResponseDto.kt index 44f95a8..ba70ed5 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthResponseDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/dto/AuthResponseDto.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.applicationservice.auth.dto +package com.withaeng.api.applicationservice.auth.dto data class UserResponse( val userId: Long, diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthServiceRequestDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/dto/AuthServiceRequestDto.kt similarity index 91% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthServiceRequestDto.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/dto/AuthServiceRequestDto.kt index 7963c23..c14d3b5 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/auth/dto/AuthServiceRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/dto/AuthServiceRequestDto.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.applicationservice.auth.dto +package com.withaeng.api.applicationservice.auth.dto import java.time.LocalDate diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/common/PagingResponse.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/common/PagingResponse.kt similarity index 86% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/common/PagingResponse.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/common/PagingResponse.kt index c552d80..41d89dc 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/common/PagingResponse.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/common/PagingResponse.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.applicationservice.common +package com.withaeng.api.applicationservice.common import org.springframework.data.domain.Page diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/test/TestApplicationService.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/test/TestApplicationService.kt similarity index 70% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/test/TestApplicationService.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/test/TestApplicationService.kt index 3502224..b04ef71 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/test/TestApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/test/TestApplicationService.kt @@ -1,8 +1,8 @@ -package com.travel.withaeng.applicationservice.test +package com.withaeng.api.applicationservice.test -import com.travel.withaeng.domain.user.UserService -import com.travel.withaeng.security.authentication.UserInfo -import com.travel.withaeng.security.jwt.JwtAgent +import com.withaeng.domain.user.UserService +import com.withaeng.api.security.authentication.UserInfo +import com.withaeng.api.security.jwt.JwtAgent import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/UserApplicationService.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/UserApplicationService.kt similarity index 55% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/UserApplicationService.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/UserApplicationService.kt index 9566a06..0e0459a 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/UserApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/UserApplicationService.kt @@ -1,15 +1,17 @@ -package com.travel.withaeng.applicationservice.user +package com.withaeng.api.applicationservice.user -import com.travel.withaeng.applicationservice.user.dto.AddUserDetailsServerRequest -import com.travel.withaeng.applicationservice.user.dto.UserDetailsResponse -import com.travel.withaeng.applicationservice.user.dto.toDomainDto -import com.travel.withaeng.domain.user.UserService +import com.withaeng.api.applicationservice.user.dto.AddUserDetailsServerRequest +import com.withaeng.api.applicationservice.user.dto.UserDetailsResponse +import com.withaeng.api.applicationservice.user.dto.toDomainDto +import com.withaeng.domain.user.UserService import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @Transactional(readOnly = true) @Service -class UserApplicationService(private val userService: UserService) { +class UserApplicationService( + private val userService: UserService +) { @Transactional fun addDetails(addUserDetailsServerRequest: AddUserDetailsServerRequest): UserDetailsResponse { diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/dto/UserResponseDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserResponseDto.kt similarity index 73% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/dto/UserResponseDto.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserResponseDto.kt index ec79c59..31935f9 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/dto/UserResponseDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserResponseDto.kt @@ -1,15 +1,15 @@ -package com.travel.withaeng.applicationservice.user.dto +package com.withaeng.api.applicationservice.user.dto -import com.travel.withaeng.domain.user.UserConsumeStyle -import com.travel.withaeng.domain.user.UserDetailsDto -import com.travel.withaeng.domain.user.UserDrinkingType -import com.travel.withaeng.domain.user.UserFoodRestriction -import com.travel.withaeng.domain.user.UserMbti -import com.travel.withaeng.domain.user.UserPreferAccompanyGender -import com.travel.withaeng.domain.user.UserPreferTravelTheme -import com.travel.withaeng.domain.user.UserPreferTravelType -import com.travel.withaeng.domain.user.UserSimpleDto -import com.travel.withaeng.domain.user.UserSmokingType +import com.withaeng.domain.user.UserConsumeStyle +import com.withaeng.domain.user.UserDetailsDto +import com.withaeng.domain.user.UserDrinkingType +import com.withaeng.domain.user.UserFoodRestriction +import com.withaeng.domain.user.UserMbti +import com.withaeng.domain.user.UserPreferAccompanyGender +import com.withaeng.domain.user.UserPreferTravelTheme +import com.withaeng.domain.user.UserPreferTravelType +import com.withaeng.domain.user.UserSimpleDto +import com.withaeng.domain.user.UserSmokingType import java.time.LocalDate data class UserDetailsResponse( diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/dto/UserServiceRequestDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceRequestDto.kt similarity index 59% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/dto/UserServiceRequestDto.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceRequestDto.kt index 576e098..c138bd0 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/applicationservice/user/dto/UserServiceRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceRequestDto.kt @@ -1,16 +1,16 @@ -package com.travel.withaeng.applicationservice.user.dto +package com.withaeng.api.applicationservice.user.dto -import com.travel.withaeng.domain.user.AddDetailsUserDto -import com.travel.withaeng.domain.user.UserConsumeStyle -import com.travel.withaeng.domain.user.UserDrinkingType -import com.travel.withaeng.domain.user.UserFoodRestriction -import com.travel.withaeng.domain.user.UserMbti -import com.travel.withaeng.domain.user.UserPreferAccompanyGender -import com.travel.withaeng.domain.user.UserPreferTravelTheme -import com.travel.withaeng.domain.user.UserPreferTravelType -import com.travel.withaeng.domain.user.UserSmokingType +import com.withaeng.domain.user.AddDetailsUserDto +import com.withaeng.domain.user.UserConsumeStyle +import com.withaeng.domain.user.UserDrinkingType +import com.withaeng.domain.user.UserFoodRestriction +import com.withaeng.domain.user.UserMbti +import com.withaeng.domain.user.UserPreferAccompanyGender +import com.withaeng.domain.user.UserPreferTravelTheme +import com.withaeng.domain.user.UserPreferTravelType +import com.withaeng.domain.user.UserSmokingType -data class AddUserDetailsServerRequest ( +data class AddUserDetailsServerRequest( val userId: Long, val nickname: String? = null, val mbti: UserMbti? = null, diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ApiResponse.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/common/ApiResponse.kt similarity index 82% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/common/ApiResponse.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/common/ApiResponse.kt index 4a35116..d5cd1bd 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ApiResponse.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/common/ApiResponse.kt @@ -1,8 +1,8 @@ -package com.travel.withaeng.common +package com.withaeng.api.common -import com.travel.withaeng.applicationservice.common.Paging -import com.travel.withaeng.applicationservice.common.PagingResponse -import com.travel.withaeng.common.exception.WithaengExceptionType +import com.withaeng.api.applicationservice.common.Paging +import com.withaeng.api.applicationservice.common.PagingResponse +import com.withaeng.common.exception.WithaengExceptionType data class ApiResponse( val success: Boolean = true, diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/Constants.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/common/Constants.kt similarity index 91% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/common/Constants.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/common/Constants.kt index 9ded966..d74fb24 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/Constants.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/common/Constants.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.common +package com.withaeng.api.common object Constants { object Authentication { diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ControllerExceptionAdvice.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/common/ControllerExceptionAdvice.kt similarity index 96% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/common/ControllerExceptionAdvice.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/common/ControllerExceptionAdvice.kt index e688510..6270efa 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/ControllerExceptionAdvice.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/common/ControllerExceptionAdvice.kt @@ -1,8 +1,8 @@ -package com.travel.withaeng.common +package com.withaeng.api.common import com.fasterxml.jackson.databind.JsonMappingException -import com.travel.withaeng.common.exception.WithaengException -import com.travel.withaeng.common.exception.WithaengExceptionType +import com.withaeng.common.exception.WithaengException +import com.withaeng.common.exception.WithaengExceptionType import org.slf4j.Logger import org.slf4j.LoggerFactory import org.springframework.http.HttpStatus diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/Events.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/common/Events.kt similarity index 91% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/common/Events.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/common/Events.kt index cf65cc3..8212c9f 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/Events.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/common/Events.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.common +package com.withaeng.api.common import org.springframework.context.ApplicationEventPublisher diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/PageInfoRequest.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/common/PageInfoRequest.kt similarity index 96% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/common/PageInfoRequest.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/common/PageInfoRequest.kt index a0fd0f2..e577916 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/PageInfoRequest.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/common/PageInfoRequest.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.common +package com.withaeng.api.common import io.swagger.v3.oas.annotations.media.Schema import org.springframework.data.domain.PageRequest diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/WhiteList.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/common/WhiteList.kt similarity index 90% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/common/WhiteList.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/common/WhiteList.kt index 8bd280f..59dd412 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/common/WhiteList.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/common/WhiteList.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.common +package com.withaeng.api.common object WhiteList { diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/AsyncConfig.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/config/AsyncConfig.kt similarity index 95% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/config/AsyncConfig.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/config/AsyncConfig.kt index 24b527d..1215210 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/AsyncConfig.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/config/AsyncConfig.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.config +package com.withaeng.api.config import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/AuthConfig.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/config/AuthConfig.kt similarity index 85% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/config/AuthConfig.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/config/AuthConfig.kt index 93eaa45..dc96ee1 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/AuthConfig.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/config/AuthConfig.kt @@ -1,8 +1,8 @@ -package com.travel.withaeng.config +package com.withaeng.api.config import com.fasterxml.jackson.databind.ObjectMapper -import com.travel.withaeng.security.jwt.JwtAgent -import com.travel.withaeng.security.jwt.JwtAgentImpl +import com.withaeng.api.security.jwt.JwtAgent +import com.withaeng.api.security.jwt.JwtAgentImpl import org.springframework.boot.context.properties.ConfigurationProperties import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.context.annotation.Bean @@ -11,7 +11,6 @@ import org.springframework.context.annotation.Configuration @Configuration @EnableConfigurationProperties(AuthProperty::class) class AuthConfig { - @Bean fun jwtAgent(mapper: ObjectMapper, authProperty: AuthProperty): JwtAgent { return JwtAgentImpl( diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/EventConfig.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/config/EventConfig.kt similarity index 86% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/config/EventConfig.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/config/EventConfig.kt index 4d06045..1ff52ba 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/EventConfig.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/config/EventConfig.kt @@ -1,6 +1,6 @@ -package com.travel.withaeng.config +package com.withaeng.api.config -import com.travel.withaeng.common.Events +import com.withaeng.api.common.Events import org.springframework.beans.factory.InitializingBean import org.springframework.context.ApplicationEventPublisher import org.springframework.context.annotation.Bean diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/JacksonConfig.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/config/JacksonConfig.kt similarity index 95% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/config/JacksonConfig.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/config/JacksonConfig.kt index 45a47dd..3c61287 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/JacksonConfig.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/config/JacksonConfig.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.config +package com.withaeng.api.config import com.fasterxml.jackson.databind.DeserializationFeature import com.fasterxml.jackson.databind.Module @@ -6,7 +6,7 @@ import com.fasterxml.jackson.databind.SerializationFeature import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer -import com.travel.withaeng.jackson.EnumModule +import com.withaeng.api.jackson.EnumModule import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/SchedulerConfig.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/config/SchedulerConfig.kt similarity index 76% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/config/SchedulerConfig.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/config/SchedulerConfig.kt index b36be83..7935666 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/SchedulerConfig.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/config/SchedulerConfig.kt @@ -1,6 +1,6 @@ -package com.travel.withaeng.config +package com.withaeng.api.config -import com.travel.withaeng.scheduler.SchedulerBasePackage +import com.withaeng.api.scheduler.SchedulerBasePackage import org.springframework.context.annotation.ComponentScan import org.springframework.context.annotation.Configuration import org.springframework.scheduling.annotation.EnableScheduling diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/SecurityConfig.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/config/SecurityConfig.kt similarity index 88% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/config/SecurityConfig.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/config/SecurityConfig.kt index 45a944f..49a7988 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/SecurityConfig.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/config/SecurityConfig.kt @@ -1,12 +1,12 @@ -package com.travel.withaeng.config +package com.withaeng.api.config import com.fasterxml.jackson.databind.ObjectMapper -import com.travel.withaeng.common.WhiteList.getWhiteListForSecurityConfig -import com.travel.withaeng.domain.user.UserRole -import com.travel.withaeng.security.handler.HttpStatusAccessDeniedHandler -import com.travel.withaeng.security.handler.HttpStatusAuthenticationEntryPoint -import com.travel.withaeng.security.jwt.JwtAgent -import com.travel.withaeng.security.jwt.JwtFilter +import com.withaeng.domain.user.UserRole +import com.withaeng.api.common.WhiteList.getWhiteListForSecurityConfig +import com.withaeng.api.security.handler.HttpStatusAccessDeniedHandler +import com.withaeng.api.security.handler.HttpStatusAuthenticationEntryPoint +import com.withaeng.api.security.jwt.JwtAgent +import com.withaeng.api.security.jwt.JwtFilter import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.http.HttpHeaders diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/SwaggerConfig.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/config/SwaggerConfig.kt similarity index 90% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/config/SwaggerConfig.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/config/SwaggerConfig.kt index 5113cdc..8548a79 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/SwaggerConfig.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/config/SwaggerConfig.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.config +package com.withaeng.api.config import io.swagger.v3.oas.annotations.enums.SecuritySchemeType import io.swagger.v3.oas.annotations.security.SecurityScheme diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/WebConfigurer.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/config/WebConfigurer.kt similarity index 91% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/config/WebConfigurer.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/config/WebConfigurer.kt index 4375465..889d301 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/config/WebConfigurer.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/config/WebConfigurer.kt @@ -1,6 +1,6 @@ -package com.travel.withaeng.config +package com.withaeng.api.config -import com.travel.withaeng.security.resolver.UserInfoArgumentResolver +import com.withaeng.api.security.resolver.UserInfoArgumentResolver import org.springframework.context.annotation.Configuration import org.springframework.http.converter.ByteArrayHttpMessageConverter import org.springframework.http.converter.HttpMessageConverter diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/AccompanyController.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt similarity index 78% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/AccompanyController.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt index 68f1361..a294731 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/AccompanyController.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt @@ -1,14 +1,14 @@ -package com.travel.withaeng.controller.accompany +package com.withaeng.api.controller.accompany -import com.travel.withaeng.applicationservice.accompany.AccompanyApplicationService -import com.travel.withaeng.applicationservice.accompany.dto.AccompanyResponse -import com.travel.withaeng.applicationservice.accompany.dto.FindAccompanyResponse -import com.travel.withaeng.common.ApiResponse -import com.travel.withaeng.controller.accompany.dto.CreateAccompanyRequest -import com.travel.withaeng.controller.accompany.dto.UpdateAccompanyRequest -import com.travel.withaeng.controller.accompany.dto.toServiceRequest -import com.travel.withaeng.security.authentication.UserInfo -import com.travel.withaeng.security.resolver.GetAuth +import com.withaeng.api.applicationservice.accompany.AccompanyApplicationService +import com.withaeng.api.applicationservice.accompany.dto.AccompanyResponse +import com.withaeng.api.applicationservice.accompany.dto.FindAccompanyResponse +import com.withaeng.api.common.ApiResponse +import com.withaeng.api.controller.accompany.dto.CreateAccompanyRequest +import com.withaeng.api.controller.accompany.dto.UpdateAccompanyRequest +import com.withaeng.api.controller.accompany.dto.toServiceRequest +import com.withaeng.api.security.authentication.UserInfo +import com.withaeng.api.security.resolver.GetAuth import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.security.SecurityRequirement import io.swagger.v3.oas.annotations.tags.Tag diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/dto/AccompanyRequestDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt similarity index 87% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/dto/AccompanyRequestDto.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt index b30dcb9..2914fc9 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompany/dto/AccompanyRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt @@ -1,11 +1,11 @@ -package com.travel.withaeng.controller.accompany.dto +package com.withaeng.api.controller.accompany.dto import com.fasterxml.jackson.databind.annotation.JsonDeserialize -import com.travel.withaeng.applicationservice.accompany.dto.CreateAccompanyServiceRequest -import com.travel.withaeng.applicationservice.accompany.dto.UpdateAccompanyServiceRequest -import com.travel.withaeng.domain.accompany.AccompanyAge -import com.travel.withaeng.domain.accompany.AccompanyAgeDeserializer -import com.travel.withaeng.domain.user.UserPreferAccompanyGender +import com.withaeng.domain.accompany.AccompanyAge +import com.withaeng.domain.accompany.AccompanyAgeDeserializer +import com.withaeng.domain.user.UserPreferAccompanyGender +import com.withaeng.api.applicationservice.accompany.dto.CreateAccompanyServiceRequest +import com.withaeng.api.applicationservice.accompany.dto.UpdateAccompanyServiceRequest import io.swagger.v3.oas.annotations.media.Schema import java.time.LocalDate diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanylike/AccompanyLikeController.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompanylike/AccompanyLikeController.kt similarity index 83% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanylike/AccompanyLikeController.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompanylike/AccompanyLikeController.kt index c65a30c..11158ae 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanylike/AccompanyLikeController.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompanylike/AccompanyLikeController.kt @@ -1,9 +1,9 @@ -package com.travel.withaeng.controller.accompanylike +package com.withaeng.api.controller.accompanylike -import com.travel.withaeng.applicationservice.accompanylike.AccompanyLikeApplicationService -import com.travel.withaeng.common.ApiResponse -import com.travel.withaeng.security.authentication.UserInfo -import com.travel.withaeng.security.resolver.GetAuth +import com.withaeng.api.applicationservice.accompanylike.AccompanyLikeApplicationService +import com.withaeng.api.common.ApiResponse +import com.withaeng.api.security.authentication.UserInfo +import com.withaeng.api.security.resolver.GetAuth import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.security.SecurityRequirement import io.swagger.v3.oas.annotations.tags.Tag diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompanyreply/AccompanyReplyController.kt similarity index 87% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompanyreply/AccompanyReplyController.kt index 4837fd6..9e8edbf 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/AccompanyReplyController.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompanyreply/AccompanyReplyController.kt @@ -1,15 +1,15 @@ -package com.travel.withaeng.controller.accompanyreply +package com.withaeng.api.controller.accompanyreply -import com.travel.withaeng.applicationservice.accompanyreply.AccompanyReplyApplicationService -import com.travel.withaeng.applicationservice.accompanyreply.dto.AccompanyReplyResponse -import com.travel.withaeng.applicationservice.accompanyreply.dto.FindAccompanyReplyResponse -import com.travel.withaeng.common.ApiResponse -import com.travel.withaeng.common.PageInfoRequest -import com.travel.withaeng.controller.accompanyreply.dto.CreateAccompanyReplyRequest -import com.travel.withaeng.controller.accompanyreply.dto.UpdateAccompanyReplyRequest -import com.travel.withaeng.controller.accompanyreply.dto.toServiceRequest -import com.travel.withaeng.security.authentication.UserInfo -import com.travel.withaeng.security.resolver.GetAuth +import com.withaeng.api.applicationservice.accompanyreply.AccompanyReplyApplicationService +import com.withaeng.api.applicationservice.accompanyreply.dto.AccompanyReplyResponse +import com.withaeng.api.applicationservice.accompanyreply.dto.FindAccompanyReplyResponse +import com.withaeng.api.common.ApiResponse +import com.withaeng.api.common.PageInfoRequest +import com.withaeng.api.controller.accompanyreply.dto.CreateAccompanyReplyRequest +import com.withaeng.api.controller.accompanyreply.dto.UpdateAccompanyReplyRequest +import com.withaeng.api.controller.accompanyreply.dto.toServiceRequest +import com.withaeng.api.security.authentication.UserInfo +import com.withaeng.api.security.resolver.GetAuth import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.security.SecurityRequirement import io.swagger.v3.oas.annotations.tags.Tag diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/dto/AccompanyReplyRequestDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompanyreply/dto/AccompanyReplyRequestDto.kt similarity index 80% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/dto/AccompanyReplyRequestDto.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompanyreply/dto/AccompanyReplyRequestDto.kt index 5712d32..4e966cb 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreply/dto/AccompanyReplyRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompanyreply/dto/AccompanyReplyRequestDto.kt @@ -1,7 +1,7 @@ -package com.travel.withaeng.controller.accompanyreply.dto +package com.withaeng.api.controller.accompanyreply.dto -import com.travel.withaeng.applicationservice.accompanyreply.dto.CreateAccompanyReplyServiceRequest -import com.travel.withaeng.applicationservice.accompanyreply.dto.UpdateAccompanyReplyServiceRequest +import com.withaeng.api.applicationservice.accompanyreply.dto.CreateAccompanyReplyServiceRequest +import com.withaeng.api.applicationservice.accompanyreply.dto.UpdateAccompanyReplyServiceRequest import io.swagger.v3.oas.annotations.media.Schema @Schema(description = "[Request] 동행 댓글 생성") diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreplylike/AccompanyReplyLikeController.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompanyreplylike/AccompanyReplyLikeController.kt similarity index 83% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreplylike/AccompanyReplyLikeController.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompanyreplylike/AccompanyReplyLikeController.kt index 727f40a..2619456 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/accompanyreplylike/AccompanyReplyLikeController.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompanyreplylike/AccompanyReplyLikeController.kt @@ -1,9 +1,9 @@ -package com.travel.withaeng.controller.accompanyreplylike +package com.withaeng.api.controller.accompanyreplylike -import com.travel.withaeng.applicationservice.accompanyreplylike.AccompanyReplyLikeApplicationService -import com.travel.withaeng.common.ApiResponse -import com.travel.withaeng.security.authentication.UserInfo -import com.travel.withaeng.security.resolver.GetAuth +import com.withaeng.api.applicationservice.accompanyreplylike.AccompanyReplyLikeApplicationService +import com.withaeng.api.common.ApiResponse +import com.withaeng.api.security.authentication.UserInfo +import com.withaeng.api.security.resolver.GetAuth import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.security.SecurityRequirement import io.swagger.v3.oas.annotations.tags.Tag diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/auth/AuthController.kt similarity index 67% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/controller/auth/AuthController.kt index cbd3a23..2bc7e3b 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/AuthController.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/auth/AuthController.kt @@ -1,28 +1,19 @@ -package com.travel.withaeng.controller.auth +package com.withaeng.api.controller.auth -import com.travel.withaeng.applicationservice.auth.AuthApplicationService -import com.travel.withaeng.applicationservice.auth.dto.UserResponse -import com.travel.withaeng.common.ApiResponse -import com.travel.withaeng.controller.auth.dto.ChangePasswordRequest -import com.travel.withaeng.controller.auth.dto.ResendEmailRequest -import com.travel.withaeng.controller.auth.dto.SendEmailForChangePasswordRequest -import com.travel.withaeng.controller.auth.dto.SignInRequest -import com.travel.withaeng.controller.auth.dto.SignUpRequest -import com.travel.withaeng.controller.auth.dto.ValidateEmailRequest -import com.travel.withaeng.controller.auth.dto.toServiceRequest +import com.withaeng.api.applicationservice.auth.AuthApplicationService +import com.withaeng.api.applicationservice.auth.dto.UserResponse +import com.withaeng.api.common.ApiResponse +import com.withaeng.api.controller.auth.dto.* import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.tags.Tag -import org.springframework.web.bind.annotation.PostMapping -import org.springframework.web.bind.annotation.PutMapping -import org.springframework.web.bind.annotation.RequestBody -import org.springframework.web.bind.annotation.RequestMapping -import org.springframework.web.bind.annotation.RestController +import org.springframework.web.bind.annotation.* @Tag(name = "Auth", description = "인증 API") @RestController @RequestMapping("/api/v1/auth") -class AuthController(private val authApplicationService: AuthApplicationService) { - +class AuthController( + private val authApplicationService: AuthApplicationService +) { @Operation(summary = "Sign Up API", description = "회원가입 API") @PostMapping("/sign-up") fun signUp(@RequestBody request: SignUpRequest): ApiResponse { diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/dto/AuthRequestDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/auth/dto/AuthRequestDto.kt similarity index 82% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/dto/AuthRequestDto.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/controller/auth/dto/AuthRequestDto.kt index f7c15df..3b09480 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/auth/dto/AuthRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/auth/dto/AuthRequestDto.kt @@ -1,11 +1,6 @@ -package com.travel.withaeng.controller.auth.dto - -import com.travel.withaeng.applicationservice.auth.dto.ChangePasswordServiceRequest -import com.travel.withaeng.applicationservice.auth.dto.ResendEmailServiceRequest -import com.travel.withaeng.applicationservice.auth.dto.SendEmailForChangePasswordServiceRequest -import com.travel.withaeng.applicationservice.auth.dto.SignInServiceRequest -import com.travel.withaeng.applicationservice.auth.dto.SignUpServiceRequest -import com.travel.withaeng.applicationservice.auth.dto.ValidateEmailServiceRequest +package com.withaeng.api.controller.auth.dto + +import com.withaeng.api.applicationservice.auth.dto.* import io.swagger.v3.oas.annotations.media.Schema import java.time.LocalDate diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/test/TestController.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/test/TestController.kt similarity index 84% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/controller/test/TestController.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/controller/test/TestController.kt index 1d14f07..072c225 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/test/TestController.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/test/TestController.kt @@ -1,7 +1,7 @@ -package com.travel.withaeng.controller.test +package com.withaeng.api.controller.test -import com.travel.withaeng.applicationservice.test.TestApplicationService -import com.travel.withaeng.common.ApiResponse +import com.withaeng.api.applicationservice.test.TestApplicationService +import com.withaeng.api.common.ApiResponse import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.tags.Tag import org.springframework.web.bind.annotation.* diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/user/UserController.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/UserController.kt similarity index 70% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/controller/user/UserController.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/UserController.kt index 948043f..82ea3f3 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/user/UserController.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/UserController.kt @@ -1,12 +1,12 @@ -package com.travel.withaeng.controller.user +package com.withaeng.api.controller.user -import com.travel.withaeng.applicationservice.user.UserApplicationService -import com.travel.withaeng.applicationservice.user.dto.UserDetailsResponse -import com.travel.withaeng.common.ApiResponse -import com.travel.withaeng.controller.user.dto.AddUserDetailsRequest -import com.travel.withaeng.controller.user.dto.toServiceRequest -import com.travel.withaeng.security.authentication.UserInfo -import com.travel.withaeng.security.resolver.GetAuth +import com.withaeng.api.applicationservice.user.UserApplicationService +import com.withaeng.api.applicationservice.user.dto.UserDetailsResponse +import com.withaeng.api.common.ApiResponse +import com.withaeng.api.controller.user.dto.AddUserDetailsRequest +import com.withaeng.api.controller.user.dto.toServiceRequest +import com.withaeng.api.security.authentication.UserInfo +import com.withaeng.api.security.resolver.GetAuth import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.security.SecurityRequirement import io.swagger.v3.oas.annotations.tags.Tag diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/user/dto/UserRequestDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/dto/UserRequestDto.kt similarity index 90% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/controller/user/dto/UserRequestDto.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/dto/UserRequestDto.kt index cbc8616..654316e 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/controller/user/dto/UserRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/dto/UserRequestDto.kt @@ -1,7 +1,7 @@ -package com.travel.withaeng.controller.user.dto +package com.withaeng.api.controller.user.dto -import com.travel.withaeng.applicationservice.user.dto.AddUserDetailsServerRequest -import com.travel.withaeng.domain.user.* +import com.withaeng.domain.user.* +import com.withaeng.api.applicationservice.user.dto.AddUserDetailsServerRequest import io.swagger.v3.oas.annotations.media.Schema import org.hibernate.validator.constraints.Length diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/jackson/EnumModule.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/jackson/EnumModule.kt similarity index 64% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/jackson/EnumModule.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/jackson/EnumModule.kt index c36061b..f470094 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/jackson/EnumModule.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/jackson/EnumModule.kt @@ -1,11 +1,10 @@ -package com.travel.withaeng.jackson +package com.withaeng.api.jackson import com.fasterxml.jackson.databind.module.SimpleModule -import com.travel.withaeng.domain.user.* -import com.travel.withaeng.jackson.deserializer.SimpleEnumDeserializer +import com.withaeng.api.jackson.deserializer.SimpleEnumDeserializer +import com.withaeng.domain.user.* class EnumModule : SimpleModule() { - init { // User addSimpleEnumDeserializer() @@ -18,7 +17,7 @@ class EnumModule : SimpleModule() { addSimpleEnumDeserializer() } - private inline fun > addSimpleEnumDeserializer() { - addDeserializer(T::class.java, object: SimpleEnumDeserializer(T::class.java){}) + private inline fun > addSimpleEnumDeserializer() { + addDeserializer(T::class.java, object : SimpleEnumDeserializer(T::class.java) {}) } } diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/jackson/deserializer/SimpleEnumDeserializer.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/jackson/deserializer/SimpleEnumDeserializer.kt similarity index 75% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/jackson/deserializer/SimpleEnumDeserializer.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/jackson/deserializer/SimpleEnumDeserializer.kt index b1f8a1c..bb34f9d 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/jackson/deserializer/SimpleEnumDeserializer.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/jackson/deserializer/SimpleEnumDeserializer.kt @@ -1,12 +1,12 @@ -package com.travel.withaeng.jackson.deserializer +package com.withaeng.api.jackson.deserializer import com.fasterxml.jackson.core.JsonParser import com.fasterxml.jackson.databind.DeserializationContext import com.fasterxml.jackson.databind.JsonDeserializer -open class SimpleEnumDeserializer>( +open class SimpleEnumDeserializer>( private val enumType: Class -) : JsonDeserializer(){ +) : JsonDeserializer() { override fun deserialize(parser: JsonParser, ctxt: DeserializationContext): T { val node = parser.text diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/DeleteValidatingEmailScheduler.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/DeleteValidatingEmailScheduler.kt similarity index 88% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/DeleteValidatingEmailScheduler.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/DeleteValidatingEmailScheduler.kt index e81fc76..58d4296 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/DeleteValidatingEmailScheduler.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/DeleteValidatingEmailScheduler.kt @@ -1,7 +1,7 @@ -package com.travel.withaeng.scheduler +package com.withaeng.api.scheduler -import com.travel.withaeng.domain.validateemail.ValidatingEmailService -import com.travel.withaeng.domain.validateemail.ValidatingEmailStatus +import com.withaeng.domain.validateemail.ValidatingEmailService +import com.withaeng.domain.validateemail.ValidatingEmailStatus import org.slf4j.Logger import org.slf4j.LoggerFactory import org.springframework.scheduling.annotation.Async @@ -14,7 +14,6 @@ import java.time.LocalDateTime class DeleteValidatingEmailScheduler( private val validatingEmailService: ValidatingEmailService ) { - private val log: Logger = LoggerFactory.getLogger(DeleteValidatingEmailScheduler::class.java) @Scheduled(cron = "0 * * * * *") diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/SchedulerBasePackage.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/SchedulerBasePackage.kt new file mode 100644 index 0000000..ac9a698 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/SchedulerBasePackage.kt @@ -0,0 +1,3 @@ +package com.withaeng.api.scheduler + +interface SchedulerBasePackage \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/SendEmailScheduler.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/SendEmailScheduler.kt similarity index 78% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/SendEmailScheduler.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/SendEmailScheduler.kt index a985f89..2c65529 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/scheduler/SendEmailScheduler.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/SendEmailScheduler.kt @@ -1,12 +1,12 @@ -package com.travel.withaeng.scheduler +package com.withaeng.api.scheduler -import com.travel.withaeng.common.Constants.Url.CHANGING_PASSWORD_EMAIL_URL -import com.travel.withaeng.common.Constants.Url.VALIDATING_EMAIL_URL -import com.travel.withaeng.domain.validateemail.ValidatingEmailService -import com.travel.withaeng.domain.validateemail.ValidatingEmailStatus -import com.travel.withaeng.domain.validateemail.ValidatingEmailType -import com.travel.withaeng.external.ses.MailSender -import com.travel.withaeng.external.ses.MailType +import com.withaeng.api.common.Constants.Url.CHANGING_PASSWORD_EMAIL_URL +import com.withaeng.api.common.Constants.Url.VALIDATING_EMAIL_URL +import com.withaeng.domain.validateemail.ValidatingEmailService +import com.withaeng.domain.validateemail.ValidatingEmailStatus +import com.withaeng.domain.validateemail.ValidatingEmailType +import com.withaeng.external.ses.MailSender +import com.withaeng.external.ses.MailType import org.slf4j.Logger import org.slf4j.LoggerFactory import org.springframework.scheduling.annotation.Async diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/authentication/JwtAuthentication.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/security/authentication/JwtAuthentication.kt similarity index 94% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/security/authentication/JwtAuthentication.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/security/authentication/JwtAuthentication.kt index b3c8211..eb10051 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/authentication/JwtAuthentication.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/security/authentication/JwtAuthentication.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.security.authentication +package com.withaeng.api.security.authentication import org.springframework.security.core.Authentication import org.springframework.security.core.GrantedAuthority diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/authentication/UserInfo.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/security/authentication/UserInfo.kt similarity index 68% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/security/authentication/UserInfo.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/security/authentication/UserInfo.kt index 89ad30b..5ad7087 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/authentication/UserInfo.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/security/authentication/UserInfo.kt @@ -1,7 +1,7 @@ -package com.travel.withaeng.security.authentication +package com.withaeng.api.security.authentication -import com.travel.withaeng.domain.user.UserRole -import com.travel.withaeng.domain.user.UserSimpleDto +import com.withaeng.domain.user.UserRole +import com.withaeng.domain.user.UserSimpleDto data class UserInfo( val id: Long, diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/handler/HttpStatusAccessDeniedHandler.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/security/handler/HttpStatusAccessDeniedHandler.kt similarity index 94% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/security/handler/HttpStatusAccessDeniedHandler.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/security/handler/HttpStatusAccessDeniedHandler.kt index 05f9ac9..78672c9 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/handler/HttpStatusAccessDeniedHandler.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/security/handler/HttpStatusAccessDeniedHandler.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.security.handler +package com.withaeng.api.security.handler import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletResponse diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/handler/HttpStatusAuthenticationEntryPoint.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/security/handler/HttpStatusAuthenticationEntryPoint.kt similarity index 94% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/security/handler/HttpStatusAuthenticationEntryPoint.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/security/handler/HttpStatusAuthenticationEntryPoint.kt index 7a21905..41168bd 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/handler/HttpStatusAuthenticationEntryPoint.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/security/handler/HttpStatusAuthenticationEntryPoint.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.security.handler +package com.withaeng.api.security.handler import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletResponse diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtAgent.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/security/jwt/JwtAgent.kt similarity index 85% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtAgent.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/security/jwt/JwtAgent.kt index 735db10..3f77446 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtAgent.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/security/jwt/JwtAgent.kt @@ -1,6 +1,6 @@ -package com.travel.withaeng.security.jwt +package com.withaeng.api.security.jwt -import com.travel.withaeng.security.authentication.UserInfo +import com.withaeng.api.security.authentication.UserInfo interface JwtAgent { diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtAgentImpl.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/security/jwt/JwtAgentImpl.kt similarity index 90% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtAgentImpl.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/security/jwt/JwtAgentImpl.kt index efd9f9a..cbfe537 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtAgentImpl.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/security/jwt/JwtAgentImpl.kt @@ -1,9 +1,9 @@ -package com.travel.withaeng.security.jwt +package com.withaeng.api.security.jwt import com.fasterxml.jackson.databind.ObjectMapper -import com.travel.withaeng.common.exception.WithaengException -import com.travel.withaeng.common.exception.WithaengExceptionType -import com.travel.withaeng.security.authentication.UserInfo +import com.withaeng.api.security.authentication.UserInfo +import com.withaeng.common.exception.WithaengException +import com.withaeng.common.exception.WithaengExceptionType import io.jsonwebtoken.JwtParser import io.jsonwebtoken.Jwts import io.jsonwebtoken.io.Decoders diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtFilter.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/security/jwt/JwtFilter.kt similarity index 89% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtFilter.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/security/jwt/JwtFilter.kt index ca54d4d..ad69195 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/jwt/JwtFilter.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/security/jwt/JwtFilter.kt @@ -1,11 +1,11 @@ -package com.travel.withaeng.security.jwt +package com.withaeng.api.security.jwt import com.fasterxml.jackson.databind.ObjectMapper -import com.travel.withaeng.common.ApiResponse -import com.travel.withaeng.common.Constants.Authentication.BEARER_TYPE -import com.travel.withaeng.common.exception.WithaengException -import com.travel.withaeng.common.exception.WithaengExceptionType -import com.travel.withaeng.security.authentication.JwtAuthentication +import com.withaeng.api.common.ApiResponse +import com.withaeng.api.common.Constants.Authentication.BEARER_TYPE +import com.withaeng.api.security.authentication.JwtAuthentication +import com.withaeng.common.exception.WithaengException +import com.withaeng.common.exception.WithaengExceptionType import jakarta.servlet.FilterChain import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletResponse diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/resolver/GetAuth.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/security/resolver/GetAuth.kt similarity index 79% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/security/resolver/GetAuth.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/security/resolver/GetAuth.kt index d7be26a..80ae512 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/resolver/GetAuth.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/security/resolver/GetAuth.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.security.resolver +package com.withaeng.api.security.resolver import io.swagger.v3.oas.annotations.media.Schema diff --git a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/resolver/UserInfoArgumentResolver.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/security/resolver/UserInfoArgumentResolver.kt similarity index 81% rename from withaeng-api/src/main/kotlin/com/travel/withaeng/security/resolver/UserInfoArgumentResolver.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/security/resolver/UserInfoArgumentResolver.kt index 83d33ce..f6ed1ec 100644 --- a/withaeng-api/src/main/kotlin/com/travel/withaeng/security/resolver/UserInfoArgumentResolver.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/security/resolver/UserInfoArgumentResolver.kt @@ -1,9 +1,9 @@ -package com.travel.withaeng.security.resolver +package com.withaeng.api.security.resolver -import com.travel.withaeng.common.exception.WithaengException -import com.travel.withaeng.common.exception.WithaengExceptionType -import com.travel.withaeng.security.authentication.JwtAuthentication -import com.travel.withaeng.security.authentication.UserInfo +import com.withaeng.api.security.authentication.JwtAuthentication +import com.withaeng.api.security.authentication.UserInfo +import com.withaeng.common.exception.WithaengException +import com.withaeng.common.exception.WithaengExceptionType import org.springframework.core.MethodParameter import org.springframework.security.core.context.SecurityContextHolder import org.springframework.web.bind.support.WebDataBinderFactory diff --git a/withaeng-api/src/test/kotlin/com/travel/withaeng/applicationservice/user/UserNicknameUtilsTest.kt b/withaeng-api/src/test/kotlin/com/withaeng/api/applicationservice/user/UserNicknameUtilsTest.kt similarity index 78% rename from withaeng-api/src/test/kotlin/com/travel/withaeng/applicationservice/user/UserNicknameUtilsTest.kt rename to withaeng-api/src/test/kotlin/com/withaeng/api/applicationservice/user/UserNicknameUtilsTest.kt index b2ef8cf..a3c64e6 100644 --- a/withaeng-api/src/test/kotlin/com/travel/withaeng/applicationservice/user/UserNicknameUtilsTest.kt +++ b/withaeng-api/src/test/kotlin/com/withaeng/api/applicationservice/user/UserNicknameUtilsTest.kt @@ -1,6 +1,6 @@ -package com.travel.withaeng.applicationservice.user +package com.withaeng.api.applicationservice.user -import com.travel.withaeng.applicationservice.auth.UserNicknameUtils +import com.withaeng.api.applicationservice.auth.UserNicknameUtils import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test diff --git a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/WithaengException.kt b/withaeng-common/src/main/kotlin/com/withaeng/common/exception/WithaengException.kt similarity index 94% rename from withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/WithaengException.kt rename to withaeng-common/src/main/kotlin/com/withaeng/common/exception/WithaengException.kt index 267d2dd..9345ca5 100644 --- a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/WithaengException.kt +++ b/withaeng-common/src/main/kotlin/com/withaeng/common/exception/WithaengException.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.common.exception +package com.withaeng.common.exception class WithaengException( val errorCode: String, diff --git a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/WithaengExceptionType.kt b/withaeng-common/src/main/kotlin/com/withaeng/common/exception/WithaengExceptionType.kt similarity index 97% rename from withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/WithaengExceptionType.kt rename to withaeng-common/src/main/kotlin/com/withaeng/common/exception/WithaengExceptionType.kt index 3e6abf7..ab7471d 100644 --- a/withaeng-common/src/main/kotlin/com/travel/withaeng/common/exception/WithaengExceptionType.kt +++ b/withaeng-common/src/main/kotlin/com/withaeng/common/exception/WithaengExceptionType.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.common.exception +package com.withaeng.common.exception enum class WithaengExceptionType( val message: String, diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/WithaengDomainModule.kt b/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/WithaengDomainModule.kt deleted file mode 100644 index 509cc53..0000000 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/WithaengDomainModule.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.travel.withaeng.domain - -interface WithaengDomainModule \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/BaseEntity.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/BaseEntity.kt similarity index 96% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/BaseEntity.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/BaseEntity.kt index 1d2586b..e7cc93f 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/BaseEntity.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/BaseEntity.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain +package com.withaeng.domain import jakarta.persistence.* import org.springframework.data.annotation.CreatedDate diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/WithaengDomainModule.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/WithaengDomainModule.kt new file mode 100644 index 0000000..163424a --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/WithaengDomainModule.kt @@ -0,0 +1,3 @@ +package com.withaeng.domain + +interface WithaengDomainModule \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt similarity index 92% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt index e3a4638..d4eb4ee 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Accompany.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt @@ -1,16 +1,16 @@ -package com.travel.withaeng.domain.accompany +package com.withaeng.domain.accompany -import com.travel.withaeng.converter.TagIdsConverter -import com.travel.withaeng.domain.BaseEntity -import com.travel.withaeng.domain.accompanystatistics.AccompanyStatistics -import com.travel.withaeng.domain.user.UserPreferAccompanyGender +import com.withaeng.domain.BaseEntity +import com.withaeng.domain.accompanystatistics.AccompanyStatistics +import com.withaeng.domain.converter.TagIdsConverter +import com.withaeng.domain.user.UserPreferAccompanyGender import jakarta.persistence.* import org.hibernate.annotations.Comment import org.hibernate.annotations.DynamicUpdate import java.time.LocalDate -@DynamicUpdate @Entity +@DynamicUpdate @Table(name = "accompany") class Accompany( diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyAge.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyAge.kt similarity index 86% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyAge.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyAge.kt index 57b2e70..9de163b 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyAge.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyAge.kt @@ -1,10 +1,10 @@ -package com.travel.withaeng.domain.accompany +package com.withaeng.domain.accompany import com.fasterxml.jackson.core.JsonParser import com.fasterxml.jackson.databind.DeserializationContext import com.fasterxml.jackson.databind.JsonDeserializer -import com.travel.withaeng.common.exception.WithaengException -import com.travel.withaeng.common.exception.WithaengExceptionType +import com.withaeng.common.exception.WithaengException +import com.withaeng.common.exception.WithaengExceptionType enum class AccompanyAge( val code: String, diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestination.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyDestination.kt similarity index 92% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestination.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyDestination.kt index dddc1fc..90aaaaf 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDestination.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyDestination.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.accompany +package com.withaeng.domain.accompany import jakarta.persistence.Column import jakarta.persistence.Embeddable diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyDto.kt similarity index 95% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyDto.kt index 0e02c1f..c8e32e0 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyDto.kt @@ -1,6 +1,6 @@ -package com.travel.withaeng.domain.accompany +package com.withaeng.domain.accompany -import com.travel.withaeng.domain.user.UserPreferAccompanyGender +import com.withaeng.domain.user.UserPreferAccompanyGender import java.time.LocalDate data class CreateAccompanyDto( diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyIncrementViewCountEvent.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyIncrementViewCountEvent.kt similarity index 62% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyIncrementViewCountEvent.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyIncrementViewCountEvent.kt index eb7aabe..1e0ad59 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyIncrementViewCountEvent.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyIncrementViewCountEvent.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.accompany +package com.withaeng.domain.accompany class AccompanyIncrementViewCountEvent( val accompanyId: Long? = null diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepository.kt similarity index 77% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepository.kt index 3179722..fabf83b 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepository.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.accompany +package com.withaeng.domain.accompany import org.springframework.data.jpa.repository.JpaRepository diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustom.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryCustom.kt similarity index 70% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustom.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryCustom.kt index 6119d2a..5cefa2a 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryCustom.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryCustom.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.accompany +package com.withaeng.domain.accompany interface AccompanyRepositoryCustom { fun findAccompanyDetail(accompanyId: Long): FindAccompanyDto? diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryImpl.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryImpl.kt similarity index 85% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryImpl.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryImpl.kt index 44359a6..209c9fd 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyRepositoryImpl.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryImpl.kt @@ -1,11 +1,11 @@ -package com.travel.withaeng.domain.accompany +package com.withaeng.domain.accompany import com.querydsl.core.types.dsl.BooleanExpression import com.querydsl.jpa.impl.JPAQueryFactory -import com.travel.withaeng.domain.accompany.QAccompany.accompany -import com.travel.withaeng.domain.accompanylike.QAccompanyLike.accompanyLike -import com.travel.withaeng.domain.accompanystatistics.QAccompanyStatistics.accompanyStatistics -import com.travel.withaeng.domain.user.QUser.user +import com.withaeng.domain.accompany.QAccompany.accompany +import com.withaeng.domain.accompanylike.QAccompanyLike.accompanyLike +import com.withaeng.domain.accompanystatistics.QAccompanyStatistics.accompanyStatistics +import com.withaeng.domain.user.QUser.user class AccompanyRepositoryImpl( @@ -56,7 +56,7 @@ class AccompanyRepositoryImpl( .fetchOne() } - private fun accompanyIdEq(accompanyId: Long): BooleanExpression? { + private fun accompanyIdEq(accompanyId: Long): BooleanExpression { return accompany.id.eq(accompanyId) } } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyService.kt similarity index 87% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyService.kt index 9688075..98547f3 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyService.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyService.kt @@ -1,8 +1,8 @@ -package com.travel.withaeng.domain.accompany +package com.withaeng.domain.accompany -import com.travel.withaeng.common.exception.WithaengException -import com.travel.withaeng.common.exception.WithaengExceptionType -import com.travel.withaeng.domain.tag.TagRepository +import com.withaeng.common.exception.WithaengException +import com.withaeng.common.exception.WithaengExceptionType +import com.withaeng.domain.tag.TagRepository import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -60,7 +60,9 @@ class AccompanyService( private fun filterValidTagIds(tagIds: Set?): Set { if (tagIds == null) return emptySet() - return tagRepository.findAllById(tagIds).map { it.id }.toSet() + return tagRepository.findAllById(tagIds) + .map { it.id } + .toSet() } companion object { diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyStatus.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyStatus.kt similarity index 74% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyStatus.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyStatus.kt index 9fd4188..aa460f7 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/AccompanyStatus.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyStatus.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.accompany +package com.withaeng.domain.accompany enum class AccompanyStatus(val statusDescription: String) { ING("동행 구인중"), diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/City.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/City.kt similarity index 99% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/City.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/City.kt index 5a58c92..e7556c5 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/City.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/City.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.accompany +package com.withaeng.domain.accompany enum class City( val countryCode: String, diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Continent.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Continent.kt similarity index 90% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Continent.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Continent.kt index 6773203..f541c5e 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Continent.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Continent.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.accompany +package com.withaeng.domain.accompany enum class Continent( val continentCode: String, diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Country.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Country.kt similarity index 99% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Country.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Country.kt index d04471d..edef910 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/Country.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Country.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.accompany +package com.withaeng.domain.accompany enum class Country( val continentCode: String, diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/FindAccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/FindAccompanyDto.kt similarity index 86% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/FindAccompanyDto.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/FindAccompanyDto.kt index 98e87c1..4b51473 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/FindAccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/FindAccompanyDto.kt @@ -1,7 +1,7 @@ -package com.travel.withaeng.domain.accompany +package com.withaeng.domain.accompany import com.querydsl.core.annotations.QueryProjection -import com.travel.withaeng.domain.user.UserPreferAccompanyGender +import com.withaeng.domain.user.UserPreferAccompanyGender import java.time.LocalDate data class FindAccompanyDto @QueryProjection constructor( diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/FindAccompanyUserInfoDto.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/FindAccompanyUserInfoDto.kt similarity index 90% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/FindAccompanyUserInfoDto.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/FindAccompanyUserInfoDto.kt index 4bb89c6..cfb0be3 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompany/FindAccompanyUserInfoDto.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/FindAccompanyUserInfoDto.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.accompany +package com.withaeng.domain.accompany import com.querydsl.core.annotations.QueryProjection import java.time.LocalDateTime diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLike.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanylike/AccompanyLike.kt similarity index 84% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLike.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanylike/AccompanyLike.kt index 50e2157..0a75117 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLike.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanylike/AccompanyLike.kt @@ -1,6 +1,6 @@ -package com.travel.withaeng.domain.accompanylike +package com.withaeng.domain.accompanylike -import com.travel.withaeng.domain.BaseEntity +import com.withaeng.domain.BaseEntity import jakarta.persistence.Column import jakarta.persistence.Entity import jakarta.persistence.Table diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeRepository.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanylike/AccompanyLikeRepository.kt similarity index 84% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeRepository.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanylike/AccompanyLikeRepository.kt index 86c5b54..1d25f49 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanylike/AccompanyLikeRepository.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.accompanylike +package com.withaeng.domain.accompanylike import org.springframework.data.jpa.repository.JpaRepository diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanylike/AccompanyLikeService.kt similarity index 85% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanylike/AccompanyLikeService.kt index 2d70d8e..81d2b1e 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanylike/AccompanyLikeService.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanylike/AccompanyLikeService.kt @@ -1,9 +1,9 @@ -package com.travel.withaeng.domain.accompanylike +package com.withaeng.domain.accompanylike -import com.travel.withaeng.common.exception.WithaengException -import com.travel.withaeng.common.exception.WithaengExceptionType -import com.travel.withaeng.domain.accompany.AccompanyRepository -import com.travel.withaeng.domain.user.UserRepository +import com.withaeng.common.exception.WithaengException +import com.withaeng.common.exception.WithaengExceptionType +import com.withaeng.domain.accompany.AccompanyRepository +import com.withaeng.domain.user.UserRepository import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreply/AccompanyReply.kt similarity index 92% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreply/AccompanyReply.kt index 0a55ebb..a131952 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReply.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreply/AccompanyReply.kt @@ -1,6 +1,6 @@ -package com.travel.withaeng.domain.accompanyreply +package com.withaeng.domain.accompanyreply -import com.travel.withaeng.domain.BaseEntity +import com.withaeng.domain.BaseEntity import jakarta.persistence.* import org.hibernate.annotations.DynamicUpdate import java.time.LocalDateTime diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreply/AccompanyReplyDto.kt similarity index 92% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreply/AccompanyReplyDto.kt index f330315..61154b9 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreply/AccompanyReplyDto.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.accompanyreply +package com.withaeng.domain.accompanyreply import com.querydsl.core.annotations.QueryProjection import java.time.LocalDateTime diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt similarity index 76% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt index e7479cd..0bdcee8 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreply/AccompanyReplyRepository.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.accompanyreply +package com.withaeng.domain.accompanyreply import org.springframework.data.jpa.repository.JpaRepository diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustom.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustom.kt similarity index 82% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustom.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustom.kt index 43d6e6f..ad1a205 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustom.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreply/AccompanyReplyRepositoryCustom.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.accompanyreply +package com.withaeng.domain.accompanyreply import org.springframework.data.domain.Page import org.springframework.data.domain.Pageable diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryImpl.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreply/AccompanyReplyRepositoryImpl.kt similarity index 88% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryImpl.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreply/AccompanyReplyRepositoryImpl.kt index 35fdcf1..4f2d54b 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyRepositoryImpl.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreply/AccompanyReplyRepositoryImpl.kt @@ -1,10 +1,10 @@ -package com.travel.withaeng.domain.accompanyreply +package com.withaeng.domain.accompanyreply import com.querydsl.core.types.dsl.BooleanExpression import com.querydsl.jpa.impl.JPAQueryFactory -import com.travel.withaeng.domain.accompanyreply.QAccompanyReply.accompanyReply -import com.travel.withaeng.domain.accompanyreplylike.QAccompanyReplyLike.accompanyReplyLike -import com.travel.withaeng.domain.user.QUser.user +import com.withaeng.domain.accompanyreply.QAccompanyReply.accompanyReply +import com.withaeng.domain.accompanyreplylike.QAccompanyReplyLike.accompanyReplyLike +import com.withaeng.domain.user.QUser.user import org.springframework.data.domain.Page import org.springframework.data.domain.Pageable import org.springframework.data.support.PageableExecutionUtils diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreply/AccompanyReplyService.kt similarity index 69% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreply/AccompanyReplyService.kt index bf3d742..0d9b37b 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyService.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreply/AccompanyReplyService.kt @@ -1,9 +1,9 @@ -package com.travel.withaeng.domain.accompanyreply +package com.withaeng.domain.accompanyreply -import com.travel.withaeng.common.exception.WithaengException -import com.travel.withaeng.common.exception.WithaengExceptionType -import com.travel.withaeng.domain.accompany.AccompanyRepository -import com.travel.withaeng.domain.user.UserRepository +import com.withaeng.common.exception.WithaengException +import com.withaeng.common.exception.WithaengExceptionType +import com.withaeng.domain.accompany.AccompanyRepository +import com.withaeng.domain.user.UserRepository import org.springframework.data.domain.Page import org.springframework.data.domain.Pageable import org.springframework.data.repository.findByIdOrNull @@ -25,10 +25,7 @@ class AccompanyReplyService( validateNotExistsParentId(parentId) } val accompanyReply = AccompanyReply.create( - accompanyId = accompanyId, - userId = userId, - content = content, - parentId = parentId + accompanyId = accompanyId, userId = userId, content = content, parentId = parentId ) accompanyReplyRepository.save(accompanyReply) return accompanyReply.toDto() @@ -36,8 +33,7 @@ class AccompanyReplyService( fun findById(replyId: Long): AccompanyReplyDto { val accompanyReply = accompanyReplyRepository.findByIdOrNull(replyId) ?: throw WithaengException.of( - type = WithaengExceptionType.NOT_EXIST, - message = "해당하는 댓글을 찾을 수 없습니다." + type = WithaengExceptionType.NOT_EXIST, message = "해당하는 댓글을 찾을 수 없습니다." ) return accompanyReply.toDto() } @@ -54,8 +50,7 @@ class AccompanyReplyService( @Transactional fun update(replyId: Long, content: String): AccompanyReplyDto { val accompanyReply = accompanyReplyRepository.findByIdOrNull(replyId) ?: throw WithaengException.of( - type = WithaengExceptionType.NOT_EXIST, - message = "해당하는 댓글을 찾을 수 없습니다." + type = WithaengExceptionType.NOT_EXIST, message = "해당하는 댓글을 찾을 수 없습니다." ) accompanyReply.update(content) return accompanyReply.toDto() @@ -64,8 +59,7 @@ class AccompanyReplyService( @Transactional fun delete(replyId: Long) { val accompanyReply = accompanyReplyRepository.findByIdOrNull(replyId) ?: throw WithaengException.of( - type = WithaengExceptionType.NOT_EXIST, - message = "해당하는 댓글을 찾을 수 없습니다." + type = WithaengExceptionType.NOT_EXIST, message = "해당하는 댓글을 찾을 수 없습니다." ) accompanyReply.delete() } @@ -78,8 +72,7 @@ class AccompanyReplyService( private fun validateExistsAccompany(accompanyId: Long) { if (!accompanyRepository.existsById(accompanyId)) { throw WithaengException.of( - type = WithaengExceptionType.NOT_EXIST, - message = "해당하는 동행을 찾을 수 없습니다." + type = WithaengExceptionType.NOT_EXIST, message = "해당하는 동행을 찾을 수 없습니다." ) } } @@ -87,8 +80,7 @@ class AccompanyReplyService( private fun validateExistsUser(userId: Long) { if (!userRepository.existsById(userId)) { throw WithaengException.of( - type = WithaengExceptionType.NOT_EXIST, - message = "해당하는 유저를 찾을 수 없습니다." + type = WithaengExceptionType.NOT_EXIST, message = "해당하는 유저를 찾을 수 없습니다." ) } } @@ -96,8 +88,7 @@ class AccompanyReplyService( private fun validateNotExistsParentId(parentId: Long) { if (accompanyReplyRepository.existsById(parentId)) { throw WithaengException.of( - type = WithaengExceptionType.NOT_EXIST, - message = "해당하는 댓글을 찾을 수 없습니다." + type = WithaengExceptionType.NOT_EXIST, message = "해당하는 댓글을 찾을 수 없습니다." ) } } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyStatus.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreply/AccompanyReplyStatus.kt similarity index 52% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyStatus.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreply/AccompanyReplyStatus.kt index 8e42d87..6fd1155 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/AccompanyReplyStatus.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreply/AccompanyReplyStatus.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.accompanyreply +package com.withaeng.domain.accompanyreply enum class AccompanyReplyStatus { ACTIVE, DELETED diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/FindAccompanyReplyDto.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreply/FindAccompanyReplyDto.kt similarity index 88% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/FindAccompanyReplyDto.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreply/FindAccompanyReplyDto.kt index 4371e61..fb90a90 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/FindAccompanyReplyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreply/FindAccompanyReplyDto.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.accompanyreply +package com.withaeng.domain.accompanyreply import com.querydsl.core.annotations.QueryProjection import java.time.LocalDateTime diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/FindAccompanyReplyUserInfoDto.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreply/FindAccompanyReplyUserInfoDto.kt similarity index 79% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/FindAccompanyReplyUserInfoDto.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreply/FindAccompanyReplyUserInfoDto.kt index e090800..df217ca 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreply/FindAccompanyReplyUserInfoDto.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreply/FindAccompanyReplyUserInfoDto.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.accompanyreply +package com.withaeng.domain.accompanyreply import com.querydsl.core.annotations.QueryProjection diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLike.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreplylike/AccompanyReplyLike.kt similarity index 77% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLike.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreplylike/AccompanyReplyLike.kt index 204a78a..f6b7a73 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLike.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreplylike/AccompanyReplyLike.kt @@ -1,6 +1,6 @@ -package com.travel.withaeng.domain.accompanyreplylike +package com.withaeng.domain.accompanyreplylike -import com.travel.withaeng.domain.BaseEntity +import com.withaeng.domain.BaseEntity import jakarta.persistence.Column import jakarta.persistence.Entity import jakarta.persistence.Table diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt similarity index 83% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt index 661577b..4ea57ba 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreplylike/AccompanyReplyLikeRepository.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.accompanyreplylike +package com.withaeng.domain.accompanyreplylike import org.springframework.data.jpa.repository.JpaRepository diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt similarity index 84% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt index f026686..f8ace60 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreplylike/AccompanyReplyLikeService.kt @@ -1,9 +1,9 @@ -package com.travel.withaeng.domain.accompanyreplylike +package com.withaeng.domain.accompanyreplylike -import com.travel.withaeng.common.exception.WithaengException -import com.travel.withaeng.common.exception.WithaengExceptionType -import com.travel.withaeng.domain.accompanyreply.AccompanyReplyRepository -import com.travel.withaeng.domain.user.UserRepository +import com.withaeng.common.exception.WithaengException +import com.withaeng.common.exception.WithaengExceptionType +import com.withaeng.domain.accompanyreply.AccompanyReplyRepository +import com.withaeng.domain.user.UserRepository import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanystatistics/AccompanyStatistics.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanystatistics/AccompanyStatistics.kt similarity index 83% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanystatistics/AccompanyStatistics.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanystatistics/AccompanyStatistics.kt index a73f093..b53a2dd 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/accompanystatistics/AccompanyStatistics.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanystatistics/AccompanyStatistics.kt @@ -1,6 +1,6 @@ -package com.travel.withaeng.domain.accompanystatistics +package com.withaeng.domain.accompanystatistics -import com.travel.withaeng.domain.accompany.Accompany +import com.withaeng.domain.accompany.Accompany import jakarta.persistence.* import org.hibernate.annotations.Comment diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/config/JasyptConfig.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/config/JasyptConfig.kt similarity index 85% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/config/JasyptConfig.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/config/JasyptConfig.kt index 6bf92d9..ab5eba1 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/config/JasyptConfig.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/config/JasyptConfig.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.config +package com.withaeng.domain.config import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties import org.springframework.context.annotation.Configuration diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/config/JpaConfig.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/config/JpaConfig.kt similarity index 83% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/config/JpaConfig.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/config/JpaConfig.kt index 2f037cd..0fb66d0 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/config/JpaConfig.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/config/JpaConfig.kt @@ -1,6 +1,6 @@ -package com.travel.withaeng.config +package com.withaeng.domain.config -import com.travel.withaeng.domain.WithaengDomainModule +import com.withaeng.domain.WithaengDomainModule import org.springframework.boot.autoconfigure.domain.EntityScan import org.springframework.context.annotation.Configuration import org.springframework.data.jpa.repository.config.EnableJpaAuditing diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/config/JpaQueryDslConfig.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/config/JpaQueryDslConfig.kt similarity index 93% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/config/JpaQueryDslConfig.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/config/JpaQueryDslConfig.kt index 1d5203f..6f965e4 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/config/JpaQueryDslConfig.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/config/JpaQueryDslConfig.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.config +package com.withaeng.domain.config import com.querydsl.jpa.impl.JPAQueryFactory import jakarta.persistence.EntityManager diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/TagIdsConverter.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/converter/TagIdsConverter.kt similarity index 92% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/TagIdsConverter.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/converter/TagIdsConverter.kt index 92a64ed..70b1cf1 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/TagIdsConverter.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/converter/TagIdsConverter.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.converter +package com.withaeng.domain.converter import jakarta.persistence.AttributeConverter diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserFoodRestrictionConverter.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/converter/UserFoodRestrictionConverter.kt similarity index 85% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserFoodRestrictionConverter.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/converter/UserFoodRestrictionConverter.kt index 38ee0aa..2bd9ad4 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserFoodRestrictionConverter.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/converter/UserFoodRestrictionConverter.kt @@ -1,6 +1,6 @@ -package com.travel.withaeng.converter +package com.withaeng.domain.converter -import com.travel.withaeng.domain.user.UserFoodRestriction +import com.withaeng.domain.user.UserFoodRestriction import jakarta.persistence.AttributeConverter class UserFoodRestrictionConverter : AttributeConverter, String> { diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserPreferTravelThemeConverter.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/converter/UserPreferTravelThemeConverter.kt similarity index 72% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserPreferTravelThemeConverter.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/converter/UserPreferTravelThemeConverter.kt index cf342d8..989c3cf 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserPreferTravelThemeConverter.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/converter/UserPreferTravelThemeConverter.kt @@ -1,9 +1,9 @@ -package com.travel.withaeng.converter +package com.withaeng.domain.converter -import com.travel.withaeng.domain.user.UserPreferTravelTheme +import com.withaeng.domain.user.UserPreferTravelTheme import jakarta.persistence.AttributeConverter -class UserPreferTravelThemeConverter: AttributeConverter, String> { +class UserPreferTravelThemeConverter : AttributeConverter, String> { override fun convertToDatabaseColumn(attribute: Set): String { return attribute.joinToString(DELIMITER) { it.name } } diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserRoleConverter.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/converter/UserRoleConverter.kt similarity index 86% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserRoleConverter.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/converter/UserRoleConverter.kt index 6bbb507..ed1f128 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/converter/UserRoleConverter.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/converter/UserRoleConverter.kt @@ -1,6 +1,6 @@ -package com.travel.withaeng.converter +package com.withaeng.domain.converter -import com.travel.withaeng.domain.user.UserRole +import com.withaeng.domain.user.UserRole import jakarta.persistence.AttributeConverter class UserRoleConverter : AttributeConverter, String> { diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/tag/Tag.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/tag/Tag.kt similarity index 64% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/tag/Tag.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/tag/Tag.kt index 2529a07..c59d9bf 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/tag/Tag.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/tag/Tag.kt @@ -1,13 +1,13 @@ -package com.travel.withaeng.domain.tag +package com.withaeng.domain.tag -import com.travel.withaeng.domain.BaseEntity +import com.withaeng.domain.BaseEntity import jakarta.persistence.Column import jakarta.persistence.Entity import jakarta.persistence.Table @Table(name = "tags") @Entity -class Tag ( +class Tag( @Column(name = "name", nullable = false) val name: String -): BaseEntity() \ No newline at end of file +) : BaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/tag/TagRepository.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/tag/TagRepository.kt similarity index 74% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/tag/TagRepository.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/tag/TagRepository.kt index 7d2260b..b10df58 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/tag/TagRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/tag/TagRepository.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.tag +package com.withaeng.domain.tag import org.springframework.data.jpa.repository.JpaRepository diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/User.kt similarity index 90% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/user/User.kt index 91d9d22..8cf4161 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/User.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/User.kt @@ -1,9 +1,9 @@ -package com.travel.withaeng.domain.user +package com.withaeng.domain.user -import com.travel.withaeng.converter.UserFoodRestrictionConverter -import com.travel.withaeng.converter.UserPreferTravelThemeConverter -import com.travel.withaeng.converter.UserRoleConverter -import com.travel.withaeng.domain.BaseEntity +import com.withaeng.domain.BaseEntity +import com.withaeng.domain.converter.UserFoodRestrictionConverter +import com.withaeng.domain.converter.UserPreferTravelThemeConverter +import com.withaeng.domain.converter.UserRoleConverter import jakarta.persistence.* import java.time.LocalDate diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserConsumeStyle.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserConsumeStyle.kt similarity index 63% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserConsumeStyle.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserConsumeStyle.kt index f89837c..c814368 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserConsumeStyle.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserConsumeStyle.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.user +package com.withaeng.domain.user enum class UserConsumeStyle { BUDGET_FRIENDLY, SPLURGE, LUXURY diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserDrinkingType.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserDrinkingType.kt similarity index 70% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserDrinkingType.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserDrinkingType.kt index 5c9222b..30cf428 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserDrinkingType.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserDrinkingType.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.user +package com.withaeng.domain.user enum class UserDrinkingType { FREQUENT_DRINKER, OCCASIONAL_DRINKER, ABSTAINER, NON_DRINKER diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserFoodRestriction.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserFoodRestriction.kt similarity index 80% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserFoodRestriction.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserFoodRestriction.kt index 23db736..1e17016 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserFoodRestriction.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserFoodRestriction.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.user +package com.withaeng.domain.user enum class UserFoodRestriction { SHELLFISH, SEAFOOD, SPICY_FOOD, MEAT, STRONGLY_FLAVORED, diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserMbti.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserMbti.kt similarity index 76% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserMbti.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserMbti.kt index 1e94e34..a2c688b 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserMbti.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserMbti.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.user +package com.withaeng.domain.user enum class UserMbti { ISTJ, ISTP, ISFJ, ISFP, INFJ, INTP, INFP, INTJ, diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserPreferAccompanyGender.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserPreferAccompanyGender.kt similarity index 64% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserPreferAccompanyGender.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserPreferAccompanyGender.kt index 24f781a..606605b 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserPreferAccompanyGender.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserPreferAccompanyGender.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.user +package com.withaeng.domain.user enum class UserPreferAccompanyGender { MALE, FEMALE, NO_PREFERENCE diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserPreferTravelTheme.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserPreferTravelTheme.kt similarity index 82% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserPreferTravelTheme.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserPreferTravelTheme.kt index 4413eb2..5509e92 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserPreferTravelTheme.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserPreferTravelTheme.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.user +package com.withaeng.domain.user enum class UserPreferTravelTheme { PICTURE, FOOD, TOURIST_ATTRACTION, NATURE, CAFE, MUSEUM, EXHIBITION_HALL, diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserPreferTravelType.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserPreferTravelType.kt similarity index 61% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserPreferTravelType.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserPreferTravelType.kt index ef8b8c8..b067280 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserPreferTravelType.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserPreferTravelType.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.user +package com.withaeng.domain.user enum class UserPreferTravelType { DOMESTIC, INTERNATIONAL diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRepository.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserRepository.kt similarity index 83% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRepository.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserRepository.kt index e145117..9bd2074 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserRepository.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.user +package com.withaeng.domain.user import org.springframework.data.jpa.repository.JpaRepository diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRole.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserRole.kt similarity index 83% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRole.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserRole.kt index 2a6955f..980e988 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserRole.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserRole.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.user +package com.withaeng.domain.user enum class UserRole( val role: String diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserService.kt similarity index 94% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserService.kt index 974f8d5..b20ec81 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserService.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserService.kt @@ -1,7 +1,7 @@ -package com.travel.withaeng.domain.user +package com.withaeng.domain.user -import com.travel.withaeng.common.exception.WithaengException -import com.travel.withaeng.common.exception.WithaengExceptionType +import com.withaeng.common.exception.WithaengException +import com.withaeng.common.exception.WithaengExceptionType import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserSimpleDto.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserSimpleDto.kt similarity index 98% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserSimpleDto.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserSimpleDto.kt index 238e48d..3a6c20f 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserSimpleDto.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserSimpleDto.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.user +package com.withaeng.domain.user import java.time.LocalDate diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserSmokingType.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserSmokingType.kt similarity index 71% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserSmokingType.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserSmokingType.kt index b71903a..55d9216 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/user/UserSmokingType.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserSmokingType.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.user +package com.withaeng.domain.user enum class UserSmokingType { FREQUENT_SMOKER, OCCASIONAL_SMOKER, QUITTING_SMOKER, NON_SMOKER diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmail.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmail.kt similarity index 86% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmail.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmail.kt index 9e032fd..ac450cb 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmail.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmail.kt @@ -1,6 +1,6 @@ -package com.travel.withaeng.domain.validateemail +package com.withaeng.domain.validateemail -import com.travel.withaeng.domain.BaseEntity +import com.withaeng.domain.BaseEntity import jakarta.persistence.* @Table(name = "validating_emails") diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailDto.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailDto.kt similarity index 90% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailDto.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailDto.kt index 54669e6..84f6067 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailDto.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailDto.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.validateemail +package com.withaeng.domain.validateemail import java.time.LocalDateTime diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailRepository.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailRepository.kt similarity index 93% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailRepository.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailRepository.kt index 70d369d..ade8e3d 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailRepository.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.validateemail +package com.withaeng.domain.validateemail import org.springframework.data.jpa.repository.JpaRepository import org.springframework.data.jpa.repository.Modifying diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailService.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailService.kt similarity index 91% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailService.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailService.kt index 52cb896..afc89a3 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailService.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailService.kt @@ -1,8 +1,8 @@ -package com.travel.withaeng.domain.validateemail +package com.withaeng.domain.validateemail -import com.travel.withaeng.common.exception.WithaengException -import com.travel.withaeng.common.exception.WithaengExceptionType -import com.travel.withaeng.domain.user.UserRepository +import com.withaeng.common.exception.WithaengException +import com.withaeng.common.exception.WithaengExceptionType +import com.withaeng.domain.user.UserRepository import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailStatus.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailStatus.kt similarity index 54% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailStatus.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailStatus.kt index 8aa598b..831b705 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailStatus.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailStatus.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.validateemail +package com.withaeng.domain.validateemail enum class ValidatingEmailStatus { YET, DONE, FAILED diff --git a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailType.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailType.kt similarity index 59% rename from withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailType.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailType.kt index 6b2a362..44f9dc8 100644 --- a/withaeng-domain/src/main/kotlin/com/travel/withaeng/domain/validateemail/ValidatingEmailType.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailType.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.domain.validateemail +package com.withaeng.domain.validateemail enum class ValidatingEmailType { VALIDATE_EMAIL, CHANGE_PASSWORD diff --git a/withaeng-domain/src/test/kotlin/com/travel/withaeng/config/JasyptConfigTest.kt b/withaeng-domain/src/test/kotlin/com/withaeng/api/config/JasyptConfigTest.kt similarity index 97% rename from withaeng-domain/src/test/kotlin/com/travel/withaeng/config/JasyptConfigTest.kt rename to withaeng-domain/src/test/kotlin/com/withaeng/api/config/JasyptConfigTest.kt index 9d8ed5a..f7476c1 100644 --- a/withaeng-domain/src/test/kotlin/com/travel/withaeng/config/JasyptConfigTest.kt +++ b/withaeng-domain/src/test/kotlin/com/withaeng/api/config/JasyptConfigTest.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.config +package com.withaeng.api.config import com.ulisesbocchio.jasyptspringboot.encryptor.DefaultLazyEncryptor import org.junit.jupiter.api.BeforeEach diff --git a/withaeng-domain/src/test/kotlin/com/travel/withaeng/config/TestConfiguration.kt b/withaeng-domain/src/test/kotlin/com/withaeng/api/config/TestConfiguration.kt similarity index 76% rename from withaeng-domain/src/test/kotlin/com/travel/withaeng/config/TestConfiguration.kt rename to withaeng-domain/src/test/kotlin/com/withaeng/api/config/TestConfiguration.kt index 2a48f79..a02c410 100644 --- a/withaeng-domain/src/test/kotlin/com/travel/withaeng/config/TestConfiguration.kt +++ b/withaeng-domain/src/test/kotlin/com/withaeng/api/config/TestConfiguration.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.config +package com.withaeng.api.config import org.springframework.boot.autoconfigure.SpringBootApplication diff --git a/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSender.kt b/withaeng-external/src/main/kotlin/com/withaeng/external/ses/MailSender.kt similarity index 68% rename from withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSender.kt rename to withaeng-external/src/main/kotlin/com/withaeng/external/ses/MailSender.kt index f5dea80..42c0a54 100644 --- a/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSender.kt +++ b/withaeng-external/src/main/kotlin/com/withaeng/external/ses/MailSender.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.external.ses +package com.withaeng.external.ses interface MailSender { diff --git a/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSenderImpl.kt b/withaeng-external/src/main/kotlin/com/withaeng/external/ses/MailSenderImpl.kt similarity index 98% rename from withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSenderImpl.kt rename to withaeng-external/src/main/kotlin/com/withaeng/external/ses/MailSenderImpl.kt index c3bfe37..08f4f89 100644 --- a/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailSenderImpl.kt +++ b/withaeng-external/src/main/kotlin/com/withaeng/external/ses/MailSenderImpl.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.external.ses +package com.withaeng.external.ses import com.amazonaws.services.simpleemail.AmazonSimpleEmailService import com.amazonaws.services.simpleemail.model.* diff --git a/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailType.kt b/withaeng-external/src/main/kotlin/com/withaeng/external/ses/MailType.kt similarity index 78% rename from withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailType.kt rename to withaeng-external/src/main/kotlin/com/withaeng/external/ses/MailType.kt index ec02404..85faa34 100644 --- a/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/MailType.kt +++ b/withaeng-external/src/main/kotlin/com/withaeng/external/ses/MailType.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.external.ses +package com.withaeng.external.ses enum class MailType(val templateName: String) { VALIDATE_EMAIL("validate-email-template"), diff --git a/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/config/SESConfig.kt b/withaeng-external/src/main/kotlin/com/withaeng/external/ses/config/SESConfig.kt similarity index 96% rename from withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/config/SESConfig.kt rename to withaeng-external/src/main/kotlin/com/withaeng/external/ses/config/SESConfig.kt index 65fc282..8184ae3 100644 --- a/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/config/SESConfig.kt +++ b/withaeng-external/src/main/kotlin/com/withaeng/external/ses/config/SESConfig.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.external.ses.config +package com.withaeng.external.ses.config import com.amazonaws.auth.AWSStaticCredentialsProvider import com.amazonaws.auth.BasicAWSCredentials diff --git a/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/config/ThymeleafConfig.kt b/withaeng-external/src/main/kotlin/com/withaeng/external/ses/config/ThymeleafConfig.kt similarity index 96% rename from withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/config/ThymeleafConfig.kt rename to withaeng-external/src/main/kotlin/com/withaeng/external/ses/config/ThymeleafConfig.kt index 79e0edd..5bb5a27 100644 --- a/withaeng-external/src/main/kotlin/com/travel/withaeng/external/ses/config/ThymeleafConfig.kt +++ b/withaeng-external/src/main/kotlin/com/withaeng/external/ses/config/ThymeleafConfig.kt @@ -1,4 +1,4 @@ -package com.travel.withaeng.external.ses.config +package com.withaeng.external.ses.config import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration From 5fa15316f26bd4a9c966a9789900913b7aedf9db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Tue, 10 Sep 2024 22:23:44 +0900 Subject: [PATCH 124/174] =?UTF-8?q?feat:=20=EC=9C=A0=EC=A0=80=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=20=ED=95=84=EB=93=9C=20=EB=B0=8F=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20dto=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/AccompanyReplyResponseDto.kt | 2 +- .../auth/AuthApplicationService.kt | 20 ++-- .../auth/dto/AuthServiceRequestDto.kt | 27 ++++-- .../user/UserApplicationService.kt | 17 ++-- .../user/dto/UserResponseDto.kt | 95 +++++++++++-------- .../user/dto/UserServiceRequestDto.kt | 40 ++++---- .../api/controller/auth/dto/AuthRequestDto.kt | 21 ++-- .../api/controller/user/UserController.kt | 10 +- .../api/controller/user/dto/UserRequestDto.kt | 33 +++---- .../api/security/authentication/UserInfo.kt | 2 +- .../accompany/AccompanyRepositoryImpl.kt | 12 +-- .../accompany/FindAccompanyUserInfoDto.kt | 5 +- .../AccompanyReplyRepositoryImpl.kt | 6 +- .../domain/converter/UserMbtiConverter.kt | 19 ++++ .../kotlin/com/withaeng/domain/user/Gender.kt | 5 + .../kotlin/com/withaeng/domain/user/User.kt | 59 +++--------- .../com/withaeng/domain/user/UserProfile.kt | 16 ++++ .../com/withaeng/domain/user/UserService.kt | 32 +++---- .../com/withaeng/domain/user/UserSimpleDto.kt | 87 ----------------- .../domain/user/UserTravelPreference.kt | 42 ++++++++ .../withaeng/domain/user/dto/UserCommand.kt | 23 +++++ .../com/withaeng/domain/user/dto/UserDto.kt | 80 ++++++++++++++++ 22 files changed, 364 insertions(+), 289 deletions(-) create mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/converter/UserMbtiConverter.kt create mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/user/Gender.kt create mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserProfile.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserSimpleDto.kt create mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserTravelPreference.kt create mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/user/dto/UserCommand.kt create mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/user/dto/UserDto.kt diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt index 03241be..940941b 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt @@ -4,7 +4,7 @@ import com.withaeng.api.applicationservice.user.dto.UserSimpleResponse import com.withaeng.api.applicationservice.user.dto.toSimpleResponse import com.withaeng.domain.accompanyreply.AccompanyReplyDto import com.withaeng.domain.accompanyreply.AccompanyReplyStatus -import com.withaeng.domain.user.UserSimpleDto +import com.withaeng.domain.user.dto.UserSimpleDto import java.time.LocalDateTime data class AccompanyReplyResponse( diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/AuthApplicationService.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/AuthApplicationService.kt index 7432250..2f9d18f 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/AuthApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/AuthApplicationService.kt @@ -5,10 +5,9 @@ import com.withaeng.api.security.authentication.UserInfo import com.withaeng.api.security.jwt.JwtAgent import com.withaeng.common.exception.WithaengException import com.withaeng.common.exception.WithaengExceptionType -import com.withaeng.domain.user.CreateUserDto import com.withaeng.domain.user.UserRole import com.withaeng.domain.user.UserService -import com.withaeng.domain.user.UserSimpleDto +import com.withaeng.domain.user.dto.UserSimpleDto import com.withaeng.domain.validateemail.ValidatingEmailService import com.withaeng.domain.validateemail.ValidatingEmailType import org.springframework.security.crypto.password.PasswordEncoder @@ -22,7 +21,7 @@ class AuthApplicationService( private val userService: UserService, private val validatingEmailService: ValidatingEmailService, private val jwtAgent: JwtAgent, - private val passwordEncoder: PasswordEncoder + private val passwordEncoder: PasswordEncoder, ) { @Transactional @@ -39,7 +38,12 @@ class AuthApplicationService( userService.deleteByEmail(userEmail) validatingEmailService.deleteAllByUserId(userDto.id) } - val newUserDto = userService.create(request.toCreateUserDto(UserNicknameUtils.createTemporaryNickname())) + val newUserDto = userService.create( + request.toCommand( + UserNicknameUtils.createTemporaryNickname(), + passwordEncoder.encode(request.password) + ) + ) validatingEmailService.create( email = newUserDto.email, userId = newUserDto.id, @@ -150,12 +154,4 @@ class AuthApplicationService( throw WithaengException.of(WithaengExceptionType.AUTHENTICATION_FAILURE) } } - - private fun SignUpServiceRequest.toCreateUserDto(temporaryNickname: String): CreateUserDto = CreateUserDto( - email = email, - nickname = temporaryNickname, - password = passwordEncoder.encode(password), - birth = birth, - isMale = isMale - ) } diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/dto/AuthServiceRequestDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/dto/AuthServiceRequestDto.kt index c14d3b5..a028161 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/dto/AuthServiceRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/dto/AuthServiceRequestDto.kt @@ -1,34 +1,45 @@ package com.withaeng.api.applicationservice.auth.dto +import com.withaeng.domain.user.Gender +import com.withaeng.domain.user.dto.CreateUserCommand import java.time.LocalDate data class SignUpServiceRequest( - val isMale: Boolean, - val birth: LocalDate, val email: String, - val password: String + val password: String, + val birth: LocalDate, + val gender: Gender, ) +fun SignUpServiceRequest.toCommand(temporaryNickname: String, encodedPassword: String): CreateUserCommand = + CreateUserCommand( + email = email, + password = encodedPassword, + birth = birth, + gender = gender, + nickname = temporaryNickname, + ) + data class SignInServiceRequest( val email: String, - val password: String + val password: String, ) data class ResendEmailServiceRequest( - val email: String + val email: String, ) data class ValidateEmailServiceRequest( val email: String, - val code: String + val code: String, ) data class SendEmailForChangePasswordServiceRequest( - val email: String + val email: String, ) data class ChangePasswordServiceRequest( val email: String, val code: String, - val password: String + val password: String, ) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/UserApplicationService.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/UserApplicationService.kt index 0e0459a..25a7b69 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/UserApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/UserApplicationService.kt @@ -1,8 +1,9 @@ package com.withaeng.api.applicationservice.user -import com.withaeng.api.applicationservice.user.dto.AddUserDetailsServerRequest +import com.withaeng.api.applicationservice.user.dto.UpdateTravelPreferenceServiceRequest import com.withaeng.api.applicationservice.user.dto.UserDetailsResponse -import com.withaeng.api.applicationservice.user.dto.toDomainDto +import com.withaeng.api.applicationservice.user.dto.toCommand +import com.withaeng.api.applicationservice.user.dto.toDetailResponse import com.withaeng.domain.user.UserService import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -10,14 +11,14 @@ import org.springframework.transaction.annotation.Transactional @Transactional(readOnly = true) @Service class UserApplicationService( - private val userService: UserService + private val userService: UserService, ) { @Transactional - fun addDetails(addUserDetailsServerRequest: AddUserDetailsServerRequest): UserDetailsResponse { - val userId = addUserDetailsServerRequest.userId - val userDetailsDto = userService.addDetails(userId, addUserDetailsServerRequest.toDomainDto()) - return UserDetailsResponse.from(userDetailsDto) + fun updateTravelPreference(updateTravelPreferenceServiceRequest: UpdateTravelPreferenceServiceRequest): UserDetailsResponse { + val userId = updateTravelPreferenceServiceRequest.userId + val userDetailsDto = + userService.updateTravelPreference(userId, updateTravelPreferenceServiceRequest.toCommand()) + return userDetailsDto.toDetailResponse() } - } diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserResponseDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserResponseDto.kt index 31935f9..d2c9cb3 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserResponseDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserResponseDto.kt @@ -1,61 +1,74 @@ package com.withaeng.api.applicationservice.user.dto -import com.withaeng.domain.user.UserConsumeStyle -import com.withaeng.domain.user.UserDetailsDto -import com.withaeng.domain.user.UserDrinkingType -import com.withaeng.domain.user.UserFoodRestriction -import com.withaeng.domain.user.UserMbti -import com.withaeng.domain.user.UserPreferAccompanyGender -import com.withaeng.domain.user.UserPreferTravelTheme -import com.withaeng.domain.user.UserPreferTravelType -import com.withaeng.domain.user.UserSimpleDto -import com.withaeng.domain.user.UserSmokingType +import com.withaeng.domain.user.* +import com.withaeng.domain.user.dto.UserDetailsDto +import com.withaeng.domain.user.dto.UserSimpleDto import java.time.LocalDate -data class UserDetailsResponse( +data class UserSimpleResponse( val id: Long, val email: String, val nickname: String, - val isMale: Boolean, +) + +fun UserSimpleDto.toSimpleResponse(): UserSimpleResponse = UserSimpleResponse( + id = id, + email = email, + nickname = profile.nickname +) + +data class UserDetailsResponse( + val id: Long, + val email: String, + val gender: Gender, val birth: LocalDate, - val mbti: UserMbti? = null, + val profile: UserProfileResponse, + val travelPreference: UserTravelPreferenceResponse? = null, + val mbti: Set? = emptySet(), val preferTravelType: UserPreferTravelType? = null, val preferTravelThemes: Set = emptySet(), val consumeStyle: UserConsumeStyle? = null, val foodRestrictions: Set = emptySet(), val preferAccompanyGender: UserPreferAccompanyGender? = null, val smokingType: UserSmokingType? = null, - val drinkingType: UserDrinkingType? = null -) { - companion object { - fun from(userDetailsDto: UserDetailsDto): UserDetailsResponse { - return UserDetailsResponse( - id = userDetailsDto.id, - email = userDetailsDto.email, - nickname = userDetailsDto.nickname, - isMale = userDetailsDto.isMale, - birth = userDetailsDto.birth, - mbti = userDetailsDto.mbti, - preferTravelType = userDetailsDto.preferTravelType, - preferTravelThemes = userDetailsDto.preferTravelThemes, - consumeStyle = userDetailsDto.consumeStyle, - foodRestrictions = userDetailsDto.foodRestrictions, - preferAccompanyGender = userDetailsDto.preferAccompanyGender, - smokingType = userDetailsDto.smokingType, - drinkingType = userDetailsDto.drinkingType - ) - } - } -} + val drinkingType: UserDrinkingType? = null, +) -data class UserSimpleResponse( - val id: Long, - val email: String, - val nickname: String +data class UserProfileResponse( + val nickname: String, + val introduction: String? = null, + val profileImageUrl: String? = null, ) -fun UserSimpleDto.toSimpleResponse(): UserSimpleResponse = UserSimpleResponse( +data class UserTravelPreferenceResponse( + val mbti: Set? = emptySet(), + val preferTravelType: UserPreferTravelType? = null, + val preferTravelThemes: Set = emptySet(), + val consumeStyle: UserConsumeStyle? = null, + val foodRestrictions: Set = emptySet(), + val smokingType: UserSmokingType? = null, + val drinkingType: UserDrinkingType? = null, +) + +fun UserDetailsDto.toDetailResponse(): UserDetailsResponse = UserDetailsResponse( id = id, email = email, - nickname = nickname + gender = gender, + birth = birth, + profile = UserProfileResponse( + nickname = profile.nickname, + introduction = profile.introduction, + profileImageUrl = profile.profileImageUrl, + ), + travelPreference = travelPreference?.let { + UserTravelPreferenceResponse( + mbti = it.mbti, + preferTravelType = it.preferTravelType, + preferTravelThemes = it.preferTravelThemes, + consumeStyle = it.consumeStyle, + foodRestrictions = it.foodRestrictions, + smokingType = it.smokingType, + drinkingType = it.drinkingType + ) + }, ) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceRequestDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceRequestDto.kt index c138bd0..1e15eb7 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceRequestDto.kt @@ -1,36 +1,28 @@ package com.withaeng.api.applicationservice.user.dto -import com.withaeng.domain.user.AddDetailsUserDto -import com.withaeng.domain.user.UserConsumeStyle -import com.withaeng.domain.user.UserDrinkingType -import com.withaeng.domain.user.UserFoodRestriction -import com.withaeng.domain.user.UserMbti -import com.withaeng.domain.user.UserPreferAccompanyGender -import com.withaeng.domain.user.UserPreferTravelTheme -import com.withaeng.domain.user.UserPreferTravelType -import com.withaeng.domain.user.UserSmokingType +import com.withaeng.domain.user.* +import com.withaeng.domain.user.dto.UpdateTravelPreferenceCommand -data class AddUserDetailsServerRequest( +data class UpdateTravelPreferenceServiceRequest( val userId: Long, val nickname: String? = null, - val mbti: UserMbti? = null, + val mbti: List? = null, val preferTravelType: UserPreferTravelType? = null, val preferTravelThemes: List? = null, val consumeStyle: UserConsumeStyle? = null, val foodRestrictions: List? = null, - val preferAccompanyGender: UserPreferAccompanyGender? = null, val smokingType: UserSmokingType? = null, - val drinkingType: UserDrinkingType? = null + val drinkingType: UserDrinkingType? = null, ) -fun AddUserDetailsServerRequest.toDomainDto(): AddDetailsUserDto = AddDetailsUserDto( - nickname = nickname, - mbti = mbti, - preferTravelType = preferTravelType, - preferTravelThemes = preferTravelThemes, - consumeStyle = consumeStyle, - foodRestrictions = foodRestrictions, - preferAccompanyGender = preferAccompanyGender, - smokingType = smokingType, - drinkingType = drinkingType -) +fun UpdateTravelPreferenceServiceRequest.toCommand(): UpdateTravelPreferenceCommand = + UpdateTravelPreferenceCommand( + nickname = nickname, + mbti = mbti, + preferTravelType = preferTravelType, + preferTravelThemes = preferTravelThemes, + consumeStyle = consumeStyle, + foodRestrictions = foodRestrictions, + smokingType = smokingType, + drinkingType = drinkingType + ) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/auth/dto/AuthRequestDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/auth/dto/AuthRequestDto.kt index 3b09480..bf89d7a 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/auth/dto/AuthRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/auth/dto/AuthRequestDto.kt @@ -1,29 +1,30 @@ package com.withaeng.api.controller.auth.dto import com.withaeng.api.applicationservice.auth.dto.* +import com.withaeng.domain.user.Gender import io.swagger.v3.oas.annotations.media.Schema import java.time.LocalDate @Schema(description = "[Request] 회원가입") data class SignUpRequest( - @Schema(description = "남/여 성별") - val isMale: Boolean, - - @Schema(description = "생년월일 format:[2024-05-09]") - val birth: LocalDate, - @Schema(description = "회원가입 할 이메일") val email: String, @Schema(description = "회원가입 할 패스워드") - val password: String + val password: String, + + @Schema(description = "생년월일 format:[2024-05-09]") + val birth: LocalDate, + + @Schema(description = "성별") + val gender: Gender, ) fun SignUpRequest.toServiceRequest(): SignUpServiceRequest = SignUpServiceRequest( - isMale = isMale, - birth = birth, email = email, - password = password + password = password, + birth = birth, + gender = gender, ) @Schema(description = "[Request] 로그인") diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/UserController.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/UserController.kt index 82ea3f3..26b72c6 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/UserController.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/UserController.kt @@ -3,7 +3,7 @@ package com.withaeng.api.controller.user import com.withaeng.api.applicationservice.user.UserApplicationService import com.withaeng.api.applicationservice.user.dto.UserDetailsResponse import com.withaeng.api.common.ApiResponse -import com.withaeng.api.controller.user.dto.AddUserDetailsRequest +import com.withaeng.api.controller.user.dto.UpdateTravelPreferenceRequest import com.withaeng.api.controller.user.dto.toServiceRequest import com.withaeng.api.security.authentication.UserInfo import com.withaeng.api.security.resolver.GetAuth @@ -26,13 +26,13 @@ class UserController(private val userApplicationService: UserApplicationService) description = "유저 관련 정보 수정 API", security = [SecurityRequirement(name = "Authorization")] ) - @PostMapping("/add-details") - fun addDetails( + @PostMapping("/travel-preference") + fun updateTravelPreference( @GetAuth userInfo: UserInfo, - @RequestBody @Valid request: AddUserDetailsRequest + @RequestBody @Valid request: UpdateTravelPreferenceRequest, ): ApiResponse { return ApiResponse.success( - userApplicationService.addDetails(request.toServiceRequest(userInfo.id)) + userApplicationService.updateTravelPreference(request.toServiceRequest(userInfo.id)) ) } diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/dto/UserRequestDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/dto/UserRequestDto.kt index 654316e..c849967 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/dto/UserRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/dto/UserRequestDto.kt @@ -1,18 +1,18 @@ package com.withaeng.api.controller.user.dto +import com.withaeng.api.applicationservice.user.dto.UpdateTravelPreferenceServiceRequest import com.withaeng.domain.user.* -import com.withaeng.api.applicationservice.user.dto.AddUserDetailsServerRequest import io.swagger.v3.oas.annotations.media.Schema import org.hibernate.validator.constraints.Length @Schema(description = "[Request] User 정보를 추가합니다") -data class AddUserDetailsRequest( +data class UpdateTravelPreferenceRequest( @Schema(description = "유저 닉네임") @field:Length(min = 2, max = 10, message = "닉네임은 2 ~ 10자리 문자열로 입력해야 합니다.") val nickname: String? = null, @Schema(description = "유저 MBTI") - val mbti: UserMbti? = null, + val mbti: List? = null, @Schema(description = "여행 선호 지역 (국내 / 해외)") val preferTravelType: UserPreferTravelType? = null, @@ -26,24 +26,21 @@ data class AddUserDetailsRequest( @Schema(description = "못 먹는 음식 (갑각류, 해산물 등)") val foodRestrictions: List? = null, - @Schema(description = "원하는 동행자의 성별") - val preferAccompanyGender: UserPreferAccompanyGender? = null, - @Schema(description = "흡연 타입") val smokingType: UserSmokingType? = null, @Schema(description = "음주 타입") - val drinkingType: UserDrinkingType? = null + val drinkingType: UserDrinkingType? = null, ) -fun AddUserDetailsRequest.toServiceRequest(userId: Long): AddUserDetailsServerRequest = AddUserDetailsServerRequest( - userId = userId, - nickname = nickname, - mbti = mbti, - preferTravelType = preferTravelType, - preferTravelThemes = preferTravelThemes, - consumeStyle = consumeStyle, - foodRestrictions = foodRestrictions, - preferAccompanyGender = preferAccompanyGender, - smokingType = smokingType -) +fun UpdateTravelPreferenceRequest.toServiceRequest(userId: Long): UpdateTravelPreferenceServiceRequest = + UpdateTravelPreferenceServiceRequest( + userId = userId, + nickname = nickname, + mbti = mbti, + preferTravelType = preferTravelType, + preferTravelThemes = preferTravelThemes, + consumeStyle = consumeStyle, + foodRestrictions = foodRestrictions, + smokingType = smokingType + ) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/security/authentication/UserInfo.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/security/authentication/UserInfo.kt index 5ad7087..4e8d803 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/security/authentication/UserInfo.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/security/authentication/UserInfo.kt @@ -1,7 +1,7 @@ package com.withaeng.api.security.authentication import com.withaeng.domain.user.UserRole -import com.withaeng.domain.user.UserSimpleDto +import com.withaeng.domain.user.dto.UserSimpleDto data class UserInfo( val id: Long, diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryImpl.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryImpl.kt index 209c9fd..4d02888 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryImpl.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryImpl.kt @@ -9,9 +9,9 @@ import com.withaeng.domain.user.QUser.user class AccompanyRepositoryImpl( - private val queryFactory: JPAQueryFactory + private val queryFactory: JPAQueryFactory, -) : AccompanyRepositoryCustom { + ) : AccompanyRepositoryCustom { override fun findAccompanyDetail(accompanyId: Long): FindAccompanyDto? { return queryFactory @@ -34,10 +34,10 @@ class AccompanyRepositoryImpl( accompany.tagIds, accompanyLike.count(), QFindAccompanyUserInfoDto( - user.nickname, - user.profileImageUrl, - user.isMale, - user.bio, + user.profile.nickname, + user.profile.profileImageUrl, + user.gender, + user.profile.introduction, user.createdAt, ), ) diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/FindAccompanyUserInfoDto.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/FindAccompanyUserInfoDto.kt index cfb0be3..b78e937 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/FindAccompanyUserInfoDto.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/FindAccompanyUserInfoDto.kt @@ -1,13 +1,14 @@ package com.withaeng.domain.accompany import com.querydsl.core.annotations.QueryProjection +import com.withaeng.domain.user.Gender import java.time.LocalDateTime data class FindAccompanyUserInfoDto @QueryProjection constructor( val nickname: String, val profileImageUrl: String?, - val isMale: Boolean, - val bio: String?, + val gender: Gender, + val introduction: String?, val joinDate: LocalDateTime, // TODO : 여행 관심사 Set 추가 필요 // TODO : 온도 추가 필요 diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreply/AccompanyReplyRepositoryImpl.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreply/AccompanyReplyRepositoryImpl.kt index 4f2d54b..c1b5dab 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreply/AccompanyReplyRepositoryImpl.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyreply/AccompanyReplyRepositoryImpl.kt @@ -11,9 +11,9 @@ import org.springframework.data.support.PageableExecutionUtils class AccompanyReplyRepositoryImpl( - private val queryFactory: JPAQueryFactory + private val queryFactory: JPAQueryFactory, -) : AccompanyReplyRepositoryCustom { + ) : AccompanyReplyRepositoryCustom { override fun findAccompanyReplyList( accompanyId: Long, @@ -33,7 +33,7 @@ class AccompanyReplyRepositoryImpl( QFindAccompanyReplyUserInfoDto( user.id, user.email, - user.nickname, + user.profile.nickname, ) ) ) diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/converter/UserMbtiConverter.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/converter/UserMbtiConverter.kt new file mode 100644 index 0000000..d229f6a --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/converter/UserMbtiConverter.kt @@ -0,0 +1,19 @@ +package com.withaeng.domain.converter + +import com.withaeng.domain.user.UserMbti +import jakarta.persistence.AttributeConverter + +class UserMbtiConverter : AttributeConverter, String> { + override fun convertToDatabaseColumn(attribute: Set): String { + return attribute.joinToString(DELIMITER) { it.name } + } + + override fun convertToEntityAttribute(data: String): Set { + return if (data.isBlank()) return emptySet() + else data.split(DELIMITER).map { UserMbti.valueOf(it.trim()) }.toSet() + } + + companion object { + private const val DELIMITER = "," + } +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/Gender.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/Gender.kt new file mode 100644 index 0000000..b8f302c --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/Gender.kt @@ -0,0 +1,5 @@ +package com.withaeng.domain.user + +enum class Gender { + MALE, FEMALE +} diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/User.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/User.kt index 8cf4161..e771561 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/User.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/User.kt @@ -1,8 +1,6 @@ package com.withaeng.domain.user import com.withaeng.domain.BaseEntity -import com.withaeng.domain.converter.UserFoodRestrictionConverter -import com.withaeng.domain.converter.UserPreferTravelThemeConverter import com.withaeng.domain.converter.UserRoleConverter import jakarta.persistence.* import java.time.LocalDate @@ -16,52 +14,18 @@ class User( @Column(name = "password", nullable = false) var password: String, - @Column(name = "nickname", nullable = false) - var nickname: String, - @Column(name = "birth", nullable = false) val birth: LocalDate, - @Column(name = "is_male", nullable = false) - val isMale: Boolean, - - @Column(name = "profile_image_url", nullable = true) - var profileImageUrl: String? = null, - - @Column(name = "bio", nullable = true) - var bio: String? = null, - @Enumerated(EnumType.STRING) - @Column(name = "mbti", nullable = true) - var mbti: UserMbti? = null, + @Column(name = "gender", nullable = false) + val gender: Gender, - @Enumerated(EnumType.STRING) - @Column(name = "prefer_travel_type", nullable = true) - var preferTravelType: UserPreferTravelType? = null, + @Embedded + val profile: UserProfile, - @Convert(converter = UserPreferTravelThemeConverter::class) - @Column(name = "prefer_travel_theme", nullable = false) - var preferTravelThemes: Set = emptySet(), - - @Enumerated(EnumType.STRING) - @Column(name = "consume_style", nullable = true) - var consumeStyle: UserConsumeStyle? = null, - - @Convert(converter = UserFoodRestrictionConverter::class) - @Column(name = "food_restriction", nullable = false) - var foodRestrictions: Set = emptySet(), - - @Enumerated(EnumType.STRING) - @Column(name = "prefer_accompany_gender", nullable = true) - var preferAccompanyGender: UserPreferAccompanyGender? = null, - - @Enumerated(EnumType.STRING) - @Column(name = "smoking_type", nullable = true) - var smokingType: UserSmokingType? = null, - - @Enumerated(EnumType.STRING) - @Column(name = "drinking_type", nullable = true) - var drinkingType: UserDrinkingType? = null, + @OneToOne(mappedBy = "user") + val travelPreference: UserTravelPreference? = null, @Convert(converter = UserRoleConverter::class) @Column(name = "roles") @@ -69,20 +33,21 @@ class User( ) : BaseEntity() { companion object { - fun create( email: String, - nickname: String, password: String, birth: LocalDate, - isMale: Boolean + gender: Gender, + nickname: String, ): User { return User( email = email, - nickname = nickname, password = password, birth = birth, - isMale = isMale, + gender = gender, + profile = UserProfile( + nickname = nickname + ), roles = setOf(UserRole.NON_USER) ) } diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserProfile.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserProfile.kt new file mode 100644 index 0000000..79199d4 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserProfile.kt @@ -0,0 +1,16 @@ +package com.withaeng.domain.user + +import jakarta.persistence.Column +import jakarta.persistence.Embeddable + +@Embeddable +class UserProfile( + @Column(name = "nickname", nullable = false) + var nickname: String, + + @Column(name = "introduction", nullable = true) + var introduction: String? = null, + + @Column(name = "profile_image_url", nullable = true) + var profileImageUrl: String? = null, +) diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserService.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserService.kt index b20ec81..1dac97b 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserService.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserService.kt @@ -2,6 +2,7 @@ package com.withaeng.domain.user import com.withaeng.common.exception.WithaengException import com.withaeng.common.exception.WithaengExceptionType +import com.withaeng.domain.user.dto.* import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -11,14 +12,14 @@ import org.springframework.transaction.annotation.Transactional class UserService(private val userRepository: UserRepository) { @Transactional - fun create(createUserDto: CreateUserDto): UserSimpleDto { + fun create(createUserCommand: CreateUserCommand): UserSimpleDto { return userRepository.save( User.create( - email = createUserDto.email, - nickname = createUserDto.nickname, - password = createUserDto.password, - birth = createUserDto.birth, - isMale = createUserDto.isMale + email = createUserCommand.email, + nickname = createUserCommand.nickname, + password = createUserCommand.password, + birth = createUserCommand.birth, + gender = createUserCommand.gender ) ).toSimpleDto() } @@ -32,17 +33,16 @@ class UserService(private val userRepository: UserRepository) { } @Transactional - fun addDetails(userId: Long, addDetailsUserDto: AddDetailsUserDto): UserDetailsDto { + fun updateTravelPreference(userId: Long, command: UpdateTravelPreferenceCommand): UserDetailsDto { val user = userRepository.findByIdOrNull(userId).getOrThrow() - addDetailsUserDto.nickname?.let { user.nickname = it } - addDetailsUserDto.mbti?.let { user.mbti = it } - addDetailsUserDto.preferTravelType?.let { user.preferTravelType = it } - addDetailsUserDto.preferTravelThemes?.let { user.preferTravelThemes = it.toSet() } - addDetailsUserDto.consumeStyle?.let { user.consumeStyle = it } - addDetailsUserDto.foodRestrictions?.let { user.foodRestrictions = it.toSet() } - addDetailsUserDto.preferAccompanyGender?.let { user.preferAccompanyGender = it } - addDetailsUserDto.smokingType?.let { user.smokingType = it } - addDetailsUserDto.drinkingType?.let { user.drinkingType = it } + command.nickname?.let { user.profile.nickname = it } + command.mbti?.let { user.travelPreference?.mbti = it.toSet() } + command.preferTravelType?.let { user.travelPreference?.preferTravelType = it } + command.preferTravelThemes?.let { user.travelPreference?.preferTravelThemes = it.toSet() } + command.consumeStyle?.let { user.travelPreference?.consumeStyle = it } + command.foodRestrictions?.let { user.travelPreference?.foodRestrictions = it.toSet() } + command.smokingType?.let { user.travelPreference?.smokingType = it } + command.drinkingType?.let { user.travelPreference?.drinkingType = it } return user.toDetailsDto() } diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserSimpleDto.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserSimpleDto.kt deleted file mode 100644 index 3a6c20f..0000000 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserSimpleDto.kt +++ /dev/null @@ -1,87 +0,0 @@ -package com.withaeng.domain.user - -import java.time.LocalDate - -data class UserSimpleDto( - val id: Long, - val email: String, - val password: String, - val nickname: String, - val birth: LocalDate, - val isMale: Boolean, - val profileImageUrl: String? = null, - val bio: String? = null, - val roles: Set -) - -data class UserDetailsDto( - val id: Long, - val email: String, - val password: String, - val nickname: String, - val birth: LocalDate, - val isMale: Boolean, - val profileImageUrl: String? = null, - val bio: String? = null, - val mbti: UserMbti? = null, - val preferTravelType: UserPreferTravelType? = null, - val preferTravelThemes: Set = emptySet(), - val consumeStyle: UserConsumeStyle? = null, - val foodRestrictions: Set = emptySet(), - val preferAccompanyGender: UserPreferAccompanyGender? = null, - val smokingType: UserSmokingType? = null, - val drinkingType: UserDrinkingType? = null, - val roles: Set -) - -fun User.toSimpleDto(): UserSimpleDto = UserSimpleDto( - id = id, - email = email, - password = password, - nickname = nickname, - birth = birth, - isMale = isMale, - profileImageUrl = profileImageUrl, - bio = bio, - roles = roles -) - -fun User.toDetailsDto(): UserDetailsDto = UserDetailsDto( - id = id, - email = email, - password = password, - nickname = nickname, - birth = birth, - isMale = isMale, - profileImageUrl = profileImageUrl, - bio = bio, - mbti = mbti, - preferTravelType = preferTravelType, - preferTravelThemes = preferTravelThemes, - consumeStyle = consumeStyle, - foodRestrictions = foodRestrictions, - preferAccompanyGender = preferAccompanyGender, - smokingType = smokingType, - drinkingType = drinkingType, - roles = roles -) - -data class CreateUserDto( - val email: String, - val nickname: String, - val password: String, - val birth: LocalDate, - val isMale: Boolean -) - -data class AddDetailsUserDto( - val nickname: String? = null, - val mbti: UserMbti? = null, - val preferTravelType: UserPreferTravelType? = null, - val preferTravelThemes: List? = null, - val consumeStyle: UserConsumeStyle? = null, - val foodRestrictions: List? = null, - val preferAccompanyGender: UserPreferAccompanyGender? = null, - val smokingType: UserSmokingType? = null, - val drinkingType: UserDrinkingType? = null -) diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserTravelPreference.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserTravelPreference.kt new file mode 100644 index 0000000..cb8372b --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserTravelPreference.kt @@ -0,0 +1,42 @@ +package com.withaeng.domain.user + +import com.withaeng.domain.BaseEntity +import com.withaeng.domain.converter.UserFoodRestrictionConverter +import com.withaeng.domain.converter.UserMbtiConverter +import com.withaeng.domain.converter.UserPreferTravelThemeConverter +import jakarta.persistence.* + +@Table(name = "user_travel_preference") +@Entity +class UserTravelPreference( + @Convert(converter = UserMbtiConverter::class) + @Column(name = "mbti", nullable = true) + var mbti: Set = emptySet(), + + @Enumerated(EnumType.STRING) + @Column(name = "prefer_travel_type", nullable = true) + var preferTravelType: UserPreferTravelType? = null, + + @Convert(converter = UserPreferTravelThemeConverter::class) + @Column(name = "prefer_travel_theme", nullable = false) + var preferTravelThemes: Set = emptySet(), + + @Enumerated(EnumType.STRING) + @Column(name = "consume_style", nullable = true) + var consumeStyle: UserConsumeStyle? = null, + + @Convert(converter = UserFoodRestrictionConverter::class) + @Column(name = "food_restriction", nullable = false) + var foodRestrictions: Set = emptySet(), + + @Enumerated(EnumType.STRING) + @Column(name = "smoking_type", nullable = true) + var smokingType: UserSmokingType? = null, + + @Enumerated(EnumType.STRING) + @Column(name = "drinking_type", nullable = true) + var drinkingType: UserDrinkingType? = null, + + @OneToOne + val user: User, +) : BaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/dto/UserCommand.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/dto/UserCommand.kt new file mode 100644 index 0000000..83ca95e --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/dto/UserCommand.kt @@ -0,0 +1,23 @@ +package com.withaeng.domain.user.dto + +import com.withaeng.domain.user.* +import java.time.LocalDate + +data class CreateUserCommand( + val email: String, + val password: String, + val birth: LocalDate, + val gender: Gender, + val nickname: String, +) + +data class UpdateTravelPreferenceCommand( + val nickname: String? = null, + val mbti: List? = null, + val preferTravelType: UserPreferTravelType? = null, + val preferTravelThemes: List? = null, + val consumeStyle: UserConsumeStyle? = null, + val foodRestrictions: List? = null, + val smokingType: UserSmokingType? = null, + val drinkingType: UserDrinkingType? = null, +) \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/dto/UserDto.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/dto/UserDto.kt new file mode 100644 index 0000000..3ca74ad --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/dto/UserDto.kt @@ -0,0 +1,80 @@ +package com.withaeng.domain.user.dto + +import com.withaeng.domain.user.* +import java.time.LocalDate + +data class UserSimpleDto( + val id: Long, + val email: String, + val password: String, + val birth: LocalDate, + val gender: Gender, + val profile: UserProfileDto, + val roles: Set, +) + +fun User.toSimpleDto(): UserSimpleDto = UserSimpleDto( + id = id, + email = email, + password = password, + birth = birth, + gender = gender, + profile = UserProfileDto( + nickname = profile.nickname, + introduction = profile.introduction, + profileImageUrl = profile.profileImageUrl, + ), + roles = roles, +) + +data class UserDetailsDto( + val id: Long, + val email: String, + val password: String, + val birth: LocalDate, + val gender: Gender, + val profile: UserProfileDto, + val travelPreference: UserTravelPreferenceDto? = null, + val roles: Set, +) + +data class UserProfileDto( + val nickname: String, + val introduction: String? = null, + val profileImageUrl: String? = null, +) + +data class UserTravelPreferenceDto( + val mbti: Set? = emptySet(), + val preferTravelType: UserPreferTravelType? = null, + val preferTravelThemes: Set = emptySet(), + val consumeStyle: UserConsumeStyle? = null, + val foodRestrictions: Set = emptySet(), + val smokingType: UserSmokingType? = null, + val drinkingType: UserDrinkingType? = null, +) + +fun User.toDetailsDto(): UserDetailsDto = UserDetailsDto( + id = id, + email = email, + password = password, + birth = birth, + gender = gender, + profile = UserProfileDto( + nickname = profile.nickname, + introduction = profile.introduction, + profileImageUrl = profile.profileImageUrl, + ), + travelPreference = travelPreference?.toDto(), + roles = roles +) + +fun UserTravelPreference.toDto(): UserTravelPreferenceDto = UserTravelPreferenceDto( + mbti = mbti, + preferTravelType = preferTravelType, + preferTravelThemes = preferTravelThemes, + consumeStyle = consumeStyle, + foodRestrictions = foodRestrictions, + smokingType = smokingType, + drinkingType = drinkingType, +) From c8444ae8cbc253d30dd764cc76586025024edb72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Tue, 10 Sep 2024 22:37:39 +0900 Subject: [PATCH 125/174] =?UTF-8?q?feat:=20=EC=9C=A0=EC=A0=80=20=ED=94=84?= =?UTF-8?q?=EB=A1=9C=ED=95=84=20put=20api=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/AccompanyReplyResponseDto.kt | 4 +- .../user/UserApplicationService.kt | 19 ++++----- ...iceRequestDto.kt => UserServiceRequest.kt} | 23 ++++++++--- ...rResponseDto.kt => UserServiceResponse.kt} | 28 +++++-------- ...{UserController.kt => UserMeController.kt} | 34 +++++++++++----- .../dto/{UserRequestDto.kt => UserRequest.kt} | 34 +++++++++++----- .../kotlin/com/withaeng/domain/user/User.kt | 4 +- .../com/withaeng/domain/user/UserService.kt | 40 ++++++++++++------- .../domain/user/UserTravelPreference.kt | 9 ++++- .../withaeng/domain/user/dto/UserCommand.kt | 13 ++++-- 10 files changed, 131 insertions(+), 77 deletions(-) rename withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/{UserServiceRequestDto.kt => UserServiceRequest.kt} (59%) rename withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/{UserResponseDto.kt => UserServiceResponse.kt} (62%) rename withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/{UserController.kt => UserMeController.kt} (52%) rename withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/dto/{UserRequestDto.kt => UserRequest.kt} (59%) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt index 940941b..2b206e8 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt @@ -1,6 +1,6 @@ package com.withaeng.api.applicationservice.accompanyreply.dto -import com.withaeng.api.applicationservice.user.dto.UserSimpleResponse +import com.withaeng.api.applicationservice.user.dto.UserSimpleServiceResponse import com.withaeng.api.applicationservice.user.dto.toSimpleResponse import com.withaeng.domain.accompanyreply.AccompanyReplyDto import com.withaeng.domain.accompanyreply.AccompanyReplyStatus @@ -9,7 +9,7 @@ import java.time.LocalDateTime data class AccompanyReplyResponse( val id: Long, - val author: UserSimpleResponse, + val author: UserSimpleServiceResponse, val accompanyId: Long, val parentId: Long? = null, val content: String?, diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/UserApplicationService.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/UserApplicationService.kt index 25a7b69..db44611 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/UserApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/UserApplicationService.kt @@ -1,24 +1,19 @@ package com.withaeng.api.applicationservice.user -import com.withaeng.api.applicationservice.user.dto.UpdateTravelPreferenceServiceRequest -import com.withaeng.api.applicationservice.user.dto.UserDetailsResponse -import com.withaeng.api.applicationservice.user.dto.toCommand -import com.withaeng.api.applicationservice.user.dto.toDetailResponse +import com.withaeng.api.applicationservice.user.dto.* import com.withaeng.domain.user.UserService import org.springframework.stereotype.Service -import org.springframework.transaction.annotation.Transactional -@Transactional(readOnly = true) @Service class UserApplicationService( private val userService: UserService, ) { - @Transactional - fun updateTravelPreference(updateTravelPreferenceServiceRequest: UpdateTravelPreferenceServiceRequest): UserDetailsResponse { - val userId = updateTravelPreferenceServiceRequest.userId - val userDetailsDto = - userService.updateTravelPreference(userId, updateTravelPreferenceServiceRequest.toCommand()) - return userDetailsDto.toDetailResponse() + fun updateProfile(serviceRequest: UpdateProfileServiceRequest): UserSimpleServiceResponse { + return userService.updateProfile(serviceRequest.userId, serviceRequest.toCommand()).toSimpleResponse() + } + + fun updateTravelPreference(serviceRequest: UpdateTravelPreferenceServiceRequest): UserDetailServiceResponse { + return userService.updateTravelPreference(serviceRequest.userId, serviceRequest.toCommand()).toDetailResponse() } } diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceRequestDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceRequest.kt similarity index 59% rename from withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceRequestDto.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceRequest.kt index 1e15eb7..cd7afce 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceRequest.kt @@ -1,23 +1,36 @@ package com.withaeng.api.applicationservice.user.dto import com.withaeng.domain.user.* +import com.withaeng.domain.user.dto.UpdateProfileCommand import com.withaeng.domain.user.dto.UpdateTravelPreferenceCommand +data class UpdateProfileServiceRequest( + val userId: Long, + val nickname: String?, + val introduction: String?, + val profileImageUrl: String?, +) + +fun UpdateProfileServiceRequest.toCommand(): UpdateProfileCommand = + UpdateProfileCommand( + nickname = nickname, + introduction = introduction, + profileImageUrl = profileImageUrl + ) + data class UpdateTravelPreferenceServiceRequest( val userId: Long, - val nickname: String? = null, - val mbti: List? = null, + val mbti: Set? = emptySet(), val preferTravelType: UserPreferTravelType? = null, - val preferTravelThemes: List? = null, + val preferTravelThemes: Set? = emptySet(), val consumeStyle: UserConsumeStyle? = null, - val foodRestrictions: List? = null, + val foodRestrictions: Set? = emptySet(), val smokingType: UserSmokingType? = null, val drinkingType: UserDrinkingType? = null, ) fun UpdateTravelPreferenceServiceRequest.toCommand(): UpdateTravelPreferenceCommand = UpdateTravelPreferenceCommand( - nickname = nickname, mbti = mbti, preferTravelType = preferTravelType, preferTravelThemes = preferTravelThemes, diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserResponseDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceResponse.kt similarity index 62% rename from withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserResponseDto.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceResponse.kt index d2c9cb3..f0f1021 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserResponseDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceResponse.kt @@ -5,42 +5,34 @@ import com.withaeng.domain.user.dto.UserDetailsDto import com.withaeng.domain.user.dto.UserSimpleDto import java.time.LocalDate -data class UserSimpleResponse( +data class UserSimpleServiceResponse( val id: Long, val email: String, val nickname: String, ) -fun UserSimpleDto.toSimpleResponse(): UserSimpleResponse = UserSimpleResponse( +fun UserSimpleDto.toSimpleResponse(): UserSimpleServiceResponse = UserSimpleServiceResponse( id = id, email = email, nickname = profile.nickname ) -data class UserDetailsResponse( +data class UserDetailServiceResponse( val id: Long, val email: String, val gender: Gender, val birth: LocalDate, - val profile: UserProfileResponse, - val travelPreference: UserTravelPreferenceResponse? = null, - val mbti: Set? = emptySet(), - val preferTravelType: UserPreferTravelType? = null, - val preferTravelThemes: Set = emptySet(), - val consumeStyle: UserConsumeStyle? = null, - val foodRestrictions: Set = emptySet(), - val preferAccompanyGender: UserPreferAccompanyGender? = null, - val smokingType: UserSmokingType? = null, - val drinkingType: UserDrinkingType? = null, + val profile: UserProfileServiceResponse, + val travelPreference: UserTravelPreferenceServiceResponse? = null, ) -data class UserProfileResponse( +data class UserProfileServiceResponse( val nickname: String, val introduction: String? = null, val profileImageUrl: String? = null, ) -data class UserTravelPreferenceResponse( +data class UserTravelPreferenceServiceResponse( val mbti: Set? = emptySet(), val preferTravelType: UserPreferTravelType? = null, val preferTravelThemes: Set = emptySet(), @@ -50,18 +42,18 @@ data class UserTravelPreferenceResponse( val drinkingType: UserDrinkingType? = null, ) -fun UserDetailsDto.toDetailResponse(): UserDetailsResponse = UserDetailsResponse( +fun UserDetailsDto.toDetailResponse(): UserDetailServiceResponse = UserDetailServiceResponse( id = id, email = email, gender = gender, birth = birth, - profile = UserProfileResponse( + profile = UserProfileServiceResponse( nickname = profile.nickname, introduction = profile.introduction, profileImageUrl = profile.profileImageUrl, ), travelPreference = travelPreference?.let { - UserTravelPreferenceResponse( + UserTravelPreferenceServiceResponse( mbti = it.mbti, preferTravelType = it.preferTravelType, preferTravelThemes = it.preferTravelThemes, diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/UserController.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/UserMeController.kt similarity index 52% rename from withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/UserController.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/UserMeController.kt index 26b72c6..5cc1574 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/UserController.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/UserMeController.kt @@ -1,8 +1,10 @@ package com.withaeng.api.controller.user import com.withaeng.api.applicationservice.user.UserApplicationService -import com.withaeng.api.applicationservice.user.dto.UserDetailsResponse +import com.withaeng.api.applicationservice.user.dto.UserDetailServiceResponse +import com.withaeng.api.applicationservice.user.dto.UserSimpleServiceResponse import com.withaeng.api.common.ApiResponse +import com.withaeng.api.controller.user.dto.UpdateProfileRequest import com.withaeng.api.controller.user.dto.UpdateTravelPreferenceRequest import com.withaeng.api.controller.user.dto.toServiceRequest import com.withaeng.api.security.authentication.UserInfo @@ -11,29 +13,43 @@ import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.security.SecurityRequirement import io.swagger.v3.oas.annotations.tags.Tag import jakarta.validation.Valid -import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.PutMapping import org.springframework.web.bind.annotation.RequestBody import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController @Tag(name = "User", description = "유저 정보 관리 API") @RestController -@RequestMapping("/api/v1/user") -class UserController(private val userApplicationService: UserApplicationService) { +@RequestMapping("/api/v1/user/me") +class UserMeController(private val userApplicationService: UserApplicationService) { @Operation( - summary = "Add Details", - description = "유저 관련 정보 수정 API", + summary = "Update Profile", + description = "프로필 업데이트 API", security = [SecurityRequirement(name = "Authorization")] ) - @PostMapping("/travel-preference") + @PutMapping("/profile") + fun updateProfile( + @GetAuth userInfo: UserInfo, + @RequestBody @Valid request: UpdateProfileRequest, + ): ApiResponse { + return ApiResponse.success( + userApplicationService.updateProfile(request.toServiceRequest(userInfo.id)) + ) + } + + @Operation( + summary = "Update Travel Preference", + description = "여행 선호 정보 업데이트 API", + security = [SecurityRequirement(name = "Authorization")] + ) + @PutMapping("/travel-preference") fun updateTravelPreference( @GetAuth userInfo: UserInfo, @RequestBody @Valid request: UpdateTravelPreferenceRequest, - ): ApiResponse { + ): ApiResponse { return ApiResponse.success( userApplicationService.updateTravelPreference(request.toServiceRequest(userInfo.id)) ) } - } diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/dto/UserRequestDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/dto/UserRequest.kt similarity index 59% rename from withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/dto/UserRequestDto.kt rename to withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/dto/UserRequest.kt index c849967..7fe7cde 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/dto/UserRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/dto/UserRequest.kt @@ -1,30 +1,46 @@ package com.withaeng.api.controller.user.dto +import com.withaeng.api.applicationservice.user.dto.UpdateProfileServiceRequest import com.withaeng.api.applicationservice.user.dto.UpdateTravelPreferenceServiceRequest import com.withaeng.domain.user.* import io.swagger.v3.oas.annotations.media.Schema -import org.hibernate.validator.constraints.Length -@Schema(description = "[Request] User 정보를 추가합니다") -data class UpdateTravelPreferenceRequest( +@Schema(description = "[Request] User 프로필 정보를 추가합니다") +data class UpdateProfileRequest( @Schema(description = "유저 닉네임") - @field:Length(min = 2, max = 10, message = "닉네임은 2 ~ 10자리 문자열로 입력해야 합니다.") val nickname: String? = null, + @Schema(description = "유저 소개") + val introduction: String? = null, + + @Schema(description = "프로필 이미지 URL") + val profileImageUrl: String? = null, +) + +fun UpdateProfileRequest.toServiceRequest(userId: Long): UpdateProfileServiceRequest = + UpdateProfileServiceRequest( + userId = userId, + nickname = nickname, + introduction = introduction, + profileImageUrl = profileImageUrl + ) + +@Schema(description = "[Request] User 여행 선호 스타일 정보를 추가합니다") +data class UpdateTravelPreferenceRequest( @Schema(description = "유저 MBTI") - val mbti: List? = null, + val mbti: Set? = emptySet(), @Schema(description = "여행 선호 지역 (국내 / 해외)") val preferTravelType: UserPreferTravelType? = null, @Schema(description = "여행 관심사 (사진, 음식 등)") - val preferTravelThemes: List? = null, + val preferTravelThemes: Set? = emptySet(), @Schema(description = "여행 소비 스타일 (가성비, 쓸 때 쓰는 타입 등)") val consumeStyle: UserConsumeStyle? = null, @Schema(description = "못 먹는 음식 (갑각류, 해산물 등)") - val foodRestrictions: List? = null, + val foodRestrictions: Set? = emptySet(), @Schema(description = "흡연 타입") val smokingType: UserSmokingType? = null, @@ -36,11 +52,11 @@ data class UpdateTravelPreferenceRequest( fun UpdateTravelPreferenceRequest.toServiceRequest(userId: Long): UpdateTravelPreferenceServiceRequest = UpdateTravelPreferenceServiceRequest( userId = userId, - nickname = nickname, mbti = mbti, preferTravelType = preferTravelType, preferTravelThemes = preferTravelThemes, consumeStyle = consumeStyle, foodRestrictions = foodRestrictions, - smokingType = smokingType + smokingType = smokingType, + drinkingType = drinkingType ) diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/User.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/User.kt index e771561..e582d6a 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/User.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/User.kt @@ -24,8 +24,8 @@ class User( @Embedded val profile: UserProfile, - @OneToOne(mappedBy = "user") - val travelPreference: UserTravelPreference? = null, + @OneToOne(mappedBy = "user", cascade = [CascadeType.ALL], orphanRemoval = true) + var travelPreference: UserTravelPreference? = null, @Convert(converter = UserRoleConverter::class) @Column(name = "roles") diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserService.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserService.kt index 1dac97b..774879c 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserService.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserService.kt @@ -8,9 +8,18 @@ import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @Service -@Transactional(readOnly = true) class UserService(private val userRepository: UserRepository) { + @Transactional(readOnly = true) + fun findById(id: Long): UserSimpleDto { + return userRepository.findByIdOrNull(id).getOrThrow().toSimpleDto() + } + + @Transactional(readOnly = true) + fun findByEmailOrNull(email: String): UserSimpleDto? { + return userRepository.findByEmail(email)?.toSimpleDto() + } + @Transactional fun create(createUserCommand: CreateUserCommand): UserSimpleDto { return userRepository.save( @@ -24,25 +33,26 @@ class UserService(private val userRepository: UserRepository) { ).toSimpleDto() } - fun findById(id: Long): UserSimpleDto { - return userRepository.findByIdOrNull(id).getOrThrow().toSimpleDto() - } - - fun findByEmailOrNull(email: String): UserSimpleDto? { - return userRepository.findByEmail(email)?.toSimpleDto() + @Transactional + fun updateProfile(userId: Long, command: UpdateProfileCommand): UserSimpleDto { + val user = userRepository.findByIdOrNull(userId).getOrThrow() + user.profile.nickname = command.nickname ?: user.profile.nickname + user.profile.introduction = command.introduction + user.profile.profileImageUrl = command.profileImageUrl + return user.toSimpleDto() } @Transactional fun updateTravelPreference(userId: Long, command: UpdateTravelPreferenceCommand): UserDetailsDto { val user = userRepository.findByIdOrNull(userId).getOrThrow() - command.nickname?.let { user.profile.nickname = it } - command.mbti?.let { user.travelPreference?.mbti = it.toSet() } - command.preferTravelType?.let { user.travelPreference?.preferTravelType = it } - command.preferTravelThemes?.let { user.travelPreference?.preferTravelThemes = it.toSet() } - command.consumeStyle?.let { user.travelPreference?.consumeStyle = it } - command.foodRestrictions?.let { user.travelPreference?.foodRestrictions = it.toSet() } - command.smokingType?.let { user.travelPreference?.smokingType = it } - command.drinkingType?.let { user.travelPreference?.drinkingType = it } + user.travelPreference = user.travelPreference ?: UserTravelPreference.create(user) + user.travelPreference?.mbti = command.mbti ?: emptySet() + user.travelPreference?.preferTravelType = command.preferTravelType + user.travelPreference?.preferTravelThemes = command.preferTravelThemes ?: emptySet() + user.travelPreference?.consumeStyle = command.consumeStyle + user.travelPreference?.foodRestrictions = command.foodRestrictions ?: emptySet() + user.travelPreference?.smokingType = command.smokingType + user.travelPreference?.drinkingType = command.drinkingType return user.toDetailsDto() } diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserTravelPreference.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserTravelPreference.kt index cb8372b..37b0d82 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserTravelPreference.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserTravelPreference.kt @@ -39,4 +39,11 @@ class UserTravelPreference( @OneToOne val user: User, -) : BaseEntity() \ No newline at end of file +) : BaseEntity() { + + companion object { + fun create(user: User): UserTravelPreference { + return UserTravelPreference(user = user) + } + } +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/dto/UserCommand.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/dto/UserCommand.kt index 83ca95e..10d6e44 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/dto/UserCommand.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/dto/UserCommand.kt @@ -11,13 +11,18 @@ data class CreateUserCommand( val nickname: String, ) -data class UpdateTravelPreferenceCommand( +data class UpdateProfileCommand( val nickname: String? = null, - val mbti: List? = null, + val introduction: String? = null, + val profileImageUrl: String? = null, +) + +data class UpdateTravelPreferenceCommand( + val mbti: Set? = emptySet(), val preferTravelType: UserPreferTravelType? = null, - val preferTravelThemes: List? = null, + val preferTravelThemes: Set? = emptySet(), val consumeStyle: UserConsumeStyle? = null, - val foodRestrictions: List? = null, + val foodRestrictions: Set? = emptySet(), val smokingType: UserSmokingType? = null, val drinkingType: UserDrinkingType? = null, ) \ No newline at end of file From ab22660839d2a2dfed6f11b96f4169399ef68013 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Tue, 10 Sep 2024 23:42:08 +0900 Subject: [PATCH 126/174] =?UTF-8?q?feat:=20=EC=9C=A0=EC=A0=80=20=ED=94=84?= =?UTF-8?q?=EB=A1=9C=ED=95=84,=20=EC=84=A0=ED=98=B8=20=EC=97=AC=ED=96=89?= =?UTF-8?q?=20=EC=8A=A4=ED=83=80=EC=9D=BC=20=EC=A1=B0=ED=9A=8C=20api=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 --- .../AccompanyReplyApplicationService.kt | 4 +- .../dto/AccompanyReplyResponseDto.kt | 4 +- .../test/TestApplicationService.kt | 6 +- .../user/UserApplicationService.kt | 22 +++++- .../user/dto/UserServiceResponse.kt | 70 ++++++++++++++++--- .../com/withaeng/api/config/SecurityConfig.kt | 14 +--- .../api/controller/user/UserMeController.kt | 43 +++++++++--- .../domain/accompany/AccompanyRepository.kt | 5 +- .../domain/accompany/AccompanyService.kt | 14 ++-- .../kotlin/com/withaeng/domain/user/User.kt | 3 + .../com/withaeng/domain/user/UserService.kt | 41 ++++++++++- .../com/withaeng/domain/user/dto/UserDto.kt | 10 ++- 12 files changed, 184 insertions(+), 52 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt index 95e1539..54e1a14 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanyreply/AccompanyReplyApplicationService.kt @@ -24,7 +24,7 @@ class AccompanyReplyApplicationService( @Transactional fun create(request: CreateAccompanyReplyServiceRequest): AccompanyReplyResponse { - val userSimpleDto = userService.findById(request.userId) + val userSimpleDto = userService.findSimpleById(request.userId) return accompanyReplyService.create( accompanyId = request.accompanyId, userId = request.userId, @@ -43,7 +43,7 @@ class AccompanyReplyApplicationService( @Transactional fun update(request: UpdateAccompanyReplyServiceRequest): AccompanyReplyResponse { val accompanyReplyDto = accompanyReplyService.findById(request.accompanyReplyId) - val userSimpleDto = userService.findById(request.userId) + val userSimpleDto = userService.findSimpleById(request.userId) validateUpdate(request, accompanyReplyDto) val updated = accompanyReplyService.update( replyId = accompanyReplyDto.id, diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt index 2b206e8..940941b 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompanyreply/dto/AccompanyReplyResponseDto.kt @@ -1,6 +1,6 @@ package com.withaeng.api.applicationservice.accompanyreply.dto -import com.withaeng.api.applicationservice.user.dto.UserSimpleServiceResponse +import com.withaeng.api.applicationservice.user.dto.UserSimpleResponse import com.withaeng.api.applicationservice.user.dto.toSimpleResponse import com.withaeng.domain.accompanyreply.AccompanyReplyDto import com.withaeng.domain.accompanyreply.AccompanyReplyStatus @@ -9,7 +9,7 @@ import java.time.LocalDateTime data class AccompanyReplyResponse( val id: Long, - val author: UserSimpleServiceResponse, + val author: UserSimpleResponse, val accompanyId: Long, val parentId: Long? = null, val content: String?, diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/test/TestApplicationService.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/test/TestApplicationService.kt index b04ef71..72ffbef 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/test/TestApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/test/TestApplicationService.kt @@ -1,8 +1,8 @@ package com.withaeng.api.applicationservice.test -import com.withaeng.domain.user.UserService import com.withaeng.api.security.authentication.UserInfo import com.withaeng.api.security.jwt.JwtAgent +import com.withaeng.domain.user.UserService import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -10,11 +10,11 @@ import org.springframework.transaction.annotation.Transactional @Service class TestApplicationService( private val jwtAgent: JwtAgent, - private val userService: UserService + private val userService: UserService, ) { fun provideUserToken(userId: Long): String { - return jwtAgent.provide(UserInfo.from(userService.findById(userId))) + return jwtAgent.provide(UserInfo.from(userService.findSimpleById(userId))) } @Transactional diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/UserApplicationService.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/UserApplicationService.kt index db44611..ec7881c 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/UserApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/UserApplicationService.kt @@ -1,19 +1,37 @@ package com.withaeng.api.applicationservice.user import com.withaeng.api.applicationservice.user.dto.* +import com.withaeng.domain.accompany.AccompanyService import com.withaeng.domain.user.UserService import org.springframework.stereotype.Service @Service class UserApplicationService( private val userService: UserService, + private val accompanyService: AccompanyService, ) { - fun updateProfile(serviceRequest: UpdateProfileServiceRequest): UserSimpleServiceResponse { + fun getProfile(userId: Long): UserStatisticalProfileResponse { + val userDetail = userService.findDetailById(userId) + val profileCompletionPercentage = userService.getProfileCompletionPercentage(userId) + val accompanyCount = accompanyService.countByUserId(userId) + return UserStatisticalProfileResponse.of( + userDetail = userDetail, + profileCompletionPercentage = profileCompletionPercentage, + accompanyCount = accompanyCount, + ) + } + + fun getTravelPreference(userId: Long): UserTravelPreferenceResponse { + return userService.findDetailById(userId).travelPreference?.toServiceResponse() + ?: UserTravelPreferenceResponse() + } + + fun updateProfile(serviceRequest: UpdateProfileServiceRequest): UserSimpleResponse { return userService.updateProfile(serviceRequest.userId, serviceRequest.toCommand()).toSimpleResponse() } - fun updateTravelPreference(serviceRequest: UpdateTravelPreferenceServiceRequest): UserDetailServiceResponse { + fun updateTravelPreference(serviceRequest: UpdateTravelPreferenceServiceRequest): UserDetailResponse { return userService.updateTravelPreference(serviceRequest.userId, serviceRequest.toCommand()).toDetailResponse() } } diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceResponse.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceResponse.kt index f0f1021..4a8084f 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceResponse.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceResponse.kt @@ -1,38 +1,41 @@ package com.withaeng.api.applicationservice.user.dto import com.withaeng.domain.user.* -import com.withaeng.domain.user.dto.UserDetailsDto +import com.withaeng.domain.user.dto.UserDetailDto import com.withaeng.domain.user.dto.UserSimpleDto +import com.withaeng.domain.user.dto.UserTravelPreferenceDto import java.time.LocalDate -data class UserSimpleServiceResponse( +data class UserSimpleResponse( val id: Long, val email: String, val nickname: String, ) -fun UserSimpleDto.toSimpleResponse(): UserSimpleServiceResponse = UserSimpleServiceResponse( +fun UserSimpleDto.toSimpleResponse(): UserSimpleResponse = UserSimpleResponse( id = id, email = email, nickname = profile.nickname ) -data class UserDetailServiceResponse( +data class UserDetailResponse( val id: Long, + val createdDate: LocalDate, val email: String, val gender: Gender, val birth: LocalDate, - val profile: UserProfileServiceResponse, - val travelPreference: UserTravelPreferenceServiceResponse? = null, + val mannerScore: Double, + val profile: UserProfileResponse, + val travelPreference: UserTravelPreferenceResponse? = null, ) -data class UserProfileServiceResponse( +data class UserProfileResponse( val nickname: String, val introduction: String? = null, val profileImageUrl: String? = null, ) -data class UserTravelPreferenceServiceResponse( +data class UserTravelPreferenceResponse( val mbti: Set? = emptySet(), val preferTravelType: UserPreferTravelType? = null, val preferTravelThemes: Set = emptySet(), @@ -42,18 +45,20 @@ data class UserTravelPreferenceServiceResponse( val drinkingType: UserDrinkingType? = null, ) -fun UserDetailsDto.toDetailResponse(): UserDetailServiceResponse = UserDetailServiceResponse( +fun UserDetailDto.toDetailResponse(): UserDetailResponse = UserDetailResponse( id = id, + createdDate = createdDate, email = email, gender = gender, birth = birth, - profile = UserProfileServiceResponse( + mannerScore = mannerScore, + profile = UserProfileResponse( nickname = profile.nickname, introduction = profile.introduction, profileImageUrl = profile.profileImageUrl, ), travelPreference = travelPreference?.let { - UserTravelPreferenceServiceResponse( + UserTravelPreferenceResponse( mbti = it.mbti, preferTravelType = it.preferTravelType, preferTravelThemes = it.preferTravelThemes, @@ -64,3 +69,46 @@ fun UserDetailsDto.toDetailResponse(): UserDetailServiceResponse = UserDetailSer ) }, ) + +fun UserTravelPreferenceDto.toServiceResponse(): UserTravelPreferenceResponse = + UserTravelPreferenceResponse( + mbti = mbti, + preferTravelType = preferTravelType, + preferTravelThemes = preferTravelThemes, + consumeStyle = consumeStyle, + foodRestrictions = foodRestrictions, + smokingType = smokingType, + drinkingType = drinkingType + ) + +data class UserStatisticalProfileResponse( + val id: Long, + val nickname: String, + val introduction: String? = null, + val gender: Gender, + val birth: LocalDate, + val profileImageUrl: String? = null, + val profileCompletionPercentage: Int, + val mannerScore: Double, + val accompanyCount: Int, + val createdAt: LocalDate, +) { + companion object { + fun of( + userDetail: UserDetailDto, + profileCompletionPercentage: Int, + accompanyCount: Int, + ): UserStatisticalProfileResponse = UserStatisticalProfileResponse( + id = userDetail.id, + nickname = userDetail.profile.nickname, + introduction = userDetail.profile.introduction, + gender = userDetail.gender, + birth = userDetail.birth, + profileImageUrl = userDetail.profile.profileImageUrl, + profileCompletionPercentage = profileCompletionPercentage, + mannerScore = userDetail.mannerScore, + accompanyCount = accompanyCount, + createdAt = userDetail.createdDate, + ) + } +} diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/config/SecurityConfig.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/config/SecurityConfig.kt index 49a7988..dd6311c 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/config/SecurityConfig.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/config/SecurityConfig.kt @@ -1,24 +1,20 @@ package com.withaeng.api.config import com.fasterxml.jackson.databind.ObjectMapper -import com.withaeng.domain.user.UserRole -import com.withaeng.api.common.WhiteList.getWhiteListForSecurityConfig import com.withaeng.api.security.handler.HttpStatusAccessDeniedHandler import com.withaeng.api.security.handler.HttpStatusAuthenticationEntryPoint import com.withaeng.api.security.jwt.JwtAgent import com.withaeng.api.security.jwt.JwtFilter +import com.withaeng.domain.user.UserRole import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.http.HttpHeaders -import org.springframework.http.HttpMethod import org.springframework.security.config.annotation.web.builders.HttpSecurity import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity -import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder import org.springframework.security.crypto.password.PasswordEncoder import org.springframework.security.web.SecurityFilterChain import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter -import org.springframework.security.web.util.matcher.AntPathRequestMatcher import org.springframework.web.cors.CorsConfiguration import org.springframework.web.cors.CorsConfigurationSource import org.springframework.web.cors.UrlBasedCorsConfigurationSource @@ -50,14 +46,6 @@ class SecurityConfig(private val jwtAgent: JwtAgent, private val objectMapper: O .build() } - @Bean - fun webSecurityCustomizer(): WebSecurityCustomizer { - return WebSecurityCustomizer { - it.ignoring().requestMatchers(*getWhiteListForSecurityConfig().toTypedArray()) - .requestMatchers(AntPathRequestMatcher("/api/v1/**", HttpMethod.GET.name())) - } - } - @Bean fun corsConfigurationSource(): CorsConfigurationSource { val configuration = CorsConfiguration().apply { diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/UserMeController.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/UserMeController.kt index 5cc1574..fba349a 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/UserMeController.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/UserMeController.kt @@ -1,8 +1,10 @@ package com.withaeng.api.controller.user import com.withaeng.api.applicationservice.user.UserApplicationService -import com.withaeng.api.applicationservice.user.dto.UserDetailServiceResponse -import com.withaeng.api.applicationservice.user.dto.UserSimpleServiceResponse +import com.withaeng.api.applicationservice.user.dto.UserDetailResponse +import com.withaeng.api.applicationservice.user.dto.UserSimpleResponse +import com.withaeng.api.applicationservice.user.dto.UserStatisticalProfileResponse +import com.withaeng.api.applicationservice.user.dto.UserTravelPreferenceResponse import com.withaeng.api.common.ApiResponse import com.withaeng.api.controller.user.dto.UpdateProfileRequest import com.withaeng.api.controller.user.dto.UpdateTravelPreferenceRequest @@ -13,16 +15,41 @@ import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.security.SecurityRequirement import io.swagger.v3.oas.annotations.tags.Tag import jakarta.validation.Valid -import org.springframework.web.bind.annotation.PutMapping -import org.springframework.web.bind.annotation.RequestBody -import org.springframework.web.bind.annotation.RequestMapping -import org.springframework.web.bind.annotation.RestController +import org.springframework.web.bind.annotation.* @Tag(name = "User", description = "유저 정보 관리 API") @RestController @RequestMapping("/api/v1/user/me") class UserMeController(private val userApplicationService: UserApplicationService) { + @Operation( + summary = "Get Statistics", + description = "유저 통계 정보 조회 API", + security = [SecurityRequirement(name = "Authorization")] + ) + @GetMapping("/profile") + fun getProfile( + @GetAuth userInfo: UserInfo, + ): ApiResponse { + return ApiResponse.success( + userApplicationService.getProfile(userInfo.id) + ) + } + + @Operation( + summary = "Get User Detail", + description = "유저 상세 정보 조회 API", + security = [SecurityRequirement(name = "Authorization")] + ) + @GetMapping("/travel-preference") + fun getTravelPreference( + @GetAuth userInfo: UserInfo, + ): ApiResponse { + return ApiResponse.success( + userApplicationService.getTravelPreference(userInfo.id) + ) + } + @Operation( summary = "Update Profile", description = "프로필 업데이트 API", @@ -32,7 +59,7 @@ class UserMeController(private val userApplicationService: UserApplicationServic fun updateProfile( @GetAuth userInfo: UserInfo, @RequestBody @Valid request: UpdateProfileRequest, - ): ApiResponse { + ): ApiResponse { return ApiResponse.success( userApplicationService.updateProfile(request.toServiceRequest(userInfo.id)) ) @@ -47,7 +74,7 @@ class UserMeController(private val userApplicationService: UserApplicationServic fun updateTravelPreference( @GetAuth userInfo: UserInfo, @RequestBody @Valid request: UpdateTravelPreferenceRequest, - ): ApiResponse { + ): ApiResponse { return ApiResponse.success( userApplicationService.updateTravelPreference(request.toServiceRequest(userInfo.id)) ) diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepository.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepository.kt index fabf83b..97f44da 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepository.kt @@ -2,4 +2,7 @@ package com.withaeng.domain.accompany import org.springframework.data.jpa.repository.JpaRepository -interface AccompanyRepository : JpaRepository, AccompanyRepositoryCustom \ No newline at end of file +interface AccompanyRepository : JpaRepository, AccompanyRepositoryCustom { + + fun countByUserId(userId: Long): Int +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyService.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyService.kt index 98547f3..bc5c8e2 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyService.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyService.kt @@ -11,7 +11,7 @@ import org.springframework.transaction.annotation.Transactional @Transactional(readOnly = true) class AccompanyService( private val accompanyRepository: AccompanyRepository, - private val tagRepository: TagRepository + private val tagRepository: TagRepository, ) { @Transactional @@ -48,16 +48,20 @@ class AccompanyService( accompany.increaseViewCount() } + fun findAll(): List { + return accompanyRepository.findAll().map { it.toDto() } + } + + fun countByUserId(userId: Long): Int { + return accompanyRepository.countByUserId(userId) + } + private fun findById(accompanyId: Long) = accompanyRepository.findByIdOrNull(accompanyId) ?: throw WithaengException.of( type = WithaengExceptionType.NOT_EXIST, message = NOT_EXIST_MESSAGE ) - fun findAll(): List { - return accompanyRepository.findAll().map { it.toDto() } - } - private fun filterValidTagIds(tagIds: Set?): Set { if (tagIds == null) return emptySet() return tagRepository.findAllById(tagIds) diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/User.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/User.kt index e582d6a..e4dc887 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/User.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/User.kt @@ -21,6 +21,9 @@ class User( @Column(name = "gender", nullable = false) val gender: Gender, + @Column(name = "manner_score", nullable = false) + var mannerScore: Double = 36.5, + @Embedded val profile: UserProfile, diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserService.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserService.kt index 774879c..387a536 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserService.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserService.kt @@ -6,20 +6,55 @@ import com.withaeng.domain.user.dto.* import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional +import kotlin.reflect.full.declaredMemberProperties @Service class UserService(private val userRepository: UserRepository) { @Transactional(readOnly = true) - fun findById(id: Long): UserSimpleDto { + fun findSimpleById(id: Long): UserSimpleDto { return userRepository.findByIdOrNull(id).getOrThrow().toSimpleDto() } + @Transactional(readOnly = true) + fun findDetailById(id: Long): UserDetailDto { + return userRepository.findByIdOrNull(id).getOrThrow().toDetailDto() + } + @Transactional(readOnly = true) fun findByEmailOrNull(email: String): UserSimpleDto? { return userRepository.findByEmail(email)?.toSimpleDto() } + @Transactional(readOnly = true) + fun getProfileCompletionPercentage(userId: Long): Int { + val user = userRepository.findByIdOrNull(userId).getOrThrow() + val profile = user.profile + val travelPreference = user.travelPreference + + val profileFields = UserProfile::class.declaredMemberProperties.filter { it.name != "user" } + val travelPreferenceFields = UserTravelPreference::class.declaredMemberProperties.filter { it.name != "user" } + + val totalFields = profileFields.size + travelPreferenceFields.size + var filledFields = 0 + + profileFields.forEach { field -> + if (field.get(profile) != null && field.get(profile) != "") { + filledFields++ + } + } + + travelPreferenceFields.forEach { field -> + if (travelPreference != null && field.get(travelPreference) != null + && field.get(travelPreference) != emptySet() + ) { + filledFields++ + } + } + + return ((filledFields.toDouble() / totalFields) * 100).toInt() + } + @Transactional fun create(createUserCommand: CreateUserCommand): UserSimpleDto { return userRepository.save( @@ -43,7 +78,7 @@ class UserService(private val userRepository: UserRepository) { } @Transactional - fun updateTravelPreference(userId: Long, command: UpdateTravelPreferenceCommand): UserDetailsDto { + fun updateTravelPreference(userId: Long, command: UpdateTravelPreferenceCommand): UserDetailDto { val user = userRepository.findByIdOrNull(userId).getOrThrow() user.travelPreference = user.travelPreference ?: UserTravelPreference.create(user) user.travelPreference?.mbti = command.mbti ?: emptySet() @@ -53,7 +88,7 @@ class UserService(private val userRepository: UserRepository) { user.travelPreference?.foodRestrictions = command.foodRestrictions ?: emptySet() user.travelPreference?.smokingType = command.smokingType user.travelPreference?.drinkingType = command.drinkingType - return user.toDetailsDto() + return user.toDetailDto() } @Transactional diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/dto/UserDto.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/dto/UserDto.kt index 3ca74ad..3735c17 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/dto/UserDto.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/dto/UserDto.kt @@ -9,6 +9,7 @@ data class UserSimpleDto( val password: String, val birth: LocalDate, val gender: Gender, + val mannerScore: Double, val profile: UserProfileDto, val roles: Set, ) @@ -19,6 +20,7 @@ fun User.toSimpleDto(): UserSimpleDto = UserSimpleDto( password = password, birth = birth, gender = gender, + mannerScore = mannerScore, profile = UserProfileDto( nickname = profile.nickname, introduction = profile.introduction, @@ -27,12 +29,14 @@ fun User.toSimpleDto(): UserSimpleDto = UserSimpleDto( roles = roles, ) -data class UserDetailsDto( +data class UserDetailDto( val id: Long, + val createdDate: LocalDate, val email: String, val password: String, val birth: LocalDate, val gender: Gender, + val mannerScore: Double, val profile: UserProfileDto, val travelPreference: UserTravelPreferenceDto? = null, val roles: Set, @@ -54,12 +58,14 @@ data class UserTravelPreferenceDto( val drinkingType: UserDrinkingType? = null, ) -fun User.toDetailsDto(): UserDetailsDto = UserDetailsDto( +fun User.toDetailDto(): UserDetailDto = UserDetailDto( id = id, + createdDate = createdAt.toLocalDate(), email = email, password = password, birth = birth, gender = gender, + mannerScore = mannerScore, profile = UserProfileDto( nickname = profile.nickname, introduction = profile.introduction, From 780cf11eb5fb67e1999509abdc01e16d034ff2d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Wed, 11 Sep 2024 02:11:34 +0900 Subject: [PATCH 127/174] =?UTF-8?q?fix:=20Swagger=20ui=20=EC=A0=91?= =?UTF-8?q?=EA=B7=BC=20=EC=9E=AC=ED=97=88=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/withaeng/api/config/SecurityConfig.kt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/config/SecurityConfig.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/config/SecurityConfig.kt index dd6311c..797bf65 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/config/SecurityConfig.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/config/SecurityConfig.kt @@ -1,6 +1,7 @@ package com.withaeng.api.config import com.fasterxml.jackson.databind.ObjectMapper +import com.withaeng.api.common.WhiteList.getWhiteListForSecurityConfig import com.withaeng.api.security.handler.HttpStatusAccessDeniedHandler import com.withaeng.api.security.handler.HttpStatusAuthenticationEntryPoint import com.withaeng.api.security.jwt.JwtAgent @@ -9,12 +10,15 @@ import com.withaeng.domain.user.UserRole import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.http.HttpHeaders +import org.springframework.http.HttpMethod import org.springframework.security.config.annotation.web.builders.HttpSecurity import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity +import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder import org.springframework.security.crypto.password.PasswordEncoder import org.springframework.security.web.SecurityFilterChain import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter +import org.springframework.security.web.util.matcher.AntPathRequestMatcher import org.springframework.web.cors.CorsConfiguration import org.springframework.web.cors.CorsConfigurationSource import org.springframework.web.cors.UrlBasedCorsConfigurationSource @@ -46,6 +50,14 @@ class SecurityConfig(private val jwtAgent: JwtAgent, private val objectMapper: O .build() } + @Bean + fun webSecurityCustomizer(): WebSecurityCustomizer { + return WebSecurityCustomizer { + it.ignoring().requestMatchers(*getWhiteListForSecurityConfig().toTypedArray()) + .requestMatchers(AntPathRequestMatcher("/swagger-ui", HttpMethod.GET.name())) + } + } + @Bean fun corsConfigurationSource(): CorsConfigurationSource { val configuration = CorsConfiguration().apply { From 0ef36653e6130007533bcda233126208c75b6b34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Wed, 11 Sep 2024 02:21:57 +0900 Subject: [PATCH 128/174] =?UTF-8?q?fix:=20auth=20api=20=EC=A0=91=EA=B7=BC?= =?UTF-8?q?=20=ED=97=88=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/kotlin/com/withaeng/api/config/SecurityConfig.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/config/SecurityConfig.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/config/SecurityConfig.kt index 797bf65..082136e 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/config/SecurityConfig.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/config/SecurityConfig.kt @@ -40,7 +40,8 @@ class SecurityConfig(private val jwtAgent: JwtAgent, private val objectMapper: O .httpBasic { it.disable() } .formLogin { it.disable() } .authorizeHttpRequests { - it.anyRequest().hasAnyRole(UserRole.USER.getActualRoleName(), UserRole.ADMIN.getActualRoleName()) + it.requestMatchers("/api/v1/auth/**").permitAll() + .anyRequest().hasAnyRole(UserRole.USER.getActualRoleName(), UserRole.ADMIN.getActualRoleName()) } .addFilterBefore(JwtFilter(jwtAgent, objectMapper), UsernamePasswordAuthenticationFilter::class.java) .exceptionHandling { From 200cd13ac76190a50e953eb3f24051164535012f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Sat, 14 Sep 2024 01:08:31 +0900 Subject: [PATCH 129/174] =?UTF-8?q?Fix:=20Event=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../accompany/AccompanyApplicationService.kt | 9 ++------ .../accompany/AccompanyEventListener.kt | 20 ------------------ .../kotlin/com/withaeng/api/common/Events.kt | 15 ------------- .../com/withaeng/api/config/EventConfig.kt | 21 ------------------- .../AccompanyIncrementViewCountEvent.kt | 5 ----- .../domain/accompany/AccompanyService.kt | 12 ++++++----- 6 files changed, 9 insertions(+), 73 deletions(-) delete mode 100644 withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyEventListener.kt delete mode 100644 withaeng-api/src/main/kotlin/com/withaeng/api/common/Events.kt delete mode 100644 withaeng-api/src/main/kotlin/com/withaeng/api/config/EventConfig.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyIncrementViewCountEvent.kt diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt index 587cff3..a4b7fba 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt @@ -1,27 +1,21 @@ package com.withaeng.api.applicationservice.accompany import com.withaeng.api.applicationservice.accompany.dto.* -import com.withaeng.api.common.Events -import com.withaeng.domain.accompany.AccompanyIncrementViewCountEvent import com.withaeng.domain.accompany.AccompanyService import com.withaeng.domain.accompanylike.AccompanyLikeService import org.springframework.stereotype.Service -import org.springframework.transaction.annotation.Transactional @Service -@Transactional(readOnly = true) class AccompanyApplicationService( private val accompanyService: AccompanyService, private val accompanyLikeService: AccompanyLikeService, ) { - @Transactional fun create(request: CreateAccompanyServiceRequest): AccompanyResponse { return accompanyService.create(request.toDomainDto()) .toAccompanyResponse(0L) } - @Transactional fun update(request: UpdateAccompanyServiceRequest): AccompanyResponse { val accompanyDto = accompanyService.update(request.toDomainDto()) val likeCount = countAccompanyLikeByAccompanyId(request.accompanyId) @@ -35,13 +29,14 @@ class AccompanyApplicationService( if (isHost(userId, accompanyDto.userId)) { // TODO : Host인 경우 승인보류 유저 목록 추가 필요 + println("호스트임") } return accompanyDto } private fun increaseViewCount(accompanyId: Long) { - Events.raise(AccompanyIncrementViewCountEvent(accompanyId)) + accompanyService.increaseViewCount(accompanyId) } private fun isHost(loginUserId: Long?, userId: Long) = diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyEventListener.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyEventListener.kt deleted file mode 100644 index 20377c5..0000000 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyEventListener.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.withaeng.api.applicationservice.accompany - -import com.withaeng.domain.accompany.AccompanyIncrementViewCountEvent -import com.withaeng.domain.accompany.AccompanyService -import org.springframework.context.event.EventListener -import org.springframework.scheduling.annotation.Async -import org.springframework.stereotype.Component -import org.springframework.transaction.annotation.Transactional - -@Component -class AccompanyEventListener( - private val accompanyService: AccompanyService -) { - @EventListener - @Async - @Transactional - fun incrementViewCountEventListener(event: AccompanyIncrementViewCountEvent) { - event.accompanyId?.let { accompanyService.increaseViewCount(it) } - } -} \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/common/Events.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/common/Events.kt deleted file mode 100644 index 8212c9f..0000000 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/common/Events.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.withaeng.api.common - -import org.springframework.context.ApplicationEventPublisher - -object Events { - private var eventPublisher: ApplicationEventPublisher? = null - - fun setPublisher(applicationEventPublisher: ApplicationEventPublisher) { - eventPublisher = applicationEventPublisher - } - - fun raise(event: Any) { - eventPublisher?.publishEvent(event) - } -} \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/config/EventConfig.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/config/EventConfig.kt deleted file mode 100644 index 1ff52ba..0000000 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/config/EventConfig.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.withaeng.api.config - -import com.withaeng.api.common.Events -import org.springframework.beans.factory.InitializingBean -import org.springframework.context.ApplicationEventPublisher -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration - -@Configuration -class EventConfig( - private val publisher: ApplicationEventPublisher -) { - - @Bean - fun eventInitializer(): InitializingBean { - return InitializingBean { - Events.setPublisher(publisher) - } - } - -} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyIncrementViewCountEvent.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyIncrementViewCountEvent.kt deleted file mode 100644 index 1e0ad59..0000000 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyIncrementViewCountEvent.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.withaeng.domain.accompany - -class AccompanyIncrementViewCountEvent( - val accompanyId: Long? = null -) \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyService.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyService.kt index bc5c8e2..9dcd8fd 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyService.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyService.kt @@ -8,12 +8,15 @@ import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @Service -@Transactional(readOnly = true) class AccompanyService( private val accompanyRepository: AccompanyRepository, private val tagRepository: TagRepository, ) { + companion object { + private const val NOT_EXIST_MESSAGE = "해당하는 동행을 찾을 수 없습니다." + } + @Transactional fun create(params: CreateAccompanyDto): AccompanyDto { val actualTagIds = filterValidTagIds(params.tagIds) @@ -34,6 +37,7 @@ class AccompanyService( return accompany.toDto() } + @Transactional(readOnly = true) fun detail(accompanyId: Long): FindAccompanyDto { return accompanyRepository.findAccompanyDetail(accompanyId) ?: throw WithaengException.of( @@ -48,10 +52,12 @@ class AccompanyService( accompany.increaseViewCount() } + @Transactional(readOnly = true) fun findAll(): List { return accompanyRepository.findAll().map { it.toDto() } } + @Transactional(readOnly = true) fun countByUserId(userId: Long): Int { return accompanyRepository.countByUserId(userId) } @@ -68,8 +74,4 @@ class AccompanyService( .map { it.id } .toSet() } - - companion object { - private const val NOT_EXIST_MESSAGE = "해당하는 동행을 찾을 수 없습니다." - } } \ No newline at end of file From 68f4729f6d809ce6880b0655adebab236111a313 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Sun, 15 Sep 2024 00:53:32 +0900 Subject: [PATCH 130/174] =?UTF-8?q?chore:=20=ED=99=98=EA=B2=BD=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC=20=EB=B0=8F=20=ED=99=98=EA=B2=BD=EB=B3=80=EC=88=98=20?= =?UTF-8?q?=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 + .../src/main/resources/application-local.yml | 8 --- .../src/main/resources/application.yml | 48 +++++++++++---- .../main/resources/application-domain-dev.yml | 12 ---- .../resources/application-domain-local.yml | 17 ------ .../src/main/resources/application-domain.yml | 58 ++++++++++++++++--- .../main/resources/application-external.yml | 23 +++++--- 7 files changed, 102 insertions(+), 67 deletions(-) delete mode 100644 withaeng-api/src/main/resources/application-local.yml delete mode 100644 withaeng-domain/src/main/resources/application-domain-dev.yml delete mode 100644 withaeng-domain/src/main/resources/application-domain-local.yml diff --git a/.gitignore b/.gitignore index 5a979af..ad17a53 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +*-local.properties +*-local.yaml +*-local.yml HELP.md .gradle build/ diff --git a/withaeng-api/src/main/resources/application-local.yml b/withaeng-api/src/main/resources/application-local.yml deleted file mode 100644 index a1ee886..0000000 --- a/withaeng-api/src/main/resources/application-local.yml +++ /dev/null @@ -1,8 +0,0 @@ -spring: - config: - activate: - on-profile: local - -logging: - level: - root: debug \ No newline at end of file diff --git a/withaeng-api/src/main/resources/application.yml b/withaeng-api/src/main/resources/application.yml index f3288c0..244a66c 100644 --- a/withaeng-api/src/main/resources/application.yml +++ b/withaeng-api/src/main/resources/application.yml @@ -1,12 +1,21 @@ spring: - profiles: - default: dev - config: - import: - - classpath:/application-domain.yml - - classpath:/application-external.yml - -# Swagger docs + application.name: withaeng-api + profiles.default: local + config.import: + - application-domain.yml + - application-external.yml + web.resources.add-mappings: false + +witheang: + auth: + jwt-issuer: ${JWT_ISSUER} + jwt-secret-key: ${JWT_SECRET_KEY} + +jasypt.encryptor.password: ${JASYPT_PASSWORD} + +--- +spring.config.activate.on-profile: local + springdoc: swagger-ui: path: /api-docs @@ -15,7 +24,22 @@ springdoc: groups: enabled: true -witheang: - auth: - jwt-secret-key: ENC(1t2RYsNu8JCGgZjC5HuE9t9690mWUiygMhKfUQIn3ZpVlSYI0WvRPnQswh3Uti3gBoDqJ4Zk3moN6wWswWQC7g+IFiEDUvqjTLzhfJrl9A0TIW0MOY0kd+vnVu0sernJ) - jwt-issuer: https://github.com/withaeng/withaeng-backend \ No newline at end of file +--- +spring.config.activate.on-profile: dev + +springdoc: + swagger-ui: + path: /api-docs + operations-sorter: alpha + api-docs: + groups: + enabled: true + +--- +spring.config.activate.on-profile: prod + +springdoc: + swagger-ui: + enabled: false + api-docs: + enabled: false diff --git a/withaeng-domain/src/main/resources/application-domain-dev.yml b/withaeng-domain/src/main/resources/application-domain-dev.yml deleted file mode 100644 index 9d5fc86..0000000 --- a/withaeng-domain/src/main/resources/application-domain-dev.yml +++ /dev/null @@ -1,12 +0,0 @@ -spring: - config: - activate: - on-profile: dev - jpa: - hibernate: - ddl-auto: none - properties: - hibernate: - show_sql: false - format_sql: false - use_sql_comments: false \ No newline at end of file diff --git a/withaeng-domain/src/main/resources/application-domain-local.yml b/withaeng-domain/src/main/resources/application-domain-local.yml deleted file mode 100644 index 1e2b26a..0000000 --- a/withaeng-domain/src/main/resources/application-domain-local.yml +++ /dev/null @@ -1,17 +0,0 @@ -spring: - config: - activate: - on-profile: local - datasource: - driver-class-name: com.mysql.cj.jdbc.Driver - url: ENC(lFITsL+l7aOSMUY3hRT3aR4X0GV+yqIJfYMyXaMajbZZJSW+Lv5MTrbP5Cwa8XAUxGpH7A9GxRNAZtrDhf6V4yXkD6gf3RUYWsPp77Ieguo=) - username: ENC(s1UggVxVWnWC0WqrTpmXaLw+QCpZmkuj2kvSQp+zt2vwKLbRH6WDAZKYUR75DqsR) - password: ENC(HT2z+x9LrfoHTmTTCYLkx7cO0ru9Gcbh+YGnP/0MWC1BpBwQtPfWue+zQx5RPQg8) - jpa: - hibernate: - ddl-auto: none - properties: - hibernate: - show_sql: true - format_sql: true - use_sql_comments: true \ No newline at end of file diff --git a/withaeng-domain/src/main/resources/application-domain.yml b/withaeng-domain/src/main/resources/application-domain.yml index 36c51bf..fbe0693 100644 --- a/withaeng-domain/src/main/resources/application-domain.yml +++ b/withaeng-domain/src/main/resources/application-domain.yml @@ -1,16 +1,56 @@ spring: - profiles: - default: dev datasource: - driver-class-name: com.mysql.cj.jdbc.Driver - url: ENC(hrN+eQ4p84E3NW0vTIIRfhlAvKoNxPvYFvCAN2O9CyD7UZpSDS2dI9fEsBaHp6gftj+l4UOIBo5BHRIo2BQiC403lDFKj8I5ySiIxdvhY0Pp7fheX5J9DvJD5elcnAthagf+7EFdQVuQ0xdSODL7LceQs5DCSwESYThyL9HLPVM=) - username: ENC(FTbbdqVBbcTrUysSwbf/BwFbE0HhgdyXT+Z0uC0xZfLyuftv/9ceA4wQdOp70vMT) - password: ENC(7+z+f1IVvS1HcBCtH8hYpUMbEM6mcHVBw93co3jNIhp8EuXicXkee/MlqY1DkJq2) + hikari: + data-source-properties: + rewriteBatchedStatements: true + jpa: + open-in-view: false + properties: + hibernate.default_batch_fetch_size: 100 + +--- +spring.config.activate.on-profile: local + +spring: + datasource: + driverClassName: org.h2.Driver + url: jdbc:h2:mem:withaeng;MODE=MySQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE + username: sa + password: + h2: + console: + enabled: true jpa: hibernate: ddl-auto: create properties: hibernate: - show_sql: false - format_sql: false - use_sql_comments: false \ No newline at end of file + show_sql: true + format_sql: true + use_sql_comments: true + +--- +spring.config.activate.on-profile: dev + +spring: + datasource: + driverClassName: ${DATABASE_DRIVER} + url: ${DATABASE_URL} + username: ${DATABASE_USERNAME} + password: ${DATABASE_PASSWORD} + jpa: + hibernate: + ddl-auto: update + +--- +spring.config.activate.on-profile: prod + +spring: + datasource: + driverClassName: ${DATABASE_DRIVER} + url: ${DATABASE_URL} + username: ${DATABASE_USERNAME} + password: ${DATABASE_PASSWORD} + jpa: + hibernate: + ddl-auto: none \ No newline at end of file diff --git a/withaeng-external/src/main/resources/application-external.yml b/withaeng-external/src/main/resources/application-external.yml index d951f5e..85e84cf 100644 --- a/withaeng-external/src/main/resources/application-external.yml +++ b/withaeng-external/src/main/resources/application-external.yml @@ -1,17 +1,22 @@ -spring: - thymeleaf: - prefix: classpath:/templates/ - suffix: .html - mode: HTML - encoding: UTF-8 - content-type: text/html - cache: false cloud: aws: - credentials: + credentials: # TODO environment variable로 변경 access-key: ENC(tje4pV1gRGOh5N5ig8TND1sc3NyDGe9KDIXHMiY5UgBospTEAk2pjcxphPMvoOiNshPej16XCkj/RDP8ywREdQ==) secret-key: ENC(5RTBAVDrwVdRLBQ/vrQrrE2f9K/68acjDiHgg9hc9J/8K3TZoejmca7Nagyz1exQ8XEndRKXl4XgxyXljZvykgP/56Ab7eAKuXXplny0zoQ=) region: static: ENC(1OX/+Td6WwTc/zbC8t/DVgDHX24lMOV+ZQbza/IstkTM8E3UKwloe8EaH97FKpzT) ses: from: ENC(S6WIEUO3m5JKHw7PrhpgkAvQjd1LzwwLRXEu2I9yUtzErtBEDk6EEt28Ltzypo8/fZi7Ua8VkHjWh9498FT5DA==) + +--- +spring.config.activate.on-profile: local + +spring: + thymeleaf: + cache: false + +--- +spring.config.activate.on-profile: dev + +--- +spring.config.activate.on-profile: prod \ No newline at end of file From fce444e405c4b2fc594daba74ca26bee9c7d94a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Sun, 15 Sep 2024 02:09:17 +0900 Subject: [PATCH 131/174] =?UTF-8?q?Fix:=20permitAllGet=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/withaeng/api/config/SecurityConfig.kt | 21 +++++++++----- .../HttpStatusAuthenticationEntryPoint.kt | 27 +++++++++++++++-- .../withaeng/api/security/jwt/JwtFilter.kt | 29 +++++++------------ 3 files changed, 47 insertions(+), 30 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/config/SecurityConfig.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/config/SecurityConfig.kt index 082136e..5d73181 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/config/SecurityConfig.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/config/SecurityConfig.kt @@ -1,6 +1,5 @@ package com.withaeng.api.config -import com.fasterxml.jackson.databind.ObjectMapper import com.withaeng.api.common.WhiteList.getWhiteListForSecurityConfig import com.withaeng.api.security.handler.HttpStatusAccessDeniedHandler import com.withaeng.api.security.handler.HttpStatusAuthenticationEntryPoint @@ -25,7 +24,17 @@ import org.springframework.web.cors.UrlBasedCorsConfigurationSource @Configuration @EnableWebSecurity -class SecurityConfig(private val jwtAgent: JwtAgent, private val objectMapper: ObjectMapper) { +class SecurityConfig( + private val jwtAgent: JwtAgent, +) { + + companion object { + private const val MAX_CORS_EXPIRE_SECONDS = 3600L + private val PERMIT_ALL_GET = arrayOf( + "/api/v1/accompany/**", + "/api/v1/auth/**", + ) + } @Bean fun passwordEncoder(): PasswordEncoder { @@ -40,10 +49,10 @@ class SecurityConfig(private val jwtAgent: JwtAgent, private val objectMapper: O .httpBasic { it.disable() } .formLogin { it.disable() } .authorizeHttpRequests { - it.requestMatchers("/api/v1/auth/**").permitAll() + it.requestMatchers(HttpMethod.GET, *PERMIT_ALL_GET).permitAll() .anyRequest().hasAnyRole(UserRole.USER.getActualRoleName(), UserRole.ADMIN.getActualRoleName()) } - .addFilterBefore(JwtFilter(jwtAgent, objectMapper), UsernamePasswordAuthenticationFilter::class.java) + .addFilterBefore(JwtFilter(jwtAgent), UsernamePasswordAuthenticationFilter::class.java) .exceptionHandling { it.authenticationEntryPoint(HttpStatusAuthenticationEntryPoint()) it.accessDeniedHandler(HttpStatusAccessDeniedHandler()) @@ -73,8 +82,4 @@ class SecurityConfig(private val jwtAgent: JwtAgent, private val objectMapper: O registerCorsConfiguration("api/v1/**", configuration) } } - - companion object { - private const val MAX_CORS_EXPIRE_SECONDS = 3600L - } } \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/security/handler/HttpStatusAuthenticationEntryPoint.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/security/handler/HttpStatusAuthenticationEntryPoint.kt index 41168bd..c1864ff 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/security/handler/HttpStatusAuthenticationEntryPoint.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/security/handler/HttpStatusAuthenticationEntryPoint.kt @@ -1,21 +1,42 @@ package com.withaeng.api.security.handler +import com.fasterxml.jackson.databind.ObjectMapper +import com.withaeng.api.common.ApiResponse +import com.withaeng.common.exception.WithaengExceptionType import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletResponse import org.slf4j.Logger import org.slf4j.LoggerFactory -import org.springframework.http.HttpStatus +import org.springframework.http.MediaType import org.springframework.security.core.AuthenticationException import org.springframework.security.web.AuthenticationEntryPoint class HttpStatusAuthenticationEntryPoint : AuthenticationEntryPoint { private val log: Logger = LoggerFactory.getLogger(HttpStatusAuthenticationEntryPoint::class.java) + private val objectMapper = ObjectMapper() + + companion object { + private const val ATTRIBUTE = "token_exception_message" + } override fun commence( request: HttpServletRequest, response: HttpServletResponse, - authException: AuthenticationException + authException: AuthenticationException, ) { log.debug("Not Authenticated: ${authException.message}") - response.status = HttpStatus.UNAUTHORIZED.value() + val attribute = request.getAttribute(ATTRIBUTE) as String + + responseBuilder(response, attribute) + } + + private fun responseBuilder(response: HttpServletResponse, exceptionMessage: String) { + response.contentType = MediaType.APPLICATION_JSON_VALUE + response.characterEncoding = Charsets.UTF_8.name() + response.status = HttpServletResponse.SC_UNAUTHORIZED + response.writer.print( + objectMapper.writeValueAsString( + ApiResponse.fail(WithaengExceptionType.AUTHENTICATION_FAILURE, exceptionMessage) + ) + ) } } \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/security/jwt/JwtFilter.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/security/jwt/JwtFilter.kt index ad69195..6bd6300 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/security/jwt/JwtFilter.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/security/jwt/JwtFilter.kt @@ -1,7 +1,5 @@ package com.withaeng.api.security.jwt -import com.fasterxml.jackson.databind.ObjectMapper -import com.withaeng.api.common.ApiResponse import com.withaeng.api.common.Constants.Authentication.BEARER_TYPE import com.withaeng.api.security.authentication.JwtAuthentication import com.withaeng.common.exception.WithaengException @@ -12,37 +10,34 @@ import jakarta.servlet.http.HttpServletResponse import org.slf4j.Logger import org.slf4j.LoggerFactory import org.springframework.http.HttpHeaders -import org.springframework.http.HttpStatus -import org.springframework.http.MediaType import org.springframework.security.authentication.BadCredentialsException import org.springframework.security.core.context.SecurityContextHolder import org.springframework.web.filter.OncePerRequestFilter class JwtFilter( private val jwtAgent: JwtAgent, - private val objectMapper: ObjectMapper ) : OncePerRequestFilter() { private val log: Logger = LoggerFactory.getLogger(JwtFilter::class.java) + companion object { + private const val AUTH_PROVIDER_SPLIT_DELIMITER: String = " " + private const val ATTRIBUTE = "token_exception_message" + } + override fun doFilterInternal( request: HttpServletRequest, response: HttpServletResponse, - filterChain: FilterChain + filterChain: FilterChain, ) { log.debug("JWT Filter doFilterInternal()") - runCatching { + try { setAuthenticationFromToken(request) - }.onFailure { exception -> + } catch (exception: Exception) { log.debug("Authentication Failed: Authorization value=${request.getAuthorization()}, Message=${exception.message}") SecurityContextHolder.clearContext() - response.run { - status = HttpStatus.UNAUTHORIZED.value() - addHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - val failResponse = ApiResponse.fail(WithaengExceptionType.AUTHENTICATION_FAILURE, exception.message) - writer.write(objectMapper.writeValueAsString(failResponse)) - } - }.onSuccess { + request.setAttribute(ATTRIBUTE, exception.message) + } finally { filterChain.doFilter(request, response) } } @@ -67,8 +62,4 @@ class JwtFilter( } private fun HttpServletRequest.getAuthorization(): String? = getHeader(HttpHeaders.AUTHORIZATION) - - companion object { - private const val AUTH_PROVIDER_SPLIT_DELIMITER: String = " " - } } \ No newline at end of file From b4340a9f1e650a580b69a70c3ac1756b147a3a82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Sun, 15 Sep 2024 02:05:29 +0900 Subject: [PATCH 132/174] =?UTF-8?q?chore:=20=EB=B0=B0=ED=8F=AC=EC=8B=9C=20?= =?UTF-8?q?docker=20&=20github=20environments=20secret=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/cd.yml | 75 ++++++++++++++++++++++++--------- withaeng-api/Dockerfile | 5 +++ withaeng-api/docker-compose.yml | 17 ++++++++ 3 files changed, 76 insertions(+), 21 deletions(-) create mode 100644 withaeng-api/Dockerfile create mode 100644 withaeng-api/docker-compose.yml diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 8bc27ab..08154f6 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -2,15 +2,23 @@ name: Withaeng CD with Gradle, Github Actions on: push: - branches: [ "develop" ] + branches: [ "develop" ] # todo: main branch로 변경 jobs: build: runs-on: ubuntu-latest + environment: prod + steps: - name: 체크아웃 uses: actions/checkout@v3 + - name: JDK 17 설치 + uses: actions/setup-java@v3 + with: + java-version: 17 + distribution: temurin + - name: Gradle 캐싱 uses: actions/cache@v3 with: @@ -21,13 +29,7 @@ jobs: restore-keys: | ${{ runner.os }}-gradle- - - name: JDK 17 설치 - uses: actions/setup-java@v3 - with: - java-version: 17 - distribution: adopt - - - name: 빌드 권한 부여 + - name: gradlew 실행 권한 부여 run: chmod +x ./gradlew shell: bash @@ -35,23 +37,54 @@ jobs: run: ./gradlew clean build shell: bash - - name: Jar 파일 생성 - run: ./gradlew bootJar + - name: 운영서버 디렉토리 정리 + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.SERVER_HOST }} + username: ${{ secrets.SERVER_USERNAME }} + key: ${{ secrets.SERVER_KEY }} + script: sudo rm -rf /tmp/withaeng - - name: API 빌드 파일 복사 + - name: 배포 관련 파일 전송 uses: appleboy/scp-action@master with: - host: ${{ secrets.EC2_HOST }} - username: ${{ secrets.EC2_USERNAME }} - key: ${{ secrets.EC2_KEY }} - source: "withaeng-api/build/libs/*.jar" - target: "/home/ubuntu/remote" + host: ${{ secrets.SERVER_HOST }} + username: ${{ secrets.SERVER_USERNAME }} + key: ${{ secrets.SERVER_KEY }} + source: | + withaeng-api/Dockerfile + withaeng-api/docker-compose.yml + target: /tmp/withaeng - - name: API EC2 인스턴스 접속 및 애플리케이션 실행 + - name: 빌드 파일 전송 + uses: appleboy/scp-action@master + with: + host: ${{ secrets.SERVER_HOST }} + username: ${{ secrets.SERVER_USERNAME }} + key: ${{ secrets.SERVER_KEY }} + source: withaeng-api/build/libs/*.jar + target: /tmp/withaeng/build/libs + + deploy: + needs: build + runs-on: ubuntu-latest + environment: prod + + steps: + - name: 운영서버 애플리케이션 실행 uses: appleboy/ssh-action@master with: - host: ${{ secrets.EC2_HOST }} - username: ${{ secrets.EC2_USERNAME }} - key: ${{ secrets.EC2_KEY }} + host: ${{ secrets.SERVER_HOST }} + username: ${{ secrets.SERVER_USERNAME }} + key: ${{ secrets.SERVER_SSH_KEY }} + envs: + SPRING_PROFILES_ACTIVE=prod + DATABASE_DRIVER=${{ secrets.DATABASE_DRIVER }} + DATABASE_URL=${{ secrets.DATABASE_URL }} + DATABASE_USERNAME=${{ secrets.DATABASE_USERNAME }} + DATABASE_PASSWORD=${{ secrets.DATABASE_PASSWORD }} + JWT_ISSUER=${{ secrets.JWT_ISSUER }} + JWT_SECRET_KEY=${{ secrets.JWT_SECRET_KEY }} + JASYPT_PASSWORD=${{ secrets.JASYPT_PASSWORD }} script: | - sudo /home/ubuntu/remote/deploy.sh + sudo docker compose -f /tmp/withaeng/docker-compose.yml up -d \ No newline at end of file diff --git a/withaeng-api/Dockerfile b/withaeng-api/Dockerfile new file mode 100644 index 0000000..337d1e9 --- /dev/null +++ b/withaeng-api/Dockerfile @@ -0,0 +1,5 @@ +FROM eclipse-temurin:17-jre-alpine +ENV TZ=Asia/Seoul +ENV JAVA_OPTS="-Djava.net.preferIPv4Stack=true" +COPY build/libs/*.jar app.jar +ENTRYPOINT ["java", "-jar", "/app.jar"] diff --git a/withaeng-api/docker-compose.yml b/withaeng-api/docker-compose.yml new file mode 100644 index 0000000..1260c92 --- /dev/null +++ b/withaeng-api/docker-compose.yml @@ -0,0 +1,17 @@ +services: + withaeng-api: + build: + context: . + dockerfile: Dockerfile + container_name: withaeng-api + ports: + - "8080:8080" + environment: + SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE} + DATABASE_DRIVER: ${DATABASE_DRIVER} + DATABASE_URL: ${DATABASE_URL} + DATABASE_USERNAME: ${DATABASE_USERNAME} + DATABASE_PASSWORD: ${DATABASE_PASSWORD} + JWT_ISSUER: ${JWT_ISSUER} + JWT_SECRET_KEY: ${JWT_SECRET_KEY} + JASYPT_PASSWORD: ${JASYPT_PASSWORD} From 0bf570983bc8708740ddd8bfee12c7681e3c85af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Sun, 15 Sep 2024 03:24:29 +0900 Subject: [PATCH 133/174] =?UTF-8?q?Fix:=20UserInfoArgumentResolver=20Anony?= =?UTF-8?q?mousAuthenticationToken=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/security/resolver/UserInfoArgumentResolver.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/security/resolver/UserInfoArgumentResolver.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/security/resolver/UserInfoArgumentResolver.kt index f6ed1ec..4960add 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/security/resolver/UserInfoArgumentResolver.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/security/resolver/UserInfoArgumentResolver.kt @@ -5,6 +5,7 @@ import com.withaeng.api.security.authentication.UserInfo import com.withaeng.common.exception.WithaengException import com.withaeng.common.exception.WithaengExceptionType import org.springframework.core.MethodParameter +import org.springframework.security.authentication.AnonymousAuthenticationToken import org.springframework.security.core.context.SecurityContextHolder import org.springframework.web.bind.support.WebDataBinderFactory import org.springframework.web.context.request.NativeWebRequest @@ -22,10 +23,10 @@ class UserInfoArgumentResolver : HandlerMethodArgumentResolver { parameter: MethodParameter, mavContainer: ModelAndViewContainer?, webRequest: NativeWebRequest, - binderFactory: WebDataBinderFactory? + binderFactory: WebDataBinderFactory?, ): Any? { return when (val authentication = SecurityContextHolder.getContext().authentication) { - null -> null + is AnonymousAuthenticationToken -> null is JwtAuthentication -> authentication.principal else -> throw WithaengException.of( type = WithaengExceptionType.AUTH_ERROR, From e93e7d546897fd908ddd10ee7ff27d9ce7f08d2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Sun, 15 Sep 2024 04:08:02 +0900 Subject: [PATCH 134/174] =?UTF-8?q?Feature:=20=EB=8F=99=ED=96=89=20?= =?UTF-8?q?=EC=8B=A0=EC=B2=AD=20api=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../accompany/AccompanyApplicationService.kt | 20 +++++++ .../accompany/AccompanyController.kt | 27 +++++++-- .../withaeng/domain/accompany/Accompany.kt | 6 +- .../withaeng/domain/accompany/AccompanyDto.kt | 4 +- .../domain/accompany/AccompanyService.kt | 17 ++++-- .../AccompanyJoinRequestRepository.kt | 14 +++++ .../AccompanyJoinRequestService.kt | 58 +++++++++++++++++++ .../accompanyrequests/AccompanyJoinRequest.kt | 47 +++++++++++++++ .../AccompanyJoinRequestStatus.kt | 5 ++ 9 files changed, 186 insertions(+), 12 deletions(-) create mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestRepository.kt create mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestService.kt create mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyrequests/AccompanyJoinRequest.kt create mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyrequests/AccompanyJoinRequestStatus.kt diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt index a4b7fba..7e6b24f 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt @@ -1,7 +1,10 @@ package com.withaeng.api.applicationservice.accompany import com.withaeng.api.applicationservice.accompany.dto.* +import com.withaeng.common.exception.WithaengException +import com.withaeng.common.exception.WithaengExceptionType import com.withaeng.domain.accompany.AccompanyService +import com.withaeng.domain.accompanyjoinrequests.AccompanyJoinRequestService import com.withaeng.domain.accompanylike.AccompanyLikeService import org.springframework.stereotype.Service @@ -9,6 +12,7 @@ import org.springframework.stereotype.Service class AccompanyApplicationService( private val accompanyService: AccompanyService, private val accompanyLikeService: AccompanyLikeService, + private val accompanyJoinRequestService: AccompanyJoinRequestService, ) { fun create(request: CreateAccompanyServiceRequest): AccompanyResponse { @@ -53,4 +57,20 @@ class AccompanyApplicationService( private fun countAccompanyLikeByAccompanyId(accompanyId: Long): Long { return accompanyLikeService.countByAccompanyId(accompanyId) } + + fun requestJoin(accompanyId: Long, userId: Long) { + val accompanyDto = accompanyService.findById(accompanyId) + validateCreator(accompanyDto.userId, userId) + accompanyJoinRequestService.create(accompanyId, userId) + } + + + private fun validateCreator(createUserId: Long, requestUserId: Long) { + if (createUserId == requestUserId) { + throw WithaengException.of( + type = WithaengExceptionType.ACCESS_DENIED, + message = "본인의 동행은 신청할 수 없습니다." + ) + } + } } \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt index a294731..855bdfd 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt @@ -20,7 +20,7 @@ import org.springframework.web.bind.annotation.* @RestController @RequestMapping("/api/v1/accompany") class AccompanyController( - private val accompanyApplicationService: AccompanyApplicationService + private val accompanyApplicationService: AccompanyApplicationService, ) { @Operation( @@ -32,7 +32,7 @@ class AccompanyController( @PostMapping fun create( @GetAuth userInfo: UserInfo, - @RequestBody @Valid request: CreateAccompanyRequest + @RequestBody @Valid request: CreateAccompanyRequest, ): ApiResponse { return ApiResponse.success( accompanyApplicationService.create(request.toServiceRequest(userInfo.id)) @@ -43,7 +43,7 @@ class AccompanyController( @GetMapping("/{accompanyId}") fun retrieve( @GetAuth userInfo: UserInfo?, - @PathVariable("accompanyId") accompanyId: Long + @PathVariable("accompanyId") accompanyId: Long, ): ApiResponse { return ApiResponse.success( accompanyApplicationService.detail(accompanyId, userInfo?.id) @@ -67,15 +67,30 @@ class AccompanyController( fun update( @GetAuth userInfo: UserInfo, @PathVariable accompanyId: Long, - @RequestBody @Valid param: UpdateAccompanyRequest + @RequestBody @Valid param: UpdateAccompanyRequest, ): ApiResponse { return ApiResponse.success( accompanyApplicationService.update( param.toServiceRequest( - accompanyId = accompanyId, - userId = userInfo.id + accompanyId = accompanyId, userId = userInfo.id ) ) ) } + + @Operation( + summary = "Create AccompanyJoinRequests API", + description = "동행 참가 신청 API", + security = [SecurityRequirement(name = "Authorization")] + ) + @PostMapping("/{accompanyId}/join-requests") + fun requestJoin( + @GetAuth userInfo: UserInfo, + @PathVariable accompanyId: Long, + ): ApiResponse { + accompanyApplicationService.requestJoin( + accompanyId = accompanyId, userId = userInfo.id + ) + return ApiResponse.success() + } } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt index d4eb4ee..497ae38 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt @@ -1,6 +1,7 @@ package com.withaeng.domain.accompany import com.withaeng.domain.BaseEntity +import com.withaeng.domain.accompanyrequests.AccompanyJoinRequest import com.withaeng.domain.accompanystatistics.AccompanyStatistics import com.withaeng.domain.converter.TagIdsConverter import com.withaeng.domain.user.UserPreferAccompanyGender @@ -75,6 +76,9 @@ class Accompany( @OneToOne(mappedBy = "accompany", cascade = [CascadeType.ALL], orphanRemoval = true) var accompanyStatistics: AccompanyStatistics? = null, + @OneToMany(mappedBy = "accompany", cascade = [CascadeType.ALL], orphanRemoval = true) + var joinRequests: MutableList = mutableListOf(), + ) : BaseEntity() { fun increaseViewCount() { @@ -83,7 +87,7 @@ class Accompany( fun update( content: String?, - tagIds: Set? + tagIds: Set?, ) { this.content = content ?: this.content this.tagIds = tagIds ?: this.tagIds diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyDto.kt index c8e32e0..2f3150c 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyDto.kt @@ -30,6 +30,7 @@ data class AccompanyDto( val userId: Long, val title: String, val content: String, + val accompanyStatus: AccompanyStatus, val destination: AccompanyDestination, val startTripDate: LocalDate, val endTripDate: LocalDate, @@ -48,6 +49,7 @@ fun Accompany.toDto(): AccompanyDto = AccompanyDto( userId = userId, title = title, content = content, + accompanyStatus = accompanyStatus, destination = accompanyDestination, startTripDate = startTripDate, endTripDate = endTripDate, @@ -67,7 +69,7 @@ data class SearchAccompanyDto( var startTripDate: LocalDate, // 동행 모집 시작일시 var endTripDate: LocalDate, // 동행 모집 마감일시 var pageIndex: Long, - var pageSize: Long + var pageSize: Long, ) { fun getCurrentPage(): Long { return (this.pageIndex - 1) * this.pageSize diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyService.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyService.kt index 9dcd8fd..1257c9f 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyService.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyService.kt @@ -28,7 +28,10 @@ class AccompanyService( @Transactional fun update(params: UpdateAccompanyDto): AccompanyDto { - val accompany = findById(params.accompanyId) + val accompany = accompanyRepository.findByIdOrNull(params.accompanyId) ?: throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = NOT_EXIST_MESSAGE + ) accompany.update( content = params.content, tagIds = params.tagIds, @@ -48,7 +51,10 @@ class AccompanyService( @Transactional fun increaseViewCount(accompanyId: Long) { - val accompany = findById(accompanyId) + val accompany = accompanyRepository.findByIdOrNull(accompanyId) ?: throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = NOT_EXIST_MESSAGE + ) accompany.increaseViewCount() } @@ -62,11 +68,14 @@ class AccompanyService( return accompanyRepository.countByUserId(userId) } - private fun findById(accompanyId: Long) = - accompanyRepository.findByIdOrNull(accompanyId) ?: throw WithaengException.of( + @Transactional(readOnly = true) + fun findById(accompanyId: Long): AccompanyDto { + val accompany = accompanyRepository.findByIdOrNull(accompanyId) ?: throw WithaengException.of( type = WithaengExceptionType.NOT_EXIST, message = NOT_EXIST_MESSAGE ) + return accompany.toDto() + } private fun filterValidTagIds(tagIds: Set?): Set { if (tagIds == null) return emptySet() diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestRepository.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestRepository.kt new file mode 100644 index 0000000..38f4b01 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestRepository.kt @@ -0,0 +1,14 @@ +package com.withaeng.domain.accompanyjoinrequests + +import com.withaeng.domain.accompanyrequests.AccompanyJoinRequest +import com.withaeng.domain.accompanyrequests.AccompanyJoinRequestStatus +import org.springframework.data.jpa.repository.JpaRepository + +interface AccompanyJoinRequestRepository : JpaRepository { + fun countByAccompanyIdAndStatus( + accompanyId: Long, + status: AccompanyJoinRequestStatus = AccompanyJoinRequestStatus.ACCEPT, + ): Int + + fun existsByAccompanyIdAndUserId(accompanyId: Long, userId: Long): Boolean +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestService.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestService.kt new file mode 100644 index 0000000..a915950 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestService.kt @@ -0,0 +1,58 @@ +package com.withaeng.domain.accompanyjoinrequests + +import com.withaeng.common.exception.WithaengException +import com.withaeng.common.exception.WithaengExceptionType +import com.withaeng.domain.accompany.Accompany +import com.withaeng.domain.accompany.AccompanyRepository +import com.withaeng.domain.accompany.AccompanyStatus +import com.withaeng.domain.accompanyrequests.AccompanyJoinRequest +import org.springframework.data.repository.findByIdOrNull +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional + +@Service +class AccompanyJoinRequestService( + private val accompanyJoinRequestRepository: AccompanyJoinRequestRepository, + private val accompanyRepository: AccompanyRepository, +) { + + @Transactional + fun create(accompanyId: Long, userId: Long) { + val accompany = accompanyRepository.findByIdOrNull(accompanyId) ?: throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = "해당하는 동행을 찾을 수 없습니다." + ) + validateFull(accompany, accompanyId) + validateDuplicateJoin(accompanyId, userId) + val accompanyJoinRequest = AccompanyJoinRequest.create(userId, accompany) + accompanyJoinRequestRepository.save(accompanyJoinRequest) + } + + private fun validateFull(accompany: Accompany, accompanyId: Long) { + if (isFull(accompany, accompanyId)) { + throw WithaengException.of( + type = WithaengExceptionType.INVALID_ACCESS, + message = "모집 마감되었습니다." + ) + } + } + + private fun validateDuplicateJoin(accompanyId: Long, userId: Long) { + if (existsByUser(accompanyId, userId)) { + throw WithaengException.of( + type = WithaengExceptionType.ALREADY_EXIST, + message = "동행 신청한 내역이 존재합니다." + ) + } + } + + private fun isFull(accompany: Accompany, accompanyId: Long) = + accompany.accompanyStatus == AccompanyStatus.COMPLETE || + accompany.memberCount < getAcceptedCount(accompanyId) + 1 + + private fun getAcceptedCount(accompanyId: Long) = + accompanyJoinRequestRepository.countByAccompanyIdAndStatus(accompanyId) + + private fun existsByUser(accompanyId: Long, userId: Long) = + accompanyJoinRequestRepository.existsByAccompanyIdAndUserId(accompanyId, userId) +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyrequests/AccompanyJoinRequest.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyrequests/AccompanyJoinRequest.kt new file mode 100644 index 0000000..62ce623 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyrequests/AccompanyJoinRequest.kt @@ -0,0 +1,47 @@ +package com.withaeng.domain.accompanyrequests + +import com.withaeng.domain.BaseEntity +import com.withaeng.domain.accompany.Accompany +import jakarta.persistence.* + +@Entity +@Table(name = "accompany_join_request") +class AccompanyJoinRequest( + + @Column(name = "user_id", nullable = false) + val userId: Long, + + @Enumerated(EnumType.STRING) + var status: AccompanyJoinRequestStatus, + + @ManyToOne + @JoinColumn(name = "accompany_id") + val accompany: Accompany, +) : BaseEntity() { + + companion object { + fun create(userId: Long, accompany: Accompany): AccompanyJoinRequest { + return AccompanyJoinRequest( + userId = userId, + status = AccompanyJoinRequestStatus.WAIT, + accompany = accompany, + ) + } + } + + fun accept() { + status = AccompanyJoinRequestStatus.ACCEPT + } + + fun duplicated(userId: Long): Boolean { + return requestedBy(userId) && (onStatus(AccompanyJoinRequestStatus.WAIT) || onStatus(AccompanyJoinRequestStatus.ACCEPT)) + } + + fun requestedBy(userId: Long): Boolean { + return this.userId == userId + } + + fun onStatus(accept: AccompanyJoinRequestStatus): Boolean { + return this.status == accept + } +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyrequests/AccompanyJoinRequestStatus.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyrequests/AccompanyJoinRequestStatus.kt new file mode 100644 index 0000000..c228d6d --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyrequests/AccompanyJoinRequestStatus.kt @@ -0,0 +1,5 @@ +package com.withaeng.domain.accompanyrequests + +enum class AccompanyJoinRequestStatus { + WAIT, ACCEPT, REJECT, CANCEL +} From 0546076fda2ff70149788f63807252207867b0ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Sun, 15 Sep 2024 04:32:41 +0900 Subject: [PATCH 135/174] =?UTF-8?q?fix:=20=EC=9D=B8=EC=A6=9D=EB=A9=94?= =?UTF-8?q?=EC=9D=BC=20redirect=20=EC=8B=A4=ED=8C=A8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/cd.yml | 1 + .../com/withaeng/api/common/Constants.kt | 6 - .../com/withaeng/api/config/AuthConfig.kt | 2 +- .../api/scheduler/SendEmailScheduler.kt | 19 ++- .../src/main/resources/application.yml | 3 +- .../templates/change-password-template.html | 112 +++++++++--------- .../templates/validate-email-template.html | 112 +++++++++--------- 7 files changed, 129 insertions(+), 126 deletions(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index ae10a04..aed6ad6 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -72,6 +72,7 @@ jobs: export DATABASE_URL=${{ secrets.DATABASE_URL }} export DATABASE_USERNAME=${{ secrets.DATABASE_USERNAME }} export DATABASE_PASSWORD=${{ secrets.DATABASE_PASSWORD }} + export WITHAENG_HOST=${{ secrets.WITHAENG_HOST }} export JWT_ISSUER=${{ secrets.JWT_ISSUER }} export JWT_SECRET_KEY=${{ secrets.JWT_SECRET_KEY }} export JASYPT_PASSWORD=${{ secrets.JASYPT_PASSWORD }} diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/common/Constants.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/common/Constants.kt index d74fb24..b706eda 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/common/Constants.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/common/Constants.kt @@ -5,10 +5,4 @@ object Constants { const val BEARER_TYPE = "Bearer" const val BEARER_TOKEN_PREFIX_WITH_WHITESPACE = "$BEARER_TYPE " } - - object Url { - const val BASE_URL = "localhost:3030/" - const val VALIDATING_EMAIL_URL = BASE_URL + "validate-email" - const val CHANGING_PASSWORD_EMAIL_URL = BASE_URL + "change-password" - } } diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/config/AuthConfig.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/config/AuthConfig.kt index dc96ee1..b1423cd 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/config/AuthConfig.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/config/AuthConfig.kt @@ -21,5 +21,5 @@ class AuthConfig { } } -@ConfigurationProperties(prefix = "witheang.auth") +@ConfigurationProperties(prefix = "withaeng.auth") data class AuthProperty(val jwtSecretKey: String, val jwtIssuer: String) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/SendEmailScheduler.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/SendEmailScheduler.kt index 2c65529..d473650 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/SendEmailScheduler.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/SendEmailScheduler.kt @@ -1,7 +1,5 @@ package com.withaeng.api.scheduler -import com.withaeng.api.common.Constants.Url.CHANGING_PASSWORD_EMAIL_URL -import com.withaeng.api.common.Constants.Url.VALIDATING_EMAIL_URL import com.withaeng.domain.validateemail.ValidatingEmailService import com.withaeng.domain.validateemail.ValidatingEmailStatus import com.withaeng.domain.validateemail.ValidatingEmailType @@ -9,6 +7,7 @@ import com.withaeng.external.ses.MailSender import com.withaeng.external.ses.MailType import org.slf4j.Logger import org.slf4j.LoggerFactory +import org.springframework.beans.factory.annotation.Value import org.springframework.scheduling.annotation.Async import org.springframework.scheduling.annotation.Scheduled import org.springframework.stereotype.Component @@ -18,9 +17,16 @@ import java.time.LocalDateTime @Component class SendEmailScheduler( private val validatingEmailService: ValidatingEmailService, - private val mailSender: MailSender + private val mailSender: MailSender, + @Value("\${withaeng.host}") + private val host: String, ) { + companion object { + private const val EMAIL_VALIDATE_REDIRECT_PATH = "/check-email" + private const val CHANGE_PASSWORD_REDIRECT_PATH = "/check-email-pw" + } + private val log: Logger = LoggerFactory.getLogger(SendEmailScheduler::class.java) @Scheduled(cron = "0 * * * * *") @@ -47,9 +53,10 @@ class SendEmailScheduler( } private fun ValidatingEmailType.toMailType(): MailType = - if (this == ValidatingEmailType.CHANGE_PASSWORD) MailType.CHANGE_PASSWORD - else MailType.VALIDATE_EMAIL + if (this == ValidatingEmailType.CHANGE_PASSWORD) + MailType.CHANGE_PASSWORD else MailType.VALIDATE_EMAIL private fun ValidatingEmailType.toValidatingUrl(): String = - if (this == ValidatingEmailType.CHANGE_PASSWORD) CHANGING_PASSWORD_EMAIL_URL else VALIDATING_EMAIL_URL + if (this == ValidatingEmailType.CHANGE_PASSWORD) + host + EMAIL_VALIDATE_REDIRECT_PATH else host + CHANGE_PASSWORD_REDIRECT_PATH } diff --git a/withaeng-api/src/main/resources/application.yml b/withaeng-api/src/main/resources/application.yml index 244a66c..8e9e919 100644 --- a/withaeng-api/src/main/resources/application.yml +++ b/withaeng-api/src/main/resources/application.yml @@ -6,7 +6,8 @@ spring: - application-external.yml web.resources.add-mappings: false -witheang: +withaeng: + host: ${WITHAENG_HOST} auth: jwt-issuer: ${JWT_ISSUER} jwt-secret-key: ${JWT_SECRET_KEY} diff --git a/withaeng-external/src/main/resources/templates/change-password-template.html b/withaeng-external/src/main/resources/templates/change-password-template.html index 2cabfc8..926fc9f 100644 --- a/withaeng-external/src/main/resources/templates/change-password-template.html +++ b/withaeng-external/src/main/resources/templates/change-password-template.html @@ -1,18 +1,18 @@ - - - + + + 같이행(Withaeng) - 비밀번호 재설정 - - -
-
+ >
-
+DSB1FbyQhUTFUTEbSvMY9YwSnjtjBXYUk92xs5tUrX8BKlrQCTTHH4EAAAAASUVORK5CYII="/> +
-
-

- 비밀번호 재설정 -

-

- 안녕하세요.
- 같이행 서비스 이용을 위해 이메일 주소 인증을 요청하셨습니다.
- 아래 버튼을 클릭하여 서비스를 이용할 수 있습니다. -

-
-
-
+ 비밀번호 재설정 + +

+ 안녕하세요.
+ 같이행 서비스 이용을 위해 이메일 주소 인증을 요청하셨습니다.
+ 아래 버튼을 클릭하여 서비스를 이용할 수 있습니다. +

+
+
+
-

+

- 인증은 5분 이내로 완료해주세요. -

-
- + th:href="${redirectUrl}" + > + 네, 인증합니다. + +
-
- - +
+ + diff --git a/withaeng-external/src/main/resources/templates/validate-email-template.html b/withaeng-external/src/main/resources/templates/validate-email-template.html index 98534d4..2cd38af 100644 --- a/withaeng-external/src/main/resources/templates/validate-email-template.html +++ b/withaeng-external/src/main/resources/templates/validate-email-template.html @@ -1,18 +1,18 @@ - - - + + + 같이행(Withaeng) - 이메일 인증 - - -
-
+ >
-
+DSB1FbyQhUTFUTEbSvMY9YwSnjtjBXYUk92xs5tUrX8BKlrQCTTHH4EAAAAASUVORK5CYII="/> +
-
-

- 이메일 주소 인증 메일 -

-

- 안녕하세요.
- 같이행 서비스 이용을 위해 이메일 주소 인증을 요청하셨습니다.
- 아래 버튼을 클릭하여 서비스를 이용할 수 있습니다. -

-
-
-
+ 이메일 주소 인증 메일 + +

+ 안녕하세요.
+ 같이행 서비스 이용을 위해 이메일 주소 인증을 요청하셨습니다.
+ 아래 버튼을 클릭하여 서비스를 이용할 수 있습니다. +

+
+
+
-

+

- 인증은 5분 이내로 완료해주세요. -

-
- + th:href="${redirectUrl}" + > + 네, 인증합니다. + +
-
- - +
+ + From d59e06c11a8d27b81f1b96a7ee99d380d334bed7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Sun, 15 Sep 2024 05:07:36 +0900 Subject: [PATCH 136/174] =?UTF-8?q?feat:=20=EC=9D=B4=EB=A9=94=EC=9D=BC=202?= =?UTF-8?q?0=EC=B4=88=EB=A7=88=EB=8B=A4=20=EB=B3=B4=EB=82=B4=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/withaeng/api/scheduler/SendEmailScheduler.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/SendEmailScheduler.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/SendEmailScheduler.kt index d473650..fffdddf 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/SendEmailScheduler.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/SendEmailScheduler.kt @@ -13,6 +13,7 @@ import org.springframework.scheduling.annotation.Scheduled import org.springframework.stereotype.Component import org.springframework.transaction.annotation.Transactional import java.time.LocalDateTime +import java.util.concurrent.TimeUnit @Component class SendEmailScheduler( @@ -29,7 +30,7 @@ class SendEmailScheduler( private val log: Logger = LoggerFactory.getLogger(SendEmailScheduler::class.java) - @Scheduled(cron = "0 * * * * *") + @Scheduled(timeUnit = TimeUnit.SECONDS, fixedDelay = 20) @Async("asyncSchedulerExecutor") @Transactional fun sendEmail() { From 9a141a337e3cfbef5d101dd3af762a87a766f021 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Sun, 15 Sep 2024 05:14:39 +0900 Subject: [PATCH 137/174] =?UTF-8?q?fix:=20docker-compose.yml=20withaeng=5F?= =?UTF-8?q?host=20=ED=99=98=EA=B2=BD=EB=B3=80=EC=88=98=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 --- withaeng-api/docker-compose.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/withaeng-api/docker-compose.yml b/withaeng-api/docker-compose.yml index 1260c92..e7ad2e4 100644 --- a/withaeng-api/docker-compose.yml +++ b/withaeng-api/docker-compose.yml @@ -12,6 +12,7 @@ services: DATABASE_URL: ${DATABASE_URL} DATABASE_USERNAME: ${DATABASE_USERNAME} DATABASE_PASSWORD: ${DATABASE_PASSWORD} + WITHAENG_HOST: ${WITHAENG_HOST} JWT_ISSUER: ${JWT_ISSUER} JWT_SECRET_KEY: ${JWT_SECRET_KEY} JASYPT_PASSWORD: ${JASYPT_PASSWORD} From 18bac9239d496c26bf44281def06a36350fcd610 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Sun, 15 Sep 2024 05:37:50 +0900 Subject: [PATCH 138/174] fix: docker compose up add option --build --- .github/workflows/cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index aed6ad6..8e55db2 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -77,4 +77,4 @@ jobs: export JWT_SECRET_KEY=${{ secrets.JWT_SECRET_KEY }} export JASYPT_PASSWORD=${{ secrets.JASYPT_PASSWORD }} sudo -E docker compose -f /tmp/withaeng-api/docker-compose.yml down - sudo -E docker compose -f /tmp/withaeng-api/docker-compose.yml up -d \ No newline at end of file + sudo -E docker compose -f /tmp/withaeng-api/docker-compose.yml up --build -d \ No newline at end of file From ca0fe84c6474b12444ce1aac8c0d6b4a566375a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Sun, 15 Sep 2024 05:47:22 +0900 Subject: [PATCH 139/174] =?UTF-8?q?fix:=20redirect=20url=20email-type-path?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/withaeng/api/scheduler/SendEmailScheduler.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/SendEmailScheduler.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/SendEmailScheduler.kt index fffdddf..0e9d230 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/SendEmailScheduler.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/SendEmailScheduler.kt @@ -54,10 +54,10 @@ class SendEmailScheduler( } private fun ValidatingEmailType.toMailType(): MailType = - if (this == ValidatingEmailType.CHANGE_PASSWORD) - MailType.CHANGE_PASSWORD else MailType.VALIDATE_EMAIL + if (this == ValidatingEmailType.VALIDATE_EMAIL) + MailType.VALIDATE_EMAIL else MailType.CHANGE_PASSWORD private fun ValidatingEmailType.toValidatingUrl(): String = - if (this == ValidatingEmailType.CHANGE_PASSWORD) + if (this == ValidatingEmailType.VALIDATE_EMAIL) host + EMAIL_VALIDATE_REDIRECT_PATH else host + CHANGE_PASSWORD_REDIRECT_PATH } From bff714aae2b51c6e7adf47bd3c1743f7344d741a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Sun, 15 Sep 2024 06:08:46 +0900 Subject: [PATCH 140/174] =?UTF-8?q?chore:=20=EC=8B=9C=ED=81=90=EB=A6=AC?= =?UTF-8?q?=ED=8B=B0=20=ED=95=84=EC=9A=94=ED=95=9C=20=EC=84=A4=EC=A0=95?= =?UTF-8?q?=EB=A7=8C=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/kotlin/com/withaeng/api/common/WhiteList.kt | 8 ++------ .../kotlin/com/withaeng/api/config/SecurityConfig.kt | 12 ++++-------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/common/WhiteList.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/common/WhiteList.kt index 59dd412..8fef4fe 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/common/WhiteList.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/common/WhiteList.kt @@ -5,11 +5,7 @@ object WhiteList { fun getWhiteListForSecurityConfig(): List = listOf( // swagger "/api-docs/**", "/swagger-ui/**", "/swagger-resources/**", "/v3/api-docs/**", - // error page - "/error/**", - // Auth endpoints - "/api/v1/auth/**", - // Test endpoints - "/api/v1/test/**" + // H2 console + "/h2-console/**", ) } \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/config/SecurityConfig.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/config/SecurityConfig.kt index 5d73181..97be6ef 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/config/SecurityConfig.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/config/SecurityConfig.kt @@ -17,7 +17,6 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder import org.springframework.security.crypto.password.PasswordEncoder import org.springframework.security.web.SecurityFilterChain import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter -import org.springframework.security.web.util.matcher.AntPathRequestMatcher import org.springframework.web.cors.CorsConfiguration import org.springframework.web.cors.CorsConfigurationSource import org.springframework.web.cors.UrlBasedCorsConfigurationSource @@ -30,10 +29,6 @@ class SecurityConfig( companion object { private const val MAX_CORS_EXPIRE_SECONDS = 3600L - private val PERMIT_ALL_GET = arrayOf( - "/api/v1/accompany/**", - "/api/v1/auth/**", - ) } @Bean @@ -49,7 +44,9 @@ class SecurityConfig( .httpBasic { it.disable() } .formLogin { it.disable() } .authorizeHttpRequests { - it.requestMatchers(HttpMethod.GET, *PERMIT_ALL_GET).permitAll() + it + .requestMatchers("/api/v1/auth/**", "/api/v1/test/**").permitAll() + .requestMatchers(HttpMethod.GET, "/api/v1/accompany/**").permitAll() .anyRequest().hasAnyRole(UserRole.USER.getActualRoleName(), UserRole.ADMIN.getActualRoleName()) } .addFilterBefore(JwtFilter(jwtAgent), UsernamePasswordAuthenticationFilter::class.java) @@ -63,8 +60,7 @@ class SecurityConfig( @Bean fun webSecurityCustomizer(): WebSecurityCustomizer { return WebSecurityCustomizer { - it.ignoring().requestMatchers(*getWhiteListForSecurityConfig().toTypedArray()) - .requestMatchers(AntPathRequestMatcher("/swagger-ui", HttpMethod.GET.name())) + it.ignoring().requestMatchers(HttpMethod.GET, *getWhiteListForSecurityConfig().toTypedArray()) } } From f40901877c4da41b89809a2fd5312308dcf65114 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Sun, 15 Sep 2024 16:32:49 +0900 Subject: [PATCH 141/174] =?UTF-8?q?fix:=20=EA=B0=9C=EB=B0=9C=20=EA=B8=B0?= =?UTF-8?q?=EA=B0=84=EB=8F=99=EC=95=88=20=EC=9A=B4=EC=98=81=EC=84=9C?= =?UTF-8?q?=EB=B2=84=20swagger=20=ED=99=9C=EC=84=B1=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application.yml | 26 +++++-------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/withaeng-api/src/main/resources/application.yml b/withaeng-api/src/main/resources/application.yml index 8e9e919..e1e806d 100644 --- a/withaeng-api/src/main/resources/application.yml +++ b/withaeng-api/src/main/resources/application.yml @@ -12,12 +12,7 @@ withaeng: jwt-issuer: ${JWT_ISSUER} jwt-secret-key: ${JWT_SECRET_KEY} -jasypt.encryptor.password: ${JASYPT_PASSWORD} - ---- -spring.config.activate.on-profile: local - -springdoc: +springdoc: # todo: 개발 종료 후 prod 에서는 비활성화 swagger-ui: path: /api-docs operations-sorter: alpha @@ -25,22 +20,13 @@ springdoc: groups: enabled: true +jasypt.encryptor.password: ${JASYPT_PASSWORD} + --- -spring.config.activate.on-profile: dev +spring.config.activate.on-profile: local -springdoc: - swagger-ui: - path: /api-docs - operations-sorter: alpha - api-docs: - groups: - enabled: true +--- +spring.config.activate.on-profile: dev --- spring.config.activate.on-profile: prod - -springdoc: - swagger-ui: - enabled: false - api-docs: - enabled: false From 8794e2e5c4efdb51bfcf99a5541198b8e1aae10b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Sun, 15 Sep 2024 16:28:51 +0900 Subject: [PATCH 142/174] =?UTF-8?q?fix:=20=ED=83=9C=EA=B7=B8=EB=A5=BC=20?= =?UTF-8?q?=EC=97=94=ED=8B=B0=ED=8B=B0=EA=B0=80=20=EC=95=84=EB=8B=8C=20Str?= =?UTF-8?q?ing=20=EC=BB=AC=EB=A0=89=EC=85=98=EC=9C=BC=EB=A1=9C=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 --- .../accompany/dto/AccompanyResponseDto.kt | 4 ++-- .../dto/AccompanyServiceRequestDto.kt | 10 +++++----- .../accompany/dto/FindAccompanyResponseDto.kt | 4 ++-- .../accompany/dto/AccompanyRequestDto.kt | 16 ++++++++-------- .../withaeng/domain/accompany/Accompany.kt | 14 +++++++------- .../withaeng/domain/accompany/AccompanyDto.kt | 8 ++++---- .../accompany/AccompanyRepositoryImpl.kt | 2 +- .../domain/accompany/AccompanyService.kt | 15 ++------------- .../domain/accompany/FindAccompanyDto.kt | 2 +- .../converter/AccompanyTagsConverter.kt | 19 +++++++++++++++++++ .../domain/converter/TagIdsConverter.kt | 19 ------------------- .../kotlin/com/withaeng/domain/tag/Tag.kt | 13 ------------- .../com/withaeng/domain/tag/TagRepository.kt | 5 ----- 13 files changed, 51 insertions(+), 80 deletions(-) create mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/converter/AccompanyTagsConverter.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/converter/TagIdsConverter.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/tag/Tag.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/tag/TagRepository.kt diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyResponseDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyResponseDto.kt index 95d1406..c0a862d 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyResponseDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyResponseDto.kt @@ -17,7 +17,7 @@ data class AccompanyResponse( val memberCount: Long, val viewCount: Long, val likeCount: Long, - val tagIds: Set? = null, + val tags: Set? = null, val openKakaoUrl: String? = null, val startAccompanyAge: Int, val endAccompanyAge: Int, @@ -40,5 +40,5 @@ fun AccompanyDto.toAccompanyResponse(likeCount: Long): AccompanyResponse = Accom startAccompanyAge = startAccompanyAge.value, endAccompanyAge = endAccompanyAge.value, preferGender = preferGender, - tagIds = tagIds, + tags = tags, ) \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt index ebe9710..6ad69eb 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt @@ -15,7 +15,7 @@ data class CreateAccompanyServiceRequest( val endTripDate: LocalDate, val bannerImageUrl: String? = null, val memberCount: Long, - val tagIds: Set? = emptySet(), + val tags: Set? = emptySet(), val openKakaoUrl: String, val startAccompanyAge: AccompanyAge, val endAccompanyAge: AccompanyAge, @@ -35,7 +35,7 @@ fun CreateAccompanyServiceRequest.toDomainDto(): CreateAccompanyDto = CreateAcco endTripDate = endTripDate, bannerImageUrl = bannerImageUrl, memberCount = memberCount, - tagIds = tagIds?.toSet(), + tags = tags?.toSet(), openKakaoUrl = openKakaoUrl, startAccompanyAge = startAccompanyAge, endAccompanyAge = endAccompanyAge, @@ -46,14 +46,14 @@ data class UpdateAccompanyServiceRequest( val accompanyId: Long, val userId: Long, val content: String? = null, - val tagIds: Set? = null, + val tags: Set? = null, ) fun UpdateAccompanyServiceRequest.toDomainDto(): UpdateAccompanyDto { return UpdateAccompanyDto( accompanyId = accompanyId, content = content, - tagIds = tagIds?.toSet(), + tags = tags?.toSet(), ) } @@ -61,5 +61,5 @@ data class SearchAccompanyServiceRequest( val orderBy: String, val isDescending: Boolean, val pageIndex: Long, - val pageSize: Long + val pageSize: Long, ) \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/FindAccompanyResponseDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/FindAccompanyResponseDto.kt index 6c509b5..4df5e8c 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/FindAccompanyResponseDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/FindAccompanyResponseDto.kt @@ -21,7 +21,7 @@ data class FindAccompanyResponse( val startAccompanyAge: Int, val endAccompanyAge: Int, val preferGender: UserPreferAccompanyGender, - val tagIds: Set? = emptySet(), + val tags: Set? = emptySet(), val likeCount: Long = 0, val author: FindAccompanyUserInfoDto, val approvalPendingUsers: Set? = null, @@ -43,6 +43,6 @@ fun FindAccompanyDto.toAccompanyResponse() = FindAccompanyResponse( startAccompanyAge = startAccompanyAge, endAccompanyAge = endAccompanyAge, preferGender = preferGender, - tagIds = tagIds, + tags = tags, author = author, ) \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt index 2914fc9..eac470d 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt @@ -1,11 +1,11 @@ package com.withaeng.api.controller.accompany.dto import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import com.withaeng.api.applicationservice.accompany.dto.CreateAccompanyServiceRequest +import com.withaeng.api.applicationservice.accompany.dto.UpdateAccompanyServiceRequest import com.withaeng.domain.accompany.AccompanyAge import com.withaeng.domain.accompany.AccompanyAgeDeserializer import com.withaeng.domain.user.UserPreferAccompanyGender -import com.withaeng.api.applicationservice.accompany.dto.CreateAccompanyServiceRequest -import com.withaeng.api.applicationservice.accompany.dto.UpdateAccompanyServiceRequest import io.swagger.v3.oas.annotations.media.Schema import java.time.LocalDate @@ -39,7 +39,7 @@ data class CreateAccompanyRequest( val memberCount: Long, @Schema(description = "동행 게시글에 부착할 태그 아이디 리스트") - val tagIds: Set? = emptySet(), + val tags: Set? = emptySet(), @Schema(description = "동행 게시글에 게시된 오픈 카카오톡 URL") val openKakaoUrl: String, @@ -58,7 +58,7 @@ data class CreateAccompanyRequest( @Schema(description = "[Request] 동행 게시글 수정") fun CreateAccompanyRequest.toServiceRequest( - userId: Long + userId: Long, ): CreateAccompanyServiceRequest = CreateAccompanyServiceRequest( userId = userId, title = title, @@ -70,7 +70,7 @@ fun CreateAccompanyRequest.toServiceRequest( endTripDate = endTripDate, bannerImageUrl = bannerImageUrl, memberCount = memberCount, - tagIds = tagIds, + tags = tags, openKakaoUrl = openKakaoUrl, startAccompanyAge = startAccompanyAge, endAccompanyAge = endAccompanyAge, @@ -82,15 +82,15 @@ data class UpdateAccompanyRequest( val content: String? = null, @Schema(description = "동행 게시글에 부착할 태그 아이디 리스트") - val tagIds: Set? = null, + val tags: Set? = null, ) fun UpdateAccompanyRequest.toServiceRequest( accompanyId: Long, - userId: Long + userId: Long, ): UpdateAccompanyServiceRequest = UpdateAccompanyServiceRequest( accompanyId = accompanyId, userId = userId, content = content, - tagIds = tagIds, + tags = tags, ) \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt index 497ae38..7ee0c45 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt @@ -3,7 +3,7 @@ package com.withaeng.domain.accompany import com.withaeng.domain.BaseEntity import com.withaeng.domain.accompanyrequests.AccompanyJoinRequest import com.withaeng.domain.accompanystatistics.AccompanyStatistics -import com.withaeng.domain.converter.TagIdsConverter +import com.withaeng.domain.converter.AccompanyTagsConverter import com.withaeng.domain.user.UserPreferAccompanyGender import jakarta.persistence.* import org.hibernate.annotations.Comment @@ -68,10 +68,10 @@ class Accompany( @Comment("동행 선호 성별") var preferGender: UserPreferAccompanyGender, - @Convert(converter = TagIdsConverter::class) - @Column(name = "tag_ids", nullable = false) + @Convert(converter = AccompanyTagsConverter::class) + @Column(name = "tags", nullable = false) @Comment("태그 목록") - var tagIds: Set = setOf(), + var tags: Set = setOf(), @OneToOne(mappedBy = "accompany", cascade = [CascadeType.ALL], orphanRemoval = true) var accompanyStatistics: AccompanyStatistics? = null, @@ -87,10 +87,10 @@ class Accompany( fun update( content: String?, - tagIds: Set?, + tags: Set?, ) { this.content = content ?: this.content - this.tagIds = tagIds ?: this.tagIds + this.tags = tags ?: this.tags } companion object { @@ -108,7 +108,7 @@ class Accompany( startAccompanyAge = params.startAccompanyAge.value, endAccompanyAge = params.endAccompanyAge.value, preferGender = params.preferGender, - tagIds = params.tagIds ?: setOf(), + tags = params.tags ?: setOf(), ) accompany.accompanyStatistics = AccompanyStatistics(accompany = accompany) return accompany diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyDto.kt index 2f3150c..d33dbc9 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyDto.kt @@ -12,7 +12,7 @@ data class CreateAccompanyDto( val endTripDate: LocalDate, val bannerImageUrl: String? = null, val memberCount: Long, - val tagIds: Set? = emptySet(), + val tags: Set? = emptySet(), val openKakaoUrl: String, val startAccompanyAge: AccompanyAge, val endAccompanyAge: AccompanyAge, @@ -22,7 +22,7 @@ data class CreateAccompanyDto( data class UpdateAccompanyDto( val accompanyId: Long, val content: String? = null, - val tagIds: Set? = null, + val tags: Set? = null, ) data class AccompanyDto( @@ -41,7 +41,7 @@ data class AccompanyDto( val startAccompanyAge: AccompanyAge, val endAccompanyAge: AccompanyAge, val preferGender: UserPreferAccompanyGender, - val tagIds: Set? = null, + val tags: Set? = null, ) fun Accompany.toDto(): AccompanyDto = AccompanyDto( @@ -60,7 +60,7 @@ fun Accompany.toDto(): AccompanyDto = AccompanyDto( startAccompanyAge = AccompanyAge.fromValue(startAccompanyAge), endAccompanyAge = AccompanyAge.fromValue(endAccompanyAge), preferGender = preferGender, - tagIds = tagIds, + tags = tags, ) data class SearchAccompanyDto( diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryImpl.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryImpl.kt index 4d02888..eb6c197 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryImpl.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryImpl.kt @@ -31,7 +31,7 @@ class AccompanyRepositoryImpl( accompany.startAccompanyAge, accompany.endAccompanyAge, accompany.preferGender, - accompany.tagIds, + accompany.tags, accompanyLike.count(), QFindAccompanyUserInfoDto( user.profile.nickname, diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyService.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyService.kt index 1257c9f..94196de 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyService.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyService.kt @@ -2,7 +2,6 @@ package com.withaeng.domain.accompany import com.withaeng.common.exception.WithaengException import com.withaeng.common.exception.WithaengExceptionType -import com.withaeng.domain.tag.TagRepository import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -10,7 +9,6 @@ import org.springframework.transaction.annotation.Transactional @Service class AccompanyService( private val accompanyRepository: AccompanyRepository, - private val tagRepository: TagRepository, ) { companion object { @@ -19,9 +17,7 @@ class AccompanyService( @Transactional fun create(params: CreateAccompanyDto): AccompanyDto { - val actualTagIds = filterValidTagIds(params.tagIds) - val actualParams = params.copy(tagIds = actualTagIds) - val accompanyEntity = Accompany.create(actualParams) + val accompanyEntity = Accompany.create(params) accompanyRepository.save(accompanyEntity) return accompanyEntity.toDto() } @@ -34,7 +30,7 @@ class AccompanyService( ) accompany.update( content = params.content, - tagIds = params.tagIds, + tags = params.tags, ) return accompany.toDto() @@ -76,11 +72,4 @@ class AccompanyService( ) return accompany.toDto() } - - private fun filterValidTagIds(tagIds: Set?): Set { - if (tagIds == null) return emptySet() - return tagRepository.findAllById(tagIds) - .map { it.id } - .toSet() - } } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/FindAccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/FindAccompanyDto.kt index 4b51473..58a291c 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/FindAccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/FindAccompanyDto.kt @@ -19,7 +19,7 @@ data class FindAccompanyDto @QueryProjection constructor( val startAccompanyAge: Int, val endAccompanyAge: Int, val preferGender: UserPreferAccompanyGender, - val tagIds: Set? = emptySet(), + val tags: Set? = emptySet(), val likeCount: Long = 0, val author: FindAccompanyUserInfoDto, ) \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/converter/AccompanyTagsConverter.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/converter/AccompanyTagsConverter.kt new file mode 100644 index 0000000..c1a6d57 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/converter/AccompanyTagsConverter.kt @@ -0,0 +1,19 @@ +package com.withaeng.domain.converter + +import jakarta.persistence.AttributeConverter + +class AccompanyTagsConverter : AttributeConverter, String> { + override fun convertToDatabaseColumn(attribute: Set): String { + return attribute + .filter { it.isNotBlank() } + .joinToString(DELIMITER) + } + + override fun convertToEntityAttribute(data: String): Set { + return if (data.isBlank()) emptySet() else data.split(DELIMITER).toSet() + } + + companion object { + private const val DELIMITER = "," + } +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/converter/TagIdsConverter.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/converter/TagIdsConverter.kt deleted file mode 100644 index 70b1cf1..0000000 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/converter/TagIdsConverter.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.withaeng.domain.converter - -import jakarta.persistence.AttributeConverter - -class TagIdsConverter : AttributeConverter, String> { - override fun convertToDatabaseColumn(attribute: Set): String { - return attribute.joinToString(DELIMITER) - } - - override fun convertToEntityAttribute(data: String): Set { - return if (data.isBlank()) setOf() - else data.split(DELIMITER).map { it.toLong() }.toSet() - } - - companion object { - private const val DELIMITER = "," - } - -} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/tag/Tag.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/tag/Tag.kt deleted file mode 100644 index c59d9bf..0000000 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/tag/Tag.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.withaeng.domain.tag - -import com.withaeng.domain.BaseEntity -import jakarta.persistence.Column -import jakarta.persistence.Entity -import jakarta.persistence.Table - -@Table(name = "tags") -@Entity -class Tag( - @Column(name = "name", nullable = false) - val name: String -) : BaseEntity() \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/tag/TagRepository.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/tag/TagRepository.kt deleted file mode 100644 index b10df58..0000000 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/tag/TagRepository.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.withaeng.domain.tag - -import org.springframework.data.jpa.repository.JpaRepository - -interface TagRepository : JpaRepository \ No newline at end of file From 69cf2bf7afc6303e6499444a1d2e48d6bec1ca78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Sun, 15 Sep 2024 16:49:51 +0900 Subject: [PATCH 143/174] =?UTF-8?q?chore:=20ci/cd=20=EC=8A=A4=ED=83=AD=20?= =?UTF-8?q?=ED=86=B5=EC=9D=BC=EC=84=B1=EC=9E=88=EA=B2=8C=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 --- .github/workflows/cd.yml | 19 ++++++++++--------- .github/workflows/pr.yml | 12 +----------- 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 8e55db2..ed54d02 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -2,7 +2,8 @@ name: Withaeng CD with Gradle, Github Actions on: push: - branches: [ "develop" ] # todo: main branch로 변경 + branches: + - develop # todo: main branch로 변경 jobs: build: @@ -10,16 +11,16 @@ jobs: environment: prod steps: - - name: 체크아웃 + - name: Checkout uses: actions/checkout@v3 - - name: JDK 17 설치 + - name: Set up JDK 17 uses: actions/setup-java@v3 with: java-version: 17 distribution: temurin - - name: Gradle 캐싱 + - name: Cache Gradle dependencies uses: actions/cache@v3 with: path: | @@ -29,15 +30,15 @@ jobs: restore-keys: | ${{ runner.os }}-gradle- - - name: gradlew 실행 권한 부여 + - name: Grant execute permission for gradlew run: chmod +x ./gradlew shell: bash - - name: 프로젝트 빌드 + - name: Build with Gradle run: ./gradlew clean build shell: bash - - name: 운영서버 디렉토리 정리 + - name: Clean Server Directory uses: appleboy/ssh-action@master with: host: ${{ secrets.SERVER_HOST }} @@ -45,7 +46,7 @@ jobs: key: ${{ secrets.SERVER_SSH_KEY }} script: sudo rm -rf /tmp/withaeng-api - - name: 빌드 전송 + - name: Send build artifacts to server uses: appleboy/scp-action@master with: host: ${{ secrets.SERVER_HOST }} @@ -60,7 +61,7 @@ jobs: environment: prod steps: - - name: 운영서버 애플리케이션 실행 + - name: Run Docker Compose uses: appleboy/ssh-action@master with: host: ${{ secrets.SERVER_HOST }} diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index f2d48ba..3b9cbe2 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -6,9 +6,6 @@ on: - main - develop -env: - JASYPT_ENCRYPTOR_PASSWORD: ${{ secrets.JASYPT_ENCRYPTOR_PASSWORD }} - jobs: build: runs-on: ubuntu-latest @@ -20,14 +17,7 @@ jobs: uses: actions/setup-java@v3 with: java-version: 17 - distribution: adopt - - - name: Get CurrentTime - uses: 1466587594/get-current-time@v2 - id: current-time - with: - format: YYYY-MM-DDTHH-mm-ss - utcOffset: "+09:00" + distribution: temurin - name: Grant execute permission for gradlew run: chmod +x gradlew From 33761e2385a29d63cfed773c32f16298297e2ca8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Sun, 15 Sep 2024 17:53:15 +0900 Subject: [PATCH 144/174] =?UTF-8?q?Feature:=20=EB=8F=99=ED=96=89=20?= =?UTF-8?q?=EC=8A=B9=EC=9D=B8=20api=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../accompany/AccompanyApplicationService.kt | 36 +++++++++++++------ .../accompany/AccompanyController.kt | 16 +++++++++ .../withaeng/domain/accompany/Accompany.kt | 4 +++ .../AccompanyJoinRequestService.kt | 24 ++++++++++++- 4 files changed, 68 insertions(+), 12 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt index 7e6b24f..ce712e3 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt @@ -39,13 +39,6 @@ class AccompanyApplicationService( return accompanyDto } - private fun increaseViewCount(accompanyId: Long) { - accompanyService.increaseViewCount(accompanyId) - } - - private fun isHost(loginUserId: Long?, userId: Long) = - loginUserId == userId - fun retrieveAll(): List { val accompanyDtoList = accompanyService.findAll() // TODO: Bulk로 가져오는 방법을 고안 @@ -54,16 +47,28 @@ class AccompanyApplicationService( } } - private fun countAccompanyLikeByAccompanyId(accompanyId: Long): Long { - return accompanyLikeService.countByAccompanyId(accompanyId) - } - fun requestJoin(accompanyId: Long, userId: Long) { val accompanyDto = accompanyService.findById(accompanyId) validateCreator(accompanyDto.userId, userId) accompanyJoinRequestService.create(accompanyId, userId) } + fun acceptJoin(accompanyId: Long, userId: Long, joinRequestId: Long) { + val accompanyDto = accompanyService.findById(accompanyId) + validateNonCreator(accompanyDto.userId, userId) + accompanyJoinRequestService.acceptJoin(accompanyId, joinRequestId) + } + + private fun increaseViewCount(accompanyId: Long) { + accompanyService.increaseViewCount(accompanyId) + } + + private fun isHost(loginUserId: Long?, userId: Long) = + loginUserId == userId + + private fun countAccompanyLikeByAccompanyId(accompanyId: Long): Long { + return accompanyLikeService.countByAccompanyId(accompanyId) + } private fun validateCreator(createUserId: Long, requestUserId: Long) { if (createUserId == requestUserId) { @@ -73,4 +78,13 @@ class AccompanyApplicationService( ) } } + + private fun validateNonCreator(createUserId: Long, requestUserId: Long) { + if (createUserId != requestUserId) { + throw WithaengException.of( + type = WithaengExceptionType.ACCESS_DENIED, + message = "접근 권한이 없습니다." + ) + } + } } \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt index 855bdfd..0c612b3 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt @@ -93,4 +93,20 @@ class AccompanyController( ) return ApiResponse.success() } + + @Operation( + summary = "Create AccompanyJoinRequests API", + description = "동행 승인 API", + security = [SecurityRequirement(name = "Authorization")] + ) + @PutMapping("/{accompanyId}/join-requests/{joinRequestId}/accept") + fun acceptJoin( + @GetAuth userInfo: UserInfo, + @PathVariable accompanyId: Long, + @PathVariable joinRequestId: Long, + ) { + accompanyApplicationService.acceptJoin( + accompanyId = accompanyId, userId = userInfo.id, joinRequestId = joinRequestId + ) + } } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt index 497ae38..295ed55 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt @@ -93,6 +93,10 @@ class Accompany( this.tagIds = tagIds ?: this.tagIds } + fun updateStatusToComplete() { + this.accompanyStatus = AccompanyStatus.COMPLETE + } + companion object { fun create(params: CreateAccompanyDto): Accompany { val accompany = Accompany( diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestService.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestService.kt index a915950..66a8bb1 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestService.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestService.kt @@ -28,6 +28,25 @@ class AccompanyJoinRequestService( accompanyJoinRequestRepository.save(accompanyJoinRequest) } + @Transactional + fun acceptJoin(accompanyId: Long, joinRequestId: Long) { + val accompanyJoinRequest = accompanyJoinRequestRepository.findByIdOrNull(joinRequestId) + ?: throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = "동행 신청 정보가 존재하지 않습니다." + ) + val accompany = accompanyRepository.findByIdOrNull(accompanyId) ?: throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = "해당하는 동행을 찾을 수 없습니다." + ) + validateFull(accompany, accompanyId) + accompanyJoinRequest.accept() + + if (isBelowMemberLimit(accompany, accompanyId)) { + accompany.updateStatusToComplete() + } + } + private fun validateFull(accompany: Accompany, accompanyId: Long) { if (isFull(accompany, accompanyId)) { throw WithaengException.of( @@ -48,11 +67,14 @@ class AccompanyJoinRequestService( private fun isFull(accompany: Accompany, accompanyId: Long) = accompany.accompanyStatus == AccompanyStatus.COMPLETE || - accompany.memberCount < getAcceptedCount(accompanyId) + 1 + isBelowMemberLimit(accompany, accompanyId) private fun getAcceptedCount(accompanyId: Long) = accompanyJoinRequestRepository.countByAccompanyIdAndStatus(accompanyId) private fun existsByUser(accompanyId: Long, userId: Long) = accompanyJoinRequestRepository.existsByAccompanyIdAndUserId(accompanyId, userId) + + private fun isBelowMemberLimit(accompany: Accompany, accompanyId: Long) = + accompany.memberCount < getAcceptedCount(accompanyId) + 1 } \ No newline at end of file From c98b418dd1461167658eb777ecc6805050dd4b4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Mon, 16 Sep 2024 18:40:20 +0900 Subject: [PATCH 145/174] =?UTF-8?q?feat:=20accompany=20=ED=95=84=ED=84=B0?= =?UTF-8?q?=EB=A7=81=20=EA=B2=80=EC=83=89=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../accompany/AccompanyApplicationService.kt | 13 +- .../accompany/dto/AccompanyResponseDto.kt | 40 +++++- .../dto/AccompanyServiceRequestDto.kt | 34 +++++- .../accompany/AccompanyController.kt | 18 ++- .../accompany/dto/AccompanyRequestDto.kt | 42 ++++++- .../withaeng/domain/accompany/Accompany.kt | 1 + .../accompany/AccompanyRepositoryCustom.kt | 7 ++ .../accompany/AccompanyRepositoryImpl.kt | 114 ++++++++++++++++++ .../domain/accompany/AccompanyService.kt | 8 ++ .../accompany/{ => dto}/AccompanyDto.kt | 39 +++--- .../domain/accompany/dto/AccompanyQuery.kt | 21 ++++ 11 files changed, 312 insertions(+), 25 deletions(-) rename withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/{ => dto}/AccompanyDto.kt (67%) create mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/dto/AccompanyQuery.kt diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt index 7e6b24f..7f13c45 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt @@ -1,11 +1,14 @@ package com.withaeng.api.applicationservice.accompany import com.withaeng.api.applicationservice.accompany.dto.* +import com.withaeng.api.applicationservice.common.PagingResponse +import com.withaeng.api.applicationservice.common.toPaging import com.withaeng.common.exception.WithaengException import com.withaeng.common.exception.WithaengExceptionType import com.withaeng.domain.accompany.AccompanyService import com.withaeng.domain.accompanyjoinrequests.AccompanyJoinRequestService import com.withaeng.domain.accompanylike.AccompanyLikeService +import org.springframework.data.domain.Pageable import org.springframework.stereotype.Service @Service @@ -26,6 +29,15 @@ class AccompanyApplicationService( return accompanyDto.toAccompanyResponse(likeCount) } + fun search( + pageable: Pageable, + request: SearchAccompanyServiceRequest, + ): PagingResponse> { + val pageResult = accompanyService.search(pageable, request.toQuery()) + .map { accompanyDto -> accompanyDto.toAccompanyResponse() } + return PagingResponse(pageResult.content, pageResult.toPaging()) + } + fun detail(accompanyId: Long, userId: Long?): FindAccompanyResponse { increaseViewCount(accompanyId) val accompanyDto = accompanyService.detail(accompanyId) @@ -64,7 +76,6 @@ class AccompanyApplicationService( accompanyJoinRequestService.create(accompanyId, userId) } - private fun validateCreator(createUserId: Long, requestUserId: Long) { if (createUserId == requestUserId) { throw WithaengException.of( diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyResponseDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyResponseDto.kt index c0a862d..d36f5fe 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyResponseDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyResponseDto.kt @@ -1,7 +1,9 @@ package com.withaeng.api.applicationservice.accompany.dto import com.withaeng.domain.accompany.AccompanyDestination -import com.withaeng.domain.accompany.AccompanyDto +import com.withaeng.domain.accompany.AccompanyStatus +import com.withaeng.domain.accompany.dto.AccompanyDto +import com.withaeng.domain.accompany.dto.SearchAccompanyDto import com.withaeng.domain.user.UserPreferAccompanyGender import java.time.LocalDate @@ -41,4 +43,40 @@ fun AccompanyDto.toAccompanyResponse(likeCount: Long): AccompanyResponse = Accom endAccompanyAge = endAccompanyAge.value, preferGender = preferGender, tags = tags, +) + +data class AccompanySummaryResponse( + val id: Long, + val bannerImageUrl: String?, + val status: AccompanyStatus, + val startDate: LocalDate, + val endDate: LocalDate, + val currentMemberCount: Long, + val maxMemberCount: Long, + val title: String, + val tags: Set? = null, + val host: AccompanyHostSummaryResponse, +) + +data class AccompanyHostSummaryResponse( + val id: Long, + val profileImageUrl: String?, + val nickname: String, +) + +fun SearchAccompanyDto.toAccompanyResponse(): AccompanySummaryResponse = AccompanySummaryResponse( + id = id, + bannerImageUrl = bannerImageUrl, + status = status, + startDate = startDate, + endDate = endDate, + currentMemberCount = currentMemberCount, + maxMemberCount = maxMemberCount, + title = title, + tags = tags, + host = AccompanyHostSummaryResponse( + id = host.id, + nickname = host.nickname, + profileImageUrl = host.profileImageUrl, + ), ) \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt index 6ad69eb..bc6a732 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt @@ -1,6 +1,9 @@ package com.withaeng.api.applicationservice.accompany.dto import com.withaeng.domain.accompany.* +import com.withaeng.domain.accompany.dto.CreateAccompanyDto +import com.withaeng.domain.accompany.dto.SearchAccompanyQuery +import com.withaeng.domain.accompany.dto.UpdateAccompanyDto import com.withaeng.domain.user.UserPreferAccompanyGender import java.time.LocalDate @@ -58,8 +61,29 @@ fun UpdateAccompanyServiceRequest.toDomainDto(): UpdateAccompanyDto { } data class SearchAccompanyServiceRequest( - val orderBy: String, - val isDescending: Boolean, - val pageIndex: Long, - val pageSize: Long, -) \ No newline at end of file + val continent: Continent? = null, + val country: Country? = null, + val city: City? = null, + val startDate: LocalDate? = null, + val endDate: LocalDate? = null, + val minMemberCount: Int? = null, + val maxMemberCount: Int? = null, + val minAllowedAge: AccompanyAge? = null, + val maxAllowedAge: AccompanyAge? = null, + val preferGender: UserPreferAccompanyGender? = null, +) + +fun SearchAccompanyServiceRequest.toQuery(): SearchAccompanyQuery { + return SearchAccompanyQuery( + continent = continent, + country = country, + city = city, + startDate = startDate, + endDate = endDate, + minMemberCount = minMemberCount, + maxMemberCount = maxMemberCount, + minAllowedAge = minAllowedAge, + maxAllowedAge = maxAllowedAge, + preferGender = preferGender, + ) +} \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt index 855bdfd..58bc5f7 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt @@ -2,9 +2,12 @@ package com.withaeng.api.controller.accompany import com.withaeng.api.applicationservice.accompany.AccompanyApplicationService import com.withaeng.api.applicationservice.accompany.dto.AccompanyResponse +import com.withaeng.api.applicationservice.accompany.dto.AccompanySummaryResponse import com.withaeng.api.applicationservice.accompany.dto.FindAccompanyResponse import com.withaeng.api.common.ApiResponse +import com.withaeng.api.common.PageInfoRequest import com.withaeng.api.controller.accompany.dto.CreateAccompanyRequest +import com.withaeng.api.controller.accompany.dto.SearchAccompanyRequest import com.withaeng.api.controller.accompany.dto.UpdateAccompanyRequest import com.withaeng.api.controller.accompany.dto.toServiceRequest import com.withaeng.api.security.authentication.UserInfo @@ -13,6 +16,7 @@ import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.security.SecurityRequirement import io.swagger.v3.oas.annotations.tags.Tag import jakarta.validation.Valid +import org.springdoc.core.annotations.ParameterObject import org.springframework.http.HttpStatus import org.springframework.web.bind.annotation.* @@ -50,6 +54,17 @@ class AccompanyController( ) } + @Operation(summary = "Search Accompany", description = "동행 검색 API (필터링만 지원)") + @GetMapping("/search") + fun search( + @ParameterObject pageInfoRequest: PageInfoRequest, + @ParameterObject request: SearchAccompanyRequest, + ): ApiResponse> { + return ApiResponse.success( + accompanyApplicationService.search(pageInfoRequest.toPageRequest(), request.toServiceRequest()) + ) + } + @Operation(summary = "Retrieve All Accompany API", description = "모든 동행 게시글 조회 API") @GetMapping("/all") fun retrieveAll(): ApiResponse> { @@ -72,7 +87,8 @@ class AccompanyController( return ApiResponse.success( accompanyApplicationService.update( param.toServiceRequest( - accompanyId = accompanyId, userId = userInfo.id + accompanyId = accompanyId, + userId = userInfo.id ) ) ) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt index eac470d..a45e286 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt @@ -2,9 +2,9 @@ package com.withaeng.api.controller.accompany.dto import com.fasterxml.jackson.databind.annotation.JsonDeserialize import com.withaeng.api.applicationservice.accompany.dto.CreateAccompanyServiceRequest +import com.withaeng.api.applicationservice.accompany.dto.SearchAccompanyServiceRequest import com.withaeng.api.applicationservice.accompany.dto.UpdateAccompanyServiceRequest -import com.withaeng.domain.accompany.AccompanyAge -import com.withaeng.domain.accompany.AccompanyAgeDeserializer +import com.withaeng.domain.accompany.* import com.withaeng.domain.user.UserPreferAccompanyGender import io.swagger.v3.oas.annotations.media.Schema import java.time.LocalDate @@ -93,4 +93,40 @@ fun UpdateAccompanyRequest.toServiceRequest( userId = userId, content = content, tags = tags, -) \ No newline at end of file +) + +data class SearchAccompanyRequest( + @Schema(description = "동행 대륙") + val continent: Continent? = null, + @Schema(description = "동행 나라") + val country: Country? = null, + @Schema(description = "동행 도시") + val city: City? = null, + @Schema(description = "동행 시작 날짜") + val startDate: LocalDate? = null, + @Schema(description = "동행 종료 날짜") + val endDate: LocalDate? = null, + @Schema(description = "동행 최소 인원") + val minMemberCount: Int? = null, + @Schema(description = "동행 최대 인원") + val maxMemberCount: Int? = null, + @Schema(description = "동행 최소 연령대") + val minAllowedAge: AccompanyAge? = null, + @Schema(description = "동행 최대 연령대") + val maxAllowedAge: AccompanyAge? = null, + @Schema(description = "동행 선호 성별") + val preferGender: UserPreferAccompanyGender? = null, +) + +fun SearchAccompanyRequest.toServiceRequest(): SearchAccompanyServiceRequest = SearchAccompanyServiceRequest( + continent = continent, + country = country, + city = city, + startDate = startDate, + endDate = endDate, + minMemberCount = minMemberCount, + maxMemberCount = maxMemberCount, + minAllowedAge = minAllowedAge, + maxAllowedAge = maxAllowedAge, + preferGender = preferGender +) diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt index 7ee0c45..12a07bc 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt @@ -1,6 +1,7 @@ package com.withaeng.domain.accompany import com.withaeng.domain.BaseEntity +import com.withaeng.domain.accompany.dto.CreateAccompanyDto import com.withaeng.domain.accompanyrequests.AccompanyJoinRequest import com.withaeng.domain.accompanystatistics.AccompanyStatistics import com.withaeng.domain.converter.AccompanyTagsConverter diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryCustom.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryCustom.kt index 5cefa2a..8005dd5 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryCustom.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryCustom.kt @@ -1,5 +1,12 @@ package com.withaeng.domain.accompany +import com.withaeng.domain.accompany.dto.SearchAccompanyDto +import com.withaeng.domain.accompany.dto.SearchAccompanyQuery +import org.springframework.data.domain.Page +import org.springframework.data.domain.Pageable + interface AccompanyRepositoryCustom { fun findAccompanyDetail(accompanyId: Long): FindAccompanyDto? + + fun searchAccompanies(pageable: Pageable, query: SearchAccompanyQuery): Page } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryImpl.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryImpl.kt index eb6c197..6a532e6 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryImpl.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryImpl.kt @@ -3,9 +3,17 @@ package com.withaeng.domain.accompany import com.querydsl.core.types.dsl.BooleanExpression import com.querydsl.jpa.impl.JPAQueryFactory import com.withaeng.domain.accompany.QAccompany.accompany +import com.withaeng.domain.accompany.dto.* import com.withaeng.domain.accompanylike.QAccompanyLike.accompanyLike +import com.withaeng.domain.accompanyrequests.AccompanyJoinRequestStatus +import com.withaeng.domain.accompanyrequests.QAccompanyJoinRequest.accompanyJoinRequest import com.withaeng.domain.accompanystatistics.QAccompanyStatistics.accompanyStatistics import com.withaeng.domain.user.QUser.user +import com.withaeng.domain.user.UserPreferAccompanyGender +import org.springframework.data.domain.Page +import org.springframework.data.domain.Pageable +import org.springframework.data.support.PageableExecutionUtils +import java.time.LocalDate class AccompanyRepositoryImpl( @@ -56,6 +64,112 @@ class AccompanyRepositoryImpl( .fetchOne() } + override fun searchAccompanies(pageable: Pageable, query: SearchAccompanyQuery): Page { + val result = queryFactory + .select( + QSearchAccompanyDto( + accompany.id, + accompany.bannerImageUrl, + accompany.accompanyStatus, + accompany.startTripDate, + accompany.endTripDate, + accompanyJoinRequest.count(), + accompany.memberCount, + accompany.title, + accompany.tags, + QSearchAccompanyHostDto( + user.id, + user.profile.nickname, + user.profile.profileImageUrl, + ), + ) + ) + .from(accompany) + .innerJoin(user) + .on(accompany.userId.eq(user.id)) + .leftJoin(accompanyJoinRequest).on( + accompanyJoinRequest.accompany.eq(accompany) + .and(accompanyJoinRequest.status.eq(AccompanyJoinRequestStatus.ACCEPT)) + ) + .groupBy( + accompany.id, + accompany.bannerImageUrl, + accompany.accompanyStatus, + user.id, + user.profile.nickname, + user.profile.profileImageUrl, + accompany.startTripDate, + accompany.endTripDate, + accompany.memberCount, + accompany.title, + accompany.tags + ) + .where( + continentEq(query.continent), + countryEq(query.country), + cityEq(query.city), + containTripDate(query.startDate, query.endDate), + containMemberCount(query.minMemberCount, query.maxMemberCount), + containAllowedAge(query.minAllowedAge, query.maxAllowedAge), + preferGenderEq(query.preferGender), + ) + .offset(pageable.offset) + .limit(pageable.pageSize.toLong()) + .fetch() + + val countQuery = queryFactory + .select(accompany.id.count()) + .from(accompany) + .innerJoin(user) + .on(accompany.userId.eq(user.id)) + .leftJoin(accompanyJoinRequest).on( + accompanyJoinRequest.accompany.eq(accompany) + .and(accompanyJoinRequest.status.eq(AccompanyJoinRequestStatus.ACCEPT)) + ) + .where( + continentEq(query.continent), + countryEq(query.country), + cityEq(query.city), + containTripDate(query.startDate, query.endDate), + containMemberCount(query.minMemberCount, query.maxMemberCount), + containAllowedAge(query.minAllowedAge, query.maxAllowedAge), + preferGenderEq(query.preferGender), + ) + + return PageableExecutionUtils.getPage(result, pageable) { countQuery.fetchOne() ?: 0L } + } + + private fun continentEq(continent: Continent?): BooleanExpression? { + return continent?.let { accompany.accompanyDestination.continent.eq(it) } + } + + private fun countryEq(country: Country?): BooleanExpression? { + return country?.let { accompany.accompanyDestination.country.eq(it) } + } + + private fun cityEq(city: City?): BooleanExpression? { + return city?.let { accompany.accompanyDestination.city.eq(it) } + } + + private fun containTripDate(startDate: LocalDate?, endDate: LocalDate?): BooleanExpression? { + return startDate?.let { accompany.endTripDate.goe(startDate) } + ?.and(endDate?.let { accompany.startTripDate.loe(endDate) }) + } + + private fun containMemberCount(minMemberCount: Int?, maxMemberCount: Int?): BooleanExpression? { + return minMemberCount?.let { accompany.memberCount.goe(minMemberCount) } + ?.and(maxMemberCount?.let { accompany.memberCount.loe(maxMemberCount) }) + } + + private fun containAllowedAge(minAllowedAge: AccompanyAge?, maxAllowedAge: AccompanyAge?): BooleanExpression? { + return minAllowedAge?.let { accompany.endAccompanyAge.goe(minAllowedAge.value) } + ?.and(maxAllowedAge?.let { accompany.startAccompanyAge.loe(maxAllowedAge.value) }) + } + + private fun preferGenderEq(preferGender: UserPreferAccompanyGender?): BooleanExpression? { + return preferGender?.let { accompany.preferGender.eq(it) } + } + private fun accompanyIdEq(accompanyId: Long): BooleanExpression { return accompany.id.eq(accompanyId) } diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyService.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyService.kt index 94196de..42a9a01 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyService.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyService.kt @@ -2,6 +2,9 @@ package com.withaeng.domain.accompany import com.withaeng.common.exception.WithaengException import com.withaeng.common.exception.WithaengExceptionType +import com.withaeng.domain.accompany.dto.* +import org.springframework.data.domain.Page +import org.springframework.data.domain.Pageable import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -36,6 +39,11 @@ class AccompanyService( return accompany.toDto() } + @Transactional(readOnly = true) + fun search(pageable: Pageable, query: SearchAccompanyQuery): Page { + return accompanyRepository.searchAccompanies(pageable, query) + } + @Transactional(readOnly = true) fun detail(accompanyId: Long): FindAccompanyDto { return accompanyRepository.findAccompanyDetail(accompanyId) diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/dto/AccompanyDto.kt similarity index 67% rename from withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyDto.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/dto/AccompanyDto.kt index d33dbc9..6613bb3 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/dto/AccompanyDto.kt @@ -1,5 +1,10 @@ -package com.withaeng.domain.accompany +package com.withaeng.domain.accompany.dto +import com.querydsl.core.annotations.QueryProjection +import com.withaeng.domain.accompany.Accompany +import com.withaeng.domain.accompany.AccompanyAge +import com.withaeng.domain.accompany.AccompanyDestination +import com.withaeng.domain.accompany.AccompanyStatus import com.withaeng.domain.user.UserPreferAccompanyGender import java.time.LocalDate @@ -41,7 +46,7 @@ data class AccompanyDto( val startAccompanyAge: AccompanyAge, val endAccompanyAge: AccompanyAge, val preferGender: UserPreferAccompanyGender, - val tags: Set? = null, + val tags: Set? = emptySet(), ) fun Accompany.toDto(): AccompanyDto = AccompanyDto( @@ -63,15 +68,21 @@ fun Accompany.toDto(): AccompanyDto = AccompanyDto( tags = tags, ) -data class SearchAccompanyDto( - var viewCntOrder: Boolean, // 조회수 높은 순서 - var likeCntOrder: Boolean, // 좋아요 높은 순서 - var startTripDate: LocalDate, // 동행 모집 시작일시 - var endTripDate: LocalDate, // 동행 모집 마감일시 - var pageIndex: Long, - var pageSize: Long, -) { - fun getCurrentPage(): Long { - return (this.pageIndex - 1) * this.pageSize - } -} \ No newline at end of file +data class SearchAccompanyDto @QueryProjection constructor( + val id: Long, + val bannerImageUrl: String?, + val status: AccompanyStatus, + val startDate: LocalDate, + val endDate: LocalDate, + val currentMemberCount: Long, + val maxMemberCount: Long, + val title: String, + val tags: Set? = emptySet(), + val host: SearchAccompanyHostDto, +) + +data class SearchAccompanyHostDto @QueryProjection constructor( + val id: Long, + val nickname: String, + val profileImageUrl: String?, +) diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/dto/AccompanyQuery.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/dto/AccompanyQuery.kt new file mode 100644 index 0000000..4f86926 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/dto/AccompanyQuery.kt @@ -0,0 +1,21 @@ +package com.withaeng.domain.accompany.dto + +import com.withaeng.domain.accompany.AccompanyAge +import com.withaeng.domain.accompany.City +import com.withaeng.domain.accompany.Continent +import com.withaeng.domain.accompany.Country +import com.withaeng.domain.user.UserPreferAccompanyGender +import java.time.LocalDate + +data class SearchAccompanyQuery( + val continent: Continent? = null, + val country: Country? = null, + val city: City? = null, + val startDate: LocalDate? = null, + val endDate: LocalDate? = null, + val minMemberCount: Int? = null, + val maxMemberCount: Int? = null, + val minAllowedAge: AccompanyAge? = null, + val maxAllowedAge: AccompanyAge? = null, + val preferGender: UserPreferAccompanyGender? = null, +) \ No newline at end of file From 79638de0d5c6a1074feb0ca7487a39ce594c3c96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Mon, 16 Sep 2024 18:41:24 +0900 Subject: [PATCH 146/174] =?UTF-8?q?chore:=20dto=20=ED=95=9C=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=EB=A1=9C=20=EB=AA=A8=EC=9C=BC=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../accompany/dto/FindAccompanyResponseDto.kt | 4 +-- .../accompany/AccompanyRepositoryCustom.kt | 1 + .../domain/accompany/FindAccompanyDto.kt | 25 -------------- .../accompany/FindAccompanyUserInfoDto.kt | 16 --------- .../domain/accompany/dto/AccompanyDto.kt | 34 +++++++++++++++++++ 5 files changed, 37 insertions(+), 43 deletions(-) delete mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/FindAccompanyDto.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/FindAccompanyUserInfoDto.kt diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/FindAccompanyResponseDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/FindAccompanyResponseDto.kt index 4df5e8c..6bc553f 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/FindAccompanyResponseDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/FindAccompanyResponseDto.kt @@ -1,8 +1,8 @@ package com.withaeng.api.applicationservice.accompany.dto import com.withaeng.domain.accompany.AccompanyDestination -import com.withaeng.domain.accompany.FindAccompanyDto -import com.withaeng.domain.accompany.FindAccompanyUserInfoDto +import com.withaeng.domain.accompany.dto.FindAccompanyDto +import com.withaeng.domain.accompany.dto.FindAccompanyUserInfoDto import com.withaeng.domain.user.UserPreferAccompanyGender import java.time.LocalDate diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryCustom.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryCustom.kt index 8005dd5..f719ca7 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryCustom.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryCustom.kt @@ -1,5 +1,6 @@ package com.withaeng.domain.accompany +import com.withaeng.domain.accompany.dto.FindAccompanyDto import com.withaeng.domain.accompany.dto.SearchAccompanyDto import com.withaeng.domain.accompany.dto.SearchAccompanyQuery import org.springframework.data.domain.Page diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/FindAccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/FindAccompanyDto.kt deleted file mode 100644 index 58a291c..0000000 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/FindAccompanyDto.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.withaeng.domain.accompany - -import com.querydsl.core.annotations.QueryProjection -import com.withaeng.domain.user.UserPreferAccompanyGender -import java.time.LocalDate - -data class FindAccompanyDto @QueryProjection constructor( - val id: Long, - val userId: Long, - val title: String, - val content: String, - val destination: AccompanyDestination, - val startTripDate: LocalDate, - val endTripDate: LocalDate, - val bannerImageUrl: String? = null, - val memberCount: Long, - val viewCount: Long, - val openKakaoUrl: String, - val startAccompanyAge: Int, - val endAccompanyAge: Int, - val preferGender: UserPreferAccompanyGender, - val tags: Set? = emptySet(), - val likeCount: Long = 0, - val author: FindAccompanyUserInfoDto, -) \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/FindAccompanyUserInfoDto.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/FindAccompanyUserInfoDto.kt deleted file mode 100644 index b78e937..0000000 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/FindAccompanyUserInfoDto.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.withaeng.domain.accompany - -import com.querydsl.core.annotations.QueryProjection -import com.withaeng.domain.user.Gender -import java.time.LocalDateTime - -data class FindAccompanyUserInfoDto @QueryProjection constructor( - val nickname: String, - val profileImageUrl: String?, - val gender: Gender, - val introduction: String?, - val joinDate: LocalDateTime, - // TODO : 여행 관심사 Set 추가 필요 - // TODO : 온도 추가 필요 - // TODO : 연령대 추가 필요 -) \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/dto/AccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/dto/AccompanyDto.kt index 6613bb3..6531147 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/dto/AccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/dto/AccompanyDto.kt @@ -5,8 +5,10 @@ import com.withaeng.domain.accompany.Accompany import com.withaeng.domain.accompany.AccompanyAge import com.withaeng.domain.accompany.AccompanyDestination import com.withaeng.domain.accompany.AccompanyStatus +import com.withaeng.domain.user.Gender import com.withaeng.domain.user.UserPreferAccompanyGender import java.time.LocalDate +import java.time.LocalDateTime data class CreateAccompanyDto( val userId: Long, @@ -86,3 +88,35 @@ data class SearchAccompanyHostDto @QueryProjection constructor( val nickname: String, val profileImageUrl: String?, ) + + +data class FindAccompanyDto @QueryProjection constructor( + val id: Long, + val userId: Long, + val title: String, + val content: String, + val destination: AccompanyDestination, + val startTripDate: LocalDate, + val endTripDate: LocalDate, + val bannerImageUrl: String? = null, + val memberCount: Long, + val viewCount: Long, + val openKakaoUrl: String, + val startAccompanyAge: Int, + val endAccompanyAge: Int, + val preferGender: UserPreferAccompanyGender, + val tags: Set? = emptySet(), + val likeCount: Long = 0, + val author: FindAccompanyUserInfoDto, +) + +data class FindAccompanyUserInfoDto @QueryProjection constructor( + val nickname: String, + val profileImageUrl: String?, + val gender: Gender, + val introduction: String?, + val joinDate: LocalDateTime, + // TODO : 여행 관심사 Set 추가 필요 + // TODO : 온도 추가 필요 + // TODO : 연령대 추가 필요 +) \ No newline at end of file From 370928593744d423d00ee48c33056c811d8cab6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Mon, 16 Sep 2024 18:43:41 +0900 Subject: [PATCH 147/174] =?UTF-8?q?chore:=20PreferGender=20Accompany=20?= =?UTF-8?q?=ED=8C=A8=ED=82=A4=EC=A7=80=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../accompany/dto/AccompanyResponseDto.kt | 4 ++-- .../accompany/dto/AccompanyServiceRequestDto.kt | 5 ++--- .../accompany/dto/FindAccompanyResponseDto.kt | 4 ++-- .../controller/accompany/dto/AccompanyRequestDto.kt | 5 ++--- .../kotlin/com/withaeng/api/jackson/EnumModule.kt | 1 - .../com/withaeng/domain/accompany/Accompany.kt | 3 +-- .../domain/accompany/AccompanyPreferGender.kt | 5 +++++ .../domain/accompany/AccompanyRepositoryImpl.kt | 3 +-- .../withaeng/domain/accompany/dto/AccompanyDto.kt | 12 ++++-------- .../withaeng/domain/accompany/dto/AccompanyQuery.kt | 8 ++------ .../domain/user/UserPreferAccompanyGender.kt | 5 ----- 11 files changed, 21 insertions(+), 34 deletions(-) create mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyPreferGender.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserPreferAccompanyGender.kt diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyResponseDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyResponseDto.kt index d36f5fe..0e5daaf 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyResponseDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyResponseDto.kt @@ -1,10 +1,10 @@ package com.withaeng.api.applicationservice.accompany.dto import com.withaeng.domain.accompany.AccompanyDestination +import com.withaeng.domain.accompany.AccompanyPreferGender import com.withaeng.domain.accompany.AccompanyStatus import com.withaeng.domain.accompany.dto.AccompanyDto import com.withaeng.domain.accompany.dto.SearchAccompanyDto -import com.withaeng.domain.user.UserPreferAccompanyGender import java.time.LocalDate data class AccompanyResponse( @@ -23,7 +23,7 @@ data class AccompanyResponse( val openKakaoUrl: String? = null, val startAccompanyAge: Int, val endAccompanyAge: Int, - val preferGender: UserPreferAccompanyGender, + val preferGender: AccompanyPreferGender, ) fun AccompanyDto.toAccompanyResponse(likeCount: Long): AccompanyResponse = AccompanyResponse( diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt index bc6a732..b47d334 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt @@ -4,7 +4,6 @@ import com.withaeng.domain.accompany.* import com.withaeng.domain.accompany.dto.CreateAccompanyDto import com.withaeng.domain.accompany.dto.SearchAccompanyQuery import com.withaeng.domain.accompany.dto.UpdateAccompanyDto -import com.withaeng.domain.user.UserPreferAccompanyGender import java.time.LocalDate data class CreateAccompanyServiceRequest( @@ -22,7 +21,7 @@ data class CreateAccompanyServiceRequest( val openKakaoUrl: String, val startAccompanyAge: AccompanyAge, val endAccompanyAge: AccompanyAge, - val preferGender: UserPreferAccompanyGender, + val preferGender: AccompanyPreferGender, ) fun CreateAccompanyServiceRequest.toDomainDto(): CreateAccompanyDto = CreateAccompanyDto( @@ -70,7 +69,7 @@ data class SearchAccompanyServiceRequest( val maxMemberCount: Int? = null, val minAllowedAge: AccompanyAge? = null, val maxAllowedAge: AccompanyAge? = null, - val preferGender: UserPreferAccompanyGender? = null, + val preferGender: AccompanyPreferGender? = null, ) fun SearchAccompanyServiceRequest.toQuery(): SearchAccompanyQuery { diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/FindAccompanyResponseDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/FindAccompanyResponseDto.kt index 6bc553f..37e9698 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/FindAccompanyResponseDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/FindAccompanyResponseDto.kt @@ -1,9 +1,9 @@ package com.withaeng.api.applicationservice.accompany.dto import com.withaeng.domain.accompany.AccompanyDestination +import com.withaeng.domain.accompany.AccompanyPreferGender import com.withaeng.domain.accompany.dto.FindAccompanyDto import com.withaeng.domain.accompany.dto.FindAccompanyUserInfoDto -import com.withaeng.domain.user.UserPreferAccompanyGender import java.time.LocalDate data class FindAccompanyResponse( @@ -20,7 +20,7 @@ data class FindAccompanyResponse( val openKakaoUrl: String, val startAccompanyAge: Int, val endAccompanyAge: Int, - val preferGender: UserPreferAccompanyGender, + val preferGender: AccompanyPreferGender, val tags: Set? = emptySet(), val likeCount: Long = 0, val author: FindAccompanyUserInfoDto, diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt index a45e286..6c27f10 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt @@ -5,7 +5,6 @@ import com.withaeng.api.applicationservice.accompany.dto.CreateAccompanyServiceR import com.withaeng.api.applicationservice.accompany.dto.SearchAccompanyServiceRequest import com.withaeng.api.applicationservice.accompany.dto.UpdateAccompanyServiceRequest import com.withaeng.domain.accompany.* -import com.withaeng.domain.user.UserPreferAccompanyGender import io.swagger.v3.oas.annotations.media.Schema import java.time.LocalDate @@ -53,7 +52,7 @@ data class CreateAccompanyRequest( val endAccompanyAge: AccompanyAge, @Schema(description = "동행 선호 성별") - val preferGender: UserPreferAccompanyGender, + val preferGender: AccompanyPreferGender, ) @Schema(description = "[Request] 동행 게시글 수정") @@ -115,7 +114,7 @@ data class SearchAccompanyRequest( @Schema(description = "동행 최대 연령대") val maxAllowedAge: AccompanyAge? = null, @Schema(description = "동행 선호 성별") - val preferGender: UserPreferAccompanyGender? = null, + val preferGender: AccompanyPreferGender? = null, ) fun SearchAccompanyRequest.toServiceRequest(): SearchAccompanyServiceRequest = SearchAccompanyServiceRequest( diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/jackson/EnumModule.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/jackson/EnumModule.kt index f470094..b937a72 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/jackson/EnumModule.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/jackson/EnumModule.kt @@ -12,7 +12,6 @@ class EnumModule : SimpleModule() { addSimpleEnumDeserializer() addSimpleEnumDeserializer() addSimpleEnumDeserializer() - addSimpleEnumDeserializer() addSimpleEnumDeserializer() addSimpleEnumDeserializer() } diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt index 12a07bc..2a9e22c 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt @@ -5,7 +5,6 @@ import com.withaeng.domain.accompany.dto.CreateAccompanyDto import com.withaeng.domain.accompanyrequests.AccompanyJoinRequest import com.withaeng.domain.accompanystatistics.AccompanyStatistics import com.withaeng.domain.converter.AccompanyTagsConverter -import com.withaeng.domain.user.UserPreferAccompanyGender import jakarta.persistence.* import org.hibernate.annotations.Comment import org.hibernate.annotations.DynamicUpdate @@ -67,7 +66,7 @@ class Accompany( @Column(name = "prefer_gender", nullable = false) @Comment("동행 선호 성별") - var preferGender: UserPreferAccompanyGender, + var preferGender: AccompanyPreferGender, @Convert(converter = AccompanyTagsConverter::class) @Column(name = "tags", nullable = false) diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyPreferGender.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyPreferGender.kt new file mode 100644 index 0000000..55b2292 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyPreferGender.kt @@ -0,0 +1,5 @@ +package com.withaeng.domain.accompany + +enum class AccompanyPreferGender { + MALE, FEMALE, NO_PREFERENCE +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryImpl.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryImpl.kt index 6a532e6..0cd6d65 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryImpl.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryImpl.kt @@ -9,7 +9,6 @@ import com.withaeng.domain.accompanyrequests.AccompanyJoinRequestStatus import com.withaeng.domain.accompanyrequests.QAccompanyJoinRequest.accompanyJoinRequest import com.withaeng.domain.accompanystatistics.QAccompanyStatistics.accompanyStatistics import com.withaeng.domain.user.QUser.user -import com.withaeng.domain.user.UserPreferAccompanyGender import org.springframework.data.domain.Page import org.springframework.data.domain.Pageable import org.springframework.data.support.PageableExecutionUtils @@ -166,7 +165,7 @@ class AccompanyRepositoryImpl( ?.and(maxAllowedAge?.let { accompany.startAccompanyAge.loe(maxAllowedAge.value) }) } - private fun preferGenderEq(preferGender: UserPreferAccompanyGender?): BooleanExpression? { + private fun preferGenderEq(preferGender: AccompanyPreferGender?): BooleanExpression? { return preferGender?.let { accompany.preferGender.eq(it) } } diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/dto/AccompanyDto.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/dto/AccompanyDto.kt index 6531147..77d0657 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/dto/AccompanyDto.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/dto/AccompanyDto.kt @@ -1,12 +1,8 @@ package com.withaeng.domain.accompany.dto import com.querydsl.core.annotations.QueryProjection -import com.withaeng.domain.accompany.Accompany -import com.withaeng.domain.accompany.AccompanyAge -import com.withaeng.domain.accompany.AccompanyDestination -import com.withaeng.domain.accompany.AccompanyStatus +import com.withaeng.domain.accompany.* import com.withaeng.domain.user.Gender -import com.withaeng.domain.user.UserPreferAccompanyGender import java.time.LocalDate import java.time.LocalDateTime @@ -23,7 +19,7 @@ data class CreateAccompanyDto( val openKakaoUrl: String, val startAccompanyAge: AccompanyAge, val endAccompanyAge: AccompanyAge, - val preferGender: UserPreferAccompanyGender, + val preferGender: AccompanyPreferGender, ) data class UpdateAccompanyDto( @@ -47,7 +43,7 @@ data class AccompanyDto( val openKakaoUrl: String, val startAccompanyAge: AccompanyAge, val endAccompanyAge: AccompanyAge, - val preferGender: UserPreferAccompanyGender, + val preferGender: AccompanyPreferGender, val tags: Set? = emptySet(), ) @@ -104,7 +100,7 @@ data class FindAccompanyDto @QueryProjection constructor( val openKakaoUrl: String, val startAccompanyAge: Int, val endAccompanyAge: Int, - val preferGender: UserPreferAccompanyGender, + val preferGender: AccompanyPreferGender, val tags: Set? = emptySet(), val likeCount: Long = 0, val author: FindAccompanyUserInfoDto, diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/dto/AccompanyQuery.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/dto/AccompanyQuery.kt index 4f86926..61d808b 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/dto/AccompanyQuery.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/dto/AccompanyQuery.kt @@ -1,10 +1,6 @@ package com.withaeng.domain.accompany.dto -import com.withaeng.domain.accompany.AccompanyAge -import com.withaeng.domain.accompany.City -import com.withaeng.domain.accompany.Continent -import com.withaeng.domain.accompany.Country -import com.withaeng.domain.user.UserPreferAccompanyGender +import com.withaeng.domain.accompany.* import java.time.LocalDate data class SearchAccompanyQuery( @@ -17,5 +13,5 @@ data class SearchAccompanyQuery( val maxMemberCount: Int? = null, val minAllowedAge: AccompanyAge? = null, val maxAllowedAge: AccompanyAge? = null, - val preferGender: UserPreferAccompanyGender? = null, + val preferGender: AccompanyPreferGender? = null, ) \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserPreferAccompanyGender.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserPreferAccompanyGender.kt deleted file mode 100644 index 606605b..0000000 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserPreferAccompanyGender.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.withaeng.domain.user - -enum class UserPreferAccompanyGender { - MALE, FEMALE, NO_PREFERENCE -} \ No newline at end of file From 3410d52af710fb8d8b2376301507b8b99373cc95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Mon, 16 Sep 2024 19:05:55 +0900 Subject: [PATCH 148/174] =?UTF-8?q?fix:=20PreferGender=20enumurated=20?= =?UTF-8?q?=EC=96=B4=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=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 --- .../src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt index 2a9e22c..c176fcd 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt @@ -64,6 +64,7 @@ class Accompany( @Comment("동행 종료 연령") var endAccompanyAge: Int, + @Enumerated(EnumType.STRING) @Column(name = "prefer_gender", nullable = false) @Comment("동행 선호 성별") var preferGender: AccompanyPreferGender, From ce107da66ef9851e0be38454857caf702b22adcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Mon, 16 Sep 2024 20:08:57 +0900 Subject: [PATCH 149/174] =?UTF-8?q?fix:=20=EB=8F=99=ED=96=89=20=EA=B2=80?= =?UTF-8?q?=EC=83=89=EC=8B=9C=20=EB=AA=A8=EC=A7=91=EC=A4=91=EC=9D=B8=20?= =?UTF-8?q?=EB=8F=99=ED=96=89=EB=A7=8C=20=EA=B2=80=EC=83=89=EB=90=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95,=20=EC=B5=9C=EC=8B=A0?= =?UTF-8?q?=EC=88=9C=20=EC=A0=95=EB=A0=AC=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../withaeng/domain/accompany/AccompanyRepositoryImpl.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryImpl.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryImpl.kt index 0cd6d65..ae5e72a 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryImpl.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryImpl.kt @@ -104,6 +104,7 @@ class AccompanyRepositoryImpl( accompany.tags ) .where( + statusEq(AccompanyStatus.ING), continentEq(query.continent), countryEq(query.country), cityEq(query.city), @@ -112,6 +113,7 @@ class AccompanyRepositoryImpl( containAllowedAge(query.minAllowedAge, query.maxAllowedAge), preferGenderEq(query.preferGender), ) + .orderBy(accompany.id.desc()) .offset(pageable.offset) .limit(pageable.pageSize.toLong()) .fetch() @@ -138,6 +140,10 @@ class AccompanyRepositoryImpl( return PageableExecutionUtils.getPage(result, pageable) { countQuery.fetchOne() ?: 0L } } + private fun statusEq(status: AccompanyStatus): BooleanExpression? { + return accompany.accompanyStatus.eq(status) + } + private fun continentEq(continent: Continent?): BooleanExpression? { return continent?.let { accompany.accompanyDestination.continent.eq(it) } } From f93af64ed6be1a0ee8e0a835e05e90cd1d321854 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Mon, 16 Sep 2024 20:24:38 +0900 Subject: [PATCH 150/174] =?UTF-8?q?fix:=20pageRequest=20=ED=8C=8C=EB=9D=BC?= =?UTF-8?q?=EB=AF=B8=ED=84=B0=20swagger=EC=97=90=EC=84=9C=20=EB=B3=B4?= =?UTF-8?q?=EC=9D=B4=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../accompany/AccompanyApplicationService.kt | 6 +++--- .../api/controller/accompany/AccompanyController.kt | 9 ++------- .../api/controller/accompany/dto/AccompanyRequestDto.kt | 7 +++++++ 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt index 926637b..2a04347 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt @@ -3,12 +3,12 @@ package com.withaeng.api.applicationservice.accompany import com.withaeng.api.applicationservice.accompany.dto.* import com.withaeng.api.applicationservice.common.PagingResponse import com.withaeng.api.applicationservice.common.toPaging +import com.withaeng.api.common.PageInfoRequest import com.withaeng.common.exception.WithaengException import com.withaeng.common.exception.WithaengExceptionType import com.withaeng.domain.accompany.AccompanyService import com.withaeng.domain.accompanyjoinrequests.AccompanyJoinRequestService import com.withaeng.domain.accompanylike.AccompanyLikeService -import org.springframework.data.domain.Pageable import org.springframework.stereotype.Service @Service @@ -30,10 +30,10 @@ class AccompanyApplicationService( } fun search( - pageable: Pageable, + pageInfoRequest: PageInfoRequest, request: SearchAccompanyServiceRequest, ): PagingResponse> { - val pageResult = accompanyService.search(pageable, request.toQuery()) + val pageResult = accompanyService.search(pageInfoRequest.toPageRequest(), request.toQuery()) .map { accompanyDto -> accompanyDto.toAccompanyResponse() } return PagingResponse(pageResult.content, pageResult.toPaging()) } diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt index 9acf608..87ed7ff 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt @@ -5,11 +5,7 @@ import com.withaeng.api.applicationservice.accompany.dto.AccompanyResponse import com.withaeng.api.applicationservice.accompany.dto.AccompanySummaryResponse import com.withaeng.api.applicationservice.accompany.dto.FindAccompanyResponse import com.withaeng.api.common.ApiResponse -import com.withaeng.api.common.PageInfoRequest -import com.withaeng.api.controller.accompany.dto.CreateAccompanyRequest -import com.withaeng.api.controller.accompany.dto.SearchAccompanyRequest -import com.withaeng.api.controller.accompany.dto.UpdateAccompanyRequest -import com.withaeng.api.controller.accompany.dto.toServiceRequest +import com.withaeng.api.controller.accompany.dto.* import com.withaeng.api.security.authentication.UserInfo import com.withaeng.api.security.resolver.GetAuth import io.swagger.v3.oas.annotations.Operation @@ -57,11 +53,10 @@ class AccompanyController( @Operation(summary = "Search Accompany", description = "동행 검색 API (필터링만 지원)") @GetMapping("/search") fun search( - @ParameterObject pageInfoRequest: PageInfoRequest, @ParameterObject request: SearchAccompanyRequest, ): ApiResponse> { return ApiResponse.success( - accompanyApplicationService.search(pageInfoRequest.toPageRequest(), request.toServiceRequest()) + accompanyApplicationService.search(request.toPageInfoRequest(), request.toServiceRequest()) ) } diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt index 6c27f10..08943a2 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize import com.withaeng.api.applicationservice.accompany.dto.CreateAccompanyServiceRequest import com.withaeng.api.applicationservice.accompany.dto.SearchAccompanyServiceRequest import com.withaeng.api.applicationservice.accompany.dto.UpdateAccompanyServiceRequest +import com.withaeng.api.common.PageInfoRequest import com.withaeng.domain.accompany.* import io.swagger.v3.oas.annotations.media.Schema import java.time.LocalDate @@ -95,6 +96,10 @@ fun UpdateAccompanyRequest.toServiceRequest( ) data class SearchAccompanyRequest( + @Schema(description = "요청할 페이지 번호 (0부터 시작)") + val page: String = "0", + @Schema(description = "페이지당 데이터 개수") + val size: String = "5", @Schema(description = "동행 대륙") val continent: Continent? = null, @Schema(description = "동행 나라") @@ -117,6 +122,8 @@ data class SearchAccompanyRequest( val preferGender: AccompanyPreferGender? = null, ) +fun SearchAccompanyRequest.toPageInfoRequest(): PageInfoRequest = PageInfoRequest(page = page, size = size) + fun SearchAccompanyRequest.toServiceRequest(): SearchAccompanyServiceRequest = SearchAccompanyServiceRequest( continent = continent, country = country, From 31c19d5b7d7dca9a5b7e51ffb030e568a29c1d18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Mon, 16 Sep 2024 20:47:01 +0900 Subject: [PATCH 151/174] =?UTF-8?q?fix:=20status=EB=A1=9C=20=ED=95=84?= =?UTF-8?q?=ED=84=B0=EB=A7=81=EA=B0=80=EB=8A=A5,=20=EC=B5=9C=EC=8B=A0?= =?UTF-8?q?=EC=A0=95=EB=A0=AC,=EC=9D=B8=EA=B8=B0=EC=88=9C(=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=EC=88=9C)=EC=A0=95=EB=A0=AC=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/AccompanyServiceRequestDto.kt | 4 +++ .../accompany/dto/AccompanyRequestDto.kt | 6 ++++ .../accompany/AccompanyRepositoryImpl.kt | 33 +++++++++++++++---- .../domain/accompany/AccompanySort.kt | 6 ++++ .../domain/accompany/dto/AccompanyQuery.kt | 2 ++ 5 files changed, 45 insertions(+), 6 deletions(-) create mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanySort.kt diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt index b47d334..24aadcc 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt @@ -60,6 +60,8 @@ fun UpdateAccompanyServiceRequest.toDomainDto(): UpdateAccompanyDto { } data class SearchAccompanyServiceRequest( + val sort: AccompanySort? = null, + val status: AccompanyStatus? = null, val continent: Continent? = null, val country: Country? = null, val city: City? = null, @@ -74,6 +76,8 @@ data class SearchAccompanyServiceRequest( fun SearchAccompanyServiceRequest.toQuery(): SearchAccompanyQuery { return SearchAccompanyQuery( + sort = sort, + status = status, continent = continent, country = country, city = city, diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt index 08943a2..592b0d6 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt @@ -100,6 +100,10 @@ data class SearchAccompanyRequest( val page: String = "0", @Schema(description = "페이지당 데이터 개수") val size: String = "5", + @Schema(description = "동행 정렬 기준") + val sort: AccompanySort? = null, + @Schema(description = "동행 상태") + val status: AccompanyStatus? = null, @Schema(description = "동행 대륙") val continent: Continent? = null, @Schema(description = "동행 나라") @@ -125,6 +129,8 @@ data class SearchAccompanyRequest( fun SearchAccompanyRequest.toPageInfoRequest(): PageInfoRequest = PageInfoRequest(page = page, size = size) fun SearchAccompanyRequest.toServiceRequest(): SearchAccompanyServiceRequest = SearchAccompanyServiceRequest( + sort = sort, + status = status, continent = continent, country = country, city = city, diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryImpl.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryImpl.kt index ae5e72a..f877db9 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryImpl.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryImpl.kt @@ -1,5 +1,6 @@ package com.withaeng.domain.accompany +import com.querydsl.core.types.OrderSpecifier import com.querydsl.core.types.dsl.BooleanExpression import com.querydsl.jpa.impl.JPAQueryFactory import com.withaeng.domain.accompany.QAccompany.accompany @@ -84,8 +85,8 @@ class AccompanyRepositoryImpl( ) ) .from(accompany) - .innerJoin(user) - .on(accompany.userId.eq(user.id)) + .innerJoin(user).on(accompany.userId.eq(user.id)) + .innerJoin(accompanyStatistics).on(accompany.id.eq(accompanyStatistics.accompany.id)) .leftJoin(accompanyJoinRequest).on( accompanyJoinRequest.accompany.eq(accompany) .and(accompanyJoinRequest.status.eq(AccompanyJoinRequestStatus.ACCEPT)) @@ -104,7 +105,7 @@ class AccompanyRepositoryImpl( accompany.tags ) .where( - statusEq(AccompanyStatus.ING), + statusEq(query.status), continentEq(query.continent), countryEq(query.country), cityEq(query.city), @@ -113,7 +114,7 @@ class AccompanyRepositoryImpl( containAllowedAge(query.minAllowedAge, query.maxAllowedAge), preferGenderEq(query.preferGender), ) - .orderBy(accompany.id.desc()) + .orderBy(*orderSpecifiers(query.sort)) .offset(pageable.offset) .limit(pageable.pageSize.toLong()) .fetch() @@ -140,8 +141,28 @@ class AccompanyRepositoryImpl( return PageableExecutionUtils.getPage(result, pageable) { countQuery.fetchOne() ?: 0L } } - private fun statusEq(status: AccompanyStatus): BooleanExpression? { - return accompany.accompanyStatus.eq(status) + private fun orderSpecifiers(sort: AccompanySort?): Array> { + return when (sort) { + AccompanySort.RECENT -> arrayOf( + accompany.createdAt.desc(), + accompanyStatistics.viewCount.desc(), + ) + + AccompanySort.POPULAR -> arrayOf( + accompanyStatistics.viewCount.desc(), + accompany.createdAt.desc(), + ) + + else -> arrayOf( + accompany.createdAt.desc(), + accompanyStatistics.viewCount.desc(), + ) + } + } + + + private fun statusEq(status: AccompanyStatus?): BooleanExpression? { + return status?.let { accompany.accompanyStatus.eq(it) } } private fun continentEq(continent: Continent?): BooleanExpression? { diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanySort.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanySort.kt new file mode 100644 index 0000000..143e634 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanySort.kt @@ -0,0 +1,6 @@ +package com.withaeng.domain.accompany + +enum class AccompanySort { + RECENT, + POPULAR, +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/dto/AccompanyQuery.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/dto/AccompanyQuery.kt index 61d808b..7dba0a1 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/dto/AccompanyQuery.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/dto/AccompanyQuery.kt @@ -4,6 +4,8 @@ import com.withaeng.domain.accompany.* import java.time.LocalDate data class SearchAccompanyQuery( + val sort: AccompanySort? = null, + val status: AccompanyStatus? = null, val continent: Continent? = null, val country: Country? = null, val city: City? = null, From 5ecc81e1b754cb239f71e0bc6232a9a41f00e608 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Tue, 17 Sep 2024 01:45:27 +0900 Subject: [PATCH 152/174] =?UTF-8?q?chore:=20aws=20=EC=84=A4=EC=A0=95?= =?UTF-8?q?=EA=B0=92=EB=93=A4=20=ED=99=98=EA=B2=BD=EB=B3=80=EC=88=98?= =?UTF-8?q?=EB=A1=9C=20=EB=B0=9B=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/cd.yml | 4 ++++ withaeng-api/docker-compose.yml | 4 ++++ .../com/withaeng/external/ses/config/SESConfig.kt | 2 +- .../src/main/resources/application-external.yml | 11 +++++------ 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index ed54d02..7bbe323 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -76,6 +76,10 @@ jobs: export WITHAENG_HOST=${{ secrets.WITHAENG_HOST }} export JWT_ISSUER=${{ secrets.JWT_ISSUER }} export JWT_SECRET_KEY=${{ secrets.JWT_SECRET_KEY }} + export AWS_ACCESS_KEY=${{ secrets.AWS_ACCESS_KEY }} + export AWS_SECRET_KEY=${{ secrets.AWS_SECRET_KEY }} + export AWS_SES_REGION=${{ secrets.AWS_SES_REGION }} + export AWS_SES_FROM=${{ secrets.AWS_SES_FROM }} export JASYPT_PASSWORD=${{ secrets.JASYPT_PASSWORD }} sudo -E docker compose -f /tmp/withaeng-api/docker-compose.yml down sudo -E docker compose -f /tmp/withaeng-api/docker-compose.yml up --build -d \ No newline at end of file diff --git a/withaeng-api/docker-compose.yml b/withaeng-api/docker-compose.yml index e7ad2e4..9247a3b 100644 --- a/withaeng-api/docker-compose.yml +++ b/withaeng-api/docker-compose.yml @@ -16,3 +16,7 @@ services: JWT_ISSUER: ${JWT_ISSUER} JWT_SECRET_KEY: ${JWT_SECRET_KEY} JASYPT_PASSWORD: ${JASYPT_PASSWORD} + AWS_ACCESS_KEY: ${AWS_ACCESS_KEY} + AWS_SECRET_KEY: ${AWS_SECRET_KEY} + AWS_SES_REGION: ${AWS_SES_REGION} + AWS_SES_FROM: ${AWS_SES_FROM} diff --git a/withaeng-external/src/main/kotlin/com/withaeng/external/ses/config/SESConfig.kt b/withaeng-external/src/main/kotlin/com/withaeng/external/ses/config/SESConfig.kt index 8184ae3..2ad6dbb 100644 --- a/withaeng-external/src/main/kotlin/com/withaeng/external/ses/config/SESConfig.kt +++ b/withaeng-external/src/main/kotlin/com/withaeng/external/ses/config/SESConfig.kt @@ -19,7 +19,7 @@ class SESConfig { @Value("\${cloud.aws.credentials.secret-key}") private lateinit var secretKey: String - @Value("\${cloud.aws.region.static}") + @Value("\${cloud.aws.ses.region}") private lateinit var regionName: String @Bean diff --git a/withaeng-external/src/main/resources/application-external.yml b/withaeng-external/src/main/resources/application-external.yml index 85e84cf..4174df2 100644 --- a/withaeng-external/src/main/resources/application-external.yml +++ b/withaeng-external/src/main/resources/application-external.yml @@ -1,12 +1,11 @@ cloud: aws: - credentials: # TODO environment variable로 변경 - access-key: ENC(tje4pV1gRGOh5N5ig8TND1sc3NyDGe9KDIXHMiY5UgBospTEAk2pjcxphPMvoOiNshPej16XCkj/RDP8ywREdQ==) - secret-key: ENC(5RTBAVDrwVdRLBQ/vrQrrE2f9K/68acjDiHgg9hc9J/8K3TZoejmca7Nagyz1exQ8XEndRKXl4XgxyXljZvykgP/56Ab7eAKuXXplny0zoQ=) - region: - static: ENC(1OX/+Td6WwTc/zbC8t/DVgDHX24lMOV+ZQbza/IstkTM8E3UKwloe8EaH97FKpzT) + credentials: + access-key: ${AWS_ACCESS_KEY} + secret-key: ${AWS_SECRET_KEY} ses: - from: ENC(S6WIEUO3m5JKHw7PrhpgkAvQjd1LzwwLRXEu2I9yUtzErtBEDk6EEt28Ltzypo8/fZi7Ua8VkHjWh9498FT5DA==) + region: ${AWS_SES_REGION} + from: ${AWS_SES_FROM} --- spring.config.activate.on-profile: local From e31b32cf082a627aa3b01ba1e9d0cd4861d1c3be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Tue, 17 Sep 2024 01:49:45 +0900 Subject: [PATCH 153/174] =?UTF-8?q?chore:=20jasypt=20=EC=9D=98=EC=A1=B4?= =?UTF-8?q?=EC=84=B1=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/cd.yml | 1 - gradle.properties | 2 - withaeng-api/docker-compose.yml | 1 - .../src/main/resources/application.yml | 2 - withaeng-domain/build.gradle.kts | 4 -- .../withaeng/domain/config/JasyptConfig.kt | 8 ---- .../withaeng/api/config/JasyptConfigTest.kt | 46 ------------------- .../withaeng/api/config/TestConfiguration.kt | 6 --- 8 files changed, 70 deletions(-) delete mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/config/JasyptConfig.kt delete mode 100644 withaeng-domain/src/test/kotlin/com/withaeng/api/config/JasyptConfigTest.kt delete mode 100644 withaeng-domain/src/test/kotlin/com/withaeng/api/config/TestConfiguration.kt diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 7bbe323..372e358 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -80,6 +80,5 @@ jobs: export AWS_SECRET_KEY=${{ secrets.AWS_SECRET_KEY }} export AWS_SES_REGION=${{ secrets.AWS_SES_REGION }} export AWS_SES_FROM=${{ secrets.AWS_SES_FROM }} - export JASYPT_PASSWORD=${{ secrets.JASYPT_PASSWORD }} sudo -E docker compose -f /tmp/withaeng-api/docker-compose.yml down sudo -E docker compose -f /tmp/withaeng-api/docker-compose.yml up --build -d \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 7b3047d..3596ad7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,8 +9,6 @@ springBootVersion=3.2.2 springDependencyManagementVersion=1.1.4 ### Spring mockk #### springMockkVersion=3.1.1 -### Jasypt versions ### -jasyptVersion=3.0.5 ### Persistence versions ### mysqlVersion=8.3.0 queryDslVersion=5.1.0:jakarta diff --git a/withaeng-api/docker-compose.yml b/withaeng-api/docker-compose.yml index 9247a3b..c340222 100644 --- a/withaeng-api/docker-compose.yml +++ b/withaeng-api/docker-compose.yml @@ -15,7 +15,6 @@ services: WITHAENG_HOST: ${WITHAENG_HOST} JWT_ISSUER: ${JWT_ISSUER} JWT_SECRET_KEY: ${JWT_SECRET_KEY} - JASYPT_PASSWORD: ${JASYPT_PASSWORD} AWS_ACCESS_KEY: ${AWS_ACCESS_KEY} AWS_SECRET_KEY: ${AWS_SECRET_KEY} AWS_SES_REGION: ${AWS_SES_REGION} diff --git a/withaeng-api/src/main/resources/application.yml b/withaeng-api/src/main/resources/application.yml index e1e806d..c0acbaf 100644 --- a/withaeng-api/src/main/resources/application.yml +++ b/withaeng-api/src/main/resources/application.yml @@ -20,8 +20,6 @@ springdoc: # todo: 개발 종료 후 prod 에서는 비활성화 groups: enabled: true -jasypt.encryptor.password: ${JASYPT_PASSWORD} - --- spring.config.activate.on-profile: local diff --git a/withaeng-domain/build.gradle.kts b/withaeng-domain/build.gradle.kts index cee68b8..7fc78e2 100644 --- a/withaeng-domain/build.gradle.kts +++ b/withaeng-domain/build.gradle.kts @@ -4,7 +4,6 @@ allOpen { annotation("jakarta.persistence.Embeddable") } -val jasyptVersion: String by project.extra val mysqlVersion: String by project.extra val queryDslVersion: String by project.extra dependencies { @@ -18,7 +17,4 @@ dependencies { kapt("org.springframework.boot:spring-boot-configuration-processor") runtimeOnly("com.mysql:mysql-connector-j:$mysqlVersion") - - // jasypt - api("com.github.ulisesbocchio:jasypt-spring-boot-starter:$jasyptVersion") } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/config/JasyptConfig.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/config/JasyptConfig.kt deleted file mode 100644 index ab5eba1..0000000 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/config/JasyptConfig.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.withaeng.domain.config - -import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties -import org.springframework.context.annotation.Configuration - -@EnableEncryptableProperties -@Configuration -class JasyptConfig \ No newline at end of file diff --git a/withaeng-domain/src/test/kotlin/com/withaeng/api/config/JasyptConfigTest.kt b/withaeng-domain/src/test/kotlin/com/withaeng/api/config/JasyptConfigTest.kt deleted file mode 100644 index f7476c1..0000000 --- a/withaeng-domain/src/test/kotlin/com/withaeng/api/config/JasyptConfigTest.kt +++ /dev/null @@ -1,46 +0,0 @@ -package com.withaeng.api.config - -import com.ulisesbocchio.jasyptspringboot.encryptor.DefaultLazyEncryptor -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Disabled -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.ExtendWith -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.beans.factory.annotation.Value -import org.springframework.boot.test.context.SpringBootTest -import org.springframework.core.env.ConfigurableEnvironment -import org.springframework.test.context.junit.jupiter.SpringExtension - -@Disabled -@SpringBootTest -@ExtendWith(SpringExtension::class) -class JasyptConfigTest { - @Value("\${jasypt.encryptor.password}") - private lateinit var jasyptEncryptorPassword: String - - @Autowired - private lateinit var configurableEnvironment: ConfigurableEnvironment - private lateinit var encryptor: DefaultLazyEncryptor - - @BeforeEach - internal fun setUp() { - check(jasyptEncryptorPassword.isNotBlank()) { - "jasypt.encryptor.password must not be null, empty or blank. " - } - encryptor = DefaultLazyEncryptor(configurableEnvironment) - } - - @Test - fun testForEncryption() { - val source = "test" - println("source: $source") - println("encrypted: ${encryptor.encrypt(source)}") - } - - @Test - fun testForDecryption() { - val source = "test" - println("source: $source") - println("decrypted: ${encryptor.decrypt(source)}") - } -} \ No newline at end of file diff --git a/withaeng-domain/src/test/kotlin/com/withaeng/api/config/TestConfiguration.kt b/withaeng-domain/src/test/kotlin/com/withaeng/api/config/TestConfiguration.kt deleted file mode 100644 index a02c410..0000000 --- a/withaeng-domain/src/test/kotlin/com/withaeng/api/config/TestConfiguration.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.withaeng.api.config - -import org.springframework.boot.autoconfigure.SpringBootApplication - -@SpringBootApplication -class TestConfiguration \ No newline at end of file From 221f4a3a25dac47c62448221470543478f7de1a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Thu, 19 Sep 2024 16:40:50 +0900 Subject: [PATCH 154/174] =?UTF-8?q?Feature:=20=EB=8F=99=ED=96=89=20?= =?UTF-8?q?=EA=B1=B0=EB=B6=80=20api=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../accompany/AccompanyApplicationService.kt | 6 +++ .../accompany/AccompanyController.kt | 20 +++++++- .../AccompanyJoinRequestService.kt | 48 ++++++++++++++----- .../accompanyrequests/AccompanyJoinRequest.kt | 4 ++ 4 files changed, 63 insertions(+), 15 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt index 2a04347..0702096 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt @@ -71,6 +71,12 @@ class AccompanyApplicationService( accompanyJoinRequestService.acceptJoin(accompanyId, joinRequestId) } + fun rejectJoin(accompanyId: Long, userId: Long, joinRequestId: Long) { + val accompanyDto = accompanyService.findById(accompanyId) + validateNonCreator(accompanyDto.userId, userId) + accompanyJoinRequestService.rejectJoin(accompanyId, joinRequestId) + } + private fun increaseViewCount(accompanyId: Long) { accompanyService.increaseViewCount(accompanyId) } diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt index 87ed7ff..7d7a9be 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt @@ -91,7 +91,7 @@ class AccompanyController( @Operation( summary = "Create AccompanyJoinRequests API", - description = "동행 참가 신청 API", + description = "동행 참가 신청 API - Guest", security = [SecurityRequirement(name = "Authorization")] ) @PostMapping("/{accompanyId}/join-requests") @@ -107,7 +107,7 @@ class AccompanyController( @Operation( summary = "Create AccompanyJoinRequests API", - description = "동행 승인 API", + description = "동행 승인 API - Host", security = [SecurityRequirement(name = "Authorization")] ) @PutMapping("/{accompanyId}/join-requests/{joinRequestId}/accept") @@ -120,4 +120,20 @@ class AccompanyController( accompanyId = accompanyId, userId = userInfo.id, joinRequestId = joinRequestId ) } + + @Operation( + summary = "Create AccompanyJoinRequests API", + description = "동행 거부 API - Host", + security = [SecurityRequirement(name = "Authorization")] + ) + @PutMapping("/{accompanyId}/join-requests/{joinRequestId}/reject") + fun rejectJoin( + @GetAuth userInfo: UserInfo, + @PathVariable accompanyId: Long, + @PathVariable joinRequestId: Long, + ) { + accompanyApplicationService.rejectJoin( + accompanyId = accompanyId, userId = userInfo.id, joinRequestId = joinRequestId + ) + } } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestService.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestService.kt index 66a8bb1..3cebc84 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestService.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestService.kt @@ -6,6 +6,7 @@ import com.withaeng.domain.accompany.Accompany import com.withaeng.domain.accompany.AccompanyRepository import com.withaeng.domain.accompany.AccompanyStatus import com.withaeng.domain.accompanyrequests.AccompanyJoinRequest +import com.withaeng.domain.accompanyrequests.AccompanyJoinRequestStatus import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -18,10 +19,7 @@ class AccompanyJoinRequestService( @Transactional fun create(accompanyId: Long, userId: Long) { - val accompany = accompanyRepository.findByIdOrNull(accompanyId) ?: throw WithaengException.of( - type = WithaengExceptionType.NOT_EXIST, - message = "해당하는 동행을 찾을 수 없습니다." - ) + val accompany = findAccompanyByIdOrNull(accompanyId) validateFull(accompany, accompanyId) validateDuplicateJoin(accompanyId, userId) val accompanyJoinRequest = AccompanyJoinRequest.create(userId, accompany) @@ -30,15 +28,8 @@ class AccompanyJoinRequestService( @Transactional fun acceptJoin(accompanyId: Long, joinRequestId: Long) { - val accompanyJoinRequest = accompanyJoinRequestRepository.findByIdOrNull(joinRequestId) - ?: throw WithaengException.of( - type = WithaengExceptionType.NOT_EXIST, - message = "동행 신청 정보가 존재하지 않습니다." - ) - val accompany = accompanyRepository.findByIdOrNull(accompanyId) ?: throw WithaengException.of( - type = WithaengExceptionType.NOT_EXIST, - message = "해당하는 동행을 찾을 수 없습니다." - ) + val accompanyJoinRequest = findAccompanyJoinRequestByIdOrNull(joinRequestId) + val accompany = findAccompanyByIdOrNull(accompanyId) validateFull(accompany, accompanyId) accompanyJoinRequest.accept() @@ -47,6 +38,37 @@ class AccompanyJoinRequestService( } } + @Transactional + fun rejectJoin(accompanyId: Long, joinRequestId: Long) { + val accompanyJoinRequest = findAccompanyJoinRequestByIdOrNull(joinRequestId) + val accompany = findAccompanyByIdOrNull(accompanyId) + validateFull(accompany, accompanyId) + validateWaitStatus(accompanyJoinRequest) + accompanyJoinRequest.reject() + } + + private fun findAccompanyByIdOrNull(accompanyId: Long) = + accompanyRepository.findByIdOrNull(accompanyId) ?: throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = "해당하는 동행을 찾을 수 없습니다." + ) + + private fun findAccompanyJoinRequestByIdOrNull(joinRequestId: Long) = + accompanyJoinRequestRepository.findByIdOrNull(joinRequestId) + ?: throw WithaengException.of( + type = WithaengExceptionType.NOT_EXIST, + message = "동행 신청 정보가 존재하지 않습니다." + ) + + private fun validateWaitStatus(accompanyJoinRequest: AccompanyJoinRequest) { + if (accompanyJoinRequest.status != AccompanyJoinRequestStatus.WAIT) { + throw WithaengException.of( + type = WithaengExceptionType.INVALID_ACCESS, + message = "승인 대기 상태가 아닙니다." + ) + } + } + private fun validateFull(accompany: Accompany, accompanyId: Long) { if (isFull(accompany, accompanyId)) { throw WithaengException.of( diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyrequests/AccompanyJoinRequest.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyrequests/AccompanyJoinRequest.kt index 62ce623..10fb246 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyrequests/AccompanyJoinRequest.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyrequests/AccompanyJoinRequest.kt @@ -33,6 +33,10 @@ class AccompanyJoinRequest( status = AccompanyJoinRequestStatus.ACCEPT } + fun reject() { + status = AccompanyJoinRequestStatus.REJECT + } + fun duplicated(userId: Long): Boolean { return requestedBy(userId) && (onStatus(AccompanyJoinRequestStatus.WAIT) || onStatus(AccompanyJoinRequestStatus.ACCEPT)) } From d1c746db57ada916a15130f5ac44c7959f6e47bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Thu, 19 Sep 2024 18:38:10 +0900 Subject: [PATCH 155/174] =?UTF-8?q?Feature:=20=EB=8F=99=ED=96=89=20?= =?UTF-8?q?=EC=B7=A8=EC=86=8C=20api=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../accompany/AccompanyApplicationService.kt | 20 ++++++++----- .../accompany/AccompanyController.kt | 17 +++++++++++ .../withaeng/domain/accompany/Accompany.kt | 3 ++ .../AccompanyJoinRequestService.kt | 28 +++++++++++++++++-- .../dto/AccompanyJoinRequestDto.kt | 18 ++++++++++++ .../accompanyrequests/AccompanyJoinRequest.kt | 4 +++ 6 files changed, 81 insertions(+), 9 deletions(-) create mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/dto/AccompanyJoinRequestDto.kt diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt index 0702096..bc2af0e 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt @@ -61,19 +61,25 @@ class AccompanyApplicationService( fun requestJoin(accompanyId: Long, userId: Long) { val accompanyDto = accompanyService.findById(accompanyId) - validateCreator(accompanyDto.userId, userId) + validateSelfRequestNotAllowed(accompanyDto.userId, userId) accompanyJoinRequestService.create(accompanyId, userId) } - fun acceptJoin(accompanyId: Long, userId: Long, joinRequestId: Long) { + fun cancelJoin(accompanyId: Long, userId: Long, joinRequestId: Long) { val accompanyDto = accompanyService.findById(accompanyId) - validateNonCreator(accompanyDto.userId, userId) + val accompanyJoinRequestDto = accompanyJoinRequestService.findById(joinRequestId) + validateSelfRequestNotAllowed(accompanyDto.userId, userId) + validateCreatorAccess(accompanyJoinRequestDto.userId, userId) + accompanyJoinRequestService.cancelJoin(accompanyId, joinRequestId) + } + + fun acceptJoin(accompanyId: Long, userId: Long, joinRequestId: Long) { accompanyJoinRequestService.acceptJoin(accompanyId, joinRequestId) } fun rejectJoin(accompanyId: Long, userId: Long, joinRequestId: Long) { val accompanyDto = accompanyService.findById(accompanyId) - validateNonCreator(accompanyDto.userId, userId) + validateCreatorAccess(accompanyDto.userId, userId) accompanyJoinRequestService.rejectJoin(accompanyId, joinRequestId) } @@ -88,16 +94,16 @@ class AccompanyApplicationService( return accompanyLikeService.countByAccompanyId(accompanyId) } - private fun validateCreator(createUserId: Long, requestUserId: Long) { + private fun validateSelfRequestNotAllowed(createUserId: Long, requestUserId: Long) { if (createUserId == requestUserId) { throw WithaengException.of( type = WithaengExceptionType.ACCESS_DENIED, - message = "본인의 동행은 신청할 수 없습니다." + message = "본인의 동행은 신청, 취소할 수 없습니다." ) } } - private fun validateNonCreator(createUserId: Long, requestUserId: Long) { + private fun validateCreatorAccess(createUserId: Long, requestUserId: Long) { if (createUserId != requestUserId) { throw WithaengException.of( type = WithaengExceptionType.ACCESS_DENIED, diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt index 7d7a9be..353b642 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt @@ -105,6 +105,23 @@ class AccompanyController( return ApiResponse.success() } + @Operation( + summary = "Create AccompanyJoinRequests API", + description = "동행 참가 취소 API - Guest", + security = [SecurityRequirement(name = "Authorization")] + ) + @PutMapping("/{accompanyId}/join-requests/{joinRequestId}/cancel") + fun cancelJoin( + @GetAuth userInfo: UserInfo, + @PathVariable accompanyId: Long, + @PathVariable joinRequestId: Long, + ): ApiResponse { + accompanyApplicationService.cancelJoin( + accompanyId = accompanyId, userId = userInfo.id, joinRequestId = joinRequestId + ) + return ApiResponse.success() + } + @Operation( summary = "Create AccompanyJoinRequests API", description = "동행 승인 API - Host", diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt index 454b0f5..efd70a3 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Accompany.kt @@ -98,6 +98,9 @@ class Accompany( this.accompanyStatus = AccompanyStatus.COMPLETE } + fun isCompleted() = + this.accompanyStatus == AccompanyStatus.COMPLETE + companion object { fun create(params: CreateAccompanyDto): Accompany { val accompany = Accompany( diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestService.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestService.kt index 3cebc84..991cc96 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestService.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestService.kt @@ -4,7 +4,8 @@ import com.withaeng.common.exception.WithaengException import com.withaeng.common.exception.WithaengExceptionType import com.withaeng.domain.accompany.Accompany import com.withaeng.domain.accompany.AccompanyRepository -import com.withaeng.domain.accompany.AccompanyStatus +import com.withaeng.domain.accompanyjoinrequests.dto.AccompanyJoinRequestDto +import com.withaeng.domain.accompanyjoinrequests.dto.toDto import com.withaeng.domain.accompanyrequests.AccompanyJoinRequest import com.withaeng.domain.accompanyrequests.AccompanyJoinRequestStatus import org.springframework.data.repository.findByIdOrNull @@ -26,6 +27,14 @@ class AccompanyJoinRequestService( accompanyJoinRequestRepository.save(accompanyJoinRequest) } + @Transactional + fun cancelJoin(accompanyId: Long, joinRequestId: Long) { + val accompany = findAccompanyByIdOrNull(accompanyId) + validateCompletedAccompany(accompany) + val accompanyJoinRequest = findAccompanyJoinRequestByIdOrNull(joinRequestId) + accompanyJoinRequest.cancel() + } + @Transactional fun acceptJoin(accompanyId: Long, joinRequestId: Long) { val accompanyJoinRequest = findAccompanyJoinRequestByIdOrNull(joinRequestId) @@ -47,6 +56,12 @@ class AccompanyJoinRequestService( accompanyJoinRequest.reject() } + @Transactional(readOnly = true) + fun findById(joinRequestId: Long): AccompanyJoinRequestDto { + val accompanyJoinRequest = findAccompanyJoinRequestByIdOrNull(joinRequestId) + return accompanyJoinRequest.toDto() + } + private fun findAccompanyByIdOrNull(accompanyId: Long) = accompanyRepository.findByIdOrNull(accompanyId) ?: throw WithaengException.of( type = WithaengExceptionType.NOT_EXIST, @@ -69,6 +84,15 @@ class AccompanyJoinRequestService( } } + private fun validateCompletedAccompany(accompany: Accompany) { + if (accompany.isCompleted()) { + throw WithaengException.of( + type = WithaengExceptionType.INVALID_ACCESS, + message = "모집 마감된 동행은 취소할 수 없습니다." + ) + } + } + private fun validateFull(accompany: Accompany, accompanyId: Long) { if (isFull(accompany, accompanyId)) { throw WithaengException.of( @@ -88,7 +112,7 @@ class AccompanyJoinRequestService( } private fun isFull(accompany: Accompany, accompanyId: Long) = - accompany.accompanyStatus == AccompanyStatus.COMPLETE || + accompany.isCompleted() || isBelowMemberLimit(accompany, accompanyId) private fun getAcceptedCount(accompanyId: Long) = diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/dto/AccompanyJoinRequestDto.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/dto/AccompanyJoinRequestDto.kt new file mode 100644 index 0000000..16aa966 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/dto/AccompanyJoinRequestDto.kt @@ -0,0 +1,18 @@ +package com.withaeng.domain.accompanyjoinrequests.dto + +import com.withaeng.domain.accompanyrequests.AccompanyJoinRequest +import com.withaeng.domain.accompanyrequests.AccompanyJoinRequestStatus + +data class AccompanyJoinRequestDto( + val id: Long, + val userId: Long, + val accompanyJoinRequestStatus: AccompanyJoinRequestStatus, + val accompanyId: Long, +) + +fun AccompanyJoinRequest.toDto() = AccompanyJoinRequestDto( + id = id, + userId = userId, + accompanyJoinRequestStatus = status, + accompanyId = accompany.id, +) \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyrequests/AccompanyJoinRequest.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyrequests/AccompanyJoinRequest.kt index 10fb246..aacdc22 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyrequests/AccompanyJoinRequest.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyrequests/AccompanyJoinRequest.kt @@ -29,6 +29,10 @@ class AccompanyJoinRequest( } } + fun cancel() { + status = AccompanyJoinRequestStatus.CANCEL + } + fun accept() { status = AccompanyJoinRequestStatus.ACCEPT } From fb79f6c0f9215a25c7694e4e7c963f3cec4f60ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Thu, 19 Sep 2024 19:18:48 +0900 Subject: [PATCH 156/174] Refactor: update method name --- .../accompany/AccompanyApplicationService.kt | 6 ++--- .../AccompanyJoinRequestService.kt | 26 +++++++++---------- .../accompanyrequests/AccompanyJoinRequest.kt | 13 ++-------- 3 files changed, 17 insertions(+), 28 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt index bc2af0e..17a7d6a 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt @@ -87,9 +87,6 @@ class AccompanyApplicationService( accompanyService.increaseViewCount(accompanyId) } - private fun isHost(loginUserId: Long?, userId: Long) = - loginUserId == userId - private fun countAccompanyLikeByAccompanyId(accompanyId: Long): Long { return accompanyLikeService.countByAccompanyId(accompanyId) } @@ -111,4 +108,7 @@ class AccompanyApplicationService( ) } } + + private fun isHost(loginUserId: Long?, userId: Long) = + loginUserId == userId } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestService.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestService.kt index 991cc96..b6bf16a 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestService.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestService.kt @@ -7,7 +7,6 @@ import com.withaeng.domain.accompany.AccompanyRepository import com.withaeng.domain.accompanyjoinrequests.dto.AccompanyJoinRequestDto import com.withaeng.domain.accompanyjoinrequests.dto.toDto import com.withaeng.domain.accompanyrequests.AccompanyJoinRequest -import com.withaeng.domain.accompanyrequests.AccompanyJoinRequestStatus import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -52,7 +51,7 @@ class AccompanyJoinRequestService( val accompanyJoinRequest = findAccompanyJoinRequestByIdOrNull(joinRequestId) val accompany = findAccompanyByIdOrNull(accompanyId) validateFull(accompany, accompanyId) - validateWaitStatus(accompanyJoinRequest) + validateNotWaitingJoinRequest(accompanyJoinRequest) accompanyJoinRequest.reject() } @@ -75,8 +74,14 @@ class AccompanyJoinRequestService( message = "동행 신청 정보가 존재하지 않습니다." ) - private fun validateWaitStatus(accompanyJoinRequest: AccompanyJoinRequest) { - if (accompanyJoinRequest.status != AccompanyJoinRequestStatus.WAIT) { + private fun getAcceptedJoinRequestCount(accompanyId: Long) = + accompanyJoinRequestRepository.countByAccompanyIdAndStatus(accompanyId) + + private fun existsJoinRequestByUser(accompanyId: Long, userId: Long) = + accompanyJoinRequestRepository.existsByAccompanyIdAndUserId(accompanyId, userId) + + private fun validateNotWaitingJoinRequest(accompanyJoinRequest: AccompanyJoinRequest) { + if (accompanyJoinRequest.isNotWaiting()) { throw WithaengException.of( type = WithaengExceptionType.INVALID_ACCESS, message = "승인 대기 상태가 아닙니다." @@ -103,7 +108,7 @@ class AccompanyJoinRequestService( } private fun validateDuplicateJoin(accompanyId: Long, userId: Long) { - if (existsByUser(accompanyId, userId)) { + if (existsJoinRequestByUser(accompanyId, userId)) { throw WithaengException.of( type = WithaengExceptionType.ALREADY_EXIST, message = "동행 신청한 내역이 존재합니다." @@ -112,15 +117,8 @@ class AccompanyJoinRequestService( } private fun isFull(accompany: Accompany, accompanyId: Long) = - accompany.isCompleted() || - isBelowMemberLimit(accompany, accompanyId) - - private fun getAcceptedCount(accompanyId: Long) = - accompanyJoinRequestRepository.countByAccompanyIdAndStatus(accompanyId) - - private fun existsByUser(accompanyId: Long, userId: Long) = - accompanyJoinRequestRepository.existsByAccompanyIdAndUserId(accompanyId, userId) + accompany.isCompleted() || isBelowMemberLimit(accompany, accompanyId) private fun isBelowMemberLimit(accompany: Accompany, accompanyId: Long) = - accompany.memberCount < getAcceptedCount(accompanyId) + 1 + accompany.memberCount < getAcceptedJoinRequestCount(accompanyId) + 1 } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyrequests/AccompanyJoinRequest.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyrequests/AccompanyJoinRequest.kt index aacdc22..0224707 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyrequests/AccompanyJoinRequest.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyrequests/AccompanyJoinRequest.kt @@ -41,15 +41,6 @@ class AccompanyJoinRequest( status = AccompanyJoinRequestStatus.REJECT } - fun duplicated(userId: Long): Boolean { - return requestedBy(userId) && (onStatus(AccompanyJoinRequestStatus.WAIT) || onStatus(AccompanyJoinRequestStatus.ACCEPT)) - } - - fun requestedBy(userId: Long): Boolean { - return this.userId == userId - } - - fun onStatus(accept: AccompanyJoinRequestStatus): Boolean { - return this.status == accept - } + fun isNotWaiting() = + this.status != AccompanyJoinRequestStatus.WAIT } \ No newline at end of file From 9294cd4c6ec73dc69d78ce27d6b1cae3bf60dc1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Thu, 19 Sep 2024 21:10:57 +0900 Subject: [PATCH 157/174] =?UTF-8?q?Feature:=20=ED=98=B8=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20=EB=8F=99=ED=96=89=20=EC=83=81=EC=84=B8=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 --- .../accompany/AccompanyApplicationService.kt | 7 ++- .../accompany/dto/FindAccompanyResponseDto.kt | 29 +++++++++-- .../AccompanyJoinRequestRepository.kt | 5 +- .../AccompanyJoinRequestRepositoryCustom.kt | 7 +++ .../AccompanyJoinRequestRepositoryImpl.kt | 48 +++++++++++++++++++ .../AccompanyJoinRequestService.kt | 4 ++ .../dto/AccompanyJoinRequestDto.kt | 16 +++++++ 7 files changed, 108 insertions(+), 8 deletions(-) create mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestRepositoryCustom.kt create mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestRepositoryImpl.kt diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt index 17a7d6a..62d39d1 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt @@ -41,14 +41,13 @@ class AccompanyApplicationService( fun detail(accompanyId: Long, userId: Long?): FindAccompanyResponse { increaseViewCount(accompanyId) val accompanyDto = accompanyService.detail(accompanyId) - .toAccompanyResponse() if (isHost(userId, accompanyDto.userId)) { - // TODO : Host인 경우 승인보류 유저 목록 추가 필요 - println("호스트임") + val joinRequests = accompanyJoinRequestService.findJoinRequestsByAccompanyId(accompanyId) + return accompanyDto.toGuestAccompanyResponse(joinRequests) } - return accompanyDto + return accompanyDto.toHostAccompanyResponse() } fun retrieveAll(): List { diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/FindAccompanyResponseDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/FindAccompanyResponseDto.kt index 37e9698..303fa6c 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/FindAccompanyResponseDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/FindAccompanyResponseDto.kt @@ -4,6 +4,7 @@ import com.withaeng.domain.accompany.AccompanyDestination import com.withaeng.domain.accompany.AccompanyPreferGender import com.withaeng.domain.accompany.dto.FindAccompanyDto import com.withaeng.domain.accompany.dto.FindAccompanyUserInfoDto +import com.withaeng.domain.accompanyjoinrequests.dto.FindAccompanyJoinRequestDto import java.time.LocalDate data class FindAccompanyResponse( @@ -24,10 +25,10 @@ data class FindAccompanyResponse( val tags: Set? = emptySet(), val likeCount: Long = 0, val author: FindAccompanyUserInfoDto, - val approvalPendingUsers: Set? = null, + val joinRequestUsers: List = emptyList(), ) -fun FindAccompanyDto.toAccompanyResponse() = FindAccompanyResponse( +fun FindAccompanyDto.toHostAccompanyResponse() = FindAccompanyResponse( id = id, userId = userId, title = title, @@ -45,4 +46,26 @@ fun FindAccompanyDto.toAccompanyResponse() = FindAccompanyResponse( preferGender = preferGender, tags = tags, author = author, -) \ No newline at end of file +) + +fun FindAccompanyDto.toGuestAccompanyResponse(joinRequests: List) = + FindAccompanyResponse( + id = id, + userId = userId, + title = title, + content = content, + destination = destination, + startTripDate = startTripDate, + endTripDate = endTripDate, + bannerImageUrl = bannerImageUrl, + memberCount = memberCount, + viewCount = viewCount, + likeCount = likeCount, + openKakaoUrl = openKakaoUrl, + startAccompanyAge = startAccompanyAge, + endAccompanyAge = endAccompanyAge, + preferGender = preferGender, + tags = tags, + author = author, + joinRequestUsers = joinRequests, + ) \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestRepository.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestRepository.kt index 38f4b01..3e633f0 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestRepository.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestRepository.kt @@ -4,11 +4,14 @@ import com.withaeng.domain.accompanyrequests.AccompanyJoinRequest import com.withaeng.domain.accompanyrequests.AccompanyJoinRequestStatus import org.springframework.data.jpa.repository.JpaRepository -interface AccompanyJoinRequestRepository : JpaRepository { +interface AccompanyJoinRequestRepository : JpaRepository, + AccompanyJoinRequestRepositoryCustom { fun countByAccompanyIdAndStatus( accompanyId: Long, status: AccompanyJoinRequestStatus = AccompanyJoinRequestStatus.ACCEPT, ): Int fun existsByAccompanyIdAndUserId(accompanyId: Long, userId: Long): Boolean + + fun findByAccompanyId(accompanyId: Long): List } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestRepositoryCustom.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestRepositoryCustom.kt new file mode 100644 index 0000000..4e0bc01 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestRepositoryCustom.kt @@ -0,0 +1,7 @@ +package com.withaeng.domain.accompanyjoinrequests + +import com.withaeng.domain.accompanyjoinrequests.dto.FindAccompanyJoinRequestDto + +interface AccompanyJoinRequestRepositoryCustom { + fun findJoinRequestsByAccompanyId(accompanyId: Long): List +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestRepositoryImpl.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestRepositoryImpl.kt new file mode 100644 index 0000000..a7427b4 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestRepositoryImpl.kt @@ -0,0 +1,48 @@ +package com.withaeng.domain.accompanyjoinrequests + +import com.querydsl.core.types.dsl.CaseBuilder +import com.querydsl.jpa.impl.JPAQueryFactory +import com.withaeng.domain.accompanyjoinrequests.dto.FindAccompanyJoinRequestDto +import com.withaeng.domain.accompanyjoinrequests.dto.QFindAccompanyJoinRequestDto +import com.withaeng.domain.accompanyrequests.AccompanyJoinRequestStatus +import com.withaeng.domain.accompanyrequests.QAccompanyJoinRequest.accompanyJoinRequest +import com.withaeng.domain.user.QUser.user + + +class AccompanyJoinRequestRepositoryImpl( + + private val queryFactory: JPAQueryFactory, + + ) : AccompanyJoinRequestRepositoryCustom { + + override fun findJoinRequestsByAccompanyId(accompanyId: Long): List { + return queryFactory + .select( + QFindAccompanyJoinRequestDto( + accompanyJoinRequest.id, + accompanyJoinRequest.status, + user.profile.nickname, + user.profile.profileImageUrl, + user.gender, + user.profile.introduction, + user.createdAt, + ) + ) + .from(accompanyJoinRequest) + .innerJoin(user) + .on(accompanyJoinRequest.userId.eq(user.id)) + .where( + accompanyJoinRequest.accompany.id.eq(accompanyId), + accompanyJoinRequest.status.notIn(AccompanyJoinRequestStatus.CANCEL) + ) + .orderBy(findJoinRequestsSort()) + .fetch() + } + + private fun findJoinRequestsSort() = CaseBuilder() + .`when`(accompanyJoinRequest.status.eq(AccompanyJoinRequestStatus.WAIT)).then(1) + .`when`(accompanyJoinRequest.status.eq(AccompanyJoinRequestStatus.ACCEPT)).then(2) + .`when`(accompanyJoinRequest.status.eq(AccompanyJoinRequestStatus.REJECT)).then(3) + .otherwise(4) + .asc() +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestService.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestService.kt index b6bf16a..8a6b792 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestService.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestService.kt @@ -121,4 +121,8 @@ class AccompanyJoinRequestService( private fun isBelowMemberLimit(accompany: Accompany, accompanyId: Long) = accompany.memberCount < getAcceptedJoinRequestCount(accompanyId) + 1 + + @Transactional(readOnly = true) + fun findJoinRequestsByAccompanyId(accompanyId: Long) = + accompanyJoinRequestRepository.findJoinRequestsByAccompanyId(accompanyId) } \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/dto/AccompanyJoinRequestDto.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/dto/AccompanyJoinRequestDto.kt index 16aa966..1f43e64 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/dto/AccompanyJoinRequestDto.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/dto/AccompanyJoinRequestDto.kt @@ -1,7 +1,10 @@ package com.withaeng.domain.accompanyjoinrequests.dto +import com.querydsl.core.annotations.QueryProjection import com.withaeng.domain.accompanyrequests.AccompanyJoinRequest import com.withaeng.domain.accompanyrequests.AccompanyJoinRequestStatus +import com.withaeng.domain.user.Gender +import java.time.LocalDateTime data class AccompanyJoinRequestDto( val id: Long, @@ -15,4 +18,17 @@ fun AccompanyJoinRequest.toDto() = AccompanyJoinRequestDto( userId = userId, accompanyJoinRequestStatus = status, accompanyId = accompany.id, +) + +data class FindAccompanyJoinRequestDto @QueryProjection constructor( + val joinRequestId: Long, + val joinRequestStatus: AccompanyJoinRequestStatus, + val nickname: String, + val profileImageUrl: String?, + val gender: Gender, + val introduction: String?, + val joinDate: LocalDateTime, + // TODO : 여행 관심사 Set 추가 필요 + // TODO : 온도 추가 필요 + // TODO : 연령대 추가 필요 ) \ No newline at end of file From b4793e1cae13497e567d2b4099f99e48ef962df5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Thu, 19 Sep 2024 23:58:20 +0900 Subject: [PATCH 158/174] =?UTF-8?q?Feature:=20=EB=8F=99=ED=96=89=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D=20memberCount=20=ED=95=84=EB=93=9C=20?= =?UTF-8?q?=EC=9C=A0=ED=9A=A8=EC=84=B1=20=EA=B2=80=EC=82=AC=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/withaeng/api/common/ControllerExceptionAdvice.kt | 4 ++-- .../api/controller/accompany/dto/AccompanyRequestDto.kt | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/common/ControllerExceptionAdvice.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/common/ControllerExceptionAdvice.kt index 6270efa..58c7e67 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/common/ControllerExceptionAdvice.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/common/ControllerExceptionAdvice.kt @@ -66,7 +66,7 @@ class ControllerExceptionAdvice { @ExceptionHandler(MethodArgumentNotValidException::class) protected fun handleMethodArgumentNotValidException(e: MethodArgumentNotValidException): ResponseEntity> { logger.error("MethodArgumentNotValidException handler", e) - val errorMessage = e.allErrors.joinToString(" ,") + val errorMessage = e.bindingResult.fieldError?.defaultMessage return errorResponse(WithaengExceptionType.ARGUMENT_NOT_VALID, errorMessage) } @@ -92,7 +92,7 @@ class ControllerExceptionAdvice { private fun errorResponse( exceptionType: WithaengExceptionType, - message: String? + message: String?, ) = errorResponse( exceptionType.httpStatusCode, ApiErrorResponse(exceptionType.name, message) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt index 592b0d6..1338900 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt @@ -7,6 +7,7 @@ import com.withaeng.api.applicationservice.accompany.dto.UpdateAccompanyServiceR import com.withaeng.api.common.PageInfoRequest import com.withaeng.domain.accompany.* import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.Min import java.time.LocalDate @Schema(description = "[Request] 동행 게시글 생성") @@ -36,6 +37,7 @@ data class CreateAccompanyRequest( val bannerImageUrl: String? = null, @Schema(description = "동행 멤버수") + @field:Min(2, message = "멤버 수는 최소 2명 이상(본인 + 동행자 1명 이상)이어야 합니다.") val memberCount: Long, @Schema(description = "동행 게시글에 부착할 태그 아이디 리스트") From b4e99370a8c1a6a677894cc8a9c41bbe8d3640dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Fri, 20 Sep 2024 00:04:08 +0900 Subject: [PATCH 159/174] =?UTF-8?q?Fix:=20=EB=8F=99=ED=96=89=20=EC=8A=B9?= =?UTF-8?q?=EC=9D=B8=20isBelowMemberLimit=20=EB=B3=B8=EC=9D=B8=20=ED=8F=AC?= =?UTF-8?q?=ED=95=A8=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=9C=A0=ED=9A=A8?= =?UTF-8?q?=EC=84=B1=20=EA=B2=80=EC=82=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/accompanyjoinrequests/AccompanyJoinRequestService.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestService.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestService.kt index 8a6b792..187bb7b 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestService.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompanyjoinrequests/AccompanyJoinRequestService.kt @@ -120,7 +120,7 @@ class AccompanyJoinRequestService( accompany.isCompleted() || isBelowMemberLimit(accompany, accompanyId) private fun isBelowMemberLimit(accompany: Accompany, accompanyId: Long) = - accompany.memberCount < getAcceptedJoinRequestCount(accompanyId) + 1 + accompany.memberCount <= getAcceptedJoinRequestCount(accompanyId) + 1 @Transactional(readOnly = true) fun findJoinRequestsByAccompanyId(accompanyId: Long) = From 037b6fdcca0f60bff0da78b0a5ba6753ae2b6a1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Sun, 22 Sep 2024 00:31:10 +0900 Subject: [PATCH 160/174] =?UTF-8?q?refactor:=20templated=20email=20send=20?= =?UTF-8?q?=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/AuthApplicationService.kt | 38 ++++----- .../auth/dto/AuthServiceRequestDto.kt | 2 +- .../api/controller/auth/AuthController.kt | 8 +- .../api/controller/auth/dto/AuthRequestDto.kt | 14 ++-- .../DeleteValidatingEmailScheduler.kt | 38 --------- .../DeleteVerificationEmailScheduler.kt | 38 +++++++++ .../api/scheduler/SendEmailScheduler.kt | 79 ++++++++++++------- .../validateemail/ValidatingEmailDto.kt | 23 ------ .../ValidatingEmailRepository.kt | 19 ----- .../validateemail/ValidatingEmailStatus.kt | 5 -- .../validateemail/ValidatingEmailType.kt | 5 -- .../VerificationEmail.kt} | 16 ++-- .../verificationemail/VerificationEmailDto.kt | 23 ++++++ .../VerificationEmailRepository.kt | 19 +++++ .../VerificationEmailService.kt} | 34 ++++---- .../VerificationEmailStatus.kt | 5 ++ .../VerificationEmailType.kt | 5 ++ withaeng-external/build.gradle.kts | 3 +- .../withaeng/external/email/EmailSender.kt | 6 ++ .../com/withaeng/external/email/SesConfig.kt | 28 +++++++ .../withaeng/external/email/SesEmailSender.kt | 18 +++++ .../external/email/template/EmailTemplate.kt | 51 ++++++++++++ .../email/template/EmailTemplateRenderer.kt | 18 +++++ .../email/template/TemplatedEmailSender.kt | 5 ++ .../template/TemplatedEmailSenderImpl.kt | 16 ++++ .../com/withaeng/external/ses/MailSender.kt | 6 -- .../withaeng/external/ses/MailSenderImpl.kt | 60 -------------- .../com/withaeng/external/ses/MailType.kt | 6 -- .../withaeng/external/ses/config/SESConfig.kt | 33 -------- .../external/ses/config/ThymeleafConfig.kt | 36 --------- ...ord-template.html => change-password.html} | 0 ...-email-template.html => verify-email.html} | 0 32 files changed, 339 insertions(+), 318 deletions(-) delete mode 100644 withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/DeleteValidatingEmailScheduler.kt create mode 100644 withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/DeleteVerificationEmailScheduler.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailDto.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailRepository.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailStatus.kt delete mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailType.kt rename withaeng-domain/src/main/kotlin/com/withaeng/domain/{validateemail/ValidatingEmail.kt => verificationemail/VerificationEmail.kt} (65%) create mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/verificationemail/VerificationEmailDto.kt create mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/verificationemail/VerificationEmailRepository.kt rename withaeng-domain/src/main/kotlin/com/withaeng/domain/{validateemail/ValidatingEmailService.kt => verificationemail/VerificationEmailService.kt} (62%) create mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/verificationemail/VerificationEmailStatus.kt create mode 100644 withaeng-domain/src/main/kotlin/com/withaeng/domain/verificationemail/VerificationEmailType.kt create mode 100644 withaeng-external/src/main/kotlin/com/withaeng/external/email/EmailSender.kt create mode 100644 withaeng-external/src/main/kotlin/com/withaeng/external/email/SesConfig.kt create mode 100644 withaeng-external/src/main/kotlin/com/withaeng/external/email/SesEmailSender.kt create mode 100644 withaeng-external/src/main/kotlin/com/withaeng/external/email/template/EmailTemplate.kt create mode 100644 withaeng-external/src/main/kotlin/com/withaeng/external/email/template/EmailTemplateRenderer.kt create mode 100644 withaeng-external/src/main/kotlin/com/withaeng/external/email/template/TemplatedEmailSender.kt create mode 100644 withaeng-external/src/main/kotlin/com/withaeng/external/email/template/TemplatedEmailSenderImpl.kt delete mode 100644 withaeng-external/src/main/kotlin/com/withaeng/external/ses/MailSender.kt delete mode 100644 withaeng-external/src/main/kotlin/com/withaeng/external/ses/MailSenderImpl.kt delete mode 100644 withaeng-external/src/main/kotlin/com/withaeng/external/ses/MailType.kt delete mode 100644 withaeng-external/src/main/kotlin/com/withaeng/external/ses/config/SESConfig.kt delete mode 100644 withaeng-external/src/main/kotlin/com/withaeng/external/ses/config/ThymeleafConfig.kt rename withaeng-external/src/main/resources/templates/{change-password-template.html => change-password.html} (100%) rename withaeng-external/src/main/resources/templates/{validate-email-template.html => verify-email.html} (100%) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/AuthApplicationService.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/AuthApplicationService.kt index 2f9d18f..89d57b3 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/AuthApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/AuthApplicationService.kt @@ -8,8 +8,8 @@ import com.withaeng.common.exception.WithaengExceptionType import com.withaeng.domain.user.UserRole import com.withaeng.domain.user.UserService import com.withaeng.domain.user.dto.UserSimpleDto -import com.withaeng.domain.validateemail.ValidatingEmailService -import com.withaeng.domain.validateemail.ValidatingEmailType +import com.withaeng.domain.verificationemail.VerificationEmailService +import com.withaeng.domain.verificationemail.VerificationEmailType import org.springframework.security.crypto.password.PasswordEncoder import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -19,7 +19,7 @@ import java.util.* @Transactional(readOnly = true) class AuthApplicationService( private val userService: UserService, - private val validatingEmailService: ValidatingEmailService, + private val verificationEmailService: VerificationEmailService, private val jwtAgent: JwtAgent, private val passwordEncoder: PasswordEncoder, ) { @@ -36,7 +36,7 @@ class AuthApplicationService( ) } userService.deleteByEmail(userEmail) - validatingEmailService.deleteAllByUserId(userDto.id) + verificationEmailService.deleteAllByUserId(userDto.id) } val newUserDto = userService.create( request.toCommand( @@ -44,11 +44,11 @@ class AuthApplicationService( passwordEncoder.encode(request.password) ) ) - validatingEmailService.create( + verificationEmailService.create( email = newUserDto.email, userId = newUserDto.id, code = UUID.randomUUID().toString(), - type = ValidatingEmailType.VALIDATE_EMAIL + type = VerificationEmailType.VERIFY_EMAIL ) return UserResponse(newUserDto.id, newUserDto.email, jwtAgent.provide(UserInfo.from(newUserDto))) } @@ -76,17 +76,17 @@ class AuthApplicationService( message = "이미 인증된 유저입니다." ) } - validatingEmailService.deleteAllByUserIdAndEmailType(userDto.id, ValidatingEmailType.VALIDATE_EMAIL) - validatingEmailService.create( + verificationEmailService.deleteAllByUserIdAndEmailType(userDto.id, VerificationEmailType.VERIFY_EMAIL) + verificationEmailService.create( email = userDto.email, userId = userDto.id, code = UUID.randomUUID().toString(), - type = ValidatingEmailType.VALIDATE_EMAIL + type = VerificationEmailType.VERIFY_EMAIL ) } @Transactional - fun validateEmail(request: ValidateEmailServiceRequest) { + fun verifyEmail(request: VerifyEmailServiceRequest) { val requestedEmail = request.email val userDto = userService.findByEmailOrNull(requestedEmail) ?: throw WithaengException.of( @@ -99,7 +99,7 @@ class AuthApplicationService( message = "이미 인증된 유저입니다." ) } - validateEmailCode( + verifyEmailCode( email = requestedEmail, userId = userDto.id, code = request.code @@ -113,12 +113,12 @@ class AuthApplicationService( type = WithaengExceptionType.NOT_EXIST, message = "이메일에 해당하는 유저를 찾을 수 없습니다." ) - validatingEmailService.deleteAllByUserIdAndEmailType(userDto.id, ValidatingEmailType.CHANGE_PASSWORD) - validatingEmailService.create( + verificationEmailService.deleteAllByUserIdAndEmailType(userDto.id, VerificationEmailType.CHANGE_PASSWORD) + verificationEmailService.create( email = userDto.email, userId = userDto.id, code = UUID.randomUUID().toString(), - type = ValidatingEmailType.CHANGE_PASSWORD + type = VerificationEmailType.CHANGE_PASSWORD ) } @@ -129,7 +129,7 @@ class AuthApplicationService( type = WithaengExceptionType.NOT_EXIST, message = "이메일에 해당하는 유저를 찾을 수 없습니다." ) - validateEmailCode( + verifyEmailCode( email = email, userId = userDto.id, code = request.code @@ -137,12 +137,12 @@ class AuthApplicationService( userService.updatePassword(userDto.id, passwordEncoder.encode(request.password)) } - private fun validateEmailCode(email: String, userId: Long, code: String) { - val validatingEmailDto = validatingEmailService.findByEmail(email) - if (validatingEmailDto.userId != userId || validatingEmailDto.code != code) { + private fun verifyEmailCode(email: String, userId: Long, code: String) { + val verificationEmailDto = verificationEmailService.findByEmail(email) + if (verificationEmailDto.userId != userId || verificationEmailDto.code != code) { throw WithaengException.of(WithaengExceptionType.INVALID_INPUT, "Code가 올바르지 않습니다.") } - validatingEmailService.deleteById(validatingEmailDto.id) + verificationEmailService.deleteById(verificationEmailDto.id) } private fun UserSimpleDto.isValidUser(): Boolean { diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/dto/AuthServiceRequestDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/dto/AuthServiceRequestDto.kt index a028161..3b59250 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/dto/AuthServiceRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/dto/AuthServiceRequestDto.kt @@ -29,7 +29,7 @@ data class ResendEmailServiceRequest( val email: String, ) -data class ValidateEmailServiceRequest( +data class VerifyEmailServiceRequest( val email: String, val code: String, ) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/auth/AuthController.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/auth/AuthController.kt index 2bc7e3b..080d2d8 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/auth/AuthController.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/auth/AuthController.kt @@ -12,7 +12,7 @@ import org.springframework.web.bind.annotation.* @RestController @RequestMapping("/api/v1/auth") class AuthController( - private val authApplicationService: AuthApplicationService + private val authApplicationService: AuthApplicationService, ) { @Operation(summary = "Sign Up API", description = "회원가입 API") @PostMapping("/sign-up") @@ -38,10 +38,10 @@ class AuthController( ) } - @Operation(summary = "Validating Email API", description = "이메일 인증 API") + @Operation(summary = "Email Verify API", description = "이메일 인증 API") @PutMapping("/validate-email") - fun validateEmail(@RequestBody request: ValidateEmailRequest): ApiResponse { - authApplicationService.validateEmail(request.toServiceRequest()) + fun verifyEmail(@RequestBody request: VerifyEmailRequest): ApiResponse { + authApplicationService.verifyEmail(request.toServiceRequest()) return ApiResponse.success() } diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/auth/dto/AuthRequestDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/auth/dto/AuthRequestDto.kt index bf89d7a..27abac9 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/auth/dto/AuthRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/auth/dto/AuthRequestDto.kt @@ -33,7 +33,7 @@ data class SignInRequest( val email: String, @Schema(description = "로그인 할 패스워드") - val password: String + val password: String, ) fun SignInRequest.toServiceRequest(): SignInServiceRequest = SignInServiceRequest( @@ -44,7 +44,7 @@ fun SignInRequest.toServiceRequest(): SignInServiceRequest = SignInServiceReques @Schema(description = "[Request] 이메일 재전송") data class ResendEmailRequest( @Schema(description = "재전송 할 이메일") - val email: String + val email: String, ) fun ResendEmailRequest.toServiceRequest(): ResendEmailServiceRequest = ResendEmailServiceRequest( @@ -52,15 +52,15 @@ fun ResendEmailRequest.toServiceRequest(): ResendEmailServiceRequest = ResendEma ) @Schema(description = "[Request] 이메일 인증") -data class ValidateEmailRequest( +data class VerifyEmailRequest( @Schema(description = "이메일 인증 할 이메일") val email: String, @Schema(description = "이메일 인증으로 보낸 코드 (UUID 형태)") - val code: String + val code: String, ) -fun ValidateEmailRequest.toServiceRequest(): ValidateEmailServiceRequest = ValidateEmailServiceRequest( +fun VerifyEmailRequest.toServiceRequest(): VerifyEmailServiceRequest = VerifyEmailServiceRequest( email = email, code = code ) @@ -69,7 +69,7 @@ fun ValidateEmailRequest.toServiceRequest(): ValidateEmailServiceRequest = Valid @Schema(description = "[Request] 비밀번호 재설정을 위한 이메일 전송") data class SendEmailForChangePasswordRequest( @Schema(description = "이메일 인증 할 이메일") - val email: String + val email: String, ) fun SendEmailForChangePasswordRequest.toServiceRequest(): SendEmailForChangePasswordServiceRequest = @@ -84,7 +84,7 @@ data class ChangePasswordRequest( val code: String, @Schema(description = "새로운 패스워드") - val password: String + val password: String, ) fun ChangePasswordRequest.toServiceRequest(): ChangePasswordServiceRequest = ChangePasswordServiceRequest( diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/DeleteValidatingEmailScheduler.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/DeleteValidatingEmailScheduler.kt deleted file mode 100644 index 58d4296..0000000 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/DeleteValidatingEmailScheduler.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.withaeng.api.scheduler - -import com.withaeng.domain.validateemail.ValidatingEmailService -import com.withaeng.domain.validateemail.ValidatingEmailStatus -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import org.springframework.scheduling.annotation.Async -import org.springframework.scheduling.annotation.Scheduled -import org.springframework.stereotype.Component -import org.springframework.transaction.annotation.Transactional -import java.time.LocalDateTime - -@Component -class DeleteValidatingEmailScheduler( - private val validatingEmailService: ValidatingEmailService -) { - private val log: Logger = LoggerFactory.getLogger(DeleteValidatingEmailScheduler::class.java) - - @Scheduled(cron = "0 * * * * *") - @Async("asyncSchedulerExecutor") - @Transactional - fun deleteEmails() { - val now = LocalDateTime.now() - log.info("Start deleting validating emails at {}", now) - val willDeleteEmails = validatingEmailService.findAllByStatusNot(ValidatingEmailStatus.YET) - .filter { emailDto -> emailDto.createdAt.plusMinutes(VALIDATING_MAIL_EXPIRED_MINUTES) < now } - .map { emailDto -> emailDto.id } - .toSet() - if (willDeleteEmails.isNotEmpty()) { - validatingEmailService.deleteAllById(willDeleteEmails) - log.info("End deleteing {} validating emails at {}", willDeleteEmails.size, LocalDateTime.now()) - } - } - - companion object { - private const val VALIDATING_MAIL_EXPIRED_MINUTES = 5L - } -} diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/DeleteVerificationEmailScheduler.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/DeleteVerificationEmailScheduler.kt new file mode 100644 index 0000000..c78b72d --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/DeleteVerificationEmailScheduler.kt @@ -0,0 +1,38 @@ +package com.withaeng.api.scheduler + +import com.withaeng.domain.verificationemail.VerificationEmailService +import com.withaeng.domain.verificationemail.VerificationEmailStatus +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import org.springframework.scheduling.annotation.Async +import org.springframework.scheduling.annotation.Scheduled +import org.springframework.stereotype.Component +import org.springframework.transaction.annotation.Transactional +import java.time.LocalDateTime + +@Component +class DeleteVerificationEmailScheduler( + private val verificationEmailService: VerificationEmailService, +) { + companion object { + private const val VERIFICATION_EMAIL_EXPIRED_MINUTES = 5L + } + + private val log: Logger = LoggerFactory.getLogger(DeleteVerificationEmailScheduler::class.java) + + @Scheduled(cron = "0 * * * * *") + @Async("asyncSchedulerExecutor") + @Transactional + fun deleteEmails() { + val now = LocalDateTime.now() + log.info("Start deleting verification emails at {}", now) + val willDeleteEmails = verificationEmailService.findAllByStatusNot(VerificationEmailStatus.YET) + .filter { emailDto -> emailDto.createdAt.plusMinutes(VERIFICATION_EMAIL_EXPIRED_MINUTES) < now } + .map { emailDto -> emailDto.id } + .toSet() + if (willDeleteEmails.isNotEmpty()) { + verificationEmailService.deleteAllById(willDeleteEmails) + log.info("End deleting {} verification emails at {}", willDeleteEmails.size, LocalDateTime.now()) + } + } +} diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/SendEmailScheduler.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/SendEmailScheduler.kt index 0e9d230..15c593c 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/SendEmailScheduler.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/scheduler/SendEmailScheduler.kt @@ -1,10 +1,11 @@ package com.withaeng.api.scheduler -import com.withaeng.domain.validateemail.ValidatingEmailService -import com.withaeng.domain.validateemail.ValidatingEmailStatus -import com.withaeng.domain.validateemail.ValidatingEmailType -import com.withaeng.external.ses.MailSender -import com.withaeng.external.ses.MailType +import com.withaeng.domain.verificationemail.VerificationEmailDto +import com.withaeng.domain.verificationemail.VerificationEmailService +import com.withaeng.domain.verificationemail.VerificationEmailStatus +import com.withaeng.domain.verificationemail.VerificationEmailType +import com.withaeng.external.email.template.EmailTemplate +import com.withaeng.external.email.template.TemplatedEmailSender import org.slf4j.Logger import org.slf4j.LoggerFactory import org.springframework.beans.factory.annotation.Value @@ -17,47 +18,65 @@ import java.util.concurrent.TimeUnit @Component class SendEmailScheduler( - private val validatingEmailService: ValidatingEmailService, - private val mailSender: MailSender, - @Value("\${withaeng.host}") - private val host: String, + private val verificationEmailService: VerificationEmailService, + private val templatedEmailSender: TemplatedEmailSender, + @Value("\${withaeng.host}") private val host: String, ) { companion object { - private const val EMAIL_VALIDATE_REDIRECT_PATH = "/check-email" + private const val FIXED_DELAY_SECONDS = 20L + private const val VERIFY_EMAIL_REDIRECT_PATH = "/check-email" private const val CHANGE_PASSWORD_REDIRECT_PATH = "/check-email-pw" } private val log: Logger = LoggerFactory.getLogger(SendEmailScheduler::class.java) - @Scheduled(timeUnit = TimeUnit.SECONDS, fixedDelay = 20) + @Scheduled(timeUnit = TimeUnit.SECONDS, fixedDelay = FIXED_DELAY_SECONDS) @Async("asyncSchedulerExecutor") @Transactional fun sendEmail() { val now = LocalDateTime.now() log.info("Start sending emails at {}", now) - val willSendMails = validatingEmailService.findAllByStatusNot(ValidatingEmailStatus.DONE) - willSendMails.forEach { emailDto -> - val to = emailDto.email - val code = emailDto.code - val type = emailDto.type - val redirectUrl = "${type.toValidatingUrl()}?code=$code&email=$to" - mailSender.send(redirectUrl, to, emailDto.type.toMailType()) + + val verificationEmails = getSendTargets() + if (verificationEmails.isEmpty()) { + log.info("No emails to send at {}", now) + return } - if (willSendMails.isNotEmpty()) { - val updateCount = validatingEmailService.updateStatusByIds( - willSendMails.map { it.id }.toSet(), - ValidatingEmailStatus.DONE + + verificationEmails.forEach(this::sendVerificationEmail) + + val updatedCount = updateEmailStatuses(verificationEmails) + log.info("End sending {} emails at {}", updatedCount, now) + } + + private fun getSendTargets() = verificationEmailService.findAllByStatusNot(VerificationEmailStatus.DONE) + + private fun sendVerificationEmail(verificationEmail: VerificationEmailDto) = + templatedEmailSender.send( + to = verificationEmail.email, + template = verificationEmail.toEmailTemplate(), + variables = mapOf( + "email" to verificationEmail.email, + "redirectUrl" to createRedirectUrl(verificationEmail), ) - log.info("End sending {} emails at {}", updateCount, now) - } + ) + + private fun updateEmailStatuses(verificationEmails: List): Int { + val emailIds = verificationEmails.map { it.id }.toSet() + return verificationEmailService.updateStatusByIds(emailIds, VerificationEmailStatus.DONE) } - private fun ValidatingEmailType.toMailType(): MailType = - if (this == ValidatingEmailType.VALIDATE_EMAIL) - MailType.VALIDATE_EMAIL else MailType.CHANGE_PASSWORD + private fun createRedirectUrl(verificationEmail: VerificationEmailDto): String = + "${host}${verificationEmail.toRedirectPath()}?email=${verificationEmail.email}&code=${verificationEmail.code}" - private fun ValidatingEmailType.toValidatingUrl(): String = - if (this == ValidatingEmailType.VALIDATE_EMAIL) - host + EMAIL_VALIDATE_REDIRECT_PATH else host + CHANGE_PASSWORD_REDIRECT_PATH + private fun VerificationEmailDto.toEmailTemplate(): EmailTemplate = when (this.type) { + VerificationEmailType.VERIFY_EMAIL -> EmailTemplate.VERIFY_EMAIL + VerificationEmailType.CHANGE_PASSWORD -> EmailTemplate.CHANGE_PASSWORD + } + + private fun VerificationEmailDto.toRedirectPath(): String = when (this.type) { + VerificationEmailType.VERIFY_EMAIL -> VERIFY_EMAIL_REDIRECT_PATH + VerificationEmailType.CHANGE_PASSWORD -> CHANGE_PASSWORD_REDIRECT_PATH + } } diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailDto.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailDto.kt deleted file mode 100644 index 84f6067..0000000 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailDto.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.withaeng.domain.validateemail - -import java.time.LocalDateTime - -data class ValidatingEmailDto( - val id: Long, - val email: String, - val userId: Long, - val code: String, - val status: ValidatingEmailStatus, - val type: ValidatingEmailType, - val createdAt: LocalDateTime -) - -fun ValidatingEmail.toDto(): ValidatingEmailDto = ValidatingEmailDto( - id = id, - email = email, - userId = userId, - code = code, - status = status, - type = type, - createdAt = createdAt -) diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailRepository.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailRepository.kt deleted file mode 100644 index ade8e3d..0000000 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailRepository.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.withaeng.domain.validateemail - -import org.springframework.data.jpa.repository.JpaRepository -import org.springframework.data.jpa.repository.Modifying -import org.springframework.data.jpa.repository.Query - -interface ValidatingEmailRepository : JpaRepository { - fun findAllByStatusNot(status: ValidatingEmailStatus): List - - fun findByEmail(email: String): ValidatingEmail? - - @Modifying - @Query("UPDATE ValidatingEmail v SET v.status = :status WHERE v.id in :ids") - fun updateStatusByIds(ids: Set, status: ValidatingEmailStatus): Int - - fun deleteAllByUserId(userId: Long) - - fun deleteAllByUserIdAndType(id: Long, status: ValidatingEmailType) -} diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailStatus.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailStatus.kt deleted file mode 100644 index 831b705..0000000 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailStatus.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.withaeng.domain.validateemail - -enum class ValidatingEmailStatus { - YET, DONE, FAILED -} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailType.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailType.kt deleted file mode 100644 index 44f9dc8..0000000 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailType.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.withaeng.domain.validateemail - -enum class ValidatingEmailType { - VALIDATE_EMAIL, CHANGE_PASSWORD -} diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmail.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/verificationemail/VerificationEmail.kt similarity index 65% rename from withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmail.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/verificationemail/VerificationEmail.kt index ac450cb..8783fdc 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmail.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/verificationemail/VerificationEmail.kt @@ -1,25 +1,25 @@ -package com.withaeng.domain.validateemail +package com.withaeng.domain.verificationemail import com.withaeng.domain.BaseEntity import jakarta.persistence.* -@Table(name = "validating_emails") +@Table(name = "verification_email") @Entity -class ValidatingEmail( +class VerificationEmail( @Column(name = "email", nullable = false) val email: String, - @Column(name = "user_id", nullable = false) - val userId: Long, - @Column(name = "code", nullable = false) val code: String, @Enumerated(EnumType.STRING) @Column(name = "type", nullable = false) - val type: ValidatingEmailType = ValidatingEmailType.VALIDATE_EMAIL, + val type: VerificationEmailType, @Enumerated(EnumType.STRING) @Column(name = "status", nullable = false) - val status: ValidatingEmailStatus = ValidatingEmailStatus.YET, + val status: VerificationEmailStatus = VerificationEmailStatus.YET, + + @Column(name = "user_id", nullable = false) + val userId: Long, ) : BaseEntity() diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/verificationemail/VerificationEmailDto.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/verificationemail/VerificationEmailDto.kt new file mode 100644 index 0000000..03c688a --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/verificationemail/VerificationEmailDto.kt @@ -0,0 +1,23 @@ +package com.withaeng.domain.verificationemail + +import java.time.LocalDateTime + +data class VerificationEmailDto( + val id: Long, + val createdAt: LocalDateTime, + val email: String, + val code: String, + val type: VerificationEmailType, + val status: VerificationEmailStatus, + val userId: Long, +) + +fun VerificationEmail.toDto(): VerificationEmailDto = VerificationEmailDto( + id = id, + createdAt = createdAt, + email = email, + code = code, + type = type, + status = status, + userId = userId, +) diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/verificationemail/VerificationEmailRepository.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/verificationemail/VerificationEmailRepository.kt new file mode 100644 index 0000000..b439322 --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/verificationemail/VerificationEmailRepository.kt @@ -0,0 +1,19 @@ +package com.withaeng.domain.verificationemail + +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.data.jpa.repository.Modifying +import org.springframework.data.jpa.repository.Query + +interface VerificationEmailRepository : JpaRepository { + fun findAllByStatusNot(status: VerificationEmailStatus): List + + fun findByEmail(email: String): VerificationEmail? + + @Modifying + @Query("UPDATE VerificationEmail v SET v.status = :status WHERE v.id in :ids") + fun updateStatusByIds(ids: Set, status: VerificationEmailStatus): Int + + fun deleteAllByUserId(userId: Long) + + fun deleteAllByUserIdAndType(id: Long, status: VerificationEmailType) +} diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailService.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/verificationemail/VerificationEmailService.kt similarity index 62% rename from withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailService.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/verificationemail/VerificationEmailService.kt index afc89a3..27549a7 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/validateemail/ValidatingEmailService.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/verificationemail/VerificationEmailService.kt @@ -1,4 +1,4 @@ -package com.withaeng.domain.validateemail +package com.withaeng.domain.verificationemail import com.withaeng.common.exception.WithaengException import com.withaeng.common.exception.WithaengExceptionType @@ -9,13 +9,13 @@ import org.springframework.transaction.annotation.Transactional @Service @Transactional(readOnly = true) -class ValidatingEmailService( +class VerificationEmailService( private val userRepository: UserRepository, - private val validatingEmailRepository: ValidatingEmailRepository + private val verificationEmailRepository: VerificationEmailRepository, ) { @Transactional - fun create(email: String, userId: Long, code: String, type: ValidatingEmailType): ValidatingEmailDto { + fun create(email: String, userId: Long, code: String, type: VerificationEmailType): VerificationEmailDto { userRepository.findByIdOrNull(userId) ?: throw WithaengException.of( type = WithaengExceptionType.NOT_EXIST, message = "$userId 에 해당하는 사용자를 찾을 수 없습니다." @@ -26,8 +26,8 @@ class ValidatingEmailService( message = "이메일 인증을 진행하는데 올바르지 않은 입력입니다." ) } - return validatingEmailRepository.save( - ValidatingEmail( + return verificationEmailRepository.save( + VerificationEmail( email = email, userId = userId, code = code, @@ -36,40 +36,40 @@ class ValidatingEmailService( ).toDto() } - fun findByEmail(email: String): ValidatingEmailDto { - return validatingEmailRepository.findByEmail(email)?.toDto() + fun findByEmail(email: String): VerificationEmailDto { + return verificationEmailRepository.findByEmail(email)?.toDto() ?: throw WithaengException.of( type = WithaengExceptionType.NOT_EXIST, message = "이메일에 해당하는 요청이 없습니다." ) } - fun findAllByStatusNot(status: ValidatingEmailStatus): List { - return validatingEmailRepository.findAllByStatusNot(status).map { it.toDto() } + fun findAllByStatusNot(status: VerificationEmailStatus): List { + return verificationEmailRepository.findAllByStatusNot(status).map { it.toDto() } } @Transactional fun deleteById(id: Long) { - validatingEmailRepository.deleteById(id) + verificationEmailRepository.deleteById(id) } @Transactional fun deleteAllById(ids: Set) { - validatingEmailRepository.deleteAllById(ids) + verificationEmailRepository.deleteAllById(ids) } @Transactional fun deleteAllByUserId(userId: Long) { - validatingEmailRepository.deleteAllByUserId(userId) + verificationEmailRepository.deleteAllByUserId(userId) } @Transactional - fun deleteAllByUserIdAndEmailType(userId: Long, emailType: ValidatingEmailType) { - validatingEmailRepository.deleteAllByUserIdAndType(userId, emailType) + fun deleteAllByUserIdAndEmailType(userId: Long, emailType: VerificationEmailType) { + verificationEmailRepository.deleteAllByUserIdAndType(userId, emailType) } @Transactional - fun updateStatusByIds(ids: Set, status: ValidatingEmailStatus): Int { - return validatingEmailRepository.updateStatusByIds(ids, status) + fun updateStatusByIds(ids: Set, status: VerificationEmailStatus): Int { + return verificationEmailRepository.updateStatusByIds(ids, status) } } diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/verificationemail/VerificationEmailStatus.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/verificationemail/VerificationEmailStatus.kt new file mode 100644 index 0000000..b33b0cb --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/verificationemail/VerificationEmailStatus.kt @@ -0,0 +1,5 @@ +package com.withaeng.domain.verificationemail + +enum class VerificationEmailStatus { + YET, DONE, FAILED +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/verificationemail/VerificationEmailType.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/verificationemail/VerificationEmailType.kt new file mode 100644 index 0000000..57d3ecc --- /dev/null +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/verificationemail/VerificationEmailType.kt @@ -0,0 +1,5 @@ +package com.withaeng.domain.verificationemail + +enum class VerificationEmailType { + VERIFY_EMAIL, CHANGE_PASSWORD +} diff --git a/withaeng-external/build.gradle.kts b/withaeng-external/build.gradle.kts index a27e38d..2355b51 100644 --- a/withaeng-external/build.gradle.kts +++ b/withaeng-external/build.gradle.kts @@ -1,4 +1,5 @@ dependencies { + // Email + implementation("software.amazon.awssdk:ses:2.28.3") implementation("org.springframework.boot:spring-boot-starter-thymeleaf") - implementation("com.amazonaws:aws-java-sdk-ses:1.12.408") } \ No newline at end of file diff --git a/withaeng-external/src/main/kotlin/com/withaeng/external/email/EmailSender.kt b/withaeng-external/src/main/kotlin/com/withaeng/external/email/EmailSender.kt new file mode 100644 index 0000000..2df83b5 --- /dev/null +++ b/withaeng-external/src/main/kotlin/com/withaeng/external/email/EmailSender.kt @@ -0,0 +1,6 @@ +package com.withaeng.external.email + +interface EmailSender { + + fun send(to: String, subject: String, content: String) +} \ No newline at end of file diff --git a/withaeng-external/src/main/kotlin/com/withaeng/external/email/SesConfig.kt b/withaeng-external/src/main/kotlin/com/withaeng/external/email/SesConfig.kt new file mode 100644 index 0000000..24f42d0 --- /dev/null +++ b/withaeng-external/src/main/kotlin/com/withaeng/external/email/SesConfig.kt @@ -0,0 +1,28 @@ +package com.withaeng.external.email + +import org.springframework.beans.factory.annotation.Value +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider +import software.amazon.awssdk.regions.Region +import software.amazon.awssdk.services.ses.SesClient + +@Configuration +class SesConfig( + @Value("\${cloud.aws.credentials.access-key}") + private var accessKey: String, + @Value("\${cloud.aws.credentials.secret-key}") + private var secretKey: String, + @Value("\${cloud.aws.ses.region}") + private var region: String, +) { + + @Bean + fun sesClient(): SesClient { + return SesClient.builder() + .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(accessKey, secretKey))) + .region(Region.of(region)) + .build() + } +} \ No newline at end of file diff --git a/withaeng-external/src/main/kotlin/com/withaeng/external/email/SesEmailSender.kt b/withaeng-external/src/main/kotlin/com/withaeng/external/email/SesEmailSender.kt new file mode 100644 index 0000000..ff81833 --- /dev/null +++ b/withaeng-external/src/main/kotlin/com/withaeng/external/email/SesEmailSender.kt @@ -0,0 +1,18 @@ +package com.withaeng.external.email + +import org.springframework.beans.factory.annotation.Value +import org.springframework.stereotype.Component +import software.amazon.awssdk.services.ses.SesClient + +@Component +class SesEmailSender( + private val sesClient: SesClient, + @Value("\${cloud.aws.ses.from}") + private var from: String, +) : EmailSender { + + override fun send(to: String, subject: String, content: String) { + val request = SesFactory.createRequest(to, subject, from, content) + sesClient.sendEmail(request) + } +} diff --git a/withaeng-external/src/main/kotlin/com/withaeng/external/email/template/EmailTemplate.kt b/withaeng-external/src/main/kotlin/com/withaeng/external/email/template/EmailTemplate.kt new file mode 100644 index 0000000..21e6b20 --- /dev/null +++ b/withaeng-external/src/main/kotlin/com/withaeng/external/email/template/EmailTemplate.kt @@ -0,0 +1,51 @@ +package com.withaeng.external.email.template + +enum class EmailTemplate( + private val subject: String, + private val variables: Map>, +) { + VERIFY_EMAIL( + "같이행 서비스 이메일 인증을 부탁드립니다.", + mapOf( + "email" to String::class.java, + "redirectUrl" to String::class.java + ) + ), + CHANGE_PASSWORD( + "같이행 서비스 이메일 인증을 부탁드립니다.", + mapOf( + "email" to String::class.java, + "redirectUrl" to String::class.java + ) + ); + + fun templateName(): String { + return this.name.lowercase().replace("_", "-") + } + + fun subject(): String { + return this.subject + } + + fun validateVariables(variables: Map) { + validateHasRequiredVariables(variables) + validateVariableTypes(variables) + } + + private fun validateHasRequiredVariables(variables: Map) { + val requiredVariables = this.variables.keys + val missingVariables = requiredVariables.filter { !variables.containsKey(it) } + if (missingVariables.isNotEmpty()) { + throw IllegalArgumentException("Missing variables: $missingVariables") + } + } + + private fun validateVariableTypes(variables: Map) { + val invalidVariables = variables.filter { (key, value) -> + this.variables[key]?.isInstance(value) == false + } + if (invalidVariables.isNotEmpty()) { + throw IllegalArgumentException("Invalid variables: $invalidVariables") + } + } +} diff --git a/withaeng-external/src/main/kotlin/com/withaeng/external/email/template/EmailTemplateRenderer.kt b/withaeng-external/src/main/kotlin/com/withaeng/external/email/template/EmailTemplateRenderer.kt new file mode 100644 index 0000000..111f768 --- /dev/null +++ b/withaeng-external/src/main/kotlin/com/withaeng/external/email/template/EmailTemplateRenderer.kt @@ -0,0 +1,18 @@ +package com.withaeng.external.email.template + +import org.springframework.stereotype.Component +import org.thymeleaf.TemplateEngine +import org.thymeleaf.context.Context + +@Component +class EmailTemplateRenderer( + private val templateEngine: TemplateEngine, +) { + fun render(template: EmailTemplate, variables: Map): String { + template.validateVariables(variables) + val context = Context().apply { + setVariables(variables) + } + return templateEngine.process(template.templateName(), context) + } +} \ No newline at end of file diff --git a/withaeng-external/src/main/kotlin/com/withaeng/external/email/template/TemplatedEmailSender.kt b/withaeng-external/src/main/kotlin/com/withaeng/external/email/template/TemplatedEmailSender.kt new file mode 100644 index 0000000..35bed97 --- /dev/null +++ b/withaeng-external/src/main/kotlin/com/withaeng/external/email/template/TemplatedEmailSender.kt @@ -0,0 +1,5 @@ +package com.withaeng.external.email.template + +interface TemplatedEmailSender { + fun send(to: String, template: EmailTemplate, variables: Map) +} \ No newline at end of file diff --git a/withaeng-external/src/main/kotlin/com/withaeng/external/email/template/TemplatedEmailSenderImpl.kt b/withaeng-external/src/main/kotlin/com/withaeng/external/email/template/TemplatedEmailSenderImpl.kt new file mode 100644 index 0000000..5850499 --- /dev/null +++ b/withaeng-external/src/main/kotlin/com/withaeng/external/email/template/TemplatedEmailSenderImpl.kt @@ -0,0 +1,16 @@ +package com.withaeng.external.email.template + +import com.withaeng.external.email.EmailSender +import org.springframework.stereotype.Component + +@Component +class TemplatedEmailSenderImpl( + private val emailSender: EmailSender, + private val templateRenderer: EmailTemplateRenderer, +) : TemplatedEmailSender { + + override fun send(to: String, template: EmailTemplate, variables: Map) { + val content = templateRenderer.render(template, variables) + emailSender.send(to, template.subject(), content) + } +} diff --git a/withaeng-external/src/main/kotlin/com/withaeng/external/ses/MailSender.kt b/withaeng-external/src/main/kotlin/com/withaeng/external/ses/MailSender.kt deleted file mode 100644 index 42c0a54..0000000 --- a/withaeng-external/src/main/kotlin/com/withaeng/external/ses/MailSender.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.withaeng.external.ses - -interface MailSender { - - fun send(redirectUrl: String, to: String, type: MailType) -} diff --git a/withaeng-external/src/main/kotlin/com/withaeng/external/ses/MailSenderImpl.kt b/withaeng-external/src/main/kotlin/com/withaeng/external/ses/MailSenderImpl.kt deleted file mode 100644 index 08f4f89..0000000 --- a/withaeng-external/src/main/kotlin/com/withaeng/external/ses/MailSenderImpl.kt +++ /dev/null @@ -1,60 +0,0 @@ -package com.withaeng.external.ses - -import com.amazonaws.services.simpleemail.AmazonSimpleEmailService -import com.amazonaws.services.simpleemail.model.* -import org.springframework.beans.factory.annotation.Value -import org.springframework.stereotype.Service -import org.thymeleaf.TemplateEngine -import org.thymeleaf.context.Context -import java.nio.charset.StandardCharsets - -@Service -class MailSenderImpl( - private val emailService: AmazonSimpleEmailService, - private val templateEngine: TemplateEngine -) : MailSender { - - @Value("\${cloud.aws.ses.from}") - private lateinit var from: String - - override fun send(redirectUrl: String, to: String, type: MailType) { - send( - template = type.templateName, - variables = mapOf( - VARIABLE_THYMELEAF_REDIRECT_URL to redirectUrl, - VARIABLE_THYMELEAF_EMAIL to to - ), - to = to - ) - } - - private fun send(template: String, variables: Map, to: String) { - val content = templateEngine.process(template, createContext(variables)) - val request = createSendEmailRequest(content, to) - emailService.sendEmail(request) - } - - private fun createContext(variables: Map): Context { - return Context().apply { setVariables(variables) } - } - - private fun createSendEmailRequest(content: String, to: String): SendEmailRequest { - return SendEmailRequest() - .withDestination(Destination().withToAddresses(to)) - .withSource(from) - .withMessage( - Message() - .withSubject( - Content().withCharset(StandardCharsets.UTF_8.name()).withData(VALIDATING_EMAIL_SUBJECT) - ) - .withBody(Body().withHtml(Content().withCharset(StandardCharsets.UTF_8.name()).withData(content))) - ) - } - - companion object { - private const val VALIDATING_EMAIL_SUBJECT = "같이행 서비스 이메일 인증을 부탁드립니다." - - private const val VARIABLE_THYMELEAF_REDIRECT_URL = "redirectUrl" - private const val VARIABLE_THYMELEAF_EMAIL = "email" - } -} diff --git a/withaeng-external/src/main/kotlin/com/withaeng/external/ses/MailType.kt b/withaeng-external/src/main/kotlin/com/withaeng/external/ses/MailType.kt deleted file mode 100644 index 85faa34..0000000 --- a/withaeng-external/src/main/kotlin/com/withaeng/external/ses/MailType.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.withaeng.external.ses - -enum class MailType(val templateName: String) { - VALIDATE_EMAIL("validate-email-template"), - CHANGE_PASSWORD("change-password-template") -} diff --git a/withaeng-external/src/main/kotlin/com/withaeng/external/ses/config/SESConfig.kt b/withaeng-external/src/main/kotlin/com/withaeng/external/ses/config/SESConfig.kt deleted file mode 100644 index 2ad6dbb..0000000 --- a/withaeng-external/src/main/kotlin/com/withaeng/external/ses/config/SESConfig.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.withaeng.external.ses.config - -import com.amazonaws.auth.AWSStaticCredentialsProvider -import com.amazonaws.auth.BasicAWSCredentials -import com.amazonaws.regions.Regions -import com.amazonaws.services.simpleemail.AmazonSimpleEmailService -import com.amazonaws.services.simpleemail.AmazonSimpleEmailServiceClientBuilder -import org.springframework.beans.factory.annotation.Value -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration - -@Configuration -// TODO: Device SES Config from development environment (local or prod) -class SESConfig { - - @Value("\${cloud.aws.credentials.access-key}") - private lateinit var accessKey: String - - @Value("\${cloud.aws.credentials.secret-key}") - private lateinit var secretKey: String - - @Value("\${cloud.aws.ses.region}") - private lateinit var regionName: String - - @Bean - fun amazonSimpleEmailService(): AmazonSimpleEmailService { - val credentials = BasicAWSCredentials(accessKey, secretKey) - return AmazonSimpleEmailServiceClientBuilder.standard() - .withRegion(Regions.fromName(regionName)) - .withCredentials(AWSStaticCredentialsProvider(credentials)) - .build() - } -} \ No newline at end of file diff --git a/withaeng-external/src/main/kotlin/com/withaeng/external/ses/config/ThymeleafConfig.kt b/withaeng-external/src/main/kotlin/com/withaeng/external/ses/config/ThymeleafConfig.kt deleted file mode 100644 index 5bb5a27..0000000 --- a/withaeng-external/src/main/kotlin/com/withaeng/external/ses/config/ThymeleafConfig.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.withaeng.external.ses.config - -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.thymeleaf.TemplateEngine -import org.thymeleaf.spring6.SpringTemplateEngine -import org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver -import org.thymeleaf.templatemode.TemplateMode - -@Configuration -class ThymeleafConfig { - - @Bean - fun htmlTemplateEngine(springResourceTemplateResolver: SpringResourceTemplateResolver): TemplateEngine { - return SpringTemplateEngine().apply { - addTemplateResolver(springResourceTemplateResolver) - } - } - - @Bean - fun springResourceTemplateResolver(): SpringResourceTemplateResolver { - return SpringResourceTemplateResolver().apply { - prefix = TEMPLATE_PREFIX - characterEncoding = TEMPLATE_CHARACTER_ENCODING - suffix = TEMPLATE_SUFFIX - templateMode = TemplateMode.HTML - isCacheable = false - } - } - - companion object { - private const val TEMPLATE_PREFIX = "classpath:templates/" - private const val TEMPLATE_CHARACTER_ENCODING = "UTF-8" - private const val TEMPLATE_SUFFIX = ".html" - } -} \ No newline at end of file diff --git a/withaeng-external/src/main/resources/templates/change-password-template.html b/withaeng-external/src/main/resources/templates/change-password.html similarity index 100% rename from withaeng-external/src/main/resources/templates/change-password-template.html rename to withaeng-external/src/main/resources/templates/change-password.html diff --git a/withaeng-external/src/main/resources/templates/validate-email-template.html b/withaeng-external/src/main/resources/templates/verify-email.html similarity index 100% rename from withaeng-external/src/main/resources/templates/validate-email-template.html rename to withaeng-external/src/main/resources/templates/verify-email.html From 0c9d407bc24ca106d3d3d04f1237240edd0bcf81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Sun, 22 Sep 2024 00:39:50 +0900 Subject: [PATCH 161/174] =?UTF-8?q?fix:=20factory=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/withaeng/external/email/SesFactory.kt | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 withaeng-external/src/main/kotlin/com/withaeng/external/email/SesFactory.kt diff --git a/withaeng-external/src/main/kotlin/com/withaeng/external/email/SesFactory.kt b/withaeng-external/src/main/kotlin/com/withaeng/external/email/SesFactory.kt new file mode 100644 index 0000000..47bc908 --- /dev/null +++ b/withaeng-external/src/main/kotlin/com/withaeng/external/email/SesFactory.kt @@ -0,0 +1,36 @@ +package com.withaeng.external.email + +import software.amazon.awssdk.services.ses.model.* +import java.nio.charset.StandardCharsets + +object SesFactory { + + fun createRequest(to: String, from: String, subject: String, content: String): SendEmailRequest = + SendEmailRequest.builder() + .destination(destination(to)) + .source(from) + .message(message(utf8Content(subject), body(content))) + .build() + + private fun destination(to: String): Destination = + Destination.builder() + .toAddresses(to) + .build() + + private fun message(content: Content, body: Body): Message = + Message.builder() + .subject(content) + .body(body) + .build() + + private fun body(content: String): Body = + Body.builder() + .html(utf8Content(content)) + .build() + + private fun utf8Content(subject: String): Content = + Content.builder() + .charset(StandardCharsets.UTF_8.name()) + .data(subject) + .build() +} \ No newline at end of file From 436958d20d93fa9a9bc1027e386899e5ed17a3bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Sun, 22 Sep 2024 01:34:19 +0900 Subject: [PATCH 162/174] chore: add ApiResponse for APIs with no response data --- .../api/controller/accompany/AccompanyController.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt index 353b642..85fec46 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt @@ -132,10 +132,11 @@ class AccompanyController( @GetAuth userInfo: UserInfo, @PathVariable accompanyId: Long, @PathVariable joinRequestId: Long, - ) { + ): ApiResponse { accompanyApplicationService.acceptJoin( accompanyId = accompanyId, userId = userInfo.id, joinRequestId = joinRequestId ) + return ApiResponse.success() } @Operation( @@ -148,9 +149,10 @@ class AccompanyController( @GetAuth userInfo: UserInfo, @PathVariable accompanyId: Long, @PathVariable joinRequestId: Long, - ) { + ): ApiResponse { accompanyApplicationService.rejectJoin( accompanyId = accompanyId, userId = userInfo.id, joinRequestId = joinRequestId ) + return ApiResponse.success() } } \ No newline at end of file From 232b709f849c81935b068807f352462c1a977218 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9C=A4=EC=84=A0?= Date: Sun, 22 Sep 2024 01:39:54 +0900 Subject: [PATCH 163/174] chore: add @Parameter to PathVariable --- .../accompany/AccompanyController.kt | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt index 85fec46..c970b43 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt @@ -9,6 +9,7 @@ import com.withaeng.api.controller.accompany.dto.* import com.withaeng.api.security.authentication.UserInfo import com.withaeng.api.security.resolver.GetAuth import io.swagger.v3.oas.annotations.Operation +import io.swagger.v3.oas.annotations.Parameter import io.swagger.v3.oas.annotations.security.SecurityRequirement import io.swagger.v3.oas.annotations.tags.Tag import jakarta.validation.Valid @@ -43,7 +44,7 @@ class AccompanyController( @GetMapping("/{accompanyId}") fun retrieve( @GetAuth userInfo: UserInfo?, - @PathVariable("accompanyId") accompanyId: Long, + @Parameter(description = "동행 id") @PathVariable("accompanyId") accompanyId: Long, ): ApiResponse { return ApiResponse.success( accompanyApplicationService.detail(accompanyId, userInfo?.id) @@ -76,7 +77,7 @@ class AccompanyController( @PutMapping("/{accompanyId}") fun update( @GetAuth userInfo: UserInfo, - @PathVariable accompanyId: Long, + @Parameter(description = "동행 id") @PathVariable accompanyId: Long, @RequestBody @Valid param: UpdateAccompanyRequest, ): ApiResponse { return ApiResponse.success( @@ -97,7 +98,7 @@ class AccompanyController( @PostMapping("/{accompanyId}/join-requests") fun requestJoin( @GetAuth userInfo: UserInfo, - @PathVariable accompanyId: Long, + @Parameter(description = "동행 id") @PathVariable accompanyId: Long, ): ApiResponse { accompanyApplicationService.requestJoin( accompanyId = accompanyId, userId = userInfo.id @@ -113,8 +114,8 @@ class AccompanyController( @PutMapping("/{accompanyId}/join-requests/{joinRequestId}/cancel") fun cancelJoin( @GetAuth userInfo: UserInfo, - @PathVariable accompanyId: Long, - @PathVariable joinRequestId: Long, + @Parameter(description = "동행 id") @PathVariable accompanyId: Long, + @Parameter(description = "동행 참가 요청 id") @PathVariable joinRequestId: Long, ): ApiResponse { accompanyApplicationService.cancelJoin( accompanyId = accompanyId, userId = userInfo.id, joinRequestId = joinRequestId @@ -130,8 +131,8 @@ class AccompanyController( @PutMapping("/{accompanyId}/join-requests/{joinRequestId}/accept") fun acceptJoin( @GetAuth userInfo: UserInfo, - @PathVariable accompanyId: Long, - @PathVariable joinRequestId: Long, + @Parameter(description = "동행 id") @PathVariable accompanyId: Long, + @Parameter(description = "동행 참가 요청 id") @PathVariable joinRequestId: Long, ): ApiResponse { accompanyApplicationService.acceptJoin( accompanyId = accompanyId, userId = userInfo.id, joinRequestId = joinRequestId @@ -147,8 +148,8 @@ class AccompanyController( @PutMapping("/{accompanyId}/join-requests/{joinRequestId}/reject") fun rejectJoin( @GetAuth userInfo: UserInfo, - @PathVariable accompanyId: Long, - @PathVariable joinRequestId: Long, + @Parameter(description = "동행 id") @PathVariable accompanyId: Long, + @Parameter(description = "동행 참가 요청 id") @PathVariable joinRequestId: Long, ): ApiResponse { accompanyApplicationService.rejectJoin( accompanyId = accompanyId, userId = userInfo.id, joinRequestId = joinRequestId From 07f1d06ed7259735e8ae5f6664bbb63d01c541ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Sun, 22 Sep 2024 00:54:49 +0900 Subject: [PATCH 164/174] =?UTF-8?q?feat:=20preSignedUrl=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- withaeng-external/build.gradle.kts | 3 ++ .../withaeng/external/image/PreSignedUrl.kt | 13 ++++++ .../external/image/PreSignedUrlGenerator.kt | 42 +++++++++++++++++++ .../com/withaeng/external/image/S3Config.kt | 28 +++++++++++++ .../main/resources/application-external.yml | 3 ++ 5 files changed, 89 insertions(+) create mode 100644 withaeng-external/src/main/kotlin/com/withaeng/external/image/PreSignedUrl.kt create mode 100644 withaeng-external/src/main/kotlin/com/withaeng/external/image/PreSignedUrlGenerator.kt create mode 100644 withaeng-external/src/main/kotlin/com/withaeng/external/image/S3Config.kt diff --git a/withaeng-external/build.gradle.kts b/withaeng-external/build.gradle.kts index 2355b51..af6758b 100644 --- a/withaeng-external/build.gradle.kts +++ b/withaeng-external/build.gradle.kts @@ -2,4 +2,7 @@ dependencies { // Email implementation("software.amazon.awssdk:ses:2.28.3") implementation("org.springframework.boot:spring-boot-starter-thymeleaf") + + // Image + implementation("software.amazon.awssdk:s3:2.28.3") } \ No newline at end of file diff --git a/withaeng-external/src/main/kotlin/com/withaeng/external/image/PreSignedUrl.kt b/withaeng-external/src/main/kotlin/com/withaeng/external/image/PreSignedUrl.kt new file mode 100644 index 0000000..ca5f3e4 --- /dev/null +++ b/withaeng-external/src/main/kotlin/com/withaeng/external/image/PreSignedUrl.kt @@ -0,0 +1,13 @@ +package com.withaeng.external.image + +class PreSignedUrl( + private val url: String, +) { + fun uploadUrl(): String { + return url + } + + fun imageUrl(): String { + return url.substring(0, url.indexOf("?")) + } +} diff --git a/withaeng-external/src/main/kotlin/com/withaeng/external/image/PreSignedUrlGenerator.kt b/withaeng-external/src/main/kotlin/com/withaeng/external/image/PreSignedUrlGenerator.kt new file mode 100644 index 0000000..dc66b14 --- /dev/null +++ b/withaeng-external/src/main/kotlin/com/withaeng/external/image/PreSignedUrlGenerator.kt @@ -0,0 +1,42 @@ +package com.withaeng.external.image + +import org.springframework.beans.factory.annotation.Value +import org.springframework.stereotype.Component +import software.amazon.awssdk.services.s3.model.PutObjectRequest +import software.amazon.awssdk.services.s3.presigner.S3Presigner +import software.amazon.awssdk.services.s3.presigner.model.PutObjectPresignRequest +import java.time.Duration + + +@Component +class PreSignedUrlGenerator( + private val presigner: S3Presigner, + @Value("\${cloud.aws.s3.bucket}") + private var bucket: String, +) { + + fun generate(objectKey: String): PreSignedUrl = + PreSignedUrl( + presigner.presignPutObject( + preSignRequest( + Duration.ofMinutes(1), objectRequest(objectKey) + ) + ).url().toString() + ) + + private fun preSignRequest( + expiration: Duration, + objectRequest: PutObjectRequest?, + ): PutObjectPresignRequest? = PutObjectPresignRequest.builder() + .signatureDuration(expiration) + .putObjectRequest(objectRequest) + .build() + + private fun objectRequest(objectKey: String): PutObjectRequest? { + val objectRequest = PutObjectRequest.builder() + .bucket(bucket) + .key(objectKey) + .build() + return objectRequest + } +} \ No newline at end of file diff --git a/withaeng-external/src/main/kotlin/com/withaeng/external/image/S3Config.kt b/withaeng-external/src/main/kotlin/com/withaeng/external/image/S3Config.kt new file mode 100644 index 0000000..4b6b3f9 --- /dev/null +++ b/withaeng-external/src/main/kotlin/com/withaeng/external/image/S3Config.kt @@ -0,0 +1,28 @@ +package com.withaeng.external.image + +import org.springframework.beans.factory.annotation.Value +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider +import software.amazon.awssdk.regions.Region +import software.amazon.awssdk.services.s3.presigner.S3Presigner + +@Configuration +class S3Config( + @Value("\${cloud.aws.credentials.access-key}") + private var accessKey: String, + @Value("\${cloud.aws.credentials.secret-key}") + private var secretKey: String, + @Value("\${cloud.aws.s3.region}") + private var region: String, +) { + + @Bean + fun s3Presigner(): S3Presigner { + return S3Presigner.builder() + .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(accessKey, secretKey))) + .region(Region.of(region)) + .build() + } +} \ No newline at end of file diff --git a/withaeng-external/src/main/resources/application-external.yml b/withaeng-external/src/main/resources/application-external.yml index 4174df2..fa6ddb2 100644 --- a/withaeng-external/src/main/resources/application-external.yml +++ b/withaeng-external/src/main/resources/application-external.yml @@ -6,6 +6,9 @@ cloud: ses: region: ${AWS_SES_REGION} from: ${AWS_SES_FROM} + s3: + region: ${AWS_S3_REGION} + bucket: ${AWS_S3_BUCKET} --- spring.config.activate.on-profile: local From aca043e431af3b516ff6a13ba6cee7b811fd066a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Sun, 22 Sep 2024 02:01:09 +0900 Subject: [PATCH 165/174] =?UTF-8?q?feat:=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20?= =?UTF-8?q?=EC=97=85=EB=A1=9C=EB=93=9C=20=ED=95=84=EC=9A=94=20api=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 --- .../accompany/AccompanyApplicationService.kt | 23 +++++++++-- .../accompany/dto/AccompanyResponseDto.kt | 5 +++ .../dto/AccompanyServiceRequestDto.kt | 6 +-- .../auth/AuthApplicationService.kt | 2 +- .../user/UserApplicationService.kt | 40 +++++++++++++++++-- .../user/dto/UserServiceRequest.kt | 8 ++-- .../user/dto/UserServiceResponse.kt | 5 +++ .../accompany/AccompanyController.kt | 3 +- .../accompany/dto/AccompanyRequestDto.kt | 8 ++-- .../api/controller/user/UserMeController.kt | 36 ++++++++++++----- .../api/controller/user/dto/UserRequest.kt | 10 ++--- .../com/withaeng/domain/user/UserService.kt | 28 ++++++++----- .../com/withaeng/external/email/SesConfig.kt | 4 +- .../withaeng/external/email/SesEmailSender.kt | 14 +++++-- .../external/image/AwsS3StorageClient.kt | 22 ++++++++++ .../com/withaeng/external/image/S3Config.kt | 13 ++++-- .../external/image/S3StorageClient.kt | 6 +++ .../main/resources/application-external.yml | 18 ++++----- 18 files changed, 182 insertions(+), 69 deletions(-) create mode 100644 withaeng-external/src/main/kotlin/com/withaeng/external/image/AwsS3StorageClient.kt create mode 100644 withaeng-external/src/main/kotlin/com/withaeng/external/image/S3StorageClient.kt diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt index 62d39d1..a94502a 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/AccompanyApplicationService.kt @@ -9,18 +9,35 @@ import com.withaeng.common.exception.WithaengExceptionType import com.withaeng.domain.accompany.AccompanyService import com.withaeng.domain.accompanyjoinrequests.AccompanyJoinRequestService import com.withaeng.domain.accompanylike.AccompanyLikeService +import com.withaeng.external.image.PreSignedUrl +import com.withaeng.external.image.PreSignedUrlGenerator import org.springframework.stereotype.Service +import java.util.* + +private const val ACCOMPANY_IMAGE_STORAGE_DIR = "accompany" @Service class AccompanyApplicationService( private val accompanyService: AccompanyService, private val accompanyLikeService: AccompanyLikeService, private val accompanyJoinRequestService: AccompanyJoinRequestService, + private val preSignedUrlGenerator: PreSignedUrlGenerator, ) { - fun create(request: CreateAccompanyServiceRequest): AccompanyResponse { - return accompanyService.create(request.toDomainDto()) - .toAccompanyResponse(0L) + fun create(request: CreateAccompanyServiceRequest): CreateAccompanyResponse { + if (request.hasImage) { + val preSignedUrl = generatePreSignedUrl() + val createAccompanyDto = request.toDomainDto(preSignedUrl.imageUrl()) + val accompanyDto = accompanyService.create(createAccompanyDto) + return CreateAccompanyResponse(accompanyDto.id, preSignedUrl.uploadUrl()) + } + val accompanyDto = accompanyService.create(request.toDomainDto()) + return CreateAccompanyResponse(accompanyDto.id) + } + + private fun generatePreSignedUrl(): PreSignedUrl { + val objectKey = "$ACCOMPANY_IMAGE_STORAGE_DIR/${UUID.randomUUID()}" + return preSignedUrlGenerator.generate(objectKey) } fun update(request: UpdateAccompanyServiceRequest): AccompanyResponse { diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyResponseDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyResponseDto.kt index 0e5daaf..7dff625 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyResponseDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyResponseDto.kt @@ -79,4 +79,9 @@ fun SearchAccompanyDto.toAccompanyResponse(): AccompanySummaryResponse = Accompa nickname = host.nickname, profileImageUrl = host.profileImageUrl, ), +) + +data class CreateAccompanyResponse( + val id: Long, + val preSignedUrl: String? = null, ) \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt index 24aadcc..6cd5924 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt @@ -15,16 +15,16 @@ data class CreateAccompanyServiceRequest( val city: String, val startTripDate: LocalDate, val endTripDate: LocalDate, - val bannerImageUrl: String? = null, val memberCount: Long, val tags: Set? = emptySet(), val openKakaoUrl: String, val startAccompanyAge: AccompanyAge, val endAccompanyAge: AccompanyAge, val preferGender: AccompanyPreferGender, + val hasImage: Boolean = false, ) -fun CreateAccompanyServiceRequest.toDomainDto(): CreateAccompanyDto = CreateAccompanyDto( +fun CreateAccompanyServiceRequest.toDomainDto(imageUrl: String? = null): CreateAccompanyDto = CreateAccompanyDto( userId = userId, title = title, content = content, @@ -35,7 +35,7 @@ fun CreateAccompanyServiceRequest.toDomainDto(): CreateAccompanyDto = CreateAcco ), startTripDate = startTripDate, endTripDate = endTripDate, - bannerImageUrl = bannerImageUrl, + bannerImageUrl = imageUrl, memberCount = memberCount, tags = tags?.toSet(), openKakaoUrl = openKakaoUrl, diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/AuthApplicationService.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/AuthApplicationService.kt index 89d57b3..a62977e 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/AuthApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/auth/AuthApplicationService.kt @@ -134,7 +134,7 @@ class AuthApplicationService( userId = userDto.id, code = request.code ) - userService.updatePassword(userDto.id, passwordEncoder.encode(request.password)) + userService.replacePassword(userDto.id, passwordEncoder.encode(request.password)) } private fun verifyEmailCode(email: String, userId: Long, code: String) { diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/UserApplicationService.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/UserApplicationService.kt index ec7881c..6dbaf9d 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/UserApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/UserApplicationService.kt @@ -3,12 +3,20 @@ package com.withaeng.api.applicationservice.user import com.withaeng.api.applicationservice.user.dto.* import com.withaeng.domain.accompany.AccompanyService import com.withaeng.domain.user.UserService +import com.withaeng.external.image.PreSignedUrl +import com.withaeng.external.image.PreSignedUrlGenerator +import com.withaeng.external.image.S3StorageClient import org.springframework.stereotype.Service +import java.util.* + +private const val USER_IMAGE_STORAGE_DIR = "user" @Service class UserApplicationService( private val userService: UserService, private val accompanyService: AccompanyService, + private val preSignedUrlGenerator: PreSignedUrlGenerator, + private val s3StorageClient: S3StorageClient, ) { fun getProfile(userId: Long): UserStatisticalProfileResponse { @@ -27,11 +35,35 @@ class UserApplicationService( ?: UserTravelPreferenceResponse() } - fun updateProfile(serviceRequest: UpdateProfileServiceRequest): UserSimpleResponse { - return userService.updateProfile(serviceRequest.userId, serviceRequest.toCommand()).toSimpleResponse() + fun updateProfile(userId: Long, serviceRequest: UpdateProfileServiceRequest): UpdateProfileResponse { + if (serviceRequest.hasImage) { + val preSignedUrl = generatePreSignedUrl() + val userSimpleDto = userService.updateProfile(userId, serviceRequest.toCommand(preSignedUrl.imageUrl())) + return UpdateProfileResponse(userSimpleDto.id, preSignedUrl.uploadUrl()) + } + val userSimpleDto = userService.updateProfile(userId, serviceRequest.toCommand()) + return UpdateProfileResponse(userSimpleDto.id) + } + + private fun generatePreSignedUrl(): PreSignedUrl { + val objectKey = "$USER_IMAGE_STORAGE_DIR/${UUID.randomUUID()}" + return preSignedUrlGenerator.generate(objectKey) + } + + fun updateTravelPreference(userId: Long, serviceRequest: UpdateTravelPreferenceServiceRequest): UserDetailResponse { + return userService.replaceTravelPreference(userId, serviceRequest.toCommand()).toDetailResponse() + } + + fun deleteProfileImage(id: Long) { + val userSimpleDto = userService.findSimpleById(id) + userSimpleDto.profile.profileImageUrl?.let { + userService.deleteProfileImage(id) + deleteS3Image(it) + } } - fun updateTravelPreference(serviceRequest: UpdateTravelPreferenceServiceRequest): UserDetailResponse { - return userService.updateTravelPreference(serviceRequest.userId, serviceRequest.toCommand()).toDetailResponse() + private fun deleteS3Image(it: String) { + val objectKey = "$USER_IMAGE_STORAGE_DIR/${it.split("/").last()}" + s3StorageClient.delete(objectKey) } } diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceRequest.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceRequest.kt index cd7afce..911b610 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceRequest.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceRequest.kt @@ -5,21 +5,19 @@ import com.withaeng.domain.user.dto.UpdateProfileCommand import com.withaeng.domain.user.dto.UpdateTravelPreferenceCommand data class UpdateProfileServiceRequest( - val userId: Long, val nickname: String?, val introduction: String?, - val profileImageUrl: String?, + val hasImage: Boolean = false, ) -fun UpdateProfileServiceRequest.toCommand(): UpdateProfileCommand = +fun UpdateProfileServiceRequest.toCommand(imageUrl: String? = null): UpdateProfileCommand = UpdateProfileCommand( nickname = nickname, introduction = introduction, - profileImageUrl = profileImageUrl + profileImageUrl = imageUrl ) data class UpdateTravelPreferenceServiceRequest( - val userId: Long, val mbti: Set? = emptySet(), val preferTravelType: UserPreferTravelType? = null, val preferTravelThemes: Set? = emptySet(), diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceResponse.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceResponse.kt index 4a8084f..0c8bddb 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceResponse.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceResponse.kt @@ -112,3 +112,8 @@ data class UserStatisticalProfileResponse( ) } } + +data class UpdateProfileResponse( + val id: Long, + val preSignedUrl: String? = null, +) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt index c970b43..d91f84b 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/AccompanyController.kt @@ -3,6 +3,7 @@ package com.withaeng.api.controller.accompany import com.withaeng.api.applicationservice.accompany.AccompanyApplicationService import com.withaeng.api.applicationservice.accompany.dto.AccompanyResponse import com.withaeng.api.applicationservice.accompany.dto.AccompanySummaryResponse +import com.withaeng.api.applicationservice.accompany.dto.CreateAccompanyResponse import com.withaeng.api.applicationservice.accompany.dto.FindAccompanyResponse import com.withaeng.api.common.ApiResponse import com.withaeng.api.controller.accompany.dto.* @@ -34,7 +35,7 @@ class AccompanyController( fun create( @GetAuth userInfo: UserInfo, @RequestBody @Valid request: CreateAccompanyRequest, - ): ApiResponse { + ): ApiResponse { return ApiResponse.success( accompanyApplicationService.create(request.toServiceRequest(userInfo.id)) ) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt index 1338900..a53dd3e 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt @@ -33,9 +33,6 @@ data class CreateAccompanyRequest( @Schema(description = "동행 종료 날짜 (1999-01-01)") val endTripDate: LocalDate, - @Schema(description = "동행 게시글 배너 이미지 URL") - val bannerImageUrl: String? = null, - @Schema(description = "동행 멤버수") @field:Min(2, message = "멤버 수는 최소 2명 이상(본인 + 동행자 1명 이상)이어야 합니다.") val memberCount: Long, @@ -56,6 +53,9 @@ data class CreateAccompanyRequest( @Schema(description = "동행 선호 성별") val preferGender: AccompanyPreferGender, + + @Schema(description = "이미지 업로드 여부") + val hasImage: Boolean = false, ) @Schema(description = "[Request] 동행 게시글 수정") @@ -70,13 +70,13 @@ fun CreateAccompanyRequest.toServiceRequest( city = city, startTripDate = startTripDate, endTripDate = endTripDate, - bannerImageUrl = bannerImageUrl, memberCount = memberCount, tags = tags, openKakaoUrl = openKakaoUrl, startAccompanyAge = startAccompanyAge, endAccompanyAge = endAccompanyAge, preferGender = preferGender, + hasImage = hasImage, ) data class UpdateAccompanyRequest( diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/UserMeController.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/UserMeController.kt index fba349a..77302c8 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/UserMeController.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/UserMeController.kt @@ -1,8 +1,8 @@ package com.withaeng.api.controller.user import com.withaeng.api.applicationservice.user.UserApplicationService +import com.withaeng.api.applicationservice.user.dto.UpdateProfileResponse import com.withaeng.api.applicationservice.user.dto.UserDetailResponse -import com.withaeng.api.applicationservice.user.dto.UserSimpleResponse import com.withaeng.api.applicationservice.user.dto.UserStatisticalProfileResponse import com.withaeng.api.applicationservice.user.dto.UserTravelPreferenceResponse import com.withaeng.api.common.ApiResponse @@ -50,33 +50,47 @@ class UserMeController(private val userApplicationService: UserApplicationServic ) } + @Operation( + summary = "Update Travel Preference", + description = "여행 선호 정보 업데이트 API", + security = [SecurityRequirement(name = "Authorization")] + ) + @PutMapping("/travel-preference") + fun updateTravelPreference( + @GetAuth userInfo: UserInfo, + @RequestBody @Valid request: UpdateTravelPreferenceRequest, + ): ApiResponse { + return ApiResponse.success( + userApplicationService.updateTravelPreference(userInfo.id, request.toServiceRequest()) + ) + } + @Operation( summary = "Update Profile", description = "프로필 업데이트 API", security = [SecurityRequirement(name = "Authorization")] ) - @PutMapping("/profile") + @PatchMapping("/profile") fun updateProfile( @GetAuth userInfo: UserInfo, @RequestBody @Valid request: UpdateProfileRequest, - ): ApiResponse { + ): ApiResponse { return ApiResponse.success( - userApplicationService.updateProfile(request.toServiceRequest(userInfo.id)) + userApplicationService.updateProfile(userInfo.id, request.toServiceRequest()) ) } @Operation( - summary = "Update Travel Preference", - description = "여행 선호 정보 업데이트 API", + summary = "Delete Profile Image", + description = "프로필 이미지 삭제 API", security = [SecurityRequirement(name = "Authorization")] ) - @PutMapping("/travel-preference") - fun updateTravelPreference( + @DeleteMapping("/profile-image") + fun deleteProfileImage( @GetAuth userInfo: UserInfo, - @RequestBody @Valid request: UpdateTravelPreferenceRequest, - ): ApiResponse { + ): ApiResponse { return ApiResponse.success( - userApplicationService.updateTravelPreference(request.toServiceRequest(userInfo.id)) + userApplicationService.deleteProfileImage(userInfo.id) ) } } diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/dto/UserRequest.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/dto/UserRequest.kt index 7fe7cde..96fd009 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/dto/UserRequest.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/dto/UserRequest.kt @@ -14,15 +14,14 @@ data class UpdateProfileRequest( val introduction: String? = null, @Schema(description = "프로필 이미지 URL") - val profileImageUrl: String? = null, + val hasImage: Boolean = false, ) -fun UpdateProfileRequest.toServiceRequest(userId: Long): UpdateProfileServiceRequest = +fun UpdateProfileRequest.toServiceRequest(): UpdateProfileServiceRequest = UpdateProfileServiceRequest( - userId = userId, nickname = nickname, introduction = introduction, - profileImageUrl = profileImageUrl + hasImage = hasImage, ) @Schema(description = "[Request] User 여행 선호 스타일 정보를 추가합니다") @@ -49,9 +48,8 @@ data class UpdateTravelPreferenceRequest( val drinkingType: UserDrinkingType? = null, ) -fun UpdateTravelPreferenceRequest.toServiceRequest(userId: Long): UpdateTravelPreferenceServiceRequest = +fun UpdateTravelPreferenceRequest.toServiceRequest(): UpdateTravelPreferenceServiceRequest = UpdateTravelPreferenceServiceRequest( - userId = userId, mbti = mbti, preferTravelType = preferTravelType, preferTravelThemes = preferTravelThemes, diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserService.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserService.kt index 387a536..1fe9068 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserService.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserService.kt @@ -69,16 +69,7 @@ class UserService(private val userRepository: UserRepository) { } @Transactional - fun updateProfile(userId: Long, command: UpdateProfileCommand): UserSimpleDto { - val user = userRepository.findByIdOrNull(userId).getOrThrow() - user.profile.nickname = command.nickname ?: user.profile.nickname - user.profile.introduction = command.introduction - user.profile.profileImageUrl = command.profileImageUrl - return user.toSimpleDto() - } - - @Transactional - fun updateTravelPreference(userId: Long, command: UpdateTravelPreferenceCommand): UserDetailDto { + fun replaceTravelPreference(userId: Long, command: UpdateTravelPreferenceCommand): UserDetailDto { val user = userRepository.findByIdOrNull(userId).getOrThrow() user.travelPreference = user.travelPreference ?: UserTravelPreference.create(user) user.travelPreference?.mbti = command.mbti ?: emptySet() @@ -92,12 +83,21 @@ class UserService(private val userRepository: UserRepository) { } @Transactional - fun updatePassword(userId: Long, password: String): UserSimpleDto { + fun replacePassword(userId: Long, password: String): UserSimpleDto { val user = userRepository.findByIdOrNull(userId).getOrThrow() user.password = password return user.toSimpleDto() } + @Transactional + fun updateProfile(userId: Long, command: UpdateProfileCommand): UserSimpleDto { + val user = userRepository.findByIdOrNull(userId).getOrThrow() + user.profile.nickname = command.nickname ?: user.profile.nickname + user.profile.introduction = command.introduction ?: user.profile.introduction + user.profile.profileImageUrl = command.profileImageUrl ?: user.profile.profileImageUrl + return user.toSimpleDto() + } + @Transactional fun grantUserRole(id: Long) { val user = userRepository.findByIdOrNull(id) @@ -111,6 +111,12 @@ class UserService(private val userRepository: UserRepository) { return userRepository.deleteByEmail(email) } + @Transactional + fun deleteProfileImage(id: Long) { + val user = userRepository.findByIdOrNull(id).getOrThrow() + user.profile.profileImageUrl = null + } + private fun User?.getOrThrow(): User { this ?: throw WithaengException.of( type = WithaengExceptionType.NOT_EXIST, diff --git a/withaeng-external/src/main/kotlin/com/withaeng/external/email/SesConfig.kt b/withaeng-external/src/main/kotlin/com/withaeng/external/email/SesConfig.kt index 24f42d0..4b6e45d 100644 --- a/withaeng-external/src/main/kotlin/com/withaeng/external/email/SesConfig.kt +++ b/withaeng-external/src/main/kotlin/com/withaeng/external/email/SesConfig.kt @@ -14,15 +14,13 @@ class SesConfig( private var accessKey: String, @Value("\${cloud.aws.credentials.secret-key}") private var secretKey: String, - @Value("\${cloud.aws.ses.region}") - private var region: String, ) { @Bean fun sesClient(): SesClient { return SesClient.builder() .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(accessKey, secretKey))) - .region(Region.of(region)) + .region(Region.AP_NORTHEAST_2) .build() } } \ No newline at end of file diff --git a/withaeng-external/src/main/kotlin/com/withaeng/external/email/SesEmailSender.kt b/withaeng-external/src/main/kotlin/com/withaeng/external/email/SesEmailSender.kt index ff81833..2540aca 100644 --- a/withaeng-external/src/main/kotlin/com/withaeng/external/email/SesEmailSender.kt +++ b/withaeng-external/src/main/kotlin/com/withaeng/external/email/SesEmailSender.kt @@ -1,18 +1,24 @@ package com.withaeng.external.email -import org.springframework.beans.factory.annotation.Value import org.springframework.stereotype.Component import software.amazon.awssdk.services.ses.SesClient @Component class SesEmailSender( private val sesClient: SesClient, - @Value("\${cloud.aws.ses.from}") - private var from: String, ) : EmailSender { + companion object { + private const val FROM = "withaeng@gmail.com" + } + override fun send(to: String, subject: String, content: String) { - val request = SesFactory.createRequest(to, subject, from, content) + val request = SesFactory.createRequest( + to = to, + from = FROM, + subject = subject, + content = content + ) sesClient.sendEmail(request) } } diff --git a/withaeng-external/src/main/kotlin/com/withaeng/external/image/AwsS3StorageClient.kt b/withaeng-external/src/main/kotlin/com/withaeng/external/image/AwsS3StorageClient.kt new file mode 100644 index 0000000..ac3ffb9 --- /dev/null +++ b/withaeng-external/src/main/kotlin/com/withaeng/external/image/AwsS3StorageClient.kt @@ -0,0 +1,22 @@ +package com.withaeng.external.image + +import org.springframework.beans.factory.annotation.Value +import org.springframework.scheduling.annotation.Async +import org.springframework.stereotype.Component +import software.amazon.awssdk.services.s3.S3Client + +@Component +class AwsS3StorageClient( + private val s3Client: S3Client, + @Value("\${cloud.aws.s3.bucket}") + private var bucket: String, +) : S3StorageClient { + + @Async + override fun delete(objectKey: String) { + s3Client.deleteObject { + it.bucket(bucket) + it.key(objectKey) + } + } +} \ No newline at end of file diff --git a/withaeng-external/src/main/kotlin/com/withaeng/external/image/S3Config.kt b/withaeng-external/src/main/kotlin/com/withaeng/external/image/S3Config.kt index 4b6b3f9..77fc898 100644 --- a/withaeng-external/src/main/kotlin/com/withaeng/external/image/S3Config.kt +++ b/withaeng-external/src/main/kotlin/com/withaeng/external/image/S3Config.kt @@ -6,6 +6,7 @@ import org.springframework.context.annotation.Configuration import software.amazon.awssdk.auth.credentials.AwsBasicCredentials import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider import software.amazon.awssdk.regions.Region +import software.amazon.awssdk.services.s3.S3Client import software.amazon.awssdk.services.s3.presigner.S3Presigner @Configuration @@ -14,15 +15,21 @@ class S3Config( private var accessKey: String, @Value("\${cloud.aws.credentials.secret-key}") private var secretKey: String, - @Value("\${cloud.aws.s3.region}") - private var region: String, ) { + @Bean + fun s3Client(): S3Client { + return S3Client.builder() + .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(accessKey, secretKey))) + .region(Region.AP_NORTHEAST_2) + .build() + } + @Bean fun s3Presigner(): S3Presigner { return S3Presigner.builder() .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(accessKey, secretKey))) - .region(Region.of(region)) + .region(Region.AP_NORTHEAST_2) .build() } } \ No newline at end of file diff --git a/withaeng-external/src/main/kotlin/com/withaeng/external/image/S3StorageClient.kt b/withaeng-external/src/main/kotlin/com/withaeng/external/image/S3StorageClient.kt new file mode 100644 index 0000000..dbe3a03 --- /dev/null +++ b/withaeng-external/src/main/kotlin/com/withaeng/external/image/S3StorageClient.kt @@ -0,0 +1,6 @@ +package com.withaeng.external.image + +interface S3StorageClient { + + fun delete(objectKey: String) +} \ No newline at end of file diff --git a/withaeng-external/src/main/resources/application-external.yml b/withaeng-external/src/main/resources/application-external.yml index fa6ddb2..629deca 100644 --- a/withaeng-external/src/main/resources/application-external.yml +++ b/withaeng-external/src/main/resources/application-external.yml @@ -3,22 +3,20 @@ cloud: credentials: access-key: ${AWS_ACCESS_KEY} secret-key: ${AWS_SECRET_KEY} - ses: - region: ${AWS_SES_REGION} - from: ${AWS_SES_FROM} - s3: - region: ${AWS_S3_REGION} - bucket: ${AWS_S3_BUCKET} --- spring.config.activate.on-profile: local -spring: - thymeleaf: - cache: false +spring.thymeleaf.cache: false + +cloud.aws.s3.bucket: withaeng-images-dev --- spring.config.activate.on-profile: dev +cloud.aws.s3.bucket: withaeng-images-dev + --- -spring.config.activate.on-profile: prod \ No newline at end of file +spring.config.activate.on-profile: prod + +cloud.aws.s3.bucket: withaeng-images \ No newline at end of file From aeb7bbb663fec290718d1a38d4614f31199045ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Mon, 23 Sep 2024 20:06:40 +0900 Subject: [PATCH 166/174] =?UTF-8?q?refactor:=20=ED=94=84=EB=A1=9C=ED=95=84?= =?UTF-8?q?=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20api=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/UserApplicationService.kt | 36 +++++++---- .../user/dto/UserServiceRequest.kt | 14 ----- .../user/dto/UserServiceResponse.kt | 44 +------------ .../com/withaeng/api/common/IdResponse.kt | 5 ++ .../api/controller/user/UserMeController.kt | 62 ++++++++++++++----- .../api/controller/user/dto/UserRequest.kt | 20 ++---- .../com/withaeng/domain/user/UserService.kt | 38 ++++++++---- 7 files changed, 107 insertions(+), 112 deletions(-) create mode 100644 withaeng-api/src/main/kotlin/com/withaeng/api/common/IdResponse.kt diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/UserApplicationService.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/UserApplicationService.kt index 6dbaf9d..cfac3b9 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/UserApplicationService.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/UserApplicationService.kt @@ -1,8 +1,10 @@ package com.withaeng.api.applicationservice.user import com.withaeng.api.applicationservice.user.dto.* +import com.withaeng.api.common.IdResponse import com.withaeng.domain.accompany.AccompanyService import com.withaeng.domain.user.UserService +import com.withaeng.domain.user.dto.UserSimpleDto import com.withaeng.external.image.PreSignedUrl import com.withaeng.external.image.PreSignedUrlGenerator import com.withaeng.external.image.S3StorageClient @@ -35,14 +37,25 @@ class UserApplicationService( ?: UserTravelPreferenceResponse() } - fun updateProfile(userId: Long, serviceRequest: UpdateProfileServiceRequest): UpdateProfileResponse { - if (serviceRequest.hasImage) { - val preSignedUrl = generatePreSignedUrl() - val userSimpleDto = userService.updateProfile(userId, serviceRequest.toCommand(preSignedUrl.imageUrl())) - return UpdateProfileResponse(userSimpleDto.id, preSignedUrl.uploadUrl()) - } - val userSimpleDto = userService.updateProfile(userId, serviceRequest.toCommand()) - return UpdateProfileResponse(userSimpleDto.id) + fun updateTravelPreference(userId: Long, serviceRequest: UpdateTravelPreferenceServiceRequest): IdResponse { + return userService.replaceTravelPreference(userId, serviceRequest.toCommand()).toIdResponse() + } + + fun updateNickname(id: Long, nickname: String?): IdResponse { + return userService.updateNickname(id, nickname).toIdResponse() + } + + fun putIntroduction(id: Long, introduction: String?): IdResponse { + return userService.putIntroduction(id, introduction).toIdResponse() + } + + fun putProfileImage(id: Long): PutProfileImageResponse { + val preSignedUrl = generatePreSignedUrl() + val userSimpleDto = userService.putProfileImage(id, preSignedUrl.imageUrl()) + return PutProfileImageResponse( + id = userSimpleDto.id, + preSignedUrl = preSignedUrl.uploadUrl(), + ) } private fun generatePreSignedUrl(): PreSignedUrl { @@ -50,10 +63,6 @@ class UserApplicationService( return preSignedUrlGenerator.generate(objectKey) } - fun updateTravelPreference(userId: Long, serviceRequest: UpdateTravelPreferenceServiceRequest): UserDetailResponse { - return userService.replaceTravelPreference(userId, serviceRequest.toCommand()).toDetailResponse() - } - fun deleteProfileImage(id: Long) { val userSimpleDto = userService.findSimpleById(id) userSimpleDto.profile.profileImageUrl?.let { @@ -66,4 +75,7 @@ class UserApplicationService( val objectKey = "$USER_IMAGE_STORAGE_DIR/${it.split("/").last()}" s3StorageClient.delete(objectKey) } + + fun UserSimpleDto.toIdResponse(): IdResponse = IdResponse(id) + } diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceRequest.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceRequest.kt index 911b610..b1f226f 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceRequest.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceRequest.kt @@ -1,22 +1,8 @@ package com.withaeng.api.applicationservice.user.dto import com.withaeng.domain.user.* -import com.withaeng.domain.user.dto.UpdateProfileCommand import com.withaeng.domain.user.dto.UpdateTravelPreferenceCommand -data class UpdateProfileServiceRequest( - val nickname: String?, - val introduction: String?, - val hasImage: Boolean = false, -) - -fun UpdateProfileServiceRequest.toCommand(imageUrl: String? = null): UpdateProfileCommand = - UpdateProfileCommand( - nickname = nickname, - introduction = introduction, - profileImageUrl = imageUrl - ) - data class UpdateTravelPreferenceServiceRequest( val mbti: Set? = emptySet(), val preferTravelType: UserPreferTravelType? = null, diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceResponse.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceResponse.kt index 0c8bddb..63be36f 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceResponse.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/user/dto/UserServiceResponse.kt @@ -18,23 +18,6 @@ fun UserSimpleDto.toSimpleResponse(): UserSimpleResponse = UserSimpleResponse( nickname = profile.nickname ) -data class UserDetailResponse( - val id: Long, - val createdDate: LocalDate, - val email: String, - val gender: Gender, - val birth: LocalDate, - val mannerScore: Double, - val profile: UserProfileResponse, - val travelPreference: UserTravelPreferenceResponse? = null, -) - -data class UserProfileResponse( - val nickname: String, - val introduction: String? = null, - val profileImageUrl: String? = null, -) - data class UserTravelPreferenceResponse( val mbti: Set? = emptySet(), val preferTravelType: UserPreferTravelType? = null, @@ -45,31 +28,6 @@ data class UserTravelPreferenceResponse( val drinkingType: UserDrinkingType? = null, ) -fun UserDetailDto.toDetailResponse(): UserDetailResponse = UserDetailResponse( - id = id, - createdDate = createdDate, - email = email, - gender = gender, - birth = birth, - mannerScore = mannerScore, - profile = UserProfileResponse( - nickname = profile.nickname, - introduction = profile.introduction, - profileImageUrl = profile.profileImageUrl, - ), - travelPreference = travelPreference?.let { - UserTravelPreferenceResponse( - mbti = it.mbti, - preferTravelType = it.preferTravelType, - preferTravelThemes = it.preferTravelThemes, - consumeStyle = it.consumeStyle, - foodRestrictions = it.foodRestrictions, - smokingType = it.smokingType, - drinkingType = it.drinkingType - ) - }, -) - fun UserTravelPreferenceDto.toServiceResponse(): UserTravelPreferenceResponse = UserTravelPreferenceResponse( mbti = mbti, @@ -113,7 +71,7 @@ data class UserStatisticalProfileResponse( } } -data class UpdateProfileResponse( +data class PutProfileImageResponse( val id: Long, val preSignedUrl: String? = null, ) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/common/IdResponse.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/common/IdResponse.kt new file mode 100644 index 0000000..e82250a --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/common/IdResponse.kt @@ -0,0 +1,5 @@ +package com.withaeng.api.common + +data class IdResponse( + val id: Long, +) \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/UserMeController.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/UserMeController.kt index 77302c8..9686844 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/UserMeController.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/UserMeController.kt @@ -1,13 +1,14 @@ package com.withaeng.api.controller.user import com.withaeng.api.applicationservice.user.UserApplicationService -import com.withaeng.api.applicationservice.user.dto.UpdateProfileResponse -import com.withaeng.api.applicationservice.user.dto.UserDetailResponse +import com.withaeng.api.applicationservice.user.dto.PutProfileImageResponse import com.withaeng.api.applicationservice.user.dto.UserStatisticalProfileResponse import com.withaeng.api.applicationservice.user.dto.UserTravelPreferenceResponse import com.withaeng.api.common.ApiResponse -import com.withaeng.api.controller.user.dto.UpdateProfileRequest -import com.withaeng.api.controller.user.dto.UpdateTravelPreferenceRequest +import com.withaeng.api.common.IdResponse +import com.withaeng.api.controller.user.dto.PatchNicknameRequest +import com.withaeng.api.controller.user.dto.PutIntroductionRequest +import com.withaeng.api.controller.user.dto.PutTravelPreferenceRequest import com.withaeng.api.controller.user.dto.toServiceRequest import com.withaeng.api.security.authentication.UserInfo import com.withaeng.api.security.resolver.GetAuth @@ -51,38 +52,67 @@ class UserMeController(private val userApplicationService: UserApplicationServic } @Operation( - summary = "Update Travel Preference", + summary = "Replace Travel Preference", description = "여행 선호 정보 업데이트 API", security = [SecurityRequirement(name = "Authorization")] ) @PutMapping("/travel-preference") - fun updateTravelPreference( + fun putTravelPreference( @GetAuth userInfo: UserInfo, - @RequestBody @Valid request: UpdateTravelPreferenceRequest, - ): ApiResponse { + @RequestBody @Valid request: PutTravelPreferenceRequest, + ): ApiResponse { return ApiResponse.success( userApplicationService.updateTravelPreference(userInfo.id, request.toServiceRequest()) ) } @Operation( - summary = "Update Profile", - description = "프로필 업데이트 API", + summary = "Replace Introduction", + description = "이전 소개글은 삭제됩니다.", security = [SecurityRequirement(name = "Authorization")] ) - @PatchMapping("/profile") - fun updateProfile( + @PutMapping("/introduction") + fun putIntroduction( @GetAuth userInfo: UserInfo, - @RequestBody @Valid request: UpdateProfileRequest, - ): ApiResponse { + @RequestBody @Valid request: PutIntroductionRequest, + ): ApiResponse { return ApiResponse.success( - userApplicationService.updateProfile(userInfo.id, request.toServiceRequest()) + userApplicationService.putIntroduction(userInfo.id, request.introduction) + ) + } + + @Operation( + summary = "Replace Profile Image", + description = "이전 프로필 이미지는 삭제됩니다.", + security = [SecurityRequirement(name = "Authorization")] + ) + @PutMapping("/profile-image") + fun putProfileImage( + @GetAuth userInfo: UserInfo, + ): ApiResponse { + return ApiResponse.success( + userApplicationService.putProfileImage(userInfo.id) + ) + } + + @Operation( + summary = "Update Nickname", + description = "nickname 값이 null 이면 기존 닉네임이 유지됩니다.", + security = [SecurityRequirement(name = "Authorization")] + ) + @PatchMapping("/nickname") + fun patchNickname( + @GetAuth userInfo: UserInfo, + @RequestBody @Valid request: PatchNicknameRequest, + ): ApiResponse { + return ApiResponse.success( + userApplicationService.updateNickname(userInfo.id, request.nickname) ) } @Operation( summary = "Delete Profile Image", - description = "프로필 이미지 삭제 API", + description = "", security = [SecurityRequirement(name = "Authorization")] ) @DeleteMapping("/profile-image") diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/dto/UserRequest.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/dto/UserRequest.kt index 96fd009..7c11438 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/dto/UserRequest.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/user/dto/UserRequest.kt @@ -1,31 +1,23 @@ package com.withaeng.api.controller.user.dto -import com.withaeng.api.applicationservice.user.dto.UpdateProfileServiceRequest import com.withaeng.api.applicationservice.user.dto.UpdateTravelPreferenceServiceRequest import com.withaeng.domain.user.* import io.swagger.v3.oas.annotations.media.Schema @Schema(description = "[Request] User 프로필 정보를 추가합니다") -data class UpdateProfileRequest( +data class PatchNicknameRequest( @Schema(description = "유저 닉네임") val nickname: String? = null, +) +@Schema(description = "[Request] User 소개 정보를 추가합니다") +data class PutIntroductionRequest( @Schema(description = "유저 소개") val introduction: String? = null, - - @Schema(description = "프로필 이미지 URL") - val hasImage: Boolean = false, ) -fun UpdateProfileRequest.toServiceRequest(): UpdateProfileServiceRequest = - UpdateProfileServiceRequest( - nickname = nickname, - introduction = introduction, - hasImage = hasImage, - ) - @Schema(description = "[Request] User 여행 선호 스타일 정보를 추가합니다") -data class UpdateTravelPreferenceRequest( +data class PutTravelPreferenceRequest( @Schema(description = "유저 MBTI") val mbti: Set? = emptySet(), @@ -48,7 +40,7 @@ data class UpdateTravelPreferenceRequest( val drinkingType: UserDrinkingType? = null, ) -fun UpdateTravelPreferenceRequest.toServiceRequest(): UpdateTravelPreferenceServiceRequest = +fun PutTravelPreferenceRequest.toServiceRequest(): UpdateTravelPreferenceServiceRequest = UpdateTravelPreferenceServiceRequest( mbti = mbti, preferTravelType = preferTravelType, diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserService.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserService.kt index 1fe9068..313f553 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserService.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/user/UserService.kt @@ -69,7 +69,7 @@ class UserService(private val userRepository: UserRepository) { } @Transactional - fun replaceTravelPreference(userId: Long, command: UpdateTravelPreferenceCommand): UserDetailDto { + fun replaceTravelPreference(userId: Long, command: UpdateTravelPreferenceCommand): UserSimpleDto { val user = userRepository.findByIdOrNull(userId).getOrThrow() user.travelPreference = user.travelPreference ?: UserTravelPreference.create(user) user.travelPreference?.mbti = command.mbti ?: emptySet() @@ -79,7 +79,7 @@ class UserService(private val userRepository: UserRepository) { user.travelPreference?.foodRestrictions = command.foodRestrictions ?: emptySet() user.travelPreference?.smokingType = command.smokingType user.travelPreference?.drinkingType = command.drinkingType - return user.toDetailDto() + return user.toSimpleDto() } @Transactional @@ -89,15 +89,6 @@ class UserService(private val userRepository: UserRepository) { return user.toSimpleDto() } - @Transactional - fun updateProfile(userId: Long, command: UpdateProfileCommand): UserSimpleDto { - val user = userRepository.findByIdOrNull(userId).getOrThrow() - user.profile.nickname = command.nickname ?: user.profile.nickname - user.profile.introduction = command.introduction ?: user.profile.introduction - user.profile.profileImageUrl = command.profileImageUrl ?: user.profile.profileImageUrl - return user.toSimpleDto() - } - @Transactional fun grantUserRole(id: Long) { val user = userRepository.findByIdOrNull(id) @@ -107,8 +98,24 @@ class UserService(private val userRepository: UserRepository) { } @Transactional - fun deleteByEmail(email: String) { - return userRepository.deleteByEmail(email) + fun updateNickname(id: Long, nickname: String?): UserSimpleDto { + val user = userRepository.findByIdOrNull(id).getOrThrow() + user.profile.nickname = nickname ?: user.profile.nickname + return user.toSimpleDto() + } + + @Transactional + fun putIntroduction(id: Long, introduction: String?): UserSimpleDto { + val user = userRepository.findByIdOrNull(id).getOrThrow() + user.profile.introduction = introduction + return user.toSimpleDto() + } + + @Transactional + fun putProfileImage(id: Long, imageUrl: String): UserSimpleDto { + val user = userRepository.findByIdOrNull(id).getOrThrow() + user.profile.profileImageUrl = imageUrl + return user.toSimpleDto() } @Transactional @@ -117,6 +124,11 @@ class UserService(private val userRepository: UserRepository) { user.profile.profileImageUrl = null } + @Transactional + fun deleteByEmail(email: String) { + return userRepository.deleteByEmail(email) + } + private fun User?.getOrThrow(): User { this ?: throw WithaengException.of( type = WithaengExceptionType.NOT_EXIST, From 7e302de9893ac7a574acfc212946a7c932a7cda2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Mon, 23 Sep 2024 20:46:32 +0900 Subject: [PATCH 167/174] =?UTF-8?q?feat:=20=EB=AA=A8=EB=93=A0=20=EB=8C=80?= =?UTF-8?q?=EB=A5=99,=20=EB=82=98=EB=9D=BC,=20=EB=8F=84=EC=8B=9C=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../accompany/dto/AccompanyResponseDto.kt | 8 +++++ .../dto/AccompanyServiceRequestDto.kt | 3 ++ .../DestinationApplicationService.kt | 29 +++++++++++++++++++ .../com/withaeng/api/config/SecurityConfig.kt | 2 +- .../accompany/dto/AccompanyRequestDto.kt | 3 ++ .../destination/DestinationController.kt | 22 ++++++++++++++ .../domain/accompany/AccompanyDestination.kt | 5 +++- .../accompany/AccompanyRepositoryImpl.kt | 5 +++- .../domain/accompany/dto/AccompanyQuery.kt | 8 ++++- .../domain/{accompany => destination}/City.kt | 4 +-- .../{accompany => destination}/Continent.kt | 4 +-- .../{accompany => destination}/Country.kt | 4 +-- 12 files changed, 87 insertions(+), 10 deletions(-) create mode 100644 withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/destination/DestinationApplicationService.kt create mode 100644 withaeng-api/src/main/kotlin/com/withaeng/api/controller/destination/DestinationController.kt rename withaeng-domain/src/main/kotlin/com/withaeng/domain/{accompany => destination}/City.kt (99%) rename withaeng-domain/src/main/kotlin/com/withaeng/domain/{accompany => destination}/Continent.kt (85%) rename withaeng-domain/src/main/kotlin/com/withaeng/domain/{accompany => destination}/Country.kt (99%) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyResponseDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyResponseDto.kt index 7dff625..b59aa9b 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyResponseDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyResponseDto.kt @@ -5,7 +5,11 @@ import com.withaeng.domain.accompany.AccompanyPreferGender import com.withaeng.domain.accompany.AccompanyStatus import com.withaeng.domain.accompany.dto.AccompanyDto import com.withaeng.domain.accompany.dto.SearchAccompanyDto +import com.withaeng.domain.destination.City +import com.withaeng.domain.destination.Continent +import com.withaeng.domain.destination.Country import java.time.LocalDate +import java.util.* data class AccompanyResponse( val id: Long, @@ -84,4 +88,8 @@ fun SearchAccompanyDto.toAccompanyResponse(): AccompanySummaryResponse = Accompa data class CreateAccompanyResponse( val id: Long, val preSignedUrl: String? = null, +) + +data class DestinationResponse( + val continents: EnumMap>>, ) \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt index 6cd5924..df9dbd9 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyServiceRequestDto.kt @@ -4,6 +4,9 @@ import com.withaeng.domain.accompany.* import com.withaeng.domain.accompany.dto.CreateAccompanyDto import com.withaeng.domain.accompany.dto.SearchAccompanyQuery import com.withaeng.domain.accompany.dto.UpdateAccompanyDto +import com.withaeng.domain.destination.City +import com.withaeng.domain.destination.Continent +import com.withaeng.domain.destination.Country import java.time.LocalDate data class CreateAccompanyServiceRequest( diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/destination/DestinationApplicationService.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/destination/DestinationApplicationService.kt new file mode 100644 index 0000000..2421079 --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/destination/DestinationApplicationService.kt @@ -0,0 +1,29 @@ +package com.withaeng.api.applicationservice.destination + +import com.withaeng.api.applicationservice.accompany.dto.DestinationResponse +import com.withaeng.domain.destination.City +import com.withaeng.domain.destination.Continent +import com.withaeng.domain.destination.Country +import org.springframework.stereotype.Service +import java.util.* + +@Service +class DestinationApplicationService { + + fun getDestinations(): DestinationResponse { + val structure = EnumMap>>(Continent::class.java) + Continent.entries.forEach { continent -> + val countriesInContinent = EnumMap>(Country::class.java) + Country.entries + .filter { it.continentCode == continent.continentCode } + .forEach { country -> + val citiesInCountry = City.entries + .filter { it.countryCode == country.countryCode } + .toList() + countriesInContinent[country] = citiesInCountry + } + structure[continent] = countriesInContinent + } + return DestinationResponse(structure) + } +} \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/config/SecurityConfig.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/config/SecurityConfig.kt index 97be6ef..8e12e9c 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/config/SecurityConfig.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/config/SecurityConfig.kt @@ -45,7 +45,7 @@ class SecurityConfig( .formLogin { it.disable() } .authorizeHttpRequests { it - .requestMatchers("/api/v1/auth/**", "/api/v1/test/**").permitAll() + .requestMatchers("/api/v1/auth/**", "/api/v1/test/**", "/api/v1/destinations").permitAll() .requestMatchers(HttpMethod.GET, "/api/v1/accompany/**").permitAll() .anyRequest().hasAnyRole(UserRole.USER.getActualRoleName(), UserRole.ADMIN.getActualRoleName()) } diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt index a53dd3e..d20a661 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt @@ -6,6 +6,9 @@ import com.withaeng.api.applicationservice.accompany.dto.SearchAccompanyServiceR import com.withaeng.api.applicationservice.accompany.dto.UpdateAccompanyServiceRequest import com.withaeng.api.common.PageInfoRequest import com.withaeng.domain.accompany.* +import com.withaeng.domain.destination.City +import com.withaeng.domain.destination.Continent +import com.withaeng.domain.destination.Country import io.swagger.v3.oas.annotations.media.Schema import jakarta.validation.constraints.Min import java.time.LocalDate diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/destination/DestinationController.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/destination/DestinationController.kt new file mode 100644 index 0000000..0cd200d --- /dev/null +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/destination/DestinationController.kt @@ -0,0 +1,22 @@ +package com.withaeng.api.controller.destination + +import com.withaeng.api.applicationservice.accompany.dto.DestinationResponse +import com.withaeng.api.applicationservice.destination.DestinationApplicationService +import com.withaeng.api.common.ApiResponse +import io.swagger.v3.oas.annotations.tags.Tag +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController + +@Tag(name = "Destination", description = "여행지 API") +@RestController +@RequestMapping("/api/v1/destinations") +class DestinationController(private val destinationApplicationService: DestinationApplicationService) { + + @GetMapping + fun getDestinations(): ApiResponse { + return ApiResponse.success( + destinationApplicationService.getDestinations() + ) + } +} \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyDestination.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyDestination.kt index 90aaaaf..a3978c2 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyDestination.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyDestination.kt @@ -1,5 +1,8 @@ package com.withaeng.domain.accompany +import com.withaeng.domain.destination.City +import com.withaeng.domain.destination.Continent +import com.withaeng.domain.destination.Country import jakarta.persistence.Column import jakarta.persistence.Embeddable import jakarta.persistence.EnumType @@ -21,5 +24,5 @@ data class AccompanyDestination( @Enumerated(EnumType.STRING) @Column(name = "city") @Comment("도시") - val city: City + val city: City, ) \ No newline at end of file diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryImpl.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryImpl.kt index f877db9..497d127 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryImpl.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/AccompanyRepositoryImpl.kt @@ -9,6 +9,9 @@ import com.withaeng.domain.accompanylike.QAccompanyLike.accompanyLike import com.withaeng.domain.accompanyrequests.AccompanyJoinRequestStatus import com.withaeng.domain.accompanyrequests.QAccompanyJoinRequest.accompanyJoinRequest import com.withaeng.domain.accompanystatistics.QAccompanyStatistics.accompanyStatistics +import com.withaeng.domain.destination.City +import com.withaeng.domain.destination.Continent +import com.withaeng.domain.destination.Country import com.withaeng.domain.user.QUser.user import org.springframework.data.domain.Page import org.springframework.data.domain.Pageable @@ -152,7 +155,7 @@ class AccompanyRepositoryImpl( accompanyStatistics.viewCount.desc(), accompany.createdAt.desc(), ) - + else -> arrayOf( accompany.createdAt.desc(), accompanyStatistics.viewCount.desc(), diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/dto/AccompanyQuery.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/dto/AccompanyQuery.kt index 7dba0a1..f348d28 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/dto/AccompanyQuery.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/dto/AccompanyQuery.kt @@ -1,6 +1,12 @@ package com.withaeng.domain.accompany.dto -import com.withaeng.domain.accompany.* +import com.withaeng.domain.accompany.AccompanyAge +import com.withaeng.domain.accompany.AccompanyPreferGender +import com.withaeng.domain.accompany.AccompanySort +import com.withaeng.domain.accompany.AccompanyStatus +import com.withaeng.domain.destination.City +import com.withaeng.domain.destination.Continent +import com.withaeng.domain.destination.Country import java.time.LocalDate data class SearchAccompanyQuery( diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/City.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/destination/City.kt similarity index 99% rename from withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/City.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/destination/City.kt index e7556c5..d12e7ae 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/City.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/destination/City.kt @@ -1,9 +1,9 @@ -package com.withaeng.domain.accompany +package com.withaeng.domain.destination enum class City( val countryCode: String, val cityCode: String, - val cityName: String + val cityName: String, ) { SEOUL(Country.KOREA.countryCode, "SEOUL", "서울"), diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Continent.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/destination/Continent.kt similarity index 85% rename from withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Continent.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/destination/Continent.kt index f541c5e..3c15be8 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Continent.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/destination/Continent.kt @@ -1,8 +1,8 @@ -package com.withaeng.domain.accompany +package com.withaeng.domain.destination enum class Continent( val continentCode: String, - val continentName: String + val continentName: String, ) { EAST_ASIA("EA", "동아시아"), diff --git a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Country.kt b/withaeng-domain/src/main/kotlin/com/withaeng/domain/destination/Country.kt similarity index 99% rename from withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Country.kt rename to withaeng-domain/src/main/kotlin/com/withaeng/domain/destination/Country.kt index edef910..7f2da51 100644 --- a/withaeng-domain/src/main/kotlin/com/withaeng/domain/accompany/Country.kt +++ b/withaeng-domain/src/main/kotlin/com/withaeng/domain/destination/Country.kt @@ -1,9 +1,9 @@ -package com.withaeng.domain.accompany +package com.withaeng.domain.destination enum class Country( val continentCode: String, val countryCode: String, - val countryName: String + val countryName: String, ) { KOREA(Continent.EAST_ASIA.continentCode, "KOREA", "한국"), From b4cb5356147edf6a574032088548fa7c0fd7ee16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Mon, 23 Sep 2024 20:51:44 +0900 Subject: [PATCH 168/174] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EB=A0=88=EC=9D=B4=EC=96=B4=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DestinationApplicationService.kt | 29 ------------------- .../destination/DestinationController.kt | 26 +++++++++++++++-- 2 files changed, 23 insertions(+), 32 deletions(-) delete mode 100644 withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/destination/DestinationApplicationService.kt diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/destination/DestinationApplicationService.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/destination/DestinationApplicationService.kt deleted file mode 100644 index 2421079..0000000 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/destination/DestinationApplicationService.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.withaeng.api.applicationservice.destination - -import com.withaeng.api.applicationservice.accompany.dto.DestinationResponse -import com.withaeng.domain.destination.City -import com.withaeng.domain.destination.Continent -import com.withaeng.domain.destination.Country -import org.springframework.stereotype.Service -import java.util.* - -@Service -class DestinationApplicationService { - - fun getDestinations(): DestinationResponse { - val structure = EnumMap>>(Continent::class.java) - Continent.entries.forEach { continent -> - val countriesInContinent = EnumMap>(Country::class.java) - Country.entries - .filter { it.continentCode == continent.continentCode } - .forEach { country -> - val citiesInCountry = City.entries - .filter { it.countryCode == country.countryCode } - .toList() - countriesInContinent[country] = citiesInCountry - } - structure[continent] = countriesInContinent - } - return DestinationResponse(structure) - } -} \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/destination/DestinationController.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/destination/DestinationController.kt index 0cd200d..e4bfa4b 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/destination/DestinationController.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/destination/DestinationController.kt @@ -1,22 +1,42 @@ package com.withaeng.api.controller.destination import com.withaeng.api.applicationservice.accompany.dto.DestinationResponse -import com.withaeng.api.applicationservice.destination.DestinationApplicationService import com.withaeng.api.common.ApiResponse +import com.withaeng.domain.destination.City +import com.withaeng.domain.destination.Continent +import com.withaeng.domain.destination.Country import io.swagger.v3.oas.annotations.tags.Tag import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController +import java.util.* @Tag(name = "Destination", description = "여행지 API") @RestController @RequestMapping("/api/v1/destinations") -class DestinationController(private val destinationApplicationService: DestinationApplicationService) { +class DestinationController { @GetMapping fun getDestinations(): ApiResponse { return ApiResponse.success( - destinationApplicationService.getDestinations() + DestinationResponse(createDestinationsMap()) ) } + + private fun createDestinationsMap(): EnumMap>> { + val structure = EnumMap>>(Continent::class.java) + Continent.entries.forEach { continent -> + val countriesInContinent = EnumMap>(Country::class.java) + Country.entries + .filter { it.continentCode == continent.continentCode } + .forEach { country -> + val citiesInCountry = City.entries + .filter { it.countryCode == country.countryCode } + .toList() + countriesInContinent[country] = citiesInCountry + } + structure[continent] = countriesInContinent + } + return structure + } } \ No newline at end of file From 7d643f8d10107ba29c0a37ba3b7b92fa5e04e975 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Mon, 23 Sep 2024 21:50:59 +0900 Subject: [PATCH 169/174] =?UTF-8?q?fix:=20=EC=9D=91=EB=8B=B5=20=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0=20=ED=8A=B8=EB=A6=AC=20=ED=98=95=ED=83=9C=EB=A1=9C=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 --- .../accompany/dto/AccompanyResponseDto.kt | 8 ---- .../destination/DestinationController.kt | 40 ++++++++++++------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyResponseDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyResponseDto.kt index b59aa9b..7dff625 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyResponseDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/applicationservice/accompany/dto/AccompanyResponseDto.kt @@ -5,11 +5,7 @@ import com.withaeng.domain.accompany.AccompanyPreferGender import com.withaeng.domain.accompany.AccompanyStatus import com.withaeng.domain.accompany.dto.AccompanyDto import com.withaeng.domain.accompany.dto.SearchAccompanyDto -import com.withaeng.domain.destination.City -import com.withaeng.domain.destination.Continent -import com.withaeng.domain.destination.Country import java.time.LocalDate -import java.util.* data class AccompanyResponse( val id: Long, @@ -88,8 +84,4 @@ fun SearchAccompanyDto.toAccompanyResponse(): AccompanySummaryResponse = Accompa data class CreateAccompanyResponse( val id: Long, val preSignedUrl: String? = null, -) - -data class DestinationResponse( - val continents: EnumMap>>, ) \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/destination/DestinationController.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/destination/DestinationController.kt index e4bfa4b..320cf11 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/destination/DestinationController.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/destination/DestinationController.kt @@ -1,6 +1,5 @@ package com.withaeng.api.controller.destination -import com.withaeng.api.applicationservice.accompany.dto.DestinationResponse import com.withaeng.api.common.ApiResponse import com.withaeng.domain.destination.City import com.withaeng.domain.destination.Continent @@ -9,7 +8,6 @@ import io.swagger.v3.oas.annotations.tags.Tag import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController -import java.util.* @Tag(name = "Destination", description = "여행지 API") @RestController @@ -17,26 +15,38 @@ import java.util.* class DestinationController { @GetMapping - fun getDestinations(): ApiResponse { + fun getDestinations(): ApiResponse { return ApiResponse.success( - DestinationResponse(createDestinationsMap()) + getDestinationsTree() ) } - private fun createDestinationsMap(): EnumMap>> { - val structure = EnumMap>>(Continent::class.java) - Continent.entries.forEach { continent -> - val countriesInContinent = EnumMap>(Country::class.java) - Country.entries + fun getDestinationsTree(): GetDestinationsResponse { + val continents = Continent.entries.map { continent -> + val countriesInContinent = Country.entries .filter { it.continentCode == continent.continentCode } - .forEach { country -> + .map { country -> val citiesInCountry = City.entries .filter { it.countryCode == country.countryCode } - .toList() - countriesInContinent[country] = citiesInCountry + .map { it.name } + CountryNode(name = country.name, cities = citiesInCountry) } - structure[continent] = countriesInContinent + ContinentNode(name = continent.name, countries = countriesInContinent) } - return structure + return GetDestinationsResponse(continents = continents) } -} \ No newline at end of file +} + +data class GetDestinationsResponse( + val continents: List, +) + +data class ContinentNode( + val name: String, + val countries: List, +) + +data class CountryNode( + val name: String, + val cities: List, +) \ No newline at end of file From eadb1716c0b952b8116cca2e770e9dc701cc55da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Thu, 26 Sep 2024 20:23:36 +0900 Subject: [PATCH 170/174] =?UTF-8?q?fix:=20=EB=B0=9C=EC=8B=A0=20=EC=9D=B4?= =?UTF-8?q?=EB=A9=94=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/kotlin/com/withaeng/external/email/SesEmailSender.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/withaeng-external/src/main/kotlin/com/withaeng/external/email/SesEmailSender.kt b/withaeng-external/src/main/kotlin/com/withaeng/external/email/SesEmailSender.kt index 2540aca..976682c 100644 --- a/withaeng-external/src/main/kotlin/com/withaeng/external/email/SesEmailSender.kt +++ b/withaeng-external/src/main/kotlin/com/withaeng/external/email/SesEmailSender.kt @@ -9,7 +9,7 @@ class SesEmailSender( ) : EmailSender { companion object { - private const val FROM = "withaeng@gmail.com" + private const val FROM = "reply@withaeng.com" } override fun send(to: String, subject: String, content: String) { From b1b7ed1e0abea1bffa50c5b60d2ec008b06920ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Sat, 28 Sep 2024 09:51:55 +0900 Subject: [PATCH 171/174] =?UTF-8?q?fix:=20page=20request=20int=EB=A1=9C=20?= =?UTF-8?q?=EB=B0=9B=EA=B3=A0=20=EA=B8=B0=EB=B3=B8=20=EC=82=AC=EC=9D=B4?= =?UTF-8?q?=EC=A6=88=208=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../withaeng/api/common/PageInfoRequest.kt | 25 +++---------------- .../accompany/dto/AccompanyRequestDto.kt | 4 +-- 2 files changed, 5 insertions(+), 24 deletions(-) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/common/PageInfoRequest.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/common/PageInfoRequest.kt index e577916..7ec7ea4 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/common/PageInfoRequest.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/common/PageInfoRequest.kt @@ -6,29 +6,10 @@ import org.springframework.data.domain.PageRequest @Schema(description = "[Request] 페이지 정보") data class PageInfoRequest( @Schema(description = "요청할 페이지 번호 (0부터 시작)") - private val page: String = "0", + private val page: Int = 0, @Schema(description = "페이지당 데이터 개수") - private val size: String = "5", + private val size: Int = 8, ) { - private val pageAsInt = initPage(getIntegerValue(page)) - private val sizeAsInt = initSize(getIntegerValue(size)) - - fun toPageRequest() = PageRequest.of(pageAsInt, sizeAsInt) - - private fun getIntegerValue(value: String?) = value?.toIntOrNull() - - private fun initPage(page: Int?): Int { - val defaultPage = 0 - val minimumPage = 0 - return page?.takeIf { it >= minimumPage } ?: defaultPage - } - - private fun initSize(size: Int?): Int { - val defaultSize = 5 - val minimumSize = 1 - val maxSize = 20 - return size?.takeIf { it in minimumSize..maxSize } ?: defaultSize - } - + fun toPageRequest() = PageRequest.of(page, size) } \ No newline at end of file diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt index d20a661..35da197 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/accompany/dto/AccompanyRequestDto.kt @@ -102,9 +102,9 @@ fun UpdateAccompanyRequest.toServiceRequest( data class SearchAccompanyRequest( @Schema(description = "요청할 페이지 번호 (0부터 시작)") - val page: String = "0", + val page: Int = 0, @Schema(description = "페이지당 데이터 개수") - val size: String = "5", + val size: Int = 8, @Schema(description = "동행 정렬 기준") val sort: AccompanySort? = null, @Schema(description = "동행 상태") From 3815314212f5d54881ed17d86910016a4b5bd370 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Sat, 28 Sep 2024 09:53:49 +0900 Subject: [PATCH 172/174] =?UTF-8?q?fix:=20test=20=ED=86=A0=ED=81=B0=20?= =?UTF-8?q?=EC=9A=B4=EC=98=81=EC=84=9C=EB=B2=84=EC=97=90=EC=84=9C=EB=8A=94?= =?UTF-8?q?=20=EC=82=AC=EC=9A=A9=20=EB=B6=88=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/withaeng/api/controller/test/TestController.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/test/TestController.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/test/TestController.kt index 072c225..cdb8ccd 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/controller/test/TestController.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/controller/test/TestController.kt @@ -4,13 +4,15 @@ import com.withaeng.api.applicationservice.test.TestApplicationService import com.withaeng.api.common.ApiResponse import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.tags.Tag +import org.springframework.context.annotation.Profile import org.springframework.web.bind.annotation.* @Tag(name = "Test", description = "테스트를 위한 API") +@Profile("!prod") @RequestMapping("/api/v1/test") @RestController class TestController( - private val testApplicationService: TestApplicationService + private val testApplicationService: TestApplicationService, ) { @Operation(summary = "Provide Test Access Token", description = "테스트 토큰 발급") From 6639f8bc72a15daa2e7bd45a52748a3f77e4441a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Sat, 28 Sep 2024 10:09:54 +0900 Subject: [PATCH 173/174] =?UTF-8?q?fix:=20=EC=8A=A4=EC=9B=A8=EA=B1=B0=20?= =?UTF-8?q?=EC=9A=B4=EC=98=81=EC=84=9C=EB=B2=84=20=EC=84=9C=EB=B2=84=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/withaeng/api/config/SwaggerConfig.kt | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/withaeng-api/src/main/kotlin/com/withaeng/api/config/SwaggerConfig.kt b/withaeng-api/src/main/kotlin/com/withaeng/api/config/SwaggerConfig.kt index 8548a79..00e5324 100644 --- a/withaeng-api/src/main/kotlin/com/withaeng/api/config/SwaggerConfig.kt +++ b/withaeng-api/src/main/kotlin/com/withaeng/api/config/SwaggerConfig.kt @@ -2,7 +2,13 @@ package com.withaeng.api.config import io.swagger.v3.oas.annotations.enums.SecuritySchemeType import io.swagger.v3.oas.annotations.security.SecurityScheme +import io.swagger.v3.oas.models.OpenAPI +import io.swagger.v3.oas.models.info.Info +import io.swagger.v3.oas.models.servers.Server +import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration +import org.springframework.context.annotation.Primary +import org.springframework.context.annotation.Profile @Configuration @SecurityScheme( @@ -11,4 +17,29 @@ import org.springframework.context.annotation.Configuration bearerFormat = "JWT", scheme = "bearer" ) -class SwaggerConfig \ No newline at end of file +class SwaggerConfig { + + @Bean + fun defaultSwagger(): OpenAPI { + return OpenAPI() + .info( + Info() + .title("Withaeng API") + .version("1.0") + ) + } + + @Profile("prod") + @Primary + @Bean + fun prodSwagger(defaultSwagger: OpenAPI): OpenAPI { + return defaultSwagger + .servers( + listOf( + Server() + .url("https://api.withaeng.com") + .description("Production server"), + ) + ) + } +} \ No newline at end of file From 994ef9324cf48359fcb98aa515f0ea0540ee5be9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=88=EC=98=81=EA=B8=B8?= Date: Sat, 28 Sep 2024 10:22:38 +0900 Subject: [PATCH 174/174] =?UTF-8?q?fix:=20github=20action=20cd=20main=20?= =?UTF-8?q?=EB=B8=8C=EB=9E=9C=EC=B9=98=20=EA=B8=B0=EC=A4=80=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 372e358..1be7210 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -3,7 +3,7 @@ name: Withaeng CD with Gradle, Github Actions on: push: branches: - - develop # todo: main branch로 변경 + - main jobs: build: